DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

samuelraj-game /

samuelraj-game/dsh-plugin-annotation

Verified

This plugin has no description yet.

★ 1 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHubProject homepage
READMESource: main@e87bda82

dsh-plugin-annotation

Annotate passages in a DeepSeek Harness conversation: select text, add a comment, and the annotation rides your next turn as hidden context. Annotations persist per session, so switching conversations does not lose them.

What it does

  1. Select text anywhere in the conversation.
  2. A Comment pill appears beside the selection; click it.
  3. Type an optional comment and press Enter to stage it, or Ctrl+Enter to send only that annotation immediately.

Staged annotations stay out of the composer draft. They collect in a small count pill above the composer:

[ 💬 2 annotations  (×) ]

Hover the pill to open the stack. The panel lists each annotation with its quoted passage, your comment, and edit/remove actions:

2 annotations                                            [Send all]
 1  SELECTED TEXT
    "remove"
    USER COMMENT
    are you sure?
 2  SELECTED TEXT
    "the official 0.4.10 installer"
    USER COMMENT
    no comment
  • Each annotation carries a numbered pin over the passage it came from; the passage stays highlighted.
  • Hovering a row or its pin paints that passage with a stronger highlight.
  • The panel is resizable vertically and matches the composer width.
  • The × button appears when you hover the count pill and clears the whole stack.
  • A blank comment is allowed: the selection alone is staged, so it can stand as context or agreement for the prompt you are about to write.
  • Ctrl+Enter sends only the annotation you are drafting, even when other annotations are already staged.
  • Annotations are stored per session and reload when you return to a conversation. Pins are re-anchored by finding the quoted passage again.
  • Comments support bullet and numbered lists: - and 1. continue on Enter, Tab indents, and Enter on an empty item ends the list.

Annotations never enter your text field. They are held by the plugin's host half and attached to the next turn as a hidden context message, so the model sees the quoted passage and your comment while the conversation shows only your own message:

(shown)  please also check the checksum
(hidden) The user annotated passages of the conversation. …
         1. Quoted passage:
         remove

         User comment: are you sure?

Press the composer's normal Send button (or Enter) and the staged stack goes with it. With annotations pending and an empty composer, the send button stays enabled because the plugin keeps an invisible token in the draft; the host strips it before the model step.

Keyboard

Where Key Effect
Comment card Enter Stage in the stack (continues a list item when the line is one)
Comment card Ctrl/Cmd+Enter Send only this annotation now
Comment card Shift+Enter New line
Comment card Tab / Shift+Tab Indent / outdent a list item
Comment card Esc Cancel
Count pill Hover Open the stack
Count pill × (on hover) Clear the stack
Stack panel Send all Send the stack plus the draft

Install

From a plugin market

Add this index source in Plugins → Discover → Add index source:

https://samuelraj-game.github.io/dsh-plugin-annotation/index.json

(Discover needs the experimental Custom plugin markets bundle switched on in Plugins → More.)

From npm

dsh plugin install dsh-plugin-annotation

Or add the bundle in the app: Plugins → Installed → Add bundle, then pick dsh-plugin-annotation.

As a profile bundle

This package is both a bundle and a plugin. The bundle patch (cordis.patch.yml) inserts its own row:

- insert:
    - id: ui-annotation
      name: dsh-plugin-annotation

Adding dsh-plugin-annotation to the profile's dsh.profile.bundles (and installing the package) is enough — no hand-editing of cordis.patch.yml.

