DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

Heeweelee /

Heeweelee/dsh-prompt-suggestions

Verified

DSH 输入建议插件:↑/↓ 回滚本会话发过的全部提问,Ctrl+↑ 搜索,灰色幽灵文字预测下一句,→ 采纳,绝不自动发送。Prompt Suggestions for DeepSeek Harness.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@2663f05a

输入建议 / Prompt Suggestions

包名 dsh-composer-suggestions(GitHub 仓库 Heeweelee/dsh-prompt-suggestions)· DSH 插件 · MIT · v1.1.0

English summary. A DSH composer plugin. ↑ / ↓ recall every prompt you have sent in the current session — including ones you accepted from a prediction, not only what you typed — Ctrl+↑ opens a searchable history picker, grey ghost text previews your next message, and → accepts it as plain, editable text. It never auto-sends: every key only edits the draft, and sending still takes your own Enter.

给 DSH 输入框加上「历史回滚 + 下一句预测」,像 Claude Desktop 那样不用重复打字。

DSH 的输入框只有当前这一句;这个插件把两件事补上:往回翻——把你在本会话里发过的提问一键翻回来重新编辑;往前猜——根据刚才的对话,把你的下一句话以灰色幽灵文字写在输入框里,按一下 → 就能用。

功能一览

你能得到什么 怎么用
不再重打旧提问:本会话发过的每一条都能翻回来,长会话也能一直翻到第一句 空输入框按 ↑,按一次退一条
翻过头了能回来,草稿不会丢 ↓ 逐条前进;越过最新一条时恢复你原本没发出去的草稿
历史太多时直接搜:面板里按关键词过滤,独立输入框,不打断正文 Ctrl+↑ 打开面板,输入关键词,↑↓ 选择,Enter 填入
下一句不用从头想:模型读最近几轮对话,给出你大概率要发的那句 空闲时自动出现在输入框里,灰色
一键采纳,仍可编辑:采纳后就是普通文本,改完再发 → 采纳
绝不自动发送:任何按键都只改草稿,发不发、什么时候发由你决定 —
回滚覆盖整场会话:手打、粘贴、→ 采纳预测后发送、排队插话发送,全都算「你发过的」 判据是会话记录里的 source.kind = user,运行时注入(时间上下文、技能目录等)自动排除
不劫持键盘:多行编辑、光标在中间、输入法组字时方向键照常工作 只在草稿为空 / 单行草稿 / 光标停在开头时接管 ↑
按键 行为
↑ 把本会话上一条用户消息回填到输入框(再按继续往前)
↓ 回到下一条;越过最新一条时恢复你未发送的草稿
Ctrl+↑ 打开本会话历史提问面板:可输入关键词筛选、↑↓ 选择、Enter 填入、Esc 关闭
→ 采纳灰色幽灵文字,变成普通可编辑文本

永远不会自动发送:以上按键只改草稿,发送仍需你自己按 Enter。

安装

推荐从 GitHub 直接装(不需要 registry):

dsh plugin --profile desktop add github:Heeweelee/dsh-prompt-suggestions

其他方式详见 INSTALL.md:

# A. 从 npm 装
plugin_manager install_bundle  dsh-composer-suggestions

# B. 用 Releases 里的 tarball
#    在 profile 的 package.json 里加  "dsh-composer-suggestions": "file:D:/path/dsh-composer-suggestions-1.1.0.tgz"

# C. 本地开发目录
plugin_manager install_bundle  D:\Ai_Tool\dsh_tool\packages\prompt-suggestions

安装后在「插件 → 已安装插件」里可开关。

两半结构

文件 平台 作用
index.js Host 在 DSH Web 服务器上注册 POST /prompt-suggestions/suggest(预测下一条)与 POST /prompt-suggestions/history(本会话全部用户提问)
client.js Web Client 注册 conversation.input.overlay 槽位:拦截方向键、回溯历史、绘制幽灵文字

历史回填的实现

数据源有两层,Host 优先:

  1. Host 权威列表(POST /prompt-suggestions/history → {prompts:[{text,time}]}):直接读该 Session 的完整事件日志,取所有 user/message 且 source.kind === 'user' 的消息,按时间正序返回最近 200 条,每条保留完整原文(含换行,上限 4000 字符)。这样不受聊天窗口分页限制,也不受 compaction 把早期轮次从 surface 剪掉的影响 —— 长会话里 ↑ 能一直翻到第一句。
  2. 本地窗口(useChat 的 order + nodes)作为兜底:Host 路由不可达时仍然可用;并把 Host 列表之后新产生、尚未被拉到的那条消息补在末尾。

