diff --git a/src/config/comfySettings.ts b/src/config/comfySettings.ts index 39e67f1e..c622f12d 100644 --- a/src/config/comfySettings.ts +++ b/src/config/comfySettings.ts @@ -10,12 +10,16 @@ export const DEFAULT_SETTINGS: ComfySettingsData = { 'Comfy.Workflow.WorkflowTabsPosition': 'Topbar', 'Comfy.Workflow.ShowMissingModelsWarning': true, 'Comfy.Server.LaunchArgs': {}, + 'Comfy-Desktop.PythonInstallMirror': '', + 'Comfy-Desktop.PypiInstallMirror': '', } as const; export interface ComfySettingsData { 'Comfy-Desktop.AutoUpdate': boolean; 'Comfy-Desktop.SendStatistics': boolean; 'Comfy.Server.LaunchArgs': Record; + 'Comfy-Desktop.PythonInstallMirror': string; + 'Comfy-Desktop.PypiInstallMirror': string; [key: string]: unknown; } diff --git a/src/install/installWizard.ts b/src/install/installWizard.ts index 5ef4bcbb..88cdea06 100644 --- a/src/install/installWizard.ts +++ b/src/install/installWizard.ts @@ -64,6 +64,8 @@ export class InstallWizard implements HasTelemetry { ...existingSettings, 'Comfy-Desktop.AutoUpdate': this.installOptions.autoUpdate, 'Comfy-Desktop.SendStatistics': this.installOptions.allowMetrics, + 'Comfy-Desktop.PythonInstallMirror': this.installOptions.pythonMirror, + 'Comfy-Desktop.PypiInstallMirror': this.installOptions.pypiMirror, }; if (this.installOptions.device === 'cpu') { diff --git a/src/main-process/comfyDesktopApp.ts b/src/main-process/comfyDesktopApp.ts index b6fb0d09..6f46d00e 100644 --- a/src/main-process/comfyDesktopApp.ts +++ b/src/main-process/comfyDesktopApp.ts @@ -6,7 +6,6 @@ import path from 'node:path'; import { graphics } from 'systeminformation'; import { ComfyServerConfig } from '../config/comfyServerConfig'; -import { ComfySettings } from '../config/comfySettings'; import { IPC_CHANNELS, ProgressStatus, ServerArgs } from '../constants'; import { InstallationManager } from '../install/installationManager'; import { DownloadManager } from '../models/DownloadManager'; @@ -23,14 +22,15 @@ import { ComfyServer } from './comfyServer'; export class ComfyDesktopApp implements HasTelemetry { public comfyServer: ComfyServer | null = null; - public comfySettings: ComfySettings; private terminal: Terminal | null = null; // Only created after server starts. constructor( public installation: ComfyInstallation, public appWindow: AppWindow, readonly telemetry: ITelemetry - ) { - this.comfySettings = new ComfySettings(installation.basePath); + ) {} + + get comfySettings() { + return this.installation.comfySettings; } get basePath() { diff --git a/src/main-process/comfyInstallation.ts b/src/main-process/comfyInstallation.ts index d2fe59e1..f96bd1c4 100644 --- a/src/main-process/comfyInstallation.ts +++ b/src/main-process/comfyInstallation.ts @@ -2,6 +2,7 @@ import log from 'electron-log/main'; import { rm } from 'node:fs/promises'; import { ComfyServerConfig } from '../config/comfyServerConfig'; +import { ComfySettings } from '../config/comfySettings'; import type { InstallValidation, TorchDeviceType } from '../preload'; import { type ITelemetry, getTelemetry } from '../services/telemetry'; import { useDesktopConfig } from '../store/desktopConfig'; @@ -32,6 +33,7 @@ export class ComfyInstallation { } virtualEnvironment: VirtualEnvironment; + comfySettings: ComfySettings; _basePath: string; /** The base path of the desktop app. Models, nodes, and configuration are saved here by default. */ @@ -41,7 +43,7 @@ export class ComfyInstallation { set basePath(value: string) { // Duplicated in constructor to avoid non-nullable type assertions. this._basePath = value; - this.virtualEnvironment = new VirtualEnvironment(value, this.telemetry, this.device); + this.virtualEnvironment = this.createVirtualEnvironment(value); } /** @@ -61,7 +63,17 @@ export class ComfyInstallation { ) { // TypeScript workaround: duplication of basePath setter this._basePath = basePath; - this.virtualEnvironment = new VirtualEnvironment(basePath, telemetry, device); + this.comfySettings = new ComfySettings(basePath); + this.virtualEnvironment = this.createVirtualEnvironment(basePath); + } + + private createVirtualEnvironment(basePath: string) { + return new VirtualEnvironment(basePath, { + telemetry: this.telemetry, + selectedDevice: this.device, + pythonMirror: this.comfySettings.get('Comfy-Desktop.PythonInstallMirror'), + pypiMirror: this.comfySettings.get('Comfy-Desktop.PypiInstallMirror'), + }); } /** @@ -105,7 +117,7 @@ export class ComfyInstallation { validation.basePath = 'OK'; this.onUpdate?.(validation); - const venv = new VirtualEnvironment(basePath, this.telemetry, this.device); + const venv = this.createVirtualEnvironment(basePath); if (await venv.exists()) { validation.venvDirectory = 'OK'; this.onUpdate?.(validation); diff --git a/src/preload.ts b/src/preload.ts index 6ed11054..90023284 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -26,6 +26,9 @@ export interface InstallOptions { migrationItemIds?: string[]; /** Torch compute device */ device: TorchDeviceType; + /** UV python mirrors */ + pythonMirror?: string; // UV_PYTHON_INSTALL_MIRROR + pypiMirror?: string; // UV_PYPI_INSTALL_MIRROR } export interface SystemPaths { diff --git a/src/virtualEnvironment.ts b/src/virtualEnvironment.ts index 939ecbd0..27fa22c7 100644 --- a/src/virtualEnvironment.ts +++ b/src/virtualEnvironment.ts @@ -33,6 +33,9 @@ export class VirtualEnvironment implements HasTelemetry { readonly comfyUIRequirementsPath: string; readonly comfyUIManagerRequirementsPath: string; readonly selectedDevice?: string; + readonly telemetry: ITelemetry; + readonly pythonMirror?: string; + readonly pypiMirror?: string; uvPty: pty.IPty | undefined; /** @todo Refactor to `using` */ @@ -51,6 +54,8 @@ export class VirtualEnvironment implements HasTelemetry { UV_TOOL_BIN_DIR: this.cacheDir, UV_PYTHON_INSTALL_DIR: this.cacheDir, VIRTUAL_ENV: this.venvPath, + UV_PYTHON_INSTALL_MIRROR: this.pythonMirror, + UV_PYPI_INSTALL_MIRROR: this.pypiMirror, }, }); } @@ -59,13 +64,26 @@ export class VirtualEnvironment implements HasTelemetry { constructor( venvPath: string, - readonly telemetry: ITelemetry, - selectedDevice: TorchDeviceType | undefined, - pythonVersion: string = '3.12.8' + { + telemetry, + selectedDevice, + pythonVersion, + pythonMirror, + pypiMirror, + }: { + telemetry: ITelemetry; + selectedDevice?: TorchDeviceType; + pythonVersion?: string; + pythonMirror?: string; + pypiMirror?: string; + } ) { this.venvRootPath = venvPath; - this.pythonVersion = pythonVersion; + this.telemetry = telemetry; + this.pythonVersion = pythonVersion ?? '3.12'; this.selectedDevice = selectedDevice; + this.pythonMirror = pythonMirror; + this.pypiMirror = pypiMirror; // uv defaults to .venv this.venvPath = path.join(venvPath, '.venv'); diff --git a/tests/unit/comfySettings.test.ts b/tests/unit/comfySettings.test.ts index 87a3bbae..021df92e 100644 --- a/tests/unit/comfySettings.test.ts +++ b/tests/unit/comfySettings.test.ts @@ -83,6 +83,8 @@ describe('ComfySettings', () => { 'Comfy-Desktop.AutoUpdate': false, 'Comfy-Desktop.SendStatistics': false, 'Comfy.Server.LaunchArgs': { test: 'value' }, + 'Comfy-Desktop.PythonInstallMirror': '', + 'Comfy-Desktop.PypiInstallMirror': '', }; vi.mocked(fs.access).mockResolvedValue();