← 返回列表
未验证
给 DSH Web 侧边栏加一层按话题分组会话的能力。
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/12 · 已提供中文文档
DeepSeek Harness (DSH) 的侧边栏话题分组插件——仅客户端、零宿主服务依赖,并带有离线冒烟测试。
综合分
28.7
GitHub 分
28.7
用户评分
—
★ Stars
0
周下载量
—
兼容 / 相关生态插件(非 dsh 原生,请按其对应运行时安装)
git clone https://github.com/WangXuexin24/dsh-session-topics.git信任档位:已验证本站已于 0 天前真实安装成功
- 是什么
- 生态应用(桌面端 / Web 外壳,不以 dsh plugin add 安装)
- 装得上吗
- 本站已真实安装成功(非静态推断)
- 安全吗
- 本站尚未对该插件做风险分级(暂未覆盖,不等同于无风险)
- 还在维护吗
- 活跃:最近一次提交在 13 天前
档位由下列信号合成:本站实装验证(真实安装,当前最高到 L4)· 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。下方各区块是它的证据明细。 验证判据与等级说明 →
🟢实装验证通过· 2026/9/25
由本站实装验证器在真实 dsh 环境安装成功,非静态推断。
数据截至 2026/9/24(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
由 DeepSeek 最新模型翻译生成dsh-session-topics 给 DSH Web 侧边栏加一层按话题分组会话的能力。 只想先会用? 跳到 用户手册(装 / 开 / 关 / 恢复 / 卸载 / 升级)。 想接手改进代码? 读 docs/HANDOFF.md —— 面向下一个 agent 的交接文档 (代码地图、必须遵守的契约、已知问题与改进路线)。 解决什么问题 DSH 官方的侧边栏只能按工作区分组,而工作区的成员资格是从每个会话记录的 cwd 推导出来的 —— 一个工作区只拥有 cwd 等于它自己路径的会话。所以同一个 目录下开出来的会话全挤在一组里,没法按主题拆开。 本插件加一条纯展示层的轴:话题文件夹。 核心设计:话题归属于工作区 话题是工作区作用域的 —— 一个话题只属于一个工作区,会话绝不会被挪到不属于 它的工作区里。这不是随手定的,有两条理由: 1. 它跟 DSH 自己的模型一致。 workspace 记账硬性保证“一个会话只属于一个工作区”, insertSessionBefore 的会话排序也是按工作区的。跨工作区的话题会同时破坏这两点。 2. 它让工作区保持可读。 如果会话能自由迁移进全局话题,工作区小节就会空掉, 用户再也答不上“这个会话是哪个项目来的”。 因此:跨工作区的拖拽会被直接拒绝(不建话题、不改归属)。这是有意为之。 功能 - 侧边栏渲染成 工作区 → [话题 → 子话题 → 会话] + 未归话题 - 每个工作区行右侧有 +,在那个工作区里新建话题 - 会话行右侧显示相对时间(「刚刚 / 5 分钟前 / 2 小时前 / 3 天前 / N 个月前」),每分钟自动刷新 - 拖会话到另一个会话的上/下半 → 调整顺序(插入指示线在上或在下),顺序由 host 持久化 - 拖到话题标题上(含子话题)→ 归入该话题 - 拖到「未归话题」标题上 → 移出话题回到未归类(归错了能拖回来) - 话题行悬停出现 + / ✎ / ×:新建子话题 / 重命名 / 删除 - 话题嵌套一层(话题 → 子话题)。数据模型是递归的,只有 UI 限层,见 MAX_TOPIC_DEPTH,改一个常数即可放开 - 会话右键菜单:重命名会话(内联编辑)/ 分叉会话 / 归档会话 / 移出话题 - 工作区右键菜单:新建话题 / 重命名工作区 / 删除工作区(删除前确认) - 展开/折叠、话题、归属关系全部持久化,刷新和重启都保留 - 点会话行照常打开会话 「拖拽排序」和「拖成文件夹」是两件事 官方的拖拽手势是排序(拖到行的上/下半,host 持久化)。第一版把它挪用成 「拖到会话上就建话题」,等于抢走了用户本来就有的手势,还让排序和分组两个概念 再也分不清。 现在的边界是明确的: | 你想干什么 | 怎么操作 | |---|---| | 调整顺序 | 拖到另一会话的上/下半(显示插入线) | | 归入某个话题 | 拖到话题标题上 | | 移出话题 | 拖到「未归话题」标题上 | | 新建话题 | 工作区行右侧 +(或右键工作区) | | 新建子话题 | 话题行悬停的 + | 接管官方槽位,就必须继承官方职责 本插件用 priority: -1 顶替官方 ui-workspace 注册的浏览器 —— 会话行从此由本插件 渲染。这意味着官方行上原有的每一个操作都属于本插件的责任。 第一版只实现了“打开会话”,于是重命名 / 分叉 / 归档 / 工作区重命名删除全部静默消失。 保留会话是因为用户只看得见“少了个功能”,看不见“是谁拿走的”。任何接管槽位的插件 都必须先盘点被替换方的全部能力,再逐条实现。 设计取舍(为什么它比同类插件“干净”) | | 本插件 | 社区同类插件 | |---|---|---| | host 半边 | 空壳,不 inject 任何服务 | 有的 inject storageDomain/workspaceRegistry | | 持久化 | 浏览器本地(客户端 store) | 有的落 ~/.dsh 文件 | | 启动风险 | 结构性为零(不依赖任何 host 服务) | 有挂起启动的先例 | | 删除会话 | 不做 | 有的会写 .ps1 并 ExecutionPolicy Bypass 执行 | | 官方数据 | 只读,从不写 | 有的改写/替换官方渲染器 | | 官方 store key | 从不触碰(自有 dsh.session.topics.v2) | — | 明确不做的事:不删除会话、不调子进程、不生成脚本、不写任何 host 文件、不注册 任何面向模型的工具或提示词(零 token 成本)。 两条来自踩坑的硬约束: - 垃圾回收器只能删它能证明已死的东西。 清理“死引用”的那一趟,在刷新后的 前几帧会用空的 workspaces/byId 去比对已经加载好的话题表 —— 于是每个话题 都被判定“所属工作区已不存在”,每次刷新都把用户的分组整个删光。 修法是两层:数据没到齐(phase !== 'ready')就不跑;并且 store 层的 retain() 在比较集为空时直接返回(空的比较集意味着“还没加载”,不是“全都没了”)。 - 用户手搭的东西必须有第二份。 分组无法再生成,所以每次非空变更都会把快照写进 dsh.session.topics.v2.bak;当主存储为空而备份有内容时,侧边栏顶部会出现一条 恢复条,一键还原。 - 不依赖 store action 的返回值。 需要原子性的写入都做成单个 action (如 createTopicWithSessions),因为 store 实现可以不返回值(Redux 风格), 靠读返回值拿新 id 会静默失效。 - 必须接住 shell 的滚动契约。 官方 ui-workspace 的根节点是 flex:1; min-height:0; flex-direction:column,内层列表 flex:1; overflow-y:auto。 不这么做,内容会被 overflow:hidden 的区域裁掉且无法滚动 —— 看起来像 “前端卡死”,但 JS 线程其实完全健康。 - 捕获阶段的监听器会抢在一切之前。 右键菜单用捕获阶段的 mousedown 做 “点外面关闭”,结果连菜单内部的按下也被它先看到 —— 菜单在 click 触发前就被 卸载,所有菜单项变成摆设。stopPropagation 救不了(捕获早于冒泡), 必须显式判断 ref.current.contains(event.target)。 - parentId 是分叉血缘,不是子代理。 用它过滤会把每一个分叉出来的会话 藏起来 —— 用户点完“分叉”就找不到子会话了。唯一正确的过滤条件是 origin === 'subagent'。 - fixed 定位的菜单必须钳制在视口内。 在贴近屏幕底部右键时,按光标坐标摆放 会把末尾几项推出视口 —— 菜单看着正常,但最后几项物理上点不到。 要在挂载后量尺寸再钳制,而不是渲染前估算。 安装(本地目录) dsh plugin --profile web add D:/DSH/projects/dsh-session-topics 或按本 profile 已有的 link: 惯例,在 ~/.dsh/profiles/web/package.json 里加: "dsh-session-topics": "link:D:/DSH/projects/dsh-session-topics" 并把它加进同一文件的 dsh.profile.bundles 数组。 改代码后只需刷新浏览器页面(客户端 bundle 每次加载都重新取),不必重启 dsh web。 验证与回滚 node "/node_modules/@deepseek-ai/dsh/lib/bin.js" --profile web --dump-config node "/node_modules/@deepseek-ai/dsh/lib/bin.js" plugin --profile web remove dsh-session-topics 本机 dsh.cmd / dsh.ps1 在受限 shell 里会被执行策略拦掉(返回空输出,容易被误判成 “命令没生效”),直接 node .../lib/bin.js 更稳。 离线自测 不需要浏览器,不需要装依赖: node test/smoke.mjs 测试桩是故意做成迷你 React 的:函数组件会被真正调用、hook 状态跨渲染持久、 effect 尊重依赖数组,并且 store 的 action 故意不返回值。这三点都是踩过的坑 —— 早期版本的桩太松,把真 bug 放过去了。 覆盖:模块加载、slot 注册与 shadow 优先级、会话过滤(隐藏 subagent / 已归档 / 非当前空白会话)、按工作区建话题、空话题可见、真实 input→commit 重命名路径、 同工作区拖拽建话题、跨工作区拖拽被拒绝(含拖到标题上)、嵌套与层数上限、 删除父话题连带子树、点击打开会话、滚动契约 CSS、官方同款 14px 字号。 以及一组“接管不能丢功能”的回归:会话右键菜单存在且含重命名/分叉/归档、 重命名走内联编辑并提交到 host RPC、分叉与归档路由正确、工作区菜单含 新建话题/重命名/删除、拖到「未归话题」能把会话移出话题、跨工作区移出被拒绝、 retain() 会清掉已死话题/工作区的展开态 key。 还有一条菜单可点击性回归:菜单内部按下不能把它关掉(否则 click 永远不触发), 菜单项点击必须真的执行动作,菜单外部按下必须关闭。 结构 package.json "." → 空壳 host;"./client" → 浏览器半边 cordis.patch.yml 插入 host 行(id: session-topics) lib/index.js host 空壳,故意不 inject 任何服务 lib/client.js 全部功能(__ModuleLoader__ 包装的浏览器产物) test/smoke.mjs 离线冒烟测试 已知限制 - 两级话题,无更深嵌套(改 MAX_TOPIC_DEPTH 可放开,但侧边栏宽度会先撑不住)。 - 话题归属存在浏览器本地:换浏览器或清缓存会丢,也不跨设备同步。 这是为了换取“零 host 依赖、零启动风险”而做的刻意取舍。 - 接管了 sidebar.workspaces 槽位(priority: -1 压过官方的 0)。这是加会话级 分组的前提 —— 会话行本来就是官方那个渲染器画的。官方将来更新该槽位时需人工跟进。 - 未实现官方的「添加工作区…」目录流子 slot(官方 sidebar.workspaces.directoryFlow 已由官方条目声明,本插件故意不重复声明)。需要新增工作区时用官方入口或 dsh CLI。 用户手册(装 / 开 / 关 / 恢复 / 卸载 / 升级) | 我想… | 怎么做 | |---|---| | 装 | 插件市场 → 安装;或 dsh plugin --profile web add D:/DSH/projects/dsh-session-topics | | 临时关掉 | 插件市场 → 已安装 → 本插件卡片的「启用中」开关关掉 → 按提示重启 DeepSeek Harness | | 再打开 | 同一开关打开 → 重启 | | 恢复出厂(重置分组) | 卡片上的「恢复」按钮 | | 卸载 | 卡片上的「卸载」;或 dsh plugin --profile web remove dsh-session-topics | | 升级本地代码 | 直接改 D:/DSH/projects/dsh-session-topics 里的文件 → 刷新浏览器页面即可(客户端 bundle 每次加载都重新取)。只有改了 package.json / cordis.patch.yml 才需要重启 dsh web | | 确认它在跑 | 侧边栏是「话题」分组而不是官方的纯工作区分组 = 它在跑;node test/smoke.mjs 应输出 RESULT: all checks passed | 开关与「恢复 / 卸载」是插件市场(dshmarket)的能力:它改的是 profile 的 patch 层, 所以开关之后要按提示重启才生效。本插件自身不实现开关。 疑难排错 | 症状 | 原因 | 处理 | |---|---|---| | 侧边栏变回官方按工作区分组 | 插件被关掉 / 没加载(priority: -1 没生效) | 看插件市场里是否「启用中」;重启 dsh web | | 分组整个不见了 | 浏览器本地存储被清(换浏览器、清缓存) | 顶部若有恢复条点还原;否则查 localStorage["dsh.session.topics.v2.bak"] | | 列表滚不动、像前端卡死 | 滚动契约被破坏(根节点的 flex 与列表 overflow) | 见 docs/HANDOFF.md §3.3 | | 侧边栏冒出一批空对话 | 不是本插件的问题 | 见下方「已知问题」 | | 右键菜单点不动 | 捕获阶段的监听器把菜单提前关掉了 | 见 docs/HANDOFF.md §3.7 | | 冒烟测试不过 | 改了 UI / 过滤逻辑 | node test/smoke.mjs 看具体断言,改完必须全绿 | 已知问题 - 空对话:DSH 的冷会话摘要把 blank 默认成 false (dsh-api-session-controller 的 summarizeCold),于是"开起来就死"的空壳会话 在官方侧边栏和本插件里都会显示。根因、识别特征与三条缓解路径见 docs/HANDOFF.md §5.1。 - 官方 sidebar.workspaces 槽位演进时需要人工跟进(本插件顶替了官方浏览器)。 - 分组数据存在浏览器本地:不跨设备、清缓存即丢(有 .bak + 恢复条兜底)。 发布状态 - 已公开发布:(PUBLIC,main) - 他人安装:dsh plugin --profile web add github:WangXuexin24/dsh-session-topics - 本机仍以 link: 安装,出现在插件市场「已安装」列表(带开关) - lib/ 已随仓库提交(dsh 从 git 安装不跑构建) - npm:未发布 —— 可选。不发也能从 GitHub 安装;发了市场才会显示下载量。 - 社区目录收录(出现在市场「发现 / 主题」):可选,尚未提交。 条目已备好在 docs/market-submission.yml,随时可用; 另有「仓库创建满 1 天」的 CI 门槛。不收录不影响安装,只影响被搜到的概率。 License MIT