source.kind 是区分「人发的」与「机器塞的」的唯一依据:运行时注入(时间上下文、技能目录、压缩存档、子任务通知)也是 user 角色消息,必须排除。凡是成功提交的提问 —— 手打、粘贴、从插件预测 → 采纳后发送、排队/插话发送 —— 在会话里都是同一条 user/message(kind: "user"),因此全部覆盖。

回填走 inputActions.setDraft(text),不做提交。

↑ 的拦截条件:草稿为空,或单行草稿(其内容会被保存,↓ 可恢复),或多行草稿但光标停在最开头 —— 因此多行编辑时光标移动不受影响。

历史面板(Ctrl+↑)

不需要 DOM 剪贴或额外数据源:直接复用同一份 chat 投影,按时间正序渲染,打开时选中最新一条并滚动到底部。面板是 position: fixed 的浮层,锚在输入卡片正上方(left/width 取自卡片矩形,max-height 取卡片上方空间,避免压住输入框)。

面板打开时键盘交给面板自己的 <input>:筛选框是真实输入框,因此 Enter / ↑↓ / Esc 都在面板内部消费,不与宿主输入框抢事件;卡片上的捕获监听同时被短路(面板渲染在槽位内,事件仍会冒泡到卡片)。任何外部 mousedown 关闭面板并把焦点交还编辑器。填入走 inputActions.setDraft,同样不提交。

幽灵文字的两种绘制方式

都只在 Session 空闲(未在生成)且草稿为空白 / 是预测前缀时显示:

  1. 草稿为空 — 在 conversation.input.overlay 里绝对定位一层灰色文本,位置对齐宿主占位符所在的盒子,字体行高从编辑器 getComputedStyle 复制,底色用 --dsw-specific-input-major 盖住占位符。
  2. 草稿是预测的前缀 — 写入宿主自带的行内提示通道:把 remainder 写进 [data-composer-card] 的 --dsh-composer-hint 变量,宿主的 CSS p:last-child::after { content: var(--dsh-composer-hint) } 会把半透明灰色文字接在正文后面,因此换行与字距与真实输入完全一致;卸载时移除该变量。

→ 采纳:草稿为空时 setDraft(prediction),草稿是前缀时 insertText(remainder, caretSpan)(走宿主自己的撤销栈)。

预测请求

POST /prompt-suggestions/suggest
x-prompt-suggestions: 1
{"sessionId": "session-..."}   →   {"suggestion": "...", "cached": false}
  • 上下文取自 session.deriveMessages()(与模型看到的历史一致),取最后 10 条,单条截断 700 字符,总长 4000 字符,以 JSON 框架嵌入提示词。
  • 模型路由取 ctx.agentDefaultModel.currentSelection(),reasoningEffort 强制降到该路由最省的一档(本机为 off),maxTokens: 700。
  • 5 分钟按 sessionId + 消息数 缓存,避免刷新页面重复计费。
  • 传输层用 document.baseURI 解析 URL,不假设 http(s):桌面版把界面跑在自定义协议 dsh-app://app/ 上(渲染进程带 --standard-schemes=dsh-app --fetch-schemes=dsh-app),主进程把该 scheme 下所有非静态资源路径连同 Host Cookie 转发给真正的 Host 服务。用 location.origin 判断 scheme 会拿到 "null",桌面版就永远发不出请求。
  • 防空话重试:如果模型只回了「继续 / 好的 / ok / 继续吧」之类的空话,会带上更严格的提示词再要一次具体建议;两次都是空话则不显示幽灵文字(宁可不猜,也不糊你一脸「继续」)。
  • 失败重试:请求失败(Host 路由尚未注册、刷新撞上启动)按 0.6s / 1.2s / 2.4s 退避重试,四次都失败才降级到本地规则;降级后窗口重新获得焦点或可见性恢复时会再试一次——一次启动竞态不会锁死整轮。
  • 调试:加 x-prompt-suggestions-debug: 1 返回 debug 字段(阶段、attempts、filler、原始输出、finish 原因、实际路由)。调试请求绕过缓存读(但仍写回),便于不换会话就拿到一次真实结果。

预测来源是可见的

角标同时是溯源标记:

角标 含义
→ 采纳 模型预测(悬停显示「模型预测 · 1832ms」)
→ 采纳 · 本地 服务端没响应,用的是本地规则
预测不可用 服务端没响应且本地规则也给不出有意义的建议(此时不显示幽灵文字,悬停会显示失败原因,如 HTTP 404 / 网络错误 …)

DevTools Console 每轮也会有一行 [prompt-suggestions] model 1832ms <文本>,或 local fallback <ms> 加上失败原因和实际请求的 URL。

已验证(真实浏览器 + 真实模型)

