DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Sidebar Focus — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
S

dsh-sidebar-focus

Sidebar Focus

根据实际运行情况控制 DSH 左侧边栏的排序和展开状态:工作区中的某个会话启动时,该工作区会浮到顶部,并在会话结束后保持该位置;只有最近活跃的 N 个工作区保持展开;六个开关和一个数量设置分别控制这些规则。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:wjingshan/dsh-sidebar-focus#b47c4ea2931822147231e4082d198d27ba80c8a6
README兼容性版本

兼容性与来源证明

Sidebar Focus 以 dsh-sidebar-focus 发布,当前版本为 0.3.2。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/10/18

版本

0.3.2stable
2026/10/18
0.3.1stable
2026/10/18
0.2.0stable
2026/10/15
查看其余 1 个版本收起版本
0.1.0stable
2026/10/11

相关插件

正在加载相关插件…

最新版
0.3.2
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
github
GitHub
★ 0
周下载
0
最近提交
2026/10/18
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 ui-customization 分类下经过校验的插件。

Web App@deepseek-ai/dsh-web-appdsh 浏览器界面捆绑包:位于 dsh-base 之上的 Web 补丁层,加上运行时粘合插件(提供前端 dist、Web 界面提示符、bash 运行时变量和 URL 行)Experimental Agent Team Web Profile@deepseek-ai/dsh-experimental-agent-team-web-profile用于 Agent Teams Remote 和 UI 插件的实验性 Web 配置层Whale Widgetdsh-whale-widgetDSH Web 界面右下角的 DeepSeek 余额小鲸鱼挂件:余额/今日已用/峰谷定价、自定义泡泡点击序列(文本/余额/今日/峰谷/图片/随机语句与并列加权选择)、逐行样式与字体、悬浮快捷编辑、音效与每轮消耗、自定义角色/动图/音效、吸附与翻转自定义Ab Chartdsh-ab-chart带有绘制其调用的浏览器卡片的图表渲染工具,封装在一个可发布的插件包中

README

dsh-sidebar-focus

左侧工作区的排序与展开:按「有没有在跑」和「你正在哪儿」决定。六条规则,每条一个开关,位置在 插件页 → 点开 dsh-sidebar-focus 之后的详情页里(在描述与行列表之间)。

安装

dsh plugin --profile web add dsh-sidebar-focus

还没上 npm 时用 GitHub 源:

dsh plugin --profile web add github:wjingshan/dsh-sidebar-focus

装完刷新页面即可 —— 本插件是纯客户端(宿主半身是空的),不需要重启 dsh web。

它做什么

设置默认作用
置顶最近有活动的工作区开有会话跑过的工作区排到最前,按最近一次活动排序。跑完不会掉回原位,只有更新的活动才把它往下挤一位。只影响显示,你手动拖出来的工作区顺序从不被改写
置顶当前会话所在的工作区开你正在用的那个会话(包括刚新建、还没开始跑的)所在的工作区也排到最前。新建的会话不渲染状态点,只靠上面那条永远浮不上来
自动展开正在运行的工作区开有会话在跑、或正在等你的工作区自动展开。宿主本身只在「当前会话所在的工作区」上这么做,这条把它扩展到所有在跑的工作区
置顶正在进行的会话开运行中与等待你处理的会话排到所属工作区的最前
收起没有运行的工作区开没有会话在跑的工作区保持折叠;刚跑完的会先留 2.5 秒再收(宿主分两步报告「跑完了」:先清 running、之后才升起完成提醒)
保留未读完成提醒开含「已完成未查看」的工作区不自动折叠,避免刚跑完的会话被收起来
只保留最近活跃的工作区展开2最近有会话跑过的前 N 个工作区一直展开,其余空闲的在宽限期后收起。用 − / + 调整,范围 0–20,0 = 关掉这条

交互语义:什么时候它不接管

自动折叠最烦人的失败模式是「你点开、它立刻折回去」。所以两侧都留了 意图豁免:

  • 你亲手展开一个空闲工作区 → 它保持展开,插件不再碰它,直到这个工作区重新变忙再变闲;
  • 你亲手折叠一个正在运行的工作区 → 它保持折叠,插件不替你展开,同样直到忙碌状态再次变化。

豁免只在本次页面会话内有效,刷新后回到规则本身。判断依据是 aria-expanded 上不是本插件 写出的翻转——所以「搜索结果跳转」「新建会话」这类宿主自己的展开,也被当成你的意图而保留。

另外两条不参与自动折叠的例外:

  • 未分组(Ungrouped)永不折叠:那是散落会话的收容所,不是谁主动选的工作区;
  • 当前选中会话所在的工作区保持展开:否则切换会话会落到一个被折起来的组上 (宿主的自动展开只对「没有存过状态」的组生效,而本插件会写状态)。

