mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:00:42 +00:00
refactor: share speech provider helpers
This commit is contained in:
@@ -1,6 +1,3 @@
|
||||
import { rmSync } from "node:fs";
|
||||
import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";
|
||||
|
||||
// Public speech helpers for bundled or third-party plugins.
|
||||
//
|
||||
// Keep this surface provider-facing: types, validation, directive parsing, and
|
||||
@@ -42,60 +39,10 @@ export {
|
||||
trimToUndefined,
|
||||
truncateErrorDetail,
|
||||
} from "../tts/provider-error-utils.js";
|
||||
|
||||
const TEMP_FILE_CLEANUP_DELAY_MS = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
export function requireInRange(value: number, min: number, max: number, label: string): void {
|
||||
if (!Number.isFinite(value) || value < min || value > max) {
|
||||
throw new Error(`${label} must be between ${min} and ${max}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeLanguageCode(code?: string): string | undefined {
|
||||
const trimmed = code?.trim();
|
||||
if (!trimmed) {
|
||||
return undefined;
|
||||
}
|
||||
const normalized = normalizeLowercaseStringOrEmpty(trimmed);
|
||||
if (!/^[a-z]{2}$/.test(normalized)) {
|
||||
throw new Error("languageCode must be a 2-letter ISO 639-1 code (e.g. en, de, fr)");
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export function normalizeApplyTextNormalization(mode?: string): "auto" | "on" | "off" | undefined {
|
||||
const trimmed = mode?.trim();
|
||||
if (!trimmed) {
|
||||
return undefined;
|
||||
}
|
||||
const normalized = normalizeLowercaseStringOrEmpty(trimmed);
|
||||
if (normalized === "auto" || normalized === "on" || normalized === "off") {
|
||||
return normalized;
|
||||
}
|
||||
throw new Error("applyTextNormalization must be one of: auto, on, off");
|
||||
}
|
||||
|
||||
export function normalizeSeed(seed?: number): number | undefined {
|
||||
if (seed == null) {
|
||||
return undefined;
|
||||
}
|
||||
const next = Math.floor(seed);
|
||||
if (!Number.isFinite(next) || next < 0 || next > 4_294_967_295) {
|
||||
throw new Error("seed must be between 0 and 4294967295");
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
export function scheduleCleanup(
|
||||
tempDir: string,
|
||||
delayMs: number = TEMP_FILE_CLEANUP_DELAY_MS,
|
||||
): void {
|
||||
const timer = setTimeout(() => {
|
||||
try {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
} catch {
|
||||
// ignore cleanup errors
|
||||
}
|
||||
}, delayMs);
|
||||
timer.unref();
|
||||
}
|
||||
export {
|
||||
normalizeApplyTextNormalization,
|
||||
normalizeLanguageCode,
|
||||
normalizeSeed,
|
||||
requireInRange,
|
||||
scheduleCleanup,
|
||||
} from "../tts/tts-provider-helpers.js";
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { rmSync } from "node:fs";
|
||||
import { completeSimple, type TextContent } from "@mariozechner/pi-ai";
|
||||
import { getApiKeyForModel, requireApiKey } from "../agents/model-auth.js";
|
||||
import {
|
||||
@@ -10,13 +9,15 @@ import {
|
||||
import { resolveModelAsync } from "../agents/pi-embedded-runner/model.js";
|
||||
import { prepareModelForSimpleCompletion } from "../agents/simple-completion-transport.js";
|
||||
import type { OpenClawConfig } from "../config/types.js";
|
||||
import {
|
||||
normalizeOptionalLowercaseString,
|
||||
normalizeOptionalString,
|
||||
} from "../shared/string-coerce.js";
|
||||
import { normalizeOptionalString } from "../shared/string-coerce.js";
|
||||
import type { ResolvedTtsConfig } from "./tts-types.js";
|
||||
|
||||
const TEMP_FILE_CLEANUP_DELAY_MS = 5 * 60 * 1000; // 5 minutes
|
||||
export {
|
||||
normalizeApplyTextNormalization,
|
||||
normalizeLanguageCode,
|
||||
normalizeSeed,
|
||||
requireInRange,
|
||||
scheduleCleanup,
|
||||
} from "./tts-provider-helpers.js";
|
||||
|
||||
type SummarizeTextDeps = {
|
||||
completeSimple: typeof completeSimple;
|
||||
@@ -36,45 +37,6 @@ function resolveDefaultSummarizeTextDeps(): SummarizeTextDeps {
|
||||
};
|
||||
}
|
||||
|
||||
export function requireInRange(value: number, min: number, max: number, label: string): void {
|
||||
if (!Number.isFinite(value) || value < min || value > max) {
|
||||
throw new Error(`${label} must be between ${min} and ${max}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeLanguageCode(code?: string): string | undefined {
|
||||
const normalized = normalizeOptionalLowercaseString(code);
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
if (!/^[a-z]{2}$/.test(normalized)) {
|
||||
throw new Error("languageCode must be a 2-letter ISO 639-1 code (e.g. en, de, fr)");
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export function normalizeApplyTextNormalization(mode?: string): "auto" | "on" | "off" | undefined {
|
||||
const normalized = normalizeOptionalLowercaseString(mode);
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
if (normalized === "auto" || normalized === "on" || normalized === "off") {
|
||||
return normalized;
|
||||
}
|
||||
throw new Error("applyTextNormalization must be one of: auto, on, off");
|
||||
}
|
||||
|
||||
export function normalizeSeed(seed?: number): number | undefined {
|
||||
if (seed == null) {
|
||||
return undefined;
|
||||
}
|
||||
const next = Math.floor(seed);
|
||||
if (!Number.isFinite(next) || next < 0 || next > 4_294_967_295) {
|
||||
throw new Error("seed must be between 0 and 4294967295");
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
type SummarizeResult = {
|
||||
summary: string;
|
||||
latencyMs: number;
|
||||
@@ -195,17 +157,3 @@ export async function summarizeText(
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
export function scheduleCleanup(
|
||||
tempDir: string,
|
||||
delayMs: number = TEMP_FILE_CLEANUP_DELAY_MS,
|
||||
): void {
|
||||
const timer = setTimeout(() => {
|
||||
try {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
} catch {
|
||||
// ignore cleanup errors
|
||||
}
|
||||
}, delayMs);
|
||||
timer.unref();
|
||||
}
|
||||
|
||||
57
src/tts/tts-provider-helpers.ts
Normal file
57
src/tts/tts-provider-helpers.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { rmSync } from "node:fs";
|
||||
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
|
||||
|
||||
const TEMP_FILE_CLEANUP_DELAY_MS = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
export function requireInRange(value: number, min: number, max: number, label: string): void {
|
||||
if (!Number.isFinite(value) || value < min || value > max) {
|
||||
throw new Error(`${label} must be between ${min} and ${max}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeLanguageCode(code?: string): string | undefined {
|
||||
const normalized = normalizeOptionalLowercaseString(code);
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
if (!/^[a-z]{2}$/.test(normalized)) {
|
||||
throw new Error("languageCode must be a 2-letter ISO 639-1 code (e.g. en, de, fr)");
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export function normalizeApplyTextNormalization(mode?: string): "auto" | "on" | "off" | undefined {
|
||||
const normalized = normalizeOptionalLowercaseString(mode);
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
if (normalized === "auto" || normalized === "on" || normalized === "off") {
|
||||
return normalized;
|
||||
}
|
||||
throw new Error("applyTextNormalization must be one of: auto, on, off");
|
||||
}
|
||||
|
||||
export function normalizeSeed(seed?: number): number | undefined {
|
||||
if (seed == null) {
|
||||
return undefined;
|
||||
}
|
||||
const next = Math.floor(seed);
|
||||
if (!Number.isFinite(next) || next < 0 || next > 4_294_967_295) {
|
||||
throw new Error("seed must be between 0 and 4294967295");
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
export function scheduleCleanup(
|
||||
tempDir: string,
|
||||
delayMs: number = TEMP_FILE_CLEANUP_DELAY_MS,
|
||||
): void {
|
||||
const timer = setTimeout(() => {
|
||||
try {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
} catch {
|
||||
// ignore cleanup errors
|
||||
}
|
||||
}, delayMs);
|
||||
timer.unref();
|
||||
}
|
||||
Reference in New Issue
Block a user