Only list LoRAs tagged for the selected image engine in the dropdown.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-09-02 21:49:21 -05:00
co-authored by Cursor
parent 46629ca51b
commit eccf8c0081
3 changed files with 33 additions and 6 deletions
+6 -1
View File
@@ -105,6 +105,7 @@ import {
clampLoraStrength, clampLoraStrength,
loraFriendlyName, loraFriendlyName,
loraIdentityKey, loraIdentityKey,
loraMatchesImageEngine,
loraTriggerFor, loraTriggerFor,
makeLoraStackItem, makeLoraStackItem,
type LoraStackItem type LoraStackItem
@@ -121,6 +122,7 @@ const props = withDefaults(defineProps<{
clipStrength?: boolean clipStrength?: boolean
triggers?: Record<string, string> triggers?: Record<string, string>
aliases?: Record<string, string> aliases?: Record<string, string>
engine?: 'flux' | 'krea' | ''
}>(), { }>(), {
label: 'LoRA', label: 'LoRA',
emptyLabel: 'None', emptyLabel: 'None',
@@ -130,7 +132,8 @@ const props = withDefaults(defineProps<{
disabled: false, disabled: false,
clipStrength: true, clipStrength: true,
triggers: () => ({}), triggers: () => ({}),
aliases: () => ({}) aliases: () => ({}),
engine: ''
}) })
const emit = defineEmits<{ const emit = defineEmits<{
@@ -145,8 +148,10 @@ const dragOverIndex = ref<number | null>(null)
const availableNames = computed(() => { const availableNames = computed(() => {
const taken = new Set(model.value.map(item => loraIdentityKey(item.name))) const taken = new Set(model.value.map(item => loraIdentityKey(item.name)))
const engine = props.engine === 'flux' || props.engine === 'krea' ? props.engine : null
return props.names return props.names
.filter(name => !taken.has(loraIdentityKey(name))) .filter(name => !taken.has(loraIdentityKey(name)))
.filter(name => !engine || loraMatchesImageEngine(name, engine))
.slice() .slice()
.sort((a, b) => labelFor(a).localeCompare(labelFor(b), undefined, { sensitivity: 'base' })) .sort((a, b) => labelFor(a).localeCompare(labelFor(b), undefined, { sensitivity: 'base' }))
}) })
+2
View File
@@ -828,6 +828,7 @@
<LoraSelect <LoraSelect
v-model="imageV2LoraStack" v-model="imageV2LoraStack"
:names="imageV2LoraOptions" :names="imageV2LoraOptions"
:engine="v2Engine"
:triggers="loraTriggers" :triggers="loraTriggers"
:aliases="loraAliases" :aliases="loraAliases"
label="LoRA" label="LoRA"
@@ -958,6 +959,7 @@
<LoraSelect <LoraSelect
v-model="imageLoraStack" v-model="imageLoraStack"
:names="imageLoraOptions" :names="imageLoraOptions"
engine="flux"
:triggers="loraTriggers" :triggers="loraTriggers"
:aliases="loraAliases" :aliases="loraAliases"
label="LoRA" label="LoRA"
+25 -5
View File
@@ -229,20 +229,39 @@ export function isKleinImageLora(name: string) {
return /flux-?2-klein|klein_snofs|flux2-klein-9b-consistency|(^|[^a-z0-9])klein([^a-z0-9]|$)/i.test(id) return /flux-?2-klein|klein_snofs|flux2-klein-9b-consistency|(^|[^a-z0-9])klein([^a-z0-9]|$)/i.test(id)
} }
function hasImageEngineToken(source: string, engine: 'flux' | 'krea') {
const value = String(source || '').replace(/\\/g, '/').toLowerCase()
if (!value) return false
const token = engine === 'krea' ? 'krea' : 'flux'
return new RegExp(`(?:^|[/_.-])${token}`).test(value)
}
/** /**
* Image engine from the filename: `xaigen-flux-…` / `flux-…` vs `xaigen-krea-…` / `krea-…`. * Image engine from the filename: `xaigen-flux-…` / `flux-…` vs `xaigen-krea-…` / `krea-…`.
* Klein / SNOFS files without that prefix still count as Flux or Krea. * Klein / SNOFS files without that prefix still count as Flux or Krea.
*/ */
export function imageLoraEngineOf(name: string): 'flux' | 'krea' | null { export function imageLoraEngineOf(name: string): 'flux' | 'krea' | null {
const id = loraIdentityKey(name) const raw = String(name || '')
if (/snofs_krea|(^|[_-])krea([_-]|$)/i.test(id) || /^krea\d*[-_.]/i.test(id)) return 'krea' const base = loraBasename(raw)
if (isKleinImageLora(name) || /flux-?2-klein|flux2-klein/i.test(id) || /^flux\d*[-_.]/i.test(id)) return 'flux' const id = loraIdentityKey(raw)
if (
hasImageEngineToken(raw, 'krea')
|| hasImageEngineToken(base, 'krea')
|| hasImageEngineToken(id, 'krea')
|| /snofs_krea/i.test(id)
) return 'krea'
if (
hasImageEngineToken(raw, 'flux')
|| hasImageEngineToken(base, 'flux')
|| hasImageEngineToken(id, 'flux')
|| isKleinImageLora(raw)
|| /flux-?2-klein|flux2-klein/i.test(id)
) return 'flux'
return null return null
} }
export function loraMatchesImageEngine(name: string, engine: 'flux' | 'krea') { export function loraMatchesImageEngine(name: string, engine: 'flux' | 'krea') {
const tagged = imageLoraEngineOf(name) return imageLoraEngineOf(name) === engine
return !tagged || tagged === engine
} }
export function filterLorasForImageEngine(names: string[], engine: 'flux' | 'krea') { export function filterLorasForImageEngine(names: string[], engine: 'flux' | 'krea') {
@@ -285,6 +304,7 @@ export function inferLoraUse(name: string): LoraUse[] | null {
export function loraMatchesUse(name: string, use: LoraUse) { export function loraMatchesUse(name: string, use: LoraUse) {
if (isSystemGraphLora(name)) return false if (isSystemGraphLora(name)) return false
if (use === 'flux' || use === 'krea') return imageLoraEngineOf(name) === use
const inferred = inferLoraUse(name) const inferred = inferLoraUse(name)
if (!inferred) return true if (!inferred) return true
return inferred.includes(use) return inferred.includes(use)