Skip to content
dsh.fish
Bundle

dsh-smooth-scroll

DSH 平滑滚底插件:会话装载与“回到最新”瞬时钉底,流式内容以恒速平滑跟随(缓启动/软尾);无 transform、不扰动输入栏等 UI、不干扰 DSH 自身跟随状态机,prefers-reduced-motion 自动回退官方行为。适配 dsh-v0.1.2-alpha.1 ~ rc.1。

Source
VinciBeans
License
MIT
Updated
Updated 6 days ago

Readme

<div align="center">

# dsh-smooth-scroll

**让 DSH 会话滚底从瞬时跳变变成恒速平滑跟随**

装上后,流式内容增长时消息列平滑跟随到底部,回到最新仍保持瞬时。

<p align="center">
  <a href="https://www.npmjs.com/package/dsh-smooth-scroll">
    <img src="https://img.shields.io/npm/v/dsh-smooth-scroll/alpha?style=flat&colorA=000000&colorB=000000" />
  </a>
  <a href="https://github.com/VinciBeans/dsh-smooth-plugin/blob/main/LICENSE">
    <img src="https://img.shields.io/github/license/VinciBeans/dsh-smooth-plugin?style=flat&colorA=000000&colorB=000000" />
  </a>
</p>

</div>

## Install

需要已安装 DSH,并至少成功启动过一次 Web GUI。从 npm 安装(按 dist-tag 选择):

1. **npm `latest`**(0.1.1-rc.2)— 兼容 dsh v0.1.1-rc.2(旧 client-runtime 代):
   ```sh
   dsh plugin --profile web add dsh-smooth-scroll
   ```
2. **npm `next`**(0.1.2-rc.1)— 兼容 dsh v0.1.2-alpha.1 ~ rc.1:
   ```sh
   dsh plugin --profile web add dsh-smooth-scroll@next
   ```
3. **npm `alpha`**(0.1.2-alpha.5)— 兼容 dsh v0.1.2-alpha.1 ~ rc.1(与 `next` 同一契约代):
   ```sh
   dsh plugin --profile web add dsh-smooth-scroll@alpha
   ```

源码安装(GitHub Release `v0.1.2-rc.1` 即当前源码版):`dsh plugin --profile web add .`。

## Quickstart

```sh
dsh plugin --profile web add dsh-smooth-scroll@alpha
dsh --profile web --dump-config          # 看到 dsh-smooth-scroll 层即安装成功
# 重启 dsh web,打开会话,流式内容平滑滚到底部
```

## 滚动行为

直接在原生 `scrollTop` 上做有节奏的平滑滚动,配合合成 getter:平滑期间 `scrollTop` 读到目标值,DSH 自身状态机看不到中间位置,不误判脱钩、不重复钉底。

- **速度剖面:** 起步 0 到 0.9px/ms 用 240ms 缓升,巡航恒速 0.9px/ms,收尾 220ms 软着陆。
- **用户滚动接管:** 真实位置连续偏离动画写入 ≥2 帧才停动画,DSH 正常脱钩,回到最新按钮照常;单帧偏差(浏览器滚动锚定等一次性非用户位移)自动重基后继续钉底跟随——发送消息等操作引发的非用户位移不会导致误判脱钩或停在信息处;内容收窄导致的夹紧则在 2 帧内停止于新底部(同样不掉队)。与之对称,孤立的一次性小幅定位(如滚动条点一格)也会被当作非用户位移吸收、随后被跟随回底部;只有持续 ≥2 帧的偏离才视为用户接管。另:主机内(输入栏除外)的指针按下立即停动画并让 getter 回落真实值——turn 导轨跳转(`landOnRow` 的 `el.scrollTop += flowTop - 24` 复合读改写)由此读到真实位置,落点不被合成目标偏移(真实宿主 e2e 实测:流式中点击「跳转到第 N 轮」后漂移 0px)。
- **同目标兜底:** DSH 每滚动事件重跑 toBottom 而目标不变时忽略,动画不被逐帧重启。
- **减少动效:** prefers-reduced-motion 时完全回退官方瞬时行为。
- **无 transform:** 不应用任何 transform,输入栏 overlay/sticky 永不受扰。

## 参数

| 常量 | 默认 | 含义 |
| --- | --- | --- |
| VEL | 0.9 | 巡航速度(px/ms) |
| RAMP_MS | 240 | 起步缓加速时长 |
| QUIET_MS | 240 | 判定停止增长的静默窗口 |
| TAIL_PX | 120 | 进入软尾的剩余距离阈值 |
| TAIL_MS | 220 | 软尾缓动时长 |
| DIVERGE_STOP_FRAMES | 2 | 真实位置连续偏离动画写入的帧数阈值(≥2 帧判定读者接管) |

改参数:编辑 `src/client.js` 顶部常量区,`pnpm run build` 后重启 dsh web。

## 兼容性

- **dsh v0.1.2-alpha.1 ~ rc.1(支持):** 插件的唯一 DOM 锚点 `[data-conversation-scroll]`(会话滚动容器,ConversationRoot 的 scrollBody)与宿主跟随状态机(`observedTopRef` / `movedByReader` / ResizeObserver follow、`el.scrollTop` 读写面)在 `dsh-v0.1.2-alpha.1` ~ `dsh-v0.1.2-alpha.5` 五个 tag 上一致;`dsh-v0.1.2-rc.1` 相对 alpha.5 的整仓差异仅全仓包 `package.json` 版本号变更(非 `package.json` 文件零变化、非版本行零变化),`[data-conversation-scroll]` / `[data-composer-seat]` 锚点、`el.scrollTop = el.scrollHeight` 钉底写与跟随状态机均在 rc.1 tag 上复核,与 alpha.5 逐字一致;turn 导轨跳转 `landOnRow` 仍为 `el.scrollTop += flowTop - 24` 复合读改写,pointerdown 接管先停动画、复合写读到真实位置。alpha.4 把宿主滚动几何采样改为每 500ms 一次并以 `scrollend` 提前采样(`ChatView` 的 `SCROLL_SAMPLE_INTERVAL_MS`);真实宿主行为 e2e(见验证)确认该节奏下追击无停顿(流式最大离底 0px、追击停顿 0ms)、滚轮接管后漂移 0px 且宿主正常脱钩。
- **0.1.1-rc.2 及更早(不支持):** 该代使用 `@deepseek-ai/dsh-client-runtime`,滚动宿主结构不同,不兼容。
- 验证:`pnpm test`(契约冒烟,bundle 自包含)+ `node test/scroll-follow.test.mjs`(15 个 e2e 场景,含「追击中点击导轨」回归点;需 Playwright 与 Chromium)+ `node test/alpha4-realhost-e2e.mjs <token>`(真实 `dsh web` 0.1.2-alpha.4 + 真 Chromium:流式追击、滚轮接管、导轨跳转、reduced-motion、控制台错误;token 取自 `dsh web` 启动输出)。

## License

MIT

Install

dsh plugin --profile web add github:VinciBeans/dsh-smooth-plugin#70d3fa36272c2ce0d5b7183e36c2f3bf191a7bb9

Profile: web

  • This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
Source