shaoeric/dsh-suggest

dsh 建议

项目介绍Project Overview

dsh-suggest 是 DeepSeek Harness 插件,在每轮 Agent 回答下方生成 3 个可点击、可编辑的后续问题。它基于最近 3 条用户消息及助手回复,优先用同 provider 的 flash 模型并关闭思考来快速生成,点击可直接发送,悬停可编辑后再发,带缓存、骨架占位与失败重试。适合想延续对话、减少手动提问时使用。注意推荐仅显示在最新一轮,动态形态重启后失效。

dsh-suggest is a DeepSeek Harness plugin that renders three clickable, editable follow-up questions under each agent answer. It uses the latest three user messages and intervening replies, preferring the provider’s flash model with thinking disabled for fast generation; clicks submit directly, while hover editing fills the draft first. Use it to continue conversations with less typing. Suggestions appear only on the latest turn, and the dynamic form is lost on restart.

或使用命令行安装(适合开发者)Or use CLI install (for developers)

命令行安装CLI Install

dsh plugin --profile web add github:shaoeric/dsh-suggest

shaoeric/dsh-suggest 加入你的 DSH 配置(web profile)即可启用。

READMEREADME

dsh-suggest

DeepSeek Harness 插件(动态 + 正式双形态):Agent 每轮回答完成后,在答案下方生成 3 个可点击、可编辑的推荐后续问题。

A DeepSeek Harness (DSH) plugin (dynamic and formal forms) that renders three clickable, editable follow-up question suggestions under every agent answer.

🏠 仓库:https://github.com/shaoeric/dsh-suggest

English | 中文


✨ 功能特性 / Features

  • 自动生成:Agent 回答完成后,基于最近 3 条用户消息(含其间助手回复)自动生成 3 个推荐问题,以用户意图为锚点、紧扣最新进展;
  • 一键直达:点击推荐项 → 内容直接提交给 Agent,自动开启新一轮回答;
  • 先编辑再发送:悬停推荐项会浮现 ✏️ 编辑按钮,点击后内容填入输入框,编辑满意后自行发送;
  • flash 模型 + 关闭思考:优先使用同 provider 的 flash 模型,请求携带 reasoningEffort: 'off'(DeepSeek 适配器映射为 thinking: disabled),生成又快又省;找不到 flash 或适配器不支持时自动回退;失败则回退会话原模型;
  • 稳定兜底:按会话+轮次缓存、生成中显示骨架占位、失败显示具体原因并可一键重试;
  • 只显示最新一轮:推荐项只在最新一轮回答下方显示,发起新一轮对话后自动隐藏,避免误触;同时补渲染 📎 产物行不丢失;
  • 主题自适应:全部配色使用 --dsw-alias-* 主题变量,自动适配明暗模式。

🧱 工作原理 / How It Works

半区 平台 职责
host.js Host(Node) 通过 harness.handle('recommendations') 暴露包内 RPC(正式版经 Typert Remote 暴露 suggest/recommendations);读取会话日志(≤ 收尾 seq),以最近 3 条用户消息为锚点截取上下文;优先使用同 provider 的 flash 模型(找不到则回退会话模型)调用 llm.stream 生成 3 个推荐(关闭思考模式),带缓存与并发去重
client.js Client(浏览器) 注册 conversation.chat.turnTail 链式插槽(priority: -1);渲染垂直左对齐的推荐列表;点击 → inputActions.setDraft + submit() 直发;点 ✏️ → 仅 setDraft 填入输入框
回答完成 → turn-tail 节点渲染
          → 链选举命中本插件 → 组件挂载
          → host.call('recommendations', {sessionId, turn, seq})
          → Host 截取最近 3 条用户消息上下文 → flash 模型(thinking off)生成 JSON 数组
          → 返回 3 条推荐 → 渲染为可点击列表

📁 文件结构 / Files

dsh-suggest/
├── host.js          # 动态插件 Host 半:推荐生成(RPC、会话读取、LLM 调用、缓存)
├── client.js        # 动态插件 Client 半:turnTail UI、点击直发、hover 编辑、产物行
├── lib/
│   ├── index.js     # 正式插件 Host 半(与 host.js 同逻辑;Typert Remote + strict manifest)
│   └── client.js    # 正式插件 Client 半(与 client.js 同逻辑;ModuleLoader bundle)
├── package.json     # 正式插件包清单(dsh.bundle.patch + dsh.client)
├── cordis.patch.yml # 正式插件插入 host composition 的 patch 层
├── dsh.plugin.json  # 正式插件清单
├── LICENSE          # MIT License
└── README.md

🚀 安装与使用 / Install & Run

本插件提供两种安装方式:正式插件(从仓库安装,持久化,推荐)动态插件(临时,进程重启即失效)。两套代码功能一致:lib/ 是正式插件形态,host.js / client.js 是其动态源。

方式一:正式插件(从仓库安装,持久化,推荐)

仓库根目录本身就是一个标准 Harness web 插件包(声明了 dsh.bundle.patchdsh.client)。把仓库克隆到本地后,用 dsh plugin 直接装进 web profile,跨重启常驻。

从仓库安装:

git clone https://github.com/shaoeric/dsh-suggest
cd dsh-suggest
dsh plugin --profile web add file:$(pwd)      # Linux/macOS
# Windows(PowerShell)换成仓库绝对路径,例如:
dsh plugin --profile web add file:C:/path/to/dsh-suggest

