fix(desktop): sync lockfile, gate Windows GPU flags, document desktop hardening

- Regenerate pnpm-lock.yaml for the new electron@^33.4.11 CLI dependency so
  --frozen-lockfile stops failing every PR-check job.
- Gate the GPU/sandbox-disabling Electron flags (--no-sandbox, --disable-gpu,
  etc.) to Windows only via os.platform(); applying them on macOS/Linux was a
  security and rendering regression. This also resolves the unused os import
  that failed lint.
- Add FNXC comments for the Windows GPU flags, desktop user-data isolation, and
  CLI dashboard-server reuse per project comment convention.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-07-03 08:13:06 -07:00
parent 6d7715fe9e
commit d97e66a657
4 changed files with 102 additions and 73 deletions

View File

@@ -2,6 +2,6 @@
"@runfusion/fusion": patch
---
summary: Add `electron` as a runtime dependency so `fusion desktop` works from a published npm install.
summary: Fix `fusion desktop` on Windows and published npm installs (Electron dependency, GPU/sandbox flags, dashboard reuse).
category: fix
dev: `packages/cli/package.json` now depends on `electron`. Previously the desktop launcher called `require("electron")`, which is only available inside the source checkout (via `pnpm-workspace.yaml` `onlyBuiltDependencies`) and is missing for npm consumers, causing `fusion desktop` to hang or fail silently.
dev: `packages/cli/package.json` now depends on `electron` at runtime; previously the desktop launcher called `require("electron")`, which is only available inside the source checkout (via `pnpm-workspace.yaml` `onlyBuiltDependencies`) and is missing for npm consumers, causing `fusion desktop` to hang or fail silently. The launcher now applies GPU/sandbox-disabling Electron flags only on Windows (`os.platform() === "win32"`), keeps hardware acceleration and the Chromium sandbox on macOS/Linux, exports `FUSION_SERVER_PORT` so the desktop reuses the CLI-started dashboard instead of double-binding ports, and isolates desktop user-data under `~/.fusion/desktop-user-data`.

View File

@@ -178,14 +178,25 @@ export async function runDesktop(options: RunDesktopOptions = {}): Promise<void>
const runtime = await startDashboardRuntime(rootDir, Boolean(options.paused), Boolean(options.noAuth));
const electronBinary = resolveElectronBinary();
/*
FNXC:DesktopWindowsGpuFlags 2026-07-03-14:40:
Windows Electron renderers observed blank/flickering GPU output and sandbox-related launch instability on some GPUs during the 0.52.0 desktop release (field report Issue 7). Disable GPU acceleration and the Chromium sandbox ONLY on Windows so macOS/Linux keep hardware acceleration and the security sandbox. Applying `--no-sandbox`/`--disable-gpu` on every platform would be a needless security and rendering regression off Windows.
*/
const isWindows = os.platform() === "win32";
const windowsGpuFlags = isWindows
? [
"--disable-gpu",
"--disable-gpu-compositing",
"--disable-gpu-sandbox",
"--disable-software-rasterizer",
"--no-sandbox",
]
: [];
const electronArgs = [
"--enable-source-maps",
desktopEntry,
"--disable-gpu",
"--disable-gpu-compositing",
"--disable-gpu-sandbox",
"--disable-software-rasterizer",
"--no-sandbox",
...windowsGpuFlags,
...(options.dev ? ["--dev"] : []),
];

View File

