拆分会话头并折叠侧栏面板,腾出更多工作空间
28/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/22 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add TowardsDawn/dsh-layout-tweaks该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
DSH上边栏和左边栏布局优化
README
由 DeepSeek 最新模型翻译生成dsh-layout-tweaks
DSH Web GUI 布局微调 —— 会话头上边栏拆成两行、左侧栏面板列表一键折叠
纯渲染层实现 · 不修改任何其他插件 · 不干预侧栏底部区域 · 免构建
功能 · 效果 · 安装 · 配置 · 工作原理 · 被放弃的尝试 · 兼容性 · FAQ
这是什么
DSH Web GUI 里有两处空间上的不便:会话头上边栏把会话名、工作模式和十几个操作按钮挤在同一行;左侧栏顶部的面板模块(插件、任务看板、技能中心、SSH)始终占着位置,而它们并不是每时每刻都要用。
dsh-layout-tweaks 用一个客户端插件处理这两处,且:
- 不接管任何 slot、不修改其他插件的任何代码;
- 完全不碰侧栏底部区域 —— 上下文洞察 / 会话管理 / 检查更新 / 远程访问 / 今日消费 / 设置 的位置与顺序全由宿主和其他插件决定,本插件一个属性都不写(这是 v0.3.0 起的硬边界,理由见附录);
- 全部通过注入 CSS(外加一个自建的折叠头)完成,React 渲染树零感知;
- 免构建:lib/ 直接手写可加载产物,不需要 tsdown / rolldown / tsc;
- 找不到锚点时静默失效,绝不会把宿主界面改坏。
展开完整文档(README 剩余 1 节)
dsh-layout-tweaks
DSH Web GUI 布局微调 —— 会话头上边栏拆成两行、左侧栏面板列表一键折叠
纯渲染层实现 · 不修改任何其他插件 · 不干预侧栏底部区域 · 免构建
功能 · 效果 · 安装 · 配置 · 工作原理 · 被放弃的尝试 · 兼容性 · FAQ
这是什么
DSH Web GUI 里有两处空间上的不便:会话头上边栏把会话名、工作模式和十几个操作按钮挤在同一行;左侧栏顶部的面板模块(插件、任务看板、技能中心、SSH)始终占着位置,而它们并不是每时每刻都要用。
dsh-layout-tweaks 用一个客户端插件处理这两处,且:
- 不接管任何 slot、不修改其他插件的任何代码;
- 完全不碰侧栏底部区域 —— 上下文洞察 / 会话管理 / 检查更新 / 远程访问 / 今日消费 / 设置 的位置与顺序全由宿主和其他插件决定,本插件一个属性都不写(这是 v0.3.0 起的硬边界,理由见附录);
- 全部通过注入 CSS(外加一个自建的折叠头)完成,React 渲染树零感知;
- 免构建:lib/ 直接手写可加载产物,不需要 tsdown / rolldown / tsc;
- 找不到锚点时静默失效,绝不会把宿主界面改坏。
功能
| # | 功能 | 默认 | 说明 |
| ① | 会话头拆两行 | 开 | 第 1 行 = 会话名 + 工作模式;第 2 行 = 撤销 / 恢复 / 快照 / 对话撤回 / 归档 / 标签备注 / 移动至工作区 / 复制链接等其余控件;页签行保持不变 |
| ② | 面板列表折叠 | 展开 | 侧栏顶部新增折叠头,一键收起「插件 / 任务看板 / 技能中心 / SSH」,把空间让给工作区与会话列表 |
② 就是点击折叠头本体,状态即时生效并记忆;侧栏收起成 56px 轨道时折叠头自动隐藏。
效果
Before → After
| Before(未启用) | After(已启用) |
| before | after |
- 会话头:dsh bug 检查 + 标准模式 独占第一行,其余控件整体下移一行,不再横向挤压。
- 侧栏:面板列表上方多了一个折叠头 ▾ 面板与插件 4。
底部区域在两张图里完全一致 —— ⟳ 检查更新 / ⇄ 远程访问 / 上下文洞察 / 会话管理 / 今日消费 / 设置 的位置、顺序、横向排列都没有任何变化。这是刻意的边界:本插件不下发任何针对底部区域的规则,也不给那里的节点写任何属性(夹具右下角会实时报告「底部区域被写入的节点数」,必须为 0)。
② 折叠
collapsed
示意图由仓库内的离线夹具 test/fixture.html 渲染 —— 它用实测的 DSH 客户端 DOM(class 名与层级取自真机核对)复刻了会话头与左侧栏,因此不用登录 GUI 也能验证布局。
安装
方式一:用 dsh plugin 命令(推荐)
dsh plugin --profile web add "github:TowardsDawn/dsh-layout-tweaks"
该命令会把本包写进 profile 的 dsh.profile.bundles,并让 bundle 层读取本包的 cordis.patch.yml。
方式二:手动挂载
1. 把本目录放到任意位置(例如 <DSH插件目录>/dsh-layout-tweaks);
2. 编辑 <DSH_HOME>/profiles/web/package.json:
{
"dependencies": {
"dsh-layout-tweaks": "file:<本目录绝对路径>" },
"dsh": {
"profile": {
"bundles": [
// …其他插件…
"dsh-layout-tweaks"
]
}
}
}
3. 重启 dsh web。
本插件是纯客户端插件:host 半(lib/index.js)只是装配树里的挂载点,不注册服务、不读取会话。
注意:客户端半(lib/client.js)是被宿主在启动时读入内存的(响应头带 immutable + 一年缓存),所以改动 lib/client.js 之后需要重启 dsh web 才会生效;日常的折叠开关不受影响,即时生效。
临时停用(不卸载)
编辑本包 cordis.patch.yml:
- insert:
- id: dsh-layout-tweaks
name: 'dsh-layout-tweaks'
disabled: true
卸载
删掉 dsh.profile.bundles 里的那一行与对应依赖即可。插件在卸载时会自行移除注入样式、自建节点与 上的状态属性。
配置
折叠开关(②)
点击折叠头即可折叠 / 展开面板列表。状态记在浏览器 localStorage,键名 dsh-layout-tweaks:v1:
json
{ "headerTwoRows": true, "collapsed": false }
关闭两行模式(①)
v0.3.0 起,折叠头上不再挂设置入口(原来的 ⚙ 与弹层已移除),① 默认开启。需要关掉时,在浏览器控制台执行: js
const s = JSON.parse(localStorage.getItem('dsh-layout-tweaks:v1') || '{}')
s.headerTwoRows = false
localStorage.setItem('dsh-layout-tweaks:v1', JSON.stringify(s))
location.reload()
恢复默认(两行开启、面板展开): js
localStorage.removeItem('dsh-layout-tweaks:v1'); location.reload()
旧版本留下的 foldEntries / bottomKeep 字段已不再读取,留着无影响。
工作原理
为什么不走 slot
DSH 的 slot 系统对「重排别人的 UI」有三个硬约束(详见 @deepseek-ai/dsh-client-ui-slots 的设计):
1. single 槽位独占、声明即认领:conversation.session.header 已被 @deepseek-ai/dsh-client-ui-conversation 自己注册占据,再注册会抛 SlotOwnershipError。
2. 条目的 disposer 会递归移除它声明的子槽:即使强拆原注册再顶替,actions / utilities / corner 三个子槽连同其他插件注册的按钮会一起消失。
3. list 条目的渲染位置由宿主决定:sidebar.footer.action 与 sidebar.panellist 是两个不同的槽位与容器,注册对象绑定槽位名,跨容器搬移不可能。
因此本插件只做「渲染层重排」:不改结构、不搬 React 节点、不抢槽位。它对 DOM 的全部写入只有一个属于自己的折叠头节点。
① 会话头拆两行:零 DOM 注入的断行符
真实 DOM(data-slot 锚点是 display:contents 的透明包装,所以 titleRow/tabs 直接参与 的 grid): html
会话名
标准模式 ← agent-preset,order:-10,恒定第一个撤销 / 恢复 / 快照 …
归档 / 标签 / 移动 …
做法: css /* 拆掉 titleCluster / headerActions 两层盒子,让 crumbs 与各控件成为 titleRow 的 flex item / … > div:first-child{ flex-wrap:wrap } … > div:first-child > div:has(> nav){ display:contents } … div:has(> [data-slot="conversation.session.header.actions"]){ display:contents } / 零宽断行符:伪元素本身就是 titleRow 的一个 flex item /
… > div:first-child::after{ content:""; order:5; flex-basis:100%; height:0 }
/ 排序 / … nav{ order:0 } [data-slot="conversation.session.header.actions"] > :nth-child(1){ order:1 } /* 工作模式 / [data-slot="conversation.session.header.actions"] > :nth-child(n+2){ order:10 } … headerUtilities{ order:11 } … headerCorner{ order:12 }
::after 伪元素的妙处:它天然是宿主元素内部的 flex item,因此不需要往 DOM 里插任何节点就能造出断行点,React reconciliation 完全无感。
② 折叠头
唯一注入的 DOM 节点(.dsh-lt-head),由插件自己创建、自己插入、自己清理:
- 定位锚点:侧栏根的直接子元素 nav(面板列表),退化为工作区区容器;用 insertBefore 放在它前面,不移动任何 React 管理的节点;
- 收起动作是纯 CSS:html[data-dsh-lt-collapsed] [data-slot="sidebar"] > div > nav{ display:none };
- 维护方式:MutationObserver(documentElement + subtree)+ requestAnimationFrame 节流,确保 SPA 重挂载后回到位;
- 自激防护:文本只在真的变化时写入(否则 textContent 赋值会再次触发 observer);
- 侧栏收起为 56px 轨道时由 CSS 隐藏([class="collapsed"])。
使用的 DOM 锚点
| 用途 | 锚点 |
| 会话头槽位 | [data-slot="conversation.session.header"] |
| 头部控件槽位 | [data-slot="conversation.session.header.actions" / .utilities / .corner] |
| 侧栏宿主 / 根 | [data-slot="sidebar"] → 其第一个子元素 |
| 面板列表 | 侧栏根的直接子元素 nav |
| 工作区区(折叠头兜底锚点) | 侧栏根的子元素 div:has(> [data-slot="sidebar.workspaces"]) |
全部为 data-slot 属性、结构关系与类名后缀,不使用会随版本变化的 CSS Module hash 前缀(如 wSkVaW_ / hHd-Xa_)。
附录:一次被放弃的尝试
v0.1.0 → v0.2.4 之间,本插件还做过一件事:把侧栏底部的「上下文洞察 / 会话管理」这类功能入口搬到面板列表下方,并收进折叠块。v0.3.0 把它整套删掉了,因为收益(少占一屏)远小于代价。留下的教训写在这里,免得以后重蹈:
1. 底部入口与面板列表的注册方式差异很大。 它们属于不同的槽位、住在不同的容器里、受不同的布局约束;「并入折叠块」只能靠在渲染层把整条容器链拆成 display:contents 来伪造,天生脆弱。
2. order 作用于「布局」上的 flex item,而选择器必须按「DOM 层级」书写。 display:contents 只让容器在布局上透明,它在 DOM 里仍是那些条目的父元素 —— 一开始把选择器写成直接子级,结果匹配不到任何条目,它们保持默认 order:0 全部堆到侧栏顶上。
3. 拆掉容器盒子会连带改变容器自身的 flex 方向。 这是最贵的一个坑:底部入口原本待在横向容器里靠 flex:1 占满宽度,被搬进侧栏根(纵向容器)后,同一个 flex:1 变成「抢占高度」—— 实测入口被撑到 125px(正常 36px),工作区列表被挤到 0 高度,表现是「工作区/会话列表不见了」。
4. 同一批条目可能已经被别的插件排序了。 实测有另一个插件(用 data-dsh-frame / data-dsh-part 标记侧栏)下发 [data-dsh-frame]:not(…) [class="footerActions"] > [data-slot="sidebar.footer.action"] > :not(…) { order: 1 },特异性 (0,6,0),比本插件的 (0,3,1) 高,会把分类结果整片压掉。最终只能靠清一色 !important 对抗 —— 而这本身就是在给别的插件制造同类问题。
5. 基线规则的特异性会反噬分类规则,得靠 :where() 把基线压到零特异性才压得住。
结论:侧栏底部区域交给宿主和其他插件,本插件一个字都不改 —— 外显布局与「本插件从未有过 footer 干预」时逐像素一致,新插件注册什么就长什么样。从 v0.3.0 起,npm test 里有一组反向断言专门盯着这条边界:源码中一旦重新出现 data-dsh-lt-fold / data-dsh-lt-keep / data-dsh-lt-box / data-dsh-lt-settings / BOTTOM_KEEP_SELECTORS / sidebar.footer.action / footerActions,测试直接失败。
兼容性
| 项目 | 要求 |
| 宿主 | DSH Web 客户端(DOM 形态基于 0.2.0-rc 系列实测) |
| 浏览器 | 支持 :has() 的现代浏览器(Chrome / Edge 105+、Firefox 121+、Safari 15.4+) |
| 降级 | 不支持 :has() 时两行重排规则被 @supports 挡下,插件静默不生效;折叠功能仍可用(它不依赖 :has()) |
| Node(仅安装时) | ≥ 22.19 |
已知限制
- 依赖宿主 DOM 形态:DSH 大版本若重构会话头或侧栏结构,规则会失配。此时表现是「插件不生效」而不是报错;更新选择器即可。
- 折叠头假设侧栏根的第一个 nav 就是面板列表(找不到时退化为工作区区容器)。面板列表为空的极端情况下,折叠头会插在工作区区之上 —— 仍可点击,只是没有面板可折叠。
- 顶部两行假设 actions 的第一项是工作模式(它本身带 order:-10,恒定第一个)。若上游调换顺序,第 1 行的内容会跟着变。
- 第 2 行是普通 flex 行(flex-wrap):窗口很窄或注册了很多头部按钮时会自然溢出到更多行,这是刻意行为,保证控件不被裁切。
- 折叠头是自建节点,与宿主原生的面板列表标题(若有)可能视觉上并列 —— 属预期。
FAQ
会影响其他插件吗?
不会。插件不调用任何其他插件的接口、不改它们的注册、不移动它们渲染的节点,也不给侧栏底部区域的任何节点写过属性。它对 DOM 的唯一写入是一个属于自己的折叠头节点(卸载时移除)。
为什么不做成标准的 slot 插件?
见工作原理 —— single 槽位独占、子槽级联销毁、list 条目位置由宿主决定,这三条让「重排别人的 UI」在 slot 层无法实现。渲染层重排是唯一不牵连其他插件的做法。
为什么不再把底部入口(上下文洞察 / 会话管理)搬进折叠块?
见附录。一句话:那批条目的注册方式与面板列表差异太大,跨容器搬移必然要拆容器盒子、改容器 flex 方向、与其他插件的排序规则抢优先级 —— 换来的只是少占一屏,不值得。
改完要重启 DSH 吗?
改 lib/client.js 需要重启 dsh web(客户端半在启动时被读入内存,并带长缓存);安装/卸载同理。日常的折叠开关不需要,即时生效并自动记忆。
怎么完全恢复原样?
点开折叠头展开面板列表,然后清掉 localStorage 的 dsh-layout-tweaks:v1(或按配置里的代码关掉 ①)。要在装配层面彻底移除,见安装里的「卸载」。
怎么确认插件没有动我的底部控件?
打开离线夹具 test/fixture.html?on=1(或 &collapsed=1),右下角会显示自检结果:「底部区域被写入的节点数:0(应为 0)」。那一页的底部区域是按真机结构复刻的(图标按钮 / 功能入口 / 多控件卡片 / 设置),数字非 0 就说明边界被破坏了。
开发
本插件免构建,lib/ 即产物: bash
离线预检(语法解析 / 模块注册协议 / factory 导出 / host 半 /
关键标记 / 底部区域零干预反向断言 / 必需文件,共 24 项)
—— 客户端插件最容易翻车的一类错误会在这里被拦下:整段 CSS 活在一个模板字符串里,
注释里误用反引号会提前终止它,模块 import 失败(DSH 界面报 "import failed")
npm test
离线夹具:用实测 DOM 复刻件验证布局(无需登录 GUI)
test/fixture.html → 关闭插件(before)
test/fixture.html?on=1 → 启用插件(after)
test/fixture.html?on=1&collapsed=1 → 启用并处于折叠态
push 前请先跑 npm test:客户端插件的错误只会在浏览器里炸,而这个脚本不需要 DSH、也不需要浏览器。
夹具里复刻了真机底部区域的原样结构(含另一插件的 order 规则),并内置一条自检:底部区域被本插件写入的节点数必须为 0。修改 lib/client.js 里的 CSS 常量后刷新浏览器即可看到结果;若在真实 DSH 里验证,注意先展开侧栏(收起为 56px 轨道时插件不显示折叠头)。
目录结构
dsh-layout-tweaks/
├─ lib/
│ ├─ index.js # host 半:空挂载点 │ └─ client.js # 浏览器半:两行重排 + 折叠头(免构建) ├─ test/ │ ├─ fixture.html # 离线夹具(实测 DOM 复刻 + 零干预自检) │ └─ smoke.mjs # 离线预检(npm test) ├─ assets/ # README 截图 ├─ cordis.patch.yml # bundle patch:把插件挂进装配树 ├─ package.json ├─ CHANGELOG.md └─ LICENSE
License
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
TowardsDawn/dsh-layout-tweaks
拆分会话头并折叠侧栏面板,腾出更多工作空间
相关插件 · 其他
模型破甲清洗HunYiSage/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 16,993已汉化DeepSeek 客户端
73
女娲蒸馏alchaincyf/nuwa-skill
输入名人名字,提炼其思维模型与决策方式供你调用
★ 37,308已汉化DSH
72
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 888已汉化DSH
71.6
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,269已汉化DSH
70.8
这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。