Han-1413141 / dsh-sticky-disclosure

Listed

DSH Web client plugin: collapse every expanded section (Think / tool cards) in the conversation in one click, with a customizable hotkey.

mainTool View source

Installation

npx -y @deepseek-ai/dsh plugin --profile web add github:Han-1413141/dsh-sticky-disclosure

This installation command is an unverified starting point generated from the GitHub repository address.

README

Maintainer-authored documentation snapshot.

View on GitHub ↗
Commit 873bc91Synced Aug 18, 2026

dsh-sticky-disclosure

License: MIT Tests awesome · DSH plugin English | 中文

宣传图:一键收起 + 滑出屏幕自动钉住 Think 等标签

DSH Web 客户端插件:一键收起会话里所有展开的可折叠区块(Think 思考行、工具卡片、命令卡片、上下文注入行等),带实时计数的常驻按钮 + 可自定义的快捷键。展开的区块滑出屏幕时,标题会自动钉在会话顶部,随时可以点一下收起。

钉住示意图:滑出屏幕的 Think 等标签自动钉在顶部

✨ 功能

功能说明
📌 滑出自动钉住展开的 Think / 工具 / 命令标签滑出会话顶部后,自动在顶部生成 chip,点击即收起原区块
🔘 全部收起按钮聊天区右下角常驻药丸,实时计数(·N = 当前展开的区块数),一键收起全部展开区块
⌨️ 自定义快捷键默认 Ctrl+Alt+C(macOS ⌘⌥C),齿轮按钮 → 按下新组合键即改,持久保存
🎨 原生外观全部使用应用 --dsw-* 设计令牌,自动跟随深色/浅色主题
🪶 无侵入纯 DOM 实现,不动应用代码;卸载即全量还原

实机截图(真实 DSH Web 实例)

展开中的 Think 行 + 右下角带计数的「全部收起」按钮

展开状态

快捷键设置面板(齿轮 → 设置 → 按下新组合键)

设置面板 捕获新快捷键

一键收起后,计数归零

收起后

为什么需要它

对话一长,展开的 Think 思考行、工具卡片就会攒下一堆——想收起它们得一个个去点标题,而且往下读的时候,标题还会被顶出屏幕。本插件在聊天区右下角放一枚常驻的「全部收起」按钮(实时显示当前展开了几个),再配一个自定义快捷键:一次点击 / 一次按键,全部收起。展开区块滑出屏幕时,标题会自动钉在会话顶部,不用滚回去也能随时收起。

行为细节

  • 滑出自动钉住:展开区块的标题整行滑出会话滚动区顶部后,顶部会出现一枚 chip,显示该区块标题(Think、工具名……);点击 chip 即收起原区块,滚回可见或收起后 chip 自动消失。
  • 「全部收起」按钮常驻会话滚动区右下角,带实时计数(·N);点击收起会话里所有展开的可折叠区块。
  • 快捷键(默认 Ctrl+Alt+C,macOS ⌘⌥C)与按钮等效:一键收起所有展开区块,按下立刻有可观察效果。
  • 展开/收起状态、流式输出、切换会话都由 MutationObserver + 滚动/尺寸监听自动同步,计数始终准确;插件卸载(HMR / 停用)时全部还原。
  • 插件加载时打一条 console.info("[dsh-sticky-disclosure] applied …"),并提供调试句柄 window.dshStickyDisclosureexpanded() / hotkey() / setHotkey(spec))。

⌨️ 自定义快捷键

  1. 点击「全部收起」按钮旁的 ⌨ 齿轮按钮,打开设置面板;
  2. 点击 「设置」,面板进入捕获状态;
  3. 直接按下新的组合键(必须含 Ctrl / / Alt 之一,例如 Ctrl+Shift+K)——立即生效并持久保存(仅存于浏览器 localStorage,不会上传);
  4. Esc 取消捕获;点 「恢复默认」 回到 Ctrl+Alt+C

也可编程设置:

