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.
@@ -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
- # Changelog
1
+ # 更新日志
2
2
 
3
- All notable changes to **dsh-quick-toc** are documented here.
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
- ### Changed
8
- - 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.
17
+ ### 变更
18
+ - 文档整理:README 的兼容表与功能列表更新,npm 包描述补充了关键字搜索与对话内高亮。
9
19
 
10
20
  ## [0.3.1] - 2026-09-08
11
21
 
12
- ### Fixed
13
- - 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.
14
- - 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`.
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
- ### Changed
17
- - Compatibility declaration also lists DSH `0.1.5-rc.1` (verified compatible; `engines.dsh` stays `>=0.1.2-rc.1`).
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
- ### Fixed
22
- - **DSH 0.1.2-rc.1 compatibility**: the removed `@deepseek-ai/dsh-client-runtime` package no longer breaks plugin loading (externals drift). Runtime hooks now arrive as session-scope slot props.
23
- - 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.
24
- - Panel mount moved into the session-scoped `conversation.input.overlay` slot. In 0.1.2-rc.1 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.
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
- ### Changed
27
- - `dsh.client.inject` now lists `dsh-client-ui-chat` / `dsh-client-ui-conversation` / `dsh-client-ui-layout` instead of the removed runtime package.
28
- - Dropped the unused `sessions` service from the client inject list.
36
+ ### 变更
37
+ - `dsh.client.inject` 改为列出 `dsh-client-ui-chat` / `dsh-client-ui-conversation` / `dsh-client-ui-layout`,替代已移除的运行时包。
38
+ - 从客户端 inject 列表中移除未使用的 `sessions` 服务。
29
39
 
30
- ### Added
31
- - 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).
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
- ### Added
36
- - Keyword search: header magnifier button opens a search box; Enter cycles through matches (n/N counter); Escape or the magnifier toggles it closed
37
- - Search scope toggle: 标题 (heading titles only) or 全文 (also user messages and AI reply texts)
38
- - 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
39
- - Every occurrence counts toward n/N (multiple hits in one message = multiple matches)
40
- - 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)
45
+ ### 新增
46
+ - 关键字搜索:标题栏放大镜打开搜索框,回车逐处跳转(`n/N` 计数),Esc 或再次点击放大镜关闭
47
+ - 搜索范围切换:仅标题,或同时搜索用户消息与 AI 回复正文
48
+ - 对话内高亮:命中的关键字在对话中高亮,当前命中单独标亮并滚动到视口中上部
49
+ - 同一条消息内的多次命中都计入 `n/N`
50
+ - 无标题的回合也有独立的时间条目;所有组头在时间旁显示该回合首行预览(点击跳转)
41
51
 
42
- ### Changed
43
- - Panel collapse animation unified for both docks: clip-path hides the panel at the sidebar/screen edge (shadow removed to avoid clipping artifacts)
44
- - Inactive outline groups dimmed to 0.6 opacity
52
+ ### 变更
53
+ - 两种停靠的面板收起动画统一:由 clip-path 在侧栏/屏幕边缘裁切(移除阴影,避免裁切残影)
54
+ - 非激活的大纲组降到 0.6 不透明度
45
55
 
46
56
  ## [0.1.1] - 2026-08-17
47
57
 
48
- ### Changed
49
- - Release workflow also uploads a stable-named tarball (`dsh-quick-toc.tgz`) so `/releases/latest/download/` always resolves to the newest release
58
+ ### 变更
59
+ - 发布流程额外上传稳定命名的 tarball(`dsh-quick-toc.tgz`),使 `/releases/latest/download/` 始终解析到最新版本
50
60
 
51
61
  ## [0.1.0] - 2026-08-17
52
62
 
53
- ### Added
54
- - Turn-grouped outline: each user message + its AI replies form one group, with the group's end time as the header
55
- - 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
56
- - Smooth jump: clicking a heading glides to the exact heading position in the conversation (with a small top offset)
57
- - Dock left/right with a draggable top bar, resizable from the edges/corner, collapsible into a draggable edge handle
58
- - Scrollbar follows the dock side (left when docked left, right when docked right)
59
- - Paged rendering: latest groups first; scrolling the outline to the top loads older groups
60
- - Auto "load older": when the outline reaches the top with everything loaded, it clicks the conversation's own load-more button
61
- - Header time jump: clicking a group's time label jumps to that turn's start
62
- - Markdown-aware titles: `**bold**`, `*italic*`, `` `code` ``, `[links](url)`, `~~strike~~` stripped from heading text
63
- - Persisted panel state (dock side, position, size) with automatic migration from older key names
64
- - Auto-hides when the conversation has no headings; light/dark theme support
65
-
66
- ### Published
67
- - npm: `dsh-quick-toc@0.1.0`
68
- - GitHub: `LyaxZ/dsh-quick-toc` with auto-release workflow (tag push -> npm pack -> release asset)
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 quick conversation TOC plugin for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH): extracts Markdown headings (H1–H6) from AI replies into a navigable outline panel, grouped by conversation turn, with auto-follow highlighting, keyword search and in-chat match highlighting.
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 + its AI replies form one group, with the group's end time as the header (plus the turn's first-line preview; click it to jump to the turn start)
10
- - **Keyword search** — a magnifier in the header opens the search box; Enter cycles matches (n/N counter), Esc closes; toggle between **title / full-text** scope
11
- - **In-chat 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; every occurrence counts toward n/N
12
- - **Auto-follow highlight** — as you scroll the conversation, the turns visible in the viewport light up in the outline (multiple at once); the outline auto-loads and scrolls to keep them visible
13
- - **Smooth jump** — click a heading to glide to the exact heading position in the conversation
14
- - **Dockable & resizable** — dock left or right (drag the top bar), resize from the edges/corner, collapse to a draggable edge handle; panel size/position remembered
15
- - **Paged rendering** — shows the latest groups first; scrolling to the top of the outline loads older ones
16
- - **Markdown-aware titles** — inline `**bold**`, *italic*, `` `code` ``, `[links](url)`, `~~strike~~` are stripped from heading text
17
- - Auto-hides when the conversation has no headings; works in light/dark themes; the inner-shadow card look adapts to the theme (white bevel in dark)
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.2** (latest) | **≥ 0.1.2-rc.1** (verified on 0.1.2-rc.1 / 0.1.5-rc.1) |
24
- | 0.3.0 0.3.1 | same |
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.3.0 re-targeted the host integration (new slot architecture + `useChat` session data) and **only supports DSH 0.1.2-rc.1 and above**; for older DSH builds install 0.2.2. On install/update the DSH market pre-flights host compatibility from `dsh.compatibility.dshReleases` and `peerDependencies` in package.json and warns on a mismatch.
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 (published on npm — name only):
32
+ With the DSH CLI:
32
33
 
33
34
  ```
