npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-round-inject

v0.1.28

Published

Periodic prompt injection for the DeepSeek Harness Web GUI: every N model invocations (conversation turns and tool-call steps both count) the plugin injects a user-configured prompt as a model-visible user message; the first injection happens at conversat

Readme

dsh-round-inject

为 DeepSeek Harness Web GUI 提供的周期性提示词注入插件。

每 N 次模型调用(对话轮与工具调用轮各计一次)注入一次用户配置的提示词,作为模型可见、带来源标记的用户消息进入上下文;每次对话开始默认注入一次。

| | | | --- | --- | | Host | agent/pre-step 瀑布(统计每个真正进入的 step,并把注入消息追加到该 step 的请求) | | Client | 一个设置页(settings.section),通过 configForms 读写本条目 Config。DSH 0.1.7 会依据 volatile Config 字段派生表单数据,但并未随附任何会为其渲染页面的客户端(autoGenerate 是给未来客户端预留的),因此仍需自行提供页面 | | 配置 | 插件条目自身的 Config(live volatile() 字段),在自动生成的设置页中编辑 |

功能

  • 轮次统计 —— 每次模型调用计 1 次,包括工具结果触发的下一步(工具调用后模型会再次被调用 = 又一个 step)。计数器按 agent 隔离(主会话与子代理互不影响)。
  • 周期注入 —— 距上次注入恰好满 interval 个已完成模型调用后,把配置的提示词追加到那一步的消息中(默认 50):开启开始注入时,注入发生在会话的第 1、1+interval、1+2·interval… 次调用;关闭时发生在第 interval、2·interval、3·interval… 次调用。注入消息携带 source: { kind: 'plugin', plugin: 'round-inject' },写入会话日志,模型可见。
  • 对话开始注入 —— 开启且填了开始提示词时,会话的第一次模型调用即携带开始提示词,周期计数随后从这次调用重新起算。
  • 设置界面 —— 设置 → 提示词注入:启用开关、触发轮次(数字输入,默认 50)、注入提示词(多行输入框)、对话开始时注入开关。写入通过标准 settingsScope 服务落到 round-inject 命名空间(持久化到 DSH 设置文档)。
  • 默认安全 —— 提示词为空 ⇒ 不注入;关闭 ⇒ 不计数也不注入;不真正调用模型的 step 不会被计数。

安装

本包是发布到 npm 的 DSH 插件。在 DSH profile 目录执行:

dsh plugin --profile web add dsh-round-inject

或手动把依赖加入 profile 的 package.json,并把 "dsh-round-inject" 追加到 dsh.profile.bundles,然后重启 profile。

配置

组合行(同时也是设置命名空间的 base 层):

- **0.1.17** —— 修复 0.1.15 适配引入的挂载失败:`cannot get property "sessionProjections" without inject`。Cordis 对服务访问有守卫,从 `ctx` 读取服务必须先声明 —— 插件现导出 `inject = ['sessionProjections']`(内置 fold 也是同样声明)。已在启用守卫的真实 cordis Context 下挂载验证通过。
- id: round-inject
  name: 'dsh-round-inject'
  config:
    enabled: true        # 总开关
    interval: 50         # 两次注入之间的模型调用次数
    prompt: ''           # 注入的提示词文本(为空则不注入)
    injectOnStart: true  # 每次对话开始注入一次

所有值都可以在 设置 → 提示词注入 中实时修改,无需重启。

工作原理

宿主在 sessionProjections 接缝上注册一个纯 fold,并在 agent/pre-step 瀑布上执行注入:

  1. 计数与书签共用一个 fold —— round-inject 投影是对会话事件流的纯折叠,只消费内置事件、从不追加自定义事件类型,因此恢复会话永远不会因本插件的词汇失败:
    • 每个 step/end(一次完成的模型调用,与内置 "N 轮 · M 步" 统计同一事件)推进 totalSteps,并在会话注入过之后推进 sinceInject(距上次注入消息已完成的调用数);
    • 一条由本插件追加的 user/message(以其 source: { kind: 'plugin', plugin: 'round-inject' } 识别)记录 lastInjectSeq 并把 sinceInject 归零。 注册表把状态检查点到 <root>/session_projcache/,因此计数与书签都扛得住压缩、翻页、会话恢复与宿主重启。书签放在这份派生状态里(而不是 0.1.11 会跨会话泄漏的设置命名空间,也不是 0.1.13 中不存在的 session.events —— 后者让每一步都崩溃),使间隔精确:每个事件 O(1) 折叠,绝不每步全量扫描日志。
  2. 注入(副作用) —— 监听 agent/pre-step 瀑布(每个拟议 step 一次)。在 next() 返回 loop 自身决策后:
    • 忽略 reject 决策与空消息 step(这些不会调用模型);
    • 通过 live volatile() 引用读取最新配置;
    • 读取投影状态(totalSteps / sinceInject / lastInjectSeq)并判定:
      • 本会话从未注入且开启开始注入 → 把开始提示词追加到第一次模型调用;
      • 从未注入且无开始提示词 → 把周期提示词追加到会话第 interval 次调用;
      • 否则当 sinceInject >= interval → 把周期提示词追加到下一次模型调用 —— 正好在上次注入之后 interval 步;
    • 整个判定有防护:任何意外错误只记 warning 并放行该步(不注入),插件永远无法拖垮一轮 agent 运行。 注入消息作为 createUserMessage({ content: [{ type: 'text', text: prompt }], source: { kind: 'plugin', plugin: 'round-inject' } }) 追加,成为该步持久化用户消息的一部分 —— 模型可见、会话日志可审计,并适用于任何模型路由。