How it works

  • The browser half registers one entry in the conversation.input.overlay slot, which the shell mounts once per Session, so it is available in every conversation.
  • Selections are tracked with mouseup / keyup / selectionchange; selections inside editable surfaces (the composer, inputs) are ignored.
  • The host half owns the pending annotations: a per-session store behind six loopback routes under /dsh-plugin-annotation, each mutation requiring the x-dsh-plugin-annotation header.
  • On the next agent/pre-step, the host appends a separate hidden user/message whose source.kind is annotation, then drains the store. The direct user message is left untouched and the raw block never renders, because Chat hides ordinary context nodes.
  • Quote-only sends stay possible through an invisible draft token (U+2063): the client writes it so the native send button enables, and the host strips it before the model step, substituting (annotation) if the message becomes empty.
  • Annotated ranges are painted with the CSS Custom Highlight API (::highlight(dsh-annotation)), and the hovered annotation gets a second, stronger highlight; numbered pins re-measure on scroll, resize, and a light interval.
  • Because only the quote text survives a session switch, restored annotations are re-anchored by locating that text in the rendered transcript; a passage that is gone simply gets no pin.
  • Styles use the shell's design tokens (--dsw-alias-*), so light and dark themes both look native.

Compatibility and permissions

DSH >= 0.2.1-rc.5 (declared in engines.dsh)
Profile a base-backed web or Desktop profile that mounts @deepseek-ai/dsh-client-ui-conversation and @deepseek-ai/dsh-host-webserver
Node.js DSH's own — the host half uses only node: built-ins (Buffer), no dependencies
OS any platform the DSH client runs on (Windows, macOS, Linux)

Permissions: no DSH permission category is used. No filesystem access, no outbound network, no command execution, no credential access, no MCP or host APIs.

  • Host reads/writes: one in-memory Map keyed by session id. Nothing is written to disk.
  • Host routes: six routes under the /dsh-plugin-annotation prefix on DSH's own loopback web server. Mutations require the x-dsh-plugin-annotation request header and are rejected otherwise.
  • Client reads: the browser's text selection and the composer draft state already supplied to UI plugins.
  • Client writes: the composer draft through the public inputActions face, one <style> element, and its own fixed-position overlay elements.
  • Dependencies: none. No dependencies, no runtime devDependencies, no preinstall / install / postinstall / prepare scripts, no native binaries, no dynamic code loading.
  • Build: the shipped lib/client.js is the artifact; consuming the package needs no build step.

Main risks

  • The injected context message is persisted in conversation history, so annotations become part of the session log once sent.
  • Pending annotations are volatile: they live in host memory and are lost on a Host restart.
  • The plugin observes text selection document-wide; selections inside editable surfaces and its own UI are ignored.
  • The invisible draft token (U+2063) is written into the composer when annotations are pending and the composer is empty. The host strips it before the model step; if a send fails mid-flight the token can remain in the draft, where it is invisible and harmless but present.

Known limits

  • Pins follow the live DOM range. If the transcript re-renders and detaches the range (for example a streaming message that replaces its nodes), the pin disappears while the annotation stays in the stack.
  • Pending annotations are kept in Host memory: a Host restart clears them. They survive page reloads and session switches.
  • A restored annotation is re-anchored by matching its quote text in the rendered transcript. If the passage was edited, compacted away, or is not currently rendered, the annotation returns without a pin.

Releasing

node scripts/release.mjs patch     # 0.4.0 -> 0.4.1
node scripts/release.mjs minor     # 0.4.0 -> 0.5.0
node scripts/release.mjs 0.4.2     # explicit version

One command bumps package.json, commits the release, pins that commit in docs/index.json, commits the index, and pushes. Add --dry-run to see the plan without touching anything. It requires a clean working tree on main, and it does not publish to npm — the market installs straight from the pinned commit.

Development

The repository is the published package; lib/client.js is hand-authored in the bundle format the client module system expects:

window.__ModuleLoader__.load({ id: "dsh-plugin-annotation", factory: (require) => { /* ... */ } });

After changing the client half, copy lib/client.js into <profile>/node_modules/dsh-plugin-annotation/lib/ and reload the app. Host-half changes need a profile restart, because its routes and the agent/pre-step listener are registered at Host startup.

npm run check    # node --check both halves, then run the host tests

docs/ holds the plugin-market index (index.json + icons/), published with GitHub Pages (Settings → Pages → Deploy from a branch → main / /docs).

License

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit e87bda82274c

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout