DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

Biu-Bong /

Biu-Bong/dsh-menu-hidden

Verified

DSH 插件:收起重复的 DeepSeek 账号 / 官方 API 入口、设置里的登录状态与账号菜单的意见反馈,并给应用菜单补上刷新与重启

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@ad6e63cd

dsh-menu-hidden · 菜单隐藏

DeepSeek Harness 插件。把界面上重复的 DeepSeek 账号 / 官方 API 入口收起来,顺手给应用菜单补上「刷新页面」「重启应用与 Host」。

开关在 设置 → 菜单隐藏,翻一下立刻生效,不用刷新页面。

效果

示意图,按真实界面的文案、分组顺序和配色复刻。图里的第三方厂商与模型都是随手编的示例名字(OpenAI 的 GPT 6 Astra / GPT 6.1 Sol、Anthropic 的 Claude Opus 5.5、xAI 的 Grok 4.6 / 4.7),不代表任何真实账号。

模型下拉框 左:装之前(DeepSeek 账号 / DeepSeek 两组重复) 右:装之后(只剩 OpenAI / Anthropic / xAI)

设置 · 模型 左:装之前(两行 DeepSeek,其中一行带「已登录」) 右:装之后

设置 → 菜单隐藏(插件自己的页面,六个开关逐个对应上面六条)

应用菜单 左:装之前 右:写入补丁并重启之后

账号菜单 左:装之前 右:装之后

装

--profile 后面写你要装进哪个 profile。桌面版和浏览器版是两个 profile,各装各的,也可以都装。

你用的形态 profile 名 装完怎么生效
桌面应用(Electron,DeepSeek Harness.exe) desktop 重启应用;第 5 条还要在设置里点一次「写入补丁」,再重启一次
浏览器版 dsh web web 重启 dsh web 进程,然后刷新页面

桌面版:

dsh plugin --profile desktop add github:Biu-Bong/dsh-menu-hidden

# 锁到某个提交,升级不漂移
dsh plugin --profile desktop add github:Biu-Bong/dsh-menu-hidden#<commit-sha>

浏览器版:

dsh plugin --profile web add github:Biu-Bong/dsh-menu-hidden

# 装完重启 web 进程
dsh web --profile web

dsh 是 DSH 自带的 CLI(应用菜单「应用 → 管理 dsh 命令…」会把 dsh 写进 PATH)。 装完重启一次:bundle 的挂载行(dsh.profile.bundles)是启动时读的。

卸载:

dsh plugin --profile desktop remove dsh-menu-hidden
dsh plugin --profile web remove dsh-menu-hidden

也可以把仓库地址交给 DSH 助手,一句话:装一下 github:Biu-Bong/dsh-menu-hidden。

支持范围

功能 桌面版 dsh web
1 / 2 / 3 / 4 / 6(模型下拉框、设置·模型、账号菜单那五条) ✅ 翻开关立刻生效 ✅ 翻开关立刻生效
5(应用菜单「刷新页面 / 重启应用与 Host」) ✅ 点「写入补丁」+ 重启应用 — 浏览器里没有原生应用菜单

为什么 web 端也能跑:客户端半用的是 Web UI 的 DOM 和 slot,package.json 里 dsh.client.platform 就是 "web",桌面版加载的也是同一套 Web 前端;宿主半只要求 webServer 服务,web profile 里也有。第 5 条走的是 Electron 主进程的 Menu.buildFromTemplate(...).popup(),浏览器里没有承载物——这种环境下宿主半找不到 lib/main.js,设置页那一行会显示「没找到外壳文件」,点按钮只会回一句说明,不会动到任何文件。

六条功能与实现