KV cache 说明

注入会改变注入 step 的请求内容,因此从该请求起 provider KV/prefix cache 会失效一个回合的若干 step。默认 50 轮时影响可忽略;调小轮次会增加失效频率。

更新历史

  • 0.1.28 —— 兼容 DSH 0.2.x。 peerDependencies 把 @deepseek-ai/dsh-llm 卡在 ^0.1.1-rc.1 || ^0.1.7-rc.1、 @deepseek-ai/dsh-session-projection 卡在 ^0.1.7-rc.1。0.x 版本的脱字符 永远够不到下一个次版本(^0.1.7-rc.1 实际含义是 <0.2.0),而 DSH 会把每个 @deepseek-ai/dsh* 的 peer 与当前运行时做带预发布的比对 —— 于是从 0.2.0-rc.2 起, profile 判定本插件不兼容并直接跳过加载(设置页与注入就这么消失了,不报错、不崩溃)。 现改为开放下界(>=0.1.1-rc.1、>=0.1.7-rc.1),与同系列的 dsh-per-message-model 用法一致。除此之外没有任何改动:本插件用到的每个接口在 0.2.0-rc.2 中都原样存在,发布前已对着运行中的运行时逐项核实。
  • 0.1.27 —— 周期性注入从不按节奏触发。「距上次注入的步数」计数器只在已经注入过一次之后才开始累加(它以上一次注入为起点),所以在首次注入之前它恒为 0,首次周期注入只能靠另一条兜底判据触发 —— 而那条判据会漂移。实测:真实会话在 interval: 50、497 次模型调用的情况下,只注入了 1 次,且落在第 443 次调用。现在把起点改为步数(lastInjectStep,首次注入前为 -1),从会话第一次调用起每个完成的步都推进计数,首次与后续注入共用同一套算术:关闭开始注入时落在第 50、100、150… 次;开启时落在第 1、51、101… 次。投影 stateVersion 升到 3;过期的缓存行会被忽略并按日志重算,已有会话的注入书签得以保留、不会重复注入。
  • 0.1.26 —— 两项修复。(1) 注入会报错:failed format v4 message requires a producer-owned source kind —— 注入消息带的是已废弃的 { kind: 'plugin', plugin: 'round-inject' } 包装,而会话格式 v4 的准入检查会直接拒绝它。现改为扁平的生产者标识 plugin:round-inject(与框架自身 V3 转换器对第三方插件生成的写法一致);同时书签 fold 仍识别旧包装,已有会话的计数不会断。(2) 恢复原有页面布局:同样的五行(启用开关、触发轮次、会话开始提示词、周期注入提示词、对话开始时注入开关)、同样的中文文案与提示、3/6 行文本框,以及"草稿 + 保存按钮"的行为。只有数据通道变了 —— 改绑 ctx.configForms.get('round-inject'),其快照与原页面所依赖的 status/value/writable 形状一致(settingsScope 已不存在)。
  • 0.1.24 —— 修复 0.1.22 之后仍存在的「该插件当前未加载」提示。页面背后的投影漏掉了 available 字段,而共享框架只要看到该字段为假就渲染未加载提示 —— 于是即使 whileServed 已命中、表单快照本身已是 ready,界面仍把已加载的插件报成缺失。现在 available 与其他 shell 字段一起进入投影,且客户端测试会断言 SettingsFormShell 的每个字段都已发布,防止再次遗漏。
  • 0.1.22 —— 修复恢复页面后暴露的两个缺陷:侧栏标签显示成原始键 nav(字典里只写了 description,t('nav') 查不到就回退成键名),以及正文显示「该插件当前未加载」(SettingsFormModel 在 Host 的 describe 镜像收录该条目之前一律报 available: false,所以无条件注册会在插件已加载时也显示这句提示)。字典已补上标签键,页面改为通过 configForms.whileServed(['round-inject']) 注册,与官方所有配置页一致 —— 条目被服务时出现,且此时必定报为可用。
  • 0.1.21 —— 恢复 0.1.7 下的配置页。0.1.15 适配时误以为「0.1.7 会依据 volatile Config 字段渲染页面」而删掉了客户端半端;事实并非如此 —— dsh-settings 文档明确写着 autoGenerate 只是给「依据 schema 生成页面的客户端」预留的标记,且「目前没有任何随附客户端会这样做」。页面已恢复:注册到 settings.section 与 Plugins 页的 plugins.row.config 槽(键 dsh-round-inject#round-inject),通过 ctx.configForms.get('round-inject') 读写,并用共享的 SettingsForm 组件渲染。host 半端在可选的 ctx.inject(['settings'], …) 子上下文中声明 configure({ auto: false }),因此在没有 Settings 的部署里插件照常加载。同时补上 inject = ['sessionProjections'](Cordis 会拒绝未声明的服务读取)。
  • 0.1.17 —— 修复 0.1.15 适配引入的挂载失败:cannot get property "sessionProjections" without inject。Cordis 对服务访问有守卫,从 ctx 读取服务必须先声明 —— 插件现导出 inject = ['sessionProjections'](内置 fold 也是同样声明)。已在启用守卫的真实 cordis Context 下挂载验证通过。
  • 0.1.15 —— 适配 DSH 0.1.7-rc.1。0.1.7 已移除 settings.register() / settingsScope:插件改为把 Config 字段声明为 .volatile()(以 .get() 读取的实时引用),配置改动即时生效、无需重载插件。此版本误删了 client.js(当时以为 0.1.7 会依据这些字段自动渲染页面;实际不会),0.1.21 已恢复。投影注册改为直连 ctx.sessionProjections.register,与内置 fold 一致。注入行为不变:第一次模型调用带开始提示词,此后恰好每隔 interval 个已完成步注入一次。
  • 0.1.14 —— 修复 "session.events is not iterable"(每轮运行失败):书签扫描误用了 session.events(会话对象上不存在的属性,公共接口是 session.snapshotEvents())。书签现移入投影状态(派生、每事件 O(1)、可持久化),判定全程有防护,内部错误不再拖垮整轮。注入时机精确:开启开始注入时,注入发生在会话第 1、1+interval、1+2·interval… 次调用;关闭时在第 interval、2·interval、3·interval… 次调用(不再 ±1 漂移)。默认触发轮次从 80 调整为 50。

故障排查

DSH 共享宿主包声明为 peerDependencies(0.1.6)

插件把全部 DSH 提供的运行时包(@deepseek-ai/cordis、@deepseek-ai/dsh-llm、@deepseek-ai/dsh-settings、@deepseek-ai/schemastery)声明为 peerDependencies,而非 dependencies。DSH 通过共享宿主包目录(~/.dsh/profiles/node_modules/@deepseek-ai/)以符号链接指向宿主精确版本,插件必须经宿主解析这些包,不能自装副本。

0.1.6 之前插件把 dsh-llm 放在 dependencies,导致 pnpm 把独立的 [email protected] 提升到 profile 根目录。Node 解析会优先命中这份副本而非宿主的共享符号链接,于是插件与宿主跑在不同的 dsh-llm 实例上(宿主为 0.1.1-rc.2)。两个版本的 createUserMessage 签名恰好一致所以能跑,但任何 API 漂移都会静默出错。判断方法:在 profile 下执行 require.resolve('@deepseek-ai/dsh-llm/package.json'),若解析到 profiles/web/node_modules/... 而非宿主安装路径即为被遮蔽。更新到 0.1.6 后在 profile 里重装以清理旧副本:

cd ~/.dsh/profiles/web
pnpm add "[email protected]"   # 清理旧的提升副本
node -p "require.resolve('@deepseek-ai/dsh-llm/package.json')"  # 应指向宿主路径,而非 profiles/web/node_modules

"设置服务不可用" / 设置项不可编辑 / 命名空间缺失

开发

├── index.js       # Host 半端(ESM;设置注册 + session-start 重置 + pre-step 计数/注入)
├── client.js      # 浏览器半端(设置页面;__ModuleLoader__.load 工厂,无构建步骤)
├── cordis.patch.yml
└── package.json

无需构建 —— 两个半端均为手写 ESM / 浏览器工厂(与 dsh-strata 同模式)。发布:

npm publish

License

MIT