Agent Skillshikariming/dshfind › desktop-market

desktop-market

GitHub

定义DSH桌面端插件市场的安装契约,维护npm包名与版本信息。包含探测插件安装方式、排查安装失败原因及核对七项复核标准,确保用户能正确一键安装插件。

.claude/skills/desktop-market/SKILL.md hikariming/dshfind

Trigger Scenarios

排查插件在桌面端市场无法安装或版本过旧的问题 核对插件是否满足桌面端preview的七项复核要求 查询或验证插件的安装契约数据

Install

npx skills add hikariming/dshfind --skill desktop-market -g -y
More Options

Non-standard path

npx skills add https://github.com/hikariming/dshfind/tree/main/.claude/skills/desktop-market -g -y

Use without installing

npx skills use hikariming/dshfind@desktop-market

指定 Agent (Claude Code)

npx skills add hikariming/dshfind --skill desktop-market -a claude-code -g -y

安装 repo 全部 skill

npx skills add hikariming/dshfind --all -g -y

预览 repo 内 skill

npx skills add hikariming/dshfind --list

SKILL.md

Frontmatter
{
    "name": "desktop-market",
    "description": "维护发给 DSH 桌面端插件市场的安装契约(\/market\/v1\/plugins)——探测插件的安装方式与 npm 最新版本、排查某个插件为什么在桌面端市场里装不了或装到旧版本、核对某个包是否满足桌面端 preview 的七项复核。"
}

DSH 桌面端插件市场契约

deepseek-harness-desktop 的社区市场把 dshfind 当标准目录源接进去,桌面端用户 在市场里点「安装」,装的就是我们发过去的包名和版本号。所以 plugins 表里那几列 不是展示字段,是安装契约——填错等于让用户装错东西,不填等于这个插件在市场里 根本不存在。

两个端点

端点 内容
GET https://api.dshfind.com/market/manifest.json 静态 manifest,内容恒定
GET https://api.dshfind.com/market/v1/plugins 契约分页,?q= ?category= ?cursor= ?limit=

实现在 server/internal/httpapi/market.go,schema 逐条对齐 dsh-community-market/docs/catalog-provider-contract.mdadditionalProperties: false, 所以那边用的是独立白名单响应类型,不要复用 /v1/plugins 的形状)。

一条 item 长这样,package + latestVersion 是能不能一键安装的分水岭:

{
  "id": "bowenliang123/dsh-context",
  "repository": { "url": "https://github.com/bowenliang123/dsh-context" },
  "package": { "registry": "npm", "name": "dsh-context" },  // 有它才装得了
  "latestVersion": "0.30.2"                                  // 桌面端照着它装
}

三道闸门

一个插件要在桌面端市场里可安装,得同时满足:

  1. is_plugin = 1 —— p.IsPlugin == nil || !*p.IsPlugin 的条目 market 端点直接跳过。 未探测(NULL)也算不满足:契约端点不做猜测。所以从没跑过 probe:install 的仓库 一个都进不了市场
  2. npm_desktop_installable = 1 —— 探测侧预演了桌面端安装前的七项复核 (scripts/lib/install.mjs desktopPreviewVerdict),全过才发安装证据。
  3. npm_latest_version 非空 —— 必须是精确稳定 semver(x.y.z),prerelease 与 deprecated 一律不采信。

差一条就只剩 repository,桌面端只能引导用户去 GitHub 自己装。

七项复核(desktopPreviewVerdict)

桌面端复核在 v2.0.3(2026-08-26 发布,提交 7ec8213e)大幅简化createNpmRegistryVerifier 现在只验包名合法、npm latest 精确稳定版本、名称一致、 dsh.bundle.patch 安全——repository 比对、deprecated、生命周期脚本、运行时 range、 engines.node、dist 完整性全部删掉了。

但 v2.0.1/v2.0.2 的存量客户端还在跑老版全量复核,所以我们的 desktopPreviewVerdict新旧两代的交集发证据(即保留全部七条,只把第 4 条的 monorepo 处理改聪明了)。等 v2.0.1/v2.0.2 存量消失后,2/3/6/7 可以整体放宽。

