mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-26 00:49:30 +00:00
fix(ui): correct rounding boundary comment from 999,500 to 999,950
This commit is contained in:
@@ -8,6 +8,7 @@ import type {
|
||||
SpeechProviderConfig,
|
||||
SpeechProviderOverrides,
|
||||
SpeechProviderPlugin,
|
||||
SpeechSynthesisRequest,
|
||||
SpeechVoiceOption,
|
||||
} from "openclaw/plugin-sdk/speech";
|
||||
import {
|
||||
@@ -389,6 +390,40 @@ async function listElevenLabsVoices(params: {
|
||||
}
|
||||
}
|
||||
|
||||
type ElevenLabsSynthesisRequest = Pick<
|
||||
SpeechSynthesisRequest,
|
||||
"providerConfig" | "providerOverrides" | "text" | "timeoutMs"
|
||||
>;
|
||||
|
||||
function resolveElevenLabsTtsRequest(
|
||||
req: ElevenLabsSynthesisRequest,
|
||||
options: Pick<Parameters<typeof elevenLabsTTS>[0], "outputFormat" | "latencyTier">,
|
||||
): Parameters<typeof elevenLabsTTS>[0] {
|
||||
const config = readElevenLabsProviderConfig(req.providerConfig);
|
||||
const overrides = req.providerOverrides ?? {};
|
||||
const apiKey =
|
||||
config.apiKey || resolveElevenLabsApiKeyWithProfileFallback() || process.env.XI_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("ElevenLabs API key missing");
|
||||
}
|
||||
return {
|
||||
text: req.text,
|
||||
apiKey,
|
||||
baseUrl: config.baseUrl,
|
||||
voiceId: trimToUndefined(overrides.voiceId) ?? config.voiceId,
|
||||
modelId: normalizeElevenLabsTtsModelId(trimToUndefined(overrides.modelId)) ?? config.modelId,
|
||||
outputFormat: options.outputFormat,
|
||||
seed: normalizeElevenLabsSeed(overrides.seed) ?? config.seed,
|
||||
applyTextNormalization:
|
||||
(trimToUndefined(overrides.applyTextNormalization) as "auto" | "on" | "off" | undefined) ??
|
||||
config.applyTextNormalization,
|
||||
languageCode: trimToUndefined(overrides.languageCode) ?? config.languageCode,
|
||||
latencyTier: options.latencyTier,
|
||||
voiceSettings: resolveVoiceSettingsOverride(config.voiceSettings, overrides.voiceSettings),
|
||||
timeoutMs: req.timeoutMs,
|
||||
};
|
||||
}
|
||||
|
||||
export function buildElevenLabsSpeechProvider(): SpeechProviderPlugin {
|
||||
return {
|
||||
id: "elevenlabs",
|
||||
@@ -509,37 +544,16 @@ export function buildElevenLabsSpeechProvider(): SpeechProviderPlugin {
|
||||
process.env.XI_API_KEY,
|
||||
),
|
||||
synthesize: async (req) => {
|
||||
const config = readElevenLabsProviderConfig(req.providerConfig);
|
||||
const overrides = req.providerOverrides ?? {};
|
||||
const apiKey =
|
||||
config.apiKey || resolveElevenLabsApiKeyWithProfileFallback() || process.env.XI_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("ElevenLabs API key missing");
|
||||
}
|
||||
const outputFormat =
|
||||
trimToUndefined(overrides.outputFormat) ??
|
||||
(req.target === "voice-note" ? "opus_48000_64" : "mp3_44100_128");
|
||||
const latencyTier = normalizeElevenLabsLatencyTier(overrides.latencyTier);
|
||||
const audioBuffer = await elevenLabsTTS({
|
||||
text: req.text,
|
||||
apiKey,
|
||||
baseUrl: config.baseUrl,
|
||||
voiceId: trimToUndefined(overrides.voiceId) ?? config.voiceId,
|
||||
modelId:
|
||||
normalizeElevenLabsTtsModelId(trimToUndefined(overrides.modelId)) ?? config.modelId,
|
||||
outputFormat,
|
||||
seed: normalizeElevenLabsSeed(overrides.seed) ?? config.seed,
|
||||
applyTextNormalization:
|
||||
(trimToUndefined(overrides.applyTextNormalization) as
|
||||
| "auto"
|
||||
| "on"
|
||||
| "off"
|
||||
| undefined) ?? config.applyTextNormalization,
|
||||
languageCode: trimToUndefined(overrides.languageCode) ?? config.languageCode,
|
||||
latencyTier,
|
||||
voiceSettings: resolveVoiceSettingsOverride(config.voiceSettings, overrides.voiceSettings),
|
||||
timeoutMs: req.timeoutMs,
|
||||
});
|
||||
const audioBuffer = await elevenLabsTTS(
|
||||
resolveElevenLabsTtsRequest(req, {
|
||||
outputFormat,
|
||||
latencyTier: normalizeElevenLabsLatencyTier(overrides.latencyTier),
|
||||
}),
|
||||
);
|
||||
return {
|
||||
audioBuffer,
|
||||
outputFormat,
|
||||
@@ -548,37 +562,16 @@ export function buildElevenLabsSpeechProvider(): SpeechProviderPlugin {
|
||||
};
|
||||
},
|
||||
streamSynthesize: async (req) => {
|
||||
const config = readElevenLabsProviderConfig(req.providerConfig);
|
||||
const overrides = req.providerOverrides ?? {};
|
||||
const apiKey =
|
||||
config.apiKey || resolveElevenLabsApiKeyWithProfileFallback() || process.env.XI_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("ElevenLabs API key missing");
|
||||
}
|
||||
const outputFormat =
|
||||
trimToUndefined(overrides.outputFormat) ??
|
||||
(req.target === "voice-note" ? "opus_48000_64" : "mp3_44100_128");
|
||||
const latencyTier = normalizeElevenLabsLatencyTier(overrides.latencyTier);
|
||||
const stream = await elevenLabsTTSStream({
|
||||
text: req.text,
|
||||
apiKey,
|
||||
baseUrl: config.baseUrl,
|
||||
voiceId: trimToUndefined(overrides.voiceId) ?? config.voiceId,
|
||||
modelId:
|
||||
normalizeElevenLabsTtsModelId(trimToUndefined(overrides.modelId)) ?? config.modelId,
|
||||
outputFormat,
|
||||
seed: normalizeElevenLabsSeed(overrides.seed) ?? config.seed,
|
||||
applyTextNormalization:
|
||||
(trimToUndefined(overrides.applyTextNormalization) as
|
||||
| "auto"
|
||||
| "on"
|
||||
| "off"
|
||||
| undefined) ?? config.applyTextNormalization,
|
||||
languageCode: trimToUndefined(overrides.languageCode) ?? config.languageCode,
|
||||
latencyTier,
|
||||
voiceSettings: resolveVoiceSettingsOverride(config.voiceSettings, overrides.voiceSettings),
|
||||
timeoutMs: req.timeoutMs,
|
||||
});
|
||||
const stream = await elevenLabsTTSStream(
|
||||
resolveElevenLabsTtsRequest(req, {
|
||||
outputFormat,
|
||||
latencyTier: normalizeElevenLabsLatencyTier(overrides.latencyTier),
|
||||
}),
|
||||
);
|
||||
return {
|
||||
audioStream: stream.audioStream,
|
||||
outputFormat,
|
||||
@@ -588,34 +581,9 @@ export function buildElevenLabsSpeechProvider(): SpeechProviderPlugin {
|
||||
};
|
||||
},
|
||||
synthesizeTelephony: async (req) => {
|
||||
const config = readElevenLabsProviderConfig(req.providerConfig);
|
||||
const overrides = req.providerOverrides ?? {};
|
||||
const apiKey =
|
||||
config.apiKey || resolveElevenLabsApiKeyWithProfileFallback() || process.env.XI_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("ElevenLabs API key missing");
|
||||
}
|
||||
const outputFormat = "pcm_22050";
|
||||
const sampleRate = 22_050;
|
||||
const audioBuffer = await elevenLabsTTS({
|
||||
text: req.text,
|
||||
apiKey,
|
||||
baseUrl: config.baseUrl,
|
||||
voiceId: trimToUndefined(overrides.voiceId) ?? config.voiceId,
|
||||
modelId:
|
||||
normalizeElevenLabsTtsModelId(trimToUndefined(overrides.modelId)) ?? config.modelId,
|
||||
outputFormat,
|
||||
seed: normalizeElevenLabsSeed(overrides.seed) ?? config.seed,
|
||||
applyTextNormalization:
|
||||
(trimToUndefined(overrides.applyTextNormalization) as
|
||||
| "auto"
|
||||
| "on"
|
||||
| "off"
|
||||
| undefined) ?? config.applyTextNormalization,
|
||||
languageCode: trimToUndefined(overrides.languageCode) ?? config.languageCode,
|
||||
voiceSettings: resolveVoiceSettingsOverride(config.voiceSettings, overrides.voiceSettings),
|
||||
timeoutMs: req.timeoutMs,
|
||||
});
|
||||
const audioBuffer = await elevenLabsTTS(resolveElevenLabsTtsRequest(req, { outputFormat }));
|
||||
return { audioBuffer, outputFormat, sampleRate };
|
||||
},
|
||||
};
|
||||
|
||||
@@ -34,7 +34,10 @@ import {
|
||||
} from "../../infra/outbound/channel-target-prefix.js";
|
||||
import { isSubagentSessionKey } from "../../routing/session-key.js";
|
||||
import { parseAgentSessionKey } from "../../sessions/session-key-utils.js";
|
||||
import { normalizeMessageChannel } from "../../utils/message-channel.js";
|
||||
import {
|
||||
isDeliverableMessageChannel,
|
||||
normalizeMessageChannel,
|
||||
} from "../../utils/message-channel.js";
|
||||
import type { GatewayRequestHandlers, RespondFn } from "./types.js";
|
||||
|
||||
type CronJobIdParams = { id?: string; jobId?: string };
|
||||
@@ -67,6 +70,22 @@ async function listConfiguredAnnounceChannelIds(cfg: OpenClawConfig): Promise<st
|
||||
return await listConfiguredMessageChannels(cfg);
|
||||
}
|
||||
|
||||
function hasExplicitChannelConfigEntry(cfg: OpenClawConfig): boolean {
|
||||
const channels = cfg.channels;
|
||||
if (!channels || typeof channels !== "object" || Array.isArray(channels)) {
|
||||
return false;
|
||||
}
|
||||
return Object.entries(channels).some(([channelId, entry]) => {
|
||||
if (channelId === "defaults" || channelId === "modelByChannel") {
|
||||
return false;
|
||||
}
|
||||
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
||||
return false;
|
||||
}
|
||||
return Object.keys(entry).length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
async function assertConfiguredAnnounceChannel(params: {
|
||||
cfg: OpenClawConfig;
|
||||
channel?: string;
|
||||
@@ -90,6 +109,12 @@ async function assertConfiguredAnnounceChannel(params: {
|
||||
}
|
||||
|
||||
if (configuredChannels.length === 0) {
|
||||
if (!hasExplicitChannelConfigEntry(params.cfg)) {
|
||||
if (!isDeliverableMessageChannel(normalizedChannel)) {
|
||||
throw new Error(`${params.field} is not a known channel: ${normalizedChannel}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
throw new Error(`${params.field} is not configured: ${normalizedChannel}`);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user