dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
DSH 插件(Web 版 / 桌面版通用):输入框上方常驻快捷条 + 闪电笔弹层,点选预设提示词追加到原有内容之后(不清空),可按条开启自动发送、可设序号排序,支持 MD 导入导出;数据存全局 ~/.dsh/quick-prompts.json 永不丢失
English: A DeepSeek Harness (DSH) quick prompt input plugin that works in both the Web profile and the Desktop app — a persistent two-row shortcut bar (row 1: categories, row 2: titles) above the input field, plus a "lightning pen" popup whose top row holds an "MD 管理" dropdown (import / export / copy) and a category dropdown + ‹ › / ⋯ / 新增 / 修改 / 撤销重做 (pick a category, add into it, edit only that category, rename or delete a whole category, bulk select/move/delete, undo-redo, cross-category search, and a server-side conflict check before saving); clicking a prompt appends its content after whatever is already in the input box (nothing is cleared, nothing is sent). Each prompt can optionally enable auto-send (⏎ icon; replaces the draft with that prompt and submits immediately via the official submit channel) and carry a numeric order index (prompts render left-to-right sorted by index ascending). Prompts are stored globally in ~/.dsh/quick-prompts.json, so they survive environment restarts and project switches — and the same file is shared by the Web profile and the Desktop app. Prompts added or changed anywhere (another window, a CLI, an AI editing the file) appear in the bar within 2 seconds — no page reload needed; unchanged data causes zero re-renders. Both rows always stay a single line: when the content overflows, press and drag the row sideways to reveal the rest (no wrapping, no extra height).(中文说明见下)
DeepSeek Harness (DSH) 插件:输入框快捷输入(分类快捷条 + 闪电笔),Web 版与桌面版通用。
📦 本仓库只放插件本体(公开)。提示词 / 快捷语 / 用户侧文档 / 密钥属于私有仓库 lnyuqian/dsh-quick-prompts-data; 在本目录做提交前请先读 AGENTS.md。
输入框上方常驻横向快捷条:第一行显示分类、第二行显示当前分类下的标题;鼠标悬停分类即切换下方标题;点击标题把内容追加到输入框原有内容之后(不清空已输入的内容,也不自动发送)。工具行「权限切换」右侧另有闪电笔按钮,弹层顶部是「MD 管理」下拉(导入 / 导出 / 复制三个动作收在一个下拉里)与「分类」下拉 + 新增 / 修改:选定分类后「新增」把新条目放进这个分类、「修改」只列出这个分类的条目,保存前还会先查一次冲突。数据存全局 ~/.dsh/quick-prompts.json,重启环境、换项目都不会丢,Web 版与桌面版共用同一份数据;v0.7.11 起别处新增/修改的提示语最长 2 秒自动出现在条上,不用手动刷新页面。
padding:4px/0px/6px/0px),两行首控件左边缘一致(实测 281 = 条左 280 + 边框 1),这段空位全部让给分类与提示语;条高仍是 61px。#2563eb,实测 rgb(37, 99, 235))标识,那一格的宽度也还给了文字。闪电笔弹层里的 ⏎ 图标样式保持不变(面板 UI 不动)。快捷输入 · 分类下拉 · ‹ › · ⋯ · 新增 · 修改 ·(右)搜索 · MD 管理(编辑态则是 …↶ ↷ · 新增 · 取消 · 保存)。
去掉了左边的「分类」二字;分类下拉与搜索框各 6 字宽 + 10px(calc(6em + 10px),实测都是 82px @12px 字号);
‹ 在分类下拉左边、› 在右边(夹住下拉,实测 prevStep.right 369 ≤ select.left 375、nextStep.left 463 ≥ select.right 457),两个箭头各 22×22;成功提示改成贴在这一行里的省略号文本,不再单独占行。
顶部一行 37px(实测),列表因此多出约 80px —— 可见提示语从 12 行增到 15 行。
同时修掉一个实测抓到的真 bug:弹层是纵向 flex,内容一多头部会被压扁(控件被 overflow:hidden 裁掉)→ 现在只有列表伸缩,其余(头部 / 提示 / 冲突条 / 批量条)一律 flex:none。/api/quick-prompts,任何写入者(另一个窗口 / 命令行 / 别处的 AI 直接改 ~/.dsh/quick-prompts.json)落盘后最长 2 秒自己出现(实测 1353ms / 1126ms)。
以前只有四个刷新时机:打开弹层、窗口重新获得焦点、页面重新可见、弹层开着时的 60 秒兜底 —— 坐在窗口里不动由别处改数据,四个一个都不触发,只能整页重载(而 DSH 的菜单里并没有刷新入口)。
内容没变时零通知、零渲染(实测 2.4 秒内 GET 从 1→2,而重渲染次数 2→2 纹丝不动);轮询不占用 loading(那是保存前冲突探测的忙判据,共用会让 2 秒一次的轮询挤掉一道保护);页面不可见时不轮询,回到前台立刻补一次。
顺手修掉一个假警报:编辑期间服务端没变也会挂「数据已在别处更新」——原来先看编辑锁、后比指纹,现在先比指纹(实测:编辑中 2.4 秒无变化 → 无提示;别处真改后 1126ms 出提示,且正在输入的标题一个字符都没被覆盖)。
「MD 管理」下拉里新增 「重载界面」:提示语数据已经不用刷了,但插件代码更新后仍需整页重载,DSH 菜单里没有这个入口,就补在这里(编辑中不可点,免得丢掉未保存的编辑)。input + datalist,浏览器会按当前值过滤候选项,必须先删掉当前分类才能看到别的分类。)Esc 分三层 —— 先撤冲突提示 → 编辑态等于「取消」(回浏览态、面板不关)→ 再按才关面板。「MD 管理」下拉在编辑态会说明为什么导出/复制暂时不可用。常用(8),旁边一对 ‹ › 按钮直接跳上/下一个分类(分类多了比展开下拉快)。常用(1/2)),留空即恢复原样。⋯ 打开菜单 —— 「重命名分类」把该分类的所有行一起改名(每行分别去改太费事);「删除这个分类」把它的条目逐条标记为待删除,保存前都能「恢复」。↶ ↷,也支持 Ctrl/⌘ + Z 撤销、Ctrl/⌘ + Shift + Z(或 Ctrl + Y)重做;从进入编辑态那一刻打底,之后每个动作一个快照(上限 50 步)。max-width:calc(100vw - 16px),手机窄屏不会被撑出屏幕。ROW_H / DOCK_CLEARANCE …),CSS 与定位算法不会两边各写一个数。### 解析分类、无序列表解析标题、缩进列表解析内容;同名标题跳过、其余合并追加。quick-prompts.md;桌面版另有「MD 管理 → 复制MD」,把同一份 MD 文本写入剪贴板——桌面外壳的下载通道受宿主策略影响,剪贴板是可靠退路。~/.dsh/quick-prompts.json(DSH_HOME 目录下),与会话、项目无关,Web 版与桌面版共用;旧版按项目存放的数据可在新版里重新导入。assets/快捷输入.svg,以 currentColor 内联渲染,自动跟随明暗主题与悬停色。localStorage,不写三端共用的数据文件,手机收起不会连累电脑)。input + datalist 会按当前值过滤候选项,必须先删干净才能选别的)。选「+ 新建分类…」进入输入模式,选「选择已有…」回到下拉。### 分类名
- 快捷语标题
- 快捷语内容(可多行,多条缩进行自动拼接)
- 自动发送的标题 ⏎
- 内容(该条开启自动发送:导出时标题尾部带 ⏎ 标记,导入时识别还原)
dsh web / web profile)方式一:一键安装(推荐) 通过 DSH 命令行从 GitHub Release 安装到你的 web profile:
dsh plugin --profile web add "https://github.com/lnyuqian/dsh-quick-prompts/releases/latest/download/dsh-quick-prompts.tgz"
该命令会安装依赖并把本插件登记为 profile 的 bundle(自动识别 dsh.bundle),随后重启 dsh web 并刷新页面即可生效。
方式二:本地开发安装
git clone https://github.com/lnyuqian/dsh-quick-prompts.git
cd dsh-quick-prompts
dsh plugin --profile web add "link:<本仓库的绝对路径>"
# 重启 dsh web 并刷新页面
桌面版跑的是 desktop profile,这个 profile 由 Electron 独占管理:全局 dsh CLI 会直接拒绝它
(error: profile "desktop" is managed exclusively by the Electron application)。所以有两条路:
方式一:应用内插件管理(推荐,无需重启)
桌面版运行时打开 设置 → 插件 安装,或直接让 DSH 助手用内置的 plugin_manager 安装:
帮我把
<本仓库的绝对路径>装进桌面版:用 plugin_manager 的 install_bundle, target 传link:<本仓库的绝对路径>。
宿主会热重组配置并让页面按需加载新 bundle —— 不需要重启桌面版。
方式二:完全退出桌面版后用脚本安装
# 先完全退出 DeepSeek Harness(CLI 需要独占 profile/package.json)
cd <克隆下来的插件目录>
powershell -ExecutionPolicy Bypass -File .\install-desktop.ps1 # link 安装(默认)
powershell -ExecutionPolicy Bypass -File .\install-desktop.ps1 -Mode Tarball # 从 tgz 安装
powershell -ExecutionPolicy Bypass -File .\install-desktop.ps1 -Uninstall # 卸载
脚本调用的是桌面安装自带的 CLI 载体(app.asar 内的 dsh-desktop-host/lib/cli.js,带
manageDesktopProfile 权限),因此能合法管理 desktop profile。
Web 版:重新执行上面的 dsh plugin --profile web add ...,然后重启 dsh web 并刷新页面。
桌面版:link 安装时改代码即生效(重启或等宿主热重组);tgz 安装时重新执行安装命令。
也可以直接把上面的命令发给你的 DSH 助手:“帮我升级 dsh-quick-prompts”。
桌面客户端(Electron)渲染的是同一套 Web 前端,页面挂在自定义协议 dsh-app://app/ 下,因此:
| 关注点 | 桌面版行为 |
|---|---|
| 槽位 | conversation.input.dock / conversation.input.left 与 Web 版完全相同,快捷条与闪电笔直接复用 |
/api/quick-prompts | 页面里相对路径的 fetch 由 Electron 主进程 forwardWebRequest 带上认证 cookie 转发到本地 webserver(方法、请求体原样转发),因此服务端半部不用改 |
| 数据文件 | 同一个 ~/.dsh/quick-prompts.json —— Web 版与桌面版共享同一份快捷语 |
dsh.client.platform | 仍然是 "web":桌面端复用的就是 web 客户端载体(dsh-client-modules 只认 platform === 'web'),改成别的值反而会导致客户端半部不被加载 |
| 弹层定位 | 桌面窗口通常更小,弹层改为按可视区自适应(向上/向下展开、左右夹紧、按可用空间限高) |
| MD 导出 | 「MD 管理」下拉里另提供「复制MD」(仅在桌面端出现),下载通道异常时可把同一份 MD 文本写入剪贴板 |
### 分类 / 列表标题 / 缩进内容 解析导入(同名标题跳过)。Esc 依次用来撤提示、退出编辑态、关面板。‹ › 换分类、⋯ 里重命名/删除整个分类;每行左侧勾选框 → 批量移到别的分类或批量删除;标题行 ↶ ↷(或 Ctrl+Z / Ctrl+Shift+Z)撤销重做;说明行右侧切「只看本分类 / 显示全部」。浏览态顶部的搜索框按标题/内容跨分类过滤。⠿ 把手上下拖,松手即重排该分类的序号;不习惯拖拽就用每行的「序」下拉,两者等价。拖错了 Ctrl+Z 退回。两类状态刻意分开存:快捷语内容存共享的
~/.dsh/quick-prompts.json(三端一致、永不丢),快捷条是否收起存本设备localStorage(各设备独立)。
| 半部 | 说明 |
|---|---|
lib/index.js(服务端) | 注册 GET/POST /api/quick-prompts,读写全局 ~/.dsh/quick-prompts.json(v2 分类结构,自动兼容旧 v1 平铺并迁移为「默认」分类)。Web 版由 webserver 直接处理;桌面版由 Electron 主进程把 dsh-app://app/api/... 带认证 cookie 转发到同一张路由表 |
lib/client.js(浏览器) | 纯 JS(React.createElement,无构建),通过 window.__ModuleLoader__.load 注册,注入 conversation.input.dock(常驻横向条)与 conversation.input.left(闪电笔弹层),持久化走 /api/quick-prompts。点击条目时经 useInput 快照(或 dock owner 的 InputState,再退化为 DOM)读取当前草稿,追加后交 inputActions.setDraft 写回 |
这两条都是桌面版实测踩出来的坑,写成约定以免回归:
| 约定 | 不遵守的后果 | 正确做法 |
|---|---|---|
webServer.register() 返回的 disposer 必须挂进 ctx.effect | 每次 HMR 重组 / 插件启停都会重复注册同一路径,第二次直接 webserver: duplicate exact route → 整条插件行激活失败(桌面版安装会连续组合多次,必现) | ctx.effect(() => webServer.register({ ... }));并对同进程重复注册做窄容错:只吞 duplicate 并告警,其余错误照抛 |
注入的 <style> 必须带 data-plugin="<包名>" 归属标记,且要在 factory 物化期注入 | 客户端模块系统按 data-plugin 认领/回收 bundle 样式;标记或时机不对时,宿主图更新会把 <style> 收走,而插件实例还挂着 → 界面退化成浏览器默认样式、布局整体塌陷(「UI 易位、改变形态」) | 物化期 ensureStyles() 注入并显式打 data-plugin;apply 里再用 MutationObserver 观察 document.head,被回收时自动重注入 |
node test-load.mjs # 载入自检:客户端 bundle 能加载 / 能物化 / 导出完整 / 零日志 / 按钮与三角真的渲染出来
node test-append.mjs # 点击=追加而非覆盖(含 useInput / DOM 兜底 / 自动发送)+ 样式注入归属 + 折叠渲染
node test-parser.mjs # MD 解析与合并(分类、⏎ 标记、序号稳定排序)
node test-roundtrip.mjs # 导出 ↔ 导入 往返一致
node test-desktop.mjs # 桌面适配:弹层定位、dsh-app 环境识别、复制MD 兜底
node test-server.mjs # 服务端半部:路由生命周期/重复注册容错 + 隔离 DSH_HOME 下的读写往返
node test-collapse.mjs # 折叠默认值与每设备记忆(窄屏默认收起、记录优先、localStorage 不可用时回退)
node test-category.mjs # 分类下拉:选项来自全部分类(含草稿内新分类),切换无需先清空当前值
node test-drag.mjs # 单行 + 按住拖动(没超宽不接管、位移不足仍算点击、拖动中不误切分类、拖完不吃下次点击)
node test-panel-header.mjs # 弹层工具行(MD 管理下拉 / 分类下拉 / 新增 / 修改)+ 删除可撤销 + 保存前冲突 + 搜索 / 批量 / 撤销重做 / 分类操作(17 项)
node test-hold-to-send.mjs # 长按 300ms 才发:短按只填入、长按才发送、普通条目不变、拖动不算点击(8 项)
node test-row-reorder.mjs # 拖拽排序:分类内换位 + 序号重排 1..N、落点计算、边界与其他字段保留(7 项)
node test-refresh.mjs # 外部变化刷新 + 编辑锁 + 自动同步:首拉/重拉/节流/编辑期间只暂存/2 秒自动同步/假警报回归(12 项)
npm test把它们按顺序串起来跑(约 3 秒)。其中test-load.mjs排在第一位: 它真的把lib/client.js加载并物化一遍 —— 2026-10-17 出过一次「删函数漏删internals导出引用 → 模块一加载就抛ReferenceError→ 闪电笔按钮与折叠三角全都不显示」,node --check查不出来,这一条能立刻拦住。可选:提交闸门(把这个仓库当 link 安装用时尤其值):
git config core.hooksPath .githooks # 之后 git commit 会先跑 test-load.mjs
dsh-quick-prompts/
├── package.json # dsh.bundle.patch + dsh.client.platform: web(web/desktop 共用)
├── dsh.plugin.json # 插件清单
├── cordis.patch.yml # 宿主组合补丁(注册服务端插件行)
├── install-desktop.ps1 # 桌面版安装/卸载脚本(走桌面自带的 CLI 载体)
├── lib/index.js # 服务端半部
├── lib/client.js # 客户端半部
├── test-*.mjs # 回归测试
└── assets/快捷输入.svg # 按钮图标源文件
MIT