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

@avantf/dsh-compat

v0.1.0

Published

DSH plugin startup compatibility gate: prove the host API is the one this build was written against, refuse to load when it is not, and only warn on a version difference

Readme

@avantf/dsh-compat

DSH 插件的启动兼容性底座:在 apply() 最前面确认"宿主 API 还是本构建写的那一套",证明不兼容就拒绝加载,只有版本号不同则只警告。

不依赖任何 dsh 版本 —— 这是它的立身之本:src/ 只 import node 内置模块与 zod(peer),一个 @deepseek-ai/* 都没有;清单里不出现任何 dsh 版本号(dependencies/peerDependencies/devDependencies 都没有)。需要 dsh 声明的地方改成依赖注入probeTool: toolProbeDeclaration(defineTool) 由调用方传自己的 helper(探针本来就该镜像插件自己的声明路径)。唯一的 dsh 接触在测试里 —— 它挂载宿主真实的注册表来验证探针,用的是你装的那份 dsh(scripts/link-dsh.mjs,不钉版本)。

dsh 变得快,而插件的整个 API 面都是 dsh 的。没有这道门时,失败方式恰恰是最难查的两种:apply 中途抛错(半个插件挂上了),或者插件挂上了却完全惰性(工具注册到空气里、唤醒闸门永远不进,一句报错都没有)。这个包把判断、探针与复查做成通用件,插件只需声明"自己调了什么"。

用法

npm i @avantf/dsh-compat     # 或源码依赖:link:/file: 指向本仓库目录

插件侧三处接线,全部集中在一个 provision.ts 里:

import { defineTool } from '@deepseek-ai/dsh-tools'
import {
  provision, registerMegaphone, compatReport, verifyRegisteredFaces,
  readBuildVersions, readDeclaredVersions, readRuntimeVersions, schemaNamesFrom, toolProbeDeclaration,
  type CompatSpec,
} from '@avantf/dsh-compat'

const SPEC: CompatSpec = {
  packageId: '@acme/my-plugin',
  // 探针声明由你注入:包里不认识 dsh 类型,而探针必须是你自己的真身声明
  probeTool: toolProbeDeclaration(defineTool),
  // 传你的真身 contribution —— 这样「探针通过」就等于「接下来那次注册会通过」
  probeTypert: () => myWireContribution,
  // 本插件调用的服务与方法;required = 缺了就拒绝加载(cordis 的 inject 没有可选形式,
  // 能降级用的服务用 ctx.get 读,这里写 required: false)
  services: [
    { name: 'tools', required: true, methods: ['register', 'get'] },
    { name: 'typert', required: false, methods: ['register', 'get', 'list', 'listPackages', 'toJSONSchema'] },
  ],
  // 「本构建编译时对着哪一版」:优先读构建时烧在产物旁边的 dsh-build.json(精确版本),
  // 取不到才逐包回落到自身 package.json 的 peer 区间地板
  declared: readBuildVersions(
    new URL('./dsh-build.json', import.meta.url),
    ['@deepseek-ai/dsh-tools'],
    readDeclaredVersions(new URL('../package.json', import.meta.url), ['@deepseek-ai/dsh-tools']),
  ),
  // 本产物自己的链接解析出的版本(不是宿主版本 —— 见「已知边界」)
  runtime: readRuntimeVersions(['@deepseek-ai/dsh-tools'], import.meta.url),
  needsInterval: true,
  schemaNames: schemaNamesFrom(myWireContribution),
  events: ['agent/pre-step'],
}

export function apply(ctx: Context): void {
  const log = myLogger(ctx.logger)
  const verdict = provision(ctx, log, SPEC)      // 第一步,什么都还没注册
  if (!verdict.load) {
    registerMegaphone({
      ctx, log,
      command: { name: 'myplugin', description: '报告插件为何未加载' },
      text: compatReport(verdict, {
        heading: '插件未加载:与当前 dsh 的兼容性检查未通过。',
        warningsLabel: '风险提示:',
        warnings: verdict.warnings,
        fix: '修复:重新构建,或把 @deepseek-ai/dsh 换回本构建声明的版本。',
      }),
    })
    return
  }

  // …正常挂载…

  // 真身注册完之后:按精确 key 数一遍 schema、把工具名逐个读回(warn-only)
  verifyRegisteredFaces({ ctx, log, packageId: SPEC.packageId, schemaNames: SPEC.schemaNames, toolNames })
}

判据

| 结论 | 触发 | 后果 | |---|---|---| | 拒绝加载 | 必需服务或方法消失,或注册表拒绝了与真实声明同形的探针 | load: false:什么都不注册,日志给期望 vs 实际 | | 警告 | 本产物自己链接解析出的版本构建时编译对着的版本(烧入的 dsh-build.json,回落 peer 地板)不同 | 继续加载 | | 只记一笔 | 版本解析不出来(compat: ok 行里写成 unknown)、事件名、未挂载的可选服务、没有查询面的注册表 | 继续加载 |

  • 探针是主动的,而且必须是你自己的真身声明tools 用你注入的 defineTool 造一个一次性工具(注册 → get 读回 → 撤回);typert 注册你给的那份 contribution(推荐 probeTypert: () => 你的真身 contribution)→ 按它声明的 schema 名查 get/list/listPackages/toJSONSchema → 撤回。"register 是个函数"和"注册我们真正注册的东西能成"是两回事,只有后者能抓到契约移动。 这条规则是踩出来的:本包曾提供一个"最小但像样"的默认探针,它在 dsh 0.1.6 上给出 ok —— 因为它没有 codec,而 0.1.6 恰好改了 codec 契约(0.1.5 查 schema.parse,0.1.6 查 create())—— 紧接着真身注册在 apply 中途抛错,插件半挂载。所以现在没有默认探针:不传就是"未探测"(记一笔,不拦),要探就给真身。只有当真 contribution 确实没有 codec 时,才用 minimalTypertProbeDeclaration 并在注释里写明原因。
  • 拒绝,但绝不抛错apply 里抛出的异常不只影响你自己 —— Cordis loader 会让整次 update 失败并回滚(同一棵配置树里的每一行都被 dispose + 重新 create),而重新 create 可能撞上 storage-domain 的"同名域单开"(already-open)再也回不来。活证:某插件在 0.1.6 上因 codec 契约变化在 apply 中途抛错,回滚把邻居的工作区注册表搞成未挂载,界面里工作区像消失了一样。所以本包的规则是:把风险挪到加载前(探针 = 真身),失败就 load: false + 日志 + 可选的扩音器命令;调用方在 apply 里也应当只在什么都还没分配的位置做有风险的注册。
  • 版本差异只警告:不同版本从来没有单独让插件出过错,按它拒载会把插件从"只是升级了 dsh"的部署里踢出去。两侧的语义要读准:declared = 本构建编译时对着哪一版(优先构建时烧入的精确版本,见下),runtime = 本产物自己的链接现在解析到哪一版。ok 行因此写 dsh links: <包> <版本> 并注明"宿主身份未观测",而不是 running
  • declared 优先用烧入版本:构建脚本在链接好那份要编译的 dsh 之后,把逐包精确版本写成产物旁边的 lib/dsh-build.jsonBUILD_VERSIONS_FILE),运行时用 readBuildVersions(new URL('./dsh-build.json', import.meta.url), packages, peer地板) 读回。没有这个文件(开发树、单测、老产物)就逐包回落到 peer 区间地板 —— 回落是逐包的,一个写坏的条目不会把整份文件作废。这也让原地升级安装版 dsh 后的那次 WARN 有意义:警告说得出"我编译时是 X,现在链接解析到 Y"。
  • 绝不抛错apply 抛出会让 loader entry 失败、一路带到 CLI(process.exit(1)),一次版本漂移不该让整个 dsh 起不来。拒绝加载的效果一样(引擎一点也没挂上)。

API

| 名字 | 作用 | |---|---| | provision(ctx, log, spec) | 一步入口:取证 + 判定 + 打日志,返回 CompatVerdict | | verdictOf(evidence) / floorOf(range) | 纯判据,零 DSH 依赖,可脱离宿主全分支单测 | | readBuildVersions(buildUrl, packages, fallback?) / BUILD_VERSIONS_FILE | 读构建时烧入的精确版本,缺失逐包回落到 peer 地板 | | readDeclaredVersions(manifestUrl, packages) / readRuntimeVersions(packages, base?) | peer 区间地板(回落用)/本产物自己链接解析出的版本 | | gatherEvidence(ctx, spec) / checkServices / checkInterval | 取证 | | probeToolsRegistry / probeTypertRegistry | 两个注册表探针(各自可单独用) | | toolProbeDeclaration(defineTool) | 生成 tools 探针声明:把调用方的 helper 注入进来,免得包里认识 dsh 类型 | | minimalTypertProbeDeclaration(packageId) | 仅限「contribution 里没有 codec」的场景;默认位置留给调用方的真身 | | verifyRegisteredFaces / schemaNamesFrom / declaredSchemaKeys | 真身注册后的复查 | | registerMegaphone / compatReport | 拒绝时留给用户一条能说明原因的命令 | | COMPAT_PREFIX | 所有日志行的统一前缀(compat:) |

CompatVerdictload(可否继续)、skippedstatusok / version-mismatch / version-unknown / probe-skipped / probe-failed)、problems / warnings / noteslines(可直接喂 logger)、reason

已知边界

  • 版本比较只覆盖「本产物 ↔ 它链接的那份 dsh」,宿主身份未观测 —— 这是设计边界,不是 bug。插件里没有任何办法看到宿主自己的版本(没有哪个 dsh 服务把它暴露给插件),readRuntimeVersions 解析的是本产物自己 import.meta.url 那条链接指向的包。于是两种形态会打印出"看起来不对"的版本号,且都是正确的:
    • checkout 宿主 + 安装版链接:宿主是 0.1.6 checkout,而插件的 @deepseek-ai/* 链接指向安装版 0.1.5-rc.2 → ok 行打印 0.1.5-rc.2。宿主是否同源不在本包能力内,此时只有真身探针是真的防线(本包正是为此把探针做成"注册你真身声明")。
    • 原地升级了安装版 dsh、但没有重建插件runtime 变成新版本、declared(烧入版本或 peer 地板)还是旧版本 → 一条 WARN,插件照常加载。 两侧都只描述"插件 ↔ 它链接的那份 dsh",ok 行因此写 dsh links: 并显式注明宿主身份未观测;要判定进程里到底混装了几份 dsh,得用符号探针(TOOL_RUNTIME_SCHEDULER 之类的 unique symbol),不是本包。
  • 事件名无法证明:监听器注册在改名后的事件上照样成功、然后永远不跑。所以事件清单只进"记一笔",运维能拿到的信号是版本行与 compat: 日志。
  • invocation endpoint 不在公开查询面里list/listPackages 只暴露 schema 与 package model),所以复查覆盖的是 schema key 与工具名。
  • 探针误判会把能用的插件变成拒载的插件 —— 这是本包最大的风险,所以两个探针都对着宿主真实的注册表(ToolRuntime / TypertRegistry)跑常驻测试。

开发

pnpm install
pnpm typecheck   # 先链接 DSH peers(需要一份已安装的 dsh)
pnpm test
pnpm release:check   # typecheck + build + test + pack(含 tarball 内容断言)
pnpm build && npm publish

测试用的 @deepseek-ai/* 全部来自已安装的 dshscripts/link-dsh.mjs--dsh <dir> 可指定非全局安装),仓库里不钉版本:探针的常驻测试就是"在你装的那份 dsh 上仍然工作"。

作为源码依赖被别的仓库引用时(消费方 link:/file: 指向本目录):

pnpm install && pnpm build     # 消费方读到的是 lib/,改完源码要重建
node_modules/.bin/tsc -w -p tsconfig.json   # 开发底座本身时可以挂着 watch

解析走本目录的 realpath,所以 peers 必须在本目录链接过(上面两条命令已包含)。

zod 这个 peer 的区间刻意放宽到 >=4.4.3 <5:本包只用它构造探针 schema,而家族消费方带着两份都能工作的 zod —— 4.4.3(对齐 harness checkout)与 4.6.5(已安装 dsh 自带的)。^4.6.5 会拒掉前者;两端都用 pnpm typecheck && pnpm test 实测过。

License

MIT