dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
按工作区路径或会话 ID 分发 system prompt 人设(完全一致 / 前缀 / 包含 / 正则),可指定一条默认人设兜底;会话页有「人设」页签,能看到实际发出去的提示词;人设列表可导入导出;另有一个开关拒绝工具写入人设存储。
给不同的工作区、不同的会话,用不同的 system prompt 人设。
一个 DSH 部署里常常同时跑着好几摊活:写前端、写文档、盯告警、做代码审查。它们需要不同的身份、口径和约束。 这个插件把人设按工作区或会话分发出去,每一份都是 system prompt 里的一段:
tools.guard,拒绝一切指向人设
存储的写入(write / edit 各类文件工具,以及含写入特征的 shell 命令),只读命令照旧放行。personas.json.bak-<时间戳>;备份失败就不会写入。三处界面,各管一件事:
| 界面 | 位置 | 用途 |
|---|---|---|
| 设置页 | 设置 → Agent 人设 | 新建/编辑/删除/复制/排序人设;写正文、Markdown 预览、让 AI 改一版。标题旁另有 GitHub / npm 链接与当前安装的版本号(悬浮会说明这一份是 npm 装来的还是本地开发目录加载的) |
| 会话视图 | 对话页顶部的 人设 标签 | 看这条会话命中了哪条人设、实际发出去的 system prompt(渲染/源码两视图),以及就地管理全部人设 |
| 侧边栏卡片 | dsh-better-sidebar 的右侧栏 | 把上面那个「人设」页面挂进右侧栏(需要装了该插件) |
五个偏好开关(编辑后自动保存 / 在对话页显示「人设」标签 / 注册到 dsh-better-sidebar / 禁止模型改写人设文件 / 保存人设版本历史)
都在设置 → Agent 人设页里,并且这个页面不受这些开关影响 —— 关掉「对话页显示」或「注册到 dsh-better-sidebar」后,
回到这里就能重新打开。本插件不在设置 → 通用设置里添加任何条目;鼠标停在开关上会给出每个开关的完整说明。
DSH 会把工作区指令(AGENTS.md 之类)变成一条 user 角色的消息,那条消息自己的导语就写着
"They do not override system, developer, or direct user instructions." 而这个插件写的是
system prompt 的一个 section(section 名 agent-persona,order 1,紧跟在身份行之后)。
这个先后关系是框架定的,不是插件自己声明的 —— 也正因为如此,工作区里怎么改文件都动不了这层人设。
实测过的 DSH 版本:0.1.5-rc.1(作者的开发环境)、0.1.5-rc.2、0.2.0-rc.2 与最新版
0.2.1-rc.2。 package.json 的 dsh.compatibility 声明的就是这四项 —— 含义是"我们在这些版本上跑过",
不是对更早或更新版本做过兼容工作的承诺;其它版本请自行验证。
侧边栏卡片还需要 dsh-better-sidebar:没装它时,「注册到 dsh-better-sidebar」这个开关不会出现
(没有可注册的地方),插件其余功能照常。
dsh plugin --profile web add dsh-agent-persona
装完重启一次 dsh web:profile 的 bundles 只在启动时读取,插件行是从那里挂进去的。
重启后能看到:
cat ~/.dsh/dsh-agent-persona/state.json —— 插件的加载心跳,写明了它加载了哪个文件、人设存哪、几条人设。仓库里也有本地安装脚本:bash scripts/install.sh(Windows 是 scripts/install.ps1)。
升级与卸载(dsh plugin … 就是在 profile 目录里代跑包管理器):
dsh plugin --profile web update dsh-agent-persona # 升级(按依赖的版本范围取最新)
dsh plugin --profile web add dsh-agent-persona@latest # 想跨大版本升到最新
dsh plugin --profile web remove dsh-agent-persona # 卸载
升级或卸载后重启一次 dsh web。人设文件不会被删、也不会被覆盖:卸载是人设只留在文件里的操作。

点 新建人设 → 在「适用范围」里加行,选工作区或会话 → 写正文 → 打开启用开关 → 保存。
展开一张卡是这样:

打开设置页的 保存人设版本历史,之后每次保存都会把这次的正文改动记成一条 diff(写在
personas.history.json)。编辑器底部的 版本历史 按钮打开对比窗口:

