# DSH Conversation Navigator (dsh-conversation-navigator) [English](README.en.md) | [中文](README.md) [![npm](https://img.shields.io/npm/v/dsh-conversation-navigator?style=flat-square&color=blue)](https://www.npmjs.com/package/dsh-conversation-navigator) [![downloads](https://img.shields.io/npm/dm/dsh-conversation-navigator?style=flat-square&color=blue)](https://www.npmjs.com/package/dsh-conversation-navigator) [![downloads-total](https://img.shields.io/npm/dt/dsh-conversation-navigator?style=flat-square&color=blue)](https://www.npmjs.com/package/dsh-conversation-navigator) [![stars](https://img.shields.io/github/stars/gjj-star/dsh-conversation-navigator?style=flat-square&color=green)](https://github.com/gjj-star/dsh-conversation-navigator) [![license](https://img.shields.io/github/license/gjj-star/dsh-conversation-navigator?style=flat-square&color=teal)](https://github.com/gjj-star/dsh-conversation-navigator) [![dependencies](https://img.shields.io/badge/dependencies-0-brightgreen?style=flat-square)](https://www.npmjs.com/package/dsh-conversation-navigator) [![awesome · DSH plugin](https://awesome-dsh-plugin.com/badge.svg)](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin) [![DeepSeek Harness](https://img.shields.io/badge/DeepSeek_Harness-Plugin-blue?style=flat-square)](https://github.com/deepseek-ai/deepseek-harness) [![dsh.so risk](https://www.dsh.so/badge/dsh-conversation-navigator-2.svg)](https://www.dsh.so/artifact/dsh-conversation-navigator-2/) [![dsh.so install](https://www.dsh.so/badge/install/dsh-conversation-navigator-2.svg)](https://www.dsh.so/artifact/dsh-conversation-navigator-2/) A **DeepSeek Harness (DSH) Web conversation navigator panel**: a turn-folded outline floating on the **right** side of the conversation page. Click any node to smooth-jump, watch the current reading position highlight as you scroll, with step badges colored to match the built-in "Trajectory" view. Browser-only (no host behavior), plain JavaScript, zero build step, zero npm dependencies (buttons/tooltips reuse the official primitives from the DSH kernel seed). ![Dark mode](https://raw.githubusercontent.com/gjj-star/dsh-conversation-navigator/main/assets/modes/dark.png) ![Light mode](https://raw.githubusercontent.com/gjj-star/dsh-conversation-navigator/main/assets/modes/light.png) > The conversation navigator in dark and light mode. Three forms: full, hidden, and minimal-left (minimal-right is shelved as of 0.2.6, code retained). The minimal strips collapse to the in-row indicator bars; hover expands the positioning panel. More screenshots in [assets/screenshots](./assets/screenshots). ## Features - **Turn-folded outline**: shows "Turn N + your question" rows by default, long conversations at a glance - **Keyword filter**: click the top-left search icon to reveal the inline input; matches only your questions + the assistant's actual reply text (context, tool calls, commands, compaction and reasoning never match); hits are highlighted and the list text is windowed to the keyword - **Expand / collapse steps**: the arrow button on the right of each turn row (`▸ N`, rotates to `▾` when expanded) smoothly expands or collapses the turn's step details (assistant replies, tool calls, commands, compaction points, etc.) - **Hover full text**: rest the mouse on a turn row and a bubble shows the user's complete question, no longer truncated to one line - **Full / Hidden / Minimal-left modes**: the header toggle cycles three states — - **Full**: the classic grouped view (system events like compaction are shown bold, at the same level as turns) - **Hidden**: every row is a trajectory badge + text (user = business blue, assistant = violet, compaction = neutral gray) - **Minimal-left**: the indicator-bar strip pinned to the left edge of the conversation area (at the right border of the DSH sidebar), leaving the right side for dsh-better-sidebar and zero overlap with the official rail - The minimal strip collapses to the in-row indicator bars (current = solid brand color, others = 40% foreground-color mix); hovering expands a fixed 7-row positioning panel (click to jump, hover bubble for the full question, thumb-only scrollbar beyond 7 rows; left-aligned expands from left to right); a floating button above the bars keeps cycling forward (minimal-left → Full); the toggle yields while the search input is open - **Draggable panel**: in Full / Hidden mode, grab the header to drag the panel anywhere in the viewport (auto-clamped to the edges; the expanded height is capped at half the viewport with the top edge fixed and the panel growing downward — expanding a huge turn scrolls the list internally while the "Back to latest / Collapse all" footer stays reachable); the pin button in the header toggles between the default right-dock and the last dragged position; the dragged position and the minimal left/right alignment survive page reloads via localStorage - **Resizable panel**: drag from the bottom-left rounded corner (Full / Hidden modes only) — width 240–560 px, height vertical. Height follows a content-adaptive + cap model: actual height = min(turn content, the cap you drag to), tracking the number of turns with no blank space under the footer; floor ~3 turns, ceiling within the conversation viewport. The drag tracks the pointer 1:1 and is fully reversible; width/height persist in localStorage - **Silky motion**: panel fade, step expand/collapse height transitions, staggered fade-in of filter results, rotating collapse arrow — all pure CSS, zero dependencies - **Click to locate**: click a turn or a step to smooth-scroll the conversation to that exact position (fold state is preserved) - **Load earlier / Load all**: two buttons on top — "Load earlier" pages one batch back, "Load all" loads every historical turn into the navigator for arbitrary jumps (the page itself stays lazily loaded until you click) - **Position tracking**: scrolling the conversation highlights and follows the turn you are currently reading - **Right-side docking (default)**: the panel is anchored to the right edge of the viewport and stays put when the left sidebar collapses or expands; unpin (drag it or hit the pin) to place it anywhere - **Back to latest / Collapse all**: two shortcut buttons at the bottom; "Collapse all" is disabled when no turn is expanded, so it never looks broken for doing nothing - **Trajectory colors**: user/steering = business blue, context = success green, assistant = violet, tool = amber, compaction = neutral gray (`--dsw` theme tokens matching the built-in trajectory view, light/dark adaptive) - **Native DSH look**: action buttons reuse the official `Button`/`Tooltip` components and official icons (search, close); the remaining icons (navigate, load earlier, load all, back to latest, collapse all, switch modes, …) are outline icons from **Lucide** (ISC License, [lucide.dev](https://lucide.dev)), `currentColor` adaptive to light/dark themes - Follows workspace/session switches automatically and rebuilds the outline ## Install This plugin is a spec-compliant **bundle** (`dsh.bundle` manifest + `dsh.client` declaration), plain JavaScript with no build step. Install with the official CLI: ```sh # Option 1: npm (no build authorization needed once published) dsh plugin --profile web add dsh-conversation-navigator # Option 2: GitHub (pure JS package, no prepare/allowBuilds required) dsh plugin --profile web add github:gjj-star/dsh-conversation-navigator # Option 3: local tarball pnpm pack dsh plugin --profile web add ./dsh-conversation-navigator-.tgz ``` `dsh plugin` forwards to pnpm inside the profile directory, so **pnpm must be on your PATH**; installation appends this package to the profile's `dsh.profile.bundles`, and its bundled `cordis.patch.yml` layer inserts the plugin row. Restart `dsh web` and the panel appears. **Dual-form defaults**: on official DSH < 0.1.2-rc.1 (no built-in navigator) the panel is expanded by default; on official DSH ≥ 0.1.2-rc.1 (the conversation view ships the built-in TurnNavigator rail) the panel starts closed in "minimal-left" form with the search box collapsed, summoned by the "导航" title-bar toggle, with zero overlap against the official right-edge rail. > Manual install (no pnpm): place the repo at `\profiles\\node_modules\dsh-conversation-navigator` and append the content of [`example.patch.yml`](./example.patch.yml) to the top-level array of the profile's `cordis.patch.yml`. ## Updates Edit `lib/client.js` and restart `dsh web`. Docked state, dragged position, minimal alignment and the panel width/height persist (localStorage `dsh-cnvnav:ui:v2`); the open/closed state is deliberately NOT persisted — on the new host the panel always starts closed — and search keywords still live only within the page session. > Published to npm as `dsh-conversation-navigator` (the version badge above always shows the latest release); to upgrade an installed copy, update from the marketplace or run `dsh plugin --profile web add dsh-conversation-navigator` again, then restart. ## How it works - Slots: `conversation.session.header.utilities` (the "导航" toggle in the title bar) + `shell.overlay` (the floating panel) - Data (dual-form): legacy hosts read the session-level standard props `useSession`; new hosts (official ≥ 0.1.2-rc.1) read the `uiConversation.binding(binding).target("chat")` snapshot — the primary channel groups by the official `timeline.turnOrder` + `locations` index, backs off to `ChatNodeStore.values()` (mapping via the node's own `location` or its `anchorSeq` against the official turn boundaries), and finally merges the official `turnOutline` projection (`sessions.projectionStore(sid).get("turnOutline")` / the slot standard prop `useProjection`, the same source the official rail's `mergeTurnRailItems` uses) to restore user messages the assembly index drops and to add out-of-window turns; re-derived automatically on `loadOlder` - History backfill: pages back through `sessions`'s `binding(sessionId).session.loadOlder()`, "Load all" loops until `hasMore=false` - Jumping: reuses the DSH chat view's own stable DOM anchor `[data-chat-anchor-key]` (the same anchor the product uses internally for paging/scroll positioning) with `scrollIntoView` smooth scrolling - Position tracking: captures scroll events on the `[data-conversation-scroll]` container (throttled 120ms) and computes the first visible node at the viewport top - Keyword filter: extracts searchable text only for `user` and `assistant-step` nodes (`dialogueText`), case-insensitive matching, hits wrapped in `` and the display windowed around the first hit - Hover full text: the turn-row bubble reads `fullDialogueText` (all text blocks of the user node joined), shown via `Tooltip` with a 340px width cap - Modes: the header button cycles `viewMode` (full/hidden/minimal-left; `minimal`/minimal-right is commented out and retained); hidden replaces the turn head title with a trajectory badge (`titleNode` strategy); minimal-left is pinned to `scrollport.left + 12` (the placement key includes `r.left` and a ResizeObserver on the chat area re-anchors it whenever the left sidebar expands or collapses); the toggle yields while the search input is open - Drag & persistence: the full-panel header is draggable (pointer events, clamped to the viewport); dragging or the pin toggles `docked`; `place()` only clamps a freely-placed panel into the viewport instead of re-docking it; the position, docked state and alignment choice persist in localStorage (`dsh-cnvnav:ui:v1`) - Resize: a transparent bottom-left corner grip captures pointer events; width writes `style.width` directly (240–560), height only adjusts `maxHeight` while `height` stays `auto`, so the actual height is always min(content, cap) with no blank space; dragging follows the start point linearly (`base + delta`) and shares the same container/viewport clamps as `place()` so nothing snaps on release; width/height persist as `panelWidth`/`panelHeight` - Styling: `Button`/`Tooltip`/search & close icons reuse `@deepseek-ai/dsh-client-ui-primitives`, the rest are inline Lucide SVGs (ISC License); the panel injects its own `