feat(ui): gray out enrich-hf-llm when no hf_url, add backend fast-fail, rename labels across locales, reposition menu item

This commit is contained in:
Will Miao
2026-07-06 00:34:18 +08:00
parent d0e8938039
commit 308d8f71b8
15 changed files with 95 additions and 66 deletions

View File

@@ -781,7 +781,7 @@
"complete": "Automatische Organisation abgeschlossen", "complete": "Automatische Organisation abgeschlossen",
"error": "Fehler: {error}" "error": "Fehler: {error}"
}, },
"enrichHfAgent": "Metadaten mit KI anreichern" "enrichHfAgent": "HF-Metadaten mit KI anreichern"
}, },
"contextMenu": { "contextMenu": {
"refreshMetadata": "Civitai-Daten aktualisieren", "refreshMetadata": "Civitai-Daten aktualisieren",
@@ -806,7 +806,7 @@
"viewAllLoras": "Alle LoRAs anzeigen", "viewAllLoras": "Alle LoRAs anzeigen",
"downloadMissingLoras": "Fehlende LoRAs herunterladen", "downloadMissingLoras": "Fehlende LoRAs herunterladen",
"deleteRecipe": "Rezept löschen", "deleteRecipe": "Rezept löschen",
"enrichHfAgent": "Metadaten mit KI anreichern" "enrichHfAgent": "HF-Metadaten mit KI anreichern"
} }
}, },
"recipes": { "recipes": {

View File

@@ -781,7 +781,7 @@
"complete": "Auto-organize complete", "complete": "Auto-organize complete",
"error": "Error: {error}" "error": "Error: {error}"
}, },
"enrichHfAgent": "Enrich Metadata (AI)" "enrichHfAgent": "Enrich HF Metadata (AI)"
}, },
"contextMenu": { "contextMenu": {
"refreshMetadata": "Refresh Civitai Data", "refreshMetadata": "Refresh Civitai Data",
@@ -806,7 +806,7 @@
"viewAllLoras": "View All LoRAs", "viewAllLoras": "View All LoRAs",
"downloadMissingLoras": "Download Missing LoRAs", "downloadMissingLoras": "Download Missing LoRAs",
"deleteRecipe": "Delete Recipe", "deleteRecipe": "Delete Recipe",
"enrichHfAgent": "Enrich Metadata (AI)" "enrichHfAgent": "Enrich HF Metadata (AI)"
} }
}, },
"recipes": { "recipes": {

View File

@@ -781,7 +781,7 @@
"complete": "Auto-organización completada", "complete": "Auto-organización completada",
"error": "Error: {error}" "error": "Error: {error}"
}, },
"enrichHfAgent": "Enriquecer metadatos (IA)" "enrichHfAgent": "Enriquecer metadatos HF (IA)"
}, },
"contextMenu": { "contextMenu": {
"refreshMetadata": "Actualizar datos de Civitai", "refreshMetadata": "Actualizar datos de Civitai",
@@ -806,7 +806,7 @@
"viewAllLoras": "Ver todos los LoRAs", "viewAllLoras": "Ver todos los LoRAs",
"downloadMissingLoras": "Descargar LoRAs faltantes", "downloadMissingLoras": "Descargar LoRAs faltantes",
"deleteRecipe": "Eliminar receta", "deleteRecipe": "Eliminar receta",
"enrichHfAgent": "Enriquecer metadatos (IA)" "enrichHfAgent": "Enriquecer metadatos HF (IA)"
} }
}, },
"recipes": { "recipes": {

View File

@@ -781,7 +781,7 @@
"complete": "Auto-organisation terminée", "complete": "Auto-organisation terminée",
"error": "Erreur : {error}" "error": "Erreur : {error}"
}, },
"enrichHfAgent": "Enrichir les métadonnées (IA)" "enrichHfAgent": "Enrichir les métadonnées HF (IA)"
}, },
"contextMenu": { "contextMenu": {
"refreshMetadata": "Actualiser les données Civitai", "refreshMetadata": "Actualiser les données Civitai",
@@ -806,7 +806,7 @@
"viewAllLoras": "Voir tous les LoRAs", "viewAllLoras": "Voir tous les LoRAs",
"downloadMissingLoras": "Télécharger les LoRAs manquants", "downloadMissingLoras": "Télécharger les LoRAs manquants",
"deleteRecipe": "Supprimer la recipe", "deleteRecipe": "Supprimer la recipe",
"enrichHfAgent": "Enrichir les métadonnées (IA)" "enrichHfAgent": "Enrichir les métadonnées HF (IA)"
} }
}, },
"recipes": { "recipes": {

View File

@@ -781,7 +781,7 @@
"complete": "ארגון אוטומטי הושלם", "complete": "ארגון אוטומטי הושלם",
"error": "שגיאה: {error}" "error": "שגיאה: {error}"
}, },
"enrichHfAgent": "העשרת מטא-דאטה (AI)" "enrichHfAgent": "העשרת HF מטא-דאטה (AI)"
}, },
"contextMenu": { "contextMenu": {
"refreshMetadata": "רענן נתוני Civitai", "refreshMetadata": "רענן נתוני Civitai",
@@ -806,7 +806,7 @@
"viewAllLoras": "הצג את כל ה-LoRAs", "viewAllLoras": "הצג את כל ה-LoRAs",
"downloadMissingLoras": "הורד LoRAs חסרים", "downloadMissingLoras": "הורד LoRAs חסרים",
"deleteRecipe": "מחק מתכון", "deleteRecipe": "מחק מתכון",
"enrichHfAgent": "העשרת מטא-דאטה (AI)" "enrichHfAgent": "העשרת HF מטא-דאטה (AI)"
} }
}, },
"recipes": { "recipes": {

View File

@@ -781,7 +781,7 @@
"complete": "自動整理が完了しました", "complete": "自動整理が完了しました",
"error": "エラー:{error}" "error": "エラー:{error}"
}, },
"enrichHfAgent": "メタデータをAIで補完" "enrichHfAgent": "HF メタデータをAIで補完"
}, },
"contextMenu": { "contextMenu": {
"refreshMetadata": "Civitaiデータを更新", "refreshMetadata": "Civitaiデータを更新",
@@ -806,7 +806,7 @@
"viewAllLoras": "すべてのLoRAを表示", "viewAllLoras": "すべてのLoRAを表示",
"downloadMissingLoras": "不足しているLoRAをダウンロード", "downloadMissingLoras": "不足しているLoRAをダウンロード",
"deleteRecipe": "レシピを削除", "deleteRecipe": "レシピを削除",
"enrichHfAgent": "メタデータをAIで補完" "enrichHfAgent": "HF メタデータをAIで補完"
} }
}, },
"recipes": { "recipes": {

View File

@@ -781,7 +781,7 @@
"complete": "자동 정리 완료", "complete": "자동 정리 완료",
"error": "오류: {error}" "error": "오류: {error}"
}, },
"enrichHfAgent": "AI로 메타데이터 보강" "enrichHfAgent": "HF AI로 메타데이터 보강"
}, },
"contextMenu": { "contextMenu": {
"refreshMetadata": "Civitai 데이터 새로고침", "refreshMetadata": "Civitai 데이터 새로고침",
@@ -806,7 +806,7 @@
"viewAllLoras": "모든 LoRA 보기", "viewAllLoras": "모든 LoRA 보기",
"downloadMissingLoras": "누락된 LoRA 다운로드", "downloadMissingLoras": "누락된 LoRA 다운로드",
"deleteRecipe": "레시피 삭제", "deleteRecipe": "레시피 삭제",
"enrichHfAgent": "AI로 메타데이터 보강" "enrichHfAgent": "HF AI로 메타데이터 보강"
} }
}, },
"recipes": { "recipes": {

View File

@@ -781,7 +781,7 @@
"complete": "Автоматическая организация завершена", "complete": "Автоматическая организация завершена",
"error": "Ошибка: {error}" "error": "Ошибка: {error}"
}, },
"enrichHfAgent": "Обогатить метаданные (ИИ)" "enrichHfAgent": "Обогатить HF метаданные (ИИ)"
}, },
"contextMenu": { "contextMenu": {
"refreshMetadata": "Обновить данные Civitai", "refreshMetadata": "Обновить данные Civitai",
@@ -806,7 +806,7 @@
"viewAllLoras": "Посмотреть все LoRAs", "viewAllLoras": "Посмотреть все LoRAs",
"downloadMissingLoras": "Загрузить отсутствующие LoRAs", "downloadMissingLoras": "Загрузить отсутствующие LoRAs",
"deleteRecipe": "Удалить рецепт", "deleteRecipe": "Удалить рецепт",
"enrichHfAgent": "Обогатить метаданные (ИИ)" "enrichHfAgent": "Обогатить HF метаданные (ИИ)"
} }
}, },
"recipes": { "recipes": {

View File

@@ -781,7 +781,7 @@
"complete": "自动整理已完成", "complete": "自动整理已完成",
"error": "错误:{error}" "error": "错误:{error}"
}, },
"enrichHfAgent": "AI 元数据增强" "enrichHfAgent": "AI HF 元数据增强"
}, },
"contextMenu": { "contextMenu": {
"refreshMetadata": "刷新 Civitai 数据", "refreshMetadata": "刷新 Civitai 数据",
@@ -806,7 +806,7 @@
"viewAllLoras": "查看所有 LoRA", "viewAllLoras": "查看所有 LoRA",
"downloadMissingLoras": "下载缺失的 LoRA", "downloadMissingLoras": "下载缺失的 LoRA",
"deleteRecipe": "删除配方", "deleteRecipe": "删除配方",
"enrichHfAgent": "AI 元数据增强" "enrichHfAgent": "AI HF 元数据增强"
} }
}, },
"recipes": { "recipes": {

View File

@@ -781,7 +781,7 @@
"complete": "自動整理完成", "complete": "自動整理完成",
"error": "錯誤:{error}" "error": "錯誤:{error}"
}, },
"enrichHfAgent": "AI 中繼資料增強" "enrichHfAgent": "AI HF 中繼資料增強"
}, },
"contextMenu": { "contextMenu": {
"refreshMetadata": "刷新 Civitai 資料", "refreshMetadata": "刷新 Civitai 資料",
@@ -806,7 +806,7 @@
"viewAllLoras": "檢視全部 LoRA", "viewAllLoras": "檢視全部 LoRA",
"downloadMissingLoras": "下載缺少的 LoRA", "downloadMissingLoras": "下載缺少的 LoRA",
"deleteRecipe": "刪除配方", "deleteRecipe": "刪除配方",
"enrichHfAgent": "AI 中繼資料增強" "enrichHfAgent": "AI HF 中繼資料增強"
} }
}, },
"recipes": { "recipes": {

View File

@@ -242,6 +242,7 @@ class AgentService:
total = len(model_paths) total = len(model_paths)
processed = 0 processed = 0
success_count = 0 success_count = 0
skipped_count = 0
updated_models: List[Dict[str, Any]] = [] updated_models: List[Dict[str, Any]] = []
errors: List[str] = [] errors: List[str] = []
post_processor = PostProcessor() post_processor = PostProcessor()
@@ -261,10 +262,21 @@ class AgentService:
skill_name, processed + 1, total, model_filename, skill_name, processed + 1, total, model_filename,
) )
updated_data: Dict[str, Any] = {} updated_data: Dict[str, Any] = {}
skip_model = False
try: try:
from ...metadata_ops import read_metadata from ...metadata_ops import read_metadata
metadata = await read_metadata(model_path) metadata = await read_metadata(model_path)
# Fast-fail: enrich_hf_metadata requires hf_url to have HF README context
if skill_name == "enrich_hf_metadata" and not metadata.get("hf_url", ""):
logger.info(
"[%s] SKIP %s — no hf_url in metadata",
skill_name, model_filename,
)
skipped_count += 1
skip_model = True
if not skip_model:
prompt_vars: Dict[str, Any] = {"model_path": model_path} prompt_vars: Dict[str, Any] = {"model_path": model_path}
if skill.llm_required and llm_configured: if skill.llm_required and llm_configured:
prompt_vars = await self._build_prompt_context( prompt_vars = await self._build_prompt_context(
@@ -321,6 +333,7 @@ class AgentService:
await self._emit_progress( await self._emit_progress(
progress_callback, skill_name, status="processing", progress_callback, skill_name, status="processing",
total=total, processed=processed, success=success_count, total=total, processed=processed, success=success_count,
skipped=skipped_count,
current_path=model_path, current_path=model_path,
updated_data=updated_data, updated_data=updated_data,
) )
@@ -329,12 +342,13 @@ class AgentService:
success=success_count > 0, success=success_count > 0,
updated_models=updated_models, updated_models=updated_models,
errors=errors, errors=errors,
summary=f"Processed {processed}/{total} models, {success_count} succeeded", summary=f"Processed {processed}/{total} models, {success_count} succeeded, {skipped_count} skipped",
) )
await self._emit_progress( await self._emit_progress(
progress_callback, skill_name, status="completed", progress_callback, skill_name, status="completed",
total=total, processed=processed, success=success_count, total=total, processed=processed, success=success_count,
skipped=skipped_count,
updated_models=updated_models, errors=errors, summary=result.summary, updated_models=updated_models, errors=errors, summary=result.summary,
) )

