From 5f4f7834300658df87c47bd061e8ffb904a2bd06 Mon Sep 17 00:00:00 2001 From: gustav-fff <286169375+gustav-fff@users.noreply.github.com> Date: Sun, 5 Jul 2026 17:00:12 -0700 Subject: [PATCH] fix(pi-fff): feature-detect ctx.ui.addAutocompleteProvider (#651) pi forks (e.g. omp) do not expose addAutocompleteProvider, causing session_start to throw "FFF init failed: ... is not a function" and skipping tool registration entirely. Skip UI wiring when the host lacks the method; tools still register. Refs #651 --- packages/pi-fff/src/index.ts | 6 +++++- packages/pi-fff/test/extension.test.ts | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/pi-fff/src/index.ts b/packages/pi-fff/src/index.ts index f8f65c0cb..86eff2329 100644 --- a/packages/pi-fff/src/index.ts +++ b/packages/pi-fff/src/index.ts @@ -403,11 +403,15 @@ export default function fffExtension(pi: ExtensionAPI) { function registerAutocompleteProvider(ctx: { ui: { - addAutocompleteProvider: ( + addAutocompleteProvider?: ( factory: (current: AutocompleteProvider) => AutocompleteProvider, ) => void; }; }) { + // pi forks (e.g. omp) may not expose addAutocompleteProvider; skip UI wiring + // and let tools continue to work instead of failing session_start. + if (typeof ctx.ui.addAutocompleteProvider !== "function") return; + ctx.ui.addAutocompleteProvider((current) => { const mentionProvider = createFffMentionProvider(getMentionItems); diff --git a/packages/pi-fff/test/extension.test.ts b/packages/pi-fff/test/extension.test.ts index 1fa80ef40..3695a84e0 100644 --- a/packages/pi-fff/test/extension.test.ts +++ b/packages/pi-fff/test/extension.test.ts @@ -161,6 +161,24 @@ describe("pi-fff autocomplete registration", () => { ]); }); + test("session_start survives hosts without addAutocompleteProvider", async () => { + const setup = createPi(); + const ctx = { + cwd: "/tmp/workspace", + ui: { + notify: mock(() => undefined), + setEditorComponent: mock(() => undefined), + }, + }; + fffExtension(setup.pi as any); + + const sessionStart = setup.events.get("session_start"); + await sessionStart?.({ reason: "startup" }, ctx); + + expect(ctx.ui.notify).not.toHaveBeenCalled(); + expect(createCalls).toHaveLength(1); + }); + test("delegates non-@ completions to the current provider", async () => { const { ctx } = await start(); const factory = ctx.ui.addAutocompleteProvider.mock.calls[0][0];