34
35
  dsh plugin --profile web add dsh-quick-toc
35
36
  ```
36
37
 
37
- or from GitHub:
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
- or, for a local checkout:
44
+ Or from a local folder:
44
45
 
45
46
  ```
46
- dsh plugin --profile web add <path-to-this-folder>
47
+ dsh plugin --profile web add <path-to-the-plugin-folder>
47
48
  ```
48
49
 
49
- Restart DSH (double-click `restart-dsh.bat` on Windows) and open the Web UI. The outline is collapsed by default — click the small edge handle on the left side of the conversation to expand it.
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
- - Click a heading in the outline to jump to that heading in the conversation
54
- - Drag the top bar to move the panel; use the **◀ / ▶** button to dock left/right
55
- - Drag the right edge (width), bottom edge (height) or the bottom-right corner (both) to resize
56
- - Scroll the outline to the top to load older groups
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 no-op entry (extend with a version gate if needed)
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
- - **Since 0.3.0 the plugin targets the new plugin model**: the panel registers into the session-scoped `conversation.input.overlay` slot (session hooks are contributed via `ctx.uiSession.provide`, `useChat` by ui-chat), and the panel body `createPortal`s to `document.body` as a fixed floating dock; data comes from `props.useChat` (`ChatSnapshot.order` + `nodes`; node shape: `kind: user/assistant-step`, `location.turn`, `data.blocks`)
64
- - Client changes need a DSH restart (boot rev is content-based)
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
- - **关键字搜索** —— 标题栏放大镜打开搜索框,回车逐个定位(n/N 计数),Esc 关闭;支持 **标题 / 全文** 范围切换
11
- - **对话内高亮** —— 命中关键字在对话中高亮,当前命中单独标亮并滚动到视口上方约 1/3 处;同一条消息内的多次命中都计入 n/N
12
- - **自动跟随高亮** —— 滚动对话框时,视口内可见的回合在大纲中自动点亮(多组可同时点亮);大纲自动加载并滚动,保证正在读的组始终可见
13
- - **平滑跳转** —— 点击标题平滑滚动到对话中该标题的准确位置
14
- - **可停靠、可缩放** —— 左右停靠(拖顶部横条移动)、边缘/角部拖拽调整大小、收起成可拖动的边缘把手;大小与位置自动记忆
15
- - **分页渲染** —— 默认显示最近几组,大纲滚动到顶部自动加载更早的组
16
- - **Markdown 清理** —— 标题中的 `**加粗**`、*斜体*、`` `代码` ``、`[链接](url)`、`~~删除线~~` 等行内标记自动剥离
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.2**(最新) | **≥ 0.1.2-rc.1**(已在 0.1.2-rc.1 / 0.1.5-rc.1 验证) |
24
- | 0.3.0 0.3.1 | 同上 |
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
- 0.3.0 重写了与宿主的对接(新版 slot 架构 + `useChat` 会话数据),**只支持 DSH 0.1.2-rc.1 及以上**;旧版 DSH 请安装 0.2.2。安装/更新时 DSH 市场会根据 package.json `dsh.compatibility.dshReleases` 与 `peerDependencies` 做 host 兼容预检,版本不符会给出提示。
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 安装(已发布 npm,只要名字):
32
+ 通过 DSH CLI 安装:
32
33
 
33
34
  ```
34
35
  dsh plugin --profile web add dsh-quick-toc
35
36
  ```
36
37
 
37
- 或从 GitHub 安装:
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
- 重启 DSH(Windows 上双击 `restart-dsh.bat`)后打开 Web UI。大纲默认收起——点击对话区左侧边缘的小把手展开。
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
- - **0.3.0 起对接新版插件模型**:面板注册进会话级 `conversation.input.overlay` 槽(会话级 hook 由 `ctx.uiSession.provide` 贡献,`useChat` ui-chat 贡献),面板本体 `createPortal` `document.body` 渲染成固定浮层;数据入口为 `props.useChat`(`ChatSnapshot.order` + `nodes`,节点形状:`kind: user/assistant-step`、`location.turn`、`data.blocks`)
64
- - client.js 后需重启 DSH(boot rev 按内容算)
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.2-rc.1: the old @deepseek-ai/dsh-client-runtime package is gone.
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.2-rc.1: the conversation moved out of the session snapshot —
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.2-rc.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
- var panelOpacity = open ? (hovered ? 0.95 : 0.45) : 0;
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
- transition: panelTransition,
1046
- pointerEvents: "auto"
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
- transition: "transform 0.4s " + EASE,
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.2-rc.1: session-scoped hooks (useChat/useSession/sessionId) only arrive
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.2",
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.2-rc.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.2-rc.1",
45
- "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.2-rc.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": [