dsh-codex-subscription 2.2.11 → 2.3.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/README.en.md CHANGED
@@ -16,12 +16,21 @@ No OpenAI API key or Codex CLI. Models, search, quota, and image generation stay
16
16
  [![MIT](https://img.shields.io/badge/license-MIT-111111.svg)](LICENSE)
17
17
  [![Star](https://img.shields.io/github/stars/WSL043/dsh-codex-subscription?style=flat&logo=github&label=Star)](https://github.com/WSL043/dsh-codex-subscription/stargazers)
18
18
 
19
- [Features](#feature-overview) · [Install](#install) · [Daily use](#inside-the-plugin) · [Examples](#from-sketch-to-image) · [User guide](docs/GUIDE.en.md) · [Update and uninstall](#update-and-uninstall)
19
+ [What's new](#whats-new-in-230) · [Features](#feature-overview) · [Install](#install) · [Daily use](#inside-the-plugin) · [Examples](#from-sketch-to-image) · [User guide](docs/GUIDE.en.md) · [Update and uninstall](#update-and-uninstall)
20
20
 
21
21
  </div>
22
22
 
23
23
  <p align="center"><img src="docs/assets/product-account-demo-en.png" width="1100" alt="Codex subscription account and quota interface with model choices, quota windows and alerts; demonstration data"></p>
24
24
 
25
+ ## What's new in 2.3.0
26
+
27
+ - **The official desktop app works.** The official DeepSeek Harness desktop app (0.2.0-rc.2) passed a hands-on acceptance run: plugin install, sign-in, model list, hiding models, a chat with a tool call, and image generation. See [Install](#install).
28
+ - **Models come only from your account.** The model list is read entirely from the account catalog; before sign-in or when the read fails no model is shown, and there is no built-in fallback. Under Models & runtime you can show or hide each model in the composer.
29
+ - **Settings reorganised.** Models and search are separate cards, switches use DSH's own control, and dead buttons no longer appear while signed out.
30
+ - **Ultrafast speed tier (Beta).** The new tier from OpenAI's developer event. It appears in the model menu only when your account catalog lists it for that model (today Pro 500 with GPT-6 Astra); other accounts never see it and it is never silently swapped for another tier. It is Beta because it has not been run on a Pro 500 account yet.
31
+ - **Shorter support diagnostics.** "Copy report" now copies the conclusions, recent failures and per-feature status (about 1 KB); the full report can still be copied separately from the details.
32
+ - **Subtasks and stability.** Codex subtasks now really take effect on 0.2.0 and no longer expose the apps connected to your account; image generation being rejected by the host on the desktop app is fixed (2.2.11).
33
+
25
34
  ## Feature overview
26
35
 
27
36
  Subscription access, model controls, quota management, and image creation in one DSH workflow. Each capability is listed below; model access and quota depend on your account.
@@ -34,7 +43,7 @@ Subscription access, model controls, quota management, and image creation in one
34
43
  | **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; the account catalog is the only source, so signed out or when it cannot be read no models are shown and no bundled list stands in |
35
44
  | **Model list** | Show or hide individual models in the composer picker under Models & runtime | Display only; selected models and requests still work |
36
45
  | **Reasoning levels** | Choose supported reasoning effort in the composer | Levels vary by model |
37
- | **Fast mode** | Switch supported models between Standard and Fast, with a lightning indicator | Standard by default; Fast increases usage |
46
+ | **Speed tiers** | Switch supported models between Standard and Fast; Ultrafast (Beta) too when the account catalog offers it, with a lightning indicator | Standard by default; Fast and Ultrafast increase usage, and Ultrafast is Pro 500 only today |
38
47
  | **Response verbosity** | Request short, medium, or detailed responses | Follows the model default unless changed |
39
48
  | **Input image detail** | Choose Low, High, Original, or Auto detail for images sent to the chat model | Affects input tokens; Auto by default |
40
49
  | **Subscription web search** | Use Codex search or choose DSH search | Auto, DSH, and Codex routing options |
@@ -81,7 +90,7 @@ Subscription access, model controls, quota management, and image creation in one
81
90
  | **Subtask component management** | Install, disable, or uninstall the official Codex subtask component from settings | Managed by supported DSH hosts; no extra login |
82
91
  | **Cloud context compaction** | Continue long conversations using Codex compaction while retaining DSH history and native compaction | Beta / experimental; off by default, enabled requests use SSE |
83
92
  | **WebSocket transport** | Experimentally reuse connections and context transfers, with SSE fallback on connection failure | Beta / experimental; SSE by default, no speed guarantee |
84
- | **Support diagnostics** | Inspect prerequisites, recent operation results and host registrations without credentials or conversation text | Settings → Maintenance; unverified does not mean broken |
93
+ | **Support diagnostics** | Inspect prerequisites and recent operation results, and copy a short report (about 1 KB; the full one can be copied separately) without credentials or conversation text | Settings → Maintenance; unverified does not mean broken |
85
94
  | **Forecast cache cleanup** | Inspect and clear local quota forecast history | Keeps sign-in, drafts, originals, and shared dependencies |
86
95
 
87
96
  [Usage details, limitations, and optional components →](docs/GUIDE.en.md)
@@ -104,7 +113,7 @@ This plugin supports the latest DeepSeek Harness release recorded in its package
104
113
  2. Paste this package name, with its version, into the **Package name or address** field:
105
114
 
106
115
  ```text
107
- dsh-codex-subscription@2.2.11
116
+ dsh-codex-subscription@2.3.0
108
117
  ```
109
118
 
110
119
  3. Click **Install** and wait for completion. Follow the page instructions; save your work before restarting if requested.
@@ -139,7 +148,7 @@ dsh --profile headless "Reply with only the word: ok"
139
148
 
140
149
  ### Everyday controls, right in the composer
141
150
 
142
- Choose a model, adjust reasoning, enable Fast mode, and check remaining quota without opening settings for every request.
151
+ Choose a model, adjust reasoning, switch speed tiers, and check remaining quota without opening settings for every request.
143
152
 
144
153
  <p align="center"><img src="docs/assets/composer-quota-en.png" width="800" alt="DSH composer with GPT-6-Luna, reasoning controls and remaining quota"></p>
145
154
 
package/README.md CHANGED
@@ -16,12 +16,21 @@
16
16
  [![MIT](https://img.shields.io/badge/license-MIT-111111.svg)](LICENSE)
17
17
  [![Star](https://img.shields.io/github/stars/WSL043/dsh-codex-subscription?style=flat&logo=github&label=Star)](https://github.com/WSL043/dsh-codex-subscription/stargazers)
18
18
 
19
- [功能](#功能一览) · [安装](#安装) · [日常使用](#界面一览) · [作品案例](#从草图到作品) · [使用指南](docs/GUIDE.zh-CN.md) · [更新与卸载](#更新与卸载)
19
+ [更新亮点](#230-更新亮点) · [功能](#功能一览) · [安装](#安装) · [日常使用](#界面一览) · [作品案例](#从草图到作品) · [使用指南](docs/GUIDE.zh-CN.md) · [更新与卸载](#更新与卸载)
20
20
 
21
21
  </div>
22
22
 
23
23
  <p align="center"><img src="docs/assets/product-account-demo.png" width="1100" alt="Codex 订阅账号与额度界面:模型选择、双周期额度与提醒;使用演示数据"></p>
24
24
 
25
+ ## 2.3.0 更新亮点
26
+
27
+ - **官方桌面端可用**:DeepSeek Harness 官方桌面版(0.2.0-rc.2)已完成实机验收——安装插件、登录、模型列表、隐藏模型、带工具调用的对话、图片生成均通过;安装方式见[安装](#安装)。
28
+ - **模型只来自你的账号**:模型列表完全读取账号目录,登录前或读取失败时不显示任何模型,也没有内置兜底;“模型与运行”里可逐个显示 / 隐藏输入框中的模型。
29
+ - **设置页重新整理**:模型与搜索分成两个卡片,开关统一使用 DSH 自带控件,未登录时不再出现无效按钮。
30
+ - **极速档 Ultrafast(Beta)**:OpenAI 发布会新增的速度档。只有账号模型目录明确给出该档位(目前为 Pro 500 的 GPT-6 Astra)才会在模型菜单里出现,其他账号不显示,也不会被悄悄降级到别的档位;由于暂无 Pro 500 账号做实机验证,标为 Beta。
31
+ - **更短的支持诊断**:“复制诊断”现在只复制结论、近期失败和各能力状态(约 1 KB),完整报告仍可在详情里单独复制。
32
+ - **子任务与稳定性**:Codex 子任务在 0.2.0 上真正生效,并且不再暴露账号里连接的应用;修复了图片生成在桌面版上被宿主拒绝的问题(2.2.11)。
33
+
25
34
  ## 功能一览
26
35
 
27
36
  把订阅接入、模型控制、额度管理和图片创作放在同一个 DSH 工作流里。下面逐项列出插件提供的能力;模型权限和额度以账号实际返回为准。
@@ -34,7 +43,7 @@
34
43
  | **模型目录同步** | 自动读取账号可用模型与推理档位,支持手动刷新;目录标注退役的模型会在模型名称旁显示退役日期,不会自动切换你的选择 | 新型号以账号目录开放情况为准;模型只来自账号目录,未登录或读取失败时不显示任何模型,也不使用内置列表 |
35
44
  | **模型列表** | 在“模型与运行”中逐个显示或隐藏输入框中的模型 | 仅影响列表显示;已选模型和请求不受影响 |
36
45
  | **推理等级** | 在输入框选择模型支持的推理档位 | 档位随模型变化 |
37
- | **高速模式** | 在支持的模型上切换标准 / Fast,输入框显示闪电标识 | 默认标准;Fast 会增加用量消耗 |
46
+ | **速度档位** | 在支持的模型上切换标准 / Fast;账号目录提供时还有 Ultrafast(Beta),输入框显示闪电标识 | 默认标准;Fast 和 Ultrafast 会增加用量消耗,Ultrafast 目前仅 Pro 500 |
38
47
  | **输出详略** | 选择简短、适中或详细的回答偏好 | 默认跟随模型 |
39
48
  | **输入图片精度** | 为发送给聊天模型的图片选择低、高、原图或自动精度 | 影响输入 token 用量;默认自动 |
40
49
  | **订阅联网搜索** | 使用 Codex 搜索,或选择 DSH 搜索 | 可选自动、DSH、Codex 路由 |
@@ -81,7 +90,7 @@
81
90
  | **子任务组件管理** | 在设置里安装、停用或卸载官方 Codex 子任务组件 | 由支持的 DSH 宿主管理,无需额外登录 |
82
91
  | **云端上下文压缩** | 使用 Codex 云端压缩继续长对话,同时保留 DSH 历史与原生压缩 | Beta / 实验性;默认关闭,开启的请求使用 SSE |
83
92
  | **WebSocket 连接** | 实验性复用连接和上下文传输,连接失败可回退 SSE | Beta / 实验性;默认 SSE,不保证更快 |
84
- | **支持诊断** | 查看功能前置条件、近期操作结果与宿主注册信息;报告不含凭据和会话正文 | 设置 → 维护;未验证不代表故障 |
93
+ | **支持诊断** | 查看功能前置条件和近期操作结果,一键复制约 1 KB 的精简报告(完整报告可另行复制);不含凭据和会话正文 | 设置 → 维护;未验证不代表故障 |
85
94
  | **预测缓存清理** | 查看并清理本地额度预测历史 | 保留登录、草稿、原图和共享依赖 |
86
95
 
87
96
  [详细用法、限制与可选组件 →](docs/GUIDE.zh-CN.md)
@@ -104,7 +113,7 @@
104
113
  2. 在 **包名或地址** 输入框中粘贴下面的包名(已带版本号):
105
114
 
106
115
  ```text
107
- dsh-codex-subscription@2.2.11
116
+ dsh-codex-subscription@2.3.0
108
117
  ```
109
118
 
110
119
  3. 点击 **安装**,等待安装完成;按页面提示操作,需要重启时先保存工作。
@@ -139,7 +148,7 @@ dsh --profile headless "只回复:ok"
139
148
 
140
149
  ### 日常操作,留在输入框
141
150
 
142
- 选模型、调推理档位、开启高速模式,同时查看剩余额度。无需为每次请求打开设置。
151
+ 选模型、调推理档位、切换速度档位,同时查看剩余额度。无需为每次请求打开设置。
143
152
 
144
153
  <p align="center"><img src="docs/assets/composer-astra-fast.png" width="800" alt="DSH 输入框:GPT-6-Astra Max、闪电标识的 Fast 高速模式与剩余额度"></p>
145
154
 
package/lib/client.js CHANGED
@@ -4977,6 +4977,8 @@ window.__ModuleLoader__.load({
4977
4977
  quotaAlertsHint: "低于所选剩余阈值时提醒;自定义可分别设置短周期与长周期。仅使用新鲜数据,不弹窗打断。",
4978
4978
  quotaWarning: "{window}额度剩余 {value}%,请留意用量与重置时间。",
4979
4979
  speedFastAstraHint: "Astra 约 2 倍速度,消耗更多 Credits",
4980
+ speedUltrafast: "极速 Beta",
4981
+ speedUltrafastHint: "Ultrafast 档,仅账号目录提供时显示(目前为 Pro 500);速度最快,额度和 Credits 消耗更快",
4980
4982
  imageEditLocation: "位置",
4981
4983
  imageEditReferenceGuide: "本次编辑的干净源图为「{sourceName}」,编号定位参考图为「{referenceName}」。坐标以图片左上角为原点,x 向右、y 向下,百分比相对于整张图片。请查看这两张图片,将它们同时作为编辑工具的参考图,并在工具提示词中完整保留下方编号、位置和修改要求。只修改源图中对应位置的内容;定位参考图上的编号、圆点和引线仅用于定位,不得绘入最终结果。若无法读取两张图片或确定位置,请说明问题,不要猜测或忽略标注。",
4982
4984
  nav: "Codex 订阅",
@@ -5010,7 +5012,8 @@ window.__ModuleLoader__.load({
5010
5012
  diagnostics: "支持诊断",
5011
5013
  diagnosticsLoad: "生成诊断",
5012
5014
  diagnosticsLoading: "生成中…",
5013
- diagnosticsCopy: "复制诊断",
5015
+ diagnosticsCopy: "复制诊断(精简)",
5016
+ diagnosticsCopyFull: "复制完整诊断",
5014
5017
  diagnosticsCopied: "已复制",
5015
5018
  diagnosticsFailed: "服务端诊断不可用,已生成可复制的本地脱敏诊断。请检查 DSH 服务连接与插件版本。",
5016
5019
  feedbackOpen: "反馈问题",
@@ -5532,6 +5535,8 @@ window.__ModuleLoader__.load({
5532
5535
  quotaAlertsHint: "Warn at the selected remaining threshold. Custom sets short and long windows separately. Fresh data only; no interrupting popups.",
5533
5536
  quotaWarning: "{window}: {value}% remaining. Check usage and reset time.",
5534
5537
  speedFastAstraHint: "About 2x speed on Astra; higher Credits use",
5538
+ speedUltrafast: "Ultrafast Beta",
5539
+ speedUltrafastHint: "Ultrafast tier, shown only when your account catalog offers it (Pro 500 today); fastest, uses allowance and Credits faster",
5535
5540
  imageEditLocation: "Location",
5536
5541
  imageEditReferenceGuide: "The clean source for this edit is \"{sourceName}\"; \"{referenceName}\" is the numbered location reference. Coordinates start at the top-left, x increases rightward and y downward; percentages refer to the whole image. Inspect both images and pass both as references to the image-editing tool. Preserve every number, position and requested change below in the tool prompt. Edit the corresponding content in the clean source; numbers, dots and leader lines on the location reference are guidance only and must not appear in the final result. If either image cannot be read or a location is unclear, explain the problem instead of guessing or ignoring annotations.",
5537
5542
  nav: "Codex",
@@ -5565,7 +5570,8 @@ window.__ModuleLoader__.load({
5565
5570
  diagnostics: "Support diagnostics",
5566
5571
  diagnosticsLoad: "Create report",
5567
5572
  diagnosticsLoading: "Creating…",
5568
- diagnosticsCopy: "Copy report",
5573
+ diagnosticsCopy: "Copy report (short)",
5574
+ diagnosticsCopyFull: "Copy full report",
5569
5575
  diagnosticsCopied: "Copied",
5570
5576
  diagnosticsFailed: "Server diagnostics unavailable. A local, redacted report is available to copy. Check the DSH service and plugin version.",
5571
5577
  feedbackOpen: "Report a problem",
@@ -7047,7 +7053,6 @@ window.__ModuleLoader__.load({
7047
7053
  const DEFAULT_SEARCH_PROVIDER = SEARCH_PROVIDER_AUTO;
7048
7054
  const SPEED_MODE_FIELD = "speedMode";
7049
7055
  const SPEED_MODE_STANDARD = "standard";
7050
- const SPEED_MODE_FAST = "fast";
7051
7056
  const DEFAULT_SPEED_MODE = SPEED_MODE_STANDARD;
7052
7057
  const OUTPUT_VERBOSITY_FIELD = "outputVerbosity";
7053
7058
  const OUTPUT_VERBOSITY_DEFAULT = "default";
@@ -7115,7 +7120,11 @@ window.__ModuleLoader__.load({
7115
7120
  ].includes(value) ? value : DEFAULT_OUTPUT_VERBOSITY;
7116
7121
  const normalizeInputImageDetail = (value) => INPUT_IMAGE_DETAILS.includes(value) ? value : DEFAULT_INPUT_IMAGE_DETAIL;
7117
7122
  const normalizeStreamIdleTimeoutMinutes = (value) => STREAM_IDLE_TIMEOUT_MINUTES.includes(value) ? value : 10;
7118
- const normalizeSpeedMode = (value) => ["standard", "fast"].includes(value) ? value : DEFAULT_SPEED_MODE;
7123
+ const normalizeSpeedMode = (value) => [
7124
+ "standard",
7125
+ "fast",
7126
+ "ultrafast"
7127
+ ].includes(value) ? value : DEFAULT_SPEED_MODE;
7119
7128
  const normalizeContextMode = (value) => [
7120
7129
  "standard",
7121
7130
  "extended",
@@ -7155,6 +7164,7 @@ window.__ModuleLoader__.load({
7155
7164
  let availableModels = [];
7156
7165
  let verbosityModels = [];
7157
7166
  let fastModels;
7167
+ let ultrafastModels = [];
7158
7168
  let catalogStatus;
7159
7169
  let modelsLoading = false;
7160
7170
  let modelError = false;
@@ -7199,6 +7209,7 @@ window.__ModuleLoader__.load({
7199
7209
  disabledModels: normalizeDisabledModels(value?.[DISABLED_MODELS_FIELD]),
7200
7210
  verbosityModels,
7201
7211
  fastModels,
7212
+ ultrafastModels,
7202
7213
  catalogStatus,
7203
7214
  modelsLoading,
7204
7215
  modelError,
@@ -7226,6 +7237,7 @@ window.__ModuleLoader__.load({
7226
7237
  availableModels = Array.isArray(value?.availableModels) ? value.availableModels : [];
7227
7238
  verbosityModels = Array.isArray(value?.verbosityModels) ? value.verbosityModels : [];
7228
7239
  fastModels = Array.isArray(value?.fastModels) ? value.fastModels : void 0;
7240
+ ultrafastModels = Array.isArray(value?.ultrafastModels) ? value.ultrafastModels : [];
7229
7241
  catalogStatus = value?.catalogStatus;
7230
7242
  }
7231
7243
  fallbackStatus = "ready";
@@ -7270,6 +7282,8 @@ window.__ModuleLoader__.load({
7270
7282
  availableModels = Array.isArray(value?.availableModels) ? value.availableModels : [];
7271
7283
  verbosityModels = Array.isArray(value?.verbosityModels) ? value.verbosityModels : [];
7272
7284
  fastModels = Array.isArray(value?.fastModels) ? value.fastModels : void 0;
7285
+ ultrafastModels = Array.isArray(value?.ultrafastModels) ? value.ultrafastModels : [];
7286
+ ultrafastModels = Array.isArray(value?.ultrafastModels) ? value.ultrafastModels : [];
7273
7287
  catalogStatus = value?.catalogStatus;
7274
7288
  }
7275
7289
  } else acceptFallback(value);
@@ -7293,13 +7307,15 @@ window.__ModuleLoader__.load({
7293
7307
  const nextAvailableModels = Array.isArray(value?.availableModels) ? value.availableModels : [];
7294
7308
  const nextVerbosityModels = Array.isArray(value?.verbosityModels) ? value.verbosityModels : [];
7295
7309
  const nextFastModels = Array.isArray(value?.fastModels) ? value.fastModels : void 0;
7310
+ const nextUltrafastModels = Array.isArray(value?.ultrafastModels) ? value.ultrafastModels : [];
7296
7311
  catalogStatus = value?.catalogStatus;
7297
- const changed = !sameModels(contextModels, nextContextModels) || !sameModels(availableModels, nextAvailableModels) || !sameModels(verbosityModels, nextVerbosityModels) || JSON.stringify(fastModels) !== JSON.stringify(nextFastModels);
7312
+ const changed = !sameModels(contextModels, nextContextModels) || !sameModels(availableModels, nextAvailableModels) || !sameModels(verbosityModels, nextVerbosityModels) || JSON.stringify(fastModels) !== JSON.stringify(nextFastModels) || JSON.stringify(ultrafastModels) !== JSON.stringify(nextUltrafastModels);
7298
7313
  if (changed) {
7299
7314
  contextModels = nextContextModels;
7300
7315
  availableModels = nextAvailableModels;
7301
7316
  verbosityModels = nextVerbosityModels;
7302
7317
  fastModels = nextFastModels;
7318
+ ultrafastModels = nextUltrafastModels;
7303
7319
  publish();
7304
7320
  }
7305
7321
  return changed;
@@ -7660,7 +7676,7 @@ window.__ModuleLoader__.load({
7660
7676
  }
7661
7677
  //#endregion
7662
7678
  //#region src/version.js
7663
- const PACKAGE_VERSION = "2.2.11";
7679
+ const PACKAGE_VERSION = "2.3.0";
7664
7680
  //#endregion
7665
7681
  //#region src/client-recovery.js
7666
7682
  async function recoveryCall(rpc, endpoint, payload = {}, timeoutMs = 1e4) {
@@ -7950,7 +7966,10 @@ window.__ModuleLoader__.load({
7950
7966
  const modelLabel = currentChoice?.model.name ?? t("selectModel");
7951
7967
  const speedSupported = state.current?.provider === "openai-codex" && (preferenceSnapshot.fastModels?.includes(state.current?.model) ?? supportsCodexFastMode(state.current?.model));
7952
7968
  const speedWritable = preferenceSnapshot.status === "ready" && preferenceSnapshot.writable === true;
7953
- const fast = speedSupported && preferenceSnapshot.speedMode === "fast";
7969
+ const ultrafastSupported = state.current?.provider === "openai-codex" && (preferenceSnapshot.ultrafastModels ?? []).includes(state.current?.model);
7970
+ const ultrafast = ultrafastSupported && preferenceSnapshot.speedMode === "ultrafast";
7971
+ const fast = ultrafast || speedSupported && preferenceSnapshot.speedMode === "fast";
7972
+ const speedKey = ultrafast ? "speedUltrafast" : fast ? "speedFast" : "speedStandard";
7954
7973
  const verbositySupported = state.current?.provider === "openai-codex" && preferenceSnapshot.verbosityModels.includes(state.current?.model);
7955
7974
  const verbosityWritable = preferenceSnapshot.status === "ready" && preferenceSnapshot.writable === true;
7956
7975
  const verbosityItems = [
@@ -8158,21 +8177,32 @@ window.__ModuleLoader__.load({
8158
8177
  className: "codexModelSelectSubmenu",
8159
8178
  role: "menu",
8160
8179
  "aria-label": t("speedTitle"),
8161
- children: [option({
8162
- key: SPEED_MODE_STANDARD,
8163
- label: t("speedStandard"),
8164
- description: t("speedStandardHint"),
8165
- selected: !fast,
8166
- disabled: !speedWritable,
8167
- onClick: () => chooseSpeed(SPEED_MODE_STANDARD)
8168
- }), option({
8169
- key: SPEED_MODE_FAST,
8170
- label: t("speedFast"),
8171
- description: t(state.current?.model === "gpt-6-astra" ? "speedFastAstraHint" : "speedFastHint"),
8172
- selected: fast,
8173
- disabled: !speedWritable,
8174
- onClick: () => chooseSpeed(SPEED_MODE_FAST)
8175
- })]
8180
+ children: [
8181
+ option({
8182
+ key: SPEED_MODE_STANDARD,
8183
+ label: t("speedStandard"),
8184
+ description: t("speedStandardHint"),
8185
+ selected: !fast,
8186
+ disabled: !speedWritable,
8187
+ onClick: () => chooseSpeed(SPEED_MODE_STANDARD)
8188
+ }),
8189
+ speedSupported && option({
8190
+ key: "fast",
8191
+ label: t("speedFast"),
8192
+ description: t(state.current?.model === "gpt-6-astra" ? "speedFastAstraHint" : "speedFastHint"),
8193
+ selected: fast && !ultrafast,
8194
+ disabled: !speedWritable,
8195
+ onClick: () => chooseSpeed("fast")
8196
+ }),
8197
+ ultrafastSupported && option({
8198
+ key: "ultrafast",
8199
+ label: t("speedUltrafast"),
8200
+ description: t("speedUltrafastHint"),
8201
+ selected: ultrafast,
8202
+ disabled: !speedWritable,
8203
+ onClick: () => chooseSpeed("ultrafast")
8204
+ })
8205
+ ]
8176
8206
  });
8177
8207
  else if (pane === "verbosity") submenu = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8178
8208
  className: "codexModelSelectSubmenu",
@@ -8231,7 +8261,7 @@ window.__ModuleLoader__.load({
8231
8261
  children: [
8232
8262
  cell("model", t("modelLabel"), modelLabel),
8233
8263
  reasoning === void 0 ? null : cell("effort", t("effortLabel"), effortLabel),
8234
- speedSupported && cell("speed", t("speedTitle"), t(fast ? "speedFast" : "speedStandard")),
8264
+ (speedSupported || ultrafastSupported) && cell("speed", t("speedTitle"), t(speedKey)),
8235
8265
  verbositySupported && cell("verbosity", t("verbosityTitle"), verbosityLabel),
8236
8266
  submenu
8237
8267
  ]
@@ -9919,6 +9949,38 @@ window.__ModuleLoader__.load({
9919
9949
  };
9920
9950
  }
9921
9951
  //#endregion
9952
+ //#region src/diagnostic-compact.js
9953
+ function compactDiagnostic(report) {
9954
+ const summary = report.summary ?? { findings: [] };
9955
+ return {
9956
+ format: "compact-1",
9957
+ plugin: report.version,
9958
+ dsh: report.client?.version,
9959
+ generatedAt: report.generatedAt,
9960
+ account: report.account?.status,
9961
+ catalog: report.catalog ? {
9962
+ source: report.catalog.source,
9963
+ refresh: report.catalog.refresh
9964
+ } : void 0,
9965
+ configuration: report.configuration,
9966
+ findings: summary.findings.map((item) => ({
9967
+ code: item.code,
9968
+ severity: item.severity,
9969
+ ...item.code === "recent-failure" ? { failures: item.evidence.map((event) => ({
9970
+ action: event.action,
9971
+ source: event.source,
9972
+ at: new Date(event.observedAt).toISOString()
9973
+ })) } : {}
9974
+ })),
9975
+ capabilities: (report.inspection?.capabilities ?? []).filter((item) => item.readiness !== "not-applicable").map((item) => ({
9976
+ id: item.id,
9977
+ reason: item.reason,
9978
+ ...item.latest ? { latest: `${item.latest.action} ${item.latest.status}` } : { latest: "not-verified" }
9979
+ })),
9980
+ ...report.client?.status === "unknown" ? { hostCollected: false } : {}
9981
+ };
9982
+ }
9983
+ //#endregion
9922
9984
  //#region src/client-diagnostics.jsx
9923
9985
  function DiagnosticsCard({ rpc, t, diagnostics }) {
9924
9986
  const [report, setReport] = (0, react.useState)();
@@ -9943,10 +10005,10 @@ window.__ModuleLoader__.load({
9943
10005
  });
9944
10006
  }).finally(() => setBusy(false));
9945
10007
  };
9946
- const copy = () => {
10008
+ const copy = (full = false) => {
9947
10009
  if (report === void 0) return;
9948
10010
  setCopyError(false);
9949
- Promise.resolve().then(() => navigator.clipboard.writeText(JSON.stringify(report, null, 2))).then(() => setCopied(true)).catch(() => setCopyError(true));
10011
+ Promise.resolve().then(() => navigator.clipboard.writeText(JSON.stringify(full ? report : compactDiagnostic(report), null, 2))).then(() => setCopied(true)).catch(() => setCopyError(true));
9950
10012
  };
9951
10013
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9952
10014
  className: "codexSubscriptionCard codexSubscriptionDiagnostics",
@@ -9972,7 +10034,7 @@ window.__ModuleLoader__.load({
9972
10034
  report === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
9973
10035
  type: "button",
9974
10036
  variant: "outline",
9975
- onClick: copy,
10037
+ onClick: () => copy(),
9976
10038
  children: copied ? t("diagnosticsCopied") : t("diagnosticsCopy")
9977
10039
  }),
9978
10040
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
@@ -10038,7 +10100,16 @@ window.__ModuleLoader__.load({
10038
10100
  className: "codexSubscriptionHelp",
10039
10101
  children: report.client?.topology?.length ? t("diagnosticsHostCollected") : t("diagnosticsHostUnknown")
10040
10102
  }),
10041
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: t("diagnosticsDetails") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { children: JSON.stringify(report, null, 2) })] })
10103
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", { children: [
10104
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: t("diagnosticsDetails") }),
10105
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
10106
+ type: "button",
10107
+ variant: "outline",
10108
+ onClick: () => copy(true),
10109
+ children: t("diagnosticsCopyFull")
10110
+ }),
10111
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { children: JSON.stringify(report, null, 2) })
10112
+ ] })
10042
10113
  ] }),
10043
10114
  error ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
10044
10115
  className: "codexSubscriptionError",
package/lib/index.js CHANGED
@@ -206,6 +206,7 @@ const DEFAULT_SEARCH_PROVIDER = SEARCH_PROVIDER_AUTO;
206
206
  const SPEED_MODE_FIELD = "speedMode";
207
207
  const SPEED_MODE_STANDARD = "standard";
208
208
  const SPEED_MODE_FAST = "fast";
209
+ const SPEED_MODE_ULTRAFAST = "ultrafast";
209
210
  const DEFAULT_SPEED_MODE = SPEED_MODE_STANDARD;
210
211
  const OUTPUT_VERBOSITY_FIELD = "outputVerbosity";
211
212
  const OUTPUT_VERBOSITY_DEFAULT = "default";
@@ -364,7 +365,11 @@ const PREFERENCE_FIELDS = Object.freeze({
364
365
  error: "Invalid search provider preference"
365
366
  },
366
367
  [SPEED_MODE_FIELD]: {
367
- choices: [SPEED_MODE_STANDARD, SPEED_MODE_FAST],
368
+ choices: [
369
+ SPEED_MODE_STANDARD,
370
+ SPEED_MODE_FAST,
371
+ SPEED_MODE_ULTRAFAST
372
+ ],
368
373
  default: DEFAULT_SPEED_MODE,
369
374
  error: "Invalid speed mode preference"
370
375
  },
@@ -2878,6 +2883,7 @@ function normalizeTransportEvent(event, signal) {
2878
2883
  //#endregion
2879
2884
  //#region src/pi-ai-runtime.js
2880
2885
  const FAST_SERVICE_TIER = "priority";
2886
+ const ULTRAFAST_SERVICE_TIER = "ultrafast";
2881
2887
  /** Apply the chosen detail to user and tool-result images after the provider assembles the request. */
2882
2888
  function withInputImageDetail(payload, detail) {
2883
2889
  if (!Array.isArray(payload.input)) return payload;
@@ -2937,13 +2943,14 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
2937
2943
  const metadata = modelMetadata(model);
2938
2944
  const requestedVerbosity = resolveOutputVerbosity();
2939
2945
  const textVerbosity = supportsVerbosity(model) ? requestedVerbosity === "default" ? metadata?.defaultVerbosity ?? "medium" : requestedVerbosity : void 0;
2940
- const fast = resolveSpeedMode() === "fast" && (metadata?.supportsFast ?? supportsCodexFastMode(model?.id));
2946
+ const speedMode = resolveSpeedMode();
2947
+ const serviceTier = speedMode === "ultrafast" && metadata?.supportsUltrafast === true ? ULTRAFAST_SERVICE_TIER : speedMode === "fast" && (metadata?.supportsFast ?? supportsCodexFastMode(model?.id)) ? FAST_SERVICE_TIER : void 0;
2941
2948
  const inputImageDetail = normalizeInputImageDetail(resolveInputImageDetail());
2942
2949
  const onPayload = options.onPayload;
2943
2950
  return {
2944
2951
  ...options,
2945
2952
  ...textVerbosity === void 0 ? {} : { textVerbosity },
2946
- ...fast ? { serviceTier: FAST_SERVICE_TIER } : {},
2953
+ ...serviceTier === void 0 ? {} : { serviceTier },
2947
2954
  async onPayload(payload, requestModel) {
2948
2955
  const preferred = {
2949
2956
  ...payload,
@@ -2951,7 +2958,7 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
2951
2958
  ...payload.text ?? {},
2952
2959
  verbosity: textVerbosity
2953
2960
  } },
2954
- ...fast ? { service_tier: FAST_SERVICE_TIER } : {}
2961
+ ...serviceTier === void 0 ? {} : { service_tier: serviceTier }
2955
2962
  };
2956
2963
  const managed = compaction?.preparePayload(preferred, model?.contextWindow) ?? preferred;
2957
2964
  const next = await onPayload?.(managed, requestModel);
@@ -2962,7 +2969,7 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
2962
2969
  ...detailed.text ?? {},
2963
2970
  verbosity: textVerbosity
2964
2971
  } },
2965
- ...fast ? { service_tier: FAST_SERVICE_TIER } : {}
2972
+ ...serviceTier === void 0 ? {} : { service_tier: serviceTier }
2966
2973
  };
2967
2974
  }
2968
2975
  };
@@ -3051,7 +3058,7 @@ async function readSubscriptionCredentials(getAuth, readCredential, signal) {
3051
3058
  }
3052
3059
  //#endregion
3053
3060
  //#region src/version.js
3054
- const PACKAGE_VERSION = "2.2.11";
3061
+ const PACKAGE_VERSION = "2.3.0";
3055
3062
  const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
3056
3063
  //#endregion
3057
3064
  //#region src/model-catalog.js
@@ -3114,6 +3121,7 @@ function reasoningMap(levels) {
3114
3121
  return map;
3115
3122
  }
3116
3123
  const capabilityNames = (values) => [...new Set(values.filter((value) => typeof value === "string" && /^[a-z][a-z0-9_-]{0,31}$/u.test(value)))].sort().slice(0, 16);
3124
+ const speedTierIds = (value) => [...Array.isArray(value.additional_speed_tiers) ? value.additional_speed_tiers : [], ...Array.isArray(value.service_tiers) ? value.service_tiers.map((tier) => tier?.id) : []];
3117
3125
  function unsupportedCapabilities(value) {
3118
3126
  const reasoning = capabilityNames((value.supported_reasoning_levels ?? []).map((item) => item?.effort)).filter((level) => !["none", ...LEVELS.slice(1)].includes(level));
3119
3127
  const inputs = capabilityNames(Array.isArray(value.input_modalities) ? value.input_modalities : []).filter((input) => !["text", "image"].includes(input));
@@ -3122,7 +3130,8 @@ function unsupportedCapabilities(value) {
3122
3130
  "default",
3123
3131
  "standard",
3124
3132
  "fast",
3125
- "priority"
3133
+ "priority",
3134
+ "ultrafast"
3126
3135
  ].includes(tier));
3127
3136
  return {
3128
3137
  ...reasoning.length ? { reasoning } : {},
@@ -3166,7 +3175,8 @@ function visibleModel(value, displayNames, now) {
3166
3175
  "medium",
3167
3176
  "high"
3168
3177
  ].includes(value.default_verbosity) ? value.default_verbosity : void 0,
3169
- 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")
3178
+ supportsFast: speedTierIds(value).some((tier) => tier === "fast" || tier === "priority"),
3179
+ supportsUltrafast: speedTierIds(value).includes("ultrafast")
3170
3180
  };
3171
3181
  }
3172
3182
  function parseOfficialModelCatalog(value, now = Date.now()) {
@@ -5829,6 +5839,7 @@ function createSubscriptionRpcHandler({ authHandler, usageReader, resetCreditSer
5829
5839
  contextModels: Array.isArray(value?.contextModels) ? value.contextModels : [],
5830
5840
  verbosityModels: Array.isArray(value?.verbosityModels) ? value.verbosityModels : [],
5831
5841
  fastModels: Array.isArray(value?.fastModels) ? value.fastModels : [],
5842
+ ultrafastModels: Array.isArray(value?.ultrafastModels) ? value.ultrafastModels : [],
5832
5843
  catalogStatus: value?.catalogStatus
5833
5844
  }
5834
5845
  };
@@ -6100,6 +6111,7 @@ function apply(ctx, config = {}) {
6100
6111
  })),
6101
6112
  catalogStatus: modelCatalog.status(),
6102
6113
  verbosityModels: provider.getModels().filter((model) => modelCatalog.metadata(model.id)?.supportVerbosity ?? model.id !== "gpt-5.3-codex-spark").map((model) => model.id),
6114
+ ultrafastModels: provider.getModels().filter((model) => modelCatalog.metadata(model.id)?.supportsUltrafast === true).map((model) => model.id),
6103
6115
  fastModels: provider.getModels().filter((model) => modelCatalog.metadata(model.id)?.supportsFast ?? supportsCodexFastMode(model.id)).map((model) => model.id),
6104
6116
  writable: ctx.settings.writable
6105
6117
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-codex-subscription",
3
- "version": "2.2.11",
3
+ "version": "2.3.0",
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",