Skip to content
dsh.fish
Bundle

dsh-suggest-actions

在每条回复下方给出可点的下一步建议,点一下就作为你的消息发出去。Clickable next-step suggestions under every reply; one click sends that sentence as your message.

Source
hiJoeLee
License
MIT
Updated
Updated 24 days ago

Readme

# dsh-suggest-actions(建议按钮)

<img src="assets/icon.svg" width="96" alt="图标">

给 DeepSeek Harness 的每条回复末尾加一排**可点的下一步建议**。点一下,那句话就直接作为你的消息发出去——不用自己打。

它解决的是"我读完了,接下来想让它干 A 还是 B"这件事:与其自己组织语言,不如直接点。

## 和"输入框补全"不是一回事

生态里已经有几个"下一句建议"插件(`dsh-suggest-prompt`、`dsh-prompt-for-me`、`dsh-suggest-ghost`、`dsh-input-assist`),它们都是**输入框里的 ghost text**:靠**另跑一次模型调用**去猜你要说什么,给一条,按 Tab 采纳,**然后还要自己按回车**。

这个插件换了个思路:

|  | 输入框补全类 | 本插件 |
|---|---|---|
| 位置 | 输入框内 | **回复下方**(轮次尾部) |
| 条数 | 1 条 | **默认 3 条**(最多 5 条,多的收起来) |
| 内容来源 | 插件猜你想说什么 | **模型按上下文主动给**——"重启 DSH 让按钮生效"这种具体动作,补全类猜不出来 |
| 额外开销 | 要多跑一次模型调用(另起一次请求去猜) | **不额外调用**——建议由主模型收尾时顺手给出,这一轮正常结束 |
| 采纳 | Tab,再自己按回车 | **点一下就发出** |
| 不想要它 | 得忽略或按 Esc | 不看就行,它不占输入框 |

## 安装

```bash
dsh plugin --profile desktop add dsh-suggest-actions
```

装完**重启 DSH 并刷新一次页面**——host 只在启动时读插件清单,客户端代码也要重新加载。这两步缺一不可(踩过)。

## 它怎么工作

- **Host 侧**:注册一个 `suggest_actions` 工具。它**不阻塞、立即返回**——模型在收尾时调用一次,参数里带 2-3 条建议,这一轮正常结束。
- **客户端侧**画两处:
  - `tool.call.toolview` 挂一个**静默采集器**:渲染时把建议记进插件内存,不画任何东西;
  - `conversation.chat.turnTail`(轮次尾部)挂**展示器**:读内存、画按钮。
- **为什么放轮次尾部**:DSH 的"过程组折叠"会把思考与工具调用收成一行,画在工具卡片里的东西默认看不见;轮次尾部在折叠范围之外,所以过程收起来按钮照样露着(这条是读了官方源码才定的,见下)。
- **点按钮**走的是 `conversation.input.shell(sessionId).actions`:写进会话输入框 → 提交。和用户自己敲键盘回车是同一条路。

## 建议的「立场」和「推荐」

这一轮加了两样东西:一个管"几条建议别是同一个角度",一个管"哪条最该先做"。

**立场**:每条建议背后都要标一个立场,五档——先验证(更小的一步,先确认再往下)、常规推进(顺这条路的正常下一步)、更用力(还是这条路,但更快、更敢冒险)、换一条路(当前做法不走了)、可以不做(这事本身不必做)。同一轮里一个立场只能出现一次,重复的直接丢掉,空出的位置留给别的角度——所以"三条其实是一回事"这种列表到不了你面前。最多三条;只想到两条时就给两条,不硬凑。

立场**不会显示在按钮上**,它是给模型定的格式约束。为什么不在提示里嘱咐一句"请给不同角度的建议"就算了:嘱咐是可以不听的,格式约束绕不过去。

**推荐**:哪条最该先做,由模型单独标出来,跟它排在第几位无关——标了的那条会被自动提到第一位,旁边挂一个「推荐」小标签。它的底色和别的按钮一样,只有鼠标停在上面时才变深一点。反过来,「可以不做」那条不管给在第几位,都会被压到最后;其余几条保持模型给的顺序。几条确实差不多时,也可以一个都不标。

**把鼠标停在按钮上**(键盘操作是聚焦到它),按钮会就地展开,显示点下去真正会发出去的那句话;移开就收回去。这一步是为了让"看到的"和"发出去的"对得上——按钮上是摘要,真正发出去的那句常常更长。这段全文**长在按钮外面**,所以展开之后点它不会误发,想选中文字复制随便点。

**几条按钮一样宽**:宽度按最长的那条标签定,不按各自内容伸缩——箭头排成一列好扫读,指令写得长也不会把按钮撑开。

**多于三条时**:默认只露前三条,其余收在下面一行"还有 N 条"里,点开就地铺开、展开后照样能点。展开状态不记忆——翻回去再回来,它又是收起的。

界面上的几个字(「推荐」「还有 N 条」「收起」)跟着界面语言走:中文界面显示中文,其它语言显示英文。

不带立场的建议照常显示(向后兼容)。

## 已知限制

- 需要 DSH **0.1.7** 这一线(用到了 `conversation.chat.turnTail`、`conversation.input.shell`、`tool.call.toolview`)。
- 按钮文字由模型给:太长会显得笨重,建议每条不超过 20 字。
- 点击**直接发送**,没有二次确认——这是设计意图,不是疏忽。
- 一次点击有约 0.9 秒的防连点。

## 开发者备注

实现细节、踩过的坑、以及"为什么不用另外三个位置"都在仓库注释里;`conversation.chat.turnTail` 这个落点是从官方 72 个 slot 扩展点里筛出来的。

## 许可

MIT

## 配置

改单轮上限,**别写在 profile 的 `cordis.patch.yml` 里**——那份 patch 先于插件的插入行应用,同 id 的行这时还不存在,会被静默忽略(2026-09-26 在另一个插件上实测过)。正确的位置是插件自己的 bundle patch:

```yaml
- insert:
    - id: suggest-actions
      name: 'dsh-suggest-actions'
      config:
        maxActions: 2     # 单轮最多给几条(1–6),超出的丢掉;界面就按这个数显示
```

不写 `config` 时用默认值 3。改完要重启一次 DSH——配置在启动时读。

## 开发

```bash
pnpm test      # 21 个单测,零外部依赖(node:test)
```

代码分工:

- `lib/normalize.js` —— 清洗规则全在这里(空白、去重、立场、排序、上限),纯函数、可单测
- `lib/index.js` —— 注册工具、读配置;清洗后的名单随工具结果一起交给界面
- `lib/client.js` —— 浏览器侧。只管两件事:把 host 交回来的名单记下来、画出来。规则一条都不重复(客户端 bundle 拿不到插件配置,上限只能由 host 给)

边界行为都有测试锁定:非数组、坏 JSON、空白 label、重复 label、重复立场、非法立场、超限条数、`maxActions` 越界。UI 侧另有:按钮最多 520px 宽、文案最多两行(悬停显示全文)、点击后 0.9 秒防连点、标了"推荐"的那条会高亮。历史轮次偶尔会跟着多显示一份最新建议——这是有意的取舍:宁可偶发重复,也不能让最新一轮没有按钮。

Install

dsh plugin --profile web add github:hiJoeLee/dsh-suggest-actions

Profile: web

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source