DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Ungrouped Top — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
U

dsh-ungrouped-top

Ungrouped Top

Pin “Uncategorized” to the top of the DSH sidebar, and have “New Conversation” default to conversations without a workspace. Zero-dependency client plugin.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:wqzhellohhwy/dsh-ungrouped-top#5c43c0069939c1f72da8f704e60ee63b7659c39f
READMECompatibilityVersions

Compatibility and provenance

Ungrouped Top is published as dsh-ungrouped-top and currently resolves to version 1.3.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
10/9/2026

Versions

1.3.0stable
10/9/2026
1.2.2stable
10/9/2026
1.1.1stable
10/9/2026
Show 1 more versionCollapse versions
1.0.0stable
10/8/2026

Related plugins

Loading related plugins…

Latest
1.3.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
10/10/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in ui-customization.

Web App@deepseek-ai/dsh-web-appThe dsh browser-surface bundle: the web patch layer over dsh-base plus the runtime glue plugin (frontend dist serving, web-surface prompt, bash runtime variables, URL line)Experimental Agent Team Web Profile@deepseek-ai/dsh-experimental-agent-team-web-profileExperimental Web profile layer for Agent Teams Remote and UI pluginsAb Chartdsh-ab-chartChart rendering tool with the browser card that draws its calls, in one publishable plugin packageWhale Widgetdsh-whale-widgetDeepSeek balance whale widget in the bottom-right corner of the DSH Web interface: balance/today’s usage/peak-off-peak pricing, customizable bubble click sequence (text/balance/today/peak-off-peak/image/random phrases and parallel weighted selection), per-line styles and fonts, floating quick editin

README

dsh-ungrouped-top

把 DSH 侧边栏的**「未分组」钉在最上面**,并让**「新会话」默认落进无工作区会话**。

一个零依赖的 DeepSeek Harness Web / Desktop 客户端插件。它不改 DSH 源码,只在运行时注入一小段样式,并在 uiWorkspace 服务的一个方法上做一层薄包装。


它解决什么问题

DSH 的侧边栏有两个写死的行为,设置里没有开关:

1. 「未分组」永远垫底。 分组列表由 groupByWorkspace() 生成——先按顺序铺开所有工作区,最后才把不属于任何工作区的会话追加成「未分组」组;而且这一组没有拖拽手柄(拖拽属性只在真实工作区上挂),既拖不动自己,也不能当作别人的落点。容器还是普通 block 布局,所以连 CSS order 都失效。

2. 「新会话」永远跳回某个工作区。 uiWorkspace.startSession() 挑工作区的顺序是:

显式指定的工作区  →  当前会话所属的工作区  →  最近使用的工作区

无工作区会话不属于任何工作区,所以永远轮不到它——每次点「新会话」都会跳回最近用过的那个工作区。


它做什么

  • 未分组置顶:把侧边栏列表容器临时变成 flex 纵向布局,再给「未分组」那一组 order: -1。工作区之间的拖动排序不受影响。
  • 新会话默认无工作区(需配合 dsh-projectless-session 之类的 provider):拦截无参数的「新会话」调用并转交给 provider;给某个工作区分组点「+」时仍在该工作区里新建。
  • 各分组始终「最近更新」在上:DSH 的排序模式是全局的,而手动排序模式下任何持有「已保存顺序」的分组都会冻结;DSH 还会在你选中空白会话时把所有分组的当前顺序一次性回写(工作区因此也会被冻结,哪怕你从没拖过)。插件持续把已持有顺序的分组刷新成当前时间序——工作区与未分组一起保持「最新在上」。
  • 临时分组标题校正:provider 给临时工作区改名的那一步偶发会输给工作区列表刷新(结果分组标题退化成 session-… 目录名),插件会重试写回正确标题。
  • 临时分组改名抢跑 + 置顶:临时工作区一出现在列表里就被改名(不等 provider 走完「建目录 → 建工作区 → 开会话」整轮),并在它存在期间排到「未分组」之上——新会话不会再顶着 session-… 的名字、出现在松散会话列表的下方。

它不做什么

  • 不修改 DSH 源码或 app.asar,不写任何 DSH 安装目录。
  • 不创建目录、不管理会话生命周期、不做空白会话回收——那是 provider(如 projectless)的职责,本插件只调用它公开的入口。
  • 不注册任何工具、不注入提示词、不读环境变量、不发任何网络请求。
  • 不硬编码任何用户目录、profile 名或盘符。

安装

DSH 的插件装进某个 profile(web、desktop 等)。先把仓库取到本地,再选一种方式装进去。

