From 3e8ca9cfeba6681055ae5856f57fee9c764bc9be Mon Sep 17 00:00:00 2001 From: chenydev Date: Sun, 9 Aug 2026 00:44:48 +0800 Subject: [PATCH] fix(pi-fff): cache sdk import across reloads to avoid hang Pi reloads extension modules with jiti moduleCache:false, so loadSdk() re-executes a dynamic import of the fff-bun module graph on every /reload. The fff-bun graph top-level awaits a type:file import of the native .so, which never resolves when re-imported inside the Bun-compiled pi binary, leaving the reload screen stuck forever (pi awaits session_start handlers without a timeout). Cache the first import on globalThis so reloads reuse it. Closes #757 --- packages/pi-fff/src/sdk.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/pi-fff/src/sdk.ts b/packages/pi-fff/src/sdk.ts index 8299ea01..af2d1620 100644 --- a/packages/pi-fff/src/sdk.ts +++ b/packages/pi-fff/src/sdk.ts @@ -22,8 +22,21 @@ function detectRuntime(): "bun" | "node" { export function loadSdk(): Promise<{ FileFinder: FileFinderStatic }> { if (sdkPromise) return sdkPromise; + // Pi reloads extension modules with jiti moduleCache:false, so this module + // is re-executed on every /reload. Re-importing the fff-bun module graph + // (which top-level awaits a `type: "file"` import of the native .so) hangs + // forever inside the Bun-compiled pi binary. Cache the first import on + // globalThis so reloads reuse the resolved module instead of re-importing. + const g = globalThis as Record; + if (g.__fffSdkPromiseGlobal) { + sdkPromise = g.__fffSdkPromiseGlobal as Promise<{ FileFinder: FileFinderStatic }>; + return sdkPromise; + } + // default to node as it seems like default option const pkg = detectRuntime() === "bun" ? "@ff-labs/fff-bun" : "@ff-labs/fff-node"; - sdkPromise = import(pkg) as Promise<{ FileFinder: FileFinderStatic }>; - return sdkPromise; + const p = import(pkg) as Promise<{ FileFinder: FileFinderStatic }>; + sdkPromise = p; + (globalThis as Record).__fffSdkPromiseGlobal = p; + return p; }