From fa2010cce6c4986b355662ca05bf97dcd3ca6f64 Mon Sep 17 00:00:00 2001 From: hebulin Date: Tue, 25 Aug 2026 11:10:23 +0800 Subject: [PATCH] fix(daemon): signal ready before SDK preload to unblock Java startup The daemon previously awaited preloadSdks() before sending the ready event, blocking the Java plugin's DaemonBridge startup for the full Claude Agent SDK import duration (potentially seconds on slow disks). Move the ready signal before preloadSdks(). The SDK is now loaded in the background; acquireRuntime() already lazy-loads via ensureQueryFn() with its own promise cache, so the first send simply waits for the in-flight load instead of blocking daemon startup. Heartbeat and status commands become available immediately. Also emit a sdk_ready event when the background preload completes, so the Java side can log the transition for diagnostics. --- ai-bridge/daemon.js | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/ai-bridge/daemon.js b/ai-bridge/daemon.js index a9f64ce7..9e26ac28 100644 --- a/ai-bridge/daemon.js +++ b/ai-bridge/daemon.js @@ -580,19 +580,29 @@ async function runDaemonMain() { platform: process.platform, }); - // Pre-load SDK - await preloadSdks(); + // Signal ready BEFORE pre-loading the SDK so the Java side can start sending + // heartbeats and status queries immediately. The SDK load is moved to + // background: acquireRuntime() already lazy-loads via ensureQueryFn() with + // its own caching, so the first send will simply wait for the in-flight load + // instead of blocking daemon startup. (#performance) + sendDaemonEvent('ready', { + pid: process.pid, + sdkPreloaded: false, // SDK is loading in the background + }); + + // Pre-load SDK in the background (non-blocking). Errors are logged but do + // not affect daemon readiness — a failed preload is retried lazily on the + // first send via ensureQueryFn(). + preloadSdks().then(() => { + sendDaemonEvent('sdk_ready', { pid: process.pid }); + }).catch((e) => { + _originalStderrWrite(`[daemon] Background SDK preload failed: ${e?.message || e}\n`, 'utf8'); + }); // Best-effort cleanup of stale temp image files (>24h). Fire-and-forget so // it doesn't block daemon readiness. cleanupStaleTempImages().catch(() => {}); - // Signal ready - sendDaemonEvent('ready', { - pid: process.pid, - sdkPreloaded, - }); - // --- Listen for requests on stdin --- const rl = createInterface({ input: process.stdin,