下拉框旁边那个按钮会打开一个只读弹窗:左右气泡式对话(你的输入在右、Agent 的回复在左)。
AGENTS.md)、运行时上下文快照、skill 目录说明这类
插件注入的"看起来像用户消息"的东西一律不展示,弹窗顶部只写「已隐藏 N 条插件注入内容」,
不占位置,也不会让你困惑"这条我没说过"。
选中一条会话后,对话页顶部有 人设 / 提示词 / 管理 三个面板:
| 开关 | 默认 | 含义 | 生效时机 |
|---|---|---|---|
| 编辑后自动保存 | 关 | 停手约 1 秒自动保存编辑区内容 | 立即;切换到人设规则行(工作区/会话)时不自动保存,避免存下半截选择 |
| 在对话页显示「人设」标签 | 开 | 是否注册对话页那个视图 | 立即(运行时注册/注销) |
| 注册到 dsh-better-sidebar | 开 | 是否把「人设」页面注册进 dsh-better-sidebar 的右侧栏 | 立即;没装该插件时这个开关不显示 |
| 禁止模型改写人设文件 | 开 | 按能力判定:任何会写入/删除人设存储(含它的历史文件与备份副本)的工具调用都拒绝,读取、grep、把路径写进笔记都不受影响;关掉后不拦 | 立即;对下一次工具调用生效 |
| 保存人设版本历史 | 关 | 每次保存记一条可重放的 diff(最多 200 条,可查看/对比/恢复) | 立即;关掉后不再记新版本,已有历史仍可查看 |
偏好存在人设文件的 prefs 字段里(不是浏览器),所以它和数据的可见范围一致;浏览器里只留一份镜像,
供"加载时决定要不要注册视图"用。
| 方式 | 效果 |
|---|---|
| 追加(默认) | 保留 DSH 自带的那句身份提示,这条人设接在它后面 |
| 替换 | 去掉 DSH 自带的身份句(以及部署自己写的 persona 段),只用这条人设 |
「替换」只动部署自己写的那句 persona;如果某个 Agent 预设在自己作用域里写了 persona(把这一段遮蔽了), 插件不会去覆盖它 —— 别人的身份提示优先。
宿主在每次组装 system prompt 时按这个顺序过一遍:
⋯ 菜单里调);四种匹配方式里只有 完全一致 会把路径归一化(/a/project/ 和 /a/project 算同一个);
开头是、包含、正则匹配 都是拿你写的字符串直接比。值空着、正则写错、或者会话没有那个字段,
都算「不匹配」,不会报错。
~/.dsh/dsh-agent-persona/
├── personas.json # 人设数据 + 偏好,权限 600,原子写入
├── personas.history.json # 版本历史(开关打开后才出现)
└── state.json # 加载心跳,每次加载时重写
正文里可以写 {{model}} 和 {{cwd}},渲染时替换成当前的值;其他 {{...}} 会被去掉(未注册的变量会让
整个组装抛错,所以这里做了保护)。
配置项(Schemastery schema,加载时校验,写错类型会加载失败而不是被忽略):
| 配置 | 默认 | 说明 |
|---|---|---|
storePath | '' | 人设文件位置;留空即 $DSH_HOME/dsh-agent-persona/personas.json |
tuneProvider | '' | AI 调优用哪个 provider;留空即 DSH 当前设置的模型 |
tuneModel | '' | 同上,模型 id |
人设数据默认是全局一份($DSH_HOME/dsh-agent-persona/personas.json,与其它插件的状态目录同一约定),
所以同一台机器上的多个 profile 共用同一份人设。要让某个 profile 独立,在该 profile 的
cordis.patch.yml 里覆盖它自己的路径(是覆盖字段,不要再 insert 一行):
# ~/.dsh/profiles/<该 profile>/cordis.patch.yml
- id: agent-persona
config:
storePath: /Users/you/.dsh/profiles/<该 profile>/personas.json
也可以用 DSH_HOME 环境变量把整个 ~/.dsh 指向别的目录(那样连会话记录、其它插件状态一起隔离)。
当前生效的文件路径始终显示在「Agent 人设」页面的 meta 行上(保存在 …),不会出现"改了半天不知道改的是哪一份"。
默认用 DSH 当前设置的模型,设置页里的下拉框会把它预选好;想固定别的模型就用上面的 tuneProvider/tuneModel。
AI 只产出建议稿,点「采用」或「追加」才会进编辑框,再点保存才落盘。
tools.guard,它不看工具叫什么名字,而是看这次调用会不会写到
受保护的文件 —— 参数里的路径(解析 ~ 与相对路径)、shell 命令里的重定向目标、写入型命令(删、移、原地改、解释器
-c),以及补丁正文里的 *** Update File: 目标。受保护的是主文件 personas.json、它的历史文件和它们的备份/临时副本。danger-full-access 下改插件代码、改 profile 补丁文件都能绕过;脚本里
运行时拼出来的路径静态看不出;$VAR 展开看不出;别名/函数包装也看不出。要更结实得在本机层面做:
chflags uchg <人设文件>(自己改之前先 chflags nouchg),或者把 DSH 跑在受限沙箱里、让人设文件属于别的用户。源码是 TypeScript,lib/ 是构建产物(不进 git,npm publish 前由 prepare 构建):
src/index.ts host 半边:存储、匹配、system-prompt section、远程服务
src/client.ts client 半边:设置页 + 会话视图 + 侧边栏卡片(打包成单文件 lib/client.js)
src/endpoints.ts 远程方法的单一来源(生成 src/remote.ts 与 src/typert.ts)
scripts/ 生成器 + 安装脚本
test/ 单元测试与源码审计
docs/ 架构、开发笔记、设计决策
npm install
npm run build # generate:remote → tsc → esbuild(产出 lib/)
npm run typecheck # 两个 tsconfig 都不报错
npm test # 236 + 187 条断言 + 生成产物漂移校验
dsh --profile web --dump-config | grep -c 'id: agent-persona' # 组合自检,应输出 1
改代码之后怎么生效:
src/** 改完必须 npm run build(lib/ 是产物)。lib/client.js)改内容:客户端会按内容重算,刷新页面即可;别改文件名。lib/index.js)改内容:ESM 按 URL 缓存模块,不会自动重载 —— 重启 dsh web。package.json 的 dsh.bundle.patch 或 profile 的 bundles 有改动:必须重启。src/remote.ts、src/typert.ts)不要手改:改 src/endpoints.ts 后跑
npm run generate:remote,npm test 会校验它们是否与来源一致。细节在 docs/development.md,内部结构在 docs/architecture.md。
Apache-2.0,见 LICENSE。