dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
DeepSeek Harness(DSH) Web 插件。新建对话时输入 /,可以从本地目录里的 .md 提示词模板中选一个。模板的约束力等同于 AGENTS.md,对这个对话之后的每一轮都有效。还可以设置对所有新对话生效的全局提示词,用 {{env:变量名}} 在提示词中引用环境变量,并通过 WebDAV 在多台设备之间同步提示词模板和环境变量。还可以开启删除对话,在左侧对话栏的菜单中彻底删除对话。
>=0.1.7-alpha.1,即 0.1.7 系列的 alpha 版及之后的正式版;Node >=22.19package.json 里声明了 dsh.bundle.patch 和 dsh.client,Host 半和 Browser 半都是纯 ESM,没有运行时依赖,安装时不需要构建| 设置页 | 设置 → 提示词模板:选择模板目录(弹出系统文件夹对话框,也可以直接填路径),读取目录第一层的全部 .md 文件(不读子目录),每个模板有激活开关和「编辑」按钮,另有「刷新」按钮 |
/ 菜单 | 已激活的模板按文件名显示在 / 菜单里,默认排在 Harness 自带指令之前(可以关闭) |
| 约束整个对话 | 选中模板并发送第一条消息后,模板以 AGENTS.md 同样的方式写入会话,之后每一轮都生效。上下文压缩、恢复会话、分叉会话后都会保留 |
| 只对新对话生效 | 已经进行过对话的会话里使用模板会被拒绝:模板不生效,消息也不发出,草稿保留 |
| 全局提示词 | 选一个 .md 文件(以文件名作为名称),或者直接输入一段文本并为其取名(保存为模板目录下的 名称.md),作为全局提示词。开启后,之后新建的每个对话都会遵守它;在新对话里再用 / 选择模板时,模板追加在全局提示词之后,两者同时生效,不会互相覆盖 |
| WebDAV 云同步 | 独立的「WebDAV 云同步」标签页:配置服务器、可选的 HTTP / SOCKS5 代理、一键测试连接;「同步到本地」「同步到云端」列出对方目录第一层的 .md 文件,勾选后同步,遇到同名文件逐个询问是否覆盖(可全部覆盖 / 全部跳过) |
| 环境变量 | 独立的「环境变量」标签页:每行一个变量(变量名 + 字符串),可新增、修改、删除。提示词模板和全局提示词里的 {{env:变量名}} 在发送给模型前替换为对应的值,未定义的变量直接删除 |
| 环境变量同步 | 「WebDAV 云同步」里的「同步环境变量文件」开关:环境变量文件放在 WebDAV 目录根目录,支持「合并配置文件」「本地覆盖云端」「云端覆盖本地」;合并时同名同值合为一条,同名不同值逐个选择用云端还是本地的值 |
| 删除对话 | 独立的「允许删除对话」标签页(默认关闭):开启后,左侧对话栏每个对话的「…」菜单在「置顶 / 重命名 / 分叉 / 归档」之后多出红色的「删除对话」,确认后彻底删除该对话,不可撤销;「工作区」右侧的「视图选项」菜单多出红色的「删除所有已归档」,确认后删除全部已归档对话 |
| 模板编辑 | 整页编辑视图:大号等宽编辑框,Ctrl+S 保存,显示未保存状态,检测保存冲突,并自动同步在外部编辑器里所做的修改。「用其他程序打开…」会弹出系统的“打开方式”对话框,由你自己选择编辑器 |
git clone https://github.com/mikulo/dsh-plugins.git
cd dsh-plugins
node install.mjs --profile web --only dsh-prompt-switcher
dsh plugin --profile web add github:mikulo/dsh-prompt-switcher
安装后重启 dsh web 并刷新页面。
dsh plugin --profile web update @mikulo/dsh-prompt-switcher,然后重启 dsh webdsh plugin --profile web remove @mikulo/dsh-prompt-switcherDSH 仍是测试版,可能有破坏性更新。本插件和 DSH 本身都做了隔离,插件出问题时一般只是功能失效,不会导致 DSH 起不来:
万一升级后 dsh web 异常,可以:
dsh plugin --profile web remove @mikulo/dsh-prompt-switcher,再启动 dsh web。设置和环境变量文件保存在 ~/.dsh/,不会丢失。dsh --profile rescue(profile 里只列 @deepseek-ai/dsh-base 和 @deepseek-ai/dsh-web-app 两个 bundle)。插件的 Browser 半会随页面热更新,Host 半必须重启
dsh web才会加载新代码。两边版本不一致时,设置页顶部会提示“请重启 dsh web”。
*.md 文件,扩展名不区分大小写。列表按文件名显示。/,已激活的模板(例如 代码审查)会出现在菜单里。继续输入文字可以过滤。/代码审查 再按空格)后,输入框为 /代码审查 ,接着输入第一条消息并发送。发送时插件识别开头的模板名并绑定模板,之后这个对话的每一轮都会遵守该模板。
/代码审查 以普通文字显示(不再变成蓝色命令词)。这是为了绕开 DSH 输入框的一个问题:命令词高亮会打断中文输入法的组字,导致拼音重复、文字变蓝且无法删除。/ 键会输入 、。输入框开头的 、(或全角 /)会自动换成 /,同样弹出模板菜单,两者等效。句子中间的 、(如“苹果、香蕉”)不受影响。仓库里的 examples/ 有两个示例模板,可以把它设为模板目录来体验。
在 设置 → 提示词模板 → 全局提示词 中配置:
.md 文件中选一个,文件名(不含扩展名)就是全局提示词的名称。之后更换模板目录不影响已选的文件。名称.md(需要先配置模板目录),之后也会出现在模板列表里,可以用「编辑」修改。目录中已有同名的其他文件时,会先询问是否覆盖。改名后保存会写入新文件,旧文件保留。规则:
/ 选择模板时,会话里依次是 全局提示词 → 模板 → 你的第一条消息。模板追加在全局提示词之后,两者同时生效。/ 菜单中的模板说明会显示“追加在全局提示词「…」之后”。在 设置 → 提示词模板 顶部切换到「WebDAV 云同步」标签页:
https://dav.jianguoyun.com/dav/prompts/)、用户名和密码(坚果云等服务请使用应用专用密码)。密码只保存在本机,不会回传到页面;再次保存时密码框留空表示保持不变。127.0.0.1:7891,可以修改。开关决定「测试连接」和同步是否经过代理。暂不支持需要认证的代理。同步(只处理两边目录第一层的 .md 文件,不含子目录):
.md 文件,默认全部勾选,「全选 / 取消全选」一键切换。点「同步到本地」下载到模板目录。.md 文件,操作同上,上传到云端目录;云端目录不存在时自动创建。说明:只支持 Basic 认证;单个文件上限 1 MiB;配置保存在 $DSH_HOME/dsh-prompt-switcher.json,其中密码是明文。
打开「同步」下方的「同步环境变量文件」开关(默认关闭)后,点「同步环境变量…」。插件同时读取本地和云端的 dsh-prompt-switcher.env.json(云端位于 WebDAV 目录根目录),显示两边各有多少变量、哪些相同、哪些只在一边、哪些同名但值不同,然后选择同步方式:
| 情况 | 可选方式 |
|---|---|
| 两边都有文件 | 合并配置文件:两边的变量合并成一份,同时写入本地和云端。同名且值相同的合并为一条;同名但值不同的逐个列出云端和本地的值,由你选择(也可以「全部使用本地 / 全部使用云端」) 本地覆盖云端 / 云端覆盖本地:会被覆盖的一方如果有独有的变量,执行前会列出并确认 |
| 只有本地有 | 上传到云端(云端目录不存在时自动创建) |
| 只有云端有 | 下载到本地 |
| 两边完全一致 | 提示无需同步 |
同步时 Host 会重新读取两边的文件;比较之后如果文件又有变化,出现新的冲突时会重新让你选择。
在 设置 → 提示词模板 顶部切换到「环境变量」标签页:
{{env:变量名}} 复制到剪贴板。_ 开头,只能包含字母、汉字、数字、_、.、-,不能重复(区分大小写)。变量名和值都为空的行保存时忽略。{{env:变量名}}(花括号内允许空格,如 {{ env: github_api }})。例如变量 github_api = 123456,模板里的 github的api是{{env:github_api}} 发送给模型时是 github的api是123456;如果没有定义这个变量,就变成 github的api是。{{env:…}} 这一种写法。{{name}}、<name>、${name} 等其他写法原样保留,不会被误删。环境变量保存在 $DSH_HOME/dsh-prompt-switcher.env.json(默认 ~/.dsh/dsh-prompt-switcher.env.json),格式如下,也可以手动编辑(手写成 { "变量名": "值" } 这样的简单对象同样能识别):
{
"version": 1,
"variables": [
{ "name": "github_api", "value": "123456" }
]
}
这个文件不在模板目录里,卸载或重装插件都不会丢失。
DSH 自带的对话菜单只能归档,不能删除。本插件可以加上删除功能:
删除时插件会:
dsh web 进程中已加载的实例,然后删除它在 ~/.dsh/sessions/<项目>/<会话 ID>/ 下的会话记录,连同它的子代理会话一起删除,并清理它的投影缓存、置顶和归档记录。开关打开后,点击左侧对话栏「工作区」文字右侧的「视图选项」按钮,筛选菜单「隐藏已归档 / 全部对话(显示已归档)/ 仅显示已归档」下面多出红色的「删除所有已归档」。点击后弹出确认框「是否删除所有已归档的对话,删除不可撤销」,并显示将删除的对话数量;点「是」后逐个删除全部已归档的对话(每个都按上面的流程,连同子代理会话),某个失败不影响其余的,失败项会列在确认框里。指向已不存在会话的归档记录会顺便清掉。
这个菜单在 DSH 里是写死的列表,没有提供插件槽位,所以插件在菜单弹出时向它的页面元素里追加这一行(通过菜单的 …_viewOptionsMenu 样式类或「隐藏已归档」这一行识别,外观复用原有菜单行的样式)。DSH 以后改了这个菜单的结构时,这一行可能不再出现,但不会影响菜单原有的功能。
说明:
dsh web 后完全消失。~/.dsh/dsh-prompt-switcher.json 的 allowDeleteSession 字段,重装插件不会丢失。sessionPersistence.locate()),所以用 DSH_HOME 等方式改了数据目录,或在配置里改了会话存储根目录,删除都会作用到实际的位置;DSH 程序本身装在哪个目录与此无关。插件的设置文件同样遵循 DSH_HOME(支持 ~/… 写法)。在列表中点「编辑」进入编辑视图:
| 需求 | 实现 |
|---|---|
| 设置页面 | Browser 半向 settings.section 槽位注册页面 |
| 文件夹对话框 | 优先使用 Host 的 directoryPicker 服务(原生对话框)。该服务不可用时,Windows 上用 PowerShell 的 FolderBrowserDialog,其他平台提示手动输入 |
| 设置与模板读写 | Host 路由 /api/dsh-prompt-switcher/*,只接受本机回环地址的请求。只接受当前目录扫描结果里的文件名,访问不到目录以外的路径。配置保存在 $DSH_HOME/dsh-prompt-switcher.json(默认 ~/.dsh) |
/ 菜单显示中文名 | Host 命令名只能用 ASCII,所以 Browser 半注册了自己的 / 输入触发源。选中后只插入普通文本 /模板名 ,按 Enter 时由触发源的 matchEnter 认领草稿,提交 Host 命令 /prompt-template <模板id> <消息>。不使用 onPick / matchSpace 认领,因为 DSH 的认领高亮会在输入法组字期间拆分文本节点。置顶就是调整触发源的 order |
、 等效于 / | DSH 的触发检测只认 ASCII /(TriggerChar 只有 / 和 @),所以 Browser 半在 document 上(捕获阶段)监听输入框 [data-composer-input] 的事件:直接提交的 、 在 beforeinput 中拦截并改插 /;输入法组字提交的 、 在 compositionend 之后选中并替换为 /。只处理输入框开头(前面只有空白)的位置,不修改 DSH 本体文件 |
| 绑定模板 | Handler 先确认这是新对话,然后 agent.inject(模板消息),再 agent.steer(用户消息),与官方 /plan 的做法相同 |
| 约束力等同于 AGENTS.md | 模板以带来源 {kind:'prompt-switcher', form:'instructions'} 的 <system-reminder> user 消息写入会话日志,措辞与 dsh-agent-instructions 一致,即不高于 system、developer 或用户的直接指令 |
| 持续生效 | 会话投影从完整日志中折叠出已绑定的模板快照,所以恢复和分叉会话都能还原。agent/pre-step 钩子在模板被上下文压缩掉后,重新注入同一份快照 |
| 全局提示词 | agent/pre-step 钩子在新顶层对话的第一轮,把全局提示词以来源 {kind:'prompt-switcher-global', form:'instructions'} 的 <system-reminder> 消息放在本步消息最前面;通过 / 模板开始的对话,由命令 handler 依次注入 全局提示词 → 模板 → 用户消息。同一会话投影同时折叠全局提示词和模板快照,压缩后按同样顺序补回 |
| WebDAV 同步 | Host 半只用 Node 内置模块实现 WebDAV 客户端(PROPFIND 列目录、GET 下载、PUT 上传、MKCOL 建目录,Basic 认证)。代理:HTTP 代理用 CONNECT 隧道,SOCKS5 由代理解析域名,隧道建立后再按需做 TLS。只接受当前列表里的文件名;是否覆盖同名文件由 Host 在写入前重新检查 |
| 删除对话 | Browser 半向官方槽位 sidebar.workspaces.session.menu.item 注册菜单行(order 500,排在归档之后,danger 红色样式),确认框注册在 shell.overlay(菜单关闭时会卸载,确认框不能放在菜单里)。Host 路由 POST /api/dsh-prompt-switcher/session-delete 依次:用 workspaceRegistry.archiveSession(id, { stopActivity: true }) 停止工作,通过 Agent 生命周期 effect(agentLoop.lifecycle(<id>))卸载已加载的实例,按 sessionPersistence.locate() 找到并校验会话目录后删除(含 origin: 'subagent' 的子会话),删除投影缓存行,清理置顶 / 归档记录,最后发出 api-session/removed 让所有页面移除该行 |
| 环境变量 | Host 在绑定模板 / 全局提示词时读取 $DSH_HOME/dsh-prompt-switcher.env.json,把 {{env:NAME}} 替换为对应的值(未定义则替换为空),再做 </system-reminder> 转义,所以变量值也无法闭合插件的框架。环境变量同步用同一个 WebDAV 客户端 GET / PUT 根目录下的同名文件,合并时同名不同值没有选择会返回 409 和冲突列表 |
注意:
</system-reminder> 会被转义。npm run build # src/ → lib/:写入版本号,校验 Host/Client 协议号与模块 id,并做语法检查
npm test # 确认 lib/ 与 src/ 一致,然后用伪造的 Harness 服务跑 Host 与 Client 冒烟测试,
# 并用本地假 WebDAV 服务器、HTTP 代理和 SOCKS5 代理跑同步测试
src/ 后运行 npm run build,并把 lib/ 一起提交。插件通过 github: 安装时直接使用仓库里的 lib/,没有安装时构建脚本。src/index.js 和 src/client.js 中的 HOST_PROTOCOL。本地联调可以用 link 安装:dsh plugin --profile web add link:<本仓库绝对路径>。改代码后重新构建,再重启 dsh web。
DSH_HOME 支持 ~/… 写法。插件各功能单独容错,DSH 接口变化时只影响对应功能、不影响对话和其余功能。Host/Client 协议号升为 8,更新后需重启 dsh web。、(及全角 /)等效于 /,可直接弹出提示词模板菜单。/模板名 后用中文输入法(如 QQ 拼音)输入时,拼音重复插入、文字变蓝且无法删除的问题。/ 模板不再占用 DSH 输入框的「命令认领」,改为发送时识别;模板名含空格时也能正确匹配。{{env:变量名}} 在发送前替换为对应的值;WebDAV 新增「同步环境变量文件」开关,支持合并配置文件(同名不同值逐个选择)、本地覆盖云端、云端覆盖本地。名称.md;新增「WebDAV 云同步」标签页(服务器配置、HTTP / SOCKS5 代理、测试连接、双向选择性同步与同名覆盖确认)。/ 模板追加在全局提示词之后。/ 选择提示词模板、模板编辑器、外部编辑器同步。