vlcode-lite.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. #!/usr/bin/env node
  2. import { VLCodeLite } from '../src/app.js';
  3. import fs from 'fs';
  4. import os from 'os';
  5. import path from 'path';
  6. import { fileURLToPath } from 'url';
  7. const __dirname = path.dirname(fileURLToPath(import.meta.url));
  8. const crashLogPath = resolveCrashLogPath();
  9. const CRASH_LOG_MAX_BYTES = 10 * 1024 * 1024; // 10 MB
  10. function resolveCrashLogPath() {
  11. const packagedLogPath = process.env.VLCODE_LOG_DIR
  12. ? path.join(process.env.VLCODE_LOG_DIR, 'backend-crash.log')
  13. : path.join(os.homedir(), '.vl-code', 'logs', 'backend-crash.log');
  14. if (process.env.VLCODE_IS_PACKAGED === '1' || __dirname.includes('app.asar')) {
  15. return packagedLogPath;
  16. }
  17. return path.join(__dirname, '..', '.vlcode-lite', 'crash.log');
  18. }
  19. function safeConsoleError(...args) {
  20. try {
  21. console.error(...args);
  22. } catch {}
  23. }
  24. function appendCrashLog(level, msg) {
  25. const entry = `[${new Date().toISOString()}] ${level}: ${msg}\n`;
  26. try {
  27. const dir = path.dirname(crashLogPath);
  28. if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
  29. if (fs.existsSync(crashLogPath)) {
  30. const stat = fs.statSync(crashLogPath);
  31. if (stat.size > CRASH_LOG_MAX_BYTES) {
  32. const buf = fs.readFileSync(crashLogPath, 'utf-8');
  33. const keepFrom = buf.length - Math.floor(CRASH_LOG_MAX_BYTES / 2);
  34. const nextNewline = buf.indexOf('\n', keepFrom);
  35. fs.writeFileSync(crashLogPath, '[LOG ROTATED]\n' + buf.slice(nextNewline + 1));
  36. }
  37. }
  38. fs.appendFileSync(crashLogPath, entry);
  39. } catch (_) {}
  40. }
  41. process.on('uncaughtException', (err) => {
  42. const stack = err.stack || String(err);
  43. safeConsoleError('[FATAL] Uncaught exception:', stack);
  44. appendCrashLog('UNCAUGHT', stack);
  45. });
  46. process.on('unhandledRejection', (reason) => {
  47. const name = reason?.name || reason?.constructor?.name || '';
  48. const msg = reason?.message || '';
  49. if (name === 'APIUserAbortError' || name === 'AbortError' ||
  50. msg === 'Request was aborted.' || msg.includes('aborted')) return;
  51. safeConsoleError('[Server] Unhandled rejection:', msg || reason);
  52. appendCrashLog('REJECTION', msg || String(reason));
  53. });
  54. const app = new VLCodeLite();
  55. app.run(process.argv.slice(2)).catch(err => {
  56. safeConsoleError('Fatal error:', err.message);
  57. appendCrashLog('FATAL', err.stack || String(err));
  58. process.exit(1);
  59. });