Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
03035ae
Document UV package manager research findings
webfiltered Aug 26, 2025
1277afb
Add comprehensive UV pip install output analysis
webfiltered Aug 26, 2025
3ad7d30
Fix UV output analysis after complete file reading
webfiltered Aug 26, 2025
4337ffa
Add specific output examples for each stage transition
webfiltered Aug 26, 2025
63cde83
Document exact verbatim output for stage transitions
webfiltered Aug 26, 2025
8547257
Fix UV output documentation accuracy
webfiltered Aug 26, 2025
cc275f6
Remove cache checking as separate stage
webfiltered Aug 26, 2025
2e8f07b
Add rationale for each phase start marker
webfiltered Aug 26, 2025
bcb1f91
Make time unit patterns flexible in UV parser
webfiltered Aug 26, 2025
170651e
Remove erroneously re-added cache_checking stage
webfiltered Aug 26, 2025
8bfd0f4
Add regex patterns for each UV installation phase
webfiltered Aug 26, 2025
c441b0e
Remove 'Regex pattern:' headers from documentation
webfiltered Aug 26, 2025
2615174
Document UV download stream analysis
webfiltered Aug 26, 2025
950387a
Fix UV analysis to avoid hard-coded assumptions
webfiltered Aug 26, 2025
cf94e29
Remove example-specific download timeline
webfiltered Aug 26, 2025
86eb8d2
Update UV analysis for cached vs download scenarios
webfiltered Aug 26, 2025
029b4ae
Standardize conditional stage documentation
webfiltered Aug 26, 2025
92ef912
Clean up stage documentation consistency
webfiltered Aug 26, 2025
bf2cf21
Use exact raw output lines from logs
webfiltered Aug 26, 2025
1fca4c3
Update UV parser to correctly match documented patterns
webfiltered Aug 26, 2025
8306ae6
Remove redundant installation flows section
webfiltered Aug 26, 2025
42cc094
Fix inconsistent 'Why this marks the phase' formatting
webfiltered Aug 26, 2025
7200d54
Clean up python test scripts
webfiltered Aug 26, 2025
e4b7e5a
nit
webfiltered Aug 26, 2025
b07500d
Design UV parser interfaces and types
webfiltered Aug 26, 2025
4fbe862
Remove unnecessary FinalPackage interface
webfiltered Aug 26, 2025
db457d1
Fix LogLevel type based on actual UV output
webfiltered Aug 26, 2025
b791d71
Refactor UV parser to stateless architecture
webfiltered Aug 26, 2025
1580b67
Remove deprecated ParseLineResult interface
webfiltered Aug 26, 2025
6d7e211
Simplify UVParserOptions for stateless design
webfiltered Aug 26, 2025
755776b
Clean up interfaces for stateless parser
webfiltered Aug 26, 2025
56b219d
Rename FinalPackageListItem to ChangedPackage
webfiltered Aug 26, 2025
f07022a
Remove calculated fields from parsed output types
webfiltered Aug 26, 2025
323a055
Remove rawLine and lineNumber from ParsedOutput
webfiltered Aug 26, 2025
4878640
Refactor UV parser to stateless architecture
webfiltered Aug 26, 2025
d614415
Implement stateless UV output parser
webfiltered Aug 27, 2025
177fadb
Add parse-file script for JSON output
webfiltered Aug 27, 2025
ed7a9e3
Update HTTP/2 frame parsing to track direction and bytes
webfiltered Aug 27, 2025
4f3f3eb
Refactor Http2Frame to discriminated union
webfiltered Aug 27, 2025
1cd93e1
Remove unnecessary type assertions
webfiltered Aug 27, 2025
acf14e2
Use 'satisfies' instead of 'as const'
webfiltered Aug 27, 2025
380b3a0
Remove redundant Http2Frame union type
webfiltered Aug 27, 2025
4b0b4d5
Fix loose typing in parser
webfiltered Aug 27, 2025
7cd01b7
Add UV state management system
webfiltered Aug 27, 2025
ee067e6
nit
webfiltered Aug 28, 2025
edfc885
Remove .js extensions from TypeScript imports
webfiltered Aug 28, 2025
47473a5
Implement UVProcess class to replace node-pty approach
webfiltered Aug 28, 2025
0ab304e
Rename UV parser files to camelCase convention
webfiltered Aug 28, 2025
23f205a
Remove .js extensions from all imports
webfiltered Aug 28, 2025
60ee244
Add uvProcessExamples.ts with UV process usage examples
webfiltered Aug 28, 2025
4a78ba2
Add proper interfaces and JSDoc to UV factory functions
webfiltered Aug 28, 2025
f519892
Fix egregious TypeScript patterns
webfiltered Aug 28, 2025
915dc48
Rename UV-prefixed symbols to PascalCase
webfiltered Aug 28, 2025
d5e5d9e
Add install stage tracking definitions
webfiltered Aug 29, 2025
8b4886f
Add install stage tracking to app state
webfiltered Aug 29, 2025
007458c
Register install state handlers and add initial tracking
webfiltered Aug 29, 2025
d350ff6
Add install stage tracking throughout installation flow
webfiltered Aug 29, 2025
157eee1
Add detailed validation stage tracking
webfiltered Aug 29, 2025
3ce47ac
Fix critical: Add INSTALLING_REQUIREMENTS stage tracking
webfiltered Aug 29, 2025
c104bf6
Add consistent error stage handling
webfiltered Aug 29, 2025
af2a289
nit
webfiltered Aug 30, 2025
dc3bc24
Fix test mocks for appState.setInstallStage
webfiltered Aug 30, 2025
7bac618
Add LSP server for agent symbol lookup
webfiltered Aug 30, 2025
1d294b1
Add startup debug logger utility
webfiltered Aug 31, 2025
1e8d3cc
Add debug logging to ComfyServer startup
webfiltered Aug 31, 2025
2e1ed39
Add debug logging to VirtualEnvironment
webfiltered Aug 31, 2025
127351f
Add debug logging to ComfyDesktopApp
webfiltered Aug 31, 2025
efb15f6
Add debug logging to DesktopApp main flow
webfiltered Aug 31, 2025
33feb7e
Add debug logging to main entry point
webfiltered Aug 31, 2025
61d0a97
Run formatter on debug logging code
webfiltered Aug 31, 2025
383d7e4
Allow InstallStage to be used in frontend
webfiltered Sep 1, 2025
d75e5a7
Add progress values to desktopApp.ts install stages
webfiltered Sep 3, 2025
e6caecf
Add progress values to installationManager.ts stages
webfiltered Sep 3, 2025
9b53961
Add progress values to virtualEnvironment.ts stages
webfiltered Sep 3, 2025
d1d6fee
Add progress values to comfyInstallation.ts validation stages
webfiltered Sep 3, 2025
f6ac45f
Add progress value to installWizard.ts config stage
webfiltered Sep 3, 2025
3cefbc7
Add progress value to IDLE stage in appState.ts
webfiltered Sep 3, 2025
6d65bbc
Make progress property required in InstallStageInfo
webfiltered Sep 3, 2025
203f841
Adjust progress allocation: hardware 10%, Python expanded 20%
webfiltered Sep 3, 2025
0f7613a
Revert "Add startup debug logger utility"
webfiltered Sep 3, 2025
b8e2ab9
Update test expectation - this is being removed.
webfiltered Sep 3, 2025
d9791a7
Add node-pty rebuild bug workaround for CC
webfiltered Sep 4, 2025
4cbe9cc
Remove validation progress update calls
webfiltered Sep 4, 2025
72f9d85
Redistribute installation progress percentages
webfiltered Sep 4, 2025
4d15140
Add progress update for PyTorch installation
webfiltered Sep 4, 2025
b2d2824
Add INSTALLING_PYTORCH as proper install stage
webfiltered Sep 4, 2025
3898d6d
Update PyTorch installation to use INSTALLING_PYTORCH stage
webfiltered Sep 4, 2025
c5c0686
Add separate install stages for ComfyUI and Manager requirements
webfiltered Sep 4, 2025
ef2702f
Update all requirement installations to use proper stages
webfiltered Sep 4, 2025
614516d
Complete refactoring of install stages with proper naming
webfiltered Sep 4, 2025
e6a2a7a
Force 1024x768 window size for fresh installs
webfiltered Sep 4, 2025
b21525f
Fix progress ordering: ComfyUI requirements before PyTorch
webfiltered Sep 4, 2025
eeb9624
Update STARTING_SERVER progress to 95%
webfiltered Sep 4, 2025
b49b180
Restore INSTALLING_REQUIREMENTS stage
webfiltered Sep 4, 2025
4b7c1b2
Simplify repo scripts - always auto-fix, use caching
webfiltered Sep 4, 2025
dc3e23d
Set starting server progress to undefined
webfiltered Sep 4, 2025
ef69c9d
Allow undefined progress for indeterminate states
webfiltered Sep 4, 2025
89ab620
Revert uv parser AppState - being split out
webfiltered Sep 4, 2025
6da1665
Revert uv parser - being split out
webfiltered Sep 4, 2025
df0b196
nit
webfiltered Sep 4, 2025
56bf40d
nit - remove commented
webfiltered Sep 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .claude/cclsp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"servers": [
{
"extensions": ["js", "ts", "jsx", "tsx"],
"command": ["npx", "--", "typescript-language-server", "--stdio"],
"rootDir": "."
}
]
}
9 changes: 4 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@
### Code Quality (ALWAYS RUN AFTER CHANGES)