window.dshStickyDisclosure.setHotkey({ ctrl: true, shift: true, code: "KeyK" }) // Ctrl+Shift+K
window.dshStickyDisclosure.hotkey()                                              // "Ctrl+Shift+K"

快捷键设计要点

  • 刻意不用 Escape:应用的对话框与 popup 已占用 Escape(插件内部用 Esc 取消捕获,不影响应用);
  • 输入框聚焦时同样生效(焦点通常留在输入框);
  • 避开 IME 组合输入(isComposing)与 AltGr 组合(getModifierState("AltGraph"),某些布局里 AltGr 会以 Ctrl+Alt 上报,绝不能拦截它输入的字符)。

遮挡关系

  • 「全部收起」按钮与齿轮固定在会话滚动区的右下角。
  • z-index: 15(设置面板 16):高于聊天内容,低于应用浮层(20)与所有弹窗(100/1000 级)——不会盖住权限弹窗、设置面板或欢迎遮罩
  • 全部使用 --dsw-* 设计令牌,自动跟随主题与字体;入场动画尊重 prefers-reduced-motion

安装

需求:Node.js ≥ 20 + DeepSeek Harness(带 dsh plugin 命令的版本,npm install -g @deepseek-ai/dsh)。插件随 dsh web 启动。

方式〇:一键安装(推荐,无需克隆仓库)

PowerShell 一键脚本(复制整行粘贴回车;自动补齐 pnpm、自动探测 git):

irm https://raw.githubusercontent.com/Han-1413141/dsh-sticky-disclosure/main/install.ps1 | iex

或直接命令行(机器上需已有 pnpm 与 git):

dsh plugin --profile web add github:Han-1413141/dsh-sticky-disclosure

没有 git 时可用 GitHub 打包直链(更新时先 remove 再 add):

dsh plugin --profile web add https://github.com/Han-1413141/dsh-sticky-disclosure/archive/refs/heads/main.tar.gz

方式一:本地开发(dsh plugin + 符号链接)

在本仓库父目录执行(相对路径会被锚定到调用目录):

git clone https://github.com/Han-1413141/dsh-sticky-disclosure.git
cd <克隆目录的父目录>
# 符号链接,改 lib/client.js 后刷新页面即生效:
dsh plugin --profile web add link:./dsh-sticky-disclosure
# 或固定安装:
# dsh plugin --profile web add file:./dsh-sticky-disclosure

方式二:手工安装(机器上没有 pnpm)

  1. <DSH_HOME>\profiles\web\package.json(默认 %USERPROFILE%\.dsh\profiles\web\package.json)中:
    • dependencies 增加 "dsh-sticky-disclosure": "link:<本仓库的绝对路径>"
    • dsh.profile.bundles 末尾追加 "dsh-sticky-disclosure"
  2. 在 profile 的 node_modules 里建目录联接(与 pnpm link: 依赖留下的链接一致):
    New-Item -ItemType Junction `
      -Path "$env:USERPROFILE\.dsh\profiles\web\node_modules\dsh-sticky-disclosure" `
      -Target "<本仓库的绝对路径>"
    

激活

插件集合变化在重启时生效(运行中的服务保持旧图)。插件 bundle 按 no-cache 提供:改完 lib/client.js 后只需刷新页面(Ctrl+F5)即可拿到新代码,无需重启服务。

# 首次安装后:停掉当前 dsh web 再启动
dsh web

验证是否进入插件图(应看到 id: sticky-disclosurename: dsh-sticky-disclosure):

dsh --profile web --dump-config | findstr sticky-disclosure

页面加载后,聊天区右下角出现「全部收起」药丸按钮即表示插件已激活。

更新 / 卸载

dsh plugin --profile web update dsh-sticky-disclosure  # 更新到最新提交(git 方式;或重跑一键脚本)
dsh plugin --profile web remove dsh-sticky-disclosure  # 卸载

手工方式:从 package.jsondependencies/bundles 删掉对应条目,删除 profiles\web\node_modules\dsh-sticky-disclosure 联接,然后重启 dsh web

