档案 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 上一致。
72 lines
4.8 KiB
JavaScript
72 lines
4.8 KiB
JavaScript
#!/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)
|