dsh-codex-subscription 1.11.2 → 1.11.4
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 +4 -4
- package/compatibility.json +2 -1
- package/lib/client.js +43 -11
- package/lib/index.js +46 -6
- package/package.json +17 -17
package/AGENTS.md
CHANGED
|
@@ -6,7 +6,7 @@ Use this guide when a user asks an Agent to install, update, verify, or remove
|
|
|
6
6
|
## Safety
|
|
7
7
|
|
|
8
8
|
- Confirm the target DSH installation and profile. Use `web` only when it is the user's target.
|
|
9
|
-
- Use the exact `1.11.
|
|
9
|
+
- Use the exact `1.11.4` package below; do not install a moving branch.
|
|
10
10
|
- Never print OAuth credentials, account IDs, authorization callbacks, or credential-store contents.
|
|
11
11
|
- Preserve the DSH profile, unrelated plugins, sessions, and saved sign-in.
|
|
12
12
|
- Do not start, stop, or restart DSH without explicit permission.
|
|
@@ -34,13 +34,13 @@ For an official DSH installation run through npm, keep the complete `npx` prefix
|
|
|
34
34
|
run command does not create a global `dsh` command:
|
|
35
35
|
|
|
36
36
|
```sh
|
|
37
|
-
npx -y @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add dsh-codex-subscription@1.11.
|
|
37
|
+
npx -y @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add dsh-codex-subscription@1.11.4
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
With an existing global `dsh` command:
|
|
41
41
|
|
|
42
42
|
```sh
|
|
43
|
-
dsh plugin --profile web add dsh-codex-subscription@1.11.
|
|
43
|
+
dsh plugin --profile web add dsh-codex-subscription@1.11.4
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
Use the same `add` command to update or repair. This is the complete package-changing operation.
|
|
@@ -58,7 +58,7 @@ dsh --profile web --dump-config
|
|
|
58
58
|
|
|
59
59
|
For the official npm route, run the same checks with `npx -y @deepseek-ai/dsh@0.1.1-rc.2` in place of `dsh`.
|
|
60
60
|
|
|
61
|
-
1. `dsh-codex-subscription` version `1.11.
|
|
61
|
+
1. `dsh-codex-subscription` version `1.11.4` appears exactly once.
|
|
62
62
|
2. `codex-subscription` appears exactly once in the composed config.
|
|
63
63
|
3. No unrelated plugin or profile was changed and DSH was not restarted.
|
|
64
64
|
|
package/compatibility.json
CHANGED
package/lib/client.js
CHANGED
|
@@ -329,6 +329,7 @@ window.__ModuleLoader__.load({
|
|
|
329
329
|
quickQuotaBar: "进度条",
|
|
330
330
|
quickQuotaForecast: "续航预测",
|
|
331
331
|
quickQuotaBeta: "Beta",
|
|
332
|
+
quickQuotaForecastHint: "至少观察 30 分钟且额度变化 1% 后显示;重启 DSH 后重新校准。",
|
|
332
333
|
contextTitle: "上下文窗口",
|
|
333
334
|
contextStandard: "标准",
|
|
334
335
|
contextStandardHint: "使用模型目录默认值;官方 Agent 预设会自动管理上下文。",
|
|
@@ -341,7 +342,16 @@ window.__ModuleLoader__.load({
|
|
|
341
342
|
contextMaximum: "范围 128000–{value}",
|
|
342
343
|
quickQuotaStatus: "Codex 剩余额度 {value}%",
|
|
343
344
|
quickQuotaForecastStatus: "Codex 剩余额度 {value}%,按当前速度预计可用 {duration}",
|
|
345
|
+
quickQuotaForecastCalibrating: "校准中",
|
|
346
|
+
quickQuotaForecastCalibratingStatus: "Codex 剩余额度 {value}%,续航预测正在校准",
|
|
347
|
+
quickQuotaForecastIdle: "用量稳定",
|
|
348
|
+
quickQuotaForecastIdleStatus: "Codex 剩余额度 {value}%,当前没有可测量的消耗速度",
|
|
349
|
+
quickQuotaForecastUntilReset: "够用到重置",
|
|
350
|
+
quickQuotaForecastUntilResetStatus: "Codex 剩余额度 {value}%,按当前速度足够用到重置",
|
|
344
351
|
quotaForecast: "按当前速度 {symbol}{duration}",
|
|
352
|
+
quotaForecastCalibrating: "续航正在校准",
|
|
353
|
+
quotaForecastIdle: "当前用量稳定",
|
|
354
|
+
quotaForecastUntilReset: "按当前速度足够用到重置",
|
|
345
355
|
runwayDaysHours: "{days} 天 {hours} 小时",
|
|
346
356
|
runwayDays: "{days} 天",
|
|
347
357
|
runwayHours: "{hours} 小时",
|
|
@@ -495,6 +505,7 @@ window.__ModuleLoader__.load({
|
|
|
495
505
|
quickQuotaBar: "Progress bar",
|
|
496
506
|
quickQuotaForecast: "Runway",
|
|
497
507
|
quickQuotaBeta: "Beta",
|
|
508
|
+
quickQuotaForecastHint: "Appears after at least 30 minutes and a 1% quota change; restarting DSH recalibrates it.",
|
|
498
509
|
contextTitle: "Context window",
|
|
499
510
|
contextStandard: "Standard",
|
|
500
511
|
contextStandardHint: "Use the model catalog default; official agent presets manage context automatically.",
|
|
@@ -507,7 +518,16 @@ window.__ModuleLoader__.load({
|
|
|
507
518
|
contextMaximum: "128000–{value}",
|
|
508
519
|
quickQuotaStatus: "Codex quota: {value}% remaining",
|
|
509
520
|
quickQuotaForecastStatus: "Codex quota: {value}% remaining; about {duration} at the current pace",
|
|
521
|
+
quickQuotaForecastCalibrating: "Calibrating",
|
|
522
|
+
quickQuotaForecastCalibratingStatus: "Codex quota: {value}% remaining; runway is calibrating",
|
|
523
|
+
quickQuotaForecastIdle: "Usage stable",
|
|
524
|
+
quickQuotaForecastIdleStatus: "Codex quota: {value}% remaining; no measurable consumption pace",
|
|
525
|
+
quickQuotaForecastUntilReset: "Enough until reset",
|
|
526
|
+
quickQuotaForecastUntilResetStatus: "Codex quota: {value}% remaining; enough until reset at the current pace",
|
|
510
527
|
quotaForecast: "At current pace {symbol}{duration}",
|
|
528
|
+
quotaForecastCalibrating: "Runway calibrating",
|
|
529
|
+
quotaForecastIdle: "Usage currently stable",
|
|
530
|
+
quotaForecastUntilReset: "Enough until reset at current pace",
|
|
511
531
|
runwayDaysHours: "{days}d {hours}h",
|
|
512
532
|
runwayDays: "{days}d",
|
|
513
533
|
runwayHours: "{hours}h",
|
|
@@ -576,7 +596,7 @@ window.__ModuleLoader__.load({
|
|
|
576
596
|
.codexSubscriptionTag{border:1px solid var(--dsw-alias-border-l3);border-radius:4px;padding:1px 6px;font-size:11px;line-height:16px;color:var(--dsw-alias-label-secondary)}
|
|
577
597
|
.codexSubscriptionNote{font-size:13px;line-height:20px;color:var(--dsw-alias-label-tertiary)}
|
|
578
598
|
.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}
|
|
579
|
-
.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}
|
|
599
|
+
.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}.codexSubscriptionPreferenceHint{max-width:300px;font-size:11px;line-height:17px;color:var(--dsw-alias-label-tertiary)}
|
|
580
600
|
.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;white-space:nowrap}.codexSubscriptionQuotaMode small{margin-left:3px;font-size:9px;line-height:1;color:var(--dsw-alias-label-tertiary)}.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}
|
|
581
601
|
.codexSubscriptionContext{display:flex;flex-direction:column;gap:8px}.codexSubscriptionContextHead{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.codexSubscriptionContextCopy{display:flex;min-width:0;flex:1;flex-direction:column;gap:2px}.codexSubscriptionContextHint{font-size:11px;line-height:17px;color:var(--dsw-alias-label-tertiary)}.codexSubscriptionContextTrigger{height:32px;min-width:108px;display:inline-flex;align-items:center;justify-content:space-between;gap:10px;padding:0 10px 0 12px;border:0;border-radius:999px;outline:0;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;cursor:pointer}.codexSubscriptionContextTrigger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.codexSubscriptionContextTrigger:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}.codexSubscriptionContextTrigger:disabled{color:var(--dsw-alias-label-dimmed);cursor:not-allowed}.codexSubscriptionContextTrigger svg{color:var(--dsw-alias-label-tertiary);transition:transform 120ms var(--ds-ease-in-out)}.codexSubscriptionContextTrigger[aria-expanded=true] svg{transform:rotate(180deg)}.codexSubscriptionContextModels{display:flex;flex-direction:column;border-top:1px solid var(--dsw-alias-border-l2)}.codexSubscriptionContextModel{min-height:42px;display:flex;align-items:center;justify-content:space-between;gap:12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.codexSubscriptionContextModel:last-child{border-bottom:0}.codexSubscriptionContextModelCopy{display:flex;min-width:0;flex-direction:column}.codexSubscriptionContextModelCopy strong{font-size:12px;line-height:18px;font-weight:500}.codexSubscriptionContextModelCopy span{font-size:11px;line-height:16px;color:var(--dsw-alias-label-tertiary)}.codexSubscriptionContextInput{width:116px}
|
|
582
602
|
.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)}
|
|
@@ -1212,6 +1232,17 @@ window.__ModuleLoader__.load({
|
|
|
1212
1232
|
if (hours > 0) return fill(t("runwayHours"), { hours });
|
|
1213
1233
|
return fill(t("runwayMinutes"), { minutes });
|
|
1214
1234
|
};
|
|
1235
|
+
const formatQuotaForecast = (forecast, t) => {
|
|
1236
|
+
if (forecast?.status === "calibrating") return t("quotaForecastCalibrating");
|
|
1237
|
+
if (forecast?.status === "idle") return t("quotaForecastIdle");
|
|
1238
|
+
if (forecast?.status !== "ready") return void 0;
|
|
1239
|
+
if (forecast.survivesReset) return t("quotaForecastUntilReset");
|
|
1240
|
+
const duration = formatRunway(forecast.runwaySeconds, t);
|
|
1241
|
+
return duration === void 0 ? void 0 : fill(t("quotaForecast"), {
|
|
1242
|
+
symbol: "≈",
|
|
1243
|
+
duration
|
|
1244
|
+
});
|
|
1245
|
+
};
|
|
1215
1246
|
function useQuickQuota(rpc, enabled, model) {
|
|
1216
1247
|
const [quota, setQuota] = (0, react.useState)();
|
|
1217
1248
|
(0, react.useEffect)(() => {
|
|
@@ -1274,12 +1305,15 @@ window.__ModuleLoader__.load({
|
|
|
1274
1305
|
});
|
|
1275
1306
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1276
1307
|
className: "codexSubscriptionPreference",
|
|
1277
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.
|
|
1308
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1278
1309
|
className: "codexSubscriptionPreferenceCopy",
|
|
1279
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1310
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1280
1311
|
className: "codexSubscriptionPreferenceLabel",
|
|
1281
1312
|
children: t("quickQuotaSetting")
|
|
1282
|
-
})
|
|
1313
|
+
}), snapshot.quickQuotaMode === "forecast" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1314
|
+
className: "codexSubscriptionPreferenceHint",
|
|
1315
|
+
children: t("quickQuotaForecastHint")
|
|
1316
|
+
}) : null]
|
|
1283
1317
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1284
1318
|
className: "codexSubscriptionQuotaModes",
|
|
1285
1319
|
role: "radiogroup",
|
|
@@ -1502,8 +1536,9 @@ window.__ModuleLoader__.load({
|
|
|
1502
1536
|
if (!quotaEnabled || quota === void 0) return null;
|
|
1503
1537
|
const value = Math.round(Number(quota.remainingPercent) * 10) / 10;
|
|
1504
1538
|
const display = percent(value);
|
|
1505
|
-
const
|
|
1506
|
-
const
|
|
1539
|
+
const forecast = forecastMode ? quota.forecast : void 0;
|
|
1540
|
+
const duration = forecast?.status === "ready" && !forecast.survivesReset ? formatRunway(forecast.runwaySeconds, t) : void 0;
|
|
1541
|
+
const label = forecast?.status === "calibrating" ? fill(t("quickQuotaForecastCalibratingStatus"), { value: display }) : forecast?.status === "idle" ? fill(t("quickQuotaForecastIdleStatus"), { value: display }) : forecast?.status === "ready" && forecast.survivesReset ? fill(t("quickQuotaForecastUntilResetStatus"), { value: display }) : duration === void 0 ? fill(t("quickQuotaStatus"), { value: display }) : fill(t("quickQuotaForecastStatus"), {
|
|
1507
1542
|
value: display,
|
|
1508
1543
|
duration
|
|
1509
1544
|
});
|
|
@@ -1517,7 +1552,7 @@ window.__ModuleLoader__.load({
|
|
|
1517
1552
|
max: 100,
|
|
1518
1553
|
value,
|
|
1519
1554
|
"aria-hidden": "true"
|
|
1520
|
-
}) :
|
|
1555
|
+
}) : forecast?.status === "calibrating" ? `${display}% · ${t("quickQuotaForecastCalibrating")}` : forecast?.status === "idle" ? `${display}% · ${t("quickQuotaForecastIdle")}` : forecast?.status === "ready" && forecast.survivesReset ? `${display}% · ${t("quickQuotaForecastUntilReset")}` : forecastMode && duration !== void 0 ? `${display}% · ≈${duration}` : `${display}%`
|
|
1521
1556
|
});
|
|
1522
1557
|
}
|
|
1523
1558
|
function CodexModelSelect({ locked, available, directory, load, select, preference, t }) {
|
|
@@ -2424,10 +2459,7 @@ window.__ModuleLoader__.load({
|
|
|
2424
2459
|
}),
|
|
2425
2460
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2426
2461
|
className: "codexSubscriptionLimitMeta",
|
|
2427
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: window.forecast
|
|
2428
|
-
symbol: window.forecast.survivesReset ? "≥" : "≈",
|
|
2429
|
-
duration: formatRunway(window.forecast.runwaySeconds, t)
|
|
2430
|
-
}) : windowLabel(window.windowSeconds, t) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResetTime, {
|
|
2462
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatQuotaForecast(window.forecast, t) ?? windowLabel(window.windowSeconds, t) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResetTime, {
|
|
2431
2463
|
resetsAt: window.resetsAt,
|
|
2432
2464
|
t
|
|
2433
2465
|
})]
|
package/lib/index.js
CHANGED
|
@@ -44,11 +44,14 @@ function parseOAuthCredential(value) {
|
|
|
44
44
|
*/
|
|
45
45
|
var DshOAuthCredentialStore = class {
|
|
46
46
|
#chains = /* @__PURE__ */ new Map();
|
|
47
|
-
constructor(credentials, ref, legacyRefs = []) {
|
|
47
|
+
constructor(credentials, ref, legacyRefs = [], options = {}) {
|
|
48
48
|
if (credentials === void 0 || credentials === null) throw new Error("Codex OAuth requires the DSH credentials service");
|
|
49
|
+
const expirySkewMs = options.expirySkewMs ?? 0;
|
|
50
|
+
if (!Number.isFinite(expirySkewMs) || expirySkewMs < 0) throw new Error("Codex OAuth expiry skew must be a non-negative finite number");
|
|
49
51
|
this.credentials = credentials;
|
|
50
52
|
this.ref = ref;
|
|
51
53
|
this.legacyRefs = Object.freeze([...legacyRefs]);
|
|
54
|
+
this.expirySkewMs = expirySkewMs;
|
|
52
55
|
}
|
|
53
56
|
#enqueue(providerId, operation, options) {
|
|
54
57
|
assertProvider(providerId);
|
|
@@ -78,7 +81,11 @@ var DshOAuthCredentialStore = class {
|
|
|
78
81
|
}
|
|
79
82
|
abortIfNeeded(options);
|
|
80
83
|
if (hit?.value === void 0 || hit.value === "") return void 0;
|
|
81
|
-
|
|
84
|
+
const credential = parseOAuthCredential(hit.value);
|
|
85
|
+
return this.expirySkewMs === 0 ? credential : {
|
|
86
|
+
...credential,
|
|
87
|
+
expires: credential.expires - this.expirySkewMs
|
|
88
|
+
};
|
|
82
89
|
}
|
|
83
90
|
read(providerId, options) {
|
|
84
91
|
return this.#enqueue(providerId, () => this.#read(providerId, options), options);
|
|
@@ -935,7 +942,7 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
|
|
|
935
942
|
}
|
|
936
943
|
//#endregion
|
|
937
944
|
//#region src/version.js
|
|
938
|
-
const PACKAGE_VERSION = "1.11.
|
|
945
|
+
const PACKAGE_VERSION = "1.11.4";
|
|
939
946
|
const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
|
|
940
947
|
//#endregion
|
|
941
948
|
//#region src/model-catalog.js
|
|
@@ -1836,6 +1843,8 @@ async function createSubscriptionDiagnostics({ auth, preferences, login = { phas
|
|
|
1836
1843
|
const CODEX_USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
|
|
1837
1844
|
const DEFAULT_TTL_MS = 6e4;
|
|
1838
1845
|
const DEFAULT_TIMEOUT_MS$1 = 15e3;
|
|
1846
|
+
const DEFAULT_FAILURE_TTL_MS = 5e3;
|
|
1847
|
+
const DEFAULT_MAX_RETRY_AFTER_MS = 5 * 6e4;
|
|
1839
1848
|
const record$1 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1840
1849
|
function windowOf(value) {
|
|
1841
1850
|
if (value === void 0 || value === null) return void 0;
|
|
@@ -1951,6 +1960,15 @@ const requestSignal$1 = (signal, timeoutMs) => {
|
|
|
1951
1960
|
const timeout = AbortSignal.timeout(timeoutMs);
|
|
1952
1961
|
return signal === void 0 ? timeout : AbortSignal.any([signal, timeout]);
|
|
1953
1962
|
};
|
|
1963
|
+
function retryAfterMs(response, now, maximum) {
|
|
1964
|
+
if (response.status !== 429) return void 0;
|
|
1965
|
+
const raw = response.headers?.get?.("retry-after")?.trim();
|
|
1966
|
+
if (!raw) return void 0;
|
|
1967
|
+
const seconds = Number(raw);
|
|
1968
|
+
const delay = Number.isFinite(seconds) && seconds >= 0 ? seconds * 1e3 : Date.parse(raw) - now();
|
|
1969
|
+
if (!Number.isFinite(delay) || delay < 0) return void 0;
|
|
1970
|
+
return Math.min(delay, maximum);
|
|
1971
|
+
}
|
|
1954
1972
|
/**
|
|
1955
1973
|
* Read quota through the same refreshable OAuth lifecycle used by model turns.
|
|
1956
1974
|
* The browser receives only a parsed quota projection; bearer and account id
|
|
@@ -1963,7 +1981,10 @@ function createCodexUsageReader(options) {
|
|
|
1963
1981
|
const now = options.now ?? Date.now;
|
|
1964
1982
|
const ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
|
|
1965
1983
|
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS$1;
|
|
1984
|
+
const failureTtlMs = options.failureTtlMs ?? DEFAULT_FAILURE_TTL_MS;
|
|
1985
|
+
const maxRetryAfterMs = options.maxRetryAfterMs ?? DEFAULT_MAX_RETRY_AFTER_MS;
|
|
1966
1986
|
let cached;
|
|
1987
|
+
let failed;
|
|
1967
1988
|
let inFlight;
|
|
1968
1989
|
let generation = 0;
|
|
1969
1990
|
const load = async (signal) => {
|
|
@@ -1984,7 +2005,11 @@ function createCodexUsageReader(options) {
|
|
|
1984
2005
|
},
|
|
1985
2006
|
signal: requestSignal$1(signal, timeoutMs)
|
|
1986
2007
|
});
|
|
1987
|
-
if (!response.ok)
|
|
2008
|
+
if (!response.ok) {
|
|
2009
|
+
const error = /* @__PURE__ */ new Error(response.status === 401 || response.status === 403 ? "ChatGPT sign-in needs to be renewed" : `ChatGPT usage request failed (HTTP ${response.status})`);
|
|
2010
|
+
Object.defineProperty(error, "retryAfterMs", { value: retryAfterMs(response, now, maxRetryAfterMs) });
|
|
2011
|
+
throw error;
|
|
2012
|
+
}
|
|
1988
2013
|
let value;
|
|
1989
2014
|
try {
|
|
1990
2015
|
value = await response.json();
|
|
@@ -1998,12 +2023,25 @@ function createCodexUsageReader(options) {
|
|
|
1998
2023
|
};
|
|
1999
2024
|
return Object.freeze({
|
|
2000
2025
|
read({ force = false, signal } = {}) {
|
|
2026
|
+
if (failed !== void 0 && now() < failed.retryAt) return Promise.reject(new Error(failed.message));
|
|
2001
2027
|
if (!force && cached !== void 0 && now() - cached.fetchedAt < ttlMs) return Promise.resolve(structuredClone(cached));
|
|
2002
2028
|
if (inFlight !== void 0) return inFlight.then(structuredClone);
|
|
2003
2029
|
const currentGeneration = generation;
|
|
2004
2030
|
const current = load(signal).then((value) => {
|
|
2005
|
-
if (generation === currentGeneration)
|
|
2031
|
+
if (generation === currentGeneration) {
|
|
2032
|
+
cached = structuredClone(value);
|
|
2033
|
+
failed = void 0;
|
|
2034
|
+
}
|
|
2006
2035
|
return structuredClone(value);
|
|
2036
|
+
}).catch((error) => {
|
|
2037
|
+
if (generation === currentGeneration && error?.name !== "AbortError") {
|
|
2038
|
+
const delay = Number.isFinite(error?.retryAfterMs) ? error.retryAfterMs : failureTtlMs;
|
|
2039
|
+
failed = {
|
|
2040
|
+
message: error instanceof Error ? error.message : "ChatGPT usage request failed",
|
|
2041
|
+
retryAt: now() + delay
|
|
2042
|
+
};
|
|
2043
|
+
}
|
|
2044
|
+
throw error;
|
|
2007
2045
|
}).finally(() => {
|
|
2008
2046
|
if (inFlight === current) inFlight = void 0;
|
|
2009
2047
|
});
|
|
@@ -2013,6 +2051,7 @@ function createCodexUsageReader(options) {
|
|
|
2013
2051
|
clear() {
|
|
2014
2052
|
generation += 1;
|
|
2015
2053
|
cached = void 0;
|
|
2054
|
+
failed = void 0;
|
|
2016
2055
|
inFlight = void 0;
|
|
2017
2056
|
}
|
|
2018
2057
|
});
|
|
@@ -2404,6 +2443,7 @@ const inject = [
|
|
|
2404
2443
|
"attachments"
|
|
2405
2444
|
];
|
|
2406
2445
|
const PROVIDER = "openai-codex";
|
|
2446
|
+
const OAUTH_EXPIRY_SKEW_MS = 6e4;
|
|
2407
2447
|
const CREDENTIAL_REF = credentialRef("OPENAI_CODEX_SUBSCRIPTION_OAUTH");
|
|
2408
2448
|
const LEGACY_CREDENTIAL_REF = credentialRef("WSL043_OPENAI_CODEX_OAUTH");
|
|
2409
2449
|
const CHANNEL = "/codex-subscription";
|
|
@@ -2616,7 +2656,7 @@ function apply(ctx) {
|
|
|
2616
2656
|
const searchProvider = createSearchProviderSwitcher(ctx.loader);
|
|
2617
2657
|
const network = createCodexNetworkTransport();
|
|
2618
2658
|
const originalImages = new OriginalImageStore();
|
|
2619
|
-
const store = new DshOAuthCredentialStore(ctx.credentials, CREDENTIAL_REF, [LEGACY_CREDENTIAL_REF]);
|
|
2659
|
+
const store = new DshOAuthCredentialStore(ctx.credentials, CREDENTIAL_REF, [LEGACY_CREDENTIAL_REF], { expirySkewMs: OAUTH_EXPIRY_SKEW_MS });
|
|
2620
2660
|
const baseProvider = createOpenAICodexProvider();
|
|
2621
2661
|
let resolveAuth = async () => void 0;
|
|
2622
2662
|
const modelCatalog = createOfficialModelCatalog({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-codex-subscription",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.4",
|
|
4
4
|
"description": "Use ChatGPT and Codex subscriptions in DeepSeek Harness with OAuth, quota, safe resets, web search, images, and Fast mode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -77,22 +77,22 @@
|
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
79
|
"@deepseek-ai/cordis": "4.0.1 || 4.0.2",
|
|
80
|
-
"@deepseek-ai/dsh-api-remotes": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
81
|
-
"@deepseek-ai/dsh-client-connection": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
82
|
-
"@deepseek-ai/dsh-client-locale": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
83
|
-
"@deepseek-ai/dsh-client-runtime": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
84
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
85
|
-
"@deepseek-ai/dsh-client-ui-model-selection": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
86
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
87
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
88
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
89
|
-
"@deepseek-ai/dsh-client-ui-tool": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
90
|
-
"@deepseek-ai/dsh-credentials": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
91
|
-
"@deepseek-ai/dsh-llm": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
92
|
-
"@deepseek-ai/dsh-llm-pi-ai": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
93
|
-
"@deepseek-ai/dsh-settings": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
94
|
-
"@deepseek-ai/dsh-tools": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
95
|
-
"@deepseek-ai/dsh-web": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2",
|
|
80
|
+
"@deepseek-ai/dsh-api-remotes": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
81
|
+
"@deepseek-ai/dsh-client-connection": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
82
|
+
"@deepseek-ai/dsh-client-locale": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
83
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
84
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
85
|
+
"@deepseek-ai/dsh-client-ui-model-selection": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
86
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
87
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
88
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
89
|
+
"@deepseek-ai/dsh-client-ui-tool": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
90
|
+
"@deepseek-ai/dsh-credentials": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
91
|
+
"@deepseek-ai/dsh-llm": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
92
|
+
"@deepseek-ai/dsh-llm-pi-ai": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
93
|
+
"@deepseek-ai/dsh-settings": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
94
|
+
"@deepseek-ai/dsh-tools": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
95
|
+
"@deepseek-ai/dsh-web": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-alpha.2 || 0.1.2-alpha.3",
|
|
96
96
|
"@deepseek-ai/schemastery": "3.18.1",
|
|
97
97
|
"@earendil-works/pi-ai": "0.82.1",
|
|
98
98
|
"react": "^18.2.0",
|