Skip to content

Commit 17dbf2b

Browse files
committed
fix: sanitize polluted profiles fields in openclaw config
1 parent 88d4c67 commit 17dbf2b

File tree

4 files changed

+380
-163
lines changed

4 files changed

+380
-163
lines changed

scripts/dev-api.js

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,16 +1146,31 @@ function getUid() {
11461146
}
11471147

11481148
function stripUiFields(config) {
1149+
if (!config || typeof config !== 'object' || Array.isArray(config)) return config
11491150
// 清理根层级 ClawPanel 内部字段(version info 等),避免污染 openclaw.json
11501151
// Issue #89: 这些字段被写入 openclaw.json 后导致 Gateway 无法启动(Unknown config keys)
11511152
const uiRootKeys = [
11521153
'current', 'latest', 'recommended', 'update_available',
11531154
'latest_update_available', 'is_recommended', 'ahead_of_recommended',
1154-
'panel_version', 'source',
1155+
'panel_version', 'source', 'qqbot', 'profiles',
11551156
]
11561157
for (const key of uiRootKeys) {
11571158
delete config[key]
11581159
}
1160+
if (config.auth && typeof config.auth === 'object' && !Array.isArray(config.auth)) {
1161+
delete config.auth.profiles
1162+
}
1163+
if (config.agents && typeof config.agents === 'object' && !Array.isArray(config.agents)) {
1164+
delete config.agents.profiles
1165+
if (Array.isArray(config.agents.list)) {
1166+
for (const agent of config.agents.list) {
1167+
if (!agent || typeof agent !== 'object' || Array.isArray(agent)) continue
1168+
delete agent.current
1169+
delete agent.latest
1170+
delete agent.update_available
1171+
}
1172+
}
1173+
}
11591174
// 清理模型测试相关的临时字段
11601175
const providers = config?.models?.providers
11611176
if (providers) {
@@ -1174,6 +1189,15 @@ function stripUiFields(config) {
11741189
return config
11751190
}
11761191

1192+
function cleanLoadedConfig(config) {
1193+
const before = JSON.stringify(config)
1194+
const cleaned = stripUiFields(config)
1195+
if (fs.existsSync(CONFIG_PATH) && JSON.stringify(cleaned) !== before) {
1196+
writeOpenclawConfigFile(cleaned)
1197+
}
1198+
return cleaned
1199+
}
1200+
11771201
// === Ed25519 设备密钥管理 ===
11781202

11791203
function getOrCreateDeviceKey() {
@@ -1287,7 +1311,6 @@ function calibrationRichnessScore(config) {
12871311
if (!config || typeof config !== 'object' || Array.isArray(config)) return 0
12881312
let score = 0
12891313
if (config.models?.providers && Object.keys(config.models.providers).length) score += 4
1290-
if (config.auth?.profiles && Object.keys(config.auth.profiles).length) score += 3
12911314
if (config.agents?.defaults) score += 2
12921315
if (Array.isArray(config.agents?.list) && config.agents.list.length) score += 3
12931316
if (config.channels && Object.keys(config.channels).length) score += 2
@@ -1316,7 +1339,6 @@ function buildCalibrationBaseline() {
13161339
$schema: 'https://openclaw.ai/schema/config.json',
13171340
meta: { lastTouchedVersion: calibrationLastTouchedVersion() },
13181341
models: { providers: {} },
1319-
auth: { profiles: {} },
13201342
agents: {
13211343
defaults: { workspace: calibrationDefaultWorkspace() },
13221344
list: [],
@@ -1382,9 +1404,6 @@ function normalizeCalibratedConfig(input) {
13821404
config.models = config.models && typeof config.models === 'object' && !Array.isArray(config.models) ? config.models : {}
13831405
config.models.providers = config.models.providers && typeof config.models.providers === 'object' && !Array.isArray(config.models.providers) ? config.models.providers : {}
13841406

1385-
config.auth = config.auth && typeof config.auth === 'object' && !Array.isArray(config.auth) ? config.auth : {}
1386-
config.auth.profiles = config.auth.profiles && typeof config.auth.profiles === 'object' && !Array.isArray(config.auth.profiles) ? config.auth.profiles : {}
1387-
13881407
config.agents = config.agents && typeof config.agents === 'object' && !Array.isArray(config.agents) ? config.agents : {}
13891408
config.agents.defaults = config.agents.defaults && typeof config.agents.defaults === 'object' && !Array.isArray(config.agents.defaults) ? config.agents.defaults : {}
13901409
if (!String(config.agents.defaults.workspace || '').trim()) config.agents.defaults.workspace = calibrationDefaultWorkspace()
@@ -1571,18 +1590,18 @@ function patchGatewayOrigins() {
15711590
if (!config.gateway) config.gateway = {}
15721591
if (!config.gateway.controlUi) config.gateway.controlUi = {}
15731592
config.gateway.controlUi.allowedOrigins = merged
1574-
fs.copyFileSync(CONFIG_PATH, CONFIG_PATH + '.bak')
1575-
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2))
1593+
writeOpenclawConfigFile(config)
15761594
return true
15771595
}
15781596

15791597
function readOpenclawConfigOptional() {
1580-
return fs.existsSync(CONFIG_PATH) ? JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8')) : {}
1598+
if (!fs.existsSync(CONFIG_PATH)) return {}
1599+
return cleanLoadedConfig(JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8')))
15811600
}
15821601

15831602
function readOpenclawConfigRequired() {
15841603
if (!fs.existsSync(CONFIG_PATH)) throw new Error('openclaw.json 不存在')
1585-
return JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'))
1604+
return cleanLoadedConfig(JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8')))
15861605
}
15871606

15881607
function mergeConfigsPreservingFields(existing, next) {
@@ -1601,8 +1620,9 @@ function mergeConfigsPreservingFields(existing, next) {
16011620
}
16021621

16031622
function writeOpenclawConfigFile(config) {
1623+
const cleaned = stripUiFields(config)
16041624
if (fs.existsSync(CONFIG_PATH)) fs.copyFileSync(CONFIG_PATH, CONFIG_PATH + '.bak')
1605-
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2))
1625+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(cleaned, null, 2))
16061626
}
16071627

16081628
function ensureAgentsList(config) {
@@ -2690,9 +2710,7 @@ function serverCached(key, ttlMs, fn) {
26902710
const handlers = {
26912711
// 配置读写
26922712
read_openclaw_config() {
2693-
if (!fs.existsSync(CONFIG_PATH)) throw new Error('openclaw.json 不存在,请先安装 OpenClaw')
2694-
const content = fs.readFileSync(CONFIG_PATH, 'utf8')
2695-
return JSON.parse(content)
2713+
return readOpenclawConfigRequired()
26962714
},
26972715

26982716
calibrate_openclaw_config({ mode } = {}) {
@@ -4837,7 +4855,7 @@ const handlers = {
48374855
const src = path.join(BACKUPS_DIR, name)
48384856
if (!fs.existsSync(src)) throw new Error('备份不存在')
48394857
if (fs.existsSync(CONFIG_PATH)) handlers.create_backup()
4840-
fs.copyFileSync(src, CONFIG_PATH)
4858+
writeOpenclawConfigFile(JSON.parse(fs.readFileSync(src, 'utf8')))
48414859
return true
48424860
},
48434861

@@ -4866,8 +4884,7 @@ const handlers = {
48664884
}
48674885
}
48684886
if (changed) {
4869-
fs.copyFileSync(CONFIG_PATH, CONFIG_PATH + '.bak')
4870-
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2))
4887+
writeOpenclawConfigFile(config)
48714888
}
48724889
return changed
48734890
},
@@ -5009,12 +5026,11 @@ const handlers = {
50095026
const backupPath = CONFIG_PATH + '.bak'
50105027
if (fs.existsSync(backupPath)) {
50115028
const backupContent = fs.readFileSync(backupPath, 'utf8')
5012-
JSON.parse(backupContent)
5013-
fs.writeFileSync(CONFIG_PATH, backupContent)
5029+
writeOpenclawConfigFile(JSON.parse(backupContent))
50145030
return { created: false, restored: true, message: '已从 openclaw.json.bak 恢复配置文件' }
50155031
}
50165032
const defaultConfig = stripUiFields(normalizeCalibratedConfig(buildCalibrationBaseline()))
5017-
fs.writeFileSync(CONFIG_PATH, JSON.stringify(defaultConfig, null, 2))
5033+
writeOpenclawConfigFile(defaultConfig)
50185034
return { created: true, restored: false, message: '配置文件已创建' }
50195035
},
50205036

0 commit comments

Comments
 (0)