import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { spawn } from 'node:child_process'; import { stopOwnedChild } from './processes.mjs'; export const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); if (fs.existsSync(path.join(root, '.env'))) process.loadEnvFile(path.join(root, '.env')); export function pythonPath() { const executable = process.env.ASSISTANT_PYTHON || path.join(root, '.venv', process.platform === 'win32' ? 'Scripts/python.exe' : 'bin/python'); if (!fs.existsSync(executable)) throw new Error('请先建立 .venv 并安装 apps/server/requirements.txt 中的依赖。'); return executable; } export function startServer() { return spawn(pythonPath(), ['-m', 'scripts.serve', '--port', process.env.ASSISTANT_API_PORT || '8810'], { cwd: root, env: { ...process.env, PYTHONUTF8: '1', ASSISTANT_NODE: process.execPath }, stdio: ['pipe', 'inherit', 'inherit'], windowsHide: true, }); } if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { const child = startServer(); for (const signal of ['SIGINT', 'SIGTERM']) process.on(signal, () => void stopOwnedChild(child, { graceful: true })); child.on('error', error => { console.error(error.message); process.exitCode = 1; }); child.on('exit', code => { process.exitCode = code || 0; }); }