mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 04:47:03 -06:00
fix(doctor): stop repeating talk normalization
This commit is contained in:
@@ -2916,6 +2916,19 @@ describe("doctor config flow", () => {
|
||||
modelId: "eleven_v3",
|
||||
},
|
||||
},
|
||||
realtime: {
|
||||
provider: "openai",
|
||||
providers: {
|
||||
openai: {
|
||||
model: "gpt-realtime",
|
||||
},
|
||||
},
|
||||
model: "gpt-realtime",
|
||||
voice: "cedar",
|
||||
mode: "realtime",
|
||||
transport: "gateway-relay",
|
||||
brain: "agent-consult",
|
||||
},
|
||||
},
|
||||
},
|
||||
null,
|
||||
|
||||
@@ -1251,6 +1251,37 @@ describe("normalizeCompatibilityConfigValues", () => {
|
||||
expect(res.changes).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it("does not report talk provider normalization for realtime voice aliases", () => {
|
||||
const input = {
|
||||
talk: {
|
||||
provider: "elevenlabs",
|
||||
providers: {
|
||||
elevenlabs: {
|
||||
voiceId: "voice-123",
|
||||
},
|
||||
},
|
||||
realtime: {
|
||||
provider: "openai",
|
||||
providers: {
|
||||
openai: {
|
||||
model: "gpt-realtime",
|
||||
},
|
||||
},
|
||||
model: "gpt-realtime",
|
||||
voice: "cedar",
|
||||
mode: "realtime",
|
||||
transport: "gateway-relay",
|
||||
brain: "agent-consult",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const res = normalizeCompatibilityConfigValues(input as OpenClawConfig);
|
||||
|
||||
expect(res.config).toEqual(input);
|
||||
expect(res.changes).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it("migrates tools.message.allowCrossContextSend to canonical crossContext settings", () => {
|
||||
const res = normalizeCompatibilityConfigValues({
|
||||
tools: {
|
||||
|
||||
@@ -102,6 +102,38 @@ describe("legacy migrate provider-shaped config", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("does not treat an existing realtime voice alias as Talk provider repair", () => {
|
||||
const input: OpenClawConfig = {
|
||||
talk: {
|
||||
provider: "elevenlabs",
|
||||
providers: {
|
||||
elevenlabs: {
|
||||
voiceId: "voice-1",
|
||||
},
|
||||
},
|
||||
realtime: {
|
||||
provider: "openai",
|
||||
providers: {
|
||||
openai: {
|
||||
model: "gpt-realtime",
|
||||
},
|
||||
},
|
||||
model: "gpt-realtime",
|
||||
voice: "cedar",
|
||||
mode: "realtime",
|
||||
transport: "gateway-relay",
|
||||
brain: "agent-consult",
|
||||
},
|
||||
},
|
||||
};
|
||||
const changes: string[] = [];
|
||||
|
||||
const migrated = normalizeLegacyTalkConfig(input, changes);
|
||||
|
||||
expect(changes).toStrictEqual([]);
|
||||
expect(migrated).toEqual(input);
|
||||
});
|
||||
|
||||
it("moves messages.tts.<provider> keys into messages.tts.providers", () => {
|
||||
const res = migrateLegacyConfig({
|
||||
messages: {
|
||||
|
||||
@@ -41,6 +41,27 @@ function buildLegacyRealtimeTalkCompat(
|
||||
return normalizeTalkSection({ realtime: compat } as OpenClawConfig["talk"])?.realtime;
|
||||
}
|
||||
|
||||
function removeDerivedRealtimeSpeakerVoice(
|
||||
rawTalk: Record<string, unknown>,
|
||||
normalizedTalk: NonNullable<OpenClawConfig["talk"]>,
|
||||
): void {
|
||||
const rawRealtime = rawTalk.realtime;
|
||||
const normalizedRealtime = normalizedTalk.realtime;
|
||||
if (
|
||||
!isRecord(rawRealtime) ||
|
||||
!normalizedRealtime ||
|
||||
rawRealtime.speakerVoice !== undefined ||
|
||||
normalizedRealtime.speakerVoice === undefined ||
|
||||
normalizedRealtime.speakerVoice !== normalizedRealtime.voice
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Runtime clients still get speakerVoice from the deprecated voice alias, but
|
||||
// doctor should not persist that derived value or report it as provider repair.
|
||||
delete normalizedRealtime.speakerVoice;
|
||||
}
|
||||
|
||||
/** Normalize legacy Talk provider/realtime fields into current talk.providers and talk.realtime. */
|
||||
export function normalizeLegacyTalkConfig(cfg: OpenClawConfig, changes: string[]): OpenClawConfig {
|
||||
const rawTalk = cfg.talk;
|
||||
@@ -66,6 +87,7 @@ export function normalizeLegacyTalkConfig(cfg: OpenClawConfig, changes: string[]
|
||||
...normalizedTalk.realtime,
|
||||
};
|
||||
}
|
||||
removeDerivedRealtimeSpeakerVoice(rawTalk, normalizedTalk);
|
||||
if (Object.keys(normalizedTalk).length === 0 || isDeepStrictEqual(normalizedTalk, rawTalk)) {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user