perplexica / OpenReels /src /cli /validate-env.ts
abc1181's picture
Motion Factory: OpenReels edition
1da8cb0 verified
Raw History Blame Contribute Delete
3.81 kB
import type {
ImageProviderKey,
LLMProviderKey,
MusicProviderKey,
SearchProviderKey,
TTSProviderKey,
VideoProviderKey,
} from "../schema/providers.js";
interface EnvRequirement {
key: string;
provider: string;
signupUrl: string;
required: boolean;
}
export function validateEnv(opts: {
provider: LLMProviderKey;
ttsProvider: TTSProviderKey;
imageProvider: ImageProviderKey;
videoProvider?: VideoProviderKey;
musicProvider?: MusicProviderKey;
searchProvider?: SearchProviderKey;
}): void {
const requirements: EnvRequirement[] = [
{
key: "ANTHROPIC_API_KEY",
provider: "Anthropic (LLM)",
signupUrl: "https://console.anthropic.com/",
required: opts.provider === "anthropic",
},
{
key: "OPENAI_API_KEY",
provider: "OpenAI (LLM/Image)",
signupUrl: "https://platform.openai.com/api-keys",
required:
opts.provider === "openai" ||
opts.imageProvider === "openai" ||
opts.ttsProvider === "openai-tts",
},
{
key: "GOOGLE_API_KEY",
provider: "Google Gemini (LLM/Image/Video/TTS)",
signupUrl: "https://aistudio.google.com/apikey",
required:
opts.provider === "gemini" ||
opts.imageProvider === "gemini" ||
opts.videoProvider === "gemini" ||
opts.ttsProvider === "gemini-tts" ||
opts.musicProvider === "lyria",
},
{
key: "ELEVENLABS_API_KEY",
provider: "ElevenLabs (TTS)",
signupUrl: "https://elevenlabs.io/",
required: opts.ttsProvider === "elevenlabs",
},
{
key: "INWORLD_TTS_API_KEY",
provider: "Inworld (TTS)",
signupUrl: "https://inworld.ai/",
required: opts.ttsProvider === "inworld",
},
{
key: "OPENROUTER_API_KEY",
provider: "OpenRouter (LLM)",
signupUrl: "https://openrouter.ai/",
required: opts.provider === "openrouter",
},
{
key: "TAVILY_API_KEY",
provider: "Tavily (Web Search)",
signupUrl: "https://tavily.com/",
required: opts.searchProvider === "tavily",
},
];
const missing = requirements.filter((r) => r.required && !process.env[r.key]);
// Stock keys are optional — the pipeline degrades gracefully (black frames) — but
// warn upfront so users aren't surprised by missing visuals on stock_image/stock_video scenes.
const hasStockKey = process.env["PEXELS_API_KEY"] || process.env["PIXABAY_API_KEY"];
if (!hasStockKey) {
console.warn(
"\nWarning: No stock media API key found (PEXELS_API_KEY or PIXABAY_API_KEY).\n" +
"Scenes using stock_image or stock_video will render as blank frames.\n" +
"Get a free key: https://www.pexels.com/api/ or https://pixabay.com/api/docs/\n",
);
}
// Warn when openrouter/openai-compatible without explicit search provider and no Tavily key
const needsSearchWarning =
(opts.provider === "openrouter" || opts.provider === "openai-compatible") &&
!opts.searchProvider &&
!process.env["TAVILY_API_KEY"];
if (needsSearchWarning) {
console.warn(
"\nWarning: TAVILY_API_KEY not set. Web search will be disabled for this provider.\n" +
"Research agent will use parametric knowledge only.\n" +
"Get a key: https://tavily.com/ or use --search-provider none to suppress this warning.\n",
);
}
if (missing.length === 0) return;
console.error("\nMissing required API keys:\n");
console.error(" Key Status Get it at");
console.error(" " + "-".repeat(70));
for (const r of missing) {
const key = r.key.padEnd(24);
console.error(` ${key}MISSING ${r.signupUrl}`);
}
console.error(
"\nSet these in your .env file (or pass with `docker run --env-file .env` when using Docker).\n",
);
process.exit(1);
}