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-remote-kit

v1.0.0

Published

Remote-access kit for a DSH (DeepSeek Harness) web instance running in a headless container: mobile UI polish, old-browser polyfills, loopback-equivalent trust for public entries, and headless directory picking. One `dsh plugin add` registers all four.

Readme

dsh-remote-kit

给无桌面容器里跑的 DSH(DeepSeek Harness)Web 实例用的一套远程访问插件。一个包、四个插件、一条安装命令。

dsh plugin --profile web add dsh-remote-kit

装完自动并入 profile 的插件层(dsh.profile.bundles),重启 DSH 即全部生效。不改任何官方文件,DSH 升级后不丢。


它解决四个具体问题

| # | 症状 | 插件 | 根因 | |---|---|---|---| | 1 | 老浏览器打开 DSH 报 Iterator is not defined,界面显示 "Failed to load plugins" | dsh-remote-kit/browser-compat | 官方 documentpreview 直接取 Iterator.prototype(ES2025,Chrome 122+),老浏览器上抛 ReferenceError 导致整个插件模块导入失败。垫片补齐 35 项新 API | | 2 | 用公网 IP / 局域网 IP 访问时,设置页报 settings are unavailable in this browser | dsh-remote-kit/loopback-trust | 客户端 isLoopback 只看 location.hostname,不认 --trusted-host → 设置持久化降级为 memory,一个请求都不发。本插件走官方预留的 __DSH_TRANSPORT__.ownsHost 修正判据 | | 3 | 无桌面容器里工作区创建不了,点「添加工作区…」没反应 | dsh-remote-kit/headless-picker | 容器 entrypoint 导出了 DISPLAY=:0 指向不存在的 X 服务器 → 官方选了 native 对话框后端 → spawn zenity 失败(exit 1)→ 被当成「用户取消」→ 前端静默无反应。本插件做能力探测,不可达就摘掉该变量 | | 4 | 手机上用 DSH 界面难用(头部重叠、按钮错位、设置页层级混乱) | dsh-remote-kit(包根) | 官方 UI 按桌面设计。本插件是移动端深度适配,所有 CSS 挂在 [data-mobile] 下,桌面端逐字节不受影响 |


包结构(为什么长这样)

dsh-remote-kit
├── package.json          dsh.client + dsh.bundle.patch
├── cordis.patch.yml      注册全部四个插件
└── lib/
    ├── index.js          ← 包根 = mobile-polish 宿主半
    ├── client.js         ← 包根 = mobile-polish client 半
    ├── browser-compat.js
    ├── polyfill.js
    ├── loopback-trust.js
    ├── snippet.js
    └── headless-picker.js

为什么 mobile-polish 必须占包根? 两个硬约束,都有源码出处:

  1. dsh-client-modules 的 exactPackageSpecifier() 只接受不含 / 的 specifier。含 / 的(如 dsh-remote-kit/mobile-polish)会被判为「不是 client 包」→ client 半静默不注册(不报错,最难查)。
  2. client bundle 里的 id 必须等于包名 —— 入口图的每一行按包名校验 factories.has(id),对不上就报 bundle loaded without registering "..."。所以 lib/client.js 的 id 与 data-plugin-css 已同步为 dsh-remote-kit。

其余三个是纯宿主半,走子路径导出 —— 这是官方惯用法,官方自己的补丁层里就有 @deepseek-ai/dsh-agent/invariant 等 9 处同样写法。

⚠️ 纯宿主半插件绝不能声明 dsh.client:声明了就必须提供 ./client 导出,否则 DSH 直接起不来(报 declares dsh.client but exports no "./client" bundle,且日志可能是 0 字节)。

给维护者的提醒(本包是从已有插件改名的,别踩)

本包由四个独立插件合并改名而来。改动前请先读这三条,否则会出现「不报错但不生效」:

  1. lib/client.js 里的 id 与 data-plugin-css 必须等于包名(现为 dsh-remote-kit,共 4 处字面量)。 改包名时必须同步改这 4 处 —— 入口图每行按包名校验 factories.has(id),对不上会报 bundle ... loaded without registering "..."。
  2. lib/client.js 里 MP_PLUGIN_DESCS 描述表的键要跟 cordis.patch.yml 的 name: 对齐 —— 插件列表卡片的 title 就是这个 name,查不到就没有中文描述(不报错)。 本包已写全 4 个键:dsh-remote-kit、dsh-remote-kit/browser-compat、 dsh-remote-kit/loopback-trust、dsh-remote-kit/headless-picker。
  3. 宿主半 lib/index.js 里 export const name 只是「显示名」(cordis Fiber#name, 仅用于日志/诊断),改不改都不影响功能 —— 官方自己的子路径插件也各不相同 (如 @deepseek-ai/dsh-agent/invariant 导出 "agent-invariant")。

安装

前置:DSH 侧的信任栅栏

用非回环地址访问时,必须给 DSH 加 --trusted-host,否则界面能加载但 /api/* 全 403(不是 404):

dsh web --port 3080 --no-open --trusted-host <公网IP>:<端口>

判据:curl -sS http://<入口>/ → 200,而 /api/boot → 404(栅栏已过)。 若是 403,就是缺 --trusted-host。

前置:pnpm

dsh plugin 是 pnpm 的薄转发层,机器上必须有 pnpm。没有就装:

corepack enable pnpm     # 或 npm i -g pnpm

安装

dsh plugin --profile web add dsh-remote-kit

命令做的事:在 profile 目录跑 pnpm add,然后按已安装状态重整 dsh.profile.bundles —— 凡是声明了 dsh.bundle 的依赖会被自动追加进插件层列表。所以不用手改任何 yml。

装完重启 DSH。


验证

装完后逐条对判据(都在浏览器 console 里跑):

// ① mobile-polish —— data-mobile 只有本插件会设置
document.documentElement.hasAttribute('data-mobile')
//   手机视口 → true      桌面视口 → false(桌面必须 false,这是设计红线)

// ② browser-compat —— 垫片已生效
window.__dshBrowserCompatApplied
//   现代浏览器 → ['Iterator helpers'] 之类的一两项;老浏览器 → 一长串

// ③ loopback-trust —— 仅非回环入口才干预
window.__DSH_TRANSPORT__.ownsHost
//   公网/局域网入口 → true      真回环 127.0.0.1 → undefined(正确,不干预)

服务端判据(headless-picker):

curl -sS http://127.0.0.1:3080/ | grep -oE "directory-picker-[a-z]+"
# 无桌面容器 → browse(正确)   有桌面 → native(正确)

四个插件是否都注册了:

dsh --profile web --dump-config | grep -A5 'dsh-remote-kit'

设计红线(这些行为是刻意的,不是 bug)

| 插件 | 红线 | |---|---| | browser-compat | 全部 typeof 能力探测 → 现代浏览器上是 no-op,零行为改变。垫片全程 try/catch,读不到文件只记日志,失败绝不拖垮页面 | | loopback-trust | 真回环页面一字不改(本机行为 100% 不变);不覆盖 __DSH_TRANSPORT__ 既有字段;幂等 | | headless-picker | 真有显示服务器时一字不改;DISPLAY=host:0 这类无法本地验证的一律放行;X11 与 Wayland 各判各的 | | mobile-polish | 全部 CSS 作用域在 [data-mobile] 下,且 data-mobile 要求「窄屏 且 非 hover+fine 指针」→ 桌面浏览器无论窗口多窄都保持官方 UI |


安全提示(请务必读)

loopback-trust 会让非回环页面获得与回环页面相同的设置读写能力。DSH 原本把非回环页面降级是有意的保守设计,本插件是在明确知情下放开。

仅在入口本身已被信任时使用 —— 即服务端已 --trusted-host,且该入口有别的门卫(认证/内网/隧道)。若入口是公网裸奔的,本插件不会引入新的漏洞面(能访问的人本来就能控制 DSH),但请清楚这一点。


常见问题

装完没生效?

  1. 重启 DSH(改 package.json / cordis.patch.yml 必须重启;改 lib/*.js 刷新页面即可)。
  2. dsh --profile web --dump-config | grep dsh-remote-kit 确认四个条目都在。
  3. 看 DSH 启动日志有没有 declares no dsh.bundle 警告 —— 有就说明包版本太旧。

client 半没注册(首页 boot 清单里没有 dsh-remote-kit/client.js)? 包名里带了 / 就会这样(见上文「为什么包根必须是 mobile-polish」)。必须是包根。

dsh plugin add 报 pnpm not found on PATH? 装 pnpm(见前置)。

/api/* 返回 403? 缺 --trusted-host(见前置)。

dsh plugin add ./本地目录 报 Package name ... is invalid, it should have a @scope? 这是 pnpm 12.1.0 对本地路径的已知问题。从 npm 安装不受影响。本地调试可手写 "dsh-remote-kit": "link:/abs/path" 到 profile 的 package.json,再跑 dsh plugin --profile web install。


卸载

dsh plugin --profile web remove dsh-remote-kit

dsh.profile.bundles 里的条目会被自动清掉(reconcile 的反向逻辑)。


License

MIT