dsh-codex-subscription 3.0.0-beta.1 → 3.0.0-beta.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 CHANGED
@@ -10,6 +10,8 @@
10
10
 
11
11
  Sign in with ChatGPT Plus / Pro to use GPT-6 and other Codex models, quota, web search, and image generation inside DSH. No OpenAI API key or Codex CLI.
12
12
 
13
+ **New: control the DSH on your computer from the ChatGPT mobile app (Beta)** — DeepSeek and any other DSH model work from your phone.
14
+
13
15
  [![CI](https://github.com/WSL043/dsh-codex-subscription/actions/workflows/ci.yml/badge.svg)](https://github.com/WSL043/dsh-codex-subscription/actions/workflows/ci.yml)
14
16
  [![npm](https://img.shields.io/npm/v/dsh-codex-subscription?logo=npm&label=npm)](https://www.npmjs.com/package/dsh-codex-subscription)
15
17
  [![total npm downloads](https://img.shields.io/npm/dt/dsh-codex-subscription?logo=npm&label=total%20downloads)](https://www.npmjs.com/package/dsh-codex-subscription)
@@ -78,7 +80,7 @@ Subscription access, model controls, quota management, and image creation in one
78
80
 
79
81
  | Feature | What you can do | Availability / setup |
80
82
  | --- | --- | --- |
81
- | **Phone remote control** | Drive the DSH on your computer from the Codex section of the ChatGPT mobile app: start and continue conversations, switch model and permissions, approve tool calls; DeepSeek and any other DSH model work | Beta; off by default; Settings → Models & runtime → Phone remote control, pair by QR or manual code |
83
+ | **Phone remote control** | Drive the DSH on your computer from the Codex section of the ChatGPT mobile app: start, continue and archive conversations, switch model and permissions, answer approvals and questions; DeepSeek and any other DSH model work | Beta (3.0.0-beta.3); off by default; Settings → Codex → Models & runtime → Phone remote control, pair by QR or manual code |
82
84
  | **Codex independent subtasks** | Reuse subscription sign-in and workspace permissions; select allowed models and reasoning levels | Beta; DSH by default, Codex requires the optional component and model-selection setup |
83
85
  | **Subtask component management** | Install, disable, or uninstall the official Codex subtask component from settings | Managed by supported DSH hosts; no extra login |
84
86
  | **Cloud context compaction** | Continue long conversations using Codex compaction while retaining DSH history and native compaction | Beta / experimental; off by default, enabled requests use SSE |
@@ -91,7 +93,7 @@ Subscription access, model controls, quota management, and image creation in one
91
93
 
92
94
  ## Prepare DSH
93
95
 
94
- Verified against DSH `0.2.0-rc.2` (`next` channel) and `0.1.7-rc.2` (`latest` channel), with earlier accepted versions still supported.
96
+ 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.
95
97
 
96
98
  This plugin supports the latest DeepSeek Harness release recorded in its package metadata and requires a ChatGPT account that currently has Codex access.
97
99
 
@@ -152,6 +154,20 @@ Choose a model, adjust reasoning, switch speed tiers, and check remaining quota
152
154
 
153
155
  <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>
154
156
 
157
+ ### Control DSH from your phone (Beta)
158
+
159
+ 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:
160
+
161
+ - browse, start, continue, interrupt and archive DSH conversations from the phone, with DeepSeek, Codex or any other DSH model;
162
+ - switch model, reasoning level and permissions (workspace write / full access) from the phone;
163
+ - 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;
164
+ - replies appear on the phone as they are written;
165
+ - model errors are shown on the phone.
166
+
167
+ 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.3`.
168
+
169
+ <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>
170
+
155
171
  ### Accounts and preferences, in one place
156
172
 
157
173
  Open **Settings → Codex** to manage accounts and quota. Enable other features as your tasks need them.
@@ -162,7 +178,7 @@ Open **Settings → Codex** to manage accounts and quota. Enable other features
162
178
  | Settings tab | What it controls |
163
179
  | --- | --- |
164
180
  | **Account** | Sign-in, account switching, reset times, quota display and alerts |
165
- | **Models & runtime** | Subscription search, context budget, connections and subtasks |
181
+ | **Models & runtime** | Subscription search, context budget, connections, subtasks and phone remote control |
166
182
  | **Images & sketch** | Separate switches for image generation, the canvas, and agent drawing |
167
183
  | **Maintenance** | Support diagnostics and local quota forecast cache |
168
184
 
@@ -287,6 +303,13 @@ DSH 0.2.0-rc.2 did not exist when any release before 2.2.10 was published, and a
287
303
 
288
304
  </details>
289
305
 
306
+ <details>
307
+ <summary>How does this relate to the official Codex bundle (dsh-hooks-codex) in the plugin list?</summary>
308
+
309
+ They are unrelated and can be installed together. The official Codex / Claude Code bundles let DSH run Codex or Claude Code style hooks configs (scripts that run before and after tool calls). This plugin signs in with your ChatGPT subscription and provides Codex models, quota, search, images and phone remote control.
310
+
311
+ </details>
312
+
290
313
  <details>
291
314
  <summary>No dsh command on your computer?</summary>
292
315
 
package/README.md CHANGED
@@ -10,6 +10,8 @@
10
10
 
11
11
  用 ChatGPT Plus / Pro 订阅登录,即可在 DSH 中使用 GPT-6 等 Codex 模型、查额度、联网搜索和生图。无需 OpenAI API Key,也不依赖 Codex CLI。
12
12
 
13
+ **新:用 ChatGPT 手机 App 远程控制电脑上的 DSH(Beta)**,DeepSeek 等任意 DSH 模型都能在手机上用。
14
+
13
15
  [![CI](https://github.com/WSL043/dsh-codex-subscription/actions/workflows/ci.yml/badge.svg)](https://github.com/WSL043/dsh-codex-subscription/actions/workflows/ci.yml)
14
16
  [![npm](https://img.shields.io/npm/v/dsh-codex-subscription?logo=npm&label=npm)](https://www.npmjs.com/package/dsh-codex-subscription)
15
17
  [![npm 总下载量](https://img.shields.io/npm/dt/dsh-codex-subscription?logo=npm&label=%E6%80%BB%E4%B8%8B%E8%BD%BD%E9%87%8F)](https://www.npmjs.com/package/dsh-codex-subscription)
@@ -78,7 +80,7 @@
78
80
 
79
81
  | 功能 | 你可以做什么 | 使用方式 / 条件 |
80
82
  | --- | --- | --- |
81
- | **手机远程控制** | 在 ChatGPT 手机 App 的 Codex 里直接指挥电脑上的 DSH:新建、续聊、切换模型和权限、批准工具调用,DeepSeek 等任意 DSH 模型都能用 | Beta;默认关闭,设置 → 模型与运行 → 手机远程控制,扫码或输入手动码配对 |
83
+ | **手机远程控制** | 在 ChatGPT 手机 App 的 Codex 里直接指挥电脑上的 DSH:新建、续聊、归档对话,切换模型和权限,回答审批和提问,DeepSeek 等任意 DSH 模型都能用 | Beta(3.0.0-beta.3);默认关闭,设置 → Codex 订阅 → 模型与运行 → 手机远程控制,扫码或输入手动码配对 |
82
84
  | **Codex 独立子任务** | 复用订阅登录和工作区权限执行独立任务,可指定允许的模型与推理档位 | Beta;默认 DSH,Codex 需安装可选组件并配置模型选择 |
83
85
  | **子任务组件管理** | 在设置里安装、停用或卸载官方 Codex 子任务组件 | 由支持的 DSH 宿主管理,无需额外登录 |
84
86
  | **云端上下文压缩** | 使用 Codex 云端压缩继续长对话,同时保留 DSH 历史与原生压缩 | Beta / 实验性;默认关闭,开启的请求使用 SSE |
@@ -91,7 +93,7 @@
91
93
 
92
94
  ## 准备 DSH
93
95
 
94
- 已验证兼容 DSH `0.2.0-rc.2`(`next` 通道)和 `0.1.7-rc.2`(`latest` 通道),并继续支持更早的已验收版本。
96
+ 已验证兼容 DSH `0.2.0-rc.2`(`latest` 与 `next` 通道),最低支持 `0.1.7-rc.2`;更早的 DSH 请先升级。
95
97
 
96
98
  本插件支持软件包元数据中记录的最新版 DeepSeek Harness,并需要一个当前具有 Codex 使用资格的 ChatGPT 账户。
97
99
 
@@ -152,6 +154,20 @@ dsh --profile headless "只回复:ok"
152
154
 
153
155
  <p align="center"><img src="docs/assets/composer-astra-fast.png" width="800" alt="DSH 输入框:GPT-6-Astra Max、闪电标识的 Fast 高速模式与剩余额度"></p>
154
156
 
157
+ ### 手机远程控制 DSH(Beta)
158
+
159
+ 打开 **设置 → Codex 订阅 → 模型与运行 → 手机远程控制**,用 ChatGPT 手机 App 的 Codex 扫码配对,这台电脑上的 DSH 就会出现在手机的主机列表里:
160
+
161
+ - 在手机上查看、新建、续聊、中断和归档 DSH 对话,DeepSeek、Codex 以及其他 DSH 模型都能用;
162
+ - 在手机上切换模型、推理档位和权限(工作区内修改 / 完全访问);
163
+ - DSH 需要批准工具调用或向你提问时,手机会直接弹出;手机掉线会在重新打开时再弹一次,否则交回电脑处理;
164
+ - 回复边生成边显示在手机上;
165
+ - 模型报错会显示在手机上。
166
+
167
+ 默认关闭。电脑需要保持开机、联网并打开 DSH。这是 OpenAI 尚未向第三方开放的 ChatGPT 能力,随时可能变化,所以标为 Beta。目前在预发布版中提供:`dsh-codex-subscription@3.0.0-beta.3`。
168
+
169
+ <p align="center"><img src="docs/assets/remote-control.png" width="560" alt="官方桌面版设置页:手机远程控制已连接,显示配对二维码和手动码"></p>
170
+
155
171
  ### 账号与偏好,集中管理
156
172
 
157
173
  在 **设置 → Codex 订阅** 中管理账号和额度;其余功能按任务需要开启。
@@ -162,7 +178,7 @@ dsh --profile headless "只回复:ok"
162
178
  | 设置页 | 在这里做什么 |
163
179
  | --- | --- |
164
180
  | **账号与额度** | 登录与切换账号、查看重置时间、设置额度显示和提醒 |
165
- | **模型与运行** | 订阅搜索、上下文预算、连接方式与独立子任务 |
181
+ | **模型与运行** | 订阅搜索、上下文预算、连接方式、独立子任务与手机远程控制 |
166
182
  | **图片与草图** | 分别开启图片生成、画板和 Agent 绘图 |
167
183
  | **维护** | 生成支持诊断、管理本地额度预测缓存 |
168
184
 
@@ -316,6 +332,13 @@ dsh plugin --profile web remove dsh-codex-subscription
316
332
 
317
333
  </details>
318
334
 
335
+ <details>
336
+ <summary>和官方插件列表里的 Codex 组合包(dsh-hooks-codex)是什么关系?</summary>
337
+
338
+ 没有关系,可以同时安装。官方的 Codex / Claude Code 组合包让 DSH 运行 Codex 或 Claude Code 格式的 hooks 配置(工具调用前后自动执行的脚本);本插件负责用 ChatGPT 订阅登录、使用 Codex 模型、查看额度、搜索、生图和手机远程控制。
339
+
340
+ </details>
341
+
319
342
  <details>
320
343
  <summary>电脑没有 dsh 命令,怎么安装?</summary>
321
344
 
@@ -1,22 +1,12 @@
1
1
  {
2
2
  "latestTested": "0.2.0-rc.2",
3
3
  "supported": [
4
- "0.1.2-rc.1",
5
- "0.1.5-rc.1",
6
- "0.1.5-rc.2",
7
- "0.1.5-rc.3",
8
- "0.1.7-rc.1",
9
4
  "0.1.7-rc.2",
10
5
  "0.2.0-rc.1",
11
6
  "0.2.0-rc.2"
12
7
  ],
13
8
  "previews": [
14
- "0.1.5-alpha.1",
15
- "0.1.5-alpha.2",
16
- "0.1.6-alpha.1",
17
- "0.1.6-alpha.2",
18
- "0.1.7-alpha.1",
19
- "0.1.7-alpha.2",
20
- "0.2.1-alpha.1"
9
+ "0.2.1-alpha.1",
10
+ "0.2.1-alpha.2"
21
11
  ]
22
12
  }
package/lib/client.js CHANGED
@@ -487,20 +487,20 @@ window.__ModuleLoader__.load({
487
487
  //#endregion
488
488
  //#region src/client-session-compat.js
489
489
  async function withComposerSession(sessions, id, operation) {
490
- const reference = typeof sessions.retain === "function" ? sessions.retain(id, { source: "controllerOperation" }) : void 0;
490
+ if (typeof sessions?.retain !== "function") throw new Error("Image composer is unavailable");
491
+ const reference = sessions.retain(id, { source: "controllerOperation" });
491
492
  try {
492
- if (reference) await reference.ready;
493
- const context = reference ? reference.binding.ctx : sessions.scope(id);
493
+ await reference.ready;
494
+ const context = reference.binding.ctx;
494
495
  if (!context) throw new Error("Image composer is unavailable");
495
496
  return await operation(context);
496
497
  } finally {
497
- reference?.release();
498
+ reference.release();
498
499
  }
499
500
  }
500
- function openComposerSession(sessions, workspace, id) {
501
- if (typeof workspace?.openSession === "function") workspace.openSession(id);
502
- else if (typeof sessions.open === "function") sessions.open(id);
503
- else throw new Error("Session navigation is unavailable");
501
+ function openComposerSession(_sessions, workspace, id) {
502
+ if (typeof workspace?.openSession !== "function") throw new Error("Session navigation is unavailable");
503
+ workspace.openSession(id);
504
504
  }
505
505
  function createSessionOpeners() {
506
506
  const entries = /* @__PURE__ */ new Map();
@@ -5469,17 +5469,16 @@ window.__ModuleLoader__.load({
5469
5469
  const Switch = _deepseek_ai_dsh_client_ui_primitives.Switch;
5470
5470
  const useAnchoredPosition = _deepseek_ai_dsh_client_ui_primitives.useAnchoredPosition;
5471
5471
  const useDismissOnOutsidePointer = _deepseek_ai_dsh_client_ui_primitives.useDismissOnOutsidePointer;
5472
- const IconCheckOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconCheckOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconCheckOutlineRegular;
5473
- const IconChevronDownOutline14 = _deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14 ?? _deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular;
5474
- const IconChevronRightOutline14 = _deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14 ?? _deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineRegular;
5472
+ const IconCheckOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconCheckOutlineRegular;
5473
+ const IconChevronDownOutline14 = _deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular;
5474
+ const IconChevronRightOutline14 = _deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineRegular;
5475
5475
  const Menu = _deepseek_ai_dsh_client_ui_primitives.Menu;
5476
5476
  const Tooltip = _deepseek_ai_dsh_client_ui_primitives.Tooltip;
5477
- const IconChevronLeftOutline14 = _deepseek_ai_dsh_client_ui_primitives.IconChevronLeftOutline14 ?? _deepseek_ai_dsh_client_ui_primitives.IconChevronLeftOutlineRegular;
5478
- const IconCloseOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconCloseOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconCloseOutlineRegular;
5479
- const IconCopyOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconCopyOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconCopyOutlineRegular;
5480
- const IconDownloadOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconDownloadOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconDownloadOutlineRegular;
5481
- const IconEditOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconEditOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular;
5482
- _deepseek_ai_dsh_client_ui_primitives.IconFullscreenOutline16 ?? _deepseek_ai_dsh_client_ui_primitives.IconFullscreenOutlineRegular;
5477
+ const IconChevronLeftOutline14 = _deepseek_ai_dsh_client_ui_primitives.IconChevronLeftOutlineRegular;
5478
+ const IconCloseOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconCloseOutlineRegular;
5479
+ const IconCopyOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconCopyOutlineRegular;
5480
+ const IconDownloadOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconDownloadOutlineRegular;
5481
+ const IconEditOutline16 = _deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular;
5483
5482
  //#endregion
5484
5483
  //#region src/image-workspace.jsx
5485
5484
  function ImageWorkspace(props) {
@@ -5514,16 +5513,12 @@ window.__ModuleLoader__.load({
5514
5513
  //#endregion
5515
5514
  //#region src/image-composer.js
5516
5515
  function attachImageFiles(conversation, input, files, sessionId) {
5517
- const modern = typeof conversation.createDrafts === "function";
5518
- const create = modern ? () => conversation.createDrafts(sessionId, files) : () => conversation.createDraftImages(files);
5519
- const release = modern ? (items) => conversation.releaseDraftAttachments(items) : (items) => conversation.releaseDraftImages(items);
5520
- const add = modern ? input.addAttachments : input.addImages;
5521
- if (typeof add !== "function" || modern && !sessionId) throw new Error("Image composer is unavailable");
5522
- const created = create();
5516
+ if (typeof conversation.createDrafts !== "function" || typeof input.addAttachments !== "function" || !sessionId) throw new Error("Image composer is unavailable");
5517
+ const created = conversation.createDrafts(sessionId, files);
5523
5518
  try {
5524
- if (!add.call(input, created.map((item) => item.id))) throw new Error("The composer is busy");
5519
+ if (!input.addAttachments(created.map((item) => item.id))) throw new Error("The composer is busy");
5525
5520
  } catch (error) {
5526
- release(created);
5521
+ conversation.releaseDraftAttachments(created);
5527
5522
  throw error;
5528
5523
  }
5529
5524
  return created;
@@ -8392,6 +8387,8 @@ window.__ModuleLoader__.load({
8392
8387
  limitId: limit.id
8393
8388
  }))).filter((window) => Number.isFinite(window.remainingPercent) && window.remainingPercent >= 0 && window.remainingPercent <= (mode === "custom" ? readCapabilitySettings(thresholds)[window.windowSeconds > 0 && window.windowSeconds <= 6 * 3600 ? "quotaShortThreshold" : "quotaLongThreshold"] : mode === "early" && window.windowSeconds > 0 && window.windowSeconds <= 6 * 3600 ? 50 : 20) && (!Number.isFinite(window.resetsAt) || window.resetsAt * 1e3 > now)).sort((a, b) => a.remainingPercent - b.remainingPercent)[0];
8394
8389
  }
8390
+ //#endregion
8391
+ //#region src/settings-contract.js
8395
8392
  const DISABLED_MODELS_FIELD = "disabledModels";
8396
8393
  const AUTO_QUOTA_RETRY_FIELD = "autoQuotaRetry";
8397
8394
  const QUICK_QUOTA_MODE_FIELD = "quickQuotaMode";
@@ -8503,10 +8500,9 @@ window.__ModuleLoader__.load({
8503
8500
  const supportsCodexFastMode = (modelId) => typeof modelId === "string" && (/^gpt-5\.(?:5|6)(?:$|-)/u.test(modelId) || modelId === "gpt-5.4" || modelId === "gpt-6-astra");
8504
8501
  //#endregion
8505
8502
  //#region src/preference-controller.js
8506
- function createPreferenceController(scope, rpc) {
8503
+ function createPreferenceController(rpc) {
8507
8504
  let updating = false;
8508
8505
  let error = false;
8509
- let fallbackStatus = "loading";
8510
8506
  let fallback;
8511
8507
  let pendingPatch;
8512
8508
  let failedPatch;
@@ -8525,10 +8521,8 @@ window.__ModuleLoader__.load({
8525
8521
  let subagentBackendAvailable = false;
8526
8522
  let subagentRuntimeInstalled = false;
8527
8523
  const sameModels = (left, right) => left.length === right.length && left.every((model, index) => JSON.stringify(model) === JSON.stringify(right[index]));
8528
- const nativeSnapshot = () => scope.getSnapshot();
8529
8524
  const read = () => {
8530
- const native = nativeSnapshot();
8531
- const current = native.status === "ready" ? native : fallbackStatus === "ready" ? fallback : native;
8525
+ const current = fallback ?? { status: "unavailable" };
8532
8526
  const value = pendingPatch === void 0 ? current.value : {
8533
8527
  ...current.value,
8534
8528
  ...pendingPatch
@@ -8577,11 +8571,6 @@ window.__ModuleLoader__.load({
8577
8571
  snapshot = read();
8578
8572
  for (const listener of listeners) listener();
8579
8573
  };
8580
- const disposeScope = scope.subscribe(() => {
8581
- error = false;
8582
- if (!updating) failedPatch = void 0;
8583
- publish();
8584
- });
8585
8574
  const acceptFallback = (value) => {
8586
8575
  subagentBackendAvailable = value?.subagentBackendAvailable === true;
8587
8576
  subagentRuntimeInstalled = value?.subagentRuntimeInstalled === true;
@@ -8593,7 +8582,6 @@ window.__ModuleLoader__.load({
8593
8582
  ultrafastModels = Array.isArray(value?.ultrafastModels) ? value.ultrafastModels : [];
8594
8583
  catalogStatus = value?.catalogStatus;
8595
8584
  }
8596
- fallbackStatus = "ready";
8597
8585
  fallback = {
8598
8586
  status: "ready",
8599
8587
  value: {
@@ -8622,29 +8610,16 @@ window.__ModuleLoader__.load({
8622
8610
  const current = ++generation;
8623
8611
  updating = false;
8624
8612
  pendingPatch = void 0;
8625
- fallbackStatus = "loading";
8626
8613
  fallback = void 0;
8627
8614
  error = false;
8628
8615
  publish();
8629
8616
  try {
8630
8617
  const value = unwrap(await rpc.call(CHANNEL, "preferences/status", {}));
8631
8618
  if (current !== generation || disposed) return;
8632
- subagentBackendAvailable = value?.subagentBackendAvailable === true;
8633
- subagentRuntimeInstalled = value?.subagentRuntimeInstalled === true;
8634
- if (nativeSnapshot().status === "ready") {
8635
- if (!modelRefreshStarted) {
8636
- contextModels = Array.isArray(value?.contextModels) ? value.contextModels : [];
8637
- availableModels = Array.isArray(value?.availableModels) ? value.availableModels : [];
8638
- verbosityModels = Array.isArray(value?.verbosityModels) ? value.verbosityModels : [];
8639
- fastModels = Array.isArray(value?.fastModels) ? value.fastModels : void 0;
8640
- ultrafastModels = Array.isArray(value?.ultrafastModels) ? value.ultrafastModels : [];
8641
- catalogStatus = value?.catalogStatus;
8642
- }
8643
- } else acceptFallback(value);
8619
+ acceptFallback(value);
8644
8620
  publish();
8645
8621
  } catch {
8646
- if (current !== generation || disposed || nativeSnapshot().status === "ready") return;
8647
- fallbackStatus = "unavailable";
8622
+ if (current !== generation || disposed) return;
8648
8623
  publish();
8649
8624
  }
8650
8625
  };
@@ -8687,46 +8662,19 @@ window.__ModuleLoader__.load({
8687
8662
  }
8688
8663
  }
8689
8664
  };
8690
- const accepted = (entries, wait = 1500) => new Promise((resolve) => {
8691
- const matches = () => entries.every(([field, value]) => JSON.stringify(nativeSnapshot().value?.[field]) === JSON.stringify(value));
8692
- if (matches()) return resolve(true);
8693
- let timer;
8694
- const stop = scope.subscribe(() => {
8695
- if (!matches()) return;
8696
- clearTimeout(timer);
8697
- stop();
8698
- resolve(true);
8699
- });
8700
- timer = setTimeout(() => {
8701
- stop();
8702
- resolve(matches());
8703
- }, wait);
8704
- });
8705
8665
  const set = async (patch) => {
8706
8666
  if (disposed || snapshot.status !== "ready" || snapshot.writable !== true) return;
8707
8667
  const current = ++generation;
8708
- const entries = Object.entries(patch);
8709
8668
  updating = true;
8710
8669
  pendingPatch = patch;
8711
8670
  error = false;
8712
8671
  failedPatch = void 0;
8713
8672
  publish();
8714
8673
  try {
8715
- if (nativeSnapshot().status === "ready" && !Object.hasOwn(patch, "subagentBackend")) {
8716
- for (const [field, value] of entries) {
8717
- if (current !== generation) return;
8718
- await scope.set(field, value);
8719
- }
8720
- if (current !== generation) return;
8721
- error = !await accepted(entries);
8722
- if (error) failedPatch = patch;
8723
- pendingPatch = void 0;
8724
- } else {
8725
- const value = unwrap(await rpc.call(CHANNEL, "preferences/update", patch));
8726
- if (current !== generation) return;
8727
- acceptFallback(value);
8728
- pendingPatch = void 0;
8729
- }
8674
+ const value = unwrap(await rpc.call(CHANNEL, "preferences/update", patch));
8675
+ if (current !== generation) return;
8676
+ acceptFallback(value);
8677
+ pendingPatch = void 0;
8730
8678
  } catch {
8731
8679
  if (current === generation) {
8732
8680
  pendingPatch = void 0;
@@ -8754,7 +8702,6 @@ window.__ModuleLoader__.load({
8754
8702
  disposed = true;
8755
8703
  generation += 1;
8756
8704
  modelRefreshGeneration += 1;
8757
- disposeScope();
8758
8705
  }
8759
8706
  };
8760
8707
  }
@@ -9135,7 +9082,7 @@ window.__ModuleLoader__.load({
9135
9082
  }
9136
9083
  //#endregion
9137
9084
  //#region src/version.js
9138
- const PACKAGE_VERSION = "3.0.0-beta.1";
9085
+ const PACKAGE_VERSION = "3.0.0-beta.3";
9139
9086
  //#endregion
9140
9087
  //#region src/client-recovery.js
9141
9088
  async function recoveryCall(rpc, endpoint, payload = {}, timeoutMs = 1e4) {
@@ -14972,10 +14919,7 @@ window.__ModuleLoader__.load({
14972
14919
  return () => tag.remove();
14973
14920
  }, "codex-subscription: style");
14974
14921
  const rpc = createSubscriptionRpcClient(ctx.get("connection").rpc);
14975
- const preference = createPreferenceController(ctx.get("settingsScope")?.bind({ namespace: "codex-subscription" }) ?? {
14976
- getSnapshot: () => ({ status: "unavailable" }),
14977
- subscribe: () => () => {}
14978
- }, rpc);
14922
+ const preference = createPreferenceController(rpc);
14979
14923
  const defaultModel = createDefaultModelController(rpc);
14980
14924
  ctx.effect(() => {
14981
14925
  let previous = JSON.stringify(preference.getSnapshot(), (key, value) => key.startsWith("image") || key === "" ? value : void 0);
@@ -15123,7 +15067,6 @@ window.__ModuleLoader__.load({
15123
15067
  const tool = Array.isArray(extraFiles);
15124
15068
  if (!preference.getSnapshot().imageEditing) throw new Error("Image editing is disabled");
15125
15069
  return withComposerSession(sessions, sessionId, async (actx) => {
15126
- if (conversation.input?.for === void 0) throw new Error("This DSH version does not provide the image composer bridge");
15127
15070
  const response = await fetch(src, { signal: lifetime.signal });
15128
15071
  if (!response.ok) throw new Error("Could not read generated image");
15129
15072
  const blob = await response.blob();
package/lib/index.js CHANGED
@@ -24,8 +24,7 @@ import { openaiCodexProvider as createOpenAICodexProvider } from "@earendil-work
24
24
  import { createModels } from "@earendil-works/pi-ai";
25
25
  import { WebError } from "@deepseek-ai/dsh-web";
26
26
  //#region src/settings-adapter.js
27
- function createSettingsAdapter(ctx, schema, config, namespace) {
28
- if (typeof ctx.settings.register === "function") return ctx.settings.register(namespace, schema);
27
+ function createSettingsAdapter(ctx, config) {
29
28
  if (typeof ctx.settings.configure !== "function" || typeof ctx.settings.update !== "function") throw new Error("DSH settings API is unavailable");
30
29
  ctx.effect(() => ctx.settings.configure({ auto: false }));
31
30
  const entry = ctx.fiber.entry;
@@ -36,7 +35,13 @@ function createSettingsAdapter(ctx, schema, config, namespace) {
36
35
  get,
37
36
  update: (patch) => ctx.settings.update(id, patch),
38
37
  watch(listener) {
39
- return ctx.on("loader/volatile-update", () => listener(get()));
38
+ let previous = get();
39
+ return ctx.on("loader/volatile-update", () => {
40
+ const value = get();
41
+ const before = previous;
42
+ previous = value;
43
+ listener(value, before);
44
+ });
40
45
  }
41
46
  };
42
47
  }
@@ -276,7 +281,6 @@ function capabilityPatch(payload) {
276
281
  }
277
282
  //#endregion
278
283
  //#region src/settings-contract.js
279
- const SETTINGS_NAMESPACE = "codex-subscription";
280
284
  const DISABLED_MODELS_FIELD = "disabledModels";
281
285
  const AUTO_QUOTA_RETRY_FIELD = "autoQuotaRetry";
282
286
  const QUICK_QUOTA_MODE_FIELD = "quickQuotaMode";
@@ -1296,13 +1300,11 @@ function authenticatedSubagentChild(child, { Transport, getTokens, thread, signa
1296
1300
  //#region src/subagent-runtime.js
1297
1301
  const SUBAGENT_RUNTIME_PACKAGE = "@deepseek-ai/dsh-subagent-codex";
1298
1302
  const SUPPORTED_RUNTIME_VERSIONS = Object.freeze([
1299
- "0.1.5-rc.2",
1300
- "0.1.5-rc.3",
1301
- "0.1.7-rc.1",
1302
1303
  "0.1.7-rc.2",
1303
1304
  "0.2.0-rc.1",
1304
1305
  "0.2.0-rc.2",
1305
- "0.2.1-alpha.1"
1306
+ "0.2.1-alpha.1",
1307
+ "0.2.1-alpha.2"
1306
1308
  ]);
1307
1309
  const require = createRequire(import.meta.url);
1308
1310
  const execute = promisify(execFile);
@@ -2042,10 +2044,11 @@ function originalImageRefsEqual(left, right) {
2042
2044
  /** Resolve only an exact original reference copied into a DSH fork prefix. */
2043
2045
  function inheritedOriginalImageRef(session, assetId) {
2044
2046
  const parentSession = session?.header?.parentSession;
2045
- const seedLength = Number.isSafeInteger(session?.inheritedEventCount) ? session.inheritedEventCount : session?.header?.seedLength;
2047
+ const seedLength = session?.inheritedEventCount;
2046
2048
  if (typeof parentSession !== "string" || parentSession.length === 0 || !Number.isSafeInteger(seedLength) || seedLength < 0 || !ORIGINAL_IMAGE_ID_PATTERN.test(assetId)) return void 0;
2047
- let events = session?.events;
2048
- if (!Array.isArray(events) && typeof session?.snapshotEvents === "function") try {
2049
+ if (typeof session?.snapshotEvents !== "function") return void 0;
2050
+ let events;
2051
+ try {
2049
2052
  events = session.snapshotEvents();
2050
2053
  } catch {
2051
2054
  return;
@@ -2059,7 +2062,7 @@ function inheritedOriginalImageRef(session, assetId) {
2059
2062
  }
2060
2063
  //#endregion
2061
2064
  //#region src/version.js
2062
- const PACKAGE_VERSION = "3.0.0-beta.1";
2065
+ const PACKAGE_VERSION = "3.0.0-beta.3";
2063
2066
  const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
2064
2067
  //#endregion
2065
2068
  //#region src/codex-images.js
@@ -2232,7 +2235,7 @@ async function readSessionImage(attachmentId, attachments, signal, messages) {
2232
2235
  };
2233
2236
  }
2234
2237
  async function editImages(values, attachments, signal, messages) {
2235
- if (!Array.isArray(values) || values.length === 0 || values.length > MAX_REFERENCE_IMAGES) throw new Error(`referenceImages must contain between 1 and ${MAX_REFERENCE_IMAGES} images`);
2238
+ if (!Array.isArray(values) || values.length === 0 || values.length > MAX_REFERENCE_IMAGES) throw new Error(`referenceImages must contain between 1 and ${MAX_REFERENCE_IMAGES} images; omit it to generate a new image`);
2236
2239
  const available = messages === void 0 ? void 0 : sessionImageReferences(messages);
2237
2240
  const references = values.map((value) => {
2238
2241
  const id = normalizeAttachmentId(value?.attachmentId);
@@ -2478,6 +2481,10 @@ function createCodexImageTool(options) {
2478
2481
  timeoutMs: 300 * 1e3,
2479
2482
  isConcurrencySafe: () => false,
2480
2483
  async execute(args, exec) {
2484
+ if (Array.isArray(args.referenceImages) && args.referenceImages.length === 0) {
2485
+ const { referenceImages: _empty, ...rest } = args;
2486
+ args = rest;
2487
+ }
2481
2488
  assertImageOperation(options.getFeatures?.(), args.referenceImages !== void 0);
2482
2489
  const defaults = readImageDefaults(options.getFeatures?.());
2483
2490
  args = {
@@ -4161,6 +4168,61 @@ function createDshRemoteControl({ controller, agents, permissions = () => void 0
4161
4168
  return decision === "accept" || decision === "acceptForSession" ? "allowed-once" : decision === "cancel" ? "cancelled" : "rejected";
4162
4169
  }, () => next());
4163
4170
  };
4171
+ const streams = /* @__PURE__ */ new Map();
4172
+ const onStream = (session, frame) => {
4173
+ const running = session ? active.get(session.id) : void 0;
4174
+ if (!running || !subscribers.has(session.id)) return;
4175
+ const id = session.id;
4176
+ if (frame.type === "start") {
4177
+ streams.delete(id);
4178
+ return;
4179
+ }
4180
+ if (frame.type === "end") {
4181
+ const stream = streams.get(id);
4182
+ if (stream && frame.outcome?.eventType !== "assistant/message") {
4183
+ streams.delete(id);
4184
+ stream.item.text = stream.text;
4185
+ emit(id, "item/completed", {
4186
+ threadId: id,
4187
+ turnId: running.turn.id,
4188
+ item: stream.item,
4189
+ completedAtMs: Date.now()
4190
+ });
4191
+ }
4192
+ return;
4193
+ }
4194
+ const chunk = frame.chunk;
4195
+ if (chunk?.type !== "text-delta" || typeof chunk.text !== "string" || chunk.text === "") return;
4196
+ let stream = streams.get(id);
4197
+ if (!stream) {
4198
+ stream = {
4199
+ item: {
4200
+ type: "agentMessage",
4201
+ id: randomUUID(),
4202
+ text: "",
4203
+ phase: null,
4204
+ memoryCitation: null,
4205
+ delivery: null
4206
+ },
4207
+ text: ""
4208
+ };
4209
+ streams.set(id, stream);
4210
+ running.turn.items.push(stream.item);
4211
+ emit(id, "item/started", {
4212
+ threadId: id,
4213
+ turnId: running.turn.id,
4214
+ item: stream.item,
4215
+ startedAtMs: Date.now()
4216
+ });
4217
+ }
4218
+ stream.text += chunk.text;
4219
+ emit(id, "item/agentMessage/delta", {
4220
+ threadId: id,
4221
+ turnId: running.turn.id,
4222
+ itemId: stream.item.id,
4223
+ delta: chunk.text
4224
+ });
4225
+ };
4164
4226
  /** Forward committed assistant and tool events of a phone-started turn as items. */
4165
4227
  const onSessionEvent = (session, event) => {
4166
4228
  const running = active.get(session.id);
@@ -4193,9 +4255,27 @@ function createDshRemoteControl({ controller, agents, permissions = () => void 0
4193
4255
  const items = projectTurns([{
4194
4256
  role: "user",
4195
4257
  id: "x",
4196
- content: []
4258
+ content: [{
4259
+ type: "text",
4260
+ text: "x"
4261
+ }]
4197
4262
  }, message]).flatMap((turn) => turn.items.slice(1));
4263
+ const stream = streams.get(session.id);
4264
+ streams.delete(session.id);
4265
+ let reuse = stream?.item;
4198
4266
  for (const item of items) {
4267
+ if (reuse && item.type === "agentMessage") {
4268
+ const shown = reuse;
4269
+ reuse = void 0;
4270
+ shown.text = item.text;
4271
+ emit(session.id, "item/completed", {
4272
+ threadId: session.id,
4273
+ turnId: running.turn.id,
4274
+ item: shown,
4275
+ completedAtMs: Date.now()
4276
+ });
4277
+ continue;
4278
+ }
4199
4279
  running.turn.items.push(item);
4200
4280
  emit(session.id, "item/started", {
4201
4281
  threadId: session.id,
@@ -4214,6 +4294,7 @@ function createDshRemoteControl({ controller, agents, permissions = () => void 0
4214
4294
  return {
4215
4295
  methods,
4216
4296
  onSessionEvent,
4297
+ onStream,
4217
4298
  onApproval,
4218
4299
  onQuestion,
4219
4300
  forget: (notify) => {
@@ -5106,6 +5187,7 @@ function normalizeTransportEvent(event, signal) {
5106
5187
  const FAST_SERVICE_TIER = "priority";
5107
5188
  const ULTRAFAST_SERVICE_TIER = "ultrafast";
5108
5189
  /** Apply the chosen detail to user and tool-result images after the provider assembles the request. */
5190
+ const withoutUserAgent = (headers) => headers && typeof headers === "object" ? Object.fromEntries(Object.entries(headers).filter(([name]) => name.toLowerCase() !== "user-agent")) : headers;
5109
5191
  function withInputImageDetail(payload, detail) {
5110
5192
  if (!Array.isArray(payload.input)) return payload;
5111
5193
  let changed = false;
@@ -5184,6 +5266,7 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
5184
5266
  const { temperature: _temperature, onPayload, ...rest } = options;
5185
5267
  return {
5186
5268
  ...rest,
5269
+ ...rest.headers === void 0 ? {} : { headers: withoutUserAgent(rest.headers) },
5187
5270
  ...textVerbosity === void 0 ? {} : { textVerbosity },
5188
5271
  ...serviceTier === void 0 ? {} : { serviceTier },
5189
5272
  async onPayload(payload, requestModel) {
@@ -5245,6 +5328,7 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
5245
5328
  const { temperature: _temperature, onPayload, ...rest } = options;
5246
5329
  return {
5247
5330
  ...rest,
5331
+ ...rest.headers === void 0 ? {} : { headers: withoutUserAgent(rest.headers) },
5248
5332
  async onPayload(payload, requestModel) {
5249
5333
  const { temperature: _dropped, service_tier: _tier, text: _text, ...accepted } = await onPayload?.(payload, requestModel) ?? payload;
5250
5334
  return {
@@ -5333,9 +5417,9 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
5333
5417
  });
5334
5418
  }
5335
5419
  Object.freeze([
5336
- "0.82.1",
5337
5420
  "0.85.1",
5338
- "0.87.1"
5421
+ "0.87.1",
5422
+ "1.1.0"
5339
5423
  ]);
5340
5424
  //#endregion
5341
5425
  //#region src/model-catalog.js
@@ -7835,7 +7919,7 @@ const PROVIDER = "openai-codex";
7835
7919
  const OAUTH_EXPIRY_SKEW_MS = 6e4;
7836
7920
  const CREDENTIAL_REF = dshCredentials.credentialRef("OPENAI_CODEX_SUBSCRIPTION_OAUTH");
7837
7921
  const LEGACY_CREDENTIAL_REF = dshCredentials.credentialRef("WSL043_OPENAI_CODEX_OAUTH");
7838
- const ACCOUNT_VAULT_KEY = typeof dshCredentials.credentialKey === "function" ? dshCredentials.credentialKey("codex-subscription", "accounts") : void 0;
7922
+ const ACCOUNT_VAULT_KEY = dshCredentials.credentialKey("codex-subscription", "accounts");
7839
7923
  const WEB_ENTRY_ID = "web";
7840
7924
  const DSH_SEARCH_PROVIDER_FALLBACK = "deepseek-official";
7841
7925
  const MAX_REQUEST_IMAGE_BYTES = 20 * 1024 * 1024;
@@ -7890,17 +7974,17 @@ const settingsFields = {
7890
7974
  };
7891
7975
  const Config = z.object(Object.fromEntries(Object.entries(settingsFields).map(([key, field]) => [key, field.extra("volatile", true)])));
7892
7976
  function apply(ctx, config = {}) {
7893
- const settings = createSettingsAdapter(ctx, z.object(settingsFields), config, SETTINGS_NAMESPACE);
7977
+ const settings = createSettingsAdapter(ctx, config);
7894
7978
  const searchProvider = createSearchProviderSwitcher(ctx.loader);
7895
7979
  const network = createCodexNetworkTransport();
7896
7980
  const diagnosticOperations = createDiagnosticOperations();
7897
7981
  ctx.effect(() => ctx.on?.("tools/result", (exec, result) => diagnosticOperations.tool(exec, result)), "codex-subscription: operation evidence");
7898
7982
  const originalImages = new OriginalImageStore();
7899
- const accountVault = ACCOUNT_VAULT_KEY !== void 0 && typeof ctx.credentials.readRecord === "function" && typeof ctx.credentials.modifyRecord === "function" && typeof ctx.credentials.deleteRecord === "function" ? new DshOAuthAccountVault(ctx.credentials, {
7983
+ const accountVault = new DshOAuthAccountVault(ctx.credentials, {
7900
7984
  key: ACCOUNT_VAULT_KEY,
7901
7985
  legacyRef: CREDENTIAL_REF,
7902
7986
  legacyRefs: [LEGACY_CREDENTIAL_REF]
7903
- }) : void 0;
7987
+ });
7904
7988
  const store = new DshOAuthCredentialStore(ctx.credentials, CREDENTIAL_REF, [LEGACY_CREDENTIAL_REF], {
7905
7989
  expirySkewMs: OAUTH_EXPIRY_SKEW_MS,
7906
7990
  vault: accountVault
@@ -8185,6 +8269,11 @@ function apply(ctx, config = {}) {
8185
8269
  methods: remoteBridge.methods,
8186
8270
  onClose: (_client, notify) => remoteBridge.forget(notify)
8187
8271
  });
8272
+ ctx.on("agent/assistant-stream", ({ agent, frame }) => {
8273
+ try {
8274
+ remoteBridge.onStream(agent?.session, frame);
8275
+ } catch {}
8276
+ });
8188
8277
  ctx.on("session/event", (session, event) => {
8189
8278
  try {
8190
8279
  remoteBridge.onSessionEvent(session, event);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-codex-subscription",
3
- "version": "3.0.0-beta.1",
3
+ "version": "3.0.0-beta.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",
@@ -76,25 +76,25 @@
76
76
  "node": "^22.19.0 || >=24.0.0"
77
77
  },
78
78
  "peerDependencies": {
79
- "@deepseek-ai/cordis": "4.0.1 || 4.0.2 || 4.0.3 || 4.0.4 || 4.0.5-alpha.1",
80
- "@deepseek-ai/dsh-api-remotes": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
81
- "@deepseek-ai/dsh-client-connection": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
82
- "@deepseek-ai/dsh-client-locale": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
83
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
84
- "@deepseek-ai/dsh-client-ui-model-selection": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
85
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
86
- "@deepseek-ai/dsh-client-ui-settings": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
87
- "@deepseek-ai/dsh-client-ui-slots": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
88
- "@deepseek-ai/dsh-client-ui-tool": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
89
- "@deepseek-ai/dsh-credentials": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
90
- "@deepseek-ai/dsh-llm": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
91
- "@deepseek-ai/dsh-llm-pi-ai": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
92
- "@deepseek-ai/dsh-settings": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
93
- "@deepseek-ai/dsh-subagent-codex": "0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
94
- "@deepseek-ai/dsh-tools": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
95
- "@deepseek-ai/dsh-web": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.1",
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",
96
96
  "@deepseek-ai/schemastery": "3.18.1 || ^3.18.2",
97
- "@earendil-works/pi-ai": "0.82.1 || 0.85.1 || 0.87.1",
97
+ "@earendil-works/pi-ai": "0.85.1 || 0.87.1 || 1.1.0",
98
98
  "react": "^18.2.0",
99
99
  "react-dom": "^18.2.0"
100
100
  },