85 lines
3.1 KiB
TypeScript
85 lines
3.1 KiB
TypeScript
function env(name: string, fallback = ""): string {
|
|
return process.env[name] ?? fallback;
|
|
}
|
|
|
|
function envBool(name: string, fallback: boolean): boolean {
|
|
const v = process.env[name];
|
|
if (v === undefined) return fallback;
|
|
return v === "1" || v.toLowerCase() === "true";
|
|
}
|
|
|
|
function envInt(name: string, fallback: number): number {
|
|
const v = Number.parseInt(process.env[name] ?? "", 10);
|
|
return Number.isFinite(v) ? v : fallback;
|
|
}
|
|
|
|
export const config = {
|
|
// "production" under the NixOS module / CI builds, "development" locally.
|
|
nodeEnv: env("NODE_ENV", "development"),
|
|
isProduction: env("NODE_ENV", "development") === "production",
|
|
|
|
port: envInt("PORT", 3000),
|
|
host: env("HOST", "127.0.0.1"),
|
|
appPassword: env("APP_PASSWORD", ""),
|
|
sessionTtlMs: envInt("SESSION_TTL_HOURS", 720) * 3600_000,
|
|
dataDir: env("DATA_DIR", "./data"),
|
|
|
|
rateLimitMax: envInt("RATE_LIMIT_MAX", 5),
|
|
rateLimitWindowMs: envInt("RATE_LIMIT_WINDOW_MIN", 10) * 60_000,
|
|
|
|
ollamaHost: env("OLLAMA_HOST", "http://localhost:11434"),
|
|
ollamaEnabled: envBool("OLLAMA_ENABLED", true),
|
|
|
|
mistralApiKey: env("MISTRAL_API_KEY", ""),
|
|
mistralEnabled: envBool("MISTRAL_ENABLED", false),
|
|
|
|
deepseekApiKey: env("DEEPSEEK_API_KEY", ""),
|
|
deepseekEnabled: envBool("DEEPSEEK_ENABLED", false),
|
|
|
|
anthropicApiKey: env("ANTHROPIC_API_KEY", ""),
|
|
anthropicEnabled: envBool("ANTHROPIC_ENABLED", false),
|
|
|
|
openaiApiKey: env("OPENAI_API_KEY", ""),
|
|
openaiEnabled: envBool("OPENAI_ENABLED", false),
|
|
|
|
glmApiKey: env("GLM_API_KEY", ""),
|
|
glmEnabled: envBool("GLM_ENABLED", false),
|
|
// Zhipu has two platforms: international (api.z.ai, default) and
|
|
// mainland China (open.bigmodel.cn) — override for the latter.
|
|
glmBaseUrl: env("GLM_BASE_URL", "https://api.z.ai/api/paas/v4"),
|
|
|
|
// Public docs wiki (served by the hosted git forge, e.g. Gitea wiki pages).
|
|
// The app redirects GET /wiki there (302) so the target stays configurable.
|
|
wikiUrl: env("WIKI_URL", "https://git.kisakay.com/k/chat/wiki"),
|
|
|
|
// Per-driver debug logging to stdout ([driver:name] lines).
|
|
// On by default in development, off unless asked for in production.
|
|
driverDebug: envBool("DRIVER_DEBUG", !env("NODE_ENV", "development")),
|
|
|
|
// Local file CDN (avatars today, more namespaces tomorrow).
|
|
// Dev default is a folder next to the codebase; NixOS module points it
|
|
// under the service state dir.
|
|
cdnDir: env("CDN_DIR", "./cdn"),
|
|
|
|
// OCR tool (tesseract binary).
|
|
ocrLang: env("OCR_LANG", "eng"),
|
|
ocrMaxChars: envInt("OCR_MAX_CHARS", 100_000),
|
|
|
|
// Key recovery via email (optional — empty SMTP_HOST disables it).
|
|
smtpHost: env("SMTP_HOST", ""),
|
|
smtpPort: envInt("SMTP_PORT", 587),
|
|
smtpSecure: envBool("SMTP_SECURE", false), // true = implicit TLS (port 465)
|
|
smtpUser: env("SMTP_USER", ""),
|
|
smtpPass: env("SMTP_PASS", ""),
|
|
smtpFrom: env("SMTP_FROM", "KisAssistant <[email protected]>"),
|
|
appUrl: env("APP_URL", "http://localhost:3000").replace(/\/$/, ""),
|
|
resetTtlMs: envInt("RESET_TTL_MIN", 60) * 60_000,
|
|
};
|
|
|
|
export function assertConfig(): void {
|
|
if (!config.appPassword) {
|
|
console.error("FATAL: APP_PASSWORD is not set. Copy .env.example to .env and set it.");
|
|
process.exit(1);
|
|
}
|
|
}
|