@@ -1146,16 +1146,31 @@ function getUid() {
11461146}
11471147
11481148function 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
11791203function 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
15791597function 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
15831602function 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
15881607function mergeConfigsPreservingFields ( existing , next ) {
@@ -1601,8 +1620,9 @@ function mergeConfigsPreservingFields(existing, next) {
16011620}
16021621
16031622function 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
16081628function ensureAgentsList ( config ) {
@@ -2690,9 +2710,7 @@ function serverCached(key, ttlMs, fn) {
26902710const 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