DeepSeek Harness 默认 System Prompt 管理插件:在 Web…
43.7/100
综合分
24
GitHub 星标
1,760
npm 周下载
—/5
用户评分
数据截至 2026/10/24 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-prompt-settingnpm 源 · dsh-prompt-setting 的发布者账号已校验与本仓库一致
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · skill
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 8 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过安装清单取自 packages/dsh-prompt-setting/package.json
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-prompt-setting @ 0.2.5
✓Node 引擎要求 >=22 · 基线 Node 22.19 满足
✓dsh CLI 依赖要求 >=0.2.1-0 <0.3.0-0 · 最新 0.2.1-rc.2 兼容
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/26 17:41:40
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 62 处,展示前 54 条)
- 读取本地文件index.js:491
const manifest = JSON.parse(readFileSync(OWN_MANIFEST_URL, 'utf8')); - 读取本地文件index.js:516
return repositoryUrlOf(JSON.parse(readFileSync(OWN_MANIFEST_URL, 'utf8'))); - 读取本地文件index.js:3481
const manifest = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')); - 发起网络请求client.js:3924
const response = await fetch(path, { - 写入剪贴板client.js:4051
await primitives.writeClipboard(text); - 写入剪贴板client.js:4055
await navigator.clipboard.writeText(text); - 读取本地文件scripts/prepare.mjs:51
return readFileSync(path, 'utf8'); - 读取本地文件scripts/prepare.mjs:66
return readdirSync(path); - 读取本地文件core/compat.js:308
return readdirSync(path); - 读取本地文件core/compat.js:400
const readFile = options.readFile ?? ((path) => readFileSync(path, 'utf8')); - 删除本地文件core/store.js:97
rmSync(path, { force: true }); - 读取本地文件core/store.js:149
raw = readFileSync(path, 'utf8'); - 读取本地文件core/store.js:212
raw = readFileSync(path, 'utf8'); - 读取本地文件core/store.js:300
const raw = readFileSync(clientPath, 'utf8'); - 读取本地文件core/store.js:301
const stats = statSync(clientPath); - 读取本地文件core/store.js:343
names = readdirSync(clientDir); - 读取本地文件core/store.js:351
const raw = readFileSync(path, 'utf8'); - 写入本地文件core/store.js:426
mkdirSync(directory, { recursive: true }); - 写入本地文件core/store.js:433
writeFileSync(temp, serialized, 'utf8'); - 写入本地文件core/store.js:434
renameSync(temp, path); - 删除本地文件core/store.js:437
rmSync(temp, { force: true }); - 写入本地文件core/store.js:530
mkdirSync(directory, { recursive: true }); - 写入本地文件core/store.js:536
writeFileSync(temp, text, 'utf8'); - 写入本地文件core/store.js:537
renameSync(temp, path); - 读取本地文件scripts/client-chunks.mjs:112
entries = readdirSync(join(packageDir, CLIENT_SRC_DIR)); - 读取本地文件scripts/client-chunks.mjs:120
if (readFileSync(join(packageDir, relPath), 'utf8').includes(BLOCK_OPEN)) hits.push(relPath); - 读取本地文件scripts/client-chunks.mjs:131
const source = readFileSync(CLIENT_PATH, 'utf8'); - 读取本地文件scripts/client-chunks.mjs:139
const segment = segmentPath === null ? null : readFileSync(join(PACKAGE_DIR, segmentPath), 'utf8'); - 写入本地文件scripts/client-chunks.mjs:167
if (nextSegment !== segment) writeFileSync(join(PACKAGE_DIR, segmentPath), nextSegment); - 写入本地文件scripts/client-chunks.mjs:169
writeFileSync(CLIENT_PATH, writeDeclaredStamps(source, actual)); - 读取本地文件scripts/locale-pack.mjs:135
raw = readFileSync(path, 'utf8'); - 读取本地文件scripts/locale-pack.mjs:328
return readdirSync(join(packageDir, relPath)); - 读取本地文件scripts/locale-pack.mjs:335
return readFileSync(join(packageDir, relPath), 'utf8'); - 读取本地文件scripts/locale-pack.mjs:500
return readFileSync(join(PACKAGE_DIR, relPath), 'utf8'); - 读取本地文件scripts/locale-pack.mjs:509
return readdirSync(join(PACKAGE_DIR, relPath)); - 写入本地文件scripts/locale-pack.mjs:558
writeFileSync(CLIENT_PATH, next); - 写入本地文件scripts/locale-pack.mjs:566
writeFileSync(join(PACKAGE_DIR, CLIENT_SRC_DIR, segment.name), next); - 写入本地文件scripts/locale-pack.mjs:576
writeFileSync(CLIENT_PATH, want); - 读取本地文件scripts/client-build.mjs:173
const readDir = io.readDir ?? ((relPath) => readdirSync(join(packageDir, relPath))); - 读取本地文件scripts/client-build.mjs:174
const read = io.read ?? ((relPath) => readFileSync(join(packageDir, relPath), 'utf8')); - 读取本地文件scripts/client-build.mjs:268
return readdirSync(join(packageDir, relPath)); - 读取本地文件scripts/client-build.mjs:353
current = readFileSync(join(packageDir, 'client.js'), 'utf8'); - 读取本地文件scripts/client-build.mjs:445
const current = readFileSync(CLIENT_PATH, 'utf8'); - 写入本地文件scripts/client-build.mjs:460
writeFileSync(CLIENT_PATH, generated); - 读取本地文件scripts/check-compat.mjs:41
return readFileSync(path, 'utf8'); - 执行外部命令固定命令scripts/real-layers-check.mjs:61
return execFileSync('git', ['rev-parse', '--path-format=absolute', '--git-common-dir'], { - 读取本地文件scripts/real-layers-check.mjs:91
if (!existsSync(path)) { - 读取本地文件scripts/real-layers-check.mjs:100
userConfig = validateConfig(JSON.parse(readFileSync(realUserPath, 'utf8'))); - 读取本地文件scripts/real-layers-check.mjs:101
workspaceConfig = validateConfig(JSON.parse(readFileSync(realWorkspacePath, 'utf8'))); - 读取本地文件scripts/verify.mjs:123
const entries = readdirSync(join(PACKAGE_DIR, 'test'), { withFileTypes: true }) - 读取本地文件scripts/verify.mjs:142
entries = readdirSync(join(dir, 'test')); - 发起网络请求src/05-helpers-b.js:467
const response = await fetch(path, { - 写入剪贴板src/05-helpers-b.js:594
await primitives.writeClipboard(text); - 写入剪贴板src/05-helpers-b.js:598
await navigator.clipboard.writeText(text);
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
界面预览
1 张 · 点击查看大图功能亮点
- 浏览系统提示词
- 检索系统提示词
- 覆盖会话系统提示词
展开完整介绍(76 字)↓
DeepSeek Harness 默认 System Prompt 管理插件:在 Web GUI「设置」里浏览、检索并覆盖最终装配进每轮会话的系统提示词
最近更新
在 GitHub 查看全部 →0.2.52026-10-24
· Added 新增
· 「我的预设」标签:预设库文档升到 version: 2,顶层新增独立的标签集合
tags: [{id, name, createdAt, updatedAt}],每个预设新增 tagIds: [](去重、保序、只允许现存标签);
旧文档(无 tags)读出空标签集,不需要迁移。设置页新增标签筛选条(「全部」+ 各标签 chip、单选、
点已选取消)、行内标签 chip、编辑器里的多选标签 picker,以及标签管理对话框(新增 / 改名 / 删除);
删除走页面统一的二次确认,正文说明「{count} 个预设会去掉这个标签」。GET /presets 与 PUT /presets
携带 tags[] / tagIds[],新增 PUT /prompt-setting/presets/tags 与
DELETE /prompt-setting/presets/tags?id=;删除是原子的,并在同一次返回里把该 tagId 从所有预设剥掉
(删除后不存在悬空 tagId),不碰任何工作区层、不写历史。导入导出自然携带标签,导入按整份替换
严格校验(悬空 tagId、重复 id/名、超限一律拒绝)。
· 「我的 Prompt」就地状态摘要:在「我的 Prompt」标题区下方插入两行只读摘要——①最近
关键节点的装配结论 + 送达结论(沿用页面既有的 assemblyVerdictOf / deliveryVerdictOf 与既有文案
键,不复制第二套口径),②本层覆盖计数「本层覆盖 {total} 条 · {ineffective} 条未生效」。摘要不展开
逐条原因、不含装配开关、不渲染覆盖列表;「详情」会把「高级」钉到同一个 session 再切换,全局范围
不发请求。同时澄清清理入口文案:只删本层「我的 Prompt」段 / 整层清空(含它)/ 「清除全部覆盖」三者
的区别。路由、按钮结构与确认流程一律未动。
· 会话输入框上方的装配状态栏:在宿主 conversation.input.dock 追加一条常驻只读栏,
五个分区:装配段数、用户级层、工作区级层、装配状态摘要、插件设置入口。口径全部复用页面已有函数
(effective.sections.length / mineCoverageOf / assemblyVerdictOf / deliveryVerdictOf),只发
GET(带 ?session=),刷新按钮只重读;无 session 时零请求(effect 直接短路,return null
在全部 hook 之后)。视觉是胶囊仪表条:品牌区 + 五个内联 SVG 图标 + 语义色值,永不折行(窄宽收缩并
省略号),=0.2.1-0 <0.3.0-0
Full Changelog:
0.2.42026-10-18
· Added 新增
· **文案真源迁出 bundle:locale/*.json + scripts/locale-pack.mjs
· Changed 变更
· 内部工程:客户端生成期分段与发布前门禁
· cwd 变量弃用的探测:按真实变量表适配,不按版本号猜:上游
dsh-agent-loop 不再注册 cwd,shipped preset 也不再发 Your working directory is {{cwd}}.。插件把
GET /prompt-setting/interpolate 早已返回的 variables(一次真实 assemble() 的键集,已按 mount
缓存)接到「我的 Prompt」面板:注记里的变量列表按当前实际注册名渲染——旧版 DSH 仍列出
{{cwd}},0.2.1-rc.1 及以后不列并在同一段文案里点名其弃用与「保持字面量 / 保存被拒」两个后果;
探测失败(variables: null)显示 ?,不编造可用集合。写入/开启校验在拒绝未注册的 {{cwd}}
时追加一句迁移提示(表里仍有 cwd 时一字不加),状态码、错误码与零字节保证均不变。旧版 DSH 的
行为、文案与判定方向逐字不变;已有文本照常进入 prompt(保留段永不插值、插件展开宽松,绝不抛错)。
零新增路由/字段;每页加载/重载多一次已缓存的 GET /interpolate(不触发新的 assemble())。
client.js 保持 12382 行(行数中性改写),docs/refactor-plan.md 的段表与引用行号零漂移。
· 作用域模型收敛:页面「查看范围」只服务「我的 Prompt」
· 跨机备份恢复改为「跳过」语义 + 导入预览提示「整份替换」
· 「查看范围」移入「我的 Prompt」
· 「一级 tab」换成纯文字 + 选中下划线,并加计数与更新红点
· 删除预设=对每个已应用的工作区取消应用
· 「装配状态提示」移到「高级」面板顶部
· 「备份与恢复」变成真正的全量备份,并同步解除导入写锁
· Fixed 修复
· 备份/恢复的路径安全绕过:presets.applied[].workspaceRoot 过去只检查「非空字符串」,
而 DELETE /prompt-setting/presets?id= 会用记录里的 root 直接写 /.dsh-prompt-setting/overrides.json。
于是一份导入的备份可以命名任意磁盘路径(/etc 也行),删除预设就成了任意路径写入原语——评审 PoC 实测未注册
目录下的层文件被真实改写。修复:形状规则抽到 core/workspace-root.js,由 workspaces[].root 与
presets.applied[].workspaceRoot 共用同一个函数;导入与删除两条路径都对 root 过注册表白名单(未注册即
整体拒绝、零写入);导出不再携带无法在本机还原的 applied 记录(条数由 exportScope.omittedApplied 声明),
使插件自己产出的备份一定能被自己的导入读回。
Full Changelog**:
0.2.22026-10-13
· Added 新增
· 「预设」库:设置面板新增「我的预设」tab,可以把一整套 Prompt 存成命名
预设,随时编辑或删除;一次「应用」把预设写进所选工作区,再点一次即取消应用。预设按粒度
独立记账:要取消的是哪一次应用就还原哪一次,后一次应用不会吞掉前一次,重复应用同一预设是幂等的
(不会叠加成双份),多个预设叠加时按应用顺序回放。编辑与覆盖已应用的预设、以及所有破坏性动作
(删除、取消应用)都走二次确认,未保存的草稿在关闭弹窗时受保护,不会被静默丢弃。
· 会话内「装配状态提示」:DSH 每个 model step 都会重新装配 system prompt,
但「装配到」不等于「送达到模型」。改动 Prompt 后的下一个 run 会主动弹一次 toast,说明本次装配是否
读到了新文本、以及它是否进入本次请求;设置页保留同一份详情与开关。提示只落界面——不进上下文、
不占 token、不改模型收到的 prompt,且只在关键节点提示一次(新会话首次装配、每次变更后的下一个 run),
因此不会变成刷屏。
· Changed 变更
· 客户端半代码复用收口
· Fixed 修复
· 官方组件探测恒为假:判定「宿主是否提供官方组件」的条件是 typeof Button === 'function',
但 React.forwardRef 的产物是对象,typeof 永远是 'object' ⇒ 该判定自诞生起恒为 false,设置页
一直退回自绘控件,从未真正启用宿主官方组件。现在新增 isComponentExport:函数组件,或带 React
组件 brand(forwardRef → render、memo → type)且结构字段合法者;未知 brand、字段缺失或
getter 抛错一律判不可用(保持 fail-open)。同一判据统一用于图标、差异块、UI.Input / Tag、分段
tab 与 toast。
Full Changelog:
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。
README
由 DeepSeek 最新模型翻译生成dsh-prompt-setting:DSH 的系统提示词管理
dsh-prompt-setting
DSH(DeepSeek Harness)的系统提示词管理。 它给 Web GUI 的设置页加了一个提示词管理器:你能看到会话每一轮实际拼装出的系统提示词,搜索它,把自己的指令写进去,也能回滚一次改坏的编辑——全程不用碰全局 DSH 安装。
- 零运行时依赖,零构建步骤:一个纯 JS 包,不用下载,不用编译。
- 升级安全:配置只写进插件自己的数据目录,升级或重装 DSH 都不会丢失,也不会被覆盖。
1. 解决什么问题
DSH 每一轮都会注入一段基础系统提示词,由 @deepseek-ai/dsh-system-prompt 拼装。在此之前,想调整它只有一条路:手动改全局 pnpm node_modules 里的文件。代价是:
- 下次升级 DSH 就把它覆盖掉,你的改动没了;
- 污染全局安装,别人、别的机器都复现不出来;
- 没有记录,不知道改了什么,也不知道改之前长什么样;
- 最要命的是,你看不到最终拼装出的系统提示词到底长什么样。
这个插件把这件事搬进设置页:拼装结果按段铺开,你写的那部分单独成段、固定在末尾,其他内置段一律只读,改动带历史、带 diff、可导出备份。
展开完整文档(README 剩余 1 节)
dsh-prompt-setting:DSH 的系统提示词管理
dsh-prompt-setting
DSH(DeepSeek Harness)的系统提示词管理。 它给 Web GUI 的设置页加了一个提示词管理器:你能看到会话每一轮实际拼装出的系统提示词,搜索它,把自己的指令写进去,也能回滚一次改坏的编辑——全程不用碰全局 DSH 安装。
- 零运行时依赖,零构建步骤:一个纯 JS 包,不用下载,不用编译。
- 升级安全:配置只写进插件自己的数据目录,升级或重装 DSH 都不会丢失,也不会被覆盖。
1. 解决什么问题
DSH 每一轮都会注入一段基础系统提示词,由 @deepseek-ai/dsh-system-prompt 拼装。在此之前,想调整它只有一条路:手动改全局 pnpm node_modules 里的文件。代价是:
- 下次升级 DSH 就把它覆盖掉,你的改动没了;
- 污染全局安装,别人、别的机器都复现不出来;
- 没有记录,不知道改了什么,也不知道改之前长什么样;
- 最要命的是,你看不到最终拼装出的系统提示词到底长什么样。
这个插件把这件事搬进设置页:拼装结果按段铺开,你写的那部分单独成段、固定在末尾,其他内置段一律只读,改动带历史、带 diff、可导出备份。
2. 安装后你会得到什么
设置页多出一个 「Prompt settings」 面板(id: prompt-setting),含六个顶层标签页:
| 标签页 | 你能做什么 |
| My Prompt | 唯一的写入面:写你自己的系统级指令(选层 → 编辑 → 保存),外加一键「Restore default」。这段文本放在所有内置段之后。「View scope」选择器就在这个面板里、标题下方(自 g-071 起):它决定保存落到哪一层,也是唯一能改作用域的地方(面板还会以只读行重复显示当前目标)。自 g-084 起,目标行下方多了一段只读的两行状态摘要:最新关键节点的拼装 / 投递结论,以及「本层:N 条覆盖 · M 条未生效」。它跟随「View scope」(全局作用域会明说,不借用任何会话),「Details」会打开 Advanced 并定位到该会话,它不带开关,也不给逐条原因。「Restore default」只删除本层的 My Prompt 条目,保留本层其他覆盖。 |
| 我的预设 | 可复用文本的目录:把文本保存为预设(新建 / 编辑 / 删除),再应用到某个工作区(写入该工作区层预留的区段),或取消应用,取消后工作区会精确还原到应用前的状态。删除已应用的预设会先取消它的应用:每个受影响的工作区先还原到应用前的状态,然后才从库中移除该预设(确认框会列出这些工作区)。标签(g-082):库有自己的一套标签;一个预设可携带 0–N 个标签,列表一次按一个标签筛选。标签在「管理标签」下新建、重命名和删除;删除前会先询问,并说明有多少预设会失去该标签——这些预设保留其他标签,只去掉这一个。 |
| 提示词总览 | 只读:组装后的区段列表(状态标记 / 搜索 / 筛选 / 复制)、全文,以及 base ↔ effective 差异——你能清楚看到改动到底做了什么。 |
| 版本历史 | 历史列表(固定高度、内部滚动、分页——默认每页 50 条)和行级版本差异。日志有自己的范围选择器(工作区维度),与 My Prompt 里的「查看范围」选择器相互独立:用户层的日志是全局的,从不按会话切分。 |
| 备份与恢复 | 导出配置供下载,并预览导入(写入任何内容前先查看变更计划)。 |
| 高级 | 旧版覆盖项的只读列表、两个二次确认按钮(「清除所有覆盖项」「重置整个层」)、「检查更新」开关(默认开启;关闭后本插件完全不发起网络请求)、「立即更新」操作(宿主安装横幅所指的版本;重启由你自己完成——命令行启动的,重新运行 dsh web;桌面应用的,退出并重新打开 DeepSeek Harness),以及完整的状态区(挂载状态 / 构建指纹 / 渲染器自检)。完整的组装状态块及其开关都在这里;自 g-084 起,每次清除都会用文字说明范围——「重置整个层」会清除该层,包括 My Prompt,而「清除所有覆盖项」会保留它。 |
所有界面文案都跟随 DSH 的语言设置:把 DSH 切成中文,这个页面就变成中文,无需刷新或重启。
标签栏本身。 六个顶层标签是纯文本——无填充、无边框、不等宽分栏。选中的标签带一条短下划线,紧贴栏下方的浅色分隔线,标签栏保持单行,面板比标签窄时横向滚动(绝不撑宽页面)。「我的预设」用 (N) 显示库的大小——在真正知道大小之前不显示数字,所以占位符 (0) 永远不会出现。「高级」在有新版本可更新时显示一个小红点;关闭更新横幅不会清除红点,因为红点陈述事实,而横幅只是提示。
网络访问:只检查一次更新(可以关掉)
设置页打开时,宿主(Node 侧)会发一次 GET 请求到 https://api.github.com/repos/zangxx66/dsh-prompt-setting/releases/latest —— 这个 URL 来自本包的 package.json(repository.url),不会在别处再硬编码一次。这是插件唯一的对外请求,而且可以开关:
- 只发一次请求,别的什么都不做:不带 body、不带 cookie、不带本地/会话/工作区数据; User-Agent: dsh-prompt-setting/<version>;5 秒超时;同一进程内六小时内不重复;
- 只有确认有新版本时才出声:页面顶部出现可关闭的横幅(新版本号 + 发布页链接)。没有更新、还没发布、或请求失败,页面顶部什么都不显示 —— 不提示,也不报错。「还没发布 / tag 解析不了」是上游的事实,所以在 Advanced 开关卡片里给一行中性说明;检查失败则不给这一行;
- 关掉它:设置 → Prompt settings → Advanced → 关掉 「Check for updates」。关掉后零请求,包括页面加载时;<DSH_HOME>/prompt-setting/preferences.json 会记下 {"updateCheck": false}。手动改这个文件 —— 或者删掉它恢复默认(开启)—— 效果一样;
- 它从不做的事:不自动下载、不自动安装、不自动重启,也不检查 DSH 平台版本。
安装更新(「Update now」)
装的是版本,重启还是你来 —— 页面会说明怎么做。 横幅上的 Update now 按钮会弹出二次确认(确认框里也这么写),确认后宿主通过官方插件管理器把该 release 的 .tgz 装进当前配置档。之后页面按它面对的启动形态给出答复:命令行宿主说「vX.Y.Z 已安装 —— 请自行重启 dsh web」,官方桌面应用说「退出并重新打开 DeepSeek Harness」(桌面用户没有终端,所以那里永远不会出现 dsh web),判断不出形态时回退到两种读者都能照做的文案。这里不会重启任何东西。
- 装的是什么:release asset https://github.com/zangxx66/dsh-prompt-setting/releases/download/<tag>/dsh-prompt-setting-<version>.tgz,其中 <tag>/<version> 取自同一次更新检查 —— 所以公布的版本就是安装的版本,命中缓存的检查依然零对外请求。因为是 asset,不需要 pnpm 构建脚本审批;
- 怎么跑:点击后立刻返回 requestId,页面轮询它(1.5–5 秒一次,最长 16 分钟),带取消按钮。失败会标明类别(asset 缺失 404 / 构建被阻止 / 网络 / pnpm 缺失 / …)并提供重试 —— 绝不自动重试,绝不自动重启;
- 拒绝 link: 安装:如果某个配置档把这个包作为 link:/本地路径持有,那它就是开发工作树,所以按钮会拒绝,并指向手动方式,而不是用已发布版本覆盖那个链接;
- 给发布者:每次发布都必须上传 npm pack 产物,文件名严格为 dsh-prompt-setting-<version>.tgz,并且这个包不得添加 postinstall/install 脚本(带这类脚本的 tarball 会被 pnpm 的构建门禁拦下)。见 packages/dsh-prompt-setting/NOTES.md §107。
3. 安装
前置条件:DSH 已安装,版本在 >= 0.2.1-0 < 0.3.0-0 范围内——每个 0.2.1 预发布版(alpha、beta、rc.N,以及合成的 -0 下限)、0.2.1 正式版本身、以及之后每个 0.2.x 补丁(0.2.2、0.2.9……)都在范围内;低于 0.2.1 的 0.1.x / 0.2.0 系列不在范围内,整个 0.3.0 系列及其之后的所有版本也不在——下一个小版本必须先重新声明(并测试)才能被接纳。Node >= 22 只在运行测试或开发时才需要。
registry 是主要入口(这个包已发布;npm 上的 latest 是 0.2.2——本仓库是 0.2.5,发布后两者就一致了):
dsh plugin --profile <name> add dsh-prompt-setting
Web GUI 的配置档是 web。另外三条路径——git/GitHub、本地检出、tarball——属于开发 / 离线 / 兜底方式。四条路径都是把这个包装进一个 DSH 配置档——同样的配置档文件、同样的包管理器、同样的日志——所以按手头有什么来选。不要手动编辑配置档的配置文件。
GUI 自带的 Plugins 页面(无需终端)
当前 DSH 在 Web GUI 侧边栏里有独立的 Plugins 页面。它不在 Settings 下——Settings → Built-in plugins 是只读清单,不是安装器:
1. 侧边栏 → Plugins → Add plugin;
2. 输入和交给 dsh plugin add 一样的 spec,然后点 Install:
- registry 名称——dsh-prompt-setting(首选;从 npm 拉取最新版本);
- 本地路径(开发)——本仓库包目录的绝对路径: <absolute path to repo>/packages/dsh-prompt-setting(先克隆或下载仓库;相对路径会被拒绝,因为宿主的工作目录对浏览器没有意义);
- git 地址(开发 / 兜底)—— github:zangxx66/dsh-prompt-setting#path:/packages/dsh-prompt-setting(这个 monorepo 必须带 #path: 部分);
- tarball(离线 / 兜底)——dsh-prompt-setting-<version>.tgz,放在磁盘上或通过 http(s) 提供;
3. 宿主会在安装任何东西之前先读取 spec(名称、版本、一句话简介、包里是否真的带 bundle),读不出来就在输入框下方说明,而不是直接安装;spec 通过后,pnpm 的输出会流式显示在 Show install details 后面,旁边有 Cancel install,并且运行失败或取消时,会把配置档文件还原;
4. 安装完成后会提供 Enable now;插件包自己的页面带有开关、条目列表和 uninstall。如果 pnpm 拦截了某个依赖的安装脚本,失败界面会列出这些包,并提供 Allow these scripts and retry。
本地路径会以 link: 方式安装 —— 配置档和你的检出目录变成同一份文件。这是开发用的工作树,插件自带的「Update now」按钮会刻意拒绝用已发布版本覆盖它(见上文「Update now」说明):这类安装请用 git pull 更新。
如果你的 DSH 构建在侧边栏没有 Plugins 入口,就用下面的 dsh 命令行。
在会话里把仓库地址交给智能体
把地址粘贴到会话里,说明要做什么 —— 智能体会把它安装到该会话正在运行的配置档:
install https://github.com/zangxx66/dsh-prompt-setting into this profile
在 Creator 模式下,智能体有 plugin_manager 工具,会直接调用:
plugin_manager(action: "install_bundle", target: "github:zangxx66/dsh-prompt-setting#path:/packages/dsh-prompt-setting", enabled: true)
- #path: 部分必须带上:这个仓库是 monorepo,插件放在子目录里。不带的话,pnpm 会安装以仓库根目录为根的合成 0.0.0 空包,插件永远不会出现;
- 你在批准什么:安装会改写配置档的 package.json 和插件包选择,装好的 Host 代码随后在进程内运行,位于工作区沙箱之外 —— 因此该工具要求 danger-full-access,或每次调用单独批准。批准前先读规范。
dsh 命令行
dsh plugin --profile <name> <pnpm args…> 会在该配置档目录里运行 pnpm,并选中本次运行新增的插件包。Web GUI 的配置档是 web:
from the registry (primary)
dsh plugin --profile web add dsh-prompt-setting
straight from GitHub — development / fallback; no clone first; the #path: part is required for this monorepo
dsh plugin --profile web add 'github:zangxx66/dsh-prompt-setting#path:/packages/dsh-prompt-setting'
a local checkout — development (absolute path; installed as link:)
dsh plugin --profile web add '<absolute path to repo>/packages/dsh-prompt-setting'
a tarball built from the package directory — offline / fallback; same behaviour
cd packages/dsh-prompt-setting && pnpm pack
dsh plugin --profile web add '<absolute path to the .tgz>'
pnpm ≥10 默认不会运行 git 依赖的构建脚本,所以 git 安装第一次会失败,并打印确切的包键(ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED);把这个键复制到配置档的 pnpm-workspace.yaml 里 allowBuilds 下,再重新运行 add。这项授权意味着「该包的代码可以在安装时于你的机器上执行」,所以只授权给你信任的来源,并锁定
提交(…#<sha>)。本包零构建:prepare 只跑一次发布自检——声明的入口点是否齐全、是否都在 files 白名单内、每条补丁行是否都能解析。想完全避开授权,可以 pnpm pack 打一个 tarball,再用 add 装它;行为完全一致。
确认已挂载
打开 DSH Web GUI → Settings:应该能看到 “Prompt settings” 面板。要确认宿主那一半已挂载,看页面「raw response」区域里 GET /prompt-setting/ping 返回的 JSON,或者在页面控制台执行 await (await fetch('/prompt-setting/ping')).json()。
直接对该路由发 curl 会被拒绝(401):它要求浏览器的 cookie 认证。这是预期行为,不代表路由缺失。见 NOTES.md §4。
实测输出、完整检查表和未测试项见 NOTES.md §96;包级摘要——它是什么、功能、安装,中英双语——见 packages/dsh-prompt-setting/README.md。
4. 需要知道的事(容易踩的坑)
- 何时生效:保存的文本从下一轮 / 下一个会话开始生效;它绝不会改写已在进行的轮次。
- 可写面很窄:只有「My Prompt」这一节可写。其他所有内置节都是只读——PUT 和单名 DELETE 返回 403 write-locked(拒绝时一个字节都不碰文件)。自 g-074 起 import 是唯一例外:备份就是整个安装(两层的所有覆盖、所有已注册的工作区层、预设库、偏好设置),恢复它不能被可写面挡住。这个豁免不额外付出检查代价——文档校验至少和以前一样严格,被拒绝的导入不写任何东西(CONTRACT §11.1、§11.7、§15.7)。
- 两层:用户级默认加工作区级覆盖。Cover(默认)让工作区文本替换用户文本;Stack 让工作区文本跟在用户文本后面,中间空一行,两段都进入提示词。适合「一套全局设置,再加这个项目的几行」。
- 装了但为空 = 没装:没有文本时,这一节对最终提示词毫无贡献,渲染结果逐字节相同。
- 数据在哪:只在插件自己的数据目录里(一个用户级层文件、一个工作区级层文件,外加一个 history.jsonl)。
「My Prompt」注入文本——它不是行为开关
- 它做的事是把你的文本注入到系统提示词末尾,排在所有内置节之后(本机实测:自 2026-09-30 21:32 起,standard 会话中 100% 存在、100% 排在最后)。它不是对模型行为的硬开关。
- 表层风格——输出语言之类——通常有效。 但对推理 / 内部思考语言的影响并不可靠,由模型和平台决定。我们在同一会话里测到过可见的中文输出,旁边却是全英文的推理。这和「插件没生效」不是一回事。
- 两种可证明无法生效的情况(要和「模型没理会」区分开):① 会话的智能体预设声明了 complete: true(内置的 minimal,以及本机的「梁神模式」)——平台把装配压成单个 section,本插件的文本进不了最终提示词,设置页会弹出阻断提示;② 插件根本没加载——插件坏了从不会影响 DSH 启动,所以终端是唯一信号;先跑 node scripts/check-compat.mjs。
为本次会话取证(两条路径,外加一条失败判定规则):
Path 1 (hardest evidence): read this session's persisted final prompt
ls ~/.dsh/sessions # find your workspace dir (escaped; non-ASCII becomes ~XXXX~)
F=~/.dsh/sessions/<workspace-dir>/<session-id>/session.v4.jsonl.zstd # e.g. --Users-me-Documents-proj--
zstd -dc "$F" | jq -r 'select(.type=="system/message") | .data.message.content[0].text[-200:]'
- 路径 2(图形界面):设置 → Prompt settings → 「My Prompt」面板看冻结警告,Advanced 标签页的状态卡看冻结状态和构建指纹(matches host / page is stale / unknown;「stale」只说明页面旧了——刷新即可)。
- 怎么读结果:末尾有你的那几行 ⇒ 注入正常,模型不遵守的话,原因在模型遵从度或预设被冻结;没有这些行(或文本为空)⇒ 先查该会话的 agentPreset 和冻结状态。
5. 仓库结构
packages/dsh-prompt-setting/ # the plugin package (publishable to npm on its own)
├── index.js # host half: routes + assembly listeners + the reserved section
├── client.js # client half: the four Settings tabs
├── core/ # pure-function kernels + the only module that touches the filesystem
├── cordis.patch.yml # bundle patch (one insert row mounting both halves)
├── scripts/ # check-compat.mjs (read-only diagnostic) + prepare.mjs (git-install gate)
├── CONTRACT.md # the frozen REST contract (the client is written against it)
├── NOTES.md # design trade-offs, measurements, untested items
└── test/ # eighteen test suites
assets/ # the hero image for this README
.dsh-graph/ # project board and event log (separate inner repo, not part of this one)
.worktrees/ # isolated worktrees for subagents (not part of this one)
6. 开发与测试
cd packages/dsh-prompt-setting
syntax
node --check index.js && node --check client.js && for f in core/.js scripts/.mjs; do node --check "$f"; done
node --test # 十八个测试套件;集成套件跑在真实 DSH 包上,必须通过(不能跳过)
node scripts/check-compat.mjs # 只读兼容性自检(不联网、从不抛错、始终 exit 0)
node scripts/prepare.mjs # pnpm 在 git 安装时执行的 prepare 门禁(失败时 exit 1)
npm pack --dry-run # 确认发布产物干净(29 个文件,不含 test/,不含 .dsh-graph)
本机最近一次运行:node --test 740 个测试全部通过,0 跳过(其中 31 个在集成套件里);npm pack --dry-run 报告 29 个文件(测量时间 2026-10-09)。
值得了解:
- test/integration.test.mjs 从你本地的 DSH 安装根目录解析出真实的 @deepseek-ai/dsh-system-prompt 和真实的 Cordis,在真实上下文里验证装配语义(waterfall 顺序、complete 冻结、作用域遮蔽)——这些结论是实测出来的,不是猜的——同样的结论也写进了 CONTRACT.md 和快照的 experiments 字段。
- 解析不到真实包时,套件会 skip,这样在没有 DSH 的机器上 node --test 依然全绿;但在开发机上你必须看到它通过,而不是跳过——跳过意味着证据缺失。
- 测试不需要浏览器:client.js 跑在 node:vm 沙箱里,require / React / fetch 全部打桩,所以「原语可用 / 不可用」和「探测成功 / HTTP 错误 / 网络错误」都能离线断言。
- 测试从不读写你真实的 ~/.dsh:相关套件把 $DSH_HOME 指向临时目录。
DSH 升级后插件不出现、终端又什么都不说,先跑 node scripts/check-compat.mjs——它会打印四种启动失败模式的终端特征和救援步骤。代码改动如何生效、维护者命令有哪些,见包 README 的「For maintainers」一节;详细测量数据见 NOTES.md §91。
7. 设计说明
- 可见:宿主侧调用 ctx.systemPrompt.assemble({scope: agent}),拿回各个 section(sections[{name,text}])和完整文本。
- 可写,且不碰核心:注册官方的 system-prompt/assemble waterfall 钩子,按 section 名替换 / 隐藏 / 追加——不改 DSH 核心,也不改全局安装。
- 插件注册自己的 section:在 apply 期间注册保留 section prompt-setting:custom-prompt(空文本,interpolate: false);你的文本经覆盖引擎落到这个 section 上,再由最外层监听器挪到最终装配的末尾。interpolate: false 不是风格选择:用户文本一旦参与插值,单个
{{unknown-variable}} 会让之后每一次装配都抛错。
- 分层设计,方便测试:除 store.js 外,core/ 下所有模块都是纯数据进、纯数据出;store.js 是唯一接触文件系统的模块,且不在装配路径上。装配路径上的监听器只读内存,并且总是调用 next()。
- 保守的失败策略:注册、自检或装配期间抛异常,绝不会让 DSH 启动失败;apply 执行中途失败会回滚已注册的效果,不留半挂载状态。
8. 文档地图
| 文档 | 面向 | 内容 |
| 本文件 | 所有人 | 是什么、怎么安装、怎么用、仓库速览 |
| packages/dsh-prompt-setting/README.md | 用户 / 开发者 | 包概览与功能(双语)、安装、维护者说明、故障排查 |
| CONTRACT.md | 开发者 | 冻结的 REST 契约:每个字段、action 枚举、大小限制和 4xx |
| NOTES.md | 开发者 | 设计取舍与实测数据(包括未测项和不得不撤回的结论) |
| CHANGELOG.md | 用户 / 开发者 | 每个版本的用户可见变更(双语;已发布 —— npm latest 是 0.2.2,本仓库是 0.2.5) |
9. 状态与路线图
- 已交付:插件骨架与本地配置档挂载(两部分,Settings 入口)、宿主侧装配快照 + system-prompt/assemble 覆盖引擎 + 用户/工作区两层持久化、Settings 提示词管理器(分区浏览、全文搜索、就地编辑并标出不可覆盖的分区、覆盖管理)、版本历史 + 差异对比、恢复默认、导出 / 导入。
- 当前形态(契约 Revision 8):写入面收窄到保留的「My Prompt」分区;其他分区全部只读;Settings 按功能和使用频率拆成四个顶层标签页。
- 本机验收状态、剩余边界和未测项见上面三份包文档;进度和验收证据在 .dsh-graph 看板上。
10. 许可证
MIT —— 见 LICENSE(packages/dsh-prompt-setting/LICENSE 是同一文件,随 npm 包发布)。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
zangxx66/dsh-prompt-setting
DeepSeek Harness 默认 System Prompt 管理插件:在 Web…
相关插件 · 技能 / 提示词
人设统管ZiChuanLan/agent-purge
一份系统提示词,喂给多个 coding…
★ 931已汉化DSH
73.8
人物画像蒸馏titanwings/distilly
Distilly — 把他们的思考方式提炼成可复用的技能,供任何智能体或机器人使用。原名 Colleague Skill(原同事 Skill)。
★ 25,659已汉化DSH
71.3
推理工作空间套件Tiger3807861189/J-Space-Cognition-Suite
J-Space 是面向复杂推理、大型仓库工程、子代理协作与授权安全分析的推理时工作空间和控制套件。
★ 2,957已汉化DSH
70.5
两阶段工具锚定预设xiaobright/dsh-anchored-standard
实验性 DeepSeek Harness agent preset…
★ 3,742已汉化DSH
70.1
智能体工作流编排nrslib/takt
不再日夜盯着 AI 编码智能体。
★ 1,402已汉化DSH
70
Agent 运行时手册Electricitysheep/dsh-handbook
DeepSeek Harness dsh 从 0 到 1 深度手册:安装/插件开发/性能调优/实测案例/同模型多…
★ 827已汉化DSH
68.7