diff --git a/apps/cli/src/cli.ts b/apps/cli/src/cli.ts index 7e6bd9fb..2a124ceb 100644 --- a/apps/cli/src/cli.ts +++ b/apps/cli/src/cli.ts @@ -17,6 +17,7 @@ import { verifyCliDataPath, initAppLogger, appLogger, + getSystemLogsDir, } from '@openchatlab/node-runtime' import { getSessionMeta, @@ -486,7 +487,7 @@ program console.log('\nChatLab Status') console.log('─'.repeat(36)) - console.log(` Logs: ${new NodePathProvider().getLogsDir()}`) + console.log(` Logs: ${getSystemLogsDir()}`) if (svc.installed) { const portStr = svc.port ? `http://${svc.host ?? '127.0.0.1'}:${svc.port}` : '' @@ -611,14 +612,16 @@ function printTable(columns: string[], rows: Record[]): void { /** CLI entry function */ export function run(argv?: string[]): void { // Logs go to ~/.chatlab/logs/app.log regardless of configured user data dir. - initAppLogger(new NodePathProvider().getLogsDir()) + initAppLogger(getSystemLogsDir()) process.on('uncaughtException', (error) => { console.error('Uncaught Exception:', error) appLogger.error('crash', 'uncaughtException', error) + process.exit(1) }) process.on('unhandledRejection', (reason) => { console.error('Unhandled Rejection:', reason) appLogger.error('crash', 'unhandledRejection', reason) + process.exit(1) }) program.parse(argv) } diff --git a/apps/desktop/main/index.ts b/apps/desktop/main/index.ts index 4b5fe132..7a8a6fcb 100644 --- a/apps/desktop/main/index.ts +++ b/apps/desktop/main/index.ts @@ -429,12 +429,14 @@ process.on('uncaughtException', (error) => { logger.error( `Uncaught Exception: ${error instanceof Error ? `${error.message}\n${error.stack ?? ''}` : String(error)}` ) + process.exit(1) }) process.on('unhandledRejection', (reason) => { console.error('Unhandled Rejection:', reason) logger.error( `Unhandled Rejection: ${reason instanceof Error ? `${reason.message}\n${reason.stack ?? ''}` : String(reason)}` ) + process.exit(1) }) new MainProcess() diff --git a/packages/node-runtime/src/index.ts b/packages/node-runtime/src/index.ts index b191d852..43a864a2 100644 --- a/packages/node-runtime/src/index.ts +++ b/packages/node-runtime/src/index.ts @@ -59,6 +59,7 @@ export { NodePathProvider, applyPendingNodeDataDirMigrationIfNeeded, getDefaultNodeUserDataDir, + getSystemLogsDir, hasPendingElectronDataWarning, } from './node-path-provider' export { DatabaseManager } from './database-manager' diff --git a/packages/node-runtime/src/logging/app-logger.ts b/packages/node-runtime/src/logging/app-logger.ts index d045cd61..b6893ae6 100644 --- a/packages/node-runtime/src/logging/app-logger.ts +++ b/packages/node-runtime/src/logging/app-logger.ts @@ -55,11 +55,11 @@ class AppLogger { if (LEVEL_ORDER[level] < LEVEL_ORDER[this.threshold]) return let line = `[${new Date().toISOString()}] [${level}] [${scope}] ${message}` - const tail = formatData(data) - if (tail) line += `\n${tail}` - line += '\n' try { + const tail = formatData(data) + if (tail) line += `\n${tail}` + line += '\n' ensureDir(path.dirname(this.logFile)) this.rotateIfNeeded() fs.appendFileSync(this.logFile, line, 'utf-8') diff --git a/packages/node-runtime/src/node-path-provider.ts b/packages/node-runtime/src/node-path-provider.ts index 97591627..ae2fedd3 100644 --- a/packages/node-runtime/src/node-path-provider.ts +++ b/packages/node-runtime/src/node-path-provider.ts @@ -150,6 +150,10 @@ export function getDefaultNodeUserDataDir(): string { return path.join(os.homedir(), '.chatlab', 'data') } +export function getSystemLogsDir(): string { + return path.join(SYSTEM_DIR, 'logs') +} + function expandHome(filePath: string): string { if (filePath.startsWith('~/') || filePath === '~') { return path.join(os.homedir(), filePath.slice(1)) diff --git a/src/services/log-report.ts b/src/services/log-report.ts index 90f54569..eec64ea5 100644 --- a/src/services/log-report.ts +++ b/src/services/log-report.ts @@ -30,7 +30,7 @@ export function reportError(message: string, stack?: string): void { const key = `${message}::${stack?.split('\n')[1] ?? ''}` if (!shouldReport(key)) return // Fire-and-forget; never let reporting throw or block the UI. - void post('/_web/logs/report', { + void post('/logs/report', { level: 'error', message, stack,