做法,以及为什么

  • 排序不移动 DOM:列表列原本是 overflow-y:auto 的块容器,order 对它无效;插件先把它变成 flex 列([data-wsf-rank-tree]),再用 order 给忙碌工作区 / 活动会话排名。DOM 节点从不移动, 所以 React 的 reconciliation 与内置的 FLIP 行动画都不受影响。
    • order 作用在 flex item 上,而每一行外面还套着 HoverCard 的 <span>,所以排名规则用 :has() 同时匹配「被包一层」与「裸行」两种形状;JS 侧同样不能假设 parentElement, 分组位置一律由 sectionOf() 向上解析。
    • 排序是纯展示:不写 Workspace.sessionIds,也不碰你手动排序的结果。
  • 「浮到顶部」有两个互相独立的理由:工作区忙(行状态点 ∪ 状态快照),或者它装着你当前选中的 会话。后者专门为 blank 的新会话而加:宿主的 SessionNodeItem 把状态槽写成 !row.blank && …, 一个刚建、还没发消息的会话一个状态点都不渲染(data-state 根本不存在),状态快照里也还没有它, 所以「忙」这条路永远看不见它;而 aria-selected="true" 对 blank 行同样成立,正好补上这个缺口。 两条理由分别由 pinBusyWorkspaces 与 pinCurrentWorkspace 掌管,关掉一条不会影响另一条。
  • 名次是锁存的,不是实时读数:只有工作区从「不活跃」变成「活跃」的那一刻才记时间戳,活跃期间 不再刷新;排名写成内联 order(每条工作区的名次都不同,静态 CSS 表达不了),从未活动过的工作区 不带 order,保持原生顺序排在后面。于是跑完不掉位,只有更新的活动才把它往下挤一位。
  • 排序分两段,运行中的永远在前:第 1 段是正在跑 / 正在等你的工作区(段内按最近活动倒序), 第 2 段是其它曾经活跃过的工作区(同样按最近活动倒序)。所以「跑了很久但还在跑」不会被「刚活动完 又闲下来」的挤到后面 —— 锁存只决定同一段内的相对顺序,不跨越段。
  • 折叠要等连续空闲 2.5 秒:宿主分两步报告「跑完了」(先清 running,之后才升起 completionUnread),在第一帧「看起来空闲」时就折,会关掉一个刚出结果、提醒还没到的工作区。 两个配套细节:宽限期到点时若没有任何 DOM 变化,是没有人来叫醒扫描的(用 wakeIn() 定时器补); 新活动挣到的名次是在扫描过程中发现的,而 ranking 算在扫描开头(用 rankDirty 补一次扫描)。
  • 「最近几个保持展开」和「排序」共用同一个次序:折叠判定里读的就是 ranking(lastActive 排名), 所以列表最上面那 N 个就是保持展开的那 N 个,不会出现「浮在最上面却折着」的矛盾。把它设成 0 时判定退化成原来的「空闲 + 宽限期就折」。正在运行的工作区本来就因为 blocking 不会被折,与排名无关。
  • 折叠是一次状态写入:折叠的组根本不渲染会话行(宿主的 deriveGroups 对折叠组返回空 sessions),所以 DOM 层做不到,必须改展开状态本身。写入走宿主自己的视图 store: ctx.get('uiWorkspace').view.setGroupExpanded(key, expanded),键就是工作区 id。
  • 「有没有在跑」不能只读行:只看 DOM 的判据在这里必然出错——组一折起来就没有行可读,于是 「里面有会话开始跑了」永远看不见,那个工作区会一直关着(用户报过:正在运行的工作区被折叠,打不开)。 忙碌判定因此改为读 Session 状态快照 useSessionStatus(running / pendingInteraction / completionUnread,与三条判据一一对应)加 Workspace 成员表 useWorkspaces (items[].sessionIds 说明哪些会话属于哪个工作区)。这两个事实与「有没有渲染成一行」无关, 折叠态照样成立,所以折叠中的工作区一旦开工就会被看见并展开。 两个 hook 由挂在 shell.overlay 上的零渲染桥接组件发布给 watcher(选它只因为那个席位永远挂载)。 行仍然照读——行级标记要用,快照未就绪时也要回退;两个来源取并集,任一见到在跑就不许关。
  • 所有开关都是开关:关闭时对应的 data-wsf-* 标记会被移除,CSS 规则随之失效,侧栏回到原生 布局与原生折叠行为——不做「半开」状态。

依赖的宿主契约(实测于本 profile 的内置 dsh-client-ui-workspace)

