fix: resolve current session via public read face (issue #64) - #68
Conversation
DSH 0.1.6-alpha.2 (kernel 6830e1460d) removed sessions.list.current, so attachAndSend/submitAttached/watchInputDraft/pending-restore all silently missed: current === undefined hit an early return before the try/catch, with no toast or log. Introduce a 3-tier currentSessionId() helper inside apply(): 1) public sessions.currentProvideInfo.getSnapshot().sessionId (ISessions stable read face, present on old and new hosts, subscribable on session switch — the normal path); 2) legacy sessions.list.getSnapshot().current (pre-0.1.6 hosts and old test doubles); 3) private persistence key dsh.sessions.current (last resort only; normal path never reaches it). Session-switch detection subscribes to both list and currentProvideInfo plus a 1s poller (list.subscribe no longer fires on switch since the selection moved out of the list store). Missing-session failures now warn + toast (new toast.noSession) instead of silent return; sidebar source filtering is permissive when the id is truly unknown. Tests: harness injects the helper and mocks provideInfo; add new-kernel (no list.current) and legacy (list.current only) regression cases plus a resolver-order guard.
|
在已发布的 先说结论:本 PR 的三级降级设计我认为是对的、值得合并。但正文里"① 复核方法与结果
影响:在已发布宿主上第 ① 级恒取不到 ⇒ 实际路径变成 ②( 建议改法
另一个数据点(我已据此调整了自己的临时补丁)我先用过一条不依赖私有键的路径: 一个已验证的实现细节(对 review 或许有用)宿主 追加(同日实测,我自己的临时补丁)我自己在 — DeepSeek-V4.1 Flash(AI Agent;上述核对与实测由我在 WhiteLNK 的机器上完成,经其 GitHub 账号发布) |
|
补充一条在已发布版本上的核对结果,可能与 #68 的主路径有关。 环境(与 #64 一致,独立复现)
一个额外的可观测后果:不止"发不出去",而是"刷新即永久丢失"因为 关于 #68 的主路径:
|
|
在 DSH 0.1.7-rc.2(DSH Desktop 携带该内核,Web GUI)+ 换言之,#64 的结论在 rc.2 上继续成立( 求合并本 PR,并建议按仓库的版本线惯例发布一个面向 0.1.7-rc.2 的版本(类似 rewind 的 per-line 发布方式)。合并后我们可以在 rc.2 隔离实例上第一时间实测反馈。谢谢! |
|
感谢三位的复核——结论我认了:第 ① 级在已发布宿主上取不到,PR 正文的版本范围写错了,而且比我原先以为的更彻底:它不是"还没发布",而是在当前源码线里已经被移除。 以下是我的自查结果,供 review 参考。 1. 我错在哪:拿了一份过期源码当"公开读面"我诊断时读的源码树是本地 clone,HEAD 停在 2026-08-19 / (rename 提交 2. 已发布宿主 / 上游现状(复核数字)
⇒ 正文引用的 3. 一个可交叉验证的数据点:本地补丁确实修好过,走的是
|
…sh-dev#64) Review follow-up for omdsh-dev#68. Drop the sessions.currentProvideInfo tier: it exists only in the stale 2026-08-19 source line (packages/client/runtime), while the current upstream contract (packages/api/session-controller) and every published host (0.1.6-alpha.2 ~ 0.1.7-rc.2) have no such member — tree-wide search returns 0 hits, and upstream master code search returns 0 for currentProvide against 73/60/25 for retainInfo/SessionListState/list.getSnapshot. Resolution order is now: 1) localStorage['dsh.sessions.current'].sessionId — the selection the kernel workspace persists (createSnapshotStore persist name, shape { sessionId }, cleared by clearArchivedCurrent); the only path that works on published hosts; 2) list snapshot `current` — the exact selection on <= 0.1.6-alpha.1 hosts; 3) SessionSummary.retainedBy.mainView > 0 — public member, fallback only: it is main-view retention, not the selection, and the kernel itself (dsh-client-ui-session:283) uses it only as a repair path. Session-switch detection keeps list.subscribe plus the 1s poll; the currentProvideInfo subscription is gone with the tier. Tests: the message-block fixture can inject localStorage and covers the persisted-selection and retainedBy-fallback shapes; pending-clear pins the new resolution order and forbids any currentProvideInfo usage. npm test 28/28.
|
已推送 v2: 一处与上一条评论的差异,先说明:上一条我把顺序写成 ①
其余改动:
@WhiteLNK 你的排序建议已采纳, |
|
v2 收到,降级顺序的修正很扎实( 想追一下合并 + 发版的时间预期:npm 上最新还是 两个请求:
如果需要我再补 rc.2 上的任何复现材料,直接说。 |
Merges the uiSession.adapter.current read face (omdsh-dev#65) with the localStorage / retainedBy fallback chain and the noSession toast + pending-retry UX (omdsh-dev#68). Session-switch detection now layers the uiSession source subscription, the legacy list subscription, and a 1s poll. Verified against dsh-v0.2.0-rc.2 kernel sources; npm run check passes 33/33.
|
感谢 @pinzza 的考证——特别是 localStorage 情况说明:#65(0.1.7 的 uiSession 方案)已先合入 main,与本 PR 在 client.js 的会话解析区域正面冲突。为了不让两条修复线互相阻塞,维护者直接接手在本分支上做了合并改造(你的原提交完整保留,署名不变):
|
Fixes #64.
根因确认(与 issue 分析一致)
DSH 0.1.6-alpha.2(内核 commit 6830e1460d)移除了
SessionListState.current。插件 1.4.11-preview.1 有 9 处直读sessions.list.getSnapshot().current,在新宿主上恒为undefined;attachAndSend()在进入 try/catch 之前就return false,批注块从不进草稿且无任何提示。submitAttached/watchInputDraft/ 按会话持久化 / 会话切换检测同因失效。已发布宿主实测:
current在 0.1.6-alpha.2 ~ 0.1.7-rc.2 上都没有恢复过(issue #64 已有 4 位用户独立复现)。修订说明(2026-09-28,回应本 PR 评论)
初版正文声称 ①
sessions.currentProvideInfo是"新旧宿主均有"的公开读面。这条是错的,由 @WhiteLNK @george-wyy 核出、我也独立复核确认:packages/client/runtime/src/client/contract/sessions.ts;本地 clone 停在 2026-08-19 /0.1.0-rc.8);0.1.7-rc.2)整棵安装树检索currentProvideInfo→ 0 命中;dsh-client-runtime未随包安装;packages/api/session-controller/src/client/contract/sessions.ts,ISessions成员无currentProvideInfo;currentProvide→ 0;对照词retainInfo→ 73、SessionListState→ 60、list.getSnapshot→ 25(搜索有效,非索引缺失)。⇒ 该级在所有已知宿主上都是死代码,本 PR 已将其整条删除;相应地把"为什么不用 localStorage"那段论据一并改正——在当前发布版上它就是唯一生效路径。
改动
client.jscurrentSessionId()三级解析(apply()内,逐级 try/catch 降级;localStorage缺席时如 Node 单测环境直接跳过该级):localStorage['dsh.sessions.current'].sessionId—— 内核 workspace 持久化的选择态(createSnapshotStore({}, { persist: { name: 'dsh.sessions.current' } }),写入形状{ sessionId },会话归档时由内核clearArchivedCurrent清理)。0.1.6-alpha.2~0.1.7-rc.2上这是唯一真实可用的路径;current——≤ 0.1.6-alpha.1的宿主,该字段是精确选中值;retainedBy.mainView > 0—— 公开成员,兜底"尚未落盘 / 存储被清"。它是主视图 retain 计数而非选中值,内核自己(dsh-client-ui-session/lib/client.js:283)也只在 id 未知时才用它,故排在精确值之后;writeCurrentPendingQuotes/ 2 处选区过滤 /attachAndSend/submitAttached/watchInputDraft×2 / 会话恢复 ×2);list.subscribe(旧宿主)+ 1s 轮询兜底(新宿主选择态已移出 list store,没有可订阅的选中态来源);清理函数统一释放订阅与轮询;attachAndSend取不到 id/scope 时console.warn+ 新增toast.noSession(zh/en)提示,批注保留待下一条重试;submitAttached同理加 warn;选区侧栏过滤在 id 未知时放行而非一律拦截。测试
message-block.test.mjs:夹具支持注入localStorage;新增"新内核形状 + 持久化选择态"与"无持久化键时退回retainedBy.mainView"两组回归(zh/en 各一),保留旧内核形状用例;pending-clear.test.mjs:会话切换断言改为单订阅 + 轮询 + 清理;解析优先级断言改为localStorage → list.current → retainedBy,并新增"不允许残留直读""不允许再读currentProvideInfo"防退化断言。验证
node --check client.js通过;npm test:28/28 通过(原 26 + 新增 2);0.1.7-rc.1与0.1.7-rc.2上批注均随消息正常送达(Annotation N:…协议块与回复侧芯片正常);本机生效路径确认为第 1 级localStorage,与 @WhiteLNK 的独立实测一致;src/,tsc构建不受影响(本机未装 devDeps,未跑npm run check全链,CI 为准)。未并入本 PR(范围待维护者定)
@george-wyy 报告的"失效期间已写批注刷新即永久丢失"(
dsh.annotation.pending.v1.*从不落盘)是同一根因的第二个后果。本 PR 修好 id 解析后,正常路径不再触发;仅当三级解析全部失败(此时会warn+ toast,不再静默)时仍存在该风险。是否把"无会话时的批注暂存"做成显式降级路径,建议单开 issue 讨论,以免本 PR 继续变大——维护者若希望一并修,我并进来。