






























@@ -44,6 +44,57 @@ function hasLegacyPluginEntryTtsProviderKeys(value: unknown): boolean {
4444});
4545}
464647+function hasLegacyTtsEnabled(value: unknown): boolean {
48+return typeof getRecord(value)?.enabled === "boolean";
49+}
50+51+function hasLegacyTtsEnabledInAgentLocations(value: unknown): boolean {
52+const agents = getRecord(value);
53+if (hasLegacyTtsEnabled(getRecord(getRecord(agents?.defaults)?.tts))) {
54+return true;
55+}
56+const agentList = Array.isArray(agents?.list) ? agents.list : [];
57+return agentList.some((entry) => hasLegacyTtsEnabled(getRecord(getRecord(entry)?.tts)));
58+}
59+60+function hasLegacyTtsEnabledInChannelLocations(value: unknown): boolean {
61+const channels = getRecord(value);
62+for (const [channelId, channelValue] of Object.entries(channels ?? {})) {
63+if (isBlockedObjectKey(channelId)) {
64+continue;
65+}
66+const channel = getRecord(channelValue);
67+if (hasLegacyTtsEnabled(getRecord(channel?.tts))) {
68+return true;
69+}
70+const accounts = getRecord(channel?.accounts);
71+for (const [accountId, accountValue] of Object.entries(accounts ?? {})) {
72+if (isBlockedObjectKey(accountId)) {
73+continue;
74+}
75+if (hasLegacyTtsEnabled(getRecord(getRecord(accountValue)?.tts))) {
76+return true;
77+}
78+}
79+}
80+return false;
81+}
82+83+function hasLegacyTtsEnabledInPluginLocations(value: unknown): boolean {
84+const entries = getRecord(value);
85+if (!entries) {
86+return false;
87+}
88+return Object.entries(entries).some(([pluginId, entryValue]) => {
89+if (isBlockedObjectKey(pluginId) || !LEGACY_TTS_PLUGIN_IDS.has(pluginId)) {
90+return false;
91+}
92+const entry = getRecord(entryValue);
93+const config = getRecord(entry?.config);
94+return hasLegacyTtsEnabled(getRecord(config?.tts));
95+});
96+}
97+4798function getOrCreateTtsProviders(tts: Record<string, unknown>): Record<string, unknown> {
4899const providers = getRecord(tts.providers) ?? {};
49100tts.providers = providers;
@@ -121,7 +172,73 @@ function migrateLegacyTtsConfig(
121172}
122173}
123174124-const LEGACY_TTS_RULES: LegacyConfigRule[] = [
175+function migrateLegacyTtsEnabled(
176+tts: Record<string, unknown> | null | undefined,
177+pathLabel: string,
178+changes: string[],
179+): void {
180+if (!tts || typeof tts.enabled !== "boolean") {
181+return;
182+}
183+const nextAuto = tts.enabled ? "always" : "off";
184+delete tts.enabled;
185+if (typeof tts.auto === "string" && tts.auto.trim()) {
186+changes.push(`Removed ${pathLabel}.enabled because ${pathLabel}.auto is already set.`);
187+return;
188+}
189+tts.auto = nextAuto;
190+changes.push(`Moved ${pathLabel}.enabled → ${pathLabel}.auto "${nextAuto}".`);
191+}
192+193+function visitKnownTtsConfigLocations(
194+raw: Record<string, unknown>,
195+visit: (tts: Record<string, unknown> | null | undefined, pathLabel: string) => void,
196+): void {
197+const messages = getRecord(raw.messages);
198+visit(getRecord(messages?.tts), "messages.tts");
199+200+const agents = getRecord(raw.agents);
201+const agentDefaults = getRecord(agents?.defaults);
202+visit(getRecord(agentDefaults?.tts), "agents.defaults.tts");
203+204+const agentList = Array.isArray(agents?.list) ? agents.list : [];
205+agentList.forEach((entry, index) => {
206+const agent = getRecord(entry);
207+visit(getRecord(agent?.tts), `agents.list[${index}].tts`);
208+});
209+210+const channels = getRecord(raw.channels);
211+for (const [channelId, channelValue] of Object.entries(channels ?? {})) {
212+if (isBlockedObjectKey(channelId)) {
213+continue;
214+}
215+const channel = getRecord(channelValue);
216+visit(getRecord(channel?.tts), `channels.${channelId}.tts`);
217+const accounts = getRecord(channel?.accounts);
218+for (const [accountId, accountValue] of Object.entries(accounts ?? {})) {
219+if (isBlockedObjectKey(accountId)) {
220+continue;
221+}
222+visit(
223+getRecord(getRecord(accountValue)?.tts),
224+`channels.${channelId}.accounts.${accountId}.tts`,
225+);
226+}
227+}
228+229+const plugins = getRecord(raw.plugins);
230+const pluginEntries = getRecord(plugins?.entries);
231+for (const [pluginId, entryValue] of Object.entries(pluginEntries ?? {})) {
232+if (isBlockedObjectKey(pluginId) || !LEGACY_TTS_PLUGIN_IDS.has(pluginId)) {
233+continue;
234+}
235+const entry = getRecord(entryValue);
236+const config = getRecord(entry?.config);
237+visit(getRecord(config?.tts), `plugins.entries.${pluginId}.config.tts`);
238+}
239+}
240+241+const LEGACY_TTS_PROVIDER_RULES: LegacyConfigRule[] = [
125242{
126243path: ["messages", "tts"],
127244message:
@@ -136,11 +253,36 @@ const LEGACY_TTS_RULES: LegacyConfigRule[] = [
136253},
137254];
138255256+const LEGACY_TTS_ENABLED_RULES: LegacyConfigRule[] = [
257+{
258+path: ["messages", "tts"],
259+message: 'messages.tts.enabled is legacy; use messages.tts.auto. Run "openclaw doctor --fix".',
260+match: (value) => hasLegacyTtsEnabled(value),
261+},
262+{
263+path: ["agents"],
264+message: 'agents.*.tts.enabled is legacy; use agents.*.tts.auto. Run "openclaw doctor --fix".',
265+match: (value) => hasLegacyTtsEnabledInAgentLocations(value),
266+},
267+{
268+path: ["channels"],
269+message:
270+'channels.*.tts.enabled is legacy; use channels.*.tts.auto. Run "openclaw doctor --fix".',
271+match: (value) => hasLegacyTtsEnabledInChannelLocations(value),
272+},
273+{
274+path: ["plugins", "entries"],
275+message:
276+'plugins.entries.voice-call.config.tts.enabled is legacy; use plugins.entries.voice-call.config.tts.auto. Run "openclaw doctor --fix".',
277+match: (value) => hasLegacyTtsEnabledInPluginLocations(value),
278+},
279+];
280+139281export const LEGACY_CONFIG_MIGRATIONS_RUNTIME_TTS: LegacyConfigMigrationSpec[] = [
140282defineLegacyConfigMigration({
141283id: "tts.providers-generic-shape",
142284describe: "Move legacy bundled TTS config keys into messages.tts.providers",
143-legacyRules: LEGACY_TTS_RULES,
285+legacyRules: LEGACY_TTS_PROVIDER_RULES,
144286apply: (raw, changes) => {
145287const messages = getRecord(raw.messages);
146288migrateLegacyTtsConfig(getRecord(messages?.tts), "messages.tts", changes);
@@ -164,4 +306,14 @@ export const LEGACY_CONFIG_MIGRATIONS_RUNTIME_TTS: LegacyConfigMigrationSpec[] =
164306}
165307},
166308}),
309+defineLegacyConfigMigration({
310+id: "tts.enabled-auto-mode",
311+describe: "Move legacy TTS enabled toggles to auto mode",
312+legacyRules: LEGACY_TTS_ENABLED_RULES,
313+apply: (raw, changes) => {
314+visitKnownTtsConfigLocations(raw, (tts, pathLabel) =>
315+migrateLegacyTtsEnabled(tts, pathLabel, changes),
316+);
317+},
318+}),
167319];
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。