事实来源
会话列表是 div[role="tree"]AnimatedRows.render
工作区行是 div[data-row-key="workspace:<key>"][role="treeitem"][aria-expanded]ProjectRowItem
每一行都被 HoverCard 套了一层 <span>,所以行的 parentElement 不是分组容器;分组要向上找(父元素是列表列本身,或父元素是 role="group" 容器)。未分组是唯一例外——宿主对它直接返回裸行ProjectRowItem / HoverCard
会话行是 div[data-row-key="session:<id>"][role="treeitem"][aria-selected],第一个子元素是该行自己的状态槽(同样被 HoverCard 包着,所以 :scope > 读不到它)SessionNodeItem
状态点带 data-state ∈ {ongoing, warning, done, error, idle}ui-primitives 的 StateDot
展开状态存在 dsh.workspace.view.v5,groupExpansion[key] 显式为 false 才折叠createWorkspaceViewStore / deriveGroups
接口是 ctx.get('uiWorkspace').view.setGroupExpanded(key, expanded)UiWorkspaceService 的 view 字段
折叠的组不渲染任何会话行,所以运行状态必须另有来源deriveGroups 的 GroupNode.sessions
槽位标准钩子 useSessionStatus / useWorkspaces 提供状态快照与工作区成员shell.overlay 的 standardProps
WorkspaceSnapshot.items[].sessionIds 是「谁属于哪个工作区」dsh-api-workspace-controller 的 WorkspaceView / WorkspaceSnapshot

这些是构建产物的结构,不是文档化 API:宿主升级后如果结构变了,插件会安静地什么都不做 (data-wsf-* 标记无处可落),而不是弄坏侧栏。若 uiWorkspace.view.setGroupExpanded 不存在, 折叠会被整体关闭,并在该插件的详情页上显示告警、控制台打印原因——不会静默失败。

已知限制

  • 不折叠未分组,理由见上;如果你要连它一起收,改 scanGroup 里的 key === '' 判断。
  • 自动折叠写的是宿主自己的视图偏好:被自动折起来的工作区,其 groupExpansion[key] 会以 false 持久化。卸载本插件后它们会保持折叠——手动点开即可恢复,或在插件页里禁用这个包再刷新。
  • 子工作区(树形分组)不参与置顶:子组在父组的 role="group" 容器里,不是列表列的直接子元素, order 在那里无效。会话级排序不受影响。
  • 状态判定只读「运行中 ongoing」与「等待你 warning」;error 不参与。

验证状态

已验证:

  • node --check 通过;manifest 解析通过;
  • 安装返回 application: applied,profile 的 dependencies 与 dsh.profile.bundles 都已登记;
  • 实时客户端注册已生效:plugins.bundle.config 席位上出现了 dsh-sidebar-focus 这个 key (cordis_inspect_query 可见)。插件页只在存在该 key 的注册时才渲染那块配置 (owner 的判据是 ledger.bundles.has(pkg.name)),所以这一条同时证明详情页里会出现这 6 个开关 + 1 个计数器;
  • 原先在「设置 → 通用」的 5 行已确认从 settings.general.item 移除,不会两处重复;
  • 状态桥接已确认挂载:shell.overlay 的实时占用者里有 dsh-sidebar-focus.status-bridge, 而该席位的 standardProps 同时提供 useSessionStatus 与 useWorkspaces。

真实 GUI 实测确认(2026-10-17,用户实际操作):

  • 新建会话的工作区浮到顶部;
  • 会话跑完不掉回原位,只有更新的活动才把它挤下去一位;
  • 另一个工作区开跑时,那个顶上来、原来的顺延;
  • 跑完的工作区不会立刻收起;
  • 「只保留最近 N 个展开」及其 − / + 计数器工作正常。

包括 0.1.1 那个根因修复(sectionOf() 的三种形状 + CSS :has())在内,这些行为此前只是从宿主源码 推演出来的,现在有了真实页面上的确认。

仍未验证(没有可读的 DOM 通道;按插件规范的验证边界,未用截图或模拟 DOM 冒充):

  • 视觉细节:flex 化后的行高与间距、浅色/深色两套主题下的观感;
  • 与内置 FLIP 行动画、拖拽排序的共存表现;
  • 子工作区(树形分组)的排序:order 对子组无效,这是已声明的限制;
  • 在已折叠的工作区里启动会话、它应当自动展开这一条,没有被单独复现过(依赖状态快照路径)。

自查方式:刷新 Web 页面 → 打开一个正在跑的工作区(应自动展开并置顶)→ 打开一个空闲工作区 (应保持折叠,你手动展开后应保持展开)→ 控制台不应出现 [dsh-sidebar-focus] 开头的报错。