[codex] add locked file updates for config writes (#785)

* add locked file updates for config writes

* add glm vision turbo preset
This commit is contained in:
ekko
2026-05-16 13:11:59 +08:00
committed by GitHub
parent 217b721648
commit 67723d9315
16 changed files with 822 additions and 314 deletions
@@ -1,9 +1,9 @@
import { readFile, writeFile, copyFile } from 'fs/promises'
import YAML from 'js-yaml'
import { readFile } from 'fs/promises'
import { getGatewayManagerInstance } from '../../services/gateway-bootstrap'
import { getActiveConfigPath, getActiveEnvPath } from '../../services/hermes/hermes-profile'
import { saveEnvValue } from '../../services/config-helpers'
import { logger } from '../../services/logger'
import { safeFileStore } from '../../services/safe-file-store'
const PLATFORM_SECTIONS = new Set([
'telegram', 'discord', 'slack', 'whatsapp', 'matrix',
@@ -90,20 +90,7 @@ async function readEnvPlatforms(): Promise<Record<string, any>> {
}
async function readConfig(): Promise<Record<string, any>> {
const raw = await readFile(configPath(), 'utf-8')
return (YAML.load(raw, { json: true }) as Record<string, any>) || {}
}
async function writeConfig(data: Record<string, any>): Promise<void> {
const cp = configPath()
await copyFile(cp, cp + '.bak')
const yamlStr = YAML.dump(data, {
lineWidth: -1,
noRefs: true,
quotingType: '"',
forceQuotes: true, // Force quotes on all string values
})
await writeFile(cp, yamlStr, 'utf-8')
return safeFileStore.readYaml(configPath())
}
export async function getConfig(ctx: any) {
@@ -139,9 +126,15 @@ export async function updateConfig(ctx: any) {
ctx.status = 400; ctx.body = { error: 'Missing section or values' }; return
}
try {
const config = await readConfig()
config[section] = deepMerge(config[section] || {}, values)
await writeConfig(config)
await safeFileStore.updateYaml(configPath(), (config) => {
config[section] = deepMerge(config[section] || {}, values)
return config
}, {
backup: true,
dumpOptions: {
forceQuotes: true,
},
})
// 使用 GatewayManager 重启平台网关
if (PLATFORM_SECTIONS.has(section)) {
@@ -173,37 +166,41 @@ export async function updateCredentials(ctx: any) {
if (!envMap) {
ctx.status = 400; ctx.body = { error: `Unknown platform: ${platform}` }; return
}
const config = await readConfig()
let configChanged = false
const flatValues: Record<string, any> = {}
for (const [key, val] of Object.entries(values)) {
if (key === 'extra' && val && typeof val === 'object') {
for (const [subKey, subVal] of Object.entries(val as Record<string, any>)) { flatValues[`extra.${subKey}`] = subVal }
} else { flatValues[key] = val }
}
for (const [cfgPath, val] of Object.entries(flatValues)) {
const envVar = envMap[cfgPath]
if (!envVar) continue
if (val === undefined || val === null || val === '') {
await saveEnvValue(envVar, '')
const parts = cfgPath.split('.')
let obj: any = config.platforms?.[platform]
if (obj) {
if (parts.length === 1) { delete obj[parts[0]] }
else {
let cur = obj
for (let i = 0; i < parts.length - 1; i++) { if (!cur[parts[i]]) break; cur = cur[parts[i]] }
delete cur[parts[parts.length - 1]]
if (obj.extra && Object.keys(obj.extra).length === 0) delete obj.extra
await safeFileStore.updateYaml(configPath(), async (config) => {
for (const [cfgPath, val] of Object.entries(flatValues)) {
const envVar = envMap[cfgPath]
if (!envVar) continue
if (val === undefined || val === null || val === '') {
await saveEnvValue(envVar, '')
const parts = cfgPath.split('.')
let obj: any = config.platforms?.[platform]
if (obj) {
if (parts.length === 1) { delete obj[parts[0]] }
else {
let cur = obj
for (let i = 0; i < parts.length - 1; i++) { if (!cur[parts[i]]) break; cur = cur[parts[i]] }
delete cur[parts[parts.length - 1]]
if (obj.extra && Object.keys(obj.extra).length === 0) delete obj.extra
}
if (Object.keys(obj).length === 0) { if (!config.platforms) config.platforms = {}; delete config.platforms[platform] }
}
if (Object.keys(obj).length === 0) { if (!config.platforms) config.platforms = {}; delete config.platforms[platform] }
configChanged = true
} else {
await saveEnvValue(envVar, String(val))
}
} else {
await saveEnvValue(envVar, String(val))
}
}
if (configChanged) { await writeConfig(config) }
return config
}, {
backup: true,
dumpOptions: {
forceQuotes: true,
},
})
// 使用 GatewayManager 重启平台网关
const mgr = getGatewayManagerInstance()