sunlei1214/dsh-session-requirement:给单个对话挂一条恒定要求的插件

前言

在 DSH 里做长循环任务时,经常会遇到一件事:某条要求要跟着整个对话走,比如「只输出中文」「表格必须带单位」「这份文档用 Word 格式输出」。目前的常见做法是把这类要求写进第一条消息,或者反复在后续消息里重复提醒。第一条做法容易被模型在长对话中遗忘,第二种做法会增加每轮输入的噪声。

sunlei1214/dsh-session-requirement(版本 1.1.0,MIT 许可证)就是为此设计的:它在 DSH 的对话标题栏右侧提供一个输入框,让你写下针对「当前这个对话」的整体要求,并可以用 @ 挑选技能,然后由插件把这段内容附加到该对话的每一条消息上。更适合用在工作流类场景。

这是什么

一句话定位:一个挂在对话标题栏上的「对话级约束框」,只负责选择、存储和转发,不负责执行。

它解决的痛点是:把跨多轮的固定要求从消息正文里抽出来,交给插件统一注入。要求文本和所选技能都按对话维度存储,切换对话即清空,新对话默认是空的、开关也是关的。

需要注意两点:

  • 本插件运行在当前 DSH 进程的权限下,安装范围即意味着信任边界。
  • 技能来源不是本地硬编码清单,而是通过 ctx.remote.skills.list 读取 harness 的实时技能注册表,因此没有可用技能时不会伪造列表,而是提示当前无目录。

核心功能

下面介绍 README 中明确列出的能力。

一个全局开关,控制整个框的显隐

开关位于 Settings → General → 本对话的整体要求,状态写在全局 state 文件中。安装后默认关闭;打开时所有对话的标题行立刻出现输入框,无需刷新或重启;关闭时标题行完全没有预留空位。

两种尺寸,标题行为固定高度

收起状态是标题行右侧的一行,尺寸固定 380px × 28px,因此标题行不会发生回流。聚焦时输入框浮起为 470px 的浮动卡片,覆盖在 tab 行上方,标题栏本身不增高。

空白对话场景下,标题行的边栏原本不渲染,插件会把同一份字段登记到 conversation.input.dock(order: -100),在标题行出现前先显示在输入框 dock 中;注册表保证屏幕上只有一份实例。

要求文本 + @ 技能选择

  • 文本框和技能 chips 都是按对话存储的。
  • 在行首或空白后输入 @ 打开技能选择器,按名称、描述和 whenToUse 过滤。↑/↓ 移动,Enter 选中,Esc 关闭,点击也可选中;结果为空或加载失败时显示行内提示,不破坏输入。
  • 选中的技能变成不可编辑的 @name × chip,点击 × 移除;输入框为空时按 Backspace 移除最后一个;重复项被忽略;上限为 maxSkills(默认 10)。

按条件附加到每条消息

附加动作发生在服务端的 agent/pre-step。客户端的 conversation.send() 是纯透传,没有可供钩挂的发送前转换,因此持久化、模型可见的接入点选在这一步:当当前消息批次里含真实用户消息时(也就是新的一次发送,而非工具循环的后续步骤),插件会追加一条 user/message:

<session_requirement>
The user set a standing requirement for this whole conversation. Apply it to every reply until the user changes it.
<requirement>…</requirement>
<selected_skills>office-docx, office-xlsx</selected_skills>
</session_requirement>

<skill_content name="office-docx">…</skill_content>

它走 harness 自己的 surfaceOp: "append" 路径提交,source.kind = "session-requirement",因此像内置 /skill 调用一样出现在对话记录里,不会伪装成一次用户动作。

同时生效的条件是:GUI 开关打开、该对话的开关打开、内容有效(requirementText.trim().length > 0 || skillIds.length > 0)。

整条对话的开关行为如下:无内容时显示灰色,点击会聚焦输入框;第一次出现有效内容时自动变为打开;手动关闭后仍保留文本和技能,但不再附加;清空所有内容后开关重新变灰。

