From 0760787f9a7eef258ac28934c65c246a62ea3490 Mon Sep 17 00:00:00 2001 From: Tom X Nguyen Date: Fri, 12 Jun 2026 21:31:40 +0700 Subject: [PATCH 1/2] fix(pi-fff): persist fff-mode across /reload and session resume The /fff-mode command only mutated an in-memory variable that was lost on /reload and session restart. Now the selected mode is persisted using two complementary mechanisms: - process.env.PI_FFF_MODE: survives /reload (process stays alive, the factory already reads this env var on init) - pi.appendEntry('fff-mode', { mode }): survives process restart via the session file; restored on session_start and used to set the env var for subsequent reloads The "requires restart" notice is updated to "requires /reload" since that now actually works. --- packages/pi-fff/src/index.ts | 37 ++++++++++++++++++++++++-- packages/pi-fff/test/extension.test.ts | 1 + 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/packages/pi-fff/src/index.ts b/packages/pi-fff/src/index.ts index 1947d718..89e1e321 100644 --- a/packages/pi-fff/src/index.ts +++ b/packages/pi-fff/src/index.ts @@ -467,6 +467,31 @@ export default function fffExtension(pi: ExtensionAPI) { pi.on("session_start", async (_event, ctx) => { try { activeCwd = ctx.cwd; + + // Restore persisted mode from session entries. This handles session + // resume after process restart where env vars are lost, and ensures + // the env var is set for the next /reload in the same session. + const entries = ctx.sessionManager?.getEntries(); + if (entries) { + const modeEntry = [...entries] + .reverse() + .find( + (e: { type: string; customType?: string }) => + e.type === "custom" && e.customType === "fff-mode", + ); + if ( + modeEntry && + typeof (modeEntry as any).data?.mode === "string" && + VALID_MODES.includes((modeEntry as any).data.mode as FffMode) + ) { + const restored = (modeEntry as any).data.mode as FffMode; + if (restored !== currentMode) { + currentMode = restored; + process.env.PI_FFF_MODE = restored; + } + } + } + registerAutocompleteProvider(ctx); await ensureFinder(activeCwd); } catch (e: unknown) { @@ -921,7 +946,10 @@ export default function fffExtension(pi: ExtensionAPI) { const mode = getMode(); const flag = pi.getFlag("fff-mode") ?? "unset"; const env = process.env.PI_FFF_MODE ?? "unset"; - ctx.ui.notify(`Current mode: '${mode}'\nFlag: ${flag}, Env: ${env}`, "info"); + ctx.ui.notify( + `Current mode: '${mode}'\nFlag: ${flag}, Env: ${env}`, + "info", + ); return; } @@ -935,9 +963,14 @@ export default function fffExtension(pi: ExtensionAPI) { const oldMode = getMode(); setMode(newMode); + // Persist so the mode survives /reload (process survives) and + // session resume (entry survives in the session file). + process.env.PI_FFF_MODE = newMode; + pi.appendEntry("fff-mode", { mode: newMode }); + const note = (oldMode === "override") !== (newMode === "override") - ? " (tool name change requires restart)" + ? " (tool name change requires /reload)" : ""; ctx.ui.notify(`Mode changed: '${oldMode}' → '${newMode}'${note}`, "info"); }, diff --git a/packages/pi-fff/test/extension.test.ts b/packages/pi-fff/test/extension.test.ts index 4293f89e..1fa80ef4 100644 --- a/packages/pi-fff/test/extension.test.ts +++ b/packages/pi-fff/test/extension.test.ts @@ -93,6 +93,7 @@ function createPi(mode?: string) { }), registerFlag: mock(() => undefined), registerTool: mock(() => undefined), + appendEntry: mock(() => undefined), }; return { pi, events, commands }; From 651986ba9806594a0d7a38a79c6edf6c59743156 Mon Sep 17 00:00:00 2001 From: Tom X Nguyen Date: Sat, 13 Jun 2026 00:59:09 +0700 Subject: [PATCH 2/2] fix(pi-fff): remove process.env mutation, use appendEntry only for mode persistence --- packages/pi-fff/src/index.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/pi-fff/src/index.ts b/packages/pi-fff/src/index.ts index 89e1e321..7c8091f4 100644 --- a/packages/pi-fff/src/index.ts +++ b/packages/pi-fff/src/index.ts @@ -487,7 +487,6 @@ export default function fffExtension(pi: ExtensionAPI) { const restored = (modeEntry as any).data.mode as FffMode; if (restored !== currentMode) { currentMode = restored; - process.env.PI_FFF_MODE = restored; } } } @@ -945,9 +944,8 @@ export default function fffExtension(pi: ExtensionAPI) { if (!arg) { const mode = getMode(); const flag = pi.getFlag("fff-mode") ?? "unset"; - const env = process.env.PI_FFF_MODE ?? "unset"; ctx.ui.notify( - `Current mode: '${mode}'\nFlag: ${flag}, Env: ${env}`, + `Current mode: '${mode}' (flag: ${flag})`, "info", ); return; @@ -963,9 +961,6 @@ export default function fffExtension(pi: ExtensionAPI) { const oldMode = getMode(); setMode(newMode); - // Persist so the mode survives /reload (process survives) and - // session resume (entry survives in the session file). - process.env.PI_FFF_MODE = newMode; pi.appendEntry("fff-mode", { mode: newMode }); const note =