# 复核 现状 不过的典型原因
1 name / version 存在且是非空字符串 两代都要 几乎不会踩
2 deprecated 字段 仅旧版 作者废弃了旧包名
3 preinstall / install / postinstall / prepare 生命周期脚本 仅旧版 最常见:留了 prepare: husky
4 repository 剥掉 git+ 后是 https:// 且回链到本仓库;monorepo 子包的 directory 合规即放行(见下) 仅旧版 scp 式 git@github.com: 直接拒;directory: "." 仍拒
5 dsh.bundle.patch 存在且是安全相对路径 两代都要 不是组合包,或写了 ../ 逃逸
6 cordis 不能出现(legacy);@deepseek-ai/cordis@deepseek-ai/dsh* 的 range 要覆盖桌面端运行时 仅旧版 锁死了老版本 range
7 engines.node 覆盖桌面端 Node;dist.integrity 是 sha512、dist.tarball 是官方源无凭据 仅旧版 engines.node: "20.x" 把自己挡在外面

monorepo 子包(repository.directory / subdirectory)

manifest 带 repository.directory 的 npm 包(monorepo 子包)不再一票否决:

  • directory 能过 catalogSubdirectoryscripts/lib/install.mjs,逐字镜像桌面端 contracts/identity.ts normalizeSubdirectory + wire schema)→ 放行,探测把它写进 npm_repo_directory 列,契约条目随安装证据发 repository.subdirectorymarket.go / gen-api-artifacts.mjs,两侧逐字节对齐)。v2.0.1/v2.0.2 的旧复核 要求「manifest directory ↔ 目录 subdirectory 相等」,发出去正好两代通吃。
  • 不合规(最常见是发布工具写的 directory: ".",2026-08-28 全库 9 个带 directory 的被挡包里占 6 个)→ 继续拒:那个值我们发不出去——桌面端 normalizeRepositoryIdentity 对不合规 subdirectory 抛异常且整页拒收, 发错一个值等于把整个 dshfind 源在桌面端搞挂。这也是改这条链路时最大的稳定性红线。
  • schema 从 v2.0.1(dshfind 源首次出现的版本)起就认 repository.subdirectory, 发这个字段对所有能浏览我们目录的桌面端版本都是 wire 安全的。

运行时常量:值冻结于 v2.0.2,HEAD 上已经没有了

第 6 条依赖的三个常量在 scripts/lib/install.mjs 顶部。桌面端 v2.0.3 把它们 连同整段复核一起删了——对 HEAD grep RUNTIME_VERSION 会查空,别被误导。 现在的抄本对齐的是最后一个还执行该复核的版本:

# v2.0.2(最后一个带运行时复核的版本)里的原值
curl -s https://raw.githubusercontent.com/anywhere-labs/deepseek-harness-desktop/v2.0.2/\
dsh-community-market/src/install/service.ts | grep RUNTIME_VERSION

这三个值不会再漂(v2.0.2 已定格);整段第 6/7 条什么时候删,取决于 v2.0.1/v2.0.2 存量客户端何时可以忽略。

历史事故记录(2026-08-25,当时 HEAD 还带复核):我们停在 0.1.0-rc.7,桌面端已是 0.1.1-rc.2,生态普遍升到 ^0.1.0-rc.8satisfies 全线为 false,★2778 的 DSH-better-sidebar(全站第 3)14 个依赖集体误判、掉出一键安装。改复核规则后必须 联网重探--rederive 不行(复核要的 npm 版本文档没有入库):

pnpm probe:install --all --npm-bundles   # 只重探已发 npm 的组合包,受影响的只有这批

一眼自查:头部插件里若成片出现 runtime-range:@deepseek-ai/dsh-*,先怀疑常量, 而不是怀疑几十个作者同时写错了范围。

日常维护

# 头部全量重探(一百多个仓库,一两分钟)——pnpm refresh 已经内置这一步
pnpm probe:install --all --min-stars 100

