dsh-prompt-polish
给 DeepSeek Harness 输入框加一个**「优化」按钮**:草稿写好但还没发送时按一下,用当前默认模型把这段提示词改写得更清晰、更可执行,结果直接回填到输入框,你可以继续改、继续发。
+ [完全权限] [计划] [✦ 优化] [模型] [发送]
^^^^^^^^ 这里
为什么
写提示词时最费劲的是「把脑子里的模糊想法写成一段可执行的话」。这个按钮把这一步压成一次点击,改完的文本仍然在你的草稿里,可以继续手工调。它不发送、不进入会话上下文、不产生新回合,只是一次独立的一次性模型调用。
交互细节
- 草稿为空、或正在提交时按钮自动置灰
- 点击后图标脉动、文字变「优化中」
- 失败时按钮变红约 3 秒,hover 可看到具体错误
- 草稿里带
@文件/ 会话引用标记时,按钮提示会说明这些标记会被替换掉
怎么用
- 把提示词写在输入框里,先不要发送
- 点「✦ 优化」
- 模型返回后,改写结果替换当前草稿
- 满意就发送,不满意就 Ctrl+Z 或继续手改
安装
# 推荐:按 profile 安装
dsh plugin --profile desktop add Lstalu/dsh-prompt-polish
装完重启 DSH 宿主(关窗口再开),服务端插件不会热加载。
本地开发时改用 link,不走 registry:
cd "$DSH_HOME/profiles/desktop"
# package.json 的 dependencies 加:
# "dsh-prompt-polish": "link:<你的路径>/dsh-prompt-polish"
# package.json 的 dsh.profile.bundles 加:
# "dsh-prompt-polish"
pnpm install
卸载
从 dependencies 和 dsh.profile.bundles 各删掉对应行,pnpm install,重启。
原理
一个插件包,两张面孔:
| 半部 | 文件 | 做什么 |
|---|---|---|
| 宿主 | index.js |
在 ctx.webServer 上挂 POST /prompt-polish/optimize;收到草稿后调 ctx.llm.stream() 做一次一次性模型调用(不进入 Agent 回合、不占用会话上下文);模型取 ctx.agentDefaultModel.currentSelection() |
| 浏览器 | lib/client.js |
在 conversation.input.left 槽注册按钮;用槽的 standard props useInput 读草稿与提交状态,用 inputActions.setDraft() 写回 |
宿主端点带同源校验:带 Origin 的请求必须与请求 Host 一致,浏览器里打开的第三方页面无法借道调用你的模型额度。
另外提供一个 GET /prompt-polish/health,用来确认插件是否真的加载了、当前用的是哪个模型。
可调参数
在 profile 的 cordis.patch.yml 里给这一行加 config:
- id: prompt-polish
config:
temperature: 0.2 # 默认 0.2,越低越保守
maxTokens: 2048 # 默认 2048
开发
# 宿主半部:mock cordis ctx,真打一遍 HTTP 端点
node test/host-smoke.test.mjs
# 浏览器半部:mock ModuleLoader,检查 bundle 加载、槽注册、缺 props 不崩
node test/client-load.test.mjs
verify.ps1 用于装完后自检:自动遍历运行中的 DSH 进程监听端口,逐个试 /prompt-polish/health,不需要手动指定端口。
开发约定(踩过的坑,别再犯)
window.__ModuleLoader__.load({ id }) 里的 id 必须等于 package.json 的 name(这里就是 dsh-prompt-polish),不能写 cordis 行 id(prompt-polish)。
两者不一致时,client-modules 按包名找不到已注册的 factory,会退化成用单个资源 URL 再执行一遍 bundle,于是第二次注册同一个 id 并抛出:
client-modules: duplicate factory registration for "prompt-polish"
后果不是按钮不出来,而是整个 Web entry 导入失败、应用打不开。cordis.patch.yml 里的 entry id 保持 prompt-polish 是正确的——它和 bundle id 是两个不同层级的标识。
这条约束不容易看出来:参考对象 quota-meter 的包名和 bundle id 恰好都是 quota-meter,规则在它身上是隐形的。抄写法时要连着包名一起核对。
slots.register({ id }) 里那个 id: "prompt-polish" 是 slot 条目 id,与 bundle id 无关,保持原样。
配套的教训写在测试里:test/client-load.test.mjs 断言的是「bundle id 等于 package.json 的 name」,而不是「等于某个字符串」。用硬编码字符串当期望值,等于把自己的假设固化成测试,错误会被测成通过。
已知限制
- 改写使用当前默认模型,暂不支持在按钮上单独选模型
setDraft()会把草稿整体替换成纯文本,草稿里已有的@引用 chip 会被移除(按钮提示里会写明数量)- 草稿上限 12000 字符
- 每次点击就是一次独立的模型请求,会计入账户用量
- 改写用的系统提示词写死在
index.js的SYSTEM_PROMPT,想调整风格直接改那里
License
MIT
No comments yet. Be the first to write one.