dsh-session-plus

September 10, 2026 · View on GitHub

dsh-session-plus

Session enhancement plugin: live model provider in the model menu · turn selected text into a code block at the start of the input

中文 English

License DSH Version

dsh-session-plus is a session enhancement plugin for DeepSeek Harness (DSH) that adds two lightweight boosts to the chat session page:

  • 🏷 Show the active model provider at the top of the model selection menu, in real time
  • ✂️ Turn any selected text into a Markdown code block, prepended to the input, with one click

Note

As of v0.4.0, "Open Workspace" has been removed from this plugin. DSH 0.1.5-rc.1 ships a richer built-in Open In… split button (top-right of the session header) that opens the session workspace in an installed directory app, so this plugin no longer duplicates it. See CHANGELOG.md for details.

📑 Table of Contents


✨ Features

1️⃣ Model Provider Header

FeatureDescription
Menu headerInjects a quiet Provider: xxx info row at the top of the model selection menu
Display name firstUses the provider display name from the model directory (same source as the in-menu group titles); falls back to the raw provider id when missing
Live updatesSubscribes to the per-session model directory while the menu is open; the header refreshes instantly on switch
Empty stateShows before the directory reports a selection, then resolves automatically
Bilingual copyFollows the UI locale (简体中文 / English)
Read-only, non-invasivePure display, never interactive or focusable; never touches the shipped menu's behavior or styles; the /model popup stays untouched

2️⃣ Selected Text → Add to Conversation

FeatureDescription
Floating buttonSelect text in the chat message area or the better-sidebar right panel — an "Add to conversation" pill appears centered above the selection; flips below when there's no room above
Prepend insertionClicking inserts the text as a Markdown code block (no language tag) at the start of the input; existing draft stays after it, separated by a blank line
Trailing blank lineThe result ends with a blank line so you can keep typing right after
Fixed triple-backtick fenceAlways uses ``` (product requirement: only ``` is shown)
Standard toolbar behaviorHides on outside click / Escape / collapsed selection / message-area scroll; returns automatically when scrolling stops and the selection is visible again; after clicking, the selection clears, the button hides, and the input regains focus
ScopedTriggers only in the chat page and the better-sidebar right panel; selections in the input, sidebar, or settings never show it
No length limitWraps the whole selection, unbounded
flowchart LR
    A["Drag-select text (chat page / right sidebar)"] --> B{"Selection in an allowed area?"}
    B -- No --> X["No button shown"]
    B -- Yes --> C["Pill appears centered above the selection"]
    C --> D{"Button clicked?"}
    C --> F["Outside click / Esc / scroll"]
    F --> C
    D -- Yes --> E["Text wrapped in a code block, prepended to the input"]
    E --> G["Trailing blank line · clear selection · focus input"]
    D -- No --> H["Keep floating, wait for action"]
    H --> C

🚀 Quick Start

1. Install

cd <absolute-path-to-plugin> && pnpm install
dsh plugin --profile web add dsh-session-plus@link:<absolute-path-to-plugin>

2. Restart and verify

This is a bundle-layer plugin; restart dsh web to activate:

# Stop with Ctrl+C in the terminal, then start again
npm exec @deepseek-ai/dsh web

After restart, open any session:

  • Click the composer's model select — the menu shows the current provider at the top
  • Drag-select text in the message area — the "Add to conversation" button appears

Note

An "Open In…" button in the session header's top-right comes from DSH itself, not from this plugin.

Upgrade & Rollback

Expand

Upgrade: client-layer changes apply on page refresh / HMR; bundle / host-layer changes require restarting dsh web.

Rollback:

dsh plugin --profile web remove dsh-session-plus
# Restart dsh web to finish uninstall

📖 Usage

Model Provider Header

  • Position: first row of the model selection menu (appears as soon as the menu opens).
  • Content: Provider: <display name>; raw provider id when the directory lacks the group; before a selection is loaded.
  • Live: switching models/providers while open refreshes the header immediately; closing the menu removes it, reopening re-injects it.
  • No side effects: model list scrolling, effort levels, and keyboard navigation are untouched; the /model popup is not injected.

Selected Text → Add to Conversation

  • Trigger: drag-select text in the chat message area (assistant reply or user message) or in the better-sidebar right panel; the "Add to conversation" button appears above the selection on release.
  • Result: clicking puts a ```-fenced code block at the start of the input; existing draft content stays after it (blank line separated); the result ends with a trailing blank line.
  • Dismiss: outside click, Escape, collapsed selection, or scrolling the message area hides it; it returns automatically once scrolling stops and the selection is visible again; after clicking, the selection clears and the input regains focus.
  • Edges: selections inside the input / sidebar / settings never trigger.

Note

The fence is always three backticks. If the selected text itself contains three backticks, it may affect that block's Markdown rendering — a known limitation.

Supported Scope

ItemScope
DSH0.1.5-rc.1 (current web profile)
OSNo platform restriction (the host half no longer runs any native command)
BrowserModern Chrome / Safari / Edge

🧪 Tests

npm test

20 unit tests, all passing:

  • Provider label: display-name priority / raw-id fallback / empty-state placeholder / tolerance for empty groups and names
  • Code-block insertion: fence always ``` / prepend composition / empty draft / trailing-blank-line idempotency / ``` inside text still uses ```
  • Host-half mounting: export surface is exactly name + apply (a no-op without inject) — guards the "the host row must stay" constraint
  • Browser-half registration surface: only two conversation.input.overlay registrations, three remaining locale keys, both dictionary and style effects intact, and the session-header / shell.overlay registrations verifiably gone

🗂 Project Structure

dsh-session-plus/
├── lib/
│   ├── client.js   # Browser half: provider header + selected-text add (single bundle, 2 overlay registrations)
│   ├── index.js    # Host half: deliberately empty apply (lets dsh-client-modules discover the browser half)
│   ├── insert.js   # Selected text → code-block composition (unit-testable)
│   └── label.js    # Provider-label pure function (unit-testable)
├── test/           # client / index / label / insert test suites
├── cordis.patch.yml
├── CHANGELOG.md
├── package.json
└── LICENSE

🛠 Tech Stack

CategoryTechnology
RuntimeDeepSeek Harness (DSH 0.1.5-rc.1) · Cordis plugin system
LanguagePlain JavaScript (ESM, no build step)
Browser sideDSH client runtime (@deepseek-ai/dsh-client-*), injected as a single bundle
Host sideNo runtime dependencies: an empty apply host row, kept so dsh-client-modules discovers the browser half
StylingDSH theme variables (--dsw-alias-*), zero custom stylesheets
TestsNode built-in test runner (node --test)

🧭 Roadmap

  • Model provider header (live updates + bilingual copy)
  • Selected text → add to conversation (floating button + code-block insertion)
  • Scoped triggers (chat page + better-sidebar right panel only)
  • Trailing blank line after insertion
  • Remove "Open Workspace" (superseded by DSH's built-in Open In…, see CHANGELOG.md)
  • Escaping / tolerance for fences inside the selected text
  • Insert position options (start / end / cursor)

📄 License

This project is released under the MIT license (SPDX: MIT).