Skip to content

dsh-plugin-browserskill@0.2.1 与 dsh-better-sidebar@0.19.x 不兼容:Cannot read properties of undefined (reading 'kind') #233

Description

@FelixTennouji

问题概述

dsh-better-sidebar@0.19.x 下,@wxg-prc-cpg/browser-skill-dsh-plugin@0.2.1 的客户端部分会在第一次 SidebarStore.setSession() 时抛异常,导致 better-sidebar 的整个底部工作台崩溃。用户实际看到的是由 better-sidebar 根错误边界渲染出来的、具有误导性的文案:

dsh-better-sidebar: Cannot read properties of undefined (reading 'kind')

环境

  • @deepseek-ai/dsh@0.1.5-rc.1(Windows 11,Node 24)
  • @wxg-prc-cpg/browser-skill-dsh-plugin@0.2.1(当前最新)
  • dsh-better-sidebar@0.19.1(当前最新)
  • BrowserSkill CLI bsk 0.2.1,浏览器已连接

复现步骤

  1. 在 DSH web profile 中安装 dsh-better-sidebar@0.19.1@wxg-prc-cpg/browser-skill-dsh-plugin@0.2.1
  2. 启动 dsh web,打开任意会话(侧边栏 store 在会话激活时 hydrate)。
  3. 底部侧边栏面板出现红色错误条:dsh-better-sidebar: Cannot read properties of undefined (reading 'kind')

根因

lib/client.cjs(源码位于 packages/dsh-plugin-browserskill/src/client/...):

function* leafNodes(node) {
  if (node.kind === "leaf") {        // <-- 这里的 node 是 undefined
    yield node;
    return;
  }
  for (const child of node.children) yield* leafNodes(child);
}

/** 是否已经有一个本插件的标签页打开在任一侧边栏工作台里 */
function observationTabOpen(state) {
  if (state === void 0) return false;
  for (const root of [state.splits, state.bottomSplits])
    for (const leaf of leafNodes(root)) /* ... */ ;
  return false;
}

state.splits 这个字段已经不存在了。dsh-better-sidebar@0.19.0 把右侧栏交给了 DSH 0.1.5 的原生右侧边栏,它自己的 SidebarState 现在只保留 bottomSplits

// dsh-better-sidebar src/client/state.ts (0.19.1)
export interface SidebarState {
  activePane: string | null;
  // ...
  /** 底部工作台的分栏树 */
  bottomSplits: SplitNode;
  // `splits`(旧版右侧栏分栏树)已被移除
}

于是这次遍历从一个 undefined 开始,leafNodes(undefined) 直接读取 undefined.kind 就炸了。

同一个函数里还有第二处过期假设:state.panelOpen 在同一版本中已改名为 state.bottomOpen,导致「面板被关闭后再自动打开」这一分支永远不会触发。

真实堆栈

浏览器控制台抓到的堆栈如下:

TypeError: Cannot read properties of undefined (reading 'kind')
    at leafNodes            (@wxg-prc-cpg/browser-skill-dsh-plugin/client.js)
    at leafNodes.next (<anonymous>)
    at observationTabOpen   (…)
    at evaluate             (…)
    at SidebarStore.notify  (dsh-better-sidebar/lib/client.js)
    at SidebarStore.setSession (dsh-better-sidebar/lib/client.js)
    at <better-sidebar Sidebar useEffect: store.setSession(current)>

这个异常之所以会冒进 better-sidebar 的 React 树,是因为 registerObservationSidebar() 调用了 store.subscribe(evaluate),而 SidebarStore.notify() 是在 setSession() 内部同步执行订阅者的,此时 React 恰好在提交 better-sidebar 自己的 effect。因此它被 better-sidebar 的根 RenderBoundary 捕获,而不是被本插件自己的错误边界捕获。

修复建议

给分栏树遍历加空值保护,并在生态迁移期同时兼容两种字段名:

function* leafNodes(node) {
  if (node === undefined || node === null) return;
  if (node.kind === "leaf") {
    yield node;
    return;
  }
  for (const child of node.children) yield* leafNodes(child);
}

function observationTabOpen(state) {
  if (state === undefined) return false;
  for (const root of [state.splits, state.bottomSplits]) {
    if (root === undefined || root === null) continue;
    for (const leaf of leafNodes(root))
      if (leaf.tabs.some((tab) => tab.type === "browserskill:observation")) return true;
  }
  return false;
}

以及:

// 原来是:state.panelOpen === false
if (previousVisible === 0 && count > 0 && open && (state.bottomOpen ?? state.panelOpen) === false) 

长期来看,在 better-sidebar >= 0.19 上可以直接去掉 state.splits(或对状态结构做特性检测),因为已经不存在右侧分栏树需要扫描了。

验证方式

我在本地用上面两处保护改了 lib/client.cjs,再用无头 Chrome 加载页面:打补丁前,控制台在页面加载后约 1 秒内必现该报错;打补丁后控制台干净,工作台正常渲染。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions