feat: implement generation workflow with resource loading and candidate management

This commit is contained in:
syntaxbullet
2026-07-10 23:54:52 +02:00
parent 9697075d29
commit 51a54dbdb2
9 changed files with 308 additions and 117 deletions

View File

@@ -2,9 +2,9 @@ import { useEffect, useRef, useState, type RefObject } from "react";
import { CaretDown, CaretUp } from "@phosphor-icons/react";
import { commandIds } from "@commands/ids";
import type { AppStore } from "@editor/store";
import type { GenerationOptions, GenerationResourcesState } from "@editor/state";
import { generateArchitectureDefaults } from "@editor/tools";
import type { GenerateArchitecture, GenerateMode, GenerateModel, GenerateSettings } from "@editor/tools";
import type { GenerationResourcesState } from "@editor/state";
import type { GenerateArchitecture, GenerateMode, GenerateSettings } from "@editor/tools";
import { resolveGenerationModeOptions, resolveGenerationModelOptions, resolveGenerationStringOptions, resolveGenerationSupportOptions } from "@operations/generation/options";
import { BottomControlSelectMenu, type BottomControlSelectOption } from "./SelectMenu";
import { BottomControlSlider } from "./Slider";
@@ -55,11 +55,11 @@ export function GenerateControls({ settings, resources, dispatch }: GenerateCont
const [inpaintOpen, setInpaintOpen] = useState(false);
const [sizeOpen, setSizeOpen] = useState(false);
const sizeRef = useRef<HTMLDivElement>(null);
const modelOptions = resolveModelOptions(settings, comfyOptions);
const supportOptions = resolveSupportOptions(settings, comfyOptions);
const samplerOptions = resolveStringOptions(comfyOptions?.samplers, settings.sampler);
const schedulerOptions = resolveStringOptions(comfyOptions?.schedulers, settings.scheduler);
const modeOptions = resolveModeOptions(settings, comfyOptions);
const modelOptions = resolveGenerationModelOptions(settings, comfyOptions);
const supportOptions = resolveGenerationSupportOptions(settings, comfyOptions);
const samplerOptions = resolveGenerationStringOptions(comfyOptions?.samplers, settings.sampler);
const schedulerOptions = resolveGenerationStringOptions(comfyOptions?.schedulers, settings.scheduler);
const modeOptions = resolveGenerationModeOptions(settings, comfyOptions, modes);
useEffect(() => {
if (!sizeOpen) return;
@@ -197,38 +197,6 @@ export function GenerateControls({ settings, resources, dispatch }: GenerateCont
);
}
function resolveModelOptions(settings: GenerateSettings, comfyOptions: GenerationOptions | undefined): readonly BottomControlSelectOption<GenerateModel>[] {
const architecture = comfyOptions?.architectures?.find((option) => option.value === settings.architecture);
const models = architecture?.models ?? (settings.architecture === "sdxl" ? comfyOptions?.models : undefined) ?? [];
const fallbackModel = architecture?.defaultModel ?? generateArchitectureDefaults[settings.architecture].model;
const values = unique(["auto", ...models, ...(models.length === 0 && fallbackModel !== "auto" ? [fallbackModel] : []), settings.model]);
return values.map((model) => ({ value: model, label: model === "auto" ? "Auto" : model }));
}
function resolveSupportOptions(settings: GenerateSettings, comfyOptions: GenerationOptions | undefined) {
const defaults = generateArchitectureDefaults[settings.architecture];
return {
textEncoders: resolveStringOptions([...(comfyOptions?.textEncoders ?? []), defaults.textEncoder].filter((value) => value !== "auto"), settings.textEncoder),
vaes: resolveStringOptions([...(comfyOptions?.vaes ?? []), defaults.vae].filter((value) => value !== "auto"), settings.vae),
};
}
function resolveStringOptions(values: string[] | undefined, current: string): readonly BottomControlSelectOption<string>[] {
return unique([...(values ?? []), current]).map((value) => ({ value, label: value }));
}
function resolveModeOptions(settings: GenerateSettings, comfyOptions: GenerationOptions | undefined): readonly BottomControlSelectOption<GenerateMode>[] {
const architecture = comfyOptions?.architectures?.find((option) => option.value === settings.architecture);
const supportedModes = architecture?.supportedModes?.length ? architecture.supportedModes : generateArchitectureDefaults[settings.architecture].supportedModes;
const availableModes = modes.filter((mode) => supportedModes.includes(mode.value));
if (availableModes.some((mode) => mode.value === settings.mode)) return availableModes;
return [modes.find((mode) => mode.value === settings.mode), ...availableModes].filter((mode): mode is BottomControlSelectOption<GenerateMode> => Boolean(mode));
}
function unique<T>(values: T[]): T[] {
return Array.from(new Set(values));
}
function SectionTitle({ title }: { title: string }) {
return <div className="px-1 text-xs font-semibold uppercase tracking-[0.18em] text-white/35">{title}</div>;
}