packages/dsh-task-board
zhu1090093659/dsh-web侧边栏多列任务看板:卡片交给真实 DSH 智能体会话执行,支持 cron 定时(Host 侧到点执行,关浏览器也生效)。
插钮聚合器(载体+驻场 LLM 范式):把任何插件的散落按钮聚合到统一入口(SSiD 标题栏 / web 悬浮球)——LLM 按环境注册、右键删除=注销,纯数据零代码,不动插件源码。
本插件属于 @max-null/* 插件系列——这一系列共同构成 SSID(思灵 · Seek Soul in Darkness) 桌面体验。SSID 是整合它们的盒:dsh-capture · dsh-chat-rail · dsh-chinese-thinking · dsh-draft-polish · dsh-guardian · dsh-habit · dsh-memory · dsh-node-appearance · dsh-plugin-center · dsh-quick-toolbar · dsh-skill-mcp-center · dsh-ssid-panels · dsh-ssid-zh-ui。
This plugin belongs to the @max-null/* family — a set of plugins that together form the SSID (思灵 · Seek Soul in Darkness) desktop experience.
面向 DeepSeek Harness 的插件按钮聚合器:把三方插件散乱的按钮(插件中心/侧栏/底栏/会话管理…)聚合到统一入口——SSiD 壳 → 标题栏按钮组;DSH web → iOS 小白点式悬浮球(自由定位拖拽、球↔面板 morph 展开、球永远锁定面板屏幕外侧角)。核心价值 = 可扩展性:本插件是「载体」(协议 + 引擎 + 注册表),每个人都可以把自己环境里任何插件的按钮聚合进来(LLM 一键注册 / 右键删除 = 注册制/注销制,全程不动插件源码、不写一行代码)——不要求第三方插件配合,不需要等作者适配。面板里还带一个置顶会话入口:把常回的会话钉起来,按工作区分组放在面板右侧的二级列里,点一下即切过去。
A plugin-button aggregator for DeepSeek Harness: gathers scattered third-party plugin buttons (plugin center / sidebar / bottom bar / session manager …) into one entry — an SSiD title-bar button group in the SSID shell, and an iOS assistive-touch-style floating ball on plain DSH web (free positioning & dragging, ball↔panel morph expand, ball always locked to the panel's screen-outer corner). Extensibility is the point: this plugin is a carrier (protocol + engine + registry) — everyone can register the buttons of any plugin in their own environment (LLM one-click registration / right-click deregistration; no plugin source touched, no code written, no cooperation required from third-party plugins). The panel also carries a pinned-sessions entry: pin the sessions you keep returning to; they sit in a secondary column to the right of the panel, grouped by workspace, one click away.
你的环境 = 插件 A · 插件 B · 插件 C(各自散落的按钮)
└── 聚合到本工具栏(一个入口)
▲
注册(➕ 一键,LLM 探查+数据注册)/ 注销(右键删除=移除注册)
| 聚合面板(内置 + LLM 注册按钮 + ➕) | 右键滑动删除(注销制) |
|---|---|
![]() | ![]() |
| 二次点击关闭(引擎探测语义) | ➕ LLM 注册会话(反问 → 探查 → 注册) |
|---|---|
![]() | ![]() |

Remote 为用户 LLM 现场注册的按钮(ds-harness-remote 入口)——演示「任何插件按钮都能聚合进统一入口」;右侧面板同时展示 LLM 按任务书先反问目标、再探查注册的完整流程。
| SSiD 标题栏(壳) | web 悬浮球 |
|---|---|
![]() | ![]() |
截图环境:SSiD 壳(标题栏/聚合面板)与 DSH web(悬浮球);Remote 为用户 LLM 现场注册的按钮(ds-harness-remote 入口),演示「统一入口聚合散落按钮」。

面板顶部是「☆ 置顶当前会话」与「置顶会话(N)」入口。鼠标移到入口上,面板右侧展开 一列独立的置顶列表——它挂在
body上、不在壳内,因此不占用一级菜单的高度(壳带overflow:hidden,壳内的浮层溢不出去)。分组标题带工作区图标,与会话项左对齐。置顶按工作区分组,判据是工作区的成员表(
WorkspaceView.sessionIds,与 DSH 左侧栏的 分组同一来源),不是会话的cwd;没有数量上限。点条目即切过去;行尾「图钉 + 斜杠」 取消置顶(平时不显形,悬停或键盘聚焦才出来,避免误触)。会话被删除后条目降透明、但仍 然可点——否则就再也取消不掉它了。数据落在内核的置顶集合(
WorkspaceSnapshot.pinnedSessionIds),读写分走workspaces.list与uiWorkspace,与官方 UI 共享同一份——不是插件自管的文件。
# 走 DSH 插件安装(或 SSiD 预制 vendor)
dsh plugin --profile web add @max-null/dsh-quick-toolbar
adapters.prompt.md 到任意会话 → LLM 生成 { "adapters": [...] } → 写入 ~/.dsh/quick-toolbar-adapters.json → 刷新页面生效(host API 校验,非法条目丢弃并报明细)。推荐直接走 ➕(见教程)。/quick-toolbar/api/state → ~/.dsh/quick-toolbar-state.json,SSiD 开发手册 §7.10 规则)——内核动态端口不再丢状态。WorkspaceView.sessionIds,与 DSH 左侧栏的分组同一来源),不是会话的 cwd;未归入任何工作区的会话自成一组。没有数量上限。
uiWorkspace.openSession。导航归视图所有者——ISessions 接口本身没有 open(其 JSDoc 写着 "navigation belongs to view owners"),早期版本调 sessions.open 因而从未生效。data-current 标记并弱化显示,但不禁用:跳到自己无害,禁用反而会被读成「坏了」。default-workspace 按当前语言显示为「默认工作区」,与侧栏一致(同一套判据见 DSH 的 workspaceDisplayTitle);用户手动改过的名字原样显示。核心观念:迁移按钮不是自己写配置,而是开一个会话,把任务交给环境里的 LLM。 本插件是「载体」,不内置扫描器、不预设所有场景——适配由你环境里的 LLM 现场完成 (驻场工程师模式);你只需要告诉它要哪个按钮。此设计不是社区主流,但它承诺: 环境里任何按钮都能被聚合,无需第三方插件配合、无需等待本插件适配。
推荐路径(三步,约 1 分钟):
adapters.prompt.md 到任意会话。{ "adapters": [{ "id": "...", "button": "..." }] } 写入
~/.dsh/quick-toolbar-adapters.json。你刷新页面,按钮即出现在工具栏。
若未出现,告诉 LLM,它会修正重试。手动方式(高级用户):跳过会话,直接编辑 ~/.dsh/quick-toolbar-adapters.json
(同 id 覆盖既有注册;非法条目被 host 校验丢弃并报明细——详见 adapters.prompt.md 字段表)。
说明:注册结果是纯数据(图标/文字/点击由载体派生或按声明执行),不是代码—— LLM 注册完就无需在场;那份 JSON 可导出、可备份、可随环境迁移。
删除按钮:在工具栏面板里右键点击该按钮 → 「删除此按钮」(仅用户注册的按钮;
内置按钮不可删)。删除后原按钮恢复显示、配置写回 ~/.dsh/quick-toolbar-adapters.json
(也可直接手动编辑该 JSON)。SSiD 壳环境路径:标题栏「悬浮球」开关(圆圈+圆点)→
球显示 → 点球展开面板 → 右键按钮 → 滑出「删除」。
English quick start — Moving a button in is NOT a settings task: open a session and let the on-site LLM do it. Click the ➕ "Add button" in the toolbar panel; the plugin creates an "Add button" session and injects the registration brief into it (auto-runs; falls back to a composer draft if the session service is unavailable). The LLM will first ask you which button to migrate / what new button you want, then it explores the environment, verifies the selector, writes
{ "adapters": [...] }to~/.dsh/quick-toolbar-adapters.json, and you refresh the page. Registration results are plain data — the carrier derives icon/text/click from the original button, and the LLM is no longer needed afterwards.
src/adapters.ts:适配器 schema + 内置适配器集(黄金示例)src/behaviors.ts:行为库(click / toggle-panel / dispatch-event / open-settings(语义锚点+再点关闭)/ command(composer 注入)——全部实现,v2 M1)src/engine.ts:执行器(防御执行)src/schema.ts:用户配置 zod 校验(LLM 产物防线)src/register-brief.ts:➕ 按钮注入的注册任务书(先反问 → 探查 → 最小注册,与协议字段同步,锚点测试防漂移)src/index.ts(host 半):GET /quick-toolbar/api/adapters(用户适配器)+ GET/POST /quick-toolbar/api/state(状态 host 化,原子写)doc/设计/2026-08-30-quick-toolbar-独立化设计方案.md、doc/设计/2026-08-30-quick-toolbar-v2设计.mdpnpm install
pnpm typecheck && pnpm test && pnpm build # L1 门槛(91 用例)
tsdown.config.ts 用的是数组配置(两次独立构建),而不是一个 entry: ['src/index.ts', 'src/client.ts']。原因:一旦某模块被 host 半与 client 半同时 import,多入口单次构建就会把它提成 <name>-<hash>.js 共享 chunk,lib/client.js 顶部随之多出一条 import ... from './<name>-<hash>.js';而 DSH 的 client 模块加载器按单文件取 /plugins/<pkg>/client.js(合并 bundle 的 ??pkg/client.js,... 协议不会去拉那个相对 chunk),于是整个 client 半静默失效——2026-09-14 实测现象是工具栏连同所有功能按钮一起消失、页面无报错,而 host 路由仍正常响应(很容易误判成服务端问题)。当时触发它的是 src/favorites.ts;那个文件后来并入了 pinned.ts 与 legacy-favorites.ts,当前两半没有交集,但配置保持分开——这个坑一旦出现是静默的,不值得赌。
同步 vendor 时同理:产物不保证就是固定两个文件,要整目录镜像并清掉不再产出的旧 hash 文件,别只复制 client.js/index.js。
另外 host 半用 platform: 'node'(对其本来语义正确),该组合下 ESM 默认输出 .mjs,已用 outExtensions 钉死 .js 以匹配 package.json 的 main/exports。
SSiD 的 profile 以 file:./vendor/dsh-quick-toolbar 声明本插件,其 client 半因此不在 DSH 的 client modules 表里:artifactBaseline(id) 返回 undefined,而 HMR 的监听集正是「graph 中能提供 baseline 的行」(packages/client/hmr/src/index.ts:128-141,artifactBaseline 见 packages/client/modules/src/index.ts:624)。
实测(2026-09-14):改 node_modules 或 vendor 任意一份 lib/client.js 的内容,30 秒内无任何重载反应;同一时刻改 npm 包形式的 dsh-chat-rail(0.6.1)3 秒即重载。后果:改本插件的样式或逻辑后需重启内核才生效(发版/归档流程不受影响——那本就是重新部署)。
待办:查清这是 DSH 的既定行为,还是我们的声明方式可调。
file: 依赖可换写法(例如改回 npm 包声明、vendor 只作归档源)→ 本插件即可恢复热更新。已做的兼容(commit 47c86ca):apply 的样式注入已改为幂等 + 内容比对,并提到防重守卫之前——一旦它被重载(插件中心禁用/启用、内核重启,或将来 HMR 覆盖到它),不会重复注入,SHELL_CSS 也能在壳标志晚到时补进去。
SSiD 全家桶(max-null-plugins)的一员;SSiD 壳内与标题栏桥接协作(__SSID_SHELL__ 分支)。