dsh-plugin-dshm 0.1.0 → 0.1.1
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/CHANGELOG.md +11 -0
- package/README.md +13 -9
- package/README.zh-CN.md +11 -7
- package/lib/projection/compatibility.d.mts +2 -0
- package/lib/projection/compatibility.mjs +4 -0
- package/lib/projection/native.d.ts +1 -0
- package/lib/projection/native.js +17 -5
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.1 — Unreleased
|
|
4
|
+
|
|
5
|
+
- Support DSH 0.2.1-rc.5 (npm latest verified 2026-10-30), retaining exact
|
|
6
|
+
support for 0.2.1-rc.3. Other prereleases and future versions remain blocked.
|
|
7
|
+
- Include the previously verified task-032 interaction-status correction:
|
|
8
|
+
concurrent read/correlation timeouts publish the native running/idle fallback
|
|
9
|
+
and its warning before returning a session snapshot.
|
|
10
|
+
- Native macOS integration covers approvals/questions, reconnects, transfers,
|
|
11
|
+
path policy and restart. Windows verification of this new combination is
|
|
12
|
+
pending; no new Windows compatibility result is claimed.
|
|
13
|
+
|
|
3
14
|
## 0.1.0 — 2026-10-28
|
|
4
15
|
|
|
5
16
|
Initial DSHM bridge release for DeepSeek Harness 0.2.1-rc.3.
|
package/README.md
CHANGED
|
@@ -8,9 +8,10 @@ your paired device over your local network or your own VPN.
|
|
|
8
8
|
|
|
9
9
|
## Requirements and compatibility
|
|
10
10
|
|
|
11
|
-
- DeepSeek Harness **0.2.1-rc.3
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
- DeepSeek Harness **0.2.1-rc.3 or 0.2.1-rc.5**. Plugin 0.1.1 adds support for
|
|
12
|
+
**0.2.1-rc.5**, the npm `latest` release verified on 2026-10-30. These are
|
|
13
|
+
exact tested versions; other releases, including the separate 0.2.2 alpha
|
|
14
|
+
channel, are not automatically compatible.
|
|
14
15
|
- A running DSH desktop app or `dsh web` on your computer, and a compatible DSHM
|
|
15
16
|
iPhone/iPad build. This npm package does not install the iOS app.
|
|
16
17
|
- Node 24 or later in the DSH runtime, and `openssl` on its PATH for the initial
|
|
@@ -19,9 +20,10 @@ your paired device over your local network or your own VPN.
|
|
|
19
20
|
connected VPN such as Tailscale.
|
|
20
21
|
|
|
21
22
|
The bridge has been exercised with DSH 0.2.1-rc.3 on macOS, including the desktop
|
|
22
|
-
app and isolated `dsh web`.
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
app and isolated `dsh web`. Plugin 0.1.1 is also tested against real DSH
|
|
24
|
+
0.2.1-rc.5 in isolated `dsh web`, including approvals, reconnects, file transfers,
|
|
25
|
+
path restrictions and restart. The new 0.1.1 / rc.5 combination still needs a
|
|
26
|
+
Windows native check; macOS results do not substitute for Windows verification. Physical-phone network acceptance is also separate from
|
|
25
27
|
the local test-client and Simulator results. Mainland China is outside the v1
|
|
26
28
|
release scope; mainland network reachability is not claimed.
|
|
27
29
|
|
|
@@ -190,8 +192,10 @@ credentials/session directories. Uninstall does not remove your DSH sessions.
|
|
|
190
192
|
|
|
191
193
|
## New DSH release checklist (maintainers)
|
|
192
194
|
|
|
193
|
-
1.
|
|
194
|
-
|
|
195
|
+
1. Review upstream DSH changes, especially the projection APIs and bundle
|
|
196
|
+
loader. In an unpublished candidate, update the explicit runtime allowlist
|
|
197
|
+
and `engines.dsh` together so DSH can install it for isolated verification.
|
|
198
|
+
Do not publish or claim support before the following tests pass.
|
|
195
199
|
2. Install the candidate DSH runtime through its normal distribution and run
|
|
196
200
|
`pnpm -C bridge test:integration` against it in the isolated `.dsh-test` home.
|
|
197
201
|
Review the explicit runtime version guard in `bridge/src/projection/native.ts`
|
|
@@ -203,7 +207,7 @@ credentials/session directories. Uninstall does not remove your DSH sessions.
|
|
|
203
207
|
3. Run `pnpm -C bridge test`, `pnpm -C protocol validate` and
|
|
204
208
|
`pnpm -C protocol gen:check`. Fix compatibility changes only inside the
|
|
205
209
|
appropriate boundary and review the results.
|
|
206
|
-
4. **Only after the real-DSH suite passes**,
|
|
210
|
+
4. **Only after the real-DSH suite passes**, finalize `engines.dsh` as the explicit
|
|
207
211
|
tested versions/range. Never assume an entire future minor release is safe.
|
|
208
212
|
Update the tested range in `tools/release-plugin/check-release.mjs` with the
|
|
209
213
|
recorded evidence, keeping it aligned with the runtime compatibility guard.
|
package/README.zh-CN.md
CHANGED
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
## 环境与兼容性
|
|
9
9
|
|
|
10
|
-
- DeepSeek Harness **0.2.1-rc.3
|
|
11
|
-
|
|
10
|
+
- DeepSeek Harness **0.2.1-rc.3 或 0.2.1-rc.5**。插件 0.1.1 新增对
|
|
11
|
+
**0.2.1-rc.5** 的支持,这是 2026-10-30 验证的 npm `latest` 版本。
|
|
12
|
+
仅支持这些已测试的精确版本;其他版本(包括独立的 0.2.2 alpha 通道)
|
|
13
|
+
不会自动视为兼容。
|
|
12
14
|
- 电脑正在运行 DSH 桌面应用或 `dsh web`,手机或平板已安装兼容的 DSHM
|
|
13
15
|
构建版本。这个 npm 包不会安装 iOS 应用。
|
|
14
16
|
- DSH 运行环境使用 Node 24 或更新版本,且 PATH 中有 `openssl`,供首次
|
|
@@ -16,8 +18,9 @@
|
|
|
16
18
|
- 两台设备之间能够直接通信,或已连接到你自己的 Tailscale 等 VPN。
|
|
17
19
|
|
|
18
20
|
目前已在 macOS 上使用 DSH 0.2.1-rc.3 验证桌面应用及隔离的 `dsh web`。
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
插件 0.1.1 还在真实 DSH 0.2.1-rc.5 的隔离 `dsh web` 中通过了审批、重连、
|
|
22
|
+
文件传输、路径限制及重启测试。新的 0.1.1 / rc.5 组合仍需 Windows 原生验证;
|
|
23
|
+
macOS 通过的测试不能代替 Windows 验证。真实手机的网络测试也与本地测试客户端、
|
|
21
24
|
Simulator 的结果分别记录。v1 不包含中国大陆市场,也不声明已验证大陆网络可达性。
|
|
22
25
|
|
|
23
26
|
## 在 DSH 中安装
|
|
@@ -158,8 +161,9 @@ APNs 已经接收的通知无法撤回。终端输出仍仅供查看;桥接插
|
|
|
158
161
|
|
|
159
162
|
## 新 DSH 版本发布检查清单(维护者)
|
|
160
163
|
|
|
161
|
-
1.
|
|
162
|
-
|
|
164
|
+
1. 先阅读上游改动,尤其是 projection 接口和插件加载器。在尚未发布的候选包中,
|
|
165
|
+
同步更新显式运行时允许列表及 `engines.dsh`,以便通过 DSH 安装并进行隔离
|
|
166
|
+
验证。以下测试通过前,不发布该包,也不对外声明支持新版本。
|
|
163
167
|
2. 通过 DSH 的正常发布渠道安装候选运行时,在隔离的 `.dsh-test` home 中对
|
|
164
168
|
**该候选版本**运行 `pnpm -C bridge test:integration`。兼容性改动必须同时
|
|
165
169
|
审查 `bridge/src/projection/native.ts` 中的显式运行时版本保护;只改包元数据
|
|
@@ -168,7 +172,7 @@ APNs 已经接收的通知无法撤回。终端输出仍仅供查看;桥接插
|
|
|
168
172
|
记录实际版本和结果;声明新的 Windows 组合已支持前,完成 Windows 清单。
|
|
169
173
|
3. 运行 `pnpm -C bridge test`、`pnpm -C protocol validate` 和
|
|
170
174
|
`pnpm -C protocol gen:check`。在正确的架构边界内修复兼容性问题并审查结果。
|
|
171
|
-
4. **只有真实 DSH
|
|
175
|
+
4. **只有真实 DSH 集成测试通过后**,才最终确定 `engines.dsh` 中明确验证过的
|
|
172
176
|
版本或范围。不要假定未来整个小版本都兼容。根据实际验证记录,更新
|
|
173
177
|
`tools/release-plugin/check-release.mjs` 中的已测试范围,并与运行时版本保护
|
|
174
178
|
保持一致。从 `bridge/package.json`
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Enumerate verified carriers; a future prerelease is not implicitly compatible.
|
|
2
|
+
// Keep package metadata and the release gate aligned with the native test receipt.
|
|
3
|
+
export const supportedDSHVersions = Object.freeze(['0.2.1-rc.3', '0.2.1-rc.5']);
|
|
4
|
+
export const supportsDSH = version => supportedDSHVersions.includes(version);
|
|
@@ -87,6 +87,7 @@ export declare class LivePeer implements ProjectionPeer {
|
|
|
87
87
|
private accept;
|
|
88
88
|
private waitForProjection;
|
|
89
89
|
private expireMissingInteractions;
|
|
90
|
+
private warnUnidentifiedInteraction;
|
|
90
91
|
private interactionsReady;
|
|
91
92
|
private loadChanges;
|
|
92
93
|
private acceptNative;
|
package/lib/projection/native.js
CHANGED
|
@@ -5,6 +5,7 @@ import { dirname, resolve } from 'node:path';
|
|
|
5
5
|
import { homedir } from 'node:os';
|
|
6
6
|
import { createProjectionFold } from './fold-recording.mjs';
|
|
7
7
|
import { FileProjection } from './files.js';
|
|
8
|
+
import { supportsDSH } from './compatibility.mjs';
|
|
8
9
|
import { interactionIdentity, expectedInteractionIds } from './interactions.js';
|
|
9
10
|
const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
10
11
|
const array = (value) => Array.isArray(value) ? value : [];
|
|
@@ -82,7 +83,7 @@ export function createProjectionHost(context) {
|
|
|
82
83
|
}
|
|
83
84
|
catch { /* The bundle may not run under a DSH CLI carrier. */ }
|
|
84
85
|
}
|
|
85
|
-
const status = version
|
|
86
|
+
const status = supportsDSH(version) ? 'ok' : 'incompatible';
|
|
86
87
|
const diagnostics = { createdPeers: 0, disposedPeers: 0, activePeers: 0 };
|
|
87
88
|
const peers = new Set();
|
|
88
89
|
const attachments = new Map();
|
|
@@ -259,7 +260,8 @@ export class LivePeer {
|
|
|
259
260
|
const state = await this.ensure(sessionId);
|
|
260
261
|
const request = object(frame.request);
|
|
261
262
|
const nativeId = string(frame.eventId);
|
|
262
|
-
|
|
263
|
+
const kind = frame.event === 'approval/request' ? 'approval' : 'question';
|
|
264
|
+
state.identifying.set(nativeId, kind);
|
|
263
265
|
let identity;
|
|
264
266
|
try {
|
|
265
267
|
identity = await this.waitForProjection(state, () => interactionIdentity(sessionId, string(frame.event), request, state.records));
|
|
@@ -274,7 +276,7 @@ export class LivePeer {
|
|
|
274
276
|
}
|
|
275
277
|
if (!identity) {
|
|
276
278
|
this.expireMissingInteractions(state);
|
|
277
|
-
this.
|
|
279
|
+
this.warnUnidentifiedInteraction(state, kind);
|
|
278
280
|
return;
|
|
279
281
|
}
|
|
280
282
|
const { id, callId } = identity;
|
|
@@ -405,13 +407,23 @@ export class LivePeer {
|
|
|
405
407
|
if (ids.length)
|
|
406
408
|
this.accept(state, { source: 'interaction-expire', frame: { ids, status: this.summary(this.nativeSummaries.get(state.id) ?? { sessionId: state.id }).status }, atMs: 0 });
|
|
407
409
|
}
|
|
410
|
+
warnUnidentifiedInteraction(state, kind) {
|
|
411
|
+
this.accept(state, { source: 'interaction-warning', frame: { kind, status: this.summary(this.nativeSummaries.get(state.id) ?? { sessionId: state.id }).status }, atMs: 0 });
|
|
412
|
+
}
|
|
408
413
|
async interactionsReady(state, signal, deadline = Date.now() + 2000) {
|
|
409
414
|
const ready = await this.waitForProjection(state, () => state.followReady && !state.identifying.size &&
|
|
410
415
|
expectedInteractionIds(state.id, state.records).every(id => this.deliveries.has(id) || state.expiredInteractions.has(id)) ? true : undefined, signal, deadline);
|
|
411
416
|
// A durable audit can outlive its native waterfall after a crash. Keep the
|
|
412
417
|
// session readable, but never present an unanswerable row as live.
|
|
413
|
-
if (!ready)
|
|
418
|
+
if (!ready) {
|
|
414
419
|
this.expireMissingInteractions(state);
|
|
420
|
+
// The read deadline can settle before the correlation callback. Publish
|
|
421
|
+
// the fallback now so its snapshot cannot retain stale running state or
|
|
422
|
+
// omit the warning. The later callback may still identify a valid delivery.
|
|
423
|
+
const kind = state.identifying.values().next().value;
|
|
424
|
+
if (kind)
|
|
425
|
+
this.warnUnidentifiedInteraction(state, kind);
|
|
426
|
+
}
|
|
415
427
|
}
|
|
416
428
|
async loadChanges(state, seq) {
|
|
417
429
|
const url = new URL('http://localhost/api/changes.summary');
|
|
@@ -458,7 +470,7 @@ export class LivePeer {
|
|
|
458
470
|
if (!native)
|
|
459
471
|
throw fault('not-found');
|
|
460
472
|
const metadata = { live: true, scenario: 'live', sessionId: id, title: null, recordedAt: iso(native.updatedAt), summary: this.summary(native), cwd: native.cwd };
|
|
461
|
-
const state = { id, metadata, fold: createProjectionFold(metadata), records: [], nativeSeq: -1, listeners: new Set(), ready: Promise.resolve(), followReady: false, cancel: new AbortController(), changed: new Set(), identifying: new
|
|
473
|
+
const state = { id, metadata, fold: createProjectionFold(metadata), records: [], nativeSeq: -1, listeners: new Set(), ready: Promise.resolve(), followReady: false, cancel: new AbortController(), changed: new Set(), identifying: new Map(), expiredInteractions: new Set() };
|
|
462
474
|
this.lifetime.signal.addEventListener('abort', () => state.cancel.abort(), { once: true });
|
|
463
475
|
this.sessions.set(id, state);
|
|
464
476
|
state.ready = this.startStream('session/follow', { request: { address: { kind: 'session', sessionId: id }, assistantStream: true, maxMessages: 200 } }, async (frame) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-dshm",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Pair your iPhone or iPad with DeepSeek Harness over a private, authenticated connection",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
],
|
|
32
32
|
"engines": {
|
|
33
33
|
"node": ">=24",
|
|
34
|
-
"dsh": "0.2.1-rc.3"
|
|
34
|
+
"dsh": "0.2.1-rc.3 || 0.2.1-rc.5"
|
|
35
35
|
},
|
|
36
36
|
"dsh": {
|
|
37
37
|
"bundle": {
|