Files
dsh_shenxian/scripts/verify-dsh-compat.mjs
admin 29c57a8207 feat(web): 模型设置页复刻官方交互 + 官方推荐插件按 dsh 版本过滤(档案 91/92/93)
档案 91 ——「模型设置」页折行 + 复刻官方交互(插件 0.3.15)
· 折行根因不是"窄":原「我已添加的厂家」是 4 列表格(列宽 auto)⇒ 名称/状态/两按钮三处折行同源;
  改官方 dsh-client-ui-settings-models 的**卡片行**(rowHead + rowActions margin-left:auto,两侧 nowrap)
· 「新增」改官方**两步式**:默认两个虚线按钮 → 点开才出卡片,主字段只剩「API 密钥」
  (官方原文:页面从不询问环境变量名);次要字段收进 <details>「自定义设置」
· CSS 数值逐值照抄官方 CSS 模块;顺修「由 admin 配置」「密钥可留空」两处错文案,补删除二次确认

档案 92 —— 官方推荐插件列表按 dsh 版本过滤(插件 0.3.16)
· 官方目录不带 dsh 版本字段 ⇒ 逐包查 npm 声明与平台真实版本比,分类 match/none/newer/older/unknown
· 默认隐藏「仅兼容更旧版本」,「需更高版本」橙色标注;勾选框为逃生口;说明行给隐藏计数(不静默消失)
· ⚠️ 判 satisfies 必须带 includePrerelease(平台是 prerelease,默认语义会把在跑的 dshmarket 之类判成更旧)

档案 93 —— 兼容判定收口(服务器 CI 由红转绿)
· 「单测长期红」真相 = 服务器源码落后于 git(本机 48/0 全绿)⇒ 同步即修,非代码问题
· 伞包 @deepseek-ai/dsh 收口到 dsh-install.platformPackageVersion()(它不在自己的 node_modules 里,
  原先恒判 null ⇒ 声明在伞包上的"要求更高版本"全被放行);闸门与列表共用同一份版本表
· 闸门判据 A 加 prerelease 兜底:实测抽样 300 里 prerelease-artifact 117 条(≈39% 假阳性,
  含在跑的 dshmarket)⇒ 容忍下能满足则只计数(prereleaseOnly)不阻断

校验
· 新增 scripts/verify-dsh-compat.mjs(21 条回归锚点)与 verify-models-dict.mjs / verify-models-render.cjs
· verify-platform-admin-section.mjs:断言从旧 UI(表格/下拉「自定义厂家…」)改成断言新 UI
  (含模拟点击两个新增入口 + 选中目录厂家)
· 两个仓库外的动作:服务器 npm run build + ci.sh(CI OK)+ systemctl restart dshs;插件 0.3.16 已铺发

⚠️ 本提交未包含 src/supervisor/orchestrator.ts —— 那是别人在途的内存配额改动
(BASE 160→448 / MIN 384→512 / MAX 1024→1536 / mcn 128→256),其对应的客户端常量尚未同步,
本机 verify-mem-model 因此有 4 项红;提交后仓库树两边均为旧值,该断言在 HEAD 上一致。
2026-09-14 21:13:32 +08:00

