const fs = require('fs'); const path = require('path'); const { spawn } = require('child_process'); const { applyWorkspaceContext } = require('../mcp/src/core/runtime-context'); const packageRoot = path.resolve(__dirname, '..'); applyWorkspaceContext({ packageRoot }); const { ensureRelayDaemon } = require('../mcp/src/core/relay-daemon'); const { startServer } = require('../mcp/src/dashboard/server'); function ensureCallbackRuntime() { const statePath = path.join(packageRoot, 'outputs', 'runtime', 'qiwei-runtime.json'); let state = {}; try { state = JSON.parse(fs.readFileSync(statePath, 'utf8')); } catch {} const pid = Number(state.pid || 0); const alive = pid > 0 ? (() => { try { process.kill(pid, 0); return true; } catch { return false; } })() : false; if (alive && ['starting', 'running'].includes(state.status)) { console.log(`[start-dashboard] callback runtime 已在运行 (pid=${pid})`); return; } const runtimeScript = path.join(packageRoot, 'scripts', 'start-callback-runtime.mjs'); fs.mkdirSync(path.join(packageRoot, 'outputs', 'runtime'), { recursive: true }); const outFd = fs.openSync(path.join(packageRoot, 'outputs', 'runtime', 'runtime.stdout.log'), 'a'); const errFd = fs.openSync(path.join(packageRoot, 'outputs', 'runtime', 'runtime.stderr.log'), 'a'); const child = spawn(process.execPath, [runtimeScript, 'start', '--no-dashboard'], { cwd: packageRoot, detached: true, stdio: ['ignore', outFd, errFd], windowsHide: true, }); fs.closeSync(outFd); fs.closeSync(errFd); child.unref(); console.log(`[start-dashboard] 已同步拉起 callback runtime (pid=${child.pid})`); } ensureCallbackRuntime(); ensureRelayDaemon(); startServer().catch(error => { console.error('启动 Dashboard 失败:', error); process.exit(1); });