Commit Graph

12 Commits

Author SHA1 Message Date
gsxdsm
7568705244 fix(desktop): boot embedded Postgres in packaged app and ship omp dist (#2106)
## Summary

Packaged Fusion desktop Local mode failed after the SQLite→Postgres
cutover:

1. **Embedded Postgres** could not start from `app.asar` — platform
packages resolve `initdb`/`postgres` via `import.meta.url` into the asar
virtual path, and `spawn` fails with `ENOTDIR`.
2. **After Postgres was fixed**, Local mode still fell back to the mode
chooser because `@fusion-plugin-examples/omp-runtime` was never built
into `dist/` (dashboard imports it from `runtime-provider-probes.ts`).

This PR makes packaged Local mode boot embedded Postgres reliably and
keep the dashboard shell up.

### Changes

- **CJS bootstrap** (`main-bootstrap.cjs`) as Electron `main`: patches
`child_process.spawn` / `fs.promises.stat|chmod` before the ESM main
loads so asar binary paths rewrite to real files.
- **Materialize** the full native PG install (`bin` + `lib` + `share`)
under `~/.fusion/embedded-postgres/runtime-bin/<plat-arch>/`.
- **electron-builder**: full `asarUnpack` of embedded-postgres packages;
allowlist PG deps and `@fusion-plugin-examples/**/*` (+ plugin-sdk / ACP
SDK).
- **Build** `fusion-plugin-omp-runtime` with the other dashboard-static
runtime plugins; export `DASHBOARD_RUNTIME_PLUGIN_PACKAGES` for tests.
- Unit coverage for asar path rewrite, packaging allowlists, and omp
build inclusion.

## Test plan

- [x] `pnpm --filter @fusion/core test:embedded-postgres` (23/23)
- [x] Desktop packaging unit tests (`build-bundling`,
`electron-builder-config`)
- [x] Packaged macOS `Fusion.app` Local mode:
  - [x] `embedded postgres: ready on port … (database "fusion")`
  - [x] `desktopMode` stays `"local"` (no chooser fallback)
- [x] `GET /api/health` → `status: ok`, `database.healthy: true`,
`engine.available: true`
- [x] Linux embedded binary lifecycle smoke (Docker aarch64,
`@embedded-postgres/linux-arm64`) — initdb/start/persist/restart
- [ ] CI release desktop jobs (macOS/Linux) when this lands
- [ ] Windows packaged desktop Local + PG (separate agent / host)

## Verification notes

| Platform | Embedded Postgres | Packaged Local shell |
|----------|-------------------|----------------------|
| macOS | Working | Working after this PR |
| Linux | Native binary smoke pass | Full AppImage not built on this
host |
| Windows | Out of scope here | Separate verification |

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Improved embedded PostgreSQL reliability in Electron-packaged apps by
rewriting bundled `app.asar` binary paths to their unpacked/materialized
locations.
* Ensured embedded PostgreSQL runtime binaries resolve correctly across
platforms/architectures, with best-effort executable permissions and
macOS dylib link normalization.

* **Packaging**
* Updated the desktop Electron entry to use a bootstrap module for
embedded PostgreSQL binary resolution.
* Expanded Electron Builder inclusion and asar-unpack rules for
embedded-postgres and related packages, plus required runtime plugin/sdk
assets.

* **Tests**
* Updated and added checks to match the new packaging and plugin/runtime
expectations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-14 20:44:09 -07:00
gsxdsm
1b9dce22c0 fix(desktop): harden embedded Postgres packaging 2026-07-14 09:47:41 -07:00
gsxdsm
c3c3861efa fix: stale TRANSITIVE_EXTERNALS + dashboard dist/client clean + cross-worker build lock (round 12) (#2065)
## Summary

Fixes shard 3 failures from runs 29258546612 + 29259574946 (FN-7936
drift).

## Fixes

### `package-config.test.ts` — stale TRANSITIVE_EXTERNALS entry
FN-7936 aliased `@fusion/core` to a runtime shim in bundled plugin
outputs; it's no longer a tsup external. Removed the stale allowlist
entry.

### `bundle-output.test.ts` — stale dashboard client hash ENOENT
**Root cause:** Two test files (`bundle-output.test.ts` +
`extension-integration.test.ts`) call
`buildCliWithRealDashboardAssets()` which triggers concurrent vite/tsup
builds. Vitest runs them in parallel (`pool: "forks"`, `fileParallelism:
true`). Without coordination, two builds clean and write `dist/client`
simultaneously, causing `ENOENT` on content-hashed chunk files.

**Fix (3 parts):**
1. **`workspace-tools.ts buildDashboardClient`** — `rm dist/client`
before vite build. Prevents stale content-hash references from previous
builds.
2. **`bundle-output-helpers.ts`** — atomic `mkdirSync` file lock around
`buildCliWithRealDashboardAssets()`. Winner builds; losers poll with
`Atomics.wait`, then re-check `hasBuiltDashboardAssets()`. On timeout,
**throws** (never builds without owning the lock).
3. Lock uses `Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0,
0, 500)` for sync sleep — no child process spawning.

## Verification
- Gate: exit 0 ✅

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Improved dashboard asset builds by removing stale files before
rebuilding.
* Prevented concurrent builds from producing incomplete or corrupted
dashboard assets.
* Added safeguards to detect stalled asset builds and fail with clearer
errors.

* **Tests**
* Updated package validation checks to reflect current runtime bundling
behavior.
  * Improved reliability of CLI build-related test execution.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-13 08:14:20 -07:00
gsxdsm
081dae0e0f FN-7705: Add Grok CLI runtime support as a bundled plugin
Adds a new bundled Grok CLI runtime plugin, wiring it end-to-end into settings, auth routes, model discovery, and the dashboard authentication UI.

- New `fusion-plugin-grok-runtime` package with CLI spawn, probe, provider, process-manager, and runtime-adapter modules plus tests
- Bundled-plugin install list (CLI + core) updated to auto-install the grok-cli plugin
- New `useGrokCli`/`grokCliBinaryPath` settings in `settings-schema.ts` and `types.ts`
- Dashboard: `GrokCliProviderCard` component/styles, `ProviderIcon` grok entry, `AuthenticationSection` wiring
- New `grok-model-cache.ts` for caching `grok models` discovery results, registered model/auth routes for `/auth/grok-cli` and `/providers/grok-cli/status`, merged into `/api/models`
- `runtime-provider-probes.ts` extended with Grok CLI probe/model-discovery delegation
- Docs updated (`PLUGIN_AUTHORING.md`, `settings-reference.md`) and changeset added (minor, feature)
- Workspace config (`pnpm-workspace.yaml`, `pnpm-lock.yaml`) updated to register the new plugin package

Files changed:
 .changeset/fn-7705-grok-cli-runtime.md             |   7 +
 docs/PLUGIN_AUTHORING.md                           |   2 +-
 docs/settings-reference.md                         |   4 +
 packages/cli/src/plugins/bundled-plugin-install.ts |   8 +
 .../cli/src/plugins/staged-bundled-plugin-ids.ts   |   1 +
 packages/cli/vitest.config.ts                      |  12 +
 .../core/src/__tests__/grok-cli-settings.test.ts   |  34 +++
 packages/core/src/index.ts                         |   1 +
 .../core/src/plugins/bundled-plugin-install.ts     |  10 +
 packages/core/src/settings-schema.ts               |   6 +
 packages/core/src/types.ts                         |   9 +
 packages/dashboard/app/api/legacy.ts               |  40 ++++
 .../app/components/GrokCliProviderCard.css         |  65 ++++++
 .../app/components/GrokCliProviderCard.tsx         | 204 ++++++++++++++++
 packages/dashboard/app/components/ProviderIcon.tsx |   5 +
 .../__tests__/GrokCliProviderCard.test.tsx         | 105 +++++++++
 .../app/components/__tests__/ProviderIcon.test.tsx |   8 +
 .../settings/sections/AuthenticationSection.tsx    |   8 +-
 packages/dashboard/package.json                    |   1 +
 .../src/__tests__/grok-model-cache.test.ts         | 152 ++++++++++++
 .../register-model-routes-grok-cli.test.ts         | 214 +++++++++++++++++
 .../dashboard/src/__tests__/routes-auth.test.ts    | 258 ++++++++++++++++++++-
 packages/dashboard/src/grok-model-cache.ts         | 166 +++++++++++++
 packages/dashboard/src/routes.ts                   |   1 +
 .../dashboard/src/routes/register-auth-routes.ts   | 134 ++++++++++-
 .../dashboard/src/routes/register-model-routes.ts  |  51 ++++
 packages/dashboard/src/runtime-provider-probes.ts  |  43 ++++
 packages/dashboard/vitest.config.ts                |  12 +
 packages/desktop/scripts/workspace-tools.ts        |   3 +-
 plugins/fusion-plugin-grok-runtime/CHANGELOG.md    |   7 +
 plugins/fusion-plugin-grok-runtime/README.md       |  54 +++++
 plugins/fusion-plugin-grok-runtime/manifest.json   |   6 +
 plugins/fusion-plugin-grok-runtime/package.json    |  40 ++++
 .../src/__tests__/cli-spawn.test.ts                | 103 ++++++++
 .../src/__tests__/index.test.ts                    |  12 +
 .../src/__tests__/probe.test.ts                    | 135 +++++++++++
 .../src/__tests__/process-manager.test.ts          |  96 ++++++++
 .../src/__tests__/provider.test.ts                 |  57 +++++
 .../src/__tests__/runtime-adapter.test.ts          |  21 ++
 .../fusion-plugin-grok-runtime/src/cli-spawn.ts    |  50 ++++
 plugins/fusion-plugin-grok-runtime/src/index.ts    |  74 ++++++
 plugins/fusion-plugin-grok-runtime/src/probe.ts    | 107 +++++++++
 .../src/process-manager.ts                         |  86 +++++++
 plugins/fusion-plugin-grok-runtime/src/provider.ts |  25 ++
 .../src/runtime-adapter.ts                         |  25 ++
 plugins/fusion-plugin-grok-runtime/src/types.ts    |  12 +
 plugins/fusion-plugin-grok-runtime/tsconfig.json   |  10 +
 .../fusion-plugin-grok-runtime/vitest.config.ts    |  22 ++
 pnpm-lock.yaml                                     |  25 ++
 pnpm-workspace.yaml                                |   1 +
 50 files changed, 2525 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-7705

Fusion-Task-Lineage: b8194ea8-c773-4199-a52a-b0e4e7347192

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-08 23:39:34 -07:00
gsxdsm
62c1fa14fa build(desktop): allow redirecting staged deploy via FUSION_DESKTOP_DEPLOY_DIR
pnpm deploy's final temp-dir rename hits EPERM on the orca-managed Windows workspace mount and litters
deeply-nested deploy_tmp_* dirs. Let local Windows installer builds redirect the staged closure to an
external plain-NTFS path via FUSION_DESKTOP_DEPLOY_DIR; CI and the default in-tree path are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 07:49:49 -07:00
gsxdsm
abd596b700 fix: pack full desktop dependency closure + resolve bun/desktop plugin loading on Windows
Desktop "Local" mode crashed with ERR_MODULE_NOT_FOUND because electron-builder's
pnpm collector drops `deduped` subtrees, so engine's transitive closure
(@modelcontextprotocol/sdk, pi-ai provider SDKs, etc.) was never packed. Stage the
complete flat prod closure with `pnpm deploy --legacy --config.node-linker=hoisted`
and package it via `electron-builder --projectDir deploy`, bypassing the lossy
collector entirely.

Also make the dashboard-imported example plugins loadable under plain Node (the
Electron main runtime): cursor/droid/roadmap now expose compiled `dist` on the
`import` condition (keeping `source`→src for the bun CLI) and are built during the
desktop build. Add `source` conditions to paperclip/agent-browser/even-cards/
even-realities-glasses/whatsapp-chat so the bun `--conditions=source` Windows CLI
compile resolves them from source.

Validated on macOS: @fusion/core|engine|dashboard import cleanly from the staged
deploy; packing yields a complete 705-package asar; bun-windows-x64 cross-compiles
with all plugin dist removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 20:40:02 -07:00
gsxdsm
3aef6dd5cf fix: build @fusion/core and @fusion/engine dist in desktop packaging
The packaged desktop "Local" runtime dynamically imports @fusion/engine, whose
tsc dist is gitignored. desktop-windows.yml built only `@fusion/desktop build`
(no root `pnpm build`), so it packaged an empty engine/dist and the app crashed
on Local mode with ERR_MODULE_NOT_FOUND for app.asar/node_modules/@fusion/engine.

Make the desktop build self-contained (build core then engine before packaging)
and add the parity `pnpm build` step to desktop-windows.yml.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 19:34:11 -07:00
gsxdsm
1f3a15ec1c FN-7360: fix Windows desktop runtime packaging
Fix packaged Windows desktop startup by preserving Node-safe runtime dependencies and dashboard registry assets.

- Externalize Electron main/preload npm packages so CommonJS updater dependencies load natively.
- Load the dashboard plugin registry manifest through file IO and copy it into dashboard server dist from all build paths.
- Split Windows NSIS and portable artifact names and verify required Electron runtime resources in CI.
- Cover the packaging/runtime invariants with desktop and dashboard regression tests.

Files changed:
 .changeset/fn-7360-desktop-windows.md              |  7 +++
 .github/workflows/desktop-windows.yml              | 21 ++++++++
 packages/dashboard/package.json                    |  2 +-
 .../src/__tests__/plugin-registry-dist.test.ts     | 32 ++++++++++++
 .../src/__tests__/routes-plugin-registry.test.ts   | 10 ++--
 packages/dashboard/src/plugin-routes.ts            | 27 +++++++++-
 packages/desktop/README.md                         |  5 +-
 packages/desktop/electron-builder.yml              |  9 ++++
 packages/desktop/scripts/build.ts                  | 29 ++++++++--
 packages/desktop/scripts/workspace-tools.ts        |  4 ++
 .../desktop/src/__tests__/build-bundling.test.ts   | 61 ++++++++++++++++++++++
 .../src/__tests__/electron-builder-config.test.ts  | 15 ++++++
 packages/desktop/src/__tests__/ipc.test.ts         | 15 ++++++
 .../desktop/src/__tests__/local-runtime.test.ts    | 20 +++++++
 14 files changed, 247 insertions(+), 10 deletions(-)

Fusion-Task-Id: FN-7360

Fusion-Task-Lineage: a2d88130-c24f-43e2-932a-1e174b6afa35

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-01 08:01:59 -07:00
gsxdsm
63f1e097a2 FN-6366: fix desktop Vitest constructor mocks
Stabilize the desktop Vitest suite under Vitest 4.1.8 while keeping dashboard builds complete.

- Convert Electron constructor mocks to constructable function implementations for BrowserWindow, Tray, Notification, and LocalRuntimeManager.\n- Assert local runtime initialization uses the mocked home directory in desktop main-process tests.\n- Build dashboard runtime plugin packages before the desktop dashboard build.

Files changed:\n packages/desktop/scripts/workspace-tools.ts        | 15 ++++++++++++++\n packages/desktop/src/__tests__/deep-link.test.ts   |  4 +++-\n .../desktop/src/__tests__/main-integration.test.ts | 23 ++++++++++++++--------\n .../desktop/src/__tests__/main-local-mode.test.ts  | 19 ++++++++++++++----\n .../desktop/src/__tests__/main.integration.test.ts | 21 ++++++++++++--------\n packages/desktop/src/__tests__/main.test.ts        | 13 +++++++++---\n packages/desktop/src/__tests__/native.test.ts      |  6 ++++--\n 7 files changed, 75 insertions(+), 26 deletions(-)

Fusion-Task-Id: FN-6366

Fusion-Task-Lineage: 4e4ccdbc-845f-47d9-a565-cc5d659cf089
2026-06-13 09:01:39 -07:00
gsxdsm
4148f43ce4 fix(release): honor --publish never, guard Windows signing, fix desktop spawn
Second pass after the cache/arch fix unblocked `pnpm build` and surfaced
later-stage failures:

- Desktop packaging called `pnpm --filter @fusion/desktop dist:mac -- <args>`,
  but pnpm leaks the `--` separator into the script args. electron-builder
  stops parsing at `--`, so `--publish never` was ignored — it auto-published
  to api.github.com/repos/gsxdsm/fusion/releases and 404'd. The same leak
  dropped Linux's `--x64 --arm64`. Switch all four desktop packaging steps to
  `pnpm --filter @fusion/desktop exec electron-builder ...`, which forwards
  args cleanly (verified locally).
- Windows CLI signing now skips when WINDOWS_CERTIFICATE_BASE64 is absent,
  mirroring the macOS guard (was hard-failing the bun-windows-x64 job).
- Desktop build spawns workspace .cmd bins with shell:true on Windows; Node
  rejects .cmd/.bat spawns without a shell (EINVAL) since CVE-2024-27980,
  which broke `@fusion/desktop build` on the Windows runner.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 00:30:39 -07:00
gsxdsm
e5af9c93ae fix(desktop): packaged macOS app launched with no window / blank white screen
In packaged Electron builds, `process.argv[1]` is undefined (Electron loads
the main script via package.json `main`, not via argv), so the bottom-of-file
guard never invoked `run()` and the app started without creating a window.
Also build the dashboard client with `--base ./` so its `file://`-loaded
index.html resolves `./assets/*` from inside the asar instead of the
filesystem root, which was producing a blank white window.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 22:01:51 -07:00
Fusion (runfusion.ai)
477f79f3eb feat(FN-4737): parameterize worktree-escape test to use configured worktree
Adds parameterized test cases to the worktree-liveness test to exercise different configured `worktreesDir` paths, improving coverage of the worktree escape/isolation path.

Fusion-Task-Id: FN-4737

Fusion-Task-Lineage: 40e262ea-2507-461e-b9f5-940b3b4490f9
2026-05-16 09:56:28 -07:00