dsh-ask-first
在输入框加一个按钮:先复述你的草稿,再用可点的选项问几个问题——每题都带一个「我不知道,你替我定」的逃生项——最后把草稿改写成 AI 能直接开工的需求。全程可以一个字都不打,而且它不会替你发送。
安装
dsh plugin --profile web add dsh-ask-first
沙箱测试
这个插件还没测过。提交测试 →
README
dsh-ask-first · 说清楚点
<p align="center"><img src="assets/icon.png" width="280" alt="dsh-ask-first"></p>
DeepSeek Harness 输入框里的一个澄清按钮:先问你什么意思,再动笔改写。
[English](README.md) · 源码
大多数「优化提示词」的插件都假设你已经能把自己的想法讲明白,它们只负责把措辞修整齐。
这个插件的假设正好相反:草稿之所以含糊,是因为人还没想清楚、或者不会说。所以它先复述一遍
听懂了什么,再问两三个点一下就能答的问题,最后才重写——重写成一条 agent 能直接开工、不必回头再问的需求。
它先说它认为你想要什么,再问真会改变结果的那几点,最后交给你的是一条带目标、约束和完成标准的需求。
安装
dsh plugin --profile web add dsh-ask-first
或者打开 GUI:插件 → 添加插件,填 dsh-ask-first。
插件带浏览器半边,装完需要重启宿主。之后按钮就在输入框左下角、发送那一行的左侧。
没有配置项,也没有 key 要填。
拿一句含糊的话试一遍
1. 写三个字,点「说清楚点」
在输入框里随便写一句,哪怕只是「帮我做个页面」,然后在发送之前点左下角的 说清楚点。
按钮的悬停提示是:不用会描述:点几下选项,我替你把需求问清楚。
面板打开时标题是 说清楚点,下面一行是 先问清楚,再发送。你原来那句话一个字没动,也什么都没发出去。
2. 先看复述,再点着答
面板最上面单独一块,标签是 我理解你想要的是,一句话,用模型自己的话复述它从你草稿里读到了什么。
这句话是判断它有没有听懂的唯一依据,所以它单独成块,而不是被揉进重写结果里。
下面一行是 理解对了吗?下面几问点一下就行,不用打字。 再往下是两三个问题,挑的都是「答案会改变结果」的
那几点。每个问题都带可点选项,并且每个问题的最后一项固定是 我不知道,你替我定——答不上来的人也有路可走。
全程打字都是可选的。每道题下面还有一行自由输入,标签是 或者自己写一个答法(可留空),
面板上也说清楚了:不想答的留空就行;一个都不选也能直接重写。
3. 把重写结果拿回输入框
点 按这些重写,先看到 正在按你的选择重写……,然后是结果,配一句
觉得可以就直接填回输入框;还能再改。,以及字数。
结果是能直接开工的一条需求:先说清目标,再列关键约束,最后写什么算完成。它真不知道的信息不会瞎编,
会留成看得见的 [待补充:…] 占位。三个按钮:填回输入框、重新问一遍、关掉。
它从不替你发送。 把草稿写回输入框是它做的最后一件事,发送键始终在你手上。
它和其它提示词改写插件差在哪
- 先复述,再追问——面板第一块就是「我理解你想要的是……」,理解错了在花掉一次重写之前就能看见。
- 问题可以不打字就答完——选项是按这一句草稿现生成的,不是固定问卷;每问最后一项固定是 我不知道,你替我定。
- 零打字这条路由代码兜底——模型没给选项、或者忘了那个逃生项,Host 半边在面板渲染前补上;不指望提示词自觉。
- 不编参数——确实不知道的留成
[待补充:…],由你补或删。 - 从不替你发送——结果用
inputActions.setDraft()写回输入框就停下。 - 用你当前的模型,零配置——不要 API key,不配 provider,没有设置页。
- 模型不听话不算故障——解析不出 JSON 时,原文直接当作复述,面板跳到重写。
什么时候别用它
- 你本来就会把话说清楚。 那每一次点击都是白花两次模型调用。
- 你希望 agent 立刻开工。 这个按钮的全部工作就是「先问」——和「别问了赶紧干」正好相反。
- 你只是想要另一种说法。 换语气、翻译、缩短是改写活儿;这个插件改的是「需求本身是什么」。
- 你的宿主没接 LLM 服务。 面板会直接说连不上本机改写服务,而不是编一个结果给你。
工作原理
两半,一个包。
文件 · 作用
lib/index.js · Host 半边。注册三条只接受 loopback 的 POST 路由,所有模型调用都在这里(ctx.llm.stream)。
lib/client.js · 浏览器半边。在 conversation.input.left 插槽注册按钮与面板,用 inputActions.setDraft() 回填输入框。
cordis.patch.yml · 让宿主把这个包插进插件树。
test-offline.mjs · 离线自检。不联网、不启宿主:node test-offline.mjs。
接口
方法 · 路径 · 请求体 · 响应
POST · /api/dsh-ask-first/health · {} · { ok, value: { llm, provider?, model? } }
POST · /api/dsh-ask-first/ask · { draft } · { ok, value: { guess, questions: [{ id, question, hint, options[] }] } }
POST · /api/dsh-ask-first/rewrite · { draft, answers: [{ question, answer }] } · { ok, value: { text } }
三条都只接受本机请求:socket 地址必须是 127.0.0.1、::1 或 ::ffff:127.0.0.1,Host 头必须是
loopback,Origin 指向别的宿主、或者带 sec-fetch-site: cross-site 的请求一律 403。
用哪个模型
不需要填 API key,不需要配 provider,没有设置页。插件调 ctx.llm.stream 时用的是
agentDefaultModel.currentSelection() 报的 provider / model——就是输入框右下角显示的那一个。
拿不到这个服务就整对省略,让宿主自己回退到最后一次用过的目标。
实话说的成本:点一次是两次模型调用——一次问,一次重写——算在你当前会话头上。
模型不听话时
向模型要的是严格 JSON,而模型不总听话。解析不出 JSON 不算错误:原文直接当作「我理解你想要的是」
那句话,面板跳到重写步骤。问题最多三条、选项最多四个、过长字段截断,所以一次失控的回复弄不坏面板。
下面这些是给检查包的人看的,不是给决定要不要装的人看的。
自检
node test-offline.mjs
39 项,不联网、不起宿主:路由注册、请求校验、从围栏里抠 JSON、选项清洗、跨站拒绝,以及发给模型
的请求体内容。
给评审的说明
lib/client.js是一个window.__ModuleLoader__.load({ id, factory })包裹。这是 DeepSeek Harness 客户端插件的标准形态,不是打包产物:模块体是可读明文源码、没有压缩,唯一的require是react与react-dom,两个都由宿主提供。- 没有凭据、没有埋点、没有对外请求。唯一的网络调用就是上面那三条 loopback 路由,唯一的模型调用走宿主自己的
ctx.llm服务。 - 没有安装期脚本。
preview/shot.html是 README 截图所用的页面。它把真实的lib/client.js加载进来,外面配一个假宿主和假后端,所以截出来的就是真面板。它不在发布包里(见package.json的files);要重跑截图需要preview/vendor/下有 React 的 UMD 构建,那个目录被 gitignore 了,从 jsDelivr 取即可。
许可
[MIT](LICENSE)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:3,最后更新 2026-10-31