Eidosiny
dsh-accessory-hub
配件中心(Accessory Hub):DSH Web GUI 悬浮卡片插件 —— 可拖动/可缩放,聚合插件、MCP、预设、技能卡片,支持自定义显示名与颜色、彩色关系连线、确认注入"请使用xxx"前缀。A floating-card plugin for the DeepSeek Harness Web GUI.
- Stars
- 1
- Language
- JavaScript
- Created
- Aug 16, 2026
- Updated
- Aug 16, 2026
Introduction
配件中心(Accessory Hub)
DSH(DeepSeek Harness)Web GUI 悬浮卡片插件:右上角折叠圆形(DeepSeek 鲸鱼图标)→ 点击展开浅色便签纸风格画布(米黄格子底 + 便签卡片)。
只显示你手动添加的配件(插件 / MCP 服务 / Agent 预设 / 技能,DSH 自带配件不会自动上画布),支持:
- 自定义显示名与颜色
- 彩色连线表示附属 / 兼容关系(可点击编辑、删除)
- 选中卡片高亮关联连线、其余变暗
- 底部「确认使用」:在下一条用户消息开头注入「请使用<显示名>」前缀(如
请使用llm-vision-mcp 分析一下这张图片) - 悬浮卡本体可自由拖动(圆形 / 标题栏,位置联动记忆)、右下角手柄自由调节尺寸
- 所有自定义持久化于
DSH_HOME/accessory-hub/state.json,刷新/重启后保留
安装
要求
- DeepSeek Harness(
@deepseek-ai/dsh)web profile 已可运行(dsh --profile web) - Node.js 环境(DSH 自带)
方式一(推荐):cordis.patch.yml 显式装配
-
把本仓库放到 web profile 的 vendor 目录(确保
lib/index.js与lib/client.js存在):git clone https://github.com/Eidosiny/dsh-accessory-hub.git \ <DSH_HOME>/profiles/web/vendor/dsh-accessory-hub -
编辑
<DSH_HOME>/profiles/web/cordis.patch.yml,追加一个插件行:- insert: - id: dsh-accessory-hub name: '@dsh-external/dsh-accessory-hub' config: {} -
重启 web:
dsh --profile web(或你的启动方式),然后刷新浏览器页面(客户端 bundle 在页面加载时装配)。 -
右上角出现鲸鱼圆形按钮即安装成功。
方式二:super-injector 运行时注入(免重启)
在 DSH 会话中使用超模注入器(dsh-super-injector)提供的 dev_inject_plugin 工具,或在其设置页「插件」中拖入 / 输入插件目录路径后「注入」:
dev_inject_plugin <本仓库绝对路径>
⚠️ 常见错误:不要加进 dsh.profile.bundles
本包只声明 dsh.client(客户端注入包),没有 dsh.bundle.patch。把它写进 profiles/web/package.json 的 dsh.profile.bundles 会让 dsh web 启动即失败:
Error: dsh: profile bundle "@dsh-external/dsh-accessory-hub" declares no dsh.bundle in its package.json
客户端 bundle 的正确装配路径是 cordis.patch.yml 插件行(方式一):client-modules 会扫描 loader entries 中声明 dsh.client.platform: "web" 的包,自动把 exports["./client"] 指向的 bundle 挂到 /plugins/<id>/client.js 并在页面加载时注册。
结构
lib/index.js— 宿主侧插件:提供GET/POST /accessory-hub/api/*REST API(配件枚举 + 自定义状态持久化;skills 带文件系统兜底枚举DSH_HOME/skills/;MCP 服务单独归类:检测config.serverName的 loader 条目 →mcps数组,含 transport/url/command/args)。lib/client.js— 客户端 bundle:shell.overlay槽位注册 React FC(浅色主题、米黄格子画布、添加/删除配件、拖动、编辑、连线、高亮、前缀注入)。package.json— 包元数据 +dsh.client客户端注入声明。
使用
- 点右上角圆形按钮展开面板(悬浮卡可自由拖动且位置联动:折叠态拖圆形按钮、展开态拖标题栏 ⠿,两者共用同一位置锚点——面板默认从圆形向左展开(右上角钉在圆形右上角),拖任意一方另一方跟随,位置自动记忆);面板尺寸可调:拖右下角 ⤡ 手柄自由缩放(最小 360×280,上限视口),尺寸同样持久化;
- 「+ 添加配件」从目录(插件 / MCP / 预设 / 技能,可搜索、按类过滤)选择要上画布的配件;MCP 服务按 serverName 列出(如
vision、playwright),描述显示传输方式与端点(stdio · npx -y @me9rez/llm-vision-mcp等),可改名(如llm-vision-mcp); - 画布上拖动排布、✎ 编辑显示名与颜色、删除卡片(✎ → 删除卡片,关联连线自动清理);
- 「连线模式」点两张卡建立关系(附属=实线/兼容=虚线,颜色取起点卡色),点线可改关系/颜色/删除;
- 点击卡片选中(关联线高亮、其余变暗),底部「确认使用」把「请使用<显示名>」注入输入框草稿开头(无当前会话时提示)。
宿主 API
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /accessory-hub/api/catalog | { ok, plugins:[{id,name,active}], mcps:[{id,name,transport,url,command,args,active}], presets:[{id,name,description,broken}], skills:[{name,description,provider}], warnings } |
| GET | /accessory-hub/api/state | 读 DSH_HOME/accessory-hub/state.json,不存在/损坏回 {} |
| POST | /accessory-hub/api/state | body { state: {...} },浅校验后原子写回(tmp + renameSync) |
持久化状态 schema:{ version, plugins, presets, skills, mcps, edges, ui },各配件 section 以配件 id 为键存 { label, color, x, y };edges 存关系连线,ui 存悬浮卡位置与面板尺寸。原子写复用 tmp + renameSync 模式。
安全性
详见 SECURITY.md。要点:
- 无远程网络请求:宿主侧只使用 Node 内置模块,不发起任何对外 HTTP;客户端只请求同源
/accessory-hub/api/*。 - 无任意代码执行:无
eval/new Function/ 子进程 / shell。 - 无 XSS:客户端全部通过 React 文本节点渲染(无
innerHTML/dangerouslySetInnerHTML),卡片名、目录描述等输入均被转义。 - 本机隔离:API 只绑定 DSH web 的回环地址(默认
127.0.0.1),响应不带 CORS 头 → 跨源网页无法读取或写入。 - 写入受限:POST
/state有 2MB 体积上限 + 浅校验,只写固定路径DSH_HOME/accessory-hub/state.json(原子 tmp+rename),无路径穿越面。 - 数据面最小:只读 loader 条目 / 预设 / 技能目录的元数据(名称、描述),不读取文件正文(技能仅读 SKILL.md 首行做描述)。
服务注入
宿主侧:webServer、loader、agentPresets、skills。
客户端侧(dsh.client.inject):@deepseek-ai/dsh-client-runtime、@deepseek-ai/dsh-client-ui-layout、@deepseek-ai/dsh-client-ui-conversation。