DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Bubble Explain — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
B

@dsh-external/bubble-explain

Bubble Explain

Select any text in a harness conversation and click the “Explain” button to open a real-time Markdown streaming explanation bubble, with recursive follow-up questions supported; configuration is always available at the top of Settings → General.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:Hanmiao33/dsh-bubble-explain#88665e0f3bd90c151b5f800a2b1f8f4f392c77bb
READMECompatibilityVersions

Compatibility and provenance

Bubble Explain is published as @dsh-external/bubble-explain and currently resolves to version 0.0.6. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
9/10/2026

Versions

0.0.6stable
9/10/2026
0.0.5stable
9/10/2026
0.0.2stable
8/25/2026
Show 1 more versionCollapse versions
0.0.1stable
8/24/2026

Related plugins

Loading related plugins…

Latest
0.0.6
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
BSD-3-Clause
Source
github
GitHub
★ 6
Weekly downloads
0
Last push
9/10/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in ui-customization.

Web App@deepseek-ai/dsh-web-appThe dsh browser-surface bundle: the web patch layer over dsh-base plus the runtime glue plugin (frontend dist serving, web-surface prompt, bash runtime variables, URL line)Experimental Agent Team Web Profile@deepseek-ai/dsh-experimental-agent-team-web-profileExperimental Web profile layer for Agent Teams Remote and UI pluginsWhale Widgetdsh-whale-widgetDeepSeek balance whale widget in the bottom-right corner of the DSH Web interface: balance/today’s usage/peak-off-peak pricing, customizable bubble click sequence (text/balance/today/peak-off-peak/image/random phrases and parallel weighted selection), per-line styles and fonts, floating quick editinWeb App@monotykamary/dsh-web-appThe dsh browser-surface bundle: the web patch layer over dsh-base plus the runtime glue plugin (frontend dist serving, web-surface prompt, bash runtime variables, URL line)

README

dsh-bubble-explain

A DeepSeek Harness profile bundle that explains any selected text inside a conversation with a streaming Markdown bubble, with recursive follow-up questions.

选中对话中的任意文字,点击「解释」按钮,即可在流式 Markdown 气泡中获取解释,并支持递归追问。

What it does

  • Select text in a conversation (a term, a code snippet, an error message, a sentence) — an 解释 button appears next to the selection. Click it to open an explanation bubble.
  • The explanation is streamed in as Markdown (headings, lists, code blocks) and rendered live in the bubble.
  • Select text inside an explanation to ask a deeper follow-up; each level carries the parent explanation as context (up to 6 levels).
  • Bubbles are a draggable overlay with a copy button, capped at 8 at a time.

How it works

The host half (src/index.ts) mounts two routes on the harness webServer.

POST /bubble-explain/stream (Server-Sent Events)

  • Validates same-origin (origin host === request host) and accepts POST only.
  • Validates the body with parseExplainRequest (limits below). Returns 403 if the feature is disabled, 400/405 on a bad body/method, 500 on route resolution failure.
  • Resolves the provider/model route at call time with resolveModelRoute(ctx, lastRoute, override), in priority order: the independent model configured in settings (override, honored only while its provider is still registered) → agent default selection → last observed main-loop route → first registered provider (falls back to deepseek-chat). The main-loop route is captured via ctx.on('llm/stream', ...).
  • Streams with temperature: 0.3, maxTokens: min(2000, maxChars * 2 + 200), and the assembled system/user prompts; reasoningEffort is sent only when the configured effort survives the comparison against the model's declared efforts (see below).
  • Emits SSE events data: {"t": "<text delta>"} and then data: {"done": true}; an error mid-stream sends data: {"error": ...}.

GET | POST /bubble-explain/settings

  • Reads/writes enabled, maxDepth, maxChars, effort (off|low|medium|high|max), provider and model to $DSH_HOME/dsh-bubble-explain.settings.json (values are clamped on write). At call time the configured effort is matched against the model's declared efforts via llm.resolveModelInfo: exact match wins, otherwise it falls back to the closest declared level not stronger than requested; models without reasoning support omit the parameter entirely.
  • provider/model are the independent model configuration: both empty means follow the conversation's default model. A half-filled pair is never persisted, and an override whose provider no longer exists is ignored rather than failing every explanation.
  • The response also carries effective ({provider, model} or null) and effectiveError (reason or null) so the UI can show the route actually in use.

