Repository navigation
Releases
v0.6.5 — 适配核心 0.1.5-alpha.2:图标与分隔条回归原生
主要变化(自 v0.5.0)
- 适配核心 0.1.5-alpha.2 的面板模型:核心把中央列改成 keyed 的
main槽,插件改为接管main的conversation键;0.1.2-rc.1上仍可用(0.1.5 才有的东西不存在时优雅降级)。 - pane 的图标全部来自核心:分屏 / 上下分屏 / 全屏 / 关闭的 glyph 由
scripts/sync-icons.mjs从核心源码提取生成,不再手抄 —— 和核心自己的按钮同款、同尺寸、同描边。 - 分隔条不画任何东西:与核心的列 resize handle 一致(核心注释:"No handle draws a visible pill"),只保留 cursor;键盘
:focus-visible时才有一条品牌色描边,键盘调节仍可用。 - 新建对话的 pane 那栏只留图标:行几何照抄核心 header(顶内边距 10px + 30px 标题行),图标和旁边会话 pane 的按钮落在同一条线上。
- 上游跟踪与发布:每 6h 检测核心 release,只在上游真正触碰本插件消费的接触面时开升级 PR(全绿才开,发版仍人工);核心 pin 记在
core-pin.json;构建产物跨机器逐字节可复现。
兼容性
开发与发布基线是核心 0.1.5-alpha.2(vendored 渲染器副本来自该版本)。0.1.5-rc.2 已实测:插件消费的接触面(渲染器 / 图标 / 会话契约)逐字节未变,无需改动。0.1.2-rc.1 也可用。
安装
下载下面的 dsh-external-dsh-split-panes.tgz(固定文件名,releases/latest/download/dsh-external-dsh-split-panes.tgz 永远指向最新构建),装法见 README。
v0.5.0 — 免补丁分屏:跑核心自己的渲染器
免补丁分屏,跑核心自己的渲染器
架构(最大变化)
每个 pane 不再手写 slot dispatch,而是把核心的 slot 渲染器逐字节 vendor 进插件,给它一个 pane 作用域的 SlotRendererHost(公开接口)——核心的 outlet 用该 pane 的 session binding 渲染。于是 header、消息流、composer、hero 全是核心自己的代码,插件的 dispatch 复刻层整体删除。
src/client/vendor/renderer/{bind.ts,bindings.tsx,scoped-slots.tsx}:逐字节副本scripts/sync-renderer-vendor.mjs:从核心检出同步;--check只比对tests/renderer-vendor.spec.ts:在测试里再比对一次,上游一改就红- root standard-source binding 用
ctx.inject反应式补齐(workspaces/ keyedresource)
修复
- 输入框 / 会话内容乱渲染:旧的手写 dispatch 与核心漂移(
t座位每帧新身份、keyed hook 每帧重订阅)——现在跑的就是核心代码。 - 右侧边栏点"展开侧栏"没反应:
ui-sidebar-right的 store handle 被 pane 与核心渲染的区域共享,解析成了两个实例;现在handle.create(scopeKey)全局按 key 记忆化,两侧共用同一实例。 - 分屏后 pane 已有会话时点"新会话"没反应:核心的
conversation槽是 session-maybe,选中变化会重挂载整个工作区,旧的"上一次选中"ref 因此失效;改成与焦点 pane 自身会话做幂等比较。 - 嵌套分屏的分隔条拖不动:
setRatio未递归到嵌套 split。
新增
- 窗格全屏:pane header 的全屏按钮把该窗格铺满整列,分屏树原样保留;再点一次或按
Esc退出,精确回到分屏状态。
交互模型
- 点 pane → 它成为焦点,全局选中跟随(侧边栏高亮同步)
- 点侧边栏会话 → 改的是焦点 pane 的内容,其余 pane 保持 pinned
- 拖侧边栏会话到 pane 中心 = 替换;拖到边缘 = 向该侧分屏
- 占位 pane 里选工作区 → 新会话落回发起它的那个 pane
兼容性
- 开发与测试基线:核心 0.1.5-alpha.1(vendor 的渲染器即该版本)
- 0.1.2-rc.1 实测可用:分屏、双 pane 各自会话、焦点路由、拖拽替换均正常;0.1.5 才有的功能(右侧栏等)在该版本上不存在,插件优雅降级
- 安装:
dsh plugin --profile web add link:/path/to/dsh-split-panes
安装包
固定地址(始终指向最新构建):
https://github.com/lehhair/dsh-split-panes/releases/latest/download/dsh-external-dsh-split-panes.tgz
v0.4.0 — stable hook order; split-panes-only scope
v0.4.0 — hook 顺序稳定 + 只做分屏
修复
- 输入框时常不渲染 /
Cannot read properties of null (reading 'destroy'):composer 输入条是 session-maybe 槽,其 InputBar 组件实例跨 hero/active 转换保持。keyed projection hook 的 absent 分支此前不调用 useSyncExternalStore,导致组件跨状态转换时 hook 调用数变化、React hook 链损坏。现在 absent 分支与官方渲染器的 keyedObservableHook absent 臂一致(始终订阅 absent source,selector 永不被调用)。 - 移除全局标题栏/侧边栏 chrome 修改(PaneGlobal.module.css):插件现在在 pane 表面之外零视觉修改,只做分屏。
焦点同步模型(验证通过)
- 分屏后点击侧边栏会话 → 新会话路由到焦点 pane(其余 pane 保持各自的会话)
- 点击 pane → 全局选择跟随该 pane 的会话(侧边栏高亮同步)
- 新分出的 pane 是新建对话占位(hero),在其中开始对话才创建会话并绑定
31 tests 全绿,typecheck + build 通过。
v0.3.0 — pure-extension: capture ConversationRoot (native layout per pane)
v0.3.0 — 纯扩展架构修正:捕获 ConversationRoot,不再复刻布局
重大架构修正。之前「接管 conversation 槽 + 自建渲染层 + 复刻布局」的方向被证明不可行,现已改为纯扩展的正确做法,端到端验证通过。
核心修正
核心没有按 id 渲染的扩展点(ScopeBindingContext/host 实例/renderArea 的内容 dispatch 都是包私有),而复刻 ConversationRoot 布局(hero/workspace picker/composer/测量/width handles)既不可能(内部组件和 CSS 不导出)也不可维护(395 行复杂逻辑)。
正确做法:捕获原生 ConversationRoot 组件,喂给它 pane 会话的数据与 dispatch——每个 pane 渲染真正的原生对话界面。
变更
PaneConversation:捕获conversation槽的原生ConversationRoot条目(component + inject + locale),按 pane 会话通过 by-id kit 重新托管——原生对话界面逐字节渲染(hero、workspace picker、composer、消息流、width handles),只是 session 不同- 复用 ConversationRoot 条目的 inject(原生
selectWorkspace+hooks.composerBlock)——工作区选择逻辑无需重写 renderPane渲染 ConversationRoot(单窗格=current session,分屏=各 pane 自己的 session);删除PaneBody- render-host 新增
renderConversationRoot()(选中非 takeover 的原生条目)、store/inject 缓存、owner props 合并、槽级 inject 工厂、memo/forwardRef 组件支持 - kit 的 absent hook 与渲染器 maybe-hook 语义一致(selector 不被调用——hero 态
useSession/useConversation返回 undefined,不再报undefined.promptError)
验证
- takeover 渲染原生 chrome(header + composer,无「未知 surface」)
- 分屏各 pane 渲染原生对话(15k+ HTML、分隔条、新建对话 hero、无 fallback)
- 31 tests 全绿,typecheck + build 通过
修复的历史问题
- 「首页新建对话只剩标题+按钮」→ ConversationRoot 的 hero 原生保留
- 「未知 surface 事件」→ chat node 的 memo 组件 + dispatch 修复
- 「丢失 composer/workspace picker」→ ConversationRoot 原生保留
- 「状态丢失」→ render-host 的 store/inject 缓存
纯扩展,免补丁。
v0.2.3 — fix owner merge + slot inject in pane dispatch
v0.2.3 — 修复 dispatch 的 owner 合并、槽级 inject 与无会话门控
修复 v0.2.2 安装后的三类渲染崩溃。
修复
Cannot read properties of undefined (reading 'data')(ToolCallTree):pane 的 renderSlot 此前丢弃了 owner 参数——chat node 的 dispatch(ChatNodeSeat)把 node/selectedCallId/cwd/... 作为 owner props 传入,渲染器把它们最后合并(胜出)。pane dispatch 现在完全镜像该合并顺序(kit → entry inject → store → slot inject → contextual hooks → owner)。- 槽级 inject(chat node 的 CHAT_NODE_INJECT / useTurnData):现在读取槽 spec 的 inject face(registry spec()),其 hook 工厂按每次 dispatch 的 hookContext 绑定——与渲染器的 cachedSlotInject/bindSlotHookFactories 一致。
useConversation is not a function:PaneBody 对严格 session 槽(header/body/docks)按会话身份门控——无会话窗格跳过这些槽(composer bar 是 session-maybe 槽,照常渲染为惰性态),与 ui-conversation 的 ConversationRoot 一致;且 binding 中缺失的 hook 不再以 undefined 写入 props。
回归测试
新增 pane-dispatch.spec.tsx:keyed dispatch 回归,覆盖 owner 合并与 hookContext 工厂两个形态(31 tests 全绿)。
v0.2.2 — fix workspaces inject + button t seat
v0.2.2 — 修复 workspaces inject 与按钮 t seat
修复 v0.2.1 安装后的两处运行时报错。
修复
cannot get property "workspaces" without inject:pane kit 读取 ctx.workspaces(useWorkspaces 根源),但插件 cordis inject 列表未声明该服务——cordis 对未注入服务的 getter 直接抛错。已把 workspaces 加入 inject,并在 buildPaneKit 里对缺失该源的环境加了守卫。t is not a function(SplitPaneButton / SplitVerticalButton):渲染器只为声明了 locale 命名空间的条目合成 t seat;header 按钮注册时漏了locale: NS。三个 header 按钮现在都声明 panes 命名空间。
验证
29 tests 全绿;构建产物确认 inject 列表与按钮 locale 声明。
v0.2.1 — fix real-render crashes
v0.2.1 — 修复真实渲染崩溃 (fix real-render crashes)
修复 v0.2.0 安装后分屏渲染报错的问题。
修复
selector is not a function:keyed hook(useProjection 等)的 selector 现在可选(核心契约:TodoDock 调用 useProjection('todos') 不带 selector)Cannot read properties of undefined (reading 'byId'):pane kit 现在携带 ROOT 标准源(useSessions/useWorkspaces/useSessionPendingInteraction),镜像渲染器的 {...root, ...session} 合成t is not a function:按条目 locale 命名空间合成 t seat(ctx.locale.bind)- hooks 空指针崩溃:测试环境 react 双实例问题(resolve.dedupe)
测试
新增真实渲染集成测试(pane-render-host.spec.tsx):装配真实 ui-conversation,通过 pane kit 渲染真实原生组件(header + chat view + composer)。29 tests 全绿。
v0.2.0 — patch-free upgrade to DSH 0.1.3+
v0.2.0 — 免补丁升级 (patch-free upgrade)
DSH 核心 0.1.3-alpha.1 起不再需要渲染器补丁。分屏功能现完全基于核心公开 API 实现。
变更
- 移除核心补丁 (SessionScope / conversation.panes):不再需要 patch 核心
- 插件自持渲染层级:\ctx.uiSession.adapter.resolve\ 按窗格会话解析标准源、捕获原生槽位组件重新托管
- \conversation\ 槽低优先级影子接管分屏;卸载即回原生渲染
- 依赖:删除已移除的 @deepseek-ai/dsh-client-runtime\,改用 cordis + api-session-controller + ui-renderer/ui-session 等
- 4 个测试文件 26 个用例全部通过;typecheck + build 全绿