# 全库补探:从没探过的仓库进不了市场,新收录的批次要补
pnpm probe:install                    # 默认只探没探过 / 超 7 天没探的
pnpm probe:install --stale-days 3     # 头部发版快,缩短新鲜度阈值

# 排查单个插件(不写库),会打印契约变化
pnpm probe:install --only owner/repo --dry-run

# 改了桌面端运行时常量后,定向重探可能受影响的行(已发 npm 的组合包,约 2200 个)
pnpm probe:install --all --npm-bundles

# 改了推导规则后离线重算,不联网(注意:不会重算桌面端复核结论)
pnpm probe:install --rederive
pnpm test

给作者的答复模板:--only <仓库> --dry-run 拿到结论,再照「七项复核」那张表说明是哪一条不过。 最常见的三条是生命周期脚本scp 式 git@ repository最新版是预发布

跑完看这段输出,它就是这轮契约变了什么:

桌面端市场契约变化:
  + 6 个开始可一键安装
  - 2 个不再可一键安装(包被撤、版本转预发布或复核不过)
  ↑ 15 个的安装版本更新
      bowenliang123/dsh-context: 0.15.0 → 0.30.2

三条不能忘的规矩

  1. 版本号必须勤探。 npm_latest_version 是发给桌面端的精确 revision,桌面端照着装。 头部插件一周能发十几个版本(实测 dsh-context 五天走了 0.15.0 → 0.30.2, dsh-im 走了 0.11.0 → 2.1.0)。这一列放着不动,市场里的人就一直在装几周前的旧版。
  2. 抓不到 ≠ 没有。 429 / 5xx / 超时一律判 unknown,事实沿用上一轮、探测时间不刷新, 下轮立刻重探(fetchOutcome / mergeManifestProbe / mergeNpmProbe)。 只有 404 / 410 才是「确认不存在」。这条线不守住,一次限流就能把一个正常插件 从市场里除名,而且下一轮还会把这个错误结论当既成事实留着。 跑完那句「⚠️ N 个仓库这轮没问全」就是这个机制在工作,不是错误。
  3. 包名归属必须回链。 全库两千多个「已发布」里有一千多个的包名在 npm 上属于别人。 回链不通过就不发安装证据——否则桌面端会去装一个陌生人的包。

全库一轮要跑几小时,脚本按 400 行一片探完就写库(SLICE),中途被打断只损失当前这片, 已完成的部分连探测时间一起落库,下轮 stale 自然跳过。别改回「攒到最后一把写」—— 踩过一次:跑到 6700/10923 卡住,整轮一行都没落库。

页面侧

详情页的安装命令与版本号来自同一批列,但版本号的口径和契约一致、和仓库不一致

  • pkgVersion = 仓库 package.json 的版本(作者可能已提交但没发布)
  • installVersion = 这条命令实际会装到的版本,npm 装法取 npm_latest_version (见 src/lib/install.ts installVersionOf

两者经常差一截(dsh-context 仓库里是 0.30.3,npm 上是 0.30.2)。页面标的是后者。

构建期预渲染的头部 24 个详情页读不到 Turso,走 realPlugins 静态快照兜底, 所以安装方式也写进了快照(gen-plugins-real.mjsinstallOf)。 插件超市列表用不上它,staticFallback() 会剥掉,别让几千条命令进懒加载响应体。

相关

  • 下载量口径:.claude/skills/track-downloads/SKILL.md
  • 整轮数据刷新:.claude/skills/refresh-site/SKILL.md

Version History

  • 6e038a7 Current 2026-09-02 21:32

    新增monorepo子包目录探测与subdirectory契约支持,优化desktopPreviewVerdict复核逻辑以兼容新旧客户端。

  • b1b1af0 2026-08-27 09:15

Same Skill Collection

.claude/skills/refresh-site/SKILL.md
.claude/skills/score-plugins/SKILL.md
.claude/skills/track-downloads/SKILL.md

Metadata

Files
0
Version
6e038a7
Hash
dff62716
Indexed
2026-08-27 09:15

ホーム - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-09-05 18:49
浙ICP备14020137号-1 $お客様$