JHboy203/dsh-plugin-installer ↗★ 0
dsh-plugin-installer
DSH 侧边栏「插件/Skill 安装面板」:把 GitHub 链接、Release、.tgz/.zip 直链或本地压缩包丢进来,宿主侧确定性完成下载 → 解包 → 识别 → 安全预检 → 安装 → 快照/回滚 → 诊断;安装执行零 token,AI 只能推荐与提交请求。
同名包的其他仓库
安装
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:JHboy203/dsh-plugin-installer说明文档
阅读完整 README ↗dsh-plugin-installer · 插件 / Skill 安装面板
状态:开发版,非最终版本。 这是「边用边改」放出来的版本:功能与界面会不定期更新, 安装流水线、配置项与数据目录都可能变。装之前请确认下一节的 DSH 版本区间。
Status: development build — not a final release. Released as-is from daily use; features and UI change from time to time (the install pipeline, settings and the data directory may change too). Check the DSH version range below before installing.

装完在哪打开:重启 DSH 之后,左侧栏会出现一个方块里带向下箭头的图标(文案「插件安装」, 排在你其它面板图标之间)。点它,右边就切成这个面板。 找不到图标时:侧栏底部「设置 → 插件」里搜
dsh-plugin-installer,确认它是启用状态; 插件树是按启动期读的,所以装完必须重启一次 DSH。 想在任意页面按一下就自检:Ctrl+Alt+D(设置里可改键位或关掉)。
侧边栏一个图标,点开是「插件 / Skill 安装」面板:把 GitHub 链接、Release 页、.tgz/.zip
直链,或者本机压缩包/目录丢进去,面板自己完成 下载 → 解包 → 识别 → 安全预检 → 快照 →
安装 → 诊断 →(按需)回滚。
安装执行全程不调用模型:确定性代码在宿主侧跑,AI 只做「推荐」和「递请求」。 本机实测一次 Skill 安装 约 1.8 秒、插件安装到确认前 约 0.6 秒,都不花 token。
R12 起它也回答「我装了哪些、哪些能升级」:面板里多一张「已装插件」卡(默认折叠),
按 profile 的四类来源分开标(npm / 本机 link: 目录 / 本面板重打包的 .tgz / Git),
点「检查更新」才联网比对 npm 最新版 —— 本机实测 17 个可比对的包里 7 个可升级,
每一行都能直接点「升级到 x.y.z」走原流水线(预检 / 快照 / 诊断 / 回滚一个不少)。
侧栏图标(红点在这里) ─┬─→ 点开 = main 面板
└─ 红点只在「装失败 / 等你确认 / 诊断有冲突」时亮
1. 它在哪、怎么用
R2(2026-10-20)新增三件事,都不改九步流水线:
- 诊断卡默认就写「怎么解决」:每条发现带
fix: [{text, command?}]步骤清单,命令可一键复制;- 「大白话解释」开关(用户指定的名字,别再改回「通俗讲给我听」):卡片右上角, 存
localStorage的dpi.plain-explain;打开后把术语换成大白话,原文收进「术语原文」折叠。 诊断卡本身永远先给一句大白话结论(diagnosis.plain)。- 7z / rar 现在能装了:借 Windows 自带的
%SystemRoot%\System32\tar.exe(bsdtar + libarchive 3.8,本机实测能造能解 7z),解完再按实际落盘的东西复核围栏 (链接/数量/单文件/总量/压缩比),因为 bsdtar 自己不管这些。zip64 与少见存储方法 (deflate64 等)也走同一个兜底。自检从 92 → 111 项(新增:
plain/fix数据契约、client 静态契约、7z 往返 + 围栏)。 7z 那组要 spawn 子进程,只能在宿主进程里跑(见 §7 的host_selfcheck),沙箱里会 EPERM。R3(2026-10-20 04:00)再加两件(宿主侧代码,重启生效):
- 搜索从 2 个源扩到 6 个源(npm 两串 / GitHub 两串 / topic 发现 / dsh-hub.cc 商店目录), 每条命中带
trust(官方、许可证、有源码、近期更新 + 红旗:无仓库、已归档、刷星、 年轻但星极多)与popularity(npm 周下载量、商店安装量/评分、stars、本机评分)。 见lib/sources.js。- 按用途判断权限是否合理(
lib/purpose.js):推断用途档(界面/网络/媒体/运维/数据/Skill) → 与扫描到的能力对账 →ok / warn / error / unknown+ 大白话 + 建议;预检卡新增 「用途 vs 权限」块。eval/vm/new Function/混淆 在任何用途里都算 error;Skill 里带可执行文件 直接 error;用途认不出来就不判。自检 111 → 132;无头渲染 12 → 18;新增只读探针
dev/probe-repo.mjs(下载→解包→扫描→预检+用途判定,不安装)。R4(2026-10-20 13:10)把「花多少 token」变成可测的:确定性步骤全部 0 token, 唯一模型调用是异步 AI 审查(实测材料 7,055 字符 ≈ 2.5k 输入,封顶 ≈4k); 新增
reviewWorthIt()(只有安装脚本/提示注入/高危命中/用途不符才审,否则跳过并写明理由)、estimateReviewTokens()(面板显示「≈2610 token」或「省下 ≈2650 token」); 并收紧扫描规则:obfuscation只认长 base64 字面量、native不再误吃'egress.node', 每条命中带why。自检 132 → 152,渲染 18 → 22。R5(2026-10-20 18:40)修三件「自检查不到」的事(宿主侧,重启生效):
- 命中密度不再被丢掉。
scanTree一直同时算了counts(样本,每类最多 5 条)和真实分布, 但摘要只读前者 —— 实测dsh-our-free-model面板上全是「×5」,真实是 74 个文件都在发网络请求。 现在新增density(每类能力出现在几个文件里,跨文件精确、零额外成本),摘要改用它, 面板显示「网络请求(74 个文件)」;purpose的发现也带「N 个文件里都有」。 同时加一条bundle-payload组合信号:同类命中铺满几十个文件时折成一条, 明说「这是把依赖/bundle 一起提交的仓库,按发布者可信度判断,别逐条数命中」。- 搜索加了 TTL 缓存(
memoizeTtl:同 key 5 分钟一次、并发共享、抛错不缓存; npm 下载量 30 分钟)。原因很实:一次搜索固定 6 个源 + 最多 10 个下载量请求,而 GitHub 搜索 API 未认证只有 10 次/分(一次搜索用 3 次)→ 一分钟内第 4 次搜索必 429。 撞限流时输出里直接给「设DSH_GITHUB_TOKEN可提到 30 次/分」的处置。- 文案与实现对齐:工具数 4 → 5(启动日志按实际数量打印)、
install_hub_search_plugins描述写明 6 个源(含 dsh-hub 商店评分/安装量)、AI 推荐提示词说明候选来自商店、 删掉download.js里已无调用方的旧searchNpm/searchGitHub。自检 152 → 172,渲染 22 项不变。
R5.1(2026-10-20 19:05)把 R5 列出的四个缺陷修掉(宿主侧,重启生效):
- 构建标记:
buildStamp()= package 版本 + 源码(index.js / client.js / lib/*.js)里最新 mtime →/health的build不再是写死的"p2-pack",/state的host.build、install_hub_status第二行、环境体检卡都能看到。client.js另加BUILD号随client-state上报。- 「等待确认」的现场有保鲜:
prune()现在用stagingKeepNames(pkg, jobs)—— 没跑完的任务(queued/running/awaiting-confirm)引用的staging/uploads//与staging//不再被 24 小时 mtime 清掉(以前跨夜 + 重启 = lost-state)。- 升级 / 降级 / 同版本重装说清楚:预检读
profile/node_modules//package.json, 新增理由「这是升级:已装 0.0.5 → 本次 0.1.0」,降级给 warn。- 商店源用满:
shapeHub展示「分类 · 界面」徽章、安装量 why 带评论数/点装数, hub 搜索取min(20, per*2)条再本地重排。自检 172 → 194(+build 4、+prune 4、+installed 6、+hub 4、+client/index 静态契约 4)。
R6(2026-10-20 19:30)面板「设置」——个性化,但不放松判据。右上角「设置」:
- 提醒:侧栏红点(默认开)、声音(默认关,WebAudio 一短音)、桌面弹窗(默认关,
Notification;未授权先问一次)。红点关掉后attention.dot=false,但count/items照常给。- 审核三档:严格(检出任何能力特征就停 + 低/中危也 AI 审一次)→ 普通(默认 = 现有强度) → 关闭(不停、不调模型,但 profile/未识别/版本不兼容 照样阻断)。
- 「跳过审核」按钮(默认开):只在「等待确认 + 这次本来要审」时出现;点击后原地二次确认 (写明不停下 / 不花 token / 风险提示仍有效 / 可回滚),宿主留痕
reviewSkipped与日志。- 其余:轮询 2.5/5/10s、历史 5/8/20 条、快照 20/40/80 份、搜索源 npm/GitHub/商店(至少留一个)。 落盘
data/settings.json,默认档 = 标准版;写坏了会被归一化夹取回默认。自检 194 → 245(+设置 23、审核三档 9、红点与跳过审核 7、搜索源 3、路由/客户端契约 9); 渲染 22 → 42(真渲染设置面板两轮 + 跳过审核按钮三态)。
R7(2026-10-20 19:20)自检热键
Ctrl+Alt+D(纯客户端):任意页面按一下就跑一次环境自检 (复用宿主action:"repair",不新开一套判据),结果用游离浮窗报(面板没挂载也看得见), 浮窗自己消失、热重载先摘旧监听(否则一次按键发 N 个请求);键位存dpi.selfcheck.hotkey, 可在设置里改Ctrl+Shift+D/Alt+Shift+D/ 关闭;有任务在跑时拒绝动手,宿主doctor(apply)也有并发闸。自检 +15 → 260。
R8(2026-10-20 19:40)把「装完就起不来」的判据并进面板(宿主侧,重启生效):
- 预检第 ⑤ 项:工具注册契约(
lib/contract.js)。DSH 0.2.1 起ctx.tools.register()要求output { schema, render },漏了不是静默降级 —— 插件激活失败;required 插件还会让 整次启动中止(症状:恢复对话框 + 一串「等待服务」的插件,2026-10-18 就这么挂的)。 现在装之前扫解包目录(precheck给 warn + 两条处置步骤),装之后diagnose再扫一遍已装的目录,直接进诊断卡。- 环境体检扩成 7 类(
lib/profilehealth.js):dsh.profile.bundles与 node_modules 对账 (被「禁用第三方插件」按钮裁到 2 项也认)、已装插件的 output 契约、pnpm 的 dsh-tools 钉子是否 随宿主升级过期、最近一次启动失败(crash-*-host.log宿主崩溃 /crash-*-web-boot.log前端入口 没激活,R17 起两类都读)点名了哪些插件、属于已知签名里的哪一类。apply:true除原有两项外, 还会把钉子同步到宿主版本、从最近快照写回 bundles/patch(写前自动再存一份快照)。- 一次调用看全:
install_hub_doctor默认只回「一行结论 + 每条发现一行」,verbose:true才带 detail;contract:false可跳过已装插件扫描提速。换会话 / 装完 / 起不来时只需这一个工具。- 自检 260 → 269(+契约扫描 4、profile 体检与修复 5)。
R6.1(2026-10-20 22:30)把「怎么验收」固化成
dev/audit.mjs(收尾轮): 28 项自洽检查 —— 默认档冻结快照(改DEFAULTS而不改承诺会红)/ 5 个工具的 output 契约 / 构建标记格式(0.1.0 · YYYY-MM-DD HH:MM,且/health不许写死)/ 客户端设置与热键入口 /settings.json归一化后逐字不变 / 等待确认任务的 staging 现场还在 / README 与交接文件里的 断言数是否等于EXPECTED_ASSERTIONS。不碰宿主、不 spawn、不写盘,只打印 「接着跑 host_selfcheck(885)+ render-check(153)」。自洽检查现已 177 项。 三层分工至此固定:audit = 自洽,host_selfcheck = 行为,render-check = 界面。 线上实测:构建标签0.1.0 · 2026-10-20 19:45、客户端r6.0、GET/POST /settings正常 (非法值当场夹取回默认)、clientReport里有 360×658 的窄屏实例。R9(2026-10-22 01:15)「装不上」时说清为什么、并给出真能走的一步(宿主侧;实测被运行中的宿主重新 apply,未重启即生效,但别把它当保证):
- 失败分诊(新
lib/installfailure.js):把宿主自己的两条判据搬到面板 —— ① pnpm 失败的 10 类(build-blocked/not-found/no-matching-version/disk-full/permission/integrity/network/timeout/pnpm-missing/unknown,次序与正则 照抄dsh-plugin-manager的LOG_KINDS);②ManagementFailure的 11 个拒绝码 (incompatible-version/already-installed/ambiguous-install/not-bundle/invalid-spec/stale-approval/management-required/stop-profile/bundle-in-use/not-removable/unaddressable)。每条都给「为什么(大白话)+ 建议 + 2–3 条处置步骤」, 原始输出留 4 KB。以前:只有 pnpm 的英文原文;宿主拒绝时甚至只有一行incompatible-version。- 安装脚本待批准的完整闭环:pnpm 拒绝执行构建脚本时,宿主机把包名以哨兵
"set this to true or false"写进 profile 的pnpm-workspace.yaml → allowBuilds然后失败。 面板现在:读回名单(parseAllowBuilds,不引 YAML 依赖)→ 卡片逐个列名 + 二次确认 → 经installBundle(spec, { approvedBuilds })转交(宿主自己写allowBuilds=true再跑 pnpm; 名单过期它抛stale-approval,我们翻成人话)。复核在宿主侧:只接受仍然 pending 的包名, 面板不提供「一键放宽权限」。- 模型拿不到这个动作:
approve-builds只在面板路由里,五个工具都没有它 —— 「让作者写的脚本在本机执行」只能由人来按。- 体检多一条:profile 里还挂着待批准脚本(跨任务残留,会挡住下一次装同一个依赖),只报不修。
- 顺手修掉一个真 bug(线上撞出来的):
save()用固定state.json.tmp, 而「action 响应里顺带跑的snapshotState()→ensureReconciled()→save()」会和新任务的execute()撞在同一个 tmp 上 —— 先完成的那次 rename 走了文件,后一次报ENOENT: rename 'state.json.tmp' -> 'state.json',而这条错误会被当成安装失败记在任务上。 现在:save 串行 + 每次唯一 tmp 名 + rename 对瞬时错误(ENOENT/EPERM/EACCES/EBUSY)重试;settings.json同样处理。实测证据:修前那条重试任务报 ENOENT,修后同一条重试报出真实原因 (「认不出这是压缩包」)。- 自检 269 → 372(+103:分诊 10 / 文案与拒绝码 14 / 批准闭环 20 / 落盘竞态 3 / 豁免与兼容 44 / 接线与暴露面 12), 无头渲染 42 → 62(+20:批准卡两态 + 兼容卡三态),自洽 28 → 52。
R10(2026-10-22 01:45)「版本不兼容」从死路变成一条说得清的路(宿主侧 + 面板):
- 面板不认宿主已有的豁免 → 死循环(真 bug):判定兼容性时没把 profile 的
compatibility.json传进evaluatePluginCompatibility,于是「已经授权过的版本」 回来装还是被红牌挡住,而卡片给的下一步是「先退出 DSH 再跑 CLI」。现在:读记录 (lib/exemptions.js,宿主接口优先、文件兜底)+ 认证传参,授权过的版本按 「不兼容但已豁免」继续装。- 体检误报(真 bug,本机实测):
install_hub_doctor把 3 个已豁免的插件报成 「会被跳过」—— 而那三只当时工具全都好用。现在:体检也带豁免判定,分成 「真会被跳过(error)」与「已豁免(info,只知情)」,外加「豁免对当前 DSH 已失效」的 warn(升级后常见)。- 面板里直接授权:对「装到一半被版本判据挡住」的任务给一张卡 —— 点名
包@精确版本+ 当前 DSH + 不满足的范围,二次确认(写明可能崩溃/损坏数据、只对这一个版本生效、写进compatibility.json)→ 走宿主setVersionExemption(...)→ 回读确认 → 开新任务重试。 目标由服务端从预检结论推出,客户端不能自带包名/版本(不能用来预先放宽一个兼容的包); 五个工具都不暴露它。- 降级判定对齐宿主(真 bug):版本侦测不到时,本地 semver 用严格预发布规则会把 17 个插件判成不兼容(宿主真值 3 个)。现在两条修正:
evaluateCompat接受调用方显式 传入的运行版本;本地判定改用宿主的宽容口径(includePrerelease)。修完实测与宿主完全一致:incompatible=0 / exempted=3。R11(2026-10-22 02:00)「等确认的现场不许被按时间清掉」+ 状态里多一行「环境注意」:
- staging 生命周期按「任务还有没有后续动作」判(真 bug):
prune()原来只按 24 小时清data/staging/*,于是一个「等待确认」的任务放一天多再点确认,解包现场已经没了 —— 用户看到「文件不在」而他什么也没做错。现在:非终态任务(queued/running/awaiting-confirm)的现场一律不按时间清;终态的老现场照常清。install_hub_status多一行「环境注意」:把「版本豁免 N 条(M 条对当前 DSH 已失效: …)」与「待批准安装脚本 K 个(…)—— 下次装同一个依赖还会卡住」压成一行。这两件事 不提醒就等于没有(一个让插件安静消失、一个让下一次安装卡在同一处),但都只读、只提醒, 修/批仍然只能在面板里由人点头。- 自检 372 → 378(+6:staging 真目录 + 真 mtime 验证两条 / 环境注意四态), 自洽 52 → 55(+3:三处接线)。
R11.1(2026-10-22 02:05)「跑的是不是新代码」变成自动答案(
lib/codestamp.js): R9/R10 各踩一次「改了lib/*却没换新」,当时只能人工做行为探针(加一个动作、再打一次请求看谁回话)。 现在:模块首次被 import 时把index.js + client.js + lib/*.js的内容哈希记在内存里(那就是真正被加载的代码), 之后/health的code与install_hub_status的「运行中的代码」一行直接回答:与磁盘一致(31 个文件 · ab12…)或旧(磁盘已改:lib/x.js,需要重启 DSH 才会换新)。 构建标签(源码 mtime)从此只用于「磁盘上新不新」,不再冒充「跑的是哪一版」。 自检 378 → 383(+5:freshness 判定 / 指纹覆盖面 / 两种人话 / 降级),自洽 55 → 57(+2)。R12(2026-10-22 02:3x)「我装了哪些、哪些能升级」—— 面板第一次有"已有资产"的视角: 以前它只会装:想升级一个已装插件得自己记得名字、搜一次、再提交一次,而「哪些落后了」 从来没被回答过。现在多一张已装插件卡(折叠时只说规模,展开才逐条列):
lib/inventory.js(纯本地读,30 秒缓存):把 profile 的 44 条依赖按声明形态分成四类, 它们的「能不能升级」完全不同——npm范围才有 registry 最新版可比;link:是本机源码目录 (改了就生效,没有"新版本")、file:是本面板重打包的.tgz(升级要重新提交新包)、github:的版本在仓库里而不在 registry 上。混为一谈就会产出真误导(把本机目录说成"落后")。@deepseek-ai/*一律标「宿主自带、不参与升级」——从 npm 装第二份会遮蔽宿主(dsh-tools 那个雷的同类)。lib/updates.js(只在人点「检查更新」时联网):registry/ /latest比对, 失败逐条隔离(404/超时/被墙不拖垮整张表)、30 分钟 TTL、并发封顶 4、弃用标记原样带回。 本机实测:17 个可比对的包里 7 个可升级(dsh-checkpoint-rewind0.6.24→0.6.33 等)。- 可升级行直接给「升级到 x.y.z」按钮 → 走
npm:@交给原流水线(预检/快照/诊断/回滚一个不少)。- 搜索结果与状态工具也接上了:命中带「已装 vX」标记(不重复装同一个包);
install_hub_status({updates:true})多「已装 / 更新 / 可升级」三行(默认不联网)。- 顺手修了一个真 bug:输入
npm:包名@版本时把npm:前缀当成了包名的一部分 → registry 404 → 静态扫描被跳过(安全降级),安装时又把非法 spec 交给 pnpm。现在两处都剥掉前缀。 自检 383 → 453(+70:清单判据 24 / 更新比对 20 / npm 前缀 4 / 接线 9 / codestamp re-apply 5 / 其它 8), 渲染 62 → 80(+18:折叠态 / 展开态 / 可升级按钮 / 三种兜底态),自洽 57 → 69(+12)。 渲染脚本从此自己比对条数(EXPECTED_TOTAL)—— 源码里check(有 103 处、实际只跑 80 条 (其余在else/catch兜底分支里),数源码不等于数断言。R12.1(同一轮顺手):把「运行中的代码」那一行从会误报改成会说清。 实测撞出来的:
/inventory已经回 200(新代码在跑),可这一行还在说「旧 · 需要重启 DSH」—— 根因是「指纹只在codestamp.js自己被加载时算一次」+「宿主是逐文件换新的」 (codestamp.js没改,就一直沿用 02:04 那个实例)。判据反过来指挥人做无用功,是最坏的一种错。 修法:apply()每次(重新)apply 都记账(recordApply()→globalThis),freshness()多回appliedAt/appliedAfterLoad,于是三档分开说:一致 / 「宿主已在 HH:MM 重新 apply,看行为、 别盲目重启」/「改完没有任何 re-apply → 真该重启」。它仍不是万灵药:只证明入口被重新 apply 过, 不证明每个lib/*都换了 —— 真判据只能是行为(新路由/新字段回不回话)。
R13(2026-10-22 12:5x)「装上了 ≠ 起来了」—— 一次真实静默失效换来的三条判据。 起因:本机 10 小时里装过
dsh-imgops两次,两条任务都是红色「安装失败」,可 pnpm 明明是成功的。 翻回执才看清:宿主是正常返回{ application: "failed", stage: "enable", error: { code: "operation-error", diagnostic: "dsh: warning: 1 entry did not activate\nimgops (dsh-imgops): Error: cannot get property \"tools\" without inject" } }—— 包装进了 profile,但激活那一步炸了:插件入口apply(ctx)用了ctx.tools,却没写export const inject = ["tools"]。 而面板当时报的是「package manager 报告安装失败」,⑨诊断还判「一切正常」。三条病一起治:
lib/inject.js(新):静态扫「入口函数体里用了ctx.,但 inject 没声明它」。判据刻意做窄 —— 只认apply自己的函数体(同文件里 canvas 的ctx.fillRect不会被算成服务),注释里的示例不算,inject: [...](客户端 bundle 的对象写法)也算声明。修法直接给一行可粘的export const inject = ['tools']。 接在预检(装之前拦)与诊断(装之后兜)两处。失败分诊补上「不抛异常的那种失败」:
application:"failed"以前不走describeInstallFailure, 于是failure = null,面板只剩一句错的通用话。现在把宿主的error.code+diagnostic+ pnpm 输出一起喂进去, 新增kind: "activation-failed"(标题点名「装上了但没激活」+ 缺哪个服务 + 那一行修法)。诊断第一次看得见「行勾着但没激活」:
fiberPhase是宿主行记录里的真字段(active / null),但旧代码的plugins.find(p => p.entryId === row.id)永远匹配不上 —— 宿主给的是include:,于是那一整段 「插件行没有运行」从来没生效过。现在按include:前缀宽匹配,并新增判据:enabled && fiberPhase !== "active"→ error「装上了,但没激活」,带上宿主原话与修法。
already-installed不再算失败:第二条任务就是它(同版本再装一次)。它表示「已经在依赖里、这次没改动」, 现在收成 done + 备注,并照常跑诊断(用户真正想知道的是「它起没起来」)。端到端又撞出第二个真 bug(同一轮修掉):把
dsh-imgops修好、版本提到 0.1.1 重新提交, 宿主仍回already-installed—— 因为判「装过没有」看的是依赖行里的 spec 字符串,不看文件内容; 而 vendor 包名一直是pkg-.tgz(不含版本),换了内容也是同一个 spec。于是**「重装/升级」静默无效**, 用户只会看到一条红色的「安装失败」。修法:vendor 包名带版本(pkg--.tgz), 并把同一个插件没人引用的旧包收掉(profile 还指着的绝不删,宁可少删)。体检也升级了:
install_hub_doctor现在会逐插件扫 inject 契约,并读listPlugins()的fiberPhase报「行开着但没激活」—— 这正是「装了怎么没反应」最常见的两个答案。固定成插件能力(不是留在脚本里):判据抽成唯一的
lib/activation.js(scanActivation/activationFindings/summarizeActivation),被安装后诊断、环境体检、 状态工具、新增的GET /plugin-installer/activation四处共用;install_hub_status多一行 「激活:47 行在跑 / 共 48 行 · 1 行没激活」,面板的体检卡直接显示对应 finding。node dev/verify-r13.mjs --port --yes是对应的端到端验收器(中文路径必须走它)。断言:hosttest 453 → 506(+53:inject 六种写法/边界 14、回执分诊 10、诊断行匹配与 fiberPhase 4、 版本化 vendor 名与旧包清理 4、codestamp 的「apply 是否晚于磁盘」3、体检两项 5、激活视图 10、接线 3)。
R14(2026-10-22 14:0x)补齐「Skill」那一半:面板标题从第一版起就写着「插件 / Skill 安装」, 可是它只回答过插件那一半 —— 装了哪些技能、宿主认不认、名字有没有撞车,全都没有入口。 而本机真出现过「技能装了却从不被自动调用」,根因恰恰是这些看不见的事实。
- 新增「已装 Skill」卡 +
GET /plugin-installer/skills:磁盘扫技能根(59 个目录,每个读 SKILL.md 的 name/description),再和宿主ctx.skills.list()的SkillSummary对账,给出四类异常: 宿主没认(磁盘有、清单没有 = 装了但用不上)/ 重名(同层两个目录声明同一个 name)/ 备份残留(.bak-*还躺在技能根里,且带着同样的 name)/ 不会自动调用(宿主modelInvocable=false)。 摘要一行与状态工具、体检共用同一句话(lib/skills.js是唯一口径)。- 修掉一个「读到了但读错」的真 bug:
parseSkillFrontmatter只认单行标量,于是description: >这种折叠块把指示符>当成了描述 —— 面板上显示一个「>」,用途推断还拿它去和能力比对。 本机 11 个技能是这种写法。现在按 YAML 处理三种形态(>折叠 /|字面 / 缩进续行)、剥 BOM、剥引号。- 对账的假结论被钉死:读不到宿主清单时不许把每个技能都标成「没被认」(那是最容易犯的错)。
buildSkillView用hostKnown闸门分开「对账不了」与「没被认」,两种情况的摘要与结论都不同; hosttest 里各有一条断言盯着它(ctx.get("skills")也一样:本插件没 inject skills,只写ctx.skills会永远读到 undefined —— 那会得到一个「本机没有技能服务」的假结论)。- 体检并入技能结论:
install_hub_doctor现在也会报「N 个技能目录宿主没认」(error)、 「N 组合法性问题」(warn)、「N 个备份残留」(info),每条都带大白话与处置步骤。