View File

@@ -40,6 +40,12 @@
margin: 3px 0; margin: 3px 0;
} }
.context-menu-item.disabled {
opacity: 0.4;
cursor: not-allowed;
pointer-events: none;
}
.context-menu-item.delete-item { .context-menu-item.delete-item {
color: var(--danger-color); color: var(--danger-color);
} }

View File

@@ -27,8 +27,9 @@ export class BaseContextMenu {
const menuItem = e.target.closest('.context-menu-item'); const menuItem = e.target.closest('.context-menu-item');
if (!menuItem || !this.currentCard) return; if (!menuItem || !this.currentCard) return;
// Ignore clicks on submenu trigger (has-submenu parent) // Ignore clicks on submenu trigger (has-submenu parent) or disabled items
if (menuItem.classList.contains('has-submenu')) return; if (menuItem.classList.contains('has-submenu')) return;
if (menuItem.classList.contains('disabled')) return;
const action = menuItem.dataset.action; const action = menuItem.dataset.action;
if (!action) return; if (!action) return;

View File

@@ -24,6 +24,14 @@ export class LoraContextMenu extends BaseContextMenu {
showMenu(x, y, card) { showMenu(x, y, card) {
super.showMenu(x, y, card); super.showMenu(x, y, card);
this.updateExcludeMenuItem(); this.updateExcludeMenuItem();
this.updateEnrichMenuItem(card);
}
updateEnrichMenuItem(card) {
const enrichItem = this.menu?.querySelector('[data-action="enrich-hf-llm"]');
if (!enrichItem) return;
const hasHfUrl = !!card.dataset.hf_url;
enrichItem.classList.toggle('disabled', !hasHfUrl);
} }
handleMenuAction(action, menuItem) { handleMenuAction(action, menuItem) {

View File

@@ -12,12 +12,12 @@
<div class="context-menu-item" data-action="check-updates"> <div class="context-menu-item" data-action="check-updates">
<i class="fas fa-bell"></i> <span>{{ t('loras.contextMenu.checkUpdates') }}</span> <i class="fas fa-bell"></i> <span>{{ t('loras.contextMenu.checkUpdates') }}</span>
</div> </div>
<div class="context-menu-item" data-action="enrich-hf-llm">
<i class="fas fa-wand-magic-sparkles"></i> <span>{{ t('loras.contextMenu.enrichHfAgent') }}</span>
</div>
<div class="context-menu-item" data-action="relink-civitai"> <div class="context-menu-item" data-action="relink-civitai">
<i class="fas fa-link"></i> <span>{{ t('loras.contextMenu.relinkCivitai') }}</span> <i class="fas fa-link"></i> <span>{{ t('loras.contextMenu.relinkCivitai') }}</span>
</div> </div>
<div class="context-menu-item" data-action="enrich-hf-llm">
<i class="fas fa-wand-magic-sparkles"></i> <span>{{ t('loras.contextMenu.enrichHfAgent') }}</span>
</div>
<div class="context-menu-separator menu-section-break"></div> <div class="context-menu-separator menu-section-break"></div>
<!-- Workflow --> <!-- Workflow -->
<div class="context-menu-item" data-action="copyname"> <div class="context-menu-item" data-action="copyname">