feat(lora): support relative paths in <lora:folder/name:strength> syntax (#917)

Autocomplete, copy/send-to-workflow, and recipe syntax now emit
<lora:folder/name:strength> instead of <lora:name:strength>, using
relative paths to disambiguate identically-named loras in different
subfolders without requiring file renames.

Backend: 3-tier hybrid resolution (path → bare → basename fallback)
across get_lora_info, get_lora_info_absolute, get_model_preview_url,
get_model_civitai_url, get_model_info_by_name, get_lora_metadata_by_filename,
and get_hash_by_filename. Also fix get_random_loras and get_cycler_list
to return path-prefixed names for randomizer/cycler consistency.

Frontend: autocomplete, copyLoraSyntax, handleSendToWorkflow emit
folder-prefixed syntax. extract_lora_name preserves relative paths.

Saved image metadata (<lora:...> in EXIF) intentionally keeps basename-only
for compatibility with A1111/Forge ecosystem.
This commit is contained in:
Will Miao
2026-05-20 19:39:12 +08:00
parent 33e5f3d85d
commit 9ce56dd40c
13 changed files with 404 additions and 48 deletions

View File

@@ -430,7 +430,9 @@ export function buildLoraSyntax(fileName, usageTips = {}) {
export function copyLoraSyntax(card) {
const usageTips = JSON.parse(card.dataset.usage_tips || "{}");
const baseSyntax = buildLoraSyntax(card.dataset.file_name, usageTips);
const folder = card.dataset.folder || '';
const loraName = folder ? `${folder}/${card.dataset.file_name}` : card.dataset.file_name;
const baseSyntax = buildLoraSyntax(loraName, usageTips);
// Check if trigger words should be included
const includeTriggerWords = state.global.settings.include_trigger_words;