@@ -14,6 +14,7 @@ import {
1414} from "../../../config/legacy.shared.js" ;
1515import { DEFAULT_GATEWAY_PORT } from "../../../config/paths.js" ;
1616import { isBlockedObjectKey } from "../../../config/prototype-keys.js" ;
17+ import { LEGACY_CONFIG_MIGRATIONS_RUNTIME_TTS } from "./legacy-config-migrations.runtime.tts.js" ;
1718import { migrateLegacyXSearchConfig } from "./legacy-x-search-migrate.js" ;
1819
1920const AGENT_HEARTBEAT_KEYS = new Set ( [
@@ -34,9 +35,6 @@ const AGENT_HEARTBEAT_KEYS = new Set([
3435] ) ;
3536
3637const CHANNEL_HEARTBEAT_KEYS = new Set ( [ "showOk" , "showAlerts" , "useIndicator" ] ) ;
37- const LEGACY_TTS_PROVIDER_KEYS = [ "openai" , "elevenlabs" , "microsoft" , "edge" ] as const ;
38- const LEGACY_TTS_PLUGIN_IDS = new Set ( [ "voice-call" ] ) ;
39-
4038function sandboxScopeFromPerSession ( perSession : boolean ) : "session" | "shared" {
4139 return perSession ? "session" : "shared" ;
4240}
@@ -131,14 +129,6 @@ function mergeLegacyIntoDefaults(params: {
131129 params . raw [ params . rootKey ] = root ;
132130}
133131
134- function hasLegacyTtsProviderKeys ( value : unknown ) : boolean {
135- const tts = getRecord ( value ) ;
136- if ( ! tts ) {
137- return false ;
138- }
139- return LEGACY_TTS_PROVIDER_KEYS . some ( ( key ) => Object . prototype . hasOwnProperty . call ( tts , key ) ) ;
140- }
141-
142132function hasLegacySandboxPerSession ( value : unknown ) : boolean {
143133 const sandbox = getRecord ( value ) ;
144134 return Boolean ( sandbox && Object . prototype . hasOwnProperty . call ( sandbox , "perSession" ) ) ;
@@ -150,72 +140,6 @@ function hasLegacyAgentListSandboxPerSession(value: unknown): boolean {
150140 }
151141 return value . some ( ( agent ) => hasLegacySandboxPerSession ( getRecord ( agent ) ?. sandbox ) ) ;
152142}
153- function hasLegacyPluginEntryTtsProviderKeys ( value : unknown ) : boolean {
154- const entries = getRecord ( value ) ;
155- if ( ! entries ) {
156- return false ;
157- }
158- return Object . entries ( entries ) . some ( ( [ pluginId , entryValue ] ) => {
159- if ( isBlockedObjectKey ( pluginId ) || ! LEGACY_TTS_PLUGIN_IDS . has ( pluginId ) ) {
160- return false ;
161- }
162- const entry = getRecord ( entryValue ) ;
163- const config = getRecord ( entry ?. config ) ;
164- return hasLegacyTtsProviderKeys ( config ?. tts ) ;
165- } ) ;
166- }
167-
168- function getOrCreateTtsProviders ( tts : Record < string , unknown > ) : Record < string , unknown > {
169- const providers = getRecord ( tts . providers ) ?? { } ;
170- tts . providers = providers ;
171- return providers ;
172- }
173-
174- function mergeLegacyTtsProviderConfig (
175- tts : Record < string , unknown > ,
176- legacyKey : string ,
177- providerId : string ,
178- ) : boolean {
179- const legacyValue = getRecord ( tts [ legacyKey ] ) ;
180- if ( ! legacyValue ) {
181- return false ;
182- }
183- const providers = getOrCreateTtsProviders ( tts ) ;
184- const existing = getRecord ( providers [ providerId ] ) ?? { } ;
185- const merged = structuredClone ( existing ) ;
186- mergeMissing ( merged , legacyValue ) ;
187- providers [ providerId ] = merged ;
188- delete tts [ legacyKey ] ;
189- return true ;
190- }
191-
192- function migrateLegacyTtsConfig (
193- tts : Record < string , unknown > | null | undefined ,
194- pathLabel : string ,
195- changes : string [ ] ,
196- ) : void {
197- if ( ! tts ) {
198- return ;
199- }
200- const movedOpenAI = mergeLegacyTtsProviderConfig ( tts , "openai" , "openai" ) ;
201- const movedElevenLabs = mergeLegacyTtsProviderConfig ( tts , "elevenlabs" , "elevenlabs" ) ;
202- const movedMicrosoft = mergeLegacyTtsProviderConfig ( tts , "microsoft" , "microsoft" ) ;
203- const movedEdge = mergeLegacyTtsProviderConfig ( tts , "edge" , "microsoft" ) ;
204-
205- if ( movedOpenAI ) {
206- changes . push ( `Moved ${ pathLabel } .openai → ${ pathLabel } .providers.openai.` ) ;
207- }
208- if ( movedElevenLabs ) {
209- changes . push ( `Moved ${ pathLabel } .elevenlabs → ${ pathLabel } .providers.elevenlabs.` ) ;
210- }
211- if ( movedMicrosoft ) {
212- changes . push ( `Moved ${ pathLabel } .microsoft → ${ pathLabel } .providers.microsoft.` ) ;
213- }
214- if ( movedEdge ) {
215- changes . push ( `Moved ${ pathLabel } .edge → ${ pathLabel } .providers.microsoft.` ) ;
216- }
217- }
218-
219143const MEMORY_SEARCH_RULE : LegacyConfigRule = {
220144 path : [ "memorySearch" ] ,
221145 message :
@@ -242,21 +166,6 @@ const X_SEARCH_RULE: LegacyConfigRule = {
242166 'tools.web.x_search.apiKey moved to the xAI plugin; use plugins.entries.xai.config.webSearch.apiKey instead. Run "openclaw doctor --fix".' ,
243167} ;
244168
245- const LEGACY_TTS_RULES : LegacyConfigRule [ ] = [
246- {
247- path : [ "messages" , "tts" ] ,
248- message :
249- 'messages.tts.<provider> keys (openai/elevenlabs/microsoft/edge) are legacy; use messages.tts.providers.<provider>. Run "openclaw doctor --fix".' ,
250- match : ( value ) => hasLegacyTtsProviderKeys ( value ) ,
251- } ,
252- {
253- path : [ "plugins" , "entries" ] ,
254- message :
255- 'plugins.entries.voice-call.config.tts.<provider> keys (openai/elevenlabs/microsoft/edge) are legacy; use plugins.entries.voice-call.config.tts.providers.<provider>. Run "openclaw doctor --fix".' ,
256- match : ( value ) => hasLegacyPluginEntryTtsProviderKeys ( value ) ,
257- } ,
258- ] ;
259-
260169const LEGACY_SANDBOX_SCOPE_RULES : LegacyConfigRule [ ] = [
261170 {
262171 path : [ "agents" , "defaults" , "sandbox" ] ,
@@ -447,33 +356,7 @@ export const LEGACY_CONFIG_MIGRATIONS_RUNTIME: LegacyConfigMigrationSpec[] = [
447356 changes . push ( `Normalized gateway.bind "${ escapeControlForLog ( bindRaw ) } " → "${ mapped } ".` ) ;
448357 } ,
449358 } ) ,
450- defineLegacyConfigMigration ( {
451- id : "tts.providers-generic-shape" ,
452- describe : "Move legacy bundled TTS config keys into messages.tts.providers" ,
453- legacyRules : LEGACY_TTS_RULES ,
454- apply : ( raw , changes ) => {
455- const messages = getRecord ( raw . messages ) ;
456- migrateLegacyTtsConfig ( getRecord ( messages ?. tts ) , "messages.tts" , changes ) ;
457-
458- const plugins = getRecord ( raw . plugins ) ;
459- const pluginEntries = getRecord ( plugins ?. entries ) ;
460- if ( ! pluginEntries ) {
461- return ;
462- }
463- for ( const [ pluginId , entryValue ] of Object . entries ( pluginEntries ) ) {
464- if ( isBlockedObjectKey ( pluginId ) || ! LEGACY_TTS_PLUGIN_IDS . has ( pluginId ) ) {
465- continue ;
466- }
467- const entry = getRecord ( entryValue ) ;
468- const config = getRecord ( entry ?. config ) ;
469- migrateLegacyTtsConfig (
470- getRecord ( config ?. tts ) ,
471- `plugins.entries.${ pluginId } .config.tts` ,
472- changes ,
473- ) ;
474- }
475- } ,
476- } ) ,
359+ ...LEGACY_CONFIG_MIGRATIONS_RUNTIME_TTS ,
477360 defineLegacyConfigMigration ( {
478361 id : "heartbeat->agents.defaults.heartbeat" ,
479362 describe : "Move top-level heartbeat to agents.defaults.heartbeat/channels.defaults.heartbeat" ,
0 commit comments