🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

分层提示词管理 elfmingh/dsh-prompt-manager

DeepSeek 客户端
elfmingh4 天前有提交已提供中文文档扫描:含敏感能力兼容 / 相关生态

DeepSeek Harness 的分层提示词管理器 —— 档案条目按「全局 / 工作区 /…

31.1/100
综合分
2
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/elfmingh/dsh-prompt-manager.git

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
生态应用
桌面端 / Web 外壳,不以 dsh plugin add 安装
装得上吗
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 4 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件发起外部网络请求
查看扫描证据(共 3 处,展示前 3 条)
  • 写入本地文件
    index.js:560
    appendFileSync(join(dshHome(), 'prompt-manager-debug.log'), `${nowIso()} ${message}\n`)
  • 读取本地文件
    index.js:2090
    for (const name of await readdir(join(home, 'profiles'))) {
  • 发起网络请求
    client.js:291
    const response = await fetch(url, init)
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DeepSeek Harness 的分层提示词管理器:按工作区或会话复用条目,内置分区覆盖与行级 diff,还有真实的组装快照。

README

由 DeepSeek 最新模型翻译生成
dsh-prompt-manager 本页中英逐段对照:每个中文段落后跟英文段。 本页每段中文都配了对应的英文版本。 DeepSeek Harness 的分层提示词管理器 —— 档案条目按「全局 / 工作区 / 会话」三级投放,内置段落与运行时上下文可以禁用或覆盖,每次改动都能看到逐行 diff。没有构建步骤,改完刷新页面。 DeepSeek Harness 的分层提示词管理器 —— 可复用的提示词条目按三级投放(全局 / 工作区 / 会话),内置段落和运行时上下文都能禁用或替换,每次改动都有行级 diff。没有构建步骤:改完刷新即可。 侧边栏面板:左侧是档案库,右侧把条目拖进「全局」或某个工作区即可投放 左侧是档案库,右侧是投放区:把条目拖进「全局」就是所有会话都带上,拖进某个工作区就只在那个目录生效。图底部那行是存储文件的实际位置。 左边是档案库,右边是投放区。 把条目拖进「全局」,所有会话都会带上它;拖进某个工作区,就只有那个目录生效。底部那行显示存储文件的实际位置。
展开完整文档(README 剩余 1 节)
dsh-prompt-manager

本页中英逐段对照:每个中文段落后跟英文段。 本页每段中文都配了对应的英文版本。

DeepSeek Harness 的分层提示词管理器 —— 档案条目按「全局 / 工作区 / 会话」三级投放,内置段落与运行时上下文可以禁用或覆盖,每次改动都能看到逐行 diff。没有构建步骤,改完刷新页面。

DeepSeek Harness 的分层提示词管理器 —— 可复用的提示词条目按三级投放(全局 / 工作区 / 会话),内置段落和运行时上下文都能禁用或替换,每次改动都有行级 diff。没有构建步骤:改完刷新即可。

侧边栏面板:左侧是档案库,右侧把条目拖进「全局」或某个工作区即可投放

左侧是档案库,右侧是投放区:把条目拖进「全局」就是所有会话都带上,拖进某个工作区就只在那个目录生效。图底部那行是存储文件的实际位置。

左边是档案库,右边是投放区。 把条目拖进「全局」,所有会话都会带上它;拖进某个工作区,就只有那个目录生效。底部那行显示存储文件的实际位置。

它解决的是这几件事:

- 想给所有会话固定加一段指令,但又不想动 DSH 源码或每次手动粘贴
- 想只在某个项目里关掉某条内置约定,别的地方保持原样
- 想知道这一轮真实的系统提示词长什么样 —— 包括子代理拿到的那一份

它解决三个问题:

- 给所有会话固定加一段指令,不用改 DSH 源码,也不用每次手动粘贴
- 只在某个项目里关掉某条内置约定,其他地方保持原样
- 看清这一轮的系统提示词实际长什么样 —— 包括子代理收到的那一份

✨ 功能 · Features

- 三级投放 —— 一条条目可以只给当前工作区、只给某个会话,或者全局。工作区按归一化路径识别,换目录自动切换。
- 内置段落改写 —— Harness 和其他插件注册的 section 都能禁用或替换全文。列表是真实装配出来的,不是硬编码清单。
- 运行时上下文改写 —— working-directory:current、sandbox:policy、team:identity 这类每轮动态生成的 context 同样可禁用或覆盖。
- 逐行 diff —— 被覆盖的段落用行级 LCS 标出真正变化的行,未变段落折叠成「⋯ N 段未变」,同一行内再用公共前后缀剥离定位到具体那几个字。
- 父子智能体作用域 —— 条目可选「主+子代理 / 仅主代理 / 仅子代理」,判定依据是框架写入的 origin / parentSession / delegationDepth。
- 改动时机分两条路 —— 全局改完等下一个会话,会话页改完立即生效且只影响那一个会话。原因是提示词前缀缓存:前缀一动,整段缓存作废。
- 真实装配快照 —— 每轮记录 system-prompt/assemble 的结果,可枚举 agent 作用域的段落和全部工具,是唯一能看到子代理提示词的地方。
- 工具 + HTTP 接口 —— 全部能力都能从 prompt_manager 工具或 /prompt-manager/api 调用,Web 界面只是其中一层壳。

英文版:

- 三级投放 —— 条目可以投给当前工作区、单个会话,或全部。工作区按归一化路径识别,切换目录就切换生效的条目集合。
- 内置段落改写 —— Harness 或其他插件注册的任何 section 都能整段禁用或替换。列表来自真实装配,绝不是硬编码清单。
- 运行时上下文重写 —— 每轮的上下文,比如 working-directory:current、sandbox:policy、team:identity,也能禁用或覆盖。
- 行级 diff —— 覆盖过的段落按行做 LCS 比对,只高亮真正改动的行;没变的连续行折叠成「⋯ N 行未变」;改动行内部再剥掉公共前缀和后缀,把高亮收窄到真正不同的那几个字符。
- 父/子智能体作用域 —— 条目可以标成「主智能体 + 子代理 / 仅主智能体 / 仅子代理」,依据是框架写进 SessionHeader 的 origin / parentSession / delegationDepth。
- 两种生效时机,故意这么设计 —— 全局改动等下一个会话;会话页改动立即生效,且只作用于那一个会话。原因是提示词前缀缓存:前缀一动,整段缓存就作废。
- 真实装配快照 —— 每轮都记录 system-prompt/assemble 的结果,列出智能体作用域的各个段落和全部工具。这是唯一能看到子代理提示词的地方。
- 工具 + HTTP API —— 所有功能都能通过 prompt_manager 工具或 /prompt-manager/api 访问。Web UI 只是套在外面的一层壳。

🚀 安装 · Installation

前置:DSH >= 0.2.1-rc.2,Node ^22.19.0 || >=24.0.0。

Requires DSH >= 0.2.1-rc.2 and Node ^22.19.0 || >=24.0.0.

安装 / Install:

dsh plugin --profile web add @vertixara/dsh-prompt-manager

本地源码(开发时)/ From source, while developing:

git clone https://github.com/elfmingh/dsh-prompt-manager.git
dsh plugin --profile web add link:./dsh-prompt-manager
dsh web

dsh plugin 是 pnpm 的转发器,但它多做一步关键动作:把包名写进 profile package.json 的 dsh.profile.bundles。那个列表才是启用开关 —— 包装上了但没进 bundles,DSH 不会加载它。

dsh plugin forwards to pnpm, but with one extra step that matters: it writes the package name into dsh.profile.bundles in the profile's package.json. That list is the enable switch. Install a package without adding it to bundles and DSH will never load it.

卸载与更新 / Uninstall and update:

dsh plugin --profile web remove @vertixara/dsh-prompt-manager
dsh plugin --profile web update @vertixara/dsh-prompt-manager@latest

🎯 五分钟上手 · Quick start

1. 打开左侧边栏的提示词面板
2. 在「提示词档案」页签新建一条:填标题和正文
3. 右侧「全局」区块里把它的开关打开
4. 新开一个会话 —— 条目会出现在那个会话的系统提示词里,会话页签的「本会话生效条目」能看到它

English:

1. Open the Prompts panel in the left sidebar
2. Under the Prompt library tab, create an entry: title and body
3. Flip its switch in the Global block on the right
4. Start a new session — the entry is now in that session's system prompt, visible under Effective entries on the session tab

想临时试一段话不想留档?直接在会话页签里加临时条目,下一轮就注入,只影响这个会话。

Want a one-off without keeping it? Add a temporary entry from the session tab: it is injected on the next turn and affects that session only.

⏱️ 改动什么时候生效 · When changes take effect

这是这个插件最需要理解的一点。提示词是服务端的前缀缓存,前缀一变整段缓存就作废,所以规则故意分成两条路: 这是理解插件时最值得搞清楚的一点。 提示词在服务端做前缀缓存:前缀一动,整个缓存就失效。所以改动被刻意分成两条路径。

| 你在哪改 | 写进哪里 | 生效时机 | 影响范围 |
| 主页 | sections / contexts | 新建会话 | 全局 |
| 会话页 | sessionSections / sessionContexts | 立即 | 只那个会话 |
| 主页总开关 | enabled | 立即 | 全局 |

主页是配置,改完等下一个会话;会话页是当场的精细操作,你清楚自己在动缓存,就立即给你看到效果。

会话第一次装配时会冻结当时的全局规则(freezeBaseline),之后主页再改不会追杀已经在跑的会话。反过来说,主页禁用了某个段落、你想让当前会话恢复它,就在会话页点「重新开启」—— 那会写一条会话级 {"mode":"enable"} 推翻基线,而不是去动全局规则。

因此 override.set 的 mode 有三种:disable、replace(需 text)、enable。

👪 谁能看到什么

档案条目和临时条目都能标作用域:

| 标记 | 注入给 |
| 主代理 + 子代理(默认) | 两者都注入 |
| 仅主代理 | 只有主会话 |
| 仅子代理 | 只有它派生的子代理 |

判定依据是框架写进 SessionHeader 的 origin / parentSession / delegationDepth,插件不自己推断。

临时条目写在「打开它的那个会话」名下,但会沿父链传给该会话派生的子代理、孙代理 —— 否则在会话页给子代理写的东西永远到不了子代理。无关会话之间照旧隔离。

所有提示词都按字面量注入:{{...}} 不会被当成变量解析。宿主默认会解析,遇到未定义的变量直接抛异常让整轮装配失败,写一句模板示例就能搞坏一个会话。

🧭 核心概念

| 概念 | 是什么 | 存在哪 |
| 档案条目 | 长期保存的提示词片段,只存内容不存作用域 | entries[] |
| 应用关系 / Application | 哪个条目在哪个范围里启用/禁用/设为默认 / Which entry is enabled/disabled/default in which scope | applications |
| 临时条目 / Temporary entry | 绑定单个会话、走后注入、可随时删 / Bound to one session, injected post-hoc, disposable | temporary[] |
| 改写规则 / Override | 对 section / context 的 disable 或 replace / Disable or replace a section or context | overrides |

拆开「条目」和「应用」的原因:同一条指令往往既想在全局生效、又想在某个项目里例外,合并成一个对象就没法表达了。

Entries and applications are separate on purpose: the same instruction usually needs to apply globally and have an exception in one project. Fold both into a single object and you cannot express that.

🖥️ 界面 · UI

侧边栏面板 · Sidebar panel

两个页签:

- 提示词档案 —— 左侧档案列表(可搜索),右侧全局 / 工作区应用区
- 内置与其他插件 —— 真实装配出的 sections 与 tools;段落可开关、可覆盖,工具只读(五十多项,默认折叠,搜索时自动展开)

Two tabs:

- Prompt library — searchable entry list on the left, global and per-workspace application areas on the right
- Built-in and other plugins — the sections and tools from real assembly; sections are toggleable and overridable, tools are read-only (fifty-plus, collapsed by default, expanded while searching)

顶部左侧是改写状态徽章(绿「改写生效中」/ 灰「改写已停用」标注状态),右侧是独立的动作按钮(生效时「停用改写」、停用时「启用改写」)加「全部恢复」和规则计数。状态和动作分开,一眼能看出现在是哪种。

Top left is the override status badge (green "active" / grey "disabled"). Top right holds the separate action buttons — "Disable overrides" when active, "Enable overrides" when not — plus "Restore all" and a rule count. Status and action are split so you can tell which state you are in at a glance.

会话页签 · Session tab

每个会话的「提示词」页签额外展示:

- 本会话生效条目 —— 全局 + 工作区 + 临时合并后的最终结果
- 系统提示词段落(默认折叠)—— 和主页同一套管理,但改动立即生效、只影响本会话
- 本会话上下文 —— 该会话动态生成的运行时信息,同样只作用于本会话
- 本会话的子代理 —— 拉起过的子代理各自继承了哪些条目,「仅主代理」「仅子代理」标签会显示在这里
- 临时条目管理 —— 可选择注入给主代理还是子代理

Each session's Prompts tab additionally shows:

- Effective entries — the merged result of global, workspace, and temporary
- System prompt sections (collapsed by default) — same management as the main page, but immediate and scoped to this session
- Session contexts — runtime information generated for this session, likewise session-scoped
- Subagents of this session — which entries each spawned subagent inherited; the scope tags appear here
- Temporary entries — choose whether it targets the main agent or subagents

颜色语言 · Colour language

| 颜色 / Colour | 含义 / Meaning |
| 红 / Red | 禁用 / 被移除 — disabled or removed |
| 黄 / Yellow | 覆盖(--dsw-alias-state-warn-primary)— overridden |
| 绿 / Green | 正常生效 — active |

diff 里新增行是黄色、删除行是红色,行内高亮用 color-mix 混合该 token,跟随明暗主题。被禁用的条目仍留在列表里标红划线,点「重新开启」就能恢复。

In diffs, added lines are yellow and removed ones red; inline highlights use color-mix against that token so they follow light and dark themes. Disabled entries stay in the list, struck through in red, until you click "Re-enable".

🗂️ 数据 · Data

$DSH_HOME/prompt-manager.json

{
"version": 2,
"entries": [{ "id": "...", "title": "...", "text": "...", "order": 9000, "agentScope": "inherit" }],
"applications": {
"global": { "enabled": ["entry-id"] },
"workspaces": {
"d:/my-project": {
"enabled": [], "disabled": [], "default": [],
"hotReload": false // true = 该工作区条目走后注入 / post-hoc injection } } },
"temporary": [{ "id": "temp-...", "sessionId": "...", "title": "...", "text": "...", "order": 9000, "agentScope": "inherit", "createdAt": "..." }],
"overrides": {
"enabled": true, // 总开关 / master switch (immediate)
"sections": { "harness:identity": { "mode": "disable" },
"ui:deliverable-file-references": { "mode": "replace", "text": "..." } },
"contexts": { "team:identity": { "mode": "disable" } }, // 全局基线,新建会话生效 / global baseline, next session
"sessionSections": { // 按会话隔离,立即生效 / per-session, immediate
"session-abc": { "plan:policy": { "mode": "disable" } }
},
"sessionContexts": {
"session-abc": { "app:web-surface": { "mode": "disable" } }
},
"saved": [{ "id": "saved-...", "name": "...", "layer": "sections", "text": "...", "createdAt": "..." }]
}
}

工作区键是归一化路径(小写、正斜杠)。saved 是覆盖文本归档:恢复默认或一键恢复时自动写入,可在面板点「应用」重新装上,最多保留 100 条;来自某个会话的覆盖会带上 sessionId,应用时回到那个会话。

version 是数据格式版本,跟包版本无关。旧 store 会自动补齐缺失字段。

🧰 工具与 HTTP · Tool and HTTP API

工具名 prompt_manager,动作如下:

list | preview | library.add | library.update | library.remove
apply.toggle | apply.default | apply.hotReload
override.set | override.clear | override.toggle | override.reset | override.restore | override.forget
temp.add | temp.remove | reload | path

override.set 需要 name + mode(disable / replace / enable),可带 layer(section / context,默认 section)。带 sessionId 只写该会话的规则(立即生效),不带则写全局基线(新建会话生效)。

HTTP 端点挂在 /prompt-manager/api,都接受 sessionId:

| 查询 | 返回 |
| 无参数,或 ?view=snapshot | 档案、应用、临时条目、overrides 全文 |
| ?view=session | 某会话当前解析出的条目(静态 + 后注入)/ Entries resolved for one session (static + post-hoc) |
| ?view=assembled | 真实装配快照,含智能体作用域段落、全部上下文与工具 / Real assembly snapshot: agent-scoped sections, all contexts and tools |
| ?view=system | ⚠️ 已废弃 / deprecated,响应带 deprecated: true,仅宿主作用域调试用 / host-scoped debugging only |

?view=system 拿不到智能体作用域的内容(assemble({}) 不传 scope,waterfall 不派发给 scoped listener),返回的宿主段落与真实提示词不一致,容易误导。面板一律用 ?view=assembled —— 后者由 waterfall 每轮记录,没产生过装配的会话会返回 ok:false 加原因。

?view=system cannot see agent-scoped content: assemble({}) passes no scope, so the waterfall never dispatches to scoped listeners, and the host sections it returns do not match the real prompt. The panel always uses ?view=assembled, which the waterfall records every turn; a session that has never assembled returns ok:false with a reason.

端点安全 · Endpoint security

路由直接挂在宿主的 webServer 上,宿主不提供统一的认证或来源策略,所以由插件自己守:

The route mounts directly on the host's webServer. The host offers no central authentication or origin policy, so the plugin enforces its own:

- Host 必须是回环地址(127.0.0.1 / localhost / [::1],可带端口)—— 这一条挡的是 DNS rebinding:攻击者把自己的域名解析到 127.0.0.1,让用户浏览器朝本机端口发请求,此时 Host 和 Origin 都是攻击者的域名、二者自洽,只比较同源的检查会全部放行。Host 由浏览器按实际目标填写,页面脚本改不了它,所以校验 Host 是可靠判据。
/ Host must be a loopback address (127.0.0.1 / localhost / [::1], port optional). This blocks DNS rebinding: an attacker points their domain at 127.0.0.1, the browser then sends both Host and Origin as that domain, so a same-origin-only check passes everything. The browser fills Host from the real destination and page scripts cannot forge it, which makes it the reliable signal.
- 带 Origin 且与 Host 不同源 → 403 / Origin present and not same-origin with Host → 403
- 写操作必须是 content-type: application/json —— 跨站的「简单请求」发不出这个类型,浏览器会先预检,而本路由不返回任何 CORS 响应头,预检必然失败 / Writes must be content-type: application/json — a cross-site "simple request" cannot send that type, the browser preflights first, and with no CORS headers on this route the preflight always fails
- 请求体上限 1 MB / 1 MB body cap

挡不住的是本机任意进程:它本来就能直接读 $DSH_HOME/prompt-manager.json。这里防的是浏览器跨站。

What this does not stop is any local process: it can read $DSH_HOME/prompt-manager.json directly anyway. The guard is aimed at cross-site browser requests.

如果你的界面不是从回环地址打开的(局域网 IP、反向代理、容器里映射出来的主机名),上面第一条会把你自己的正常请求也挡掉,需要把那个主机名加进白名单:

If you open the UI from something other than a loopback address (a LAN IP, a reverse proxy, a hostname mapped out of a container), the first rule will block your own legitimate requests too. Add the hostname to the allowlist:

profile 的 bundle patch 里,和 storeFile 同级 config: allowedHosts:
- 127.0.0.1
- localhost
- my-dsh-box.lan # 你实际访问用的主机名

只加主机名,不要带协议和路径;端口会被自动忽略。

🛠️ 开发 · Development

dsh-prompt-manager/
├─ index.js Host 端插件(工具 + HTTP + 注入逻辑) ├─ client.js Web 客户端(侧边栏面板 + 会话页签) ├─ cordis.patch.yml 插入到 profile 的 bundle patch ├─ locale/ 面板文案(zh / en) ├─ test/ 测试(不随包发布) └─ scripts/ 维护脚本(不随包发布)

有两种注入路径,理解它们的差别才能看懂代码:

| 方式 | 实现 | 生效时机 |
| 静态 | systemPrompt.section() | agent 创建时注册 |
| 后注入 | system-prompt/assemble waterfall 追加 | 每轮装配 |
| 覆盖 | 同一个 waterfall 里改 sections / contexts | 每轮装配 |

section() 是一次性注册,agent 创建之后再加的段落不会进入它已经装配好的提示词 —— 临时条目必须走 waterfall 才能在下一轮出现。
powershell
npm test # 59 个用例
npm run check:diff # diff 算法 10 项断言
npm run check:client # 客户端工厂能否被 ModuleLoader 加载

测试用 mock ctx 在进程内跑真实 apply(),不需要起 DSH 进程;$DSH_HOME 指向临时目录,不碰真实存储。--experimental-test-isolation=none 是必需的:受限沙箱里 node --test 默认给每个文件开子进程会被 EPERM 拒绝。

CI 在 Node 22 和 24 上各跑一遍。推 v 标签触发完整的自动化交付:校验标签与 package.json 版本一致 → 跑测试与自检 → 发 npm(带 provenance)→ 等 registry 可见 → 建 GitHub release 并挂上 tarball。任一步失败后续不执行,不会出现「npm 上有版本但仓库没产物」这类漂移。

维护脚本: powershell
node scripts/snapshot-sections.mjs http://127.0.0.1:<port> [sessionId] # 抓一次装配快照
node scripts/find-in-asar.mjs "要搜的文本" [前后字符数] # 在 app.asar 里按字面量搜

前者把 ?view=assembled 的结果写入 docs/snapshots/sections-<timestamp>.{json,md},用于版本对比。docs/snapshots/ 和 research/ 都在 .gitignore 里:它们含本机路径和会话内容,不进公开仓库。

发布全自动: 改 package.json 里的 version,提交,推一个同名标签,剩下的交给流水线。publishConfig.access 已是 public,files 白名单只含运行时文件。CI 需要仓库里有个 NPM_TOKEN secret,权限限定到本包。

⚠️ 已知限制 · Known limitations

- 界面语言跟随 DSH 的界面语言,切换后立即生效。 取值顺序:宿主 locale 服务(ctx.locale.getLocale().active)→ → navigator.language。前两个都同步可读,第三条只是兜底 —— 拿系统语言判断是错的,系统中文 + DSH 英文时会判成中文。侧边栏和会话页签的标题由宿主渲染,它本来就订阅了 ctx.locale,语言一变就重新调 label(),所以插件里的 t() 也必须现场读,不能缓存。另有少量文案来自 Host 侧(工具返回值、prompt_manager 的 action 结果),这些也跟随界面语言,通过请求上的 ?lang= 传过去。
- 静态注册的条目改不到已经在运行的智能体,只能重建会话
- 后注入只能追加,要撤掉已注入的内容必须用 override disable
- required: true 的上下文被移除后是否恢复,由框架决定
- 工具描述只读:改它需要动 assembly.tools,风险过高,未开放
- 面板显示的 tools 数量取决于目标会话是否产生过装配
- complete 段落会在 waterfall 之后被框架还原,对它做改写无效(当前环境未观测到)

存储与并发 · Storage and concurrency

- 同一个存储文件只允许一个写入进程。 插件用「临时文件 + rename」保证单进程内的原子替换,并让全部读写事务走同一条队列,但没有跨进程互斥。同时跑两个 DSH 实例并指向同一个 prompt-manager.json,两边会互相覆盖。需要多进程时请各自用不同的 storeFile。
- 排队有期限。 写入要排队;等了 10 秒还没轮到的请求会明确失败(WRITE_QUEUE_TIMEOUT),而不是无限期挂着。已经开始执行的事务不受这个期限约束,会正常跑完。
- 读不到配置时拒绝修改。 存储文件读取失败时,界面仍会展示最后一次成功读到的内容,但所有修改动作会被拒绝(STORE_UNREADABLE)—— 否则会拿旧内容整份写回,把磁盘上可能还完好的数据覆盖掉。
- .tmp 文件需要手工清理。 保存是先写 <storeFile>.<pid>-<ts>-<nonce>.tmp 再 rename。
rename 失败时这份临时文件会被故意保留(它是唯一一份完整可用的内容)。确认自己不需要之后,手工删掉即可;插件不会自动清理,因为无法可靠判断某个临时文件是否还属于一个正在进行的事务。
- .corrupt- 是抢救记录。 首次加载时如果存储文件无法解析,它会被改名成 <storeFile>.corrupt-<时间戳> 留证据。确认内容没用了再手工删。
- 写入使用 flush: true 请求把内容刷到存储设备,降低掉电后留下空文件或半截文件的可能。
这不是断电保证:目录项的持久化取决于操作系统与文件系统。

English:
- 面板语言跟随 DSH 的 UI 语言,并实时切换。 解析顺序是:先取宿主 locale 服务(ctx.locale.getLocale().active),再取 ,最后取 navigator.language。前两者可同步读取;第三个只是兜底——按系统语言判断是错的,因为中文系统把 DSH 设成英文时,解析结果仍是中文。侧边栏和会话标签页标题由宿主渲染,宿主已经订阅 ctx.locale,每次切换都会重新调用 label(),所以插件的 t() 必须实时读取,不能缓存。少数文案来自宿主侧(工具返回值、prompt_manager 动作结果),它们同样跟随 UI 语言,通过请求上的 ?lang= 传递。
- 静态条目无法触达已在运行的智能体;只有重建会话才有用
- 事后注入只能追加;要移除已注入的内容,得用覆盖项 disable
- required: true 的上下文移除后是否回来,由框架决定
- 工具描述是只读的:要改就得改动 assembly.tools,风险太大,保持关闭
- 面板显示的工具数量,取决于该会话是否装配过
- complete 段由框架在水瀑布之后恢复,改写它没有效果(本环境未观察到)
- 每个存储文件只允许一个写入进程。 单进程内保证原子替换,每次读写事务共用一条队列,但没有跨进程锁。两个 DSH 实例指向同一个 prompt-manager.json 会互相覆盖;请给每个实例分配自己的 storeFile。
- 排队有上限。 10 s 内还没开始的写入会以 WRITE_QUEUE_TIMEOUT 失败,而不是一直挂着。已经开始的事务永远不会被中断。
- 存储不可读时拒绝写入。 存储读不出来时,UI 继续显示最后一次成功加载的内容,但所有变更操作都会以 STORE_UNREADABLE 拒绝——否则过期副本会被写回去,覆盖可能仍然完好的数据。
- .tmp 文件需要手动清理。 保存时先写 <storeFile>.<pid>-<ts>-<nonce>.tmp,再重命名。重命名失败会故意保留该文件(它是唯一完整的副本)。确认不再需要后请手动删除;插件不会自动清理,因为它无法可靠判断临时文件是否还属于某个正在运行的事务。
- .corrupt-* 文件是抢救证据。 无法解析的存储在首次加载时会被重命名为 <storeFile>.corrupt-<timestamp>。处理完后请手动删除。
- 写入使用 flush: true,请操作系统把内容推送到存储设备,降低断电后出现空文件或半写文件的可能性。这不是断电保证:目录项的持久性取决于操作系统和文件系统。

👤 作者 · Author

Vertixara

- 邮箱 / Email: <public@vertixara.com>
- 仓库:<https://github.com/elfmingh/dsh-prompt-manager>
- 问题反馈:<https://github.com/elfmingh/dsh-prompt-manager/issues>
- 变更记录:CHANGELOG.md

发现安全问题请直接发邮件,不要开公开 issue。

🙏 贡献与致谢

代码与文档由 AI 与 Vertixara 结对完成,审计独立进行。列在这里,是为了让后来者知道每部分由谁负责、按什么标准看过。

| 参与者 | 负责 |
| DeepSeek 4.1 Flash | 实现、核查、测试与文档 |
| GPT 6.1 Sol | 独立代码审计(审计报告):查出 2 项 P1、8 项 P2 |

🤖 关于这份代码

Host 端、Web 客户端、测试与 CI 绝大多数由 DeepSeek 4.1 Flash 与 Vertixara 结对写成:需求、取舍和验收由 Vertixara 拍板,实现、核查与修复由 DeepSeek 4.1 Flash 执行,审计由 GPT 6.1 Sol 独立完成。

写下这一点,是为了让后来者知道按什么标准读它 —— 哪些结论经过真机验证、哪些只有单元测试覆盖,都写在下面这段历史里:

- 0.2.1 的十项修复来自 GPT 6.1 Sol 的独立审计(报告保留在 docs/audit-2026-10-23.md),每条都回到代码和宿主源码逐条复核后才动手,未发现误报;其中鉴权、并发写入、路由生命周期三项在真实运行的 DSH 上做过验证。
- 剩下七项由 59 个用例覆盖,每条用例名带审计编号。测试全部在进程内用 mock ctx 跑真实 apply(),不需要起 DSH 进程。
- README 里关于宿主行为的断言(interpolate: false 的语义、register() 没有鉴权层、section() 只在创建时注册)都读过宿主安装包里的实际实现,不是推测。

📄 License

MIT
预览分享卡片长什么样 ↓elfmingh/dsh-prompt-manager
分享 · DeepSeek Harness Hub
elfmingh/dsh-prompt-manager

DeepSeek Harness 的分层提示词管理器 —— 档案条目按「全局 / 工作区 /…

这是你的仓库?认领条目

回到顶部