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

提示词注入器 yukk4159-bit/dsh-prompt-injector

DeepSeek Harness
yukk4159-bit21 天前有提交已提供中文文档扫描:含敏感能力

发送时把预设提示词拼到消息最前面,输入框保持干净

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

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

自动兼容检查有告警:未发布到 npm registry,仅可从源码安装。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add yukk4159-bit/dsh-prompt-injector
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:待复验
是什么
dsh 原生插件 · skill
装得上吗
曾在 dsh 0.2.0-rc.2 下真实安装成功,但当前 dsh 已更新至 0.2.1-rc.5,本站尚未在新版下复验
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 21 天前
档位由哪些信号合成

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

未发布到 npm registry,仅可从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-prompt-injector(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=22.5 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/13 09:38:35

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

读写/删除本地文件发起外部网络请求
查看扫描证据(共 6 处,展示前 6 条)
  • 发起网络请求
    client/client.js:166
    const response = await fetch(`/prompt-injector/${CONFIG.id}${path}`, {
  • 读取本地文件
    lib/store.js:40
    const body = await readFile(path, 'utf8')
  • 写入本地文件
    lib/store.js:55
    await mkdir(dirname(path), { recursive: true })
  • 写入本地文件
    lib/store.js:57
    await writeFile(temporary, `${JSON.stringify(value, null, 2)}\n`, 'utf8')
  • 写入本地文件
    lib/store.js:58
    await rename(temporary, path)
  • 发起网络请求
    client/index.js:124
    const response = await fetch(`/prompt-injector/${CONFIG.id}${path}`, {
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 发送时拼接预设提示词
  • 仅下一条生效
  • 每轮持续注入

DeepSeek Harness 插件:发送消息时把可复用的提示词预设插到消息最前面,可选仅下一条消息或每轮都注入。提示词注入器

README

由 DeepSeek 最新模型翻译生成
dsh-prompt-injector · 提示词注入器 一个 DeepSeek Harness Web 插件:把可复用的提示词预设在发送的那一刻注入到消息首部,而不是填进输入框。 注入几次由你决定:💌 只注入下一条(默认)或 💖 每轮都注入。 萌系二次元画面风格:🌸 粉紫渐变、圆角卡片、会呼吸的小表情。 在 DeepSeek Harness 0.2.0-rc.2 上实测可用(Host 侧 67 个用例,浏览器半在真实 GUI 里跑通,见已验证)。 长什么样 先选注入方式,再点预设: 选预设:面板顶部先选「只注入下一条」或「每轮都注入」 选好之后 chip 变成 💌 名字 下一条,输入框里一个字符都不会多: 只注入下一条:chip 显示 💌 … 下一条,输入框内容不动 发送时才是注入发生的时刻。
展开完整文档(README 剩余 1 节)
dsh-prompt-injector · 提示词注入器

一个 DeepSeek Harness Web 插件:把可复用的提示词预设在发送的那一刻注入到消息首部,而不是填进输入框。

注入几次由你决定:💌 只注入下一条(默认)或 💖 每轮都注入。

萌系二次元画面风格:🌸 粉紫渐变、圆角卡片、会呼吸的小表情。

在 DeepSeek Harness 0.2.0-rc.2 上实测可用(Host 侧 67 个用例,浏览器半在真实 GUI 里跑通,见已验证)。

长什么样

先选注入方式,再点预设:

选预设:面板顶部先选「只注入下一条」或「每轮都注入」

选好之后 chip 变成 💌 名字 下一条,输入框里一个字符都不会多:

只注入下一条:chip 显示 💌 … 下一条,输入框内容不动

发送时才是注入发生的时刻。下面是「每轮都注入」连发两条的结果——两条消息都带上了预设块,而输入框始终只有你自己写的话:

每轮都注入:两条消息都带预设块,输入框依然是空的

和「提示词预设」类插件的区别

| | 常见的预设插件 | 提示词注入器 |
| 选中预设后 | 把提示词填进输入框 | 只在输入框左侧显示一个 💌 / 💖 徽章,输入框内容完全不动 |
| 你打字时 | 要在一大段提示词后面接着写 | 输入框里只有你自己写的话 |
| 注入几条 | 选中就一直生效 | 默认只注入下一条,发完自动松开;想每轮都注入得自己切 |
| 发送时 | 提示词就是消息的一部分(你在输入框里看得见) | Host 端在 agent/pre-step 把提示词拼到消息最前面 |
| 对话记录 | 提示词和你的话混在一起 | 记录里是完整的注入后文本(模型看到什么,记录就是什么) |

实现位置:lib/inject.js 的 applyInjection(),注册在 agent/pre-step 瀑布事件上——这是消息进入会话日志之前的最后一个接缝。

为什么不是「往输入框塞标记」

最初的设计是往 composer 草稿里写一个不可见的选取标记,随消息一起送到 Host。实测下来这条路在当前版本走不通:

- DSH 的 composer 是 Lexical 编辑器,没有任何公开的草稿写入服务;
- Lexical 自己拥有文档状态,直接改 DOM 会被它下一次 reconcile 覆盖;
- 通过 DOM 事件(execCommand('insertText'))写入也依赖当前选区,而打开面板后焦点已经不在编辑器上。

所以选择改由 Host 侧按会话记录:浏览器半把「这个会话选了哪个预设、注入到什么时候」通过插件的 HTTP 接口告诉 Host(lib/http.js 的 /selection),Host 在发送瞬间查表注入。这样完全不依赖编辑器的内部实现,也不需要污染消息文本——顺带还让「只注入一条」变得容易实现:Host 注入完就把这条选择丢掉。

早期版本还写了一套「尽力而为」的草稿写入代码,已经删掉了:它写得进去也不起决定作用(真正生效的是 Host 侧的选择),留着只会让「到底谁说了算」变模糊。现在插件完全不碰输入框。

安装

插件是「bundle」形态(根目录有 cordis.patch.yml),用 dsh plugin 安装:

dsh plugin --profile web add "github:yukk4159-bit/dsh-prompt-injector"

dsh plugin 把包管理转发给 pnpm,所以也可以装本地路径或指定分支:

本地检出(改代码时用这个,改完重启就生效)
dsh plugin --profile web add "/path/to/prompt-injector"

指定分支或 tag
dsh plugin --profile web add "github:yukk4159-bit/dsh-prompt-injector#main"

或者在没有全局 dsh 的环境里:

npx -p @deepseek-ai/dsh dsh plugin --profile web add "github:yukk4159-bit/dsh-prompt-injector"

装完重启该 profile,然后打开 Web GUI:

- 输入框左边会多一个 🌸 预设 按钮 —— 点开挑预设;
- 左侧边栏 → 设置 → 提示词注入器 —— 管理预设库(增删改查、搜索、标签过滤)。

用法

1. 设置页写预设:名字、ID(可选)、标签、注入内容 → 保存。
保存会写进该 profile 的配置文件(cordis.patch.yml 的 config.presets),重启、切会话都不会丢。
2. 在输入框左边点 🌸,面板顶部先选注入方式,再点一个预设:
- 💌 只注入下一条(默认)——只有你紧接着发送的那一条会被注入,Host 注入完就把这条选择丢掉,再发就干干净净;
- 💖 每轮都注入——一直生效,直到你点「取消」。
面板顶部的切换是立刻生效的:已经选了预设时改方式,等于同时把那条选择改成新方式。
chip 上会写清楚现在是哪种(💌 名字 下一条 / 💖 名字 每轮),不会出现「以为只注入一次、其实一直在注入」。
3. 正常写你的话,回车发送。
4. 发送瞬间,Host 把预设正文按模板拼到消息最前面再交给模型。
5. 默认方式下,发完那一条之后 chip 自己回到 🌸(面板打开时每 3 秒问一次 Host,因为一次性选择是 Host 释放的,它没法主动通知页面)。

再点一次同一个预设、或点面板里的「取消」即取消。

不点面板也能用:{{ID}}

在消息里直接写 {{code}}(code 是这个预设的 ID),那一条就会用对应预设,发完即止——这本来就是一次性的,和 chip 的选择互不干扰。

- 写了一个库里有的 ID:注入并把这处 {{code}} 从消息里拿走;
- 写了一个库里没有的 ID:当成普通文字原样发出去,也不会挡住 chip 的选择;
- 指向已停用的预设:不注入,文字原样保留。

注入取值的优先级

1. 消息正文里的选取标记({{id}},或早期版本写入的私有区标记);
2. 本会话的选择(就是上面第 2 步记录的那个);
3. config.defaultPresetId。

私有区标记若指向一个不存在或已停用的预设,会刻意压掉后两级回退——你点名要它,就不该偷偷换成别的。手打的 {{id}} 没这个特权,因为它可能只是普通的文字。

关系

- 选择是按会话的:不同会话可以选不同预设,互不干扰。
- 「注入几条」记在浏览器里(localStorage),下次打开面板还是你上次选的方式。
- 选择本身存在 Host 进程内存里,重启即清空——它表达的是「这一轮我想用哪个」,不是持久配置。想常驻就用 defaultPresetId(它按定义就是每轮都注入)。

预设长什么样

presets:
- id: code
name: 代码评审 text: 请以资深工程师视角严格评审这段代码,指出风险与改进点。
tags: [work, code]
enabled: true

注入模板

config.template 决定包装形式,支持 {{name}}、{{id}}、{{text}}:

[{{name}}]
{{text}}
[/{{name}}]

配 config.separator(默认两个换行)拼在你自己的文字和预设块之间。
config.position 从 prefix(默认,消息首部)改成 suffix 就改成拼到末尾。

全部配置项

| 配置 | 默认 | 说明 |
| enabled | true | 总开关。关掉后 UI 还在,但不再注入。 |
| position | prefix | prefix 拼到消息首部,suffix 拼到末尾。 |
| template | [{{name}}]\n{{text}}\n[/{{name}}] | 预设正文外面的包装。 |
| separator | 两个换行 | 预设块与你自己的文字之间的连接串。 |
| defaultPresetId | 空 | 兜底预设:没人选、消息里也没有标记时用它。它按定义是每轮都注入;留空表示不注入。 |
| agentPresets | [] | 只对这些 agent preset 生效;留空表示全部。 |
| libraryPath | 空 | 可选的 JSON 副本路径(默认 <DSH_HOME>/prompt-injector/prompt-injector.json)。 |
| presets | [] | 预设库本体。 |

「注入几条」不是配置项:它是每次挑选时的一个手势,所以留在界面和浏览器里,不写进配置。

数据存在哪

1. 预设库主存储:该 profile 的 cordis.patch.yml 里的 config.presets。
设置页保存时通过 Harness 的 settings.update() 写回,所以它同时是「插件配置」和「预设库」,设置页的自动表单也能直接编辑它。
2. 可选 JSON 副本:设置在 settings 提供方不可用时(或者你想让库跟着仓库走)会退化写到 libraryPath;用一个 profile 里没有的 agent 跑时也能从这里读起来。
3. 会话选择:只在 Host 进程内存里,不落盘(见上)。

HTTP 接口

浏览器半用这三条路由和 Host 半对话;它们挂在组合后的 Host Web 服务器上,因此同样受该服务器的浏览器信任栅栏与鉴权保护。

| 方法 | 路径 | 作用 |
| GET | /prompt-injector/prompt-injector/library | 读预设库、标签和全部会话选择 |
| PUT | /prompt-injector/prompt-injector/library | 整库覆盖写入 |
| PUT | /prompt-injector/prompt-injector/preset | 新增或更新一条(按 id) |
| DELETE | /prompt-injector/prompt-injector/preset?id=… | 删除一条 |
| GET | /prompt-injector/prompt-injector/selection | 只读会话选择(面板的轮询用这条) |
| PUT | /prompt-injector/prompt-injector/selection | 记录/清空某会话的选择,body 为 {sessionId, presetId, mode},mode 取 once / sticky |

GET /library 返回的 selections 形如 {"session-…": {"presetId": "code", "mode": "once"}}。当 mode 是 once 时,Host 注入完那一条就会把这一项删掉——所以下一次 GET 里它就没了,面板据此把 chip 还原成 🌸。

路径里的 prompt-injector 是插件条目 id,两个实例不会互相覆盖。

项目结构

prompt-injector/
├─ cordis.patch.yml # bundle 入口:一行 insert ├─ package.json # dsh.bundle + dsh.client 声明 ├─ lib/ # Host 半(Node) │ ├─ index.js # 插件入口:Config、pre-step 注入、一次性选择的释放、路由与存储装配 │ ├─ config.js # Config schema(单独一个文件,为了隔离 schemastery 依赖) │ ├─ core.js # 纯函数:预设规范化、标记编解码、注入方式、模板渲染、拼接 │ ├─ inject.js # agent/pre-step 的注入逻辑(纯函数 + 消息重写) │ ├─ store.js # 预设库存储 + 会话选择(含 once/sticky):settings 写透 + JSON 原子副本 │ ├─ http.js # /prompt-injector/<id>/library、/preset、/selection │ └─ client/client.js # 构建产物:浏览器半 ├─ client/ # 浏览器半(手写 lazy-CJS 工厂,无需打包器) │ ├─ index.js # 入口:apply/inject、槽位注册、库与选择同步、方式偏好 │ └─ src/ # config / core / styles / composer / settings-page ├─ scripts/build-client.mjs # 把 client/ 组装成 client/client.js ├─ docs/ # README 里的截图 └─ test/ # node:test,无第三方依赖

client/client.js 是提交进仓库的构建产物:Harness 直接加载它,所以别人 clone 下来不需要构建就能装。

构建浏览器半 sh
node scripts/build-client.mjs

脚本自己做四件事:解析相对的 import、把 react / react-dom 转成平台 require、把每个源文件包进各自的闭包、最后包成模块加载器要的
window.__ModuleLoader__.load({ id, factory })。没有打包器依赖。

测试 sh
node --test --experimental-test-isolation=none "test/.test.js"

或

node scripts/build-client.mjs && node --test --experimental-test-isolation=none "test/.test.js"

必须写文件通配符:--experimental-test-isolation=none 下不能直接传目录。
在受限沙箱(workspace-write)里也必须保留 --experimental-test-isolation=none——默认的测试运行器会用管道 spawn 子进程,被沙箱拒绝(EPERM)。

覆盖:预设规范化 / 标记编解码(含手打 {{id}})/ 注入方式归一化 / 模板与拼接 / 消息重写(含非人类消息的排除、禁用预设、
allow-list、{{id}} 命中与否)/ 会话选择与一次性释放 / 存储写透与 JSON 原子副本 /
浏览器 bundle 的注册与槽位贡献 / Host 端 apply() 的完整 pre-step 路径。
共 67 个用例;其中「Config 默认值」需要 @deepseek-ai/schemastery 可解析,在纯仓库检出里会跳过。

已验证 / 待验证

已经实测:

- 注入真的发生在发送时、并且真的到了模型请求里。用一个临时观察插件监听 llm/stream,对 agent/pre-step 改写后的消息取证:请求里拿到的是 [PROBE-INJECTED] Reply with exactly: PROBE-OK,说明改写后的内容就是模型收到的那一条。
- 插件能被真实 profile 加载:dsh plugin --profile <name> add <本目录> 之后 bundle 层出现 - id: prompt-injector,Host 半正常 apply,禁用预设被过滤,HTTP 路由注册成功。
- 浏览器半在真实 GUI 里跑通:输入框左侧出现 🌸 预设 chip;面板能打开、搜索、按标签过滤;选中后 chip 显示预设名与方式;Host 侧 /library 的 selections 里能看到该会话的选择;「取消」后选择被清空。
- 「只注入下一条」真的只注入一条:在预览 profile 里真的打字 + 回车发送 4 条消息(该 profile 用的是假密钥,请求会 401,但注入发生在 agent/pre-step,即请求之前)。Host trace 与写进会话日志的正文分别是:
- 第 1 条(💌 选 code-review):changed=true preset=code-review source=session
- 第 2 条:changed=false source=none —— 选择已被释放
- 第 3 条(切到 💖 novel):changed=true preset=novel source=session
- 第 4 条:changed=true preset=novel source=session —— 每轮模式下继续注入会话日志里逐条对应:第 1 条带 [严格代码评审]… 块,第 2 条原样,第 3、4 条都带 [小说续写]… 块。发完之后 GET /selection 返回 {},chip 自己回到 🌸。
- 手打 {{id}} 也对:发一条 {{code-review}} 顺手看看 {{nope}} 这个写法,日志里记下的是预设块 + 顺手看看 {{nope}} 这个写法——命中的被注入并摘掉,没命中的原样留着。
- 设置页能读能写:左侧「设置 → 提示词注入器」列出 6 条预设(含停用项,标 🚫),搜索与标签过滤正常,保存后 Host 的 /library 确实返回了改动后的库。
- 选择 → 注入的完整链路(自动化用例):test/host.test.js 里一条测试直接走 HTTP 路由写选择,再驱动 agent/pre-step,断言消息首部出现 [小说续写],并断言 sticky 会连续两条都注入、once 只注入第一条且随后被释放。
- Host 端 67 个用例,66 通过、1 跳过(跳过的那条需要本机可解析 @deepseek-ai/schemastery)。

没验证的:真机上模型真的回话(预览 profile 没有可用密钥)、以及 DeepSeek 官方路由以外 provider 的行为——这两件都和注入逻辑无关。

调试开关

DSH_PROMPT_INJECTOR_TRACE=1 会在 stderr 打出 Host 半每一步(apply、库大小、webServer 等待、pre-step 决策、注入结果)。

实现要点
- 注入点是 agent/pre-step。它以 waterfall 方式运行,本插件先调用 next(),再改写返回的 messages,因此能和压缩等其它 pre-step 策略组合,而不是覆盖它们。
- 只改写「人类写的」用户消息:source.kind === 'user'。运行上下文快照、技能提醒、工具追加都不会被注入。
- 每个 step 最多改写一条,避免同一个预设被乘上多份。
- 标记用私有区字符,正常文本里不可能出现,因此不会误伤。
- 失败即放行:任何注入异常都会被记录并原样放行消息,绝不因为插件问题丢失你发出去的内容。
- 资源都有归属:路由、效果、样式表都注册在插件 fiber 的 effect 上,插件卸载自动回收。

已知限制

- 选择只在 Host 进程内存里,重启 DSH 会清空。它是「这一轮用哪个」的意图,不是持久配置;想常驻请配 defaultPresetId。
- 预设库的写入依赖 Harness 的 settings 服务。该服务不可用时退化为 JSON 副本,此时设置页的修改只在当前进程内生效。
- 注入后的文本会进入会话日志——这是有意为之:记录应当等于模型真正收到的东西。
- 一次性选择由 Host 释放,页面只能事后知道:面板打开时每 3 秒 GET /selection 一次(只在有一次性选择待发时轮询)。所以发完消息后 chip 可能需要最多 3 秒才从 💌 变回 🌸——这不影响注入,只是徽章慢一拍。
- {{id}} 只在 ID 命中库里的预设时才当作引用,所以预设 ID 起得越像普通词(例如 code),越有可能误伤正文里的 {{code}} 写法。介意的话把 ID 起得独特一点(例如 pi-code)。

贡献

欢迎开 issue 报 bug、提想法,或者直接 PR。改浏览器半的代码之后记得跑一次 node scripts/build-client.mjs——client/client.js 是要一起提交的构建产物。

许可

MIT,见 LICENSE。
预览分享卡片长什么样 ↓yukk4159-bit/dsh-prompt-injector
分享 · DeepSeek Harness Hub
yukk4159-bit/dsh-prompt-injector

发送时把预设提示词拼到消息最前面,输入框保持干净

回到顶部