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 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
- Compatible with DSH `0.2.0-rc.1` plugin compatibility checks and settings APIs, while retaining support for previously supported versions.
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
- 已适配 DSH `0.2.0-rc.1` 的插件兼容性检查与设置接口,同时保留已支持版本的兼容。
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 resultsOf = (event) => event?.type === "tool/result" && event.data.meta?.kind === "codex-subscription-image" ? (event.data.message?.content ?? []).filter((block) => block.type === "tool-result" && !block.isError && block.content?.some((part) => part.type === "image" && part.attachment)) : [];
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 复用订阅登录和工作区权限;默认继承当前订阅模型。开启 DSH 子任务模型选择并新建会话后,可在聊天中指定允许的订阅模型与推理档位;非订阅会话需指定。共享上下文子任务仍用 DSH。",
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. Enable DSH subtask model selection 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.",
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.5";
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: effort === void 0 ? {} : { model_reasoning_effort: effort }
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.5";
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: nonEmpty$2(value.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 remote = parseOfficialModelCatalog(await response.json());
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.5",
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",