Files
Sybil-2/server/src/env.ts

52 lines
1.6 KiB
TypeScript
Raw Normal View History

2026-05-02 18:14:41 -07:00
import path from "node:path";
import { fileURLToPath } from "node:url";
import { config as loadDotenv } from "dotenv";
2026-02-13 22:43:55 -08:00
import { z } from "zod";
2026-05-02 18:14:41 -07:00
loadDotenv({ quiet: true });
loadDotenv({ path: path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../.env"), quiet: true });
const OptionalUrlSchema = z.preprocess(
(value) => (typeof value === "string" && value.trim() === "" ? undefined : value),
z.string().trim().url().optional()
);
const ChatWebSearchEngineSchema = z.preprocess(
(value) => {
if (typeof value !== "string") return value;
const trimmed = value.trim();
return trimmed ? trimmed.toLowerCase() : undefined;
},
z.enum(["exa", "searxng"]).default("exa")
);
2026-02-13 22:43:55 -08:00
const EnvSchema = z.object({
PORT: z.coerce.number().int().positive().default(8787),
HOST: z.string().default("0.0.0.0"),
// simple bearer-token auth for your personal backend
ADMIN_TOKEN: z.string().min(20).optional(),
// provider keys
OPENAI_API_KEY: z.string().optional(),
ANTHROPIC_API_KEY: z.string().optional(),
XAI_API_KEY: z.string().optional(),
2026-02-13 23:49:55 -08:00
EXA_API_KEY: z.string().optional(),
2026-05-02 18:14:41 -07:00
// Chat-mode web_search tool configuration. Search mode remains Exa-only for now.
CHAT_WEB_SEARCH_ENGINE: ChatWebSearchEngineSchema,
SEARXNG_BASE_URL: OptionalUrlSchema,
}).superRefine((value, ctx) => {
if (value.CHAT_WEB_SEARCH_ENGINE === "searxng" && !value.SEARXNG_BASE_URL) {
ctx.addIssue({
code: "custom",
path: ["SEARXNG_BASE_URL"],
message: "SEARXNG_BASE_URL is required when CHAT_WEB_SEARCH_ENGINE=searxng",
});
}
2026-02-13 22:43:55 -08:00
});
export type Env = z.infer<typeof EnvSchema>;
export const env: Env = EnvSchema.parse(process.env);