Update files
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
import path from "node:path";
|
||||
|
||||
import type { PaseoDaemonConfig } from "./bootstrap.js";
|
||||
import type { STTConfig } from "./speech/providers/openai/stt.js";
|
||||
import type { TTSConfig } from "./speech/providers/openai/tts.js";
|
||||
import { loadPersistedConfig } from "./persisted-config.js";
|
||||
import type { AgentProvider } from "./agent/agent-sdk-types.js";
|
||||
import { AGENT_PROVIDER_IDS } from "./agent/provider-manifest.js";
|
||||
import { resolveSpeechConfig } from "./speech/speech-config-resolver.js";
|
||||
import {
|
||||
mergeAllowedHosts,
|
||||
parseAllowedHostsEnv,
|
||||
@@ -27,69 +26,6 @@ export type CliConfigOverrides = Partial<{
|
||||
allowedHosts: AllowedHostsConfig;
|
||||
}>;
|
||||
|
||||
function parseOpenAIConfig(
|
||||
env: NodeJS.ProcessEnv,
|
||||
configApiKey: string | undefined,
|
||||
config: {
|
||||
dictationSttModel?: string;
|
||||
dictationSttConfidenceThreshold?: number;
|
||||
voiceSttModel?: string;
|
||||
voiceTtsVoice?: TTSConfig["voice"];
|
||||
voiceTtsModel?: TTSConfig["model"];
|
||||
}
|
||||
) {
|
||||
const apiKey = env.OPENAI_API_KEY ?? configApiKey;
|
||||
if (!apiKey) return undefined;
|
||||
|
||||
const sttConfidenceThreshold = env.STT_CONFIDENCE_THRESHOLD
|
||||
? parseFloat(env.STT_CONFIDENCE_THRESHOLD)
|
||||
: config.dictationSttConfidenceThreshold;
|
||||
const sttModel = (
|
||||
env.STT_MODEL ??
|
||||
config.voiceSttModel ??
|
||||
config.dictationSttModel
|
||||
) as STTConfig["model"] | undefined;
|
||||
const ttsVoice = (env.TTS_VOICE || "alloy") as
|
||||
| "alloy"
|
||||
| "echo"
|
||||
| "fable"
|
||||
| "onyx"
|
||||
| "nova"
|
||||
| "shimmer";
|
||||
const ttsModel = (env.TTS_MODEL || config.voiceTtsModel || "tts-1") as
|
||||
| "tts-1"
|
||||
| "tts-1-hd";
|
||||
const configuredVoice = config.voiceTtsVoice;
|
||||
|
||||
return {
|
||||
apiKey,
|
||||
stt: {
|
||||
apiKey,
|
||||
confidenceThreshold: sttConfidenceThreshold,
|
||||
...(sttModel ? { model: sttModel } : {}),
|
||||
},
|
||||
tts: {
|
||||
apiKey,
|
||||
voice: configuredVoice ?? ttsVoice,
|
||||
model: ttsModel,
|
||||
responseFormat: "pcm" as TTSConfig["responseFormat"],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function parseSpeechProviderId(value: unknown): "openai" | "local" | null {
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
}
|
||||
const normalized = value.trim().toLowerCase();
|
||||
if (!normalized) {
|
||||
return null;
|
||||
}
|
||||
if (normalized === "openai") return "openai";
|
||||
if (normalized === "local") return "local";
|
||||
return null;
|
||||
}
|
||||
|
||||
function parseVoiceLlmProviderId(value: unknown): AgentProvider | null {
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
@@ -103,36 +39,6 @@ function parseVoiceLlmProviderId(value: unknown): AgentProvider | null {
|
||||
: null;
|
||||
}
|
||||
|
||||
function normalizeSherpaSttPreset(value: string): string {
|
||||
const raw = value.trim();
|
||||
const normalized = raw.toLowerCase();
|
||||
if (normalized === "zipformer" || normalized === "zipformer-bilingual") {
|
||||
return "zipformer-bilingual-zh-en-2023-02-20";
|
||||
}
|
||||
if (normalized === "paraformer") {
|
||||
return "paraformer-bilingual-zh-en";
|
||||
}
|
||||
if (normalized === "parakeet" || normalized === "parakeet-v3" || normalized === "parakeet-tdt") {
|
||||
return "parakeet-tdt-0.6b-v3-int8";
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
function normalizeSherpaTtsPreset(value: string): string {
|
||||
const raw = value.trim();
|
||||
const normalized = raw.toLowerCase();
|
||||
if (normalized === "pocket" || normalized === "pocket-tts") {
|
||||
return "pocket-tts-onnx-int8";
|
||||
}
|
||||
if (normalized === "kitten") {
|
||||
return "kitten-nano-en-v0_1-fp16";
|
||||
}
|
||||
if (normalized === "kokoro") {
|
||||
return "kokoro-en-v0_19";
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
export function loadConfig(
|
||||
paseoHome: string,
|
||||
options?: {
|
||||
@@ -185,79 +91,12 @@ export function loadConfig(
|
||||
const appBaseUrl =
|
||||
env.PASEO_APP_BASE_URL ?? persisted.app?.baseUrl ?? DEFAULT_APP_BASE_URL;
|
||||
|
||||
const openai = parseOpenAIConfig(env, persisted.providers?.openai?.apiKey, {
|
||||
dictationSttModel: persisted.features?.dictation?.stt?.model,
|
||||
dictationSttConfidenceThreshold:
|
||||
persisted.features?.dictation?.stt?.confidenceThreshold,
|
||||
voiceSttModel: persisted.features?.voiceMode?.stt?.model,
|
||||
voiceTtsModel: persisted.features?.voiceMode?.tts?.model,
|
||||
voiceTtsVoice: persisted.features?.voiceMode?.tts?.voice,
|
||||
const { openai, speech } = resolveSpeechConfig({
|
||||
paseoHome,
|
||||
env,
|
||||
persisted,
|
||||
});
|
||||
|
||||
const dictationSttProvider =
|
||||
parseSpeechProviderId(env.PASEO_DICTATION_STT_PROVIDER) ??
|
||||
parseSpeechProviderId(persisted.features?.dictation?.stt?.provider) ??
|
||||
"local";
|
||||
|
||||
const voiceSttProvider =
|
||||
parseSpeechProviderId(env.PASEO_VOICE_STT_PROVIDER) ??
|
||||
parseSpeechProviderId(persisted.features?.voiceMode?.stt?.provider) ??
|
||||
"local";
|
||||
|
||||
const voiceTtsProvider =
|
||||
parseSpeechProviderId(env.PASEO_VOICE_TTS_PROVIDER) ??
|
||||
parseSpeechProviderId(persisted.features?.voiceMode?.tts?.provider) ??
|
||||
"local";
|
||||
|
||||
const shouldConfigureSherpa =
|
||||
dictationSttProvider === "local" ||
|
||||
voiceSttProvider === "local" ||
|
||||
voiceTtsProvider === "local" ||
|
||||
typeof env.PASEO_SHERPA_ONNX_MODELS_DIR === "string" ||
|
||||
Boolean(persisted.providers?.sherpaOnnx);
|
||||
|
||||
const sherpaModelsDir =
|
||||
(env.PASEO_SHERPA_ONNX_MODELS_DIR ?? persisted.providers?.sherpaOnnx?.modelsDir)?.trim() ||
|
||||
path.join(paseoHome, "models", "sherpa-onnx");
|
||||
|
||||
const sherpaOnnx = shouldConfigureSherpa
|
||||
? {
|
||||
modelsDir: sherpaModelsDir,
|
||||
autoDownload:
|
||||
env.PASEO_SHERPA_ONNX_AUTO_DOWNLOAD !== undefined
|
||||
? env.PASEO_SHERPA_ONNX_AUTO_DOWNLOAD === "1"
|
||||
: persisted.providers?.sherpaOnnx?.autoDownload ??
|
||||
// In tests we should never hit the network unexpectedly.
|
||||
Boolean(env.VITEST) === false,
|
||||
stt: {
|
||||
preset: normalizeSherpaSttPreset(
|
||||
(env.PASEO_SHERPA_STT_PRESET ?? persisted.providers?.sherpaOnnx?.stt?.preset)?.trim() ||
|
||||
(persisted.features?.voiceMode?.stt?.preset ??
|
||||
persisted.features?.dictation?.stt?.preset)?.trim() ||
|
||||
"parakeet-tdt-0.6b-v3-int8"
|
||||
),
|
||||
},
|
||||
tts: {
|
||||
preset: normalizeSherpaTtsPreset(
|
||||
(env.PASEO_SHERPA_TTS_PRESET ??
|
||||
persisted.providers?.sherpaOnnx?.tts?.preset ??
|
||||
persisted.features?.voiceMode?.tts?.preset)?.trim() ||
|
||||
(env.VITEST ? "kitten-nano-en-v0_1-fp16" : "pocket-tts-onnx-int8")
|
||||
),
|
||||
speakerId:
|
||||
env.PASEO_SHERPA_TTS_SPEAKER_ID !== undefined
|
||||
? Number.parseInt(env.PASEO_SHERPA_TTS_SPEAKER_ID, 10)
|
||||
: persisted.providers?.sherpaOnnx?.tts?.speakerId ??
|
||||
persisted.features?.voiceMode?.tts?.speakerId,
|
||||
speed:
|
||||
env.PASEO_SHERPA_TTS_SPEED !== undefined
|
||||
? Number.parseFloat(env.PASEO_SHERPA_TTS_SPEED)
|
||||
: persisted.providers?.sherpaOnnx?.tts?.speed ??
|
||||
persisted.features?.voiceMode?.tts?.speed,
|
||||
},
|
||||
}
|
||||
: undefined;
|
||||
|
||||
const envVoiceLlmProvider = parseVoiceLlmProviderId(env.PASEO_VOICE_LLM_PROVIDER);
|
||||
const persistedVoiceLlmProvider = parseVoiceLlmProviderId(
|
||||
persisted.features?.voiceMode?.llm?.provider
|
||||
@@ -284,12 +123,7 @@ export function loadConfig(
|
||||
relayPublicEndpoint,
|
||||
appBaseUrl,
|
||||
openai,
|
||||
speech: {
|
||||
dictationSttProvider,
|
||||
voiceSttProvider,
|
||||
voiceTtsProvider,
|
||||
...(sherpaOnnx ? { sherpaOnnx } : {}),
|
||||
},
|
||||
speech,
|
||||
voiceLlmProvider,
|
||||
voiceLlmProviderExplicit,
|
||||
voiceLlmModel,
|
||||
|
||||
Reference in New Issue
Block a user