```bash
yarn lint # Check ESLint issues
yarn lint:fix # Auto-fix ESLint issues
yarn format # Check Prettier formatting
yarn format:fix # Auto-format code
yarn lint # Check & auto-fix ESLint issues
yarn format # Auto-format code
yarn typescript # TypeScript type checking
```

Expand Down Expand Up @@ -57,6 +55,7 @@ yarn vite:compile # Compile with Vite
### Troubleshooting

- If you encounter errors regarding `NODE_MODULE_VERSION`, try running `npx electron-rebuild` before other troubleshooting steps.
- If that still fails, try `yarn rebuild`

## Custom testing

Expand Down Expand Up @@ -138,7 +137,7 @@ The app packages these components:

## Before Committing

1. Use `yarn format:fix` to ensure consistent formatting
1. Use `yarn format` to ensure consistent formatting
1. Run `yarn lint` and `yarn typescript` to check code quality
1. Run `yarn test:unit` to ensure unit tests pass
1. Consider running `yarn test:e2e` for UI changes
Expand Down
6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,8 @@
"download:uv": "node scripts/downloadUV.js",
"download-frontend": "node scripts/downloadFrontend.js",
"make:frontend": "yarn run download-frontend",
"format": "prettier --check .",
"format:fix": "prettier --write .",
"lint": "eslint src",
"lint:fix": "eslint --fix src",
"format": "prettier --write --cache --log-level warn .",
"lint": "eslint --fix --cache src",
"make": "yarn run vite:compile && electron-builder build --config=builder-debug.config.ts && yarn run verify:build",
"make:assets": "node scripts/makeComfy.js",
"make:nvidia": "yarn run make -- --nvidia",
Expand Down
8 changes: 8 additions & 0 deletions src/desktopApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import log from 'electron-log/main';