插件本身不执行技能,只做选择、存储和转发,模型收到技能正文后自行决定如何处理。

安装与启用

README 给出的安装方式是克隆后通过 link: 指向检出目录。

git clone https://github.com/sunlei1214/dsh-session-requirement.git

然后改 profile 的 package.json:

// <DSH_HOME>/profiles/<profile>/package.json
"dependencies": { "dsh-session-requirement": "link:C:/path/to/dsh-session-requirement" },
"dsh": { "profile": { "bundles": [ …, "dsh-session-requirement" ] } }

改完后需要重新安装 profile 并重启 DeepSeek Harness。浏览器那半部分是静态客户端 bundle,只刷新页面是不够的。

README 特别提醒要用 link: 而不是 file::pnpm 会复制 file: 目录依赖并做缓存,后续修改不会同步到 profile;link: 创建 junction(Windows)或 symlink,profile 始终读取当前源码。

卸载时移除依赖和 bundle 条目,重新安装并重启。插件会注销路由、agent/pre-step 监听器、文档监听器、防抖定时器和缓存,并中止在途请求。删除 <DSH_HOME>/session-requirement.json 是可选操作。

配置与命令

配置项只有两个:

选项 默认值 含义
maxSkills 10 单个对话最多可选的技能数
maxTextLength 8000 要求文本的最大长度

命令有两个:

  • /requirement 打印当前对话的状态。
  • /requirement clear 清空内容并关闭当前对话的开关。

HTTP 接口与状态文件

路由 用途
GET /api/session-requirement?sessionId=… 读取一个对话的状态(同时返回 visible)
GET /api/session-requirement?mode=settings 只读取 GUI 开关,不涉及对话
POST /api/session-requirement 写入一个对话的状态:{ sessionId, requirementText, requirementEnabled, skillIds }
POST /api/session-requirement { visible } 单独翻转 GUI 开关

状态写在 <DSH_HOME>/session-requirement.json,采用 .tmp + rename 的原子写方式:

{
  "version": 1,
  "settings": { "visible": false },
  "sessions": {
    "session-…": { "conversationId": "session-…", "requirementText": "", "requirementEnabled": false, "skillIds": [], "updatedAt": 0 }
  }
}

当 sessionId 格式非法、文本超过 maxTextLength、或 skillIds 不是去重后且不超过 maxSkills 个技能名时,请求直接返回 400,不做静默修正。

适用场景与注意

适合这几类情况:

  • 需要在一次长对话里反复强调固定约束的写作或表格任务。
  • 希望按对话切换约束、而不是一条全局约束覆盖所有任务的用户。
  • 工作流类场景:把技能挑选和整体要求放在同一处管理。

要求与限制也要说清楚:

  • 运行环境要求 DeepSeek Harness 0.2.x(桌面版或 Web 版)、Cordis v4。
  • 无任何 npm 依赖,host 端只用 Node 内置模块,浏览器端是手写 CJS bundle,react 从 harness loader 获取。
  • 插件以当前 DSH 进程权限运行,安装第三方插件前应先检查源码与许可证(本仓库为 MIT)。
  • 本地跑测试可以直接执行 node test/host-check.mjs 和 node test/client-check.mjs;如果 PowerShell 执行策略拦截了 npm.ps1,按 README 说的直接运行这两个文件即可。两个测试都是在真实源码上搭的离线 harness,不需要安装 harness。

结尾

这个插件的价值不在于新增了什么执行能力,而在于把「对话级要求」从消息正文中剥离出来,用统一接口注入到每一轮请求,并保留技能引用的可追溯性。如果你在 DSH 里做长流程任务时需要跨轮约束,可以先把源码和许可证过一遍再装。

目录页:https://www.skillhub.cn/plugins/sunlei1214/dsh-session-requirement

代码仓库:https://github.com/sunlei1214/dsh-session-requirement

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