'use strict'; // 環境檢查:start 前確認 codex CLI、pm2、git 等工具是否就緒。 const { execSync } = require('child_process'); const fs = require('fs'); const os = require('os'); const path = require('path'); function tryExec(cmd) { try { return execSync(cmd, { encoding: 'utf-8', windowsHide: true, stdio: ['ignore', 'pipe', 'ignore'], timeout: 15000 }).trim(); } catch { return null; } } // 回傳 [{ name, ok, required, message }] function runChecks() { const checks = []; const nodeMajor = Number(process.versions.node.split('.')[0]); checks.push({ name: 'Node.js', ok: nodeMajor >= 18, required: true, message: nodeMajor >= 18 ? process.version : `${process.version}(需要 ≥ 18)`, }); const codexVer = tryExec('codex --version'); checks.push({ name: 'Codex CLI', ok: !!codexVer, required: true, message: codexVer || '找不到 codex,請安裝:npm install -g @openai/codex', }); if (codexVer) { const authFile = path.join(os.homedir(), '.codex', 'auth.json'); const loggedIn = fs.existsSync(authFile); checks.push({ name: 'Codex 登入', ok: loggedIn, required: false, message: loggedIn ? '已登入' : '尚未登入,請先執行:codex login(bot 啟動後才需要)', }); } const pm2Ver = tryExec('pm2 -v'); checks.push({ name: 'pm2', ok: !!pm2Ver, required: true, message: pm2Ver ? `v${pm2Ver.split('\n').pop()}` : '找不到 pm2,請安裝:npm install -g pm2', }); const gitVer = tryExec('git --version'); checks.push({ name: 'git', ok: !!gitVer, required: false, message: gitVer || '找不到 git(非必要:bot 以 --skip-git-repo-check 執行,但 Codex 要做版控操作時會需要)', }); return checks; } function printChecks(checks) { for (const c of checks) { const icon = c.ok ? '✅' : c.required ? '❌' : '⚠️'; console.log(`${icon} ${c.name}:${c.message}`); } } function hasBlocker(checks) { return checks.some((c) => c.required && !c.ok); } module.exports = { runChecks, printChecks, hasBlocker };