dsh-quick-toc 0.3.2 → 0.3.3
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 +78 -0
- package/CHANGELOG.md +55 -45
- package/README.en.md +29 -27
- package/README.md +28 -26
- package/lib/client.js +96 -8
- package/package.json +5 -5
package/CHANGELOG.en.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to **dsh-quick-toc** are documented here. Chinese version: [CHANGELOG.md](CHANGELOG.md).
|
|
4
|
+
|
|
5
|
+
## [0.3.3] - 2026-09-10
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- The panel and its collapsed edge handle fade out while the center column shows another view (trajectory, context, plugin views) and fade back in on the chat view. The check polls lightly (120 ms) and falls back to visible whenever the active view cannot be determined.
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Compatibility is declared for DSH `0.1.5-rc.1` only (`engines.dsh`, `dsh.compatibility.dshReleases` and `peerDependencies`), which is the version this plugin is verified against.
|
|
12
|
+
- READMEs updated: the feature list and the usage section now cover search, search-scope switching, in-chat highlighting and turn jumping, and the compatibility table lists the supported DSH version of the last two releases.
|
|
13
|
+
- GitHub release bodies now default to the Chinese CHANGELOG section with the English section folded below it, and the changelog is split into `CHANGELOG.md` (Chinese, default) and `CHANGELOG.en.md` (English).
|
|
14
|
+
|
|
15
|
+
## [0.3.2] - 2026-09-08
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Documentation pass: the compatibility matrix and feature list in the READMEs are refreshed, and the npm package description now mentions keyword search and in-chat highlighting.
|
|
19
|
+
|
|
20
|
+
## [0.3.1] - 2026-09-08
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
- Panel and collapsed edge handle no longer float above DSH modals: the base z-index is now 500 (above app popovers at z 100 and the transcript width handles at z 8, but below DSH's modal layer at z 1000), so opening Settings covers the outline instead of the outline sitting on top of it.
|
|
24
|
+
- Circular controls are true circles again on DSH 0.1.5-rc.1: the theme applies `corner-shape: superellipse(1.5)` to every element, which turned `border-radius: 50%` into a squircle. The icon buttons, search-scope toggle, top drag bar and edge handle now declare `corner-shape: round`.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- Compatibility declaration also lists DSH `0.1.5-rc.1` (verified compatible; `engines.dsh` stays `>=0.1.2-rc.1`).
|
|
28
|
+
|
|
29
|
+
## [0.3.0] - 2026-08-24
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
- Compatibility with the then-current DSH 0.1.2-rc.1: the removed `@deepseek-ai/dsh-client-runtime` package no longer breaks plugin loading (externals drift). Runtime hooks now arrive as session-scope slot props.
|
|
33
|
+
- Conversation data access moved from `useSession(s => s.chat.*)` to the session-scope `useChat` hook (`ChatSnapshot.order` + `nodes` map, contributed by `dsh-client-ui-chat`). Node shape unchanged (`kind: user/assistant-step`, `location.turn`, `data.blocks`), so grouping / search / highlight / jump logic is untouched.
|
|
34
|
+
- Panel mount moved into the session-scoped `conversation.input.overlay` slot. In that DSH version session-scoped hooks only reach a declared *session* slot; a frame-floating `shell.overlay` occupant's `SessionProvider` binds to the root binding (no session id) and rendered the panel slot empty. The panel still draws its own fixed, frame-floating dock (position: fixed), so the overlay seat is only the hook source.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
- `dsh.client.inject` now lists `dsh-client-ui-chat` / `dsh-client-ui-conversation` / `dsh-client-ui-layout` instead of the removed runtime package.
|
|
38
|
+
- Dropped the unused `sessions` service from the client inject list.
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
- Version guard: `dsh.compatibility.dshReleases` declares `0.1.2-rc.1: compatible` and `engines.dsh: ">=0.1.2-rc.1"` (dshmarket install-time host-compat preflight); peerDependencies pin `dsh-client-ui-chat` / `dsh-client-ui-conversation` `>=0.1.2-rc.1`. The panel degrades gracefully with a console warning when the `chat` hook is unavailable (older hosts).
|
|
42
|
+
|
|
43
|
+
## [0.2.2] - 2026-08-24
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
- Keyword search: header magnifier button opens a search box; Enter cycles through matches (n/N counter); Escape or the magnifier toggles it closed
|
|
47
|
+
- Search scope toggle: 标题 (heading titles only) or 全文 (also user messages and AI reply texts)
|
|
48
|
+
- In-chat match highlighting: matched keywords are highlighted in the conversation; the current match gets a distinct highlight and is scrolled to the upper-middle of the viewport
|
|
49
|
+
- Every occurrence counts toward n/N (multiple hits in one message = multiple matches)
|
|
50
|
+
- Heading-less turns get a standalone time entry; all group headers show the turn's first-line preview next to the time (click to jump)
|
|
51
|
+
|
|
52
|
+
### Changed
|
|
53
|
+
- Panel collapse animation unified for both docks: clip-path hides the panel at the sidebar/screen edge (shadow removed to avoid clipping artifacts)
|
|
54
|
+
- Inactive outline groups dimmed to 0.6 opacity
|
|
55
|
+
|
|
56
|
+
## [0.1.1] - 2026-08-17
|
|
57
|
+
|
|
58
|
+
### Changed
|
|
59
|
+
- Release workflow also uploads a stable-named tarball (`dsh-quick-toc.tgz`) so `/releases/latest/download/` always resolves to the newest release
|
|
60
|
+
|
|
61
|
+
## [0.1.0] - 2026-08-17
|
|
62
|
+
|
|
63
|
+
### Added
|
|
64
|
+
- Turn-grouped outline: each user message + its AI replies form one group, with the group's end time as the header
|
|
65
|
+
- Auto-follow highlight: turns visible in the conversation viewport light up in the outline (multiple at once); the outline auto-loads and scrolls to keep them visible
|
|
66
|
+
- Smooth jump: clicking a heading glides to the exact heading position in the conversation (with a small top offset)
|
|
67
|
+
- Dock left/right with a draggable top bar, resizable from the edges/corner, collapsible into an edge handle (click it to expand)
|
|
68
|
+
- Scrollbar follows the dock side (left when docked left, right when docked right)
|
|
69
|
+
- Paged rendering: latest groups first; scrolling the outline to the top loads older groups
|
|
70
|
+
- Auto "load older": when the outline reaches the top with everything loaded, it clicks the conversation's own load-more button
|
|
71
|
+
- Header time jump: clicking a group's time label jumps to that turn's start
|
|
72
|
+
- Markdown-aware titles: `**bold**`, `*italic*`, `` `code` ``, `[links](url)`, `~~strike~~` stripped from heading text
|
|
73
|
+
- Persisted panel state (dock side, position, size) with automatic migration from older key names
|
|
74
|
+
- Auto-hides when the conversation has no headings; light/dark theme support
|
|
75
|
+
|
|
76
|
+
### Published
|
|
77
|
+
- npm: `dsh-quick-toc@0.1.0`
|
|
78
|
+
- GitHub: `LyaxZ/dsh-quick-toc` with auto-release workflow (tag push -> npm pack -> release asset)
|
package/CHANGELOG.md
CHANGED
|
@@ -1,68 +1,78 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 更新日志
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**dsh-quick-toc** 的重要变更都记录在这里。英文版见 [CHANGELOG.en.md](CHANGELOG.en.md)。
|
|
4
|
+
|
|
5
|
+
## [0.3.3] - 2026-09-10
|
|
6
|
+
|
|
7
|
+
### 新增
|
|
8
|
+
- 中间列切到其他视图(轨迹、上下文、插件视图)时,大纲面板与收起后的边缘把手会渐隐,切回对话视图时渐显。检测为轻量轮询(120ms);无法判断当前视图时按"可见"处理。
|
|
9
|
+
|
|
10
|
+
### 变更
|
|
11
|
+
- 兼容性只声明 DSH `0.1.5-rc.1`(`engines.dsh`、`dsh.compatibility.dshReleases` 与 `peerDependencies`),即本插件验证过的版本。
|
|
12
|
+
- README 更新:功能列表与「使用」章节补齐搜索、搜索范围切换、对话内高亮与回合跳转;兼容表列出最近两个版本各自支持的 DSH 版本。
|
|
13
|
+
- GitHub Release 的描述默认取中文 CHANGELOG 段落,英文段落折叠在其下方可展开;CHANGELOG 拆分为 `CHANGELOG.md`(中文,默认)与 `CHANGELOG.en.md`(英文)。
|
|
4
14
|
|
|
5
15
|
## [0.3.2] - 2026-09-08
|
|
6
16
|
|
|
7
|
-
###
|
|
8
|
-
-
|
|
17
|
+
### 变更
|
|
18
|
+
- 文档整理:README 的兼容表与功能列表更新,npm 包描述补充了关键字搜索与对话内高亮。
|
|
9
19
|
|
|
10
20
|
## [0.3.1] - 2026-09-08
|
|
11
21
|
|
|
12
|
-
###
|
|
13
|
-
-
|
|
14
|
-
-
|
|
22
|
+
### 修复
|
|
23
|
+
- 面板与收起把手不再浮在 DSH 弹层之上:基础 z-index 改为 500(高于应用弹出层 z100 与对话宽度手柄 z8,低于 DSH 弹层 z1000),打开设置时设置面板会盖住大纲。
|
|
24
|
+
- 圆形控件在 DSH 0.1.5-rc.1 上恢复为正圆:主题对所有元素应用了 `corner-shape: superellipse(1.5)`,会把 `border-radius: 50%` 变成方圆角;图标按钮、搜索范围切换、顶部拖条与边缘把手现声明 `corner-shape: round`。
|
|
15
25
|
|
|
16
|
-
###
|
|
17
|
-
-
|
|
26
|
+
### 变更
|
|
27
|
+
- 兼容声明加入 DSH `0.1.5-rc.1`(当时 `engines.dsh` 仍为 `>=0.1.2-rc.1`)。
|
|
18
28
|
|
|
19
29
|
## [0.3.0] - 2026-08-24
|
|
20
30
|
|
|
21
|
-
###
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
31
|
+
### 修复
|
|
32
|
+
- 适配当时的目标版本 DSH 0.1.2-rc.1:已被移除的 `@deepseek-ai/dsh-client-runtime` 不再导致插件加载失败(externals drift),运行时 hook 改为由会话作用域槽位的 props 注入。
|
|
33
|
+
- 对话数据访问由 `useSession(s => s.chat.*)` 改为会话作用域的 `useChat`(`ChatSnapshot.order` + `nodes`,由 `dsh-client-ui-chat` 贡献);节点形状未变(`kind: user/assistant-step`、`location.turn`、`data.blocks`),因此分组、搜索、高亮与跳转逻辑未受影响。
|
|
34
|
+
- 面板挂载改到会话作用域的 `conversation.input.overlay` 槽:该版本中会话级 hook 只到达已声明的会话槽,而 root 作用域 `shell.overlay` 里的 `SessionProvider` 绑定的是无 sessionId 的 root binding,导致子槽始终空渲染。面板本体仍以 `position: fixed` 自绘浮层,挂载槽只作为 hook 来源。
|
|
25
35
|
|
|
26
|
-
###
|
|
27
|
-
- `dsh.client.inject`
|
|
28
|
-
-
|
|
36
|
+
### 变更
|
|
37
|
+
- `dsh.client.inject` 改为列出 `dsh-client-ui-chat` / `dsh-client-ui-conversation` / `dsh-client-ui-layout`,替代已移除的运行时包。
|
|
38
|
+
- 从客户端 inject 列表中移除未使用的 `sessions` 服务。
|
|
29
39
|
|
|
30
|
-
###
|
|
31
|
-
-
|
|
40
|
+
### 新增
|
|
41
|
+
- 版本守卫:`dsh.compatibility.dshReleases` 与 `engines.dsh` 声明(供 dshmarket 安装时做宿主兼容预检),并以 peerDependencies 约束相关 DSH 包版本;`chat` hook 不可用时,面板以控制台警告优雅降级。
|
|
32
42
|
|
|
33
43
|
## [0.2.2] - 2026-08-24
|
|
34
44
|
|
|
35
|
-
###
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
45
|
+
### 新增
|
|
46
|
+
- 关键字搜索:标题栏放大镜打开搜索框,回车逐处跳转(`n/N` 计数),Esc 或再次点击放大镜关闭
|
|
47
|
+
- 搜索范围切换:仅标题,或同时搜索用户消息与 AI 回复正文
|
|
48
|
+
- 对话内高亮:命中的关键字在对话中高亮,当前命中单独标亮并滚动到视口中上部
|
|
49
|
+
- 同一条消息内的多次命中都计入 `n/N`
|
|
50
|
+
- 无标题的回合也有独立的时间条目;所有组头在时间旁显示该回合首行预览(点击跳转)
|
|
41
51
|
|
|
42
|
-
###
|
|
43
|
-
-
|
|
44
|
-
-
|
|
52
|
+
### 变更
|
|
53
|
+
- 两种停靠的面板收起动画统一:由 clip-path 在侧栏/屏幕边缘裁切(移除阴影,避免裁切残影)
|
|
54
|
+
- 非激活的大纲组降到 0.6 不透明度
|
|
45
55
|
|
|
46
56
|
## [0.1.1] - 2026-08-17
|
|
47
57
|
|
|
48
|
-
###
|
|
49
|
-
-
|
|
58
|
+
### 变更
|
|
59
|
+
- 发布流程额外上传稳定命名的 tarball(`dsh-quick-toc.tgz`),使 `/releases/latest/download/` 始终解析到最新版本
|
|
50
60
|
|
|
51
61
|
## [0.1.0] - 2026-08-17
|
|
52
62
|
|
|
53
|
-
###
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
- Markdown
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
|
|
66
|
-
###
|
|
67
|
-
- npm
|
|
68
|
-
- GitHub
|
|
63
|
+
### 新增
|
|
64
|
+
- 按回合分组的大纲:每条用户消息与其后续 AI 回复为一组,组头显示该组的结束时间
|
|
65
|
+
- 自动跟随高亮:对话视口内可见的回合在大纲中点亮(可同时多组);大纲自动加载并滚动,使其保持可见
|
|
66
|
+
- 平滑跳转:点击标题平滑滚动到对话中该标题的位置(带少量顶部偏移)
|
|
67
|
+
- 左右停靠(拖顶部横条移动)、从边缘/角部调整大小、收起为边缘把手(点击展开)
|
|
68
|
+
- 滚动条随停靠方向(停靠左侧时在左,停靠右侧时在右)
|
|
69
|
+
- 分页渲染:默认显示最新的若干组;在大纲中滚到顶部加载更早的组
|
|
70
|
+
- 自动「加载更早」:大纲到达顶部且已全部加载时,会点击对话自身的「加载更多」按钮
|
|
71
|
+
- 组头时间跳转:点击组的时间标签跳到该回合开头
|
|
72
|
+
- Markdown 感知标题:剥离 `**加粗**`、`*斜体*`、`` `代码` ``、`[链接](url)`、`~~删除线~~`
|
|
73
|
+
- 面板状态持久化(停靠边、位置、尺寸),并从旧键名自动迁移
|
|
74
|
+
- 对话无标题时自动隐藏;支持亮/暗主题
|
|
75
|
+
|
|
76
|
+
### 发布
|
|
77
|
+
- npm:`dsh-quick-toc@0.1.0`
|
|
78
|
+
- GitHub:`LyaxZ/dsh-quick-toc`,带自动发布流程(推送标签 → npm pack → release 资产)
|
package/README.en.md
CHANGED
|
@@ -2,66 +2,68 @@
|
|
|
2
2
|
|
|
3
3
|
> **English** | [中文](README.md)
|
|
4
4
|
|
|
5
|
-
A
|
|
5
|
+
A conversation TOC plugin for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH): it turns the Markdown headings (H1–H6) of AI replies into a navigable outline panel, grouped by conversation turn, with auto-follow highlighting, keyword search and in-chat match highlighting.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
- **Turn-grouped outline** — each user message
|
|
10
|
-
- **Keyword search** —
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
17
|
-
-
|
|
9
|
+
- **Turn-grouped outline** — each user message plus its following AI replies form one group; the group header shows the turn's end time and a first-line preview, and clicking it jumps to the start of the turn
|
|
10
|
+
- **Keyword search** — the magnifier in the panel header opens a search box; press **Enter** to jump to the next match (wrapping), **Esc** to close, with an `n/N` match counter
|
|
11
|
+
- **Search scope toggle** — the **title / full-text** button in the search box switches between searching heading titles only and also searching user messages plus AI reply text
|
|
12
|
+
- **In-chat highlighting** — matched keywords are highlighted in the conversation; the current match is highlighted distinctly and scrolled into the upper part of the viewport; every occurrence inside a message counts toward `n/N`
|
|
13
|
+
- **Auto-follow highlighting** — while scrolling the conversation, the turns visible in the viewport light up in the outline (several at once) and the rest dim; the outline loads and scrolls so the group being read stays visible
|
|
14
|
+
- **Jumping** — click a heading to jump to its position in the conversation, or click a group header's time/preview to jump to the start of that turn
|
|
15
|
+
- **Dockable and resizable** — drag the top bar to move the panel, use ◀ / ▶ to dock it left or right, drag an edge or corner to resize, and collapse it into an edge handle (click it to expand); the panel's position and size are remembered
|
|
16
|
+
- **Paging and loading older** — the most recent groups show first; scrolling up inside the outline loads older groups
|
|
17
|
+
- **Markdown-aware titles** — inline markup in headings (`**bold**`, `*italic*`, `` `code` ``, `[links](url)`, `~~strike~~`) is stripped before display
|
|
18
|
+
- **Chat view only** — when the center column switches to another view (trajectory, context, …), the panel and its edge handle fade out
|
|
19
|
+
- The panel hides itself when the conversation has no headings; it adapts to the dark and light themes (the inner-shadow card follows the theme)
|
|
18
20
|
|
|
19
21
|
## Compatibility
|
|
20
22
|
|
|
21
|
-
| Plugin | DSH |
|
|
23
|
+
| Plugin | Supported DSH |
|
|
22
24
|
| --- | --- |
|
|
23
|
-
| **0.3.
|
|
24
|
-
| 0.3.
|
|
25
|
-
| 0.2.2 | DSH versions before 0.1.2-rc.1 (install as `dsh-quick-toc@legacy`) |
|
|
25
|
+
| **0.3.3** (latest) | 0.1.5-rc.1 |
|
|
26
|
+
| 0.3.2 | ≥ 0.1.2-rc.1 |
|
|
26
27
|
|
|
27
|
-
0.
|
|
28
|
+
The latest version has only been verified against **DSH 0.1.5-rc.1**, so that is the only version it declares; older 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`.
|
|
28
29
|
|
|
29
30
|
## Install
|
|
30
31
|
|
|
31
|
-
With the DSH CLI
|
|
32
|
+
With the DSH CLI:
|
|
32
33
|
|
|
33
34
|
```
|
|
34
35
|
dsh plugin --profile web add dsh-quick-toc
|
|
35
36
|
```
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
Or from GitHub:
|
|
38
39
|
|
|
39
40
|
```
|
|
40
41
|
dsh plugin --profile web add github:LyaxZ/dsh-quick-toc
|
|
41
42
|
```
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
Or from a local folder:
|
|
44
45
|
|
|
45
46
|
```
|
|
46
|
-
dsh plugin --profile web add <path-to-
|
|
47
|
+
dsh plugin --profile web add <path-to-the-plugin-folder>
|
|
47
48
|
```
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
After installing, restart DSH and open the Web UI. The panel starts collapsed; click the edge handle next to the conversation to expand it.
|
|
50
51
|
|
|
51
52
|
## Usage
|
|
52
53
|
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
54
|
+
- **Jumping**: click a heading in the outline to jump to its position; click a group header's time or first-line preview to jump to the start of that turn
|
|
55
|
+
- **Search**: click the magnifier in the header to open the search box, type a keyword and press Enter to step through matches (`n/N` shows the current position and the total); press Esc or the magnifier again to close it; use the **title / full-text** button to change the search scope
|
|
56
|
+
- **Moving and docking**: drag the top bar to move the panel; use ◀ / ▶ to switch between left and right docking
|
|
57
|
+
- **Resizing**: drag the right edge for width, the bottom edge for height, or the bottom-right corner for both
|
|
58
|
+
- **Loading older turns**: scroll up inside the outline to load older groups; when the conversation itself offers a "load older messages" button, the outline also triggers it on reaching the top
|
|
57
59
|
|
|
58
60
|
## Development
|
|
59
61
|
|
|
60
62
|
- `lib/client.js` — all UI logic (browser side)
|
|
61
|
-
- `lib/index.js` — host-side
|
|
63
|
+
- `lib/index.js` — host-side entry (empty; this plugin ships browser-side UI only)
|
|
62
64
|
- `cordis.patch.yml` — loader patch (official DSH bundle format)
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
+
- 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`)
|
|
66
|
+
- Changes to `lib/client.js` take effect after restarting DSH
|
|
65
67
|
|
|
66
68
|
## License
|
|
67
69
|
|
package/README.md
CHANGED
|
@@ -6,62 +6,64 @@
|
|
|
6
6
|
|
|
7
7
|
## 功能
|
|
8
8
|
|
|
9
|
-
- **按回合分组** —— 每条用户消息 + 其后续 AI
|
|
10
|
-
- **关键字搜索** ——
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
9
|
+
- **按回合分组** —— 每条用户消息 + 其后续 AI 回复为一组;组头显示该组最后一条消息的结束时间,并附带该回合首行预览,点击可跳到回合开头
|
|
10
|
+
- **关键字搜索** —— 标题栏放大镜打开搜索框;输入后按 **回车** 跳到下一处命中(循环),按 **Esc** 关闭;命中计数以 `n/N` 显示
|
|
11
|
+
- **搜索范围切换** —— 搜索框内的 **标题 / 全文** 按钮切换范围:仅标题,或同时搜索用户消息与 AI 回复正文
|
|
12
|
+
- **对话内高亮** —— 命中的关键字在对话中高亮,当前命中单独标亮并滚动到视口上部;同一条消息中的多次命中都会计入 `n/N`
|
|
13
|
+
- **自动跟随高亮** —— 滚动对话时,视口内可见的回合在大纲中自动点亮(可同时点亮多组),其余组变暗;大纲自动加载并滚动,使正在阅读的组保持可见
|
|
14
|
+
- **跳转** —— 点击标题跳到对话中该标题所在位置;点击组头的时间或预览跳到该回合开头
|
|
15
|
+
- **可停靠、可缩放** —— 拖顶部横条移动,按 ◀ / ▶ 切换左右停靠,拖边缘或角部调整宽高,收起后成为边缘把手(点击展开);面板位置与尺寸会被记住
|
|
16
|
+
- **分页与加载更早** —— 默认显示最近的若干组;在大纲中向上滚动(或滚动到顶部)会加载更早的组
|
|
17
|
+
- **Markdown 清理** —— 标题中的行内标记(`**加粗**`、`*斜体*`、`` `代码` ``、`[链接](url)`、`~~删除线~~`)会被剥离后显示
|
|
18
|
+
- **仅对话视图显示** —— 中间列切到轨迹、上下文等其他视图时,面板与边缘把手渐隐
|
|
19
|
+
- 对话中没有标题时面板自动隐藏;适配深色与浅色主题(内阴影质感随主题切换)
|
|
18
20
|
|
|
19
21
|
## 兼容性
|
|
20
22
|
|
|
21
|
-
| 插件版本 | DSH 版本 |
|
|
23
|
+
| 插件版本 | 支持的 DSH 版本 |
|
|
22
24
|
| --- | --- |
|
|
23
|
-
| **0.3.
|
|
24
|
-
| 0.3.
|
|
25
|
-
| 0.2.2 | 0.1.2-rc.1 之前的旧版 DSH(npm 上 `dsh-quick-toc@legacy`) |
|
|
25
|
+
| **0.3.3**(最新) | 0.1.5-rc.1 |
|
|
26
|
+
| 0.3.2 | ≥ 0.1.2-rc.1 |
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
最新版目前只在 **DSH 0.1.5-rc.1** 上验证过,因此仅声明该版本兼容;更早的 DSH 版本未经验证,不作声明。使用更早版本 DSH 时,可用的最新插件版本是 **0.3.2**。安装或更新时,DSH 市场会依据 `package.json` 中的 `engines.dsh`、`dsh.compatibility.dshReleases` 与 `peerDependencies` 做宿主兼容预检。
|
|
28
29
|
|
|
29
30
|
## 安装
|
|
30
31
|
|
|
31
|
-
通过 DSH CLI
|
|
32
|
+
通过 DSH CLI 安装:
|
|
32
33
|
|
|
33
34
|
```
|
|
34
35
|
dsh plugin --profile web add dsh-quick-toc
|
|
35
36
|
```
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
也可以从 GitHub 安装:
|
|
38
39
|
|
|
39
40
|
```
|
|
40
41
|
dsh plugin --profile web add github:LyaxZ/dsh-quick-toc
|
|
41
42
|
```
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
或以本地目录安装:
|
|
44
45
|
|
|
45
46
|
```
|
|
46
|
-
dsh plugin --profile web add
|
|
47
|
+
dsh plugin --profile web add <插件目录路径>
|
|
47
48
|
```
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
安装后重启 DSH 并打开 Web UI。面板默认收起,点击对话区边缘的把手即可展开。
|
|
50
51
|
|
|
51
52
|
## 使用
|
|
52
53
|
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
54
|
+
- **跳转**:点击大纲标题跳到该标题所在位置;点击组头的时间或首行预览跳到该回合开头
|
|
55
|
+
- **搜索**:点击标题栏的放大镜展开搜索框,输入关键字后按回车逐处跳转(`n/N` 显示当前位置与命中总数),按 Esc 或再次点击放大镜关闭;用 **标题 / 全文** 按钮切换搜索范围
|
|
56
|
+
- **移动与停靠**:拖顶部横条移动面板,按 ◀ / ▶ 在左右之间切换停靠
|
|
57
|
+
- **调整大小**:拖右边缘调宽度、拖下边缘调高度、拖右下角同时调整
|
|
58
|
+
- **加载更早**:在大纲中向上滚动即可加载更早的回合;对话本身有"加载更早消息"按钮时,大纲滚到顶部也会触发它
|
|
57
59
|
|
|
58
60
|
## 开发
|
|
59
61
|
|
|
60
62
|
- `lib/client.js` —— 全部 UI 逻辑(浏览器端)
|
|
61
|
-
- `lib/index.js` ——
|
|
63
|
+
- `lib/index.js` —— 宿主端入口(空实现;本插件只提供浏览器端 UI)
|
|
62
64
|
- `cordis.patch.yml` —— loader patch(符合官方 bundle 规范)
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
+
- 面板注册进会话级 `conversation.input.overlay` 槽以取得会话级 hook(`useChat`、`useSession`、`sessionId` 等),面板本体通过 `createPortal` 渲染到 `document.body` 成为固定浮层;对话数据来自 `props.useChat`(`ChatSnapshot.order` 与 `nodes`,节点形状:`kind: user/assistant-step`、`location.turn`、`data.blocks`)
|
|
66
|
+
- 修改 `lib/client.js` 后需重启 DSH 生效
|
|
65
67
|
|
|
66
68
|
## License
|
|
67
69
|
|
package/lib/client.js
CHANGED
|
@@ -7,7 +7,7 @@ window.__ModuleLoader__.load({
|
|
|
7
7
|
let react = require("react");
|
|
8
8
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
9
|
let react_dom = require("react-dom"); // createPortal -> panel stays a top-level overlay (highest pointer priority)
|
|
10
|
-
// DSH 0.1.
|
|
10
|
+
// Recent DSH (0.1.5-rc.1): the old @deepseek-ai/dsh-client-runtime package is gone.
|
|
11
11
|
// Runtime hooks (useChat etc.) now arrive as session-scope slot props —
|
|
12
12
|
// no runtime package to require here anymore.
|
|
13
13
|
|
|
@@ -168,6 +168,56 @@ window.__ModuleLoader__.load({
|
|
|
168
168
|
return null;
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
+
// ---- which view is the conversation area showing? ----
|
|
172
|
+
// The center column hosts ONE view at a time (chat / trajectory / context /
|
|
173
|
+
// any plugin view): DSH renders only the selected view entry, but the
|
|
174
|
+
// scrollport is shared, so our overlay would otherwise float over every view.
|
|
175
|
+
// The tab list (rendered when there is more than one view) marks the active
|
|
176
|
+
// view with aria-selected; ui-chat registers the chat view with order 0, so
|
|
177
|
+
// its tab comes first. Anything unknowable degrades to "chat" (visible).
|
|
178
|
+
var CHAT_VIEW_LABELS = ["对话", "chat"];
|
|
179
|
+
// Cached so the fast poll costs one isConnected check in the common case.
|
|
180
|
+
var _chatTablistCache = null;
|
|
181
|
+
function conversationTablist() {
|
|
182
|
+
var cached = _chatTablistCache;
|
|
183
|
+
if (cached && cached.isConnected) return cached;
|
|
184
|
+
var found = null;
|
|
185
|
+
// Scope the lookup to the conversation area: walk up from the shared
|
|
186
|
+
// scrollport and take the first tab list an ancestor owns, so an
|
|
187
|
+
// unrelated tab list (e.g. inside a settings dialog) can never match.
|
|
188
|
+
var sp = document.querySelector("[data-conversation-scroll]");
|
|
189
|
+
if (sp) {
|
|
190
|
+
var node = sp;
|
|
191
|
+
for (var d = 0; d < 6 && node && !found; d++) {
|
|
192
|
+
node = node.parentElement;
|
|
193
|
+
if (node) found = node.querySelector('[role="tablist"]');
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (!found) found = document.querySelector('[role="tablist"]');
|
|
197
|
+
_chatTablistCache = found;
|
|
198
|
+
return found;
|
|
199
|
+
}
|
|
200
|
+
function isChatViewActive() {
|
|
201
|
+
try {
|
|
202
|
+
var tablist = conversationTablist();
|
|
203
|
+
if (!tablist) return true; // a single view: no tab list, and it is chat
|
|
204
|
+
var tabs = tablist.querySelectorAll('button[role="tab"]');
|
|
205
|
+
if (tabs.length < 2) return true;
|
|
206
|
+
var activeIdx = -1;
|
|
207
|
+
var chatIdx = -1;
|
|
208
|
+
for (var i = 0; i < tabs.length; i++) {
|
|
209
|
+
var label = (tabs[i].textContent || "").trim().toLowerCase();
|
|
210
|
+
if (chatIdx === -1 && CHAT_VIEW_LABELS.indexOf(label) !== -1) chatIdx = i;
|
|
211
|
+
if (activeIdx === -1 && tabs[i].getAttribute("aria-selected") === "true") activeIdx = i;
|
|
212
|
+
}
|
|
213
|
+
if (activeIdx === -1) return true; // no explicit selection -> assume chat
|
|
214
|
+
if (chatIdx === -1) chatIdx = 0; // chat is order 0 -> the first tab
|
|
215
|
+
return activeIdx === chatIdx;
|
|
216
|
+
} catch (e) {
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
171
221
|
// ---- search keyword highlight in the conversation ----
|
|
172
222
|
var highlightSpans = [];
|
|
173
223
|
|
|
@@ -306,13 +356,13 @@ window.__ModuleLoader__.load({
|
|
|
306
356
|
|
|
307
357
|
// ---------- component ----------
|
|
308
358
|
function OutlinePanel(props) {
|
|
309
|
-
// DSH 0.1.
|
|
359
|
+
// Recent DSH (0.1.5-rc.1): the conversation moved out of the session snapshot —
|
|
310
360
|
// it is now the session-scope `chat` hook (ChatSnapshot: order + nodes
|
|
311
361
|
// map + legacy projection), contributed by dsh-client-ui-chat. Same node
|
|
312
362
|
// shape as before (kind user/assistant-step, location.turn, data.blocks).
|
|
313
363
|
var useChat = props.useChat;
|
|
314
364
|
if (!useChat) {
|
|
315
|
-
console.warn("[dsh-quick-toc] useChat prop missing (requires DSH >= 0.1.
|
|
365
|
+
console.warn("[dsh-quick-toc] useChat prop missing (requires DSH >= 0.1.5-rc.1)");
|
|
316
366
|
return null;
|
|
317
367
|
}
|
|
318
368
|
var order = useChat(function (s) { return s.order; });
|
|
@@ -434,6 +484,39 @@ window.__ModuleLoader__.load({
|
|
|
434
484
|
var didInitScroll = react.useRef(false);
|
|
435
485
|
var outlineTouchRef = react.useRef(0); // last time the user touched the outline
|
|
436
486
|
|
|
487
|
+
// ---- the outline belongs to the CHAT view only: when the center column
|
|
488
|
+
// switches to another view (trajectory / context / plugin views), fade the
|
|
489
|
+
// panel and its collapsed handle out. Polled lightly because view switches
|
|
490
|
+
// are user clicks and the tab DOM is remounted on session/view changes.
|
|
491
|
+
var _sView = react.useState(true);
|
|
492
|
+
var chatViewActive = _sView[0];
|
|
493
|
+
var setChatViewActive = _sView[1];
|
|
494
|
+
var chatViewRef = react.useRef(true);
|
|
495
|
+
// True briefly after a view switch: lets the fade use its own fast
|
|
496
|
+
// transition instead of the slower dock/collapse one.
|
|
497
|
+
var _sFade = react.useState(false);
|
|
498
|
+
var viewFading = _sFade[0];
|
|
499
|
+
var setViewFading = _sFade[1];
|
|
500
|
+
var viewFadeTimerRef = react.useRef(null);
|
|
501
|
+
react.useEffect(function () {
|
|
502
|
+
var detect = function () {
|
|
503
|
+
var v = isChatViewActive();
|
|
504
|
+
if (v !== chatViewRef.current) {
|
|
505
|
+
chatViewRef.current = v;
|
|
506
|
+
setChatViewActive(v);
|
|
507
|
+
setViewFading(true);
|
|
508
|
+
if (viewFadeTimerRef.current) clearTimeout(viewFadeTimerRef.current);
|
|
509
|
+
viewFadeTimerRef.current = setTimeout(function () { setViewFading(false); }, 380);
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
detect();
|
|
513
|
+
var timer = setInterval(detect, 120);
|
|
514
|
+
return function () {
|
|
515
|
+
clearInterval(timer);
|
|
516
|
+
if (viewFadeTimerRef.current) clearTimeout(viewFadeTimerRef.current);
|
|
517
|
+
};
|
|
518
|
+
}, []);
|
|
519
|
+
|
|
437
520
|
// ---- search: header button opens a keyword box; Enter cycles through
|
|
438
521
|
// matching headings and jumps to each ----
|
|
439
522
|
var _s13 = react.useState(false);
|
|
@@ -1018,7 +1101,8 @@ window.__ModuleLoader__.load({
|
|
|
1018
1101
|
panelClip = "inset(0 0 0 " + (panelW + 8) + "px)";
|
|
1019
1102
|
}
|
|
1020
1103
|
}
|
|
1021
|
-
|
|
1104
|
+
// faded out entirely while another center-column view is active
|
|
1105
|
+
var panelOpacity = open && chatViewActive ? (hovered ? 0.95 : 0.45) : 0;
|
|
1022
1106
|
|
|
1023
1107
|
var panelEl = react_jsx_runtime.jsx("div", {
|
|
1024
1108
|
style: {
|
|
@@ -1042,8 +1126,10 @@ window.__ModuleLoader__.load({
|
|
|
1042
1126
|
// soft shade in light) — outer shadow would be clipped by the collapse
|
|
1043
1127
|
// clip-path and the panel edges.
|
|
1044
1128
|
boxShadow: innerShadow(),
|
|
1045
|
-
|
|
1046
|
-
|
|
1129
|
+
// A view switch swaps in a short, delay-free opacity fade; the dock and
|
|
1130
|
+
// collapse animations keep their own (slower) timings.
|
|
1131
|
+
transition: viewFading ? "opacity 0.3s ease" : panelTransition,
|
|
1132
|
+
pointerEvents: chatViewActive ? "auto" : "none"
|
|
1047
1133
|
},
|
|
1048
1134
|
onMouseEnter: function () { setHovered(true); },
|
|
1049
1135
|
onMouseLeave: function () { setHovered(false); },
|
|
@@ -1436,7 +1522,9 @@ window.__ModuleLoader__.load({
|
|
|
1436
1522
|
zIndex: Z_BASE,
|
|
1437
1523
|
top: (viewport ? viewport.top + viewport.height / 2 - 46 : "50%"),
|
|
1438
1524
|
transform: handleShown ? "translateX(0)" : (dockRight ? "translateX(16px)" : "translateX(-16px)"),
|
|
1439
|
-
|
|
1525
|
+
opacity: chatViewActive ? 1 : 0,
|
|
1526
|
+
pointerEvents: chatViewActive ? "auto" : "none",
|
|
1527
|
+
transition: "transform 0.4s " + EASE + ", opacity 0.26s ease",
|
|
1440
1528
|
...(dockRight
|
|
1441
1529
|
? { right: viewport ? viewport.right + 52 : 60 } // clear of the milestone rail
|
|
1442
1530
|
: { left: viewport ? viewport.left : 0 })
|
|
@@ -1611,7 +1699,7 @@ window.__ModuleLoader__.load({
|
|
|
1611
1699
|
ctx.effect(function () {
|
|
1612
1700
|
return ctx.locale.register("dsh-quick-toc", { zh: zh, en: en });
|
|
1613
1701
|
}, "dsh-quick-toc: dictionaries");
|
|
1614
|
-
// DSH 0.1.
|
|
1702
|
+
// Recent DSH (0.1.5-rc.1): session-scoped hooks (useChat/useSession/sessionId) only arrive
|
|
1615
1703
|
// inside a declared session slot. Register the panel into the session-scoped
|
|
1616
1704
|
// conversation.input.overlay (list/additive) so it receives useChat; the panel
|
|
1617
1705
|
// itself renders a fixed, frame-floating dock, so the overlay seat is just the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-quick-toc",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Conversation TOC for DeepSeek Harness (DSH): turn-grouped Markdown heading outline with keyword search (title/full-text scope), in-chat match highlighting, auto-follow and smooth jump navigation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
"README.md",
|
|
11
11
|
"README.en.md",
|
|
12
12
|
"CHANGELOG.md",
|
|
13
|
+
"CHANGELOG.en.md",
|
|
13
14
|
"LICENSE"
|
|
14
15
|
],
|
|
15
16
|
"engines": {
|
|
16
|
-
"dsh": ">=0.1.
|
|
17
|
+
"dsh": ">=0.1.5-rc.1"
|
|
17
18
|
},
|
|
18
19
|
"exports": {
|
|
19
20
|
".": "./lib/index.js",
|
|
@@ -34,15 +35,14 @@
|
|
|
34
35
|
},
|
|
35
36
|
"compatibility": {
|
|
36
37
|
"dshReleases": {
|
|
37
|
-
"0.1.2-rc.1": "compatible",
|
|
38
38
|
"0.1.5-rc.1": "compatible"
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"react": "^18.2.0",
|
|
44
|
-
"@deepseek-ai/dsh-client-ui-chat": ">=0.1.
|
|
45
|
-
"@deepseek-ai/dsh-client-ui-conversation": ">=0.1.
|
|
44
|
+
"@deepseek-ai/dsh-client-ui-chat": ">=0.1.5-rc.1",
|
|
45
|
+
"@deepseek-ai/dsh-client-ui-conversation": ">=0.1.5-rc.1"
|
|
46
46
|
},
|
|
47
47
|
"license": "MIT",
|
|
48
48
|
"keywords": [
|