一键停答并回退会话,把上条提示词放回输入框
29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/28 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add icrefin/dsh-prompt-recall该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
dsh 原生插件 · chat
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 5 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🟢 扫描:未发现敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。
扫描于 2026/10/31(0 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-ui-conversation@deepseek-ai/dsh-client-ui-slots给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
在 DeepSeek Harness 里撤回上一条提示词:一键停住当前回合,把会话回退到它之前,并把文本送回输入框。
README
由 DeepSeek 最新模型翻译生成dsh-prompt-recall
把最后一条提示词收回来。 你最新发出的提示词下面会多一个图标,与 复制 同一行,用同一套动作按钮样式绘制。点击它会停止正在执行的回合、把会话回退到这条提示词之前,并把文本放回输入框,供你修改后重新发送。
它解决的场景
提示词已经发出,答案进行到一半你才发现措辞不对。此前只有两个选择:等它答完再补一句修正,或者停掉再从头把提示词敲一遍。撤回是第三种。
撤回前 ⇢ 点击一次之后 ┌───────────────────────────────────┐ ┌────────────────────────────────────┐ │ ▸ 你 │ │ ▸ 你 │ │ 总结一下 relay/README.md 里的 │ │ (上一回合,未受影响) │ │ 重试逻辑并提一个 PR │ │ │ │ 09:26 ⧉ ↻ │ ├────────────────────────────────────┤ ├───────────────────────────────────┤ │ ✎ 用三条要点重新总结重试策略 │ │ ▸ 深度思考中…
展开完整文档(README 剩余 1 节)
dsh-prompt-recall
把最后一条提示词收回来。 你最新发出的提示词下面会多一个图标,与 复制 同一行,用同一套动作按钮样式绘制。点击它会停止正在执行的回合、把会话回退到这条提示词之前,并把文本放回输入框,供你修改后重新发送。
它解决的场景
提示词已经发出,答案进行到一半你才发现措辞不对。此前只有两个选择:等它答完再补一句修正,或者停掉再从头把提示词敲一遍。撤回是第三种。
撤回前 ⇢ 点击一次之后 ┌───────────────────────────────────┐ ┌────────────────────────────────────┐ │ ▸ 你 │ │ ▸ 你 │ │ 总结一下 relay/README.md 里的 │ │ (上一回合,未受影响) │ │ 重试逻辑并提一个 PR │ │ │ │ 09:26 ⧉ ↻ │ ├────────────────────────────────────┤ ├───────────────────────────────────┤ │ ✎ 用三条要点重新总结重试策略 │ │ ▸ 深度思考中…(仍在执行) │ │ ↑ │ │ │ │ 光标在此,可直接重发 └───────────────────────────────────┘ └────────────────────────────────────┘ 09:26 = 时间 ⧉ = 复制 ↻ = 撤回
它贡献了什么
| 位置 | 作用 |
| 最新提示词的动作行 | 在自带的 复制 按钮旁新增一个图标按钮,并沿用该按钮自己的 class 样式 |
| 语言命名空间 dsh-prompt-recall | 提示气泡、执行中状态与三条失败提示的中英文文案 |
| conversation.input.right | 承载控制器:它拥有该按钮,并把撤回的文本注入输入框——自身不渲染可见控件 |
没有宿主路由、没有宿主服务、没有 Config。宿主半边(exports["."])只为让 Loader 行能够携带浏览器半边(exports["./client"])。
一次点击做了什么
on(recall)
stop 取消该会话作用域内的 conversation.cancel() # 与「停止」按钮同一操作 plan 从事件窗口读取提示词文本与 seq rewind sessions.fork({ sessionId, atSeq: boundary }) # 与「分支」按钮同一操作 stage 把文本交给子会话的输入框 open 跳转到子会话 retire 把发起撤回的那个会话归档 # 与 ⌘⇧A 同一操作
1. 停止。 在会话自身的作用域内取消进行中的回合,与输入框的「停止」按钮完全一致。此处的失败会被吞掉——空闲会话本就无可取消,而这不应阻塞回退。
2. 回退。 会话从自身日志中的一段精确前缀继续。
3. 还原。 撤回的文本被暂存给子会话的输入框,在其挂载时写入,随后把光标交还给它。
为什么是在一个新会话里继续
会话日志是只追加的持久记录,且运行中的 Agent 持有它。平台没有「删除最后一轮」的操作,而在 Agent 运行期间改写日志会破坏会话。平台对「从更早的位置继续」给出的答案就是 session/fork——把一段精确的事件前缀复制进新会话——这正是自带的 分支 按钮所做的事。
撤回是同一个操作,只是切点不同:
| | 切点 | 结果 |
| 分支(自带) | 你选择的那一轮结束处 | 复制全部内容,换一种方式继续 |
| 撤回(本插件) | 该提示词入队之前 | 一段不包含该提示词的历史 |
子会话保留工作目录、Agent 预设与所属工作区,标题会递增,侧边栏因此不会出现两行难以分辨的记录。
撤回可以重复:每撤回一次就再往前切一条提示词,并归档它来自的那个会话,因此一条回退链上永远只有一个可见会话。
旧会话会怎样:归档,而不是删除
只做 fork 会让同一段对话同时存在两份,所以撤回会把它来自的那个会话退休掉——而平台为此提供的操作是归档。DSH 里根本不存在「删除会话」:archiveSession / unarchiveSession 就是全部词汇(会话索引里的 _deleteSession 只是搜索缓存的维护,workspaces.delete 删的是工作区)。这恰好适合这个动作:
- 日志原封不动——被撤回的提示词仍在那个会话里,什么都没丢,unarchiveSession 会让它回到列表中原有的位置;
- 它让「撤回」更彻底——provider 的 agent/pre-step 唤醒闸门读的正是这份持久归档集合,所以被退休的会话无法被唤醒、把你刚收回的提示词再跑一遍;
- 它写的就是自带 ⌘⇧A 快捷键所写的同一份持久状态,并带 stopActivity——当会话还有活在跑时,DSH 自己的确认弹窗提供的就是这个升级选项,而撤回已经替你决定了。
想拿回来: 侧边栏的视图选项可以按归档状态过滤(default / show / only),而会话搜索结果里每条已归档会话都带一个「取消归档」按钮。不需要改文件,也不需要重启。
如果归档失败(最常见的原因是注册表还不认识这个会话),撤回已经完成的部分全部保留,并在新会话里提示「上一个会话未能归档——它仍然在侧边栏里」,而不是把整个动作丢掉。
子会话(subagent)中不提供撤回:它的记录是父会话的证据而不是一段对话,fork 它会用一个子代理前缀造出一个普通会话,归档它则会把它从父会话的目录里移除。
按钮放在哪里,以及为什么用 DOM 定位
Chat 视图没有为用户消息的动作行提供 slot。conversation.chat.assistant-actions 与 conversation.chat.turnTail 都只在回合结束后渲染,而 Agent 仍在工作时两者都不存在——那恰恰是撤回按钮必须可点的时刻。若改为覆盖 conversation.chat.node 中 user 这一 keyed 条目,就必须重新实现自带的用户气泡、引用 chip、附件与样式表,并在每次 Harness 更新时随之漂移。
因此控制器改用这些行自身样式表所使用的同一套公开 DOM 约定来定位,并限定在包含自己输入框的那个 Conversation 实例内:
| 选择器 | 含义 |
| [data-conversation-content] | 一个 Conversation 实例,带 data-conversation-session 标记 |
| [data-chat-flow-kind="user"] | 一条用户(或插话)消息的流式条目 |
| [data-clock="start"] | 动作行本身——复制按钮所在处 |
它取最新可见的那条用户行,因此按钮会跟着会话走。它还从相邻的 复制 按钮上复制实时的 class 属性,这正是它此刻与将来都与之一模一样的原因:给复制按钮定样式的那条规则,同样给撤回按钮定样式。插件自带的样式表只是兜底,仅在无法复制到相邻 class 时生效(:not([class]))。
定位通过 MutationObserver 反复求值,而不是在渲染期读取——因为那一行由另一棵 React 树渲染,两棵树的提交顺序没有约定。按钮本身是一个 React portal,因此住在对话流 DOM 里的同时,仍保留 React 的生命周期、气泡提示与事件处理。
如何读出提示词与切点
两个事实都来自会话绑定自身的事件窗口(SessionBinding.eventSource)——即 Chat 视图组装对话所用的同一个连续、经会话授权的数据源。因此撤回的文本是发送时的原文,而不是它的展示投影。
on(plan)
prompt = 最新的 user/message,且 source.kind 为 "user"、surfaceOp 为 append
boundary = 把该 prompt 放入 Inbox 的那条 splice 事件之前的那一个事件
(找不到时回退到所属的 turn/start) if boundary < 0
boundary = none # 该提示词是这个会话的第一个事件
切点不是 seq - 1。 提示词是经由 Inbox 送达 Agent 的:输入框把它 splice 进去,而「认领」它的移除事件在更后面。若切在 promptSeq - 1,前缀里折叠后的 Inbox 仍会把它当作待处理工作——子会话会把它当成排队消息带着,恢复后的 Agent 甚至可能再跑一次。切在那条 splice 之前,才是让这条提示词彻底消失所需要排除的最后一个事件。
source.kind === "user" 同时定义了「最新提示词」是你的最新提示词:宿主也会为工作区说明、运行时上下文、审批与 Inbox 通知写入 user/message 事件,而它们都不是用户可以撤回的东西。
会还原什么,不会还原什么
| ✅ 提示词文本 | 与发送时完全一致,包括 /命令 与 @引用 的发送形态 |
| ❌ 附件 | 提示词上的图片或文件不会被重新挂载;文本会还原,文件需要重新选择 |
| ❌ 更早的回合 | 完全不动——撤回移动的是对话的末尾,而不是开头 |
撤回文本只会写入空的输入框。若在交接途中你已经开始输入,以你的输入为准,插件会提示「撤回的提示词无法放回输入框」,而不是把它覆盖掉。
当没有可回退的位置时
如果你要撤回的提示词恰好是该会话的第一个事件,就不存在可 fork 的前缀。此时撤回会在同一工作目录下用一个全新的空白会话继续对话——效果相同,只是离原会话又远了一步——而不是拒绝这次操作。
文件结构
src/
├── index.ts # 宿主半边:Loader 行的空实现入口 ├── version.ts # 本包对外汇报的唯一版本串 └── client/ ├── index.tsx # 注册:词典、样式、控制器条目 ├── window.ts # 提示词与切点规则(纯函数) ├── recall.ts # 撤回动作,针对各 port 表达(纯函数) ├── RecallAction.tsx # 控制器组件:portal 按钮 + 草稿注入 ├── anchor.ts # 按钮所依赖的 DOM 约定 ├── staging.ts # 撤回文本在两个会话之间的短暂停留 ├── locales.ts # en / zh 词典 ├── styles.ts # 兜底的动作按钮样式 └── primitives.d.ts # 本插件用到的那两个引导期静态模块成员 test/ # 切点规则、动作顺序、DOM 定位、清单一致性 tools/ ├── e2e-recall.mjs # 通过 CDP 驱动真实 Chromium 走完整套动作 └── seed-dev-home.mjs # 用一条真实会话种入隔离的开发 profile
window.ts 与 recall.ts 是纯函数,承载全部值得推敲的规则;组件只负责把它们接到一行 DOM 与一个输入框上。
安装
桌面 profile 由 Electron 应用持有,请通过 设置 → 插件(或 plugin_manager 工具)安装,路径为:
dsh-prompt-recall/dist/dsh-prompt-recall-0.1.2.tgz
scripts/install.sh # 打包并打印上面的路径 scripts/install.sh --profile tui # 打包并安装到 CLI 管理的 profile
然后重启应用:在运行中的 profile 里新增的 bundle,在该进程内要等到下次启动才会被导入。
开发
pnpm install
pnpm check # 两端类型检查 · 构建 bundle · 跑测试
如果想在不影响桌面应用所用 profile 的前提下实测:
scripts/dev-profile.sh boot 19498 # 在 .dev-home/ 下建立隔离的 DSH home
node tools/seed-dev-home.mjs \
~/.dsh/sessions/<store>/<session> /path/to/workspace # 需要先停掉宿主 scripts/dev-profile.sh boot 19498 # 用种入的样例重启
node tools/e2e-recall.mjs "<打印出的 url>" "<会话标题>" "<提示词前缀>"
scripts/dev-profile.sh remove
端到端驱动会在无头 Chromium 中断言整套动作:按钮出现在最新提示词的自带动作行内、带有自带的 action class、点击后会话在新会话中继续、被撤回的提示词离开对话流、其文本回到输入框,并且被退休的会话确实进入了宿主的持久归档集合(直接读开发 home 的注册表——这是注册表写入,不是渲染结果)。任何页面异常或 console.error 都会让本次运行失败,因此会抛错的客户端插件无法蒙混过关。
样例会话处于空闲状态(隔离的开发 home 没有模型凭据,无法真正起一轮对话),因此还有一条路径由测试而非浏览器运行覆盖:Agent 正在执行时撤回——「先停止」以及「停止失败不阻塞回退」由 test/recall.spec.ts 固定。
已知限制
- 撤回不等于撤销模型的工作。 已经跑过工具的回合,其副作用仍留在原地;回退移除的是对话里的这条提示词,而不是文件系统在这期间发生的变化。
- 子会话是真实会话。 它会出现在侧边栏并计入会话列表,与分支完全一样。
- 被退休的会话是归档而非删除——它留在磁盘上,只是离开默认侧边栏列表,取消归档即可回来。若你更希望保留撤回前的会话,动作结束后取消归档即可;DSH 里没有「删除会话」可以替代。
- 定位约定是 DSH 的 DOM。 若未来 Harness 重命名 data-chat-flow-kind、data-clock 或动作按钮的 class,按钮会消失(软失败——不崩溃、不破坏那一行)。这三个选择器集中声明在 anchor.ts,并配有测试。
- 附件不会还原——见上表。
参与贡献
欢迎提 issue 与 pull request —— bug 表单会问到「断在哪一步」,通常已足够复现。命令与每个测试文件固定了什么,见 CONTRIBUTING.md;安全漏洞请走 SECURITY.md,不要开公开 issue。本项目遵循贡献者公约。
如果这个按钮替你省下重打一条提示词,点一颗 ⭐ 能让更多 DSH 用户找到它。
许可
MIT — 见 LICENSE。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
icrefin/dsh-prompt-recall
一键停答并回退会话,把上条提示词放回输入框
相关插件 · 对话 / 记忆
上下文中枢oceanbase/powercontext
上下文跟着工作走 —— 跨会话、跨智能体、跨人。
★ 1,462已汉化DSH
73
智能体记忆库plastic-labs/honcho
Honcho 是记忆基础设施,用来构建有状态的智能体。这些智能体能理解不断变化的人、智能体、群组、项目和想法。
★ 7,848已汉化DSH
71.7
长程智能体控制面loopx-project/loopx
给 Agent 一个目标,让工作持续向前。
★ 6,358已汉化DSH
71.3
智能体上下文数据库volcengine/OpenViking
给 AI 智能体用的上下文数据库
★ 41,246已汉化DSH
71.3
长效机器人团队Fei2411/DS-Bot
DS Bot 是一个基于 DeepSeek Harness简称 dsh的 bot 插件,插件将 dsh 改造为 bot…
★ 4,717已汉化DSH
71.1
可携带记忆层EverMind-AI/EverOS
为什么选择 EverOS
★ 13,711已汉化DSH
71.1