npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dsh-packforge/dsh-pack-plugin

v0.3.5

Published

DSH 纯方案 B 插件 bundle:.dspack 导出/导入/多 profile,零官方源码改动、零第三方插件

Readme

@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 成致命错误把页面带下水),所以自己建 <script src> 并吞掉 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 环境验证。