feat: enhance logging capabilities, implement runtime diagnostics, and update preinstalled skills metadata
This commit is contained in:
@@ -7,7 +7,7 @@ import configManager from '@electron/service/config-service'
|
||||
import themeManager from '@electron/service/theme-service'
|
||||
import { runTaskOperationService } from '@electron/process/runTaskOperationService'
|
||||
import { initScriptStoreService } from '@electron/service/script-store-service'
|
||||
import log from 'electron-log';
|
||||
import logManager from '@electron/service/logger';
|
||||
import 'bytenode'; // Ensure bytenode is bundled/externalized correctly
|
||||
import { appUpdater } from '@electron/service/updater';
|
||||
import axios from 'axios';
|
||||
@@ -21,9 +21,19 @@ import { applyLaunchAtStartupSetting, syncLaunchAtStartupSettingFromConfig } fro
|
||||
import { ensureBuiltinSkillsInstalled, ensurePreinstalledSkillsInstalled } from '@electron/utils/skill-config';
|
||||
import { initTelemetry, shutdownTelemetry } from '@electron/utils/telemetry';
|
||||
import { syncGatewayConfigBeforeLaunch } from '@electron/gateway/config-sync';
|
||||
import { installRuntimeDiagnostics, logStartupCheckpoint, startLocalCrashReporter } from '@electron/utils/runtime-diagnostics';
|
||||
|
||||
// 初始化 updater,确保在 app ready 之前或者之中注册好 IPC
|
||||
appUpdater.init();
|
||||
startLocalCrashReporter();
|
||||
installRuntimeDiagnostics();
|
||||
logStartupCheckpoint('main-module-loaded');
|
||||
|
||||
try {
|
||||
appUpdater.init();
|
||||
logStartupCheckpoint('app-updater-initialized');
|
||||
} catch (error) {
|
||||
logManager.captureException('Failed to initialize app updater', error);
|
||||
}
|
||||
|
||||
// 注册 hostapi:fetch IPC 代理
|
||||
// 模型管理相关接口在本地处理(对齐 ClawX),其余接口代理到远端后端
|
||||
@@ -48,7 +58,7 @@ function refreshProviderRuntime(): { warnings: string[] } {
|
||||
try {
|
||||
return syncProviderRuntimeSnapshot();
|
||||
} catch (error) {
|
||||
log.error('provider runtime sync failed', error);
|
||||
logManager.captureException('provider runtime sync failed', error);
|
||||
return {
|
||||
warnings: [error instanceof Error ? error.message : String(error)],
|
||||
};
|
||||
@@ -237,12 +247,12 @@ function bindGatewayLifecycleEvents(): void {
|
||||
}
|
||||
|
||||
function requestQuitOnSignal(signal: NodeJS.Signals): void {
|
||||
log.info(`Received ${signal}; requesting app quit`);
|
||||
logManager.info(`Received ${signal}; requesting app quit`);
|
||||
app.quit();
|
||||
}
|
||||
|
||||
function emergencyGatewayCleanup(reason: string, error: unknown): void {
|
||||
log.error(`${reason}:`, error);
|
||||
logManager.captureException(reason, error);
|
||||
hostEventBus.closeAll();
|
||||
void closeHostApiServer().catch(() => {
|
||||
// ignore host API server close failures during emergency cleanup
|
||||
@@ -321,14 +331,14 @@ app.on('before-quit', (event) => {
|
||||
gatewayQuitCleanupInProgress = true;
|
||||
hostEventBus.closeAll();
|
||||
const closeServerPromise = closeHostApiServer().catch((error) => {
|
||||
log.warn('Host API server close failed during quit:', error);
|
||||
logManager.captureException('Host API server close failed during quit', error);
|
||||
});
|
||||
|
||||
const stopPromise = Promise.all([
|
||||
closeServerPromise,
|
||||
gatewayManager.stop(),
|
||||
]).catch((error) => {
|
||||
log.warn('gatewayManager.stop() error during quit:', error);
|
||||
logManager.captureException('gatewayManager.stop() error during quit', error);
|
||||
});
|
||||
const timeoutPromise = new Promise<'timeout'>((resolve) => {
|
||||
setTimeout(() => resolve('timeout'), GATEWAY_QUIT_TIMEOUT_MS);
|
||||
@@ -339,38 +349,43 @@ app.on('before-quit', (event) => {
|
||||
timeoutPromise,
|
||||
]).then(async (result) => {
|
||||
if (result === 'timeout') {
|
||||
log.warn('Gateway shutdown timed out during app quit; proceeding with forced quit');
|
||||
logManager.warn('Gateway shutdown timed out during app quit; proceeding with forced quit');
|
||||
try {
|
||||
const terminated = await gatewayManager.forceTerminateOwnedProcessForQuit();
|
||||
if (terminated) {
|
||||
log.warn('Forced gateway process termination completed after quit timeout');
|
||||
logManager.warn('Forced gateway process termination completed after quit timeout');
|
||||
}
|
||||
} catch (error) {
|
||||
log.warn('Forced gateway termination failed after quit timeout:', error);
|
||||
logManager.captureException('Forced gateway termination failed after quit timeout', error);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await shutdownTelemetry();
|
||||
} catch (error) {
|
||||
log.warn('Telemetry shutdown failed during app quit:', error);
|
||||
logManager.captureException('Telemetry shutdown failed during app quit', error);
|
||||
}
|
||||
|
||||
gatewayQuitCleanupCompleted = true;
|
||||
app.quit();
|
||||
}).catch((error) => {
|
||||
gatewayQuitCleanupInProgress = false;
|
||||
log.warn('Gateway quit cleanup failed:', error);
|
||||
logManager.captureException('Gateway quit cleanup failed', error);
|
||||
gatewayQuitCleanupCompleted = true;
|
||||
app.quit();
|
||||
});
|
||||
});
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
logStartupCheckpoint('app-ready');
|
||||
await configManager.init();
|
||||
logStartupCheckpoint('config-initialized');
|
||||
await syncLaunchAtStartupSettingFromConfig();
|
||||
logStartupCheckpoint('launch-at-startup-synced');
|
||||
await themeManager.init();
|
||||
logStartupCheckpoint('theme-initialized');
|
||||
await initTelemetry();
|
||||
logStartupCheckpoint('telemetry-initialized');
|
||||
bindGatewayLifecycleEvents();
|
||||
|
||||
try {
|
||||
@@ -386,8 +401,9 @@ app.whenReady().then(async () => {
|
||||
);
|
||||
},
|
||||
});
|
||||
logStartupCheckpoint('host-api-server-started');
|
||||
} catch (error) {
|
||||
log.error('Failed to start Host API server:', error);
|
||||
logManager.captureException('Failed to start Host API server', error);
|
||||
}
|
||||
|
||||
let launchAtStartup = Boolean(configManager.get(CONFIG_KEYS.LAUNCH_AT_STARTUP));
|
||||
@@ -409,23 +425,25 @@ app.whenReady().then(async () => {
|
||||
});
|
||||
|
||||
void ensureBuiltinSkillsInstalled().catch((error) => {
|
||||
log.warn('Failed to install built-in skills:', error);
|
||||
logManager.captureException('Failed to install built-in skills', error);
|
||||
});
|
||||
|
||||
void ensurePreinstalledSkillsInstalled().catch((error) => {
|
||||
log.warn('Failed to install preinstalled skills:', error);
|
||||
logManager.captureException('Failed to install preinstalled skills', error);
|
||||
});
|
||||
|
||||
try {
|
||||
await syncGatewayConfigBeforeLaunch();
|
||||
logStartupCheckpoint('gateway-config-synced');
|
||||
} catch (error) {
|
||||
log.warn('Failed to sync OpenClaw config before launch:', error);
|
||||
logManager.captureException('Failed to sync OpenClaw config before launch', error);
|
||||
}
|
||||
|
||||
refreshProviderRuntime();
|
||||
void gatewayManager.init().catch((error) => {
|
||||
log.warn('Failed to initialize GatewayManager:', error);
|
||||
logManager.captureException('Failed to initialize GatewayManager', error);
|
||||
});
|
||||
logStartupCheckpoint('gateway-init-requested');
|
||||
|
||||
onProviderChange(() => {
|
||||
const runtimeSync = refreshProviderRuntime();
|
||||
@@ -437,14 +455,20 @@ app.whenReady().then(async () => {
|
||||
});
|
||||
|
||||
setupMainWindow();
|
||||
logStartupCheckpoint('main-window-requested');
|
||||
|
||||
// 初始化脚本存储服务
|
||||
initScriptStoreService()
|
||||
logStartupCheckpoint('script-store-initialized');
|
||||
|
||||
// 开启任务操作子进程
|
||||
runTaskOperationService()
|
||||
logStartupCheckpoint('task-operation-service-started');
|
||||
|
||||
// 开启subagent子进程
|
||||
}).catch((error) => {
|
||||
logManager.captureException('Fatal error during app bootstrap', error);
|
||||
emergencyGatewayCleanup('Fatal error during app bootstrap', error);
|
||||
});
|
||||
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
@@ -452,7 +476,7 @@ app.whenReady().then(async () => {
|
||||
// explicitly with Cmd + Q.
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin' && !configManager.get(CONFIG_KEYS.MINIMIZE_TO_TRAY)) {
|
||||
log.info('app closing due to all windows being closed');
|
||||
logManager.info('app closing due to all windows being closed');
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user