方式 A:本地目录 link(推荐,改完即生效)

git clone https://github.com/wqzhellohhwy/dsh-ungrouped-top.git D:\dsh-plugins\dsh-ungrouped-top
dsh plugin --profile web add "link:D:/dsh-plugins/dsh-ungrouped-top"

方式 B:直接从 GitHub 装

dsh plugin --profile web add github:wqzhellohhwy/dsh-ungrouped-top

把 --profile web 换成你自己的 profile 名(桌面版通常是 desktop)。 装完重启 DSH;桌面版重启后如果不生效,再按一次 Ctrl+R 刷新界面。

可选:配合无工作区插件使用

「新会话默认无工作区」这一条需要环境里存在一个无工作区会话 provider。推荐:

dsh plugin --profile web add dsh-projectless-session

provider 不在时,插件安静降级:未分组置顶照常生效,「新会话」回到 DSH 原生行为(跳回最近使用的工作区),控制台只会留一条 console.warn,不会报错也不会崩。


工作原理

未分组置顶(纯 CSS)

DSH 侧边栏的分组行带一个 data-row-key 标记:工作区是 workspace:<workspaceId>,未分组是 workspace:(id 为空)。插件据此定位并注入:

[role="tree"]:has([data-row-key="workspace:"])            { display:flex; flex-direction:column }
[role="tree"]:has([data-row-key="workspace:"]) > *        { flex:0 0 auto }
[role="tree"]:has([data-row-key="workspace:"]) > div:has([data-row-key="workspace:"]) { order:-1 }

display:flex 只在该容器里确实存在未分组分组时才应用,其他视图(单一列表、无松散会话的工作区树)完全不受影响。

新会话转交(包装一个方法)

插件包装 uiWorkspace.startSession:

  • 带了 workspaceId(某个工作区分组的「+」)→ 原样交给 DSH;
  • 没带(侧边栏「新会话」按钮、session.new 快捷键、空状态)→ 交给 provider。

provider 的入口从 hero 工作区插槽 conversation.hero.workspace 里取:先按 locale 命名空间 / 组件名里含 projectless 识别,识别不到就退化为「任何注入了 createProjectlessSession 的插槽条目」,因此 provider 改名也能继续工作。

分组排序(时间序刷新)

DSH 的排序模式(视图选项里的「手动排序 / 最近更新」)是全局的,两种模式对"新成员"的处理方式不同:

  • 最近更新模式:每个分组都实时按 updatedAt 倒序,谁都追得上。
  • 手动排序模式:分组一旦持有「已保存顺序」,成员就按那份顺序冻结。

而 DSH 在手动排序模式下有个连带行为:只要当前选中一个空白会话(刚新建、还没发消息),它就把每个账户的当前渲染顺序一次性回写进存储(syncSessionOrders)。所以"没拖过就没有顺序"并不成立——新建一次会话,所有分组就被冻结了,工作区从此也不再按「最近更新」重排。

插件因此订阅会话列表与视图存储,在手动排序模式下核对每一个已持有顺序的账户:一旦它与当前时间序(updatedAt 倒序)不一致就刷新它。顺序一致时不做任何写入,因此不会产生写入循环。在「最近更新」模式下插件完全静默——DSH 自己就是时间序。

只刷新已经持有顺序的账户:没有顺序的分组本来就按时间序渲染,插件不会凭空创建一个。「单一列表」视图的账户不处理(它的成员口径由 DSH 自己维护)。

代价:手动拖拽排出的固定顺序会被下一次刷新覆盖。这是刻意的取舍——本插件的立场是各分组永远「最新在上」。

临时工作区分组(抢名 + 置顶)

无工作区会话在发出第一条消息之前必须借一个临时工作区落脚(DSH 不给没有工作区的会话完整界面)。provider 的流程是:建目录 → 注册临时工作区 → 开会话 → 改名 → 首条消息后注销注册。

问题出在中间那段时间:临时工作区先是顶着目录名(session-26-05-31-a1b2c3d4)出现在侧边栏,而且排在「未分组」下面——看起来就像新建的会话跑错了地方。插件因此做两件事:

  • 抢名:调用 provider 之前就订阅工作区列表,临时工作区一出现(标题仍等于目录名、路径形状匹配 <root>/YYYY-MM-DD/session-…)就立刻改名成 provider 的分组名,不等 provider 走完剩下几步。
  • 置顶:给标题等于 provider 分组名的那个分组打上 data-ungrouped-top-temp,样式表据此把它排到「未分组」之上(order:-2)。

