import log from "electron-log"; import { app, BrowserWindow } from "electron"; import { getDb, readSetting } from "../db"; import { startComputerServer } from "../services/computerServer"; import { mcpProxyManager, DEFAULT_MCP_PROXY_CONFIG, pruneDisabledDefaultMcpServers, } from "../services/packages/mcp"; import { getConfiguredPorts } from "../services/startupPorts"; import { DEPS_SYNC_TIMEOUT } from "@shared/constants"; import { startSandboxService, stopSandboxService, } from "../services/sandbox/serviceBootstrap"; /** 依赖同步是否正在进行 */ let _depsSyncInProgress = false; export function isDepsSyncInProgress(): boolean { return _depsSyncInProgress; } export async function runStartupTasks(): Promise { // 从 SQLite 恢复镜像配置 const { setMirrorConfig, getInitDepsState, syncInitDependencies, getSetupRequiredDependencies, } = await import("../services/system/dependencies"); const mirrorConfig = readSetting("mirror_config"); if (mirrorConfig) { try { setMirrorConfig(mirrorConfig); } catch (e) { log.warn("[Mirror] Failed to apply mirror config:", e); } } // 尽早启动 Computer HTTP Server(对齐 rcoder /computer/* API),端口来自聚合配置 { const { agent: agentPort } = getConfiguredPorts(); startComputerServer(agentPort).then((r) => { if (r.success) log.info(`[Init] Computer HTTP server listening on port ${agentPort}`); else log.warn(`[Init] Computer HTTP server failed: ${r.error}`); }); } // 初始化 MCP Proxy 配置(从数据库加载) try { const db = getDb(); const savedConfig = db ?.prepare("SELECT value FROM settings WHERE key = ?") .get("mcp_proxy_config") as { value: string } | undefined; if (savedConfig) { try { const parsed = JSON.parse(savedConfig.value); // 合并可用的默认服务器;旧版本持久化的 chrome-devtools npx 默认项 // 在本地未安装且未显式启用时会被过滤,避免启动时阻塞 60s。 const merged = { ...parsed, mcpServers: pruneDisabledDefaultMcpServers({ ...DEFAULT_MCP_PROXY_CONFIG.mcpServers, ...(parsed.mcpServers || {}), }), }; mcpProxyManager.setConfig(merged); } catch (e) { log.warn("[McpProxy] Init config parse failed:", e); } } log.info("[McpProxy] Config loaded"); } catch (e) { log.warn("[McpProxy] Init config failed:", e); } // 初始化沙箱服务(后台启动,不阻塞主流程) setImmediate(async () => { try { await startSandboxService(); log.info("[Sandbox] Sandbox service started"); } catch (e) { log.warn("[Sandbox] Sandbox service start failed (non-fatal):", e); // 沙箱服务失败不阻塞应用,只是功能降级 } }); // 客户端升级后:若 appVersion 或 installVersion 变化,后台同步初始化依赖到写死版本 // 同步检查是否需要 dep sync,提前设置标志,避免 renderer 在 setImmediate 之前 // 读到 syncInProgress=false 而过早启动服务(竞态条件) const state = getInitDepsState(); const currentVersion = app.getVersion(); const versionChanged = !state || state.appVersion !== currentVersion; let packagesChanged = false; if (state?.packages) { for (const dep of getSetupRequiredDependencies()) { if (!dep.installVersion) continue; if (state.packages[dep.name] !== dep.installVersion) { packagesChanged = true; break; } } } else { packagesChanged = true; } const needsSync = versionChanged || packagesChanged; if (needsSync) { _depsSyncInProgress = true; } setImmediate(async () => { if (!needsSync) return; try { try { let syncTimer: ReturnType; const { updated } = await Promise.race([ syncInitDependencies(), new Promise((_, reject) => { syncTimer = setTimeout( () => reject( new Error( `Dependency sync timeout after ${DEPS_SYNC_TIMEOUT}ms`, ), ), DEPS_SYNC_TIMEOUT, ); }), ]).finally(() => clearTimeout(syncTimer!)); if (updated.length > 0) log.info("[Init] Init dependencies synced:", updated); } finally { _depsSyncInProgress = false; // 通知所有渲染进程依赖同步完成,重新检测 for (const win of BrowserWindow.getAllWindows()) { if (!win.isDestroyed()) { win.webContents.send("deps:syncCompleted"); } } } } catch (e) { _depsSyncInProgress = false; // 同步失败也通知渲染进程重新检测实际状态 for (const win of BrowserWindow.getAllWindows()) { if (!win.isDestroyed()) { win.webContents.send("deps:syncCompleted"); } } log.warn("[Init] Init dependencies sync failed:", e); } }); }