feat(recipes): add reconnect remediation paths for missing recipe LoRAs

- Snapshot pre-rematch entry state (reconnectSnapshot) so rematched
  entries can be undone via the existing restore flow
- Bulk missing-LoRA downloads mark unresolvable failures hash-invalid,
  flipping those entries from download to reconnect candidacy
- Recipe modal always offers a reconnect action next to download for
  missing LoRA entries
- Rematch runs collect an opt-in relaxed-matching choice (also reconnect
  missing models by file name) via a pre-run options dialog on the
  global, bulk and single-recipe entries
- L4 (filename-level) matches are listed in a results dialog with
  per-entry undo
This commit is contained in:
Will Miao
2026-09-09 06:59:54 +08:00
parent e747946f7a
commit 1b5cbbbaa0
33 changed files with 2103 additions and 76 deletions
+17
View File
@@ -1501,6 +1501,22 @@
"note": "Dateien werden mit Standard-Pfad-Vorlagen heruntergeladen. Dies kann je nach Anzahl der LoRAs eine Weile dauern.",
"downloadButton": "{count} LoRA(s) herunterladen"
},
"rematchOptions": {
"title": "[TODO: Translate] Rematch Recipes",
"messageGlobal": "[TODO: Translate] All recipes will be scanned against your local model library.",
"messageSingle": "[TODO: Translate] This recipe will be scanned against your local model library.",
"messageBulk": "[TODO: Translate] {count} selected recipe(s) will be scanned against your local model library.",
"relaxedLabel": "[TODO: Translate] Relaxed matching",
"relaxedDescription": "[TODO: Translate] Also try to reconnect models marked \"Not in Library\" by matching file names. May link a different version of a model — matches will be listed for review and can be undone.",
"confirmButton": "[TODO: Translate] Rematch"
},
"rematchResults": {
"title": "[TODO: Translate] Rematch Results — Filename Matches",
"message": "[TODO: Translate] These entries were reconnected by file name and may link a different version of a model. Review them and undo any that are wrong.",
"undo": "[TODO: Translate] Undo",
"undone": "[TODO: Translate] Undone",
"undoFailed": "[TODO: Translate] Failed to undo rematch: {message}"
},
"exampleAccess": {
"title": "Lokale Beispielbilder",
"message": "Keine lokalen Beispielbilder für dieses Modell gefunden. Ansichtsoptionen:",
@@ -2168,6 +2184,7 @@
"createMissingData": "Erforderliche Daten zum Erstellen des Rezepts fehlen",
"created": "Rezept erfolgreich erstellt",
"noMissingLoras": "Keine fehlenden LoRAs zum Herunterladen",
"unresolvableMarkedForReconnect": "[TODO: Translate] {count} unresolvable entr(ies) marked — they can now be reconnected to a local LoRA.",
"noPreviousRecipe": "Kein vorheriges Rezept verfügbar",
"noNextRecipe": "Kein weiteres Rezept verfügbar",
"missingLorasInfoFailed": "Fehler beim Abrufen der Informationen für fehlende LoRAs",
+17
View File
@@ -1501,6 +1501,22 @@
"note": "Files will be downloaded using default path templates. This may take a while depending on the number of LoRAs.",
"downloadButton": "Download {count} LoRA(s)"
},
"rematchOptions": {
"title": "Rematch Recipes",
"messageGlobal": "All recipes will be scanned against your local model library.",
"messageSingle": "This recipe will be scanned against your local model library.",
"messageBulk": "{count} selected recipe(s) will be scanned against your local model library.",
"relaxedLabel": "Also reconnect missing models by file name",
"relaxedDescription": "These models could also be fixed by downloading — download is more accurate. Matches may link a different version; they'll be listed for review and can be undone.",
"confirmButton": "Rematch"
},
"rematchResults": {
"title": "Rematch Results — Filename Matches",
"message": "These entries were reconnected by file name and may link a different version of a model. Review them and undo any that are wrong.",
"undo": "Undo",
"undone": "Undone",
"undoFailed": "Failed to undo rematch: {message}"
},
"exampleAccess": {
"title": "Local Example Images",
"message": "No local example images found for this model. View options:",
@@ -2168,6 +2184,7 @@
"createMissingData": "Missing required data to create recipe",
"created": "Recipe created successfully",
"noMissingLoras": "No missing LoRAs to download",
"unresolvableMarkedForReconnect": "{count} unresolvable entr(ies) marked — they can now be reconnected to a local LoRA.",
"noPreviousRecipe": "No previous recipe available",
"noNextRecipe": "No next recipe available",
"missingLorasInfoFailed": "Failed to get information for missing LoRAs",
+17
View File
@@ -1501,6 +1501,22 @@
"note": "Los archivos se descargarán usando las plantillas de ruta predeterminadas. Esto puede tomar un tiempo dependiendo del número de LoRAs.",
"downloadButton": "Descargar {count} LoRA(s)"
},
"rematchOptions": {
"title": "[TODO: Translate] Rematch Recipes",
"messageGlobal": "[TODO: Translate] All recipes will be scanned against your local model library.",
"messageSingle": "[TODO: Translate] This recipe will be scanned against your local model library.",
"messageBulk": "[TODO: Translate] {count} selected recipe(s) will be scanned against your local model library.",
"relaxedLabel": "[TODO: Translate] Relaxed matching",
"relaxedDescription": "[TODO: Translate] Also try to reconnect models marked \"Not in Library\" by matching file names. May link a different version of a model — matches will be listed for review and can be undone.",
"confirmButton": "[TODO: Translate] Rematch"
},
"rematchResults": {
"title": "[TODO: Translate] Rematch Results — Filename Matches",
"message": "[TODO: Translate] These entries were reconnected by file name and may link a different version of a model. Review them and undo any that are wrong.",
"undo": "[TODO: Translate] Undo",
"undone": "[TODO: Translate] Undone",
"undoFailed": "[TODO: Translate] Failed to undo rematch: {message}"
},
"exampleAccess": {
"title": "Imágenes de ejemplo locales",
"message": "No se encontraron imágenes de ejemplo locales para este modelo. Opciones de visualización:",
@@ -2168,6 +2184,7 @@
"createMissingData": "Faltan datos necesarios para crear la receta",
"created": "Receta creada exitosamente",
"noMissingLoras": "No hay LoRAs faltantes para descargar",
"unresolvableMarkedForReconnect": "[TODO: Translate] {count} unresolvable entr(ies) marked — they can now be reconnected to a local LoRA.",
"noPreviousRecipe": "No hay receta anterior disponible",
"noNextRecipe": "No hay siguiente receta disponible",
"missingLorasInfoFailed": "Error al obtener información de LoRAs faltantes",
+17
View File
@@ -1501,6 +1501,22 @@
"note": "Les fichiers seront téléchargés en utilisant les modèles de chemins par défaut. Cela peut prendre un certain temps selon le nombre de LoRAs.",
"downloadButton": "Télécharger {count} LoRA(s)"
},
"rematchOptions": {
"title": "[TODO: Translate] Rematch Recipes",
"messageGlobal": "[TODO: Translate] All recipes will be scanned against your local model library.",
"messageSingle": "[TODO: Translate] This recipe will be scanned against your local model library.",
"messageBulk": "[TODO: Translate] {count} selected recipe(s) will be scanned against your local model library.",
"relaxedLabel": "[TODO: Translate] Relaxed matching",
"relaxedDescription": "[TODO: Translate] Also try to reconnect models marked \"Not in Library\" by matching file names. May link a different version of a model — matches will be listed for review and can be undone.",
"confirmButton": "[TODO: Translate] Rematch"
},
"rematchResults": {
"title": "[TODO: Translate] Rematch Results — Filename Matches",
"message": "[TODO: Translate] These entries were reconnected by file name and may link a different version of a model. Review them and undo any that are wrong.",
"undo": "[TODO: Translate] Undo",
"undone": "[TODO: Translate] Undone",
"undoFailed": "[TODO: Translate] Failed to undo rematch: {message}"
},
"exampleAccess": {
"title": "Images d'exemple locales",
"message": "Aucune image d'exemple locale trouvée pour ce modèle. Options d'affichage :",
@@ -2168,6 +2184,7 @@
"createMissingData": "Données requises manquantes pour créer le Recipe",
"created": "Recipe créé avec succès",
"noMissingLoras": "Aucun LoRA manquant à télécharger",
"unresolvableMarkedForReconnect": "[TODO: Translate] {count} unresolvable entr(ies) marked — they can now be reconnected to a local LoRA.",
"noPreviousRecipe": "Aucune Recipe précédente",
"noNextRecipe": "Aucune Recipe suivante",
"missingLorasInfoFailed": "Échec de l'obtention des informations pour les LoRAs manquants",
+17
View File
@@ -1501,6 +1501,22 @@
"note": "הקבצים יורדו באמצעות תבניות נתיב ברירת מחדל. זה עשוי לקחת זמן בהתאם למספר ה-LoRAs.",
"downloadButton": "הורד {count} LoRA(s)"
},
"rematchOptions": {
"title": "[TODO: Translate] Rematch Recipes",
"messageGlobal": "[TODO: Translate] All recipes will be scanned against your local model library.",
"messageSingle": "[TODO: Translate] This recipe will be scanned against your local model library.",
"messageBulk": "[TODO: Translate] {count} selected recipe(s) will be scanned against your local model library.",
"relaxedLabel": "[TODO: Translate] Relaxed matching",
"relaxedDescription": "[TODO: Translate] Also try to reconnect models marked \"Not in Library\" by matching file names. May link a different version of a model — matches will be listed for review and can be undone.",
"confirmButton": "[TODO: Translate] Rematch"
},
"rematchResults": {
"title": "[TODO: Translate] Rematch Results — Filename Matches",
"message": "[TODO: Translate] These entries were reconnected by file name and may link a different version of a model. Review them and undo any that are wrong.",
"undo": "[TODO: Translate] Undo",
"undone": "[TODO: Translate] Undone",
"undoFailed": "[TODO: Translate] Failed to undo rematch: {message}"
},
"exampleAccess": {
"title": "תמונות דוגמה מקומיות",
"message": "לא נמצאו תמונות דוגמה מקומיות למודל זה. אפשרויות צפייה:",
@@ -2168,6 +2184,7 @@
"createMissingData": "חסרים נתונים נדרשים ליצירת המתכון",
"created": "המתכון נוצר בהצלחה",
"noMissingLoras": "אין LoRAs חסרים להורדה",
"unresolvableMarkedForReconnect": "[TODO: Translate] {count} unresolvable entr(ies) marked — they can now be reconnected to a local LoRA.",
"noPreviousRecipe": "אין מתכון קודם זמין",
"noNextRecipe": "אין מתכון נוסף זמין",
"missingLorasInfoFailed": "קבלת מידע עבור LoRAs חסרים נכשלה",
+17
View File
@@ -1501,6 +1501,22 @@
"note": "ファイルはデフォルトのパステンプレートを使用してダウンロードされます。LoRA の数によっては時間がかかる場合があります。",
"downloadButton": "{count} 個の LoRA をダウンロード"
},
"rematchOptions": {
"title": "[TODO: Translate] Rematch Recipes",
"messageGlobal": "[TODO: Translate] All recipes will be scanned against your local model library.",
"messageSingle": "[TODO: Translate] This recipe will be scanned against your local model library.",
"messageBulk": "[TODO: Translate] {count} selected recipe(s) will be scanned against your local model library.",
"relaxedLabel": "[TODO: Translate] Relaxed matching",
"relaxedDescription": "[TODO: Translate] Also try to reconnect models marked \"Not in Library\" by matching file names. May link a different version of a model — matches will be listed for review and can be undone.",
"confirmButton": "[TODO: Translate] Rematch"
},
"rematchResults": {
"title": "[TODO: Translate] Rematch Results — Filename Matches",
"message": "[TODO: Translate] These entries were reconnected by file name and may link a different version of a model. Review them and undo any that are wrong.",
"undo": "[TODO: Translate] Undo",
"undone": "[TODO: Translate] Undone",
"undoFailed": "[TODO: Translate] Failed to undo rematch: {message}"
},
"exampleAccess": {
"title": "ローカル例画像",
"message": "このモデルのローカル例画像が見つかりませんでした。表示オプション:",
@@ -2168,6 +2184,7 @@
"createMissingData": "レシピ作成に必要なデータが不足しています",
"created": "レシピを作成しました",
"noMissingLoras": "ダウンロードする不足LoRAがありません",
"unresolvableMarkedForReconnect": "[TODO: Translate] {count} unresolvable entr(ies) marked — they can now be reconnected to a local LoRA.",
"noPreviousRecipe": "前のレシピがありません",
"noNextRecipe": "次のレシピがありません",
"missingLorasInfoFailed": "不足LoRAの情報取得に失敗しました",
+17
View File
@@ -1501,6 +1501,22 @@
"note": "파일은 기본 경로 템플릿을 사용하여 다운로드됩니다. LoRA의 수에 따라 다소 시간이 걸릴 수 있습니다.",
"downloadButton": "{count}개 LoRA 다운로드"
},
"rematchOptions": {
"title": "[TODO: Translate] Rematch Recipes",
"messageGlobal": "[TODO: Translate] All recipes will be scanned against your local model library.",
"messageSingle": "[TODO: Translate] This recipe will be scanned against your local model library.",
"messageBulk": "[TODO: Translate] {count} selected recipe(s) will be scanned against your local model library.",
"relaxedLabel": "[TODO: Translate] Relaxed matching",
"relaxedDescription": "[TODO: Translate] Also try to reconnect models marked \"Not in Library\" by matching file names. May link a different version of a model — matches will be listed for review and can be undone.",
"confirmButton": "[TODO: Translate] Rematch"
},
"rematchResults": {
"title": "[TODO: Translate] Rematch Results — Filename Matches",
"message": "[TODO: Translate] These entries were reconnected by file name and may link a different version of a model. Review them and undo any that are wrong.",
"undo": "[TODO: Translate] Undo",
"undone": "[TODO: Translate] Undone",
"undoFailed": "[TODO: Translate] Failed to undo rematch: {message}"
},
"exampleAccess": {
"title": "로컬 예시 이미지",
"message": "이 모델의 로컬 예시 이미지를 찾을 수 없습니다. 보기 옵션:",
@@ -2168,6 +2184,7 @@
"createMissingData": "레시피 생성에 필요한 데이터가 없습니다",
"created": "레시피가 생성되었습니다",
"noMissingLoras": "다운로드할 누락된 LoRA가 없습니다",
"unresolvableMarkedForReconnect": "[TODO: Translate] {count} unresolvable entr(ies) marked — they can now be reconnected to a local LoRA.",
"noPreviousRecipe": "이전 레시피가 없습니다",
"noNextRecipe": "다음 레시피가 없습니다",
"missingLorasInfoFailed": "누락된 LoRA 정보를 가져오는데 실패했습니다",
+17
View File
@@ -1501,6 +1501,22 @@
"note": "Файлы будут скачаны с использованием шаблонов путей по умолчанию. Это может занять некоторое время в зависимости от количества LoRAs.",
"downloadButton": "Скачать {count} LoRA(s)"
},
"rematchOptions": {
"title": "[TODO: Translate] Rematch Recipes",
"messageGlobal": "[TODO: Translate] All recipes will be scanned against your local model library.",
"messageSingle": "[TODO: Translate] This recipe will be scanned against your local model library.",
"messageBulk": "[TODO: Translate] {count} selected recipe(s) will be scanned against your local model library.",
"relaxedLabel": "[TODO: Translate] Relaxed matching",
"relaxedDescription": "[TODO: Translate] Also try to reconnect models marked \"Not in Library\" by matching file names. May link a different version of a model — matches will be listed for review and can be undone.",
"confirmButton": "[TODO: Translate] Rematch"
},
"rematchResults": {
"title": "[TODO: Translate] Rematch Results — Filename Matches",
"message": "[TODO: Translate] These entries were reconnected by file name and may link a different version of a model. Review them and undo any that are wrong.",
"undo": "[TODO: Translate] Undo",
"undone": "[TODO: Translate] Undone",
"undoFailed": "[TODO: Translate] Failed to undo rematch: {message}"
},
"exampleAccess": {
"title": "Локальные примеры изображений",
"message": "Локальные примеры изображений для этой модели не найдены. Варианты просмотра:",
@@ -2168,6 +2184,7 @@
"createMissingData": "Отсутствуют необходимые данные для создания рецепта",
"created": "Рецепт успешно создан",
"noMissingLoras": "Нет отсутствующих LoRAs для загрузки",
"unresolvableMarkedForReconnect": "[TODO: Translate] {count} unresolvable entr(ies) marked — they can now be reconnected to a local LoRA.",
"noPreviousRecipe": "Предыдущий рецепт отсутствует",
"noNextRecipe": "Следующий рецепт отсутствует",
"missingLorasInfoFailed": "Не удалось получить информацию для отсутствующих LoRAs",
+17
View File
@@ -1501,6 +1501,22 @@
"note": "文件将使用默认路径模板下载。根据 LoRAs 的数量,这可能需要一些时间。",
"downloadButton": "下载 {count} 个 LoRA(s)"
},
"rematchOptions": {
"title": "[TODO: Translate] Rematch Recipes",
"messageGlobal": "[TODO: Translate] All recipes will be scanned against your local model library.",
"messageSingle": "[TODO: Translate] This recipe will be scanned against your local model library.",
"messageBulk": "[TODO: Translate] {count} selected recipe(s) will be scanned against your local model library.",
"relaxedLabel": "[TODO: Translate] Relaxed matching",
"relaxedDescription": "[TODO: Translate] Also try to reconnect models marked \"Not in Library\" by matching file names. May link a different version of a model — matches will be listed for review and can be undone.",
"confirmButton": "[TODO: Translate] Rematch"
},
"rematchResults": {
"title": "[TODO: Translate] Rematch Results — Filename Matches",
"message": "[TODO: Translate] These entries were reconnected by file name and may link a different version of a model. Review them and undo any that are wrong.",
"undo": "[TODO: Translate] Undo",
"undone": "[TODO: Translate] Undone",
"undoFailed": "[TODO: Translate] Failed to undo rematch: {message}"
},
"exampleAccess": {
"title": "本地示例图片",
"message": "未找到此模型的本地示例图片。可选操作:",
@@ -2168,6 +2184,7 @@
"createMissingData": "缺少创建配方所需的数据",
"created": "配方创建成功",
"noMissingLoras": "没有缺失的 LoRA 可下载",
"unresolvableMarkedForReconnect": "[TODO: Translate] {count} unresolvable entr(ies) marked — they can now be reconnected to a local LoRA.",
"noPreviousRecipe": "没有上一个配方",
"noNextRecipe": "没有下一个配方",
"missingLorasInfoFailed": "获取缺失 LoRA 信息失败",
+17
View File
@@ -1501,6 +1501,22 @@
"note": "檔案將使用預設路徑模板下載。根據 LoRAs 的數量,這可能需要一些時間。",
"downloadButton": "下載 {count} 個 LoRA(s)"
},
"rematchOptions": {
"title": "[TODO: Translate] Rematch Recipes",
"messageGlobal": "[TODO: Translate] All recipes will be scanned against your local model library.",
"messageSingle": "[TODO: Translate] This recipe will be scanned against your local model library.",
"messageBulk": "[TODO: Translate] {count} selected recipe(s) will be scanned against your local model library.",
"relaxedLabel": "[TODO: Translate] Relaxed matching",
"relaxedDescription": "[TODO: Translate] Also try to reconnect models marked \"Not in Library\" by matching file names. May link a different version of a model — matches will be listed for review and can be undone.",
"confirmButton": "[TODO: Translate] Rematch"
},
"rematchResults": {
"title": "[TODO: Translate] Rematch Results — Filename Matches",
"message": "[TODO: Translate] These entries were reconnected by file name and may link a different version of a model. Review them and undo any that are wrong.",
"undo": "[TODO: Translate] Undo",
"undone": "[TODO: Translate] Undone",
"undoFailed": "[TODO: Translate] Failed to undo rematch: {message}"
},
"exampleAccess": {
"title": "本機範例圖片",
"message": "此模型未找到本機範例圖片。可選擇:",
@@ -2168,6 +2184,7 @@
"createMissingData": "缺少建立配方所需的資料",
"created": "配方建立成功",
"noMissingLoras": "無缺少的 LoRA 可下載",
"unresolvableMarkedForReconnect": "[TODO: Translate] {count} unresolvable entr(ies) marked — they can now be reconnected to a local LoRA.",
"noPreviousRecipe": "沒有上一個配方",
"noNextRecipe": "沒有下一個配方",
"missingLorasInfoFailed": "取得缺少 LoRA 資訊失敗",