两条规则都先核对路径形状与标题,因此不会误伤真实工作区;标记在插件卸载时清除。

护栏

护栏为什么需要
在途锁 + 复用已打开的空白会话连点「新会话」不会并发开出多个临时工作区
标题重试(400ms × 5)provider 改名会输给紧随其后的工作区列表刷新,标题会退化成目录名
未分组顺序按时间序刷新手动排序模式下「未分组」会冻结成固定顺序,不再「最新在上」

自检上报

Client 面在加载后(以及每次「新会话」被调用时)把自身状态 POST 给 Host 面注册的 /api/ungrouped-top/diagnostics,Host 以 JSONL 追加写到 os.tmpdir()/dsh-ungrouped-top-diagnostics.json:

{"phase":"applied","providerFound":true,"wrapperInstalled":true,"orderBy":"manual","taggedTemporarySections":1}
{"phase":"startSession","mode":"default","providerFound":true}

它不改变任何行为,只用来回答"插件到底有没有在工作"——因为"插件没加载""加载了但 provider 没找到""包装被换掉了"这三种情况,从 Host 侧看是一模一样的(插件都是 active)。不需要就关掉:

- id: dsh-ungrouped-top
  config:
    diagnostics: false

兼容性

项要求
DeepSeek Harness0.2.0-rc.2(用到 uiWorkspace、slots、locale、sessions、workspaces 客户端服务)
Node.js>=22.19(随 DSH 运行时,无需单独安装)
平台Windows / macOS / Linux —— 插件不触碰文件系统与平台 API
profileWeb / Desktop(需要浏览器端 UI)

关于 DSH 升级:插件依赖三个 DSH 内部约定——侧边栏的 [role="tree"] + data-row-key 标记(临时分组置顶还要读分组行的标题文本)、uiWorkspace.startSession 的兜底链、以及 sidebar.workspaces 插槽注册上携带的视图存储(用于刷新未分组顺序)。DSH 大版本升级后如果失效,改的是这三处,改动量都很小。


卸载

dsh plugin --profile web remove dsh-ungrouped-top

插件在 apply 里用 ctx.effect 注册了样式与方法包装,卸载时会自动撤销(样式节点移除、startSession 还原成原方法)。DSH 自带的「未分组」行为随之恢复。


开发

没有构建步骤:lib/ 里的两个文件就是源码,也是发布产物(Host 侧是标准 ESM,Client 侧是 DSH 的 __ModuleLoader__.load({ id, factory }) 形式)。

改完之后:

# 本地 link 安装的情况下,重启 DSH 即可生效
# 桌面版:重启后再 Ctrl+R 刷新界面

调试时看浏览器控制台,插件所有异常都以 dsh-ungrouped-top: 开头。

目录结构

lib/index.js        Host 侧入口:空插件(只为让包成为一个完整的 DSH bundle)
lib/client.js       Client 侧全部逻辑:样式注入 + startSession 包装 + 未分组顺序刷新 + 临时分组抢名与置顶
cordis.patch.yml    bundle patch:把本插件插入 loader
package.json        包元数据 + dsh.bundle / dsh.client 声明

常见问题

装完没反应? 先确认重启过 DSH(桌面版再 Ctrl+R),再确认 profile 名选对了。控制台若出现 dsh-ungrouped-top: 开头的警告,把它贴到 issue 里。

「新会话」还是跳回工作区? 说明环境里没有无工作区 provider。装 dsh-projectless-session,或把 provider 的入口暴露方式告知作者。

「未分组」或某个工作区不按最新更新排序? 说明视图选项里选的是「手动排序」,而那个分组持有「已保存顺序」。插件会把已持有顺序的分组自动刷成时间序(见上文「分组排序」);如果没生效,先确认 Ctrl+R 刷过界面,再看控制台有没有 cannot refresh a stored order。

禁用插件之后再启用,功能没回来? 按 Ctrl+R 刷新界面。客户端插件代码只在页面加载时执行一次,在设置页里开关插件不会让它重新运行。刷新后控制台会有一行 dsh-ungrouped-top: client face applied 表示已生效;连这行都没有,说明插件根本没被加载(去检查 profile 的 bundles)。

未分组还是能拖动? 它本来就不能拖——DSH 没给这一组拖拽能力,本插件只改显示顺序,不伪造拖拽。

会不会和别的插件打架? 本插件只包装 uiWorkspace.startSession 一个方法,并且只拦截无参数调用;样式也不覆盖任何 DSH 原有规则。dsh-projectless-session 是设计上配合的对象,两者不冲突。


许可证

MIT