import { ProgressStatus } from './constants';
import { IPC_CHANNELS } from './constants';
import { InstallStage } from './constants';
import { registerAppHandlers } from './handlers/AppHandlers';
import { registerAppInfoHandlers } from './handlers/appInfoHandlers';
import { registerGpuHandlers } from './handlers/gpuHandlers';
Expand All @@ -19,6 +20,7 @@ import { AppWindow } from './main-process/appWindow';
import { ComfyDesktopApp } from './main-process/comfyDesktopApp';
import type { ComfyInstallation } from './main-process/comfyInstallation';
import { DevOverrides } from './main-process/devOverrides';
import { createInstallStageInfo } from './main-process/installStages';
import SentryLogging from './services/sentry';
import { type HasTelemetry, type ITelemetry, getTelemetry, promptMetricsConsent } from './services/telemetry';
import { DesktopConfig } from './store/desktopConfig';
Expand All @@ -39,6 +41,7 @@ export class DesktopApp implements HasTelemetry {
/** Load start screen - basic spinner */
async showLoadingPage() {
try {
this.appState.setInstallStage(createInstallStageInfo(InstallStage.APP_INITIALIZING, { progress: 1 }));
await this.appWindow.loadPage('desktop-start');
} catch (error) {
DesktopApp.fatalError({
Expand Down Expand Up @@ -84,6 +87,7 @@ export class DesktopApp implements HasTelemetry {

if (!appState.ipcRegistered) this.registerIpcHandlers();

appState.setInstallStage(createInstallStageInfo(InstallStage.CHECKING_EXISTING_INSTALL, { progress: 2 }));
const installation = await this.initializeInstallation();
if (!installation) return;
this.installation = installation;
Expand All @@ -102,21 +106,25 @@ export class DesktopApp implements HasTelemetry {
// Start server
if (!overrides.useExternalServer && !comfyDesktopApp.serverRunning) {
try {
appState.setInstallStage(createInstallStageInfo(InstallStage.STARTING_SERVER));
await comfyDesktopApp.startComfyServer(serverArgs);
} catch (error) {
log.error('Unhandled exception during server start', error);
appWindow.send(IPC_CHANNELS.LOG_MESSAGE, `${error}\n`);
appWindow.sendServerStartProgress(ProgressStatus.ERROR);
appState.setInstallStage(createInstallStageInfo(InstallStage.ERROR, { progress: 0, error: String(error) }));
return;
}
}
appWindow.sendServerStartProgress(ProgressStatus.READY);
await appWindow.loadComfyUI(serverArgs);

// App start complete
appState.setInstallStage(createInstallStageInfo(InstallStage.READY, { progress: 100 }));
appState.emitLoaded();
} catch (error) {
log.error('Unhandled exception during app startup', error);
appState.setInstallStage(createInstallStageInfo(InstallStage.ERROR, { error: String(error) }));
appWindow.sendServerStartProgress(ProgressStatus.ERROR);
appWindow.send(IPC_CHANNELS.LOG_MESSAGE, `${error}\n`);
if (!this.appState.isQuitting) {
Expand Down
6 changes: 6 additions & 0 deletions src/install/installWizard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import path from 'node:path';
import { ComfyConfigManager } from '../config/comfyConfigManager';
import { ComfyServerConfig, ModelPaths } from '../config/comfyServerConfig';
import { ComfySettings, type ComfySettingsData } from '../config/comfySettings';
import { InstallStage } from '../constants';
import { useAppState } from '../main-process/appState';
import { createInstallStageInfo } from '../main-process/installStages';
import { InstallOptions } from '../preload';
import { HasTelemetry, ITelemetry, trackEvent } from '../services/telemetry';

Expand All @@ -31,6 +34,9 @@ export class InstallWizard implements HasTelemetry {
// Setup the ComfyUI folder structure.
ComfyConfigManager.createComfyDirectories(this.basePath);
this.initializeUserFiles();

useAppState().setInstallStage(createInstallStageInfo(InstallStage.INITIALIZING_CONFIG, { progress: 10 }));

await this.initializeSettings();
await this.initializeModelPaths();
}
Expand Down
19 changes: 17 additions & 2 deletions src/install/installationManager.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Notification, app, dialog, ipcMain, shell } from 'electron';
import log from 'electron-log/main';

import { IPC_CHANNELS, ProgressStatus } from '../constants';
import { IPC_CHANNELS, InstallStage, ProgressStatus } from '../constants';
import { useAppState } from '../main-process/appState';
import type { AppWindow } from '../main-process/appWindow';
import { ComfyInstallation } from '../main-process/comfyInstallation';
import { createInstallStageInfo } from '../main-process/installStages';
import type { InstallOptions, InstallValidation } from '../preload';
import { CmCli } from '../services/cmCli';
import { type HasTelemetry, ITelemetry, trackEvent } from '../services/telemetry';
Expand Down Expand Up @@ -84,6 +86,10 @@ export class InstallationManager implements HasTelemetry {
this.telemetry.track('validation:error_found', { error });

log.info('Validation error - loading maintenance page.');
const appState = useAppState();
appState.setInstallStage(
createInstallStageInfo(InstallStage.MAINTENANCE_MODE, { progress: 90, message: `Validation error: ${error}` })
);
this.appWindow.loadPage('maintenance').catch((error) => {
log.error('Error loading maintenance page.', error);
const message = `An error was detected with your installation, and the maintenance page could not be loaded to resolve it. The app will close now. Please reinstall if this issue persists.\n\nError message:\n\n${error}`;
Expand All @@ -107,9 +113,11 @@ export class InstallationManager implements HasTelemetry {
async freshInstall(): Promise<ComfyInstallation> {
log.info('Starting installation.');
const config = useDesktopConfig();
const appState = useAppState();
config.set('installState', 'started');

// Check available GPU
appState.setInstallStage(createInstallStageInfo(InstallStage.HARDWARE_VALIDATION, { progress: 3 }));
const hardware = await validateHardware();
if (typeof hardware.gpu === 'string') config.set('detectedGpu', hardware.gpu);

Expand All @@ -129,11 +137,13 @@ export class InstallationManager implements HasTelemetry {
await this.appWindow.loadPage('not-supported');
} else {
log.verbose('Loading welcome renderer.');
appState.setInstallStage(createInstallStageInfo(InstallStage.WELCOME_SCREEN, { progress: 4 }));
await this.appWindow.loadPage('welcome');
}

// Check if git is installed
log.verbose('Checking if git is installed.');
appState.setInstallStage(createInstallStageInfo(InstallStage.GIT_CHECK, { progress: 5 }));
const gitInstalled = await canExecuteShellCommand('git --version');
if (!gitInstalled) {
log.verbose('git not detected in path, loading download-git page.');
Expand All @@ -153,6 +163,7 @@ export class InstallationManager implements HasTelemetry {
}

// Handover to frontend
appState.setInstallStage(createInstallStageInfo(InstallStage.INSTALL_OPTIONS_SELECTION, { progress: 6 }));
const installOptions = await optionsPromise;
this.telemetry.track('desktop:install_options_received', {
gpuType: installOptions.device,
Expand All @@ -178,10 +189,10 @@ export class InstallationManager implements HasTelemetry {
}

// Creates folders and initializes ComfyUI settings
appState.setInstallStage(createInstallStageInfo(InstallStage.CREATING_DIRECTORIES, { progress: 8 }));
const installWizard = new InstallWizard(installOptions, this.telemetry);
await installWizard.install();

this.appWindow.maximize();
const shouldMigrateCustomNodes =
!!installWizard.migrationSource && installWizard.migrationItemIds.has('custom_nodes');
if (shouldMigrateCustomNodes) {
Expand All @@ -205,10 +216,14 @@ export class InstallationManager implements HasTelemetry {
};

// Create virtual environment
appState.setInstallStage(createInstallStageInfo(InstallStage.PYTHON_ENVIRONMENT_SETUP, { progress: 15 }));
this.appWindow.sendServerStartProgress(ProgressStatus.PYTHON_SETUP);
await virtualEnvironment.create(processCallbacks);

// Migrate custom nodes
if (shouldMigrateCustomNodes) {
appState.setInstallStage(createInstallStageInfo(InstallStage.MIGRATING_CUSTOM_NODES, { progress: 75 }));
}
const customNodeMigrationError = await this.migrateCustomNodes(config, virtualEnvironment, processCallbacks);
if (customNodeMigrationError) {
// TODO: Replace with IPC callback to handle i18n (SoC).
Expand Down
19 changes: 13 additions & 6 deletions src/main-process/appState.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { app } from 'electron';
import { EventEmitter } from 'node:events';

import { InstallStage } from '@/constants';
import { AppStartError } from '@/infrastructure/appStartError';
import type { Page } from '@/infrastructure/interfaces';

import type { InstallStageInfo } from './installStages';
import { type InstallStageInfo, createInstallStageInfo } from './installStages';

/** App event names */
type AppStateEvents = {
/** Occurs once, immediately before registering IPC handlers. */
ipcRegistered: [];
/** Occurs once, immediately after the ComfyUI server has finished loading. */
loaded: [];
/** Occurs when the installation stage changes */
/** Occurs when the install stage changes. */
installStageChanged: [InstallStageInfo];
};

Expand All @@ -30,14 +31,14 @@ export interface IAppState extends Pick<EventEmitter<AppStateEvents>, 'on' | 'on
readonly loaded: boolean;
/** The last page the app loaded from the desktop side. @see {@link AppWindow.loadPage} */
currentPage?: Page;
/** The current installation stage information */
installStage?: InstallStageInfo;
/** Current installation stage information. */
readonly installStage: InstallStageInfo;

/** Updates state - IPC handlers have been registered. */
emitIpcRegistered(): void;
/** Updates state - the app has loaded. */
emitLoaded(): void;
/** Updates the installation stage */
/** Updates the current install stage. */
setInstallStage(stage: InstallStageInfo): void;
}

Expand All @@ -49,7 +50,13 @@ class AppState extends EventEmitter<AppStateEvents> implements IAppState {
ipcRegistered = false;
loaded = false;
currentPage?: Page;
installStage?: InstallStageInfo;
installStage: InstallStageInfo;

constructor() {
super();
// Initialize install stage to idle
this.installStage = createInstallStageInfo(InstallStage.IDLE, { progress: 0 });
}

initialize() {
// Store quitting state - suppresses errors when already quitting
Expand Down
9 changes: 5 additions & 4 deletions src/main-process/appWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ export class AppWindow {
const minWidth = 640;
const minHeight = 640;

// Retrieve stored window size, or use default if not available
const storedWidth = store.get('windowWidth', width);
const storedHeight = store.get('windowHeight', height);
// For fresh installs, force 1024x768 regardless of stored values
const storedWidth = installed ? store.get('windowWidth', width) : width;
const storedHeight = installed ? store.get('windowHeight', height) : height;
const storedX = store.get('windowX');
const storedY = store.get('windowY');

Expand Down Expand Up @@ -114,7 +114,8 @@ export class AppWindow {
this.window.once('ready-to-show', () => this.window.show());

if (!installed && storedX === undefined) this.window.center();
if (store.get('windowMaximized')) this.window.maximize();
// Only maximize for installed apps with the stored preference
if (installed && store.get('windowMaximized')) this.window.maximize();

this.setupWindowEvents();
this.setupAppEvents();
Expand Down
4 changes: 2 additions & 2 deletions src/main-process/installStages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type InstallStageName = ValuesOf<typeof InstallStage>;

export interface InstallStageInfo {
stage: InstallStageName;
progress: number; // 0-100
progress?: number; // 0-100, undefined for indeterminate
message?: string;
error?: string;
timestamp: number;
Expand All @@ -29,7 +29,7 @@ export function createInstallStageInfo(
): InstallStageInfo {
return {
stage,
progress: options?.progress ?? 0,
progress: options?.progress,
message: options?.message,
error: options?.error,
timestamp: Date.now(),
Expand Down
29 changes: 28 additions & 1 deletion src/virtualEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { rm } from 'node:fs/promises';
import os, { EOL } from 'node:os';
import path from 'node:path';

import { TorchMirrorUrl } from './constants';
import { InstallStage, TorchMirrorUrl } from './constants';
import { useAppState } from './main-process/appState';
import { createInstallStageInfo } from './main-process/installStages';
import type { TorchDeviceType } from './preload';
import { captureSentryException } from './services/sentry';
import { HasTelemetry, ITelemetry, trackEvent } from './services/telemetry';
Expand Down Expand Up @@ -301,6 +303,10 @@ export class VirtualEnvironment implements HasTelemetry {

@trackEvent('install_flow:virtual_environment_install_requirements')
public async installRequirements(callbacks?: ProcessCallbacks): Promise<void> {
useAppState().setInstallStage(
createInstallStageInfo(InstallStage.INSTALLING_REQUIREMENTS, { progress: 25 })
);

// pytorch nightly is required for MPS
if (process.platform === 'darwin') {
return this.manualInstall(callbacks);
Expand Down Expand Up @@ -476,6 +482,13 @@ export class VirtualEnvironment implements HasTelemetry {
}

async installPytorch(callbacks?: ProcessCallbacks): Promise<void> {
useAppState().setInstallStage(
createInstallStageInfo(InstallStage.INSTALLING_PYTORCH, {
progress: 25,
message: 'Installing PyTorch',
})
);

const torchMirror = this.torchMirror || getDefaultTorchMirror(this.selectedDevice);
const config: PipInstallConfig = {
packages: ['torch', 'torchvision', 'torchaudio'],
Expand All @@ -494,6 +507,13 @@ export class VirtualEnvironment implements HasTelemetry {
}

async installComfyUIRequirements(callbacks?: ProcessCallbacks): Promise<void> {
useAppState().setInstallStage(
createInstallStageInfo(InstallStage.INSTALLING_COMFYUI_REQUIREMENTS, {
progress: 45,
message: 'Installing ComfyUI requirements',
})
);

log.info(`Installing ComfyUI requirements from ${this.comfyUIRequirementsPath}`);
const installCmd = getPipInstallArgs({
requirementsFile: this.comfyUIRequirementsPath,
Expand All @@ -507,6 +527,13 @@ export class VirtualEnvironment implements HasTelemetry {
}

async installComfyUIManagerRequirements(callbacks?: ProcessCallbacks): Promise<void> {
useAppState().setInstallStage(
createInstallStageInfo(InstallStage.INSTALLING_MANAGER_REQUIREMENTS, {
progress: 60,
message: 'Installing ComfyUI Manager requirements',
})
);

log.info(`Installing ComfyUIManager requirements from ${this.comfyUIManagerRequirementsPath}`);
const installCmd = getPipInstallArgs({
requirementsFile: this.comfyUIManagerRequirementsPath,
Expand Down
4 changes: 0 additions & 4 deletions tests/integration/install/installApp.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ test.describe('Install App', () => {
const status = await serverStart.status.get();
expect(['loading', 'setting up python']).toContain(status);

// Confirm window is maximized, then restore (for screenshot)
await expect(app.isMaximized()).resolves.toBe(true);
await app.restoreWindow();

// When the terminal is hidden and no error is shown, the install is successful
await expect(serverStart.terminal).not.toBeVisible({ timeout: 5 * 60 * 1000 });
await expect(serverStart.status.error).not.toBeVisible();
Expand Down
Loading
Loading