From cf3c19a5039e171145628759b0b8bd8757051dc2 Mon Sep 17 00:00:00 2001 From: byrongamatos Date: Thu, 18 Jun 2026 00:25:09 -0700 Subject: [PATCH] fix(build/runtime): isolate bundled Python from the build/user site-packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two related fixes for the bundled embeddable/standalone Python: - build-common.sh exports PYTHONNOUSERSITE=1 for the whole build. Without it, pip on a dev/CI machine that has a system Python sees transitive deps as 'already satisfied' via the per-user site (~/.local, %APPDATA%\Python) and SKIPS bundling them (typing_extensions, urllib3, certifi, ...). The packaged app then crashes with ModuleNotFoundError on clean end-user machines while 'working' on the build box. Clean CI runners have no user site, so this is a no-op there. - python.ts sets PYTHONNOUSERSITE=1 in the spawned server env so a stray user-site package on an end-user machine can't shadow (or mask a gap in) the bundled deps. When packaged it also sets SLOPSMITH_SKIP_PLUGIN_INSTALL=1 so the server doesn't block startup doing runtime 'pip install' of heavy optional plugin deps (torch/whisperx/demucs) — that hung the backend past the readiness window on first launch. (Pairs with the slopsmith core change that honours that flag.) Co-Authored-By: Claude Opus 4.8 --- scripts/build-common.sh | 9 +++++++++ src/main/python.ts | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/scripts/build-common.sh b/scripts/build-common.sh index 738c2b0..6bbaefa 100644 --- a/scripts/build-common.sh +++ b/scripts/build-common.sh @@ -8,6 +8,15 @@ set -euo pipefail +# Isolate the embeddable/standalone Python used for bundling from the BUILD +# machine's per-user site-packages. Without this, pip on a dev machine that has +# a system Python installed sees transitive deps as "already satisfied" via the +# user site (~/.local or %APPDATA%\Python) and SKIPS bundling them (e.g. +# typing_extensions, urllib3, certifi). The packaged app then crashes with +# ModuleNotFoundError on clean end-user machines while "working" on the build +# box. CI runners have no user site, so this is a no-op there. +export PYTHONNOUSERSITE=1 + # Check if this is being sourced by a platform script if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then echo "Error: build-common.sh should not be run directly" >&2 diff --git a/src/main/python.ts b/src/main/python.ts index 09caa45..6c9ae8c 100644 --- a/src/main/python.ts +++ b/src/main/python.ts @@ -546,6 +546,10 @@ export async function startPython(): Promise { XDG_CACHE_HOME: cacheBase, TORCH_HOME: process.env.TORCH_HOME || path.join(cacheBase, 'torch'), HF_HOME: process.env.HF_HOME || path.join(cacheBase, 'huggingface'), + // Never read the end user's per-user site-packages — the bundle ships + // its own deps, and a stray user-site package must not shadow (or mask + // a gap in) them. Mirrors PYTHONNOUSERSITE=1 used at build time. + PYTHONNOUSERSITE: '1', RESOURCESPATH: app.isPackaged ? process.resourcesPath : path.join(__dirname, '..', '..', 'resources'), @@ -597,6 +601,12 @@ export async function startPython(): Promise { // Set PYTHONHOME for bundled Python on all platforms if (app.isPackaged) { + // Packaged builds ship plugins but must NOT block startup doing a + // runtime `pip install` of heavy optional plugin deps (torch/whisperx/ + // demucs) — that hangs the backend past the readiness window on first + // launch. The slopsmith plugin loader honours this flag and loads such + // plugins degraded (their optional features stay off until deps exist). + pythonEnv.SLOPSMITH_SKIP_PLUGIN_INSTALL = '1'; if (process.platform === 'win32') { pythonEnv.PYTHONHOME = path.join(process.resourcesPath, 'python'); } else {