选中助手回答任意片段,一键转成引用草稿待追问
30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/21 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add tupi00/dsh-quick-reply该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
DSH Web 插件:选中助手正文,一键引用回复(只填草稿,不自动发送)
README
由 DeepSeek 最新模型翻译生成dsh-quick-reply · 引用回复
给 DeepSeek Harness(下称 DSH)Web 界面用的一个小插件,两个入口,都只做「引用」:
1. 选中屏幕上任何一段文字(助手的回答、左侧会话列表里的会话标题、右侧面板里的内容),鼠标旁边会冒出一张「引用回复」小卡片。点一下,就把这段文字变成 Markdown 引用块填进草稿,不自动发送。
2. 在左侧会话列表里把鼠标移到某个会话行上,行末会出现一个引号按钮。点一下,切到那个会话,并把它最后一条已经说完的回答引用进草稿。
没有悬浮球、没有快捷键冲突。
当前版本 1.3.1,更新记录见 CHANGELOG.md。
它解决什么问题
长对话里想追问某一句时,常见做法是把那句话复制下来、粘进输入框、手动加 >、再补出处。四步,还容易粘错。
这个插件把它压成一步:选中 → 点「引用回复」→ 草稿里出现
你选中的那两行文字…(略) (引用自第7轮回答)
光标已经落在引用块下面那一行,直接写问题就行。
行为细节
- 选中范围:助手消息里只认「起点和终点都在同一条助手消息正文里」的选区——选中你自己的提问、工具调用卡片、思考过程、系统提示,按钮都不会出现,避免引错东西。聊天区以外(左侧会话列表、右侧面板)选中的文字也可以引用,那里没有「第几轮」的概念,所以只写 > 原文,不带出处标注。
展开完整文档(README 剩余 1 节)
dsh-quick-reply · 引用回复
给 DeepSeek Harness(下称 DSH)Web 界面用的一个小插件,两个入口,都只做「引用」:
1. 选中屏幕上任何一段文字(助手的回答、左侧会话列表里的会话标题、右侧面板里的内容),鼠标旁边会冒出一张「引用回复」小卡片。点一下,就把这段文字变成 Markdown 引用块填进草稿,不自动发送。
2. 在左侧会话列表里把鼠标移到某个会话行上,行末会出现一个引号按钮。点一下,切到那个会话,并把它最后一条已经说完的回答引用进草稿。
没有悬浮球、没有快捷键冲突。
当前版本 1.3.1,更新记录见 CHANGELOG.md。
它解决什么问题
长对话里想追问某一句时,常见做法是把那句话复制下来、粘进输入框、手动加 >、再补出处。四步,还容易粘错。
这个插件把它压成一步:选中 → 点「引用回复」→ 草稿里出现
你选中的那两行文字…(略) (引用自第7轮回答)
光标已经落在引用块下面那一行,直接写问题就行。
行为细节
- 选中范围:助手消息里只认「起点和终点都在同一条助手消息正文里」的选区——选中你自己的提问、工具调用卡片、思考过程、系统提示,按钮都不会出现,避免引错东西。聊天区以外(左侧会话列表、右侧面板)选中的文字也可以引用,那里没有「第几轮」的概念,所以只写 > 原文,不带出处标注。输入框里选中自己打的草稿不算引用。
- 侧栏文字本来选不中:宿主给会话行设了 user-select:none,插件把它放开成 user-select:text,才能拖选会话标题。单击行为不变(浏览器只有拖过一小段距离才算选中),行末的悬停按钮也不受影响。
- 卡片贴着鼠标出现:位置取鼠标松开的那一点(选区焦点,正拖反拖都对),卡片右缘与字尾齐平、缩在文字下方,视线不用跳。下边放不下就翻到字的上面;贴到窗口边缘时会夹进窗口,不会被切掉。滚动聊天或缩放窗口时重新定位,跟着文字走。
- 引用会自动截断:默认只留前 2 行 / 最多 120 字,超出部分用 …(略) 标记。原因是一整段回答塞进草稿会把输入框撑爆,也不方便接着写。原文仍然高亮着,想看全文回消息里看。
- 带上出处:引用块最后一行的末尾跟一个 (引用自第N轮回答),同一行,不另起一段。模型看到的只是纯文本、没有消息 ID,同一句话在历史里出现两次时它会分不清——轮次号给它一个可核对的坐标。这个 N 直接读宿主写在消息外层 div 上的 data-chat-turn,和界面右侧「轮次导航」显示的第几轮是同一个数字。在代码 / diff 面板里选中时没有「第几轮」,改成写 (引用自第79行)——行号是拿选区左边那一列数出来的,数不出来就干脆不写,不编假的。
- 光标落在引用块下一行:填完草稿后光标自动停在引用块下面的空行,直接写问题就行,不用再点一下。
- 原文高亮:用 CSS Custom Highlight API 标记选中的原文。不改宿主 DOM,所以不会和 React 的重渲染打架;浏览器不支持时静默跳过,功能不受影响,只是少了视觉提示。
- 引用过高亮一直留着:引用完那一段会「钉住」,之后你选别处、点别处、继续聊天都还亮着,方便回看自己引过哪些段。一个 Highlight 里装了多个 Range,所以「正在选的」和「已经引过的」可以同时亮。宿主重渲染后断开的 Range 会自动剔除;引用超过 50 段时丢掉最早的。页面刷新就清空。
- 把引用删掉,高亮跟着消失:判断依据是「这段字还在不在输入框里」,不是「你有没有按删除键」——整段删、撤销、发送后清空,都一样处理。逐字比较会把改标点、加空格误判成删除,所以只比字(汉字、字母、数字),标点空白忽略。
- 只填草稿,绝不发送:发不发、发什么,由你按回车决定。
- 保留已有草稿:如果输入框里已经写了东西,引用的内容会接在后面,前面空一行。
侧栏引用(会话列表里那个引号按钮)
- 引什么:那个会话最后一条已经说完的助手回答(跳过还在输出中的那一步,也跳过只有工具调用的步骤)。会话还没被回答过时,按钮点了不会有反应。
- 先切过去:点按钮会先打开那个会话,等它的历史加载完、最后一条回答出现,再把引用填进它的草稿。所以你会看到会话切换 + 草稿里出现引用块。
- 出处照旧:同样带 (引用自第N轮回答),光标同样落在引用块下一行。
- 为什么是「会话内引用」而不是跨会话引用:跨会话把别的会话的回答引到当前会话,需要插件去持有并读取另一个会话的历史,代价和出错面都大得多;而「点开这个会话、引用它自己的最后一条」用的还是同一条「当前会话」路径,简单可靠。这是刻意的取舍,不是没做完。
安装
前提
- DSH 桌面端(Electron)或 dsh web,且 Web 界面能正常打开。
- 插件通过 DSH 的插件管理器以本地包方式安装,不需要联网。
方式一:插件管理器(推荐)
在 DSH 里让 agent 执行:
plugin_manager install_bundle target = <本仓库的绝对路径>
装完后 重启 DSH 应用(宿主进程的模块缓存按 URL 记,重载不会重新求值),再刷新网页。
方式二:手动挂到 profile
把本目录放到任意位置,然后在 profile 的 package.json 里加一条依赖:
{
"dependencies": {
"@local/quick-reply": "link:<本仓库的绝对路径>" } }
并把 @local/quick-reply 追加到 bundles 列表末尾,重启 DSH。
验证装好了没有
刷新页面后:
1. 选中任意一条助手回答里的文字。鼠标旁边出现「已选中第 N 轮的文字 · 引用回复」=选区那条装好了。
2. 拖选左侧会话列表里的会话标题。卡片上写「已选中文字」(没有轮次号)=侧栏选区也装好了。
3. 把鼠标移到左侧会话列表的任意一行上,行末多出一个引号按钮 = 侧栏那条装好了。
没出现的话按顺序查:
1. 打开控制台,看有没有 @local/quick-reply 相关的加载错误;
2. 在 DSH 里查插件列表,确认它是启用状态;
3. 确认选中的确实是助手消息正文(不是工具输出、不是思考过程、不是你自己的提问);
4. 侧栏按钮不出现时,确认那个会话行是不是被归档/空白会话(宿主对这类行不渲染动作按钮)。
卸载
在插件管理器里禁用或移除,或者从 profile 的 package.json 里删掉依赖与 bundles 条目,然后重启 DSH。
技术说明
挂在哪
用三个宿主官方槽位:
- shell.overlay —— 窗口最上层、不随聊天滚动的一块浮层。卡片本体挂这里,位置由选区坐标算出来(position: fixed)。
- conversation.input.dock —— 输入框卡片上方那一整行。这里只挂一个「什么都不渲染」的桥组件,用来取输入框的 inputActions、当前草稿、以及当前会话的聊天快照。
- sidebar.workspaces.session.row.action —— 会话列表每行末尾的悬停按钮位(宿主自己的「归档」「置顶」也在这一排)。这里挂侧栏那个引号按钮。
为什么要分三处:shell.overlay 和侧栏行按钮都是 root 作用域,拿不到输入框的 inputActions,也读不到聊天快照;只有 conversation.input.dock 两样都拿得到。所以那两处只负责「告诉桥要干什么」,真正的取文字和填草稿都在桥里完成。
侧栏按钮为什么要切会话:桥跟着「当前会话」挂载,它只能读当前会话的聊天快照。所以点侧栏按钮先切过去,等新会话的历史加载完,桥自然就能读到那条回答了。好处是不需要跨会话 retain 别人的历史,坏处是用户会看到一次会话切换——这是刻意的取舍。
文件结构
QuickReply/
├── package.json # 包元数据 + dsh.client 声明(平台、注入依赖) ├── cordis.patch.yml # Cordis 加载补丁:insert 一个 id=quick-reply 的插件 ├── index.js # Host 半边(空实现;本插件纯客户端,留入口给以后扩展) ├── client.js # 浏览器半边:全部逻辑都在这里 ├── locale/zh.json # 插件列表里的标题与描述 ├── locale/en.json ├── icon.svg └── test/helpers.test.mjs # 纯函数单测(不启浏览器)
关键实现点
- 宿主插槽 props:dock 条目能拿到 inputActions(setDraft / submit 等)与当前草稿,所以填草稿走的是宿主自己的草稿接口,不是去模拟键盘。
- 为什么要缓存选区:点击按钮的 mousedown 会把页面选区清空,所以插件在 selectionchange 里先把「选中了哪段、属于第几轮、在屏幕哪个位置」记下来(用 requestAnimationFrame 合帧,拖选时不会疯狂重渲染),点按钮时用的是缓存。
- 怎么判断「这段文字能不能引」:看选区的起点和终点落在哪个容器里。两端都在同一条 [data-chat-flow-kind="assistant-step"] 里 → 能引,带轮次号;两端都不在聊天流里(侧栏、右侧面板)→ 也能引,但没轮次号;一头在里一头在外 → 跨区选择,不认。另外两端都在 [data-composer-card] 或 contenteditable 里(= 用户在选自己打的草稿)→ 不认。
- 位置在渲染后用 useLayoutEffect 算:卡片宽度要先量出来才能决定水平对齐(右缘贴字尾);layoutEffect 在浏览器绘制前跑完,用户看不到跳一下。位置没算好前先放 left:-9999px,避免在左上角闪一下。
- 锚点取选区焦点而不是 range 末尾:选区分方向,从下往上拖选时 range 的终点在文档里是上面那行。取 selection.focusNode / focusOffset 处收一个零宽 Range,才是鼠标松开的那一点。
- 按钮上 onMouseDown: preventDefault():同样是为了保住选区,避免卡片在按下的瞬间自己消失。
- 填完把光标送到末尾:focus() 的默认落点不保证在末尾,所以用 Selection API 把 range 收拢到 contenteditable 的末尾。
- 样式自己插 标签:装进 profile 的普通插件拿不到动态插件沙箱里的 styles 服务,宿主自带的客户端插件也是自己插 style 标签的。颜色一律用 --dsw-alias-* 设计令牌,跟随主题。
- 侧栏按钮和桥之间靠一个小 store 通知:两者不在同一棵 React 树里,侧栏按钮只能把「要引用哪个会话」写进模块级的 pendingQuoteStore;桥订阅它,被通知后重渲染、等目标会话的最后一条回答出现再填草稿。用普通变量的话桥的依赖项没变、effect 不会重跑,点了就像没反应。
- 挑「最后一条回答」时跳过 status === 'running' 的步骤:那一步还在往外吐字,引一半会被截断,模型看到的是半句话。
- useChat 缺失时用空壳 hook 顶上:React 要求每次渲染 hook 数量一致,props.useChat ? props.useChat(x) : null 会让两边 hook 数不同、整棵组件炸掉,所以空壳也要调一次 useSyncExternalStore。
- 不用 require 引 DSH 客户端包:插件只依赖宿主注入的 ctx、React,符合宿主对插件的要求。
开发
纯函数单测(不需要浏览器)
node test/helpers.test.mjs
语法检查
node --check client.js
node --check index.js
test/helpers.test.mjs 会用标记 // >>>PURE-HELPERS 从 client.js 里把纯函数抠出来跑,所以那几个函数里不能出现 DOM / React 调用。
已知限制
| 限制 | 说明 |
| 只引用助手正文 | 选中你自己的提问、工具输出、思考过程不会出现按钮。这是有意的。 |
| 侧栏只引「最后一条已结束的回答」 | 不提供「选第几条」的入口;想引中间某条,打开那个会话手动选中即可。 |
| 侧栏引用会切会话 | 点按钮会先打开那个会话。这是为了复用「当前会话」路径,避免跨会话读历史。 |
| 引用永远截断 | 目前没有「引用全文」入口。需要整段时手动选中复制。 |
| 依赖宿主 DOM 语义属性 | 选区判定依赖 [data-chat-flow-kind="assistant-step"] 和 [data-chat-turn]。宿主改版时插件最多失效(按钮不出现),不会弄坏聊天。 |
| 位置由 JS 算 | 卡片用 position: fixed 跟随选区坐标,不是宿主分配的布局空间。滚动/缩放时会重算,但如果宿主在浮层里加了 transform 容器,定位可能偏移。 |
| 没有配置项 | 截断行数/字数写死在 client.js 顶部(QUOTE_MAX_LINES / QUOTE_MAX_CHARS),改完需重新加载插件。 |
| 仅 Web 界面 | 宿主声明 platform: "web"。 |
许可
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
tupi00/dsh-quick-reply
选中助手回答任意片段,一键转成引用草稿待追问
相关插件 · UI / 主题
破甲增强版JeffKeeping/dsh-purge-plus
dsh-purge 的非官方分支fork:适配 DeepSeek Harness 0.2.1-rc.2、破甲内核…
★ 387已汉化DeepSeek 客户端
71.9
无代码业务系统平台nocobase/nocobase
NocoBase 是什么
★ 24,804已汉化DSH
71.8
1Panel 服务器面板1Panel-dev/1Panel
全球 250 万+ 自托管用户共同喜爱。
★ 37,362已汉化DSH
71.4
终端编码代理esengine/DeepSeek-Reasonix
· 指南 · ACP · 扩展开发 · 规格 · 官方网站 · Discord · QQ
★ 36,076已汉化DSH
71.2
工作状态行动态ccch1mneyyy/working-activity
作者:chimney@ccch1mneyyy。社区项目,非 DeepSeek 官方项目。
★ 664已汉化DSH
71.2
多模型配置管家farion1231/cc-switch
跨平台桌面一体化助手,支持 Claude Code、Codex、OpenCode、DeepSeek Harness 等工具,唯一官网 ccswitch.io
★ 151,814已汉化DSH
71.1
这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。