DSH HUB
首页插件商店插件包社区排行榜资源发布指南
插件源码
返回插件目录

LiWenzhuo001 /

LiWenzhuo001/dsh-plugin-prompt-optimizer

已验证

Prompt optimizer plugin for DeepSeek Harness: one click rewrites your composer draft into a clear, verifiable prompt. Zero dependencies.

★ 1 Stars0 Forks0 IssuesN/A 社区评分0 已确认安装
查看 GitHub
README来源: main@55b4e459

提示词优化(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. 它解决什么问题
  2. 三种使用方式
  3. 安装
  4. 配置项
  5. 分析维度与评分口径
  6. 已知边界
  7. 开发
  8. 目录结构
  9. 版本兼容矩阵
  10. 排障
  11. 发版约定

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)。安装一个组合包会做两件事:

  1. 在该 profile 的 package.json 里新增一条 dependencies;
  2. 把包名追加到 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

它会做三件事,且幂等(重复执行不会写入重复行):

  1. 把 package.json、cordis.patch.yml、lib/、src/、docs/、tools/、README.md 拷到 <profile>\node_modules\dsh-plugin-prompt-optimizer\;
  2. 在 profile 的 package.json 里写入 "dsh-plugin-prompt-optimizer": "link:<本包绝对路径>",并把包名追加进 dsh.profile.bundles(不覆盖既有顺序,dsh-plugin-whale-pet 等既有包保持原位);
  3. 在 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 路由对空白文本回 400 empty_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 逐项检查并在任一项失败时非零退出:

  1. node tools/build-host.mjs && node tools/build-client.mjs 成功,且连续两次构建产物字节一致(构建确定性是一票否决项);
  2. node --test "tests/**/*.test.mjs" 全绿;
  3. 包契约检查通过(verify/check-package-contract.mjs);
  4. npm pack --dry-run 清单与 files 白名单一致,且不含 tests/、verify/、备份目录;
  5. package.json 的 version、CHANGELOG.md 的最新条目、本文档 §9 兼容矩阵三者一致;
  6. 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 发布就绪 的证据。
—/ 5

暂无评分

已验证 DSH bundle

Commit 55b4e459e481

社区评论

还没有评论,来写第一条。

DSH HUB

社区维护的 DSH 插件索引。不是 GitHub 或 DeepSeek AI 的官方产品。

社区资源API关于