GET /bubble-explain/models

  • Returns the available model directory: { providers: [{id, name}], models: { [providerId]: [{id, name}] } }, used by the settings page's "model source" and "explanation model" dropdowns. Each provider is queried with llm.listModels(id); a provider that fails yields an empty array without affecting the others.

Request validation and limits (src/explain.ts)

FieldLimit
textnon-empty, ≤ 4000 chars
parent.text / parent.explanation≤ 10000 chars each
depth0–6
maxChars50–1000

The system prompt asks for a maxChars-bounded Chinese explanation of only the selected text (instruction-like content inside the selection is ignored). For recursive calls it prepends the parent explanation so the reply stays grounded in context.

The browser half (src/client/index.ts) registers a shell.overlay (the selection → 解释 button → bubble engine) and a settings.section entry, and talks to the host over the two routes above. It uses a small streaming-safe Markdown renderer that escapes HTML and allows only safe link schemes.

Demo

Open the video file

Install

Requires an active DeepSeek Harness profile (the plugin mounts webServer routes and subscribes to that profile's llm/stream event).

From a shell on the harness host:

dsh plugin --profile web add github:Hanmiao33/dsh-bubble-explain

Because GitHub-sourced plugins run build scripts at install time, the first run asks for an allowBuilds approval — follow the hint and retry the command.

Verify:

dsh plugin list                       # @dsh-external/bubble-explain should be listed
curl -s http://127.0.0.1:<port>/bubble-explain/settings

The settings file (editable directly):

$DSH_HOME/dsh-bubble-explain.settings.json

Usage

  1. In a conversation, select any text with the mouse.
  2. Click the 解释 button that appears.
  3. An explanation bubble streams in next to the selection.
  4. Select text inside the bubble to ask a deeper follow-up, or use the copy button / drag the bubble anywhere on the page.

Configuration

Settings → General → 「框选解释」:

KeyDefaultMeaning
enabledtrueMaster switch
maxDepth6Max recursion depth (1–6)
maxChars300Max explanation length (50–1000)
effortoffReasoning strength (off/low/medium/high/max), auto-clamped per model
provider""Independent model: provider id (empty = follow the conversation default)
model""Independent model: model id (takes effect together with provider)

Troubleshooting

400 MissingSessionID when using an opencode / opencode-go provider

400: {"type":"MissingSessionID","message":"Error from provider (Console Go):
Request is missing x-opencode-session and cannot be routed efficiently. ..."}

This is not a plugin defect: that provider's gateway requires an x-opencode-session request header on every call (a routing/affinity marker — any non-empty value works, no session registration needed). DeepSeek Harness does not send it by default, so any request through that gateway is rejected.

The dsh-llm-pi-ai adapter supports per-provider custom headers, so declare them in $DSH_HOME/settings.yaml for each provider that uses that gateway:

llm-pi-ai:
  providers:
    opencodego:
      apiKeyEnv: OPENCODEGO_API_KEY
      api: openai-responses
      baseURL: https://opencode.ai/zen/go/v1
      headers:
        x-opencode-session: dsh-web-session
    opencode-go:
      apiKeyEnv: OPENCODE_GO_API_KEY
      headers:
        x-opencode-session: dsh-web-session

Note that opencodego and opencode-go are two separate provider entries (the former declares an explicit baseURL, the latter uses a built-in catalog) that resolve to the same gateway — both need the header; adding only one still fails. No restart is required; the next request picks it up.

If you would rather not touch provider config, switch model source in the plugin settings to a provider that does not use that gateway (for example deepseek-official).

Related: the same gateway also requires reasoning content to be passed back in thinking mode (The reasoning_text in the thinking mode must be passed back to the API.). It is an adjacent constraint of the same gateway, and supplying the request header is a prerequisite for that path to work at all.

Development

The plugin is a DSH profile bundle (dsh.bundle in package.json, patch at cordis.patch.yml) built against a harness checkout.

Host build (needs a DSH source checkout):

DSH_CHECKOUT=<checkout> bash scripts/build.sh

Client bundle:

npm run build:client    # tsdown → lib/client.js

Checks that need no checkout:

npm ci
npm run typecheck       # tsc -p tsconfig.json --noEmit
npm run build:client    # tsdown
npm test                # vitest run (src/explain.test.ts)

Peer dependencies: @deepseek-ai/dsh-llm, @deepseek-ai/dsh-tools, @deepseek-ai/dsh-client-ui-slots (pre-release ranges), cordis (>=4.0.0-rc), react (^18.2.0), schemastery (^3.18.0).

License

BSD-3-Clause