file: 后面接的是仓库根目录的绝对路径——这个仓库根目录本身就是插件包(pnpm 只打包 files 字段列出的文件)。

dsh plugin add 会代理到 profile 目录里的 pnpm,并自动把包登记进 profile 的 dependenciesdsh.profile.bundles(因为包声明了 dsh.bundle)。装完重启生效:

  1. 在运行 dsh web 的终端 Ctrl+C 停掉服务器;
  2. 重新运行 dsh web;
  3. 刷新浏览器页面。

重启后:Host 半随进程启动挂载(Typert Remote 端点 suggest/recommendations),浏览器半由 Web 服务器在 /plugins/dsh-suggest/client.js 提供给每个页面。

更新(改了 lib/ 或清单后):

⚠️ file: 依赖缓存安装时的快照,直接重跑 add 不会刷新内容;先 remove 再 add。

dsh plugin --profile web remove dsh-suggest
dsh plugin --profile web add file:/绝对路径/dsh-suggest
# 然后重启 dsh web

卸载:

dsh plugin --profile web remove dsh-suggest
# 然后重启 dsh web

正式版与动态版的实现差异:

动态版(host.js / client.js) 正式版(lib/)
包内 RPC harness.handle / host.call(动态 runner 注入) Typert Remote:suggest/recommendations 端点 + strict manifest,经 api-gateway 走 /api
服务访问 ctx.get('llm') 等(动态 sandbox 门面) 相同(正式 Cordis ctx.get 语义一致)
客户端环境 runner 闭包注入的 React / host / styles 全局 require('react') + ctx.remote.$mount + <style> DOM 注入

方式二:动态插件(临时)

需要 DSH 的 Cordis 插件能力(「创造模式」agent preset)。

  1. 在 DSH Web GUI 中用「创造模式」preset 打开一个会话;
  2. 让 Agent 安装本插件(把仓库交给 Agent),或手动操作:
    • cordis_define 创建插件:code.host 粘贴 host.js 内容,code.client 粘贴 client.js 内容;
    • cordis_run 激活返回的 pluginId / packageId;
  3. 首次运行需在 GUI 中批准插件(单勾授权当前版本,双勾授权后续更新);
  4. 之后每一轮回答结束,答案下方即出现 3 个推荐问题。

⚠️ 生命周期说明:动态插件是进程内临时定义,DSH 进程重启后即丢失,需重新 define + run。如需跨重启持久存在,用上面的方式一(正式插件)。

🧰 依赖的能力 / Dependencies

  • Host 服务:llmsessions(可选 sessionQueryagentDefaultModel 作为回退);正式版另需 typert(注册 Remote manifest)
  • Client 内置:动态版 Reacthoststyles;正式版 remote(api-gateway client)、slots(client-runtime)与 react 模块
  • 客户端插槽:conversation.chat.turnTail(由 dsh-client-ui-conversation 声明)
  • 标准 Props:sessionIdinputActionsuseSession(客户端会话标准套件)

🛠️ 常见问题 / Troubleshooting

现象 处理
显示 ⚠️ 推荐生成失败 + 原因 按提示点击重试;错误文字含 kind 与错误码,可用于进一步定位
推荐项不出现 确认插件已批准并处于 running;刷新页面后查看历史轮次
希望恢复水平布局 client.js 中推荐区容器类名从 dshrec-x42-list 改回 dshrec-x42-section,并删除 list 相关 CSS

🏷️ GitHub Topics / 仓库标签

建议在仓库 Settings → Topics 中设置:

dsh  dsh-plugin  deepseek  deepseek-harness

同时推荐补上:deepseek-apicordis(可选)。

🔍 技术参考 / Where the slot dispatch lives

conversation.chat.turnTail 是 DeepSeek Harness 内置的链式(chain)插槽,其声明与分发逻辑位于 DSH 源码(deepseek-ai/DeepSeek-Harness)的三个包中:

逻辑 源文件
插槽声明与渲染入口:turn-tail 节点注册(key: 'turn-tail',children 声明 conversation.chat.turnTail chain)并调用 renderSlotChain(..., { turn, seq, openFile }) @deepseek-ai/dsh-client-ui-conversation src/client/chat/register-node-renderers.tssrc/client/chat/TurnTailNodeView.tsx
链式选举分发:按 priority 升序遍历条目,运行 entry.select(ownerProps),首个非 null 返回值胜出并以 matched 属性挂载;全部返回 null 则走 owner fallback @deepseek-ai/dsh-client-web-react src/scoped-slots.tsx(SlotOutlet / renderOutletContentspec.kind === 'chain' 分支)
条目注册与优先级排序:SlotCore.registerrec.entriespriority 升序排序;chain 注册必须提供 select @deepseek-ai/dsh-client-ui-slots src/index.ts(SlotCore.register,约 121–123 行的 next.sort)

本插件即依赖这套机制:select 无条件认领(priority: -1,先于内置的产物行条目 x6),组件内自行补渲染产物行,因此推荐项出现在每个完成的回答下方。

📄 License

MIT © 2025 shaoeric

上一个 Prev Deepseek-Harness-plug 下一个 Next dsh-file-upload-deepseek-harness-plug-in