DeepSHPlugins
dsh-bubble-explain 项目预览
GITHUB / COMMUNITY PROJECT

dsh-bubble-explain

UI 增强TypeScriptBSD-3-Clause

对话中框选任意文字后点击「解释」按钮,弹出 Markdown 实时流式解释气泡,支持递归追问。

6 StarsHanmiao33 更新时间 2026-09-10
访问 GitHub 仓库
dsh-bubble-explain 项目预览

项目介绍

中文

对话中框选任意文字后点击「解释」按钮,弹出 Markdown 实时流式解释气泡,支持递归追问。

English

Select any text in a conversation and tap the Explain button to get a streaming Markdown explanation bubble, with recursive follow-up questions.

项目信息与收录信号

快照 2026-09-11
作者 / 组织
Hanmiao33
仓库
Hanmiao33/dsh-bubble-explain
GitHub Stars
6
Forks
0
开发语言
TypeScript
许可证
BSD-3-Clause
最近推送
2026-09-10
Manifest
数据中检测到声明

公开仓库不自动等于可商用;许可证与当前兼容性以原项目文档为准。Manifest 和数据评分不构成安装安全认证。

数据评分

72/ 100
维护活跃
100
文档与实用信息
100
生态关注度
24
安装便捷信号
75
项目声明信号
100

近 1 天仍在更新;README 含完整安装与使用说明;关注度尚低(6)。

评分来自已有数据快照的五维模型,仅作浏览参考,不是实际使用评测或安全检测结论。

安装与使用

所有项目资料与许可均以对应 GitHub 仓库为准。

dsh plugin --profile web add "https://github.com/Hanmiao33/dsh-bubble-explain/releases/latest/download/dsh-external-bubble-explain.tgz"

复制命令不会自动执行。请先阅读仓库文档,确认环境要求与许可证。

项目截图

仓库 README

GitHub 原文

已保存的仓库文档快照;文档抓取时间未记录,可能与上方目录介绍处于不同版本。安装前请核对当前仓库说明。

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)

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

使用前核对

安装步骤、兼容版本与授权范围以原项目当前文档为准。Stars 和评分是快照中的导航信号。

安装与排错 · 项目问题反馈

同类项目