dsh-codex-subscription 1.11.0 → 1.11.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/AGENTS.md +4 -4
- package/README.md +2 -1
- package/README.zh-CN.md +3 -2
- package/lib/client.js +4 -1
- package/lib/index.js +79 -29
- package/package.json +1 -1
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.1` 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.1
|
|
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.1
|
|
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.1` 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/README.md
CHANGED
|
@@ -12,7 +12,7 @@ No OpenAI API key or Codex CLI. Models, search, quota, and image generation stay
|
|
|
12
12
|
[](LICENSE)
|
|
13
13
|
[](https://github.com/WSL043/dsh-codex-subscription/stargazers)
|
|
14
14
|
|
|
15
|
-
[Three-step start](#three-step-start) · [Install](#install) · [Update and uninstall](#update-and-uninstall) · [简体中文](https://github.com/WSL043/dsh-codex-subscription/blob/main/README.zh-CN.md)
|
|
15
|
+
[Three-step start](#three-step-start) · [Install](#install) · [Contribute](CONTRIBUTING.md) · [Update and uninstall](#update-and-uninstall) · [简体中文](https://github.com/WSL043/dsh-codex-subscription/blob/main/README.zh-CN.md)
|
|
16
16
|
|
|
17
17
|
</div>
|
|
18
18
|
|
|
@@ -211,6 +211,7 @@ The ChatGPT Codex backend and DSH can change independently. This community proje
|
|
|
211
211
|
|
|
212
212
|
Use the [bug report form](https://github.com/WSL043/dsh-codex-subscription/issues/new?template=install-problem.yml) for project feedback.
|
|
213
213
|
Use the [feature request form](https://github.com/WSL043/dsh-codex-subscription/issues/new?template=feature-request.yml) for focused product suggestions.
|
|
214
|
+
Focused fixes and compatibility improvements are welcome; see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
214
215
|
For DSH plugin discussion, visit [DeepSeek Harness Discussions](https://github.com/deepseek-ai/deepseek-harness/discussions).
|
|
215
216
|
Read [SECURITY.md](SECURITY.md) before reporting sensitive issues.
|
|
216
217
|
|
package/README.zh-CN.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
[](LICENSE)
|
|
14
14
|
[](https://github.com/WSL043/dsh-codex-subscription/stargazers)
|
|
15
15
|
|
|
16
|
-
[三步开始](#三步开始) · [安装](#安装) · [更新与卸载](#更新与卸载) · [English](https://github.com/WSL043/dsh-codex-subscription/blob/main/README.md)
|
|
16
|
+
[三步开始](#三步开始) · [安装](#安装) · [参与贡献](CONTRIBUTING.md) · [更新与卸载](#更新与卸载) · [English](https://github.com/WSL043/dsh-codex-subscription/blob/main/README.md)
|
|
17
17
|
|
|
18
18
|
</div>
|
|
19
19
|
|
|
@@ -139,7 +139,7 @@ dsh --profile web --dump-config
|
|
|
139
139
|
### 输入框额度
|
|
140
140
|
|
|
141
141
|
<p align="center">
|
|
142
|
-
<img src="https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/docs/assets/composer-quota
|
|
142
|
+
<img src="https://raw.githubusercontent.com/WSL043/dsh-codex-subscription/main/docs/assets/composer-quota.png" width="800" alt="中文 DSH 输入框内的 Codex 剩余额度进度条">
|
|
143
143
|
</p>
|
|
144
144
|
|
|
145
145
|
可在设置中选择关闭、百分比、进度条或 Beta 续航预测;紧凑额度只在选择 Codex 模型时显示。续航预测仅在用户主动选择后,根据本机运行内存中观察到的官方剩余百分比估算当前消耗速度;样本不足时保持安静,额度重置、登录变化或关闭功能后会重新校准。普通 Codex 使用服务端返回窗口中剩余最少的一项,
|
|
@@ -209,6 +209,7 @@ ChatGPT Codex 后端和 DSH 可能独立变化;本项目为社区项目,与
|
|
|
209
209
|
|
|
210
210
|
本项目的问题反馈请使用[使用问题表单](https://github.com/WSL043/dsh-codex-subscription/issues/new?template=install-problem.yml);
|
|
211
211
|
明确的产品建议请使用[功能建议表单](https://github.com/WSL043/dsh-codex-subscription/issues/new?template=feature-request.yml);
|
|
212
|
+
欢迎提交聚焦的修复和兼容性改进,具体要求见 [CONTRIBUTING.md](CONTRIBUTING.md);
|
|
212
213
|
DSH 插件交流可前往 [DeepSeek Harness Discussions](https://github.com/deepseek-ai/deepseek-harness/discussions)。
|
|
213
214
|
敏感问题请先阅读 [SECURITY.md](SECURITY.md)。
|
|
214
215
|
|
package/lib/client.js
CHANGED
|
@@ -318,6 +318,7 @@ window.__ModuleLoader__.load({
|
|
|
318
318
|
resetTooEarly: "请等待冷静期结束后再确认。",
|
|
319
319
|
resetAcknowledgeRequired: "请先确认已了解这次操作可能消耗重置次数。",
|
|
320
320
|
resetAccountChanged: "登录账号已变更,请重新开始。",
|
|
321
|
+
resetUncertain: "服务端返回结果不确定。请再次确认,插件会复用同一个请求,不会另外发起一次重置。",
|
|
321
322
|
creditsNote: "仅显示 Codex 为此账户或工作区实际返回的额外 Credits、消费上限或额度重置次数;三者不是同一项。",
|
|
322
323
|
creditsUsed: "已用 {used} / {limit} credits",
|
|
323
324
|
spendReached: "Credits 月度消费上限已用尽。",
|
|
@@ -483,6 +484,7 @@ window.__ModuleLoader__.load({
|
|
|
483
484
|
resetTooEarly: "Wait for the cooldown before confirming.",
|
|
484
485
|
resetAcknowledgeRequired: "Confirm that you understand this may consume a reset.",
|
|
485
486
|
resetAccountChanged: "The signed-in account changed. Start again.",
|
|
487
|
+
resetUncertain: "The server result is uncertain. Confirm again to check the same request; the plugin will not start a separate reset.",
|
|
486
488
|
creditsNote: "Shows only extra Credits, spending caps, or quota resets returned for this account or workspace; these are separate items.",
|
|
487
489
|
creditsUsed: "{used} / {limit} credits used",
|
|
488
490
|
spendReached: "The monthly Credits spending cap has been reached.",
|
|
@@ -2310,7 +2312,8 @@ window.__ModuleLoader__.load({
|
|
|
2310
2312
|
["This quota reset is already in progress", "resetInProgress"],
|
|
2311
2313
|
["Wait before confirming this quota reset", "resetTooEarly"],
|
|
2312
2314
|
["You must acknowledge that this may consume one quota reset", "resetAcknowledgeRequired"],
|
|
2313
|
-
["The signed-in ChatGPT account changed", "resetAccountChanged"]
|
|
2315
|
+
["The signed-in ChatGPT account changed", "resetAccountChanged"],
|
|
2316
|
+
["Quota reset result is uncertain; retry this confirmation to check the same request", "resetUncertain"]
|
|
2314
2317
|
])).get(error instanceof Error ? error.message : "") ?? "resetFailed");
|
|
2315
2318
|
}
|
|
2316
2319
|
function UsageCard({ rpc, t, signedIn, resetKey }) {
|
package/lib/index.js
CHANGED
|
@@ -936,7 +936,7 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
|
|
|
936
936
|
}
|
|
937
937
|
//#endregion
|
|
938
938
|
//#region src/version.js
|
|
939
|
-
const PACKAGE_VERSION = "1.11.
|
|
939
|
+
const PACKAGE_VERSION = "1.11.1";
|
|
940
940
|
const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
|
|
941
941
|
//#endregion
|
|
942
942
|
//#region src/model-catalog.js
|
|
@@ -2156,6 +2156,7 @@ const DEFAULT_CONFIRM_DELAY_MS = 5e3;
|
|
|
2156
2156
|
const DEFAULT_CHALLENGE_TTL_MS = 6e4;
|
|
2157
2157
|
const DEFAULT_TIMEOUT_MS = 15e3;
|
|
2158
2158
|
const MAX_COPY_LENGTH = 240;
|
|
2159
|
+
const UNCERTAIN_RESET_RESULT = "Quota reset result is uncertain; retry this confirmation to check the same request";
|
|
2159
2160
|
const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2160
2161
|
const requestSignal = (signal, timeoutMs) => {
|
|
2161
2162
|
const timeout = AbortSignal.timeout(timeoutMs);
|
|
@@ -2232,8 +2233,8 @@ function createCodexResetCreditService(options) {
|
|
|
2232
2233
|
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
2233
2234
|
const challenges = /* @__PURE__ */ new Map();
|
|
2234
2235
|
const resolveCredentials = async (signal) => credentialsOf(await getAuth({ signal }), await readCredential({ signal }));
|
|
2235
|
-
const readDetails = async (signal) => {
|
|
2236
|
-
const { access, accountId } = await resolveCredentials(signal);
|
|
2236
|
+
const readDetails = async (signal, credentials) => {
|
|
2237
|
+
const { access, accountId } = credentials ?? await resolveCredentials(signal);
|
|
2237
2238
|
const response = await fetchReset(CODEX_RESET_CREDITS_URL, {
|
|
2238
2239
|
method: "GET",
|
|
2239
2240
|
redirect: "error",
|
|
@@ -2267,7 +2268,24 @@ function createCodexResetCreditService(options) {
|
|
|
2267
2268
|
};
|
|
2268
2269
|
},
|
|
2269
2270
|
async prepare({ signal } = {}) {
|
|
2270
|
-
const
|
|
2271
|
+
const credentials = await resolveCredentials(signal);
|
|
2272
|
+
for (const [challengeId, challenge] of challenges) {
|
|
2273
|
+
if (challenge.accountId !== credentials.accountId || challenge.uncertain !== true) continue;
|
|
2274
|
+
if (now() > challenge.expiresAt) {
|
|
2275
|
+
challenges.delete(challengeId);
|
|
2276
|
+
continue;
|
|
2277
|
+
}
|
|
2278
|
+
return {
|
|
2279
|
+
challengeId,
|
|
2280
|
+
availableCount: challenge.availableCount,
|
|
2281
|
+
readyAt: challenge.readyAt,
|
|
2282
|
+
expiresAt: challenge.expiresAt,
|
|
2283
|
+
...challenge.creditExpiresAt === void 0 ? {} : { creditExpiresAt: challenge.creditExpiresAt },
|
|
2284
|
+
...challenge.title === void 0 ? {} : { title: challenge.title },
|
|
2285
|
+
...challenge.description === void 0 ? {} : { description: challenge.description }
|
|
2286
|
+
};
|
|
2287
|
+
}
|
|
2288
|
+
const { accountId, details } = await readDetails(signal, credentials);
|
|
2271
2289
|
const preparedAt = now();
|
|
2272
2290
|
const readyAt = preparedAt + confirmDelayMs;
|
|
2273
2291
|
const expiresAt = Math.min(preparedAt + challengeTtlMs, details.creditExpiresAt ?? Number.MAX_SAFE_INTEGER);
|
|
@@ -2279,7 +2297,12 @@ function createCodexResetCreditService(options) {
|
|
|
2279
2297
|
creditId: details.creditId,
|
|
2280
2298
|
redeemRequestId: randomUUID$1(),
|
|
2281
2299
|
readyAt,
|
|
2282
|
-
expiresAt
|
|
2300
|
+
expiresAt,
|
|
2301
|
+
availableCount: details.availableCount,
|
|
2302
|
+
creditExpiresAt: details.creditExpiresAt,
|
|
2303
|
+
title: details.title,
|
|
2304
|
+
description: details.description,
|
|
2305
|
+
uncertain: false
|
|
2283
2306
|
});
|
|
2284
2307
|
return {
|
|
2285
2308
|
challengeId,
|
|
@@ -2302,38 +2325,66 @@ function createCodexResetCreditService(options) {
|
|
|
2302
2325
|
}
|
|
2303
2326
|
if (acknowledged !== true) throw new Error("You must acknowledge that this may consume one quota reset");
|
|
2304
2327
|
challenge.state = "pending";
|
|
2328
|
+
let retryable = challenge.uncertain === true;
|
|
2305
2329
|
try {
|
|
2306
2330
|
const { access, accountId } = await resolveCredentials(signal);
|
|
2307
|
-
if (accountId !== challenge.accountId)
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2331
|
+
if (accountId !== challenge.accountId) {
|
|
2332
|
+
retryable = false;
|
|
2333
|
+
throw new Error("The signed-in ChatGPT account changed");
|
|
2334
|
+
}
|
|
2335
|
+
let response;
|
|
2336
|
+
try {
|
|
2337
|
+
response = await fetchReset(CODEX_RESET_CONSUME_URL, {
|
|
2338
|
+
method: "POST",
|
|
2339
|
+
redirect: "error",
|
|
2340
|
+
headers: {
|
|
2341
|
+
authorization: `Bearer ${access}`,
|
|
2342
|
+
"chatgpt-account-id": accountId,
|
|
2343
|
+
accept: "application/json",
|
|
2344
|
+
"content-type": "application/json",
|
|
2345
|
+
"cache-control": "no-store",
|
|
2346
|
+
"user-agent": USER_AGENT
|
|
2347
|
+
},
|
|
2348
|
+
body: JSON.stringify({
|
|
2349
|
+
redeem_request_id: challenge.redeemRequestId,
|
|
2350
|
+
credit_id: challenge.creditId
|
|
2351
|
+
}),
|
|
2352
|
+
signal: requestSignal(signal, timeoutMs)
|
|
2353
|
+
});
|
|
2354
|
+
} catch {
|
|
2355
|
+
retryable = true;
|
|
2356
|
+
throw new Error(UNCERTAIN_RESET_RESULT);
|
|
2357
|
+
}
|
|
2358
|
+
if (!response.ok) {
|
|
2359
|
+
if (response.status >= 500) {
|
|
2360
|
+
retryable = true;
|
|
2361
|
+
throw new Error(UNCERTAIN_RESET_RESULT);
|
|
2362
|
+
}
|
|
2363
|
+
if (response.status !== 401 && response.status !== 403) retryable = false;
|
|
2364
|
+
throw new Error(response.status === 401 || response.status === 403 ? "ChatGPT sign-in needs to be renewed" : `ChatGPT quota reset request failed (HTTP ${response.status})`);
|
|
2365
|
+
}
|
|
2326
2366
|
let raw;
|
|
2327
2367
|
try {
|
|
2328
2368
|
raw = await response.json();
|
|
2329
2369
|
} catch {
|
|
2330
|
-
|
|
2370
|
+
retryable = true;
|
|
2371
|
+
throw new Error(UNCERTAIN_RESET_RESULT);
|
|
2331
2372
|
}
|
|
2332
|
-
|
|
2373
|
+
let result;
|
|
2374
|
+
try {
|
|
2375
|
+
result = parseConsumeResult(raw);
|
|
2376
|
+
} catch {
|
|
2377
|
+
retryable = true;
|
|
2378
|
+
throw new Error(UNCERTAIN_RESET_RESULT);
|
|
2379
|
+
}
|
|
2380
|
+
retryable = false;
|
|
2333
2381
|
usageReader.clear();
|
|
2334
2382
|
return result;
|
|
2335
2383
|
} finally {
|
|
2336
|
-
|
|
2384
|
+
if (retryable && now() <= challenge.expiresAt) {
|
|
2385
|
+
challenge.state = "prepared";
|
|
2386
|
+
challenge.uncertain = true;
|
|
2387
|
+
} else challenges.delete(challengeId);
|
|
2337
2388
|
}
|
|
2338
2389
|
},
|
|
2339
2390
|
clear() {
|
|
@@ -2347,7 +2398,6 @@ const name = "codex-subscription";
|
|
|
2347
2398
|
const inject = [
|
|
2348
2399
|
"llm",
|
|
2349
2400
|
"credentials",
|
|
2350
|
-
"connection",
|
|
2351
2401
|
"settings",
|
|
2352
2402
|
"web",
|
|
2353
2403
|
"loader",
|
|
@@ -2723,7 +2773,7 @@ function apply(ctx) {
|
|
|
2723
2773
|
ctx.effect(() => {
|
|
2724
2774
|
modelCatalog.refresh().catch((error) => ctx.logger?.debug?.("could not refresh Codex model catalog: %s", error.message));
|
|
2725
2775
|
}, "codex-subscription: official model catalog");
|
|
2726
|
-
ctx.effect(() =>
|
|
2776
|
+
ctx.inject(["connection"], (connectionContext) => connectionContext.effect(() => connectionContext.connection.rpc.handle(CHANNEL, handler, { authority: "trusted-host" }), "codex-subscription: DSH-trusted account RPC"));
|
|
2727
2777
|
}
|
|
2728
2778
|
//#endregion
|
|
2729
2779
|
export { CODEX_IMAGE_GENERATION_URL, CODEX_IMAGE_TOOL_NAME, CODEX_RESET_CONSUME_URL, CODEX_RESET_CREDITS_URL, CODEX_USAGE_URL, CodexLoginCoordinator, DshOAuthCredentialStore, apply, assertCodexAuthUrl, commandForCodexAuthUrl, createCodexAuthService, createCodexImageTool, createCodexResetCreditService, createCodexRpcHandler, createCodexUsageReader, createSearchProviderSwitcher, createSubscriptionDiagnostics, createSubscriptionRpcHandler, decodeCodexPng, inject, name, normalizeContextMode, normalizeCustomContextWindow, openCodexAuthUrl, parseCodexUsage };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-codex-subscription",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.1",
|
|
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",
|