@@ -3,6 +3,10 @@ import { join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import os from "node:os";
/*
FNXC:DesktopUserDataIsolation 2026-07-03-14:40:
Isolate Electron desktop user-data/cache/crash artifacts under ~/.fusion/desktop-user-data so the packaged desktop does not share (or collide with) the default per-app Chromium profile across installs and Fusion versions (field report Issue 8). setPath must run before app "ready"; once locked it throws, which is non-fatal here.
*/
const fusionUserDataDir = join(os.homedir(), ".fusion", "desktop-user-data");
try {
app.commandLine.appendSwitch("user-data-dir", fusionUserDataDir);
@@ -254,6 +258,10 @@ export async function initializeApp(): Promise<void> {
currentDesktopLaunchMode = "local";
}
/*
FNXC:DesktopReuseCliServer 2026-07-03-14:40:
When `fusion desktop` launches Electron it exports FUSION_SERVER_PORT for the dashboard the CLI already started. In that case the desktop must NOT spin up its own embedded local runtime (which would double-bind ports and conflict on Windows, field report Issue 9): skip startLocalRuntimeOnce() when the port is set, and treat a "choose" mode as already-local so the shell attaches to the external CLI server.
*/
if (currentDesktopLaunchMode === "choose" && process.env.FUSION_SERVER_PORT) {
// The CLI already started a dashboard server; use it without spawning an
// embedded local runtime. The shell state will report external-cli running.

142
pnpm-lock.yaml generated
View File

@@ -55,6 +55,9 @@ importers:
dockerode:
specifier: ^4.0.12
version: 4.0.12
electron:
specifier: ^33.4.11
version: 33.4.11
express:
specifier: ^5.1.0
version: 5.2.1
@@ -1228,8 +1231,8 @@ packages:
resolution: {integrity: sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ==}
engines: {node: '>=20.0.0'}
'@aws-sdk/core@3.974.15':
resolution: {integrity: sha512-UpA0rTGW/tHGITcCqHisbuuEPraYg9GG+mWmXjY5+RxZBMLGe6aL9oe0ix50LztwAcPIkGZLH0yWdMIkCM10hw==}
'@aws-sdk/core@3.974.26':
resolution: {integrity: sha512-wRj7Pthvjk3anees97pUWlxlTa0DUjeGrEQU5fKDZVdWZV0ekaprbof0df2uaE9g8u67t035v2j+ne2AW2UMkA==}
engines: {node: '>=20.0.0'}
'@aws-sdk/credential-provider-env@3.972.41':
@@ -1292,6 +1295,10 @@ packages:
resolution: {integrity: sha512-81duvlltQlsfn5K+o8zILcystBRdbT1G2JJYVCML5NZHBz4CL/zf+sAemCtBh/uh6RQUMyInGeZLQ7/8igZhbA==}
engines: {node: '>=20.0.0'}
'@aws-sdk/types@3.973.15':
resolution: {integrity: sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ==}
engines: {node: '>=20.0.0'}
'@aws-sdk/types@3.973.9':
resolution: {integrity: sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg==}
engines: {node: '>=20.0.0'}
@@ -1300,8 +1307,8 @@ packages:
resolution: {integrity: sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==}
engines: {node: '>=20.0.0'}
'@aws-sdk/xml-builder@3.972.26':
resolution: {integrity: sha512-cDbrqvDS73whl6YAPSPq0U6whzG6UWI9PuWh0wrUuGoZexhWEqhdunbukV7iBoaWnFV1AODutM5hOD6rtn439g==}
'@aws-sdk/xml-builder@3.972.33':
resolution: {integrity: sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A==}
engines: {node: '>=20.0.0'}
'@aws/lambda-invoke-store@0.2.4':
@@ -2603,9 +2610,6 @@ packages:
'@cfworker/json-schema':
optional: true
'@nodable/entities@2.1.0':
resolution: {integrity: sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==}
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -2844,6 +2848,10 @@ packages:
resolution: {integrity: sha512-Kt8phUg45M15EjhYAbZ+fFikYneijLu9Liugz8ZsYz2i8j0hzGv27LWKpEHYRfvj+LyCOSijpcR/2i8RouV+cA==}
engines: {node: '>=18.0.0'}
'@smithy/core@3.29.1':
resolution: {integrity: sha512-qoiY4nrk5OCu1+eIR1VB8l5DmON/oKiqrd5zZFAhXJXjJlLWQusKEW/SkBDAtGDcPaz86m9kfcE1lngU0GlM6A==}
engines: {node: '>=18.0.0'}
'@smithy/credential-provider-imds@4.3.5':
resolution: {integrity: sha512-yiF8xHpdkaTfzLVqFzsP6WvNghEK+qZzLYWFD13L2SsFhbXwBGlxdocKF95qjr7s5lE5NRage+EJFK4mAsx88Q==}
engines: {node: '>=18.0.0'}
@@ -2868,10 +2876,18 @@ packages:
resolution: {integrity: sha512-QBJKWGqIknH0dc9LWpfH1mkdokAx6iXYN3UcQ3eY6uIEyScuoQAhfl94ge7ozUy9WgFUdE8xsvwBjaYBbWmPNA==}
engines: {node: '>=18.0.0'}
'@smithy/signature-v4@5.6.2':
resolution: {integrity: sha512-QgHflghMoPxCJ9axiCVh8KZfbC9fuP6vkXXyK//E3cq7nLaSSyyLj0GAoqVWezYeDQmXIZhmlRvLE16jsqDK6g==}
engines: {node: '>=18.0.0'}
'@smithy/types@4.14.2':
resolution: {integrity: sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw==}
engines: {node: '>=18.0.0'}
'@smithy/types@4.15.1':
resolution: {integrity: sha512-x3L0XSACF6UYzKpa9biqiRMgvH5+wnFFew9Tm/grFYqgaupPwx/+ojDPpPJM8dZON3S9tjz5U+PQYsCBd1Mw5Q==}
engines: {node: '>=18.0.0'}
'@smithy/util-buffer-from@2.2.0':
resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==}
engines: {node: '>=14.0.0'}
@@ -4535,6 +4551,11 @@ packages:
resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==}
engines: {node: '>=8.0.0'}
electron@33.4.11:
resolution: {integrity: sha512-xmdAs5QWRkInC7TpXGNvzo/7exojubk+72jn1oJL7keNeIlw7xNglf8TGtJtkR4rWC5FJq0oXiIXPS9BcK2Irg==}
engines: {node: '>= 12.20.55'}
hasBin: true
electron@35.7.5:
resolution: {integrity: sha512-dnL+JvLraKZl7iusXTVTGYs10TKfzUi30uEDTqsmTm0guN9V2tbOjTzyIZbh9n3ygUjgEYyo+igAwMRXIi3IPw==}
engines: {node: '>= 12.20.55'}
@@ -4793,13 +4814,6 @@ packages:
fast-wrap-ansi@0.2.2:
resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==}
fast-xml-builder@1.2.0:
resolution: {integrity: sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==}
fast-xml-parser@5.7.3:
resolution: {integrity: sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg==}
hasBin: true
fastq@1.20.1:
resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
@@ -6226,10 +6240,6 @@ packages:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
path-expression-matcher@1.5.0:
resolution: {integrity: sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==}
engines: {node: '>=14.0.0'}
path-is-absolute@1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
@@ -7004,9 +7014,6 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
strnum@2.2.3:
resolution: {integrity: sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==}
strtok3@6.3.0:
resolution: {integrity: sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==}
engines: {node: '>=10'}
@@ -7570,10 +7577,6 @@ packages:
resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==}
engines: {node: '>=18'}
xml-naming@0.1.0:
resolution: {integrity: sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==}
engines: {node: '>=16.0.0'}
xml2js@0.6.2:
resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==}
engines: {node: '>=4.0.0'}
@@ -7771,7 +7774,7 @@ snapshots:
dependencies:
'@aws-crypto/sha256-browser': 5.2.0
'@aws-crypto/sha256-js': 5.2.0
'@aws-sdk/core': 3.974.15
'@aws-sdk/core': 3.974.26
'@aws-sdk/credential-provider-node': 3.972.46
'@aws-sdk/eventstream-handler-node': 3.972.18
'@aws-sdk/middleware-eventstream': 3.972.14
@@ -7784,20 +7787,20 @@ snapshots:
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/core@3.974.15':
'@aws-sdk/core@3.974.26':
dependencies:
'@aws-sdk/types': 3.973.9
'@aws-sdk/xml-builder': 3.972.26
'@aws-sdk/types': 3.973.15
'@aws-sdk/xml-builder': 3.972.33
'@aws/lambda-invoke-store': 0.2.4
'@smithy/core': 3.24.5
'@smithy/signature-v4': 5.4.5
'@smithy/types': 4.14.2
'@smithy/core': 3.29.1
'@smithy/signature-v4': 5.6.2
'@smithy/types': 4.15.1
bowser: 2.14.1
tslib: 2.8.1
'@aws-sdk/credential-provider-env@3.972.41':
dependencies:
'@aws-sdk/core': 3.974.15
'@aws-sdk/core': 3.974.26
'@aws-sdk/types': 3.973.9
'@smithy/core': 3.24.5
'@smithy/types': 4.14.2
@@ -7805,7 +7808,7 @@ snapshots:
'@aws-sdk/credential-provider-http@3.972.43':
dependencies:
'@aws-sdk/core': 3.974.15
'@aws-sdk/core': 3.974.26
'@aws-sdk/types': 3.973.9
'@smithy/core': 3.24.5
'@smithy/fetch-http-handler': 5.4.5
@@ -7815,7 +7818,7 @@ snapshots:
'@aws-sdk/credential-provider-ini@3.972.45':
dependencies:
'@aws-sdk/core': 3.974.15
'@aws-sdk/core': 3.974.26
'@aws-sdk/credential-provider-env': 3.972.41
'@aws-sdk/credential-provider-http': 3.972.43
'@aws-sdk/credential-provider-login': 3.972.45
@@ -7831,7 +7834,7 @@ snapshots:
'@aws-sdk/credential-provider-login@3.972.45':
dependencies:
'@aws-sdk/core': 3.974.15
'@aws-sdk/core': 3.974.26
'@aws-sdk/nested-clients': 3.997.13
'@aws-sdk/types': 3.973.9
'@smithy/core': 3.24.5
@@ -7854,7 +7857,7 @@ snapshots:
'@aws-sdk/credential-provider-process@3.972.41':
dependencies:
'@aws-sdk/core': 3.974.15
'@aws-sdk/core': 3.974.26
'@aws-sdk/types': 3.973.9
'@smithy/core': 3.24.5
'@smithy/types': 4.14.2
@@ -7862,7 +7865,7 @@ snapshots:
'@aws-sdk/credential-provider-sso@3.972.45':
dependencies:
'@aws-sdk/core': 3.974.15
'@aws-sdk/core': 3.974.26
'@aws-sdk/nested-clients': 3.997.13
'@aws-sdk/token-providers': 3.1056.0
'@aws-sdk/types': 3.973.9
@@ -7872,7 +7875,7 @@ snapshots:
'@aws-sdk/credential-provider-web-identity@3.972.45':
dependencies:
'@aws-sdk/core': 3.974.15
'@aws-sdk/core': 3.974.26
'@aws-sdk/nested-clients': 3.997.13
'@aws-sdk/types': 3.973.9
'@smithy/core': 3.24.5
@@ -7895,7 +7898,7 @@ snapshots:
'@aws-sdk/middleware-websocket@3.972.23':
dependencies:
'@aws-sdk/core': 3.974.15
'@aws-sdk/core': 3.974.26
'@aws-sdk/types': 3.973.9
'@smithy/core': 3.24.5
'@smithy/fetch-http-handler': 5.4.5
@@ -7907,7 +7910,7 @@ snapshots:
dependencies:
'@aws-crypto/sha256-browser': 5.2.0
'@aws-crypto/sha256-js': 5.2.0
'@aws-sdk/core': 3.974.15
'@aws-sdk/core': 3.974.26
'@aws-sdk/signature-v4-multi-region': 3.996.30
'@aws-sdk/types': 3.973.9
'@smithy/core': 3.24.5
@@ -7925,7 +7928,7 @@ snapshots:
'@aws-sdk/token-providers@3.1048.0':
dependencies:
'@aws-sdk/core': 3.974.15
'@aws-sdk/core': 3.974.26
'@aws-sdk/nested-clients': 3.997.13
'@aws-sdk/types': 3.973.9
'@smithy/core': 3.24.5
@@ -7934,13 +7937,18 @@ snapshots:
'@aws-sdk/token-providers@3.1056.0':
dependencies:
'@aws-sdk/core': 3.974.15
'@aws-sdk/core': 3.974.26
'@aws-sdk/nested-clients': 3.997.13
'@aws-sdk/types': 3.973.9
'@smithy/core': 3.24.5
'@smithy/types': 4.14.2
tslib: 2.8.1
'@aws-sdk/types@3.973.15':
dependencies:
'@smithy/types': 4.15.1
tslib: 2.8.1
'@aws-sdk/types@3.973.9':
dependencies:
'@smithy/types': 4.14.2
@@ -7950,10 +7958,9 @@ snapshots:
dependencies:
tslib: 2.8.1
'@aws-sdk/xml-builder@3.972.26':
'@aws-sdk/xml-builder@3.972.33':
dependencies:
'@smithy/types': 4.14.2
fast-xml-parser: 5.7.3
'@smithy/types': 4.15.1
tslib: 2.8.1
'@aws/lambda-invoke-store@0.2.4': {}
@@ -9802,8 +9809,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@nodable/entities@2.1.0': {}
'@nodelib/fs.scandir@2.1.5':
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -9967,6 +9972,11 @@ snapshots:
'@smithy/types': 4.14.2
tslib: 2.8.1
'@smithy/core@3.29.1':
dependencies:
'@smithy/types': 4.15.1
tslib: 2.8.1
'@smithy/credential-provider-imds@4.3.5':
dependencies:
'@smithy/core': 3.24.5
@@ -10001,10 +10011,20 @@ snapshots:
'@smithy/types': 4.14.2
tslib: 2.8.1
'@smithy/signature-v4@5.6.2':
dependencies:
'@smithy/core': 3.29.1
'@smithy/types': 4.15.1
tslib: 2.8.1
'@smithy/types@4.14.2':
dependencies:
tslib: 2.8.1
'@smithy/types@4.15.1':
dependencies:
tslib: 2.8.1
'@smithy/util-buffer-from@2.2.0':
dependencies:
'@smithy/is-array-buffer': 2.2.0
@@ -11858,6 +11878,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
electron@33.4.11:
dependencies:
'@electron/get': 2.0.3
'@types/node': 25.5.2
extract-zip: 2.0.1
transitivePeerDependencies:
- supports-color
electron@35.7.5:
dependencies:
'@electron/get': 2.0.3
@@ -12197,18 +12225,6 @@ snapshots:
dependencies:
fast-string-width: 3.0.2
fast-xml-builder@1.2.0:
dependencies:
path-expression-matcher: 1.5.0
xml-naming: 0.1.0
fast-xml-parser@5.7.3:
dependencies:
'@nodable/entities': 2.1.0
fast-xml-builder: 1.2.0
path-expression-matcher: 1.5.0
strnum: 2.2.3
fastq@1.20.1:
dependencies:
reusify: 1.1.0
@@ -13981,8 +13997,6 @@ snapshots:
path-exists@4.0.0: {}
path-expression-matcher@1.5.0: {}
path-is-absolute@1.0.1: {}
path-key@3.1.1: {}
@@ -14859,8 +14873,6 @@ snapshots:
strip-json-comments@3.1.1: {}
strnum@2.2.3: {}
strtok3@6.3.0:
dependencies:
'@tokenizer/token': 0.3.0
@@ -15446,8 +15458,6 @@ snapshots:
xml-name-validator@5.0.0: {}
xml-naming@0.1.0: {}
xml2js@0.6.2:
dependencies:
sax: 1.6.0