dsh-codex-subscription 3.0.0-beta.5 → 3.0.0-beta.6

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
@@ -18,17 +18,122 @@ Sign in with ChatGPT Plus / Pro to use GPT-6 and other Codex models, quota, web
18
18
  [![MIT](https://img.shields.io/badge/license-MIT-111111.svg)](LICENSE)
19
19
  [![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)
20
20
 
21
- [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)
21
+ [Install](#install) · [Highlights](#highlights) · [Phone remote control](#phone-remote-control-beta) · [Examples](#from-sketch-to-image) · [All features](#all-features) · [User guide](docs/GUIDE.en.md) · [Troubleshooting](#troubleshooting)
22
22
 
23
23
  </div>
24
24
 
25
- <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>
25
+ <p align="center"><img src="docs/assets/hero-en.webp" width="1100" alt="Your subscription, now in DSH: the whale-girl mascot and the Codex subscription account quota interface"></p>
26
26
 
27
- ## Feature overview
27
+ ## Prepare DSH
28
+
29
+ Verified against DSH `0.2.0-rc.2` (`latest` and `next` channels); the minimum supported version is `0.1.7-rc.2`. Please upgrade older DSH releases first.
30
+
31
+ This plugin supports the latest DeepSeek Harness release recorded in its package metadata and requires a ChatGPT account that currently has Codex access.
32
+
33
+ - **Recommended: the official desktop app.** DeepSeek now ships a [DeepSeek Harness desktop app](https://www.deepseek.com/harness/) (macOS on Apple Silicon and 64-bit Windows; preview, open source). It needs no Node.js setup: install it, then add this plugin from the Plugins page as described below. The desktop app, the web app and the CLI share one DSH plugin system; this plugin's end-to-end acceptance is mainly run on the web app, so please [open an issue](https://github.com/WSL043/dsh-codex-subscription/issues) if the desktop app misbehaves.
34
+ - Need Linux, or prefer a community portable build? Use [DSH-Portable](https://github.com/WSL043/DSH-Portable), a community portable desktop distribution for Windows, macOS, and Linux.
35
+ - Prefer the official route? Follow the [DeepSeek Harness run guide](https://github.com/deepseek-ai/deepseek-harness#run).
36
+
37
+ ## Install
38
+
39
+ ### Install from the Plugins page (recommended)
40
+
41
+ 1. Open **Plugins → Add plugin** in DSH.
42
+ 2. Paste this package name, with its version, into the **Package name or address** field:
28
43
 
29
- 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.
44
+ ```text
45
+ dsh-codex-subscription@2.6.8
46
+ ```
30
47
 
31
- ### Models and search
48
+ 3. Click **Install** and wait for completion. Follow the page instructions; save your work before restarting if requested.
49
+ 4. Open **Settings → Codex**, sign in to ChatGPT, then select a Codex model in your conversation.
50
+
51
+ Why the version is included: DSH's plugin page only installs versions that are at least 24 hours old, so the bare package name can install an older release during the first day after a new one, and that older release may not support your DSH. With the version you get exactly this release; a day after release the bare `dsh-codex-subscription` also resolves to the latest stable release. Other version numbers are on the [releases page](https://github.com/WSL043/dsh-codex-subscription/releases).
52
+
53
+ <details>
54
+ <summary>Terminal installation (with an existing dsh command)</summary>
55
+
56
+ ```sh
57
+ dsh plugin --profile web add dsh-codex-subscription@2.6.8
58
+ ```
59
+
60
+ Follow the restart instructions, then sign in under **Settings → Codex**. Both the Plugins page and the terminal use DSH's installation management.
61
+
62
+ </details>
63
+
64
+ <details>
65
+ <summary>Headless tasks</summary>
66
+
67
+ After signing in and selecting a Codex model in Web, install the same plugin in the Headless profile:
68
+
69
+ ```sh
70
+ dsh plugin --profile headless add dsh-codex-subscription@2.6.8
71
+ dsh --profile headless "Reply with only the word: ok"
72
+ ```
73
+
74
+ </details>
75
+
76
+ ## Highlights
77
+
78
+ ### Sign in with your subscription and use Codex models
79
+
80
+ Sign in to ChatGPT under **Settings → Codex** in DSH, then pick GPT-6 and the other models in your account catalog from any conversation, set the reasoning and speed levels, and use subscription web search. No API key. Models and quota depend on your account.
81
+
82
+ ### Quota at a glance
83
+
84
+ Short-window and weekly quota, reset times, extra Credits and reset cards live in settings; the composer can keep the remaining quota in view and warn you below a threshold.
85
+
86
+ <p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="docs/assets/ui-quota-en-dark.png"><img src="docs/assets/ui-quota-en-light.png" width="560" alt="Quota card: weekly quota and reset time, with usage overview and where the allowance went below"></picture></p>
87
+
88
+ <details>
89
+ <summary>Usage overview and where the allowance went: lifetime usage, streaks, a daily heatmap and the weekly breakdown</summary>
90
+ <br>
91
+ <p align="center"><img src="docs/assets/usage-overview-en.png" width="460" alt="Usage overview and where the allowance went in the quota card: lifetime tokens, streaks, a half-year daily heatmap and the weekly allowance split by model, surface and source"></p>
92
+ </details>
93
+
94
+ ### Everyday controls, right in the composer
95
+
96
+ Pick the model, the reasoning level and the speed tier while the remaining quota stays in view, without opening settings for every request.
97
+
98
+ <p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="docs/assets/ui-composer-en-dark.png"><img src="docs/assets/ui-composer-en-light.png" width="760" alt="Composer: permission, sketch, remaining quota, the lightning mark for Fast mode and the model picker"></picture></p>
99
+
100
+ ### Phone remote control (Beta)
101
+
102
+ Pair the ChatGPT mobile app's Codex section with a QR code and the DSH on your computer shows up as a host on your phone. DeepSeek and any other DSH model work from the phone:
103
+
104
+ - follow, start, continue, interrupt and archive conversations; search conversations and keywords inside one;
105
+ - switch model, reasoning level and permission (workspace write / full access);
106
+ - approvals and questions pop up on the phone; if it drops, they pop up again when you reopen it, otherwise they go back to the computer;
107
+ - replies appear as they are written; commands, file edits with diffs, the task list, web searches, connector calls and generated images use the phone's native views;
108
+ - send photos, @ search files on the computer, / pick DSH skills, view changes with read-only git, and start chats in a real folder picker;
109
+ - DSH workspaces appear as projects; fork a conversation, see usage limits, lifetime usage and context usage;
110
+ - model errors show on the phone; paired phones are listed in settings and can be removed.
111
+
112
+ Off by default: **Settings → Codex → Models & runtime → Phone remote control**. The computer must stay on, online and running DSH. This is a ChatGPT capability OpenAI has not opened to third parties and may change at any time, hence Beta. Currently in the pre-release: `dsh-codex-subscription@3.0.0-beta.5`.
113
+
114
+ <p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="docs/assets/ui-remote-en-dark.png"><img src="docs/assets/ui-remote-en-light.png" width="560" alt="Phone remote control in settings: the switch, pairing QR code and manual code, paired phones"></picture></p>
115
+
116
+ ### Images and sketching (Beta)
117
+
118
+ Generate images with your subscription, circle a region and write a note to keep editing, or open the sketch board to draw yourself or let the agent draw, then use the sketch as the reference for the finished image.
119
+
120
+ <p align="center"><img src="docs/assets/annotate-en.webp" width="900" alt="Image preview: a region above the chimney is marked with a note, then editing continues with the note"></p>
121
+
122
+ Examples are in [From sketch to image](#from-sketch-to-image); the switches are under **Settings → Codex → Images & sketch**.
123
+
124
+ ### ChatGPT connectors (Beta)
125
+
126
+ Let DeepSeek or any other DSH model use the apps you connected in ChatGPT: GitHub, Gmail, Google Drive, Calendar and more. Models search first, then call, and every change asks for your approval. Off by default; turn it on under Models & runtime.
127
+
128
+ [Usage details, limitations and optional components →](docs/GUIDE.en.md)
129
+
130
+ ## All features
131
+
132
+ Model access and quota depend on your account.
133
+
134
+ <details>
135
+ <summary><b>Models and search</b> (13)</summary>
136
+ <br>
32
137
 
33
138
  | Feature | What you can do | Availability / setup |
34
139
  | --- | --- | --- |
@@ -46,7 +151,11 @@ Subscription access, model controls, quota management, and image creation in one
46
151
  | **Context budget** | Use standard, extended, or custom budgets per model | Limited by the model catalog |
47
152
  | **GPT-Reserve** | Select the reserve model when your account offers it | Experimental; no promise of a separate reserve quota |
48
153
 
49
- ### Accounts and quota
154
+ </details>
155
+
156
+ <details>
157
+ <summary><b>Accounts and quota</b> (10)</summary>
158
+ <br>
50
159
 
51
160
  | Feature | What you can do | Availability / setup |
52
161
  | --- | --- | --- |
@@ -61,9 +170,11 @@ Subscription access, model controls, quota management, and image creation in one
61
170
  | **Redeem reset cards** | Use an available reset card after confirmation | Confirmation and waiting safeguards; server decides the result |
62
171
  | **Retry after reset** | Wait for a confirmed short-window reset before continuing | Off by default; waiting can be stopped |
63
172
 
64
- <p align="center"><img src="docs/assets/usage-overview-en.png" width="460" alt="Usage overview and where the allowance went in the quota card: lifetime tokens, streaks, a half-year daily heatmap and the weekly allowance split by model, surface and source"></p>
173
+ </details>
65
174
 
66
- ### Images and sketching
175
+ <details>
176
+ <summary><b>Images and sketching</b> (12)</summary>
177
+ <br>
67
178
 
68
179
  | Feature | What you can do | Availability / setup |
69
180
  | --- | --- | --- |
@@ -80,7 +191,11 @@ Subscription access, model controls, quota management, and image creation in one
80
191
  | **Agent drawing** | Ask the agent to draw with `@sketch`, follow progress, and stop it; the agent can draw whole stages in SVG, imported as editable native strokes | Beta; off by default, requires the canvas |
81
192
  | **Result preview for the model** | Return a canvas image after drawing for subsequent review | Beta; off by default, adds image input usage |
82
193
 
83
- ### Advanced capabilities and maintenance
194
+ </details>
195
+
196
+ <details>
197
+ <summary><b>Advanced capabilities and maintenance</b> (9)</summary>
198
+ <br>
84
199
 
85
200
  | Feature | What you can do | Availability / setup |
86
201
  | --- | --- | --- |
@@ -94,58 +209,9 @@ Subscription access, model controls, quota management, and image creation in one
94
209
  | **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 |
95
210
  | **Forecast cache cleanup** | Inspect and clear local quota forecast history | Keeps sign-in, drafts, originals, and shared dependencies |
96
211
 
97
- [Usage details, limitations, and optional components →](docs/GUIDE.en.md)
98
-
99
- ## Prepare DSH
100
-
101
- Verified against DSH `0.2.0-rc.2` (`latest` and `next` channels); the minimum supported version is `0.1.7-rc.2`. Please upgrade older DSH releases first.
102
-
103
- This plugin supports the latest DeepSeek Harness release recorded in its package metadata and requires a ChatGPT account that currently has Codex access.
104
-
105
- - **Recommended: the official desktop app.** DeepSeek now ships a [DeepSeek Harness desktop app](https://www.deepseek.com/harness/) (macOS on Apple Silicon and 64-bit Windows; preview, open source). It needs no Node.js setup: install it, then add this plugin from the Plugins page as described below. The desktop app, the web app and the CLI share one DSH plugin system; this plugin's end-to-end acceptance is mainly run on the web app, so please [open an issue](https://github.com/WSL043/dsh-codex-subscription/issues) if the desktop app misbehaves.
106
- - Need Linux, or prefer a community portable build? Use [DSH-Portable](https://github.com/WSL043/DSH-Portable), a community portable desktop distribution for Windows, macOS, and Linux.
107
- - Prefer the official route? Follow the [DeepSeek Harness run guide](https://github.com/deepseek-ai/deepseek-harness#run).
108
-
109
- ## Install
110
-
111
- ### Install from the Plugins page (recommended)
112
-
113
- 1. Open **Plugins → Add plugin** in DSH.
114
- 2. Paste this package name, with its version, into the **Package name or address** field:
115
-
116
- ```text
117
- dsh-codex-subscription@2.5.9
118
- ```
119
-
120
- 3. Click **Install** and wait for completion. Follow the page instructions; save your work before restarting if requested.
121
- 4. Open **Settings → Codex**, sign in to ChatGPT, then select a Codex model in your conversation.
122
-
123
- Why the version is included: DSH's plugin page only installs versions that are at least 24 hours old, so the bare package name can install an older release during the first day after a new one, and that older release may not support your DSH. With the version you get exactly this release; a day after release the bare `dsh-codex-subscription` also resolves to the latest stable release. Other version numbers are on the [releases page](https://github.com/WSL043/dsh-codex-subscription/releases).
124
-
125
- <details>
126
- <summary>Terminal installation (with an existing dsh command)</summary>
127
-
128
- ```sh
129
- dsh plugin --profile web add dsh-codex-subscription@2.5.9
130
- ```
131
-
132
- Follow the restart instructions, then sign in under **Settings → Codex**. Both the Plugins page and the terminal use DSH's installation management.
133
-
134
212
  </details>
135
213
 
136
- <details>
137
- <summary>Headless tasks</summary>
138
-
139
- After signing in and selecting a Codex model in Web, install the same plugin in the Headless profile:
140
-
141
- ```sh
142
- dsh plugin --profile headless add dsh-codex-subscription@2.5.9
143
- dsh --profile headless "Reply with only the word: ok"
144
- ```
145
-
146
- </details>
147
-
148
- ## Inside the plugin
214
+ ## Interface demo
149
215
 
150
216
  <details>
151
217
  <summary><b>Interface demo (animation, click to expand)</b>: models, prompts, images, annotation, sketch board, quota and resets</summary>
@@ -153,32 +219,6 @@ dsh --profile headless "Reply with only the word: ok"
153
219
  <p align="center"><img src="docs/assets/readme-demo-en.webp" width="1100" alt="Demo: sign in with ChatGPT, pick a subscription model, ask, generate an image, view and annotate it, continue on the sketch board, and check quota and resets"></p>
154
220
  </details>
155
221
 
156
- ### Everyday controls, right in the composer
157
-
158
- Choose a model, adjust reasoning, switch speed tiers, and check remaining quota without opening settings for every request.
159
-
160
- <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>
161
-
162
- ### Control DSH from your phone (Beta)
163
-
164
- Turn on **Settings → Codex → Models & runtime → Phone remote control** and pair by scanning the QR code in the Codex section of the ChatGPT mobile app. This computer's DSH then appears in the phone's host list:
165
-
166
- - browse, start, continue, interrupt and archive DSH conversations from the phone, with DeepSeek, Codex or any other DSH model;
167
- - switch model, reasoning level and permissions (workspace write / full access) from the phone;
168
- - when DSH needs a tool approval or asks you a question, it pops up on the phone; if the phone dropped, it is asked again when you return, otherwise the computer handles it;
169
- - replies appear on the phone as they are written;
170
- - commands, file edits (with diffs), the task list and generated images use the phone's native views, and file-edit approvals show the diff;
171
- - DSH workspaces appear as projects on the phone: start chats in them, fork a conversation, see usage limits and context usage;
172
- - on the phone, @ searches files on the computer, skills can be picked, and the changes view works (read-only git); conversations can be searched, keywords found inside a conversation, and your lifetime usage viewed;
173
- - Settings lists the paired phones and lets you remove any of them;
174
- - send photos from the phone (with or without text), and images DSH produces show up on the phone;
175
- - the phone folder picker browses real folders on this computer, and a new chat can start in one of them;
176
- - model errors are shown on the phone.
177
-
178
- Off by default. The computer must stay on, online and running DSH. This uses a ChatGPT capability OpenAI has not opened to third parties and may change at any time, hence Beta. Currently available in the pre-release `dsh-codex-subscription@3.0.0-beta.5`.
179
-
180
- <p align="center"><img src="docs/assets/remote-control-en.png" width="560" alt="Official desktop app settings: phone remote control connected, showing a pairing QR code and manual code"></p>
181
-
182
222
  ### Accounts and preferences, in one place
183
223
 
184
224
  Open **Settings → Codex** to manage accounts and quota. Enable other features as your tasks need them.
@@ -268,9 +308,9 @@ The face shape, hair flow, lace, hand and speech-bubble lettering are all closer
268
308
  <details>
269
309
  <summary>View Images & sketch settings</summary>
270
310
 
271
- <p align="center"><img src="docs/assets/real-creative-en.png" width="564" alt="Images and sketch settings: generation, editing, model choice, and separate canvas and agent controls"></p>
311
+ <p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="docs/assets/ui-creative-en-dark.png"><img src="docs/assets/ui-creative-en-light.png" width="564" alt="Images and sketch settings: generation and editing, creative shortcuts, requested model and quality"></picture></p>
272
312
 
273
- Settings shown directly as cropped screenshots from the actual DSH interface.
313
+ Settings shown directly as cropped screenshots from the actual DSH interface, following the light or dark theme.
274
314
 
275
315
  </details>
276
316
 
@@ -278,14 +318,6 @@ Layers, native curves, brushes, undo/redo, and shortcuts are supported. Save mul
278
318
 
279
319
  [Image editing and draft storage →](docs/GUIDE.en.md#image-generation-and-editing-beta)
280
320
 
281
- <a id="codex-subtask-runtime"></a>
282
-
283
- ## Optional capabilities
284
-
285
- Normal subscription chat needs no Codex CLI. For **Codex independent subtasks**, use Install component under Models & runtime; disabling and uninstalling are available in the same place. Other experimental options remain opt-in.
286
-
287
- [Optional components, storage cleanup, and the full user guide →](docs/GUIDE.en.md)
288
-
289
321
  ## Update and uninstall
290
322
 
291
323
  Find this plugin on the DSH **Plugins** page and use its update or uninstall action. Follow any restart instructions. Uninstalling this plugin does not remove other plugins.
@@ -294,7 +326,7 @@ Find this plugin on the DSH **Plugins** page and use its update or uninstall act
294
326
  <summary>Terminal commands</summary>
295
327
 
296
328
  ```sh
297
- dsh plugin --profile web update dsh-codex-subscription@2.5.9
329
+ dsh plugin --profile web update dsh-codex-subscription@2.6.8
298
330
  ```
299
331
 
300
332
  Run only when you want to uninstall:
@@ -307,13 +339,6 @@ dsh plugin --profile web remove dsh-codex-subscription
307
339
 
308
340
  ## Troubleshooting
309
341
 
310
- <details>
311
- <summary>DSH 0.2.0-rc.2 reports the plugin as incompatible?</summary>
312
-
313
- DSH 0.2.0-rc.2 did not exist when any release before 2.2.10 was published, and a published package's compatibility declaration cannot be changed. Install 2.2.10 or later (a bare package name can resolve to an older release during the first 24 hours, so enter `dsh-codex-subscription@2.2.10`) from the **Plugins** page, or run `dsh plugin --profile web update dsh-codex-subscription@2.5.9`, then restart DSH.
314
-
315
- </details>
316
-
317
342
  <details>
318
343
  <summary>How does this relate to the official Codex bundle (dsh-hooks-codex) in the plugin list?</summary>
319
344
 
@@ -344,15 +369,12 @@ Diagnostics exclude credentials, account identifiers, raw responses, and full lo
344
369
 
345
370
  </details>
346
371
 
347
- ## Current icon
348
-
349
- The current plugin icon and its appearance in DSH’s Installed list.
350
-
351
- <p align="center"><img src="icon-subscription.webp" width="200" height="200" alt="Current Codex Subscription plugin icon"></p>
372
+ <details>
373
+ <summary>Do I need the Codex command line?</summary>
352
374
 
353
- <p align="center"><img src="docs/assets/plugin-installed-en.png" width="800" alt="Codex Subscription plugin card in the DSH Installed list"></p>
375
+ Not for ordinary subscription chat. Only if you want **Codex independent subtasks**: use "Install component" under Settings → Codex → Models & runtime; disabling and uninstalling are in the same place. Other experimental options are opt-in. [Optional components, storage cleanup and the full guide →](docs/GUIDE.en.md)
354
376
 
355
- <sub>Captured in DSH 0.1.7-alpha.2.</sub>
377
+ </details>
356
378
 
357
379
  ## Positioning and boundaries
358
380
 
package/README.md CHANGED
@@ -18,17 +18,122 @@
18
18
  [![MIT](https://img.shields.io/badge/license-MIT-111111.svg)](LICENSE)
19
19
  [![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)
20
20
 
21
- [功能](#功能一览) · [安装](#安装) · [日常使用](#界面一览) · [作品案例](#从草图到作品) · [使用指南](docs/GUIDE.zh-CN.md) · [更新与卸载](#更新与卸载)
21
+ [安装](#安装) · [核心功能](#核心功能) · [手机远程控制](#手机远程控制beta) · [作品案例](#从草图到作品) · [全部功能](#全部功能) · [使用指南](docs/GUIDE.zh-CN.md) · [常见问题](#常见问题)
22
22
 
23
23
  </div>
24
24
 
25
- <p align="center"><img src="docs/assets/product-account-demo.png" width="1100" alt="Codex 订阅账号与额度界面:模型选择、双周期额度与提醒;使用演示数据"></p>
25
+ <p align="center"><img src="docs/assets/hero-zh.webp" width="1100" alt="已有的订阅,在 DSH 接着用:鲸鱼少女吉祥物与 Codex 订阅账号额度界面"></p>
26
26
 
27
- ## 功能一览
27
+ ## 准备 DSH
28
+
29
+ 已验证兼容 DSH `0.2.0-rc.2`(`latest` 与 `next` 通道),最低支持 `0.1.7-rc.2`;更早的 DSH 请先升级。
30
+
31
+ 本插件支持软件包元数据中记录的最新版 DeepSeek Harness,并需要一个当前具有 Codex 使用资格的 ChatGPT 账户。
32
+
33
+ - **推荐:官方桌面端**。DeepSeek 已发布 [DeepSeek Harness 桌面版](https://www.deepseek.com/harness/)(macOS Apple Silicon、Windows 64 位,预览版、开源),无需配置 Node.js,安装后按下文在插件页面添加本插件即可。桌面端与网页版、命令行使用同一套 DSH 插件系统;本插件的端到端验收主要在网页版上完成,桌面端遇到问题请[提交 issue](https://github.com/WSL043/dsh-codex-subscription/issues);
34
+ - 需要 Linux,或想要社区便携分发:使用 [DSH-Portable](https://github.com/WSL043/DSH-Portable)。这是面向 Windows、macOS 和 Linux 的社区便携桌面分发;
35
+ - 想按官方方式运行:查看 [DeepSeek Harness 官方说明](https://github.com/deepseek-ai/deepseek-harness#run)。
36
+
37
+ ## 安装
38
+
39
+ ### 在插件页面安装(推荐)
40
+
41
+ 1. 打开 DSH 的 **插件 → 添加插件**。
42
+ 2. 在 **包名或地址** 输入框中粘贴下面的包名(已带版本号):
43
+
44
+ ```text
45
+ dsh-codex-subscription@2.6.8
46
+ ```
47
+
48
+ 3. 点击 **安装**,等待安装完成;按页面提示操作,需要重启时先保存工作。
49
+ 4. 打开 **设置 → Codex 订阅**,登录 ChatGPT,然后在会话中选择 Codex 模型。
50
+
51
+ 为什么要带版本号:DSH 的插件页只会安装发布满 24 小时的版本,只填包名时,新版本发布后的第一天可能装到更早的旧版,而旧版不一定兼容你的 DSH。带上版本号可以直接装到这一版;发布一天后只填 `dsh-codex-subscription` 也会装到最新正式版。其他版本号见[发布页](https://github.com/WSL043/dsh-codex-subscription/releases)。
52
+
53
+ <details>
54
+ <summary>终端安装(已能运行 dsh 命令)</summary>
55
+
56
+ ```sh
57
+ dsh plugin --profile web add dsh-codex-subscription@2.6.8
58
+ ```
59
+
60
+ 安装完成后按提示重启 DSH,再到 **设置 → Codex 订阅** 登录。插件页面和终端均由 DSH 管理安装。
61
+
62
+ </details>
63
+
64
+ <details>
65
+ <summary>Headless 任务</summary>
66
+
67
+ 先在 Web 中完成登录并选择一次 Codex 模型,再把同一个插件安装到 Headless profile:
28
68
 
29
- 把订阅接入、模型控制、额度管理和图片创作放在同一个 DSH 工作流里。下面逐项列出插件提供的能力;模型权限和额度以账号实际返回为准。
69
+ ```sh
70
+ dsh plugin --profile headless add dsh-codex-subscription@2.6.8
71
+ dsh --profile headless "只回复:ok"
72
+ ```
73
+
74
+ </details>
75
+
76
+ ## 核心功能
77
+
78
+ ### 用订阅登录,直接用 Codex 模型
79
+
80
+ 在 DSH 的 **设置 → Codex 订阅** 登录 ChatGPT,会话里就能选 GPT-6 等账号目录里的模型,调推理档位和速度档位,并使用订阅联网搜索。不需要 API Key。模型和额度以账号实际返回为准。
81
+
82
+ ### 额度一眼看清
83
+
84
+ 短周期和每周额度、重置时间、额外 Credits 与重置卡都在设置里;输入框旁可以常驻显示剩余额度,低于阈值会提醒。
85
+
86
+ <p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="docs/assets/ui-quota-zh-dark.png"><img src="docs/assets/ui-quota-zh-light.png" width="560" alt="额度卡片:每周额度与重置时间,下方可展开使用概览和额度去向"></picture></p>
87
+
88
+ <details>
89
+ <summary>使用概览与额度去向:累计用量、连续天数、每日热力图,以及每周额度花在哪</summary>
90
+ <br>
91
+ <p align="center"><img src="docs/assets/usage-overview.png" width="460" alt="额度卡片里的使用概览与额度去向:累计 token、连续使用天数、最近半年每日用量热力图,以及每周额度按模型、入口、来源的拆分"></p>
92
+ </details>
93
+
94
+ ### 日常操作,留在输入框
95
+
96
+ 选模型、调推理档位、切换速度档位,同时查看剩余额度,无需为每次请求打开设置。
97
+
98
+ <p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="docs/assets/ui-composer-zh-dark.png"><img src="docs/assets/ui-composer-zh-light.png" width="760" alt="输入框:权限、草图、剩余额度、闪电标识的 Fast 模式和模型选择"></picture></p>
30
99
 
31
- ### 模型与搜索
100
+ ### 手机远程控制(Beta)
101
+
102
+ 用 ChatGPT 手机 App 的 Codex 扫码配对,这台电脑上的 DSH 就出现在手机的主机列表里,DeepSeek 等任意 DSH 模型都能在手机上用:
103
+
104
+ - 查看、新建、续聊、中断、归档对话,搜索对话和对话内的关键词;
105
+ - 切换模型、推理档位和权限(工作区内修改 / 完全访问);
106
+ - 批准工具调用或回答提问时手机直接弹出;手机掉线,重新打开会再弹一次,否则交回电脑处理;
107
+ - 回复边生成边显示;命令、文件修改(带差异)、任务清单、联网搜索、连接器调用和生成的图片用手机原生视图显示;
108
+ - 发图片,@ 搜电脑上的文件,/ 选 DSH 技能,只读 git 查看改动,用真实的文件夹选择器新建对话;
109
+ - DSH 工作区对应手机上的项目;可以从手机分叉对话,看用量额度、累计用量和上下文用量;
110
+ - 模型报错会显示在手机上;设置里能看到已配对的手机,随时移除。
111
+
112
+ 默认关闭:**设置 → Codex 订阅 → 模型与运行 → 手机远程控制**。电脑需要保持开机、联网并打开 DSH。这是 OpenAI 尚未向第三方开放的 ChatGPT 能力,随时可能变化,所以标为 Beta,目前在预发布版中提供:`dsh-codex-subscription@3.0.0-beta.5`。
113
+
114
+ <p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="docs/assets/ui-remote-zh-dark.png"><img src="docs/assets/ui-remote-zh-light.png" width="560" alt="设置里的手机远程控制:开关、配对二维码和手动码、已配对的手机"></picture></p>
115
+
116
+ ### 图片与草图(Beta)
117
+
118
+ 用订阅生成图片,在图上圈出区域写备注继续修改,或者打开草图画板自己画、让 Agent 画,再以草图为参考生成成品。
119
+
120
+ <p align="center"><img src="docs/assets/annotate-zh.webp" width="900" alt="图片预览:在烟囱上方圈出区域并写下备注,再带着备注继续编辑"></p>
121
+
122
+ 案例见 [从草图到作品](#从草图到作品),开关在 **设置 → Codex 订阅 → 图片与草图**。
123
+
124
+ ### ChatGPT 连接器(Beta)
125
+
126
+ 让 DeepSeek 等任意 DSH 模型使用你在 ChatGPT 里连接的应用:GitHub、Gmail、Google 云端硬盘、日历等。模型先搜索再调用,写操作每次都要你批准。默认关闭,在“模型与运行”里开启。
127
+
128
+ [详细用法、限制与可选组件 →](docs/GUIDE.zh-CN.md)
129
+
130
+ ## 全部功能
131
+
132
+ 模型权限和额度以账号实际返回为准。
133
+
134
+ <details>
135
+ <summary><b>模型与搜索</b>(13 项)</summary>
136
+ <br>
32
137
 
33
138
  | 功能 | 你可以做什么 | 使用方式 / 条件 |
34
139
  | --- | --- | --- |
@@ -46,7 +151,11 @@
46
151
  | **上下文预算** | 按模型使用标准、扩展或自定义上下文预算 | 受模型目录上限约束 |
47
152
  | **GPT-Reserve** | 在账号开放时选择备用模型入口 | 实验性;不承诺独立备用额度 |
48
153
 
49
- ### 账号与额度
154
+ </details>
155
+
156
+ <details>
157
+ <summary><b>账号与额度</b>(10 项)</summary>
158
+ <br>
50
159
 
51
160
  | 功能 | 你可以做什么 | 使用方式 / 条件 |
52
161
  | --- | --- | --- |
@@ -61,9 +170,11 @@
61
170
  | **使用重置卡** | 在确认后主动使用服务端提供的重置卡 | 二次确认与等待保护,由服务端判定结果 |
62
171
  | **重置后重试** | 等待已确认的短时额度重置,再继续请求 | 默认关闭;等待期间可停止 |
63
172
 
64
- <p align="center"><img src="docs/assets/usage-overview.png" width="460" alt="额度卡片里的使用概览与额度去向:累计 token、连续使用天数、最近半年每日用量热力图,以及每周额度按模型、入口、来源的拆分"></p>
173
+ </details>
65
174
 
66
- ### 图片与草图
175
+ <details>
176
+ <summary><b>图片与草图</b>(12 项)</summary>
177
+ <br>
67
178
 
68
179
  | 功能 | 你可以做什么 | 使用方式 / 条件 |
69
180
  | --- | --- | --- |
@@ -80,7 +191,11 @@
80
191
  | **Agent 绘图** | 用 `@sketch` 让 Agent 绘制,查看进度并随时停止;Agent 可用 SVG 整段作画,导入为可编辑原生笔画 | Beta;默认关闭,需同时开启画板 |
81
192
  | **绘图结果回看** | 完成后向模型返回画布预览,帮助后续检查 | Beta;默认关闭,会增加图片输入用量 |
82
193
 
83
- ### 进阶能力与维护
194
+ </details>
195
+
196
+ <details>
197
+ <summary><b>进阶能力与维护</b>(9 项)</summary>
198
+ <br>
84
199
 
85
200
  | 功能 | 你可以做什么 | 使用方式 / 条件 |
86
201
  | --- | --- | --- |
@@ -94,58 +209,9 @@
94
209
  | **支持诊断** | 查看功能前置条件和近期操作结果,一键复制约 1 KB 的精简报告(完整报告可另行复制);不含凭据和会话正文 | 设置 → 维护;未验证不代表故障 |
95
210
  | **预测缓存清理** | 查看并清理本地额度预测历史 | 保留登录、草稿、原图和共享依赖 |
96
211
 
97
- [详细用法、限制与可选组件 →](docs/GUIDE.zh-CN.md)
98
-
99
- ## 准备 DSH
100
-
101
- 已验证兼容 DSH `0.2.0-rc.2`(`latest` 与 `next` 通道),最低支持 `0.1.7-rc.2`;更早的 DSH 请先升级。
102
-
103
- 本插件支持软件包元数据中记录的最新版 DeepSeek Harness,并需要一个当前具有 Codex 使用资格的 ChatGPT 账户。
104
-
105
- - **推荐:官方桌面端**。DeepSeek 已发布 [DeepSeek Harness 桌面版](https://www.deepseek.com/harness/)(macOS Apple Silicon、Windows 64 位,预览版、开源),无需配置 Node.js,安装后按下文在插件页面添加本插件即可。桌面端与网页版、命令行使用同一套 DSH 插件系统;本插件的端到端验收主要在网页版上完成,桌面端遇到问题请[提交 issue](https://github.com/WSL043/dsh-codex-subscription/issues);
106
- - 需要 Linux,或想要社区便携分发:使用 [DSH-Portable](https://github.com/WSL043/DSH-Portable)。这是面向 Windows、macOS 和 Linux 的社区便携桌面分发;
107
- - 想按官方方式运行:查看 [DeepSeek Harness 官方说明](https://github.com/deepseek-ai/deepseek-harness#run)。
108
-
109
- ## 安装
110
-
111
- ### 在插件页面安装(推荐)
112
-
113
- 1. 打开 DSH 的 **插件 → 添加插件**。
114
- 2. 在 **包名或地址** 输入框中粘贴下面的包名(已带版本号):
115
-
116
- ```text
117
- dsh-codex-subscription@2.5.9
118
- ```
119
-
120
- 3. 点击 **安装**,等待安装完成;按页面提示操作,需要重启时先保存工作。
121
- 4. 打开 **设置 → Codex 订阅**,登录 ChatGPT,然后在会话中选择 Codex 模型。
122
-
123
- 为什么要带版本号:DSH 的插件页只会安装发布满 24 小时的版本,只填包名时,新版本发布后的第一天可能装到更早的旧版,而旧版不一定兼容你的 DSH。带上版本号可以直接装到这一版;发布一天后只填 `dsh-codex-subscription` 也会装到最新正式版。其他版本号见[发布页](https://github.com/WSL043/dsh-codex-subscription/releases)。
124
-
125
- <details>
126
- <summary>终端安装(已能运行 dsh 命令)</summary>
127
-
128
- ```sh
129
- dsh plugin --profile web add dsh-codex-subscription@2.5.9
130
- ```
131
-
132
- 安装完成后按提示重启 DSH,再到 **设置 → Codex 订阅** 登录。插件页面和终端均由 DSH 管理安装。
133
-
134
- </details>
135
-
136
- <details>
137
- <summary>Headless 任务</summary>
138
-
139
- 先在 Web 中完成登录并选择一次 Codex 模型,再把同一个插件安装到 Headless profile:
140
-
141
- ```sh
142
- dsh plugin --profile headless add dsh-codex-subscription@2.5.9
143
- dsh --profile headless "只回复:ok"
144
- ```
145
-
146
212
  </details>
147
213
 
148
- ## 界面一览
214
+ ## 界面演示
149
215
 
150
216
  <details>
151
217
  <summary><b>界面演示(动图,点击展开)</b>:选模型、提问、出图、标注、草图、额度与重置</summary>
@@ -153,32 +219,6 @@ dsh --profile headless "只回复:ok"
153
219
  <p align="center"><img src="docs/assets/readme-demo.webp" width="1100" alt="演示:登录 ChatGPT 选订阅模型、提问、用订阅出图、查看与标注、进入草图、查看额度与重置"></p>
154
220
  </details>
155
221
 
156
- ### 日常操作,留在输入框
157
-
158
- 选模型、调推理档位、切换速度档位,同时查看剩余额度。无需为每次请求打开设置。
159
-
160
- <p align="center"><img src="docs/assets/composer-astra-fast.png" width="800" alt="DSH 输入框:GPT-6-Astra Max、闪电标识的 Fast 高速模式与剩余额度"></p>
161
-
162
- ### 手机远程控制 DSH(Beta)
163
-
164
- 打开 **设置 → Codex 订阅 → 模型与运行 → 手机远程控制**,用 ChatGPT 手机 App 的 Codex 扫码配对,这台电脑上的 DSH 就会出现在手机的主机列表里:
165
-
166
- - 在手机上查看、新建、续聊、中断和归档 DSH 对话,DeepSeek、Codex 以及其他 DSH 模型都能用;
167
- - 在手机上切换模型、推理档位和权限(工作区内修改 / 完全访问);
168
- - DSH 需要批准工具调用或向你提问时,手机会直接弹出;手机掉线会在重新打开时再弹一次,否则交回电脑处理;
169
- - 回复边生成边显示在手机上;
170
- - 命令、文件修改(带差异)、任务清单、生成的图片在手机上用原生视图显示,文件修改的审批也能看到差异;
171
- - DSH 工作区对应手机上的项目,可在项目里新建对话,也能从手机分叉对话、看到用量额度和上下文用量;
172
- - 手机上可以用 @ 搜索电脑上的文件、用 / 选择 DSH 技能,也能在手机上查看改动(只读 git);还能搜索对话、在对话内搜关键词,并查看累计用量;
173
- - 设置里可以看到已配对的手机,并能随时移除;
174
- - 在手机上发图片(可配文字),DSH 生成的图片也会显示在手机上;
175
- - 手机的文件夹选择器能浏览这台电脑上真实的文件夹,新对话可以直接在其中开始;
176
- - 模型报错会显示在手机上。
177
-
178
- 默认关闭。电脑需要保持开机、联网并打开 DSH。这是 OpenAI 尚未向第三方开放的 ChatGPT 能力,随时可能变化,所以标为 Beta。目前在预发布版中提供:`dsh-codex-subscription@3.0.0-beta.5`。
179
-
180
- <p align="center"><img src="docs/assets/remote-control.png" width="560" alt="官方桌面版设置页:手机远程控制已连接,显示配对二维码和手动码"></p>
181
-
182
222
  ### 账号与偏好,集中管理
183
223
 
184
224
  在 **设置 → Codex 订阅** 中管理账号和额度;其余功能按任务需要开启。
@@ -297,9 +337,9 @@ SVG 版在“这次只在草图画布上画”之前多加了一句:
297
337
  <details>
298
338
  <summary>查看图片与草图设置</summary>
299
339
 
300
- <p align="center"><img src="docs/assets/real-creative-zh.png" width="564" alt="图片与草图设置:生图编辑、请求型号,以及独立的画板和 Agent 开关"></p>
340
+ <p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="docs/assets/ui-creative-zh-dark.png"><img src="docs/assets/ui-creative-zh-light.png" width="564" alt="图片与草图设置:图片生成与编辑、创作入口、请求型号与质量"></picture></p>
301
341
 
302
- DSH 实机设置截图。
342
+ DSH 实机设置截图,随浅色 / 深色主题切换。
303
343
 
304
344
  </details>
305
345
 
@@ -307,14 +347,6 @@ DSH 实机设置截图。
307
347
 
308
348
  [图片编辑与草稿保存 →](docs/GUIDE.zh-CN.md#图片生成与编辑beta)
309
349
 
310
- <a id="codex-subtask-runtime"></a>
311
-
312
- ## 按需扩展
313
-
314
- 普通订阅聊天无需 Codex CLI。需要 **Codex 独立子任务** 时,可在“模型与运行”中点击“安装组件”,停用和卸载也在同一处完成。其余实验选项按需开启。
315
-
316
- [可选组件、存储清理与完整使用指南 →](docs/GUIDE.zh-CN.md)
317
-
318
350
  ## 更新与卸载
319
351
 
320
352
  在 DSH **插件** 页面找到本插件,使用更新或卸载操作,完成后按页面提示重启。卸载插件不会删除其他插件。
@@ -323,7 +355,7 @@ DSH 实机设置截图。
323
355
  <summary>终端方式</summary>
324
356
 
325
357
  ```sh
326
- dsh plugin --profile web update dsh-codex-subscription@2.5.9
358
+ dsh plugin --profile web update dsh-codex-subscription@2.6.8
327
359
  ```
328
360
 
329
361
  仅在需要卸载时运行:
@@ -336,13 +368,6 @@ dsh plugin --profile web remove dsh-codex-subscription
336
368
 
337
369
  ## 常见问题
338
370
 
339
- <details>
340
- <summary>DSH 0.2.0-rc.2 提示插件不兼容?</summary>
341
-
342
- 2.2.10 之前的所有版本发布时 DSH 0.2.0-rc.2 还不存在,其兼容声明无法事后修改。请安装 2.2.10 或更高版本(只填包名时,发布满 24 小时前可能装到旧版,请直接填 `dsh-codex-subscription@2.2.10`):在 **插件** 页面更新,或运行 `dsh plugin --profile web update dsh-codex-subscription@2.5.9`,然后重启 DSH。
343
-
344
- </details>
345
-
346
371
  <details>
347
372
  <summary>和官方插件列表里的 Codex 组合包(dsh-hooks-codex)是什么关系?</summary>
348
373
 
@@ -373,15 +398,12 @@ dsh plugin --profile web remove dsh-codex-subscription
373
398
 
374
399
  </details>
375
400
 
376
- ## 当前图标
377
-
378
- 这是当前使用的插件图标,以及它在 DSH「已安装」列表中的实际显示效果。
379
-
380
- <p align="center"><img src="icon-subscription.webp" width="200" height="200" alt="当前 Codex 订阅插件图标"></p>
401
+ <details>
402
+ <summary>需要装 Codex 命令行才能用吗?</summary>
381
403
 
382
- <p align="center"><img src="docs/assets/plugin-installed.png" width="800" alt="DSH 已安装列表中的 Codex 订阅插件卡片"></p>
404
+ 普通订阅聊天不需要。只有想用 **Codex 独立子任务** 时,才在“设置 → Codex 订阅 → 模型与运行”里点“安装组件”,停用和卸载也在同一处。其余实验选项按需开启。[可选组件、存储清理与完整说明 →](docs/GUIDE.zh-CN.md)
383
405
 
384
- <sub>DSH 0.1.7-alpha.2 实机界面。</sub>
406
+ </details>
385
407
 
386
408
  ## 定位与边界
387
409
 
@@ -7,6 +7,7 @@
7
7
  ],
8
8
  "previews": [
9
9
  "0.2.1-alpha.1",
10
- "0.2.1-alpha.2"
10
+ "0.2.1-alpha.2",
11
+ "0.2.1-alpha.3"
11
12
  ]
12
13
  }
package/lib/client.js CHANGED
@@ -9282,7 +9282,7 @@ window.__ModuleLoader__.load({
9282
9282
  }
9283
9283
  //#endregion
9284
9284
  //#region src/version.js
9285
- const PACKAGE_VERSION = "3.0.0-beta.5";
9285
+ const PACKAGE_VERSION = "3.0.0-beta.6";
9286
9286
  //#endregion
9287
9287
  //#region src/client-recovery.js
9288
9288
  async function recoveryCall(rpc, endpoint, payload = {}, timeoutMs = 1e4) {
package/lib/index.js CHANGED
@@ -54,6 +54,37 @@ function createSettingsAdapter(ctx, config) {
54
54
  };
55
55
  }
56
56
  //#endregion
57
+ //#region src/request-observer.js
58
+ const failureOf = (chunk) => chunk?.reason?.kind === "error" ? chunk.reason.failure : void 0;
59
+ function observed(stream, options, provider) {
60
+ return (async function* () {
61
+ try {
62
+ for await (const chunk of stream(options)) {
63
+ const failure = failureOf(chunk);
64
+ if (failure !== void 0 && !options?.signal?.aborted) provider.noteAdapterFailure?.("failure", options, failure);
65
+ yield chunk;
66
+ }
67
+ } catch (error) {
68
+ if (!options?.signal?.aborted) provider.noteAdapterFailure?.("thrown", options, error);
69
+ throw error;
70
+ }
71
+ })();
72
+ }
73
+ function observeAdapter(adapter, provider) {
74
+ return new Proxy(adapter, { get(target, property) {
75
+ if (property === "stream") return (options) => observed((o) => target.stream(o), options, provider);
76
+ if (property === "prepareCall") return async (...args) => {
77
+ const call = await target.prepareCall(...args);
78
+ return {
79
+ ...call,
80
+ stream: (options) => observed((o) => call.stream(o), options, provider)
81
+ };
82
+ };
83
+ const value = Reflect.get(target, property, target);
84
+ return typeof value === "function" ? value.bind(target) : value;
85
+ } });
86
+ }
87
+ //#endregion
57
88
  //#region src/default-model.js
58
89
  /**
59
90
  * DSH owns the model a freshly created agent starts on. This module is the
@@ -1368,7 +1399,8 @@ const SUPPORTED_RUNTIME_VERSIONS = Object.freeze([
1368
1399
  "0.2.0-rc.1",
1369
1400
  "0.2.0-rc.2",
1370
1401
  "0.2.1-alpha.1",
1371
- "0.2.1-alpha.2"
1402
+ "0.2.1-alpha.2",
1403
+ "0.2.1-alpha.3"
1372
1404
  ]);
1373
1405
  const require = createRequire(import.meta.url);
1374
1406
  const execute = promisify(execFile);
@@ -2126,7 +2158,7 @@ function inheritedOriginalImageRef(session, assetId) {
2126
2158
  }
2127
2159
  //#endregion
2128
2160
  //#region src/version.js
2129
- const PACKAGE_VERSION = "3.0.0-beta.5";
2161
+ const PACKAGE_VERSION = "3.0.0-beta.6";
2130
2162
  const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
2131
2163
  //#endregion
2132
2164
  //#region src/codex-images.js
@@ -3750,7 +3782,7 @@ const SKIP = /* @__PURE__ */ new Set([
3750
3782
  "coverage"
3751
3783
  ]);
3752
3784
  const MAX_ENTRIES = 3e4;
3753
- const MAX_DEPTH = 8;
3785
+ const MAX_DEPTH$1 = 8;
3754
3786
  const BUDGET_MS = 2e3;
3755
3787
  const RESULTS = 50;
3756
3788
  /** Subsequence match with a bonus for runs, word starts and the file name; undefined when the query is not in the text. */
@@ -3814,7 +3846,7 @@ async function searchFiles({ roots, query, folders, now = Date.now }) {
3814
3846
  score: match.score,
3815
3847
  indices: match.indices
3816
3848
  });
3817
- if (directory && !SKIP.has(entry.name) && depth < MAX_DEPTH) queue.push([join(folder, entry.name), depth + 1]);
3849
+ if (directory && !SKIP.has(entry.name) && depth < MAX_DEPTH$1) queue.push([join(folder, entry.name), depth + 1]);
3818
3850
  }
3819
3851
  }
3820
3852
  }
@@ -6329,8 +6361,78 @@ function createCodexRpcHandler(coordinator, options = {}) {
6329
6361
  };
6330
6362
  }
6331
6363
  //#endregion
6364
+ //#region src/failure-capture.js
6365
+ const KEEP = /* @__PURE__ */ new Set([
6366
+ "method",
6367
+ "type",
6368
+ "role",
6369
+ "name",
6370
+ "api",
6371
+ "provider",
6372
+ "model",
6373
+ "stopReason",
6374
+ "reasoning",
6375
+ "reasoningEffort",
6376
+ "transport",
6377
+ "mimeType",
6378
+ "kind",
6379
+ "effort",
6380
+ "toolChoice",
6381
+ "cacheRetention",
6382
+ "textVerbosity",
6383
+ "serviceTier"
6384
+ ]);
6385
+ const DROP = /* @__PURE__ */ new Set([
6386
+ "apiKey",
6387
+ "headers",
6388
+ "env",
6389
+ "authorization",
6390
+ "token",
6391
+ "signal",
6392
+ "fetch",
6393
+ "cookie"
6394
+ ]);
6395
+ const MAX_DEPTH = 10;
6396
+ const MAX_ARRAY = 40;
6397
+ const MAX_KEYS = 80;
6398
+ const MAX_NODES = 4e3;
6399
+ const MAX_TEXT$1 = 64;
6400
+ const UNDEFINED_MARKER = "$undefined";
6401
+ function redactRequest(value) {
6402
+ let nodes = 0;
6403
+ const walk = (item, key, depth) => {
6404
+ nodes += 1;
6405
+ if (nodes > MAX_NODES) return { $truncated: "nodes" };
6406
+ if (item === void 0) return { [UNDEFINED_MARKER]: true };
6407
+ if (item === null || typeof item === "boolean") return item;
6408
+ if (typeof item === "number") return Number.isFinite(item) ? item : { $number: String(item) };
6409
+ if (typeof item === "bigint" || typeof item === "symbol") return { $type: typeof item };
6410
+ if (typeof item === "function") return { $type: "function" };
6411
+ if (typeof item === "string") {
6412
+ if (KEEP.has(key) && item.length <= MAX_TEXT$1) return item;
6413
+ return item.length <= MAX_TEXT$1 ? "x".repeat(item.length) : { $text: item.length };
6414
+ }
6415
+ if (depth >= MAX_DEPTH) return { $truncated: "depth" };
6416
+ if (Array.isArray(item)) {
6417
+ const list = [];
6418
+ for (let index = 0; index < Math.min(item.length, MAX_ARRAY); index += 1) list.push(index in item ? walk(item[index], key, depth + 1) : { $hole: true });
6419
+ return item.length > MAX_ARRAY ? [...list, { $more: item.length - MAX_ARRAY }] : list;
6420
+ }
6421
+ if (item instanceof Uint8Array) return { $bytes: item.byteLength };
6422
+ if (typeof item === "object") {
6423
+ const entries = Object.keys(item).filter((name) => !DROP.has(name));
6424
+ const out = {};
6425
+ for (const name of entries.slice(0, MAX_KEYS)) out[name] = walk(item[name], name, depth + 1);
6426
+ if (entries.length > MAX_KEYS) out.$moreKeys = entries.length - MAX_KEYS;
6427
+ return out;
6428
+ }
6429
+ return { $type: typeof item };
6430
+ };
6431
+ return walk(value, "", 0);
6432
+ }
6433
+ //#endregion
6332
6434
  //#region src/transport-failure.js
6333
- const TRANSIENT_WEBSOCKET_CLOSE = /^WebSocket closed (?:1006|1011|1012|1013)(?:\s|$)/;
6435
+ const TRANSIENT_WEBSOCKET_CLOSE = /^WebSocket closed (?:1000|1006|1011|1012|1013)(?:\s|$)/;
6334
6436
  const GATEWAY_REPLAY_BUFFER_EXCEEDED = /^\s*exceeded request buffer limit while retrying upstream\s*$/;
6335
6437
  function normalizeTransportEvent(event, signal) {
6336
6438
  if (signal?.aborted || event?.type !== "error" || event.reason !== "error") return event;
@@ -6491,6 +6593,36 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
6491
6593
  sessionModel: 0,
6492
6594
  retries: 0
6493
6595
  };
6596
+ const streamFailure = {
6597
+ count: 0,
6598
+ stage: void 0,
6599
+ frame: void 0,
6600
+ request: void 0,
6601
+ adapter: void 0
6602
+ };
6603
+ const noteAdapterFailure = (kind, adapterOptions, failure) => {
6604
+ try {
6605
+ streamFailure.adapter = {
6606
+ kind,
6607
+ ...typeof failure?.code === "string" ? { code: failure.code.slice(0, 40) } : {},
6608
+ message: String(failure?.message ?? "").slice(0, 160),
6609
+ request: redactRequest(adapterOptions)
6610
+ };
6611
+ } catch {
6612
+ streamFailure.adapter = void 0;
6613
+ }
6614
+ };
6615
+ const noteStreamFailure = (stage, error, source) => {
6616
+ streamFailure.count += 1;
6617
+ streamFailure.stage = stage;
6618
+ try {
6619
+ streamFailure.request = source === void 0 ? void 0 : redactRequest(source);
6620
+ } catch {
6621
+ streamFailure.request = void 0;
6622
+ }
6623
+ const frame = typeof error?.stack === "string" ? /([\w.@-]+[\\/][\w.-]+\.[cm]?[jt]sx?):(\d+):(\d+)/u.exec(error.stack.split("\n").slice(1).join("\n")) : null;
6624
+ streamFailure.frame = frame ? `${frame[1].replaceAll("\\", "/")}:${frame[2]}:${frame[3]}` : void 0;
6625
+ };
6494
6626
  const reviewRoute = (model, context) => {
6495
6627
  if (resolveReviewModel() !== "official" || !isDshAutoReview(context)) return void 0;
6496
6628
  review.requests += 1;
@@ -6545,22 +6677,40 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
6545
6677
  };
6546
6678
  return { [Symbol.asyncIterator]: () => replay ??= run() };
6547
6679
  };
6548
- const networkIterable = (factory, options, direct = false) => {
6680
+ const networkIterable = (factory, options, direct = false, source) => {
6549
6681
  let iterator;
6550
6682
  let prepared;
6683
+ let stage = "prepare";
6551
6684
  const step = async (method, value) => {
6552
- const request = await (prepared ??= (direct ? void 0 : connection?.prepare(options)) ?? Promise.resolve({ options }));
6553
- const result = await runNetwork("model", () => {
6554
- iterator ??= factory(direct ? request.options : compaction?.requestOptions(request.options) ?? request.options)[Symbol.asyncIterator]();
6555
- return iterator[method]?.(value) ?? (method === "throw" ? Promise.reject(value) : Promise.resolve({
6556
- done: true,
6557
- value
6558
- }));
6559
- }, direct ? request.network : compaction?.networkOptions(request.network) ?? request.network);
6560
- return result.done ? result : {
6561
- ...result,
6562
- value: normalizeTransportEvent(result.value, request.options?.signal)
6563
- };
6685
+ try {
6686
+ const request = await (prepared ??= (direct ? void 0 : connection?.prepare(options)) ?? Promise.resolve({ options }));
6687
+ if (stage === "prepare") stage = "request";
6688
+ const result = await runNetwork("model", () => {
6689
+ const next = direct ? request.options : compaction?.requestOptions(request.options) ?? request.options;
6690
+ iterator ??= factory({
6691
+ ...next,
6692
+ async onPayload(payload, requestModel) {
6693
+ stage = "payload";
6694
+ return next.onPayload?.(payload, requestModel);
6695
+ }
6696
+ })[Symbol.asyncIterator]();
6697
+ return iterator[method]?.(value) ?? (method === "throw" ? Promise.reject(value) : Promise.resolve({
6698
+ done: true,
6699
+ value
6700
+ }));
6701
+ }, direct ? request.network : compaction?.networkOptions(request.network) ?? request.network);
6702
+ if (!result.done) {
6703
+ if (result.value?.type === "error" && !request.options?.signal?.aborted) noteStreamFailure(stage, void 0, source);
6704
+ else if (stage === "payload") stage = "stream";
6705
+ }
6706
+ return result.done ? result : {
6707
+ ...result,
6708
+ value: normalizeTransportEvent(result.value, request.options?.signal)
6709
+ };
6710
+ } catch (error) {
6711
+ noteStreamFailure(stage, error, source);
6712
+ throw error;
6713
+ }
6564
6714
  };
6565
6715
  return {
6566
6716
  [Symbol.asyncIterator]() {
@@ -6576,7 +6726,13 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
6576
6726
  };
6577
6727
  const routed = (method, model, context, options) => {
6578
6728
  const route = reviewRoute(model, context);
6579
- const create = () => route === void 0 ? networkIterable((prepared) => provider[method](model, context, prepared), withPreferences(model, options)) : networkIterable((prepared) => provider[method](model, context, prepared), withReview(route, options), true);
6729
+ const source = {
6730
+ method,
6731
+ model,
6732
+ context,
6733
+ options
6734
+ };
6735
+ const create = () => route === void 0 ? networkIterable((prepared) => provider[method](model, context, prepared), withPreferences(model, options), false, source) : networkIterable((prepared) => provider[method](model, context, prepared), withReview(route, options), true, source);
6580
6736
  return isDshAutoReview(context) ? reviewIterable(create) : create();
6581
6737
  };
6582
6738
  return Object.freeze({
@@ -6588,7 +6744,9 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
6588
6744
  getModels,
6589
6745
  stream: (model, context, options) => routed("stream", model, context, options),
6590
6746
  streamSimple: (model, context, options) => routed("streamSimple", model, context, options),
6591
- reviewCounters: () => ({ ...review })
6747
+ reviewCounters: () => ({ ...review }),
6748
+ streamFailure: () => ({ ...streamFailure }),
6749
+ noteAdapterFailure
6592
6750
  });
6593
6751
  }
6594
6752
  Object.freeze([
@@ -7598,6 +7756,26 @@ async function createSubscriptionDiagnostics({ auth, preferences, login = { phas
7598
7756
  "retries"
7599
7757
  ]) : void 0
7600
7758
  ],
7759
+ [
7760
+ "streamFailure",
7761
+ "transport",
7762
+ () => {
7763
+ const value = review?.streamFailure?.();
7764
+ if (!Number.isSafeInteger(value?.count)) return void 0;
7765
+ return {
7766
+ count: value.count,
7767
+ ...[
7768
+ "prepare",
7769
+ "request",
7770
+ "payload",
7771
+ "stream"
7772
+ ].includes(value.stage) ? { stage: value.stage } : {},
7773
+ ...typeof value.frame === "string" && /^[\w.@/-]{1,120}:\d+:\d+$/u.test(value.frame) ? { frame: value.frame } : {},
7774
+ ...value.request && typeof value.request === "object" && JSON.stringify(value.request).length <= 12e4 ? { request: value.request } : {},
7775
+ ...value.adapter && typeof value.adapter === "object" && JSON.stringify(value.adapter).length <= 12e4 ? { adapter: value.adapter } : {}
7776
+ };
7777
+ }
7778
+ ],
7601
7779
  [
7602
7780
  "operations",
7603
7781
  "transport",
@@ -7701,6 +7879,7 @@ async function createSubscriptionDiagnostics({ auth, preferences, login = { phas
7701
7879
  ...collected.websocket ? { websocket: collected.websocket } : {},
7702
7880
  ...collected.compaction ? { compaction: collected.compaction } : {},
7703
7881
  ...collected.review ? { review: collected.review } : {},
7882
+ ...collected.streamFailure ? { streamFailure: collected.streamFailure } : {},
7704
7883
  ...catalog && ["unavailable", "online"].includes(catalog.source) && [
7705
7884
  "idle",
7706
7885
  "refreshing",
@@ -9988,7 +10167,8 @@ function apply(ctx, config = {}) {
9988
10167
  let resolved;
9989
10168
  try {
9990
10169
  resolved = await resolveAuth();
9991
- } catch {
10170
+ } catch (error) {
10171
+ if (error?.code === "MISSING_CREDENTIAL") throw new dshLlm.LlmError("ChatGPT subscription is not signed in", "MISSING_CREDENTIAL");
9992
10172
  throw new dshLlm.LlmError("ChatGPT subscription authorization failed", "AUTH_FAILED");
9993
10173
  }
9994
10174
  if (typeof resolved?.auth.apiKey !== "string" || resolved.auth.apiKey.length === 0) throw new dshLlm.LlmError("ChatGPT subscription is not signed in", "MISSING_CREDENTIAL");
@@ -9997,7 +10177,7 @@ function apply(ctx, config = {}) {
9997
10177
  auth: adapterAuth,
9998
10178
  resolveAttachments: () => ctx.get?.("attachments")
9999
10179
  });
10000
- ctx.llm.registerAdapter([PROVIDER], compaction.wrapAdapter(adapter));
10180
+ ctx.llm.registerAdapter([PROVIDER], observeAdapter(compaction.wrapAdapter(adapter), provider));
10001
10181
  const currentAgent = () => ctx.get?.("agents")?.currentInitiator?.();
10002
10182
  const codexSearch = createCodexSearchProvider({
10003
10183
  resolvePreferences: () => readCapabilitySettings(settings.get()),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-codex-subscription",
3
- "version": "3.0.0-beta.5",
3
+ "version": "3.0.0-beta.6",
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",
@@ -76,23 +76,23 @@
76
76
  "node": "^22.19.0 || >=24.0.0"
77
77
  },
78
78
  "peerDependencies": {
79
- "@deepseek-ai/cordis": "4.0.4 || 4.0.5-alpha.1",
80
- "@deepseek-ai/dsh-api-remotes": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
81
- "@deepseek-ai/dsh-client-connection": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
82
- "@deepseek-ai/dsh-client-locale": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
83
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
84
- "@deepseek-ai/dsh-client-ui-model-selection": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
85
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
86
- "@deepseek-ai/dsh-client-ui-settings": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
87
- "@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
88
- "@deepseek-ai/dsh-client-ui-tool": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
89
- "@deepseek-ai/dsh-credentials": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
90
- "@deepseek-ai/dsh-llm": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
91
- "@deepseek-ai/dsh-llm-pi-ai": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
92
- "@deepseek-ai/dsh-settings": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
93
- "@deepseek-ai/dsh-subagent-codex": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
94
- "@deepseek-ai/dsh-tools": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
95
- "@deepseek-ai/dsh-web": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2",
79
+ "@deepseek-ai/cordis": "4.0.4 || 4.0.5-alpha.1 || 4.0.5-alpha.2",
80
+ "@deepseek-ai/dsh-api-remotes": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
81
+ "@deepseek-ai/dsh-client-connection": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
82
+ "@deepseek-ai/dsh-client-locale": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
83
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
84
+ "@deepseek-ai/dsh-client-ui-model-selection": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
85
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
86
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
87
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
88
+ "@deepseek-ai/dsh-client-ui-tool": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
89
+ "@deepseek-ai/dsh-credentials": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
90
+ "@deepseek-ai/dsh-llm": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
91
+ "@deepseek-ai/dsh-llm-pi-ai": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
92
+ "@deepseek-ai/dsh-settings": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
93
+ "@deepseek-ai/dsh-subagent-codex": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
94
+ "@deepseek-ai/dsh-tools": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
95
+ "@deepseek-ai/dsh-web": "0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
96
96
  "@deepseek-ai/schemastery": "3.18.1 || ^3.18.2",
97
97
  "@earendil-works/pi-ai": "0.85.1 || 0.87.1 || 1.1.0 || 1.2.0",
98
98
  "react": "^18.2.0",