dsh-codex-subscription 2.2.5 → 2.2.7
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.en.md +16 -2
- package/README.md +16 -2
- package/lib/client.js +18 -5
- package/lib/index.js +110 -10
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -31,7 +31,7 @@ Subscription access, model controls, quota management, and image creation in one
|
|
|
31
31
|
| Feature | What you can do | Availability / setup |
|
|
32
32
|
| --- | --- | --- |
|
|
33
33
|
| **Subscription sign-in** | Sign in to ChatGPT and use Codex subscription models without an API key | Normal chat needs no Codex CLI |
|
|
34
|
-
| **Model catalog sync** | Read available models and reasoning levels from your account, with manual refresh | New models appear when your account offers them |
|
|
34
|
+
| **Model catalog sync** | Read available models and reasoning levels from your account, with manual refresh; models marked for retirement show their retirement date next to the model name, without automatically switching your selection | New models appear when your account offers them |
|
|
35
35
|
| **Reasoning levels** | Choose supported reasoning effort in the composer | Levels vary by model |
|
|
36
36
|
| **Fast mode** | Switch supported models between Standard and Fast, with a lightning indicator | Standard by default; Fast increases usage |
|
|
37
37
|
| **Response verbosity** | Request short, medium, or detailed responses | Follows the model default unless changed |
|
|
@@ -87,7 +87,7 @@ Subscription access, model controls, quota management, and image creation in one
|
|
|
87
87
|
|
|
88
88
|
## Prepare DSH
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
Verified against DSH `0.2.0-rc.1` (`next` channel) and `0.1.7-rc.2` (`latest` channel), with earlier accepted versions still supported.
|
|
91
91
|
|
|
92
92
|
This plugin supports the latest DeepSeek Harness release recorded in its package metadata and requires a ChatGPT account that currently has Codex access.
|
|
93
93
|
|
|
@@ -270,6 +270,13 @@ dsh plugin --profile web remove dsh-codex-subscription
|
|
|
270
270
|
|
|
271
271
|
## Troubleshooting
|
|
272
272
|
|
|
273
|
+
<details>
|
|
274
|
+
<summary>DSH 0.2.0-rc.1 reports plugin 2.2.4 as incompatible?</summary>
|
|
275
|
+
|
|
276
|
+
DSH 0.2.0-rc.1 did not exist when 2.2.4 and earlier were published, and a published package's compatibility declaration cannot be changed. Update to 2.2.5 or later from the **Plugins** page, or run `dsh plugin --profile web update dsh-codex-subscription`, then restart DSH.
|
|
277
|
+
|
|
278
|
+
</details>
|
|
279
|
+
|
|
273
280
|
<details>
|
|
274
281
|
<summary>No dsh command on your computer?</summary>
|
|
275
282
|
|
|
@@ -303,6 +310,13 @@ The current plugin icon and its appearance in DSH’s Installed list.
|
|
|
303
310
|
|
|
304
311
|
<sub>Captured in DSH 0.1.7-alpha.2.</sub>
|
|
305
312
|
|
|
313
|
+
## Positioning and boundaries
|
|
314
|
+
|
|
315
|
+
- **ChatGPT / Codex subscription only**, done in depth: quota and forecasting, images and sketches, subtasks, diagnostics. Other subscriptions such as Claude or Grok are out of scope.
|
|
316
|
+
- **Fail explicitly**: requests never silently fall back to another paid route, and quota windows the account does not return are never invented.
|
|
317
|
+
- **Tracks official DSH releases**: every release is accepted end to end (install, start, remove, reinstall) against official DSH channels such as latest and next; verified versions are recorded in the [compatibility notes](docs/dsh-020-compatibility.md).
|
|
318
|
+
- Models, quota and features depend on what your account actually returns; the ChatGPT backend and DSH can change independently.
|
|
319
|
+
|
|
306
320
|
## Scope and support
|
|
307
321
|
|
|
308
322
|
The ChatGPT Codex backend and DSH can change independently. This community project is not affiliated with or endorsed by DeepSeek or OpenAI.
|
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
| 功能 | 你可以做什么 | 使用方式 / 条件 |
|
|
32
32
|
| --- | --- | --- |
|
|
33
33
|
| **订阅登录** | 直接登录 ChatGPT,使用 Codex 订阅模型,无需 API Key | 普通聊天无需 Codex CLI |
|
|
34
|
-
| **模型目录同步** |
|
|
34
|
+
| **模型目录同步** | 自动读取账号可用模型与推理档位,支持手动刷新;目录标注退役的模型会在模型名称旁显示退役日期,不会自动切换你的选择 | 新型号以账号目录开放情况为准 |
|
|
35
35
|
| **推理等级** | 在输入框选择模型支持的推理档位 | 档位随模型变化 |
|
|
36
36
|
| **高速模式** | 在支持的模型上切换标准 / Fast,输入框显示闪电标识 | 默认标准;Fast 会增加用量消耗 |
|
|
37
37
|
| **输出详略** | 选择简短、适中或详细的回答偏好 | 默认跟随模型 |
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
|
|
88
88
|
## 准备 DSH
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
已验证兼容 DSH `0.2.0-rc.1`(`next` 通道)和 `0.1.7-rc.2`(`latest` 通道),并继续支持更早的已验收版本。
|
|
91
91
|
|
|
92
92
|
本插件支持软件包元数据中记录的最新版 DeepSeek Harness,并需要一个当前具有 Codex 使用资格的 ChatGPT 账户。
|
|
93
93
|
|
|
@@ -270,6 +270,13 @@ dsh plugin --profile web remove dsh-codex-subscription
|
|
|
270
270
|
|
|
271
271
|
## 常见问题
|
|
272
272
|
|
|
273
|
+
<details>
|
|
274
|
+
<summary>DSH 0.2.0-rc.1 提示插件 2.2.4 不兼容?</summary>
|
|
275
|
+
|
|
276
|
+
2.2.4 及更早版本发布时 DSH 0.2.0-rc.1 还不存在,其兼容声明无法事后修改。请更新到 2.2.5 或更高版本:在 **插件** 页面更新,或运行 `dsh plugin --profile web update dsh-codex-subscription`,然后重启 DSH。
|
|
277
|
+
|
|
278
|
+
</details>
|
|
279
|
+
|
|
273
280
|
<details>
|
|
274
281
|
<summary>电脑没有 dsh 命令,怎么安装?</summary>
|
|
275
282
|
|
|
@@ -303,6 +310,13 @@ dsh plugin --profile web remove dsh-codex-subscription
|
|
|
303
310
|
|
|
304
311
|
<sub>DSH 0.1.7-alpha.2 实机界面。</sub>
|
|
305
312
|
|
|
313
|
+
## 定位与边界
|
|
314
|
+
|
|
315
|
+
- **只做 ChatGPT / Codex 订阅**,并把这一件事做深:额度与预测、图片与草图、子任务、诊断;不接入 Claude、Grok 等其他订阅。
|
|
316
|
+
- **失败就明确报错**:不会静默切换到其他付费路由,也不会虚构账号没有返回的额度窗口。
|
|
317
|
+
- **跟随官方 DSH 发布**:每次发版都用官方 DSH 的 latest、next 等通道做安装、启动、卸载、重装的端到端验收;已验证的版本见 [兼容性记录](docs/dsh-020-compatibility.md)。
|
|
318
|
+
- 模型、额度和功能开放情况以你的账号实际返回为准;ChatGPT 后端与 DSH 可能独立变化。
|
|
319
|
+
|
|
306
320
|
## 边界与支持
|
|
307
321
|
|
|
308
322
|
ChatGPT Codex 后端和 DSH 可能独立变化;本项目为社区项目,与 DeepSeek、OpenAI 无隶属或背书关系。
|
package/lib/client.js
CHANGED
|
@@ -734,7 +734,20 @@ window.__ModuleLoader__.load({
|
|
|
734
734
|
//#endregion
|
|
735
735
|
//#region src/image-conversation-node.js
|
|
736
736
|
const KIND = "codex-image-output";
|
|
737
|
-
const
|
|
737
|
+
const hasImage = (block) => block?.content?.some((part) => part.type === "image" && part.attachment);
|
|
738
|
+
const isImage = (part) => part?.type === "image" && part.attachment;
|
|
739
|
+
const resultsOf = (event) => {
|
|
740
|
+
if (event?.type !== "tool/result" || event.data.meta?.kind !== "codex-subscription-image") return [];
|
|
741
|
+
const content = event.data.message?.content ?? [];
|
|
742
|
+
const wrapped = content.filter((block) => block.type === "tool-result" && !block.isError && hasImage(block));
|
|
743
|
+
if (wrapped.length > 0) return wrapped;
|
|
744
|
+
return content.some(isImage) ? [{
|
|
745
|
+
type: "tool-result",
|
|
746
|
+
toolCallId: `${event.data.turn}:${event.data.step ?? event.seq}`,
|
|
747
|
+
isError: false,
|
|
748
|
+
content
|
|
749
|
+
}] : [];
|
|
750
|
+
};
|
|
738
751
|
const imageConversationNode = {
|
|
739
752
|
kind: KIND,
|
|
740
753
|
target: "chat",
|
|
@@ -1110,7 +1123,7 @@ window.__ModuleLoader__.load({
|
|
|
1110
1123
|
})
|
|
1111
1124
|
]
|
|
1112
1125
|
}),
|
|
1113
|
-
!showOutput || image === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1126
|
+
!showOutput && !settled || image === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1114
1127
|
className: "codexImageToolGallery",
|
|
1115
1128
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodexGeneratedImage, {
|
|
1116
1129
|
features,
|
|
@@ -4742,7 +4755,7 @@ window.__ModuleLoader__.load({
|
|
|
4742
4755
|
streamIdleTimeout_10: "10 分钟",
|
|
4743
4756
|
streamIdleTimeout_20: "20 分钟",
|
|
4744
4757
|
streamIdleTimeout_30: "30 分钟",
|
|
4745
|
-
subagentBackendHint: "Codex
|
|
4758
|
+
subagentBackendHint: "Codex 复用订阅登录和工作区权限;默认继承当前订阅模型。在“插件 → 子智能体”开启模型选择并勾选允许的模型后新建会话,可在聊天中指定允许的订阅模型与推理档位;非订阅会话需指定。共享上下文子任务仍用 DSH。",
|
|
4746
4759
|
subagentBackendUnavailable: "当前宿主缺少子代理服务,请更新 DSH。",
|
|
4747
4760
|
subagentRuntimeMissing: "尚未准备 Codex 子任务运行时,仅影响此选项。普通订阅对话无需安装。",
|
|
4748
4761
|
subagentRuntimePrepare: "准备方法(含离线说明)",
|
|
@@ -5290,7 +5303,7 @@ window.__ModuleLoader__.load({
|
|
|
5290
5303
|
streamIdleTimeout_10: "10 min",
|
|
5291
5304
|
streamIdleTimeout_20: "20 min",
|
|
5292
5305
|
streamIdleTimeout_30: "30 min",
|
|
5293
|
-
subagentBackendHint: "Codex reuses subscription login and workspace permissions, inheriting the current subscription model by default.
|
|
5306
|
+
subagentBackendHint: "Codex reuses subscription login and workspace permissions, inheriting the current subscription model by default. Turn on model selection under Plugins → Subagent, tick the allowed models and start a new session to request an allowed subscription model and reasoning effort in chat; other model sessions require an explicit selection. Shared-context subtasks stay in DSH.",
|
|
5294
5307
|
subagentBackendUnavailable: "Subagent services are unavailable. Update DSH to use this option.",
|
|
5295
5308
|
subagentRuntimeMissing: "Codex subtask runtime is not prepared. Subscription chat does not require it.",
|
|
5296
5309
|
subagentRuntimePrepare: "Setup and offline instructions",
|
|
@@ -7623,7 +7636,7 @@ window.__ModuleLoader__.load({
|
|
|
7623
7636
|
}
|
|
7624
7637
|
//#endregion
|
|
7625
7638
|
//#region src/version.js
|
|
7626
|
-
const PACKAGE_VERSION = "2.2.
|
|
7639
|
+
const PACKAGE_VERSION = "2.2.7";
|
|
7627
7640
|
//#endregion
|
|
7628
7641
|
//#region src/client-recovery.js
|
|
7629
7642
|
async function recoveryCall(rpc, endpoint, payload = {}, timeoutMs = 1e4) {
|
package/lib/index.js
CHANGED
|
@@ -1277,9 +1277,29 @@ function subagentThreadPolicy(parent, policy, requested = {}) {
|
|
|
1277
1277
|
modelProvider: "openai",
|
|
1278
1278
|
approvalPolicy: "never",
|
|
1279
1279
|
sandbox: policy.mode,
|
|
1280
|
-
config:
|
|
1280
|
+
config: {
|
|
1281
|
+
...CHILD_FEATURES_OFF,
|
|
1282
|
+
...effort === void 0 ? {} : { model_reasoning_effort: effort }
|
|
1283
|
+
}
|
|
1281
1284
|
};
|
|
1282
1285
|
}
|
|
1286
|
+
/**
|
|
1287
|
+
* A ChatGPT-authenticated Codex child would otherwise expose the account's
|
|
1288
|
+
* connected apps (calendar, site deploys, ...) and plugin installs, all
|
|
1289
|
+
* auto-approved. A DSH subtask gets the workspace tools only.
|
|
1290
|
+
*/
|
|
1291
|
+
const CHILD_FEATURES_OFF = Object.freeze({ features: Object.freeze(Object.fromEntries([
|
|
1292
|
+
"apps",
|
|
1293
|
+
"plugins",
|
|
1294
|
+
"plugin_sharing",
|
|
1295
|
+
"remote_plugin",
|
|
1296
|
+
"tool_suggest",
|
|
1297
|
+
"browser_use",
|
|
1298
|
+
"browser_use_external",
|
|
1299
|
+
"browser_use_full_cdp_access",
|
|
1300
|
+
"computer_use",
|
|
1301
|
+
"in_app_browser"
|
|
1302
|
+
].map((name) => [name, false]))) });
|
|
1283
1303
|
/** Reuse the official DSH process/turn provider; keep only subscription auth here. */
|
|
1284
1304
|
function createSubscriptionSubagent({ ctx, nativeHome, resolveAuth, store, refresh, loadRuntime, maintenance = () => false }) {
|
|
1285
1305
|
let runtime;
|
|
@@ -1385,6 +1405,20 @@ function createSubscriptionSubagent({ ctx, nativeHome, resolveAuth, store, refre
|
|
|
1385
1405
|
}
|
|
1386
1406
|
};
|
|
1387
1407
|
}
|
|
1408
|
+
/**
|
|
1409
|
+
* DSH 0.2 mounts Agent preset rows once, at boot and before plugins load, so the
|
|
1410
|
+
* Loader never lists them and `internal/config` never reaches a later listener.
|
|
1411
|
+
* Read them from the preset registry; a host without it simply has none.
|
|
1412
|
+
*/
|
|
1413
|
+
function presetEntries(ctx) {
|
|
1414
|
+
try {
|
|
1415
|
+
const generations = ctx.get?.("agentPresets")?.generations;
|
|
1416
|
+
if (!(generations instanceof Map)) return [];
|
|
1417
|
+
return [...generations.values()].flatMap((generation) => [...generation.mount?.tree?.entries?.() ?? []]);
|
|
1418
|
+
} catch {
|
|
1419
|
+
return [];
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1388
1422
|
/** Change only standard independent spawn tools; leave fork/custom tools untouched. */
|
|
1389
1423
|
function createSubagentBackendSwitcher({ entries, prepare, persist }) {
|
|
1390
1424
|
const originals = /* @__PURE__ */ new Map();
|
|
@@ -3010,7 +3044,7 @@ async function readSubscriptionCredentials(getAuth, readCredential, signal) {
|
|
|
3010
3044
|
}
|
|
3011
3045
|
//#endregion
|
|
3012
3046
|
//#region src/version.js
|
|
3013
|
-
const PACKAGE_VERSION = "2.2.
|
|
3047
|
+
const PACKAGE_VERSION = "2.2.7";
|
|
3014
3048
|
const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
|
|
3015
3049
|
//#endregion
|
|
3016
3050
|
//#region src/model-catalog.js
|
|
@@ -3028,6 +3062,43 @@ const DEFAULT_REFRESH_TIMEOUT_MS = 1e4;
|
|
|
3028
3062
|
const record$4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3029
3063
|
const nonEmpty$2 = (value) => typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
3030
3064
|
const positiveInteger$1 = (value) => Number.isSafeInteger(value) && value > 0 ? value : void 0;
|
|
3065
|
+
function upgradeModelId(value) {
|
|
3066
|
+
return (typeof value.upgrade === "string" ? nonEmpty$2(value.upgrade) : record$4(value.upgrade) ? nonEmpty$2(value.upgrade.model) : void 0) ?? (record$4(value.upgrade_info) ? nonEmpty$2(value.upgrade_info.model) : void 0) ?? (record$4(value.upgradeInfo) ? nonEmpty$2(value.upgradeInfo.model) : void 0);
|
|
3067
|
+
}
|
|
3068
|
+
function retirementMillis(value) {
|
|
3069
|
+
for (const source of [
|
|
3070
|
+
value,
|
|
3071
|
+
value.upgrade,
|
|
3072
|
+
value.upgrade_info,
|
|
3073
|
+
value.upgradeInfo
|
|
3074
|
+
]) {
|
|
3075
|
+
if (!record$4(source)) continue;
|
|
3076
|
+
for (const raw of [source.retirement_at, source.retirementAt]) {
|
|
3077
|
+
const seconds = positiveInteger$1(raw);
|
|
3078
|
+
if (seconds !== void 0 && Number.isSafeInteger(seconds * 1e3)) return seconds * 1e3;
|
|
3079
|
+
if (typeof raw === "string" && /^\d{4}-\d{2}-\d{2}T[\d:.]+(?:Z|[+-]\d{2}:\d{2})$/u.test(raw)) {
|
|
3080
|
+
const parsed = Date.parse(raw);
|
|
3081
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
3082
|
+
}
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
}
|
|
3086
|
+
function retirementNotice(value, now = Date.now(), targetDisplayName) {
|
|
3087
|
+
if (!record$4(value) || !Number.isFinite(now)) return void 0;
|
|
3088
|
+
const at = retirementMillis(value);
|
|
3089
|
+
if (at === void 0 || at <= now) return void 0;
|
|
3090
|
+
const date = new Date(at);
|
|
3091
|
+
if (!Number.isFinite(date.getTime())) return void 0;
|
|
3092
|
+
const dateText = `${String(date.getUTCFullYear()).padStart(4, "0")}-${String(date.getUTCMonth() + 1).padStart(2, "0")}-${String(date.getUTCDate()).padStart(2, "0")}`;
|
|
3093
|
+
const upgradeTo = upgradeModelId(value);
|
|
3094
|
+
const upgradeName = upgradeTo === void 0 ? void 0 : nonEmpty$2(targetDisplayName) ?? upgradeTo;
|
|
3095
|
+
return {
|
|
3096
|
+
text: `Retires on ${dateText} (UTC).${upgradeName === void 0 ? "" : ` Switch to ${upgradeName} to keep working.`}`,
|
|
3097
|
+
at,
|
|
3098
|
+
upgradeTo,
|
|
3099
|
+
dateText
|
|
3100
|
+
};
|
|
3101
|
+
}
|
|
3031
3102
|
function reasoningMap(levels) {
|
|
3032
3103
|
const supported = new Set((Array.isArray(levels) ? levels : []).map((level) => nonEmpty$2(record$4(level) ? level.effort : void 0)).filter(Boolean));
|
|
3033
3104
|
const map = Object.fromEntries(LEVELS.map((level) => [level, null]));
|
|
@@ -3052,7 +3123,7 @@ function unsupportedCapabilities(value) {
|
|
|
3052
3123
|
...speeds.length ? { speeds } : {}
|
|
3053
3124
|
};
|
|
3054
3125
|
}
|
|
3055
|
-
function visibleModel(value) {
|
|
3126
|
+
function visibleModel(value, displayNames, now) {
|
|
3056
3127
|
if (!record$4(value)) return void 0;
|
|
3057
3128
|
const id = nonEmpty$2(value.slug);
|
|
3058
3129
|
const reserve = id === "gpt-reserve" && ["list", "hide"].includes(value.visibility);
|
|
@@ -3063,11 +3134,19 @@ function visibleModel(value) {
|
|
|
3063
3134
|
...value,
|
|
3064
3135
|
supported_reasoning_levels: supported
|
|
3065
3136
|
});
|
|
3137
|
+
const upgradeTo = upgradeModelId(value);
|
|
3138
|
+
const retirement = retirementNotice(value, now, displayNames.get(upgradeTo));
|
|
3139
|
+
const notice = retirement?.text;
|
|
3140
|
+
const description = nonEmpty$2(value.description);
|
|
3066
3141
|
return {
|
|
3067
3142
|
...Object.keys(unsupported).length ? { unsupported } : {},
|
|
3068
3143
|
id,
|
|
3069
|
-
name: reserve ? "GPT-Reserve (Experimental)" : nonEmpty$2(value.display_name) ?? id
|
|
3070
|
-
description:
|
|
3144
|
+
name: `${reserve ? "GPT-Reserve (Experimental)" : nonEmpty$2(value.display_name) ?? id}${retirement === void 0 ? "" : ` (retires ${retirement.dateText})`}`,
|
|
3145
|
+
description: notice === void 0 ? description : description === void 0 ? notice : `${description}\n${notice}`,
|
|
3146
|
+
...retirement === void 0 ? {} : { retirement: {
|
|
3147
|
+
at: retirement.at,
|
|
3148
|
+
upgradeTo: retirement.upgradeTo
|
|
3149
|
+
} },
|
|
3071
3150
|
priority: Number.isFinite(value.priority) ? value.priority : 0,
|
|
3072
3151
|
input: input.length > 0 ? input : ["text"],
|
|
3073
3152
|
contextWindow: positiveInteger$1(value.context_window) ?? positiveInteger$1(value.max_context_window),
|
|
@@ -3083,10 +3162,17 @@ function visibleModel(value) {
|
|
|
3083
3162
|
supportsFast: [...Array.isArray(value.additional_speed_tiers) ? value.additional_speed_tiers : [], ...Array.isArray(value.service_tiers) ? value.service_tiers.map((tier) => tier?.id) : []].some((tier) => tier === "fast" || tier === "priority")
|
|
3084
3163
|
};
|
|
3085
3164
|
}
|
|
3086
|
-
function parseOfficialModelCatalog(value) {
|
|
3165
|
+
function parseOfficialModelCatalog(value, now = Date.now()) {
|
|
3087
3166
|
if (!record$4(value) || !Array.isArray(value.models)) throw new Error("Codex returned a malformed model catalog");
|
|
3167
|
+
const displayNames = /* @__PURE__ */ new Map();
|
|
3168
|
+
for (const model of value.models) {
|
|
3169
|
+
if (!record$4(model)) continue;
|
|
3170
|
+
const id = nonEmpty$2(model.slug);
|
|
3171
|
+
const name = nonEmpty$2(model.display_name);
|
|
3172
|
+
if (id !== void 0 && name !== void 0 && !displayNames.has(id)) displayNames.set(id, name);
|
|
3173
|
+
}
|
|
3088
3174
|
const seen = /* @__PURE__ */ new Set();
|
|
3089
|
-
return value.models.map(visibleModel).filter((model) => model !== void 0 && !seen.has(model.id) && seen.add(model.id)).sort((left, right) => Number(left.id === "gpt-reserve") - Number(right.id === "gpt-reserve") || right.priority - left.priority);
|
|
3175
|
+
return value.models.map((model) => visibleModel(model, displayNames, now)).filter((model) => model !== void 0 && !seen.has(model.id) && seen.add(model.id)).sort((left, right) => Number(left.id === "gpt-reserve") - Number(right.id === "gpt-reserve") || right.priority - left.priority);
|
|
3090
3176
|
}
|
|
3091
3177
|
function mergeModel(baseModels, remote) {
|
|
3092
3178
|
const base = baseModels.find((model) => model.id === remote.id) ?? baseModels.find((model) => model.id !== "gpt-5.3-codex-spark") ?? baseModels[0];
|
|
@@ -3095,6 +3181,7 @@ function mergeModel(baseModels, remote) {
|
|
|
3095
3181
|
...base,
|
|
3096
3182
|
id: remote.id,
|
|
3097
3183
|
name: remote.name,
|
|
3184
|
+
...remote.retirement === void 0 || remote.description === void 0 ? {} : { description: remote.description },
|
|
3098
3185
|
input: remote.input,
|
|
3099
3186
|
reasoning: remote.reasoning,
|
|
3100
3187
|
thinkingLevelMap: remote.thinkingLevelMap,
|
|
@@ -3110,12 +3197,14 @@ function mergeModel(baseModels, remote) {
|
|
|
3110
3197
|
}
|
|
3111
3198
|
function createOfficialModelCatalog(options = {}) {
|
|
3112
3199
|
const fetchCatalog = options.fetch ?? fetch;
|
|
3200
|
+
const getNow = options.now ?? Date.now;
|
|
3113
3201
|
const scheduleTimeout = options.setTimeout ?? setTimeout;
|
|
3114
3202
|
const cancelTimeout = options.clearTimeout ?? clearTimeout;
|
|
3115
3203
|
const timeoutMs = Number.isFinite(options.timeoutMs) && options.timeoutMs > 0 ? options.timeoutMs : DEFAULT_REFRESH_TIMEOUT_MS;
|
|
3116
3204
|
let models;
|
|
3117
3205
|
let metadata = /* @__PURE__ */ new Map();
|
|
3118
3206
|
let etag;
|
|
3207
|
+
let rawCatalog;
|
|
3119
3208
|
let revision = 0;
|
|
3120
3209
|
let refreshing;
|
|
3121
3210
|
let generation = 0;
|
|
@@ -3155,10 +3244,19 @@ function createOfficialModelCatalog(options = {}) {
|
|
|
3155
3244
|
if (currentGeneration !== generation || requestSignal.aborted) return false;
|
|
3156
3245
|
if (response.status === 304) {
|
|
3157
3246
|
outcome = "ok";
|
|
3158
|
-
return false;
|
|
3247
|
+
if (rawCatalog === void 0) return false;
|
|
3248
|
+
const remote = parseOfficialModelCatalog(rawCatalog, getNow());
|
|
3249
|
+
const next = remote.map((model) => mergeModel(options.baseModels(), model)).filter(Boolean);
|
|
3250
|
+
if (next.length === 0 || JSON.stringify(next) === JSON.stringify(models)) return false;
|
|
3251
|
+
models = next;
|
|
3252
|
+
metadata = new Map(remote.map((model) => [model.id, model]));
|
|
3253
|
+
revision += 1;
|
|
3254
|
+
options.onUpdated?.();
|
|
3255
|
+
return true;
|
|
3159
3256
|
}
|
|
3160
3257
|
if (!response.ok) throw new Error(`Codex model catalog failed (HTTP ${response.status})`);
|
|
3161
|
-
const
|
|
3258
|
+
const raw = await response.json();
|
|
3259
|
+
const remote = parseOfficialModelCatalog(raw, getNow());
|
|
3162
3260
|
if (currentGeneration !== generation || requestSignal.aborted) return false;
|
|
3163
3261
|
if (remote.length === 0) throw new Error("Codex returned an empty model catalog");
|
|
3164
3262
|
const baseModels = options.baseModels();
|
|
@@ -3166,6 +3264,7 @@ function createOfficialModelCatalog(options = {}) {
|
|
|
3166
3264
|
if (next.length === 0) throw new Error("Codex model catalog has no compatible models");
|
|
3167
3265
|
if (currentGeneration !== generation || requestSignal.aborted) return false;
|
|
3168
3266
|
models = next;
|
|
3267
|
+
rawCatalog = raw;
|
|
3169
3268
|
metadata = new Map(remote.map((model) => [model.id, model]));
|
|
3170
3269
|
etag = nonEmpty$2(response.headers.get("etag")) ?? etag;
|
|
3171
3270
|
revision += 1;
|
|
@@ -3219,6 +3318,7 @@ function createOfficialModelCatalog(options = {}) {
|
|
|
3219
3318
|
refreshing = void 0;
|
|
3220
3319
|
flight?.cancel();
|
|
3221
3320
|
models = void 0;
|
|
3321
|
+
rawCatalog = void 0;
|
|
3222
3322
|
metadata = /* @__PURE__ */ new Map();
|
|
3223
3323
|
etag = void 0;
|
|
3224
3324
|
refreshStatus = "idle";
|
|
@@ -6047,7 +6147,7 @@ function apply(ctx, config = {}) {
|
|
|
6047
6147
|
});
|
|
6048
6148
|
scoped.subagents.registerProvider(instance.provider);
|
|
6049
6149
|
const switcher = createSubagentBackendSwitcher({
|
|
6050
|
-
entries: () => scoped.loader.entries(),
|
|
6150
|
+
entries: () => [...scoped.loader.entries(), ...presetEntries(scoped)],
|
|
6051
6151
|
prepare: instance.prepare,
|
|
6052
6152
|
persist: (mode) => settings.update({ subagentBackend: mode })
|
|
6053
6153
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-codex-subscription",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.7",
|
|
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",
|