fix(recipes): distinguish unobtainable LoRAs in recipe status and skip them in syntax

The recipe card pill counted LoRAs deleted from the source (isDeleted) as
available, showing a green 'ready 2/2' for recipes that cannot be fully
reproduced. LoRAs with an unresolvable hash (hashInvalid) were counted as
missing/downloadable even though downloads always fail, and recipe syntax
generation emitted broken tokens for them.

- Four-state status on RecipeCard pill and RecipeTab badge: ready (all in
  library), missing (downloadable, red, keeps the action cue), partial
  (unobtainable entries skipped when used, amber, fa-circle-minus),
  unavailable (nothing usable, gray, fa-ban)
- Pill numerator is now the real in-library count; tooltips spell out
  missing vs unavailable (deleted from source or unresolvable hash)
- get_recipe_syntax_tokens skips hashInvalid entries like deleted ones
  instead of emitting tokens pointing at nonexistent files
- Bulk missing-download manager and recipe context menu exclude
  hashInvalid LoRAs, matching the modal's per-item download block
- New locale keys loraStatus.missingAndUnavailable/partial/noneUsable,
  translated for all 9 non-en locales
This commit is contained in:
Will Miao
2026-08-29 16:41:48 +08:00
parent ebe3df7d22
commit c972c755fc
19 changed files with 258 additions and 40 deletions
@@ -30,8 +30,9 @@ export class BulkMissingLoraDownloadManager {
if (recipe.loras && Array.isArray(recipe.loras)) {
recipe.loras.forEach(lora => {
// Only include LoRAs not in library and not deleted
if (!lora.inLibrary && !lora.isDeleted) {
// Only include LoRAs not in library and still downloadable
// (not deleted from the source, hash still resolvable)
if (!lora.inLibrary && !lora.isDeleted && !lora.hashInvalid) {
const uniqueKey = lora.hash || lora.id || lora.modelVersionId;
if (uniqueKey && !uniqueLoras.has(uniqueKey)) {