# dsh-annotation

> DSH Web browser annotation plugin: mark selected assistant reply text with labels, press Enter to send the message to the model, and replies respond to each numbered item sequentially.

## Metadata

- Author: [@omdsh-dev](https://github.com/omdsh-dev)
- Repo: <https://github.com/omdsh-dev/dsh-annotation.git>
- GitHub: [omdsh-dev/dsh-annotation](https://github.com/omdsh-dev/dsh-annotation)
- Stars: 84
- Language: HTML
- License: [MIT](https://spdx.org/licenses/MIT.html)
- Topics: `dsh`, `dsh-plugin`
- Forks: 6
- Open Issues: 1
- Last push: 2026-08-20T10:59:49.000Z
- Added: 2026-08-13T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:omdsh-dev/dsh-annotation
```

## Wiki

## One-Sentence Positioning
Adds annotation capability for assistant replies in DSH Web—select any text in assistant messages, write a note (or leave empty for marking only), press Enter, and the annotation list will be sent to the model together with your question in the input box. The model responds by annotation number, and each "Annotation N:" in the reply can be hovered to view the original text and annotation.

## Core Capabilities
- Select any text in assistant replies to pop up the annotation toolbar; after writing a note, the original text shows a blue numbered footnote + highlight
- Annotation notes can be left empty (marking only), accumulating across messages and conversation turns continuously, numbering starts from 1
- A "Annotations ×N" small tag appears next to the input box; hovering shows all annotation content, can delete items one by one
- Pressing Enter in the input box splices the annotation list into the draft right before submission, sending it together with your question
- The user message bubble won't display annotation block text, only the question + "Annotations ×N" tag (hover to see content)
- "Annotation 1:"..."Annotation N:" in model replies render as hoverable chips, hovering shows corresponding original text and annotation

## Technical Implementation
- **Language**: Browser-side hand-written CJS JavaScript (client.js), plus an empty implementation TypeScript Node entry (src/index.ts)
- **Key Dependencies**: cordis (peerDependency ^4.0.0-rc.7 || ^4.0.1, declared only not bundled), @deepseek-ai/dsh-client-runtime, @deepseek-ai/dsh-client-ui-conversation (injection target, not runtime import)
- **Architecture Pattern**: Official bundle plugin form—Node side is empty (apply() no-op), all capabilities in client.js injected to browser via dsh.client declaration; cordis.patch.yml only inserts one line of its own id, doesn't touch DSH core; connects to session and conversation services via `exports.inject = ['sessions','conversation']`
- **Entry Files**: Browser entry client.js (1801 lines), Node entry lib/index.js (src/index.ts compiled output, 6 lines empty implementation)

## Use Cases
Suitable for users who need the model to perform refined questioning or correction on **specific paragraphs** in assistant replies: for example, having the model explain specific lines in long answers paragraph by paragraph, asking the model to modify certain paragraph phrasing, or giving different instructions for multiple sections. Regular one-question-one-answer doesn't need this—**the main use case is "pointing at some text to chat with the model"**.

## Prerequisites & Compatibility
| Dependency | Min Version | Notes |
|---|---|---|
| DSH | Not declared | package.json doesn't declare DSH version, only declares cordis ^4.0.0-rc.7 || ^4.0.1 as peer; during installation, use cordis corresponding to current DSH version |
| Node | >=20 | Only affects build of Node-side empty implementation (tsc compilation), browser-side runtime doesn't depend on Node |
| Platform | Cross-platform | All capabilities run in browser (client.js), platform-agnostic |
| Native modules | None | No native dependencies introduced, pure DOM + Cordis service subscription |

## Installation
```bash
dsh plugin --profile web add github:omdsh-dev/dsh-annotation
```

## Configuration
This plugin requires no additional configuration. All behaviors (numbering style, response format, separator marker "Question:", history message self-repair, etc.) are built-in defaults—no Schema/options fields exposed in the source code.

## FAQ

**Q: Do I need to restart DSH Web after installation?**

A: Restarting is recommended. The installation command only registers the bundle, but client.js is served to the browser with no-cache per request; on macOS, the official recommendation is `launchctl kickstart -k "gui/$(id -u)/com.dsh.web"`, other platforms restart according to your DSH Web service management method.

**Q: How to confirm the plugin installed successfully?**

A: Run two self-check commands: `dsh --profile web --dump-config | rg "id: dsh-annotation"` must output exactly 1 line (to avoid duplicate insert with profile/home's cordis.patch.yml); `curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3080/plugins/@omdsh-dev/dsh-annotation/client.js` should return 200.

**Q: Can I add multiple annotations to the same text? Or can I edit the note after annotating?**

A: The same selected text region is judged as the same annotation; duplicate operations enter edit mode to update the existing note; to add a new annotation, just select a different position. Saved annotations can be removed one by one via the delete button in the "Annotations ×N" tag next to the input box.

**Q: If I switch to another conversation, will annotations carry over to the new conversation?**

A: No. When subscribing to `sessions.list` detects a conversation switch, the plugin actively clears the collected annotation set to avoid cross-session contamination.

**Q: Will it conflict with DSH's built-in citation feature?**

A: No. The plugin doesn't depend on any send completion event chain, nor does it modify the composer textarea DOM; it only intercepts Enter at the capture stage, splices the annotation block using `setDraft` right before submission (not overwriting user draft), then lets the composer's own submission logic continue.

**Q: Can it be used together with focus view plugins like dsh-focus-chat?**

A: Yes. The plugin recognizes both DSH main view (assistant rows with data-time-hover-root) and focus-chat focus view (containers with data-focus-flow and class containing assistant); selection annotation, reply chips, and scroll repositioning all work in both views.

## Getting Started Difficulty
Beginner — one command to install, no configuration; just understand the interaction flow "select → toolbar annotate → Enter to send", no need to understand Cordis or DSH internals.

## Known Issues & Limitations
- **Initial load session not loaded**: `watchInputDraft` cannot subscribe to input draft state when the plugin is just enabled and session list hasn't loaded yet (client.js:1388). The plugin's fallback strategy is MutationObserver + 1s polling (client.js:1747-1750), so the annotation bubble hide logic still works, but in extreme first-launch scenarios, the first send completion event might be missed and will self-repair in the next polling round.
- **Bubble hide depends on plain text rendering**: DSH user bubbles are MessageText single text nodes (not markdown), the annotation block hide algorithm splits by the last "\nQuestion:" (client.js:1436-1445); if DSH changes user bubbles to markdown rendering or splits into multiple text nodes in the future, the hide logic needs corresponding adjustment.
- **Reply chip depends on TreeWalker snapshot**: After streaming ends, "Annotation N:" needs to be replaced with hover chips; the source code forces snapshot first via TreeWalker to collect text nodes then replace one by one (client.js:1630-1650)—traversal mid-way replaceChild would invalidate the walker pointer and only process the first node, this is an explicitly maintained fragile point.
- **Annotation data only in memory**: ui.quotes is only stored in current page memory (client.js:655-667), unsent annotations are lost after page refresh; sent annotations are reconstructed via `tag.__annotationItems` on user messages (client.js:1500-1507).
- **DSH version not declared**: package.json doesn't specify DSH version number or compatibility range (package.json:38-58), only uses cordis peerDependency for indirect constraint; after upgrading DSH, if cordis major version is incompatible, manual verification is needed.

---

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