fix(config): 全新安装的默认值播种判据改为显式标记

播种判据曾经是「config 表为空」。而发行包的 postinst 先跑 setup.sh →
initconfig,后者会写一行 webui.listen_addr,于是**全新安装**被判定为
"已有配置"并整体跳过播种:没有 core.plugin.dir(装完 0 个插件)、没有
core.memory.* 路径、也没有随包模型对应的多模态 provider——754MB 产物与
24MB 运行库全成死重量。同样的机制此前已在协议 2 迁移演练里被观察到。

也不能改成"每次都补缺键":老安装升级时被注进新默认值,会让它突然去加载
一个 1.8GB 的模型,那是刻意要避免的静默变重。

故改为显式标记 core.internal.seed_version:
  有标记                        → 已播种,返回
  无标记但有 core.daemon.data_dir → 老安装,只补标记、不播种
  两者都没有                    → 全新安装,播种并打标记

测试:TestSeedDefaultsAfterInitconfigPrepopulate(精确复现 initconfig 的
那一行写入)、TestSeedDefaultsDoesNotInjectIntoLegacyInstall。
This commit is contained in:
JianFeeeee
2026-09-12 08:10:34 +08:00
parent 6a3439a49c
commit 5299e18cd8
2 changed files with 85 additions and 3 deletions

View File

@ -482,9 +482,30 @@ func (r *ConfigRegistry) SeedDefaults(dataDir string) {
}
func (r *ConfigRegistry) seedDBValues(dataDir string) {
var count int
r.db.QueryRow(`SELECT COUNT(*) FROM config`).Scan(&count)
if count > 0 {
// 新鲜度判据不能是「config 表非空」。
//
// 发行包的 postinst 会先跑 setup.sh → initconfig,而 initconfig 会写一行
// webui.listen_addr。于是**全新安装**的 DB 看上去"已经有内容",整个默认值
// 播种被跳过:core.plugin.dir、core.memory.*、多模态 provider 一个都没写。
// 现场表现是装完 0 个插件、随包的模型与运行库成死重量。
//
// 也不能改成"每次都补缺键":老安装升级时被注进新默认值,会让它突然
// 去加载一个 1.8GB 的模型——那是刻意要避免的行为(静默变重)。
//
// 故用显式标记区分三种情形:
// 有标记 → 已经播过种,直接返回
// 无标记但有 core.daemon.data_dir → 老安装(本键历来由播种写入),
// 只补标记、不播种
// 两者都没有 → 全新安装,播种并打标记
const markerKey = "core.internal.seed_version"
var hasMarker, hasLegacy int
r.db.QueryRow(`SELECT COUNT(*) FROM config WHERE key = ?`, markerKey).Scan(&hasMarker)
if hasMarker > 0 {
return
}
r.db.QueryRow(`SELECT COUNT(*) FROM config WHERE key = 'core.daemon.data_dir'`).Scan(&hasLegacy)
if hasLegacy > 0 {
r.db.Exec(`INSERT OR IGNORE INTO config (key, value) VALUES (?, ?)`, markerKey, "1")
return
}
@ -604,6 +625,8 @@ WebUI 概览页展示你的立绘,可通过 /mascot.webp 直接访问。如输
set("core.input_processing.audio.fallback_model", "")
set("core.input_processing.audio.describe_prompt", "请转写这段音频的内容。")
set(markerKey, "1")
tx.Commit()
}