72 lines
4.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* verify-dsh-compat.mjs —— 「官方推荐插件列表按 dsh 版本过滤」(档案 92)的**回归锚点**。
*
* 为什么需要:这条链路的关键判据**全都不是"跑得通/跑不通"能暴露的** ——
* · 少了 `includePrerelease: true`:功能照跑,但会把**在平台上跑得好好的**插件
* (`dsh-univer-office`、`dshmarket` …)判成「只兼容更旧版本」而被隐藏。
* 2026-09-14 实测:TOP300 默认语义 `match 97 / older 139`;prerelease 容忍 `match 214 / older 22`。
* · 少了「伞包 `@deepseek-ai/dsh` 单独解析」:所有"要求 dsh ≥ 0.1.5-rc.2"的插件都判不出来
* (伞包**不在自己的 node_modules 里**)—— 而那恰恰是用户要标注的那一类
* (实测 TOP300 的 3 条 `newer` **全部**只写在伞包上)。
* · 前端少了「隐藏计数/说明」:条目会**静默消失**,正是本库反复强调要避免的。
* 以上都会"静默降级",所以钉成断言。
*
* 用法:node scripts/verify-dsh-compat.mjs 退出码 0=全绿 / 1=有失败
*/
import { readFileSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import { dirname, join } from 'node:path'
const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..')
const read = (p) => readFileSync(join(ROOT, p), 'utf8')
let failed = 0
const ok = (name, cond, extra = '') => {
console.log((cond ? ' ✓ ' : ' ✗ ') + name + (extra ? ' ' + extra : ''))
if (!cond) failed++
}
const compat = read('src/web/plugin-dsh-compat.ts')
const route = read('src/web/routes/whitelist.ts')
const client = read('poc/business-plugins/lib/client.js')
const install = read('src/web/dsh-install.ts')
const legacy = read('src/web/plugin-compat.ts')
// ── ① 后端判据:prerelease 语义 + 伞包解析(两条都是"静默降级"型)──
ok('判定用 prerelease 容忍语义(includePrerelease: true)', /includePrerelease:\s*true/.test(compat))
ok('伞包解析收口在 dsh-install.platformPackageVersion(单独读 <dsh 包根>/package.json)',
/export function platformPackageVersion\(/.test(install) && /full === PKG_NAME \? dshPackageRoot\(\)/.test(install))
ok('两处消费方共用同一份版本表(不再各写一遍)',
/platformPackageVersion/.test(compat) && /platformPackageVersion/.test(legacy) &&
!/versionTable/.test(compat) && !/versionCache/.test(legacy))
ok('分类枚举含 newer / older / match / none / unknown',
['newer', 'older', 'match', 'none', 'unknown'].every((k) => new RegExp(`'${k}'`).test(compat)))
ok('"要求更高"优先于"只兼容更旧"(newer 先返回)', /if \(newer !== null\)[\s\S]{0,200}kind: 'newer'[\s\S]{0,200}if \(older\.length > 0\)/.test(compat))
ok('semver 不可用时降级为 unknown(而不是判兼容/不兼容)', /semver === null\)\s*return \{ kind: 'unknown'/.test(compat))
// 闸门(判据 A)也必须先按默认语义、再容忍 prerelease —— 否则「声明 `*`」会被判不兼容。
// 实测:抽样 300 里这类"prerelease 产物"有 117 条(dshmarket 等能跑的都在其中)。
ok('闸门判据 A 有 prerelease 兜底(默认语义不满足时先看 includePrerelease)',
/semver\.satisfies\(v, range\)[\s\S]{0,2000}includePrerelease: true/.test(legacy))
ok('prerelease 产物只计数、不进 findings(不阻断)',
/prereleaseOnly/.test(legacy) && /out\.findings\.push[\s\S]{0,200}prereleaseOnly/.test(legacy))
// ── ② 路由:过滤 + 标注 + 缓存 + 预热 + 不静默 ──
ok('GET 尊重 dshCompat 参数(=all 时只标注不过滤)', /dshCompat !== 'all'/.test(route))
ok('只隐藏 older,其余(含 unknown)照常显示', /kind !== 'older'/.test(route))
ok('响应带 hiddenByDsh(供前端说明隐藏了多少)', /hiddenByDsh/.test(route))
ok('响应带 dshVersion(当前版本)', /dshVersion: platformDshVersion\(\)/.test(route))
ok('判定结果落盘缓存(避免每次搜索打 npm)', /npm-dsh-compat\.json/.test(route))
ok('有后台预热,避免冷启动全判 unknown', /warmCompat/.test(route))
ok('请求内只给预算:取不到判 unknown 并仍显示', /COMPAT_BUDGET_MS/.test(route))
// ── ③ 前端:徽章 + 说明 + 逃生口 ──
ok('前端有兼容徽章函数 wlCompat', /function wlCompat\(/.test(client))
ok('「需更高版本」用醒目徽章(pending/橙色)', /cls = "pending"/.test(client))
ok('查询串带 dshCompat=all 逃生口', /&dshCompat=all/.test(client))
ok('说明行给出隐藏计数(不静默消失)', /pa\.pl\.cmpHidden/.test(client) && /hiddenByDsh/.test(client))
ok('表格新增 dsh 版本列', /pa\.pl\.compatCol/.test(client))
console.log(failed === 0 ? '\n全部通过(dsh 版本兼容过滤:判据 + 过滤 + 标注)' : `\n${failed} 项失败`)
process.exit(failed === 0 ? 0 : 1)