# 效果 实现方式 生效时机
1 模型选择框里隐藏「DeepSeek 账号」分组 客户端 DOM:section[data-menu-group] 按标题文字整组隐藏 立刻
2 模型选择框里隐藏「DeepSeek」(官方 API)分组 同上 立刻
3 设置 · 模型里隐藏「DeepSeek 账号」整行 客户端 DOM:按行名隐藏整个 <li>(编辑 / 删除一起走);首屏另用 li[class*="_rowCard"]:has([class*="_accountStatus"]) 的 CSS 预藏,绘制前就没了 立刻
4 设置 · 模型里隐藏「DeepSeek」官方 API 那一行 客户端 DOM:隐藏该行 <li> 立刻
5 应用菜单「退出」上方加「刷新页面」「重启应用与 Host」 宿主半:给 lib/main.js 的 applicationItems() 打开官方留着的 development 门(幂等、留备份 .menuhidden.bak、可还原) 改完重启一次应用
6 账号菜单里隐藏「意见反馈」 客户端 DOM:按文字认菜单项,藏掉(只剩它一个时连容器一起藏) 立刻

为什么不会闪

隐藏分三层,从最早到最晚:

  1. CSS 预藏:账号那一行挂 data-dshmh-account-row="1",配 li[class*="_rowCard"]:has([class*="_accountStatus"]){display:none} —— 样式在第一次绘制前就生效,连 JS 都不用等。
  2. 同步扫描:MutationObserver 的回调是微任务,跑在浏览器绘制之前。0.1.0 用 setTimeout(...,120) 合并扫描,等于把隐藏推到下一帧之后,那才是「先出现、再消失」。
  3. 按住菜单壳两帧:React 偶尔在首帧之后再提交一次(焦点、动画回调),那一帧里节点是新的、还没被藏。所以菜单一挂上来先给它 visibility:hidden,扫两遍、两帧之后才放出来 —— 用户看到的是「菜单晚一帧出现」,不是「意见反馈闪一下」。另配 800ms 兜底定时器,rAF 被节流也不会让它一直看不见。

第 2、3 层都只扫 record.target 与 addedNodes(变动的子树),不会在流式输出时每条消息都全量 querySelectorAll(document.body)。

setHidden 也不再是「看到标记就撒手」:React 重写 style 时会把 display:none 抹掉而标记还在,所以每次隐藏都补一次 display。

为什么第 5 条要动外壳文件

官方本来就有这两项,写在 lib/main.js 的 applicationItems() 里:

...development ? [
  { type: "separator" },
  { label: messages.reloadPageMenu, role: "reload" },
  { label: messages.restartAppHostMenu, click: () => { app.relaunch(); quitWithoutConfirmation() } }
] : [],

打包版 development = !app.isPackaged 恒为 false,整段被丢掉。Windows 上「应用」菜单是点开时用 Menu.buildFromTemplate(items).popup() 现拼的原生菜单,浏览器端碰不到,所以只能在主进程那边把门打开:

...(development || true) ? [

改完 Menu 下次启动才重建,所以那两项要重启一次应用才出现。插件把这件事做成了设置页上的两个按钮(写入补丁 / 还原),走一条本机路由,写入端带平台浏览器鉴权 —— 不带会话 cookie 的本机进程会被 401 挡回去。

外壳路径的找法依次是:DSH_SHELL_MAIN_JS 环境变量 → process.argv[0] 旁边的 resources/app/lib/main.js → %LOCALAPPDATA%\Programs\DeepSeek Harness\... → %ProgramFiles%\DeepSeek Harness\...。找不到就显示「没找到文件」,不动任何东西。

不想开界面也能从命令行来:

node shell/patch-shell-menu.mjs --status   # 看状态
node shell/patch-shell-menu.mjs --apply    # 写入
node shell/patch-shell-menu.mjs --revert   # 还原

设置页

设置 → 菜单隐藏:六个开关 + 两个按钮。

  • 前五个开关:模型选择框两处、设置·模型两处、账号菜单一处。开关存 localStorage 的 dsh-menu-hidden:v1,翻一下立刻重扫 DOM。
  • 「应用菜单」那一行显示外壳状态(已写入 / 未改动 / 没找到文件)+ 写入 / 还原按钮。
  • 最后一行「现在刷新一次界面」,等同应用菜单里的「刷新页面」。

隐藏只改 style="display:none!important" 并在节点上打 data-dshmh-hidden(值 = 隐藏前的整个 style 属性),不删节点、不动 React props。关掉开关就把 style 原样还回去,随时可逆。

认节点的方式

位置 选择器 稳定性
模型下拉框分组 section[data-menu-group] + [data-menu-group-heading] 官方 MenuGroup 的 data 属性,稳
分组标题文字 DeepSeek 账号 / DeepSeek Account、DeepSeek 官方 locale 与 provider displayName
设置·模型 行名 [class*="_rowName"](Vite CSS Modules 的 _hash_rowName) 用后缀,换版本不失效
已登录徽标 [class*="_accountStatus"] 同上
账号菜单项 [role="menuitem"] 且文字是 意见反馈 / Feedback 官方菜单没有 data 属性,只能按文字

找不到就安静跳过,不抛错、不碰别的地方;三个 sweep 步骤各自 try/catch,一处结构变了不影响另外两处。

结构

package.json          # dsh.bundle.patch + dsh.client(platform: web)
cordis.patch.yml      # 挂载宿主半(外壳补丁路由)
index.js              # 宿主半:/dsh-menu-hidden/api/shell-menu,读写 main.js 补丁
client.js             # 客户端半:设置页 + DOM 隐藏 + MutationObserver
shell/patch-shell-menu.mjs  # 离线 CLI,同一对 MARK,同样幂等

卸载

dsh plugin --profile desktop remove dsh-menu-hidden

外壳补丁独立于插件存在:卸载插件不会把 main.js 改回去。要还原就先在设置页点「还原」,或跑 node shell/patch-shell-menu.mjs --revert。

排障:0.1.0 重启后打不开

0.1.0 有个致命 bug,症状是装完重启 DSH 起不来。崩溃日志长这样(Windows 上在 %APPDATA%\@deepseek-ai\dsh-desktop\logs\crash-*-web-boot.log,本机实体是 D:\DeepSeek\cache\electron\dsh-desktop\logs):

phase: running
Error: web boot: 1 entry did not activate
@local/dsh-menu-hidden: import failed: module is not defined
    at file:///<安装目录>/resources/app/lib/main.js:12492:15

原因:client.js 结尾写了 module.exports = { ... }; return module.exports。浏览器里的 window.__ModuleLoader__ 只给 factory 传 require,没有 CommonJS 的 module;官方那些包能这么写,是因为打包器会在文件头上补 var module = { exports: {} } 两行,手写的 client.js 没有这层壳。于是模块在 import 阶段就抛 ReferenceError: module is not defined,整条客户端模块图判为未激活,前端直接起不来。

0.1.1 的修法是直接返回插件对象(cordis 认 { name, inject, apply } 形状):

return { name: ID, inject: ["slots", "locale"], apply };

装了 0.1.0 的话,换成 0.1.1:

dsh plugin --profile desktop remove dsh-menu-hidden
dsh plugin --profile desktop add github:Biu-Bong/dsh-menu-hidden#v0.1.1

两个测试:node test/client-load.mjs client.js(模块能不能加载)、node test/client-dom.mjs client.js(拿 jsdom 造一份真的结构化 DOM,验证六条里那五条 DOM 的命中与还原;需要先 npm i --no-save jsdom)。

回归测试也在仓库里:node test/client-load.mjs client.js 用一份假的 window.__ModuleLoader__ 把 factory 跑一遍 —— 0.1.0 的写法会在这一步抛 ReferenceError: module is not defined,0.1.1 返回 { name, inject, apply }。

如果已经起不来、连界面都进不去:把 profiles/<名字>/node_modules/dsh-menu-hidden 挪走,并从同一个 package.json 的 dsh.profile.bundles 里删掉 dsh-menu-hidden 那一行,就能先启动;进了界面之后再装 0.1.1。

License

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit ad6e63cd963d

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout