Add Image Iterate: nested multi-prompt still families.

Iterate runs a series of prompts as generate (no still), edit (still A), or compose (A+B), saves each output under one library collection like video extensions, and defaults to iterating from the original still.
This commit is contained in:
2026-09-04 22:46:19 -05:00
parent 279ac72049
commit 2435167a41
6 changed files with 261 additions and 130 deletions
+120 -38
View File
@@ -24,6 +24,12 @@
<p class="text-sm text-zinc-400">{{ studioMode === 'editv2'
? (v2Mode === 'generate'
? 'Generate: no reference image. Prompt only.'
: v2Mode === 'iterate'
? (file
? (editRefFile
? 'Iterate: each prompt runs as Compose from stills A and B (or chain from the last output). All results nest in one library collection.'
: 'Iterate: each prompt runs from still A (batch) or from the last output (chain). All results nest in one library collection.')
: 'Iterate: each prompt is a separate generate. All results nest in one library collection like video extensions.')
: v2Mode === 'refine'
? 'Refine: paint a mask on Still A. Prompt only what should change in the painted area. Strength is denoise in that region.'
: v2Mode === 'compose'
@@ -35,7 +41,7 @@
</div>
<div
v-if="!(studioMode === 'editv2' && v2Mode === 'generate')"
v-if="!(studioMode === 'editv2' && (v2Mode === 'generate' || (v2Mode === 'iterate' && !file && !inputStillId)))"
class="relative cursor-pointer rounded-2xl border border-dashed border-white/15 bg-zinc-950/50 p-4 transition hover:border-amber-300/50"
:class="{ 'border-amber-300/70 bg-amber-400/5': dragging }"
@dragover.prevent="dragging = true"
@@ -71,7 +77,14 @@
v-else-if="studioMode === 'editv2' && v2Mode === 'generate' && (file || inputStillId)"
class="rounded-2xl border border-white/10 bg-zinc-950/40 px-4 py-3 text-sm text-zinc-400"
>
Still A is loaded for Edit / Compose / Refine. Generate ignores it and uses the prompt only.
Still A is loaded for Edit / Compose / Refine / Iterate. Generate ignores it and uses the prompt only.
</div>
<div
v-else-if="studioMode === 'editv2' && v2Mode === 'iterate'"
class="rounded-2xl border border-dashed border-white/15 bg-zinc-950/40 px-4 py-3 text-sm text-zinc-400"
>
<button type="button" class="font-medium text-amber-100 hover:underline" @click="openPicker('main')">Optional · add still A</button>
<span class="mt-1 block text-zinc-500">No still = text generate iterations. With a still = edit (or compose if you add still B).</span>
</div>
<div v-if="file || inputStillId" class="mt-2 flex min-w-0 items-center gap-2">
@@ -144,7 +157,17 @@
>
Generate
</button>
<label v-if="v2Mode === 'compose'" class="ml-auto text-xs">
<button
type="button"
class="rounded-full border px-3 py-1 text-xs font-medium disabled:cursor-not-allowed disabled:opacity-40"
:class="v2Mode === 'iterate' ? 'border-amber-300/70 bg-amber-400/10 text-amber-100' : 'border-white/10 text-zinc-400 hover:text-white'"
:disabled="v2ModeLocked && v2Mode !== 'iterate'"
:title="v2ModeLocked && v2Mode !== 'iterate' ? 'Remove extra passes to change graphs' : ''"
@click="setV2Mode('iterate')"
>
Iterate
</button>
<label v-if="v2Mode === 'compose' || (v2Mode === 'iterate' && editRefFile)" class="ml-auto text-xs">
<span class="mr-2 text-zinc-500">Task</span>
<select
v-model="v2Task"
@@ -158,9 +181,9 @@
</label>
</div>
<div v-if="studioMode === 'edit' || (studioMode === 'editv2' && v2Mode === 'compose')" class="rounded-2xl border border-dashed border-white/15 bg-zinc-950/50 p-4">
<div v-if="studioMode === 'edit' || (studioMode === 'editv2' && (v2Mode === 'compose' || (v2Mode === 'iterate' && file)))" class="rounded-2xl border border-dashed border-white/15 bg-zinc-950/50 p-4">
<div class="mb-2 flex items-center justify-between gap-2">
<p class="text-sm font-medium text-zinc-300">{{ studioMode === 'editv2' ? 'Still B · required' : 'Image 2 · optional' }}</p>
<p class="text-sm font-medium text-zinc-300">{{ studioMode === 'editv2' && v2Mode === 'compose' ? 'Still B · required' : studioMode === 'editv2' ? 'Still B · optional' : 'Image 2 · optional' }}</p>
<button
v-if="editRefFile"
type="button"
@@ -203,7 +226,7 @@
<div>
<div class="mb-2 flex flex-wrap items-center justify-between gap-2">
<label class="text-sm font-medium text-zinc-300">{{ studioMode === 'editv2' && v2Mode === 'generate' ? 'Generate prompt' : studioMode === 'editv2' && v2Mode === 'refine' ? 'Refine prompt' : studioMode === 'edit' || studioMode === 'editv2' ? 'Edit prompt' : 'Motion & scene prompt' }}</label>
<label class="text-sm font-medium text-zinc-300">{{ studioMode === 'editv2' && v2Mode === 'generate' ? 'Generate prompt' : studioMode === 'editv2' && v2Mode === 'iterate' ? 'Iteration 1' : studioMode === 'editv2' && v2Mode === 'refine' ? 'Refine prompt' : studioMode === 'edit' || studioMode === 'editv2' ? 'Edit prompt' : 'Motion & scene prompt' }}</label>
<div class="flex flex-wrap items-center gap-3">
<button
v-if="identityPrompting"
@@ -292,6 +315,7 @@
</label>
</div>
<p v-if="studioMode === 'editv2' && v2Mode === 'generate'" class="mt-3 text-xs text-zinc-500">No reference image. Prompt only.</p>
<p v-else-if="studioMode === 'editv2' && v2Mode === 'iterate'" class="mt-3 text-xs text-zinc-500">Add more iterations below. Everything saves as one nested library collection.</p>
<div v-if="studioMode === 'editv2' && v2Mode === 'refine'" class="mt-3 space-y-2">
<p class="text-xs text-zinc-500">Prompt only what should change in the painted area.</p>
<div class="flex flex-wrap gap-2">
@@ -345,14 +369,14 @@
</div>
</div>
<div v-if="studioMode === 'edit' || v2PassChaining" class="mt-3 space-y-3">
<div class="grid grid-cols-2 gap-2">
<div v-if="!(v2Mode === 'iterate' && !file)" class="grid grid-cols-2 gap-2">
<button
type="button"
class="rounded-xl border px-3 py-2 text-left text-sm transition"
:class="imagePassMode === 'batch' ? 'border-amber-300 bg-amber-400/10 text-amber-100' : 'border-white/10 hover:border-white/20'"
@click="imagePassMode = 'batch'"
>
<span class="block font-semibold">Batch</span>
<span class="block font-semibold">{{ v2Mode === 'iterate' ? 'From original' : 'Batch' }}</span>
<span class="text-[11px] leading-snug text-zinc-400">Each prompt from the start still</span>
</button>
<button
@@ -361,7 +385,7 @@
:class="imagePassMode === 'chain' ? 'border-amber-300 bg-amber-400/10 text-amber-100' : 'border-white/10 hover:border-white/20'"
@click="imagePassMode = 'chain'"
>
<span class="block font-semibold">Chain</span>
<span class="block font-semibold">{{ v2Mode === 'iterate' ? 'From last' : 'Chain' }}</span>
<span class="text-[11px] leading-snug text-zinc-400">Each pass from the last output</span>
</button>
</div>
@@ -383,7 +407,7 @@
class="rounded-2xl border border-white/10 bg-zinc-950/50 p-4"
>
<div class="mb-3 flex items-center justify-between gap-2">
<p class="text-sm font-medium text-zinc-200">{{ imagePassMode === 'batch' ? 'Prompt' : 'Pass' }} {{ index + 2 }}</p>
<p class="text-sm font-medium text-zinc-200">{{ v2Mode === 'iterate' ? 'Iteration' : imagePassMode === 'batch' ? 'Prompt' : 'Pass' }} {{ index + 2 }}</p>
<button
type="button"
class="text-xs text-red-300 hover:text-red-200"
@@ -844,7 +868,7 @@
compact
:disabled="v2Turbo"
/>
<template v-if="v2Mode !== 'generate'">
<template v-if="v2Mode !== 'generate' && !(v2Mode === 'iterate' && !file)">
<LampToggle :model-value="v2ScaleOn" label="Scale to MP" @update:model-value="setV2ScaleOn" />
<Thumbwheel
v-model="v2Megapixels"
@@ -1982,7 +2006,7 @@
<p class="truncate text-xs text-zinc-500">{{ stillMetaLine(entry.stillGroup.head) }}</p>
<div class="mt-2 flex flex-wrap items-center gap-3">
<button v-if="entry.stillGroup.parts.length > 1" type="button" class="text-xs text-amber-200" @click="toggleFamily(entry.stillGroup.key)">
{{ expandedFamilies[entry.stillGroup.key] ? 'Collapse' : `Expand ${entry.stillGroup.parts.length} passes` }}
{{ expandedFamilies[entry.stillGroup.key] ? 'Collapse' : `Expand ${entry.stillGroup.parts.length} ${entry.stillGroup.head.settings?.mode === 'iterate' ? 'iterations' : 'passes'}` }}
</button>
<button type="button" class="text-xs text-amber-300" @click="openStill(entry.stillGroup.head)">Open</button>
<button type="button" class="text-xs text-amber-300" @click="useStillAsInput(entry.stillGroup.head)">Use as input</button>
@@ -3198,38 +3222,52 @@ const stillBHint = computed(() => {
const editV2Blocked = computed(() => {
if (!folderId.value) return true
if (!prompt.value.trim() && !imageFillWithoutPrompt.value) return true
if (v2Mode.value !== 'generate' && !file.value) return true
if (v2Mode.value !== 'generate' && v2Mode.value !== 'iterate' && !file.value) return true
if (v2Mode.value === 'compose' && !editRefFile.value) return true
if (v2Mode.value === 'refine' && !refineMaskDirty.value) return true
if (v2PassChaining.value && editPassQueue.value.some(item => !item.prompt.trim())) return true
if (v2Mode.value === 'iterate' && !editPassQueue.value.length) return true
return false
})
const editV2BlockReason = computed(() => {
if (v2Mode.value !== 'generate' && !file.value) return 'Load still A first.'
if (v2Mode.value !== 'generate' && v2Mode.value !== 'iterate' && !file.value) return 'Load still A first.'
if (v2Mode.value === 'compose' && !editRefFile.value) return 'Compose requires still B. This will not fall back to one-image generation.'
if (v2Mode.value === 'refine' && !refineMaskDirty.value) return 'Paint a mask on Still A first. Refine will not fall back to Edit.'
if (!prompt.value.trim() && !imageFillWithoutPrompt.value) {
return v2Mode.value === 'generate'
return v2Mode.value === 'generate' || (v2Mode.value === 'iterate' && !file.value)
? 'Write a prompt first.'
: 'Write a prompt, or pick Landscape / Portrait / Square to fill the frame.'
}
if (v2Mode.value === 'iterate' && !editPassQueue.value.length) return 'Add at least one more iteration prompt.'
if (v2PassChaining.value && editPassQueue.value.some(item => !item.prompt.trim())) return 'Each extra pass needs a prompt.'
if (!folderId.value) return 'Choose a library folder before generating.'
if (!imageComfyConfigured.value && !comfyOk.value) return 'Image v2 is not configured. Set COMFY_HOST.'
return ''
})
const v2PassChaining = computed(() => studioMode.value === 'editv2' && (v2Mode.value === 'edit' || v2Mode.value === 'compose'))
const v2PassChaining = computed(() => studioMode.value === 'editv2' && (v2Mode.value === 'edit' || v2Mode.value === 'compose' || v2Mode.value === 'iterate'))
const v2ModeLocked = computed(() => v2PassChaining.value && editPassQueue.value.length > 0)
const extraPassButtonLabel = computed(() => {
if (v2Mode.value === 'iterate') return '+ Iteration'
if (imagePassMode.value === 'batch') return '+ Prompt'
return studioMode.value === 'editv2' && v2Mode.value === 'compose' ? '+ Compose pass' : '+ Edit pass'
})
const imageBatchButtonHint = computed(() => {
const n = 1 + editPassQueue.value.length
if (imageBatchScript.value.trim() && n > 1) return `${n} prompts on the start still. Same format as a video shot list.`
return 'Paste shot 1, shot 2, shot 3. Each image is a new prompt on the original still.'
if (imageBatchScript.value.trim() && n > 1) {
return v2Mode.value === 'iterate'
? `${n} iterations. Same format as a video shot list.`
: `${n} prompts on the start still. Same format as a video shot list.`
}
return v2Mode.value === 'iterate'
? 'Paste shot 1, shot 2, shot 3. Each line becomes one nested still.'
: 'Paste shot 1, shot 2, shot 3. Each image is a new prompt on the original still.'
})
const extraPassHint = computed(() => {
if (v2Mode.value === 'iterate') {
if (!file.value) return 'Each prompt is a separate generate. Outputs nest under one library collection.'
if (imagePassMode.value === 'batch') return 'Every prompt runs from the start still. Outputs nest under one library collection.'
return 'Each prompt runs from the last output. Outputs nest under one library collection.'
}
if (imagePassMode.value === 'batch') {
return 'Every prompt runs from the start still. Paste a shot list, or add prompts one at a time. Outputs do not feed the next prompt.'
}
@@ -3239,6 +3277,7 @@ const extraPassHint = computed(() => {
return 'Each extra pass is another Edit on the last output. You cannot switch graphs between passes.'
})
const extraPassPlaceholder = computed(() => {
if (v2Mode.value === 'iterate') return 'Next iteration prompt…'
if (imagePassMode.value === 'batch') return 'Another prompt for the same start still…'
return studioMode.value === 'editv2' && v2Mode.value === 'compose'
? 'Next compose prompt, applied to the previous pass output…'
@@ -3247,14 +3286,25 @@ const extraPassPlaceholder = computed(() => {
const editV2SubmitLabel = computed(() => {
const occupied = videoBusy.value || editBusy.value || studioJobs.value.some(job => job.status === 'running')
const n = v2PassChaining.value ? editPassQueue.value.length : 0
const label = v2Mode.value === 'generate' ? 'Generate image' : v2Mode.value === 'refine' ? 'Refine image' : v2Mode.value === 'compose' ? 'Compose image' : 'Edit image'
const label = v2Mode.value === 'generate'
? 'Generate image'
: v2Mode.value === 'iterate'
? 'Iterate'
: v2Mode.value === 'refine'
? 'Refine image'
: v2Mode.value === 'compose'
? 'Compose image'
: 'Edit image'
if (!occupied) {
if (v2Mode.value === 'iterate') return n ? `Iterate × ${n + 1}` : 'Iterate'
if (!n) return label
if (imagePassMode.value === 'batch') return n === 1 ? `${label} × 2` : `${label} × ${n + 1}`
return n === 1 ? `${label} + 1 pass` : `${label} + ${n} passes`
}
if (n) {
return imagePassMode.value === 'batch' ? `Queue ${n + 1} from start still` : `Queue ${n + 1} passes`
return v2Mode.value === 'iterate'
? `Queue ${n + 1} iterations`
: imagePassMode.value === 'batch' ? `Queue ${n + 1} from start still` : `Queue ${n + 1} passes`
}
return `Queue ${label.toLowerCase()}`
})
@@ -3646,7 +3696,8 @@ function stillFamilyScript(parts: LibraryStill[]) {
function stillMetaLine(still: LibraryStill) {
const res = still.width && still.height ? `${still.width}×${still.height}` : 'image'
const mode = stillModeLabel(still)
const pass = typeof still.chainIndex === 'number' ? `pass ${still.chainIndex + 1}` : ''
const unit = still.settings?.mode === 'iterate' ? 'iteration' : 'pass'
const pass = typeof still.chainIndex === 'number' ? `${unit} ${still.chainIndex + 1}` : ''
return [res, mode, pass].filter(Boolean).join(' · ')
}
@@ -4618,7 +4669,15 @@ function applyGenerationPreset(preset: GenerationPreset) {
if (preset.kind === 'imagev2') {
const settings = preset.settings as ImageV2PresetSettings
persistImageV2LoraStack(imageV2LoraStack.value, v2Engine.value)
v2Mode.value = settings.mode === 'compose' ? 'compose' : settings.mode === 'refine' ? 'refine' : settings.mode === 'generate' ? 'generate' : 'edit'
v2Mode.value = settings.mode === 'compose'
? 'compose'
: settings.mode === 'refine'
? 'refine'
: settings.mode === 'generate'
? 'generate'
: settings.mode === 'iterate'
? 'iterate'
: 'edit'
if (v2Mode.value !== 'edit' && v2Mode.value !== 'compose') clearEditPasses()
v2Engine.value = parseImageV2Engine(settings.engine, 'flux')
v2Task.value = v2Mode.value === 'compose' ? (settings.task || 'scene') : v2Mode.value === 'refine' ? 'refine' : v2Mode.value === 'generate' ? 't2i' : 'scene'
@@ -5419,7 +5478,7 @@ async function restoreStudioEditJob(payload: {
loraStack?: LoraStackItem[]
negative?: string
imagePipeline?: 'v1' | 'v2'
v2Mode?: 'edit' | 'compose' | 'refine' | 'generate'
v2Mode?: 'edit' | 'compose' | 'refine' | 'generate' | 'iterate'
v2Task?: 'scene' | 'identity' | 'outfit' | 'face_lock' | 'refine' | 't2i'
engine?: 'flux' | 'krea'
snofsModel?: number
@@ -5445,7 +5504,7 @@ async function restoreStudioEditJob(payload: {
if (v2) {
studioMode.value = 'editv2'
outputFocus.value = 'edit'
const mode = payload.v2Mode === 'compose' || payload.v2Mode === 'refine' || payload.v2Mode === 'generate'
const mode = payload.v2Mode === 'compose' || payload.v2Mode === 'refine' || payload.v2Mode === 'generate' || payload.v2Mode === 'iterate'
? payload.v2Mode
: 'edit'
setV2Mode(mode)
@@ -5552,7 +5611,7 @@ async function restoreStudioPayload(kind: string, payload: {
shotLoraStacks?: LoraStackItem[][]
negative?: string
imagePipeline?: 'v1' | 'v2'
v2Mode?: 'edit' | 'compose' | 'refine' | 'generate'
v2Mode?: 'edit' | 'compose' | 'refine' | 'generate' | 'iterate'
v2Task?: 'scene' | 'identity' | 'outfit' | 'face_lock' | 'refine' | 't2i'
engine?: 'flux' | 'krea'
snofsModel?: number
@@ -6332,7 +6391,7 @@ function applyStillSettings(still: LibraryStill) {
if (dest === 'imagev2') {
studioMode.value = 'editv2'
outputFocus.value = 'edit'
const mode = settings?.mode === 'compose' || settings?.mode === 'refine' || settings?.mode === 'generate'
const mode = settings?.mode === 'compose' || settings?.mode === 'refine' || settings?.mode === 'generate' || settings?.mode === 'iterate'
? settings.mode
: 'edit'
setV2Mode(mode)
@@ -6392,6 +6451,7 @@ function stillUseAsInputMessage(still: LibraryStill) {
const dest = inferStillPipeline(still)
const mode = still.settings?.mode
if (dest === 'imagev2' && mode === 'generate') return 'Generate settings and still loaded. Switch to Edit anytime — the image is already in Still A.'
if (dest === 'imagev2' && mode === 'iterate') return 'Iterate settings and still loaded.'
if (dest === 'imagev2' && mode === 'compose') {
return still.settings?.referenceStillId
? 'Compose settings loaded with stills A and B.'
@@ -6976,6 +7036,7 @@ function absorbPastedImageBatch() {
}
function imagePassUnit() {
if (v2Mode.value === 'iterate') return 'Iteration'
return imagePassMode.value === 'batch' ? 'Batch' : 'Pass'
}
@@ -7102,8 +7163,12 @@ function setV2Mode(mode: ImageV2Mode) {
if (mode === 'generate') {
v2Task.value = 't2i'
}
if (mode === 'iterate') {
v2Task.value = 'scene'
imagePassMode.value = 'batch'
}
if (v2Engine.value === 'krea' && mode === 'edit') v2Denoise.value = IMAGE_V2_KREA_EDIT_DENOISE
if (v2Engine.value === 'krea' && mode === 'compose') v2Denoise.value = IMAGE_V2_KREA_COMPOSE_DENOISE
if (v2Engine.value === 'krea' && (mode === 'compose' || mode === 'iterate')) v2Denoise.value = IMAGE_V2_KREA_COMPOSE_DENOISE
}
function setV2Engine(engine: ImageV2Engine) {
@@ -7228,10 +7293,17 @@ async function editImageV2() {
await ensureGenerationNotifyPermission()
const body = new FormData()
body.append('mode', v2Mode.value)
body.append('task', v2Mode.value === 'generate' ? 't2i' : v2Mode.value === 'refine' ? 'refine' : v2Mode.value === 'compose' ? v2Task.value : 'scene')
const iterateGenerate = v2Mode.value === 'iterate' && !file.value
body.append('task', v2Mode.value === 'generate' || iterateGenerate
? 't2i'
: v2Mode.value === 'refine'
? 'refine'
: (v2Mode.value === 'compose' || (v2Mode.value === 'iterate' && editRefFile.value))
? v2Task.value
: 'scene')
if (v2Mode.value !== 'generate' && file.value) body.append('image_a', file.value)
if (v2Mode.value === 'compose' && editRefFile.value) body.append('image_b', editRefFile.value)
if (v2Mode.value === 'refine' || (v2Engine.value === 'krea' && v2Mode.value !== 'generate')) {
if ((v2Mode.value === 'compose' || v2Mode.value === 'iterate') && editRefFile.value) body.append('image_b', editRefFile.value)
if (v2Mode.value === 'refine' || (v2Engine.value === 'krea' && v2Mode.value !== 'generate' && !iterateGenerate)) {
if (v2Mode.value === 'refine') {
const maskBlob = await refinePainter.value?.exportPng()
if (!maskBlob) {
@@ -7242,7 +7314,7 @@ async function editImageV2() {
}
body.append('strength', String(clampImageV2Denoise(v2Denoise.value)))
}
if (v2Mode.value === 'generate') {
if (v2Mode.value === 'generate' || iterateGenerate) {
const size = generateSizeForAspect(aspect.value)
body.append('width', String(size.width))
body.append('height', String(size.height))
@@ -7260,7 +7332,7 @@ async function editImageV2() {
body.append('consistency_clip', String(imageV2EngineLoras().find(item => isImageV2ConsistencyLora(item.name))?.strengthClip ?? 0))
body.append('steps', String(clampImageSteps(v2Steps.value, v2Engine.value === 'krea' ? IMAGE_V2_KREA_STEPS : IMAGE_V2_STEPS_DEFAULT)))
body.append('cfg', String(clampImageCfg(v2Cfg.value, v2Engine.value === 'krea' ? IMAGE_V2_KREA_CFG : IMAGE_V2_CFG_DEFAULT)))
if (v2Mode.value !== 'generate') {
if (v2Mode.value !== 'generate' && !iterateGenerate) {
body.append('scaleToTotalPixels', String(v2ScaleOn.value))
if (v2ScaleOn.value) body.append('megapixels', String(clampImageScaleMegapixels(v2Megapixels.value, 1)))
}
@@ -7270,9 +7342,9 @@ async function editImageV2() {
body.append('hideInput', String(showPrivacyToggles.value && hideInputPreview.value))
body.append('hideThumbnail', String(showPrivacyToggles.value && hideThumbnail.value))
body.append('name', clipName.value.trim())
if (inputStillId.value) body.append('stillId', inputStillId.value)
if (inputStillId.value && file.value) body.append('stillId', inputStillId.value)
if (extraPasses.length) body.append('passes', JSON.stringify(extraPasses))
body.append('passMode', imagePassMode.value)
body.append('passMode', iterateGenerate ? 'batch' : imagePassMode.value)
const v2Stack = filterLoraStackForImageEngine(
filterLoraStackForStudio(imageV2LoraStack.value, ltxEnabled.value),
v2Engine.value
@@ -7301,9 +7373,11 @@ async function editImageV2() {
if (started.queued) {
const n = 1 + extraPasses.length
toast(n > 1
? (imagePassMode.value === 'batch'
? `Queued ${n} Image v2 stills from the start image behind the current job.`
: `Queued ${n} Image v2 passes behind the current job.`)
? (v2Mode.value === 'iterate'
? `Queued ${n} iterations behind the current job.`
: imagePassMode.value === 'batch'
? `Queued ${n} Image v2 stills from the start image behind the current job.`
: `Queued ${n} Image v2 passes behind the current job.`)
: (v2Engine.value === 'krea' ? 'Queued Krea generate behind the current job.' : 'Queued Image v2 behind the current job.'))
await refreshStudioQueue()
return
@@ -7324,7 +7398,15 @@ async function editImageV2() {
editChainLabel.value = extraPasses.length ? `${imagePassUnit()} 1` : ''
editOverallProgress.value = 0
editCompletedChainStep.value = 0
const passNoun = v2Mode.value === 'compose' ? 'Compose' : v2Mode.value === 'refine' ? 'Refine' : v2Mode.value === 'generate' ? 'Generate' : 'Edit'
const passNoun = v2Mode.value === 'iterate'
? 'Iteration'
: v2Mode.value === 'compose'
? 'Compose'
: v2Mode.value === 'refine'
? 'Refine'
: v2Mode.value === 'generate'
? 'Generate'
: 'Edit'
editActiveChainPlan.value = imagePassPlan(prompt.value.trim(), extraPasses, passNoun)
startTimer('edit')
editDownloadName.value = downloadName