75 lines
2.7 KiB
TypeScript
75 lines
2.7 KiB
TypeScript
import { config as loadDotenv } from "dotenv";
|
|
import { z } from "zod";
|
|
|
|
loadDotenv();
|
|
|
|
const emptyToUndefined = z.preprocess((value) => {
|
|
if (typeof value !== "string") {
|
|
return value;
|
|
}
|
|
const trimmed = value.trim();
|
|
return trimmed.length === 0 ? undefined : trimmed;
|
|
}, z.string().min(1).optional());
|
|
|
|
const envSchema = z.object({
|
|
DISCORD_BOT_TOKEN: emptyToUndefined,
|
|
DISCORD_APPLICATION_ID: emptyToUndefined,
|
|
DISCORD_COMMAND_GUILD_ID: emptyToUndefined,
|
|
OLLAMA_BASE_URL: z.string().min(1).default("http://localhost:11434"),
|
|
OLLAMA_MODEL: z.string().min(1).default("qwen3:0.6b"),
|
|
OLLAMA_KEEP_ALIVE: z.string().min(1).default("5m"),
|
|
OLLAMA_NUM_CTX: z.coerce.number().int().min(512).max(32768).default(4096),
|
|
LOCAL_AI_VENV_PATH: z.string().min(1).default(".local-ai/.venv"),
|
|
LOCAL_AI_CACHE_DIR: z.string().min(1).default(".local-ai/cache"),
|
|
LOCAL_AI_PYTHON: emptyToUndefined,
|
|
LOCAL_STT_MODEL: z.string().min(1).default("tiny"),
|
|
LOCAL_STT_DEVICE: z.string().min(1).default("auto"),
|
|
LOCAL_STT_COMPUTE_TYPE: z.string().min(1).default("auto"),
|
|
LOCAL_STT_BEAM_SIZE: z.coerce.number().int().min(1).max(8).default(1),
|
|
LOCAL_TTS_LANGUAGE: z.string().min(1).default("KR"),
|
|
LOCAL_TTS_SPEAKER: z.string().min(1).default("KR"),
|
|
LOCAL_TTS_DEVICE: z.string().min(1).default("auto"),
|
|
LOCAL_TTS_SPEED: z.coerce.number().min(0.8).max(1.6).default(1.12),
|
|
BOT_DEFAULT_LANGUAGE: z.string().min(2).default("ko"),
|
|
MAX_CONVERSATION_TURNS: z.coerce.number().int().min(4).max(30).default(12),
|
|
LOCAL_AUDIO_SOURCE: emptyToUndefined,
|
|
LOCAL_AUDIO_SINK: emptyToUndefined,
|
|
LOCAL_SPEAKER_NAME: z.string().min(1).default("local-user"),
|
|
DEBUG_TEXT_EVENTS: z
|
|
.string()
|
|
.optional()
|
|
.transform((value) => value === "true"),
|
|
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("info"),
|
|
});
|
|
|
|
export type AppConfig = z.infer<typeof envSchema>;
|
|
export type AssistantRuntimeConfig = AppConfig;
|
|
export type DiscordRuntimeConfig = AssistantRuntimeConfig & {
|
|
DISCORD_BOT_TOKEN: string;
|
|
DISCORD_APPLICATION_ID: string;
|
|
};
|
|
|
|
export function loadConfig(): AppConfig {
|
|
return envSchema.parse(process.env);
|
|
}
|
|
|
|
function requirePresent(value: string | undefined, name: string): string {
|
|
if (!value) {
|
|
throw new Error(`${name} 환경변수가 필요합니다.`);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
export function requireAssistantRuntimeConfig(config: AppConfig): AssistantRuntimeConfig {
|
|
return config;
|
|
}
|
|
|
|
export function requireDiscordRuntimeConfig(config: AppConfig): DiscordRuntimeConfig {
|
|
const assistant = requireAssistantRuntimeConfig(config);
|
|
return {
|
|
...assistant,
|
|
DISCORD_BOT_TOKEN: requirePresent(config.DISCORD_BOT_TOKEN, "DISCORD_BOT_TOKEN"),
|
|
DISCORD_APPLICATION_ID: requirePresent(config.DISCORD_APPLICATION_ID, "DISCORD_APPLICATION_ID"),
|
|
};
|
|
}
|