dsh-streamfold 0.5.7 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +73 -0
- package/README.en.md +76 -66
- package/README.md +77 -69
- package/lib/client.js +1514 -847
- package/package.json +6 -6
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
本项目按 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 的组织方式记录用户可感知的变化;版本号遵循语义化版本。
|
|
4
|
+
|
|
5
|
+
## [0.7.1] — 2026-10-04
|
|
6
|
+
|
|
7
|
+
**纯文档修正(无代码变更)**:0.7.0 的 npm 包内 README 仍是发布前的安装段——写着「0.7.0 尚未发布到 npm」,与仓库首页的最终版不一致(发布 commit `029df7e` 之后 50 秒才提交 README 终稿 `9f3206a`)。本版重新发布,让包内 README 与实际发布状态一致。
|
|
8
|
+
|
|
9
|
+
### 文档
|
|
10
|
+
|
|
11
|
+
- 包内 `README.md` / `README.en.md` 安装段为最终版:**DSH 插件面板为首选方式**(npm `latest` 即本版,含 provenance),命令行三种写法并列;移除已过期的「尚未发布到 npm」警告。
|
|
12
|
+
- 版本号引用不再硬编码具体版本,避免下次发布再次滞后。
|
|
13
|
+
- `lib/` 无任何改动(`lib/client.js` 仍为 `9404096f`)。
|
|
14
|
+
|
|
15
|
+
## [0.7.0] — 2026-10-04
|
|
16
|
+
|
|
17
|
+
0.6 → 0.7 的架构重建之后的**首个对外版本**(npm 上此前最新为 0.5.7,0.6 / 0.7 均未发布;本文描述的全部内容都是首次对外)。除架构重建外,本版还并入 2026-10-04 的审计修复批次:输入/卸载语义(P0)、折叠与导航(P1)、性能去重、诊断口径,以及用户点名的「瞬时判据改场景 + 展开也错峰」。
|
|
18
|
+
|
|
19
|
+
### 行为变化
|
|
20
|
+
|
|
21
|
+
- **展开也错峰,方向与收起相反。** 一次展开多行时**从最上面一组往下**、每 3 行一组、组间 70ms;收起仍是**从最下面一组往上**、每 3 行一组、组间 70ms。收/展共用同一节奏(`FOLD_CHUNK = 3`、`FOLD_CHUNK_MS = 70`)与同一判据。
|
|
22
|
+
- **「瞬时」判据从行数改为场景。** 本批覆盖 **≥2 个轮次**(加载、切会话、全量重排等批量场景)⇒ 瞬时;**单轮一律错峰**,哪怕 40+ 行。单轮只保留时长护栏:`ceil(行数 / 3) × 70ms > 2000ms`(即 ≥85 行)才瞬时。行折叠与行内思考摘要批同判据。
|
|
23
|
+
- **小窗触底吸附收窄到「当前活动的思考窗」。** 只有**本轮 running 的最新思考正文**跟尾/贴底;被取代、已跑完、上一轮的窗一律不再吸附,避免多个小窗争抢主容器滚动。
|
|
24
|
+
- **回到提问处(settle)更可靠。**
|
|
25
|
+
- 滑行途中出现外来写(JS 赋值 / `scrollIntoView` / 官方导航)不再把 element 目标顶成 position,继续滑到提问处;
|
|
26
|
+
- 目标行节点断开时,按「最后一条 user 消息」重试一次,而不是放弃导航停在原地;
|
|
27
|
+
- 到位后开启 **2s 有界观察窗口**(每 2 帧观察、最多纠正 4 次、两次纠正间隔 ≥100ms),纠正图片/代码块/摘要行等**迟到落版**;窗口到点或次数用尽后立即退出,零 rAF / 定时器残留。
|
|
28
|
+
- **嵌套滚动不再被误判为主容器接管。** 在思考小窗、工具正文、上下文注入正文里滚动**不再**让主容器撒手。滚到该嵌套区域的滚动边界后继续滚,才把滚动交给主容器(链式滚动);触摸、无 delta、纯横向 wheel 因方向不可知,维持早退。
|
|
29
|
+
- **不可达目标不再永久卡住。** 导航在 `navBudget(距离) + ≤1.2s` 无进展时由看门狗有界终止(清导航目标并走既有超时清理),随后该轮折叠照常发生。
|
|
30
|
+
- **Ctrl+F 搜索撒手。** 搜索期间主容器与小窗一起交出写权、不贴底;滚回窗尾或点「回到底部」恢复跟随。
|
|
31
|
+
- **会话切换复位。** 提问卡登记跨会话复位;短会话(内容不足一屏)里读者滚轮接管后仍能取回跟随。
|
|
32
|
+
- **「恢复默认」同时把官方档停到「完全展开」**,避免官方自己折叠与本插件折叠叠加成双重折叠。
|
|
33
|
+
|
|
34
|
+
### 修复
|
|
35
|
+
|
|
36
|
+
- **卸载即净。** `dispose` 现在恢复插件自身的视觉改动:清错峰定时器、还原折叠行行内 `max-height` 与 `hidden="until-found"`、摘掉小窗标记/回底按钮/chip/搜索标记/`html[data-dshsf-anim]`。热重载或真卸载后不再残留 0 高行与隐藏正文。
|
|
37
|
+
- **`dispose` 幂等 + 全局副作用所有权。** 二次调用直接返回;还原实例级 `scrollTop/scrollTo/scrollBy` 与 `Element.prototype.scrollIntoView` 前先确认 `window.__dshStreamfold` 仍属本实例,避免拆掉新实例的吸收器。
|
|
38
|
+
- **元素滑行守卫的零步停机回归。** 守卫分支放行外来写时同时作废方向速度态,修掉「外来写落在目标另一侧 ⇒ 帧循环停摆、协调被永久压住」的回归;另加导航看门狗兜底。
|
|
39
|
+
- **settle 预算与滑行距离同源。** 长滑行的协调预算改为 `max(1400ms, navBudget(剩余距离))`,折叠不再插进滑行中段。
|
|
40
|
+
- **置顶提问文案随行文本刷新。** 缓存失效并入结构观察(MutationObserver 按行定向删除)并以原文兜底比较,等长改写也会刷新,不再永久陈旧。
|
|
41
|
+
- **老轮正文变化后行判定失效。** 结构观察会把变化行上溯到所属轮,删掉文本缓存;热集从「最近 2 轮」扩到「运行中的轮 ∪ 最近 3 轮」。
|
|
42
|
+
- **设置页文案与真实默认同源。** 「跟随速度上限 / 加速度上限」的说明文字从 `DEFAULTS` 插值,修正旧的「默认 480 / 20000」。
|
|
43
|
+
- **短会话取回跟随。** 内容不足一屏(`floor === 0`)时读者滚轮接管后视为贴底并可接回,不再永久停跟。
|
|
44
|
+
|
|
45
|
+
### 性能
|
|
46
|
+
|
|
47
|
+
- **滑行帧强制布局读下降。** 独立复测(同一 34 帧 element 滑行):`strongReads` 7.76 → **4.76 /帧(−39%)**,`scrollTop` 读 12.71 → **5.59 /帧(−56%)**;到位精度不变(提问行顶 12px,无往返)。另一套装置对 29 帧滑行统计:总强排读 619 → 328(−47%),每帧 21.34 → 11.31。
|
|
48
|
+
- **一次扫描去重。** 行列表与 running 标记扫描内只查一次;卡片计数按行缓存:一次扫描 `querySelector` 153 → **130(−15%)**,`countCards` 的 think+tool 整树查询 48 → **0**,RUNNING 查询 2 → 1。
|
|
49
|
+
- **穿插正文判定去重。** 一次扫描总查询 300 → **263(−12%)**,`assistantBody` 的 `[data-turn-process-inline]` 查询 48 → **12**。
|
|
50
|
+
- **帧路径不再每窗重查回底按钮。** 复用已有登记表:60 帧窗口期该查询 60 → **0**。
|
|
51
|
+
- **观察窗口降频。** 2s 窗口内每 2 帧复算一次目标位置:窗口期 rect 读 119 → **59**;窗口仍保活 120 帧/2000ms,到期后 rAF 与定时器均为 0。
|
|
52
|
+
|
|
53
|
+
### 诊断
|
|
54
|
+
|
|
55
|
+
- `probe().mainFollow.settle = { turn, until, last }`:当前协调的轮次、预算截止与最后一次清理原因。
|
|
56
|
+
- `probe().mainFollow.abort = { count, last }`:看门狗有界终止的次数与详情(`last.why = "stuck"`,含 `armedAt / at / budgetMs / top`),可与正常的 `lastSettle.why = "timeout"` 区分。
|
|
57
|
+
- **`readCount` 口径校正。** 只统计插件主动发起的显式强排读(`scrollTop / scrollHeight / clientHeight`);滑行帧读数 2 → 5,不再虚报「只读 2 次」。仍轻微低估(约 2.9/帧的 `scrollTop` 读未计入)。
|
|
58
|
+
- trace 首帧 `dt`:0 → 16.67。
|
|
59
|
+
- `tickPhases` 重复键 `pin` 删除;`releaseBy.external` 标注为死字段。
|
|
60
|
+
|
|
61
|
+
### 0.6 → 0.7 架构重建(概括)
|
|
62
|
+
|
|
63
|
+
- **写权与目标分离**:`writer ∈ {us, reader}`(谁写 `scrollTop`)、`goal ∈ {tail, element, position, none}`(插件目标)。
|
|
64
|
+
- **一个滑行器**:`slide()` 是唯一移动律(指数追赶 + 精确落点),主容器与小窗共用;删除原生 `scrollTo({behavior:"smooth"})`、意图窗、距离门槛、几何回补等旧机制。
|
|
65
|
+
- **settle 有 9 个具名清理点**(session / reader / nav / lost / timeout / done / manual / official / dispose);协调未清时该轮折叠被压后,避免折叠与滑行互相打断。
|
|
66
|
+
- **设置页方案 A**:插件自己的「工作步骤展示」行(可用时以可见性方式隐藏官方那一行、可逆),不再向官方下拉注入任何项。
|
|
67
|
+
- **回尾判据改为「出现新 user 消息」**(`returnToTail`);删除 `autoFollow` / `injectMenu` 两个设置项。
|
|
68
|
+
- **默认值按真机固化**:窗口高度 360、跟随速度上限 240 px/s、加速度上限 10000 px/s²、保留穿插正文开。
|
|
69
|
+
- **自动展开移出扫描帧**:提问卡/思考/工具只登记,合成点击在下一帧 rAF 执行。
|
|
70
|
+
- **折叠内容用 `hidden="until-found"`**,兼顾长会话性能与 Ctrl+F 可搜。
|
|
71
|
+
|
|
72
|
+
[0.7.1]: https://github.com/rezon-aki/dsh-streamfold/releases/tag/v0.7.1
|
|
73
|
+
[0.7.0]: https://github.com/rezon-aki/dsh-streamfold/releases/tag/v0.7.0
|
package/README.en.md
CHANGED
|
@@ -1,95 +1,111 @@
|
|
|
1
1
|
# dsh-streamfold
|
|
2
2
|
|
|
3
|
-
[简体中文](README.md) · **English**
|
|
4
|
-
|
|
5
3
|
[](LICENSE)
|
|
6
4
|
[](cordis.patch.yml)
|
|
7
|
-
[](https://www.npmjs.com/package/dsh-streamfold)
|
|
6
|
+
|
|
7
|
+
> A better conversation window: the newest thinking window opens automatically while a turn runs, the other process rows fold into a single summary, and when the turn finishes the thinking and tool calls fold away while interleaved prose stays. Everything advances per frame, like water.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Why it exists
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
In a long conversation, tool calls and reasoning drown out the prose. The official Compact mode also stops folding while a session still has unloaded history, so it cannot help until everything is loaded. This plugin enhances the official transcript and folds on its own terms, independent of whether history has finished loading:
|
|
12
12
|
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **Forging.** While the answer streams, every new chunk throws a small spray of sparks from the writing head (the end of the last line), drifting outwards like metal struck on an anvil. Written text only; pause and the hammer stops, and the sparks burn out on their own. Colour, density, speed and lifetime are configurable.
|
|
17
|
-
- **Settle on the prompt.** When a turn finishes the view glides back to **the message that started it**, so you never have to scroll up to remember what you asked (skipped if you scrolled away yourself; on by default, can be turned off).
|
|
18
|
-
- **Pin the prompt.** The prompt of the turn you are reading stays pinned to the top of the conversation, one line with an ellipsis; it steps aside while the real row is on screen, and **clicking it glides back to that message** (on by default, can be turned off).
|
|
13
|
+
- **Process stops drowning the prose**: past turns collapse into a single "N rows folded · click to expand" line.
|
|
14
|
+
- **What you want to watch stays visible**: while a turn runs, only the newest thinking window stays open — capped height, scrolling inside itself.
|
|
15
|
+
- **No scrolling back after a turn**: when it finishes, the view glides back to the message that started it.
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
## What it looks like once installed
|
|
21
18
|
|
|
22
|
-
|
|
19
|
+
- **You can watch it think.** The newest thinking window of the running turn opens automatically (height configurable); older ones fold back into a one-line summary after a grace period. Superseded windows and past turns no longer fight for the scroll position.
|
|
20
|
+
- **Folding keeps a rhythm and does not flash.** Collapsing runs bottom-up, 3 rows per group with a 70 ms stagger; expanding runs top-down, 3 rows per group. Cross-turn batches (page load, session switch) complete instantly; even a very long single turn advances group by group (only a single turn over 84 rows takes the instant guard rail).
|
|
21
|
+
- **Settle on the prompt.** When a turn finishes, the view glides back to **the message that started it** (skipped if you scrolled away yourself). For 2 seconds after arrival it also corrects late layout shifts from images or code blocks.
|
|
22
|
+
- **Pin the prompt.** The prompt of the turn you are reading stays pinned to the top of the conversation, one line with an ellipsis; it steps aside while the real row is on screen, and clicking it glides back to that message.
|
|
23
|
+
- **Steady follow.** The bottom follow advances per frame; scrolling up stops it, and a "back to bottom" button appears once you are away. Scrolling inside a thinking window or a tool body no longer stops the follow by mistake.
|
|
24
|
+
- **Search is handled too.** Folded content is still findable with Ctrl+F; while searching the plugin releases the scroll and does not pin to the bottom, and returning to the window tail or pressing back-to-bottom resumes the follow.
|
|
25
|
+
- **Window sparks / forging.** Sparks along the bottom edge of the thinking window get brighter and denser with scroll speed; while the answer streams, each new chunk throws a spray of sparks from the writing head. Colour, density, speed and lifetime are configurable, and turning them off means they never run.
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+

|
|
28
|
+
|
|
29
|
+

|
|
27
30
|
|
|
28
31
|
## Install
|
|
29
32
|
|
|
30
33
|
**Option 1: the DSH plugin panel (recommended)** — sidebar → **Plugins** → **Add plugin**, paste the line below, then hit “Enable now”:
|
|
31
34
|
|
|
32
35
|
```
|
|
33
|
-
|
|
36
|
+
dsh-streamfold
|
|
34
37
|
```
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
> The panel installs this version (npm `latest` is this release, with provenance). Option 2 is for tracking the repository's latest code.
|
|
40
|
+
|
|
41
|
+
**Option 2: the command line** (three forms):
|
|
37
42
|
|
|
38
43
|
```bash
|
|
39
|
-
dsh plugin --profile web add
|
|
44
|
+
dsh plugin --profile web add dsh-streamfold # npm package (recommended)
|
|
45
|
+
dsh plugin --profile web add github:rezon-aki/dsh-streamfold # track the repository
|
|
40
46
|
dsh plugin --profile web add https://github.com/rezon-aki/dsh-streamfold
|
|
41
47
|
```
|
|
42
48
|
|
|
43
49
|
Restart the profile, then **refresh the browser page** (client code is injected at page load).
|
|
44
50
|
|
|
45
|
-
Requires DSH **>= 0.
|
|
51
|
+
Requires DSH **>= 0.2.0-rc.2** (the official transcript view is owned by the `configForms` service; on the 0.1.7 series use 0.5.0, and on 0.1.5 and earlier use 0.4.x).
|
|
46
52
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Uninstall:
|
|
53
|
+
Uninstall: remove it in the plugin panel, or
|
|
50
54
|
|
|
51
55
|
```bash
|
|
52
56
|
dsh plugin --profile web remove dsh-streamfold
|
|
53
57
|
```
|
|
54
58
|
|
|
59
|
+
Restart the profile and the official behaviour is back.
|
|
60
|
+
|
|
55
61
|
## Usage
|
|
56
62
|
|
|
57
|
-
Settings → General → **Work details**:
|
|
63
|
+
Settings → General → **Work details**: this row is provided by the plugin (the official row is hidden while ours is available; visibility only, reversible), with the official four modes plus **Fold**:
|
|
58
64
|
|
|
59
65
|
| Option | Behaviour |
|
|
60
66
|
| --- | --- |
|
|
61
67
|
| Compact / Standard / Detailed / Verbose | The official modes, with the official labels and behaviour |
|
|
62
|
-
| Fold | This plugin: one window for the running turn, everything else folds into one
|
|
63
|
-
|
|
64
|
-
Choosing **Fold** parks the official mode on **Verbose**, so the official side neither folds nor groups anything and folding is done by this plugin alone (no double folding). The
|
|
65
|
-
|
|
66
|
-
Dedicated settings page: Settings → **Streamfold** (
|
|
67
|
-
|
|
68
|
-
While running, only the newest thinking window opens automatically; **windows you opened yourself are never auto-collapsed**, and a superseded window folds back into a one-line summary after the "superseded grace" (
|
|
69
|
-
|
|
70
|
-
##
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
| Window
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
|
92
|
-
|
|
|
68
|
+
| Fold | This plugin: one window for the running turn, everything else folds into one summary |
|
|
69
|
+
|
|
70
|
+
Choosing **Fold** parks the official mode on **Verbose**, so the official side neither folds nor groups anything and folding is done by this plugin alone (no double folding). The labels come from the official dictionary, so they follow the official wording.
|
|
71
|
+
|
|
72
|
+
Dedicated settings page: Settings → **Streamfold** (every switch below lives there and applies immediately).
|
|
73
|
+
|
|
74
|
+
While running, only the newest thinking window opens automatically; **windows you opened yourself are never auto-collapsed**, and a superseded window folds back into a one-line summary after the "superseded grace" (2 s by default). Scrolling up stops the follow, and a "back to bottom" button appears once you are away (the same button serves the thinking windows and the main view).
|
|
75
|
+
|
|
76
|
+
## Safety
|
|
77
|
+
|
|
78
|
+
- **Client-side presentation only**: it reads the conversation DOM, makes no network requests, touches no credentials and never modifies DSH source.
|
|
79
|
+
- **The host half writes nothing**: no file I/O, no routes, no exported Config; settings live in browser localStorage only (key `dsh-streamfold`, scoped to the page origin).
|
|
80
|
+
- **Official mode changes are reversible**: the transcript view is read and written through the DSH settings service, and while our row is available only the official row is hidden (visibility, reversible).
|
|
81
|
+
- **Clean uninstall**: the settings row, window markers, back-to-bottom button and injected styles are all removed, with no leftover inline `max-height` or hidden attributes.
|
|
82
|
+
|
|
83
|
+
## Settings (22 items)
|
|
84
|
+
|
|
85
|
+
| Setting | Key | Default | Range | Meaning |
|
|
86
|
+
| --- | --- | --- | --- | --- |
|
|
87
|
+
| Work details | `mode` | Fold | Fold / official four modes | Choosing Fold parks the official mode on Verbose, avoiding double folding |
|
|
88
|
+
| Fold history turns | `foldHistory` | on | toggle | Off: do not fold past turns on page load (only while a turn runs) |
|
|
89
|
+
| Keep interleaved prose | `keepInterleavedText` | on | toggle | Keep prose rows while folding and separate them from the final answer with a rule (no capped window) |
|
|
90
|
+
| Keep LLM questions unfolded | `keepUserQuestions` | on | toggle | The `ask_user_question` card and its reply node never fold; off folds them with everything else |
|
|
91
|
+
| Follow speed cap | `followMaxSpeed` | 240 | 60–2000 px/s | Cap on our own catch-up speed; lower is softer and lags more on fast output. Content growth is not capped |
|
|
92
|
+
| Follow acceleration cap | `followMaxAccel` | 10000 | 2000–120000 px/s² | Cap on speed change; lower is softer at start/stop, higher is more responsive |
|
|
93
|
+
| Window height | `windowHeight` | 360 | 80–1200 px | Max height of a thinking / interleaved-prose window |
|
|
94
|
+
| Auto-expand thinking while running | `autoExpandReasoning` | on | toggle | Only the newest block of the running turn; superseded windows fold after the grace period |
|
|
95
|
+
| Superseded grace | `supersedeDelay` | 2 | 0–60 s | How long an older window waits before folding into a summary line (decimals allowed) |
|
|
96
|
+
| Auto-expand tools while running | `autoExpandTools` | off | toggle | Expand the newest tool card using the official card's own disclosure/scroll |
|
|
97
|
+
| Return to tail on new message | `returnToTail` | on | toggle | While stopped mid-transcript, sending a new message glides back to the bottom; off keeps the view where it is until you scroll to the bottom or press back-to-bottom |
|
|
98
|
+
| Smoothing factor | `smoothGrow` | 0.15 | 0.05–0.9 | Share of the remaining gap consumed per frame |
|
|
99
|
+
| Show "back to bottom" | `showJumpButton` | on | toggle | Shown when away from the bottom (hidden for follow lag, to avoid flicker) |
|
|
100
|
+
| Settle on the prompt | `settleToPrompt` | on | toggle | When a turn finishes, glide back to your message that started it; if you scrolled away yourself, nothing moves |
|
|
101
|
+
| Pin the prompt | `pinPrompt` | on | toggle | Keep the prompt of the turn you are reading pinned to the top: one line with ellipsis, steps aside while the real row is in view, click to glide back |
|
|
102
|
+
| Animated transitions | `animations` | on | toggle | Off makes folding / expanding / jumping instant |
|
|
103
|
+
| Window sparks | `sparks` | on | toggle | Sparks along the bottom edge of the running thinking window (off = no canvas, no frames) |
|
|
104
|
+
| Spark colour | `sparkColor` | `#4fa8ff` | colour | Spark colour; the core is brightened towards white heat |
|
|
105
|
+
| Forging sparks | `forgeSparks` | on | toggle | Sparks thrown from the writing head while the answer streams; nothing new written, no hammer |
|
|
106
|
+
| Forging spark speed | `forgeSpeed` | 1 | 0.2–4 × | Drift speed multiplier |
|
|
107
|
+
| Forging spark life | `forgeLife` | 1.3 | 0.2–5 s | How long one spark lives (±30% random) |
|
|
108
|
+
| Spark density | `sparkDensity` | 1 | 0.2–3 × | Spark count multiplier, shared by both spark kinds |
|
|
93
109
|
|
|
94
110
|
Settings live in browser localStorage, scoped to the DSH page origin.
|
|
95
111
|
|
|
@@ -99,25 +115,19 @@ Browser console:
|
|
|
99
115
|
|
|
100
116
|
```js
|
|
101
117
|
__dshStreamfold.stats() // window / fold / chip counts (incl. animation state)
|
|
102
|
-
__dshStreamfold.probe() // row state, still-visible thinking rows, window animation, jump button, spark cost
|
|
103
|
-
__dshStreamfold.state() // current settings + official "
|
|
118
|
+
__dshStreamfold.probe() // row state, still-visible thinking rows, window animation, jump button, spark cost, follow detail
|
|
119
|
+
__dshStreamfold.state() // current settings + official "Work details" snapshot
|
|
104
120
|
__dshStreamfold.set({ smoothGrow: 0.1, supersedeDelay: 3 })
|
|
105
121
|
```
|
|
106
122
|
|
|
107
123
|
When reporting an issue, attach the `probe()` output and your DSH version.
|
|
108
124
|
|
|
109
|
-
##
|
|
110
|
-
|
|
111
|
-
- Client-side presentation only: it reads the conversation DOM, makes no network requests, touches no credentials and never modifies DSH source.
|
|
112
|
-
- The host half reads no files and registers no routes: settings stay in browser localStorage, and the official transcript view is read/written through DSH's own settings service (`configForms`).
|
|
113
|
-
- Clean uninstall: the settings row, window markers and injected styles are all removed.
|
|
114
|
-
|
|
115
|
-
## Development
|
|
125
|
+
## Development and verification
|
|
116
126
|
|
|
117
|
-
- Hand-written, no build: `lib/client.js` (browser half, wrapped in `window.__ModuleLoader__`) and `lib/index.js` (host half).
|
|
127
|
+
- Hand-written, no build: `lib/client.js` (browser half, wrapped in `window.__ModuleLoader__`) and `lib/index.js` (host half, 12 lines).
|
|
118
128
|
- After editing `lib/*.js`, reload the plugin and **refresh the page**.
|
|
119
129
|
- Row anchors use official semantic attributes only: `[data-chat-flow]`, `[data-chat-flow-kind]`, `[data-chat-turn]`, `[data-disclosure-row][aria-expanded]`, `[data-variant=think]`, `[data-tool]`, `[data-sample=bash]`, `[class*=_thinkBody]`, `[class*=_bodyWrap]`, `[data-context-injection-body]` — never CSS module hashes.
|
|
120
|
-
-
|
|
130
|
+
- Tests: `npm test` (`test/spark.mjs` 28 assertions + `test/contract.mjs` + `test/client-apply.mjs`), currently EXIT=0.
|
|
121
131
|
|
|
122
132
|
## License
|
|
123
133
|
|
package/README.md
CHANGED
|
@@ -1,52 +1,56 @@
|
|
|
1
1
|
# dsh-streamfold · 流式折叠
|
|
2
2
|
|
|
3
|
-
**简体中文** · [English](README.en.md)
|
|
4
|
-
|
|
5
3
|
[](LICENSE)
|
|
6
4
|
[](cordis.patch.yml)
|
|
7
|
-
[](https://www.npmjs.com/package/dsh-streamfold)
|
|
6
|
+
|
|
7
|
+
> 一个更好的会话窗口:运行中自动展开最新的思考小窗,其它过程行折成一条摘要;一轮跑完,思考与工具调用自动折起,穿插正文保留。全程按帧推进,像水流一样。
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## 为什么需要它
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
长会话里,工具调用与思考过程会把正文淹掉;官方的「紧凑」档在会话还有未加载历史时会折叠失效,历史加载完之前帮不上忙。本插件在官方对话流上做展示增强,折叠按自己的规则走,不依赖历史是否加载完:
|
|
12
12
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
- **正文锻打。** 正文流式输出时,每写一段就从写头(最后一行末尾)向四周飘出一扇火星,像溅出来的一小团火。写了才有,停笔就不发,火星烧完自动收手。颜色、密度、速度、寿命都可调。
|
|
17
|
-
- **跑完回到提问处。** 一轮结束,视图平滑滑回**你这轮那句话**的位置——不用自己往上翻找回"我当初问的是什么"(你已经自己上滚过就不动你;可关,默认开)。
|
|
18
|
-
- **置顶显示提问。** 读到哪一轮,那一轮的提问就钉在会话顶端(一行,超出省略);它自己在屏幕上时自动让位,**点它一下平滑滑回那句发言**(可关,默认开)。
|
|
13
|
+
- **过程不再淹没正文**:非运行轮次收成一条「已折叠 N 行 · 点击展开」;
|
|
14
|
+
- **想看的随时看得见**:运行中只留最新那一个思考窗,限高、内部自滚;
|
|
15
|
+
- **读完一轮不用往回翻**:跑完自动回到你这轮的提问处。
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
## 装完是什么样
|
|
21
18
|
|
|
22
|
-
|
|
19
|
+
- **运行中看得到思考。** 自动展开本轮最新的思考窗(限高可调),旧的按宽限折回一行摘要;被取代的、上一轮的窗不再抢滚动。
|
|
20
|
+
- **折叠有节奏,不闪。** 收起从下往上、一组 3 行、组间 70ms;展开从最上面往下、同样一组 3 行。加载页面、切会话这类**跨轮批量**场景直接瞬时完成;单轮再长也逐组推进(只有单轮超过 84 行才走瞬时护栏)。
|
|
21
|
+
- **跑完回到提问处。** 一轮结束,视图平滑滑回**你这轮那句话**的位置(你自己上滚过就不动你)。到位后 2 秒内还会纠正图片/代码块迟到落版造成的偏移。
|
|
22
|
+
- **置顶显示提问。** 读到哪一轮,那一轮的提问就钉在会话顶端(一行,超出省略);它自己在屏幕上时自动让位,点它滑回那句发言。
|
|
23
|
+
- **跟随够稳。** 底部跟随按帧推进;上滚即停跟,离底出现「回到底部」;在思考小窗或工具正文里滚动不会误触发「停止跟随」。
|
|
24
|
+
- **搜索也照顾。** 折叠的内容仍可被 Ctrl+F 搜到;搜索期间不抢滚动,滚回窗尾或点回底恢复。
|
|
25
|
+
- **小窗火花 / 正文锻打。** 思考窗底部的火星随滚动速度变亮变密;正文流式写头每写一段砸出一扇火星。颜色、密度、速度、寿命都可调,关掉即完全不运行。
|
|
23
26
|
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
+

|
|
28
|
+
|
|
29
|
+

|
|
27
30
|
|
|
28
31
|
## 安装
|
|
29
32
|
|
|
30
|
-
**方式一:DSH 插件面板(推荐)** —— 侧栏
|
|
33
|
+
**方式一:DSH 插件面板(推荐)** —— 侧栏 →「**插件**」→「**添加插件**」,粘贴下面这一行,装完点「立即启用」:
|
|
31
34
|
|
|
32
35
|
```
|
|
33
|
-
|
|
36
|
+
dsh-streamfold
|
|
34
37
|
```
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
> 面板装的就是本版(npm 上 `latest` 即本版,含 provenance)。方式二适合想跟仓库最新代码的人。
|
|
40
|
+
|
|
41
|
+
**方式二:命令行**(三种写法):
|
|
37
42
|
|
|
38
43
|
```bash
|
|
39
|
-
dsh plugin --profile web add
|
|
44
|
+
dsh plugin --profile web add dsh-streamfold # npm 包(推荐)
|
|
45
|
+
dsh plugin --profile web add github:rezon-aki/dsh-streamfold # 跟仓库最新
|
|
40
46
|
dsh plugin --profile web add https://github.com/rezon-aki/dsh-streamfold
|
|
41
47
|
```
|
|
42
48
|
|
|
43
|
-
|
|
49
|
+
装完**重启 profile**,然后**刷新浏览器页面**(客户端代码在页面加载时注入)。
|
|
44
50
|
|
|
45
|
-
要求 DSH **>= 0.
|
|
51
|
+
要求 DSH **>= 0.2.0-rc.2**(官方「对话显示」档位由 `configForms` 服务托管;0.1.7 系列请用 0.5.0,0.1.5 及更早请用 0.4.x)。
|
|
46
52
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
卸载:
|
|
53
|
+
卸载:在插件面板里移除,或
|
|
50
54
|
|
|
51
55
|
```bash
|
|
52
56
|
dsh plugin --profile web remove dsh-streamfold
|
|
@@ -56,42 +60,52 @@ dsh plugin --profile web remove dsh-streamfold
|
|
|
56
60
|
|
|
57
61
|
## 用法
|
|
58
62
|
|
|
59
|
-
设置 → 通用设置 →
|
|
63
|
+
设置 → 通用设置 → **工作步骤展示**:这一行由本插件提供(官方那一行在本插件的设置行可用时隐藏,只改可见性、可逆),里面是官方四档 + 本插件的「**折叠**」:
|
|
60
64
|
|
|
61
65
|
| 选项 | 行为 |
|
|
62
66
|
| --- | --- |
|
|
63
67
|
| 简洁 / 标准 / 详细 / 完全展开 | 官方原本的四档,文案与行为都跟官方一致 |
|
|
64
|
-
| 折叠 |
|
|
65
|
-
|
|
66
|
-
选「折叠」时,官方那一档会被自动停在
|
|
67
|
-
|
|
68
|
-
专属设置页:设置 →
|
|
69
|
-
|
|
70
|
-
运行中只会自动展开最新那一个思考窗;**你自己点开的窗不会被自动收起**,被取代的旧窗按「旧窗折叠宽限」(默认 2
|
|
71
|
-
|
|
72
|
-
##
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
|
92
|
-
|
|
|
93
|
-
|
|
|
94
|
-
|
|
|
68
|
+
| 折叠 | 本插件:运行中的一轮只留一个窗,其余过程收成一条摘要 |
|
|
69
|
+
|
|
70
|
+
选「折叠」时,官方那一档会被自动停在 **完全展开**——官方自己不折、不分组,折叠只由本插件做,避免两层折叠打架;档位名与官方设置页同源(取自官方词典),官方改了文案这边跟着变。
|
|
71
|
+
|
|
72
|
+
专属设置页:设置 → **流式折叠**(本文所有开关都在这里,改动即时生效)。
|
|
73
|
+
|
|
74
|
+
运行中只会自动展开最新那一个思考窗;**你自己点开的窗不会被自动收起**,被取代的旧窗按「旧窗折叠宽限」(默认 2 秒)折回一行摘要;上滚即停跟,离底时出现回底按钮(小窗与主窗口是同一个按钮)。
|
|
75
|
+
|
|
76
|
+
## 安全边界
|
|
77
|
+
|
|
78
|
+
- **纯客户端展示增强**:只读对话 DOM,不发网络请求、不接触凭据、不改官方源码。
|
|
79
|
+
- **宿主半区不落任何东西**:不读写文件、不注册路由、不导出 Config;设置只存浏览器 localStorage(key `dsh-streamfold`,按页面源站隔离)。
|
|
80
|
+
- **对官方档位只做可逆改动**:档位读写走 DSH 自己的设置服务;本插件的设置行可用时只隐藏官方那一行(可见性、可逆)。
|
|
81
|
+
- **卸载即净**:设置行、小窗标记、回底按钮与注入样式全部撤掉,不留行内 `max-height` 与隐藏属性。
|
|
82
|
+
|
|
83
|
+
## 配置(22 项)
|
|
84
|
+
|
|
85
|
+
| 设置项 | 键 | 默认 | 取值/范围 | 说明 |
|
|
86
|
+
| --- | --- | --- | --- | --- |
|
|
87
|
+
| 工作步骤展示 | `mode` | 折叠 | 折叠 / 官方四档 | 选「折叠」时官方档自动停到「完全展开」,避免两层折叠 |
|
|
88
|
+
| 折叠历史轮次 | `foldHistory` | 开 | 开关 | 关掉后:加载页面不再自动折叠历史轮次(只在跑动时折前面的) |
|
|
89
|
+
| 保留穿插正文 | `keepInterleavedText` | 开 | 开关 | 折叠时保留带正文的行,用一条横线与正式回答分开(正文不套限高小窗) |
|
|
90
|
+
| 提问不入折叠 | `keepUserQuestions` | 开 | 开关 | LLM 的提问工具(`ask_user_question`)与其回复节点始终保留、不折进摘要;关掉则随其余内容一起折 |
|
|
91
|
+
| 跟随速度上限 | `followMaxSpeed` | 240 | 60~2000 px/s | 主动追赶时的速度上限;越小越柔、高速输出时落后越多。内容自身增长的速度不受它限制 |
|
|
92
|
+
| 跟随加速度上限 | `followMaxAccel` | 10000 | 2000~120000 px/s² | 速度变化的上限;调小起步/刹车更柔,调大更跟手 |
|
|
93
|
+
| 窗口高度 | `windowHeight` | 360 | 80~1200 px | 单个思考/穿插正文小窗的最大高度 |
|
|
94
|
+
| 运行中自动展开思考 | `autoExpandReasoning` | 开 | 开关 | 只自动展开本轮最新的那一个;被取代的旧窗按「旧窗折叠宽限」折回一行摘要 |
|
|
95
|
+
| 旧窗折叠宽限 | `supersedeDelay` | 2 | 0~60 秒 | 新的思考窗出现后,旧窗再等多久才自动折回(支持小数) |
|
|
96
|
+
| 运行中自动展开工具 | `autoExpandTools` | 关 | 开关 | 开:运行中最新的工具卡自动展开(用官方卡片自己的折叠/内滚,不套限高小窗) |
|
|
97
|
+
| 发消息回到尾部 | `returnToTail` | 开 | 开关 | 你停在中途(看过置顶、跳转过轮次)时,自己再发一条消息 ⇒ 视图滑回尾部;关掉后一律停在原地,只有滚到底或点「回到底部」才恢复跟随 |
|
|
98
|
+
| 平滑系数 | `smoothGrow` | 0.15 | 0.05~0.9 | 跟随时每帧吃掉多少差距,越小越柔 |
|
|
99
|
+
| 离底显示「回到底部」 | `showJumpButton` | 开 | 开关 | 离开底部时出现回底按钮(跟随中的轻微落后不显示,避免闪烁) |
|
|
100
|
+
| 跑完回到提问处 | `settleToPrompt` | 开 | 开关 | 一轮结束后平滑移到本轮你那句话的位置;你已经自己上滚过就不动你(动效关掉时直接到位) |
|
|
101
|
+
| 置顶显示提问 | `pinPrompt` | 开 | 开关 | 把「你正在看的那一轮」的提问钉在会话顶端:往上滚会跟着换成那一轮,超过一行只显示一行;它自己在视口里时自动让位,点它滑回那句话 |
|
|
102
|
+
| 动效过渡 | `animations` | 开 | 开关 | 关掉则折叠/展开/回底全部瞬时 |
|
|
103
|
+
| 小窗火花 | `sparks` | 开 | 开关 | 运行中思考小窗底部的火星(关掉后不建画布、不排帧) |
|
|
104
|
+
| 火花颜色 | `sparkColor` | `#4fa8ff` | 颜色 | 火星颜色;核心自动提亮成白热 |
|
|
105
|
+
| 正文锻打火花 | `forgeSparks` | 开 | 开关 | 正文流式写头砸出的火星;写头不动就不砸,跑完自动收手 |
|
|
106
|
+
| 锻打火花速度 | `forgeSpeed` | 1 | 0.2~4 × | 火星飘出去的速度倍率 |
|
|
107
|
+
| 锻打火花寿命 | `forgeLife` | 1.3 | 0.2~5 秒 | 单颗火星活多久(实际在 ±30% 内随机) |
|
|
108
|
+
| 火花密度 | `sparkDensity` | 1 | 0.2~3 × | 火星数量倍率,两种火花共用;越高越密、绘制开销越大 |
|
|
95
109
|
|
|
96
110
|
设置存在浏览器 localStorage(按 DSH 页面源站隔离)。
|
|
97
111
|
|
|
@@ -101,25 +115,19 @@ dsh plugin --profile web remove dsh-streamfold
|
|
|
101
115
|
|
|
102
116
|
```js
|
|
103
117
|
__dshStreamfold.stats() // 窗口 / 折叠 / 折叠条计数(含动效状态)
|
|
104
|
-
__dshStreamfold.probe() //
|
|
105
|
-
__dshStreamfold.state() // 当前设置 +
|
|
118
|
+
__dshStreamfold.probe() // 行状态、还看得见的思考行、小窗动画、回底按钮、火花开销、跟随明细
|
|
119
|
+
__dshStreamfold.state() // 当前设置 + 官方「工作步骤展示」取值快照
|
|
106
120
|
__dshStreamfold.set({ smoothGrow: 0.1, supersedeDelay: 3 })
|
|
107
121
|
```
|
|
108
122
|
|
|
109
123
|
报问题时附上 `probe()` 的输出与 DSH 版本,定位会快很多。
|
|
110
124
|
|
|
111
|
-
##
|
|
112
|
-
|
|
113
|
-
- 纯客户端展示增强:只读对话 DOM,不发网络请求、不接触凭据、不改官方源码。
|
|
114
|
-
- 宿主半区不读写文件、不注册路由:设置只落浏览器 localStorage;对官方「对话显示」档位的读写走 DSH 自己的设置服务(`configForms`)。
|
|
115
|
-
- 卸载即净:设置行、小窗标记与注入的样式全部撤掉。
|
|
116
|
-
|
|
117
|
-
## 开发
|
|
125
|
+
## 开发与验收
|
|
118
126
|
|
|
119
|
-
- 手写、无构建:`lib/client.js`(浏览器半区,包在 `window.__ModuleLoader__` 里)、`lib/index.js
|
|
120
|
-
- 改完 `lib/*.js`
|
|
127
|
+
- 手写、无构建:`lib/client.js`(浏览器半区,包在 `window.__ModuleLoader__` 里)、`lib/index.js`(宿主半区,12 行占位)。
|
|
128
|
+
- 改完 `lib/*.js` 后重载插件,并**刷新浏览器页面**。
|
|
121
129
|
- 行锚点全部用官方语义属性:`[data-chat-flow]`、`[data-chat-flow-kind]`、`[data-chat-turn]`、`[data-disclosure-row][aria-expanded]`、`[data-variant=think]`、`[data-tool]`、`[data-sample=bash]`、`[class*=_thinkBody]`、`[class*=_bodyWrap]`、`[data-context-injection-body]`——不用 CSS module 哈希。
|
|
122
|
-
-
|
|
130
|
+
- 测试:`npm test`(`test/spark.mjs` 28 断言 + `test/contract.mjs` + `test/client-apply.mjs`),当前 EXIT=0。
|
|
123
131
|
|
|
124
132
|
## License
|
|
125
133
|
|