refactor(dsh): adopt the typed 0.1.5 host and client boundary - #4649
Conversation
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval): reviewed exact head 0b0c1b2855706e9dc8c73d1b73a13673a85edc11, no blocking findings in the code/contract half; the release-gate half is still gated on the package environment and is named below. Merge remains the maintainer's decision.
动机
受支持的 DSH 宿主路径已经走到 0.1.5,而 packages/dsh-loopx-plugin 仍按 0.1.1 编译:peer 范围写着 >=0.1.0-rc.7 <0.1.1 || >=0.1.1-rc.1 <0.2.0-0,dev 依赖停在 0.1.1-rc.2,启动时还用 Reflect.has(connection,'fetch') 猜传输,猜不到就退回旧的 /loopx channel。RFC harness-selection-dsh-pi-v0.md 早就把这两条 dsh 面记为"不同步",并把这次升级单列为 pin 项。所以这是一个有据可依的兼容线收敛,而不是一次为了追新而追新的 bump:0.1.5 线不再发布 dsh-client-runtime(slots 席位移到 dsh-client-ui-renderer)、Session.events 变成 snapshotEvents()、Inbox.hasPending 变成两个 pending 队列,而一个 dsh.client.inject 列表无法同时给两代排序 boot 行。我判它是 justified_increment:单包、可单次 revert、且把第二个结构契约删掉而不是加一层适配。
改动思路
用宿主类型替代自造契约:src/goalbar/connection-rpc.ts 删掉本地声明的 ConnectionFetchRoute/SharedApiConnection/hasSharedApiFetch,测试改为直接引用 @deepseek-ai/dsh-client-connection 的 ConnectionRpcHandler/ConnectionFetchRoute,注册路径收窄成 Pick<HostConnectionHandle,'fetch'>,路由固定为 POST /api/loopx.goalbar。旧的 registerGoalBarConnectionRpc 仍然导出、但标注 @deprecated,只服务显式调用者,启动路径不再经过它。driver 侧只是换访问器:session.snapshotEvents()、inbox.nextTurn/nextStep,准入不变量(idle、无 pending、无 reservation、session/agent id 一致)一个字没动。observer 侧把 assistant/chunk 从 switch 分支提到一个显式的 RETIRED_SESSION_EVENT_TYPES 前置过滤,理由是更旧持久日志仍会重放这种行,而 L1 契约(只消费三种 session 事件)保持不变。这就是"复用已有 owner、删掉第二权威"的正确形状。
具体改动
22 个文件、+4829/-5404(净减),增量主要在重生成的 pnpm-lock.yaml 与更新后的 smoke;真正的源码改动只有 5 个文件、约 60 行。清单:peer/dev 依赖 → cordis 4.0.2 + 0.1.5-rc.2 全线;dsh.client.inject 里 dsh-client-runtime 换成 dsh-client-ui-renderer;tsdown.client.config.ts 的共享运行时白名单同步;connection-rpc.ts 删探针与 authority 选项;driver.ts/events.ts 换访问器;observer.ts 加 retired 集合;四个 smoke 与 Dockerfile.clean 更新;两个 RFC 镜像、插件 README、reliability_diagnostics README 双语同步。
关键代码讲解
registerGoalBarConnectionTransport(connection-rpc.ts:136):参数类型从 HostConnectionHandle 收窄为 Pick<HostConnectionHandle,'fetch'>,函数体内不再有分支,只注册唯一的共享 API 路由。这是本次最关键的行为变化——旧的自动回退被删除,不兼容宿主现在在类型/注册阶段失败,而不是静默降级到旧 channel。
registerGoalBarConnectionRpc(:130):保留导出、加 @deprecated,签名同样收窄为 Pick<HostConnectionHandle,'rpc'>,并去掉了原先的 {authority:'loopback'}。
inboxHasPending / foldSessionActivation(driver.ts:298、:287):hasPending → nextTurn.length>0 || nextStep.length>0;session.events → session.snapshotEvents()。准入条件与 try/catch 降级语义原样保留。
RETIRED_SESSION_EVENT_TYPES(observer.ts:301):把 assistant/chunk 从"switch 里丢弃"改为"进入 switch 前按类型集合过滤",语义等价但显式化,并且解释了为什么老日志需要它。
对主干的风险
兼容范围收窄是有意的破坏性变化,且已披露。 peer 下限从 0.1.0-rc.7/0.1.1-rc.1 抬到 >=0.1.5-rc.1:仍在 0.1.0–0.1.4 上的操作者升级源码插件后会失去 GoalBar。它写进了两个 RFC 镜像(三个上游迁移点 + 为什么一个 inject 列表无法服务两代)、插件 README(已发布 beta 保留其原有兼容性,本仓库不发布新版本),PR 描述也明确"不声称已发布 beta 获得该兼容性"。所以这是一条记录在案的迁移边界,不是静默改默认值。
权限面:插件侧不再声明 loopback。 旧代码在注册 legacy channel 时传 {authority:'loopback'},现在不传了;共享 /api 面的认证由宿主的 Connection plugin 拥有(runtime smoke 用 authHeaders,并在第 1039 行断言 403 拒绝、第 629 行断言 dispose 后 404)。这是我唯一没能独立核实的维度:0.1.5 的 rpc.handle 是否仍接受 authority 选项(需要安装 0.1.5-rc.2 的 peer 才能看它的 .d.ts)。如果仍接受,这个 deprecated helper 的通道就少了原先的插件侧限制;如果已被上游移除,那就只是 API 对齐。请作者确认一句,或者把同样的 authority 传回去。
我没能复现的证据。 187 个测试、typecheck/peer-range/build/packed artifact/profile 生命周期、以及真实 0.1.5-rc.2 native runtime 的演练,都依赖安装 0.1.5-rc.2 的 peer 集合(本机只有 0.1.1-rc.2),而这正是待授权的 package 环境决定。我能核到的是:该 head 的 CI 28 项全绿 0 失败;单测用的上游类型捕获证明的是插件的调用形状(不是宿主行为);runtime smoke 的断言在 diff 里真实存在。PR 自己也把两条 release gate(Docker clean install、owner-mounted browser client-to-carrier)标为未完成、未声称——这一点是诚实的,也恰好是我这份结论的边界。
其他已核对项:observer 的 L1 契约未变(仍只消费 session/created、session/event、session/disposed,未识别类型仍落到 unsupported 行);没有新增模块/状态/权限/CLI 面;改动留在 packages/<package-id>/ 而没有进 loopx/,provider 放置规则正确;净行数下降,删掉的是第二个结构契约而不是留待后人清理。
我的整体评价
这是把"声明支持的代际"和"实际编译验证的代际"重新对齐的一次正确收敛:一个传输、一套上游类型、一次可回滚的整包变更,并且把不兼容宿主从"静默降级"改成"显式失败"。文档同步做得比代码更用力(两个 RFC 镜像 + 两个 README 双语解释三个迁移点与退役输入),这是这类兼容线变更最需要的东西。因此我对代码与契约这一半给出批准结论,并把两处未核实维度明确留给后续:authority 选项是否仍存在于上游,以及需要 package 环境授权才能跑的那套验证。合并与否是你的决定;我这个评论不构成合并许可。
English verdict: APPROVE — at 0b0c1b2855706e9dc8c73d1b73a13673a85edc11 the plugin now has one typed transport on the released 0.1.5-rc.2 line, the runtime transport guess and the locally redeclared carrier interfaces are deleted, the narrowed peer floor and the deprecated legacy export are disclosed in both doc mirrors, and the observer contract is unchanged; unverified here are the 187-test suite and native 0.1.5-rc.2 runtime exercise (0.1.5-rc.2 peers not installed — the pending package-environment authorization) and whether upstream 0.1.5 rpc.handle still accepts the authority option that the deprecated helper no longer passes.
The plugin still compiled against DSH 0.1.1 while its supported host path had moved to 0.1.5. This replaces #4624 with one typed host/client boundary: upstream
HostConnectionHandle, the 0.1.5 renderer and session APIs, and authenticated shared/api/loopx.goalbarstartup. The explicitly exported legacy RPC registration remains deprecated for existing callers; startup no longer guesses between transports.The source graph is pinned to
0.1.5-rc.2, with matching peer ranges, packed-client checks and RFC compatibility checkpoints. The lockfile was regenerated under the existing release-age policy. This PR does not publish a new npm version or claim that the previously published beta has this compatibility.Validation: 187 tests, typecheck, peer-range checks, build, packed artifact/profile lifecycle, and the real DSH 0.1.5-rc.2 native runtime passed. The runtime exercise covers authenticated route/refusal, bootstrap, skill catalog, client materialization, bindings/watch cancellation, Start/Pause and disposal. Standard premerge passed all 19 selected checks plus diff hygiene; public-boundary scan and exact-scope quality qualification passed on
0b0c1b2855706e9dc8c73d1b73a13673a85edc11.Changed surfaces: optional DSH plugin runtime/client, package validation and compatibility documentation. Future-facing refactor applied: reuse upstream host types and remove automatic transport fallback instead of retaining a second structural contract.
Release limitations: Docker clean-install validation was unavailable because no daemon was running; owner-mounted browser Client-to-carrier validation remains a promotion gate. Native runtime/client materialization passed, but these release gates are not claimed complete. No provider calls or npm publication occurred. Maintainer review and merge remain pending.