dsh-deeppilot 0.9.15 → 0.9.17
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.md +5 -2
- package/README.zh-CN.md +3 -1
- package/bin/SHA256SUMS +6 -6
- package/bin/darwin-amd64/dsh-deeppilot-tunnel +0 -0
- package/bin/darwin-arm64/dsh-deeppilot-tunnel +0 -0
- package/bin/linux-amd64/dsh-deeppilot-tunnel +0 -0
- package/bin/linux-arm64/dsh-deeppilot-tunnel +0 -0
- package/bin/windows-amd64/dsh-deeppilot-tunnel.exe +0 -0
- package/bin/windows-arm64/dsh-deeppilot-tunnel.exe +0 -0
- package/docs/DSH_RELEASE_MEMORY.md +60 -0
- package/docs/NPM_PUBLISHING.md +31 -14
- package/lib/client.js +10 -79
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +140 -5
- package/lib/index.js +875 -148
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,8 +77,11 @@ Simulator or when the camera is unavailable. Switching between the LAN and
|
|
|
77
77
|
public address issues a matching new QR code and string immediately, with the
|
|
78
78
|
panel staying open.
|
|
79
79
|
|
|
80
|
-
LAN access is
|
|
81
|
-
and is TLS-only.
|
|
80
|
+
LAN access is always on (there is no switch) on the plugin's independent TCP
|
|
81
|
+
port `3098` and is TLS-only. After every connection the plugin tells the app
|
|
82
|
+
its current LAN addresses and the public Funnel address, so a paired phone
|
|
83
|
+
connects over the LAN on the same Wi-Fi and falls back to Funnel elsewhere,
|
|
84
|
+
without pairing again. The plugin generates a self-signed certificate on first start
|
|
82
85
|
(key under `$DSH_HOME/deeppilot/lan-tls/`), and the pairing QR code carries its
|
|
83
86
|
public-key fingerprint so the app pins that exact Host. DSH may continue
|
|
84
87
|
listening only on `127.0.0.1:3080`; the plugin no longer registers any `/phone`
|
package/README.zh-CN.md
CHANGED
|
@@ -64,7 +64,9 @@ DSH 重启后,打开 **设置 → DeepPilot**,开启“允许手机连接”
|
|
|
64
64
|
与证书指纹),在 App 里粘贴一次即可完成配对,适合模拟器或相机不可用时使用;在「内网 /
|
|
65
65
|
公网」之间切换会立即为所选地址生成新的二维码与配对信息,面板保持展开。
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
局域网连接始终开启(没有开关),使用插件独立的 TCP `3098` 端口,且只提供 TLS。每次连上后,
|
|
68
|
+
插件会把当前的局域网地址和公网 Funnel 地址告诉 App:同一 Wi-Fi 下手机自动走局域网,在外自动
|
|
69
|
+
改走 Funnel,不需要重新配对。插件首次启动时生成
|
|
68
70
|
自签证书(私钥位于 `$DSH_HOME/deeppilot/lan-tls/`),配对二维码携带其公钥指纹,
|
|
69
71
|
App 只信任与该指纹一致的主机。DSH 可以继续只监听 `127.0.0.1:3080`;插件不再在
|
|
70
72
|
DSH Web 服务上注册任何 `/phone` 路由。启用系统防火墙时,请仅在你使用的网络放行
|
package/bin/SHA256SUMS
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
eecc0241e0940e901c7f0bcda96945c22dcc5b24bd27349c391231d0398e50c2 ./darwin-amd64/dsh-deeppilot-tunnel
|
|
2
|
+
e834c3d5e02abe0fc459b99ba3dd4f8e9b63f9f94ade402ab8bfaf34720dea86 ./darwin-arm64/dsh-deeppilot-tunnel
|
|
3
|
+
1bcb0af171a9491566ec26f971930eb97a380f1a0db1d8dd55ee5e1fff46a9c5 ./linux-amd64/dsh-deeppilot-tunnel
|
|
4
|
+
555846f645f3bbfcf96250d4a7e981829cfaf3e1bcda8b7854cf3b74b8cc4505 ./linux-arm64/dsh-deeppilot-tunnel
|
|
5
|
+
725213a7302f325f098c6313ef38bf3a60e9b0929e4705e3f2e03e5977dca502 ./windows-amd64/dsh-deeppilot-tunnel.exe
|
|
6
|
+
90cb4018d48e7e0b637d50d7725a8c1782fc93e8775b429380a979e3a8b04887 ./windows-arm64/dsh-deeppilot-tunnel.exe
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -5,6 +5,29 @@
|
|
|
5
5
|
> move the lower bound, at each `0.x` minor boundary, or when a host inside the
|
|
6
6
|
> range breaks at runtime.
|
|
7
7
|
|
|
8
|
+
## Runtime break — image read-back since `dsh-v0.2.2-alpha.2` (2026-11-06)
|
|
9
|
+
|
|
10
|
+
- **Symptom (issue #42):** every conversation image (tool results and the
|
|
11
|
+
user's own uploads) spins forever on the phone on `0.2.2-alpha.2` through
|
|
12
|
+
`0.2.2-rc.1`; `0.2.1-rc.5` is unaffected.
|
|
13
|
+
- **Cause:** `SessionController.attachment` changed its request from
|
|
14
|
+
`{ sessionId, attachmentId }` to `{ sessionId, attachment: ImageAttachmentRef }`.
|
|
15
|
+
The host now verifies the ref's `mediaType`/`bytes`/`width`/`height` against
|
|
16
|
+
the stored file and no longer checks that the session references the image
|
|
17
|
+
(`sessionId` is a gateway scope only). The bridge still sent the old shape, so
|
|
18
|
+
`readImage(undefined)` failed and the phone got `E_NOT_FOUND`; the iOS
|
|
19
|
+
thumbnail had no failure state. Earlier audits compared method names only, so
|
|
20
|
+
this signature change was missed — audit request shapes, not just presence.
|
|
21
|
+
- **Fix (plugin, no protocol change):** `src/image-ref-index.ts` remembers the
|
|
22
|
+
full host ref for every image the bridge projects (live events, tail, history
|
|
23
|
+
pages) and, on a miss, pages back through session history (at most 20 pages of
|
|
24
|
+
500 messages). `HostBridge.attachmentData` sends `attachmentId` and
|
|
25
|
+
`attachment` together — the controller is injected directly, without schema
|
|
26
|
+
validation, so each generation reads its own field. A ref is only supplied when
|
|
27
|
+
that session projected the image, which restores the session-membership check
|
|
28
|
+
the new host dropped. `tests/dsh-api-proxy.test.ts` runs both host contracts.
|
|
29
|
+
- **Declaration:** unchanged; both generations are served.
|
|
30
|
+
|
|
8
31
|
## UI integration check — native settings controls (2026-11-05)
|
|
9
32
|
|
|
10
33
|
- **Runtime surface:** `@deepseek-ai/dsh-client-ui-primitives` is an implicit
|
|
@@ -2376,3 +2399,40 @@ release notes.
|
|
|
2376
2399
|
- **发布后核验。** 来源证明类型 `https://slsa.dev/provenance/v1`,`gitCommit` 为发布提交,工作流引用 `refs/tags/v0.9.13`,invocation 为 `40911590022`;tarball SHA1 `ca2c754e3421cddd14a795c5b4d869c5ea4b3cf9`、SHA512 与注册表一致,69 个条目、解包 131,263,175 字节。全新隔离 `DSH_HOME`(`/tmp/dsh-verify-0913`,pnpm 从 npm 安装,不是 link)在真实 `0.2.2-alpha.2` 宿主上启动,`https://127.0.0.1:3098/phone/health` 返回 200,`serverVersion` 为 `0.9.13`、`dataPlane: true`;GitHub Release 在这一步通过后才公开并标记 Latest。
|
|
2377
2400
|
- **流程变更。** 用户决定保留暂存流程;批准步骤与「工作流末尾核对在批准前必然失败」已写入 `docs/NPM_PUBLISHING.md` 与 `AGENTS.md` 发布第 4–5 步。工作流本身未改:末尾核对在 staged 版本上仍会标红,是否改成「检测到 staged 即视为成功并输出待批准」留待下次发布前决定。
|
|
2378
2401
|
- **局限。** 未做真机、Funnel 端到端、真实 `updateBundle`/HMR 回滚安装,也没有在 `0.2.1-rc.4` 上做真实业务回合;上述健康检查只证明插件能被宿主组合、启动并应答。
|
|
2402
|
+
|
|
2403
|
+
## 2026-11-07 — 插件自更新真实宿主验证:HMR 在线替换失败,禁用 HMR 后成功
|
|
2404
|
+
|
|
2405
|
+
**环境。** `dsh 0.2.2-rc.1` / Node `24.22.1` / pnpm `12.8.1`;两套独立 `DSH_HOME`(`/tmp/dsh-plugin-update-verify/` 与工作区 `.verify-plugin-update/`,web 端口 3397/3497、插件 LAN TLS 3197/3297);`dsh-deeppilot@0.9.15` 以 registry 精确 spec 安装,目标 `0.9.16`。真实 WSS 鉴权(P-256 挑战/证明)驱动 wire 帧,非内存假件。
|
|
2406
|
+
|
|
2407
|
+
**结论:能力位与查询链路通,HMR 在线替换不通。**
|
|
2408
|
+
|
|
2409
|
+
| 项目 | 实测 |
|
|
2410
|
+
|---|---|
|
|
2411
|
+
| `welcome.capabilities.pluginUpdate` | `true`(rc.1 上首次实测,此前只在 alpha.2 记过) |
|
|
2412
|
+
| `c2s.plugin.update.check` | `currentVersion 0.9.15`、`latestVersion 0.9.16`、`updateAvailable true`、`compatible true`、`protocolCompatible true`;宿主 `listVersions('dsh-deeppilot')` 真机返回 `listed`,补上 `.feature-scout/FEATURES.md:145` 的未验证项 |
|
|
2413
|
+
| `c2s.plugin.update.apply`(HMR 开启) | pnpm 成功装 0.9.16,宿主 `installBundle` 返回 `application:'failed', stage:'enable'`,触发 `restore` 装回 0.9.15;`restore` 报同一错误。两次独立复现(不同 `DSH_HOME`、不同卷、不同请求编号) |
|
|
2414
|
+
| `c2s.plugin.update.apply`(禁用 HMR) | progress → `restart-required`;profile 与磁盘变 0.9.16;重启后 health `serverVersion 0.9.16`、journal `done`(「重启后已运行目标版本,更新完成」)、`check` 返回 `currentVersion 0.9.16 / updateAvailable false`。**完整闭环成功** |
|
|
2415
|
+
|
|
2416
|
+
**根因(宿主 `updateBundle` 完整返回,见 `.verify-plugin-update/diag-updatebundle.json`)。**
|
|
2417
|
+
|
|
2418
|
+
```
|
|
2419
|
+
result.error / restore.error:
|
|
2420
|
+
code: operation-error
|
|
2421
|
+
diagnostic: dsh: warning: 1 entry did not activate
|
|
2422
|
+
deeppilot-directory-picker-browse (@deepseek-ai/dsh-host-directory-picker-browse):
|
|
2423
|
+
Error: service "directoryPicker" has been registered at <NativeDirectoryPicker>
|
|
2424
|
+
```
|
|
2425
|
+
|
|
2426
|
+
`dsh-web-app` 的 `directory-picker` 行是 `-auto`,启动时按宿主打境用 `ctx.loader.create()` 把 native 或 browse 后端挂进内存根树,disposer 异步卸载。我方 bundle 用 `disabled: true` 禁用它、再 `insert` 一个不同 id 的 `-browse` 行。`updateBundle` 有 HMR 时走 `removeBundle → installBundle`:bundle 层被移除 → `-auto` 复活并挂 `NativeDirectoryPicker` → 重新加入 bundle 时 `-browse` 注册 `directoryPicker` 撞名 → 宿主按「1 entry did not activate」把整次包操作判失败并回滚。官方 `-auto` README:40 已写明「同时挂载选择器和某个后端行会明确报错(重复的 `directoryPicker` 服务)」。CLI 覆盖安装 + 重启是全新组合、无残留,0.9.16 能正常激活,故不是包或网络问题。
|
|
2427
|
+
|
|
2428
|
+
**排除的错误修法(实测)。**
|
|
2429
|
+
|
|
2430
|
+
- 「在 patch 里覆盖 `name` 为 `-browse`」不可行:`name` 是断言不是重命名(`dsh-app-boot/lib/index.js:546`),报 `name mismatch ... skipping`。
|
|
2431
|
+
- 「删掉 picker 替换,让 `-auto` 自选」不可取:macOS 本地宿主判定 native,`c2s.directory.list` 实测返回 `E_UNSUPPORTED: directory picker unavailable`,手机端目录浏览失效。
|
|
2432
|
+
- **验证方法约束**:`updateBundle` 的 pnpm install 会从 store 重新 clone 包,手改 `node_modules/dsh-deeppilot/cordis.patch.yml` 会被还原;改 bundle patch 必须发新包才能验证。运行时代码(已加载进内存)不受此影响,故 `src/plugin-update.ts` 的修复可在隔离副本产物上真机验证。
|
|
2433
|
+
|
|
2434
|
+
**本轮代码修复(B)。** `src/plugin-update.ts` 的 `restore` 分支改为以 `listBundles()` 实际安装版本为权威,`restore.application` 降为辅助判据;`tests/plugin-update.test.ts` 同步期望并新增「实际版本未回到旧版仍判 `failed`」。单测 21 通过 / 0 失败,全量 766 通过 / 0 失败,`typecheck` 通过。真机验证:同一宿主 journal 终态由 `failed` 变为 `rolled-back`(「目标安装失败,宿主已自动恢复旧版本」)。
|
|
2435
|
+
|
|
2436
|
+
**上游渠道。** `deepseek-ai/deepseek-harness` 的 `hasIssuesEnabled=false`、`hasDiscussionsEnabled=true`;README:45 指定 bug report 走 GitHub Discussions。已按用户确认的措辞发布 [discussion #12510](https://github.com/deepseek-ai/deepseek-harness/discussions/12510)(`q-a`/`Q&A` 分类,2026-11-07,作者 `Mars-Sea`);英文正文与中文核对说明留在 [UPSTREAM_DISCUSSION-plugin-update-hmr.md](UPSTREAM_DISCUSSION-plugin-update-hmr.md),脱敏后的提交正文在 `.verify-plugin-update/discussion-body.md`。线上标题、分类与正文长度已复核。等待上游答复,不承诺修复时限。
|
|
2437
|
+
|
|
2438
|
+
**遗留。** ① 仓库 `lib/` 未重建(按用户选择只在隔离副本构建),发布前需 `npm run build` 并提交 `lib/`;② 启用 HMR 的 profile 上手机端一键更新仍会失败,需上游修复 `updateBundle` 原子性,或用户在该 profile 的 `cordis.patch.yml` 禁用 `hmr` 行(代价:配置改动不再热重载、更新后需重启);③ 真机、Funnel、无 HMR 路径在官方默认 profile 上的验收仍缺;④ `docs/技能提示对接说明.md`、`docs/移动端命令对接说明.md` 的 `dsh-plugin-manager` 清单仍是 0.2.1 口径,未重盘。
|
package/docs/NPM_PUBLISHING.md
CHANGED
|
@@ -34,12 +34,10 @@
|
|
|
34
34
|
npm 不在保存配置时验证绑定;首次发布成功才证明认证可用。
|
|
35
35
|
4. 新绑定必须在 **2 天内完成首次成功发布**。因此准备好新版本后再绑定;若过期,
|
|
36
36
|
删除过期绑定并重新创建。先验证可信发布成功,再按需调整原有令牌发布权限。
|
|
37
|
-
5.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
若要恢复直接发布,需在包设置的 Trusted Publisher 中勾选 `Allow npm publish`
|
|
42
|
-
(账户强制 2FA 时可能不可用),并同步改本节、AGENTS.md 与第 4 步的核对逻辑。
|
|
37
|
+
5. **当前绑定允许直接发布(2026-11-05 起)。** 2026-10-29 实测绑定只允许暂存发布:
|
|
38
|
+
`npm publish` 把版本送进 staged 区,需维护者 2FA 批准后才公开(见第四节第 11 条)。
|
|
39
|
+
2026-11-05 用户在 Trusted Publisher 中勾选 `Allow npm publish`,改为工作流直接公开,
|
|
40
|
+
不再需要批准;首次直接发布的结果在下一次发版时核实并记入第四节。
|
|
43
41
|
|
|
44
42
|
## 三、每次发布
|
|
45
43
|
|
|
@@ -47,7 +45,7 @@
|
|
|
47
45
|
`package-lock.json` 顶层与根包条目的版本;提交并推送,等待持续集成(CI)通过。
|
|
48
46
|
版本提交必须已经进入 `main`,且该提交包含 `publish.yml`。
|
|
49
47
|
2. 经用户授权发布该版本后,从精确的发布提交创建并推送附注标签 `v<版本>`,
|
|
50
|
-
|
|
48
|
+
按 `AGENTS.md` 发布流程第 3 步的格式(中文在前、英文在后、短标题、不硬换行)准备 GitHub 发布草稿。
|
|
51
49
|
3. 在对应标签上手动运行工作流。下例的 `0.9.5` 仅为示例,替换为已授权发布的版本:
|
|
52
50
|
|
|
53
51
|
```sh
|
|
@@ -69,13 +67,11 @@
|
|
|
69
67
|
压缩包发布跳过生命周期脚本(`--ignore-scripts`);测试、类型检查和构建已在前序
|
|
70
68
|
步骤执行,打包仍执行 `prepack`(打包前构建)。发布后核对版本、分发标签、
|
|
71
69
|
压缩包完整性和来源证明元数据。
|
|
72
|
-
6.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
`npm stage list dsh-deeppilot` → `npm stage approve <id
|
|
76
|
-
|
|
77
|
-
工作流末尾「核对发布版本、包完整性与来源证明」在批准前必然 404 失败、整次运行标红;
|
|
78
|
-
这是暂存模式的预期结果,不代表上传失败,发布证据以批准后的手工核验为准。
|
|
70
|
+
6. 发布步骤直接公开版本并写入分发标签(`latest` / `alpha`),末尾核对随即通过。
|
|
71
|
+
若核对持续 404、发布步骤提示进入 staged 区,说明绑定退回暂存模式:维护者在
|
|
72
|
+
npmjs.com 的 **Staged Packages** 标签用 2FA 批准 `dsh-deeppilot@<版本>`(或本机
|
|
73
|
+
`npm login` 后 `npm stage list dsh-deeppilot` → `npm stage approve <id>`),
|
|
74
|
+
同一版本不能重跑工作流(`E409 Cannot publish over previously staged version`)。
|
|
79
75
|
7. 确认 npm 包可安装,在全新 DSH 配置中完成安装验证后,再公开 GitHub 发布草稿。
|
|
80
76
|
工作流不自动公开发布草稿;npm 上传和发布后的核对分别记录在步骤中。
|
|
81
77
|
|
|
@@ -203,6 +199,27 @@
|
|
|
203
199
|
`/phone/health` 返回 200,`serverVersion` 为 `0.9.14`、`protocolVersion` 2、
|
|
204
200
|
`dataPlane: true`;GitHub Release 在这一步通过后才公开并标记 Latest。
|
|
205
201
|
|
|
202
|
+
13. `0.9.15` 的实际发布结果(2026-11-05):发布提交 `688dabc` 直接推到 `main`,
|
|
203
|
+
CI(运行号 `42036820848`)与 CodeQL(`42036820840`)均绿;附注标签 `v0.9.15` 指向
|
|
204
|
+
`688dabcc1b8c5f73664633750c47cb90fad1caac`。`publish.yml` 运行 `42037502337`
|
|
205
|
+
(`latest`)**整次为绿**:本次仍进入 staged 区,维护者在末尾核对的重试窗口内批准,
|
|
206
|
+
并同时勾选 `Allow npm publish`,下次发版起直接公开。注册表 `latest = 0.9.15`;
|
|
207
|
+
来源证明类型为 `https://slsa.dev/provenance/v1`、`gitCommit` 为该提交、工作流引用
|
|
208
|
+
`refs/tags/v0.9.15`、invocation 为 `42037502337`;69 个条目、解包 131,613,948 字节,
|
|
209
|
+
与本地 `npm pack --dry-run` 一致。随后在全新隔离 `DSH_HOME` 中从 npm 安装
|
|
210
|
+
`dsh-deeppilot@0.9.15`,用真实 `0.2.2-rc.1` 宿主启动:插件自有端口 `/phone/health`
|
|
211
|
+
返回 200,`serverVersion` 为 `0.9.15`、`protocolVersion` 2、`dataPlane: true`,
|
|
212
|
+
日志显示按需完成通知工具已注册;GitHub Release 在这一步通过后才公开并标记 Latest。
|
|
213
|
+
|
|
214
|
+
14. `0.9.16` 的实际发布结果(2026-11-06):PR #43 压缩合并为 `1515b7b`,`main` 上 CI(`42170870772`)、
|
|
215
|
+
CodeQL(`42170870769`)、helper 构建(`42170870802`)均绿;附注标签 `v0.9.16` 指向
|
|
216
|
+
`1515b7b7059be850e6abf15071b1a5075e5bfd27`。`publish.yml` 运行 `42171736739`(`latest`)整次为绿,
|
|
217
|
+
**首次直接公开**,未进入 staged 区。注册表 `latest = 0.9.16`,来源证明类型为
|
|
218
|
+
`https://slsa.dev/provenance/v1`;69 个条目、解包 131,743,027 字节。随后在全新隔离 `DSH_HOME` 中从 npm
|
|
219
|
+
安装 `dsh-deeppilot@0.9.16`,用真实 `0.2.2-rc.1` 宿主启动:`/phone/health` 返回 200,`serverVersion`
|
|
220
|
+
为 `0.9.16`、`protocolVersion` 2、`dataPlane: true`,补丁未写 `local.enabled` 时局域网监听照常上线;
|
|
221
|
+
GitHub Release 在这一步通过后才公开并标记 Latest。
|
|
222
|
+
|
|
206
223
|
## 五、官方资料
|
|
207
224
|
|
|
208
225
|
1. [npm 可信发布配置与限制](https://docs.npmjs.com/trusted-publishers/)
|
package/lib/client.js
CHANGED
|
@@ -572,6 +572,7 @@ window.__ModuleLoader__.load({
|
|
|
572
572
|
"system.title": "运行信息",
|
|
573
573
|
"system.description": "插件、协议与连接端点的技术信息。",
|
|
574
574
|
"local.title": "局域网连接",
|
|
575
|
+
"local.autoRoute": "局域网连接始终开启:手机和电脑在同一 Wi-Fi 下会自动走局域网,在外面自动改走公网。",
|
|
575
576
|
"local.on": "已开启:手机可通过独立端口 {port} 以 TLS 加密连接。",
|
|
576
577
|
"local.off": "已关闭:不接受局域网连接。",
|
|
577
578
|
"local.tlsFingerprint": "证书指纹",
|
|
@@ -747,7 +748,6 @@ window.__ModuleLoader__.load({
|
|
|
747
748
|
"diag.settingsUnavailable": "设置表单不可用(configForms 未提供)",
|
|
748
749
|
"diag.missingReportHook": "useDeepPilotReport hook 缺失",
|
|
749
750
|
"diag.missingEnabledHook": "useDeepPilotEnabled hook 缺失",
|
|
750
|
-
"diag.missingLocalEnabledHook": "useDeepPilotLocalEnabled hook 缺失",
|
|
751
751
|
"diag.missingLocalPortHook": "useDeepPilotLocalPort hook 缺失",
|
|
752
752
|
"diag.missingRemoteEnabledHook": "useDeepPilotRemoteEnabled hook 缺失",
|
|
753
753
|
"diag.missingRemoteLimitHook": "useDeepPilotRemoteConnectionLimit hook 缺失",
|
|
@@ -759,7 +759,6 @@ window.__ModuleLoader__.load({
|
|
|
759
759
|
"diag.missingTestRelay": "testRelay 回调缺失",
|
|
760
760
|
"diag.missingTestPush": "testPush 回调缺失",
|
|
761
761
|
"diag.missingSetEnabled": "setDeepPilotEnabled 回调缺失",
|
|
762
|
-
"diag.missingSetLocal": "setDeepPilotLocalEnabled 回调缺失",
|
|
763
762
|
"diag.missingSetLocalPort": "setDeepPilotLocalPort 回调缺失",
|
|
764
763
|
"diag.missingSetRemote": "setDeepPilotRemoteEnabled 回调缺失",
|
|
765
764
|
"diag.missingSetRemoteLimit": "setDeepPilotRemoteConnectionLimit 回调缺失",
|
|
@@ -853,6 +852,7 @@ window.__ModuleLoader__.load({
|
|
|
853
852
|
"system.title": "Runtime information",
|
|
854
853
|
"system.description": "Technical details about the plugin, protocol, and endpoints.",
|
|
855
854
|
"local.title": "LAN connection",
|
|
855
|
+
"local.autoRoute": "LAN connections are always on: on the same Wi-Fi the phone connects over the LAN automatically, and switches to the public route when away.",
|
|
856
856
|
"local.on": "On: phones connect over TLS through the independent port {port}.",
|
|
857
857
|
"local.off": "Off: LAN connections are not accepted.",
|
|
858
858
|
"local.tlsFingerprint": "Certificate fingerprint",
|
|
@@ -1028,7 +1028,6 @@ window.__ModuleLoader__.load({
|
|
|
1028
1028
|
"diag.settingsUnavailable": "Settings form unavailable (configForms not provided)",
|
|
1029
1029
|
"diag.missingReportHook": "useDeepPilotReport hook missing",
|
|
1030
1030
|
"diag.missingEnabledHook": "useDeepPilotEnabled hook missing",
|
|
1031
|
-
"diag.missingLocalEnabledHook": "useDeepPilotLocalEnabled hook missing",
|
|
1032
1031
|
"diag.missingLocalPortHook": "useDeepPilotLocalPort hook missing",
|
|
1033
1032
|
"diag.missingRemoteEnabledHook": "useDeepPilotRemoteEnabled hook missing",
|
|
1034
1033
|
"diag.missingRemoteLimitHook": "useDeepPilotRemoteConnectionLimit hook missing",
|
|
@@ -1040,7 +1039,6 @@ window.__ModuleLoader__.load({
|
|
|
1040
1039
|
"diag.missingTestRelay": "testRelay callback missing",
|
|
1041
1040
|
"diag.missingTestPush": "testPush callback missing",
|
|
1042
1041
|
"diag.missingSetEnabled": "setDeepPilotEnabled callback missing",
|
|
1043
|
-
"diag.missingSetLocal": "setDeepPilotLocalEnabled callback missing",
|
|
1044
1042
|
"diag.missingSetLocalPort": "setDeepPilotLocalPort callback missing",
|
|
1045
1043
|
"diag.missingSetRemote": "setDeepPilotRemoteEnabled callback missing",
|
|
1046
1044
|
"diag.missingSetRemoteLimit": "setDeepPilotRemoteConnectionLimit callback missing",
|
|
@@ -3917,10 +3915,6 @@ window.__ModuleLoader__.load({
|
|
|
3917
3915
|
status: "unavailable",
|
|
3918
3916
|
enabled: true
|
|
3919
3917
|
});
|
|
3920
|
-
const MISSING_LOCAL_ENABLED_HOOK = () => ({
|
|
3921
|
-
status: "unavailable",
|
|
3922
|
-
enabled: true
|
|
3923
|
-
});
|
|
3924
3918
|
const MISSING_LOCAL_PORT_HOOK = () => ({
|
|
3925
3919
|
status: "unavailable",
|
|
3926
3920
|
value: DEFAULT_LOCAL_PORT
|
|
@@ -3941,7 +3935,6 @@ window.__ModuleLoader__.load({
|
|
|
3941
3935
|
const DIAG_KEY = {
|
|
3942
3936
|
reportHook: "diag.missingReportHook",
|
|
3943
3937
|
enabledHook: "diag.missingEnabledHook",
|
|
3944
|
-
localEnabledHook: "diag.missingLocalEnabledHook",
|
|
3945
3938
|
localPortHook: "diag.missingLocalPortHook",
|
|
3946
3939
|
remoteEnabledHook: "diag.missingRemoteEnabledHook",
|
|
3947
3940
|
remoteLimitHook: "diag.missingRemoteLimitHook",
|
|
@@ -3953,7 +3946,6 @@ window.__ModuleLoader__.load({
|
|
|
3953
3946
|
testRelay: "diag.missingTestRelay",
|
|
3954
3947
|
testPush: "diag.missingTestPush",
|
|
3955
3948
|
setEnabled: "diag.missingSetEnabled",
|
|
3956
|
-
setLocal: "diag.missingSetLocal",
|
|
3957
3949
|
setLocalPort: "diag.missingSetLocalPort",
|
|
3958
3950
|
setRemote: "diag.missingSetRemote",
|
|
3959
3951
|
setRemoteLimit: "diag.missingSetRemoteLimit",
|
|
@@ -3968,7 +3960,6 @@ window.__ModuleLoader__.load({
|
|
|
3968
3960
|
["testRelay", "testRelay"],
|
|
3969
3961
|
["testPush", "testPush"],
|
|
3970
3962
|
["setEnabled", "setDeepPilotEnabled"],
|
|
3971
|
-
["setLocalEnabled", "setDeepPilotLocalEnabled"],
|
|
3972
3963
|
["setLocalPort", "setDeepPilotLocalPort"],
|
|
3973
3964
|
["setRemoteEnabled", "setDeepPilotRemoteEnabled"],
|
|
3974
3965
|
["setRemoteLimit", "setDeepPilotRemoteConnectionLimit"],
|
|
@@ -3989,7 +3980,6 @@ window.__ModuleLoader__.load({
|
|
|
3989
3980
|
const can = /* @__PURE__ */ new Set();
|
|
3990
3981
|
const useReport = isFn(source.useDeepPilotReport) ? source.useDeepPilotReport : MISSING_REPORT_HOOK;
|
|
3991
3982
|
const useEnabled = isFn(source.useDeepPilotEnabled) ? source.useDeepPilotEnabled : MISSING_ENABLED_HOOK;
|
|
3992
|
-
const useLocalEnabled = isFn(source.useDeepPilotLocalEnabled) ? source.useDeepPilotLocalEnabled : MISSING_LOCAL_ENABLED_HOOK;
|
|
3993
3983
|
const useLocalPort = isFn(source.useDeepPilotLocalPort) ? source.useDeepPilotLocalPort : MISSING_LOCAL_PORT_HOOK;
|
|
3994
3984
|
const useRemoteEnabled = isFn(source.useDeepPilotRemoteEnabled) ? source.useDeepPilotRemoteEnabled : MISSING_REMOTE_ENABLED_HOOK;
|
|
3995
3985
|
const useRemoteLimit = isFn(source.useDeepPilotRemoteConnectionLimit) ? source.useDeepPilotRemoteConnectionLimit : MISSING_REMOTE_LIMIT_HOOK;
|
|
@@ -4003,9 +3993,7 @@ window.__ModuleLoader__.load({
|
|
|
4003
3993
|
if (!isFn(source.testRelay)) diagnostics.push(t(DIAG_KEY.testRelay));
|
|
4004
3994
|
if (!isFn(source.testPush)) diagnostics.push(t(DIAG_KEY.testPush));
|
|
4005
3995
|
if (!isFn(source.setDeepPilotEnabled)) diagnostics.push(t(DIAG_KEY.setEnabled));
|
|
4006
|
-
if (!isFn(source.useDeepPilotLocalEnabled)) diagnostics.push(t(DIAG_KEY.localEnabledHook));
|
|
4007
3996
|
if (!isFn(source.useDeepPilotLocalPort)) diagnostics.push(t(DIAG_KEY.localPortHook));
|
|
4008
|
-
if (!isFn(source.setDeepPilotLocalEnabled)) diagnostics.push(t(DIAG_KEY.setLocal));
|
|
4009
3997
|
if (!isFn(source.setDeepPilotLocalPort)) diagnostics.push(t(DIAG_KEY.setLocalPort));
|
|
4010
3998
|
if (!isFn(source.useDeepPilotRemoteEnabled)) diagnostics.push(t(DIAG_KEY.remoteEnabledHook));
|
|
4011
3999
|
if (!isFn(source.setDeepPilotRemoteEnabled)) diagnostics.push(t(DIAG_KEY.setRemote));
|
|
@@ -4018,7 +4006,6 @@ window.__ModuleLoader__.load({
|
|
|
4018
4006
|
props: {
|
|
4019
4007
|
useDeepPilotReport: useReport,
|
|
4020
4008
|
useDeepPilotEnabled: useEnabled,
|
|
4021
|
-
useDeepPilotLocalEnabled: useLocalEnabled,
|
|
4022
4009
|
useDeepPilotLocalPort: useLocalPort,
|
|
4023
4010
|
useDeepPilotRemoteEnabled: useRemoteEnabled,
|
|
4024
4011
|
useDeepPilotRemoteConnectionLimit: useRemoteLimit,
|
|
@@ -4031,7 +4018,6 @@ window.__ModuleLoader__.load({
|
|
|
4031
4018
|
testRelay: isFn(source.testRelay) ? source.testRelay : void 0,
|
|
4032
4019
|
testPush: isFn(source.testPush) ? source.testPush : void 0,
|
|
4033
4020
|
setDeepPilotEnabled: isFn(source.setDeepPilotEnabled) ? source.setDeepPilotEnabled : void 0,
|
|
4034
|
-
setDeepPilotLocalEnabled: isFn(source.setDeepPilotLocalEnabled) ? source.setDeepPilotLocalEnabled : void 0,
|
|
4035
4021
|
setDeepPilotLocalPort: isFn(source.setDeepPilotLocalPort) ? source.setDeepPilotLocalPort : void 0,
|
|
4036
4022
|
setDeepPilotRemoteEnabled: isFn(source.setDeepPilotRemoteEnabled) ? source.setDeepPilotRemoteEnabled : void 0,
|
|
4037
4023
|
setDeepPilotRemoteConnectionLimit: isFn(source.setDeepPilotRemoteConnectionLimit) ? source.setDeepPilotRemoteConnectionLimit : void 0,
|
|
@@ -4388,9 +4374,6 @@ window.__ModuleLoader__.load({
|
|
|
4388
4374
|
hooks.enabled = enabledState.enabled;
|
|
4389
4375
|
hooks.switchReady = enabledState.status === "ready";
|
|
4390
4376
|
if (enabledState.status === "unavailable") diag.push(translateWith(props.t, "diag.settingsUnavailable"));
|
|
4391
|
-
const localEnabledState = props.useDeepPilotLocalEnabled((s) => s);
|
|
4392
|
-
hooks.localEnabled = localEnabledState.enabled;
|
|
4393
|
-
hooks.localSwitchReady = localEnabledState.status === "ready";
|
|
4394
4377
|
const localPortState = props.useDeepPilotLocalPort((s) => s);
|
|
4395
4378
|
hooks.localPort = localPortState.value;
|
|
4396
4379
|
hooks.localPortReady = localPortState.status === "ready";
|
|
@@ -4408,8 +4391,6 @@ window.__ModuleLoader__.load({
|
|
|
4408
4391
|
report: null,
|
|
4409
4392
|
enabled: true,
|
|
4410
4393
|
switchReady: false,
|
|
4411
|
-
localEnabled: true,
|
|
4412
|
-
localSwitchReady: false,
|
|
4413
4394
|
localPort: DEFAULT_LOCAL_PORT,
|
|
4414
4395
|
localPortReady: false,
|
|
4415
4396
|
remoteEnabled: false,
|
|
@@ -4428,8 +4409,6 @@ window.__ModuleLoader__.load({
|
|
|
4428
4409
|
const report = hooks.report;
|
|
4429
4410
|
const enabled = hooks.enabled;
|
|
4430
4411
|
const switchReady = hooks.switchReady;
|
|
4431
|
-
const localEnabled = hooks.localEnabled;
|
|
4432
|
-
const localSwitchReady = hooks.localSwitchReady;
|
|
4433
4412
|
const localPort = hooks.localPort;
|
|
4434
4413
|
const localPortReady = hooks.localPortReady;
|
|
4435
4414
|
const remoteEnabled = hooks.remoteEnabled;
|
|
@@ -4864,14 +4843,7 @@ window.__ModuleLoader__.load({
|
|
|
4864
4843
|
onChange: (next) => {
|
|
4865
4844
|
if (can("setEnabled")) props.setDeepPilotEnabled(next);
|
|
4866
4845
|
}
|
|
4867
|
-
})), (0, react.createElement)("div", { className: "pbb-channel" }, (0, react.createElement)("div", { className: "pbb-row pbb-channelRow" }, settingsIcon("wifi"), (0, react.createElement)("div", { className: "pbb-controlText" }, (0, react.createElement)("span", { className: "pbb-controlTitle" }, translateWith(props.t, "local.title")), (0, react.createElement)("div", { className: "pbb-channelState" }, (0, react.createElement)("span", { className: localMeta?.label === "online" ? "pbb-ok" : localMeta?.label === "error" ? "pbb-bad" : void 0 }, localStateText))), (0, react.createElement)(
|
|
4868
|
-
checked: localEnabled,
|
|
4869
|
-
label: translateWith(props.t, "local.title"),
|
|
4870
|
-
disabled: !localSwitchReady,
|
|
4871
|
-
onChange: (next) => {
|
|
4872
|
-
if (can("setLocalEnabled")) props.setDeepPilotLocalEnabled(next);
|
|
4873
|
-
}
|
|
4874
|
-
}), (0, react.createElement)("button", {
|
|
4846
|
+
})), (0, react.createElement)("div", { className: "pbb-channel" }, (0, react.createElement)("div", { className: "pbb-row pbb-channelRow" }, settingsIcon("wifi"), (0, react.createElement)("div", { className: "pbb-controlText" }, (0, react.createElement)("span", { className: "pbb-controlTitle" }, translateWith(props.t, "local.title")), (0, react.createElement)("div", { className: "pbb-channelState" }, (0, react.createElement)("span", { className: localMeta?.label === "online" ? "pbb-ok" : localMeta?.label === "error" ? "pbb-bad" : void 0 }, localStateText))), (0, react.createElement)("button", {
|
|
4875
4847
|
type: "button",
|
|
4876
4848
|
className: "pbb-iconButton pbb-expand",
|
|
4877
4849
|
"aria-label": translateWith(props.t, "local.options"),
|
|
@@ -4884,7 +4856,7 @@ window.__ModuleLoader__.load({
|
|
|
4884
4856
|
}, translateWith(props.t, "local.errorDetails", { message: report.local.message })) : null, report !== null && report.local.tlsIdentityRegenerated === true ? (0, react.createElement)("p", { className: "pbb-diag pbb-diagBad" }, translateWith(props.t, "local.tlsRegenerated")) : null, fold(localOptionsOpen, (0, react.createElement)("div", {
|
|
4885
4857
|
className: "pbb-channelBody",
|
|
4886
4858
|
id: localOptionsId
|
|
4887
|
-
}, report !== null && report.local.phase === "online" ? (0, react.createElement)("p", { className: "pbb-diag pbb-endpoint" }, report.local.endpoints.join(" · ")) : null, (0, react.createElement)("div", { className: "pbb-limitRow" }, (0, react.createElement)("div", { className: "pbb-controlText" }, (0, react.createElement)("label", {
|
|
4859
|
+
}, (0, react.createElement)("p", { className: "pbb-controlDescription" }, translateWith(props.t, "local.autoRoute")), report !== null && report.local.phase === "online" ? (0, react.createElement)("p", { className: "pbb-diag pbb-endpoint" }, report.local.endpoints.join(" · ")) : null, (0, react.createElement)("div", { className: "pbb-limitRow" }, (0, react.createElement)("div", { className: "pbb-controlText" }, (0, react.createElement)("label", {
|
|
4888
4860
|
className: "pbb-controlTitle",
|
|
4889
4861
|
htmlFor: "deeppilot-local-port"
|
|
4890
4862
|
}, translateWith(props.t, "local.portTitle")), (0, react.createElement)("span", { className: "pbb-controlDescription" }, translateWith(props.t, "local.portDescription")), !localPortView.valid ? (0, react.createElement)("p", { className: "pbb-diag pbb-diagBad" }, translateWith(props.t, "local.portInvalid")) : localPortDraft.message ? (0, react.createElement)("p", { className: "pbb-diag" + (localPortDraft.failed ? " pbb-diagBad" : "") }, localPortDraft.message) : null), (0, react.createElement)("div", { className: "pbb-limitControl" }, (0, react.createElement)("input", {
|
|
@@ -5309,19 +5281,10 @@ window.__ModuleLoader__.load({
|
|
|
5309
5281
|
if (snap?.status === "ready" && snap.value !== void 0) return snap.value.enabled !== false;
|
|
5310
5282
|
return enabledStore.getSnapshot().enabled;
|
|
5311
5283
|
};
|
|
5312
|
-
const localEnabledStore = createSnapshotStore({
|
|
5313
|
-
status: "loading",
|
|
5314
|
-
enabled: true
|
|
5315
|
-
});
|
|
5316
5284
|
const localPortStore = createSnapshotStore({
|
|
5317
5285
|
status: "loading",
|
|
5318
5286
|
value: DEFAULT_LOCAL_PORT
|
|
5319
5287
|
});
|
|
5320
|
-
const lastConfirmedLocalEnabled = () => {
|
|
5321
|
-
const snap = scope?.getSnapshot();
|
|
5322
|
-
if (snap?.status === "ready") return snap.value?.local?.enabled !== false;
|
|
5323
|
-
return localEnabledStore.getSnapshot().enabled;
|
|
5324
|
-
};
|
|
5325
5288
|
const lastConfirmedLocalPort = () => {
|
|
5326
5289
|
const snap = scope?.getSnapshot();
|
|
5327
5290
|
if (snap?.status === "ready") return normalizeLocalPort(snap.value?.local?.port);
|
|
@@ -5356,46 +5319,16 @@ window.__ModuleLoader__.load({
|
|
|
5356
5319
|
const adoptLocal = () => {
|
|
5357
5320
|
if (scope === void 0) return;
|
|
5358
5321
|
const snap = scope.getSnapshot();
|
|
5359
|
-
if (snap.status === "ready") {
|
|
5360
|
-
localEnabledStore.set({
|
|
5361
|
-
status: "ready",
|
|
5362
|
-
enabled: snap.value?.local?.enabled !== false
|
|
5363
|
-
});
|
|
5364
|
-
localPortStore.set({
|
|
5365
|
-
status: "ready",
|
|
5366
|
-
value: normalizeLocalPort(snap.value?.local?.port)
|
|
5367
|
-
});
|
|
5368
|
-
} else if (snap.status === "unavailable") {
|
|
5369
|
-
localEnabledStore.set({
|
|
5370
|
-
status: "unavailable",
|
|
5371
|
-
enabled: true
|
|
5372
|
-
});
|
|
5373
|
-
localPortStore.set({
|
|
5374
|
-
status: "unavailable",
|
|
5375
|
-
value: DEFAULT_LOCAL_PORT
|
|
5376
|
-
});
|
|
5377
|
-
}
|
|
5378
|
-
};
|
|
5379
|
-
scopeAdoptions.push(adoptLocal);
|
|
5380
|
-
const setDeepPilotLocalEnabled = (value) => {
|
|
5381
|
-
const previous = lastConfirmedLocalEnabled();
|
|
5382
|
-
localEnabledStore.set({
|
|
5322
|
+
if (snap.status === "ready") localPortStore.set({
|
|
5383
5323
|
status: "ready",
|
|
5384
|
-
|
|
5324
|
+
value: normalizeLocalPort(snap.value?.local?.port)
|
|
5385
5325
|
});
|
|
5386
|
-
if (
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
...currentLocal,
|
|
5390
|
-
enabled: value
|
|
5391
|
-
}).then(() => {}, (error) => {
|
|
5392
|
-
localEnabledStore.set({
|
|
5393
|
-
status: "ready",
|
|
5394
|
-
enabled: previous
|
|
5395
|
-
});
|
|
5396
|
-
console.error("[deeppilot] failed to persist local.enabled=" + String(value) + ": " + (error instanceof Error ? error.message : String(error)));
|
|
5326
|
+
else if (snap.status === "unavailable") localPortStore.set({
|
|
5327
|
+
status: "unavailable",
|
|
5328
|
+
value: DEFAULT_LOCAL_PORT
|
|
5397
5329
|
});
|
|
5398
5330
|
};
|
|
5331
|
+
scopeAdoptions.push(adoptLocal);
|
|
5399
5332
|
const setDeepPilotLocalPort = async (value) => {
|
|
5400
5333
|
const next = normalizeLocalPort(value);
|
|
5401
5334
|
if (next !== value) throw new RangeError("local port must be an integer between 1024 and 65535");
|
|
@@ -5570,7 +5503,6 @@ window.__ModuleLoader__.load({
|
|
|
5570
5503
|
hooks: {
|
|
5571
5504
|
deepPilotReport: store,
|
|
5572
5505
|
deepPilotEnabled: enabledStore,
|
|
5573
|
-
deepPilotLocalEnabled: localEnabledStore,
|
|
5574
5506
|
deepPilotLocalPort: localPortStore,
|
|
5575
5507
|
deepPilotRemoteEnabled: remoteEnabledStore,
|
|
5576
5508
|
deepPilotRemoteConnectionLimit: remoteConnectionLimitStore,
|
|
@@ -5585,7 +5517,6 @@ window.__ModuleLoader__.load({
|
|
|
5585
5517
|
testRelay: testRelayConnection,
|
|
5586
5518
|
testPush: sendTestPush,
|
|
5587
5519
|
setDeepPilotEnabled,
|
|
5588
|
-
setDeepPilotLocalEnabled,
|
|
5589
5520
|
setDeepPilotLocalPort,
|
|
5590
5521
|
setDeepPilotRemoteEnabled,
|
|
5591
5522
|
setDeepPilotRemoteConnectionLimit,
|