在 http://127.0.0.1:54796 上用独立 Chromium 通过 CDP 实测(打开真实历史会话「可拆分相机3D模型网页」):

  • 模型链路:幽灵文字 给每个零件加上编号,展开时按装配顺序逐个演示拆解动画,与 POST /prompt-suggestions/suggest 的响应体逐字一致,cached:false,角标 → 采纳、title="模型预测 · 2267ms"、data-ca-source="model",Console 一行 [prompt-suggestions] model 2267ms …
  • 启动竞态恢复:加载时把该路由阻断 2.5s(blocked: 2,前两次请求被拦),解除后第三次请求成功,最终仍是 model + 幽灵文字,没有降级
  • 服务端一直不可达(阻断且不放行):角标 预测不可用、data-ca-source="local",不出幽灵文字
  • 防空话重试:把首次提示词临时改成「只回答继续」,实测 attempts: 2、filler: false,最终给出的仍是具体建议
  • 空会话(新会话首页):路由返回空建议,不出幽灵文字、不显示任何角标
  • ↑ 一次即回填上一条提问;↓ 越过最新一条恢复原草稿,幽灵文字随之恢复
  • 采纳:→ 后草稿内容与预测文本逐字相同,全程没有任何消息被提交
  • 前缀:先输入预测的前 3 个字,宿主的行内 ::after 显示剩余部分,→ 后草稿等于完整预测
  • Ctrl+↑ 面板:2/2 条、选中最新一条、筛选「继续」后 1/2、Enter 填入后草稿等于该条、Esc 关闭且草稿不变、筛选输入不影响草稿
  • 全量回滚实测(1.1.0):在当前这个长会话(547 条消息、已被压缩过、聊天窗口只加载最后一页)里,Ctrl+↑ 面板显示 9/9,连按 9 次 ↑ 依次回填到 1/9,第一条是完整的多行原文(187 字符,未截断成第一行);POST /prompt-suggestions/history 返回同样的 9 条。同一版本在 DFM 会话上 16/16,预测链路同时复测为 model + → 采纳(模型预测 · 20ms),说明两条功能没有互相影响。
  • 无页面异常;插件页显示「输入建议」标题、中文描述与自绘图标
  • 打包产物实测(1.0.0 tarball):plugin_manager install_bundle file:…/dsh-prompt-suggestions-1.0.0.tgz → pnpm +1 package、bundle 热应用;POST /prompt-suggestions/suggest 返回 200 且 cached:false;浏览器里幽灵文字与角标正常。另在干净目录 npm install <tgz> 后 import('dsh-prompt-suggestions') 得到 inject = ["sessions","llm","agentDefaultModel","webServer"] 与 apply 函数,说明包结构(exports / dsh.bundle.patch / files)正确。
  • 桌面壳(dsh-app://app/)走的转发链路由主进程实现:protocol.handle 把非静态路径连同 Host Cookie 转发给本地服务,只接受 Origin 为空或 dsh-app://app 的请求——这也是之前桌面版拿不到预测的原因(旧版用 location.origin 判断,dsh-app 的 origin 是 "null")。

已知限制

  • 预测只在 Session 空闲时请求;正在生成时没有幽灵文字(避免打断)。
  • 模型如果两次都只给空话,就不显示幽灵文字——「有时没预测」是设计上可接受的失败方式。
  • 空会话(还没有任何消息)不会预测:没有上下文可依据。
  • 界面语言在激活时解析:优先取 Client locale 服务,服务尚未注册时退回 navigator.languages,最后才是 <html lang>(后者在启动早期仍是文档的静态值,不能作为首选)。
  • 面板不做时间分组、不做跨会话搜索;只列当前会话的提问。
  • 幽灵文字的角标位置按编辑器矩形计算,若宿主改动输入框内边距,需要重新对齐。
  • 历史来自 Session 的完整事件日志(不受分页与 compaction 影响),但 Host 侧只保留最近 200 条、每条 4000 字符;更早的提问仍在会话里,只是不再进入回滚列表。
  • Host 路由不可达时会自动降级为「当前已加载窗口」,此时长会话里能翻到的深度取决于聊天视图加载了多少。
  • /prompt-suggestions/suggest 与 /prompt-suggestions/history 走 DSH Web 服务器,未经过浏览器 Cookie 认证,仅靠自定义请求头 + 监听回环地址保护;跨站请求无法带上该请求头。
  • 面板用 position: fixed 定位;若宿主将来给输入卡片的祖先加上 transform,浮层会改为相对该祖先定位,需要改用 portal。
—/ 5

No ratings yet

Verified DSH bundle

Commit 2663f05a8a7b

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout