mirror of
https://git.openapi.site/https://github.com/desirecore/config-center.git
synced 2026-09-05 17:33:40 +08:00
feat(compute): 补 GLM-5.3 系列规格并标注 Ox Alpha 真身 (#81)
* feat(compute): 补 GLM-5.3 系列规格并标注 Ox Alpha 真身 Ox Alpha 是智谱 GLM-5.3-Flash 的匿名发布别名(canonical_slug z-ai/glm-5.3-flash-20260826,2026-08-26 揭晓后已从 OpenRouter 列表下架)。 改动: - model-specs/zhipu.json 新增 glm-5.3 与 glm-5.3-flash 正式规格。两者均 强制思考(z.ai 文档:thinking.type 仅接受 enabled;OpenRouter models API: reasoning.mandatory=true,supported_efforts=[max,high,low]),故 routing.reasoning.supportedModes 不含 off。按 #79 的教训只用 exact 匹配, 避免 glm-5.3* 误吞 glm-5.3-flash。 - model-specs/stealth.json 的 ox-alpha 用 spec.extra.modelOrigin 标注真身。 条目保留:云端算力可能仍以旧别名下发该模型。 - schemas/model-spec.schema.json 为 extra.thinkingOnly / thinkingDefault 补正式定义与 description。此前这两个键无任何说明,客户端因此从未消费, 用户选「关闭思考」即触发上游 400(见 desirecore#2307)。 - scripts/validate.mjs 新增静默失效键名巡检:extra 是开放对象,写错键名 既不报错也无告警。当前巡出 17 处扁平 extra.reasoningEffort。刻意只告警 不失败——存量取值需逐个核实各自接入面实际接受哪些 effort。 * docs(schema): 写明 extra.reasoning 与 thinkingOnly 的职责边界 provider schema 的 extra.reasoning 此前只有子字段 description、对象本身没有, 维护者看不出它与 model-spec 的 thinkingOnly 分别回答什么问题——issue desirecore#2307 的误解正源于此。补上对象级说明:本键答「接入面接受哪些 effort 值」且只能写在 provider model;thinkingOnly 答「off 能不能用」、不声明深度档位。
This commit is contained in:
@@ -105,6 +105,62 @@ export function validateFile(absPath, validators = loadSchemas()) {
|
||||
return { ok: false, schemaKey, errors: validator.errors }
|
||||
}
|
||||
|
||||
/**
|
||||
* 已知会静默失效的 extra 键名。
|
||||
*
|
||||
* `extra` 是开放对象:写错键名既不会被 schema 拒绝,也没有任何运行时告警——数据看着
|
||||
* 在那儿,客户端却永远读不到。desirecore#2307 就是这么来的:model-spec 的
|
||||
* extra.thinkingOnly 写下后零消费,provider 侧另有 10 处扁平 extra.reasoningEffort
|
||||
* 同样从未生效,直到用户撞上一个上游 400 才暴露。
|
||||
*
|
||||
* 刻意只警告、不失败:存量条目的正确取值必须逐个核实各自接入面实际接受哪些 effort,
|
||||
* 一次批量改写的风险远大于收益(声明过窄会削掉模型能力,漏写 none 会让原本能关思考
|
||||
* 的模型失去该选项)。
|
||||
*/
|
||||
const SUSPICIOUS_EXTRA_KEYS = {
|
||||
provider: {
|
||||
reasoningEffort: '客户端只读嵌套的 extra.reasoning.supportedEfforts,扁平写法永不生效',
|
||||
defaultReasoningEffort: '同上,应并入 extra.reasoning.defaultEffort',
|
||||
},
|
||||
spec: {
|
||||
reasoningEffort: 'reasoning effort 是接入面能力,只能声明在 provider model 的 extra.reasoning 中',
|
||||
},
|
||||
}
|
||||
|
||||
/** 巡检静默失效键名,返回告警列表(不影响退出码)。 */
|
||||
function lintSuspiciousExtraKeys(targets) {
|
||||
const warnings = []
|
||||
for (const file of targets) {
|
||||
const rel = relative(ROOT, file)
|
||||
let data
|
||||
try {
|
||||
data = JSON.parse(readFileSync(file, 'utf8'))
|
||||
} catch {
|
||||
continue // 解析失败由 schema 校验负责报错
|
||||
}
|
||||
if (Array.isArray(data.models)) {
|
||||
for (const model of data.models) {
|
||||
for (const [key, hint] of Object.entries(SUSPICIOUS_EXTRA_KEYS.provider)) {
|
||||
if (model?.extra && Object.hasOwn(model.extra, key)) {
|
||||
warnings.push(`${rel} → models[${model.modelName}].extra.${key}:${hint}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Array.isArray(data.specs)) {
|
||||
for (const entry of data.specs) {
|
||||
const extra = entry?.spec?.extra
|
||||
for (const [key, hint] of Object.entries(SUSPICIOUS_EXTRA_KEYS.spec)) {
|
||||
if (extra && Object.hasOwn(extra, key)) {
|
||||
warnings.push(`${rel} → specs[${entry.id}].spec.extra.${key}:${hint}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return warnings
|
||||
}
|
||||
|
||||
function main() {
|
||||
const args = process.argv.slice(2)
|
||||
const fileArgIdx = args.indexOf('--file')
|
||||
@@ -143,6 +199,14 @@ function main() {
|
||||
}
|
||||
}
|
||||
|
||||
const warnings = lintSuspiciousExtraKeys(targets)
|
||||
if (warnings.length > 0) {
|
||||
console.log()
|
||||
console.log(`静默失效键名告警(${warnings.length} 处,不影响校验结果):`)
|
||||
for (const warning of warnings) console.log(` warn ${warning}`)
|
||||
console.log(' 这些键写在 extra 里不会报错,但客户端从不读取;修正前请逐个核实该接入面实际接受的 effort。')
|
||||
}
|
||||
|
||||
console.log()
|
||||
console.log(`Summary: ${validated} validated, ${skipped} skipped, ${failures} failed`)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user