import { existsSync } from "node:fs"; import { mkdir } from "node:fs/promises"; import { spawn } from "node:child_process"; import path from "node:path"; import { loadConfig } from "./config.js"; import { resolveLocalAiCachePath, resolveLocalAiVenvPath, resolvePythonLaunch, resolveVenvPythonPath } from "./python-runtime.js"; async function run(command: string, args: string[], extraEnv?: NodeJS.ProcessEnv): Promise { await new Promise((resolve, reject) => { const child = spawn(command, args, { stdio: "inherit", env: { ...process.env, ...extraEnv, }, }); child.on("exit", (code) => { if (code === 0) { resolve(); return; } reject(new Error(`${command} ${args.join(" ")} exited with code ${code ?? "null"}`)); }); child.on("error", reject); }); } async function ensurePip(pythonBin: string, env: NodeJS.ProcessEnv): Promise { await new Promise((resolve, reject) => { const child = spawn(pythonBin, ["-m", "pip", "--version"], { stdio: "ignore", env, }); child.on("exit", (code) => { if (code === 0) { resolve(); return; } reject(new Error("pip missing")); }); child.on("error", reject); }).catch(async () => { await run(pythonBin, ["-m", "ensurepip", "--upgrade"], env); }); } async function main(): Promise { const config = loadConfig(); const venvPath = resolveLocalAiVenvPath(config); const venvPython = resolveVenvPythonPath(config); const cachePath = resolveLocalAiCachePath(config); const requirementsPath = path.resolve(process.cwd(), "python", "requirements.txt"); const baseEnv = { HF_HOME: cachePath, TRANSFORMERS_CACHE: cachePath, PYTHONIOENCODING: "utf-8", }; await mkdir(cachePath, { recursive: true }); if (!existsSync(venvPython)) { const launch = resolvePythonLaunch(config, { preferVenv: false }); console.log(`기본 Python 확인: ${launch.command} ${launch.args.join(" ")}`.trim()); console.log(`가상환경 생성: ${venvPath}`); await run(launch.command, [...launch.args, "-m", "venv", venvPath], baseEnv); } await ensurePip(venvPython, { ...process.env, ...baseEnv, }); console.log("로컬 AI 의존성 설치를 시작합니다."); await run(venvPython, ["-m", "pip", "install", "--upgrade", "pip", "setuptools", "wheel"], baseEnv); await run(venvPython, ["-m", "pip", "install", "-r", requirementsPath], baseEnv); console.log("설치가 끝났습니다."); console.log("다음 순서:"); console.log("1. bun run devices"); console.log("2. bun run start:local"); } void main().catch((error) => { console.error(error instanceof Error ? error.message : String(error)); process.exit(1); });