dsh-codex-subscription 2.1.3-beta.1 → 2.1.3
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 +59 -13
- package/README.md +59 -13
- package/lib/client.js +235 -8
- package/lib/index.js +198 -15
- package/package.json +9 -6
package/README.en.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
# DSH Codex Subscription
|
|
3
|
+
# DSH Codex Subscription — Use ChatGPT subscriptions in DeepSeek Harness
|
|
4
4
|
|
|
5
5
|
[简体中文](https://github.com/WSL043/dsh-codex-subscription/blob/main/README.md) · **English**
|
|
6
6
|
|
|
@@ -19,18 +19,20 @@ No OpenAI API key or Codex CLI. Models, search, quota, and image generation stay
|
|
|
19
19
|
</div>
|
|
20
20
|
|
|
21
21
|
<p align="center">
|
|
22
|
-
<img src="
|
|
22
|
+
<img src="docs/assets/codex-subscription-overview-en.webp" width="900" alt="Use ChatGPT and Codex subscriptions in DeepSeek Harness: sign in without an API key, choose models and view remaining quota">
|
|
23
23
|
</p>
|
|
24
24
|
|
|
25
25
|
## Three-step start
|
|
26
26
|
|
|
27
|
-
1. **Install the plugin.**
|
|
27
|
+
1. **Install the plugin.** In newer DSH, open **Plugins → Add plugin** and enter `dsh-codex-subscription`. To select a candidate, enter `package@version`, for example `dsh-codex-subscription@2.1.3-beta.1`. This field does not accept a full terminal command.
|
|
28
|
+
|
|
29
|
+
For older DSH or terminal use, run:
|
|
28
30
|
|
|
29
31
|
```sh
|
|
30
32
|
dsh plugin --profile web add dsh-codex-subscription
|
|
31
33
|
```
|
|
32
34
|
|
|
33
|
-
2. **Sign in.**
|
|
35
|
+
2. **Sign in.** Follow the installation result; save your work and restart only if requested. Open **Settings -> Codex**, and choose browser sign-in. No Codex CLI and no pasted token are required.
|
|
34
36
|
3. **Use Codex.** Select a Codex model. Quota, subscription search, image generation, and Fast mode remain inside DSH.
|
|
35
37
|
|
|
36
38
|
DSH-Portable exposes the same standard plugin command, so the command above also applies there. See below for the complete official npm, update, and uninstall routes.
|
|
@@ -55,10 +57,10 @@ These capabilities reuse the same local ChatGPT sign-in. Subscription routing fa
|
|
|
55
57
|
## Product screen
|
|
56
58
|
|
|
57
59
|
<p align="center">
|
|
58
|
-
<img src="
|
|
60
|
+
<img src="docs/assets/subscription-account-en.png" width="820" alt="DSH Codex subscription main screen: ChatGPT sign-in, remaining quota and composer preferences">
|
|
59
61
|
</p>
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
The actual Account & preferences screen shows sign-in status, subscription quota and composer preferences. Account, quota, balance and time values are demo data, not fixed plan entitlements. Advanced options and optional components are described below.
|
|
62
64
|
|
|
63
65
|
## Prepare DSH
|
|
64
66
|
|
|
@@ -134,6 +136,10 @@ Restart DSH manually after installation, then:
|
|
|
134
136
|
- Visible errors when subscription routing is unavailable, with no silent paid fallback.
|
|
135
137
|
|
|
136
138
|
|
|
139
|
+
### GPT-Reserve (Experimental)
|
|
140
|
+
|
|
141
|
+
When the account’s official catalog advertises `gpt-reserve`, it appears at the end of the model picker as an experimental option. Availability and billing are determined by the service; a successful response does not confirm use of a separate reserve allowance. The composer shows only a matching quota bucket returned by the service, and does not substitute ordinary Codex quota when none is returned.
|
|
142
|
+
|
|
137
143
|
### GPT-6 Astra context
|
|
138
144
|
|
|
139
145
|
When the official model catalog exposes GPT-6 Astra, Standard preserves the catalog window, Extended uses 872000 tokens, and Custom accepts 128000–872000 tokens (initially 272000). This limit follows the [official Codex model catalog](https://github.com/openai/codex/blob/6af345407d9c2a568da9d01b6c4b81a9e61495c0/codex-rs/models-manager/models.json#L33-L34), not the API model's total context capacity. These settings only adjust DSH's local context budget; they do not grant model access or guarantee an account's server-side capacity. Actual availability remains subject to the service.
|
|
@@ -141,7 +147,7 @@ When the official model catalog exposes GPT-6 Astra, Standard preserves the cata
|
|
|
141
147
|
### Composer quota
|
|
142
148
|
|
|
143
149
|
<p align="center">
|
|
144
|
-
<img src="
|
|
150
|
+
<img src="docs/assets/composer-quota.png" width="800" alt="Live DSH composer with GPT-6-Astra, Max reasoning, Fast mode, and remaining quota">
|
|
145
151
|
</p>
|
|
146
152
|
|
|
147
153
|
Live example: GPT-6-Astra with Max (the highest reasoning level) and Fast mode (lightning icon), with remaining quota visible on the left.
|
|
@@ -170,14 +176,14 @@ New and edited images return the exact original path on the current DSH host in
|
|
|
170
176
|
A new image request does not silently include earlier images. GPT Image 2 can take longer than a normal text turn, and detailed text, exact composition, or repeated-character consistency may still need another pass.
|
|
171
177
|
|
|
172
178
|
<p align="center">
|
|
173
|
-
<img src="
|
|
179
|
+
<img src="docs/assets/image-preview-annotations-en.png" width="800" alt="Generated image, region note, and continue editing inside the DSH Image Viewer">
|
|
174
180
|
</p>
|
|
175
181
|
|
|
176
182
|
The screenshot above illustrates image viewing and on-image notes; available buttons can vary with the image and installed viewer version.
|
|
177
183
|
|
|
178
184
|
### Sketch canvas (Beta)
|
|
179
185
|
|
|
180
|
-

|
|
181
187
|
|
|
182
188
|
Use the composer pen button for manual drawing. Selecting `@sketch` only inserts the Agent entry into the composer; the Agent opens the board after you send your drawing request. You can also choose Open in sketch from an enhanced image preview. Attachment intake and removal use the native DSH component.
|
|
183
189
|
|
|
@@ -189,7 +195,7 @@ The board supports editable shapes and text, native curves, and a side control f
|
|
|
189
195
|
|
|
190
196
|
| Original sketch | Actual plugin output |
|
|
191
197
|
| --- | --- |
|
|
192
|
-
|  |  |
|
|
193
199
|
|
|
194
200
|
The request preserves the mountain and cabin composition while creating a warm watercolor travel illustration with green peaks, an orange roof, a meadow stream and morning light, without the blue outlines. GPT-5.6-Luna made one image-tool call requesting low quality. Luna is the conversation model; the subscription backend determines the actual image model.
|
|
195
201
|
|
|
@@ -202,7 +208,7 @@ The request preserves the mountain and cabin composition while creating a warm w
|
|
|
202
208
|
|
|
203
209
|
| Native sketch | Generated result |
|
|
204
210
|
| --- | --- |
|
|
205
|
-
|  |  |
|
|
206
212
|
|
|
207
213
|
**Sketch reproduction prompt (reconstructed from the artwork, not the original conversation)**
|
|
208
214
|
|
|
@@ -228,7 +234,7 @@ Actual results supplied by the user from another computer: Astra draws on a port
|
|
|
228
234
|
|
|
229
235
|
| Native Astra sketch | GPT-generated oil painting |
|
|
230
236
|
| --- | --- |
|
|
231
|
-
|  |  |
|
|
232
238
|
|
|
233
239
|
Original sketch prompt: `@sketch 用竖版画板画一幅《蒙娜丽莎》` (Draw the Mona Lisa on a portrait canvas.)
|
|
234
240
|
|
|
@@ -249,7 +255,47 @@ see the [OpenAI Codex Speed documentation](https://learn.chatgpt.com/docs/agent-
|
|
|
249
255
|
Opt in under **Advanced & diagnostics**. SSE and DSH subtasks remain the defaults:
|
|
250
256
|
|
|
251
257
|
- **WebSocket** reuses connections and eligible context transfers. Failed handshakes can fall back to SSE; interrupted responses surface an error without automatic replay. Applies to the next request, does not expand context limits, and is not guaranteed to be faster.
|
|
252
|
-
- **Codex independent subtasks** reuse your subscription login and the official DSH Codex runtime, without a separate login
|
|
258
|
+
- **Codex independent subtasks** reuse your subscription login and the official DSH Codex runtime, without a separate login; install its optional component in settings. They inherit the current subscription model and workspace permissions by default. Enable DSH subtask model selection, configure allowed models and start a new session to specify the child model and reasoning effort in chat. Non-subscription sessions must explicitly select a subscription model. Shared-context subtasks remain with DSH.
|
|
259
|
+
|
|
260
|
+
<a id="codex-subtask-runtime"></a>
|
|
261
|
+
|
|
262
|
+
## Optional Codex subtask runtime
|
|
263
|
+
|
|
264
|
+
Subscription chat, images, and native DSH subtasks do not need Codex CLI. Only **Codex independent subtasks (Beta)** require the optional official runtime. The plugin never downloads it in the background.
|
|
265
|
+
|
|
266
|
+
In **Settings → Codex → Advanced → Independent subtasks**, click **Install component**. DSH handles installation; the page shows its stage and offers cancellation before applying. Restart after completion, then choose Codex. Installation does not enable subtasks automatically.
|
|
267
|
+
|
|
268
|
+

|
|
269
|
+
|
|
270
|
+
For older hosts without the management interface, run this in the target DSH environment, then restart:
|
|
271
|
+
|
|
272
|
+
```sh
|
|
273
|
+
dsh plugin --profile web add @deepseek-ai/dsh-subagent-codex@0.1.5-rc.2
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
In the plugin installation UI, enter only `@deepseek-ai/dsh-subagent-codex@0.1.5-rc.2`, not the full command. Select Codex in advanced settings after preparation. Missing or failed preparation does not block subscription chat or the DSH backend. Shared-context subtasks remain in DSH.
|
|
277
|
+
|
|
278
|
+
For offline preparation, install and verify beforehand on the target operating system and architecture, retaining the complete profile dependencies when moving it. The subscription archive or Codex wrapper alone is insufficient without the platform binary. First-time installation cannot complete offline unless dependencies are already prepared. Existing runtime checks and startup do not download anything; model requests still require connectivity. Do not use `--force` to install foreign-platform optional packages.
|
|
279
|
+
|
|
280
|
+
**Upgrading an existing installation:** if you use Codex subtasks, run the preparation command before upgrading this plugin to retain the runtime explicitly in the same profile. A runtime only installed transitively by an older version may be removed during dependency reconciliation. The same command repairs an already-upgraded installation; restart afterwards.
|
|
281
|
+
|
|
282
|
+
The runtime version is pinned separately; subscription updates do not silently upgrade it. This integration uses the official provider package-local CLI, never searches PATH or desktop-private runtimes, and removes the component only after an explicit uninstall request. Shared package caches are not deleted.
|
|
283
|
+
|
|
284
|
+
### When you no longer need it
|
|
285
|
+
|
|
286
|
+
To disable it, switch back to **DSH** in Advanced settings. The component stays installed so you can enable it again later.
|
|
287
|
+
|
|
288
|
+
To uninstall it, click **Uninstall component** in the same section and confirm. The plugin blocks removal while Codex subtasks are running, switches back to DSH, and uses the official uninstall interface. Restart after completion. On older hosts, run this in a terminal, replacing `web` with the profile where you installed it:
|
|
289
|
+
|
|
290
|
+
```sh
|
|
291
|
+
dsh plugin --profile web remove @deepseek-ai/dsh-subagent-codex
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
This removes the optional subtask component, not the subscription plugin. Subscription chat, image generation and native DSH subtasks are unaffected. The package manager may keep the component if another plugin still depends on it.
|
|
295
|
+
|
|
296
|
+
### Storage and cleanup
|
|
297
|
+
|
|
298
|
+
Uninstalling does not clear shared package caches or guarantee a fixed amount of reclaimed space. DSH or Portable manages those caches centrally; this plugin does not delete shared directories. Sketches, conversation history, generated originals and sign-in data are not package caches. Use their respective management controls when you want to remove them.
|
|
253
299
|
|
|
254
300
|
## Update and uninstall
|
|
255
301
|
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# DSH Codex Subscription
|
|
1
|
+
# DSH Codex Subscription — 在 DeepSeek Harness 使用 ChatGPT 订阅
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
@@ -20,18 +20,20 @@
|
|
|
20
20
|
</div>
|
|
21
21
|
|
|
22
22
|
<p align="center">
|
|
23
|
-
<img src="
|
|
23
|
+
<img src="docs/assets/codex-subscription-overview.webp" width="900" alt="在 DeepSeek Harness 登录 ChatGPT 并使用 Codex 订阅:无需 API Key,支持模型选择和剩余额度显示">
|
|
24
24
|
</p>
|
|
25
25
|
|
|
26
26
|
## 三步开始
|
|
27
27
|
|
|
28
|
-
1.
|
|
28
|
+
1. **安装插件**:在新版 DSH 的 **插件 → 添加插件** 中填写 `dsh-codex-subscription`;指定候选版本时填写完整的 `包名@版本`,例如 `dsh-codex-subscription@2.1.3-beta.1`。这个输入框不接受整条终端命令。
|
|
29
|
+
|
|
30
|
+
旧版 DSH 或偏好终端操作时,才在终端运行:
|
|
29
31
|
|
|
30
32
|
```sh
|
|
31
33
|
dsh plugin --profile web add dsh-codex-subscription
|
|
32
34
|
```
|
|
33
35
|
|
|
34
|
-
2.
|
|
36
|
+
2. **登录订阅**:按安装结果提示操作;若提示需要重启,先保存工作再重启。打开 **设置 -> Codex 订阅**,点击浏览器登录。无需 Codex CLI,也不要粘贴 token。
|
|
35
37
|
3. **开始使用**:在模型选择器中选择 Codex;额度、订阅搜索、图片生成和高速模式都在 DSH 内使用。
|
|
36
38
|
|
|
37
39
|
DSH-Portable 也提供相同的标准插件命令,因此同样使用上面的命令。完整的官方 npm、更新和卸载方式见下文。
|
|
@@ -56,10 +58,10 @@ DSH-Portable 也提供相同的标准插件命令,因此同样使用上面的
|
|
|
56
58
|
## 实际界面
|
|
57
59
|
|
|
58
60
|
<p align="center">
|
|
59
|
-
<img src="
|
|
61
|
+
<img src="docs/assets/subscription-account.png" width="820" alt="DSH Codex 订阅主界面:ChatGPT 登录、剩余额度与输入框偏好">
|
|
60
62
|
</p>
|
|
61
63
|
|
|
62
|
-
|
|
64
|
+
上图为“账号与偏好”主界面,展示登录状态、订阅额度和输入框偏好。截图中的账号、额度、余额与时间均为演示数据,不代表套餐固定权益。高级功能与可选组件见下文。
|
|
63
65
|
|
|
64
66
|
## 准备 DSH
|
|
65
67
|
|
|
@@ -135,6 +137,10 @@ dsh --profile web --dump-config
|
|
|
135
137
|
- 订阅路由不可用时明确报错,不会静默切换到其他付费路由。
|
|
136
138
|
|
|
137
139
|
|
|
140
|
+
### GPT-Reserve(实验性)
|
|
141
|
+
|
|
142
|
+
账号的官方模型目录提供 `gpt-reserve` 时,模型选择器末尾会出现实验性选项。可用性和扣费归属由服务端决定;请求成功不代表已确认使用独立备用额度。输入框只显示服务端返回的匹配额度桶,未返回时不会借用普通 Codex 额度。
|
|
143
|
+
|
|
138
144
|
### GPT-6 Astra 上下文
|
|
139
145
|
|
|
140
146
|
当官方模型目录提供 GPT-6 Astra 时,标准模式保留目录默认窗口;扩展模式使用 872000 Token,自定义模式可设置 128000–872000 Token(初始值为 272000)。该上限依据 [Codex 官方模型目录](https://github.com/openai/codex/blob/6af345407d9c2a568da9d01b6c4b81a9e61495c0/codex-rs/models-manager/models.json#L33-L34),不是 API 模型的总上下文容量。这些设置只调整 DSH 的本地上下文预算,不授予模型访问权限,也不保证账号的服务端容量;实际可用性以服务端为准。
|
|
@@ -142,7 +148,7 @@ dsh --profile web --dump-config
|
|
|
142
148
|
### 输入框额度
|
|
143
149
|
|
|
144
150
|
<p align="center">
|
|
145
|
-
<img src="
|
|
151
|
+
<img src="docs/assets/composer-quota.png" width="800" alt="DSH 实机输入框:GPT-6-Astra、Max 推理、高速模式和剩余额度">
|
|
146
152
|
</p>
|
|
147
153
|
|
|
148
154
|
实机示例:GPT-6-Astra · Max(最高推理档)· 高速模式(闪电标识),左侧直接显示剩余额度。
|
|
@@ -169,14 +175,14 @@ ChatGPT 返回可用重置卡时,设置页会把每张卡分别显示为紧凑
|
|
|
169
175
|
新的图片请求不会静默带入历史图片。GPT Image 2 可能比文本回复耗时更长,复杂文字、精确构图和连续角色一致性也可能需要再次调整。
|
|
170
176
|
|
|
171
177
|
<p align="center">
|
|
172
|
-
<img src="
|
|
178
|
+
<img src="docs/assets/image-preview-annotations.png" width="800" alt="DSH 图片查看器中的生成图、区域备注和继续编辑">
|
|
173
179
|
</p>
|
|
174
180
|
|
|
175
181
|
上图展示图片查看与图上备注的基本交互;具体按钮会随图片和所安装的查看器版本变化。
|
|
176
182
|
|
|
177
183
|
### 草图画板(Beta)
|
|
178
184
|
|
|
179
|
-

|
|
180
186
|
|
|
181
187
|
点击输入框的草图按钮手动画图。`@sketch` 是 Agent 绘图入口:选择时只填入输入框,发送绘图请求后才由 Agent 打开画板。图片预览中可选择“进入草图”;上传、粘贴和移除附件仍由 DSH 原生组件处理。
|
|
182
188
|
|
|
@@ -188,7 +194,7 @@ ChatGPT 返回可用重置卡时,设置页会把每张卡分别显示为紧凑
|
|
|
188
194
|
|
|
189
195
|
| 画板原草图 | 插件实际生成结果 |
|
|
190
196
|
| --- | --- |
|
|
191
|
-
|  |  |
|
|
192
198
|
|
|
193
199
|
示例要求:保留山峰与小屋的构图,生成温暖的水彩旅行插画,青绿山峰、橙色屋顶、草地小溪与柔和晨光,不保留蓝色线条。此例通过 GPT-5.6-Luna 发起一次图片工具调用,请求低质量;Luna 是对话模型,实际出图型号由订阅后端决定。
|
|
194
200
|
|
|
@@ -201,7 +207,7 @@ ChatGPT 返回可用重置卡时,设置页会把每张卡分别显示为紧凑
|
|
|
201
207
|
|
|
202
208
|
| 原生草图 | 实际生成结果 |
|
|
203
209
|
| --- | --- |
|
|
204
|
-
|  |  |
|
|
205
211
|
|
|
206
212
|
**草图复现提示词(按原画面整理,非完整原始对话)**
|
|
207
213
|
|
|
@@ -227,7 +233,7 @@ ChatGPT 返回可用重置卡时,设置页会把每张卡分别显示为紧凑
|
|
|
227
233
|
|
|
228
234
|
| Astra 原生草图 | GPT 生图:油画效果 |
|
|
229
235
|
| --- | --- |
|
|
230
|
-
|  |  |
|
|
231
237
|
|
|
232
238
|
草图提示词:`@sketch 用竖版画板画一幅《蒙娜丽莎》`
|
|
233
239
|
|
|
@@ -248,7 +254,47 @@ ChatGPT 返回可用重置卡时,设置页会把每张卡分别显示为紧凑
|
|
|
248
254
|
在 **高级与诊断** 中按需开启,默认仍使用 SSE 和 DSH 子任务:
|
|
249
255
|
|
|
250
256
|
- **WebSocket**:复用连接和可复用的上下文传输;握手失败可回退 SSE,已开始的响应中断会报错,不自动重放。下次请求生效,不增加模型上下文容量,也不保证更快。
|
|
251
|
-
- **Codex 独立子任务**:复用订阅登录和官方 DSH Codex
|
|
257
|
+
- **Codex 独立子任务**:复用订阅登录和官方 DSH Codex 运行时,无需另行登录;可选组件在高级设置中安装。默认继承当前订阅模型及工作区权限。开启 DSH 子任务模型选择、配置允许模型并新建会话后,可在聊天中指定子任务模型与推理档位;非订阅会话需明确选择订阅模型。共享上下文的子任务仍交给 DSH。
|
|
258
|
+
|
|
259
|
+
<a id="codex-subtask-runtime"></a>
|
|
260
|
+
|
|
261
|
+
## 可选 Codex 子任务运行时
|
|
262
|
+
|
|
263
|
+
普通订阅聊天、图片和 DSH 原生子任务不需要 Codex CLI。只有高级设置中的 **Codex 独立子任务(Beta)** 需要额外准备官方运行时,插件不会后台自动下载。
|
|
264
|
+
|
|
265
|
+
在 **设置 → Codex 订阅 → 高级与诊断 → 独立子任务** 点击 **安装组件**。DSH 负责安装,页面显示当前阶段,可取消尚未应用的安装;完成后重启,再选择 Codex。安装不会自动开启子任务。
|
|
266
|
+
|
|
267
|
+

|
|
268
|
+
|
|
269
|
+
旧版宿主没有管理接口时,才在目标 DSH 环境的终端执行,然后重启:
|
|
270
|
+
|
|
271
|
+
```sh
|
|
272
|
+
dsh plugin --profile web add @deepseek-ai/dsh-subagent-codex@0.1.5-rc.2
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
如果使用插件安装页面,在包名框只填 `@deepseek-ai/dsh-subagent-codex@0.1.5-rc.2`,不要粘贴整条命令。安装到订阅插件所在的同一个 profile。之后在高级设置选择 Codex;共享上下文子任务仍由 DSH 处理。准备失败或尚未准备不影响普通订阅聊天,可继续选择 DSH。
|
|
276
|
+
|
|
277
|
+
离线使用前,应在同系统、同架构的目标环境提前安装并验证运行时,迁移时保留完整的 DSH profile 依赖。只有订阅插件压缩包或 Codex 主包不能代替当前平台的可执行包;未提前准备时,断网无法完成首次安装。已有运行时的检查和启动不需要下载安装,但模型请求本身仍需要联网。不要使用 `--force` 安装其他平台的可选包。
|
|
278
|
+
|
|
279
|
+
**旧版升级**:如果已使用 Codex 独立子任务,请在升级订阅插件前执行上面的准备命令,将运行时显式保留在同一个 profile;仅由旧版间接安装的运行时可能随依赖整理移除。已经升级也可执行同一命令补齐,然后重启。
|
|
280
|
+
|
|
281
|
+
运行时版本单独固定,不会随订阅插件更新而自动下载新 CLI。现阶段沿用官方 provider 的包内 CLI,不自动查找 PATH,也不复用桌面应用的私有 CLI。只有明确点击卸载才移除组件,安装缓存不由插件清理。
|
|
282
|
+
|
|
283
|
+
### 不再使用时
|
|
284
|
+
|
|
285
|
+
只想停用:在高级设置切回 **DSH**,组件仍保留,之后可再次开启。
|
|
286
|
+
|
|
287
|
+
要卸载:在同一位置点击 **卸载组件** 并确认。插件会检查正在运行的子任务,切回 DSH 后交给官方接口卸载;有任务运行时不能卸载。完成后重启。旧版宿主可在终端执行(将 `web` 替换为实际安装的 profile):
|
|
288
|
+
|
|
289
|
+
```sh
|
|
290
|
+
dsh plugin --profile web remove @deepseek-ai/dsh-subagent-codex
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
卸载的是可选子任务组件,不是订阅插件;普通订阅聊天、生图和 DSH 原生子任务不受影响。若其他插件仍依赖该组件,包管理器可能保留它。
|
|
294
|
+
|
|
295
|
+
### 存储与清理
|
|
296
|
+
|
|
297
|
+
卸载不等于清空共享安装缓存,也不能保证释放某个固定大小。安装缓存由 DSH/Portable 统一管理,本插件不直接删除共享目录。草稿、会话记录、生成原图和登录信息不是安装缓存;需要删除时应使用各自的管理入口,不做一键混合清理。
|
|
252
298
|
|
|
253
299
|
## 更新与卸载
|
|
254
300
|
|
package/lib/client.js
CHANGED
|
@@ -872,6 +872,10 @@ window.__ModuleLoader__.load({
|
|
|
872
872
|
"preferences/status",
|
|
873
873
|
"preferences/models",
|
|
874
874
|
"preferences/update",
|
|
875
|
+
"runtime/status",
|
|
876
|
+
"runtime/install",
|
|
877
|
+
"runtime/remove",
|
|
878
|
+
"runtime/cancel",
|
|
875
879
|
"reset-credit/inspect",
|
|
876
880
|
"reset-credit/prepare",
|
|
877
881
|
"reset-credit/consume",
|
|
@@ -4502,6 +4506,24 @@ window.__ModuleLoader__.load({
|
|
|
4502
4506
|
//#endregion
|
|
4503
4507
|
//#region src/client-locales.js
|
|
4504
4508
|
const zh = {
|
|
4509
|
+
runtimeLoading: "正在检查组件…",
|
|
4510
|
+
runtimeRestart: "组件已更新,请重启 DSH 后使用。",
|
|
4511
|
+
runtime_installing: "正在通过 DSH 安装组件…",
|
|
4512
|
+
runtime_removing: "正在通过 DSH 卸载组件…",
|
|
4513
|
+
runtime_applying: "正在应用安装结果…",
|
|
4514
|
+
runtimeInstall: "安装组件",
|
|
4515
|
+
runtimeRemove: "卸载组件",
|
|
4516
|
+
runtimeCancel: "取消安装",
|
|
4517
|
+
runtimeKeep: "保留",
|
|
4518
|
+
runtimeConfirmRemove: "确认卸载",
|
|
4519
|
+
runtimeRefresh: "刷新状态",
|
|
4520
|
+
runtimeActive: "有 Codex 子任务正在运行,结束后才能安装或卸载。",
|
|
4521
|
+
runtimeConfirm: "卸载后将切回 DSH 子任务。普通订阅聊天、生图、登录和草稿保留。确定卸载可选组件?",
|
|
4522
|
+
runtimeFailed: "操作未完成。请刷新状态后重试;详细原因可在 DSH 插件管理中查看。",
|
|
4523
|
+
runtimeBuildBlocked: "DSH 拦截了依赖安装脚本。请在官方插件管理中审核后再安装。",
|
|
4524
|
+
runtimeCancelled: "安装已取消,可重新安装。",
|
|
4525
|
+
runtimeUnavailable: "当前宿主未提供组件管理接口,请更新 DSH 或按说明手动管理。",
|
|
4526
|
+
runtimeInstallHint: "此处只管理官方 Codex 子任务组件,由 DSH 负责安装与卸载。安装后不会自动开启子任务;仅切回 DSH 不会卸载组件。",
|
|
4505
4527
|
compactionTitle: "云端压缩",
|
|
4506
4528
|
compaction_dsh: "关闭",
|
|
4507
4529
|
compaction_cloud: "开启",
|
|
@@ -4514,6 +4536,11 @@ window.__ModuleLoader__.load({
|
|
|
4514
4536
|
connectionHint: "默认 SSE。WebSocket 实验性复用连接与上下文传输;连接失败可回退 SSE。下次请求生效,不扩大上下文容量。",
|
|
4515
4537
|
subagentBackendHint: "Codex 复用订阅登录和工作区权限;默认继承当前订阅模型。开启 DSH 子任务模型选择并新建会话后,可在聊天中指定允许的订阅模型与推理档位;非订阅会话需指定。共享上下文子任务仍用 DSH。",
|
|
4516
4538
|
subagentBackendUnavailable: "当前宿主缺少子代理服务,请更新 DSH。",
|
|
4539
|
+
subagentRuntimeMissing: "尚未准备 Codex 子任务运行时,仅影响此选项。普通订阅对话无需安装。",
|
|
4540
|
+
subagentRuntimePrepare: "准备方法(含离线说明)",
|
|
4541
|
+
subagentRuntimeInstalled: "已检测到 Codex 子任务组件;启动时会检查可执行文件。",
|
|
4542
|
+
subagentRuntimeManage: "安装、卸载与存储",
|
|
4543
|
+
subagentRuntimeCacheHint: "卸载后安装缓存可能仍保留,由 DSH 或 Portable 统一管理。此处不会删除登录、草稿或生成图片。",
|
|
4517
4544
|
sketchRecovered: "已恢复未保存草稿",
|
|
4518
4545
|
sketchRecoveryFailed: "恢复检查点保存失败,请手动保存或导出草稿。",
|
|
4519
4546
|
sketchStorageBlocked: "草稿正被其他窗口占用,请关闭其他草图窗口后重试。",
|
|
@@ -4930,6 +4957,24 @@ window.__ModuleLoader__.load({
|
|
|
4930
4957
|
imageRemoveAnnotation: "删除标注"
|
|
4931
4958
|
};
|
|
4932
4959
|
const en = {
|
|
4960
|
+
runtimeLoading: "Checking component…",
|
|
4961
|
+
runtimeRestart: "Component changed. Restart DSH before using it.",
|
|
4962
|
+
runtime_installing: "Installing through DSH…",
|
|
4963
|
+
runtime_removing: "Uninstalling through DSH…",
|
|
4964
|
+
runtime_applying: "Applying installation…",
|
|
4965
|
+
runtimeInstall: "Install component",
|
|
4966
|
+
runtimeRemove: "Uninstall component",
|
|
4967
|
+
runtimeCancel: "Cancel installation",
|
|
4968
|
+
runtimeKeep: "Keep",
|
|
4969
|
+
runtimeConfirmRemove: "Confirm uninstall",
|
|
4970
|
+
runtimeRefresh: "Refresh status",
|
|
4971
|
+
runtimeActive: "Codex subtasks are running. Wait for them to finish before installing or uninstalling.",
|
|
4972
|
+
runtimeConfirm: "Uninstalling switches subtasks back to DSH. Subscription chat, images, sign-in and sketches stay available. Uninstall this optional component?",
|
|
4973
|
+
runtimeFailed: "The operation did not complete. Refresh and retry; see DSH plugin management for details.",
|
|
4974
|
+
runtimeBuildBlocked: "DSH blocked dependency build scripts. Review them in the official plugin manager before installing.",
|
|
4975
|
+
runtimeCancelled: "Installation cancelled. You can try again.",
|
|
4976
|
+
runtimeUnavailable: "This host has no component management interface. Update DSH or use the manual instructions.",
|
|
4977
|
+
runtimeInstallHint: "DSH installs and removes the official Codex subtask component here. Installation does not enable subtasks automatically. Switching to DSH alone does not uninstall it.",
|
|
4933
4978
|
compactionTitle: "Cloud compaction",
|
|
4934
4979
|
compaction_dsh: "Off",
|
|
4935
4980
|
compaction_cloud: "On",
|
|
@@ -4942,6 +4987,11 @@ window.__ModuleLoader__.load({
|
|
|
4942
4987
|
connectionHint: "SSE by default. Experimental WebSocket reuses connections and context transfers and can fall back to SSE on connection failure. Applies to the next request; context limits stay the same.",
|
|
4943
4988
|
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.",
|
|
4944
4989
|
subagentBackendUnavailable: "Subagent services are unavailable. Update DSH to use this option.",
|
|
4990
|
+
subagentRuntimeMissing: "Codex subtask runtime is not prepared. Subscription chat does not require it.",
|
|
4991
|
+
subagentRuntimePrepare: "Setup and offline instructions",
|
|
4992
|
+
subagentRuntimeInstalled: "Codex subtask component detected; its executable is checked on startup.",
|
|
4993
|
+
subagentRuntimeManage: "Install, uninstall and storage",
|
|
4994
|
+
subagentRuntimeCacheHint: "Package caches may remain after uninstalling. DSH or Portable manages them centrally. Sign-in, sketches and generated images are not deleted here.",
|
|
4945
4995
|
sketchRecovered: "Unsaved sketch recovered",
|
|
4946
4996
|
sketchRecoveryFailed: "Recovery checkpoint failed. Save or export your draft.",
|
|
4947
4997
|
sketchStorageBlocked: "Draft storage is in use. Close other sketch windows and retry.",
|
|
@@ -5576,6 +5626,14 @@ window.__ModuleLoader__.load({
|
|
|
5576
5626
|
@container (max-width:480px){.codexSubscriptionAccountRow,.codexSubscriptionSectionHead{align-items:flex-start;flex-direction:column}
|
|
5577
5627
|
.codexSubscriptionActions{width:100%}
|
|
5578
5628
|
.codexSubscriptionSearchChoices{grid-template-columns:1fr}}
|
|
5629
|
+
.codexSubscriptionRuntime{font-size:12px;line-height:1.6;margin-top:12px;color:var(--dsw-alias-label-secondary)}
|
|
5630
|
+
.codexSubscriptionRuntime summary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-primary);border-radius:6px}
|
|
5631
|
+
.codexSubscriptionRuntime summary:focus-visible{outline:2px solid currentColor;outline-offset:4px}
|
|
5632
|
+
.codexSubscriptionRuntime p{margin:8px 0}
|
|
5633
|
+
.codexSubscriptionRuntime .codexSubscriptionPreference{flex-wrap:wrap;align-items:flex-start}
|
|
5634
|
+
.codexSubscriptionRuntime .codexSubscriptionPreference>span{flex:1;min-width:180px;font-size:12px;color:var(--dsw-alias-label-secondary)}
|
|
5635
|
+
.codexSubscriptionRuntime button{flex-shrink:0;white-space:nowrap}
|
|
5636
|
+
.codexSubscriptionRuntime code{display:block;overflow-wrap:anywhere;padding:8px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;user-select:text}
|
|
5579
5637
|
@media(max-width:640px){.codexSubscriptionCard{padding:14px}}
|
|
5580
5638
|
`;
|
|
5581
5639
|
//#endregion
|
|
@@ -6712,6 +6770,7 @@ window.__ModuleLoader__.load({
|
|
|
6712
6770
|
let modelRefreshStarted = false;
|
|
6713
6771
|
let disposed = false;
|
|
6714
6772
|
let subagentBackendAvailable = false;
|
|
6773
|
+
let subagentRuntimeInstalled = false;
|
|
6715
6774
|
const sameModels = (left, right) => left.length === right.length && left.every((model, index) => JSON.stringify(model) === JSON.stringify(right[index]));
|
|
6716
6775
|
const nativeSnapshot = () => scope.getSnapshot();
|
|
6717
6776
|
const read = () => {
|
|
@@ -6729,6 +6788,7 @@ window.__ModuleLoader__.load({
|
|
|
6729
6788
|
compactionMode: value?.compactionMode === "cloud" ? "cloud" : "dsh",
|
|
6730
6789
|
subagentBackend: value?.subagentBackend === "codex" ? "codex" : "dsh",
|
|
6731
6790
|
subagentBackendAvailable,
|
|
6791
|
+
subagentRuntimeInstalled,
|
|
6732
6792
|
quickQuotaMode: normalizeQuickQuotaMode(value?.[QUICK_QUOTA_MODE_FIELD], value?.[LEGACY_QUICK_QUOTA_FIELD]),
|
|
6733
6793
|
searchProvider: normalizeSearchProvider(value?.[SEARCH_PROVIDER_FIELD]),
|
|
6734
6794
|
speedMode: normalizeSpeedMode(value?.[SPEED_MODE_FIELD]),
|
|
@@ -6763,6 +6823,7 @@ window.__ModuleLoader__.load({
|
|
|
6763
6823
|
});
|
|
6764
6824
|
const acceptFallback = (value) => {
|
|
6765
6825
|
subagentBackendAvailable = value?.subagentBackendAvailable === true;
|
|
6826
|
+
subagentRuntimeInstalled = value?.subagentRuntimeInstalled === true;
|
|
6766
6827
|
if (!modelRefreshStarted) {
|
|
6767
6828
|
contextModels = Array.isArray(value?.contextModels) ? value.contextModels : [];
|
|
6768
6829
|
verbosityModels = Array.isArray(value?.verbosityModels) ? value.verbosityModels : [];
|
|
@@ -6800,6 +6861,7 @@ window.__ModuleLoader__.load({
|
|
|
6800
6861
|
const value = unwrap(await rpc.call(CHANNEL, "preferences/status", {}));
|
|
6801
6862
|
if (current !== generation || disposed) return;
|
|
6802
6863
|
subagentBackendAvailable = value?.subagentBackendAvailable === true;
|
|
6864
|
+
subagentRuntimeInstalled = value?.subagentRuntimeInstalled === true;
|
|
6803
6865
|
if (nativeSnapshot().status === "ready") {
|
|
6804
6866
|
if (!modelRefreshStarted) {
|
|
6805
6867
|
contextModels = Array.isArray(value?.contextModels) ? value.contextModels : [];
|
|
@@ -7172,12 +7234,19 @@ window.__ModuleLoader__.load({
|
|
|
7172
7234
|
//#region src/sidebar-quota.js
|
|
7173
7235
|
const isDisplayableWindow = (window) => Number.isFinite(window?.remainingPercent) && window.remainingPercent >= 0 && window.remainingPercent <= 100 && Number.isFinite(window?.windowSeconds) && window.windowSeconds > 0;
|
|
7174
7236
|
const normalized = (value) => String(value ?? "").toLocaleLowerCase("en-US").replaceAll(/[^a-z0-9]+/gu, "-");
|
|
7175
|
-
const
|
|
7237
|
+
const exactModelLimit = (limit, model) => {
|
|
7238
|
+
const id = normalized(model);
|
|
7239
|
+
return id.length > 0 && [limit?.id, limit?.name].some((value) => typeof value === "string" && normalized(value) === id);
|
|
7240
|
+
};
|
|
7241
|
+
const limitMatchesModel = (limit, model, hasExactLimit) => {
|
|
7242
|
+
if (hasExactLimit) return exactModelLimit(limit, model);
|
|
7243
|
+
if (normalized(model) === "gpt-reserve") return false;
|
|
7176
7244
|
if (/\bspark\b/u.test(normalized(model))) return /\bspark\b/u.test(normalized(`${limit?.id ?? ""} ${limit?.name ?? ""}`));
|
|
7177
7245
|
return limit?.id === "codex";
|
|
7178
7246
|
};
|
|
7179
7247
|
function selectModelQuotaWindows(usage, model) {
|
|
7180
|
-
|
|
7248
|
+
const hasExactLimit = Array.isArray(usage?.rateLimits) && usage.rateLimits.some((limit) => exactModelLimit(limit, model));
|
|
7249
|
+
return (Array.isArray(usage?.rateLimits) ? usage.rateLimits.filter((limit) => limitMatchesModel(limit, model, hasExactLimit) && Array.isArray(limit.windows)).flatMap((limit) => limit.windows).filter(isDisplayableWindow) : []).map((selected) => ({
|
|
7181
7250
|
remainingPercent: selected.remainingPercent,
|
|
7182
7251
|
windowSeconds: selected.windowSeconds,
|
|
7183
7252
|
...Number.isSafeInteger(selected.resetsAt) ? { resetsAt: selected.resetsAt } : {},
|
|
@@ -7186,7 +7255,7 @@ window.__ModuleLoader__.load({
|
|
|
7186
7255
|
}
|
|
7187
7256
|
//#endregion
|
|
7188
7257
|
//#region src/version.js
|
|
7189
|
-
const PACKAGE_VERSION = "2.1.3
|
|
7258
|
+
const PACKAGE_VERSION = "2.1.3";
|
|
7190
7259
|
//#endregion
|
|
7191
7260
|
//#region src/client-recovery.js
|
|
7192
7261
|
async function recoveryCall(rpc, endpoint, payload = {}, timeoutMs = 1e4) {
|
|
@@ -8043,6 +8112,158 @@ window.__ModuleLoader__.load({
|
|
|
8043
8112
|
] });
|
|
8044
8113
|
}
|
|
8045
8114
|
//#endregion
|
|
8115
|
+
//#region src/client-runtime-management.jsx
|
|
8116
|
+
function RuntimeManagement({ rpc, preference, t }) {
|
|
8117
|
+
const [state, setState] = (0, react.useState)();
|
|
8118
|
+
const [error, setError] = (0, react.useState)(false);
|
|
8119
|
+
const [sending, setSending] = (0, react.useState)(false);
|
|
8120
|
+
const [confirm, setConfirm] = (0, react.useState)(false);
|
|
8121
|
+
const alive = (0, react.useRef)(false);
|
|
8122
|
+
const busy = [
|
|
8123
|
+
"installing",
|
|
8124
|
+
"removing",
|
|
8125
|
+
"applying"
|
|
8126
|
+
].includes(state?.phase);
|
|
8127
|
+
const read = async () => {
|
|
8128
|
+
try {
|
|
8129
|
+
const result = await rpc.call(CHANNEL, "runtime/status", {});
|
|
8130
|
+
if (!alive.current) return;
|
|
8131
|
+
if (!result.ok) {
|
|
8132
|
+
setError(true);
|
|
8133
|
+
return;
|
|
8134
|
+
}
|
|
8135
|
+
setState(result.value);
|
|
8136
|
+
setError(false);
|
|
8137
|
+
} catch {
|
|
8138
|
+
if (alive.current) setError(true);
|
|
8139
|
+
}
|
|
8140
|
+
};
|
|
8141
|
+
(0, react.useEffect)(() => {
|
|
8142
|
+
alive.current = true;
|
|
8143
|
+
read();
|
|
8144
|
+
return () => {
|
|
8145
|
+
alive.current = false;
|
|
8146
|
+
};
|
|
8147
|
+
}, [rpc]);
|
|
8148
|
+
(0, react.useEffect)(() => {
|
|
8149
|
+
if (!busy) return;
|
|
8150
|
+
let stopped = false, timer;
|
|
8151
|
+
const poll = async () => {
|
|
8152
|
+
await read();
|
|
8153
|
+
if (!stopped) timer = setTimeout(poll, 1500);
|
|
8154
|
+
};
|
|
8155
|
+
timer = setTimeout(poll, 1500);
|
|
8156
|
+
return () => {
|
|
8157
|
+
stopped = true;
|
|
8158
|
+
clearTimeout(timer);
|
|
8159
|
+
};
|
|
8160
|
+
}, [busy, rpc]);
|
|
8161
|
+
const act = async (action) => {
|
|
8162
|
+
if (sending) return;
|
|
8163
|
+
setSending(true);
|
|
8164
|
+
setError(false);
|
|
8165
|
+
setConfirm(false);
|
|
8166
|
+
try {
|
|
8167
|
+
const result = await rpc.call(CHANNEL, `runtime/${action}`, {});
|
|
8168
|
+
if (!alive.current) return;
|
|
8169
|
+
if (!result.ok) {
|
|
8170
|
+
await read();
|
|
8171
|
+
if (alive.current) setError(true);
|
|
8172
|
+
return;
|
|
8173
|
+
}
|
|
8174
|
+
setState(result.value);
|
|
8175
|
+
if (action === "remove") preference.load();
|
|
8176
|
+
} catch {
|
|
8177
|
+
if (alive.current) setError(true);
|
|
8178
|
+
} finally {
|
|
8179
|
+
if (alive.current) setSending(false);
|
|
8180
|
+
}
|
|
8181
|
+
};
|
|
8182
|
+
const locked = sending || busy || state?.restartRequired || state?.active > 0;
|
|
8183
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8184
|
+
className: "codexSubscriptionRuntime",
|
|
8185
|
+
children: [
|
|
8186
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8187
|
+
className: "codexSubscriptionPreference",
|
|
8188
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8189
|
+
role: "status",
|
|
8190
|
+
children: t(!state ? "runtimeLoading" : state.restartRequired ? "runtimeRestart" : busy ? `runtime_${state.phase}` : state.installed ? "subagentRuntimeInstalled" : "subagentRuntimeMissing")
|
|
8191
|
+
}), state?.available ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
8192
|
+
type: "button",
|
|
8193
|
+
variant: "outline",
|
|
8194
|
+
disabled: locked || state.installed && !state.removable,
|
|
8195
|
+
onClick: () => state.installed ? setConfirm(true) : void act("install"),
|
|
8196
|
+
children: t(state.installed ? "runtimeRemove" : "runtimeInstall")
|
|
8197
|
+
}) : null]
|
|
8198
|
+
}),
|
|
8199
|
+
state?.active > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("runtimeActive") }) : null,
|
|
8200
|
+
busy && state.phase === "installing" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
8201
|
+
type: "button",
|
|
8202
|
+
variant: "outline",
|
|
8203
|
+
disabled: sending,
|
|
8204
|
+
onClick: () => {
|
|
8205
|
+
act("cancel");
|
|
8206
|
+
},
|
|
8207
|
+
children: t("runtimeCancel")
|
|
8208
|
+
}) : null,
|
|
8209
|
+
confirm ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8210
|
+
role: "group",
|
|
8211
|
+
"aria-label": t("runtimeRemove"),
|
|
8212
|
+
children: [
|
|
8213
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("runtimeConfirm") }),
|
|
8214
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
8215
|
+
type: "button",
|
|
8216
|
+
variant: "outline",
|
|
8217
|
+
onClick: () => setConfirm(false),
|
|
8218
|
+
children: t("runtimeKeep")
|
|
8219
|
+
}),
|
|
8220
|
+
" ",
|
|
8221
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
8222
|
+
type: "button",
|
|
8223
|
+
variant: "outline",
|
|
8224
|
+
disabled: locked,
|
|
8225
|
+
onClick: () => {
|
|
8226
|
+
act("remove");
|
|
8227
|
+
},
|
|
8228
|
+
children: t("runtimeConfirmRemove")
|
|
8229
|
+
})
|
|
8230
|
+
]
|
|
8231
|
+
}) : null,
|
|
8232
|
+
error || state?.phase === "failed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8233
|
+
role: "alert",
|
|
8234
|
+
children: t(state?.error === "build-blocked" ? "runtimeBuildBlocked" : "runtimeFailed")
|
|
8235
|
+
}) : null,
|
|
8236
|
+
state?.phase === "cancelled" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8237
|
+
role: "status",
|
|
8238
|
+
children: t("runtimeCancelled")
|
|
8239
|
+
}) : null,
|
|
8240
|
+
!busy ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
8241
|
+
type: "button",
|
|
8242
|
+
variant: "outline",
|
|
8243
|
+
disabled: sending,
|
|
8244
|
+
onClick: () => {
|
|
8245
|
+
read();
|
|
8246
|
+
preference.load();
|
|
8247
|
+
},
|
|
8248
|
+
children: t("runtimeRefresh")
|
|
8249
|
+
}) : null,
|
|
8250
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", { children: [
|
|
8251
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: t("subagentRuntimeManage") }),
|
|
8252
|
+
state && !state.available ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("runtimeUnavailable") }) : null,
|
|
8253
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("runtimeInstallHint") }),
|
|
8254
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: "@deepseek-ai/dsh-subagent-codex@0.1.5-rc.2" }),
|
|
8255
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("subagentRuntimeCacheHint") }),
|
|
8256
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
8257
|
+
href: "https://github.com/WSL043/dsh-codex-subscription/blob/main/README.md#codex-subtask-runtime",
|
|
8258
|
+
target: "_blank",
|
|
8259
|
+
rel: "noreferrer",
|
|
8260
|
+
children: t("subagentRuntimePrepare")
|
|
8261
|
+
})
|
|
8262
|
+
] })
|
|
8263
|
+
]
|
|
8264
|
+
});
|
|
8265
|
+
}
|
|
8266
|
+
//#endregion
|
|
8046
8267
|
//#region src/context-draft-state.js
|
|
8047
8268
|
const hasOwn = (value, key) => Object.prototype.hasOwnProperty.call(value ?? {}, key);
|
|
8048
8269
|
/**
|
|
@@ -8314,7 +8535,7 @@ window.__ModuleLoader__.load({
|
|
|
8314
8535
|
]
|
|
8315
8536
|
});
|
|
8316
8537
|
}
|
|
8317
|
-
function PreferencesCard({ preference, t, section = "display" }) {
|
|
8538
|
+
function PreferencesCard({ preference, rpc, t, section = "display" }) {
|
|
8318
8539
|
const snapshot = usePreferenceSnapshot(preference);
|
|
8319
8540
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8320
8541
|
className: section === "advanced" ? "codexSubscriptionAdvancedPreferences" : "codexSubscriptionCard codexSubscriptionPreferencesCard",
|
|
@@ -8411,10 +8632,10 @@ window.__ModuleLoader__.load({
|
|
|
8411
8632
|
})]
|
|
8412
8633
|
})
|
|
8413
8634
|
}),
|
|
8414
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
8635
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
8415
8636
|
className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
|
|
8416
8637
|
"aria-label": t("subagentBackendTitle"),
|
|
8417
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8638
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8418
8639
|
className: "codexSubscriptionPreference",
|
|
8419
8640
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8420
8641
|
className: "codexSubscriptionPreferenceCopy",
|
|
@@ -8440,14 +8661,18 @@ window.__ModuleLoader__.load({
|
|
|
8440
8661
|
type: "radio",
|
|
8441
8662
|
name: "codex-subagent-backend",
|
|
8442
8663
|
checked: snapshot.subagentBackend === value,
|
|
8443
|
-
disabled: !snapshot.writable || !snapshot.subagentBackendAvailable,
|
|
8664
|
+
disabled: !snapshot.writable || !snapshot.subagentBackendAvailable || value === "codex" && !snapshot.subagentRuntimeInstalled,
|
|
8444
8665
|
onChange: () => {
|
|
8445
8666
|
preference.set({ subagentBackend: value });
|
|
8446
8667
|
}
|
|
8447
8668
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(`subagentBackend_${value}`) })]
|
|
8448
8669
|
}, value))
|
|
8449
8670
|
})]
|
|
8450
|
-
})
|
|
8671
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RuntimeManagement, {
|
|
8672
|
+
rpc,
|
|
8673
|
+
preference,
|
|
8674
|
+
t
|
|
8675
|
+
})]
|
|
8451
8676
|
})
|
|
8452
8677
|
] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuickQuotaPreference, {
|
|
8453
8678
|
preference,
|
|
@@ -9493,6 +9718,7 @@ window.__ModuleLoader__.load({
|
|
|
9493
9718
|
preference
|
|
9494
9719
|
}, resetKey),
|
|
9495
9720
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PreferencesCard, {
|
|
9721
|
+
rpc,
|
|
9496
9722
|
preference,
|
|
9497
9723
|
t
|
|
9498
9724
|
})
|
|
@@ -9505,6 +9731,7 @@ window.__ModuleLoader__.load({
|
|
|
9505
9731
|
hidden: tab !== "advanced",
|
|
9506
9732
|
children: [
|
|
9507
9733
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PreferencesCard, {
|
|
9734
|
+
rpc,
|
|
9508
9735
|
preference,
|
|
9509
9736
|
t,
|
|
9510
9737
|
section: "advanced"
|
package/lib/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
1
2
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
2
3
|
import { closeOpenAICodexWebSocketSessions, resetOpenAICodexWebSocketDebugStats } from "@earendil-works/pi-ai/api/openai-codex-responses";
|
|
3
4
|
import { execFile, spawn } from "node:child_process";
|
|
@@ -9,6 +10,9 @@ import { HttpsProxyAgent } from "https-proxy-agent";
|
|
|
9
10
|
import WebSocket from "ws";
|
|
10
11
|
import { clientRequestSchema } from "@deepseek-ai/dsh-client-connection";
|
|
11
12
|
import { lstat, mkdir, open, readFile, rename, rm, stat } from "node:fs/promises";
|
|
13
|
+
import { constants, readFileSync } from "node:fs";
|
|
14
|
+
import { dirname, join, resolve } from "node:path";
|
|
15
|
+
import { pathToFileURL } from "node:url";
|
|
12
16
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
13
17
|
import * as dshCredentials from "@deepseek-ai/dsh-credentials";
|
|
14
18
|
import { dshHomePath, resolveDshHome } from "@deepseek-ai/dsh-home-paths";
|
|
@@ -18,8 +22,6 @@ import z from "@deepseek-ai/schemastery";
|
|
|
18
22
|
import { openaiCodexProvider as createOpenAICodexProvider } from "@earendil-works/pi-ai/providers/openai-codex";
|
|
19
23
|
import { createModels } from "@earendil-works/pi-ai";
|
|
20
24
|
import { WebError } from "@deepseek-ai/dsh-web";
|
|
21
|
-
import { constants } from "node:fs";
|
|
22
|
-
import { dirname, join, resolve } from "node:path";
|
|
23
25
|
//#region src/image-models.js
|
|
24
26
|
const DEFAULT_IMAGE_MODEL = "gpt-image-2";
|
|
25
27
|
const IMAGE_MODELS = Object.freeze({
|
|
@@ -875,6 +877,10 @@ const RPC_ENDPOINTS = Object.freeze([
|
|
|
875
877
|
"preferences/status",
|
|
876
878
|
"preferences/models",
|
|
877
879
|
"preferences/update",
|
|
880
|
+
"runtime/status",
|
|
881
|
+
"runtime/install",
|
|
882
|
+
"runtime/remove",
|
|
883
|
+
"runtime/cancel",
|
|
878
884
|
"reset-credit/inspect",
|
|
879
885
|
"reset-credit/prepare",
|
|
880
886
|
"reset-credit/consume",
|
|
@@ -1048,6 +1054,45 @@ function authenticatedSubagentChild(child, { Transport, getTokens, thread, signa
|
|
|
1048
1054
|
} });
|
|
1049
1055
|
}
|
|
1050
1056
|
//#endregion
|
|
1057
|
+
//#region src/subagent-runtime.js
|
|
1058
|
+
const SUBAGENT_RUNTIME_PACKAGE = "@deepseek-ai/dsh-subagent-codex";
|
|
1059
|
+
const SUBAGENT_RUNTIME_VERSION = "0.1.5-rc.2";
|
|
1060
|
+
const require = createRequire(import.meta.url);
|
|
1061
|
+
const execute = promisify(execFile);
|
|
1062
|
+
function inspectSubagentRuntime(resolve = require.resolve) {
|
|
1063
|
+
try {
|
|
1064
|
+
const manifestPath = resolve(`${SUBAGENT_RUNTIME_PACKAGE}/package.json`);
|
|
1065
|
+
if (JSON.parse(readFileSync(manifestPath, "utf8")).version !== "0.1.5-rc.2") return { installed: false };
|
|
1066
|
+
return { installed: true };
|
|
1067
|
+
} catch {
|
|
1068
|
+
return { installed: false };
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
async function loadSubagentRuntime({ resolve: resolve$1 = require.resolve, run = execute, importModule = (url) => import(url) } = {}) {
|
|
1072
|
+
if (!inspectSubagentRuntime(resolve$1).installed) throw new Error("Codex subtask runtime is not prepared");
|
|
1073
|
+
const entry = resolve$1(SUBAGENT_RUNTIME_PACKAGE);
|
|
1074
|
+
const providerRequire = createRequire(entry);
|
|
1075
|
+
const codexManifestPath = providerRequire.resolve("@openai/codex/package.json");
|
|
1076
|
+
const codex = JSON.parse(readFileSync(codexManifestPath, "utf8"));
|
|
1077
|
+
if (codex.version !== "0.153.4" || typeof codex.bin?.codex !== "string") throw new Error("Codex subtask runtime version is unsupported");
|
|
1078
|
+
const wrapper = resolve(dirname(codexManifestPath), codex.bin.codex);
|
|
1079
|
+
try {
|
|
1080
|
+
const { stdout } = await run(process.execPath, [wrapper, "--version"], {
|
|
1081
|
+
timeout: 1e4,
|
|
1082
|
+
maxBuffer: 4096,
|
|
1083
|
+
windowsHide: true
|
|
1084
|
+
});
|
|
1085
|
+
if (stdout.trim() !== "codex-cli 0.153.4") throw new Error("Unexpected CLI version");
|
|
1086
|
+
} catch {
|
|
1087
|
+
throw new Error("Codex subtask runtime is incomplete; prepare it for this platform");
|
|
1088
|
+
}
|
|
1089
|
+
const [official, { JsonRpcLineTransport: Transport }] = await Promise.all([importModule(pathToFileURL(entry).href), importModule(pathToFileURL(providerRequire.resolve("@deepseek-ai/dsh-sdk-protocol")).href)]);
|
|
1090
|
+
return {
|
|
1091
|
+
official,
|
|
1092
|
+
Transport
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
//#endregion
|
|
1051
1096
|
//#region src/subagent-backend.js
|
|
1052
1097
|
const SUBAGENT_PROVIDER = "codex-subscription-subagent";
|
|
1053
1098
|
const MODES = /* @__PURE__ */ new Set([
|
|
@@ -1086,7 +1131,7 @@ function subagentThreadPolicy(parent, policy, requested = {}) {
|
|
|
1086
1131
|
};
|
|
1087
1132
|
}
|
|
1088
1133
|
/** Reuse the official DSH process/turn provider; keep only subscription auth here. */
|
|
1089
|
-
function createSubscriptionSubagent({ ctx, nativeHome, resolveAuth, store, refresh, loadRuntime }) {
|
|
1134
|
+
function createSubscriptionSubagent({ ctx, nativeHome, resolveAuth, store, refresh, loadRuntime, maintenance = () => false }) {
|
|
1090
1135
|
let runtime;
|
|
1091
1136
|
const load = () => runtime ??= loadRuntime().catch((error) => {
|
|
1092
1137
|
runtime = void 0;
|
|
@@ -1107,6 +1152,7 @@ function createSubscriptionSubagent({ ctx, nativeHome, resolveAuth, store, refre
|
|
|
1107
1152
|
inheritsParentContext: false,
|
|
1108
1153
|
async start(request) {
|
|
1109
1154
|
if (disposed) throw new Error("Codex subagent is unavailable");
|
|
1155
|
+
if (maintenance()) throw new Error("Codex subtask component is being changed; restart DSH after completion");
|
|
1110
1156
|
const controller = new AbortController();
|
|
1111
1157
|
active.add(controller);
|
|
1112
1158
|
const signal = AbortSignal.any([request.signal, controller.signal]);
|
|
@@ -1178,7 +1224,11 @@ function createSubscriptionSubagent({ ctx, nativeHome, resolveAuth, store, refre
|
|
|
1178
1224
|
}
|
|
1179
1225
|
}
|
|
1180
1226
|
},
|
|
1181
|
-
|
|
1227
|
+
activeCount: () => active.size,
|
|
1228
|
+
prepare: () => {
|
|
1229
|
+
if (maintenance()) return Promise.reject(/* @__PURE__ */ new Error("Restart DSH after changing the Codex subtask component"));
|
|
1230
|
+
return load();
|
|
1231
|
+
},
|
|
1182
1232
|
dispose() {
|
|
1183
1233
|
disposed = true;
|
|
1184
1234
|
for (const controller of active) controller.abort();
|
|
@@ -1252,11 +1302,104 @@ function createSubagentBackendSwitcher({ entries, prepare, persist }) {
|
|
|
1252
1302
|
}
|
|
1253
1303
|
};
|
|
1254
1304
|
}
|
|
1255
|
-
|
|
1256
|
-
|
|
1305
|
+
//#endregion
|
|
1306
|
+
//#region src/runtime-management.js
|
|
1307
|
+
function createRuntimeManagement({ manager, inspect, active, selectDsh }) {
|
|
1308
|
+
let operation;
|
|
1309
|
+
let state = {
|
|
1310
|
+
phase: "idle",
|
|
1311
|
+
restartRequired: false
|
|
1312
|
+
};
|
|
1313
|
+
const supported = (value) => [
|
|
1314
|
+
"listBundles",
|
|
1315
|
+
"installBundle",
|
|
1316
|
+
"removeBundle",
|
|
1317
|
+
"cancelInstall"
|
|
1318
|
+
].every((key) => typeof value?.[key] === "function");
|
|
1319
|
+
const status = async () => {
|
|
1320
|
+
const host = manager();
|
|
1321
|
+
let bundle;
|
|
1322
|
+
let available = supported(host);
|
|
1323
|
+
try {
|
|
1324
|
+
if (available) bundle = (await host.listBundles()).find((value) => value.name === SUBAGENT_RUNTIME_PACKAGE);
|
|
1325
|
+
} catch {
|
|
1326
|
+
available = false;
|
|
1327
|
+
}
|
|
1328
|
+
return {
|
|
1329
|
+
...state,
|
|
1330
|
+
available,
|
|
1331
|
+
installed: inspect().installed,
|
|
1332
|
+
removable: available && bundle?.installed === true && !bundle.readOnlyReason,
|
|
1333
|
+
active: active()
|
|
1334
|
+
};
|
|
1335
|
+
};
|
|
1336
|
+
const start = async (action) => {
|
|
1337
|
+
if (!["install", "remove"].includes(action)) throw Error("invalid-action");
|
|
1338
|
+
if (operation) throw Error("busy");
|
|
1339
|
+
if (state.restartRequired) throw Error("restart-required");
|
|
1340
|
+
if (active() > 0) throw Error("active-tasks");
|
|
1341
|
+
const host = manager();
|
|
1342
|
+
if (!supported(host)) throw Error("unavailable");
|
|
1343
|
+
const requestId = randomUUID();
|
|
1344
|
+
const current = {
|
|
1345
|
+
action,
|
|
1346
|
+
requestId,
|
|
1347
|
+
host
|
|
1348
|
+
};
|
|
1349
|
+
operation = current;
|
|
1350
|
+
state = {
|
|
1351
|
+
phase: action === "install" ? "installing" : "removing",
|
|
1352
|
+
restartRequired: false
|
|
1353
|
+
};
|
|
1354
|
+
current.done = (async () => {
|
|
1355
|
+
try {
|
|
1356
|
+
if (action === "remove") {
|
|
1357
|
+
const bundle = (await host.listBundles()).find((value) => value.name === SUBAGENT_RUNTIME_PACKAGE);
|
|
1358
|
+
if (!bundle?.installed || bundle.readOnlyReason) throw Error("not-removable");
|
|
1359
|
+
await selectDsh();
|
|
1360
|
+
}
|
|
1361
|
+
const result = action === "install" ? await host.installBundle(`${SUBAGENT_RUNTIME_PACKAGE}@${SUBAGENT_RUNTIME_VERSION}`, {
|
|
1362
|
+
enabled: false,
|
|
1363
|
+
requestId
|
|
1364
|
+
}) : await host.removeBundle(SUBAGENT_RUNTIME_PACKAGE);
|
|
1365
|
+
if (result.application === "cancelled") state = {
|
|
1366
|
+
phase: "cancelled",
|
|
1367
|
+
restartRequired: false
|
|
1368
|
+
};
|
|
1369
|
+
else if (["applied", "restart-required"].includes(result.application)) state = {
|
|
1370
|
+
phase: "done",
|
|
1371
|
+
restartRequired: true
|
|
1372
|
+
};
|
|
1373
|
+
else state = {
|
|
1374
|
+
phase: "failed",
|
|
1375
|
+
restartRequired: false,
|
|
1376
|
+
error: result.packageResult?.kind ?? result.error?.code ?? "operation-error"
|
|
1377
|
+
};
|
|
1378
|
+
} catch (error) {
|
|
1379
|
+
state = {
|
|
1380
|
+
phase: "failed",
|
|
1381
|
+
restartRequired: false,
|
|
1382
|
+
error: error.message === "not-removable" ? "not-removable" : "operation-error"
|
|
1383
|
+
};
|
|
1384
|
+
} finally {
|
|
1385
|
+
operation = void 0;
|
|
1386
|
+
}
|
|
1387
|
+
})();
|
|
1388
|
+
return status();
|
|
1389
|
+
};
|
|
1257
1390
|
return {
|
|
1258
|
-
|
|
1259
|
-
|
|
1391
|
+
status,
|
|
1392
|
+
start,
|
|
1393
|
+
blocked: () => operation !== void 0 || state.restartRequired,
|
|
1394
|
+
progress(value) {
|
|
1395
|
+
if (operation?.action === "install" && value.requestId === operation.requestId && value.phase === "applying") state.phase = "applying";
|
|
1396
|
+
},
|
|
1397
|
+
async cancel() {
|
|
1398
|
+
const current = operation;
|
|
1399
|
+
if (current?.action !== "install") return status();
|
|
1400
|
+
if ((await current.host.cancelInstall(current.requestId)).status === "cancelled") await current.done;
|
|
1401
|
+
return status();
|
|
1402
|
+
}
|
|
1260
1403
|
};
|
|
1261
1404
|
}
|
|
1262
1405
|
//#endregion
|
|
@@ -2644,7 +2787,7 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
|
|
|
2644
2787
|
Object.freeze(["0.82.1", "0.85.1"]);
|
|
2645
2788
|
//#endregion
|
|
2646
2789
|
//#region src/version.js
|
|
2647
|
-
const PACKAGE_VERSION = "2.1.3
|
|
2790
|
+
const PACKAGE_VERSION = "2.1.3";
|
|
2648
2791
|
const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
|
|
2649
2792
|
//#endregion
|
|
2650
2793
|
//#region src/model-catalog.js
|
|
@@ -2689,7 +2832,8 @@ function unsupportedCapabilities(value) {
|
|
|
2689
2832
|
function visibleModel(value) {
|
|
2690
2833
|
if (!record$4(value)) return void 0;
|
|
2691
2834
|
const id = nonEmpty$2(value.slug);
|
|
2692
|
-
|
|
2835
|
+
const reserve = id === "gpt-reserve" && ["list", "hide"].includes(value.visibility);
|
|
2836
|
+
if (id === void 0 || value.visibility !== "list" && !reserve) return void 0;
|
|
2693
2837
|
const supported = Array.isArray(value.supported_reasoning_levels) ? value.supported_reasoning_levels : [];
|
|
2694
2838
|
const input = Array.isArray(value.input_modalities) ? value.input_modalities.filter((item) => ["text", "image"].includes(item)) : ["text", "image"];
|
|
2695
2839
|
const unsupported = unsupportedCapabilities({
|
|
@@ -2699,7 +2843,7 @@ function visibleModel(value) {
|
|
|
2699
2843
|
return {
|
|
2700
2844
|
...Object.keys(unsupported).length ? { unsupported } : {},
|
|
2701
2845
|
id,
|
|
2702
|
-
name: nonEmpty$2(value.display_name) ?? id,
|
|
2846
|
+
name: reserve ? "GPT-Reserve (Experimental)" : nonEmpty$2(value.display_name) ?? id,
|
|
2703
2847
|
description: nonEmpty$2(value.description),
|
|
2704
2848
|
priority: Number.isFinite(value.priority) ? value.priority : 0,
|
|
2705
2849
|
input: input.length > 0 ? input : ["text"],
|
|
@@ -2719,7 +2863,7 @@ function visibleModel(value) {
|
|
|
2719
2863
|
function parseOfficialModelCatalog(value) {
|
|
2720
2864
|
if (!record$4(value) || !Array.isArray(value.models)) throw new Error("Codex returned a malformed model catalog");
|
|
2721
2865
|
const seen = /* @__PURE__ */ new Set();
|
|
2722
|
-
return value.models.map(visibleModel).filter((model) => model !== void 0 && !seen.has(model.id) && seen.add(model.id)).sort((left, right) => right.priority - left.priority);
|
|
2866
|
+
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);
|
|
2723
2867
|
}
|
|
2724
2868
|
function mergeModel(baseModels, remote) {
|
|
2725
2869
|
const base = baseModels.find((model) => model.id === remote.id) ?? baseModels.find((model) => model.id !== "gpt-5.3-codex-spark") ?? baseModels[0];
|
|
@@ -4693,8 +4837,31 @@ const publicError = (code, message) => ({
|
|
|
4693
4837
|
details: { issues: [] }
|
|
4694
4838
|
}
|
|
4695
4839
|
});
|
|
4696
|
-
function createSubscriptionRpcHandler({ authHandler, usageReader, resetCreditService, preferences, diagnosticsReader, modelCatalog, originalImages, resolveInheritedOriginal, closeConnections }) {
|
|
4840
|
+
function createSubscriptionRpcHandler({ authHandler, usageReader, resetCreditService, preferences, runtimeManagement, diagnosticsReader, modelCatalog, originalImages, resolveInheritedOriginal, closeConnections }) {
|
|
4697
4841
|
return async (endpoint, payload, signal) => {
|
|
4842
|
+
if ([
|
|
4843
|
+
"runtime/status",
|
|
4844
|
+
"runtime/install",
|
|
4845
|
+
"runtime/remove",
|
|
4846
|
+
"runtime/cancel"
|
|
4847
|
+
].includes(endpoint)) try {
|
|
4848
|
+
signal.throwIfAborted();
|
|
4849
|
+
if (!runtimeManagement) return publicError("unavailable", "Runtime management is unavailable");
|
|
4850
|
+
const action = endpoint.split("/")[1];
|
|
4851
|
+
return {
|
|
4852
|
+
ok: true,
|
|
4853
|
+
value: action === "status" ? await runtimeManagement.status() : action === "cancel" ? await runtimeManagement.cancel() : await runtimeManagement.start(action)
|
|
4854
|
+
};
|
|
4855
|
+
} catch (error) {
|
|
4856
|
+
if (signal.aborted) throw error;
|
|
4857
|
+
const code = [
|
|
4858
|
+
"busy",
|
|
4859
|
+
"active-tasks",
|
|
4860
|
+
"restart-required",
|
|
4861
|
+
"unavailable"
|
|
4862
|
+
].includes(error.message) ? error.message : "operation-error";
|
|
4863
|
+
return publicError(code, code);
|
|
4864
|
+
}
|
|
4698
4865
|
if (endpoint === "image/original/chunk") try {
|
|
4699
4866
|
signal.throwIfAborted();
|
|
4700
4867
|
if (typeof payload?.sessionId !== "string" || payload.sessionId.length === 0 || payload.sessionId.length > 512 || typeof payload?.assetId !== "string" || !ORIGINAL_IMAGE_ID_PATTERN.test(payload.assetId) || !Number.isSafeInteger(payload?.offset) || payload.offset < 0 || payload.offset % 4194304 !== 0) return publicError("invalid-input", "Invalid original image request");
|
|
@@ -4915,6 +5082,16 @@ function apply(ctx) {
|
|
|
4915
5082
|
const baseProvider = createOpenAICodexProvider();
|
|
4916
5083
|
let resolveAuth = async () => void 0;
|
|
4917
5084
|
let subagentBackend;
|
|
5085
|
+
const runtimeManagement = createRuntimeManagement({
|
|
5086
|
+
manager: () => ctx.get?.("pluginManager"),
|
|
5087
|
+
inspect: inspectSubagentRuntime,
|
|
5088
|
+
active: () => subagentBackend?.activeCount() ?? 0,
|
|
5089
|
+
selectDsh: async () => {
|
|
5090
|
+
if (subagentBackend) await subagentBackend.select("dsh");
|
|
5091
|
+
else await settings.update({ subagentBackend: "dsh" });
|
|
5092
|
+
}
|
|
5093
|
+
});
|
|
5094
|
+
ctx.effect(() => ctx.on?.("plugin-manager/install-state", (value) => runtimeManagement.progress(value)));
|
|
4918
5095
|
const modelCatalog = createOfficialModelCatalog({
|
|
4919
5096
|
getAuth: (options) => resolveAuth(options),
|
|
4920
5097
|
readCredential: (options) => store.read(PROVIDER, options),
|
|
@@ -4953,6 +5130,7 @@ function apply(ctx) {
|
|
|
4953
5130
|
connectionMode: settings.get().connectionMode ?? "sse",
|
|
4954
5131
|
subagentBackend: settings.get().subagentBackend ?? "dsh",
|
|
4955
5132
|
subagentBackendAvailable: subagentBackend !== void 0,
|
|
5133
|
+
subagentRuntimeInstalled: inspectSubagentRuntime().installed,
|
|
4956
5134
|
...readCapabilitySettings(settings.get()),
|
|
4957
5135
|
[QUICK_QUOTA_MODE_FIELD]: normalizeQuickQuotaMode(settings.get()[QUICK_QUOTA_MODE_FIELD], settings.get()[LEGACY_QUICK_QUOTA_FIELD]),
|
|
4958
5136
|
[SEARCH_PROVIDER_FIELD]: settings.get()[SEARCH_PROVIDER_FIELD],
|
|
@@ -5019,7 +5197,8 @@ function apply(ctx) {
|
|
|
5019
5197
|
resolveAuth,
|
|
5020
5198
|
store,
|
|
5021
5199
|
refresh: (credential) => network.run("oauth", () => baseProvider.auth.oauth.refresh(credential)),
|
|
5022
|
-
loadRuntime: loadSubagentRuntime
|
|
5200
|
+
loadRuntime: loadSubagentRuntime,
|
|
5201
|
+
maintenance: runtimeManagement.blocked
|
|
5023
5202
|
});
|
|
5024
5203
|
scoped.subagents.registerProvider(instance.provider);
|
|
5025
5204
|
const switcher = createSubagentBackendSwitcher({
|
|
@@ -5040,7 +5219,10 @@ function apply(ctx) {
|
|
|
5040
5219
|
throw error;
|
|
5041
5220
|
}
|
|
5042
5221
|
};
|
|
5043
|
-
subagentBackend = {
|
|
5222
|
+
subagentBackend = {
|
|
5223
|
+
select,
|
|
5224
|
+
activeCount: instance.activeCount
|
|
5225
|
+
};
|
|
5044
5226
|
const sync = (value) => {
|
|
5045
5227
|
const mode = value.subagentBackend ?? "dsh";
|
|
5046
5228
|
if (mode !== requested) select(mode).catch(() => scoped.logger.warn("Could not switch the subscription subagent backend"));
|
|
@@ -5185,6 +5367,7 @@ function apply(ctx) {
|
|
|
5185
5367
|
usageReader,
|
|
5186
5368
|
resetCreditService,
|
|
5187
5369
|
preferences,
|
|
5370
|
+
runtimeManagement,
|
|
5188
5371
|
diagnosticsReader: () => createSubscriptionDiagnostics({
|
|
5189
5372
|
auth,
|
|
5190
5373
|
preferences,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-codex-subscription",
|
|
3
|
-
"version": "2.1.3
|
|
3
|
+
"version": "2.1.3",
|
|
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",
|
|
@@ -92,7 +92,8 @@
|
|
|
92
92
|
"@deepseek-ai/schemastery": "3.18.1 || ^3.18.2",
|
|
93
93
|
"@earendil-works/pi-ai": "0.82.1 || 0.85.1",
|
|
94
94
|
"react": "^18.2.0",
|
|
95
|
-
"react-dom": "^18.2.0"
|
|
95
|
+
"react-dom": "^18.2.0",
|
|
96
|
+
"@deepseek-ai/dsh-subagent-codex": "0.1.5-rc.2"
|
|
96
97
|
},
|
|
97
98
|
"devDependencies": {
|
|
98
99
|
"@deepseek-ai/cordis": "4.0.2",
|
|
@@ -120,16 +121,18 @@
|
|
|
120
121
|
"fake-indexeddb": "6.2.5",
|
|
121
122
|
"react": "18.3.1",
|
|
122
123
|
"react-dom": "18.3.1",
|
|
123
|
-
"tsdown": "0.22.2"
|
|
124
|
+
"tsdown": "0.22.2",
|
|
125
|
+
"@deepseek-ai/dsh-subagent-codex": "0.1.5-rc.2"
|
|
124
126
|
},
|
|
125
127
|
"dependencies": {
|
|
126
128
|
"@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
|
|
127
129
|
"https-proxy-agent": "7.0.6",
|
|
128
130
|
"ws": "8.21.3"
|
|
129
131
|
},
|
|
130
|
-
"
|
|
131
|
-
"@deepseek-ai/dsh-
|
|
132
|
-
|
|
132
|
+
"peerDependenciesMeta": {
|
|
133
|
+
"@deepseek-ai/dsh-subagent-codex": {
|
|
134
|
+
"optional": true
|
|
135
|
+
}
|
|
133
136
|
},
|
|
134
137
|
"scripts": {
|
|
135
138
|
"build": "tsdown --config tsdown.config.mjs",
|