diff --git a/.changeset/fifty-lobsters-remain.md b/.changeset/fifty-lobsters-remain.md new file mode 100644 index 00000000..16b21276 --- /dev/null +++ b/.changeset/fifty-lobsters-remain.md @@ -0,0 +1,5 @@ +--- +"@proofkit/cli": patch +--- + +Fix FileMaker webviewer init flow to install local addon files before prompting that no FileMaker file is open in the local MCP server. diff --git a/packages/cli/src/core/context.ts b/packages/cli/src/core/context.ts index 7a5667e0..ef37bfa7 100644 --- a/packages/cli/src/core/context.ts +++ b/packages/cli/src/core/context.ts @@ -164,6 +164,7 @@ export interface FileMakerBootstrapArtifacts { export interface FileMakerService { readonly detectLocalFmMcp: (baseUrl?: string) => Eff; + readonly installLocalWebViewerAddon: () => Eff; readonly validateHostedServerUrl: ( serverUrl: string, ottoPort?: number | null, diff --git a/packages/cli/src/core/resolveInitRequest.ts b/packages/cli/src/core/resolveInitRequest.ts index 832e5e2f..41dcd669 100644 --- a/packages/cli/src/core/resolveInitRequest.ts +++ b/packages/cli/src/core/resolveInitRequest.ts @@ -464,6 +464,7 @@ function resolveFileMakerInputs({ while (true) { const localFmMcp = yield* fileMakerService.detectLocalFmMcp(); + yield* fileMakerService.installLocalWebViewerAddon(); const selectedFile = localFmMcp.healthy ? yield* resolveLocalFmMcpFile(localFmMcp.connectedFiles) : undefined; if (localFmMcp.healthy && selectedFile) { console.info(`Using local ProofKit MCP file: ${selectedFile}`); diff --git a/packages/cli/src/services/live.ts b/packages/cli/src/services/live.ts index cea4082e..d63807ea 100644 --- a/packages/cli/src/services/live.ts +++ b/packages/cli/src/services/live.ts @@ -24,6 +24,7 @@ import { } from "~/core/context.js"; import { ExternalCommandError, FileMakerSetupError, FileSystemError, UserCancelledError } from "~/core/errors.js"; import type { AppType, FileMakerInputs, ProofKitSettings, UIType } from "~/core/types.js"; +import { installFmAddonExplicitly } from "~/installers/install-fm-addon.js"; import { openBrowser } from "~/utils/browserOpen.js"; import { deleteJson, getJson, postJson } from "~/utils/http.js"; import { detectUserPackageManager } from "~/utils/packageManager.js"; @@ -357,6 +358,17 @@ const fileMakerService = { cause, }), }), + installLocalWebViewerAddon: () => + Effect.tryPromise({ + try: async () => { + await installFmAddonExplicitly({ addonName: "wv" }); + }, + catch: (cause) => + new FileMakerSetupError({ + message: "Unable to install local ProofKit WebViewer add-on files.", + cause, + }), + }).pipe(Effect.asVoid), validateHostedServerUrl: (serverUrl: string, ottoPort?: number | null) => Effect.gen(function* () { const normalizedUrl = normalizeUrl(serverUrl); diff --git a/packages/cli/tests/resolve-init.test.ts b/packages/cli/tests/resolve-init.test.ts index bbaae7f9..290f1e47 100644 --- a/packages/cli/tests/resolve-init.test.ts +++ b/packages/cli/tests/resolve-init.test.ts @@ -392,6 +392,13 @@ describe("resolveInitRequest", () => { multiSearchSelect: [], confirm: [], }; + const tracker = { + commands: [], + gitInits: 0, + codegens: 0, + filemakerBootstraps: 0, + addonInstalls: 0, + }; const request = await Effect.runPromise( resolveInitRequest("demo", { @@ -408,6 +415,7 @@ describe("resolveInitRequest", () => { cwd: "/tmp", packageManager: "pnpm", nonInteractive: false, + tracker, prompts: { select: ["skip"], }, @@ -424,6 +432,7 @@ describe("resolveInitRequest", () => { expect(request.fileMaker).toBeUndefined(); expect(request.skipFileMakerSetup).toBe(true); + expect(tracker.addonInstalls).toBe(1); expect(promptTranscript.select).toContainEqual({ message: "ProofKit MCP Server is running, but no FileMaker file is open yet. Open one, then choose how to continue.", @@ -439,6 +448,13 @@ describe("resolveInitRequest", () => { success: [], note: [], }; + const tracker = { + commands: [], + gitInits: 0, + codegens: 0, + filemakerBootstraps: 0, + addonInstalls: 0, + }; const request = await Effect.runPromise( resolveInitRequest("demo", { @@ -455,6 +471,7 @@ describe("resolveInitRequest", () => { cwd: "/tmp", packageManager: "pnpm", nonInteractive: false, + tracker, prompts: { select: ["retry"], }, @@ -479,6 +496,7 @@ describe("resolveInitRequest", () => { mode: "local-fm-mcp", fileName: "RetryConnected.fmp12", }); + expect(tracker.addonInstalls).toBe(2); expect(consoleTranscript.info).toContain("Using local ProofKit MCP file: RetryConnected.fmp12"); }); diff --git a/packages/cli/tests/test-layer.ts b/packages/cli/tests/test-layer.ts index 0624dcb9..ae5650c6 100644 --- a/packages/cli/tests/test-layer.ts +++ b/packages/cli/tests/test-layer.ts @@ -64,6 +64,7 @@ export function makeTestLayer(options: { gitInits: number; codegens: number; filemakerBootstraps: number; + addonInstalls?: number; }; fileMaker?: { localFmMcp?: @@ -400,6 +401,12 @@ export function makeTestLayer(options: { connectedFiles: next?.connectedFiles ?? [], }); }, + installLocalWebViewerAddon: () => { + if (tracker) { + tracker.addonInstalls = (tracker.addonInstalls ?? 0) + 1; + } + return Effect.void; + }, validateHostedServerUrl: (serverUrl: string) => { if (options.failures?.validateHostedServerUrl) { return Effect.fail(options.failures.validateHostedServerUrl as FileMakerSetupError);