@@ -83,19 +83,40 @@ export const useSetupWizard = defineStore('setupWizard', () => {
8383 const disabledBackends = ref ( new Set < BackendServiceName > ( ) )
8484 const wizardDirty = ref ( false )
8585
86+ const wizardActivity = ref ( new Map < BackendServiceName , string > ( ) )
87+
8688 const errorModalOpen = ref ( false )
8789 const errorModalServiceName = ref < BackendServiceName | null > ( null )
8890 const errorModalDetails = ref < ErrorDetails | null > ( null )
8991
92+ const comfyUiNeedsVariantSwitch = computed ( ( ) => {
93+ const current = productModeStore . productMode
94+ const pending = pendingProductMode . value
95+ if ( ! current || ! pending || current === pending ) return false
96+ const crossesNvidiaBoundary = current === 'nvidia' || pending === 'nvidia'
97+ if ( ! crossesNvidiaBoundary ) return false
98+ const comfyInfo = backendServices . info . find ( ( s ) => s . serviceName === 'comfyui-backend' )
99+ return comfyInfo ?. isSetUp === true
100+ } )
101+
90102 const backendRows = computed < BackendRowViewModel [ ] > ( ( ) => {
91103 return backends . map ( ( serviceName ) => {
92104 const info = backendServices . info . find ( ( s ) => s . serviceName === serviceName )
93105 const available = isBackendAvailableInProductMode ( pendingProductMode . value , serviceName )
94106 const isRequired = info ?. isRequired ?? serviceName === 'ai-backend'
95- const isSetUp = info ?. isSetUp ?? false
96- const status = info ?. status ?? ( 'notInstalled' as BackendStatus )
107+ let isSetUp = info ?. isSetUp ?? false
108+ let status = info ?. status ?? ( 'notInstalled' as BackendStatus )
109+
110+ if ( serviceName === 'comfyui-backend' && comfyUiNeedsVariantSwitch . value ) {
111+ isSetUp = false
112+ status = 'notInstalled' as BackendStatus
113+ }
114+
97115 const isInstalling =
98- status === 'installing' || status === 'starting' || status === 'stopping'
116+ status === 'installing' ||
117+ status === 'starting' ||
118+ status === 'stopping' ||
119+ wizardActivity . value . has ( serviceName )
99120 const enabled = isRequired || installSelection . value . has ( serviceName )
100121 const toggleDisabled = isRequired || ! available || isInstalling
101122
@@ -125,20 +146,23 @@ export const useSetupWizard = defineStore('setupWizard', () => {
125146 versionDisplay = vs . installed . releaseTag
126147 ? `${ vs . installed . releaseTag } / ${ vs . installed . version } `
127148 : vs . installed . version
128- } else if ( ! isSetUp ) {
149+ } else if ( ! isSetUp && ! ( serviceName === 'comfyui-backend' && comfyUiNeedsVariantSwitch . value ) ) {
129150 versionDisplay = 'Not installed'
130151 }
131152 }
132153
154+ const activityMessage = wizardActivity . value . get ( serviceName )
133155 let installProgressText : string | null = null
134- if ( isInstalling ) {
156+ if ( isInstalling || activityMessage ) {
135157 const progress = backendServices . latestSetupProgress . get ( serviceName )
136158 if ( progress ) {
137159 const steps = knownSteps [ serviceName ] ?? [ ]
138160 const stepIdx = steps . indexOf ( progress . step )
139161 const label = stepDisplayNames [ progress . step ] ?? progress . debugMessage
140162 installProgressText =
141163 stepIdx >= 0 ? `${ label } (${ stepIdx + 1 } /${ steps . length } )` : label
164+ } else if ( activityMessage ) {
165+ installProgressText = activityMessage
142166 } else if ( status === 'stopping' ) {
143167 installProgressText = 'Stopping...'
144168 } else if ( status === 'starting' ) {
@@ -159,7 +183,10 @@ export const useSetupWizard = defineStore('setupWizard', () => {
159183 toggleDisabled,
160184 isInstalling,
161185 statusColor : mapStatusToColor ( status ) ,
162- statusText : mapToDisplayStatus ( status ) ?? status ,
186+ statusText :
187+ serviceName === 'comfyui-backend' && comfyUiNeedsVariantSwitch . value
188+ ? `Needs reinstall for ${ pendingProductMode . value === 'nvidia' ? 'CUDA' : 'XPU' } `
189+ : ( mapToDisplayStatus ( status ) ?? status ) ,
163190 versionDisplay,
164191 errorDetails : backendServices . getServiceErrorDetails ( serviceName ) ,
165192 toggleTooltip,
@@ -280,7 +307,20 @@ export const useSetupWizard = defineStore('setupWizard', () => {
280307 initialLoadingPollHandle = null
281308 }
282309
283- await productModeStore . ensureReady ( )
310+ const modeStatus = await productModeStore . ensureReady ( )
311+
312+ if ( modeStatus === 'ready' ) {
313+ const allRequiredSetUp = backendServices . info
314+ . filter ( ( s ) => s . isRequired )
315+ . every ( ( s ) => s . isSetUp )
316+
317+ if ( allRequiredSetUp ) {
318+ pendingProductMode . value = productModeStore . productMode
319+ seedInstallSelection ( )
320+ await dismiss ( )
321+ return
322+ }
323+ }
284324
285325 if ( ! productModeStore . hardwareRecommendation ) {
286326 await productModeStore . detectRecommendation ( )
@@ -304,18 +344,20 @@ export const useSetupWizard = defineStore('setupWizard', () => {
304344 async function commitAndInstall ( ) {
305345 if ( ! pendingProductMode . value ) return
306346
307- if ( pendingProductMode . value !== productModeStore . productMode ) {
308- await productModeStore . selectMode ( pendingProductMode . value )
309- }
310- await syncPresetsForCurrentProductMode ( )
311-
347+ // Capture what needs installing BEFORE syncing mode — syncing resets the
348+ // variant-switch detection because current and pending modes become equal.
312349 const toInstall = backendRows . value . filter (
313350 ( r ) =>
314351 r . enabled &&
315352 r . availableInCurrentMode &&
316353 ( r . status === 'notInstalled' || r . status === 'failed' || r . status === 'installationFailed' ) ,
317354 )
318355
356+ if ( pendingProductMode . value !== productModeStore . productMode ) {
357+ await productModeStore . selectMode ( pendingProductMode . value )
358+ }
359+ await syncPresetsForCurrentProductMode ( )
360+
319361 if ( toInstall . length > 0 ) {
320362 wizardDirty . value = true
321363
@@ -369,6 +411,12 @@ export const useSetupWizard = defineStore('setupWizard', () => {
369411 }
370412
371413 try {
414+ wizardActivity . value . set ( name , 'Detecting devices...' )
415+ wizardActivity . value = new Map ( wizardActivity . value )
416+ await backendServices . detectDevices ( name )
417+
418+ wizardActivity . value . set ( name , 'Starting...' )
419+ wizardActivity . value = new Map ( wizardActivity . value )
372420 const startStatus = await backendServices . startService ( name )
373421 if ( startStatus !== 'running' ) {
374422 const errorDetails = backendServices . getServiceErrorDetails ( name )
@@ -383,6 +431,9 @@ export const useSetupWizard = defineStore('setupWizard', () => {
383431 ? 'Service startup failed — see error log for details'
384432 : `Service startup failed: ${ error instanceof Error ? error . message : String ( error ) } `
385433 toast . error ( msg )
434+ } finally {
435+ wizardActivity . value . delete ( name )
436+ wizardActivity . value = new Map ( wizardActivity . value )
386437 }
387438 }
388439
0 commit comments