从点击到卸载:DeepSeek Harness Desktop 插件市场的信任链一次讲清
【免费下载链接】deepseek-harness-desktop为 DeepSeek Harness (DSH) 插件生态打造的现代化桌面端解决方案。万物皆「插件」,桌面本身也是「插件」。项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness-desktop
你在 DeepSeek Harness Desktop 内置的插件市场点下 Install 的那一刻,后台并不信任列表上的版本号;卸载时,它甚至不接受包名,只认一张"编号"。这篇带你跟着一枚插件走完发现、安装、卸载和出错的全程,看这条信任链到底是怎么搭起来的。
逛插件市场时,后台有多"信"来源?
结论:来源方只能提供"数据",不能提供"指令"——所有原始响应都要经 Host 侧的 adapter(可以理解为 Host 为每种来源配的"翻译器")校验、归一化,变成统一的目录快照后才进客户端,页面(Renderer)从头到尾只见到这一种格式,provider 的原始报文它看不见。
三种来源,三种脾气:
- 标准 cursor 来源(实现 public v1 契约的 HTTPS JSON 端点)和内置的dshfind:Host 只发
cursor、limit这类扫描字段,跟随page.nextCursor逐页扫描直到耗尽,把结果收进一个有界本地索引;你输入的搜索词、勾的分类从不外发。之后的本地搜索、多分类 OR 筛选、50 条/页的 UI 分页,全在这个索引上完成。dshfind 的源地址(api.dshfind.com)直接编译进 dshfind 适配器,首页以per_page=100拉取并记录data_version,后续每页原样回传;任何一页失败(比如409 stale_data)整批拒绝,宁可空窗也不发半份索引——它的匿名配额是每分钟 30 次,同步节奏特意压得更慢,首次同步就以"来源加载中"呈现。 - DSH 1024Store:不走本地索引,而是让 provider 的分页 v2 API(
/api/v2/plugins)为每次查询直接服务,无筛选浏览也一样。单分类筛选原样转发;多分类 OR 则合并有界的 provider 排序前缀,本地持一枚不透明 cursor 续页。Installable 视图每批请求200 条registry 记录,只留下页中直接的 npm 目标,页面靠下一枚不透明 cursor 继续——Host 和页面谁都不会把整个目录一次性搬进内存,逻辑见 1024Store 适配器 与 Host 路由。
来源爱挂什么安装命令都可以,规则只有一条:经审查的 1024Store adapter 仅识别一种固定形状(精确的dsh plugin --profile … add <npm-package>),从中只取出 npm 包名,命令本身当场丢弃,既不转发也不执行。来源能给目录身份,但给不了可执行 argv、凭据或安装权限。
列表里的版本数字为什么不作数?
结论:安装的版本权威只有一个——npm 官方 registry 的latest(npm 官方指针指向的那个"最新稳定版");来源列的版本只当展示用。
一个目录条目最多贡献一个npm 包身份。想进入自动安装预览,得同时过四道门:
- 从条目里归一化出恰好一个合法 npm 包名;
- 它不碰产品自有包——安装服务 里的
BLOCKED_PRODUCT_PACKAGES黑名单列着dsh-plugin-desktop、dsh-plugin-desktop-beta、dsh-community-market等,市场不代装"自己家的东西"; - 请求
https://registry.npmjs.org/<package>/latest后,返回的必须是同名包、且版本是精确稳定版(带 prerelease 后缀的预发布版,例如-alpha.1,一律拒收); - manifest 声明了合法的
dsh.bundle.patch(一个相对、无路径穿越的 DSH bundle patch 路径)。
至于来源写的版本号、仓库是否匹配、lifecycle 脚本、deprecated 标记、engine 范围、tarball 完整性元数据、provider 的验证徽章——统统不设卡。pnpm 只负责装好这一个精确版本,见 catalog-provider-contract.md 的契约说明。
点下 Install 之后:一张 5 分钟的"一次性票" 🎫
结论:确认框背后是一张绑定了一堆事实的一次性票(previewId),核销一次即焚;如果这期间 Profile 变了,票直接作废。
Preview 阶段,Host 把这几样东西绑进一枚 32 字节随机串生成的短时 token:匹配的 npm 包名、精确稳定版本、合法dsh.bundle.patch、已被观察到的目录条目(sourceRecordId+itemId)、当前激活的 Profile。票的寿命由INSTALL_INTENT_TTL_MS = 5 * 60 * 1000定死为 5 分钟,同时在手的票最多MAX_INTENTS = 256张,候选缓存另有CANDIDATE_TTL_MS = 30 * 60 * 1000的保鲜期。
执行阶段的请求体只有一枚previewId,最终落到 Host 构造的精确pnpm add(name@version)上,页面想夹带任何命令都进不来。若 preview 之后激活的 Profile 换了(名字或目录不符),执行被拒,对应conflict/intent-expired等错误码,分别映射到 409 / 410,映射表就在 routes.ts 开头不远处。失败时只保留 stdout/stderr 的有界尾部(32 KiB)写进 Desktop 日志,并在失败对话框里展示同一份诊断。
Installed 列表:Profile 直接依赖的一张"投影"
结论:Installed 视图不看市场、不看 receipt,它直接投影当前 Profile 的依赖与 bundles,所以任何渠道装的插件都自动出现。
Desktop 清单读取激活 Profile 的直接依赖和dsh.profile.bundles,于是本市场、别的市场、DSH CLI 装来的插件全在里面——不需要任何"市场间握手"协议。两条划线规则:产品自有的 core bundles 只读,不列出来;其余社区插件获得一枚绑定当前 Profile generation 的不透明bundleId(相当于 Host 发的序列号,且只提供卸载/启停,不提供"改包名"之类的操作空间)。
卸载为什么只收"编号"而不收包名?
结论:Renderer 提交的是 Host 发的bundleId,Host 前后各核对一次,确认后才动手删。
流程拆成五步:
- Host 读激活 Profile 的
dependencies与dsh.profile.bundles; - 每个直接依赖的 bundle 领一枚 generation 作用域的
bundleId; - 页面只把这枚
bundleId交回来(字段过boundedIdentifier校验:1–240 字符、不含\0); - Host 在出 preview 前先按当前清单重新解析
bundleId,执行前再复查一遍直接依赖,防止一个已被移除或变动的 bundle 被重复操作; - 确认后走
pnpm remove,删掉 bundle 引用,最后确认 Profile 不再引用该包。
对三个安装渠道一视同仁,完整分步与失败行为表可查 install-and-uninstall.md。
中途出错了找谁?恢复只有一个入口
结论:市场的失败策略是"只上报、不自救"——诊断摆出来,修复动作永远留给用户在恢复页面上亲手做。
几个边界场景:
- 包管理能力缺席:没注入
desktopProfiles/desktopPnpm这类 Profile 与 pnpm 句柄时,Discover、Sources 的只读浏览照常,只有安装入口显示不可用(入口实现 里这两个能力是软注入的); - 来源故障不挡启动:首次启动只读本地来源设置,不碰任何 provider,也没有阻塞式拉取;启动后按需取目录;
- 错误黏在所选来源上:超时给
catalog-timeout(504)、响应无效给catalog-invalid-response(502)、其余归catalog-unavailable,配 Retry 按钮,但不会偷偷切到别的已保存来源; - pnpm 失败:只展示有界诊断和 Host 派生的精确命令,附"打开 DSH Terminal"供手动跟进——不自动粘贴、不自动执行、不静默重试;
- 没有 receipt 和回滚:安装不建 receipt、快照、重试或清理路径;官方管理器负责回滚它快照过的 Profile manifest 与 lockfile,其余状态由 Desktop 的三个健康启动 Profile checkpoint(能让 Desktop 正常启动的 Profile 状态快照槽位)兜底,恢复是恢复页里的显式按钮;
- 确认后 Renderer 关闭:Host 持有的包操作继续跑,丢的只是响应。
谁能敲市场的门:回环、HTTPS 443 与 headless CI
结论:所有市场接口只对 127.0.0.1 回环敞开;来源请求只许无凭据 HTTPS 443;整条 CI 链路不碰 GUI。
- 每个路由先过
marketAuthority/marketMutationAllowed:远端地址必须落在127.0.0.0/8或::1,Host 头必须是127.0.0.1且端口匹配,cross-site请求直接拒绝;变更类请求(来源增删、安装、卸载)还要求同源 Origin; - 标准来源的 manifest 请求限定无用户名密码、无端口的 443 HTTPS,重定向逐跳核对目标地址;
- 两个经审查适配器的 HTTP client 各带独立体积上限:
MAX_DSH_1024STORE_BODY_BYTES = 2 MiB、MAX_DSHFIND_BODY_BYTES = 16 MiB,且主机名是编译期常量——用户自加的来源不会继承这些本地代理例外; - headless 约束:契约生成(Schema → TypeScript 类型)、类型检查、单元测试、包构建、export 验证、Loader smoke 这条 CI 全链都不许启动 Electron 或图形应用,tests/ 下的
contracts.spec.ts、market-install.spec.ts、host-routes.spec.ts等都在这个前提下跑,这也是市场能稳定嵌进发布链的原因。
想再深入,market-shell.md 是最短的一手说明。
【免费下载链接】deepseek-harness-desktop为 DeepSeek Harness (DSH) 插件生态打造的现代化桌面端解决方案。万物皆「插件」,桌面本身也是「插件」。项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness-desktop
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考