dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
deepseekharness自制插件,分支对话:选中对话中的文本创建锚点标签,在独立面板中围绕该文本提问。支持deepseek harness
分支对话 · Branch Chat for DeepSeek Harness
在对话里选中一段文字,就地开一个气泡分支追问;分支共享主对话的全部上下文,但问答只出现在气泡里,主对话保持原样。
Select any passage in a conversation and open a bubble branch to ask follow-ups about it. The branch shares the full context of the main conversation, while its Q&A stays inside the bubble — the main transcript is left untouched.
完整交互(约 11 秒):选中一段文字 → 开分支 → 在气泡里提问 → 回答生成 → 收起后留下 ⑂N 锚点。
Full interaction (~11s): select text → open a branch → ask in the bubble → the answer arrives → collapsing leaves an ⑂N anchor.
BubbleChat(分支对话)是 DeepSeek Harness 的客户端插件。它把「追问」变成一次就地操作:
分支不是新建会话:问题会以「引用 + 你的问题」的形式回到同一个会话,所以模型拥有完整的上下文,回答能准确接上文;生成完成后,插件把回答的渲染结果复制进气泡,并把主转录里这次分支的轮次隐藏起来。
| 功能 | 说明 |
|---|---|
| 选区开分支 | 选中文本后浮出工具条,一键创建锚点(记录轮次、字符偏移、出现序号、前后各 20 字指纹) |
| 锚点标签 | 关闭气泡后,原文旁保留 ⑂N 标签(N 为分支消息数),点击即打开对应分支 |
| 独立气泡面板 | 可拖动、八向缩放、左侧锚点列表宽度可拖、输入区高度可拖(双击各自恢复默认),位置尺寸自动记忆 |
| 共享主对话记忆 | 分支提问以隐藏标记回到同一会话,模型看到完整上下文,回答自然承接前文 |
| 主对话零污染 | 插件只维护自己独占的 <style> 来隐藏分支轮次,不修改主转录任何节点属性;清空即立刻恢复 |
| 完整渲染还原 | 不是把回答当纯文本塞进气泡,而是克隆主会话里那份渲染结果,Markdown、公式、代码高亮、表格都保留 |
| 精确定位回原文 | 轮次 + 偏移 + 上下文指纹 + 第 N 次出现多路尝试,最终用 Range.toString() 严格比对,对不上就拒绝跳转而不是「大致跳过去」 |
| 多分支管理 | 左侧列表显示每条分支的引用摘要与消息数,可切换、可删除(删除会连带该分支对话) |
| 本地持久化 | 锚点、对话、窗口位置与尺寸、隐藏状态都写在 localStorage(dsh-branch-chat/v5),刷新或重启后仍在 |
| 零依赖、无构建 | 只有一个客户端文件,React 由宿主提供;没有构建步骤,不需要打包工具 |
https://github.com/makima-coder/BubbleChat,或本地目录的绝对路径;dsh-client-ui-branch-chat,按提示重启应用;⑂ 悬浮按钮即安装成功。# 从 Git 仓库安装
dsh plugin add https://github.com/makima-coder/BubbleChat
# 或从本地目录安装
dsh plugin add C:\path\to\BubbleChat
安装后重启 DeepSeek Harness。当前 DSH 版本不支持插件自动更新,升级时需要先卸载再安装新版本。
编辑 ~/.dsh/profiles/desktop/package.json:
{
"dependencies": {
"dsh-client-ui-branch-chat": "link:C:/path/to/BubbleChat"
},
"dsh": {
"profile": {
"bundles": [
"dsh-client-ui-branch-chat"
]
}
}
}
lib/index.js 只是宿主侧的空插件,真正的界面在 lib/client.js,由 package.json 里的 dsh.client 声明自动注入浏览器侧。
Enter 发送,Shift + Enter 换行;× 收起;原文旁的 ⑂N 标签可随时重新打开;⌂ 重置窗口位置与尺寸;点圆形「定位」按钮跳回原文并高亮;× 删除某条分支(含其对话内容)。1)锚点 = 文本 + 位置指纹
创建锚点时不只记录文字本身,还记录:所在轮次(data-chat-turn)、该轮文本总长、选区起始字符偏移、这段文字在该轮中第几次出现、以及前后各 20 字的上下文指纹。恢复位置时按「前后指纹 → 前指纹 → 后指纹 → 偏移 → 第 N 次出现 → 首次出现」依次尝试,最后用 Range.toString() 严格校验还原出来的文本是否就是原文;不一致就返回失败,宁可不跳也不跳错。
2)分支消息
发送时把问题包装成带隐藏标记的消息回到同一会话:
⟦分支·<anchorId>⟧关于「<选中原文>」
<你的问题>
anchorId 让插件之后能认出「哪一轮是我这条分支」。注意:这一步是真实写入会话上下文的,所以分支回答拥有完整记忆;「主对话里看不到」只是显示层的隐藏。
3)回答捕获
插件轮询会话运行状态,等本轮生成结束后,在主转录里按标记找到该分支对应的回答容器,克隆其 DOM,移除过程性噪声(data-step-process、代码块按钮等),再注入气泡。因此气泡里的回答与主对话中渲染完全一致。
4)隐藏主对话里的分支轮次
插件只创建并维护一个自己独占的 <style id="branch-chat-hide">,内容是:
[data-chat-turn="N"]:not(:has([data-chat-turn])) { display: none !important; }
只隐藏「叶子轮次」,避免误伤包含多轮的祖先容器;用户提问轮次还要确认确实包含本条分支的标记才会被隐藏。清空这条样式即可立刻恢复,主转录的 DOM 从未被改写。
5)窗口与状态
面板位置/尺寸、输入区高度、左栏宽度、悬浮按钮位置、锚点与全部对话都持久化在 localStorage;刷新页面或重启应用后原样恢复。
BubbleChat/
├── lib/
│ ├── index.js # 宿主侧入口(空实现,仅为加载占位)
│ └── client.js # 全部 UI 与逻辑(浏览器侧,单文件)
├── cordis.patch.yml # bundle patch:单独安装时插入本插件
├── package.json # DSH 插件清单(dsh.bundle / dsh.client)
├── docs/images/ # README 截图
├── LICENSE
└── README.md
data-chat-turn、data-turn-process-answer、data-chat-group-part 等)。DeepSeek Harness 大版本升级可能改动这些标记,届时需要适配。dsh.client.platform = "web",桌面端渲染的也是 Web 客户端)。localStorage 按浏览器/设备存储,不跨设备同步;清空站点数据会丢失锚点与分支对话。lib/client.js 是被宿主直接加载的浏览器端模块,改完重启应用即可生效。[branch-chat] 已加载。localStorage 的 dsh-branch-chat/v5,调试时可手动清空以重置全部锚点。<style>。| 项目 | 版本 |
|---|---|
| DeepSeek Harness | 0.2 预览版 |
@deepseek-ai/cordis(peer) | ~4.0.4 |
| 平台 | Web 客户端(桌面端 / 浏览器) |
| 运行时依赖 | 无(React 由宿主提供) |
欢迎 Issue 与 PR。由于插件依赖 DSH 的客户端 DOM 约定,提交前请说明你测试所用的 DSH 版本与场景;改动尽量小而聚焦,方便 review。
MIT © 2026 makima-coder
BubbleChat is a client plugin for DeepSeek Harness that turns follow-up questions into an in-place gesture:
A branch is not a new session. The question is sent back to the same conversation as a quoted, marker-tagged message, so the model keeps the complete context. Once the answer finishes, the plugin clones its rendered output into the bubble and hides the branch turns in the main transcript.
| Feature | Description |
|---|---|
| Branch from selection | Select text, click the floating button; the anchor stores turn, character offset, occurrence index and 20-character context fingerprints |
| Anchor badge | After closing the bubble, an inline ⑂N badge (N = messages in that branch) marks the passage; click to reopen |
| Floating bubble | Draggable, eight-direction resizable, resizable anchor-list width and input height (double-click each to reset), geometry persisted |
| Shared main-conversation memory | Prompts return to the same session behind a marker, so the model keeps full context and answers coherently |
| Zero pollution of the main transcript | The plugin only maintains its own <style> element to hide branch turns; no node attributes of the transcript are modified and everything restores instantly |
| Faithful rendering | The answer is cloned from the main transcript's rendered DOM, so Markdown, math, syntax highlighting and tables are preserved |
| Exact locate | Turn + offset + context fingerprints + Nth occurrence, then a strict Range.toString() check — if it does not match, the plugin refuses to jump instead of guessing |
| Multi-branch management | Left-hand list with quote summary and message count; switch between branches or delete one together with its thread |
| Local persistence | Anchors, threads, window geometry and hidden state live in localStorage (dsh-branch-chat/v5) and survive reloads |
| Zero dependencies, no build | A single client file; React is provided by the host. No bundler, no build step |
https://github.com/makima-coder/BubbleChat, or the absolute path to a local clone;dsh-client-ui-branch-chat and restart the app;⑂ floating button appears at the bottom-right of the composer when it is active.dsh plugin add https://github.com/makima-coder/BubbleChat # from Git
dsh plugin add C:\path\to\BubbleChat # from a local folder
Restart DeepSeek Harness afterwards. The current DSH release does not auto-update plugins — uninstall and reinstall to upgrade.
Edit ~/.dsh/profiles/desktop/package.json:
{
"dependencies": {
"dsh-client-ui-branch-chat": "link:C:/path/to/BubbleChat"
},
"dsh": {
"profile": {
"bundles": [
"dsh-client-ui-branch-chat"
]
}
}
}
lib/index.js is an empty host-side half; the real UI is lib/client.js, injected into the browser half by the dsh.client field in package.json.
Enter sends, Shift + Enter inserts a newline;× to collapse the bubble; the inline ⑂N badge reopens it later;⌂ resets the window position/size, and the round locate button jumps back to the original passage with a highlight;× deletes a branch and its thread.1) An anchor is text plus a positional fingerprint. Besides the quote, an anchor stores its data-chat-turn, the turn's text length, the selection's character offset, the occurrence index of the quote inside the turn, and 20 characters of context before and after. Resolution tries full context → leading context → trailing context → recorded offset → Nth occurrence → first occurrence, then validates the reconstructed range with Range.toString(). A mismatch fails closed — no “close enough” jumps.
2) Branch messages. The prompt is sent back to the same session behind an internal marker:
⟦分支·<anchorId>⟧关于「<quoted text>」
<your question>
This is a real write into the session context, so the branch answer has full memory; hiding it in the main transcript is purely presentational.
3) Capturing the answer. The plugin polls the session's running state, then finds the answer container for that turn by marker, clones its DOM, strips process noise (data-step-process, code-block buttons) and injects it into the bubble — so the bubble renders exactly like the main transcript.
4) Hiding branch turns. The plugin owns a single <style id="branch-chat-hide"> with [data-chat-turn="N"]:not(:has([data-chat-turn])) { display: none !important; }, hiding only leaf turns (never ancestor containers); a user turn is hidden only after it is confirmed to contain this plugin's marker. Clearing the style restores everything; transcript DOM is never rewritten.
5) Window and state. Panel geometry, input height, list width, floating-button position, anchors and threads are persisted in localStorage and restored across reloads.
BubbleChat/
├── lib/
│ ├── index.js # host-side entry (empty placeholder)
│ └── client.js # all UI and logic (browser half, single file)
├── cordis.patch.yml # bundle patch so the plugin loads standalone
├── package.json # DSH plugin manifest (dsh.bundle / dsh.client)
├── docs/images/ # README screenshots
├── LICENSE
└── README.md
data-chat-turn, data-turn-process-answer, data-chat-group-part, …). Major DSH upgrades may change them and require adaptation.dsh.client.platform = "web"; the desktop app renders the web client).localStorage is not synced across devices; clearing site data loses anchors and threads.lib/client.js is loaded directly by the host; restart the app after edits.[branch-chat] load status.dsh-branch-chat/v5 (clear it to reset all anchors).<style>.| Item | Version |
|---|---|
| DeepSeek Harness | 0.2 preview |
@deepseek-ai/cordis (peer) | ~4.0.4 |
| Platform | Web client (desktop app / browser) |
| Runtime dependencies | none (React from the host) |
Issues and PRs are welcome. Since the plugin relies on DSH's client DOM contracts, please mention the DSH version and scenario you tested; keep changes small and focused for review.
MIT © 2026 makima-coder