/** * Configuration Utilities * * Provides centralized access to environment variables for ONNX model paths * and other configuration values. * * Works across different contexts: * - Frontend (Vite): Uses import.meta.env.VITE_* variables * - Backend/Tools (Node): Uses process.env.* variables with dotenv */ import * as path from "path"; import { fileURLToPath } from "url"; // Environment detection const isNode = typeof process !== "undefined" && process.versions?.node; const isBrowser = typeof window !== "undefined"; /** * ONNX Session Options */ export interface OnnxSessionOptions { executionProviders: string[]; intraOpNumThreads?: number; interOpNumThreads?: number; graphOptimizationLevel?: "disabled" | "basic" | "extended" | "all"; enableCpuMemArena?: boolean; enableMemPattern?: boolean; } /** * Get ONNX model paths * Returns paths appropriate for the current environment */ export function getOnnxModelPaths(): { evaluationModel: string; treeModel: string; } { // Frontend (Vite environment) if (isBrowser && typeof import.meta.env !== "undefined") { const evaluationModel = import.meta.env.VITE_ONNX_EVALUATION_MODEL; const treeModel = import.meta.env.VITE_ONNX_TREE_MODEL; if (!evaluationModel || !treeModel) { throw new Error("ONNX model paths not configured. Check VITE_ONNX_EVALUATION_MODEL and VITE_ONNX_TREE_MODEL in .env"); } return { evaluationModel, treeModel }; } // Backend/Tools (Node environment) if (isNode) { const evaluationModel = process.env.ONNX_EVALUATION_MODEL; const treeModel = process.env.ONNX_TREE_MODEL; if (!evaluationModel || !treeModel) { throw new Error("ONNX model paths not configured. Check ONNX_EVALUATION_MODEL and ONNX_TREE_MODEL in .env"); } return { evaluationModel, treeModel }; } // Should not reach here throw new Error("Unknown environment - cannot determine model paths"); } /** * Get ONNX session options from environment variables * Returns session options with threading and optimization configuration */ export function getOnnxSessionOptions(): OnnxSessionOptions { // Default values const options: OnnxSessionOptions = { executionProviders: ["cpu"], graphOptimizationLevel: "all", enableCpuMemArena: true, enableMemPattern: true }; // Frontend (Vite environment) if (isBrowser && typeof import.meta.env !== "undefined") { const intraThreadsEnv = import.meta.env.VITE_ONNX_INTRA_OP_NUM_THREADS; const interThreadsEnv = import.meta.env.VITE_ONNX_INTER_OP_NUM_THREADS; const graphOptEnv = import.meta.env.VITE_ONNX_GRAPH_OPTIMIZATION_LEVEL; if (intraThreadsEnv) options.intraOpNumThreads = parseInt(intraThreadsEnv, 10); if (interThreadsEnv) options.interOpNumThreads = parseInt(interThreadsEnv, 10); if (graphOptEnv) options.graphOptimizationLevel = graphOptEnv as any; } // Backend/Tools (Node environment) if (isNode) { const intraThreadsEnv = process.env.ONNX_INTRA_OP_NUM_THREADS; const interThreadsEnv = process.env.ONNX_INTER_OP_NUM_THREADS; const graphOptEnv = process.env.ONNX_GRAPH_OPTIMIZATION_LEVEL; const cpuMemArenaEnv = process.env.ONNX_ENABLE_CPU_MEM_ARENA; const memPatternEnv = process.env.ONNX_ENABLE_MEM_PATTERN; if (intraThreadsEnv) options.intraOpNumThreads = parseInt(intraThreadsEnv, 10); if (interThreadsEnv) options.interOpNumThreads = parseInt(interThreadsEnv, 10); if (graphOptEnv) options.graphOptimizationLevel = graphOptEnv as any; if (cpuMemArenaEnv) options.enableCpuMemArena = cpuMemArenaEnv === "true"; if (memPatternEnv) options.enableMemPattern = memPatternEnv === "true"; } return options; } /** * Get absolute path to model file (Node.js only) * Resolves relative paths to absolute paths from project root */ export function getAbsoluteModelPath(relativePath: string): string { if (!isNode) { return relativePath; // Browser environment - return as-is } // If already absolute, return as-is if (path.isAbsolute(relativePath)) { return relativePath; } // Resolve relative to project root const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const rootDir = path.resolve(__dirname, ".."); return path.resolve(rootDir, relativePath); } /** * Load environment variables from .env file (Node.js only) * Call this at the start of tool scripts * * Loading order: * 1. .env (base configuration, committed to git) * 2. .env.local (local overrides, not committed to git) */ export async function loadEnvConfig(): Promise { if (!isNode) { console.warn("[Config] loadEnvConfig() called in non-Node environment"); return; } try { // Dynamically import dotenv (ESM-compatible) const dotenv = (await import("dotenv")).default; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const rootDir = path.resolve(__dirname, ".."); // Load base .env file const baseResult = dotenv.config({ path: path.join(rootDir, ".env") }); if (baseResult.error) { console.warn("[Config] Failed to load .env:", baseResult.error.message); } else { console.log("[Config] ✓ Base environment variables loaded from .env"); } // Load .env.local for local overrides (if exists) // Use override: true to allow .env.local to override .env values const localResult = dotenv.config({ path: path.join(rootDir, ".env.local"), override: true }); if (!localResult.error) { console.log("[Config] ✓ Local overrides loaded from .env.local"); } // Silently ignore if .env.local doesn't exist (optional file) } catch (error) { console.warn("[Config] dotenv not available:", error); } }