dsh-quick-toc 0.5.0 → 0.6.0
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.en.md +37 -0
- package/CHANGELOG.md +37 -0
- package/README.en.md +35 -12
- package/README.md +34 -11
- package/lib/client.js +4257 -3282
- package/lib/index.js +63 -6
- package/package.json +8 -2
package/CHANGELOG.en.md
CHANGED
|
@@ -2,6 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to **dsh-quick-toc** are documented here. Chinese version: [CHANGELOG.md](CHANGELOG.md).
|
|
4
4
|
|
|
5
|
+
## [0.6.0] - 2026-09-14
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **A bilingual interface**: a new language setting — `follow the host` (default; uses whatever language DSH currently runs in), `中文` or `English`. Every interface string comes from one table, falling back to Chinese when an English entry is missing. Chinese stamps keep the relative words `昨天` / `前天`; English reads yesterday as the word (`yesterday`) and carries the numeric `YY-MM-DD HH:MM` date for anything older (no "2 days ago").
|
|
9
|
+
- **A plugin-configuration card**: a "Conversation Outline" card under **Settings → Plugins → Plugin configuration** (the same place DSH's own configurable plugins live), holding the language, the default docked edge (left by default), the heading levels shown, fuzzy search, the hover preview card and the console diagnostic switch. A changed field is marked "customized" and gets its own reset control back to the default.
|
|
10
|
+
- **The panel and the card are live in both directions**: they read and write one shared store. Dragging or toggling in the panel shows up in the card, and a change made in the card takes effect on the panel's next render — no page reload either way.
|
|
11
|
+
- **Preferences move into DSH's settings**: the preferences above no longer live only in the browser; they are written to the Host settings document, for which the plugin now ships a host half (it registers the `dsh-quick-toc` settings namespace with range validation). A local mirror stays in the browser: on a page that may not write settings (DSH keeps them read-only off a loopback address) the panel keeps working off the mirror, exactly as 0.5.x did. Values left behind by a 0.5.x install are imported into the host layer once, the first time it answers — and only while the user layer is still empty, so nothing already configured gets stomped.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- **Long jumps glide again**: 0.5.1 stopped animating long jumps to fix the "lands halfway" bug; 0.6.0 brings the animation back as a glide **drawn frame by frame by the plugin** (ease-in-out, ~0.37–0.77s by distance), not via the browser's smooth scrolling — some setups carry that call out as an instant jump, and drawing it guarantees a visible scroll on any setup. Every frame re-aims at the target's live offset (so a host re-page mid-flight is followed), and the landing is briefly re-checked afterwards (~0.6s), so a cross-page jump never stops halfway.
|
|
15
|
+
- **The outline fills a taller panel**: when the panel is opened or dragged taller and the latest page is shorter than the list viewport (blank space below the newest group), the window grows until the content fills the height or every turn is shown.
|
|
16
|
+
- **The "currently reading" highlight fades over 0.4s** (opacity, blue fill and border transition together, with the pinned header's blue layer in sync) — the colour change between groups is now clearly visible and calmer.
|
|
17
|
+
- **Top offset, width and height left the settings**: they describe this screen, so they are drag-only now and keep being saved per browser; the card no longer offers numeric inputs for them.
|
|
18
|
+
- **Preferences are read and written in one place**: the panel no longer writes `localStorage` on every pointer move; changes are merged and persisted after a short delay, while the live position during a drag stays in the panel's own state. The position/size keys are unchanged (`panelY.v1` / `panelW.v1` / `panelH.v1`); the other keys become the mirror of the host settings (same names, fallback layer).
|
|
19
|
+
- **The diagnostic switch moved into the card**: tick it there and the mount line prints on the spot — no more hand-editing `localStorage` and reloading.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- **The panel crashed on some conversations (React #310)**: the number of hooks it called could differ between two renders — both the bail-out when `useChat` is missing and the early return for "this conversation has no displayable turn yet" sat below part of the hook list, so those hooks reappeared on a later render and React threw `Rendered more hooks than during the previous render`, taking the panel and its slot down with it (present in 0.5.0 and 0.5.1). The panel is now split into a hook-free outer guard and an inner component, so every render calls exactly the same hooks.
|
|
23
|
+
|
|
24
|
+
## [0.5.1] - 2026-09-13
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
- **"Back to the newest row" button**: a round button in the outline list's lower-right corner. It fades in whenever the list is not at its bottom and fades out once it is; clicking scrolls the outline back to the newest entry (smooth for a short distance, instant when the list is far up).
|
|
28
|
+
- **Turn stamps carry the day**: the time shown in group headers, search result rows and hover cards is no longer a bare `HH:MM` — yesterday reads `昨天 15:04`, the day before `前天 15:04`, anything older `25-09-11 15:04` (two-digit year; decided by calendar day, not a 24-hour difference).
|
|
29
|
+
- **Failures are reported**: a turn that produced no reply at all (request timeout, upstream error) now shows a `请求失败` row under its group header with the host's own error text; clicking it jumps to that error in the conversation, and the error text is searchable in full-text scope (its result row is tagged 请求失败).
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- **The header now holds two buttons per side**: the heading-level filter and the dock toggle on the left, search and collapse on the right, with a spacer pinning the pairs to the two ends; the three-bar identity mark on the left is gone.
|
|
33
|
+
- **The level filter popup is left-aligned with its button** (it used to be right-aligned).
|
|
34
|
+
- **The mount diagnostic is silent by default**: the console no longer prints `[dsh-quick-toc] panel mounted …`. To diagnose, run `localStorage.setItem("dsh-quick-toc.debug", "1")` and reload — the line then reports `turnOutline` and the jump loader's stage-by-stage state, while normal use stays quiet.
|
|
35
|
+
- **Long jumps land instantly**: a jump across a long history no longer "stops halfway" (short jumps still glide smoothly); after landing it re-checks for ~0.6s, which corrects a target that moved while content was mounting.
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
- **Failed or aborted turns were mislabelled 未加载**: those turns have no model reply, so they carried neither a time nor headings and were re-listed as unloaded turns. A loaded user message now counts as "this turn is loaded", failures additionally show their error row, and a user-aborted turn simply shows as a heading-less turn.
|
|
39
|
+
- **Scrolling the outline up to load older messages bounced the transcript back to the newest turn**, so paging up never got anywhere: the host force-scrolls to the bottom whenever a scroll is not attributed to the reader while it still believes the reader sits at the bottom, and a page-in triggered from the outline matches exactly that condition. The plugin now lifts the transcript just off the bottom stick zone before clicking the host's "load earlier", so the page-in keeps its place.
|
|
40
|
+
- **A heading-less turn's group header was formatted unlike every other header**: it used to be enlarged (12px / 600 / primary colour), which made it read as a different kind of entry. All group headers now share one style (11px, secondary colour, one row box); a heading-less turn is simply a group with no rows under its header.
|
|
41
|
+
|
|
5
42
|
## [0.5.0] - 2026-09-12
|
|
6
43
|
|
|
7
44
|
### Added
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
**dsh-quick-toc** 的重要变更都记录在这里。英文版见 [CHANGELOG.en.md](CHANGELOG.en.md)。
|
|
4
4
|
|
|
5
|
+
## [0.6.0] - 2026-09-14
|
|
6
|
+
|
|
7
|
+
### 新增
|
|
8
|
+
- **界面中英双语**:新增语言设置——`跟随宿主`(默认,用 DSH 当前的语言)、`中文`、`English`。界面文字全部走字符串表,英文缺失时回退中文。中文的时间戳保留 `昨天` / `前天`,英文的昨天用 `yesterday`、前天及更早一律用 `YY-MM-DD HH:MM` 的日期形式(不用 "2 days ago" 这类相对词)。
|
|
9
|
+
- **插件配置卡片**:在 **设置 → 插件 → 插件配置** 里新增「对话大纲」卡片(与 DSH 自带的可配置插件同一处),集中管理:语言、默认停靠边缘(默认左侧)、显示的标题层级、模糊搜索、悬停预览卡片、控制台诊断日志开关。被改动过的字段会标「已自定义」,并带单独的「重置」(回到默认值)。
|
|
10
|
+
- **面板与卡片实时互通**:两边读写同一份偏好。在面板里拖动或切换开关,卡片随即显示新值;在卡片里改动,面板当次渲染就生效,不需要刷新页面。
|
|
11
|
+
- **偏好存入 DSH 设置**:上述偏好不再只存在浏览器里,而是写入 DSH 的宿主设置文档(跟随配置),插件为此新增了宿主半(注册 `dsh-quick-toc` 设置命名空间,带取值范围校验)。浏览器本地仍保留一份镜像:在不允许写设置的页面上(DSH 对非回环页面如此处理),面板继续按本地镜像工作,行为与 0.5.x 一致。0.5.x 留下的本地值会在宿主层第一次应答时自动导入一次(仅当用户层还是空的时候,不会覆盖已配置的值)。
|
|
12
|
+
|
|
13
|
+
### 变更
|
|
14
|
+
- **长距离跳转恢复动画**:0.5.1 为修"点击大纲跳转半途落地"让长跳直接定位,0.6.0 把动画找回来:滚动过程由插件**逐帧绘制**(ease-in-out,时长随距离约 0.37–0.77 秒),不依赖浏览器的「平滑滚动」——部分环境会把它直接执行成瞬移,自绘保证任何设置下都有滚动过程。每帧重瞄目标实时位置(宿主翻页改变偏移也会跟随),落点后短暂复检(约 0.6 秒),所以跨页远跳不会半途停下。
|
|
15
|
+
- **面板变大后大纲自动填满**:打开面板或向下拉高时,若最新一页比列表视口矮(最新一组下方留白),窗口自动长大直到内容填满高度或全部回合都已显示。
|
|
16
|
+
- **「正在阅读」蓝框的渐显渐隐加长到 0.4 秒**(透明度、蓝色填充与描边同步过渡,吸顶组头的蓝色层同步),换组时的颜色变化更明显、更柔和。
|
|
17
|
+
- **顶边距、宽度、高度移出设置**:这三项描述的是"这一块屏幕",改为只能拖拽调整,继续按浏览器保存;设置卡片不再提供数字输入。
|
|
18
|
+
- **偏好的读写收敛到一处**:面板不再在每次指针移动时直接写 `localStorage`,而是把变化合并后短延迟落盘;拖动过程中的实时位置仍由面板自己的状态负责。位置与尺寸的键名不变(`panelY.v1` / `panelW.v1` / `panelH.v1`),其余键转为宿主设置的镜像(键名不变,作回退层)。
|
|
19
|
+
- **诊断开关进入设置卡片**:可以在卡片里点选,而且打开后当下就会打印一行挂载诊断,不再需要手动改 `localStorage` 再刷新。
|
|
20
|
+
|
|
21
|
+
### 修复
|
|
22
|
+
- **面板在部分会话上崩溃(React #310)**:面板的 hook 调用数量在两次渲染之间可能不一致——`useChat` 缺失时的兜底返回、以及"这轮对话还没有任何可显示的回合"时的提前返回,都发生在部分 hook 之后,于是这些 hook 在下一次渲染被补上时 React 抛 `Rendered more hooks than during the previous render`,面板连同它所在的槽位一起消失(0.5.0 / 0.5.1 均存在)。现在面板拆成"不调用任何 hook 的外层守卫 + 内层组件",任何一次渲染的 hook 数量都相同。
|
|
23
|
+
|
|
24
|
+
## [0.5.1] - 2026-09-13
|
|
25
|
+
|
|
26
|
+
### 新增
|
|
27
|
+
- **「回到底部」浮动按钮**:大纲列表右下角的圆形按钮。列表不在底部时渐显,滚到底后渐隐;点击把大纲滚回最新一条(近距离平滑滚动,长距离即时到位)。
|
|
28
|
+
- **回合时间带日期**:组头、搜索结果行与悬停卡片里的时间不再只有 `HH:MM`——昨天显示 `昨天 15:04`,前天显示 `前天 15:04`,更早显示 `25-09-11 15:04`(年份取后两位;按自然日判定,不是按 24 小时差)。
|
|
29
|
+
- **失败回合的报错**:请求超时、上游报错这类没有产出任何回复的回合,现在在组头下方显示一行 `请求失败` 与宿主提供的报错原文;点击跳到对话中该报错的位置,报错原文同样能被全文搜索命中(结果行带「请求失败」标记)。
|
|
30
|
+
|
|
31
|
+
### 变更
|
|
32
|
+
- **标题栏改为一边两个按钮**:左侧「层级筛选 + 停靠切换」,右侧「搜索 + 收起」,中间留白把两组顶到两端;并去掉左侧的三条杠装饰标识。
|
|
33
|
+
- **层级筛选弹层改为左对齐按钮**(此前在按钮右侧对齐)。
|
|
34
|
+
- **挂载诊断日志默认静默**:控制台不再打印 `[dsh-quick-toc] panel mounted …`。需要排查时先执行 `localStorage.setItem("dsh-quick-toc.debug", "1")` 再刷新即可看到该行(`turnOutline` 与跳转加载器的分阶段状态),正常使用不再有噪音。
|
|
35
|
+
- **长距离跳转改为即时定位**:跨越很长历史的跳转不再"滚到一半停下"(近距离仍是平滑滚动),落地后还有约 0.6 秒的校验,用于纠正内容高度在飞行途中变化的情况。
|
|
36
|
+
|
|
37
|
+
### 修复
|
|
38
|
+
- **失败或中止的回合被误标成「未加载」**:这类回合没有模型回复,既没有时间也没有标题,被当成尚未加载的回合重新列了一遍。现在"该回合的用户消息已加载"本身就是已加载的依据,失败回合另加报错行;被用户中止的回合按普通无标题回合显示。
|
|
39
|
+
- **从大纲往上翻加载更早消息时,对话区会被弹回最新一条**,越翻越回到底部:宿主在"这次滚动不是读者发起、且它仍认为读者停在底部"时会强制滚回底部,而从大纲触发的翻页恰好命中该条件。现在点击宿主的「加载更早」之前会先把对话区抬离贴底区,翻页保持原位。
|
|
40
|
+
- **无标题回合的组头与其它组头格式不一致**:它此前被整体放大(12px / 600 / 正文色),与常规组头并列时像另一种条目。现在所有组头共用同一套样式(11px、次要色、同一行盒),无标题回合只是"组头下面没有行"。
|
|
41
|
+
|
|
5
42
|
## [0.5.0] - 2026-09-12
|
|
6
43
|
|
|
7
44
|
### 新增
|
package/README.en.md
CHANGED
|
@@ -7,7 +7,11 @@ A conversation TOC plugin for [DeepSeek Harness](https://github.com/deepseek-ai/
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- **Turn-grouped outline** — each user message plus its following AI replies form one group; the group header shows the turn's time and a first-line preview, and clicking it jumps to the start of that turn's model reply
|
|
10
|
-
- **Whole-session coverage** — turns the conversation window has not loaded are listed too (tagged
|
|
10
|
+
- **Whole-session coverage** — turns the conversation window has not loaded are listed too (tagged `未加载` / "Not loaded", with previews); clicking one loads that turn and jumps to it
|
|
11
|
+
- **Failures are reported** — a turn with no reply at all (request timeout, upstream error) shows `请求失败` / "Request failed" plus the host's error text, and clicking it jumps to that error in the conversation
|
|
12
|
+
- **Bilingual** — the interface language can follow the host, or be forced to Chinese or English; Chinese stamps use `昨天` / `前天`, English reads yesterday as the word (`yesterday`) and carries the `YY-MM-DD HH:MM` date for anything older
|
|
13
|
+
- **A plugin-configuration card** — a "Conversation Outline" card under Settings → Plugins → Plugin configuration: the language, the default docked edge, the heading levels shown, fuzzy search, hover previews and the diagnostic switch; changed fields are marked "customized" and can be reset individually, and the card and the panel stay in sync
|
|
14
|
+
- **Turn stamps carry the day** — yesterday reads `昨天 15:04`, the day before `前天 15:04`, anything older `25-09-11 15:04`, so times never blur together in a session spanning days (with the interface in English every stamp older than today carries a `YY-MM-DD` date instead)
|
|
11
15
|
- **Row subtitles** — under each heading, the first sentence of that section, so identically-titled headings can be told apart
|
|
12
16
|
- **Hover previews** — hovering a heading row shows the section's opening, the turn time and the heading path
|
|
13
17
|
- **Search** — title / full-text scopes; click any result row to locate and highlight that hit, `n/N` Enter stepping, Esc to close
|
|
@@ -16,8 +20,9 @@ A conversation TOC plugin for [DeepSeek Harness](https://github.com/deepseek-ai/
|
|
|
16
20
|
- **Sticky group headers** — while scrolling the outline, the current turn's header stays pinned at the top of the panel
|
|
17
21
|
- **Heading level filter** — the round levels button in the header pops down H1–H6 switches for any combination
|
|
18
22
|
- **Auto-follow** — the turn being read lights up in a closed blue box while you scroll the conversation; the outline follows on its own
|
|
19
|
-
- **Jumping** — click a heading to jump to its position in the conversation
|
|
20
|
-
- **
|
|
23
|
+
- **Jumping** — click a heading to jump to its position in the conversation (the scroll animation is drawn frame by frame by the plugin, not via the browser's smooth scrolling — some setups carry that out as an instant jump; every frame re-aims at the target's live offset, so a host re-page mid-flight is still landed on and a cross-page jump never stops halfway)
|
|
24
|
+
- **Back to the newest row** — after paging far up, a floating button in the list's lower-right corner returns to the newest entry in one click (it appears when the list is not at its bottom and disappears once it is)
|
|
25
|
+
- **Dockable and resizable** — drag the top bar to move the panel, ◀ / ▶ to dock left or right, drag an edge to resize, and collapse it into an edge handle; position and size are remembered per browser (top offset, width and height are adjusted by dragging only)
|
|
21
26
|
- **Paging** — the most recent groups show first; scrolling up both expands the index and loads older conversation
|
|
22
27
|
- **Edge hints** — a brief hint at the bottom of the panel when you keep scrolling past the first or the last entry
|
|
23
28
|
- **Markdown-aware** — inline markup in headings is stripped; `#` lines inside fenced code blocks are not headings
|
|
@@ -28,13 +33,15 @@ A conversation TOC plugin for [DeepSeek Harness](https://github.com/deepseek-ai/
|
|
|
28
33
|
|
|
29
34
|
| Plugin | Supported DSH |
|
|
30
35
|
| --- | --- |
|
|
31
|
-
| **0.
|
|
32
|
-
| 0.
|
|
33
|
-
| 0.4.0 | 0.1.5-rc.1, 0.1.5-rc.2 |
|
|
34
|
-
| 0.3.3 | 0.1.5-rc.1 |
|
|
35
|
-
| 0.
|
|
36
|
+
| **0.6.x** (latest, 0.6.0) | 0.1.5-rc.1, 0.1.5-rc.2 |
|
|
37
|
+
| 0.5.x (0.5.1) | 0.1.5-rc.1, 0.1.5-rc.2 |
|
|
38
|
+
| 0.4.x (0.4.1) | 0.1.5-rc.1, 0.1.5-rc.2 |
|
|
39
|
+
| 0.3.x (0.3.3) | 0.1.5-rc.1 |
|
|
40
|
+
| 0.2.x (0.2.2) | = 0.1.2-rc.1 |
|
|
36
41
|
|
|
37
|
-
|
|
42
|
+
Each major line lists only its newest patch (the defects a new feature introduces are fixed in the patches that follow, so within one major line the newest patch is the one to use; older patches keep working — the plugin does not break existing interfaces).
|
|
43
|
+
|
|
44
|
+
`engines.dsh` has a floor of **0.1.5-rc.1** (`>=`): from that release on, the plugin uses the host's session-scoped slot injection. 0.6.0 was tested on **0.1.5-rc.2** (including the host half's settings-namespace registration); on **0.1.5-rc.1** the plugin's loading and client-module delivery were tested for real (the host boots, and the `dsh-quick-toc/client.js` rev in its boot graph is byte-identical to this repository's `lib/client.js`). The host interfaces it relies on — the `turnOutline` projection, the session-scoped `useProjection`, the client `sessions` service and its `loadThrough` jump loader (since 0.5.0), the `turn-error` node used for failed turns (since 0.5.1), and the host `settings` service (`installSection`), the client `settingsScope` and the `settings.plugin.item` card slot added in 0.6.0 — were checked one by one against the installed 0.1.5-rc.1 and 0.1.5-rc.2 bundles, whose code is byte-identical between the two releases (`dsh-client-ui-chat` differs by a single CSS declaration unrelated to this plugin). Older or newer DSH versions are unverified and therefore not claimed; on an older DSH the newest usable plugin version is **0.3.2**. On install or update, the DSH market pre-flights host compatibility from `engines.dsh`, `dsh.compatibility.dshReleases` and `peerDependencies` in `package.json`.
|
|
38
45
|
|
|
39
46
|
## Install
|
|
40
47
|
|
|
@@ -60,23 +67,39 @@ After installing, restart DSH and open the Web UI. The panel starts collapsed; c
|
|
|
60
67
|
|
|
61
68
|
## Usage
|
|
62
69
|
|
|
63
|
-
- **Jumping**: click an outline heading or a group header to jump to it; entries tagged
|
|
70
|
+
- **Jumping**: click an outline heading or a group header to jump to it; entries tagged `未加载` / "Not loaded" load that turn first, and a failed turn's error row jumps to that error in the conversation
|
|
64
71
|
- **Search**: open the box with the magnifier, click a result to locate and highlight it, Enter to step through matches, Esc to close
|
|
65
72
|
- **Search tolerance**: full-width/half-width, case and whitespace differences match automatically; for looser matching turn on the "fuzzy" switch next to the search box
|
|
66
73
|
- **Level filter**: click the round levels button in the header to pop down the H1–H6 switches
|
|
67
74
|
- **Moving and docking**: drag the top bar to move, ◀ / ▶ to switch sides
|
|
68
75
|
- **Resizing**: drag the right edge, bottom edge or bottom-right corner
|
|
69
76
|
- **Loading older turns**: scroll up inside the outline (it both expands the index and loads older conversation)
|
|
77
|
+
- **Back to the newest row**: after paging far up, click the floating button in the list's lower-right corner
|
|
70
78
|
- **Reading position**: scroll the conversation and the turn you are reading is boxed in blue; the outline follows
|
|
79
|
+
- **Settings**: expand the "Conversation Outline" card under **Settings → Plugins → Plugin configuration** for the language, the default docked edge, the heading levels shown and the fuzzy / hover / diagnostic switches; changed fields can be reset individually. The card and the panel are live in both directions, with no reload needed, and the preferences follow the DSH settings document
|
|
80
|
+
|
|
81
|
+
## Diagnostics
|
|
82
|
+
|
|
83
|
+
Mounting the panel prints **nothing** by default. To check the host facilities, expand the "Conversation Outline" card under **Settings → Plugins → Plugin configuration** and tick "print the mount diagnostic to the console" — the line prints on the spot, no reload needed:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
[dsh-quick-toc] panel mounted · turnOutline=… · jumpLoader=… · lang=… · prefs=…
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
A missing `turnOutline` means the host has no such projection, and the staged `jumpLoader` wording (`no-sessions-service` / `no-binding-api` / `no-binding-for-session` / `no-loadThrough` / `binding-threw`) pinpoints which link of the jump bridge is broken.
|
|
71
90
|
|
|
72
91
|
## Development
|
|
73
92
|
|
|
74
93
|
- `lib/client.js` — all UI logic (browser side)
|
|
75
|
-
- `lib/index.js` — host-
|
|
94
|
+
- `lib/index.js` — the host half: registers the `dsh-quick-toc` settings namespace (a schemastery schema with range validation), which puts the preferences into DSH's settings document and provides the plugin-configuration entry
|
|
76
95
|
- `cordis.patch.yml` — loader patch (official DSH bundle format)
|
|
77
96
|
- The panel registers into the session-scoped `conversation.input.overlay` slot so it receives session-scoped hooks (`useChat`, `useSession`, `sessionId`, …), and renders itself through `createPortal` into `document.body` as a fixed floating dock; conversation data comes from `props.useChat` (`ChatSnapshot.order` and `nodes`; node shape: `kind: user/assistant-step`, `location.turn`, `data.blocks`)
|
|
78
97
|
- The "unloaded turn" capability needs two host facilities: the `turnOutline` projection (the whole-session turn index, each entry carrying its `turn/start` seq) and the turn-jump loader (the client `sessions` service's `binding(sessionId).session.loadThrough(seq)`, reached through the client ctx's declaration-free `ctx.get("sessions")` lookup). Each degrades on its own: without the projection the outline lists loaded turns only, without the loader unloaded entries are shown but not jumped to, and nothing else in the panel is affected.
|
|
79
|
-
-
|
|
98
|
+
- The failure row reads the host's `turn-error` conversation node (published when `turn/end` carries an `error` reason, with `message` and an optional `code`); on a host without that node the row is simply absent and nothing else changes.
|
|
99
|
+
- Interface text lives in one string table at the top of `lib/client.js` (`DICTS`, one Chinese and one English copy) and the language setting picks between them: on `follow the host` the host's translate function (`ctx.locale.bind("dsh-quick-toc")`, fed by the same `DICTS` tables) is asked first and the built-in table is only the fallback. The two tables must stay key-aligned; the only Chinese-only entry is `time.beforeYesterday` (English carries the date for anything older than yesterday), while `time.yesterday` exists in both (`yesterday`).
|
|
100
|
+
- Preferences sit in two layers behind one module-level store: the Host settings document (`ctx.settingsScope.bind({ namespace: "dsh-quick-toc" })` — language, docked edge, levels, fuzzy, hover and diagnostic; authoritative on a loopback page) and `localStorage` (the mirror, plus the real storage for top offset / width / height, which describe this screen and are saved per browser). Writes are routed per field: host fields go through `scope.mutate` (folded in locally, reconciled when the host answers), everything else goes to `localStorage`. On a non-loopback page DSH marks settings read-only, so the six preferences fall back to the mirror and behave exactly as in 0.5.x; values left by a 0.5.x install are imported into the host layer once, the first time it answers (and only while the user layer is empty).
|
|
101
|
+
- The configuration card registers into the `settings.plugin.item` slot (keyed on the plugin's namespace; the slot is dispatched only for namespaces the Host actually serves, so a deployment without the host half simply shows no card and the panel is unaffected). The card and the panel share the store above, which is what makes the two live in both directions.
|
|
102
|
+
- Changes to `lib/client.js` show up after a page refresh (client modules are served under a content hash and DSH's client HMR pushes reloads); changes to `lib/index.js` (the host half) need a DSH restart
|
|
80
103
|
|
|
81
104
|
## License
|
|
82
105
|
|
package/README.md
CHANGED
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
- **按回合分组** —— 每条用户消息 + 其后续 AI 回复为一组,组头显示回合时间与首行预览,点击跳到该回合模型回答的开头
|
|
10
10
|
- **覆盖整段会话** —— 未加载进对话窗口的回合也在列表里(带「未加载」标记与预览);点击即加载该回合并跳过去
|
|
11
|
+
- **失败回合的报错** —— 请求超时 / 上游报错这类没有回复的回合显示 `请求失败` 与报错原文,点击跳到对话中的报错位置
|
|
12
|
+
- **中英双语** —— 界面语言可设为跟随宿主、中文或 English;中文时间戳用 `昨天` / `前天`,英文昨天用 `yesterday`、更早用 `YY-MM-DD HH:MM` 日期
|
|
13
|
+
- **插件配置卡片** —— 设置 → 插件 → 插件配置里的「对话大纲」卡片:语言、默认停靠边缘、显示的标题层级、模糊搜索、悬停预览与诊断开关;改过的字段标「已自定义」并可单独重置,卡片与面板实时同步
|
|
14
|
+
- **回合时间带日期** —— 昨天 `昨天 15:04`、前天 `前天 15:04`、更早 `25-09-11 15:04`,跨天的会话里时间不再重影
|
|
11
15
|
- **标题行副标题** —— 每行标题下方显示该节正文的第一句,同名标题一眼可辨
|
|
12
16
|
- **悬停预览** —— 悬停标题行显示该节开头、回合时间与层级路径
|
|
13
17
|
- **搜索** —— 标题 / 全文两种范围,结果列表点击定位并高亮,`n/N` 回车逐处跳,Esc 关闭
|
|
@@ -16,8 +20,9 @@
|
|
|
16
20
|
- **组头吸顶** —— 滚动大纲时,当前回合的组头固定在面板顶部
|
|
17
21
|
- **层级筛选** —— 标题栏的圆形层级按钮弹出 H1–H6 开关,任意组合显示
|
|
18
22
|
- **自动跟随** —— 滚动对话时正在阅读的回合自动点亮(封闭蓝框),大纲自动跟随
|
|
19
|
-
- **跳转** ——
|
|
20
|
-
-
|
|
23
|
+
- **跳转** —— 点击标题跳到对话中该标题的位置(滚动动画由插件逐帧绘制,不依赖浏览器的「平滑滚动」——部分环境会把它直接执行成瞬移;每帧重瞄目标实时位置,宿主翻页改变偏移也能落准,跨页远跳不会半途停下);面板与对话双向定位
|
|
24
|
+
- **回到底部** —— 往上翻远之后,列表右下角的浮动按钮一步回到最新一条(不在底部时出现、到底后消失)
|
|
25
|
+
- **可停靠、可缩放** —— 拖顶部横条移动,◀ / ▶ 切换左右停靠,拖边缘调宽高,收起后成为边缘把手;位置与尺寸按浏览器记住(顶边距、宽度、高度只通过拖拽调整)
|
|
21
26
|
- **分页** —— 默认显示最近的若干组,向上滚动既展开索引也加载更早的对话
|
|
22
27
|
- **边界提示** —— 滚到最早或最新再继续滚动时,面板底部短暂提示
|
|
23
28
|
- **Markdown 感知** —— 标题中的行内标记会被剥离;围栏代码块里的 `#` 行不算标题
|
|
@@ -28,13 +33,15 @@
|
|
|
28
33
|
|
|
29
34
|
| 插件版本 | 支持的 DSH 版本 |
|
|
30
35
|
| --- | --- |
|
|
31
|
-
| **0.
|
|
32
|
-
| 0.
|
|
33
|
-
| 0.4.0 | 0.1.5-rc.1、0.1.5-rc.2 |
|
|
34
|
-
| 0.3.3 | 0.1.5-rc.1 |
|
|
35
|
-
| 0.
|
|
36
|
+
| **0.6.x**(最新,0.6.0) | 0.1.5-rc.1、0.1.5-rc.2 |
|
|
37
|
+
| 0.5.x(0.5.1) | 0.1.5-rc.1、0.1.5-rc.2 |
|
|
38
|
+
| 0.4.x(0.4.1) | 0.1.5-rc.1、0.1.5-rc.2 |
|
|
39
|
+
| 0.3.x(0.3.3) | 0.1.5-rc.1 |
|
|
40
|
+
| 0.2.x(0.2.2) | = 0.1.2-rc.1 |
|
|
36
41
|
|
|
37
|
-
|
|
42
|
+
每个大版本只列该系列最新的一个补丁版本(新功能引入的缺陷都在其后的补丁里修掉了,所以同一个大版本内直接用最新补丁即可;旧补丁仍可继续用,插件不破坏既有接口)。
|
|
43
|
+
|
|
44
|
+
`engines.dsh` 下限为 **0.1.5-rc.1**(`>=`,该版本起插件改用会话级槽位注入的宿主接口)。0.6.0 在 **0.1.5-rc.2** 上实测通过(含宿主半的设置命名空间注册);**0.1.5-rc.1** 上实测了插件加载与客户端模块下发(宿主启动正常、boot graph 中 `dsh-quick-toc/client.js` 的 rev 与本仓库 `lib/client.js` 逐字节一致),它依赖的宿主接口——`turnOutline` 投影、会话级槽位的 `useProjection`、客户端 `sessions` 服务与 `loadThrough` 跳转加载器(0.5.0 起)、失败回合所用的 `turn-error` 节点(0.5.1 起)、以及 0.6.0 新增的宿主 `settings` 服务(`installSection`)、客户端 `settingsScope` 与 `settings.plugin.item` 配置卡片槽位——在 0.1.5-rc.1 与 0.1.5-rc.2 的安装包中逐个核对存在(这些宿主包的代码在两版之间逐字节相同,`dsh-client-ui-chat` 仅差一条与本插件无关的 CSS 声明),因此两版都声明兼容。更早或更新的 DSH 版本未经验证,不作声明;在更早的 DSH 上可安装的最新插件版本是 **0.3.2**。安装或更新时,DSH 市场会依据 `package.json` 中的 `engines.dsh`、`dsh.compatibility.dshReleases` 与 `peerDependencies` 做宿主兼容预检。
|
|
38
45
|
|
|
39
46
|
## 安装
|
|
40
47
|
|
|
@@ -60,23 +67,39 @@ dsh plugin --profile web add <插件目录路径>
|
|
|
60
67
|
|
|
61
68
|
## 使用
|
|
62
69
|
|
|
63
|
-
-
|
|
70
|
+
- **跳转**:点击大纲标题或组头跳到对应位置;带「未加载」标记的条目会先把该回合加载进来再跳;失败回合点报错行跳到对话中的报错位置
|
|
64
71
|
- **搜索**:放大镜打开搜索框,输入后点结果定位并高亮,回车逐处跳,Esc 关闭
|
|
65
72
|
- **搜索容错**:全角/半角、大小写、空格差异会自动匹配;需要更宽松时点搜索框右侧的「模糊」开关
|
|
66
73
|
- **层级筛选**:点标题栏的圆形层级按钮弹出 H1–H6 开关,选择显示的层级
|
|
67
74
|
- **移动与停靠**:拖顶部横条移动,◀ / ▶ 切换左右停靠
|
|
68
75
|
- **调整大小**:拖右边缘、下边缘或右下角
|
|
69
76
|
- **加载更早**:在大纲中向上滚动(既展开索引,也加载更早的对话)
|
|
77
|
+
- **回到底部**:翻远了之后点列表右下角的浮动按钮回到最新一条
|
|
70
78
|
- **阅读位置**:滚动对话,正在阅读的回合会以蓝框标出;大纲会自动跟随
|
|
79
|
+
- **设置**:在 **设置 → 插件 → 插件配置** 里展开「对话大纲」卡片,可改语言、默认停靠边缘、显示的标题层级与模糊/悬停/诊断开关;改过的字段可单独重置。卡片与面板实时同步,不需要刷新;偏好保存在 DSH 的设置里,跟随配置走
|
|
80
|
+
|
|
81
|
+
## 诊断
|
|
82
|
+
|
|
83
|
+
面板挂载时默认**不打印**任何日志。需要排查宿主能力时,在 **设置 → 插件 → 插件配置** 里展开「对话大纲」卡片、勾选「在控制台打印诊断日志」——打开后当下就会打印一行(无需刷新):
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
[dsh-quick-toc] panel mounted · turnOutline=… · jumpLoader=… · lang=… · prefs=…
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`turnOutline` 缺失说明宿主没有该投影,`jumpLoader` 的分阶段措辞(`no-sessions-service` / `no-binding-api` / `no-binding-for-session` / `no-loadThrough` / `binding-threw`)可直接定位跳转桥断在哪一环。
|
|
71
90
|
|
|
72
91
|
## 开发
|
|
73
92
|
|
|
74
93
|
- `lib/client.js` —— 全部 UI 逻辑(浏览器端)
|
|
75
|
-
- `lib/index.js` ——
|
|
94
|
+
- `lib/index.js` —— 宿主半:注册 `dsh-quick-toc` 设置命名空间(schemastery schema,含取值范围校验),让偏好进入 DSH 的设置文档并提供插件配置卡片的入口
|
|
76
95
|
- `cordis.patch.yml` —— loader patch(符合官方 bundle 规范)
|
|
77
96
|
- 面板注册进会话级 `conversation.input.overlay` 槽以取得会话级 hook(`useChat`、`useSession`、`sessionId` 等),面板本体通过 `createPortal` 渲染到 `document.body` 成为固定浮层;对话数据来自 `props.useChat`(`ChatSnapshot.order` 与 `nodes`,节点形状:`kind: user/assistant-step`、`location.turn`、`data.blocks`)
|
|
78
97
|
- 「未加载回合」能力依赖宿主的两样东西:`turnOutline` 投影(整段会话的回合索引,每条含 `turn/start` 的 seq)与会话跳转加载器(客户端 `sessions` 服务的 `binding(sessionId).session.loadThrough(seq)`,通过客户端 ctx 的 `ctx.get("sessions")` 免声明查找取得)。两者各自独立降级:没有投影时只列已加载回合,没有加载器时未加载条目只展示、不跳转,面板其余功能不受影响。
|
|
79
|
-
-
|
|
98
|
+
- 失败回合的报错行读的是宿主的 `turn-error` 会话节点(宿主在 `turn/end` 的原因为 `error` 时发布,含 `message` 与可选的 `code`);宿主不提供该节点时只是不显示这一行,其余功能不受影响。
|
|
99
|
+
- 界面文字来自 `lib/client.js` 顶部的一张字符串表(`DICTS`,中英各一份),语言设置决定用哪一份:`跟随宿主` 时优先问宿主的翻译函数(`ctx.locale.bind("dsh-quick-toc")`,注册的表就来自 `DICTS`),拿不到才回退到内置表。中英两份表的键必须对齐(仅 `time.beforeYesterday`(前天)是中文独有——英文对更早的时间直接用日期;`time.yesterday` 两语言都有,英文作 `yesterday`)。
|
|
100
|
+
- 偏好存储分两层,由一个模块级 store 统一读出:宿主设置文档(`ctx.settingsScope.bind({ namespace: "dsh-quick-toc" })`,语言/停靠边/层级/模糊/悬停/诊断六项,回环页面上是权威层)与 `localStorage`(镜像 + 顶边距/宽度/高度三项的正式存储——它们描述"这一块屏幕",按浏览器保存)。写入按字段路由:宿主字段走 `scope.mutate`(本地同步折叠、宿主应答后对账),其余写 `localStorage`。非回环页面 DSH 将设置标记为只读,此时六项偏好退回本地镜像,行为与 0.5.x 一致;0.5.x 留下的本地值会在宿主层首次应答时导入一次(仅当用户层为空)。
|
|
101
|
+
- 插件配置卡片注册进 `settings.plugin.item` 槽(`key` 为插件命名空间;该槽按宿主实际提供的命名空间派发,宿主半未加载时卡片自然不出现,面板不受影响);卡片与面板共享上面那个 store,因此两边实时互通。
|
|
102
|
+
- 修改 `lib/client.js` 后刷新页面即可看到变化(客户端模块按内容哈希发版,DSH 的客户端 HMR 也会推送重载);改 `lib/index.js`(宿主半)需重启 DSH
|
|
80
103
|
|
|
81
104
|
## License
|
|
82
105
|
|