dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
给 DeepSeek Harness 的每个会话挂一个「只读参考库」:把本地目录(比如你的项目源码、内部文档)登记为参考库后,agent 回答前会先去这些目录里查证,查不到才允许走外部途径——而不是凭空猜或者直接上网搜。
装法见 📦 安装——一条命令装进 profile。npm 上还没发新版,当前从 GitHub Release 取 tarball。
当前用 GitHub Release 的 tarball 安装(npm 上还没有新版,原因见下):
# 1) 取最新 Release 的 tarball(不带 tag 就是 latest;也可以直接在浏览器打开 releases 页面下载)
gh release download --repo hpyperry/dsh-ref-lib --pattern '*.tgz'
# 2) 装进 profile
dsh plugin --profile web add ./hpyperry-dsh-ref-lib-*.tgz
# 卸载
dsh plugin --profile web remove @hpyperry/dsh-ref-lib
一个插件版本通吃多代宿主:插件自己按语义化版本号发布,能装在哪些 dsh 上由它的
peerDependencies 声明——当前是 >=0.1.5-rc.2 <0.3.0-0,也就是 dsh 0.1.5 / 0.1.6 / 0.1.7 / 0.2.x 都能用同一份包。
为什么能这样:到目前只有过一次客户端破坏,就是图标改名(0.1.7 起
Icon*16→Icon*Regular, 且两代名字不共存)。插件在取值处做了一次运行时回退(新名优先、旧名兜底),所以同一份 bundle 在多代宿主上都能正确渲染,不必按宿主分版本发布。
声明范围不等于每次都真机验过的范围:devDependencies 只能钉一代(当前钉 0.2.0-rc.2),
每次升级做真机冒烟的就是这一代;区间里更早的宿主靠"代码与该世代最后一次真机验证的版本相同"背书,
而不是每个版本都重新回归一遍。
宿主不在这个范围里时,dsh 的兼容闸门会拒绝它:plugin add 直接报不兼容、不安装;按路径装进去的
则留在盘上,但 profile 启动时该插件会被禁用(stderr 打印 disabling profile plugin …)。
闸门只检查 @deepseek-ai/dsh 与 @deepseek-ai/dsh-* 这两类 peer 区间(@deepseek-ai/cordis、
react 不在其中),唯一豁免是
dsh plugin --profile <profile> allow-version <包@版本> --dsh-version <宿主版本> --accept-risk。
⚠️ npm 上暂时不要裸装:这个包在 npm 上只发布到历史的
0.17.0(目标宿主是 dsh 0.1.1-rc.2 那一代),而它的 peer 区间^0.1.2-rc.1能通过 0.1.7 的兼容闸门—— 装得上、闸门放行,但 bundle 里是 0.1.7 起已被删除的旧图标名,结果是白屏。 新版(0.18.0及以后)尚未发布到 npm(账号仍锁着,npm whoami返回 401),请用上面的 tarball 方式装。
安装完成后重启 dsh web 生效。本地开发期想改动即时生效,也可以直接指向仓库本地路径:dsh plugin --profile web add /path/to/ref-lib。
桌面端(Electron 应用)走应用内安装:
desktopprofile 由应用独占,dsh plugin --profile desktop …会被直接拒绝(profile "desktop" is managed exclusively by the Electron application)。请在应用的插件管理 界面里安装——它接受包名、本地路径、git 地址和.tgz直链,直链形如https://github.com/hpyperry/dsh-ref-lib/releases/download/v<版本>/hpyperry-dsh-ref-lib-<版本>.tgz。
cordis.patch.yml 里改 directory-picker 配置);~ 和相对路径(相对路径基于当前会话工作区解析)。想验证效果,在对话里输入 /ref-lib list,应能看到你刚添加的库。
UI 面板和命令操作的是同一份数据,按习惯用哪个都行。
| 命令 | 作用 |
|---|---|
/ref-lib add <path> | 添加一个目录作为参考库 |
/ref-lib add <path> --note <用途> | 添加时附上用途说明 |
/ref-lib list | 列出当前会话的参考库(含失效标记) |
/ref-lib remove <id> | 删除某个参考库 |
/ref-lib import [会话] [路径...] | 从其他会话导入参考库(详见下文) |
命令结果以专属卡片展示,完整文本直接可见,并带一键复制。
想把别的会话里配好的参考库搬过来,用面板里的「从会话导入」或 /ref-lib import。流程分三步:
几个要点:
/ref-lib import 语义相同,只是遇到冲突会直接跳过该条目。| 你想知道的 | 答案 |
|---|---|
| 数据存在哪 | <dshHome>/plugin-data/ref-lib/<sessionId>.json,每个会话一个文件,随 dsh home 一起持久化,重启不丢 |
| 怎么注入给 agent | 只给配了参考库的会话注入(走 systemPrompt.context);参考库为空时不注入,零 token 开销。注入内容为定稿英文规则:库清单(含用途说明作为路由元数据)+ 强制查证流程 + 权威性/冲突处理 + 只读约束 |
| 用途说明 | 添加时可选填写;自动提取目录 README 首标题兜底。它帮助 agent 判断"这个库和当前问题相不相关",之后可在面板条目详情里随时改 |
| 分支会话 | fork 出的新会话在创建那一刻复制父会话的参考库快照,条目独立成新身份;两边之后各改各的 |
| 失效检测 | 每次读取都实时探测目录是否还在(被删除或换成了普通文件即判失效)。失效库不再注入上下文,并在面板状态行、胶囊角标、/ref-lib list 里红色标出;失效条目只能移除,不能编辑或重新打开 |
| UI 刷新 | 面板数据由交互驱动:执行 /ref-lib 命令、发消息、面板操作后即时刷新,没有后台轮询;外部改动了文件,下次界面交互时同步 |
/api/ref-lib/* 路由,带 loopback 护栏(校验源地址、Host、Origin 等),恶意网页和局域网访问都会被拒。cordis.patch.yml 里把 directory-picker 切到 @deepseek-ai/dsh-host-directory-picker-browse(应用内浏览器)。/ref-lib add 的相对路径基于当前会话工作区解析,不是 dsh 进程的启动目录。session.lock),
另一个实例拿不到它,面板会提示「该会话正在另一个 dsh 实例中运行」并禁用所有操作(那些操作必然被服务端拒绝),
只留一个「重试」——会话变活后点一下即恢复。参考库按会话管理,请固定在拥有该会话的那个实例里操作;
两个实例共写同一个 sidecar 也会互相覆盖(整文件写入,没有锁)。pnpm typecheck # 类型检查(tsc --noEmit)
pnpm lint # eslint(门禁之一)
pnpm format # prettier --write(可选,不进 CI;仓库现有代码未全量 prettier 化)
pnpm test # vitest:L0 纯函数 / L1 装配与真实语义 / L2 harness 边界回归
pnpm build # 构建 node half(tsc)+ client bundle(tsdown)→ lib/
测试分三档(L0 纯函数 / L1 装配与真实语义 / L2 harness 边界回归):每个测试文件的第一行都标了自己属于哪档,完整定义、文件归属与那道事故防线见 docs/agents/testing.md。
代码结构:src/ 是 node half(服务、/api/ref-lib/* 路由、/ref-lib 命令、上下文注入),src/client/ 是 web half(dock 胶囊、管理面板、目录浏览器、本地化),tests/ 是测试。
一条命令起联调环境:scripts/dev-isolate.sh 会自动做四件事——按通道拉一份临时 dsh(不装全局)、把 sk 从真实 home 复制进隔离 home、重装插件(吃到当前源码最新构建)、启动 web。真实 ~/.dsh 全程零写入。
./scripts/dev-isolate.sh # 跟本插件所跟踪的通道(dsh npm next),home=.dsh-dev/next,端口 3090
TRACK=main ./scripts/dev-isolate.sh # 测别的 dist-tag(main = npm latest),端口 3091
.dsh-dev/<track>,已 gitignore)——这样 agent/CI 也能直接起环境,不依赖 $HOME 写权限。home 里有从真实 home 复制来的 sk 与会话副本,脚本启动时用 git check-ignore 实测它确实被忽略,没被忽略就直接报错退出(删掉 .gitignore 里那行会立刻失败)。sessions/、storages/、.credentials.yaml、settings.yaml 一律保留(想清插件自身数据才用 RESET_PLUGIN_DATA=1)。package.json 声明的 dsh-* peer 区间内,不在范围内会警告;STRICT_VERSION=1 直接报错。BUILD / SEED_CREDENTIALS / KEEP_TOOLS / DSH_CACHE_DIR / PORT / DSH_VERSION)见脚本头注释。想彻底重置:rm -rf .dsh-dev/next(会连会话与 sk 一起删)。TRACK 可传任意 npm dist-tag(默认 next = 本插件所跟踪的通道,端口 3090;main = latest,端口 3091)。INSTALL_MODE=pack(先 pnpm pack 再装,自带构建产物;tarball 打在仓库根,已 gitignore)。把真实环境升到新通道(不是联调):scripts/upgrade-host.sh —— 升全局 dsh + 把插件重装成 tarball 冻结副本。它会动真实 ~/.dsh,所以默认先整目录备份、打印计划并要求输入 yes,也不碰你正在跑的 dsh web(只打印重启命令)。先 --check 干跑:
./scripts/upgrade-host.sh --check # 干跑:只看现状与计划
./scripts/upgrade-host.sh # 升到 npm next + 换插件(备份 → 确认 → 执行)
SKIP_HOST=1 ./scripts/upgrade-host.sh # 只换插件,宿主不动
只想拿一个指定版本的 dsh:scripts/dsh-local.sh(stdout 只打印 bin 路径,非全局安装)。
./scripts/dsh-local.sh --print-version # 该通道当前版本号
DSH_BIN="$(./scripts/dsh-local.sh)" # 装到临时目录并打印 bin
DSH_CACHE_DIR=~/.dsh-tools ./scripts/dsh-local.sh # 缓存复用,不重复下载
热更新:改 src/client/* 后跑 pnpm build:client,浏览器约 0.5 秒内生效;改 node half 需要重启 dsh web。
插件按自己的语义化版本号发布(以 package.json 的 version 为准),不与 dsh 版本号绑定;
能装在哪代 dsh 由 package.json 的 dsh-* peer 区间决定。dsh 发新版时只需要复核这个区间,
不必改版本号——区间为什么这么定、断点在哪,见
docs/adr/0001-host-version-compatibility.md。
打 tag 即自动打包并挂 Release(推荐)——把 package.json 的 version 改成目标版本并提交,然后:
git tag -a v0.20.1 -m "0.20.1" && git push origin v0.20.1
.github/workflows/release.yml 会跑门禁 → 构建 → pnpm pack,
再把 tar 挂到同名 Release(不存在则用 --generate-notes 创建,已存在则覆盖同名 asset)。
版本号带 -rc / -alpha / -beta 时自动创建为 pre-release(与 dsh 的命名节奏一致)。
tag 名必须等于 v<package.json 的 version>,不一致工作流直接失败(防止发错版)。
只想拿一个 tar 而不发版:在 Actions 页手动触发同一个工作流,tar 作为 artifact 下载。
npm —— dist-tag 与 dsh 同构:预发布进 next,正式版进 latest。目前尚未发布
(npm 账号锁定,npm whoami 返回 401;registry 上这个包全是 0.17.0 及更早的历史版本,
latest = 0.17.0,那版是 0.1.1-rc.2 时代的产物,见「安装」节的警告)。解锁后:
npm publish --tag latest # 例:0.20.1(正式版,同时把 latest 从 0.17.0 挪过来)
npm publish --tag next # 例:0.21.0-rc.1(预发布)
同一个 workflow 里已有「发布到 npm」一步,只在仓库配置了 NPM_TOKEN secret 时才执行;
配好后打 tag 即自动按版本号选 next / latest,不需要本地 npm 登录。
另外两件只有账号解锁后才能做的事(0.17.0 无法删除——见
npm unpublish 政策:超过 72 小时只能走 deprecation,
且 name@version 永久不可复用):
# ① 废弃所有会白屏的旧版本
npm deprecate "@hpyperry/dsh-ref-lib@<=0.17.0" "旧版本基于 dsh 0.1.1-rc.2;在 0.1.7+ 宿主上会白屏,请升级"
# ② 确认 latest 指向新稳定版(正常发布时会自动指过去,可用这条兜底/核对)
npm dist-tag add @hpyperry/dsh-ref-lib@0.20.1 latest
lib/ 与 cordis.patch.yml(pnpm build 先清空 lib/ 再构建,不会带历史残留);
用户也可直接装打出的 tarball:dsh plugin --profile web add ./hpyperry-dsh-ref-lib-<版本>.tgz。.github/workflows/ci.yml)在 push main 与所有 PR 上跑同样的四道门禁。.github/workflows/dsh-track-watch.yml):每周一自动跑一次(也可在 Actions 页手动触发),
比对 npm 上 dsh 的每个 dist-tag 当前指向的版本是否仍落在插件的 dsh-* peer 区间内——判定复用
scripts/dsh-track.sh 的区间检查,与联调/升级脚本同源。落在区间外时不让 CI 变红,
而是开/更新一条带 dsh-track-watch 标签的 issue(插件在那一代宿主上会被兼容闸门拒绝,这是"该去加宽区间"的信号);
registry 不可达时只警告并跳过。MIT,与 DeepSeek Harness 一致。
AGENTS.mdGLOSSARY.mddocs/adr/——其中 0001 是插件与宿主版本的兼容策略docs/agents/testing.mddocs/agents/dev-env.md