dsh-cherry-bridge 0.1.11 → 0.2.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.
@@ -46,6 +46,11 @@
46
46
  **权威来源**;实时 `interaction.updated` 流是**加速器/保鲜器**——它让插件不必为每张卡都
47
47
  回查一次,但**不保证**送达,也不构成资格依据。任何一张卡都必须仅凭 list 快照可应答。
48
48
 
49
+ **上游实证**:2.1.9 之前,桌面的通知发送链会被一次失败**永久毒死**——`RemoteConnection.send()`
50
+ 把可 rejected 的 Promise 直接存回链头,此后该连接上的 `interaction.updated` 等通知静默停发,
51
+ 而请求-应答不受影响(应答不走这条链)。2.1.9 由 PR #22593 修复。这就是「实时流只是加速器、
52
+ list 快照才是权威」的实证来源:一条健康的连接随时可能不再推送任何通知。
53
+
49
54
  **手动核验步骤**(与 `CONTRACT_DIFFERENCES[1].checklistStep` 同源):
50
55
 
51
56
  - [ ] approval-card-not-realtime: trigger a tool call on the real desktop that raises an approval card; confirm `cherry_interactions` finds it through `agent.interactions.list` even when no `interaction.updated` event arrived, and that `cherry_respond` still accepts the listed snapshot.
@@ -159,6 +164,14 @@ schema 已允许 `interrupted`,所以客户端**必须**处理,但当前服
159
164
  - [ ] 设置页同时渲染两张设备卡片,状态灯随各自连接独立变化。
160
165
  - [ ] 停用其中一台 → 该设备转 `disabled` 且套接字被断开;再启用 → 从档案重建连接。
161
166
  - [ ] `cherry_unpair` 移除一台 → 另一台连接与订阅不受影响。
167
+ - [ ] 设置页「忘记 / 恢复」:对某台设备的一个候选地址点「**忘记**」→ 该地址从「地址」行消失、
168
+ 出现在「**已忘记地址**」行;`GET /devices` 的 `forgottenHosts` 含它,且**重启桌面或重连后
169
+ 该地址不会被自动学回来**(`cherry_devices` 的 `action: "forget"` 是同一个写入)。
170
+ 点「**恢复**」→ 标记消失,桌面下次广播该地址时重新加入;只剩最后一个候选地址时点「忘记」
171
+ → 页面显示「不能忘记最后一个候选地址」而**不是** `last-address:` 前缀的服务端原文。
172
+ 另外核一条**冻结**规则:打开「地址维护」后,卡片上的「忘记 / 恢复」应变为**不可点**——那是
173
+ 因为该表单整体替换 `hosts`,它的草稿不会被卡片重新播种,编辑器开着时点「忘记」会被下一次
174
+ 「保存地址」连同标记一起覆盖掉;关掉编辑器即恢复可点。
162
175
 
163
176
  ### F. 工具启用范围(`/scope`)
164
177
 
@@ -269,8 +282,8 @@ http://127.0.0.1:23023/cherry-remote/api/scope`(宿主换过端口就换端口
269
282
  - [ ] 该端点同样受信任 fence 约束:非回环 Host、非同源 Origin、`sec-fetch-site: cross-site`
270
283
  一律 403;无 Origin 的非浏览器客户端放行。
271
284
  - [ ] 全流程日志不含 token / invitationSecret / accessToken / 消息文本 / part 文本。
272
- - [ ] **上游版本核验**(桌面端为 2.1.4–2.1.6 或已比对过的更新版本;依据见 README
273
- 「与 Cherry Studio 版本的对应关系」):
285
+ - [ ] **上游版本核验**(桌面端为 2.1.4–2.1.10 或已比对过的更新版本;依据见
286
+ src/AGENTS.md「Protocol basis」):
274
287
  - [ ] 桌面端**升级后无需重新配对**:设备档案直接连上,`desktopIdentity` 未变。
275
288
  - [ ] 桌面端为 2.1.5+ 且会话里有**来自手机上传的附件**时:该 part 为 `kind:"file"`
276
289
  并带 `name`/`mediaType`/`byteLength`,`content` 为空,且**没有**任何
@@ -284,8 +297,43 @@ http://127.0.0.1:23023/cherry-remote/api/scope`(宿主换过端口就换端口
284
297
  `data` part(任务事件等)不是附件,原样透传。
285
298
  - [ ] `cherry_send` 传空白文本(如 `" "`)→ 本地返回 `text-empty`,对端未收到
