🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

配置档案桥接 2NF/dsh-profile-bridge

DeepSeek Harness
2NF27 天前有提交已提供中文文档扫描:含敏感能力

让桌面版一键复用已装插件的 profile,可随时还原

30.8/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/7 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查有告警:未发布到 npm registry,仅可从源码安装。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add 2NF/dsh-profile-bridge
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · desktop
装得上吗
本站已在 dsh 0.2.1-rc.5 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 27 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

未发布到 npm registry,仅可从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-profile-bridge(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=20.0.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/14 10:17:41

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件
查看扫描证据(共 19 处,展示前 12 条)
  • 读取本地文件
    lib/helper.mjs:78
    let text = readFileSync(templatePath, 'utf8')
  • 写入本地文件
    lib/helper.mjs:128
    mkdirSync(dirname(helper.scriptPath), { recursive: true })
  • 写入本地文件
    lib/helper.mjs:130
    writeFileSync(helper.scriptPath, windows ? `\uFEFF${helper.text}` : helper.text, 'utf8')
  • 写入本地文件
    lib/helper.mjs:132
    writeFileSync(helper.wrapperPath, helper.wrapper, 'utf8')
  • 写入本地文件
    lib/helper.mjs:134
    if (!windows) chmodSync(helper.scriptPath, 0o755)
  • 执行外部命令来自配置/变量
    lib/helper.mjs:148
    const child = spawn(helper.command, helper.args, {
  • 读取本地文件
    lib/state.mjs:49
    if (!lstatSync(dir).isSymbolicLink()) return undefined
  • 读取本地文件
    lib/state.mjs:63
    const parsed = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'))
  • 读取本地文件
    lib/state.mjs:91
    exists: existsSync(join(dir, 'package.json')),
  • 读取本地文件
    lib/state.mjs:101
    hasNodeModules: existsSync(join(dir, 'node_modules')),
  • 读取本地文件
    lib/state.mjs:102
    hasPatch: existsSync(join(dir, 'cordis.patch.yml')),
  • 读取本地文件
    lib/state.mjs:112
    if (!existsSync(paths.profilesDir)) return []
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 目录链接切换
  • 自动备份与还原

桌面版看不到你在别的配置档里装的插件?一键让 DeepSeek Harness 桌面版改用你已有的配置档(目录链接 + 自动备份 + 随时还原)|让 DSH 桌面版用上已有的插件配置档,一键切换,完全可还原。

README

由 DeepSeek 最新模型翻译生成
dsh-profile-bridge 一句话:让 DeepSeek Harness 桌面版用上你「已经装好插件的 profile」—— 点一下切换,随时一键还原。 In one line: make the DeepSeek Harness Desktop app use the profile that already has your plugins — one click to switch, one click to revert. 桌面版看不到你在别的 profile 里装的那些插件?这个插件一个设置页、一次点击就解决,而且旧目录会自动备份、随时还原。 切换前:桌面版 → profiles/desktop(空) ✗ 看不到你的插件切换后:桌面版 → profiles/desktop → profiles/web ✓ 你装的插件全都在 它解决什么问题 Harness 的插件按 profile 隔离。桌面版把 profile 目录硬编码为 <DSH_HOME>/profiles/desktop(见 @deepseek-ai/dsh-desktop 的 lib/main.js:profile: join(dshHome, "profiles", "desktop")),并且没有提供切换 profile 的设置项或命令行参数。
展开完整文档(README 剩余 1 节)
dsh-profile-bridge

一句话:让 DeepSeek Harness 桌面版用上你「已经装好插件的 profile」—— 点一下切换,随时一键还原。
In one line: make the DeepSeek Harness Desktop app use the profile that already has your plugins — one click to switch, one click to revert.

桌面版看不到你在别的 profile 里装的那些插件?这个插件一个设置页、一次点击就解决,而且旧目录会自动备份、随时还原。

切换前:桌面版 → profiles/desktop(空) ✗ 看不到你的插件切换后:桌面版 → profiles/desktop → profiles/web ✓ 你装的插件全都在

它解决什么问题

Harness 的插件按 profile 隔离。桌面版把 profile 目录硬编码为 <DSH_HOME>/profiles/desktop(见 @deepseek-ai/dsh-desktop 的 lib/main.js:profile: join(dshHome, "profiles", "desktop")),并且没有提供切换 profile 的设置项或命令行参数。于是:

- 你在 dsh web 的 profile(通常是 web)里 dsh plugin add 装的一堆插件,桌面版完全看不到;
- 想在桌面版里用,只能逐个重装一遍,之后还要维护两套。

这个插件把那条唯一可行的路做成了 UI:让 profiles/desktop 变成指向目标 profile 的目录链接。桌面版本身不会清空既有 profile —— 它只在 profile 不存在时才写入默认清单,也不会动 pnpm 装的包和 link: 链接 —— 所以把目录接过去就能直接用。

安装

从 GitHub 安装(当前推荐,已实测可用)
dsh plugin --profile desktop add github:2NF/dsh-profile-bridge

或者本地目录(开发/离线)
dsh plugin --profile desktop add /绝对路径/dsh-profile-bridge

npm 一行待发布后可用(本包尚未发布到 npm,现在执行会 404)
dsh plugin --profile desktop add dsh-profile-bridge

装完刷新页面(或重启应用):设置 → 配置档案。

⚠️ 用哪个工具装:请用命令行 dsh plugin(或与 profile 的 node_modules 同一 pnpm 大版本的工具)。
桌面版自带的插件管理器用的是它自己的 pnpm(本例 v11),如果 profile 是 pnpm v10 装的,会报 ERR_PNPM_UNEXPECTED_STORE 并拒绝安装 —— 详见下方「已知问题」。

想让它在你切换之后仍然可用,就把本插件也装进你准备切换过去的那个 profile:
dsh plugin --profile web add github:2NF/dsh-profile-bridge

安装方式二:本地链接(不动 pnpm)

如果桌面版和 profile 的 pnpm 大版本不一致(见下方"已知问题"),包管理器会拒绝安装。可以绕开它:

Windows:把插件目录链接进 profile 的 node_modules New-Item -ItemType Junction -Path "$env:USERPROFILE\.dsh\profiles\desktop\node_modules\dsh-profile-bridge" -Target "D:\path\to\dsh-profile-bridge"

macOS / Linux
ln -s /path/to/dsh-profile-bridge ~/.dsh/profiles/desktop/node_modules/dsh-profile-bridge

然后在 profile 的 cordis.patch.yml 末尾追加一行(这就是 bundle 声明):

- insert:
- id: profile-bridge
name: 'dsh-profile-bridge'

刷新页面(Host 半边需要重启应用)即可看到设置页。

使用

1. 打开 设置 → 配置档案,页面会列出 $DSH_HOME/profiles 下所有 profile,并标出当前正在用的那个。
2. 选中要用的 profile(例如 web),点 使用它。
3. 应用会在两秒内自动关闭,脚本完成目录切换 —— 它不会自动打开,请你自己双击打开桌面版,打开后就是你的插件集合。
4. 想回去就点 还原为独立 profile(会删除链接并把切换前的目录恢复回来),同样需要你自己重新打开应用。

同页面还会显示:依赖数 / bundle 数 / node_modules 是否存在(切换前的体检)、上次操作日志、"工作原理"说明。

工作原理

切换必须在应用关闭时做:运行中的应用占着自己的 profile 目录,插件自己也跑在那个进程里。所以流程是:

点击「使用它」 └─ Host 半边校验目标 profile,渲染一个平台脚本到 <DSH_HOME>/profile-bridge/ └─ 以独立进程(detached)启动它 → 立即返回结果给页面 └─ 脚本:关闭应用 → 改名备份 → 建 junction/symlink → 合并界面设置 → 结束(不重启应用:请你自己打开)

细节(都是踩过的坑):

| 事项 | 做法 |
| 备份 | 应用 profile 改名为 desktop.fresh-<时间戳>,不删除 |
| 链接 | Windows 用目录 junction(New-Item -ItemType Junction),macOS/Linux 用 ln -s |
| 二次切换 | 已经是链接时直接删除旧链接再建新的,不会叠加备份 |
| 失败回滚 | 建链接后立刻校验目标 package.json 可读;失败就删链接、把备份改回来 |
| 界面设置 | 把桌面版首次运行写入的 ui-chat / ui-settings / ui-settings-account 三行并入目标 profile 的 cordis.patch.yml,避免重开后又走一遍引导(原文件备份为 .bak-<时间戳>) |
| 日志 | <DSH_HOME>/profile-bridge/last-run.log,页面内可查看 |
| 安全 | 脚本永不 rm -rf:删除链接用 rmdir/rm -f(只删链接本身),其余一律「改名」 |

限制与注意事项

- 切换需要关闭应用,这是操作系统的目录占用限制,不是插件的选择。脚本替你关闭应用,但不会替你重新打开(原因见下面「为什么没有自动重开」)。用 skipAppStop: true 调用 link/unlink 端点可以连关闭都交给你自己(测试模式)。
- 不要同时运行桌面版和命令行 dsh --profile <同一个 profile>:两个进程共享同一份 node_modules 与锁文件。
- macOS / Linux 走符号链接路径,逻辑与 Windows 相同,但未在真机验证(欢迎反馈 Issue / PR)。
- 只有桌面版需要这个链接。命令行用户直接 dsh --profile <名称> 就好,本页会提示这一点并且不提供按钮。
- 若目标 profile 里没有安装本插件,切换过去之后这个设置页就不在了(插件属于 profile)。按上面「安装」一节的提示两边都装即可。

已知问题(都是实测踩到的)

1. pnpm 大版本 / store 不一致

桌面版自带 pnpm v11(用自己的 store),而 dsh web(CLI)侧的 profile 常见是 pnpm v10 装的(store v10)。链接之后,桌面版的插件管理器再安装任何插件都会失败:

[ERR_PNPM_UNEXPECTED_STORE] Unexpected store location
The dependencies at "...\profiles\web\node_modules" are currently linked from the store at "...\pnpm\store\v10".
pnpm now wants to use the store at "...\pnpm\store\v11" ...

三种解法,任选其一:

| 解法 | 做法 | 代价 |
| 用 CLI 装 | dsh plugin --profile desktop add <包名>(用与 profile 一致的 pnpm) | 需要 CLI 的 pnpm 与 profile 匹配 |
| 本地链接 | 见上面「安装方式二」 | 不经过包管理器,桌面版插件页看不到它的依赖行 |
| 对齐 store | 用桌面版的 pnpm 在该 profile 里跑一次 pnpm install | 会整体重新链接 node_modules,耗时且可能影响正在运行的应用 |

2. connection.rpc.handle() 在部分版本不可用

它需要访问 Connection 服务自己的 webServer,在某些版本上会抛 cannot get property without inject。本插件先尝试官方通道,失败就自动降级为自建的同协议路由(/profile-bridge,仅接受本机 loopback 访问,信封与官方 client-request / server-response 一致),所以浏览器半边无需改动。

3. Windows 上不能用 detached 直接启动 powershell.exe

实测(Node 24 + Windows):spawn('powershell.exe', …, { detached: true, stdio: 'ignore' }) 的进程会创建但从不执行(没有日志、没有副作用,看起来像「点了没反应」);而 detached 启动 cmd.exe 完全正常,且子进程能在父进程被强杀后继续运行。

所以插件在 Windows 上生成两个文件、用 cmd.exe 中转:

| 文件 | 作用 |
| <DSH_HOME>/profile-bridge/switch.ps1 | 真正干活的脚本(带 UTF-8 BOM,否则 Windows PowerShell 会把非 ASCII 路径读成乱码) |
| <DSH_HOME>/profile-bridge/run.cmd | 一行包装:powershell.exe … -File switch.ps1 > last-run.log.out 2>&1,由插件以 detached 方式启动 |

排错时看两个日志:last-run.log(脚本的结构化日志)和 last-run.log.out(PowerShell 自身的输出——脚本连第一行都没跑到时,原因在这里)。设置页的「上次操作日志」会自动显示有内容的那个。

4. helper 的工作目录会锁住它自己要改名的目录

桌面版启动宿主时用的是 cwd = profile 目录(@deepseek-ai/dsh-desktop 的 main.js:cwd: this.projectDir)。插件 spawn 出去的 helper 会继承这个工作目录,于是出现最反直觉的一种失败:应用已完全退出、目录里没有任何别的进程,改名依然报 still locked —— 因为 helper 自己就站在那个目录里,持有它的句柄。

三重防护:

| 位置 | 做法 |
| lib/helper.mjs | spawn 时显式指定 cwd 为插件状态目录(<DSH_HOME>/profile-bridge) |
| run.cmd | 第一行 cd /d "%~dp0",先离开继承来的目录 |
| switch.ps1 / switch.sh | 开头 Set-Location $env:TEMP / cd /,并把启动时的 cwd= 写进日志 |

失败时脚本还会列出仍提到该路径的进程(rename blocked by: …)。自检里加了回归用例:故意把工作目录设为 profile 目录,再执行真实包装脚本,必须仍然切换成功。

5. 为什么没有自动重开(v0.2.0 起直接移除)

早期版本会在切换后自己把应用拉起来,为此踩了三个坑,最终决定不做这件事 —— 由用户自己打开应用:

| 踩到的坑 | 现象 |
| Node 模式环境变量 | 宿主是以 ELECTRON_RUN_AS_NODE=1 运行的 Electron,helper 继承后启动 DeepSeek Harness.exe,Electron 变成无窗口的 Node 进程:进程起来、几秒后退出、界面永不出现(而从开始菜单双击就正常) |
| 端口未释放 | 新宿主绑定不了上一个宿主还在用的端口(崩溃日志:webserver (required): listen UNKNOWN … 127.0.0.1:19387),启动审计失败 → 应用弹"The application could not start or stopped unexpectedly" |
| 单实例锁竞争 | 旧实例还没退干净,新实例会把启动请求转交给它然后自己退出,看起来就是"没反应" |

这些都能绕过(清环境变量 + 用新环境启动 + 等端口释放 + 健康检查 + 失败清场重试),但组合起来在别人机器上仍不够可靠,而切换本身根本不需要重启应用。所以现在:脚本只负责关闭应用并完成切换,日志最后一行明确写 the app stays closed on purpose - open it yourself。

手动回滚(不依赖本插件)

Windows:删链接 + 恢复备份 cmd /c rmdir "$env:USERPROFILE\.dsh\profiles\desktop" Rename-Item "$env:USERPROFILE\.dsh\profiles\desktop.fresh-<时间戳>" desktop

macOS / Linux
rm ~/.dsh/profiles/desktop
mv ~/.dsh/profiles/desktop.fresh-<时间戳> ~/.dsh/profiles/desktop

开发与验证

node verify/precheck.mjs

这个脚本会在系统临时目录里造一棵假的 profiles 树,然后真的执行一次 helper:改名备份、建 junction、合并 patch、重指向、还原,并断言每一步的结果。运行时使用 skipAppStop,不会碰你正在运行的应用。

仓库结构:

| 文件 | 说明 |
| index.js | Host 半边:共享 RPC 通道 /profile-bridge,端点 status / link / unlink |
| lib/state.mjs | profile 发现与校验(只读),状态载荷,日志尾读 |
| lib/helper.mjs | 渲染平台脚本、写入、detached 启动 |
| lib/switch.windows.ps1.txt | Windows 脚本模板(junction) |
| lib/switch.posix.sh.txt | macOS/Linux 脚本模板(symlink) |
| client.js | 浏览器半边:settings.section 设置页 |
| verify/precheck.mjs | 沙盒自检(渲染 + 真实执行脚本 + 三条 RPC 通道) |
| verify/e2e.mjs | 可选的真实端到端切换(会真的关闭应用,需 --yes) |

License

MIT

让 DeepSeek Harness Desktop 应用使用一个已经装好你插件的配置档,而不是它自己创建的空配置档。一个设置页,一次点击,完全可回滚。

问题所在

插件按配置档划分作用域,而 Desktop 应用把配置档目录写死为 <DSH_HOME>/profiles/desktop(@deepseek-ai/dsh-desktop,lib/main.js:profile: join(dshHome, "profiles", "desktop")),没有任何设置或参数能换一个目录。所以你装进 dsh web 配置档的一切,它都看不见,以前唯一的办法是把每个插件重装一遍,再维护两套。

Desktop 应用不会重置已有的配置档——目录不存在时它才写一份默认 manifest,而且它从不碰 pnpm 包或 link: 依赖——所以把目录链接过去就够了。

安装

from GitHub (recommended today; verified end to end)
dsh plugin --profile desktop add github:2NF/dsh-profile-bridge
or a local checkout
dsh plugin --profile desktop add /absolute/path/to/dsh-profile-bridge
the npm line works once the package is published (not published yet)

打开 Settings → Profiles,选你要的配置档,按 Use this one。应用会自己关闭,切换随即完成,然后你再打开应用——它就会跑在你的插件配置档上。Revert to a standalone profile 可以撤销。
用 dsh plugin 命令行(或任何 pnpm 主版本与配置档 node_modules 匹配的工具)。Desktop 应用自带的插件管理器用的是它捆绑的 pnpm(这里是 v11),往 v10 管理的配置档里安装会报 ERR_PNPM_UNEXPECTED_STORE 并拒绝安装——见下文「已知问题」。

工作原理

切换必须在应用关闭时进行(应用占着自己的配置档目录,而这个插件就跑在那个进程里),所以 Host 那一半会渲染出一小段平台脚本,以分离方式启动它,然后立刻返回。脚本等应用退出,把旧目录改名为 desktop.fresh-<stamp>,创建 junction(Windows)或 symlink(macOS/Linux),把 Desktop UI/onboarding 的行合并进目标配置档的 cordis.patch.yml,然后就停手——它不会重启应用。失败会回滚。任何东西都不会被递归删除——只移除链接,其余全部改名。日志落在 <DSH_HOME>/profile-bridge/last-run.log,并显示在页面上。

限制

- 切换按设计会关闭应用;重新打开要你自己来(见中文部分的「为什么没有自动重启」——简短版:重启得先跟 Node 模式的环境、单实例锁、以及上一个 Host 仍占着的端口较劲,而切换根本不需要这些)。
- 不要同时运行 Desktop 应用和 dsh --profile <same profile>。
- macOS/Linux 走 symlink 那条路;逻辑相同,但尚未在真机上验证。
- 插件住在配置档里,所以想在切换后看到页面,两个配置档都要装。
- Windows 启动细节(实测): spawn('powershell.exe', …, { detached: true }) 创建出的进程永远不会运行,所以 helper 是以分离的 cmd.exe 启动,由它运行 run.cmd,再由 run.cmd 调用 PowerShell,输出重定向到 last-run.log.out。面板上没有日志时,原因就在那份记录里。
- helper 不能把配置档目录当作自己的工作目录继承下去。 Desktop 应用启动 Host 时把 cwd 设为配置档目录,而工作目录就是某个目录的进程会挡住对该目录的改名——helper 会锁住自己的目标,即使应用已经退出也照样报「still locked」失败。启动器把 cwd 设为插件状态目录,run.cmd 开头是 cd /d "%~dp0",脚本再退到 $env:TEMP;回归测试则从配置档目录内部运行真正的 wrapper。

验证

沙箱套件(不碰你的任何东西):

node verify/precheck.mjs

它会搭一棵用完即弃的配置档树,在里面真的执行一次切换、一次重指向和一次回退(应用停止功能关闭),渲染并执行生成的脚本,从故意刁难的工作目录(配置档目录本身)运行真正的 wrapper,在有可用 shell 时用真实 shell 解析 POSIX 模板,并检查全部三种 host RPC 传输方式。
真正的端到端(这次真的会关掉你的应用):

json plan only
node verify/e2e.mjs unlink
node verify/e2e.mjs link web
really do it: the app closes, the switch happens, start the app yourself afterwards
node verify/e2e.mjs unlink --yes
node verify/e2e.mjs link web --yes

走的完全是插件的生产路径(渲染 → 写盘 → 分离式启动),所以它能验证沙盒测不出来的东西:分离启动、工作目录、应用是否真的被关闭、链接是否真的生效。唯一带有破坏性的测试,需要 --yes 才执行;它不会替你打开应用 —— 那本来也该由你来做。

MIT licensed.
预览分享卡片长什么样 ↓2NF/dsh-profile-bridge
分享 · DeepSeek Harness Hub
2NF/dsh-profile-bridge

让桌面版一键复用已装插件的 profile,可随时还原

回到顶部