At a glance
What it does
Selection annotation for sending selected text with a DSH message.
Web Profile
not tested
Evidence-verified
Checked Aug 28, 2026, 11:19 AM UTC
Code-evidenced contributions
What it adds to DSH
Provides dsh annotation based on the pinned repository evidence.
Mechanism evidence ↗Before you choose it
This plugin bundle provides selection annotation for sending selected text with a DSH message.
Best for
DSH users who need annotation capabilities.
Common tasks
- Use DSH Annotation for annotation workflows.
- Review the pinned repository evidence before deciding whether it fits your profile.
Permissions and data
Runtime behavior was not tested in this run; host access depends on the DSH integration and declared dependencies.
Permissions- Adds a DSH item to the selected profile.
- Runtime data handling was not tested in this run.
- May use dependencies or services declared by the pinned repository.
- No credential requirement was established by the supplied evidence.
Limitations
- Runtime installation and execution were not tested in this run.
- The description is based on pinned repository evidence.
What DSHub checked
- The source repository commit is pinned in the evidence.
- The supplied repository structure was collected deterministically.
What DSHub did not check
- Runtime installation, execution, and compatibility were not tested in this run.
- No security certification is implied.
Pinned install
Install DSH Annotation
This plugin bundle does not have a DSH Plugin install action. Use its source documentation for the delivery method.
Maintainer source
Project README
dsh-annotation
<div align="center">English · 简体中文
</div><p align="center">Selection-annotation plugin for DSH Web: select text → annotate → press Enter to send it along with your message; the model replies to each annotation by number.</p><p align="center"><strong>🌐 <a href="https://omdsh-dev.github.io/dsh-annotation/">Live Product Site — Explore dsh-annotation in DSH</a></strong></p><p align="center"> <img src="https://badgen.net/badge/license/MIT/blue" alt="license"> </p> <img width="2940" height="1770" alt="image" src="https://github.com/user-attachments/assets/c3186efc-44d3-4e7f-9523-1902d9d037e9" /> <img width="2940" height="1770" alt="image" src="https://github.com/user-attachments/assets/0b48ac02-4648-4b94-8d8f-344f8b7c25b4" /> <img width="2940" height="1770" alt="image" src="https://github.com/user-attachments/assets/8b2610d0-3d00-41be-b314-bac2fe616787" /> <img width="2940" height="1770" alt="image" src="https://github.com/user-attachments/assets/9b66deea-3786-4296-9b0d-52873a15f5e1" />Select any text in an assistant reply to annotate it (the annotation body may be left empty = just mark the passage). Annotations accumulate across messages and turns. An Annotations ×N chip appears next to the input box — hover to view all annotations, remove them one by one. Press Enter and the annotation block goes to the model together with whatever question is in the input box. The annotation block never shows up as text in your own message bubble — only the question plus the chip (content visible on hover; hidden before paint, zero flicker). The model replies with Annotation 1: … … Annotation N: …, one per annotation, and every Annotation label in the reply is a hoverable chip showing the annotated passage and your note.
Form: official bundle plugin (dsh.bundle + a dsh.client declaration in package.json, injected into the browser via client-modules; the Node half is an empty implementation). Zero core changes — no DSH files are touched; cordis.patch.yml only inserts its own id once, and the profile patch stays [].
Features
| Feature | Description |
|---|---|
| Select-to-annotate | Select assistant text → toolbar "Annotate" → write your note (may be empty); dismiss by clicking elsewhere or pressing Esc |
| Numbered marker + highlight | A blue numbered marker + highlight anchored to the passage, viewport-anchored with collision avoidance, never lost when scrolled out of view |
| Cross-turn collection | Any number of annotations accumulate across messages/turns, numbered from 1 |
| "Annotations ×N" chip | Small chip beside the input box; hover shows every annotation, deletable individually |
| Enter sends with your message | Annotation block + the question in the input box are sent to the model together (the model receives the full content) |
| Hidden in your bubble | The annotation block is removed from your bubble's DOM the moment you send (before the browser paints), leaving only the question + the chip (hover to view); historical messages self-heal after a refresh |
| Numbered reply correspondence | A format instruction is injected into the message so the model replies Annotation 1: … … Annotation N: … one by one |
| Reply annotation chips | Annotation N: in the reply renders as hoverable chips showing the passage + your note |
Interaction flow
Select assistant text ──▶ Toolbar "Annotate" ──▶ Write note / save empty ──▶ Blue numbered marker + highlight
▲ │
└────────────── any number, accumulate across turns ◀────┘
│
▼
"Annotations ×N" chip beside the input (hover to view / delete)
│
Press Enter
▼
Model receives: annotation block (number + passage + note) + your question
Your bubble: question only + "Annotations ×N" chip (zero flicker)
Model reply: Annotation 1: … Annotation 2: … (hoverable chips)
Install (official bundle path · the only one)
# Public npm package (works without an npm account)
dsh plugin --profile web add @changfenhuang/dsh-annotation
# Or install directly from the public GitHub source
dsh plugin --profile web add git+https://github.com/omdsh-dev/dsh-annotation.git
# local path install (development / debugging)
cd /path/to/dsh-annotation
dsh plugin --profile web add .
# restart the web service — see "Restarting the web service" below
To add it only as a Node dependency in an existing project:
npm install @changfenhuang/dsh-annotation
npm installonly adds the dependency; it does not register the plugin with DSH. Usedsh plugin addabove when installing it into DSH.
Migrating from the old @omdsh-dev package name
If you installed the plugin before v1.4.2, remove the old dependency before installing the renamed package:
dsh plugin --profile web remove @omdsh-dev/dsh-annotation
dsh plugin --profile web add @changfenhuang/dsh-annotation
If dsh web still fails and mentions @omdsh-dev/dsh-annotation, remove only the stale dsh-annotation entry that uses that old name from ~/.dsh/profiles/web/cordis.patch.yml. The plugin now supplies the @changfenhuang/dsh-annotation entry itself.
| Do | Don't |
|---|---|
Only dsh plugin add / only write bundles |
Never insert the same id again in the profile/home cordis.patch.yml |
Self-check:
dsh --profile web --dump-config | rg "id: dsh-annotation" # must be exactly 1 line
dsh web --no-open # open the printed one-time token URL in a browser
In the browser console, window.__DSH_BOOT__.entries.find(({ id }) => id === '@changfenhuang/dsh-annotation') must return an entry with a url. dsh 0.1.2 no longer exposes the old bare per-plugin URL.
Restarting the web service
Pick the command for your platform:
# macOS (launchd)
launchctl kickstart -k "gui/$(id -u)/com.dsh.web"
# WSL / Linux with systemd user services
# The unit name may differ by install method; check with:
# systemctl --user list-units | rg dsh
systemctl --user restart dsh-web
Environments without a service manager (e.g. some containers) often need no restart at all: client.js is served per request with no caching, so a hard refresh (Cmd/Ctrl+Shift+R) picks up plugin changes. The self-check commands above are platform-neutral.
Architecture notes
Pure browser-side: everything lives in
client.js(a hand-written CJS bundle, no build step, served no-cache per request)Message format (the literal protocol block sent to the model; follows the DSH
localepreference — zh or en):zh: 我批注了以下 N 处内容…\n\n1. 原文\n 批注:…\n\n请用「Annotation 1:…」…\n\n提问: en: I annotated the following N passage(s)…\n\n1. quote\n Note: …\n\nPlease respond… "Annotation 1: …"…\n\nAsk:The zh delimiter is 「提问:」(ask:) rather than 「问题:」(question:) — the heading line "回答我的问题:" also contains the latter, and the bubble-hiding surgery would misfire on it; the en delimiter is
Ask:. Hiding and reverse-parsing accept both languages plus the legacy 「问题:」 marker.Bubble hiding: user bubbles are plain-text rendered (a single MessageText node, not markdown); a MutationObserver in the microtask phase (before paint) splits at the last
\n提问:, cuts the annotation block, and attaches the chip; a 1 s polling fallback plus historical-message repair after refreshReply chips: after streaming settles (
data-streamingremoved), eachAnnotation N:is replaced with a hoverable chip; item data is stored on the most recent user message carrying the annotation tag (tag.__annotationItems) and rebuilt after refresh; snapshot the text nodes collected by the TreeWalker before touching the DOM, then replace one by one — replacing a child mid-walk invalidates the walker pointer and only the first node gets processedLocale-aware: UI copy and the protocol block follow DSH's
localeservice (zh/en, live switch); historical bubbles stay parseable across languages; missing locale service falls back to zhIME-safe: the Enter interception carries
isComposing/ keyCode 229 guards; never hard-edits the composer textarea's DOM;setDraftonly assembles the annotation block at the last moment before submit and never clobbers the user's draftNo reliance on send-completion event chains: bubble decoration uses MutationObserver + polling (
watchInputDraftcan be ineffective before the session is loaded at init; it is only a staging entry)Focus-chat compatible: works inside the focus conversation view of dsh-focus-chat — assistant rows there are
[data-focus-flow]containers with a*_assistantCSS-Modules class (plusdata-streamingwhile running); selection, annotation, reply chips, and re-anchoring all work in the focus tab alongside the main chat view
Version history
| Version | Highlights |
|---|---|
| v1.4.x | Locale-aware: zh/en UI copy and annotation protocol block, live switch via DSH locale service |
| v1.3.x | Numbered reply correspondence: format-instruction injection + hoverable Annotation N: chips (TreeWalker snapshot fix) |
| v1.2.x | Hidden annotation block in bubble: MutationObserver microtask zero-flicker + polling fallback + historical-message repair |
| v1.x | Self-contained annotation flow (replaces the v0.9 chip design): capture-Enter assembles the block and sends it with the message |
| v0.9.x | Early chip design (insertReference + slash codec), superseded by v1.x |
Friendly links
License
MIT
Operate deliberately
Install and manage
Prerequisites and target Profile
Target: Web Profile
Delivery: Dsh Bundle Git — omdsh-dev/dsh-annotation#5949675671d84d5c1b81f223344456d7e7216620。
Verify, update, and remove
Show lifecycle commands
dsh plugin --profile web listCompatibility and access
Not_runtime_tested: not tested。
Review compatibility evidence ↗
Risk facts
No installer script was captured; review the repository instructions before use.
Evidence ↗A package lifecycle script is declared; its runtime behavior was not tested in this run.
Evidence ↗Evidence and editorial reviewManifest, Bundle patch, distribution and freshness
Immutable evidence
Review status and source activity
Approved for publication after reviewing the source-linked content and immutable release record. AI assisted with the draft; the publication decision was human.
Human reviewed Aug 29, 2026, 3:24 PM UTC。GitHub facts last checked Aug 29, 2026, 3:21 PM UTC。
No material source change has been recorded since this evidence baseline.