微调

所有行为参数集中在 lib/client.js 顶部常量区:

常量默认含义
DEFAULT_HOTKEYCtrl+Alt+C默认快捷键(可在设置面板修改并持久化)
STORAGE_KEYdsh-sticky-disclosure:hotkey快捷键持久化的 localStorage 键
DOCK_Z_INDEX15按钮/齿轮遮挡层级(须低于应用浮层 z-20)
PANEL_Z_INDEX16设置面板层级(高于按钮、低于应用浮层)
CONTROL_INSET16「全部收起」按钮距滚动区右下角的间距

测试

python test/verify.py   # 需要 Python 3 + playwright(python -m playwright install chromium)

test/ 包含:

  • mock.html —— 复刻 DSH DOM 契约(DisclosureRow 结构 + [data-conversation-scroll] 滚动区)的静态测试台;
  • verify.py —— Playwright 验证脚本(48 项断言);
  • capture.py —— 在真实实例上采集演示截图/GIF 的脚本。

覆盖:按钮出现与计数、一键收起全部(含可见区块与输入框聚焦场景)、自定义快捷键(设置面板、捕获、Esc 取消、持久化、恢复默认、非法规格拒绝)、状态自动同步、composer 排除、卸载全量还原。

本仓库的 CI(.github/workflows/test.yml)在每次推送时运行同一套脚本。

局限

  • 只覆盖会话聊天流[data-conversation-scroll] 内)。「轨迹(Trajectory)」视图使用自己的折叠控件,不在范围内。
  • data-open / data-disclosure-row DOM 契约工作:若上游应用升级改变这些内部结构,需要同步更新选择器。当前契约见 docs/ARCHITECTURE.md

目录

dsh-sticky-disclosure/
├── .github/workflows/
│   ├── test.yml             # CI:Playwright 验证套件
│   └── install-smoke.yml    # CI:一键安装冒烟验证(Windows + Linux)
├── install.ps1              # 一键安装/更新脚本(irm … | iex)
├── package.json             # dsh.client(platform: web) + dsh.bundle 声明
├── cordis.patch.yml         # 宿主树入口行(bundle patch)
├── lib/
│   ├── index.js                 # 宿主半身:惰性标记插件(无行为)
│   └── client.js                # 浏览器半身:自包含 bundle(__ModuleLoader__ handoff)
├── test/
│   ├── mock.html                # 复刻 DSH DOM 契约的静态测试台
│   ├── verify.py                # Playwright 验证脚本(48 项断言)
│   └── capture.py               # 演示素材采集脚本
├── docs/
│   ├── assets/                  # 截图与 GIF
│   └── ARCHITECTURE.md          # 架构与实现细节
├── README.md / README.en.md
└── LICENSE

原理

  • 宿主侧 dsh-client-modules 扫描 Loader 条目中声明了 dsh.client.platform === "web" 的包,把 exports["./client"] 指向的构建产物以 /plugins/<id>/client.js 提供给浏览器,并注入 window.__DSH_BOOT__ 入口图。
  • 浏览器侧 bundle 通过 window.__ModuleLoader__.load({ id, factory }) 注册模块,导出 cordis 插件(name/apply),由 Web shell 的 Loader 激活。
  • 插件本体是纯 DOM 层:不动应用代码,只读 data-open / data-disclosure-row 契约并向原标题行派发 click,因此与应用升级/主题/语言无关。

更多细节(管线、契约、状态模型、快捷键配置、遮挡设计)见 docs/ARCHITECTURE.md

License

MIT

Project files and signals

Shown items are public repository signals detected in the directory snapshot.

TestsDetected
DocumentationDetected

Repository information

Language
JavaScript
License
MIT
Latest release
v1.0.0
Last updated
Aug 15, 2026, 8:18 AM

Install deliberately

Review source code, permissions, lifecycle hooks, dependencies and network access. Test untrusted plugins in an isolated environment.