第三方宿主(Obsidian 插件)嵌入 DSH Web UI 的若干集成障碍:输入框无可编程写入接口、iframe 嵌入缺少支持的认证方式、插件注入消息缺少身份会污染会话、会话格式容错不足 #6284
|
背景:我维护 Obsidian 插件 dsh-harness(把 dsh web 的 UI 无痕嵌入 Obsidian 面板,并做双向桥接:在笔记里框选文字 → 生成隐式信息行注入聊天框 / 或直发会话)。不改 DSH 源码,走官方扩展机制(cordis 插件 + agent/pre-step 钩子 + 本地 /api)。实测版本 0.1.5-rc.1。以下四条是我们在真机上反复踩到、且有明确证据的问题。 1)聊天输入框(Lexical)没有受支持的"程序化写入"方式 现象:宿主需要把一段文本放进输入框(用户在编辑器里框选笔记 → 注入一行信息)。任何"整体替换"写法在 Lexical 上都会失败: 现象:dsh web 打印 http://127.0.0.1:/?token=…;浏览器路径 GET /?token= → 303 + Set-Cookie dsh-auth-*; HttpOnly; SameSite=Strict,之后 / 与 /api 由 cookie 把关。宿主的 iframe 位于 app://obsidian.md(跨站)→ Strict cookie 不会带上 → 面板永远 401("dsh web authentication required; reopen the URL printed by dsh web")。 现象:注入的消息若只返回 { source, content },落盘成 user/message 后缺 id/role → 读会话报 session event at seq N lacks an identified message(真机 seq 23762 被我们实测到)。迁移链只给旧事件补 legacy-message::,运行期新注入的消息没人补。 现象一:第三方插件写了非法的 source.form(我们用过 'bridge-edit')→ 迁移链拒收整个会话。合法值只有 instructions/catalog/snapshot/notice/relay/recall。 |
Replies: 2 comments
|
这四条里,第 3 条(缺 id/role 导致整会话读不出来)我对着当前源码核实过,机制和你说的完全一致,而且比你猜测的更清楚一点。 packages/core/session/src/index.ts 的 append(),运行期插件调用 session.append() 写事件走的正是这条路径,只调用 validateSessionEventData() 和 surfaceManager.validateNext(),两者都不检查 user/message 的 id/role。真正做这项检查的是 assertMessageEventShape(),但它只在 adoptSessionEvent() 里被调用,而 adoptSessionEvent() 只在 packages/session/session-persistence/src/storage-contract.ts 第 95 行(从存储读回事件时)被用到。 也就是说,写入时完全不挡,读回时才用 lacks an identified message 拒收整个会话。这不是迁移链没补运行期新注入的消息,而是校验函数本身只挂在读路径上,append() 从未调用它。这个不对称应该可以在不碰迁移链的情况下修,给 append() 也接上同一个 assertMessageEventShape() 检查,或者一个专门给运行期注入用、能自动补 id 的辅助函数,这样第三方插件在注入时就会立刻收到明确错误,而不是等到下次打开会话才发现整段历史读不出来。你说的官方插件里的 ensureIdentifiedMessage(),目前源码里没有这个具体名字的函数,但你要的语义,注入边界自动兜底或立即报错,确实是目前缺失的一块。 其余三条,Lexical 程序化写入、iframe 认证、多帧 zstd 与格式容错,我没有逐条去核实,但整体看是一份少见的、把第三方宿主视角的真实摩擦点讲得很具体的报告,值得维护者认真看一遍。 |
|
四条逐条核实(master c291e79)。先给结论:第 3 条是确凿的写入侧缺陷且 master 未修;第 4 条机制属实;第 1、2 条是真实的宿主集成缺口,但属于需要官方支持的产品决策,下面给现状与可行绕行。 3)缺 id/role 写坏会话——属实,且根因可以更精确: 4)source.form 封闭集合属实:v0→v1 校验器只放行 2)iframe 认证:cookie 确为 1)输入框程序化写入:客户端契约面( EN summary: Item 3 verified and still live — |
四条逐条核实(master c291e79)。先给结论:第 3 条是确凿的写入侧缺陷且 master 未修;第 4 条机制属实;第 1、2 条是真实的宿主集成缺口,但属于需要官方支持的产品决策,下面给现状与可行绕行。
3)缺 id/role 写坏会话——属实,且根因可以更精确:
packages/core/session/src/index.ts:710-740的append()只调用validateSessionEventData(surface.ts:140-167,仅检查 request/header 与 tool/result)和surfaceManager.validateNext;消息身份检查assertMessageEventShape(index.ts:328-359)只挂在adoptSessionEvent(index.ts:166-172)上,而它仅在从存储读回时被调用(packages/session/session-persistence/src/storage-contract.ts:94-102)。因此运行期注入的 user/message 缺 id/role 时写入完全放行,下次打开才整会话拒读。插件作者现在就能做:注入消息必须自带id、role: 'user'、source: { kind: <合法值> }。修法建议:让append()也走同一assertMessageEventShape,在注入点即时报错——不需要动迁移链。4)source.form 封闭集合属实:v0→v1 校验器只放行
['instruction…