前言¶
在 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