fix(plugin-sdk): untangle tts runtime facade types

This commit is contained in:
Vincent Koc
2026-04-11 23:57:52 +01:00
parent 29142a9d47
commit 09a41b2da4
2 changed files with 188 additions and 12 deletions

View File

@@ -0,0 +1,2 @@
export type CreateReplyDispatcherWithTyping =
typeof import("./reply-dispatcher.js").createReplyDispatcherWithTyping;

View File

@@ -1,10 +1,152 @@
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/speech-core/runtime-api.js");
import type { ReplyPayload } from "../auto-reply/reply-payload.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import type { TtsAutoMode, TtsProvider } from "../config/types.tts.js";
import type {
SpeechProviderConfig,
SpeechVoiceOption,
TtsDirectiveOverrides,
TtsDirectiveParseResult,
} from "../tts/provider-types.js";
import type { ResolvedTtsConfig, ResolvedTtsModelOverrides } from "../tts/tts-types.js";
import {
createLazyFacadeObjectValue,
loadActivatedBundledPluginPublicSurfaceModuleSync,
} from "./facade-runtime.js";
// Manual facade. Keep loader boundary explicit and avoid typing this public SDK
// seam through the bundled speech-core runtime surface.
type TtsAttemptReasonCode =
| "success"
| "no_provider_registered"
| "not_configured"
| "unsupported_for_telephony"
| "timeout"
| "provider_error";
type TtsProviderAttempt = {
provider: string;
outcome: "success" | "skipped" | "failed";
reasonCode: TtsAttemptReasonCode;
latencyMs?: number;
error?: string;
};
type TtsStatusEntry = {
timestamp: number;
success: boolean;
textLength: number;
summarized: boolean;
provider?: string;
fallbackFrom?: string;
attemptedProviders?: string[];
attempts?: TtsProviderAttempt[];
latencyMs?: number;
error?: string;
};
type SummarizeResult = {
summary: string;
latencyMs: number;
inputLength: number;
outputLength: number;
};
type ResolveTtsAutoModeParams = {
config: ResolvedTtsConfig;
prefsPath: string;
sessionAuto?: string;
};
type ResolveExplicitTtsOverridesParams = {
cfg: OpenClawConfig;
prefsPath?: string;
provider?: string;
modelId?: string;
voiceId?: string;
};
type TtsRequestParams = {
text: string;
cfg: OpenClawConfig;
prefsPath?: string;
channel?: string;
overrides?: TtsDirectiveOverrides;
disableFallback?: boolean;
};
type TtsTelephonyRequestParams = {
text: string;
cfg: OpenClawConfig;
prefsPath?: string;
};
type ListSpeechVoicesParams = {
provider: string;
cfg?: OpenClawConfig;
config?: ResolvedTtsConfig;
apiKey?: string;
baseUrl?: string;
};
type MaybeApplyTtsToPayloadParams = {
payload: ReplyPayload;
cfg: OpenClawConfig;
channel?: string;
kind?: "tool" | "block" | "final";
inboundAudio?: boolean;
ttsAuto?: string;
};
type TtsTestFacade = {
parseTtsDirectives: (...args: unknown[]) => TtsDirectiveParseResult;
resolveModelOverridePolicy: (...args: unknown[]) => ResolvedTtsModelOverrides;
supportsNativeVoiceNoteTts: (channel: string | undefined) => boolean;
summarizeText: (...args: unknown[]) => Promise<SummarizeResult>;
getResolvedSpeechProviderConfig: (
config: ResolvedTtsConfig,
providerId: string,
cfg?: OpenClawConfig,
) => SpeechProviderConfig;
formatTtsProviderError: (provider: TtsProvider, err: unknown) => string;
sanitizeTtsErrorForLog: (err: unknown) => string;
};
type FacadeModule = {
_test: TtsTestFacade;
buildTtsSystemPromptHint: (cfg: OpenClawConfig) => string | undefined;
getLastTtsAttempt: () => TtsStatusEntry | undefined;
getResolvedSpeechProviderConfig: (
config: ResolvedTtsConfig,
providerId: string,
cfg?: OpenClawConfig,
) => SpeechProviderConfig;
getTtsMaxLength: (prefsPath: string) => number;
getTtsProvider: (config: ResolvedTtsConfig, prefsPath: string) => TtsProvider;
isSummarizationEnabled: (prefsPath: string) => boolean;
isTtsEnabled: (config: ResolvedTtsConfig, prefsPath: string, sessionAuto?: string) => boolean;
isTtsProviderConfigured: (
config: ResolvedTtsConfig,
provider: TtsProvider,
cfg?: OpenClawConfig,
) => boolean;
listSpeechVoices: (params: ListSpeechVoicesParams) => Promise<SpeechVoiceOption[]>;
maybeApplyTtsToPayload: (params: MaybeApplyTtsToPayloadParams) => Promise<ReplyPayload>;
resolveExplicitTtsOverrides: (params: ResolveExplicitTtsOverridesParams) => TtsDirectiveOverrides;
resolveTtsAutoMode: (params: ResolveTtsAutoModeParams) => TtsAutoMode;
resolveTtsConfig: (cfg: OpenClawConfig) => ResolvedTtsConfig;
resolveTtsPrefsPath: (config: ResolvedTtsConfig) => string;
resolveTtsProviderOrder: (primary: TtsProvider, cfg?: OpenClawConfig) => TtsProvider[];
setLastTtsAttempt: (entry: TtsStatusEntry | undefined) => void;
setSummarizationEnabled: (prefsPath: string, enabled: boolean) => void;
setTtsAutoMode: (prefsPath: string, mode: TtsAutoMode) => void;
setTtsEnabled: (prefsPath: string, enabled: boolean) => void;
setTtsMaxLength: (prefsPath: string, maxLength: number) => void;
setTtsProvider: (prefsPath: string, provider: TtsProvider) => void;
synthesizeSpeech: (params: TtsRequestParams) => Promise<TtsSynthesisResult>;
textToSpeech: (params: TtsRequestParams) => Promise<TtsResult>;
textToSpeechTelephony: (params: TtsTelephonyRequestParams) => Promise<TtsTelephonyResult>;
};
function loadFacadeModule(): FacadeModule {
return loadActivatedBundledPluginPublicSurfaceModuleSync<FacadeModule>({
dirName: "speech-core",
@@ -61,16 +203,48 @@ export const textToSpeech: FacadeModule["textToSpeech"] = createLazyFacadeValue(
export const textToSpeechTelephony: FacadeModule["textToSpeechTelephony"] =
createLazyFacadeValue("textToSpeechTelephony");
export type ResolvedTtsConfig = import("@openclaw/speech-core/runtime-api.js").ResolvedTtsConfig;
export type ResolvedTtsModelOverrides =
import("@openclaw/speech-core/runtime-api.js").ResolvedTtsModelOverrides;
export type TtsDirectiveOverrides =
import("@openclaw/speech-core/runtime-api.js").TtsDirectiveOverrides;
export type TtsDirectiveParseResult =
import("@openclaw/speech-core/runtime-api.js").TtsDirectiveParseResult;
export type TtsResult = import("@openclaw/speech-core/runtime-api.js").TtsResult;
export type TtsSynthesisResult = import("@openclaw/speech-core/runtime-api.js").TtsSynthesisResult;
export type TtsTelephonyResult = import("@openclaw/speech-core/runtime-api.js").TtsTelephonyResult;
export type { ResolvedTtsConfig, ResolvedTtsModelOverrides };
export type { TtsDirectiveOverrides, TtsDirectiveParseResult };
export type TtsResult = {
success: boolean;
audioPath?: string;
error?: string;
latencyMs?: number;
provider?: string;
fallbackFrom?: string;
attemptedProviders?: string[];
attempts?: TtsProviderAttempt[];
outputFormat?: string;
voiceCompatible?: boolean;
};
export type TtsSynthesisResult = {
success: boolean;
audioBuffer?: Buffer;
error?: string;
latencyMs?: number;
provider?: string;
fallbackFrom?: string;
attemptedProviders?: string[];
attempts?: TtsProviderAttempt[];
outputFormat?: string;
voiceCompatible?: boolean;
fileExtension?: string;
};
export type TtsTelephonyResult = {
success: boolean;
audioBuffer?: Buffer;
error?: string;
latencyMs?: number;
provider?: string;
fallbackFrom?: string;
attemptedProviders?: string[];
attempts?: TtsProviderAttempt[];
outputFormat?: string;
sampleRate?: number;
};
function createLazyFacadeValue<K extends keyof FacadeModule>(key: K): FacadeModule[K] {
return ((...args: unknown[]) => {