diff --git a/extensions/elevenlabs/speech-provider.ts b/extensions/elevenlabs/speech-provider.ts index f01a908f283..0b1b8903c24 100644 --- a/extensions/elevenlabs/speech-provider.ts +++ b/extensions/elevenlabs/speech-provider.ts @@ -7,10 +7,12 @@ import type { SpeechVoiceOption, } from "openclaw/plugin-sdk/speech"; import { + asObject, normalizeApplyTextNormalization, normalizeLanguageCode, normalizeSeed, requireInRange, + trimToUndefined, } from "openclaw/plugin-sdk/speech"; import { resolveElevenLabsApiKeyWithProfileFallback } from "./config-api.js"; import { elevenLabsTTS } from "./tts.js"; @@ -49,10 +51,6 @@ type ElevenLabsProviderConfig = { }; }; -function trimToUndefined(value: unknown): string | undefined { - return typeof value === "string" && value.trim() ? value.trim() : undefined; -} - function asNumber(value: unknown): number | undefined { return typeof value === "number" && Number.isFinite(value) ? value : undefined; } @@ -61,12 +59,6 @@ function asBoolean(value: unknown): boolean | undefined { return typeof value === "boolean" ? value : undefined; } -function asObject(value: unknown): Record | undefined { - return typeof value === "object" && value !== null && !Array.isArray(value) - ? (value as Record) - : undefined; -} - function parseBooleanValue(value: string): boolean | undefined { const normalized = value.trim().toLowerCase(); if (["true", "1", "yes", "on"].includes(normalized)) { diff --git a/extensions/microsoft/speech-provider.ts b/extensions/microsoft/speech-provider.ts index 897dd902697..16f79051122 100644 --- a/extensions/microsoft/speech-provider.ts +++ b/extensions/microsoft/speech-provider.ts @@ -11,6 +11,7 @@ import type { SpeechProviderPlugin, SpeechVoiceOption, } from "openclaw/plugin-sdk/speech"; +import { asObject, trimToUndefined } from "openclaw/plugin-sdk/speech"; import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/temp-path"; import { edgeTTS, inferEdgeExtension } from "./tts.js"; @@ -43,10 +44,6 @@ type MicrosoftVoiceListEntry = { }; }; -function trimToUndefined(value: unknown): string | undefined { - return typeof value === "string" && value.trim() ? value.trim() : undefined; -} - function asBoolean(value: unknown): boolean | undefined { return typeof value === "boolean" ? value : undefined; } @@ -55,12 +52,6 @@ function asNumber(value: unknown): number | undefined { return typeof value === "number" && Number.isFinite(value) ? value : undefined; } -function asObject(value: unknown): Record | undefined { - return typeof value === "object" && value !== null && !Array.isArray(value) - ? (value as Record) - : undefined; -} - function normalizeMicrosoftProviderConfig( rawConfig: Record, ): MicrosoftProviderConfig { diff --git a/extensions/minimax/speech-provider.ts b/extensions/minimax/speech-provider.ts index 475f460f822..3cffdfba3a2 100644 --- a/extensions/minimax/speech-provider.ts +++ b/extensions/minimax/speech-provider.ts @@ -5,6 +5,7 @@ import type { SpeechProviderOverrides, SpeechProviderPlugin, } from "openclaw/plugin-sdk/speech-core"; +import { asObject, trimToUndefined } from "openclaw/plugin-sdk/speech-core"; import { DEFAULT_MINIMAX_TTS_BASE_URL, MINIMAX_TTS_MODELS, @@ -31,20 +32,10 @@ type MinimaxTtsProviderOverrides = { pitch?: number; }; -function trimToUndefined(value: unknown): string | undefined { - return typeof value === "string" && value.trim() ? value.trim() : undefined; -} - function asNumber(value: unknown): number | undefined { return typeof value === "number" && Number.isFinite(value) ? value : undefined; } -function asObject(value: unknown): Record | undefined { - return typeof value === "object" && value !== null && !Array.isArray(value) - ? (value as Record) - : undefined; -} - function normalizeMinimaxProviderConfig( rawConfig: Record, ): MinimaxTtsProviderConfig { diff --git a/extensions/vydra/speech-provider.ts b/extensions/vydra/speech-provider.ts index fe3c787f06e..a45f0ec68a3 100644 --- a/extensions/vydra/speech-provider.ts +++ b/extensions/vydra/speech-provider.ts @@ -9,6 +9,7 @@ import type { SpeechProviderOverrides, SpeechProviderPlugin, } from "openclaw/plugin-sdk/speech-core"; +import { asObject } from "openclaw/plugin-sdk/speech-core"; import { DEFAULT_VYDRA_BASE_URL, DEFAULT_VYDRA_SPEECH_MODEL, @@ -33,12 +34,6 @@ const VYDRA_SPEECH_VOICES = [ }, ] as const; -function asObject(value: unknown): Record | undefined { - return typeof value === "object" && value !== null && !Array.isArray(value) - ? (value as Record) - : undefined; -} - function normalizeVydraSpeechConfig(rawConfig: Record): VydraSpeechConfig { const providers = asObject(rawConfig.providers); const raw = asObject(providers?.vydra) ?? asObject(rawConfig.vydra); diff --git a/src/plugin-sdk/speech-core.ts b/src/plugin-sdk/speech-core.ts index 105495885d9..d10295d6f94 100644 --- a/src/plugin-sdk/speech-core.ts +++ b/src/plugin-sdk/speech-core.ts @@ -35,3 +35,9 @@ export { normalizeSpeechProviderId, } from "../tts/provider-registry.js"; export { normalizeTtsAutoMode, TTS_AUTO_MODES } from "../tts/tts-auto-mode.js"; +export { + asObject, + readResponseTextLimited, + trimToUndefined, + truncateErrorDetail, +} from "../tts/provider-error-utils.js";