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

整合包工坊 DSH-PackForge/dsh-pack-plugin

DeepSeek Harnessv0.3.5
DSH-PackForge34 天前有提交已提供中文文档扫描:含敏感能力

@dsh-packforge/dsh-pack-plugin

39.2/100
综合分
15
GitHub 星标
310
npm 周下载
—/5
用户评分

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add @dsh-packforge/dsh-pack-plugin
npm 源 · @dsh-packforge/dsh-pack-plugin 的发布者账号已校验与本仓库一致

状态速览

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

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

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

✓npm 包@dsh-packforge/dsh-pack-plugin @ 0.3.5
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/1 16:37:57

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

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 45 处,展示前 41 条)
  • 读取本地文件
    lib/host.js:6137
    const rs = createReadStream(filepath, {
  • 发起网络请求
    lib/host.js:7135
    const res = await ftp2.request("EPSV");
  • 发起网络请求
    lib/host.js:7159
    const res = await ftp2.request("PASV");
  • 发起网络请求
    lib/host.js:7172
    const res = await ftp2.request("PASV");
  • 发起网络请求
    lib/host.js:7486
    return this.ftp.request(command);
  • 发起网络请求
    lib/host.js:30948
    async fetch(k, {
  • 读取本地文件
    lib/host.js:31380
    async readFile(abs) {
  • 执行外部命令来自配置/变量
    lib/host.js:31504
    child = spawn(cmd, args, {
  • 执行外部命令固定命令
    lib/host.js:31534
    spawnSync("taskkill", ["/pid", String(child.pid), "/T", "/F"], { windowsHide: true });
  • 执行外部命令固定命令
    lib/host.js:31628
    const r = spawnSync("reg", ["query", "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"], {
  • 执行外部命令固定命令
    lib/host.js:31752
    const r = spawnSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script], {
  • 执行外部命令来自配置/变量
    lib/host.js:31894
    const child = spawn2(process.execPath, args, {
  • 执行外部命令固定命令
    lib/host.js:32112
    const child2 = spawn3(
  • 读取本地文件
    lib/host.js:32704
    const bytes = await readFile(BALL_LIB_URL);
  • 读取本地文件
    lib/host.js:32887
    const { data: data2, content } = parseSkill(readFileSync(url, "utf8"));
  • 读取本地文件
    lib/migrate-helper.js:6137
    const rs = createReadStream(filepath, {
  • 发起网络请求
    lib/migrate-helper.js:7135
    const res = await ftp2.request("EPSV");
  • 发起网络请求
    lib/migrate-helper.js:7159
    const res = await ftp2.request("PASV");
  • 发起网络请求
    lib/migrate-helper.js:7172
    const res = await ftp2.request("PASV");
  • 发起网络请求
    lib/migrate-helper.js:7486
    return this.ftp.request(command);
  • 执行外部命令来自配置/变量
    lib/migrate-helper.js:26667
    const child = spawn(process.execPath, args, {
  • 发起网络请求
    lib/migrate-helper.js:27464
    async fetch(k, {
  • 执行外部命令来自配置/变量
    lib/migrate-helper.js:28020
    child = spawn2(cmd, args, {
  • 执行外部命令固定命令
    lib/migrate-helper.js:28050
    spawnSync("taskkill", ["/pid", String(child.pid), "/T", "/F"], { windowsHide: true });
  • 执行外部命令固定命令
    lib/migrate-helper.js:28144
    const r = spawnSync("reg", ["query", "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"], {
  • 执行外部命令固定命令
    lib/migrate-helper.js:28268
    const r = spawnSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script], {
  • 执行外部命令固定命令
    lib/migrate-helper.js:28911
    const child2 = spawn3(
  • 读取本地文件
    lib/progress-main.cjs:33
    raw = fs.readFileSync(progressFile, 'utf8');
  • 读取本地文件
    src/ball-host.js:70
    const bytes = await readFile(BALL_LIB_URL);
  • 执行外部命令来自配置/变量
    src/host-node.js:225
    child = spawn(cmd, args, {
  • 执行外部命令固定命令
    src/host-node.js:258
    try { spawnSync('taskkill', ['/pid', String(child.pid), '/T', '/F'], { windowsHide: true }); } catch { }
  • 执行外部命令固定命令
    src/host-node.js:353
    const r = spawnSync('reg', ['query', 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings'], {
  • 执行外部命令固定命令
    src/host-node.js:475
    const r = spawnSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', script], {
  • 执行外部命令来自配置/变量
    src/migrate-helper.js:40
    execFile(cmd, args, { windowsHide: true, ...opts }, (err, stdout, stderr) => {
  • 执行外部命令来自配置/变量
    src/migrate-helper.js:151
    const child = spawn(cmd, args, {
  • 发起网络请求
    src/migrate-helper.js:184
    const req = http.get({ host: '127.0.0.1', port: CLIENT_PORT, path: '/', timeout: 1500 }, (res) => {
  • 执行外部命令来自配置/变量
    src/migrate.js:44
    const child = spawn(process.execPath, args, {
  • 读取本地文件
    src/progress-main.cjs:33
    raw = fs.readFileSync(progressFile, 'utf8');
  • 执行外部命令固定命令
    src/progress.js:115
    const child = spawn('powershell.exe',
  • 执行外部命令来自配置/变量
    src/progress.js:124
    const child = spawn(process.execPath, [MAIN, `--progress-file=${file}`], {
  • 读取本地文件
    src/skills/index.js:41
    const { data, content } = parseSkill(readFileSync(url, 'utf8'));
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

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

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
v0.3.52026-09-30
> v0.3.5 合并发布:v0.3.2 / v0.3.3 / v0.3.4 未单独发 Release,此处一并列出(对应 tag 均已在仓库中)。 · 0.3.5 · 修复:vendored 内嵌把范围声明当版本,上游全被误判「消失」(2026-09-28) 导出 fluent-deepseek-harness-1.0.0.dspack 时,8 个依赖全部被内嵌为 -local.1 且 reason: upstream-missing,但上游全都活着。追查下来是两个正交问题: · 1. version 解析 bug(src/core/vendored.js) listProfileDependencies 把 package.json 里的依赖声明原文直接当版本(version: spec,即 ^2.0.2)。registry 的 tarball / 元数据 URL 不接受 ^: · GET /dsh-opencode-palette/^2.0.2 → 404(精确版本 2.0.2 才是 200) · …/dsh-opencode-palette-^2.0.2.tgz → 404 于是取件失败 → 回落本地重打包 → 乱加 -local.1。修复:读 node_modules//package.json 的真实安装版本折算(spec 保留原文),取件与「三处一致」都用精确版本。 顺带修了 fetchRegistryTarball 的 URL:DEFAULT_REGISTRY 带尾斜杠再拼 / 产生双斜杠(npm 容忍但部分 registry 会 404),现归一为单斜杠。 · 2. 删掉「死上游探测」(probeNpmAlive) auto 档默认会对每个 npm 依赖联网探测上游存活、404 就擅自补选内嵌。这次就是它:探测用带 ^ 的版本必 404 → 8 个包全部误判「上游消失」→ 自动内嵌 + -local.1。与其「替用户检测」翻车,不如不检测: · auto 档改为手动勾选 + 已内嵌 round-trip,打包全程不联网; · probeNpmAlive 及其 UI 文案(vendor.mode.auto)一并清理; · full 档行为不变(全部直接依赖 + 传递闭包)。 新增/调整用例:npm 范围 spec 折算为精确版本(^ 不进 tarball URL)、expandVendorSelection 的 auto 档不再探测。全量 161 通过。 --- · 0.3.4 · 修复:悬浮球打开设置后停在别人分区的成因(2026-09-28) 0.3.3 实测(desktop profile 装的就是 0.3.3 的包):点球后设置弹窗打开了,仍停在「费用估算」。 先把根因钉死:SettingsPanel 的当前分区是 const active = rows.find((r) => r.id === activeId)?.id ?? rows[0]?.id; —— 一旦我们这一节此刻不在 rows 里,shell 会把选择回退到第一行(别的插件 order 更小,占着「费用估算」)。所以「点了我们那一行」并不等于「切过去了」,光看一眼点击事件是不够的。 · 切分区改成闭环:点 → 下一拍读 shell 的 aria-current(它标的就是当前选中行)→ 不是我们就再点(maxClicks 上限 3 次)→ 2s 内始终不是我们才如实报失败。弹窗已开着的情形也走同一条循环(旧实现那条路径只点一次、不验收)。 · 旗标握手:球在点官方入口之前先立 window.__dspackWantSection;客户端插件在同一个 MutationObserver 里看到旗标,会在弹窗挂上的第一时间把导航切过去 —— 比球自己轮询更早,而且它认识自己的 label。 · 标签通道 window.__dspackSectionLabel:球拿不到钩子时也能按文案认行(归一化空白 + 容忍包含关系);导航图标标记仍作最后兜底。 · 失败要能自证:提示里带上「我看到的导航」,例如 设置已打开,请在左侧选「整合包」;我看到的导航:通用 / 费用估算 / 整合包, 同时 console.info 一份诊断;window.__dspackBall.diag() 可拿到完整快照(钩子在不在、标记在不在、我方 label、当前选中行、各行文案)。 顺带确认了一件事:profiles/desktop 是 better-deepseek-harness 的 Junction,里面装的正是 17:49 落地的 0.3.3。若点球时页面没做过硬刷新,跑的还是旧球脚本(旧脚本既没有 2s 重试,也没有失
v0.3.12026-09-27
v0.3.1 是 v0.3.x 首个对外发布版(v0.3.0 未单独发布,此处合并 0.3.0 + 0.3.1 改动)。 ## 适配 DSH 最新协议:manifest v5 r2 / pack-structure v3 r2 本版本核心是接入 DSH 打包协议第 2 版(r2),导入 / 导出 / 市场三侧全量落地。 导入侧 · vendored 阶段 0 预检:装前对账 + 逐 tarball 校验 sha256 / size,不合规直接拒装 · 统一安装算法:vendor-blobs 落盘 + package.json file: 改写 + --prefer-offline(闭包完整自动 --offline) · DSHL vendor 隐式条目消费 · dshVersions 交集决策(dshVersion 优先 → 集合内最新) · launchers 判定表(v3 §8.4 六行,警告放行不硬拒并留痕) 导出侧 · 依赖清单端点 + 面板手动勾选内嵌(round-trip / registry 原件 / 本地重打包三处一致) · vendor 档位 auto / off / full;full 沿 lockfile 收齐传递闭包 · dshVersions / launchers 兼容性编辑(.dshpkcfg 持久化 + 打包前强校验) · 体积阈值(>500MB 警告 / >2GiB 拒绝) 市场与注册表 · pack / market-detail 懒加载 + r2 徽标 · launchers/registry 机器可读注册表(1h 缓存 + 内置回落) · 安装前 launchers 警告确认弹窗 ## 技能提供器 + sendToChat 新增技能提供器(skill provider),把本项目技能(如「上传到 GitHub」)注册进 DSH;配套 sendToChat——新建会话 → 切换视图 → 经 session scope 直接发 prompt 进聊天栏。 ## 宿主自包含 bundle + 健壮性修复 · 宿主入口切 lib/host.js:esbuild 内联 fflate / proxy-agent 等,迁装不再依赖顶层 node_modules · 修复切换 profile 后 failed to import(依赖清单漏更)与自动重启失效(migrate-helper / progress 资源随打包产出) · 修复热重载后「整合包」设置入口消失(locale 重复注册安全忽略 + section-gate 幂等闸门) · 新增设置页导航图标(folder-zip logo) · skills 读 SKILL.md 容错、安装源路径去引号、sessions.create 返回形状修正 完整说明见仓库 release_log/v0.3.0.md 与 release_log/v0.3.1.md。
v0.2.02026-09-27
· 安装依赖复用 DSH 自带运行时(2026-09-27) 安装 .dspack 不再要求用户装 node/pnpm,复用 DSH 自带运行时;失败回退 PATH,代理配置两条路径一致生效。 · 下载支持代理(2026-09-27) 市场包下载支持代理,解析顺序:显式配置 → 环境变量(HTTP_PROXY/HTTPS_PROXY/ALL_PROXY/NO_PROXY)→ Windows 系统代理(WinINET 注册表,含 ProxyOverride 绕过)→ 直连。设置页「网络」三按钮切换:自动 / 直连 / 手动(填代理地址),配置持久化到 dsh-packforge.json。 · 安装日志标注代理来源(2026-09-27) 安装 .dspack 的日志首行写明本次走哪个代理:手动配置 / 环境变量 / 系统代理 / 直连(未检测到代理或用户已禁用),便于定位网络问题。 · 已安装整合包忽略 node_modules(2026-09-27) 「已安装的整合包」列表不再把 node_modules(以及 __temp__、点目录)当成整合包,与 profile 发现逻辑复用同一套跳过规则。 · 切换默认拉取最新管理器(次之复制)(2026-09-27) 切换 profile 迁装管理器默认从 NPM 拉取最新版,失败(未发布 / 网络不通)时次之回退从当前 profile 复制;确认弹窗安装方式顺序同步为「拉取最新 → 复制」。
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。

README

由 DeepSeek 最新模型翻译生成
展开完整文档(README 剩余 1 节)
@dsh-packforge/dsh-pack-plugin

整合包必备 Essential for packs

DSH 整合包(.dspack)的纯方案 B 插件 bundle:一个自包含的独立 npm 包,注入官方 DeepSeek Harness 桌面端,提供 .dspack 导出 / 安装 / 多 profile 切换 / 市场浏览 / 工作区配置 / 任务中心。只做 UI + 后端,不做 AI 驱动的整合包管理。

- 零官方源码改动:不改 apps/desktop / apps/desktop-host。
- 零第三方插件:只依赖 DSH 出厂运行时服务(ctx.connection / ctx.webServer / ctx.slots / ctx.locale / ctx.profileContext)。
- 自包含:运行时依赖仅 fflate(ZIP)+ proxy-agent(下载代理),其余全部 vendor 进仓库(src/core/、src/host-node.js),不依赖 @dsh-packforge/ 引擎包。
- 加载方式:官方 bundle 机制——cordis.patch.yml 插入 host 插件,dsh.client 注入 client 插件。

完整设计见 dsh-packforge-app/docs/dsh-pack-方案.zh.md;格式契约见 specs/。

能力总览

- 导出 .dspack:把某个 profile 打包成单文件整合包(profile 形态),或从源仓库导出(exportRepo)。UI 目前只暴露 profile 形态;dshhome(整机)形态的打包 / 安装 / 校验逻辑在 core 里就绪,未在设置面板接线。
- 安装 .dspack:本地文件 / URL / 市场包均可;按 sha256 + size 校验完整性,pnpm 重建依赖并对账,home 级 resources 与 files[] 逐项下载落位。
- 多 profile 切换:profiles/desktop 是激活指针(junction 换指),切换即换指 + 重启桌面,无需重装。
- home 级 skills / .agent-presets 隔离:per-profile 槽位(junction),换 profile 时一并换指(见下文)。
- 市场浏览:index.json 精简指针 + packs/<owner>.<repo>/ 懒加载完整清单 / README。
- 工作区配置 .dshpkcfg:每个 profile 一份,保存 / 读取 / 自动回填。
- 下载代理:About 页可配代理地址(存 config.proxy,覆盖一切);未配时依次回落环境变量(HTTP_PROXY / HTTPS_PROXY / ALL_PROXY / NO_PROXY)与 Windows 系统代理(含 ProxyOverride 旁路)。支持 http / https / socks / socks5,市场索引 / 包详情 / .dspack 安装 / npm 拉取统一生效。
- 任务中心:install / export / create 非阻塞执行,设置面板内嵌视图显示阶段时间线与进程输出。

架构

host 侧(Node) client 侧(浏览器 bundle) src/index.js ─┐ src/client.js ── bundle ──► lib/client.js src/rpc.js │ registerRpc(ctx, runtime) src/client-plugin.js(dspackforge) src/endpoints.js → ctx.webServer 挂 /dsh-pack 前缀路由 src/channel.js ┘ src/client-rpc.js(rpc.call 封装) src/profiles.js / junction.js src/settings.js(slots 设置页:管理/导出/市场) src/migrate.js / migrate-helper.js src/progress.html src/ensure-manager.js / tasks.js / progress.js src/core/(vendored 引擎) src/locale(可选)

- RPC 通道:CHANNEL = '/dsh-pack'(src/channel.js,host / client 共用)。host 侧自建前缀路由挂在 ctx.webServer 上(不走 ctx.connection.rpc.handle——它对第三方插件不可用),并用 ctx.connection 的请求授权栅栏挡住非 client 调用;client 侧 rpc.call 静默收发,不在聊天栏显示任何工具调用。
- Host DI 边界:src/core/ 不直接碰 node:fs / node:crypto / node:child_process,一律经 Host 接口(src/host.js)注入,src/host-node.js 是 Node 实现。core 因此可脱离 DSH 单独测试。除必选能力(读写文件 / download / exec 等)外,Host 还提供可选能力(如 pnpm(args, opts)):默认回退 exec('pnpm', …)(依赖 PATH),宿主可覆盖为「复用 DSH 自带 node+pnpm 运行时(resources/runtime/)」,让桌面端装包重建依赖时不依赖用户机器 PATH 上的 node/pnpm。core 用 typeof host.pnpm === 'function' 探测,旧宿主无此能力时自动回退,行为不变。
- 多 profile 切换(junction 换指):把 profiles/desktop 换成 junction 指向目标 profile,切换 = unlink 旧 junction + symlink(target, 'junction')。红线:用 unlink(lstat 语义)删 junction,绝不 rm -r——后者在 Windows 上会递归删掉 junction 目标目录的内容。

格式契约

- .dspack 容器(pack-structure v3 / v3 r2):标准 ZIP;根放 dspack.json({"format":"dspack","version":3} 标记)+ manifest.json。
- profile 形态:机器文件(package.json / pnpm-workspace.yaml / pnpm-lock.yaml)放根,其余内容放 overrides/,home 级内容放 home/。
- dshhome 形态:整机快照(profiles/、presets/、skills/、instructions/、defaultProfile 等)。
- vendored 依赖内嵌(v3 r2 §8):可选 vendor/ 目录携带依赖 tarball。导入侧已实现阶段 0 对账 + 逐 tarball sha256/size 预验(装前拒装)、tarball 落盘 vendor-blobs/ + 重建 package.json 时改写为 file: 引用 + 本地优先安装;闭包完整性检测(对照随包 pnpm-lock.yaml)——覆盖完整自动切 pnpm install --offline(零网络、缺件即报错),局部覆盖 --prefer-offline(本地与网络互为兜底);DSHL vendor: 方言包按隐式条目消费(直挂 node_modules/,依赖剔除,不传给 pnpm)。
- 导出侧手动内嵌(v3 r2 §8.6):导出面板列出依赖清单(pack/dependencies 端点,npm/git/已内嵌三类)供手动勾选,叠加 vendor 档位(.dshpkcfg vendor 键,workspace-config v1 r2):auto(默认,round-trip 保持 + 手动勾选,不联网探测)/ off(禁用)/ full(全部直接依赖,离线包形态);勾选后按坐标取件——vendor-blobs/ round-trip 复用原 tarball 字节、npm 先取 registry 原件(字节一致)、取不到时从 node_modules 重打包并按规范加 -local.N 版本后缀(dependencies 值 / vendored[].version / tarball 内 version 三处一致);体积阈值(>500 MB 警告 / >2 GiB 拒绝打包)。
- 导出侧兼容性编辑(v5 r2 §13/§14):导出面板「兼容性」组编辑 dshVersions(实测兼容版本枚举集,datalist 建议来自本机已装版本,首个即首选、未填 dshVersion 时作首选)与 launchers(四个已认领启动器 ID 的支持/冲突 + minVersion/reason,简式/全式归一);两者持久化进 .dshpkcfg(白名单已扩展)并在打包前强校验(dshVersion ∈ dshVersions 等错误在导出时报出)。
- manifest v5 / v5 r2:type: "profile" | "dshhome"(见 src/core/manifest.js)。r2 可选字段:vendored{}(§12,导入消费 + 结构校验已实现)、dshVersions(§13,交集决策已实现:dshVersion 优先 → 集合内最新)、launchers(§14,结构校验已实现;安装端判定表待接线 UI 确认流)。前向兼容:未知字段不拒装。
- 安全规则(src/core/security.js):node_modules/、dist/、密钥 / 凭据、嵌套压缩包、.dshpkcfg、.dsh-pack 等一律不进包。
- 工作区配置(specs/workspace-config/v1,src/core/workspace.js):.dshpkcfg 为单个 UTF-8 JSON 对象,2 空格缩进 + 结尾换行;只认白名单字段(name / version / displayName / description / author / icon / dshVersion / out / exportContent / profileName / mode / content / defaultProfile);空字符串表示「未填写」。
- 市场索引(specs/index/index.md,schemaVersion 2,src/core/market.js):index.json 只放 downloadUrl + sha256 + size 指针和元数据,完整 manifest / README 从 packs/<owner>.<repo>/ 懒加载。

多 profile 切换与 home 级隔离

- profiles/desktop 是硬编码的激活指针(ACTIVE_NAME = 'desktop')。切换 = 删除旧 junction + 建立新 junction。
- 首次迁移:真实的 desktop 目录要先改名成 default 才能换指,而改名必须退出桌面进程;插件用脱管 helper(migrate.js 经 process.execPath + ELECTRON_RUN_AS_NODE=1、detached:true、cwd=home 派生 migrate-helper.js)完成「杀桌面 → 换指 → 重启桌面」。
- skills / .agent-presets 隔离:两者都是 home 级内容($DSH_HOME/skills、$DSH_HOME/.agent-presets/<id>/agent.cordis.yml),不进 profile 目录。插件的做法是把 $DSH_HOME/skills 与 $DSH_HOME/.agent-presets 换成 junction,指向 .dsh-pack/skills/<profile> 与 .dsh-pack/agent-presets/<profile> 槽位;换 profile 时对两个工件各自独立做首次迁移判定(lstat,互不耦合、部分迁移幂等),归档用「活目录胜出」(rm -r 目标 + rename),没有 skills 的 profile 建空槽位。映射逻辑见 src/core/home-store.js(storeHomeRel),换指见 src/junction.js(repointHomeArtifact)。

RPC 端点

| 端点 | 作用 |
| runtime/get | 返回 profile 运行时信息(home / profilesDir / profileDir / patchPath / startedBundles) |
| config/get / config/set | 读写 home 下的 dsh-packforge.json 状态 |
| profile/list | 列出 profiles(desktop junction 指向项不重复列出,真实 desktop 目录标为 default) |
| profile/create | 新建 profile(非阻塞,立即返回 taskId;空整合包自带管理器基线,进度见任务中心) |
| profile/delete | 删除 profile |
| profile/switch | 切换激活 profile(junction 换指 + 可选 home skills/presets 换指) |
| profile/switch-check | 预检切换(如首次迁移是否需杀桌面) |
| profile/open-dir | 在系统文件管理器打开 profile 目录 |
| pack/export | 导出 .dspack / 源仓库(非阻塞,立即返回 taskId) |
| pack/config-load / pack/config-save | 读取 / 保存某 profile 的工作区配置 .dshpkcfg |
| pack/view | 校验并查看 .dspack 内容 |
| pack/install | 安装 .dspack(非阻塞,立即返回 taskId) |
| pack/market | 浏览市场(index 列表 / 详情) |
| pack/market-detail | 市场详情懒加载(manifest + README + r2 徽标:launchers 警示 / vendored / dshVersions) |
| launchers/registry | 启动器注册表(机器可读版 launchers.json,1h 缓存;失败回落内置清单)——「兼容性」编辑器的认领 ID + 显示名数据源 |
| pack/dependencies | 列出 profile 依赖清单(npm / git / 已内嵌三类,UI 手动勾选内嵌的数据源) |
| plugin/check-update | About 页检查更新:拉 registry 最新版本,与本地比较返回 {current, latest, outdated} |
| plugin/open-url | 用系统默认浏览器打开 http/https 链接(About 页作者 / 仓库 / 求 Star) |
| task/list / task/get | 列出 / 查询任务中心任务(状态、阶段时间线、进程输出) |
| GET /dsh-pack/ball.js | 下发悬浮球脚本(同一 prefix 路由,非 RPC;no-store) |

所有端点返回 {ok:true, value} | {ok:false, error:{code,message,details}};非阻塞端点立即返回 {taskId},执行进度经任务中心(内存注册表,task/list / task/get RPC 直读)呈现。

悬浮球(独立入口)

整合包会装进各种 client 插件,有的会把侧边栏或设置页搞坏 —— 那时用户进不去设置界面,连换包、卸载都做不到。所以入口不能挂在 DSH 的 slot / React 树里:

- 由宿主注入(ball-host.js):走 webserver/index-inject 结构化行(桌面壳唯一生效通道)+ webServer.tapIndex(web 形态兜底),二者靠标记去重;行内容用内联 script 而非 script-src 行 —— 官方页面解释器对两类行处理不对称(内联无 await 不可能"加载失败",script-src 失败会 reject 成致命错误把页面带下水),所以自己建 并吞掉 onerror。宿主活在 Node 进程里,别的插件把前端拆了球还在。
- 球本体(ball.js → lib/ball.js,esbuild iife):position:fixed 自建 DOM、纯尺寸驱动;拖拽用 document 级 pointer 监听 + 3px 点击阈值,拖拽中 transition:none、松手 settle() 吸附(四分之一区域、横纵轴独立、可组合出四角);位置只存「吸附边 + 离边偏移」(resize 仍贴边,脏数据夹回可视区);贴左整体镜像;关键样式 !important 顶回宿主皮肤的几何特征拦截。
- 点击 = 打开官方设置页(ball-settings.js):官方设置界面本身就是完整的弹窗,诉求只是「进不去」,不是「没有这个页面」,所以不另造页面。SettingsRoot 用组件内部 state 管开合、对外没有 API(ctx.remote.settings.openSettingsDocument() 是「在本地打开设置文档」,不是打开这个弹窗),唯一的路是点它注册到 settings.trigger 的按钮——好在那个按钮属性是语义化的 button[aria-haspopup="dialog"][aria-expanded](无哈希类名),而合成 click() 不要求元素可见:侧边栏被主题藏起来、被挤扁、变轨道态,只要弹窗组件还挂着就点得动。点开后再把导航切到本插件分区(认 data-dspack-nav-icon 标记,不依赖文案)。
- 挂载有两道保险:宿主注入(主)+ 客户端插件 mountBall()(补,幂等守卫去重)。
- 已知边界:若坏插件让侧边栏那棵 slot 子树整个崩掉(React 抛错),设置弹窗与触发按钮都不存在,此时谁也开不了官方设置页——球会如实提示「没找到官方设置入口」,不假装成功。那种场景要的是急救(禁用坏插件)或自建面板,本轮都不做。
- window.__dspackBall 暴露句柄:openSettings() / setAction(fn) / showTip() / settle() / destroy(),要接别的动作直接换。

结构

src/ host 插件 + client 插件源码 index.js / index.d.ts host 插件入口(dspack-host)与类型声明 rpc.js 自建 /dsh-pack 前缀路由(registerRpc) endpoints.js 全部 RPC 端点(ENDPOINTS 表) channel.js CHANNEL / PROFILE_NAME_RE / RESERVED_PROFILE_NAMES runtime.js resolveRuntime(profileContext 事实来源,含 env 兜底) host.js / host-node.js Host DI 边界 / NodeHost 实现(node:fs/crypto/child_process) profiles.js list / create / delete / state(dsh-packforge.json) junction.js desktop + skills/.agent-presets junction 换指(repointHomeArtifact) migrate.js / migrate-helper.js 首次迁移脱管 helper(杀桌面→换指→重启) ensure-manager.js 空整合包管理器基线(复制 manager + fflate) tasks.js 任务中心内存注册表(task/list / task/get) progress.js / progress-main.cjs / progress.html / progress-window.ps1 切换进度窗(electron + 打包态 WPF) packaged.js 打包态判定(切换进度窗走 electron GUI 还是 WPF) settings.js 客户端设置面板(管理 / 导出 / 市场 / 关于 tab + 任务中心面板 + 弹窗) client.js / client-plugin.js / client-rpc.js 客户端 bundle 入口 / 插件面(dspackforge)/ rpc 封装 ball.js 悬浮球(纯几何 + mountBall;entry 见 ball-entry.js) ball-settings.js 球的默认动作:点官方触发按钮打开原设置页并切到本插件分区 ball-entry.js 悬浮球浏览器入口(自我挂载,打成 lib/ball.js) ball-host.js 悬浮球宿主接线(index 注入行 / tapIndex / 脚本资源读取) core/ vendored 整合包引擎(仅 import fflate) index.js 公共 API 出口 host.js Host 接口(DI 边界) dspack.js ZIP 容器(buildDspack / parseDspack / encodeText / decodeText) pack.js packProfile / packHome / dspackEntryPath / summarizeHome install.js 安装(installPack 等;home 级内容经 storeHomeRel 落槽位) manifest.js manifest v5 构建 / 校验 scan.js 目录扫描(安全规则 + junction 跟随) security.js 打包安全规则(DENY_) special.js 特殊目录识别 inspect.js 检视(inspectPack 等) workspace.js 工作区配置 .dshpkcfg repo.js repo 形态导出(exportRepo) market.js 市场索引读取 discovery.js profiles / homes / DSH 版本发现 home-store.js home 级换指槽位布局(HOME_ARTIFACT_STORE / storeHomeRel) lib/client.js client 浏览器 bundle(pnpm bundle 生成) lib/ball.js 悬浮球浏览器 bundle(pnpm bundle 生成,宿主路由下发) cordis.patch.yml bundle 注入 patch scripts/bundle-client.mjs esbuild 打包脚本(client) scripts/bundle-host.mjs esbuild 打包脚本(host,自包含 node 依赖) scripts/bundle-ball.mjs esbuild 打包脚本(悬浮球,浏览器 iife) test/ 单元测试(node --test)

命令

pnpm install
pnpm test # 单元测试(node --test)
pnpm bundle # 生成 lib/client.js(浏览器)+ lib/host.js + lib/ball.js(悬浮球)

状态

- 自包含重构完成:无 @dsh-packforge/* 依赖,仅 UI + 后端(AI 整合包管理已移除)。
- v5 r2 / v3 r2 导入侧已实现:vendored 阶段 0 预检 + 统一安装算法(--prefer-offline / 闭包完整自动 --offline + file: 引用)、DSHL vendor: 方言直挂、dshVersions 交集决策、r2 字段结构校验(test/vendored.test.js)。
- v5 r2 导出侧已实现:依赖清单端点(pack/dependencies)+ 导出面板手动勾选内嵌(round-trip 复用 / registry 原件 / 本地重打包 -local.N 后缀三处一致)+ vendor 档位(auto/off/full,full 档沿 lockfile 收齐传递闭包:registry 原件 → .pnpm 重打包回退 → skip 记档;闭包条目对账按 v5 §12 闭包规则放行)+ dshVersions / launchers 兼容性编辑(.dshpkcfg 持久化 + 打包前强校验)+ 体积阈值(>500 MB 警告 / >2 GiB 拒绝)。
- 多 profile 切换(junction 换指 + 首次迁移脱管 helper)已实现并通过测试。
- skills / .agent-presets per-profile junction 隔离已实现并通过测试(真实 Windows junction 冒烟:skills/.agent-presets 被跟随、profiles/desktop 被跳过、.dsh-pack 被排除)。
- 工作区配置 .dshpkcfg、市场浏览、任务中心(非阻塞 + 内嵌面板)已接线。
- 待办(r2):安装端闭包 tarball 的 pnpm store 预填充(full 闭包包已校验内嵌,但传递依赖尚未喂给 pnpm,故含闭包条目时保守用 --prefer-offline 而非 --offline)、发版前离线 dry-run 自检、export / install 端到端真实 pnpm 环境验证。
- export / install 端到端仍需真实 profile + pnpm 环境验证。
预览分享卡片长什么样 ↓DSH-PackForge/dsh-pack-plugin
分享 · DeepSeek Harness Hub
DSH-PackForge/dsh-pack-plugin

@dsh-packforge/dsh-pack-plugin

回到顶部