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 上一致。
This commit is contained in:
1 parent
1d72e8f9c8
commit
29c57a8207
11 files changed
+1474
-209
No files matched your search
+36
-19
@@ -33,7 +33,7 @@ import { pathToFileURL } from 'node:url'
|
||||
// 平台内置包的落点**不能写死**:`npm root -g` 随发行版变(`/usr/local/lib` vs `/usr/lib`),
|
||||
// 写死只会在另一种布局上静默退化成「平台包目录不可读」而不报错(测试服实测 = 0)。
|
||||
// 统一走 `dsh-install.ts` 的按序探测。
|
||||
import { dshScopeDir } from './dsh-install.js'
|
||||
import { dshScopeDir, platformPackageVersion } from './dsh-install.js'
|
||||
|
||||
const DS_SCOPE = '@deepseek-ai/'
|
||||
|
||||
@@ -53,6 +53,11 @@ export interface CompatResult {
|
||||
platformPkgs: number
|
||||
/** 是否真的看到了 @deepseek-ai 的依赖声明或 import(区分 ok / unknown 用) */
|
||||
sawPlatformRef: boolean
|
||||
/**
|
||||
* 有几条声明「按 semver 默认语义不满足、按 prerelease 容忍满足」——**平台是 prerelease**
|
||||
* 的语义产物,**不计入 `findings`、不阻断**,只留个可观测计数(2026-09-14,档案 92)。
|
||||
*/
|
||||
prereleaseOnly?: number
|
||||
/** 判定过程出错时的说明(此时 level=unknown) */
|
||||
note?: string
|
||||
}
|
||||
@@ -61,7 +66,6 @@ export interface CompatResult {
|
||||
* 平台侧:版本表(读 package.json)与导出符号(按需 import,带缓存)
|
||||
* ------------------------------------------------------------------ */
|
||||
|
||||
const versionCache = new Map<string, string | null>()
|
||||
const exportCache = new Map<string, Set<string> | null>()
|
||||
|
||||
function shortName(pkg: string): string {
|
||||
@@ -94,22 +98,15 @@ export function platformPkgCount(): number {
|
||||
}
|
||||
}
|
||||
|
||||
/** 平台内置某包的版本;平台没有该包 → null。 */
|
||||
/** 平台内置某包的版本;平台没有该包 → `null`。
|
||||
*
|
||||
* 2026-09-14(档案 92):改为走 `dsh-install.platformPackageVersion()` —— 原实现只查
|
||||
* `<scope>/<短名>/package.json`,而**伞包 `@deepseek-ai/dsh` 不在自己的 `node_modules` 里**
|
||||
* ⇒ 对它恒判 `null`,被当作「平台没这个包,不算不兼容」而放行(实测那 3 条"要求更高版本"的
|
||||
* 插件全部只写在伞包上)。收口后该判据**含伞包**,与 `plugin-dsh-compat` 共用同一份版本表。
|
||||
*/
|
||||
function platformVersion(pkg: string): string | null {
|
||||
const hit = versionCache.get(pkg)
|
||||
if (hit !== undefined) return hit
|
||||
let v: string | null = null
|
||||
try {
|
||||
const pj = join(platformPkgDir(pkg), 'package.json')
|
||||
if (existsSync(pj)) {
|
||||
const meta = JSON.parse(readFileSync(pj, 'utf8')) as { version?: unknown }
|
||||
v = typeof meta.version === 'string' ? meta.version : null
|
||||
}
|
||||
} catch {
|
||||
v = null
|
||||
}
|
||||
versionCache.set(pkg, v)
|
||||
return v
|
||||
return platformPackageVersion(pkg)
|
||||
}
|
||||
|
||||
function resolveEntryFile(pkg: string): string | null {
|
||||
@@ -159,7 +156,7 @@ async function platformExports(pkg: string): Promise<Set<string> | null> {
|
||||
return keys
|
||||
}
|
||||
|
||||
type SemverLike = { satisfies(v: string, r: string): boolean }
|
||||
type SemverLike = { satisfies(v: string, r: string, o?: { includePrerelease?: boolean }): boolean }
|
||||
let semverPromise: Promise<SemverLike | null> | null = null
|
||||
|
||||
function loadSemver(): Promise<SemverLike | null> {
|
||||
@@ -303,8 +300,25 @@ export async function checkPluginCompat(root: string): Promise<CompatResult> {
|
||||
continue
|
||||
}
|
||||
let ok: boolean
|
||||
let prereleaseOnly = false
|
||||
try {
|
||||
ok = semver.satisfies(v, range) // **默认语义**:与 pnpm 的实际安装判定一致
|
||||
// ① 先按**默认语义**判(与 pnpm 的实际安装判定一致)
|
||||
ok = semver.satisfies(v, range)
|
||||
if (!ok) {
|
||||
// ② 不满足时再看是不是**prerelease 语义产物**。
|
||||
// 平台版本是 prerelease(`0.1.5-rc.1`、子包 `0.1.5-rc.2`),而 semver 默认语义下
|
||||
// prerelease **不满足** `*`、`^0.1.2` 这类不含 prerelease 的范围 —— 于是
|
||||
// 「声明 `*`(= 任意版本)」会被判成不兼容。
|
||||
// 实测 2026-09-14(抽样 300,见 `04-调整方案/92`):
|
||||
// real-newer 3 | narrow-pin 22 | **prerelease-artifact 117** | match 98
|
||||
// ⇒ 若把这 117 也当"不兼容",闸门会有 ~39% 假阳性(`dshmarket`、`dsh-context`
|
||||
// 这些**在平台上跑得好好的**都会被拦)。所以:**只有 prerelease 容忍下也不满足,
|
||||
// 才算真不兼容**;容忍下能满足的只记一条 note(可观测,不阻断)。
|
||||
if (semver.satisfies(v, range, { includePrerelease: true })) {
|
||||
ok = true
|
||||
prereleaseOnly = true
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
continue // 范围写法无法解析:不据此断言
|
||||
}
|
||||
@@ -314,6 +328,9 @@ export async function checkPluginCompat(root: string): Promise<CompatResult> {
|
||||
pkg,
|
||||
detail: `平台为 ${v},插件要求 ${range}(不满足)`,
|
||||
})
|
||||
} else if (prereleaseOnly) {
|
||||
// 保持可观测:这一条是"按 pnpm 语义不满足、按 prerelease 容忍满足"的平台效应
|
||||
out.prereleaseOnly = (out.prereleaseOnly ?? 0) + 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user