# dsh-sidebar-qa

> 为 DSH Web 端提供「划选对话文本→右侧面板提问」能力：在不打断主对话的前提下创建同工作区的独立追问会话，支持嵌套、上下文策略切换与追问记录树。

## Metadata

- Author: [@ChenRuoT](https://github.com/ChenRuoT)
- Repo: <https://github.com/ChenRuoT/dsh-sidebar-qa.git>
- GitHub: [ChenRuoT/dsh-sidebar-qa](https://github.com/ChenRuoT/dsh-sidebar-qa)
- Stars: 30
- Language: TypeScript
- License: [MIT](https://spdx.org/licenses/MIT.html)
- Topics: `deepseek`, `deepseek-harness`, `dsh`, `dsh-better-sidebar`, `dsh-plugin`, `dsh-plugin-market`, `dsh-plugins`, `sidebar`
- Forks: 6
- Open Issues: 3
- Last push: 2026-08-21T08:59:13.000Z
- Added: 2026-08-20T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:ChenRuoT/dsh-sidebar-qa
```

## Wiki

## One-Line Description

In any DSH Web chat, select any text segment, click the floating "Ask" button, and you'll get a complete Q&A in the right panel—the main conversation remains uninterrupted, and all follow-up questions run in automatically created independent DSH sessions within the same workspace, which can be continued, archived, or nested.

## Core Features

- After selecting text in a conversation, a floating "Ask" button appears; clicking it opens a follow-up tab in the right panel and automatically expands the sidebar (even if the panel is collapsed)
- Each question automatically creates an independent DSH sub-session in the same workspace (`❓追问·<topic>`), without touching the main conversation's agent, message stream, or queue
- Three context strategies selectable in sequence: Full Inheritance (fork sub-session hits DeepSeek prefix cache, zero compression loss) / Compression (fast model compresses old history + keep recent raw text, default) / Mechanical Trim (take last N messages as-is, zero LLM cost)
- Follow-up questions support arbitrary depth nesting—selecting text in a follow-up session to ask creates a sub-follow-up
- Follow-up records tab displays a tree layered by root (main) session, scoped to current workspace, collapsible with recent access time shown; archived/deleted nodes are grayed out with status标注, removable with one click
- The answer/summary model provider and model in the config panel have been changed to dropdown selection (from runtime-configured providers); switching provider automatically links the model; summary provider can choose to "Inherit from questioned session"

## Technical Implementation

- **Language**: TypeScript (ESM); Frontend React 18 + Backend Node 20+, bundled for both host and client halves
- **Key Dependencies**: `dsh-better-sidebar` (hard peer dependency, provides `ctx.betterSidebar` registry service); `@deepseek-ai/dsh-client-ui-primitives` (icons); `cordis` (plugin mounting framework); `schemastery` (settings schema validation)
- **Architecture Pattern**: Dual-half plugin. Host half (`src/index.ts`) registers `/sidebarqa/api` prefix route, exposes six JSON methods: `config` / `catalog` / `config.get` / `config.update` / `context` / `title`, and registers a settings panel with optimistic revision guard under `sidebarqa` namespace via `ctx.inject(['settings'], ...)`; Client half (`src/client/index.tsx`) registers two tabs (Follow-up / Follow-up Records) via `ctx.betterSidebar.registerTab` and mounts a floating "Ask" button on `document.body`; all cross-half communication goes through standard `webServer` + `sessionQuery` + `llm` service facade
- **Entry Files**: host `src/index.ts` (exports `apply` + `inject = ['webServer','sessionQuery','llm','loader']`), client `src/client/index.tsx` (exports `apply` + `inject = ['betterSidebar','sessions','connection','workspaces']`), mounting declared via `cordis.patch.yml` + `package.json#dsh.bundle.patch` for both host/client halves

## Use Cases

When collaborating with long conversation agents on DSH Web, you often need to follow up for details on a specific answer—without disrupting the main thread, or losing context by copying/pasting to a new session. This plugin makes "select text → right panel Q&A" a one-click operation: each follow-up is an independent DSH session in the same workspace, can be continued, archived, or nested; context can be switched between "Full Inheritance / Compression / Mechanical Trim" strategies as needed, putting token cost and answer fidelity in your hands.

## Prerequisites & Compatibility

| Dependency | Minimum Version | Notes |
|---|---|---|
| DSH | 0.1.0-rc.8 | Below this version cannot resolve react / cordis / dsh-better-sidebar peer dependencies; rc.7 and earlier please upgrade DSH first |
| dsh-better-sidebar | 0.14.0+ | Hard peer dependency; when not installed, this plugin remains inactive (no UI, no behavior, no session creation) |
| Node | >=20 | Declared by `package.json#engines.node` |
| @deepseek-ai/dsh-client-ui-primitives | ^0.1.0-rc.8 | Client UI icons and primitives |
| cordis | ^4.0.0-rc.8 | Plugin runtime framework |
| Platform | Cross-platform | Pure Web browser plugin, requires DSH Web to run, no native modules |

## Installation

```bash
dsh plugin --profile web add github:ChenRuoT/dsh-sidebar-qa
```

## Configuration Options

All config is served under DSH settings service `sidebarqa` namespace, writes go through `/sidebarqa/api/config.update` with revision optimistic lock (prompts retry on multi-window conflicts). Web entry is in "DSH Settings → Sidebar Cards → Follow-up Card top-right gear → Feature Config" popup; the table below lists only 8 common settings exposed by the panel; other internal tuning keys (`summarizeBudgetTokens`, `recentWindowMessages`, `backgroundWindowMessages`, `titleBudgetTokens`) can be configured directly in `settings.yaml` under the `sidebarqa` namespace.

| Config | Type | Description | Default |
|---|---|---|---|
| `historyStrategy` | Enum | Default context strategy for new follow-up: `inherit` Full Inheritance (fork + cache hit) / `compressed` Compression / `trim` Mechanical Trim; can be switched sequentially in panel | `compressed` |
| `trimWindowMessages` | Number (1-256) | Number of recent messages to keep in mechanical trim mode | `10` |
| `summarizeProvider` | String | Summary fast model provider; empty = inherit from questioned session's provider | `''` |
| `summarizeModel` | String | Summary fast no-thinking model | `deepseek-v4-flash` |
| `summarizeReasoningEffort` | Enum | Summary thinking mode `off` / `high` / `max` | `off` |
| `answerProvider` | String | Sub-conversation answer model provider | `deepseek-official` |
| `answerModel` | String | Sub-conversation answer model | `deepseek-v4-flash` |
| `answerReasoningEffort` | Enum | Sub-conversation thinking mode `off` / `high` / `max` | `off` |

## FAQ

**Q: Must I install dsh-better-sidebar first?**

A: Yes, required. dsh-better-sidebar is a hard peer dependency; when not installed, the client-side `inject = ['betterSidebar', ...]` cannot obtain the service, and this plugin remains inactive—no UI, no behavior, no session creation. First run `dsh plugin --profile web add dsh-better-sidebar@latest`, and require version 0.14.0+.

**Q: After selecting text and clicking "Ask", will the main conversation be interrupted?**

A: No. The host side only reads the main session's current model surface (`ctx.sessionQuery.readSurface`, does not enqueue for sending), and the client side creates an independent DSH sub-session for Q&A; the main conversation's agent, message stream, and queue are completely untouched.

**Q: How should I choose among the three context strategies?**

A: "Full Inheritance" forks from the main session's latest completed turn, inheriting complete history as seed, can hit DeepSeek prefix cache but must use the main session's model; "Compression" uses a fast no-thinking model to compress old history + keep recent raw text (default, saves tokens); "Mechanical Trim" directly takes the last N messages as-is, zero LLM cost. When starting a new follow-up, switch strategies sequentially via the strategy chip on the panel's left side. Full Inheritance automatically degrades to Compression when the main conversation is mid-response (no completed turn yet).

**Q: Why does the follow-up session title start as a placeholder and only update after answering?**

A: This is two-phase naming: creation uses the first line of the quoted text as a placeholder title (`❓追问·<first line>`), and after the first answer completes, the host side uses a fast no-thinking model to extract a final title ≤15 characters from "question + answer" and renames over it. If extraction fails, the placeholder is kept and no retry will occur.

**Q: What are the grayed-out "Archived / Deleted" entries in follow-up records? Does clicking "Remove" delete the DSH session?**

A: Sessions you archived or deleted on the DSH side are not automatically cleaned from this plugin's localStorage parent→child mapping; the records tab grays them out with status labels. Clicking "Remove" only cleans up this plugin's mapping and derived state (titled / collapsed), without touching the real session on the DSH side.

**Q: After closing the browser and returning, are follow-up records still there?**

A: Yes. Parent→child mapping, titled markers, and follow-up records tree collapse state are all persisted in localStorage keys `dsh-sidebar-qa:map` / `:titled` / `:collapsed`. The actual sessions on the DSH side are independently retained by DSH's own session storage.

**Q: After modifying the backend, must I restart dsh web?**

A: Host half changes (`/sidebarqa/api` summary, title, settings namespace) require restarting `dsh web`; client half changes (selection floating layer, follow-up/follow-up records tabs, model dropdown, config panel) only require a hard browser refresh, no service restart needed.

**Q: If the selection spans multiple messages or includes text currently streaming, can I select and ask?**

A: No. The selection is identified as invalid: it must fall within a single `[data-chat-anchor-key]` node, and that node must not be in `data-streaming` state—selection is only possible after the streaming output collapses back to a single message. Single selection text length limit is 2000 characters. These validations are done in `captureSelection` in `src/client/selection.ts`.

## Learning Curve

Beginner—just install dsh-better-sidebar, select text and click "Ask"; advanced parts (strategy switching, model dropdown, follow-up records tree) can be explored as needed, no source code reading required.

## Known Issues & Limitations

- DSH upstream limitation: `sessions.selectModel` unconditionally persists the selected model as the **global default model**. Therefore, when compression/trim follow-up sets the model for sub-sessions, it still changes "the starting model for new sessions"; a session that has never sent a request will also resolve its current model from this global default, which may appear to change. The plugin side has no API to avoid this (`selectModel` has no opt-out, doesn't write session logs, `sessions.models` can only pull), see CHANGELOG 0.3.2.
- Selection has 4 hard thresholds: must fall within a single message `[data-chat-anchor-key]` node, target message not streaming, selection non-empty and ≤2000 characters; if any is not met, the floating layer won't appear (`src/client/selection.ts:9-63`).
- Selection scope is limited to browser native `window.getSelection()`, cannot select across iframes / Shadow DOM; text in these areas won't trigger the floating layer.
- Full Inheritance strategy automatically degrades to Compression when the main conversation is "mid-response, no completed turn yet", panel will prompt; other fork failures (e.g., network) also degrade to Compression, won't block questioning.
- Parent→child mapping, titled markers, and collapse state are all stored in localStorage: clearing browser site data will lose this metadata, but the actual follow-up sessions on the DSH side are unaffected.
- The floating layer only listens to `selectionchange` / `mouseup` / `keyup` on `document`; when DSH Web renders conversation content in non-standard ways (e.g., custom containers without `data-chat-anchor-key` / `data-chat-flow-kind` markers), selections won't be recognized as valid conversation text.

---

This document is auto-generated by [deepseek-plugin.org](https://deepseek-plugin.org). HTML page: [dsh-sidebar-qa](https://deepseek-plugin.org/plugins/ChenRuoT/dsh-sidebar-qa)
Wiki generated by AI (model: `MiniMax-M2.5`)
