dsh-plugin-prompt-optimizer
Manifest validPrompt optimizer plugin for DeepSeek Harness: one click rewrites your composer draft into a clear, verifiable prompt. Zero dependencies.
提示词优化(dsh-plugin-prompt-optimizer)
像 WorkBuddy 的「优化提示词」一样:在输入框旁点一下,草稿被改写成更清晰的版本,还能一键还原。
用户往往只写一句「帮我优化一下那个东西,弄得好看点,尽快」。点一下按钮,插件把这句话交给模型,用一套提示词工程规则改写成目标明确、约束具体、可验收的提示词,直接替换输入框里的草稿;不满意就再点一次还原。同一个能力也提供给模型工具和斜杠命令。
- 包名:
dsh-plugin-prompt-optimizer版本:0.1.0引擎版本常量:VERSION = '0.1.0' - 运行环境:Node.js ≥ 22;DeepSeek Harness(
dsh)≥0.2.0-rc.2(见 §9 版本兼容矩阵) - 改写流程与 WorkBuddy 的
llm:enhancePrompt(agent 名enhance-prompt)同源:同样的系统提示词、同样的用户模板、同样的「只返回改写后的提示词」约束、同样的去引号后处理 - 模型不可用时自动回退到内置的确定性规则引擎,按钮不会变成死路
一行安装:
dsh plugin --profile desktop add dsh-plugin-prompt-optimizer
也可以完全不敲命令:DSH 侧栏「插件」→「添加插件」→ 输入包名 dsh-plugin-prompt-optimizer → 安装。
装完必须完全退出并重启 DSH —— 组合包只在启动时加载。详见 §3 安装。
目录
1. 它解决什么问题
一次点击完成的事:
| 阶段 | 做什么 | 对应实现 |
|---|---|---|
| 输入 | 输入框里的草稿(原样,不做预处理) | 浏览器半区读取 useInput |
| 改写 | 按提示词工程规则重写:明确目标、补上下文、设约束、定输出格式、加验收标准 | Host 调用模型,系统提示词见 ENHANCE_SYSTEM_TEMPLATE |
| 落地 | 改写结果替换输入框草稿,并保留原文作为备份 | inputActions.setDraft(...) |
| 还原 | 再点一次按钮回到原文;改过草稿后备份自动失效 | 芯片的 revert 状态 |
| 诊断(可选) | 本地确定性分析:分节、模糊表述、冗余、缺失维度、0–100 评分 | /optimize --analyze、analyze_prompt 工具 |
| 回退 | 模型不可用/失败时用本地规则改写,并说明降级原因 | fallbackToRules(默认开) |
两条实现原则:
- 浏览器半区不做模型调用。它把草稿 POST 给 Host 的私有路由
/prompt-optimizer/enhance,由 Host 用部署里已配置的模型路由去改写。这样浏览器里没有凭据、没有路由选择逻辑,也不会在会话记录里留下任何事件——点按钮不会往对话流里插东西。 - 规则引擎只服务 Host。它现在负责「诊断」和「回退改写」,因此不再打进浏览器包(浏览器的包从 ~175KB 降到 ~17KB)。
2. 三种使用方式
2.1 输入框按钮(与 WorkBuddy 一致的主路径)
输入框工具行左侧的「优化提示词」芯片(槽位 conversation.input.left,注册 id prompt-optimizer,order: 20)。它有四个状态,与参考实现的按钮一一对应:
| 状态 | 外观 | 点击行为 | 提示文案 |
|---|---|---|---|
| 空闲 | 图标 +「优化提示词」 | 把当前草稿发给模型改写 | 优化提示词 |
| 进行中 | 转圈 +「优化中」 | 取消这次调用(同时中止模型的请求) | 正在优化…(点击取消) |
| 已改写 | 回退箭头 +「还原」 | 把改写前的原文写回输入框 | 还原为优化前的提示词 |
| 出错 | 红色 +「重试」 | 再试一次 | 错误信息原文 |
细节:
- 草稿为空时按钮不显示(与参考实现一致:没有内容就没有可优化的东西)。
- 改写是原地替换:不弹面板、不插入对话流,改完就能直接发送。
- 备份会失效:如果你在改写后又手动编辑了草稿,按钮自动回到空闲态,不会再提供「还原」(避免把过期的原文写回去)。
- 失败不破坏草稿:任何失败都只体现在按钮的提示文案里,输入框内容保持原样。
- 全程中文界面,颜色走 DSH 主题变量,浅色/深色都可用。
2.2 斜杠命令
/optimize [--analyze|--offline] <原始提示词>
| 用法 | 行为 |
|---|---|
/optimize <提示词> | 模型改写,只返回改写后的提示词全文(可直接发送) |
/optimize --analyze <提示词> | 只诊断不改写:本地规则分析报告(评分、结构、问题清单、冗余、维度覆盖) |
/optimize --offline <提示词> | 用本地规则改写,不调用模型 |
前置标记不会进入提示词,也不会出现在结果里。不带参数(或只有空白)时返回用法说明与示例。
模型不可用时会自动回退,并在结果末尾注明:
---
(模型不可用,已回退到本地规则改写:<原因>)
2.3 模型工具(Agent 可自行调用)
两个工具都用原始 JSON Schema 定义参数,并在执行时自行校验。
optimize_prompt
优化一段提示词:调用模型把它改写成更清晰、更具体、更可执行的版本。默认只返回改写后的提示词全文。
| 参数 | 类型 | 必填 | 取值 | 说明 |
|---|---|---|---|---|
prompt | string | ✅ | — | 原始提示词全文;把用户的原话原样放进来 |
language | string | — | 'auto'(默认)/ 'zh' / 'en' | 语言提示;决定本地规则回退时改写正文的语言 |
level | string | — | 'standard' / 'strict' / 'concise' | 改写力度(仅作用于本地规则回退) |
taskType | string | — | code / bugfix / refactor / explain / write / analyze / plan / translate / generic | 任务类型(仅作用于本地规则回退) |
output | string | — | 'prompt'(默认)/ 'full' | prompt 只给改写全文;full 额外给评估摘要与截断提示 |
analyze_prompt
分析一段提示词的结构、模糊表述与冗余信息,返回工程规范度评分与问题清单。只诊断不改写,不消耗模型调用。
| 参数 | 类型 | 必填 | 取值 |
|---|---|---|---|
prompt | string | ✅ | — |
language | string | — | 'auto'(默认)/ 'zh' / 'en' |
返回的规范值(optimize_prompt)始终包含 input、完整的 analysis、optimized,以及:
| 字段 | 含义 |
|---|---|
source | 'llm'(模型改写)或 'rules'(本地回退) |
model | source: 'llm' 时的 provider/model |
modelFallbackReason | source: 'rules' 且发生过模型失败时的原因 |
changes / rationale | 仅本地回退时有意义;模型路径下 changes 为 [](模型不提供逐条变更) |
truncated / originalChars / maxInputChars | 截断元信息 |
也就是说:改写走模型,诊断永远在本地,程序化调用方两种信息都能拿到。
level 对本地回退改写的影响:
| 取值 | 行为 |
|---|---|
standard | 默认:保留 2 条目标/背景、3 条约束、完整输出格式与验收项(仅在缺少 examples 维度时不强行添加示例小节) |
strict | 在约束中加入「禁止事项」、在验收中加入「回答前自检」,并强制包含示例小节 |
concise | 目标/背景各保留 1 条、约束 2 条,输出格式与验收各截取 3 条,待确认问题最多 2 条;当目标已明确且评分 ≥ 50 时不再输出「待确认问题」小节 |
3. 安装
本包是一个标准的 DSH 组合包(bundle):它通过 package.json 的 dsh.bundle.patch 指向自己的 cordis.patch.yml,并通过 dsh.client 声明浏览器半区。
"dsh": {
"bundle": { "patch": "./cordis.patch.yml" },
"client": { "platform": "web", "inject": ["@deepseek-ai/dsh-client-ui-conversation"] }
}
3.1 cordis.patch.yml 的作用
它就是这个 bundle 的 patch 层:只往 profile 的组合树里插入一行,不替换任何官方行。
# Prompt optimizer bundle: adds one plugin row, replaces nothing.
- insert:
- id: prompt-optimizer
name: dsh-plugin-prompt-optimizer
id: prompt-optimizer—— 这一行在 profile 树里的条目 id,也是配置与禁用覆盖的定位键。name: dsh-plugin-prompt-optimizer—— 该行的模块名,即包名。
3.2 装到哪里:profile 的 package.json 与 dsh.profile.bundles
每个 profile 有自己的目录($DSH_HOME/profiles/<name>,本机 desktop profile 为 C:\Users\15733\.dsh\profiles\desktop)。安装一个组合包会做两件事:
- 在该 profile 的
package.json里新增一条dependencies; - 把包名追加到
dsh.profile.bundles数组末尾。
{
"dependencies": { "dsh-plugin-prompt-optimizer": "..." },
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-plugin-prompt-optimizer"
]
}
}
}
顺序语义。 profile 的组合树是「按 patch 层依次叠加」合成出来的,顺序为:先按 dsh.profile.bundles 的数组顺序叠加每个 bundle 的 patch 层,再叠加 profile 自己的 cordis.patch.yml,最后是 --patch 覆盖层。新安装的包总是被追加到数组末尾,因此本插件行位于所有官方 bundle 之后,不会覆盖官方行为。
3.3 安装入口
方式一:从 npm 安装(推荐)
# 最新版
dsh plugin --profile desktop add dsh-plugin-prompt-optimizer
# 或钉住一个具体版本(升级/回滚都用它)
dsh plugin --profile desktop add dsh-plugin-prompt-optimizer@0.1.0
不敲命令也行:DSH 侧栏「插件」→「添加插件」→ 输入包名 dsh-plugin-prompt-optimizer → 安装。
方式二:从本地路径 / tgz 安装(开发与离线场景)
图形界面的「添加插件」同样接受下列任意一种 spec:
- 本地绝对路径,例如
E:\plug\dsh-plugin-prompt-optimizer - 压缩包(tgz),例如
npm pack产出的dsh-plugin-prompt-optimizer-0.1.0.tgz
DSH 的 CLI 形式为 dsh plugin --profile <profile> <pnpm-args...>,即在该 profile 目录里执行 pnpm,并在安装后自动把新组合包追加进 dsh.profile.bundles。例如:
dsh plugin --profile desktop add E:\plug\dsh-plugin-prompt-optimizer
安装完成后对话框会提供「立即启用」。DSH 目前不支持插件自动更新:升级需要先卸载再安装新版本。注意两点:
- desktop profile 需要先启动过一次 DSH 完成初始化;
- 运行该命令前应完全退出 DSH。本机
dsh位于E:\DeepSeek\resources\runtime\cli\bin\dsh.cmd。
方式三:本包自带的零依赖安装脚本(无需 pnpm / 无需联网)
因为本插件不依赖任何 @deepseek-ai/* 包(那些包在 Harness 的 asar 里,树外包解析不到),安装它就是「拷目录 + 改两处清单」,不需要 pnpm、不需要联网、也没有安装脚本:
cd E:\plug\dsh-plugin-prompt-optimizer
# 先干跑,看清会改哪些文件
node tools/install.mjs --profile desktop --dry-run
# 真正安装(会先把待改文件备份到 <profile>\prompt-optimizer-backup-<时间戳>\)
node tools/install.mjs --profile desktop
# 卸载(逐行只删本插件那一行,其他插件行原样保留)
node tools/install.mjs --profile desktop --uninstall
它会做三件事,且幂等(重复执行不会写入重复行):
- 把
package.json、cordis.patch.yml、lib/、src/、docs/、tools/、README.md拷到<profile>\node_modules\dsh-plugin-prompt-optimizer\; - 在 profile 的
package.json里写入"dsh-plugin-prompt-optimizer": "link:<本包绝对路径>",并把包名追加进dsh.profile.bundles(不覆盖既有顺序,dsh-plugin-whale-pet等既有包保持原位); - 在 profile 的
cordis.patch.yml末尾追加一行 insert(已存在则跳过)。
--home <dir> 可指定别的 DSH home,便于在一次性 profile 里试装。
3.4 必须重启 DSH 应用
新装的组合包不会在运行中的实例里生效,必须完全退出并重新打开 DSH 应用。
DSH 自己的安装完成文案就是「已安装,下次启动后加载。」;只有重启后 Host 半区(模型工具、/optimize 命令、私有路由)和浏览器半区(输入框芯片)才会一起加载。
关闭窗口不等于退出应用——请从托盘/菜单彻底退出 DSH 后再重新打开。
4. 配置项
配置写在 profile 的 cordis.patch.yml 里,通过行 id prompt-optimizer 定位到本插件的行,再用 config 覆盖。字段与默认值均取自 src/host/config.js 的 normalizeConfig():
| 字段 | 类型 | 默认值 | 作用 |
|---|---|---|---|
enableTools | boolean | true | 是否注册两个模型工具 analyze_prompt / optimize_prompt。只有显式传 false 才关闭(判定为 raw.enableTools !== false) |
enableCommand | boolean | true | 是否注册斜杠命令 /optimize。同样只有显式传 false 才关闭 |
enableRoute | boolean | true | 是否注册浏览器半区调用的私有路由 /prompt-optimizer/enhance。关掉之后输入框按钮会失效,模型工具与命令照常可用 |
provider / model | string | 不设置 | 显式指定改写用的模型路由。不设置时跟随部署当前选中的默认模型(agentDefaultModel.currentSelection())。两个必须成对出现才有意义;同时给出时覆盖默认选择 |
maxTokens | number | 1024 | 单次改写调用的输出上限。取值必须是有限且 > 0 的数,否则回退 1024 |
timeoutMs | number | 45000 | 单次改写调用的超时(毫秒)。超时按失败处理并触发回退 |
systemPrompt | string | 内置模板 | 覆盖系统提示词。默认使用与 WorkBuddy 同源的提示词工程模板(见 src/host/llm.js 的 ENHANCE_SYSTEM_TEMPLATE) |
fallbackToRules | boolean | true | 模型不可用/失败时是否回退到本地规则改写。传 false 则把错误直接抛给调用方(工具调用会失败,按钮提示错误) |
maxInputChars | number | 20000 | 改写前先截断到该长度。取值必须是有限且 > 0 的数,否则回退到 20000;小数会向下取整。只能收紧:引擎自身的上限是 MAX_INPUT = 20000,设成大于 20000 没有意义 |
defaultLevel | string | 'standard' | 本地规则回退时的默认改写力度,取值 standard / strict / concise;非法值回退 standard |
defaultOutput | string | 'prompt' | optimize_prompt 未传 output 时的默认输出形态,取值 prompt / full;非法值回退 prompt。/optimize 命令始终直出,不受此项影响 |
配置示例(追加到 $DSH_HOME/profiles/<profile>/cordis.patch.yml):
# 覆盖本插件行的配置(行 id 必须与 cordis.patch.yml 中的 insert id 一致)
- id: prompt-optimizer
name: dsh-plugin-prompt-optimizer
config:
enableTools: true
enableCommand: true
# 固定用某个模型改写(不写则跟随当前默认模型)
provider: deepseek-account
model: deepseek-flash
maxTokens: 1024
timeoutMs: 45000
fallbackToRules: true
maxInputChars: 20000
defaultLevel: standard
defaultOutput: prompt
只想默认看到完整报告(评分 + 摘要)的写法:
- id: prompt-optimizer
name: dsh-plugin-prompt-optimizer
config:
defaultOutput: full
该配置只影响 optimize_prompt 工具;/optimize 命令与输入框按钮始终是直出。单次调用仍可用 output: 'prompt' 覆盖回来。
只注册命令、不注册模型工具的写法:
- id: prompt-optimizer
name: dsh-plugin-prompt-optimizer
config:
enableTools: false
改完配置同样需要重启 DSH 应用。
5. 分析维度与评分口径
以下全部对应 src/engine/ 中的真实实现(按主题分模块;index.js 只做再导出)。
5.1 结构识别:槽位标签
structure[].label 的取值域为 goal context constraints output acceptance examples background unknown。标题匹配大小写不敏感,允许 # / ## / ** / 数字前缀 / 中英冒号;匹配表按「顺序即优先级」生效(更具体的槽位排在前面):
| 标签 | 命中关键词(正则) |
|---|---|
context | 背景、上下文、现状、环境、前提、context、background、current state |
constraints | 约束、限制、边界、规范、技术栈、禁止、不能、不允许、constraint、limit、boundary、stack、restriction |
output | 输出、交付、格式、返回、呈现、output、deliverable、format |
acceptance | 验收、标准、测试、完成条件、自检、acceptance、criteria、test、definition of done、done when |
examples | 示例、例子、参考、example、sample、reference |
goal | 目标、任务、需求、要求、要做、目的、goal、task、objective、requirement |
background | 说明、补充、备注、note、remark |
结构类问题(findings[].kind === 'structure'):
| id | 触发条件 | 严重度 |
|---|---|---|
structure.no-sections | 没有标题,且带标签的条目少于 2 条 | 非空白字符 ≥ 200 时 high,否则 medium |
structure.run-on-blob | 无标题无列表、行数 ≤ 3,且逗号分句 ≥ 3 或某行 ≥ 80 字符 | medium |
structure.bullet-soup | 无标题,但同级条目 ≥ 6 条 | low |
5.2 模糊表述
八个类别(findings[].kind === 'vagueness')。vague.referent 与 vague.quality 的严重度取决于是否已有具体锚点(specificityHits === 0 时为 high,否则 medium):
| id | 类别 | 严重度 |
|---|---|---|
vague.object-missing | 出现动作但没有可解析的处理对象(如「帮我优化一下」) | high |
vague.referent | 指代不明确 | high / medium |
vague.quality | 质量要求无法验收(主观词) | high / medium |
vague.hedge | 不确定的表述 | medium |
vague.urgency | 只有紧迫感,没有时间点 | medium |
vague.scope | 范围没有边界 | medium |
vague.quantifier | 数量与范围含糊 | low |
vague.intensifier | 程度词没有基准 | low |
真实命中词表各举 3 例(与 VAGUE_PATTERNS 逐字一致):
| 类别 | 中文真实例子 | 英文真实例子 |
|---|---|---|
| 质量要求无法验收 | 优化、好看、更好 | optimize、improve、nice |
| 只有紧迫感没有时间点 | 尽快、赶紧、马上 | asap、urgent、quickly |
| 指代不明确 | 那个、这个、它 | it、this、that |
| 不确定的表述 | 可能、大概、尽量 | maybe、perhaps、roughly |
| 数量范围含糊 | 一些、等等、之类 | some、several、etc |
| 程度词没有基准 | 非常、特别、挺 | very、really、quite |
| 范围没有边界 | 一切、所有内容、基本上 | everything、whatever、overall |
说明:英文词表使用
\b词边界(避免it命中with),中文使用字面量匹配。另有一个反向指标QUANTIFIED_RE(数字、不超过、至少、p95等)用于抑制误报。
5.3 冗余检测
六个类别(findings[].kind === 'redundancy',同时出现在 redundancy[] 分组里):
| 分组 | id | 检测规则 | 严重度 |
|---|---|---|---|
| 重复的句子 | redundancy.duplicate-sentence | 句子规范化(去空白与标点、转小写)后完全相同,且出现 ≥ 2 次 | high |
| 同一动作反复要求 | redundancy.repeated-imperative | 同一个任务动词在不同句子里出现 ≥ 3 次 | medium |
| 目标重复表述 | redundancy.goal-restated | 两个含任务动词的句子,词元 Jaccard 相似度 ≥ 0.45,最多报 2 组 | medium |
| 同一约束换了说法 | redundancy.constraint-restated | 两个含约束线索的句子,词元 Jaccard 相似度 ≥ 0.45,最多报 2 组 | medium |
| 流水账连接词 | redundancy.filler-chain | 首先/然后/接着/其次/再者/最后/第一/第二/第三/其一/其二 或 first/then/next/second/third/finally/lastly 命中 ≥ 2 个 | low |
| 客套铺垫 | redundancy.politeness | 礼貌词加权合计 ≥ 2。词表与权重:谢谢 2、多谢 2、感谢 2、辛苦了 2、麻烦 2、拜托 2、劳驾 2、你好 1、您好 1、请 1;thanks 2、thank you 2、thx 2、appreciate it 2、kindly 1、please 1 | low |
5.4 缺失要素
六个工程维度:goal context constraints output acceptance examples(dimensions.present / dimensions.missing)。每个缺失维度产生一条 finding,id 形如 missing.<维度>:
| 维度 | 严重度 | 判定依据 |
|---|---|---|
goal | high | 有 goal 槽位标签,或「存在任务动词且存在可解析对象」 |
output | high | output 槽位标签,或内容线索正则命中 |
acceptance | high | acceptance 槽位标签,或内容线索正则命中 |
context | medium | context 槽位标签,或内容线索正则命中 |
constraints | medium | constraints 槽位标签,或内容线索正则命中 |
examples | medium | examples 槽位标签,或内容线索正则命中 |
5.5 风格类问题
| id | 类别 | 严重度 |
|---|---|---|
style.truncated | 输入超长已截断 | high(Host 补写时为 medium,见 6.2) |
style.empty-input | 输入为空 | high |
style.wall-of-text | 一行里多个句子,且既无空行也无列表 | medium |
style.no-output-format | 没有任何输出形式线索 | medium |
style.shouting | 拉丁字母 ≥ 20 且大写占比 ≥ 60% 且 ≥ 2 个全大写词 | low |
style.politeness | 礼貌词加权合计 ≥ 4 | low |
style.code-fence-no-lang | 代码围栏后没有语言名 | low |
5.6 评分口径
评分公式(源码注释原文,computeScore()):
score = 62
+ 4 * presentCount // dimensions.present 的数量(0..6)
+ min(6, 2 * specificityHits) // 具体锚点(路径 / 版本 / 标识符 / 数字 / 引号)
+ min(6, floor(charsNoSpace/100)) // 内容量:太短的提示词信息不足
- min(18, 3 * vagueHits) // 模糊表述越多,分越低
- min(15, 3 * redundancyHits) // 冗余越多,分越低
- 4 * missingHigh // 缺失 goal / output / acceptance
- 2 * missingMedium // 缺失 context / constraints / examples
- 3 * structureProblems // 结构类 finding 数
- 2 * styleProblems // 风格类 finding 数
公式刻意写成线性可加形式以保证单调性:补维度、加锚点、加内容只会加分;加模糊、加冗余、加缺失只会减分。最终结果 clamp(round(score), 0, 100)。
清晰度档位(clarityOf()):
metrics.clarity | 区间 |
|---|---|
high(面板显示「清晰」) | score >= 75 |
medium(面板显示「一般」) | 50 <= score < 75 |
low(面板显示「模糊」) | score < 50 |
问题清单的排序:先按严重度 high > medium > low,再按 id 字典序,结果稳定可复现。
6. 已知边界
6.1 确定性本地规则引擎
- 不做语义理解:引擎完全基于正则表达式与词表,不理解意图。它可以稳定地发现「缺目标」「缺验收」「有主观词」「同一句重复三遍」这类形式问题,但无法判断需求本身是否合理。
- 改写需要模型:模型路径下会真实发起一次 LLM 调用(走部署里配置的 provider/model),消耗 token;调用失败或没有可用路由时按
fallbackToRules处理。 - 浏览器半区只发一次同源请求:POST 到本插件自己的路由
/prompt-optimizer/enhance,请求体只有{ text };不发往任何第三方地址,不读凭据。 - 本地分析与回退是确定性的:规则引擎不使用
Date、Math.random、Intl;同一输入必得同一输出,可在任意进程重复。模型改写则不保证可重复(取决于模型)。 - 可能误报:例如「优化」既是任务动词,也在主观质量词表里,因此「优化 XX 模块」在缺少其他信息时仍可能被标为质量要求无法验收——这是本地分析的刻意保守取舍。
evidence绝不编造:每条findings[].evidence都必须是原文的真实子串,过滤器 (sanitizeFinding) 会丢弃任何不满足该条件的片段,因此证据为空数组是正常情况。- 不抛异常:引擎对空串、纯空白、纯 emoji、代码围栏、CRLF、制表符、超长输入都返回合法结构。
但插件层会拒绝空输入:
analyze_prompt/optimize_prompt对缺失、非 string、或只含空白的prompt抛出中文Error;/optimize无参数返回用法说明;HTTP 路由对空白文本回 400empty_input。 - 模型输出的后处理:与参考实现一致,会剥掉一层包裹引号(
"…"、'…'、“…”、「…」、`…`)以及整段的 Markdown 围栏;结果为空白时报错并触发回退。
6.2 超长输入的截断行为
存在两层上限,且插件层会被硬性夹取到引擎层的天花板:
| 层 | 常量 / 配置 | 行为 |
|---|---|---|
| 插件层(Host) | config.maxInputChars,默认 20000,生效值 = min(配置值, 20000) | 交给模型/引擎前先截断;若发生截断,补写一条 style.truncated(severity: 'medium',去重后按严重度重新排序),detail 中给出原文长度与生效上限 |
| 引擎层 | MAX_INPUT = 20000 | 输入超过 20000 字符时截断到 20000,并产生 style.truncated(severity: 'high') |
关键结论:
maxInputChars只能收紧、不能放宽。写成50000也会被夹到20000——因为引擎自身在20000处硬截断,放宽配置只会让报告与实际被分析的内容不一致。- 因此通过插件调用时,到达引擎的字符串已经不超过上限,引擎自身那条
style.truncated通常不触发,实际看到的是 Host 补写的那条。 - 返回值的截断字段以实际发生的事为准:
truncated/originalChars/maxInputChars由 Host 的截断与引擎返回的analysis.input长度共同核对。若某次引擎分析了比传入文本更短的前缀,truncated一定会是true,maxInputChars报告真实的分析窗口,绝不出现「悄悄少分析了却没提示」。 - 直出模式下若发生截断,改写正文之后会附一行说明(这是直出模式唯一多出来的内容)。
直接用 Node 调用引擎(不经过插件)时,则只会看到引擎自己那条 high 的截断 finding。参见 docs/EXAMPLES.md 中「截断行为」一节。
6.3 中英混合的判定方式
detectLanguage(cjkCount, latinLetters):统计 CJK 字符数与拉丁字母数,取 ratio = cjkCount / (cjkCount + latinLetters)。
| 条件 | 结果 |
|---|---|
| 两者都为 0,或拉丁字母数为 0 | 'zh' |
| CJK 数为 0 | 'en' |
ratio >= 0.7 | 'zh' |
ratio <= 0.3 | 'en' |
| 其余(0.3 < ratio < 0.7) | 'mixed' |
'mixed' 时改写正文使用中文(只有判定为 'en' 时才输出英文提示词)。此时如果强制传入 language: 'en',改写正文会切换为英文。
6.4 其它
- 任务类型由关键词加权打分判定,同分时按固定优先级
bugfix > refactor > translate > code > explain > analyze > plan > write > generic。 - 浏览器芯片在渲染与请求期捕获全部异常:模型失败、网络失败、返回体不是 JSON、剪贴板不可用,都只体现在按钮的提示文案里,绝不会把草稿弄丢,也不会让输入框崩溃。
- 插件不写文件、不读环境变量、不起定时器、不访问除自身路由以外的网络地址。
7. 开发
在包根目录 E:\plug\dsh-plugin-prompt-optimizer 下执行。
node tools/build-host.mjs
把 Host 半区源码构建成包入口:
- 读
src/host.js(拆分后的入口,只负责装配src/host/*.js),把其中所有相对 import 说明符from './…'改写为from '../src/…'(因为产物位于上一层目录lib/),加上// GENERATED from src/host.js — do not edit.横幅,写到lib/index.js。 - 写文件前先校验每个被 import 的
src/…模块真实存在,缺失就非零退出且不写文件,避免发布一个静默损坏的lib/index.js。 - 其余内容逐字节复制——不打包、不转译、无依赖。
- 幂等:内容没变时只打印
unchanged。 - 可选参数:
node tools/build-host.mjs <包根目录>可构建另一份 checkout。
实测输出:
build-host: E:\plug\dsh-plugin-prompt-optimizer\src\host.js -> E:\plug\dsh-plugin-prompt-optimizer\lib\index.js (3511 bytes, unchanged, 4 module imports)
node tools/build-client.mjs
零依赖打包器,把浏览器半区做成自包含 classic script:
- 规则引擎已收敛为 host-only:客户端不再内联
src/engine/,浏览器半区只包含交互层。 - 读
src/client/index.js(以 CJS 形式编写),包装成接收(require, exports, module, __styleCss)的工厂体。 - 读
src/client/style.css,内联为 JS 字符串常量__styleCss。 - 产出
lib/client.js,整体形如window.__ModuleLoader__.load({ id: "dsh-plugin-prompt-optimizer", factory: (require) => { ... return exports } })。 - 缺少任一预期标记就非零退出并给出明确信息。
- 幂等:连续构建两次字节一致,产物中不含时间戳。
实测输出:
[build-client] ok
engine (not referenced by the client; host-only)
client src\client\index.js 12832 B
style src\client\style.css 2885 B
output lib\client.js 18149 B
node --test
运行 tests/ 下的三个测试套件(引擎、Host、客户端),使用 Node 内置测试运行器,无第三方依赖。当前 68 项全部通过。
cd E:\plug\dsh-plugin-prompt-optimizer
node --test
注意(已实测):在本机 Node v24.12.0 上,
node --test tests/这种带目录参数的写法会失败——Node 把tests/当成模块入口去加载,报Error: Cannot find module '...\tests',结果是pass 0 / fail 1。请改用下面任一写法,它们都能正常运行全部 68 项:node --test # 不带参数,自动发现 tests/ node --test "tests/**/*.test.mjs" # glob 形式 npm test # package.json 的 test 脚本
package.json 中的脚本:
"scripts": {
"build": "node tools/build-host.mjs && node tools/build-client.mjs",
"test": "node --test \"tests/**/*.test.mjs\""
}
8. 目录结构
dsh-plugin-prompt-optimizer/
├── package.json # dsh.bundle + dsh.client 双声明
├── cordis.patch.yml # 组合包 patch 层:只插入本插件行
├── README.md # 本文档
├── CHANGELOG.md # 版本变更(Keep a Changelog)
├── LICENSE # MIT
├── docs/
│ ├── INTERFACES.md # 冻结接口契约
│ ├── EXAMPLES.md # 真实运行得到的改写前后对照
│ └── SECURITY.md # 安全面:数据流向与不做什么
├── lib/
│ ├── index.js # Host 半区产物(由 src/host.js 生成)
│ └── client.js # 浏览器半区产物(自包含 classic script)
├── src/
│ ├── engine/ # 分析 / 改写引擎(零依赖纯 ESM,按主题分模块)
│ │ ├── index.js # 入口:文档 + 再导出(浏览器/工具 import 面)
│ │ ├── constants.js # 冻结词汇表:版本 / 上限 / 任务类型 / 规则表
│ │ ├── text.js # 基础文本工具:预处理 / 行结构 / 围栏
│ │ ├── anchors.js # 锚点抽取:文件路径 / 版本号 / 技术名词 / 目标
│ │ ├── detectors.js # 检测器:模糊 / 冗余 / 缺失维度 / 结构 / 风格
│ │ ├── analysis.js # analyzePrompt:评分聚合
│ │ └── rewrite.js # optimizePrompt:改写生成
│ ├── host.js # Host 半区入口(装配 src/host/*.js)
│ ├── host/ # Host 半区按职责分模块
│ │ ├── constants.js # 冻结词汇:枚举 / 默认值 / 文案表
│ │ ├── utils.js # 无依赖小工具
│ │ ├── config.js # 配置归一 / 输入规整 / 截断披露
│ │ ├── pipeline.js # analyze / optimize 的公共执行管线
│ │ ├── render.js # 报告渲染(Markdown 文本)
│ │ ├── llm.js # 模型调用:选型 / 流式拼接 / 失败归一
│ │ ├── route.js # /prompt-optimizer/enhance 私有路由
│ │ ├── tools.js # analyze_prompt / optimize_prompt 工具定义
│ │ └── command.js # /optimize 命令定义
│ └── client/
│ ├── index.js # 浏览器半区源码(React.createElement,CJS 语义)
│ └── style.css # 芯片样式(构建时内联)
├── tools/
│ ├── build-host.mjs # src/host.js -> lib/index.js(相对导入改写 + 模块存在性校验)
│ ├── build-client.mjs # src/client + style.css -> lib/client.js
│ ├── release-check.mjs # 发版门禁:构建确定性 / 测试 / 契约 / 打包清单
│ └── install.mjs # 装入 profile(含 --dry-run / --uninstall)
└── tests/
├── engine.test.mjs
├── host.test.mjs
└── client.test.mjs
想直接看真实运行效果,请阅读 docs/EXAMPLES.md——其中每个「改写后」都是实际运行引擎得到的逐字输出,并附有可复现命令。
9. 版本兼容矩阵
package.json 的 engines.dsh 声明最低支持版本;下表记录实际验证过的版本(生态既有约定:声明最低、矩阵记实测)。
| 插件版本 | 适配 dsh 版本 | 验证范围 | 备注 |
|---|---|---|---|
0.1.0 | >=0.2.0-rc.2 | 实测 0.2.0-rc.2(DSH Desktop,Node 24.21.0 / pnpm 11.7.0) | 首发版本。宿主三面(工具 / 命令 / 私有路由)+ 浏览器芯片均已在本机真实 runtime 验证 |
engines.node 为 >=22。
验证证据(可复核,命令见仓库 verify/VERIFICATION.md 与 verify/ 目录):
| 检查 | 结果 |
|---|---|
| 包内测试(引擎 / Host / Client) | 68 / 68 通过 |
真实注册表契约(本机已安装的 dsh-tools 真实验证器) | 31 / 31 通过 |
| 包契约(真实扫描器规则) | 17 / 17 通过 |
| 安装产物完整性 | 26 项全过 |
| 引擎对抗性探测 | failures=0 fuzzThrows=0 |
| 构建确定性 | 连续两次构建字节一致 |
10. 排障
按「症状 → 原因 → 处理」排列。多数问题都能在这六条里找到答案。
10.1 装完了但侧栏里没有 / 芯片没出现
原因:组合包只在 DSH 启动时扫描加载,运行中的实例不会热加载新 bundle。 处理:从托盘/菜单彻底退出 DSH(关窗口不算退出)再重新打开;然后在侧栏「插件」里确认条目为启用状态。
10.2 点击芯片变成红色的「重试」
原因:改写请求失败。鼠标悬停在芯片上会显示具体原因(tooltip 就是错误文本)。 处理:按 tooltip 分类——
- 模型相关(未配置模型、额度/鉴权失败、超时):插件会自动回退到本地规则引擎改写(
fallbackToRules默认开);想直接拿到本地结果可把fallbackToRules保持默认,或在命令里用/optimize --offline。 写回输入框失败:输入框被别的插件/状态占用,草稿未改动,可重试或手动复制。
10.3 提示「请求被中止 / operation was aborted」
原因:改写过程中请求被取消——你点了芯片取消、关掉了页面,或运行中的进程还是旧版本插件(0.1.0 之前的构建把「请求体读完」误判成「客户端断开」,导致每次点击必然中止)。
处理:确认装的是 0.1.0 或更新版本,并且重启过 DSH。自查命令:
Invoke-WebRequest -Uri "http://127.0.0.1:19387/prompt-optimizer/enhance" -Method POST `
-Body '{"text":"优化当前项目"}' -ContentType 'application/json' -UseBasicParsing |
Select-Object -ExpandProperty Content
期望返回 {"ok":true,...}。
10.4 超长提示词被截断
原因:Host 先按 maxInputChars 截断(默认 20000,与引擎 MAX_INPUT 同值),且该值只能收紧、不能放宽分析上限。
处理:这是设计行为,报告里会显式披露截断(补一条 style.truncated finding)。需要完整分析请先自行精简输入。
10.5 dsh plugin add 报网络/依赖错误
原因:profile 的 registry 是镜像(如 npmmirror),与本包无关;或安装时 DSH 正在运行。 处理:完全退出 DSH 后重试;国内网络可保留镜像 registry;也可改用本包自带的零依赖安装脚本(§3.3 方式三),它不联网、不用 pnpm。
10.6 升级后没变化
原因:DSH 目前不支持插件自动更新。 处理:先卸载再安装目标版本,然后重启:
dsh plugin --profile desktop remove dsh-plugin-prompt-optimizer
dsh plugin --profile desktop add dsh-plugin-prompt-optimizer@0.1.0
11. 发版约定
11.1 发版前置门禁(缺一不发)
cd E:\plug\dsh-plugin-prompt-optimizer
npm run release:check # 构建确定性 + 68 项测试 + 包契约 + 打包清单 + 版本一致性
tools/release-check.mjs 逐项检查并在任一项失败时非零退出:
node tools/build-host.mjs && node tools/build-client.mjs成功,且连续两次构建产物字节一致(构建确定性是一票否决项);node --test "tests/**/*.test.mjs"全绿;- 包契约检查通过(
verify/check-package-contract.mjs); npm pack --dry-run清单与files白名单一致,且不含tests/、verify/、备份目录;package.json的version、CHANGELOG.md的最新条目、本文档 §9 兼容矩阵三者一致;engines.node/engines.dsh已声明。
11.2 版本号与 CHANGELOG
- SemVer。
0.x阶段允许 minor 破坏性变更,但必须在CHANGELOG.md里显著标注。 - 每次发版必在
CHANGELOG.md顶部新增条目(Added / Changed / Fixed / Removed),并同步本文档 §9 的兼容矩阵。
11.3 发布与回滚
# 1) 发布(需要先 npm login,且账号对 dsh-plugin-prompt-optimizer 有发布权限)
npm publish
# 2) 打 tag 并推送
git tag v0.1.0 && git push origin main --tags
回滚:npm 上的版本不能删除(unpublish 受限),正确做法是钉住上一个可用版本或发布一个新的修订版:
# 用户侧回滚到上一个版本
dsh plugin --profile desktop remove dsh-plugin-prompt-optimizer
dsh plugin --profile desktop add dsh-plugin-prompt-optimizer@<上一个版本>
若某版本有严重缺陷,可在 npm 上把它标记为废弃(不影响已安装用户,但阻止新装):
npm deprecate dsh-plugin-prompt-optimizer@<坏版本> "请升级到 <好版本>:<原因>"
11.4 发布后必做
- 在干净 profile(或另一台机)上仅按本文档 §3 从零安装一次,重启后确认插件可见且启用;
- 记录该次「从零安装」的实际输出,作为
G4 发布就绪的证据。
Comments
Loading…
Similar plugins
by naitoupi
DeepSeek Harness (DSH) plugin: ? optimize the composer draft with the current model. Installable bundle (dsh.bundle + dsh.client); Settings tab: on/off switch, generation params, editable system promp
★ 0
MIT
JavaScript
Sep 21, 2026
dsh plugin --profile web add prompt-optimizer-pluginby rongxingda
Prompt enhancement plugin for the DeepSeek Harness web GUI: one-click rewrite of the composer draft into a structured prompt, with preview, fill-back, and undo.
★ 7
↓ 2.4k/wk
Apache-2.0
TypeScript
Sep 30, 2026
dsh plugin --profile web add dsh-prompt-enhanceby EmotionG
Prompt optimizer for the DeepSeek Harness composer: a normal/optimize mode toggle in conversation.input.right that optimizes the draft with the session's current model and writes it back to the composer.
★ 0
MIT
TypeScript
Sep 17, 2026
dsh plugin --profile web add dsh-prompt-optimizerby lokih1028
One-click prompt enhancement and structuring button for DSH composer.
★ 0
↓ 185/wk
MIT
TypeScript
Aug 29, 2026
dsh plugin --profile web add dsh-prompt-optimizerOptimize Prompt button under the composer: one click rewrites your draft into a clearer, more executable prompt, with a before-and-after dialog and one-click replacement.
★ 0
↓ 185/wk
dsh plugin --profile web add dsh-prompt-optimizerby XXXXXQ-0206
Adds a composer button that optimizes the current prompt or designs the next one from the current session and project context.
★ 0
MIT
JavaScript
Sep 13, 2026
dsh plugin --profile web add dsh-prompt-for-me