refactor: move No LoRA feature from LoRA Pool to Lora Cycler widget

Move the 'empty/no LoRA' cycling functionality from the LoRA Pool node
to the Lora Cycler widget for cleaner architecture:

Frontend changes:
- Add include_no_lora field to CyclerConfig interface
- Add includeNoLora state and logic to useLoraCyclerState composable
- Add toggle UI in LoraCyclerSettingsView with special styling
- Show 'No LoRA' entry in LoraListModal when enabled
- Update LoraCyclerWidget to integrate new logic

Backend changes:
- lora_cycler.py reads include_no_lora from config
- Calculate effective_total_count (actual count + 1 when enabled)
- Return empty lora_stack when on No LoRA position
- Return actual LoRA count in total_count (not effective count)

Reverted files to pre-PR state:
- lora_loader.py, lora_pool.py, lora_randomizer.py, lora_stacker.py
- lora_routes.py, lora_service.py
- LoraPoolWidget.vue and related files

Related to PR #861

Co-authored-by: dogatech <dogatech@dogatech.home>
This commit is contained in:
Will Miao
2026-03-19 14:19:49 +08:00
parent 8dd849892d
commit 1ae1b0d607
22 changed files with 459 additions and 316 deletions

View File

@@ -27,10 +27,8 @@
<LicenseSection
:no-credit-required="noCreditRequired"
:allow-selling="allowSelling"
:include-empty-lora="includeEmptyLora"
@update:no-credit-required="$emit('update:noCreditRequired', $event)"
@update:allow-selling="$emit('update:allowSelling', $event)"
@update:include-empty-lora="$emit('update:includeEmptyLora', $event)"
/>
</div>
@@ -63,10 +61,9 @@ defineProps<{
// Folders
includeFolders: string[]
excludeFolders: string[]
// License & Misc
// License
noCreditRequired: boolean
allowSelling: boolean
includeEmptyLora: boolean
// Preview
previewItems: LoraItem[]
matchCount: number
@@ -79,7 +76,6 @@ defineEmits<{
'update:excludeFolders': [value: string[]]
'update:noCreditRequired': [value: boolean]
'update:allowSelling': [value: boolean]
'update:includeEmptyLora': [value: boolean]
refresh: []
}>()
</script>

View File

@@ -1,7 +1,7 @@
<template>
<div class="section">
<div class="section__header">
<span class="section__title">LICENSE & OPTIONS</span>
<span class="section__title">LICENSE</span>
</div>
<div class="section__toggles">
<label class="toggle-item">
@@ -33,22 +33,6 @@
<span class="toggle-switch__thumb"></span>
</button>
</label>
<label class="toggle-item">
<span class="toggle-item__label">Include No LoRAs</span>
<button
type="button"
class="toggle-switch"
:class="{ 'toggle-switch--active': includeEmptyLora }"
@click="$emit('update:includeEmptyLora', !includeEmptyLora)"
role="switch"
:aria-checked="includeEmptyLora"
title="Include an empty/blank LoRA option in the pool results"
>
<span class="toggle-switch__track"></span>
<span class="toggle-switch__thumb"></span>
</button>
</label>
</div>
</div>
</template>
@@ -57,13 +41,11 @@
defineProps<{
noCreditRequired: boolean
allowSelling: boolean
includeEmptyLora: boolean
}>()
defineEmits<{
'update:noCreditRequired': [value: boolean]
'update:allowSelling': [value: boolean]
'update:includeEmptyLora': [value: boolean]
}>()
</script>
@@ -87,7 +69,6 @@ defineEmits<{
.section__toggles {
display: flex;
flex-wrap: wrap;
gap: 16px;
}