286
299
  `agent.messages.send`。
300
+ - [ ] 桌面端为 2.1.8+ 且 hello 广播了 `agentMessageSummariesVersion: 1` 时:
301
+ `GET /cherry-remote/api/diagnostics` 顶层出现 `messageSummaries: 1`,且一次
302
+ `cherry_read` 正常返回消息与 parts(消息行走分页摘要,请求带 `partsMode:"paged"`,
303
+ part 经 `agent.parts.list` 按 messageId + revision 枚举)。桌面端未广播时该字段
304
+ **不出现**,读路径回落到字节安全的分页尺寸。
287
305
  - [ ] 桌面端广播了本插件不认识的支持字段时,`cherry_devices` 的 limits 投影仍只有
288
306
  4 个已知键(heartbeatMs/subscriptions/pageItems/inFlightRequests),连接不被拒。
289
307
  - [ ] `package.json` 中 `@cherrystudio/remote-protocol`、`@cherrystudio/remote-transport`
290
308
  为精确版本(无 `^`)。
291
309
  - [ ] `npm test` 全绿(含 `tests/contract/contract.test.ts`)。
310
+
311
+ ---
312
+
313
+ ## 第四部分:机器可验证项实测记录
314
+
315
+ A–G 各节要真人 + Electron 端批准,无法被 CI 化;下表只记录其中**不需要人工点击、agent
316
+ 在本机就能断言**的那部分,用于跨版本比对「哪些已经被证过」。带勾选框的条目仍是唯一判据。
317
+
318
+ ### 0.2.0(2026-10-27 · DSH profile `web` · 桌面端 ISV-ZYX 2.1.8)
319
+
320
+ | 项 | 结果 | 观测 |
321
+ | --- | --- | --- |
322
+ | 装机生效 | 通过 | 包 mtime `18:49:52` 早于宿主 PID 1 启动 `18:50:00`;装机 `dist/index.mjs`、`dist/index.d.mts`、`lib/client.js`、`locale/zh.json` 与发行 tarball sha256 全同 |
323
+ | 设备档案迁移 `schemaVersion` 2→4 | 通过 | `devices.json` 为 `schemaVersion: 4`,逐设备 `security` / `ports` 两个映射就位;设备**未重新配对**,重启后自行连上 |
324
+ | `GET /cherry-remote/api/devices` 新字段 | 通过 | 返回 `security` 与 `ports`(0.1.11 没有这两个键) |
325
+ | 分页摘要能力 | 通过 | `GET …/diagnostics` 顶层 `messageSummaries: 1`;`cherry_read` 正常返回历史会话,parts 由 `agent.parts.list` 回填 |
326
+ | 坏 pin 解析期拒绝(#153) | 通过 | `desktopIdentity: "not-a-peer-id"` → `invalid-payload`/`payload field "desktopIdentity" is not a peer id`;`connections`/`sockets`/`connectionsBuilt` 保持 1/1/1,设备数不变,**零 socket** |
327
+ | 失败分型 + 裁决有界(#142 / #148) | 通过 | 3 个 193 字符主机 → `unreachable`,每段形如 `…:9400: websocket: getaddrinfo ENOTFOUND … (+147 chars)`:分型在、端口保留、段 ≤240 |
328
+ | 进度行有界(#152) | 通过 | 宿主日志 `pairing stage validate (hosts: h0.… (+2 more))` 整行 251 字符 |
329
+
330
+ **本轮未覆盖**(环境不可达,**不是通过**):
331
+
332
+ - **#141 拨号总预算**:需要黑洞地址让每次拨号烧满 `connectTimeoutMs`,实测要挂满 30 s;
333
+ 由集成测试的 `dialBudgetMs: 0` 用例覆盖(断言 `connectionCount === 0` 且每个候选各出现一次)。
334
+ - **#133 `wsTls`**:被测环境是内网 `ws://`、没有 TLS 前置,配置该键只会被忽略;由
335
+ `tests/helpers/tls/dualPeer.ts` 的自签 TLS 握手用例覆盖。
336
+ - **#140 设置页 per-host 端口行**:该行**仅在**各主机端口与记录级 `port` 不一致时渲染,
337
+ 被测设备是单主机同端口;需要造一条混合端口记录才能走。
338
+ - **#161 `failureText`**:要制造一个 peer 可达的 caught failure(如 ack 失败)才会出现,
339
+ 本轮 `recentErrors` 为空。