From e713bd1ca280276ef29e32c837061f468192eb9d Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Fri, 12 Sep 2025 11:22:32 +0800 Subject: [PATCH 001/110] feat: add app-level proxy settings with UI integration and session management, fixes #382 --- locales/de.json | 21 ++- locales/en.json | 21 ++- locales/es.json | 21 ++- locales/fr.json | 21 ++- locales/ja.json | 21 ++- locales/ko.json | 21 ++- locales/ru.json | 21 ++- locales/zh-CN.json | 21 ++- locales/zh-TW.json | 21 ++- py/lora_manager.py | 3 - py/routes/misc_routes.py | 18 ++- py/services/downloader.py | 73 ++++++++++- py/services/settings_manager.py | 15 ++- .../css/components/modal/settings-modal.css | 55 +++++++- static/js/managers/SettingsManager.js | 120 ++++++++++++++--- .../components/modals/settings_modal.html | 124 ++++++++++++++++++ 16 files changed, 556 insertions(+), 41 deletions(-) diff --git a/locales/de.json b/locales/de.json index 49596c76..f0125334 100644 --- a/locales/de.json +++ b/locales/de.json @@ -181,7 +181,8 @@ "downloadPathTemplates": "Download-Pfad-Vorlagen", "exampleImages": "Beispielbilder", "misc": "Verschiedenes", - "metadataArchive": "Metadaten-Archiv-Datenbank" + "metadataArchive": "Metadaten-Archiv-Datenbank", + "proxySettings": "Proxy-Einstellungen" }, "contentFiltering": { "blurNsfwContent": "NSFW-Inhalte unscharf stellen", @@ -300,6 +301,24 @@ "connecting": "Verbindung zum Download-Server wird hergestellt...", "completed": "Abgeschlossen", "downloadComplete": "Download erfolgreich abgeschlossen" + }, + "proxySettings": { + "enableProxy": "App-Proxy aktivieren", + "enableProxyHelp": "Aktivieren Sie benutzerdefinierte Proxy-Einstellungen für diese Anwendung. Überschreibt die System-Proxy-Einstellungen.", + "proxyType": "Proxy-Typ", + "proxyTypeHelp": "Wählen Sie den Typ des Proxy-Servers (HTTP, HTTPS, SOCKS4, SOCKS5)", + "proxyHost": "Proxy-Host", + "proxyHostPlaceholder": "proxy.beispiel.de", + "proxyHostHelp": "Der Hostname oder die IP-Adresse Ihres Proxy-Servers", + "proxyPort": "Proxy-Port", + "proxyPortPlaceholder": "8080", + "proxyPortHelp": "Die Portnummer Ihres Proxy-Servers", + "proxyUsername": "Benutzername (optional)", + "proxyUsernamePlaceholder": "benutzername", + "proxyUsernameHelp": "Benutzername für die Proxy-Authentifizierung (falls erforderlich)", + "proxyPassword": "Passwort (optional)", + "proxyPasswordPlaceholder": "passwort", + "proxyPasswordHelp": "Passwort für die Proxy-Authentifizierung (falls erforderlich)" } }, "loras": { diff --git a/locales/en.json b/locales/en.json index 58053fca..24e4704e 100644 --- a/locales/en.json +++ b/locales/en.json @@ -181,7 +181,8 @@ "downloadPathTemplates": "Download Path Templates", "exampleImages": "Example Images", "misc": "Misc.", - "metadataArchive": "Metadata Archive Database" + "metadataArchive": "Metadata Archive Database", + "proxySettings": "Proxy Settings" }, "contentFiltering": { "blurNsfwContent": "Blur NSFW Content", @@ -300,6 +301,24 @@ "connecting": "Connecting to download server...", "completed": "Completed", "downloadComplete": "Download completed successfully" + }, + "proxySettings": { + "enableProxy": "Enable App-level Proxy", + "enableProxyHelp": "Enable custom proxy settings for this application, overriding system proxy settings", + "proxyType": "Proxy Type", + "proxyTypeHelp": "Select the type of proxy server (HTTP, HTTPS, SOCKS4, SOCKS5)", + "proxyHost": "Proxy Host", + "proxyHostPlaceholder": "proxy.example.com", + "proxyHostHelp": "The hostname or IP address of your proxy server", + "proxyPort": "Proxy Port", + "proxyPortPlaceholder": "8080", + "proxyPortHelp": "The port number of your proxy server", + "proxyUsername": "Username (Optional)", + "proxyUsernamePlaceholder": "username", + "proxyUsernameHelp": "Username for proxy authentication (if required)", + "proxyPassword": "Password (Optional)", + "proxyPasswordPlaceholder": "password", + "proxyPasswordHelp": "Password for proxy authentication (if required)" } }, "loras": { diff --git a/locales/es.json b/locales/es.json index 9072722c..a3e04cd8 100644 --- a/locales/es.json +++ b/locales/es.json @@ -181,7 +181,8 @@ "downloadPathTemplates": "Plantillas de rutas de descarga", "exampleImages": "Imágenes de ejemplo", "misc": "Varios", - "metadataArchive": "Base de datos de archivo de metadatos" + "metadataArchive": "Base de datos de archivo de metadatos", + "proxySettings": "Configuración de proxy" }, "contentFiltering": { "blurNsfwContent": "Difuminar contenido NSFW", @@ -300,6 +301,24 @@ "connecting": "Conectando al servidor de descarga...", "completed": "Completado", "downloadComplete": "Descarga completada exitosamente" + }, + "proxySettings": { + "enableProxy": "Habilitar proxy a nivel de aplicación", + "enableProxyHelp": "Habilita la configuración de proxy personalizada para esta aplicación, sobrescribiendo la configuración de proxy del sistema", + "proxyType": "Tipo de proxy", + "proxyTypeHelp": "Selecciona el tipo de servidor proxy (HTTP, HTTPS, SOCKS4, SOCKS5)", + "proxyHost": "Host del proxy", + "proxyHostPlaceholder": "proxy.ejemplo.com", + "proxyHostHelp": "El nombre de host o dirección IP de tu servidor proxy", + "proxyPort": "Puerto del proxy", + "proxyPortPlaceholder": "8080", + "proxyPortHelp": "El número de puerto de tu servidor proxy", + "proxyUsername": "Usuario (opcional)", + "proxyUsernamePlaceholder": "usuario", + "proxyUsernameHelp": "Usuario para autenticación de proxy (si es necesario)", + "proxyPassword": "Contraseña (opcional)", + "proxyPasswordPlaceholder": "contraseña", + "proxyPasswordHelp": "Contraseña para autenticación de proxy (si es necesario)" } }, "loras": { diff --git a/locales/fr.json b/locales/fr.json index 16e3e3d7..38a6b1f5 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -181,7 +181,8 @@ "downloadPathTemplates": "Modèles de chemin de téléchargement", "exampleImages": "Images d'exemple", "misc": "Divers", - "metadataArchive": "Base de données d'archive des métadonnées" + "metadataArchive": "Base de données d'archive des métadonnées", + "proxySettings": "Paramètres du proxy" }, "contentFiltering": { "blurNsfwContent": "Flouter le contenu NSFW", @@ -300,6 +301,24 @@ "connecting": "Connexion au serveur de téléchargement...", "completed": "Terminé", "downloadComplete": "Téléchargement terminé avec succès" + }, + "proxySettings": { + "enableProxy": "Activer le proxy au niveau de l'application", + "enableProxyHelp": "Activer les paramètres de proxy personnalisés pour cette application, remplaçant les paramètres de proxy système", + "proxyType": "Type de proxy", + "proxyTypeHelp": "Sélectionnez le type de serveur proxy (HTTP, HTTPS, SOCKS4, SOCKS5)", + "proxyHost": "Hôte du proxy", + "proxyHostPlaceholder": "proxy.exemple.com", + "proxyHostHelp": "Le nom d'hôte ou l'adresse IP de votre serveur proxy", + "proxyPort": "Port du proxy", + "proxyPortPlaceholder": "8080", + "proxyPortHelp": "Le numéro de port de votre serveur proxy", + "proxyUsername": "Nom d'utilisateur (optionnel)", + "proxyUsernamePlaceholder": "nom_utilisateur", + "proxyUsernameHelp": "Nom d'utilisateur pour l'authentification proxy (si nécessaire)", + "proxyPassword": "Mot de passe (optionnel)", + "proxyPasswordPlaceholder": "mot_de_passe", + "proxyPasswordHelp": "Mot de passe pour l'authentification proxy (si nécessaire)" } }, "loras": { diff --git a/locales/ja.json b/locales/ja.json index 90ab446d..f8bdefc6 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -181,7 +181,8 @@ "downloadPathTemplates": "ダウンロードパステンプレート", "exampleImages": "例画像", "misc": "その他", - "metadataArchive": "メタデータアーカイブデータベース" + "metadataArchive": "メタデータアーカイブデータベース", + "proxySettings": "プロキシ設定" }, "contentFiltering": { "blurNsfwContent": "NSFWコンテンツをぼかす", @@ -300,6 +301,24 @@ "connecting": "ダウンロードサーバーに接続中...", "completed": "完了", "downloadComplete": "ダウンロードが正常に完了しました" + }, + "proxySettings": { + "enableProxy": "アプリレベルのプロキシを有効化", + "enableProxyHelp": "このアプリケーション専用のカスタムプロキシ設定を有効にします(システムのプロキシ設定を上書きします)", + "proxyType": "プロキシタイプ", + "proxyTypeHelp": "プロキシサーバーの種類を選択(HTTP、HTTPS、SOCKS4、SOCKS5)", + "proxyHost": "プロキシホスト", + "proxyHostPlaceholder": "proxy.example.com", + "proxyHostHelp": "プロキシサーバーのホスト名またはIPアドレス", + "proxyPort": "プロキシポート", + "proxyPortPlaceholder": "8080", + "proxyPortHelp": "プロキシサーバーのポート番号", + "proxyUsername": "ユーザー名(任意)", + "proxyUsernamePlaceholder": "ユーザー名", + "proxyUsernameHelp": "プロキシ認証用のユーザー名(必要な場合)", + "proxyPassword": "パスワード(任意)", + "proxyPasswordPlaceholder": "パスワード", + "proxyPasswordHelp": "プロキシ認証用のパスワード(必要な場合)" } }, "loras": { diff --git a/locales/ko.json b/locales/ko.json index d180b076..08ab8e38 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -181,7 +181,8 @@ "downloadPathTemplates": "다운로드 경로 템플릿", "exampleImages": "예시 이미지", "misc": "기타", - "metadataArchive": "메타데이터 아카이브 데이터베이스" + "metadataArchive": "메타데이터 아카이브 데이터베이스", + "proxySettings": "프록시 설정" }, "contentFiltering": { "blurNsfwContent": "NSFW 콘텐츠 블러 처리", @@ -300,6 +301,24 @@ "connecting": "다운로드 서버에 연결 중...", "completed": "완료됨", "downloadComplete": "다운로드가 성공적으로 완료되었습니다" + }, + "proxySettings": { + "enableProxy": "앱 수준 프록시 활성화", + "enableProxyHelp": "이 애플리케이션에 대한 사용자 지정 프록시 설정을 활성화하여 시스템 프록시 설정을 무시합니다", + "proxyType": "프록시 유형", + "proxyTypeHelp": "프록시 서버 유형을 선택하세요 (HTTP, HTTPS, SOCKS4, SOCKS5)", + "proxyHost": "프록시 호스트", + "proxyHostPlaceholder": "proxy.example.com", + "proxyHostHelp": "프록시 서버의 호스트명 또는 IP 주소", + "proxyPort": "프록시 포트", + "proxyPortPlaceholder": "8080", + "proxyPortHelp": "프록시 서버의 포트 번호", + "proxyUsername": "사용자 이름 (선택사항)", + "proxyUsernamePlaceholder": "username", + "proxyUsernameHelp": "프록시 인증에 필요한 사용자 이름 (필요한 경우)", + "proxyPassword": "비밀번호 (선택사항)", + "proxyPasswordPlaceholder": "password", + "proxyPasswordHelp": "프록시 인증에 필요한 비밀번호 (필요한 경우)" } }, "loras": { diff --git a/locales/ru.json b/locales/ru.json index 6850954a..522ac612 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -181,7 +181,8 @@ "downloadPathTemplates": "Шаблоны путей загрузки", "exampleImages": "Примеры изображений", "misc": "Разное", - "metadataArchive": "Архив метаданных" + "metadataArchive": "Архив метаданных", + "proxySettings": "Настройки прокси" }, "contentFiltering": { "blurNsfwContent": "Размывать NSFW контент", @@ -300,6 +301,24 @@ "connecting": "Подключение к серверу загрузки...", "completed": "Завершено", "downloadComplete": "Загрузка успешно завершена" + }, + "proxySettings": { + "enableProxy": "Включить прокси на уровне приложения", + "enableProxyHelp": "Включить пользовательские настройки прокси для этого приложения, переопределяя системные настройки прокси", + "proxyType": "Тип прокси", + "proxyTypeHelp": "Выберите тип прокси-сервера (HTTP, HTTPS, SOCKS4, SOCKS5)", + "proxyHost": "Хост прокси", + "proxyHostPlaceholder": "proxy.example.com", + "proxyHostHelp": "Имя хоста или IP-адрес вашего прокси-сервера", + "proxyPort": "Порт прокси", + "proxyPortPlaceholder": "8080", + "proxyPortHelp": "Номер порта вашего прокси-сервера", + "proxyUsername": "Имя пользователя (необязательно)", + "proxyUsernamePlaceholder": "имя пользователя", + "proxyUsernameHelp": "Имя пользователя для аутентификации на прокси (если требуется)", + "proxyPassword": "Пароль (необязательно)", + "proxyPasswordPlaceholder": "пароль", + "proxyPasswordHelp": "Пароль для аутентификации на прокси (если требуется)" } }, "loras": { diff --git a/locales/zh-CN.json b/locales/zh-CN.json index bab32fd9..5884f1fc 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -181,7 +181,8 @@ "downloadPathTemplates": "下载路径模板", "exampleImages": "示例图片", "misc": "其他", - "metadataArchive": "元数据归档数据库" + "metadataArchive": "元数据归档数据库", + "proxySettings": "代理设置" }, "contentFiltering": { "blurNsfwContent": "模糊 NSFW 内容", @@ -300,6 +301,24 @@ "connecting": "正在连接下载服务器...", "completed": "已完成", "downloadComplete": "下载成功完成" + }, + "proxySettings": { + "enableProxy": "启用应用级代理", + "enableProxyHelp": "为此应用启用自定义代理设置,覆盖系统代理设置", + "proxyType": "代理类型", + "proxyTypeHelp": "选择代理服务器类型 (HTTP, HTTPS, SOCKS4, SOCKS5)", + "proxyHost": "代理主机", + "proxyHostPlaceholder": "proxy.example.com", + "proxyHostHelp": "代理服务器的主机名或IP地址", + "proxyPort": "代理端口", + "proxyPortPlaceholder": "8080", + "proxyPortHelp": "代理服务器的端口号", + "proxyUsername": "用户名 (可选)", + "proxyUsernamePlaceholder": "用户名", + "proxyUsernameHelp": "代理认证的用户名 (如果需要)", + "proxyPassword": "密码 (可选)", + "proxyPasswordPlaceholder": "密码", + "proxyPasswordHelp": "代理认证的密码 (如果需要)" } }, "loras": { diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 926b6888..5e982e5f 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -181,7 +181,8 @@ "downloadPathTemplates": "下載路徑範本", "exampleImages": "範例圖片", "misc": "其他", - "metadataArchive": "中繼資料封存資料庫" + "metadataArchive": "中繼資料封存資料庫", + "proxySettings": "代理設定" }, "contentFiltering": { "blurNsfwContent": "模糊 NSFW 內容", @@ -300,6 +301,24 @@ "connecting": "正在連接下載伺服器...", "completed": "已完成", "downloadComplete": "下載成功完成" + }, + "proxySettings": { + "enableProxy": "啟用應用程式代理", + "enableProxyHelp": "啟用此應用程式的自訂代理設定,將覆蓋系統代理設定", + "proxyType": "代理類型", + "proxyTypeHelp": "選擇代理伺服器類型(HTTP、HTTPS、SOCKS4、SOCKS5)", + "proxyHost": "代理主機", + "proxyHostPlaceholder": "proxy.example.com", + "proxyHostHelp": "您的代理伺服器主機名稱或 IP 位址", + "proxyPort": "代理埠號", + "proxyPortPlaceholder": "8080", + "proxyPortHelp": "您的代理伺服器埠號", + "proxyUsername": "使用者名稱(選填)", + "proxyUsernamePlaceholder": "username", + "proxyUsernameHelp": "代理驗證所需的使用者名稱(如有需要)", + "proxyPassword": "密碼(選填)", + "proxyPasswordPlaceholder": "password", + "proxyPasswordHelp": "代理驗證所需的密碼(如有需要)" } }, "loras": { diff --git a/py/lora_manager.py b/py/lora_manager.py index f6598bca..96bae4de 100644 --- a/py/lora_manager.py +++ b/py/lora_manager.py @@ -409,9 +409,6 @@ class LoraManager: await cls._remove_folder_safely(folder_path) invalid_hash_folders_removed += 1 continue - - logger.debug(f"Keeping valid example images folder: {folder_name}") - except Exception as e: logger.error(f"Error processing example images folder {folder_name}: {e}") diff --git a/py/routes/misc_routes.py b/py/routes/misc_routes.py index 5ae2eadd..013923b7 100644 --- a/py/routes/misc_routes.py +++ b/py/routes/misc_routes.py @@ -14,6 +14,7 @@ from ..utils.constants import SUPPORTED_MEDIA_EXTENSIONS, NODE_TYPES, DEFAULT_NO from ..services.service_registry import ServiceRegistry from ..services.metadata_service import get_metadata_archive_manager, update_metadata_providers from ..services.websocket_manager import ws_manager +from ..services.downloader import get_downloader logger = logging.getLogger(__name__) standalone_mode = 'nodes' not in sys.modules @@ -123,6 +124,8 @@ class MiscRoutes: """Update application settings""" try: data = await request.json() + proxy_keys = {'proxy_enabled', 'proxy_host', 'proxy_port', 'proxy_username', 'proxy_password', 'proxy_type'} + proxy_changed = False # Validate and update settings for key, value in data.items(): @@ -142,11 +145,22 @@ class MiscRoutes: if old_path != value: logger.info(f"Example images path changed to {value} - server restart required") - # Save to settings - settings.set(key, value) + # Handle deletion for proxy credentials + if value == '__DELETE__' and key in ('proxy_username', 'proxy_password'): + settings.delete(key) + else: + # Save to settings + settings.set(key, value) if key == 'enable_metadata_archive_db': await update_metadata_providers() + + if key in proxy_keys: + proxy_changed = True + + if proxy_changed: + downloader = await get_downloader() + await downloader.refresh_session() return web.json_response({'success': True}) except Exception as e: diff --git a/py/services/downloader.py b/py/services/downloader.py index dc38c0d1..4a26c38b 100644 --- a/py/services/downloader.py +++ b/py/services/downloader.py @@ -45,6 +45,7 @@ class Downloader: # Session management self._session = None self._session_created_at = None + self._proxy_url = None # Store proxy URL for current session # Configuration self.chunk_size = 4 * 1024 * 1024 # 4MB chunks for better throughput @@ -64,6 +65,13 @@ class Downloader: await self._create_session() return self._session + @property + def proxy_url(self) -> Optional[str]: + """Get the current proxy URL (initialize if needed)""" + if not hasattr(self, '_proxy_url'): + self._proxy_url = None + return self._proxy_url + def _should_refresh_session(self) -> bool: """Check if session should be refreshed""" if self._session is None: @@ -84,6 +92,26 @@ class Downloader: if self._session is not None: await self._session.close() + # Check for app-level proxy settings + proxy_url = None + if settings.get('proxy_enabled', False): + proxy_host = settings.get('proxy_host', '').strip() + proxy_port = settings.get('proxy_port', '').strip() + proxy_type = settings.get('proxy_type', 'http').lower() + proxy_username = settings.get('proxy_username', '').strip() + proxy_password = settings.get('proxy_password', '').strip() + + if proxy_host and proxy_port: + # Build proxy URL + if proxy_username and proxy_password: + proxy_url = f"{proxy_type}://{proxy_username}:{proxy_password}@{proxy_host}:{proxy_port}" + else: + proxy_url = f"{proxy_type}://{proxy_host}:{proxy_port}" + + logger.info(f"Using app-level proxy: {proxy_type}://{proxy_host}:{proxy_port}") + logger.debug("Proxy mode: app-level proxy is active.") + else: + logger.debug("Proxy mode: system-level proxy (trust_env) will be used if configured in environment.") # Optimize TCP connection parameters connector = aiohttp.TCPConnector( ssl=True, @@ -102,12 +130,15 @@ class Downloader: self._session = aiohttp.ClientSession( connector=connector, - trust_env=True, # Use system proxy settings + trust_env=proxy_url is None, # Only use system proxy if no app-level proxy is set timeout=timeout ) + + # Store proxy URL for use in requests + self._proxy_url = proxy_url self._session_created_at = datetime.now() - logger.debug("Created new HTTP session") + logger.debug("Created new HTTP session with proxy settings. App-level proxy: %s, System-level proxy (trust_env): %s", bool(proxy_url), proxy_url is None) def _get_auth_headers(self, use_auth: bool = False) -> Dict[str, str]: """Get headers with optional authentication""" @@ -164,6 +195,11 @@ class Downloader: while retry_count <= self.max_retries: try: session = await self.session + # Debug log for proxy mode at request time + if self.proxy_url: + logger.debug(f"[download_file] Using app-level proxy: {self.proxy_url}") + else: + logger.debug("[download_file] Using system-level proxy (trust_env) if configured.") # Add Range header for resume if we have partial data request_headers = headers.copy() @@ -177,7 +213,7 @@ class Downloader: if resume_offset > 0: logger.debug(f"Requesting range from byte {resume_offset}") - async with session.get(url, headers=request_headers, allow_redirects=True) as response: + async with session.get(url, headers=request_headers, allow_redirects=True, proxy=self.proxy_url) as response: # Handle different response codes if response.status == 200: # Full content response @@ -202,7 +238,7 @@ class Downloader: part_size = os.path.getsize(part_path) logger.warning(f"Range not satisfiable. Part file size: {part_size}") # Try to get actual file size - head_response = await session.head(url, headers=headers) + head_response = await session.head(url, headers=headers, proxy=self.proxy_url) if head_response.status == 200: actual_size = int(head_response.headers.get('content-length', 0)) if part_size == actual_size: @@ -345,13 +381,18 @@ class Downloader: """ try: session = await self.session + # Debug log for proxy mode at request time + if self.proxy_url: + logger.debug(f"[download_to_memory] Using app-level proxy: {self.proxy_url}") + else: + logger.debug("[download_to_memory] Using system-level proxy (trust_env) if configured.") # Prepare headers headers = self._get_auth_headers(use_auth) if custom_headers: headers.update(custom_headers) - async with session.get(url, headers=headers) as response: + async with session.get(url, headers=headers, proxy=self.proxy_url) as response: if response.status == 200: content = await response.read() return True, content @@ -387,13 +428,18 @@ class Downloader: """ try: session = await self.session + # Debug log for proxy mode at request time + if self.proxy_url: + logger.debug(f"[get_response_headers] Using app-level proxy: {self.proxy_url}") + else: + logger.debug("[get_response_headers] Using system-level proxy (trust_env) if configured.") # Prepare headers headers = self._get_auth_headers(use_auth) if custom_headers: headers.update(custom_headers) - async with session.head(url, headers=headers) as response: + async with session.head(url, headers=headers, proxy=self.proxy_url) as response: if response.status == 200: return True, dict(response.headers) else: @@ -426,12 +472,21 @@ class Downloader: """ try: session = await self.session + # Debug log for proxy mode at request time + if self.proxy_url: + logger.debug(f"[make_request] Using app-level proxy: {self.proxy_url}") + else: + logger.debug("[make_request] Using system-level proxy (trust_env) if configured.") # Prepare headers headers = self._get_auth_headers(use_auth) if custom_headers: headers.update(custom_headers) + # Add proxy to kwargs if not already present + if 'proxy' not in kwargs: + kwargs['proxy'] = self.proxy_url + async with session.request(method, url, headers=headers, **kwargs) as response: if response.status == 200: # Try to parse as JSON, fall back to text @@ -460,7 +515,13 @@ class Downloader: await self._session.close() self._session = None self._session_created_at = None + self._proxy_url = None logger.debug("Closed HTTP session") + + async def refresh_session(self): + """Force refresh the HTTP session (useful when proxy settings change)""" + await self._create_session() + logger.info("HTTP session refreshed due to settings change") # Global instance accessor diff --git a/py/services/settings_manager.py b/py/services/settings_manager.py index 7d99da48..5a95e58e 100644 --- a/py/services/settings_manager.py +++ b/py/services/settings_manager.py @@ -82,7 +82,13 @@ class SettingsManager: "civitai_api_key": "", "show_only_sfw": False, "language": "en", - "enable_metadata_archive_db": False # Enable metadata archive database + "enable_metadata_archive_db": False, # Enable metadata archive database + "proxy_enabled": False, # Enable app-level proxy + "proxy_host": "", # Proxy host + "proxy_port": "", # Proxy port + "proxy_username": "", # Proxy username (optional) + "proxy_password": "", # Proxy password (optional) + "proxy_type": "http" # Proxy type: http, https, socks4, socks5 } def get(self, key: str, default: Any = None) -> Any: @@ -94,6 +100,13 @@ class SettingsManager: self.settings[key] = value self._save_settings() + def delete(self, key: str) -> None: + """Delete setting key and save""" + if key in self.settings: + del self.settings[key] + self._save_settings() + logger.info(f"Deleted setting: {key}") + def _save_settings(self) -> None: """Save settings to file""" try: diff --git a/static/css/components/modal/settings-modal.css b/static/css/components/modal/settings-modal.css index a13dc856..3f59203e 100644 --- a/static/css/components/modal/settings-modal.css +++ b/static/css/components/modal/settings-modal.css @@ -101,7 +101,7 @@ .api-key-input input { width: 100%; padding: 6px 40px 6px 10px; /* Add left padding */ - height: 32px; + height: 20px; border-radius: var(--border-radius-xs); border: 1px solid var(--border-color); background-color: var(--lora-surface); @@ -123,6 +123,36 @@ opacity: 1; } +/* Text input wrapper styles for consistent input styling */ +.text-input-wrapper { + width: 100%; + position: relative; + display: flex; + align-items: center; +} + +.text-input-wrapper input { + width: 100%; + padding: 6px 10px; + height: 20px; + border-radius: var(--border-radius-xs); + border: 1px solid var(--border-color); + background-color: var(--lora-surface); + color: var(--text-color); + font-size: 0.95em; +} + +.text-input-wrapper input:focus { + border-color: var(--lora-accent); + outline: none; + box-shadow: 0 0 0 2px rgba(var(--lora-accent-rgb, 79, 70, 229), 0.1); +} + +/* Dark theme specific adjustments */ +[data-theme="dark"] .text-input-wrapper input { + background-color: rgba(30, 30, 30, 0.9); +} + .input-help { font-size: 0.85em; color: var(--text-color); @@ -312,7 +342,7 @@ input:checked + .toggle-slider:before { border-radius: var(--border-radius-xs); border: 1px solid var(--border-color); background-color: var(--lora-surface); - color: var (--text-color); + color: var(--text-color); font-size: 0.95em; height: 32px; } @@ -571,10 +601,31 @@ input:checked + .toggle-slider:before { background-color: rgba(30, 30, 30, 0.9); } +/* Proxy Settings Styles */ +.proxy-settings-group { + margin-left: var(--space-1); + padding-left: var(--space-1); + border-left: 2px solid var(--lora-border); + animation: slideDown 0.3s ease-out; +} + +.proxy-settings-group .setting-item { + margin-bottom: var(--space-2); +} + /* Responsive adjustments */ @media (max-width: 768px) { .placeholder-info { flex-direction: column; align-items: flex-start; } + + .proxy-settings-group { + margin-left: 0; + padding-left: var(--space-1); + border-left: none; + border-top: 1px solid var(--lora-border); + padding-top: var(--space-2); + margin-top: var(--space-2); + } } \ No newline at end of file diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index 2d477d24..96e3064d 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -125,7 +125,13 @@ export class SettingsManager { 'default_checkpoint_root', 'default_embedding_root', 'base_model_path_mappings', - 'download_path_templates' + 'download_path_templates', + 'proxy_enabled', + 'proxy_type', + 'proxy_host', + 'proxy_port', + 'proxy_username', + 'proxy_password' ]; // Build payload for syncing @@ -281,6 +287,60 @@ export class SettingsManager { const currentLanguage = state.global.settings.language || 'en'; languageSelect.value = currentLanguage; } + + this.loadProxySettings(); + } + + loadProxySettings() { + // Load proxy enabled setting + const proxyEnabledCheckbox = document.getElementById('proxyEnabled'); + if (proxyEnabledCheckbox) { + proxyEnabledCheckbox.checked = state.global.settings.proxy_enabled || false; + + // Add event listener for toggling proxy settings group visibility + proxyEnabledCheckbox.addEventListener('change', () => { + const proxySettingsGroup = document.getElementById('proxySettingsGroup'); + if (proxySettingsGroup) { + proxySettingsGroup.style.display = proxyEnabledCheckbox.checked ? 'block' : 'none'; + } + }); + + // Set initial visibility + const proxySettingsGroup = document.getElementById('proxySettingsGroup'); + if (proxySettingsGroup) { + proxySettingsGroup.style.display = proxyEnabledCheckbox.checked ? 'block' : 'none'; + } + } + + // Load proxy type + const proxyTypeSelect = document.getElementById('proxyType'); + if (proxyTypeSelect) { + proxyTypeSelect.value = state.global.settings.proxy_type || 'http'; + } + + // Load proxy host + const proxyHostInput = document.getElementById('proxyHost'); + if (proxyHostInput) { + proxyHostInput.value = state.global.settings.proxy_host || ''; + } + + // Load proxy port + const proxyPortInput = document.getElementById('proxyPort'); + if (proxyPortInput) { + proxyPortInput.value = state.global.settings.proxy_port || ''; + } + + // Load proxy username + const proxyUsernameInput = document.getElementById('proxyUsername'); + if (proxyUsernameInput) { + proxyUsernameInput.value = state.global.settings.proxy_username || ''; + } + + // Load proxy password + const proxyPasswordInput = document.getElementById('proxyPassword'); + if (proxyPasswordInput) { + proxyPasswordInput.value = state.global.settings.proxy_password || ''; + } } async loadLoraRoots() { @@ -791,6 +851,14 @@ export class SettingsManager { state.global.settings.includeTriggerWords = value; } else if (settingKey === 'enable_metadata_archive_db') { state.global.settings.enable_metadata_archive_db = value; + } else if (settingKey === 'proxy_enabled') { + state.global.settings.proxy_enabled = value; + + // Toggle visibility of proxy settings group + const proxySettingsGroup = document.getElementById('proxySettingsGroup'); + if (proxySettingsGroup) { + proxySettingsGroup.style.display = value ? 'block' : 'none'; + } } else { // For any other settings that might be added in the future state.global.settings[settingKey] = value; @@ -801,7 +869,7 @@ export class SettingsManager { try { // For backend settings, make API call - if (['show_only_sfw', 'enable_metadata_archive_db'].includes(settingKey)) { + if (['show_only_sfw', 'enable_metadata_archive_db', 'proxy_enabled'].includes(settingKey)) { const payload = {}; payload[settingKey] = value; @@ -879,6 +947,8 @@ export class SettingsManager { state.global.settings.compactMode = (value !== 'default'); } else if (settingKey === 'card_info_display') { state.global.settings.cardInfoDisplay = value; + } else if (settingKey === 'proxy_type') { + state.global.settings.proxy_type = value; } else { // For any other settings that might be added in the future state.global.settings[settingKey] = value; @@ -889,7 +959,7 @@ export class SettingsManager { try { // For backend settings, make API call - if (settingKey === 'default_lora_root' || settingKey === 'default_checkpoint_root' || settingKey === 'default_embedding_root' || settingKey === 'download_path_templates') { + if (settingKey === 'default_lora_root' || settingKey === 'default_checkpoint_root' || settingKey === 'default_embedding_root' || settingKey === 'download_path_templates' || settingKey.startsWith('proxy_')) { const payload = {}; if (settingKey === 'download_path_templates') { payload[settingKey] = state.global.settings.download_path_templates; @@ -1183,7 +1253,7 @@ export class SettingsManager { const element = document.getElementById(elementId); if (!element) return; - const value = element.value; + const value = element.value.trim(); // Trim whitespace // For API key or other inputs that need to be saved on backend try { @@ -1193,25 +1263,39 @@ export class SettingsManager { return; // No change, exit early } - // Update state - state.global.settings[settingKey] = value; + // For username and password, remove the setting if value is empty + if ((settingKey === 'proxy_username' || settingKey === 'proxy_password') && value === '') { + // Remove from state instead of setting to empty string + delete state.global.settings[settingKey]; + } else { + // Update state with value (including empty strings for non-optional fields) + state.global.settings[settingKey] = value; + } setStorageItem('settings', state.global.settings); // For backend settings, make API call - const payload = {}; - payload[settingKey] = value; - - const response = await fetch('/api/settings', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(payload) - }); + if (settingKey === 'civitai_api_key' || settingKey.startsWith('proxy_')) { + const payload = {}; + + // For username and password, send delete flag if empty to remove from backend + if ((settingKey === 'proxy_username' || settingKey === 'proxy_password') && value === '') { + payload[settingKey] = '__DELETE__'; + } else { + payload[settingKey] = value; + } + + const response = await fetch('/api/settings', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(payload) + }); - if (!response.ok) { - throw new Error('Failed to save setting'); + if (!response.ok) { + throw new Error('Failed to save setting'); + } } showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success'); diff --git a/templates/components/modals/settings_modal.html b/templates/components/modals/settings_modal.html index 3b1b3a8a..09fea0c9 100644 --- a/templates/components/modals/settings_modal.html +++ b/templates/components/modals/settings_modal.html @@ -445,6 +445,129 @@ + +
+

{{ t('settings.sections.proxySettings') }}

+ +
+
+
+ +
+
+ +
+
+
+ {{ t('settings.proxySettings.enableProxyHelp') }} +
+
+ + +
+

{{ t('settings.sections.misc') }}

@@ -466,6 +589,7 @@
+ \ No newline at end of file From a0c2d9b5ad9b9773c204196546dd9a9440ded3ca Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Fri, 12 Sep 2025 11:48:59 +0800 Subject: [PATCH 002/110] refactor: change logger info statements to debug level for improved logging granularity --- py/lora_manager.py | 4 ++-- py/services/metadata_service.py | 4 ++-- py/utils/usage_stats.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/py/lora_manager.py b/py/lora_manager.py index 96bae4de..4379a3e1 100644 --- a/py/lora_manager.py +++ b/py/lora_manager.py @@ -221,7 +221,7 @@ class LoraManager: name='post_init_tasks' ) - logger.info("LoRA Manager: All services initialized and background tasks scheduled") + logger.debug("LoRA Manager: All services initialized and background tasks scheduled") except Exception as e: logger.error(f"LoRA Manager: Error initializing services: {e}", exc_info=True) @@ -427,7 +427,7 @@ class LoraManager: f"removed {empty_folders_removed} empty folders and {invalid_hash_folders_removed} " f"folders for deleted/invalid models (total: {total_removed} removed)") else: - logger.info(f"Example images cleanup completed: checked {total_folders_checked} folders, " + logger.debug(f"Example images cleanup completed: checked {total_folders_checked} folders, " f"no cleanup needed") except Exception as e: diff --git a/py/services/metadata_service.py b/py/services/metadata_service.py index 86a94eaf..4c20b0b8 100644 --- a/py/services/metadata_service.py +++ b/py/services/metadata_service.py @@ -49,7 +49,7 @@ async def initialize_metadata_providers(): civitai_provider = CivitaiModelMetadataProvider(civitai_client) provider_manager.register_provider('civitai_api', civitai_provider) providers.append(('civitai_api', civitai_provider)) - logger.info("Civitai API metadata provider registered") + logger.debug("Civitai API metadata provider registered") except Exception as e: logger.error(f"Failed to initialize Civitai API metadata provider: {e}") @@ -68,7 +68,7 @@ async def initialize_metadata_providers(): # Only one provider available, set it as default provider_name, provider = providers[0] provider_manager.register_provider(provider_name, provider, is_default=True) - logger.info(f"Single metadata provider registered as default: {provider_name}") + logger.debug(f"Single metadata provider registered as default: {provider_name}") else: logger.warning("No metadata providers available - this may cause metadata lookup failures") diff --git a/py/utils/usage_stats.py b/py/utils/usage_stats.py index 08021964..1466ee21 100644 --- a/py/utils/usage_stats.py +++ b/py/utils/usage_stats.py @@ -62,7 +62,7 @@ class UsageStats: self._bg_task = asyncio.create_task(self._background_processor()) self._initialized = True - logger.info("Usage statistics tracker initialized") + logger.debug("Usage statistics tracker initialized") def _get_stats_file_path(self) -> str: """Get the path to the stats JSON file""" @@ -164,7 +164,7 @@ class UsageStats: if "last_save_time" in loaded_stats: self.stats["last_save_time"] = loaded_stats["last_save_time"] - logger.info(f"Loaded usage statistics from {self._stats_file_path}") + logger.debug(f"Loaded usage statistics from {self._stats_file_path}") except Exception as e: logger.error(f"Error loading usage statistics: {e}") From d5a280cf2bcfa1ef2c012c11b7d4986778b136f3 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Fri, 12 Sep 2025 14:01:52 +0800 Subject: [PATCH 003/110] fix: increase maxItems for autocomplete to improve user experience --- web/comfyui/autocomplete.js | 2 +- web/comfyui/utils.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/comfyui/autocomplete.js b/web/comfyui/autocomplete.js index 61fa1984..19b89466 100644 --- a/web/comfyui/autocomplete.js +++ b/web/comfyui/autocomplete.js @@ -7,7 +7,7 @@ class AutoComplete { this.inputElement = inputElement; this.modelType = modelType; this.options = { - maxItems: 15, + maxItems: 20, minChars: 1, debounceDelay: 200, showPreview: true, diff --git a/web/comfyui/utils.js b/web/comfyui/utils.js index 7c64621b..760cb46a 100644 --- a/web/comfyui/utils.js +++ b/web/comfyui/utils.js @@ -285,7 +285,7 @@ export function setupInputWidgetWithAutocomplete(node, inputWidget, originalCall // Initialize autocomplete on first callback if not already done if (!autocomplete && inputWidget.inputEl) { autocomplete = new AutoComplete(inputWidget.inputEl, 'loras', { - maxItems: 15, + maxItems: 20, minChars: 1, debounceDelay: 200 }); From 897787d17c415744bc89500d8cd5f890a2824077 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Fri, 12 Sep 2025 14:35:25 +0800 Subject: [PATCH 004/110] refactor(AutoComplete): simplify search term extraction and insertion logic --- py/services/base_model_service.py | 2 +- web/comfyui/autocomplete.js | 51 +++++++++++-------------------- 2 files changed, 19 insertions(+), 34 deletions(-) diff --git a/py/services/base_model_service.py b/py/services/base_model_service.py index 14a89a52..ed1fc930 100644 --- a/py/services/base_model_service.py +++ b/py/services/base_model_service.py @@ -363,7 +363,7 @@ class BaseModelService(ABC): from ..config import config return config.get_preview_static_url(preview_url) - return None + return '/loras_static/images/no-preview.png' async def get_model_civitai_url(self, model_name: str) -> Dict[str, Optional[str]]: """Get the Civitai URL for a model file""" diff --git a/web/comfyui/autocomplete.js b/web/comfyui/autocomplete.js index 19b89466..c8c33244 100644 --- a/web/comfyui/autocomplete.js +++ b/web/comfyui/autocomplete.js @@ -147,8 +147,8 @@ class AutoComplete { return ''; } - // Split on multiple delimiters: comma, space, '>' and other common separators - const segments = beforeCursor.split(/[,\s>]+/); + // Split on comma and '>' delimiters only (do not split on spaces) + const segments = beforeCursor.split(/[,\>]+/); // Return the last non-empty segment as search term const lastSegment = segments[segments.length - 1] || ''; @@ -381,7 +381,7 @@ class AutoComplete { async insertSelection(relativePath) { // Extract just the filename for LoRA name const fileName = relativePath.split(/[/\\]/).pop().replace(/\.(safetensors|ckpt|pt|bin)$/i, ''); - + // Get usage tips and extract strength let strength = 1.0; // Default strength try { @@ -389,7 +389,6 @@ class AutoComplete { if (response.ok) { const data = await response.json(); if (data.success && data.usage_tips) { - // Parse JSON string and extract strength try { const usageTips = JSON.parse(data.usage_tips); if (usageTips.strength && typeof usageTips.strength === 'number') { @@ -403,44 +402,30 @@ class AutoComplete { } catch (error) { console.warn('Failed to fetch usage tips:', error); } - + // Format the LoRA code with strength const loraCode = `, `; - + const currentValue = this.inputElement.value; const caretPos = this.getCaretPosition(); - const lastCommaIndex = currentValue.lastIndexOf(',', caretPos - 1); - - let newValue; - let newCaretPos; - - if (lastCommaIndex === -1) { - // No comma found before cursor, replace from start or current search term start - const searchTerm = this.getSearchTerm(currentValue.substring(0, caretPos)); - const searchStartPos = caretPos - searchTerm.length; - newValue = currentValue.substring(0, searchStartPos) + loraCode + currentValue.substring(caretPos); - newCaretPos = searchStartPos + loraCode.length; - } else { - // Replace text after last comma before cursor - const afterCommaPos = lastCommaIndex + 1; - // Skip whitespace after comma - let insertPos = afterCommaPos; - while (insertPos < caretPos && /\s/.test(currentValue[insertPos])) { - insertPos++; - } - - newValue = currentValue.substring(0, insertPos) + loraCode + currentValue.substring(caretPos); - newCaretPos = insertPos + loraCode.length; - } - + + // Use getSearchTerm to get the current search term before cursor + const beforeCursor = currentValue.substring(0, caretPos); + const searchTerm = this.getSearchTerm(beforeCursor); + const searchStartPos = caretPos - searchTerm.length; + + // Only replace the search term, not everything after the last comma + const newValue = currentValue.substring(0, searchStartPos) + loraCode + currentValue.substring(caretPos); + const newCaretPos = searchStartPos + loraCode.length; + this.inputElement.value = newValue; - + // Trigger input event to notify about the change const event = new Event('input', { bubbles: true }); this.inputElement.dispatchEvent(event); - + this.hide(); - + // Focus back to input and position cursor this.inputElement.focus(); this.inputElement.setSelectionRange(newCaretPos, newCaretPos); From 00b77581fca9c323ed42ac8743ec931db10fd73a Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Fri, 12 Sep 2025 15:20:34 +0800 Subject: [PATCH 005/110] refactor(Downloader): change logger info statements to debug level for proxy usage --- py/services/downloader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/services/downloader.py b/py/services/downloader.py index 4a26c38b..dd2c8c32 100644 --- a/py/services/downloader.py +++ b/py/services/downloader.py @@ -108,7 +108,7 @@ class Downloader: else: proxy_url = f"{proxy_type}://{proxy_host}:{proxy_port}" - logger.info(f"Using app-level proxy: {proxy_type}://{proxy_host}:{proxy_port}") + logger.debug(f"Using app-level proxy: {proxy_type}://{proxy_host}:{proxy_port}") logger.debug("Proxy mode: app-level proxy is active.") else: logger.debug("Proxy mode: system-level proxy (trust_env) will be used if configured in environment.") From d05076d258f42a068b24db8938c726014ba9ba4a Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Fri, 12 Sep 2025 21:13:15 +0800 Subject: [PATCH 006/110] feat: add CivArchive metadata provider and support for optional source parameter in downloads --- py/routes/base_model_routes.py | 5 + py/services/download_manager.py | 33 +++--- py/services/metadata_service.py | 11 +- py/services/model_metadata_provider.py | 138 +++++++++++++++++++++++++ py/utils/routes_common.py | 4 +- requirements.txt | 1 + 6 files changed, 173 insertions(+), 19 deletions(-) diff --git a/py/routes/base_model_routes.py b/py/routes/base_model_routes.py index be0f2695..a7970f0b 100644 --- a/py/routes/base_model_routes.py +++ b/py/routes/base_model_routes.py @@ -523,6 +523,7 @@ class BaseModelRoutes(ABC): model_version_id = request.query.get('model_version_id') download_id = request.query.get('download_id') use_default_paths = request.query.get('use_default_paths', 'false').lower() == 'true' + source = request.query.get('source') # Optional source parameter # Create a data dictionary that mimics what would be received from a POST request data = { @@ -538,6 +539,10 @@ class BaseModelRoutes(ABC): data['use_default_paths'] = use_default_paths + # Add source parameter if provided + if source: + data['source'] = source + # Create a mock request object with the data future = asyncio.get_event_loop().create_future() future.set_result(data) diff --git a/py/services/download_manager.py b/py/services/download_manager.py index 9f090b20..6638d7d2 100644 --- a/py/services/download_manager.py +++ b/py/services/download_manager.py @@ -36,17 +36,10 @@ class DownloadManager: return self._initialized = True - self._civitai_client = None # Will be lazily initialized # Add download management self._active_downloads = OrderedDict() # download_id -> download_info self._download_semaphore = asyncio.Semaphore(5) # Limit concurrent downloads self._download_tasks = {} # download_id -> asyncio.Task - - async def _get_civitai_client(self): - """Lazily initialize CivitaiClient from registry""" - if self._civitai_client is None: - self._civitai_client = await ServiceRegistry.get_civitai_client() - return self._civitai_client async def _get_lora_scanner(self): """Get the lora scanner from registry""" @@ -59,7 +52,7 @@ class DownloadManager: async def download_from_civitai(self, model_id: int = None, model_version_id: int = None, save_dir: str = None, relative_path: str = '', progress_callback=None, use_default_paths: bool = False, - download_id: str = None) -> Dict: + download_id: str = None, source: str = None) -> Dict: """Download model from Civitai with task tracking and concurrency control Args: @@ -70,6 +63,7 @@ class DownloadManager: progress_callback: Callback function for progress updates use_default_paths: Flag to use default paths download_id: Unique identifier for this download task + source: Optional source parameter to specify metadata provider Returns: Dict with download result @@ -93,7 +87,7 @@ class DownloadManager: download_task = asyncio.create_task( self._download_with_semaphore( task_id, model_id, model_version_id, save_dir, - relative_path, progress_callback, use_default_paths + relative_path, progress_callback, use_default_paths, source ) ) @@ -114,7 +108,8 @@ class DownloadManager: async def _download_with_semaphore(self, task_id: str, model_id: int, model_version_id: int, save_dir: str, relative_path: str, - progress_callback=None, use_default_paths: bool = False): + progress_callback=None, use_default_paths: bool = False, + source: str = None): """Execute download with semaphore to limit concurrency""" # Update status to waiting if task_id in self._active_downloads: @@ -144,7 +139,7 @@ class DownloadManager: result = await self._execute_original_download( model_id, model_version_id, save_dir, relative_path, tracking_callback, use_default_paths, - task_id + task_id, source ) # Update status based on result @@ -179,7 +174,7 @@ class DownloadManager: async def _execute_original_download(self, model_id, model_version_id, save_dir, relative_path, progress_callback, use_default_paths, - download_id=None): + download_id=None, source=None): """Wrapper for original download_from_civitai implementation""" try: # Check if model version already exists in library @@ -201,8 +196,12 @@ class DownloadManager: if await embedding_scanner.check_model_version_exists(model_version_id): return {'success': False, 'error': 'Model version already exists in embedding library'} - # Get metadata provider instead of civitai client directly - metadata_provider = await get_default_metadata_provider() + # Get metadata provider based on source parameter + if source == 'civarchive': + from .metadata_service import get_metadata_provider + metadata_provider = await get_metadata_provider('civarchive') + else: + metadata_provider = await get_default_metadata_provider() # Get version info based on the provided identifier version_info = await metadata_provider.get_model_version(model_id, model_version_id) @@ -396,8 +395,6 @@ class DownloadManager: model_type: str = "lora", download_id: str = None) -> Dict: """Execute the actual download process including preview images and model files""" try: - civitai_client = await self._get_civitai_client() - # Extract original filename details original_filename = os.path.basename(metadata.file_path) base_name, extension = os.path.splitext(original_filename) @@ -504,11 +501,13 @@ class DownloadManager: # Download model file with progress tracking using downloader downloader = await get_downloader() + # Determine if the download URL is from Civitai + use_auth = download_url.startswith("https://civitai.com/api/download/") success, result = await downloader.download_file( download_url, save_path, # Use full path instead of separate dir and filename progress_callback=lambda p: self._handle_download_progress(p, progress_callback), - use_auth=True # Model downloads need authentication + use_auth=use_auth # Only use authentication for Civitai downloads ) if not success: diff --git a/py/services/metadata_service.py b/py/services/metadata_service.py index 4c20b0b8..6a4f9dd8 100644 --- a/py/services/metadata_service.py +++ b/py/services/metadata_service.py @@ -52,7 +52,16 @@ async def initialize_metadata_providers(): logger.debug("Civitai API metadata provider registered") except Exception as e: logger.error(f"Failed to initialize Civitai API metadata provider: {e}") - + + # Register CivArchive provider, but do NOT add to fallback providers + try: + from .model_metadata_provider import CivArchiveModelMetadataProvider + civarchive_provider = CivArchiveModelMetadataProvider() + provider_manager.register_provider('civarchive', civarchive_provider) + logger.debug("CivArchive metadata provider registered (not included in fallback)") + except Exception as e: + logger.error(f"Failed to initialize CivArchive metadata provider: {e}") + # Set up fallback provider based on available providers if len(providers) > 1: # Always use Civitai API first, then Archive DB diff --git a/py/services/model_metadata_provider.py b/py/services/model_metadata_provider.py index 9f54a2e7..b02d0c0e 100644 --- a/py/services/model_metadata_provider.py +++ b/py/services/model_metadata_provider.py @@ -2,6 +2,8 @@ from abc import ABC, abstractmethod import json import aiosqlite import logging +import aiohttp +from bs4 import BeautifulSoup from typing import Optional, Dict, List, Tuple, Any logger = logging.getLogger(__name__) @@ -55,6 +57,142 @@ class CivitaiModelMetadataProvider(ModelMetadataProvider): async def get_model_metadata(self, model_id: str) -> Tuple[Optional[Dict], int]: return await self.client.get_model_metadata(model_id) +class CivArchiveModelMetadataProvider(ModelMetadataProvider): + """Provider that uses CivArchive HTML page parsing for metadata""" + + def __init__(self, session: aiohttp.ClientSession = None): + self.session = session + self._own_session = session is None + + async def _get_session(self): + """Get or create HTTP session""" + if self.session is None: + self.session = aiohttp.ClientSession() + return self.session + + async def close(self): + """Close HTTP session if we own it""" + if self._own_session and self.session: + await self.session.close() + self.session = None + + async def get_model_by_hash(self, model_hash: str) -> Optional[Dict]: + """Not supported by CivArchive provider""" + return None + + async def get_model_versions(self, model_id: str) -> Optional[Dict]: + """Not supported by CivArchive provider""" + return None + + async def get_model_version(self, model_id: int = None, version_id: int = None) -> Optional[Dict]: + """Get specific model version by parsing CivArchive HTML page""" + if model_id is None or version_id is None: + return None + + try: + # Construct CivArchive URL + url = f"https://civarchive.com/models/{model_id}?modelVersionId={version_id}" + + session = await self._get_session() + async with session.get(url) as response: + if response.status != 200: + return None + + html_content = await response.text() + + # Parse HTML to extract JSON data + soup = BeautifulSoup(html_content, 'html.parser') + script_tag = soup.find('script', {'id': '__NEXT_DATA__', 'type': 'application/json'}) + + if not script_tag: + return None + + # Parse JSON content + json_data = json.loads(script_tag.string) + model_data = json_data.get('props', {}).get('pageProps', {}).get('model') + + if not model_data or 'version' not in model_data: + return None + + # Extract version data as base + version = model_data['version'].copy() + + # Restructure stats + if 'downloadCount' in version and 'ratingCount' in version and 'rating' in version: + version['stats'] = { + 'downloadCount': version.pop('downloadCount'), + 'ratingCount': version.pop('ratingCount'), + 'rating': version.pop('rating') + } + + # Rename trigger to trainedWords + if 'trigger' in version: + version['trainedWords'] = version.pop('trigger') + + # Transform files data to expected format + if 'files' in version: + transformed_files = [] + for file_data in version['files']: + # Find first available mirror (deletedAt is null) + available_mirror = None + for mirror in file_data.get('mirrors', []): + if mirror.get('deletedAt') is None: + available_mirror = mirror + break + + # Create transformed file entry + transformed_file = { + 'id': file_data.get('id'), + 'sizeKB': file_data.get('sizeKB'), + 'name': available_mirror.get('filename', file_data.get('name')) if available_mirror else file_data.get('name'), + 'type': file_data.get('type'), + 'downloadUrl': available_mirror.get('url') if available_mirror else None, + 'primary': True, + 'mirrors': file_data.get('mirrors', []) + } + + # Transform hash format + if 'sha256' in file_data: + transformed_file['hashes'] = { + 'SHA256': file_data['sha256'].upper() + } + + transformed_files.append(transformed_file) + + version['files'] = transformed_files + + # Add model information + version['model'] = { + 'name': model_data.get('name'), + 'type': model_data.get('type'), + 'nsfw': model_data.get('is_nsfw', False), + 'description': model_data.get('description'), + 'tags': model_data.get('tags', []) + } + + version['creator'] = { + 'username': model_data.get('username'), + 'image': '' + } + + # Add source identifier + version['source'] = 'civarchive' + version['is_deleted'] = json_data.get('query', {}).get('is_deleted', False) + + return version + + except Exception as e: + logger.error(f"Error fetching CivArchive model version {model_id}/{version_id}: {e}") + return None + + async def get_model_version_info(self, version_id: str) -> Tuple[Optional[Dict], Optional[str]]: + """Not supported by CivArchive provider - requires both model_id and version_id""" + return None, "CivArchive provider requires both model_id and version_id" + + async def get_model_metadata(self, model_id: str) -> Tuple[Optional[Dict], int]: + """Not supported by CivArchive provider""" + return None, 404 + class SQLiteModelMetadataProvider(ModelMetadataProvider): """Provider that uses SQLite database for metadata""" diff --git a/py/utils/routes_common.py b/py/utils/routes_common.py index 80765f7b..3be2677f 100644 --- a/py/utils/routes_common.py +++ b/py/utils/routes_common.py @@ -632,6 +632,7 @@ class ModelRouteUtils: }, status=400) use_default_paths = data.get('use_default_paths', False) + source = data.get('source') # Optional source parameter # Pass the download_id to download_from_civitai result = await download_manager.download_from_civitai( @@ -641,7 +642,8 @@ class ModelRouteUtils: relative_path=data.get('relative_path', ''), use_default_paths=use_default_paths, progress_callback=progress_callback, - download_id=download_id # Pass download_id explicitly + download_id=download_id, # Pass download_id explicitly + source=source # Pass source parameter ) # Include download_id in the response diff --git a/requirements.txt b/requirements.txt index 9e280c64..4051dc74 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,4 @@ numpy natsort GitPython aiosqlite +beautifulsoup4 From 125fdecd6193dd98a083a7663bed520402cdb3b2 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sat, 13 Sep 2025 09:03:34 +0800 Subject: [PATCH 007/110] fix: handle missing download URL for primary file in metadata --- py/services/download_manager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/py/services/download_manager.py b/py/services/download_manager.py index 6638d7d2..26f3f97d 100644 --- a/py/services/download_manager.py +++ b/py/services/download_manager.py @@ -294,6 +294,8 @@ class DownloadManager: file_info = next((f for f in version_info.get('files', []) if f.get('primary')), None) if not file_info: return {'success': False, 'error': 'No primary file found in metadata'} + if not file_info.get('downloadUrl'): + return {'success': False, 'error': 'No download URL found for primary file'} # 3. Prepare download file_name = file_info['name'] From 13f13eb095086e981c824ea56b795a0657732466 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sat, 13 Sep 2025 09:20:55 +0800 Subject: [PATCH 008/110] fix: update preview versions keys for consistency in state management, fixes #406 --- static/js/components/shared/ModelCard.js | 8 -------- static/js/state/index.js | 6 +++--- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/static/js/components/shared/ModelCard.js b/static/js/components/shared/ModelCard.js index 16bdf45d..aa3208a0 100644 --- a/static/js/components/shared/ModelCard.js +++ b/static/js/components/shared/ModelCard.js @@ -216,13 +216,6 @@ function handleCardClick(card, modelType) { } async function showModelModalFromCard(card, modelType) { - // Get the appropriate preview versions map - const previewVersionsKey = modelType; - const previewVersions = state.pages[previewVersionsKey]?.previewVersions || new Map(); - const version = previewVersions.get(card.dataset.filepath); - const previewUrl = card.dataset.preview_url || '/loras_static/images/no-preview.png'; - const versionedPreviewUrl = version ? `${previewUrl}?t=${version}` : previewUrl; - // Create model metadata object const modelMeta = { sha256: card.dataset.sha256, @@ -235,7 +228,6 @@ async function showModelModalFromCard(card, modelType) { from_civitai: card.dataset.from_civitai === 'true', base_model: card.dataset.base_model, notes: card.dataset.notes || '', - preview_url: versionedPreviewUrl, favorite: card.dataset.favorite === 'true', // Parse civitai metadata from the card's dataset civitai: JSON.parse(card.dataset.meta || '{}'), diff --git a/static/js/state/index.js b/static/js/state/index.js index 65d5619f..71f6b859 100644 --- a/static/js/state/index.js +++ b/static/js/state/index.js @@ -10,9 +10,9 @@ const savedSettings = getStorageItem('settings', { }); // Load preview versions from localStorage for each model type -const loraPreviewVersions = getMapFromStorage('lora_preview_versions'); -const checkpointPreviewVersions = getMapFromStorage('checkpoint_preview_versions'); -const embeddingPreviewVersions = getMapFromStorage('embedding_preview_versions'); +const loraPreviewVersions = getMapFromStorage('loras_preview_versions'); +const checkpointPreviewVersions = getMapFromStorage('checkpoints_preview_versions'); +const embeddingPreviewVersions = getMapFromStorage('embeddings_preview_versions'); export const state = { // Global state From 1a76f74482b2a066c618b26677b62c6e387ac30d Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sat, 13 Sep 2025 13:07:25 +0800 Subject: [PATCH 009/110] refactor(BaseModelRoutes): temporary comment out model description and creator checks --- py/routes/base_model_routes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/routes/base_model_routes.py b/py/routes/base_model_routes.py index a7970f0b..aea644e3 100644 --- a/py/routes/base_model_routes.py +++ b/py/routes/base_model_routes.py @@ -630,8 +630,8 @@ class BaseModelRoutes(ABC): not model.get('civitai') or not model['civitai'].get('id') # or not model.get('tags') # Skipping tag cause it could be empty legitimately - or not model.get('modelDescription') - or not (model.get('civitai') and model['civitai'].get('creator')) + # or not model.get('modelDescription') + # or not (model.get('civitai') and model['civitai'].get('creator')) ) and ( (enable_metadata_archive_db) From e5339c178a3f470c8387c767a85dc05bb688f3f1 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sat, 13 Sep 2025 16:36:01 +0800 Subject: [PATCH 010/110] fix: increase max-height for expanded sidebar tree children to improve visibility, fixes #403 --- static/css/components/sidebar.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/css/components/sidebar.css b/static/css/components/sidebar.css index 008c16a5..c0af436d 100644 --- a/static/css/components/sidebar.css +++ b/static/css/components/sidebar.css @@ -233,7 +233,7 @@ } .sidebar-tree-children.expanded { - max-height: 9999px; + max-height: 50000px; } .sidebar-tree-children .sidebar-tree-node-content { From 6b606a5cc8114efbbc5de099506bd3f152d53e83 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sat, 13 Sep 2025 20:04:41 +0800 Subject: [PATCH 011/110] refactor(CivArchiveModelMetadataProvider): remove session management and use downloader for HTTP requests --- py/services/model_metadata_provider.py | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/py/services/model_metadata_provider.py b/py/services/model_metadata_provider.py index b02d0c0e..9957b849 100644 --- a/py/services/model_metadata_provider.py +++ b/py/services/model_metadata_provider.py @@ -4,7 +4,8 @@ import aiosqlite import logging import aiohttp from bs4 import BeautifulSoup -from typing import Optional, Dict, List, Tuple, Any +from typing import Optional, Dict, Tuple +from .downloader import get_downloader logger = logging.getLogger(__name__) @@ -60,22 +61,6 @@ class CivitaiModelMetadataProvider(ModelMetadataProvider): class CivArchiveModelMetadataProvider(ModelMetadataProvider): """Provider that uses CivArchive HTML page parsing for metadata""" - def __init__(self, session: aiohttp.ClientSession = None): - self.session = session - self._own_session = session is None - - async def _get_session(self): - """Get or create HTTP session""" - if self.session is None: - self.session = aiohttp.ClientSession() - return self.session - - async def close(self): - """Close HTTP session if we own it""" - if self._own_session and self.session: - await self.session.close() - self.session = None - async def get_model_by_hash(self, model_hash: str) -> Optional[Dict]: """Not supported by CivArchive provider""" return None @@ -92,8 +77,9 @@ class CivArchiveModelMetadataProvider(ModelMetadataProvider): try: # Construct CivArchive URL url = f"https://civarchive.com/models/{model_id}?modelVersionId={version_id}" - - session = await self._get_session() + + downloader = await get_downloader() + session = await downloader.session async with session.get(url) as response: if response.status != 200: return None From 9366d3d2d0c4f543fe66c56097e9f9fbdfa3630e Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sun, 14 Sep 2025 22:57:17 +0800 Subject: [PATCH 012/110] feat: add API endpoint for fetching application settings and update frontend settings management --- py/routes/misc_routes.py | 42 +++ py/services/settings_manager.py | 1 - settings.json.example | 1 - static/js/core.js | 5 + static/js/managers/SettingsManager.js | 498 ++++++++++++-------------- static/js/state/index.js | 10 +- 6 files changed, 291 insertions(+), 266 deletions(-) diff --git a/py/routes/misc_routes.py b/py/routes/misc_routes.py index 013923b7..494eca9b 100644 --- a/py/routes/misc_routes.py +++ b/py/routes/misc_routes.py @@ -88,6 +88,7 @@ class MiscRoutes: @staticmethod def setup_routes(app): """Register miscellaneous routes""" + app.router.add_get('/api/settings', MiscRoutes.get_settings) app.router.add_post('/api/settings', MiscRoutes.update_settings) app.router.add_get('/api/health-check', lambda request: web.json_response({'status': 'ok'})) @@ -119,6 +120,47 @@ class MiscRoutes: app.router.add_post('/api/remove-metadata-archive', MiscRoutes.remove_metadata_archive) app.router.add_get('/api/metadata-archive-status', MiscRoutes.get_metadata_archive_status) + @staticmethod + async def get_settings(request): + """Get application settings that should be synced to frontend""" + try: + # Define keys that should be synced from backend to frontend + sync_keys = [ + 'civitai_api_key', + 'default_lora_root', + 'default_checkpoint_root', + 'default_embedding_root', + 'base_model_path_mappings', + 'download_path_templates', + 'enable_metadata_archive_db', + 'language', + 'proxy_enabled', + 'proxy_type', + 'proxy_host', + 'proxy_port', + 'proxy_username', + 'proxy_password' + ] + + # Build response with only the keys that should be synced + response_data = {} + for key in sync_keys: + value = settings.get(key) + if value is not None: + response_data[key] = value + + return web.json_response({ + 'success': True, + 'settings': response_data + }) + + except Exception as e: + logger.error(f"Error getting settings: {e}", exc_info=True) + return web.json_response({ + 'success': False, + 'error': str(e) + }, status=500) + @staticmethod async def update_settings(request): """Update application settings""" diff --git a/py/services/settings_manager.py b/py/services/settings_manager.py index 5a95e58e..ec71104e 100644 --- a/py/services/settings_manager.py +++ b/py/services/settings_manager.py @@ -80,7 +80,6 @@ class SettingsManager: """Return default settings""" return { "civitai_api_key": "", - "show_only_sfw": False, "language": "en", "enable_metadata_archive_db": False, # Enable metadata archive database "proxy_enabled": False, # Enable app-level proxy diff --git a/settings.json.example b/settings.json.example index 0765577b..673aa76d 100644 --- a/settings.json.example +++ b/settings.json.example @@ -1,6 +1,5 @@ { "civitai_api_key": "your_civitai_api_key_here", - "show_only_sfw": false, "folder_paths": { "loras": [ "C:/path/to/your/loras_folder", diff --git a/static/js/core.js b/static/js/core.js index d7daa0c5..779f3094 100644 --- a/static/js/core.js +++ b/static/js/core.js @@ -38,6 +38,11 @@ export class AppCore { console.log(`AppCore: Language set: ${i18n.getCurrentLocale()}`); + // Initialize settings manager and wait for it to sync from backend + console.log('AppCore: Initializing settings...'); + await settingsManager.waitForInitialization(); + console.log('AppCore: Settings initialized'); + // Initialize managers state.loadingManager = new LoadingManager(); modalManager.initialize(); diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index 96e3064d..0767baab 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -10,122 +10,194 @@ export class SettingsManager { constructor() { this.initialized = false; this.isOpen = false; + this.initializationPromise = null; // Add initialization to sync with modal state this.currentPage = document.body.dataset.page || 'loras'; - // Ensure settings are loaded from localStorage - this.loadSettingsFromStorage(); - - // Sync settings to backend if needed - this.syncSettingsToBackendIfNeeded(); + // Start initialization but don't await here to avoid blocking constructor + this.initializationPromise = this.initializeSettings(); this.initialize(); } - loadSettingsFromStorage() { + // Add method to wait for initialization to complete + async waitForInitialization() { + if (this.initializationPromise) { + await this.initializationPromise; + } + } + + async initializeSettings() { + // Load frontend-only settings from localStorage + this.loadFrontendSettingsFromStorage(); + + // Sync settings from backend to frontend + await this.syncSettingsFromBackend(); + } + + loadFrontendSettingsFromStorage() { // Get saved settings from localStorage const savedSettings = getStorageItem('settings'); - // Migrate legacy default_loras_root to default_lora_root if present - if (savedSettings && savedSettings.default_loras_root && !savedSettings.default_lora_root) { - savedSettings.default_lora_root = savedSettings.default_loras_root; - delete savedSettings.default_loras_root; - setStorageItem('settings', savedSettings); - } + // Frontend-only settings that should be stored in localStorage + const frontendOnlyKeys = [ + 'blurMatureContent', + 'show_only_sfw', + 'autoplayOnHover', + 'displayDensity', + 'cardInfoDisplay', + 'optimizeExampleImages', + 'autoDownloadExampleImages', + 'includeTriggerWords' + ]; - // Apply saved settings to state if available + // Apply saved frontend settings to state if available if (savedSettings) { - state.global.settings = { ...state.global.settings, ...savedSettings }; + const frontendSettings = {}; + frontendOnlyKeys.forEach(key => { + if (savedSettings[key] !== undefined) { + frontendSettings[key] = savedSettings[key]; + } + }); + state.global.settings = { ...state.global.settings, ...frontendSettings }; } - // Initialize default values for new settings if they don't exist - if (state.global.settings.compactMode === undefined) { - state.global.settings.compactMode = false; + // Initialize default values for frontend settings if they don't exist + if (state.global.settings.blurMatureContent === undefined) { + state.global.settings.blurMatureContent = true; + } + + if (state.global.settings.show_only_sfw === undefined) { + state.global.settings.show_only_sfw = false; + } + + if (state.global.settings.autoplayOnHover === undefined) { + state.global.settings.autoplayOnHover = false; } - // Set default for optimizeExampleImages if undefined if (state.global.settings.optimizeExampleImages === undefined) { state.global.settings.optimizeExampleImages = true; } - // Set default for autoDownloadExampleImages if undefined if (state.global.settings.autoDownloadExampleImages === undefined) { state.global.settings.autoDownloadExampleImages = true; } - // Set default for cardInfoDisplay if undefined if (state.global.settings.cardInfoDisplay === undefined) { state.global.settings.cardInfoDisplay = 'always'; } - // Set default for defaultCheckpointRoot if undefined - if (state.global.settings.default_checkpoint_root === undefined) { - state.global.settings.default_checkpoint_root = ''; - } - - // Convert old boolean compactMode to new displayDensity string - if (typeof state.global.settings.displayDensity === 'undefined') { + if (state.global.settings.displayDensity === undefined) { + // Migrate legacy compactMode if it exists if (state.global.settings.compactMode === true) { state.global.settings.displayDensity = 'compact'; } else { state.global.settings.displayDensity = 'default'; } - // We can delete the old setting, but keeping it for backwards compatibility } - // Migrate legacy download_path_template to new structure - if (state.global.settings.download_path_template && !state.global.settings.download_path_templates) { - const legacyTemplate = state.global.settings.download_path_template; - state.global.settings.download_path_templates = { - lora: legacyTemplate, - checkpoint: legacyTemplate, - embedding: legacyTemplate - }; - delete state.global.settings.download_path_template; - setStorageItem('settings', state.global.settings); - } - - // Set default for download path templates if undefined - if (state.global.settings.download_path_templates === undefined) { - state.global.settings.download_path_templates = { ...DEFAULT_PATH_TEMPLATES }; - } - - // Ensure all model types have templates - Object.keys(DEFAULT_PATH_TEMPLATES).forEach(modelType => { - if (typeof state.global.settings.download_path_templates[modelType] === 'undefined') { - state.global.settings.download_path_templates[modelType] = DEFAULT_PATH_TEMPLATES[modelType]; - } - }); - - // Set default for base model path mappings if undefined - if (state.global.settings.base_model_path_mappings === undefined) { - state.global.settings.base_model_path_mappings = {}; - } - - // Set default for defaultEmbeddingRoot if undefined - if (state.global.settings.default_embedding_root === undefined) { - state.global.settings.default_embedding_root = ''; - } - - // Set default for includeTriggerWords if undefined if (state.global.settings.includeTriggerWords === undefined) { state.global.settings.includeTriggerWords = false; } + + // Save updated frontend settings to localStorage + this.saveFrontendSettingsToStorage(); } - async syncSettingsToBackendIfNeeded() { - // Get local settings from storage - const localSettings = getStorageItem('settings') || {}; + async syncSettingsFromBackend() { + try { + const response = await fetch('/api/settings'); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + if (data.success && data.settings) { + // Merge backend settings with current state + state.global.settings = { ...state.global.settings, ...data.settings }; + + // Set defaults for backend settings if they're null/undefined + this.setBackendSettingDefaults(); + + console.log('Settings synced from backend'); + } else { + console.error('Failed to sync settings from backend:', data.error); + } + } catch (error) { + console.error('Failed to sync settings from backend:', error); + // Set defaults if backend sync fails + this.setBackendSettingDefaults(); + } + } - // Fields that need to be synced to backend - const fieldsToSync = [ + setBackendSettingDefaults() { + // Set defaults for backend settings + const backendDefaults = { + civitai_api_key: '', + default_lora_root: '', + default_checkpoint_root: '', + default_embedding_root: '', + base_model_path_mappings: {}, + download_path_templates: { ...DEFAULT_PATH_TEMPLATES }, + enable_metadata_archive_db: false, + language: 'en', + proxy_enabled: false, + proxy_type: 'http', + proxy_host: '', + proxy_port: '', + proxy_username: '', + proxy_password: '' + }; + + Object.keys(backendDefaults).forEach(key => { + if (state.global.settings[key] === undefined || state.global.settings[key] === null) { + state.global.settings[key] = backendDefaults[key]; + } + }); + + // Ensure all model types have templates + Object.keys(DEFAULT_PATH_TEMPLATES).forEach(modelType => { + if (!state.global.settings.download_path_templates[modelType]) { + state.global.settings.download_path_templates[modelType] = DEFAULT_PATH_TEMPLATES[modelType]; + } + }); + } + + saveFrontendSettingsToStorage() { + // Save only frontend-specific settings to localStorage + const frontendOnlyKeys = [ + 'blurMatureContent', + 'show_only_sfw', + 'autoplayOnHover', + 'displayDensity', + 'cardInfoDisplay', + 'optimizeExampleImages', + 'autoDownloadExampleImages', + 'includeTriggerWords' + ]; + + const frontendSettings = {}; + frontendOnlyKeys.forEach(key => { + if (state.global.settings[key] !== undefined) { + frontendSettings[key] = state.global.settings[key]; + } + }); + + setStorageItem('settings', frontendSettings); + } + + // Helper method to determine if a setting should be saved to backend + isBackendSetting(settingKey) { + const backendKeys = [ 'civitai_api_key', 'default_lora_root', - 'default_checkpoint_root', + 'default_checkpoint_root', 'default_embedding_root', 'base_model_path_mappings', 'download_path_templates', + 'enable_metadata_archive_db', + 'language', 'proxy_enabled', 'proxy_type', 'proxy_host', @@ -133,30 +205,38 @@ export class SettingsManager { 'proxy_username', 'proxy_password' ]; + return backendKeys.includes(settingKey); + } - // Build payload for syncing - const payload = {}; + // Helper method to save setting based on whether it's frontend or backend + async saveSetting(settingKey, value) { + // Update state + state.global.settings[settingKey] = value; - fieldsToSync.forEach(key => { - if (localSettings[key] !== undefined) { - payload[key] = localSettings[key]; - } - }); - - // Only send request if there is something to sync - if (Object.keys(payload).length > 0) { + if (this.isBackendSetting(settingKey)) { + // Save to backend try { - await fetch('/api/settings', { + const payload = {}; + payload[settingKey] = value; + + const response = await fetch('/api/settings', { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { + 'Content-Type': 'application/json', + }, body: JSON.stringify(payload) }); - // Log success to console - console.log('Settings synced to backend'); - } catch (e) { - // Log error to console - console.error('Failed to sync settings to backend:', e); + + if (!response.ok) { + throw new Error('Failed to save setting to backend'); + } + } catch (error) { + console.error(`Failed to save backend setting ${settingKey}:`, error); + throw error; } + } else { + // Save frontend settings to localStorage + this.saveFrontendSettingsToStorage(); } } @@ -603,23 +683,8 @@ export class SettingsManager { async saveBaseModelMappings() { try { - // Save to localStorage - setStorageItem('settings', state.global.settings); - - // Save to backend - const response = await fetch('/api/settings', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - base_model_path_mappings: state.global.settings.base_model_path_mappings - }) - }); - - if (!response.ok) { - throw new Error('Failed to save base model mappings'); - } + // Save to backend using universal save method + await this.saveSetting('base_model_path_mappings', state.global.settings.base_model_path_mappings); // Show success toast const mappingCount = Object.keys(state.global.settings.base_model_path_mappings).length; @@ -793,23 +858,8 @@ export class SettingsManager { async saveDownloadPathTemplates() { try { - // Save to localStorage - setStorageItem('settings', state.global.settings); - - // Save to backend - const response = await fetch('/api/settings', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - download_path_templates: state.global.settings.download_path_templates - }) - }); - - if (!response.ok) { - throw new Error('Failed to save download path templates'); - } + // Save to backend using universal save method + await this.saveSetting('download_path_templates', state.global.settings.download_path_templates); showToast('toast.settings.downloadTemplatesUpdated', {}, 'success'); @@ -834,61 +884,40 @@ export class SettingsManager { const value = element.checked; - // Update frontend state - if (settingKey === 'blur_mature_content') { - state.global.settings.blurMatureContent = value; - } else if (settingKey === 'show_only_sfw') { - state.global.settings.show_only_sfw = value; - } else if (settingKey === 'autoplay_on_hover') { - state.global.settings.autoplayOnHover = value; - } else if (settingKey === 'optimize_example_images') { - state.global.settings.optimizeExampleImages = value; - } else if (settingKey === 'auto_download_example_images') { - state.global.settings.autoDownloadExampleImages = value; - } else if (settingKey === 'compact_mode') { - state.global.settings.compactMode = value; - } else if (settingKey === 'include_trigger_words') { - state.global.settings.includeTriggerWords = value; - } else if (settingKey === 'enable_metadata_archive_db') { - state.global.settings.enable_metadata_archive_db = value; - } else if (settingKey === 'proxy_enabled') { - state.global.settings.proxy_enabled = value; - - // Toggle visibility of proxy settings group - const proxySettingsGroup = document.getElementById('proxySettingsGroup'); - if (proxySettingsGroup) { - proxySettingsGroup.style.display = value ? 'block' : 'none'; - } - } else { - // For any other settings that might be added in the future - state.global.settings[settingKey] = value; - } - - // Save to localStorage - setStorageItem('settings', state.global.settings); - try { - // For backend settings, make API call - if (['show_only_sfw', 'enable_metadata_archive_db', 'proxy_enabled'].includes(settingKey)) { - const payload = {}; - payload[settingKey] = value; + // Update frontend state with mapped keys + if (settingKey === 'blur_mature_content') { + await this.saveSetting('blurMatureContent', value); + } else if (settingKey === 'show_only_sfw') { + await this.saveSetting('show_only_sfw', value); + } else if (settingKey === 'autoplay_on_hover') { + await this.saveSetting('autoplayOnHover', value); + } else if (settingKey === 'optimize_example_images') { + await this.saveSetting('optimizeExampleImages', value); + } else if (settingKey === 'auto_download_example_images') { + await this.saveSetting('autoDownloadExampleImages', value); + } else if (settingKey === 'compact_mode') { + await this.saveSetting('compactMode', value); + } else if (settingKey === 'include_trigger_words') { + await this.saveSetting('includeTriggerWords', value); + } else if (settingKey === 'enable_metadata_archive_db') { + await this.saveSetting('enable_metadata_archive_db', value); + } else if (settingKey === 'proxy_enabled') { + await this.saveSetting('proxy_enabled', value); - const response = await fetch('/api/settings', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(payload) - }); - - if (!response.ok) { - throw new Error('Failed to save setting'); - } - - // Refresh metadata archive status when enable setting changes - if (settingKey === 'enable_metadata_archive_db') { - await this.updateMetadataArchiveStatus(); + // Toggle visibility of proxy settings group + const proxySettingsGroup = document.getElementById('proxySettingsGroup'); + if (proxySettingsGroup) { + proxySettingsGroup.style.display = value ? 'block' : 'none'; } + } else { + // For any other settings that might be added in the future + await this.saveSetting(settingKey, value); + } + + // Refresh metadata archive status when enable setting changes + if (settingKey === 'enable_metadata_archive_db') { + await this.updateMetadataArchiveStatus(); } showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success'); @@ -933,55 +962,31 @@ export class SettingsManager { const value = element.value; - // Update frontend state - if (settingKey === 'default_lora_root') { - state.global.settings.default_lora_root = value; - } else if (settingKey === 'default_checkpoint_root') { - state.global.settings.default_checkpoint_root = value; - } else if (settingKey === 'default_embedding_root') { - state.global.settings.default_embedding_root = value; - } else if (settingKey === 'display_density') { - state.global.settings.displayDensity = value; - - // Also update compactMode for backwards compatibility - state.global.settings.compactMode = (value !== 'default'); - } else if (settingKey === 'card_info_display') { - state.global.settings.cardInfoDisplay = value; - } else if (settingKey === 'proxy_type') { - state.global.settings.proxy_type = value; - } else { - // For any other settings that might be added in the future - state.global.settings[settingKey] = value; - } - - // Save to localStorage - setStorageItem('settings', state.global.settings); - try { - // For backend settings, make API call - if (settingKey === 'default_lora_root' || settingKey === 'default_checkpoint_root' || settingKey === 'default_embedding_root' || settingKey === 'download_path_templates' || settingKey.startsWith('proxy_')) { - const payload = {}; - if (settingKey === 'download_path_templates') { - payload[settingKey] = state.global.settings.download_path_templates; - } else { - payload[settingKey] = value; - } + // Update frontend state with mapped keys + if (settingKey === 'default_lora_root') { + await this.saveSetting('default_lora_root', value); + } else if (settingKey === 'default_checkpoint_root') { + await this.saveSetting('default_checkpoint_root', value); + } else if (settingKey === 'default_embedding_root') { + await this.saveSetting('default_embedding_root', value); + } else if (settingKey === 'display_density') { + await this.saveSetting('displayDensity', value); - const response = await fetch('/api/settings', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(payload) - }); - - if (!response.ok) { - throw new Error('Failed to save setting'); - } - - showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success'); + // Also update compactMode for backwards compatibility + state.global.settings.compactMode = (value !== 'default'); + this.saveFrontendSettingsToStorage(); + } else if (settingKey === 'card_info_display') { + await this.saveSetting('cardInfoDisplay', value); + } else if (settingKey === 'proxy_type') { + await this.saveSetting('proxy_type', value); + } else { + // For any other settings that might be added in the future + await this.saveSetting(settingKey, value); } + showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success'); + // Apply frontend settings immediately this.applyFrontendSettings(); @@ -1167,9 +1172,8 @@ export class SettingsManager { showToast('settings.metadataArchive.downloadSuccess', 'success'); - // Update settings in state - state.global.settings.enable_metadata_archive_db = true; - setStorageItem('settings', state.global.settings); + // Update settings using universal save method + await this.saveSetting('enable_metadata_archive_db', true); // Update UI const enableCheckbox = document.getElementById('enableMetadataArchive'); @@ -1223,9 +1227,8 @@ export class SettingsManager { if (data.success) { showToast('settings.metadataArchive.removeSuccess', 'success'); - // Update settings in state - state.global.settings.enable_metadata_archive_db = false; - setStorageItem('settings', state.global.settings); + // Update settings using universal save method + await this.saveSetting('enable_metadata_archive_db', false); // Update UI const enableCheckbox = document.getElementById('enableMetadataArchive'); @@ -1255,7 +1258,6 @@ export class SettingsManager { const value = element.value.trim(); // Trim whitespace - // For API key or other inputs that need to be saved on backend try { // Check if value has changed from existing value const currentValue = state.global.settings[settingKey] || ''; @@ -1263,27 +1265,14 @@ export class SettingsManager { return; // No change, exit early } - // For username and password, remove the setting if value is empty + // For username and password, handle empty values specially if ((settingKey === 'proxy_username' || settingKey === 'proxy_password') && value === '') { // Remove from state instead of setting to empty string delete state.global.settings[settingKey]; - } else { - // Update state with value (including empty strings for non-optional fields) - state.global.settings[settingKey] = value; - } - - setStorageItem('settings', state.global.settings); - - // For backend settings, make API call - if (settingKey === 'civitai_api_key' || settingKey.startsWith('proxy_')) { - const payload = {}; - // For username and password, send delete flag if empty to remove from backend - if ((settingKey === 'proxy_username' || settingKey === 'proxy_password') && value === '') { - payload[settingKey] = '__DELETE__'; - } else { - payload[settingKey] = value; - } + // Send delete flag to backend + const payload = {}; + payload[settingKey] = '__DELETE__'; const response = await fetch('/api/settings', { method: 'POST', @@ -1294,8 +1283,11 @@ export class SettingsManager { }); if (!response.ok) { - throw new Error('Failed to save setting'); + throw new Error('Failed to delete setting'); } + } else { + // Use the universal save method + await this.saveSetting(settingKey, value); } showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success'); @@ -1312,26 +1304,8 @@ export class SettingsManager { const selectedLanguage = element.value; try { - // Update local state - state.global.settings.language = selectedLanguage; - - // Save to localStorage - setStorageItem('settings', state.global.settings); - - // Save to backend - const response = await fetch('/api/settings', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - language: selectedLanguage - }) - }); - - if (!response.ok) { - throw new Error('Failed to save language setting to backend'); - } + // Use the universal save method for language (frontend-only setting) + await this.saveSetting('language', selectedLanguage); // Reload the page to apply the new language window.location.reload(); diff --git a/static/js/state/index.js b/static/js/state/index.js index 71f6b859..9e48e86f 100644 --- a/static/js/state/index.js +++ b/static/js/state/index.js @@ -2,11 +2,17 @@ import { getStorageItem, getMapFromStorage } from '../utils/storageHelpers.js'; import { MODEL_TYPES } from '../api/apiConfig.js'; -// Load settings from localStorage or use defaults +// Load only frontend settings from localStorage with defaults +// Backend settings will be loaded by SettingsManager from the backend const savedSettings = getStorageItem('settings', { blurMatureContent: true, show_only_sfw: false, - cardInfoDisplay: 'always' + cardInfoDisplay: 'always', + autoplayOnHover: false, + displayDensity: 'default', + optimizeExampleImages: true, + autoDownloadExampleImages: true, + includeTriggerWords: false }); // Load preview versions from localStorage for each model type From 2f7e44a76fbae4a592b82f15baff1ef60a36f3b2 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 15 Sep 2025 10:30:06 +0800 Subject: [PATCH 013/110] refactor(settings): Update synchronization logic --- locales/de.json | 1 + locales/en.json | 1 + locales/es.json | 1 + locales/fr.json | 1 + locales/ja.json | 1 + locales/ko.json | 1 + locales/ru.json | 1 + locales/zh-CN.json | 19 ++-- locales/zh-TW.json | 1 + py/routes/misc_routes.py | 5 +- static/js/core.js | 4 +- static/js/managers/ExampleImagesManager.js | 104 ++++++--------------- static/js/managers/SettingsManager.js | 34 +++---- 13 files changed, 72 insertions(+), 102 deletions(-) diff --git a/locales/de.json b/locales/de.json index f0125334..0f667920 100644 --- a/locales/de.json +++ b/locales/de.json @@ -1166,6 +1166,7 @@ }, "exampleImages": { "pathUpdated": "Beispielbilder-Pfad erfolgreich aktualisiert", + "pathUpdateFailed": "Fehler beim Aktualisieren des Beispielbilder-Pfads: {message}", "downloadInProgress": "Download bereits in Bearbeitung", "enterLocationFirst": "Bitte geben Sie zuerst einen Download-Speicherort ein", "downloadStarted": "Beispielbilder-Download gestartet", diff --git a/locales/en.json b/locales/en.json index 24e4704e..306ba26b 100644 --- a/locales/en.json +++ b/locales/en.json @@ -1166,6 +1166,7 @@ }, "exampleImages": { "pathUpdated": "Example images path updated successfully", + "pathUpdateFailed": "Failed to update example images path: {message}", "downloadInProgress": "Download already in progress", "enterLocationFirst": "Please enter a download location first", "downloadStarted": "Example images download started", diff --git a/locales/es.json b/locales/es.json index a3e04cd8..f8aa33e9 100644 --- a/locales/es.json +++ b/locales/es.json @@ -1166,6 +1166,7 @@ }, "exampleImages": { "pathUpdated": "Ruta de imágenes de ejemplo actualizada exitosamente", + "pathUpdateFailed": "Error al actualizar la ruta de imágenes de ejemplo: {message}", "downloadInProgress": "Descarga ya en progreso", "enterLocationFirst": "Por favor introduce primero una ubicación de descarga", "downloadStarted": "Descarga de imágenes de ejemplo iniciada", diff --git a/locales/fr.json b/locales/fr.json index 38a6b1f5..7fc405b8 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -1166,6 +1166,7 @@ }, "exampleImages": { "pathUpdated": "Chemin des images d'exemple mis à jour avec succès", + "pathUpdateFailed": "Échec de la mise à jour du chemin des images d'exemple : {message}", "downloadInProgress": "Téléchargement déjà en cours", "enterLocationFirst": "Veuillez d'abord entrer un emplacement de téléchargement", "downloadStarted": "Téléchargement des images d'exemple démarré", diff --git a/locales/ja.json b/locales/ja.json index f8bdefc6..80488619 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -1166,6 +1166,7 @@ }, "exampleImages": { "pathUpdated": "例画像パスが正常に更新されました", + "pathUpdateFailed": "例画像パスの更新に失敗しました:{message}", "downloadInProgress": "ダウンロードは既に進行中です", "enterLocationFirst": "最初にダウンロード場所を入力してください", "downloadStarted": "例画像のダウンロードが開始されました", diff --git a/locales/ko.json b/locales/ko.json index 08ab8e38..bb8dbe37 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -1166,6 +1166,7 @@ }, "exampleImages": { "pathUpdated": "예시 이미지 경로가 성공적으로 업데이트되었습니다", + "pathUpdateFailed": "예시 이미지 경로 업데이트 실패: {message}", "downloadInProgress": "이미 다운로드가 진행 중입니다", "enterLocationFirst": "먼저 다운로드 위치를 입력해주세요", "downloadStarted": "예시 이미지 다운로드가 시작되었습니다", diff --git a/locales/ru.json b/locales/ru.json index 522ac612..99f61f5e 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -1166,6 +1166,7 @@ }, "exampleImages": { "pathUpdated": "Путь к примерам изображений успешно обновлен", + "pathUpdateFailed": "Не удалось обновить путь к примерам изображений: {message}", "downloadInProgress": "Загрузка уже в процессе", "enterLocationFirst": "Пожалуйста, сначала введите место загрузки", "downloadStarted": "Загрузка примеров изображений начата", diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 5884f1fc..7c01d9ac 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -21,17 +21,17 @@ "disabled": "已禁用" }, "language": { - "select": "语言", - "select_help": "选择你喜欢的界面语言", + "select": "Language", + "select_help": "Choose your preferred language for the interface", "english": "English", "chinese_simplified": "中文(简体)", "chinese_traditional": "中文(繁体)", - "russian": "俄语", - "german": "德语", - "japanese": "日语", - "korean": "韩语", - "french": "法语", - "spanish": "西班牙语" + "russian": "Русский", + "german": "Deutsch", + "japanese": "日本語", + "korean": "한국어", + "french": "Français", + "spanish": "Español" }, "fileSize": { "zero": "0 字节", @@ -311,7 +311,7 @@ "proxyHostPlaceholder": "proxy.example.com", "proxyHostHelp": "代理服务器的主机名或IP地址", "proxyPort": "代理端口", - "proxyPortPlaceholder": "8080", + "proxyPortPlaceholder": "8080", "proxyPortHelp": "代理服务器的端口号", "proxyUsername": "用户名 (可选)", "proxyUsernamePlaceholder": "用户名", @@ -1166,6 +1166,7 @@ }, "exampleImages": { "pathUpdated": "示例图片路径更新成功", + "pathUpdateFailed": "更新示例图片路径失败:{message}", "downloadInProgress": "下载已在进行中", "enterLocationFirst": "请先输入下载位置", "downloadStarted": "示例图片下载已开始", diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 5e982e5f..4846649c 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -1166,6 +1166,7 @@ }, "exampleImages": { "pathUpdated": "範例圖片路徑已更新", + "pathUpdateFailed": "更新範例圖片路徑失敗:{message}", "downloadInProgress": "下載已在進行中", "enterLocationFirst": "請先輸入下載位置", "downloadStarted": "範例圖片下載已開始", diff --git a/py/routes/misc_routes.py b/py/routes/misc_routes.py index 494eca9b..32f51f68 100644 --- a/py/routes/misc_routes.py +++ b/py/routes/misc_routes.py @@ -139,7 +139,10 @@ class MiscRoutes: 'proxy_host', 'proxy_port', 'proxy_username', - 'proxy_password' + 'proxy_password', + 'example_images_path', + 'optimizeExampleImages', + 'autoDownloadExampleImages' ] # Build response with only the keys that should be synced diff --git a/static/js/core.js b/static/js/core.js index 779f3094..c2ad6cdb 100644 --- a/static/js/core.js +++ b/static/js/core.js @@ -7,7 +7,7 @@ import { HeaderManager } from './components/Header.js'; import { settingsManager } from './managers/SettingsManager.js'; import { moveManager } from './managers/MoveManager.js'; import { bulkManager } from './managers/BulkManager.js'; -import { exampleImagesManager } from './managers/ExampleImagesManager.js'; +import { ExampleImagesManager } from './managers/ExampleImagesManager.js'; import { helpManager } from './managers/HelpManager.js'; import { bannerService } from './managers/BannerService.js'; import { initTheme, initBackToTop } from './utils/uiHelpers.js'; @@ -50,7 +50,7 @@ export class AppCore { bannerService.initialize(); window.modalManager = modalManager; window.settingsManager = settingsManager; - window.exampleImagesManager = exampleImagesManager; + window.exampleImagesManager = new ExampleImagesManager(); window.helpManager = helpManager; window.moveManager = moveManager; window.bulkManager = bulkManager; diff --git a/static/js/managers/ExampleImagesManager.js b/static/js/managers/ExampleImagesManager.js index 60006400..5ef58702 100644 --- a/static/js/managers/ExampleImagesManager.js +++ b/static/js/managers/ExampleImagesManager.js @@ -1,9 +1,10 @@ import { showToast } from '../utils/uiHelpers.js'; import { state } from '../state/index.js'; import { getStorageItem, setStorageItem } from '../utils/storageHelpers.js'; +import { settingsManager } from './SettingsManager.js'; // ExampleImagesManager.js -class ExampleImagesManager { +export class ExampleImagesManager { constructor() { this.isDownloading = false; this.isPaused = false; @@ -27,7 +28,12 @@ class ExampleImagesManager { } // Initialize the manager - initialize() { + async initialize() { + // Wait for settings to be initialized before proceeding + if (window.settingsManager) { + await window.settingsManager.waitForInitialization(); + } + // Initialize event listeners this.initEventListeners(); @@ -78,86 +84,41 @@ class ExampleImagesManager { // Get custom path input element const pathInput = document.getElementById('exampleImagesPath'); - // Set path from storage if available - const savedPath = getStorageItem('example_images_path', ''); - if (savedPath) { + // Set path from backend settings + const savedPath = state.global.settings.example_images_path || ''; + if (pathInput) { pathInput.value = savedPath; // Enable download button if path is set - this.updateDownloadButtonState(true); - - // Sync the saved path with the backend - try { - const response = await fetch('/api/settings', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - example_images_path: savedPath - }) - }); - - if (!response.ok) { - throw new Error(`HTTP error! Status: ${response.status}`); - } - - const data = await response.json(); - if (!data.success) { - console.error('Failed to sync example images path with backend:', data.error); - } - } catch (error) { - console.error('Failed to sync saved path with backend:', error); - } - } else { - // Disable download button if no path is set - this.updateDownloadButtonState(false); + this.updateDownloadButtonState(!!savedPath); } // Add event listener to validate path input - pathInput.addEventListener('input', async () => { - const hasPath = pathInput.value.trim() !== ''; - this.updateDownloadButtonState(hasPath); - - // Save path to storage when changed - if (hasPath) { - setStorageItem('example_images_path', pathInput.value); + if (pathInput) { + pathInput.addEventListener('input', async () => { + const hasPath = pathInput.value.trim() !== ''; + this.updateDownloadButtonState(hasPath); - // Update path in backend settings + // Update path in backend settings using settingsManager try { - const response = await fetch('/api/settings', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - example_images_path: pathInput.value - }) - }); - - if (!response.ok) { - throw new Error(`HTTP error! Status: ${response.status}`); - } - - const data = await response.json(); - if (!data.success) { - console.error('Failed to update example images path in backend:', data.error); - } else { + await settingsManager.saveSetting('example_images_path', pathInput.value); + if (hasPath) { showToast('toast.exampleImages.pathUpdated', {}, 'success'); } } catch (error) { console.error('Failed to update example images path:', error); + showToast('toast.exampleImages.pathUpdateFailed', { message: error.message }, 'error'); } - } - // Setup or clear auto download based on path availability - if (state.global.settings.autoDownloadExampleImages) { - if (hasPath) { - this.setupAutoDownload(); - } else { - this.clearAutoDownload(); + // Setup or clear auto download based on path availability + if (state.global.settings.autoDownloadExampleImages) { + if (hasPath) { + this.setupAutoDownload(); + } else { + this.clearAutoDownload(); + } } - } - }); + }); + } } catch (error) { console.error('Failed to initialize path options:', error); } @@ -255,7 +216,7 @@ class ExampleImagesManager { return; } - const optimize = document.getElementById('optimizeExampleImages').checked; + const optimize = state.global.settings.optimizeExampleImages; const response = await fetch('/api/download-example-images', { method: 'POST', @@ -746,7 +707,7 @@ class ExampleImagesManager { console.log('Performing auto download check...'); const outputDir = document.getElementById('exampleImagesPath').value; - const optimize = document.getElementById('optimizeExampleImages').checked; + const optimize = state.global.settings.optimizeExampleImages; const response = await fetch('/api/download-example-images', { method: 'POST', @@ -771,6 +732,3 @@ class ExampleImagesManager { } } } - -// Create singleton instance -export const exampleImagesManager = new ExampleImagesManager(); diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index 0767baab..bafb520d 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -47,8 +47,6 @@ export class SettingsManager { 'autoplayOnHover', 'displayDensity', 'cardInfoDisplay', - 'optimizeExampleImages', - 'autoDownloadExampleImages', 'includeTriggerWords' ]; @@ -76,14 +74,6 @@ export class SettingsManager { state.global.settings.autoplayOnHover = false; } - if (state.global.settings.optimizeExampleImages === undefined) { - state.global.settings.optimizeExampleImages = true; - } - - if (state.global.settings.autoDownloadExampleImages === undefined) { - state.global.settings.autoDownloadExampleImages = true; - } - if (state.global.settings.cardInfoDisplay === undefined) { state.global.settings.cardInfoDisplay = 'always'; } @@ -147,7 +137,10 @@ export class SettingsManager { proxy_host: '', proxy_port: '', proxy_username: '', - proxy_password: '' + proxy_password: '', + example_images_path: '', + optimizeExampleImages: true, + autoDownloadExampleImages: true }; Object.keys(backendDefaults).forEach(key => { @@ -172,8 +165,6 @@ export class SettingsManager { 'autoplayOnHover', 'displayDensity', 'cardInfoDisplay', - 'optimizeExampleImages', - 'autoDownloadExampleImages', 'includeTriggerWords' ]; @@ -203,7 +194,10 @@ export class SettingsManager { 'proxy_host', 'proxy_port', 'proxy_username', - 'proxy_password' + 'proxy_password', + 'example_images_path', + 'optimizeExampleImages', + 'autoDownloadExampleImages' ]; return backendKeys.includes(settingKey); } @@ -218,7 +212,7 @@ export class SettingsManager { try { const payload = {}; payload[settingKey] = value; - + const response = await fetch('/api/settings', { method: 'POST', headers: { @@ -230,6 +224,12 @@ export class SettingsManager { if (!response.ok) { throw new Error('Failed to save setting to backend'); } + + // Parse response and check for success + const data = await response.json(); + if (data.success === false) { + throw new Error(data.error || 'Failed to save setting to backend'); + } } catch (error) { console.error(`Failed to save backend setting ${settingKey}:`, error); throw error; @@ -985,8 +985,6 @@ export class SettingsManager { await this.saveSetting(settingKey, value); } - showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success'); - // Apply frontend settings immediately this.applyFrontendSettings(); @@ -999,8 +997,10 @@ export class SettingsManager { if (value === 'compact') densityName = "Compact"; showToast('toast.settings.displayDensitySet', { density: densityName }, 'success'); + return; } + showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success'); } catch (error) { showToast('toast.settings.settingSaveFailed', { message: error.message }, 'error'); } From 26891e12a4e87407771eec83e6055e4b44add509 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 15 Sep 2025 11:34:39 +0800 Subject: [PATCH 014/110] refactor(ExampleImagesManager): enhance path input handling with Enter key and blur events --- static/js/managers/ExampleImagesManager.js | 26 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/static/js/managers/ExampleImagesManager.js b/static/js/managers/ExampleImagesManager.js index 5ef58702..38150749 100644 --- a/static/js/managers/ExampleImagesManager.js +++ b/static/js/managers/ExampleImagesManager.js @@ -94,11 +94,10 @@ export class ExampleImagesManager { // Add event listener to validate path input if (pathInput) { - pathInput.addEventListener('input', async () => { + // Save path on Enter key or blur + const savePath = async () => { const hasPath = pathInput.value.trim() !== ''; this.updateDownloadButtonState(hasPath); - - // Update path in backend settings using settingsManager try { await settingsManager.saveSetting('example_images_path', pathInput.value); if (hasPath) { @@ -108,7 +107,6 @@ export class ExampleImagesManager { console.error('Failed to update example images path:', error); showToast('toast.exampleImages.pathUpdateFailed', { message: error.message }, 'error'); } - // Setup or clear auto download based on path availability if (state.global.settings.autoDownloadExampleImages) { if (hasPath) { @@ -117,6 +115,26 @@ export class ExampleImagesManager { this.clearAutoDownload(); } } + }; + let ignoreNextBlur = false; + pathInput.addEventListener('keydown', async (e) => { + if (e.key === 'Enter') { + ignoreNextBlur = true; + await savePath(); + pathInput.blur(); // Remove focus from the input after saving + } + }); + pathInput.addEventListener('blur', async () => { + if (ignoreNextBlur) { + ignoreNextBlur = false; + return; + } + await savePath(); + }); + // Still update button state on input, but don't save + pathInput.addEventListener('input', () => { + const hasPath = pathInput.value.trim() !== ''; + this.updateDownloadButtonState(hasPath); }); } } catch (error) { From 1147725fd74de646b563f408923b4272dc90c098 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 15 Sep 2025 12:23:46 +0800 Subject: [PATCH 015/110] feat(settings): add base model, author, and first tag option to download path templates refactor(constants): reorder preset tag suggestions for consistency --- locales/de.json | 1 + locales/en.json | 1 + locales/es.json | 1 + locales/fr.json | 1 + locales/ja.json | 1 + locales/ko.json | 1 + locales/ru.json | 1 + locales/zh-CN.json | 1 + locales/zh-TW.json | 1 + py/utils/constants.py | 6 +++--- static/js/utils/constants.js | 10 ++++++++-- templates/components/modals/settings_modal.html | 3 +++ 12 files changed, 23 insertions(+), 5 deletions(-) diff --git a/locales/de.json b/locales/de.json index 0f667920..bcff9fc9 100644 --- a/locales/de.json +++ b/locales/de.json @@ -240,6 +240,7 @@ "baseModelFirstTag": "Basis-Modell + Erster Tag", "baseModelAuthor": "Basis-Modell + Autor", "authorFirstTag": "Autor + Erster Tag", + "baseModelAuthorFirstTag": "Basis-Modell + Autor + Erster Tag", "customTemplate": "Benutzerdefinierte Vorlage" }, "customTemplatePlaceholder": "Benutzerdefinierte Vorlage eingeben (z.B. {base_model}/{author}/{first_tag})", diff --git a/locales/en.json b/locales/en.json index 306ba26b..237755c0 100644 --- a/locales/en.json +++ b/locales/en.json @@ -240,6 +240,7 @@ "baseModelFirstTag": "Base Model + First Tag", "baseModelAuthor": "Base Model + Author", "authorFirstTag": "Author + First Tag", + "baseModelAuthorFirstTag": "Base Model + Author + First Tag", "customTemplate": "Custom Template" }, "customTemplatePlaceholder": "Enter custom template (e.g., {base_model}/{author}/{first_tag})", diff --git a/locales/es.json b/locales/es.json index f8aa33e9..a4a8f401 100644 --- a/locales/es.json +++ b/locales/es.json @@ -240,6 +240,7 @@ "baseModelFirstTag": "Modelo base + primera etiqueta", "baseModelAuthor": "Modelo base + autor", "authorFirstTag": "Autor + primera etiqueta", + "baseModelAuthorFirstTag": "Modelo base + autor + primera etiqueta", "customTemplate": "Plantilla personalizada" }, "customTemplatePlaceholder": "Introduce plantilla personalizada (ej., {base_model}/{author}/{first_tag})", diff --git a/locales/fr.json b/locales/fr.json index 7fc405b8..b492d805 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -240,6 +240,7 @@ "baseModelFirstTag": "Modèle de base + Premier tag", "baseModelAuthor": "Modèle de base + Auteur", "authorFirstTag": "Auteur + Premier tag", + "baseModelAuthorFirstTag": "Modèle de base + Auteur + Premier tag", "customTemplate": "Modèle personnalisé" }, "customTemplatePlaceholder": "Entrez un modèle personnalisé (ex: {base_model}/{author}/{first_tag})", diff --git a/locales/ja.json b/locales/ja.json index 80488619..f2f889d4 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -240,6 +240,7 @@ "baseModelFirstTag": "ベースモデル + 最初のタグ", "baseModelAuthor": "ベースモデル + 作成者", "authorFirstTag": "作成者 + 最初のタグ", + "baseModelAuthorFirstTag": "ベースモデル + 作成者 + 最初のタグ", "customTemplate": "カスタムテンプレート" }, "customTemplatePlaceholder": "カスタムテンプレートを入力(例:{base_model}/{author}/{first_tag})", diff --git a/locales/ko.json b/locales/ko.json index bb8dbe37..4f329b89 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -240,6 +240,7 @@ "baseModelFirstTag": "베이스 모델 + 첫 번째 태그", "baseModelAuthor": "베이스 모델 + 제작자", "authorFirstTag": "제작자 + 첫 번째 태그", + "baseModelAuthorFirstTag": "베이스 모델 + 제작자 + 첫 번째 태그", "customTemplate": "사용자 정의 템플릿" }, "customTemplatePlaceholder": "사용자 정의 템플릿 입력 (예: {base_model}/{author}/{first_tag})", diff --git a/locales/ru.json b/locales/ru.json index 99f61f5e..a0e78b34 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -240,6 +240,7 @@ "baseModelFirstTag": "Базовая модель + Первый тег", "baseModelAuthor": "Базовая модель + Автор", "authorFirstTag": "Автор + Первый тег", + "baseModelAuthorFirstTag": "Базовая модель + Автор + Первый тег", "customTemplate": "Пользовательский шаблон" }, "customTemplatePlaceholder": "Введите пользовательский шаблон (например, {base_model}/{author}/{first_tag})", diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 7c01d9ac..9b713351 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -240,6 +240,7 @@ "baseModelFirstTag": "基础模型 + 首标签", "baseModelAuthor": "基础模型 + 作者", "authorFirstTag": "作者 + 首标签", + "baseModelAuthorFirstTag": "基础模型 + 作者 + 首标签", "customTemplate": "自定义模板" }, "customTemplatePlaceholder": "输入自定义模板(如:{base_model}/{author}/{first_tag})", diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 4846649c..1c70b7c3 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -240,6 +240,7 @@ "baseModelFirstTag": "基礎模型 + 第一標籤", "baseModelAuthor": "基礎模型 + 作者", "authorFirstTag": "作者 + 第一標籤", + "baseModelAuthorFirstTag": "基礎模型 + 作者 + 第一標籤", "customTemplate": "自訂範本" }, "customTemplatePlaceholder": "輸入自訂範本(例如:{base_model}/{author}/{first_tag})", diff --git a/py/utils/constants.py b/py/utils/constants.py index 88932766..243badff 100644 --- a/py/utils/constants.py +++ b/py/utils/constants.py @@ -53,8 +53,8 @@ AUTO_ORGANIZE_BATCH_SIZE = 50 # Process models in batches to avoid overwhelming # Civitai model tags in priority order for subfolder organization CIVITAI_MODEL_TAGS = [ - 'character', 'style', 'concept', 'clothing', - 'realistic', 'anime', 'toon', 'furry', - 'poses', 'background', 'tool', 'vehicle', 'buildings', + 'character', 'concept', 'clothing', + 'realistic', 'anime', 'toon', 'furry', 'style', + 'poses', 'background', 'tool', 'vehicle', 'buildings', 'objects', 'assets', 'animal', 'action' ] \ No newline at end of file diff --git a/static/js/utils/constants.js b/static/js/utils/constants.js index d27d6283..5690f904 100644 --- a/static/js/utils/constants.js +++ b/static/js/utils/constants.js @@ -92,6 +92,12 @@ export const DOWNLOAD_PATH_TEMPLATES = { description: 'Organize by base model and author', example: 'Flux.1 D/authorname/model-name.safetensors' }, + BASE_MODEL_AUTHOR_TAG: { + value: '{base_model}/{author}/{first_tag}', + label: 'Base Model + Author + First Tag', + description: 'Organize by base model, author, and primary tag', + example: 'Flux.1 D/authorname/style/model-name.safetensors' + }, AUTHOR_TAG: { value: '{author}/{first_tag}', label: 'Author + First Tag', @@ -189,8 +195,8 @@ export const BASE_MODEL_CATEGORIES = { // Preset tag suggestions export const PRESET_TAGS = [ - 'character', 'style', 'concept', 'clothing', - 'realistic', 'anime', 'toon', 'furry', + 'character', 'concept', 'clothing', + 'realistic', 'anime', 'toon', 'furry', 'style', 'poses', 'background', 'vehicle', 'buildings', 'objects', 'animal' ]; diff --git a/templates/components/modals/settings_modal.html b/templates/components/modals/settings_modal.html index 09fea0c9..1cba359d 100644 --- a/templates/components/modals/settings_modal.html +++ b/templates/components/modals/settings_modal.html @@ -254,6 +254,7 @@ + @@ -280,6 +281,7 @@ + @@ -306,6 +308,7 @@ + From 2b847039d4e7425a65c2487bee2414be74f42b69 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 15 Sep 2025 15:38:01 +0800 Subject: [PATCH 016/110] refactor(settings-modal): adjust font size for path template preview --- static/css/components/modal/settings-modal.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/css/components/modal/settings-modal.css b/static/css/components/modal/settings-modal.css index 3f59203e..8165bb67 100644 --- a/static/css/components/modal/settings-modal.css +++ b/static/css/components/modal/settings-modal.css @@ -376,7 +376,7 @@ input:checked + .toggle-slider:before { padding: var(--space-1); margin-top: 8px; font-family: monospace; - font-size: 1.1em; + font-size: 0.9em; color: var(--lora-accent); display: none; } From c49be91aa0f9c6fd787c08fdcfcea0e21d3e0607 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 15 Sep 2025 16:04:20 +0800 Subject: [PATCH 017/110] refactor(update_routes): exclude civitai folder from plugin update process --- py/routes/update_routes.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/py/routes/update_routes.py b/py/routes/update_routes.py index d139ce77..bf77baaf 100644 --- a/py/routes/update_routes.py +++ b/py/routes/update_routes.py @@ -154,7 +154,7 @@ class UpdateRoutes: async def _download_and_replace_zip(plugin_root: str) -> tuple[bool, str]: """ Download latest release ZIP from GitHub and replace plugin files. - Skips settings.json. Writes extracted file list to .tracking. + Skips settings.json and civitai folder. Writes extracted file list to .tracking. """ repo_owner = "willmiao" repo_name = "ComfyUI-Lora-Manager" @@ -193,7 +193,8 @@ class UpdateRoutes: zip_path = tmp_zip_path - UpdateRoutes._clean_plugin_folder(plugin_root, skip_files=['settings.json']) + # Skip both settings.json and civitai folder + UpdateRoutes._clean_plugin_folder(plugin_root, skip_files=['settings.json', 'civitai']) # Extract ZIP to temp dir with tempfile.TemporaryDirectory() as tmp_dir: @@ -202,17 +203,17 @@ class UpdateRoutes: # Find extracted folder (GitHub ZIP contains a root folder) extracted_root = next(os.scandir(tmp_dir)).path - # Copy files, skipping settings.json + # Copy files, skipping settings.json and civitai folder for item in os.listdir(extracted_root): + if item == 'settings.json' or item == 'civitai': + continue src = os.path.join(extracted_root, item) dst = os.path.join(plugin_root, item) if os.path.isdir(src): if os.path.exists(dst): shutil.rmtree(dst) - shutil.copytree(src, dst, ignore=shutil.ignore_patterns('settings.json')) + shutil.copytree(src, dst, ignore=shutil.ignore_patterns('settings.json', 'civitai')) else: - if item == 'settings.json': - continue shutil.copy2(src, dst) # Write .tracking file: list all files under extracted_root, relative to extracted_root @@ -220,8 +221,15 @@ class UpdateRoutes: tracking_info_file = os.path.join(plugin_root, '.tracking') tracking_files = [] for root, dirs, files in os.walk(extracted_root): + # Skip civitai folder and its contents + rel_root = os.path.relpath(root, extracted_root) + if rel_root == 'civitai' or rel_root.startswith('civitai' + os.sep): + continue for file in files: rel_path = os.path.relpath(os.path.join(root, file), extracted_root) + # Skip settings.json and any file under civitai + if rel_path == 'settings.json' or rel_path.startswith('civitai' + os.sep): + continue tracking_files.append(rel_path.replace("\\", "/")) with open(tracking_info_file, "w", encoding='utf-8') as file: file.write('\n'.join(tracking_files)) From 4bb8981e78cf1181abd95fdda755065d1fe0d735 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 15 Sep 2025 16:22:59 +0800 Subject: [PATCH 018/110] refactor(routes): update API endpoints for settings to use '/api/lm/settings', see #435 --- py/routes/misc_routes.py | 4 ++-- static/js/managers/OnboardingManager.js | 2 +- static/js/managers/SettingsManager.js | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/py/routes/misc_routes.py b/py/routes/misc_routes.py index 32f51f68..89fadace 100644 --- a/py/routes/misc_routes.py +++ b/py/routes/misc_routes.py @@ -88,8 +88,8 @@ class MiscRoutes: @staticmethod def setup_routes(app): """Register miscellaneous routes""" - app.router.add_get('/api/settings', MiscRoutes.get_settings) - app.router.add_post('/api/settings', MiscRoutes.update_settings) + app.router.add_get('/api/lm/settings', MiscRoutes.get_settings) + app.router.add_post('/api/lm/settings', MiscRoutes.update_settings) app.router.add_get('/api/health-check', lambda request: web.json_response({'status': 'ok'})) diff --git a/static/js/managers/OnboardingManager.js b/static/js/managers/OnboardingManager.js index ccbb971f..047cd000 100644 --- a/static/js/managers/OnboardingManager.js +++ b/static/js/managers/OnboardingManager.js @@ -186,7 +186,7 @@ export class OnboardingManager { setStorageItem('settings', state.global.settings); // Save to backend - const response = await fetch('/api/settings', { + const response = await fetch('/api/lm/settings', { method: 'POST', headers: { 'Content-Type': 'application/json', diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index bafb520d..33040aac 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -97,7 +97,7 @@ export class SettingsManager { async syncSettingsFromBackend() { try { - const response = await fetch('/api/settings'); + const response = await fetch('/api/lm/settings'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } @@ -213,7 +213,7 @@ export class SettingsManager { const payload = {}; payload[settingKey] = value; - const response = await fetch('/api/settings', { + const response = await fetch('/api/lm/settings', { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -1274,7 +1274,7 @@ export class SettingsManager { const payload = {}; payload[settingKey] = '__DELETE__'; - const response = await fetch('/api/settings', { + const response = await fetch('/api/lm/settings', { method: 'POST', headers: { 'Content-Type': 'application/json', From 4540e47055fd6d9b930fa456cbd9303b54065b30 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 15 Sep 2025 18:07:22 +0800 Subject: [PATCH 019/110] refactor(baseModelApi): update example images path retrieval to use state settings --- static/js/api/baseModelApi.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/static/js/api/baseModelApi.js b/static/js/api/baseModelApi.js index 2a7c058d..0e77823c 100644 --- a/static/js/api/baseModelApi.js +++ b/static/js/api/baseModelApi.js @@ -938,8 +938,8 @@ export class BaseModelApiClient { ws.onerror = reject; }); - // Get the output directory from storage - const outputDir = getStorageItem('example_images_path', ''); + // Get the output directory from state + const outputDir = state.global?.settings?.example_images_path || ''; if (!outputDir) { throw new Error('Please set the example images path in the settings first.'); } From 6f9245df0130ebc116dcdef20a230e6f1a64f18d Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 15 Sep 2025 18:53:04 +0800 Subject: [PATCH 020/110] refactor(downloader): enhance download_to_memory to return response headers and improve error handling --- py/services/downloader.py | 27 ++-- py/utils/example_images_processor.py | 182 +++++++++++++++++---------- 2 files changed, 136 insertions(+), 73 deletions(-) diff --git a/py/services/downloader.py b/py/services/downloader.py index dd2c8c32..4f6b5f97 100644 --- a/py/services/downloader.py +++ b/py/services/downloader.py @@ -366,8 +366,9 @@ class Downloader: self, url: str, use_auth: bool = False, - custom_headers: Optional[Dict[str, str]] = None - ) -> Tuple[bool, Union[bytes, str]]: + custom_headers: Optional[Dict[str, str]] = None, + return_headers: bool = False + ) -> Tuple[bool, Union[bytes, str], Optional[Dict]]: """ Download a file to memory (for small files like preview images) @@ -375,9 +376,10 @@ class Downloader: url: Download URL use_auth: Whether to include authentication headers custom_headers: Additional headers to include in request + return_headers: Whether to return response headers along with content Returns: - Tuple[bool, Union[bytes, str]]: (success, content or error message) + Tuple[bool, Union[bytes, str], Optional[Dict]]: (success, content or error message, response headers if requested) """ try: session = await self.session @@ -395,19 +397,26 @@ class Downloader: async with session.get(url, headers=headers, proxy=self.proxy_url) as response: if response.status == 200: content = await response.read() - return True, content + if return_headers: + return True, content, dict(response.headers) + else: + return True, content, None elif response.status == 401: - return False, "Unauthorized access - invalid or missing API key" + error_msg = "Unauthorized access - invalid or missing API key" + return False, error_msg, None elif response.status == 403: - return False, "Access forbidden" + error_msg = "Access forbidden" + return False, error_msg, None elif response.status == 404: - return False, "File not found" + error_msg = "File not found" + return False, error_msg, None else: - return False, f"Download failed with status {response.status}" + error_msg = f"Download failed with status {response.status}" + return False, error_msg, None except Exception as e: logger.error(f"Error downloading to memory from {url}: {e}") - return False, str(e) + return False, str(e), None async def get_response_headers( self, diff --git a/py/utils/example_images_processor.py b/py/utils/example_images_processor.py index 9dba4e2c..f1cfd2bf 100644 --- a/py/utils/example_images_processor.py +++ b/py/utils/example_images_processor.py @@ -23,17 +23,60 @@ class ExampleImagesProcessor: return ''.join(random.choice(chars) for _ in range(length)) @staticmethod - def get_civitai_optimized_url(image_url): - """Convert Civitai image URL to its optimized WebP version""" + def get_civitai_optimized_url(media_url): + """Convert Civitai media URL (image or video) to its optimized version""" base_pattern = r'(https://image\.civitai\.com/[^/]+/[^/]+)' - match = re.match(base_pattern, image_url) + match = re.match(base_pattern, media_url) if match: base_url = match.group(1) - return f"{base_url}/optimized=true/image.webp" + return f"{base_url}/optimized=true" - return image_url + return media_url + @staticmethod + def _get_file_extension_from_content_or_headers(content, headers, fallback_url=None): + """Determine file extension from content magic bytes or headers""" + # Check magic bytes for common formats + if content: + if content.startswith(b'\xFF\xD8\xFF'): + return '.jpg' + elif content.startswith(b'\x89PNG\r\n\x1A\n'): + return '.png' + elif content.startswith(b'GIF87a') or content.startswith(b'GIF89a'): + return '.gif' + elif content.startswith(b'RIFF') and b'WEBP' in content[:12]: + return '.webp' + elif content.startswith(b'\x00\x00\x00\x18ftypmp4') or content.startswith(b'\x00\x00\x00\x20ftypmp4'): + return '.mp4' + elif content.startswith(b'\x1A\x45\xDF\xA3'): + return '.webm' + + # Check Content-Type header + if headers: + content_type = headers.get('content-type', '').lower() + type_map = { + 'image/jpeg': '.jpg', + 'image/png': '.png', + 'image/gif': '.gif', + 'image/webp': '.webp', + 'video/mp4': '.mp4', + 'video/webm': '.webm', + 'video/quicktime': '.mov' + } + if content_type in type_map: + return type_map[content_type] + + # Fallback to URL extension if available + if fallback_url: + filename = os.path.basename(fallback_url.split('?')[0]) + ext = os.path.splitext(filename)[1].lower() + if ext in SUPPORTED_MEDIA_EXTENSIONS['images'] or ext in SUPPORTED_MEDIA_EXTENSIONS['videos']: + return ext + + # Default fallback + return '.jpg' + @staticmethod async def download_model_images(model_hash, model_name, model_images, model_dir, optimize, downloader): """Download images for a single model @@ -48,45 +91,49 @@ class ExampleImagesProcessor: if not image_url: continue - # Get image filename from URL - image_filename = os.path.basename(image_url.split('?')[0]) - image_ext = os.path.splitext(image_filename)[1].lower() - - # Handle images and videos - is_image = image_ext in SUPPORTED_MEDIA_EXTENSIONS['images'] - is_video = image_ext in SUPPORTED_MEDIA_EXTENSIONS['videos'] - - if not (is_image or is_video): - logger.debug(f"Skipping unsupported file type: {image_filename}") - continue - - # Use 0-based indexing instead of 1-based indexing - save_filename = f"image_{i}{image_ext}" - - # If optimizing images and this is a Civitai image, use their pre-optimized WebP version - if is_image and optimize and 'civitai.com' in image_url: + # Apply optimization for Civitai URLs if enabled + original_url = image_url + if optimize and 'civitai.com' in image_url: image_url = ExampleImagesProcessor.get_civitai_optimized_url(image_url) - save_filename = f"image_{i}.webp" - # Check if already downloaded - save_path = os.path.join(model_dir, save_filename) - if os.path.exists(save_path): - logger.debug(f"File already exists: {save_path}") - continue - - # Download the file + # Download the file first to determine the actual file type try: - logger.debug(f"Downloading {save_filename} for {model_name}") + logger.debug(f"Downloading media file {i} for {model_name}") - # Download using the unified downloader - success, content = await downloader.download_to_memory( + # Download using the unified downloader with headers + success, content, headers = await downloader.download_to_memory( image_url, - use_auth=False # Example images don't need auth + use_auth=False, # Example images don't need auth + return_headers=True ) if success: + # Determine file extension from content or headers + media_ext = ExampleImagesProcessor._get_file_extension_from_content_or_headers( + content, headers, original_url + ) + + # Check if the detected file type is supported + is_image = media_ext in SUPPORTED_MEDIA_EXTENSIONS['images'] + is_video = media_ext in SUPPORTED_MEDIA_EXTENSIONS['videos'] + + if not (is_image or is_video): + logger.debug(f"Skipping unsupported file type: {media_ext}") + continue + + # Use 0-based indexing with the detected extension + save_filename = f"image_{i}{media_ext}" + save_path = os.path.join(model_dir, save_filename) + + # Check if already downloaded + if os.path.exists(save_path): + logger.debug(f"File already exists: {save_path}") + continue + + # Save the file with open(save_path, 'wb') as f: f.write(content) + elif "404" in str(content): error_msg = f"Failed to download file: {image_url}, status code: 404 - Model metadata might be stale" logger.warning(error_msg) @@ -119,45 +166,49 @@ class ExampleImagesProcessor: if not image_url: continue - # Get image filename from URL - image_filename = os.path.basename(image_url.split('?')[0]) - image_ext = os.path.splitext(image_filename)[1].lower() - - # Handle images and videos - is_image = image_ext in SUPPORTED_MEDIA_EXTENSIONS['images'] - is_video = image_ext in SUPPORTED_MEDIA_EXTENSIONS['videos'] - - if not (is_image or is_video): - logger.debug(f"Skipping unsupported file type: {image_filename}") - continue - - # Use 0-based indexing instead of 1-based indexing - save_filename = f"image_{i}{image_ext}" - - # If optimizing images and this is a Civitai image, use their pre-optimized WebP version - if is_image and optimize and 'civitai.com' in image_url: + # Apply optimization for Civitai URLs if enabled + original_url = image_url + if optimize and 'civitai.com' in image_url: image_url = ExampleImagesProcessor.get_civitai_optimized_url(image_url) - save_filename = f"image_{i}.webp" - # Check if already downloaded - save_path = os.path.join(model_dir, save_filename) - if os.path.exists(save_path): - logger.debug(f"File already exists: {save_path}") - continue - - # Download the file + # Download the file first to determine the actual file type try: - logger.debug(f"Downloading {save_filename} for {model_name}") + logger.debug(f"Downloading media file {i} for {model_name}") - # Download using the unified downloader - success, content = await downloader.download_to_memory( + # Download using the unified downloader with headers + success, content, headers = await downloader.download_to_memory( image_url, - use_auth=False # Example images don't need auth + use_auth=False, # Example images don't need auth + return_headers=True ) if success: + # Determine file extension from content or headers + media_ext = ExampleImagesProcessor._get_file_extension_from_content_or_headers( + content, headers, original_url + ) + + # Check if the detected file type is supported + is_image = media_ext in SUPPORTED_MEDIA_EXTENSIONS['images'] + is_video = media_ext in SUPPORTED_MEDIA_EXTENSIONS['videos'] + + if not (is_image or is_video): + logger.debug(f"Skipping unsupported file type: {media_ext}") + continue + + # Use 0-based indexing with the detected extension + save_filename = f"image_{i}{media_ext}" + save_path = os.path.join(model_dir, save_filename) + + # Check if already downloaded + if os.path.exists(save_path): + logger.debug(f"File already exists: {save_path}") + continue + + # Save the file with open(save_path, 'wb') as f: f.write(content) + elif "404" in str(content): error_msg = f"Failed to download file: {image_url}, status code: 404 - Model metadata might be stale" logger.warning(error_msg) @@ -569,4 +620,7 @@ class ExampleImagesProcessor: return web.json_response({ 'success': False, 'error': str(e) - }, status=500) \ No newline at end of file + }, status=500) + + + \ No newline at end of file From 86074c87d74b4cbc8f9f4a032bee46222e0ed657 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 15 Sep 2025 19:24:09 +0800 Subject: [PATCH 021/110] refactor(downloader): update download_to_memory calls to include response headers --- py/services/civitai_client.py | 2 +- py/services/download_manager.py | 2 +- py/utils/routes_common.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/py/services/civitai_client.py b/py/services/civitai_client.py index 04d56d29..e037ba35 100644 --- a/py/services/civitai_client.py +++ b/py/services/civitai_client.py @@ -94,7 +94,7 @@ class CivitaiClient: async def download_preview_image(self, image_url: str, save_path: str): try: downloader = await get_downloader() - success, content = await downloader.download_to_memory( + success, content, headers = await downloader.download_to_memory( image_url, use_auth=False # Preview images don't need auth ) diff --git a/py/services/download_manager.py b/py/services/download_manager.py index 26f3f97d..76b974fb 100644 --- a/py/services/download_manager.py +++ b/py/services/download_manager.py @@ -463,7 +463,7 @@ class DownloadManager: # Download the original image to temp path using downloader downloader = await get_downloader() - success, content = await downloader.download_to_memory( + success, content, headers = await downloader.download_to_memory( images[0]['url'], use_auth=False ) diff --git a/py/utils/routes_common.py b/py/utils/routes_common.py index 3be2677f..db2f94db 100644 --- a/py/utils/routes_common.py +++ b/py/utils/routes_common.py @@ -141,7 +141,7 @@ class ModelRouteUtils: else: # For images, download and then optimize to WebP using downloader downloader = await get_downloader() - success, content = await downloader.download_to_memory( + success, content, headers = await downloader.download_to_memory( first_preview['url'], use_auth=False ) From 0dc4b6f7284dfe815da87d12cdac025849d06b01 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 15 Sep 2025 20:18:39 +0800 Subject: [PATCH 022/110] refactor(showcase): improve custom image identification logic in renderMediaItem and findLocalFile functions --- static/js/components/shared/showcase/MediaRenderers.js | 2 -- static/js/components/shared/showcase/ShowcaseView.js | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/static/js/components/shared/showcase/MediaRenderers.js b/static/js/components/shared/showcase/MediaRenderers.js index b8ef109f..9f1a6726 100644 --- a/static/js/components/shared/showcase/MediaRenderers.js +++ b/static/js/components/shared/showcase/MediaRenderers.js @@ -75,8 +75,6 @@ export function generateImageWrapper(media, heightPercent, shouldBlur, nsfwText, data-remote-src="${remoteUrl}" data-nsfw-level="${nsfwLevel}" alt="Preview" - crossorigin="anonymous" - referrerpolicy="no-referrer" width="${media.width}" height="${media.height}" class="lazy ${shouldBlur ? 'blurred' : ''}"> diff --git a/static/js/components/shared/showcase/ShowcaseView.js b/static/js/components/shared/showcase/ShowcaseView.js index e5ccfae0..b4b96b0f 100644 --- a/static/js/components/shared/showcase/ShowcaseView.js +++ b/static/js/components/shared/showcase/ShowcaseView.js @@ -191,7 +191,7 @@ function renderMediaItem(img, index, exampleFiles) { ); // Determine if this is a custom image (has id property) - const isCustomImage = Boolean(img.id); + const isCustomImage = Boolean(typeof img.id === 'string' && img.id); // Create the media control buttons HTML const mediaControlsHtml = ` @@ -235,7 +235,7 @@ function findLocalFile(img, index, exampleFiles) { let localFile = null; - if (img.id) { + if (typeof img.id === 'string' && img.id) { // This is a custom image, find by custom_ const customPrefix = `custom_${img.id}`; localFile = exampleFiles.find(file => file.name.startsWith(customPrefix)); From 64e1dd3dd68e496cd8cd2a9d516e057221a4d4b0 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 15 Sep 2025 21:35:24 +0800 Subject: [PATCH 023/110] chore(release): update release notes for v0.9.3 with new features and bug fixes --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 1627d434..7e932acc 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,11 @@ Enhance your Civitai browsing experience with our companion browser extension! S ## Release Notes +### v0.9.3 +* **Metadata Archive Database Support** - Added the ability to download and utilize a metadata archive database, enabling access to metadata for models that have been deleted from CivitAI. +* **App-Level Proxy Settings** - Introduced support for configuring a global proxy within the application, making it easier to use the manager behind network restrictions. +* **Bug Fixes** - Various bug fixes for improved stability and reliability. + ### v0.9.2 * **Bulk Auto-Organization Action** - Added a new bulk auto-organization feature. You can now select multiple models and automatically organize them according to your current path template settings for streamlined management. * **Bug Fixes** - Addressed several bugs to improve stability and reliability. From 30956aeefc4d394a70de7f0385e5a37ac4f9c230 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Tue, 16 Sep 2025 15:05:31 +0800 Subject: [PATCH 024/110] feat(middleware): add cache control middleware to manage response caching for image files --- middleware/__init__.py | 1 + middleware/cache_middleware.py | 52 ++++++++++++++++++++++++++++++++++ standalone.py | 3 +- 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 middleware/__init__.py create mode 100644 middleware/cache_middleware.py diff --git a/middleware/__init__.py b/middleware/__init__.py new file mode 100644 index 00000000..2d7c7c3a --- /dev/null +++ b/middleware/__init__.py @@ -0,0 +1 @@ +"""Server middleware modules""" diff --git a/middleware/cache_middleware.py b/middleware/cache_middleware.py new file mode 100644 index 00000000..374ef793 --- /dev/null +++ b/middleware/cache_middleware.py @@ -0,0 +1,52 @@ +"""Cache control middleware for ComfyUI server""" + +from aiohttp import web +from typing import Callable, Awaitable + +# Time in seconds +ONE_HOUR: int = 3600 +ONE_DAY: int = 86400 +IMG_EXTENSIONS = ( + ".jpg", + ".jpeg", + ".png", + ".ppm", + ".bmp", + ".pgm", + ".tif", + ".tiff", + ".webp", +) + + +@web.middleware +async def cache_control( + request: web.Request, handler: Callable[[web.Request], Awaitable[web.Response]] +) -> web.Response: + """Cache control middleware that sets appropriate cache headers based on file type and response status""" + response: web.Response = await handler(request) + + if ( + request.path.endswith(".js") + or request.path.endswith(".css") + or request.path.endswith("index.json") + ): + response.headers.setdefault("Cache-Control", "no-cache") + return response + + # Early return for non-image files - no cache headers needed + if not request.path.lower().endswith(IMG_EXTENSIONS): + return response + + # Handle image files + if response.status == 404: + response.headers.setdefault("Cache-Control", f"public, max-age={ONE_HOUR}") + elif response.status in (200, 201, 202, 203, 204, 205, 206, 301, 308): + # Success responses and permanent redirects - cache for 1 day + response.headers.setdefault("Cache-Control", f"public, max-age={ONE_DAY}") + elif response.status in (302, 303, 307): + # Temporary redirects - no cache + response.headers.setdefault("Cache-Control", "no-cache") + # Note: 304 Not Modified falls through - no cache headers set + + return response diff --git a/standalone.py b/standalone.py index b8532abf..56d4545d 100644 --- a/standalone.py +++ b/standalone.py @@ -2,6 +2,7 @@ from pathlib import Path import os import sys import json +from middleware.cache_middleware import cache_control # Create mock modules for py/nodes directory - add this before any other imports def mock_nodes_directory(): @@ -129,7 +130,7 @@ class StandaloneServer: """Server implementation for standalone mode""" def __init__(self): - self.app = web.Application(logger=logger) + self.app = web.Application(logger=logger, middlewares=[cache_control]) self.instance = self # Make it compatible with PromptServer.instance pattern # Ensure the app's access logger is configured to reduce verbosity From 4275dc30037cdec77b073c3732e9f1e2dab1d0a2 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Tue, 16 Sep 2025 15:16:53 +0800 Subject: [PATCH 025/110] refactor(middleware): reorganize cache middleware into py directory and update import paths --- {middleware => py/middleware}/__init__.py | 0 {middleware => py/middleware}/cache_middleware.py | 0 standalone.py | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename {middleware => py/middleware}/__init__.py (100%) rename {middleware => py/middleware}/cache_middleware.py (100%) diff --git a/middleware/__init__.py b/py/middleware/__init__.py similarity index 100% rename from middleware/__init__.py rename to py/middleware/__init__.py diff --git a/middleware/cache_middleware.py b/py/middleware/cache_middleware.py similarity index 100% rename from middleware/cache_middleware.py rename to py/middleware/cache_middleware.py diff --git a/standalone.py b/standalone.py index 56d4545d..f38a89fc 100644 --- a/standalone.py +++ b/standalone.py @@ -2,7 +2,7 @@ from pathlib import Path import os import sys import json -from middleware.cache_middleware import cache_control +from py.middleware.cache_middleware import cache_control # Create mock modules for py/nodes directory - add this before any other imports def mock_nodes_directory(): From 0566d50346e2517aae7c31e44283cbd361b098ac Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Tue, 16 Sep 2025 15:39:12 +0800 Subject: [PATCH 026/110] feat(middleware): add .mp4 to image extensions for cache control --- py/middleware/cache_middleware.py | 1 + 1 file changed, 1 insertion(+) diff --git a/py/middleware/cache_middleware.py b/py/middleware/cache_middleware.py index 374ef793..4df22b30 100644 --- a/py/middleware/cache_middleware.py +++ b/py/middleware/cache_middleware.py @@ -16,6 +16,7 @@ IMG_EXTENSIONS = ( ".tif", ".tiff", ".webp", + ".mp4" ) From adf7b6d4b21fb3b0bc010a5f130c0db1f0931388 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Tue, 16 Sep 2025 18:55:59 +0800 Subject: [PATCH 027/110] chore(version): bump version to 0.9.3 in pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 202fb961..1ad4e018 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui-lora-manager" description = "Revolutionize your workflow with the ultimate LoRA companion for ComfyUI!" -version = "0.9.2" +version = "0.9.3" license = {file = "LICENSE"} dependencies = [ "aiohttp", From 183c000080e47bbcc052d96e2ef46ed681412715 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Tue, 16 Sep 2025 21:48:20 +0800 Subject: [PATCH 028/110] Refactor ComfyUI: Remove legacy tags widget and related dynamic imports - Deleted the legacy tags widget implementation from legacy_tags_widget.js. - Updated trigger_word_toggle.js to directly import the new tags widget. - Removed unused dynamic import functions and version checks from utils.js. - Cleaned up lora_loader.js and lora_stacker.js by removing redundant node registration code. --- web/comfyui/legacy_loras_widget.js | 978 ----------------------------- web/comfyui/legacy_tags_widget.js | 193 ------ web/comfyui/lora_loader.js | 26 - web/comfyui/lora_stacker.js | 25 - web/comfyui/trigger_word_toggle.js | 12 +- web/comfyui/utils.js | 32 - 6 files changed, 2 insertions(+), 1264 deletions(-) delete mode 100644 web/comfyui/legacy_loras_widget.js delete mode 100644 web/comfyui/legacy_tags_widget.js diff --git a/web/comfyui/legacy_loras_widget.js b/web/comfyui/legacy_loras_widget.js deleted file mode 100644 index bf2ba96f..00000000 --- a/web/comfyui/legacy_loras_widget.js +++ /dev/null @@ -1,978 +0,0 @@ -import { api } from "../../scripts/api.js"; -import { app } from "../../scripts/app.js"; - -export function addLorasWidget(node, name, opts, callback) { - // Create container for loras - const container = document.createElement("div"); - container.className = "comfy-loras-container"; - Object.assign(container.style, { - display: "flex", - flexDirection: "column", - gap: "8px", - padding: "6px", - backgroundColor: "rgba(40, 44, 52, 0.6)", - borderRadius: "6px", - width: "100%", - }); - - // Initialize default value - const defaultValue = opts?.defaultVal || []; - - // Parse LoRA entries from value - const parseLoraValue = (value) => { - if (!value) return []; - return Array.isArray(value) ? value : []; - }; - - // Format LoRA data - const formatLoraValue = (loras) => { - return loras; - }; - - // Function to create toggle element - const createToggle = (active, onChange) => { - const toggle = document.createElement("div"); - toggle.className = "comfy-lora-toggle"; - - updateToggleStyle(toggle, active); - - toggle.addEventListener("click", (e) => { - e.stopPropagation(); - onChange(!active); - }); - - return toggle; - }; - - // Helper function to update toggle style - function updateToggleStyle(toggleEl, active) { - Object.assign(toggleEl.style, { - width: "18px", - height: "18px", - borderRadius: "4px", - cursor: "pointer", - transition: "all 0.2s ease", - backgroundColor: active ? "rgba(66, 153, 225, 0.9)" : "rgba(45, 55, 72, 0.7)", - border: `1px solid ${active ? "rgba(66, 153, 225, 0.9)" : "rgba(226, 232, 240, 0.2)"}`, - }); - - // Add hover effect - toggleEl.onmouseenter = () => { - toggleEl.style.transform = "scale(1.05)"; - toggleEl.style.boxShadow = "0 2px 4px rgba(0,0,0,0.15)"; - }; - - toggleEl.onmouseleave = () => { - toggleEl.style.transform = "scale(1)"; - toggleEl.style.boxShadow = "none"; - }; - } - - // Create arrow button for strength adjustment - const createArrowButton = (direction, onClick) => { - const button = document.createElement("div"); - button.className = `comfy-lora-arrow comfy-lora-arrow-${direction}`; - - Object.assign(button.style, { - width: "16px", - height: "16px", - display: "flex", - alignItems: "center", - justifyContent: "center", - cursor: "pointer", - userSelect: "none", - fontSize: "12px", - color: "rgba(226, 232, 240, 0.8)", - transition: "all 0.2s ease", - }); - - button.textContent = direction === "left" ? "◀" : "▶"; - - button.addEventListener("click", (e) => { - e.stopPropagation(); - onClick(); - }); - - // Add hover effect - button.onmouseenter = () => { - button.style.color = "white"; - button.style.transform = "scale(1.2)"; - }; - - button.onmouseleave = () => { - button.style.color = "rgba(226, 232, 240, 0.8)"; - button.style.transform = "scale(1)"; - }; - - return button; - }; - - // 添加预览弹窗组件 - class PreviewTooltip { - constructor() { - this.element = document.createElement('div'); - Object.assign(this.element.style, { - position: 'fixed', - zIndex: 9999, - background: 'rgba(0, 0, 0, 0.85)', - borderRadius: '6px', - boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)', - display: 'none', - overflow: 'hidden', - maxWidth: '300px', - }); - document.body.appendChild(this.element); - this.hideTimeout = null; // 添加超时处理变量 - - // 添加全局点击事件来隐藏tooltip - document.addEventListener('click', () => this.hide()); - - // 添加滚动事件监听 - document.addEventListener('scroll', () => this.hide(), true); - } - - async show(loraName, x, y) { - try { - // 清除之前的隐藏定时器 - if (this.hideTimeout) { - clearTimeout(this.hideTimeout); - this.hideTimeout = null; - } - - // 如果已经显示同一个lora的预览,则不重复显示 - if (this.element.style.display === 'block' && this.currentLora === loraName) { - return; - } - - this.currentLora = loraName; - - // 获取预览URL - const response = await api.fetchApi(`/loras/preview-url?name=${encodeURIComponent(loraName)}`, { - method: 'GET' - }); - - if (!response.ok) { - throw new Error('Failed to fetch preview URL'); - } - - const data = await response.json(); - if (!data.success || !data.preview_url) { - throw new Error('No preview available'); - } - - // 清除现有内容 - while (this.element.firstChild) { - this.element.removeChild(this.element.firstChild); - } - - // Create media container with relative positioning - const mediaContainer = document.createElement('div'); - Object.assign(mediaContainer.style, { - position: 'relative', - maxWidth: '300px', - maxHeight: '300px', - }); - - const isVideo = data.preview_url.endsWith('.mp4'); - const mediaElement = isVideo ? document.createElement('video') : document.createElement('img'); - - Object.assign(mediaElement.style, { - maxWidth: '300px', - maxHeight: '300px', - objectFit: 'contain', - display: 'block', - }); - - if (isVideo) { - mediaElement.autoplay = true; - mediaElement.loop = true; - mediaElement.muted = true; - mediaElement.controls = false; - } - - mediaElement.src = data.preview_url; - - // Create name label with absolute positioning - const nameLabel = document.createElement('div'); - nameLabel.textContent = loraName; - Object.assign(nameLabel.style, { - position: 'absolute', - bottom: '0', - left: '0', - right: '0', - padding: '8px', - color: 'rgba(255, 255, 255, 0.95)', - fontSize: '13px', - fontFamily: "'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif", - background: 'linear-gradient(transparent, rgba(0, 0, 0, 0.8))', - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - textAlign: 'center', - backdropFilter: 'blur(4px)', - WebkitBackdropFilter: 'blur(4px)', - }); - - mediaContainer.appendChild(mediaElement); - mediaContainer.appendChild(nameLabel); - this.element.appendChild(mediaContainer); - - // 添加淡入效果 - this.element.style.opacity = '0'; - this.element.style.display = 'block'; - this.position(x, y); - - requestAnimationFrame(() => { - this.element.style.transition = 'opacity 0.15s ease'; - this.element.style.opacity = '1'; - }); - } catch (error) { - console.warn('Failed to load preview:', error); - } - } - - position(x, y) { - // 确保预览框不超出视窗边界 - const rect = this.element.getBoundingClientRect(); - const viewportWidth = window.innerWidth; - const viewportHeight = window.innerHeight; - - let left = x + 10; // 默认在鼠标右侧偏移10px - let top = y + 10; // 默认在鼠标下方偏移10px - - // 检查右边界 - if (left + rect.width > viewportWidth) { - left = x - rect.width - 10; - } - - // 检查下边界 - if (top + rect.height > viewportHeight) { - top = y - rect.height - 10; - } - - Object.assign(this.element.style, { - left: `${left}px`, - top: `${top}px` - }); - } - - hide() { - // 使用淡出效果 - if (this.element.style.display === 'block') { - this.element.style.opacity = '0'; - this.hideTimeout = setTimeout(() => { - this.element.style.display = 'none'; - this.currentLora = null; - // 停止视频播放 - const video = this.element.querySelector('video'); - if (video) { - video.pause(); - } - this.hideTimeout = null; - }, 150); - } - } - - cleanup() { - if (this.hideTimeout) { - clearTimeout(this.hideTimeout); - } - // 移除所有事件监听器 - document.removeEventListener('click', () => this.hide()); - document.removeEventListener('scroll', () => this.hide(), true); - this.element.remove(); - } - } - - // 创建预览tooltip实例 - const previewTooltip = new PreviewTooltip(); - - // Function to handle strength adjustment via dragging - const handleStrengthDrag = (name, initialStrength, initialX, event, widget) => { - // Calculate drag sensitivity (how much the strength changes per pixel) - // Using 0.01 per 10 pixels of movement - const sensitivity = 0.001; - - // Get the current mouse position - const currentX = event.clientX; - - // Calculate the distance moved - const deltaX = currentX - initialX; - - // Calculate the new strength value based on movement - // Moving right increases, moving left decreases - let newStrength = Number(initialStrength) + (deltaX * sensitivity); - - // Limit the strength to reasonable bounds (now between -10 and 10) - newStrength = Math.max(-10, Math.min(10, newStrength)); - newStrength = Number(newStrength.toFixed(2)); - - // Update the lora data - const lorasData = parseLoraValue(widget.value); - const loraIndex = lorasData.findIndex(l => l.name === name); - - if (loraIndex >= 0) { - lorasData[loraIndex].strength = newStrength; - - // Update the widget value - widget.value = formatLoraValue(lorasData); - - // Force re-render to show updated strength value - renderLoras(widget.value, widget); - } - }; - - // Function to initialize drag operation - const initDrag = (loraEl, nameEl, name, widget) => { - let isDragging = false; - let initialX = 0; - let initialStrength = 0; - - // Create a style element for drag cursor override if it doesn't exist - if (!document.getElementById('comfy-lora-drag-style')) { - const styleEl = document.createElement('style'); - styleEl.id = 'comfy-lora-drag-style'; - styleEl.textContent = ` - body.comfy-lora-dragging, - body.comfy-lora-dragging * { - cursor: ew-resize !important; - } - `; - document.head.appendChild(styleEl); - } - - // Create a drag handler that's applied to the entire lora entry - // except toggle and strength controls - loraEl.addEventListener('mousedown', (e) => { - // Skip if clicking on toggle or strength control areas - if (e.target.closest('.comfy-lora-toggle') || - e.target.closest('input') || - e.target.closest('.comfy-lora-arrow')) { - return; - } - - // Store initial values - const lorasData = parseLoraValue(widget.value); - const loraData = lorasData.find(l => l.name === name); - - if (!loraData) return; - - initialX = e.clientX; - initialStrength = loraData.strength; - isDragging = true; - - // Add class to body to enforce cursor style globally - document.body.classList.add('comfy-lora-dragging'); - - // Prevent text selection during drag - e.preventDefault(); - }); - - // Use the document for move and up events to ensure drag continues - // even if mouse leaves the element - document.addEventListener('mousemove', (e) => { - if (!isDragging) return; - - // Call the strength adjustment function - handleStrengthDrag(name, initialStrength, initialX, e, widget); - - // Prevent showing the preview tooltip during drag - previewTooltip.hide(); - }); - - document.addEventListener('mouseup', () => { - if (isDragging) { - isDragging = false; - // Remove the class to restore normal cursor behavior - document.body.classList.remove('comfy-lora-dragging'); - } - }); - }; - - // Function to create menu item - const createMenuItem = (text, icon, onClick) => { - const menuItem = document.createElement('div'); - Object.assign(menuItem.style, { - padding: '6px 20px', - cursor: 'pointer', - color: 'rgba(226, 232, 240, 0.9)', - fontSize: '13px', - userSelect: 'none', - display: 'flex', - alignItems: 'center', - gap: '8px', - }); - - // Create icon element - const iconEl = document.createElement('div'); - iconEl.innerHTML = icon; - Object.assign(iconEl.style, { - width: '14px', - height: '14px', - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - }); - - // Create text element - const textEl = document.createElement('span'); - textEl.textContent = text; - - menuItem.appendChild(iconEl); - menuItem.appendChild(textEl); - - menuItem.addEventListener('mouseenter', () => { - menuItem.style.backgroundColor = 'rgba(66, 153, 225, 0.2)'; - }); - - menuItem.addEventListener('mouseleave', () => { - menuItem.style.backgroundColor = 'transparent'; - }); - - if (onClick) { - menuItem.addEventListener('click', onClick); - } - - return menuItem; - }; - - // Function to create context menu - const createContextMenu = (x, y, loraName, widget) => { - // Hide preview tooltip first - previewTooltip.hide(); - - // Remove existing context menu if any - const existingMenu = document.querySelector('.comfy-lora-context-menu'); - if (existingMenu) { - existingMenu.remove(); - } - - const menu = document.createElement('div'); - menu.className = 'comfy-lora-context-menu'; - Object.assign(menu.style, { - position: 'fixed', - left: `${x}px`, - top: `${y}px`, - backgroundColor: 'rgba(30, 30, 30, 0.95)', - border: '1px solid rgba(255, 255, 255, 0.1)', - borderRadius: '4px', - padding: '4px 0', - zIndex: 1000, - boxShadow: '0 2px 10px rgba(0,0,0,0.2)', - minWidth: '180px', - }); - - // View on Civitai option with globe icon - const viewOnCivitaiOption = createMenuItem( - 'View on Civitai', - '', - async () => { - menu.remove(); - document.removeEventListener('click', closeMenu); - - try { - // Get Civitai URL from API - const response = await api.fetchApi(`/loras/civitai-url?name=${encodeURIComponent(loraName)}`, { - method: 'GET' - }); - - if (!response.ok) { - const errorText = await response.text(); - throw new Error(errorText || 'Failed to get Civitai URL'); - } - - const data = await response.json(); - if (data.success && data.civitai_url) { - // Open the URL in a new tab - window.open(data.civitai_url, '_blank'); - } else { - // Show error message if no Civitai URL - if (app && app.extensionManager && app.extensionManager.toast) { - app.extensionManager.toast.add({ - severity: 'warning', - summary: 'Not Found', - detail: 'This LoRA has no associated Civitai URL', - life: 3000 - }); - } else { - alert('This LoRA has no associated Civitai URL'); - } - } - } catch (error) { - console.error('Error getting Civitai URL:', error); - if (app && app.extensionManager && app.extensionManager.toast) { - app.extensionManager.toast.add({ - severity: 'error', - summary: 'Error', - detail: error.message || 'Failed to get Civitai URL', - life: 5000 - }); - } else { - alert('Error: ' + (error.message || 'Failed to get Civitai URL')); - } - } - } - ); - - // Delete option with trash icon - const deleteOption = createMenuItem( - 'Delete', - '', - () => { - menu.remove(); - document.removeEventListener('click', closeMenu); - - const lorasData = parseLoraValue(widget.value).filter(l => l.name !== loraName); - widget.value = formatLoraValue(lorasData); - - if (widget.callback) { - widget.callback(widget.value); - } - } - ); - - // Save recipe option with bookmark icon - const saveOption = createMenuItem( - 'Save Recipe', - '', - () => { - menu.remove(); - document.removeEventListener('click', closeMenu); - saveRecipeDirectly(widget); - } - ); - - // Add separator - const separator = document.createElement('div'); - Object.assign(separator.style, { - margin: '4px 0', - borderTop: '1px solid rgba(255, 255, 255, 0.1)', - }); - - menu.appendChild(viewOnCivitaiOption); // Add the new menu option - menu.appendChild(deleteOption); - menu.appendChild(separator); - menu.appendChild(saveOption); - - document.body.appendChild(menu); - - // Close menu when clicking outside - const closeMenu = (e) => { - if (!menu.contains(e.target)) { - menu.remove(); - document.removeEventListener('click', closeMenu); - } - }; - setTimeout(() => document.addEventListener('click', closeMenu), 0); - }; - - // Function to render loras from data - const renderLoras = (value, widget) => { - // Clear existing content - while (container.firstChild) { - container.removeChild(container.firstChild); - } - - // Parse the loras data - const lorasData = parseLoraValue(value); - - if (lorasData.length === 0) { - // Show message when no loras are added - const emptyMessage = document.createElement("div"); - emptyMessage.textContent = "No LoRAs added"; - Object.assign(emptyMessage.style, { - textAlign: "center", - padding: "20px 0", - color: "rgba(226, 232, 240, 0.8)", - fontStyle: "italic", - userSelect: "none", // Add this line to prevent text selection - WebkitUserSelect: "none", // For Safari support - MozUserSelect: "none", // For Firefox support - msUserSelect: "none", // For IE/Edge support - }); - container.appendChild(emptyMessage); - return; - } - - // Create header - const header = document.createElement("div"); - header.className = "comfy-loras-header"; - Object.assign(header.style, { - display: "flex", - justifyContent: "space-between", - alignItems: "center", - padding: "4px 8px", - borderBottom: "1px solid rgba(226, 232, 240, 0.2)", - marginBottom: "8px" - }); - - // Add toggle all control - const allActive = lorasData.every(lora => lora.active); - const toggleAll = createToggle(allActive, (active) => { - // Update all loras active state - const lorasData = parseLoraValue(widget.value); - lorasData.forEach(lora => lora.active = active); - - const newValue = formatLoraValue(lorasData); - widget.value = newValue; - }); - - // Add label to toggle all - const toggleLabel = document.createElement("div"); - toggleLabel.textContent = "Toggle All"; - Object.assign(toggleLabel.style, { - color: "rgba(226, 232, 240, 0.8)", - fontSize: "13px", - marginLeft: "8px", - userSelect: "none", // Add this line to prevent text selection - WebkitUserSelect: "none", // For Safari support - MozUserSelect: "none", // For Firefox support - msUserSelect: "none", // For IE/Edge support - }); - - const toggleContainer = document.createElement("div"); - Object.assign(toggleContainer.style, { - display: "flex", - alignItems: "center", - }); - toggleContainer.appendChild(toggleAll); - toggleContainer.appendChild(toggleLabel); - - // Strength label - const strengthLabel = document.createElement("div"); - strengthLabel.textContent = "Strength"; - Object.assign(strengthLabel.style, { - color: "rgba(226, 232, 240, 0.8)", - fontSize: "13px", - marginRight: "8px", - userSelect: "none", // Add this line to prevent text selection - WebkitUserSelect: "none", // For Safari support - MozUserSelect: "none", // For Firefox support - msUserSelect: "none", // For IE/Edge support - }); - - header.appendChild(toggleContainer); - header.appendChild(strengthLabel); - container.appendChild(header); - - // Render each lora entry - lorasData.forEach((loraData) => { - const { name, strength, active } = loraData; - - const loraEl = document.createElement("div"); - loraEl.className = "comfy-lora-entry"; - Object.assign(loraEl.style, { - display: "flex", - justifyContent: "space-between", - alignItems: "center", - padding: "8px", - borderRadius: "6px", - backgroundColor: active ? "rgba(45, 55, 72, 0.7)" : "rgba(35, 40, 50, 0.5)", - transition: "all 0.2s ease", - marginBottom: "6px", - }); - - // Create toggle for this lora - const toggle = createToggle(active, (newActive) => { - // Update this lora's active state - const lorasData = parseLoraValue(widget.value); - const loraIndex = lorasData.findIndex(l => l.name === name); - - if (loraIndex >= 0) { - lorasData[loraIndex].active = newActive; - - const newValue = formatLoraValue(lorasData); - widget.value = newValue; - } - }); - - // Create name display - const nameEl = document.createElement("div"); - nameEl.textContent = name; - Object.assign(nameEl.style, { - marginLeft: "10px", - flex: "1", - overflow: "hidden", - textOverflow: "ellipsis", - whiteSpace: "nowrap", - color: active ? "rgba(226, 232, 240, 0.9)" : "rgba(226, 232, 240, 0.6)", - fontSize: "13px", - cursor: "pointer", // Add pointer cursor to indicate hoverable area - userSelect: "none", // Add this line to prevent text selection - WebkitUserSelect: "none", // For Safari support - MozUserSelect: "none", // For Firefox support - msUserSelect: "none", // For IE/Edge support - }); - - // Move preview tooltip events to nameEl instead of loraEl - nameEl.addEventListener('mouseenter', async (e) => { - e.stopPropagation(); - const rect = nameEl.getBoundingClientRect(); - await previewTooltip.show(name, rect.right, rect.top); - }); - - nameEl.addEventListener('mouseleave', (e) => { - e.stopPropagation(); - previewTooltip.hide(); - }); - - // Remove the preview tooltip events from loraEl - loraEl.onmouseenter = () => { - loraEl.style.backgroundColor = active ? "rgba(50, 60, 80, 0.8)" : "rgba(40, 45, 55, 0.6)"; - }; - - loraEl.onmouseleave = () => { - loraEl.style.backgroundColor = active ? "rgba(45, 55, 72, 0.7)" : "rgba(35, 40, 50, 0.5)"; - }; - - // Add context menu event - loraEl.addEventListener('contextmenu', (e) => { - e.preventDefault(); - e.stopPropagation(); - createContextMenu(e.clientX, e.clientY, name, widget); - }); - - // Create strength control - const strengthControl = document.createElement("div"); - Object.assign(strengthControl.style, { - display: "flex", - alignItems: "center", - gap: "8px", - }); - - // Left arrow - const leftArrow = createArrowButton("left", () => { - // Decrease strength - const lorasData = parseLoraValue(widget.value); - const loraIndex = lorasData.findIndex(l => l.name === name); - - if (loraIndex >= 0) { - lorasData[loraIndex].strength = (lorasData[loraIndex].strength - 0.05).toFixed(2); - - const newValue = formatLoraValue(lorasData); - widget.value = newValue; - } - }); - - // Strength display - const strengthEl = document.createElement("input"); - strengthEl.type = "text"; - strengthEl.value = typeof strength === 'number' ? strength.toFixed(2) : Number(strength).toFixed(2); - Object.assign(strengthEl.style, { - minWidth: "50px", - width: "50px", - textAlign: "center", - color: active ? "rgba(226, 232, 240, 0.9)" : "rgba(226, 232, 240, 0.6)", - fontSize: "13px", - background: "none", - border: "1px solid transparent", - padding: "2px 4px", - borderRadius: "3px", - outline: "none", - }); - - // 添加hover效果 - strengthEl.addEventListener('mouseenter', () => { - strengthEl.style.border = "1px solid rgba(226, 232, 240, 0.2)"; - }); - - strengthEl.addEventListener('mouseleave', () => { - if (document.activeElement !== strengthEl) { - strengthEl.style.border = "1px solid transparent"; - } - }); - - // 处理焦点 - strengthEl.addEventListener('focus', () => { - strengthEl.style.border = "1px solid rgba(66, 153, 225, 0.6)"; - strengthEl.style.background = "rgba(0, 0, 0, 0.2)"; - // 自动选中所有内容 - strengthEl.select(); - }); - - strengthEl.addEventListener('blur', () => { - strengthEl.style.border = "1px solid transparent"; - strengthEl.style.background = "none"; - }); - - // 处理输入变化 - strengthEl.addEventListener('change', () => { - let newValue = parseFloat(strengthEl.value); - - // 验证输入 - if (isNaN(newValue)) { - newValue = 1.0; - } - - // 更新数值 - const lorasData = parseLoraValue(widget.value); - const loraIndex = lorasData.findIndex(l => l.name === name); - - if (loraIndex >= 0) { - lorasData[loraIndex].strength = newValue.toFixed(2); - - // 更新值并触发回调 - const newLorasValue = formatLoraValue(lorasData); - widget.value = newLorasValue; - } - }); - - // 处理按键事件 - strengthEl.addEventListener('keydown', (e) => { - if (e.key === 'Enter') { - strengthEl.blur(); - } - }); - - // Right arrow - const rightArrow = createArrowButton("right", () => { - // Increase strength - const lorasData = parseLoraValue(widget.value); - const loraIndex = lorasData.findIndex(l => l.name === name); - - if (loraIndex >= 0) { - lorasData[loraIndex].strength = (parseFloat(lorasData[loraIndex].strength) + 0.05).toFixed(2); - - const newValue = formatLoraValue(lorasData); - widget.value = newValue; - } - }); - - strengthControl.appendChild(leftArrow); - strengthControl.appendChild(strengthEl); - strengthControl.appendChild(rightArrow); - - // Assemble entry - const leftSection = document.createElement("div"); - Object.assign(leftSection.style, { - display: "flex", - alignItems: "center", - flex: "1", - minWidth: "0", // Allow shrinking - }); - - leftSection.appendChild(toggle); - leftSection.appendChild(nameEl); - - loraEl.appendChild(leftSection); - loraEl.appendChild(strengthControl); - - container.appendChild(loraEl); - - // Initialize drag functionality - initDrag(loraEl, nameEl, name, widget); - }); - }; - - // Store the value in a variable to avoid recursion - let widgetValue = defaultValue; - - // Create widget with initial properties - const widget = node.addDOMWidget(name, "loras", container, { - getValue: function() { - return widgetValue; - }, - setValue: function(v) { - // Remove duplicates by keeping the last occurrence of each lora name - const uniqueValue = (v || []).reduce((acc, lora) => { - // Remove any existing lora with the same name - const filtered = acc.filter(l => l.name !== lora.name); - // Add the current lora - return [...filtered, lora]; - }, []); - - widgetValue = uniqueValue; - renderLoras(widgetValue, widget); - - // Update container height after rendering - requestAnimationFrame(() => { - const minHeight = this.getMinHeight(); - container.style.height = `${minHeight}px`; - - // Force node to update size - node.setSize([node.size[0], node.computeSize()[1]]); - node.setDirtyCanvas(true, true); - }); - }, - getMinHeight: function() { - // Calculate height based on content - const lorasCount = parseLoraValue(widgetValue).length; - return Math.max( - 100, - lorasCount > 0 ? 60 + lorasCount * 44 : 60 - ); - }, - }); - - widget.value = defaultValue; - - widget.callback = callback; - - widget.serializeValue = () => { - // Add dummy items to avoid the 2-element serialization issue, a bug in comfyui - return [...widgetValue, - { name: "__dummy_item1__", strength: 0, active: false, _isDummy: true }, - { name: "__dummy_item2__", strength: 0, active: false, _isDummy: true } - ]; - } - - widget.onRemove = () => { - container.remove(); - previewTooltip.cleanup(); - }; - - return { minWidth: 400, minHeight: 200, widget }; -} - -// Function to directly save the recipe without dialog -async function saveRecipeDirectly(widget) { - try { - // Show loading toast - if (app && app.extensionManager && app.extensionManager.toast) { - app.extensionManager.toast.add({ - severity: 'info', - summary: 'Saving Recipe', - detail: 'Please wait...', - life: 2000 - }); - } - - // Send the request - const response = await fetch('/api/recipes/save-from-widget', { - method: 'POST' - }); - - const result = await response.json(); - - // Show result toast - if (app && app.extensionManager && app.extensionManager.toast) { - if (result.success) { - app.extensionManager.toast.add({ - severity: 'success', - summary: 'Recipe Saved', - detail: 'Recipe has been saved successfully', - life: 3000 - }); - } else { - app.extensionManager.toast.add({ - severity: 'error', - summary: 'Error', - detail: result.error || 'Failed to save recipe', - life: 5000 - }); - } - } - } catch (error) { - console.error('Error saving recipe:', error); - - // Show error toast - if (app && app.extensionManager && app.extensionManager.toast) { - app.extensionManager.toast.add({ - severity: 'error', - summary: 'Error', - detail: 'Failed to save recipe: ' + (error.message || 'Unknown error'), - life: 5000 - }); - } - } -} diff --git a/web/comfyui/legacy_tags_widget.js b/web/comfyui/legacy_tags_widget.js deleted file mode 100644 index d43cb016..00000000 --- a/web/comfyui/legacy_tags_widget.js +++ /dev/null @@ -1,193 +0,0 @@ -export function addTagsWidget(node, name, opts, callback) { - // Create container for tags - const container = document.createElement("div"); - container.className = "comfy-tags-container"; - Object.assign(container.style, { - display: "flex", - flexWrap: "wrap", - gap: "4px", // 从8px减小到4px - padding: "6px", - minHeight: "30px", - backgroundColor: "rgba(40, 44, 52, 0.6)", // Darker, more modern background - borderRadius: "6px", // Slightly larger radius - width: "100%", - }); - - // Initialize default value as array - const initialTagsData = opts?.defaultVal || []; - - // Function to render tags from array data - const renderTags = (tagsData, widget) => { - // Clear existing tags - while (container.firstChild) { - container.removeChild(container.firstChild); - } - - const normalizedTags = tagsData; - - if (normalizedTags.length === 0) { - // Show message when no tags are present - const emptyMessage = document.createElement("div"); - emptyMessage.textContent = "No trigger words detected"; - Object.assign(emptyMessage.style, { - textAlign: "center", - padding: "20px 0", - color: "rgba(226, 232, 240, 0.8)", - fontStyle: "italic", - userSelect: "none", - WebkitUserSelect: "none", - MozUserSelect: "none", - msUserSelect: "none", - }); - container.appendChild(emptyMessage); - return; - } - - normalizedTags.forEach((tagData, index) => { - const { text, active } = tagData; - const tagEl = document.createElement("div"); - tagEl.className = "comfy-tag"; - - updateTagStyle(tagEl, active); - - tagEl.textContent = text; - tagEl.title = text; // Set tooltip for full content - - // Add click handler to toggle state - tagEl.addEventListener("click", (e) => { - e.stopPropagation(); - - // Toggle active state for this specific tag using its index - const updatedTags = [...widget.value]; - updatedTags[index].active = !updatedTags[index].active; - updateTagStyle(tagEl, updatedTags[index].active); - - widget.value = updatedTags; - }); - - container.appendChild(tagEl); - }); - }; - - // Helper function to update tag style based on active state - function updateTagStyle(tagEl, active) { - const baseStyles = { - padding: "4px 12px", // 垂直内边距从6px减小到4px - borderRadius: "6px", // Matching container radius - maxWidth: "200px", // Increased max width - overflow: "hidden", - textOverflow: "ellipsis", - whiteSpace: "nowrap", - fontSize: "13px", // Slightly larger font - cursor: "pointer", - transition: "all 0.2s ease", // Smoother transition - border: "1px solid transparent", - display: "inline-block", - boxShadow: "0 1px 2px rgba(0,0,0,0.1)", - margin: "2px", // 从4px减小到2px - userSelect: "none", // Add this line to prevent text selection - WebkitUserSelect: "none", // For Safari support - MozUserSelect: "none", // For Firefox support - msUserSelect: "none", // For IE/Edge support - }; - - if (active) { - Object.assign(tagEl.style, { - ...baseStyles, - backgroundColor: "rgba(66, 153, 225, 0.9)", // Modern blue - color: "white", - borderColor: "rgba(66, 153, 225, 0.9)", - }); - } else { - Object.assign(tagEl.style, { - ...baseStyles, - backgroundColor: "rgba(45, 55, 72, 0.7)", // Darker inactive state - color: "rgba(226, 232, 240, 0.8)", // Lighter text for contrast - borderColor: "rgba(226, 232, 240, 0.2)", - }); - } - - // Add hover effect - tagEl.onmouseenter = () => { - tagEl.style.transform = "translateY(-1px)"; - tagEl.style.boxShadow = "0 2px 4px rgba(0,0,0,0.15)"; - }; - - tagEl.onmouseleave = () => { - tagEl.style.transform = "translateY(0)"; - tagEl.style.boxShadow = "0 1px 2px rgba(0,0,0,0.1)"; - }; - } - - // Store the value as array - let widgetValue = initialTagsData; - - // Create widget with initial properties - const widget = node.addDOMWidget(name, "tags", container, { - getValue: function() { - return widgetValue; - }, - setValue: function(v) { - widgetValue = v; - renderTags(widgetValue, widget); - - // Update container height after rendering - requestAnimationFrame(() => { - const minHeight = this.getMinHeight(); - container.style.height = `${minHeight}px`; - - // Force node to update size - node.setSize([node.size[0], node.computeSize()[1]]); - node.setDirtyCanvas(true, true); - }); - }, - getMinHeight: function() { - const minHeight = 150; - // If no tags or only showing the empty message, return a minimum height - if (widgetValue.length === 0) { - return minHeight; // Height for empty state with message - } - - // Get all tag elements - const tagElements = container.querySelectorAll('.comfy-tag'); - - if (tagElements.length === 0) { - return minHeight; // Fallback if elements aren't rendered yet - } - - // Calculate the actual height based on tag positions - let maxBottom = 0; - - tagElements.forEach(tag => { - const rect = tag.getBoundingClientRect(); - const tagBottom = rect.bottom - container.getBoundingClientRect().top; - maxBottom = Math.max(maxBottom, tagBottom); - }); - - // Add padding (top and bottom padding of container) - const computedStyle = window.getComputedStyle(container); - const paddingTop = parseInt(computedStyle.paddingTop, 10) || 0; - const paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0; - - // Add extra buffer for potential wrapping issues and to ensure no clipping - const extraBuffer = 20; - - // Round up to nearest 5px for clean sizing and ensure minimum height - return Math.max(minHeight, Math.ceil((maxBottom + paddingBottom + extraBuffer) / 5) * 5); - }, - }); - - widget.value = initialTagsData; - - widget.callback = callback; - - widget.serializeValue = () => { - // Add dummy items to avoid the 2-element serialization issue, a bug in comfyui - return [...widgetValue, - { text: "__dummy_item__", active: false, _isDummy: true }, - { text: "__dummy_item__", active: false, _isDummy: true } - ]; - }; - - return { minWidth: 300, minHeight: 150, widget }; -} diff --git a/web/comfyui/lora_loader.js b/web/comfyui/lora_loader.js index aa62252f..f13f48a6 100644 --- a/web/comfyui/lora_loader.js +++ b/web/comfyui/lora_loader.js @@ -176,32 +176,6 @@ app.registerExtension({ inputWidget, originalCallback ); - - // Register this node with the backend - this.registerNode = async () => { - try { - await fetch("/api/register-node", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - node_id: this.id, - bgcolor: this.bgcolor, - title: this.title, - graph_id: this.graph.id, - }), - }); - } catch (error) { - console.warn("Failed to register node:", error); - } - }; - - // Ensure the node is registered after creation - // Call registration - // setTimeout(() => { - // this.registerNode(); - // }, 0); }); } }, diff --git a/web/comfyui/lora_stacker.js b/web/comfyui/lora_stacker.js index 9b812926..5648891d 100644 --- a/web/comfyui/lora_stacker.js +++ b/web/comfyui/lora_stacker.js @@ -101,31 +101,6 @@ app.registerExtension({ inputWidget, originalCallback ); - - // Register this node with the backend - this.registerNode = async () => { - try { - await fetch("/api/register-node", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - node_id: this.id, - bgcolor: this.bgcolor, - title: this.title, - graph_id: this.graph.id, - }), - }); - } catch (error) { - console.warn("Failed to register node:", error); - } - }; - - // Call registration - // setTimeout(() => { - // this.registerNode(); - // }, 0); }); } }, diff --git a/web/comfyui/trigger_word_toggle.js b/web/comfyui/trigger_word_toggle.js index 74a3fe1d..57541bd4 100644 --- a/web/comfyui/trigger_word_toggle.js +++ b/web/comfyui/trigger_word_toggle.js @@ -1,11 +1,7 @@ import { app } from "../../scripts/app.js"; import { api } from "../../scripts/api.js"; -import { CONVERTED_TYPE, dynamicImportByVersion } from "./utils.js"; - -// Function to get the appropriate tags widget based on ComfyUI version -async function getTagsWidgetModule() { - return await dynamicImportByVersion("./tags_widget.js", "./legacy_tags_widget.js"); -} +import { CONVERTED_TYPE } from "./utils.js"; +import { addTagsWidget } from "./tags_widget.js"; // TriggerWordToggle extension for ComfyUI app.registerExtension({ @@ -30,10 +26,6 @@ app.registerExtension({ // Wait for node to be properly initialized requestAnimationFrame(async () => { - // Dynamically import the appropriate tags widget module - const tagsModule = await getTagsWidgetModule(); - const { addTagsWidget } = tagsModule; - // Get the widget object directly from the returned object const result = addTagsWidget(node, "toggle_trigger_words", { defaultVal: [] diff --git a/web/comfyui/utils.js b/web/comfyui/utils.js index 760cb46a..08cbff7a 100644 --- a/web/comfyui/utils.js +++ b/web/comfyui/utils.js @@ -20,10 +20,6 @@ export function chainCallback(object, property, callback) { } } -export function getComfyUIFrontendVersion() { - return window['__COMFYUI_FRONTEND_VERSION__'] || "0.0.0"; -} - /** * Show a toast notification * @param {Object|string} options - Toast options object or message string for backward compatibility @@ -78,29 +74,6 @@ export function showToast(options, type = 'info') { } } -// Dynamically import the appropriate widget based on app version -export async function dynamicImportByVersion(latestModulePath, legacyModulePath) { - // Parse app version and compare with 1.12.6 (version when tags widget API changed) - const currentVersion = getComfyUIFrontendVersion(); - const versionParts = currentVersion.split('.').map(part => parseInt(part, 10)); - const requiredVersion = [1, 12, 6]; - - // Compare version numbers - for (let i = 0; i < 3; i++) { - if (versionParts[i] > requiredVersion[i]) { - console.log(`Using latest widget: ${latestModulePath}`); - return import(latestModulePath); - } else if (versionParts[i] < requiredVersion[i]) { - console.log(`Using legacy widget: ${legacyModulePath}`); - return import(legacyModulePath); - } - } - - // If we get here, versions are equal, use the latest module - console.log(`Using latest widget: ${latestModulePath}`); - return import(latestModulePath); -} - export function hideWidgetForGood(node, widget, suffix = "") { widget.origType = widget.type; widget.origComputeSize = widget.computeSize; @@ -124,11 +97,6 @@ export function hideWidgetForGood(node, widget, suffix = "") { } } -// Function to get the appropriate loras widget based on ComfyUI version -export async function getLorasWidgetModule() { - return await dynamicImportByVersion("./loras_widget.js", "./legacy_loras_widget.js"); -} - // Update pattern to match both formats: or export const LORA_PATTERN = //g; From 1cddeee264275aa418fc3bedb69c0e1637cffeeb Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Wed, 17 Sep 2025 11:04:51 +0800 Subject: [PATCH 029/110] style(autocomplete): remove font styles from dropdown for consistency --- web/comfyui/autocomplete.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/comfyui/autocomplete.js b/web/comfyui/autocomplete.js index c8c33244..6e4e8e03 100644 --- a/web/comfyui/autocomplete.js +++ b/web/comfyui/autocomplete.js @@ -47,8 +47,6 @@ class AutoComplete { border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); display: none; - font-family: Arial, sans-serif; - font-size: 14px; min-width: 200px; width: auto; backdrop-filter: blur(8px); From 933e2fc01d14f047f9aaa7e024627410bbfd2ee2 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Wed, 17 Sep 2025 15:47:30 +0800 Subject: [PATCH 030/110] feat(routes): integrate CivitAI model version retrieval for various model types --- py/routes/base_model_routes.py | 107 +++++++++++++++++++++++++++++++-- py/routes/checkpoint_routes.py | 59 +++--------------- py/routes/embedding_routes.py | 59 +++--------------- py/routes/lora_routes.py | 102 +++---------------------------- 4 files changed, 126 insertions(+), 201 deletions(-) diff --git a/py/routes/base_model_routes.py b/py/routes/base_model_routes.py index aea644e3..499d4617 100644 --- a/py/routes/base_model_routes.py +++ b/py/routes/base_model_routes.py @@ -14,6 +14,7 @@ from ..services.settings_manager import settings from ..services.server_i18n import server_i18n from ..services.model_file_service import ModelFileService, ModelMoveService from ..services.websocket_progress_callback import WebSocketProgressCallback +from ..services.metadata_service import get_default_metadata_provider from ..config import config logger = logging.getLogger(__name__) @@ -84,14 +85,17 @@ class BaseModelRoutes(ABC): # Autocomplete route app.router.add_get(f'/api/{prefix}/relative-paths', self.get_relative_paths) + # Common CivitAI integration + app.router.add_get(f'/api/{prefix}/civitai/versions/{{model_id}}', self.get_civitai_versions) + app.router.add_get(f'/api/{prefix}/civitai/model/version/{{modelVersionId}}', self.get_civitai_model_by_version) + app.router.add_get(f'/api/{prefix}/civitai/model/hash/{{hash}}', self.get_civitai_model_by_hash) + # Common Download management app.router.add_post(f'/api/download-model', self.download_model) app.router.add_get(f'/api/download-model-get', self.download_model_get) app.router.add_get(f'/api/cancel-download-get', self.cancel_download_get) app.router.add_get(f'/api/download-progress/{{download_id}}', self.get_download_progress) - # app.router.add_get(f'/api/civitai/versions/{{model_id}}', self.get_civitai_versions) - # Add generic page route app.router.add_get(f'/{prefix}', self.handle_models_page) @@ -704,10 +708,101 @@ class BaseModelRoutes(ABC): async def get_civitai_versions(self, request: web.Request) -> web.Response: """Get available versions for a Civitai model with local availability info""" - # This will be implemented by subclasses as they need CivitAI client access - return web.json_response({ - "error": "Not implemented in base class" - }, status=501) + try: + model_id = request.match_info['model_id'] + metadata_provider = await get_default_metadata_provider() + response = await metadata_provider.get_model_versions(model_id) + if not response or not response.get('modelVersions'): + return web.Response(status=404, text="Model not found") + + versions = response.get('modelVersions', []) + model_type = response.get('type', '') + + # Check model type - allow subclasses to override validation + if not self._validate_civitai_model_type(model_type): + return web.json_response({ + 'error': f"Model type mismatch. Expected {self._get_expected_model_types()}, got {model_type}" + }, status=400) + + # Check local availability for each version + for version in versions: + # Find the model file (type="Model" and primary=true) in the files list + model_file = self._find_model_file(version.get('files', [])) + + if model_file: + sha256 = model_file.get('hashes', {}).get('SHA256') + if sha256: + # Set existsLocally and localPath at the version level + version['existsLocally'] = self.service.has_hash(sha256) + if version['existsLocally']: + version['localPath'] = self.service.get_path_by_hash(sha256) + + # Also set the model file size at the version level for easier access + version['modelSizeKB'] = model_file.get('sizeKB') + else: + # No model file found in this version + version['existsLocally'] = False + + return web.json_response(versions) + except Exception as e: + logger.error(f"Error fetching {self.model_type} model versions: {e}") + return web.Response(status=500, text=str(e)) + + async def get_civitai_model_by_version(self, request: web.Request) -> web.Response: + """Get CivitAI model details by model version ID""" + try: + model_version_id = request.match_info.get('modelVersionId') + + # Get model details from metadata provider + metadata_provider = await get_default_metadata_provider() + model, error_msg = await metadata_provider.get_model_version_info(model_version_id) + + if not model: + # Log warning for failed model retrieval + logger.warning(f"Failed to fetch model version {model_version_id}: {error_msg}") + + # Determine status code based on error message + status_code = 404 if error_msg and "not found" in error_msg.lower() else 500 + + return web.json_response({ + "success": False, + "error": error_msg or "Failed to fetch model information" + }, status=status_code) + + return web.json_response(model) + except Exception as e: + logger.error(f"Error fetching model details: {e}") + return web.json_response({ + "success": False, + "error": str(e) + }, status=500) + + async def get_civitai_model_by_hash(self, request: web.Request) -> web.Response: + """Get CivitAI model details by hash""" + try: + hash = request.match_info.get('hash') + metadata_provider = await get_default_metadata_provider() + model = await metadata_provider.get_model_by_hash(hash) + return web.json_response(model) + except Exception as e: + logger.error(f"Error fetching model details by hash: {e}") + return web.json_response({ + "success": False, + "error": str(e) + }, status=500) + + def _validate_civitai_model_type(self, model_type: str) -> bool: + """Validate CivitAI model type - to be overridden by subclasses""" + return True # Default: accept all types + + def _get_expected_model_types(self) -> str: + """Get expected model types string for error messages - to be overridden by subclasses""" + return "any model type" + + def _find_model_file(self, files: list) -> dict: + """Find the appropriate model file from the files list - can be overridden by subclasses""" + # Find the primary model file (type="Model" and primary=true) in the files list + return next((file for file in files if file.get('type') == 'Model' and file.get('primary') == True), None) # Common model move handlers async def move_model(self, request: web.Request) -> web.Response: diff --git a/py/routes/checkpoint_routes.py b/py/routes/checkpoint_routes.py index a0f6a027..712eaafc 100644 --- a/py/routes/checkpoint_routes.py +++ b/py/routes/checkpoint_routes.py @@ -36,9 +36,6 @@ class CheckpointRoutes(BaseModelRoutes): def setup_specific_routes(self, app: web.Application, prefix: str): """Setup Checkpoint-specific routes""" - # Checkpoint-specific CivitAI integration - app.router.add_get(f'/api/{prefix}/civitai/versions/{{model_id}}', self.get_civitai_versions_checkpoint) - # Checkpoint info by name app.router.add_get(f'/api/{prefix}/info/{{name}}', self.get_checkpoint_info) @@ -46,6 +43,14 @@ class CheckpointRoutes(BaseModelRoutes): app.router.add_get(f'/api/{prefix}/checkpoints_roots', self.get_checkpoints_roots) app.router.add_get(f'/api/{prefix}/unet_roots', self.get_unet_roots) + def _validate_civitai_model_type(self, model_type: str) -> bool: + """Validate CivitAI model type for Checkpoint""" + return model_type.lower() == 'checkpoint' + + def _get_expected_model_types(self) -> str: + """Get expected model types string for error messages""" + return "Checkpoint" + async def get_checkpoint_info(self, request: web.Request) -> web.Response: """Get detailed information for a specific checkpoint by name""" try: @@ -61,54 +66,6 @@ class CheckpointRoutes(BaseModelRoutes): logger.error(f"Error in get_checkpoint_info: {e}", exc_info=True) return web.json_response({"error": str(e)}, status=500) - async def get_civitai_versions_checkpoint(self, request: web.Request) -> web.Response: - """Get available versions for a Civitai checkpoint model with local availability info""" - try: - model_id = request.match_info['model_id'] - metadata_provider = await get_default_metadata_provider() - response = await metadata_provider.get_model_versions(model_id) - if not response or not response.get('modelVersions'): - return web.Response(status=404, text="Model not found") - - versions = response.get('modelVersions', []) - model_type = response.get('type', '') - - # Check model type - should be Checkpoint - if model_type.lower() != 'checkpoint': - return web.json_response({ - 'error': f"Model type mismatch. Expected Checkpoint, got {model_type}" - }, status=400) - - # Check local availability for each version - for version in versions: - # Find the primary model file (type="Model" and primary=true) in the files list - model_file = next((file for file in version.get('files', []) - if file.get('type') == 'Model' and file.get('primary') == True), None) - - # If no primary file found, try to find any model file - if not model_file: - model_file = next((file for file in version.get('files', []) - if file.get('type') == 'Model'), None) - - if model_file: - sha256 = model_file.get('hashes', {}).get('SHA256') - if sha256: - # Set existsLocally and localPath at the version level - version['existsLocally'] = self.service.has_hash(sha256) - if version['existsLocally']: - version['localPath'] = self.service.get_path_by_hash(sha256) - - # Also set the model file size at the version level for easier access - version['modelSizeKB'] = model_file.get('sizeKB') - else: - # No model file found in this version - version['existsLocally'] = False - - return web.json_response(versions) - except Exception as e: - logger.error(f"Error fetching checkpoint model versions: {e}") - return web.Response(status=500, text=str(e)) - async def get_checkpoints_roots(self, request: web.Request) -> web.Response: """Return the list of checkpoint roots from config""" try: diff --git a/py/routes/embedding_routes.py b/py/routes/embedding_routes.py index ab028666..70b5b26b 100644 --- a/py/routes/embedding_routes.py +++ b/py/routes/embedding_routes.py @@ -35,12 +35,17 @@ class EmbeddingRoutes(BaseModelRoutes): def setup_specific_routes(self, app: web.Application, prefix: str): """Setup Embedding-specific routes""" - # Embedding-specific CivitAI integration - app.router.add_get(f'/api/{prefix}/civitai/versions/{{model_id}}', self.get_civitai_versions_embedding) - # Embedding info by name app.router.add_get(f'/api/{prefix}/info/{{name}}', self.get_embedding_info) + def _validate_civitai_model_type(self, model_type: str) -> bool: + """Validate CivitAI model type for Embedding""" + return model_type.lower() in ['textualinversion', 'embedding'] + + def _get_expected_model_types(self) -> str: + """Get expected model types string for error messages""" + return "TextualInversion/Embedding" + async def get_embedding_info(self, request: web.Request) -> web.Response: """Get detailed information for a specific embedding by name""" try: @@ -55,51 +60,3 @@ class EmbeddingRoutes(BaseModelRoutes): except Exception as e: logger.error(f"Error in get_embedding_info: {e}", exc_info=True) return web.json_response({"error": str(e)}, status=500) - - async def get_civitai_versions_embedding(self, request: web.Request) -> web.Response: - """Get available versions for a Civitai embedding model with local availability info""" - try: - model_id = request.match_info['model_id'] - metadata_provider = await get_default_metadata_provider() - response = await metadata_provider.get_model_versions(model_id) - if not response or not response.get('modelVersions'): - return web.Response(status=404, text="Model not found") - - versions = response.get('modelVersions', []) - model_type = response.get('type', '') - - # Check model type - should be TextualInversion (Embedding) - if model_type.lower() not in ['textualinversion', 'embedding']: - return web.json_response({ - 'error': f"Model type mismatch. Expected TextualInversion/Embedding, got {model_type}" - }, status=400) - - # Check local availability for each version - for version in versions: - # Find the primary model file (type="Model" and primary=true) in the files list - model_file = next((file for file in version.get('files', []) - if file.get('type') == 'Model' and file.get('primary') == True), None) - - # If no primary file found, try to find any model file - if not model_file: - model_file = next((file for file in version.get('files', []) - if file.get('type') == 'Model'), None) - - if model_file: - sha256 = model_file.get('hashes', {}).get('SHA256') - if sha256: - # Set existsLocally and localPath at the version level - version['existsLocally'] = self.service.has_hash(sha256) - if version['existsLocally']: - version['localPath'] = self.service.get_path_by_hash(sha256) - - # Also set the model file size at the version level for easier access - version['modelSizeKB'] = model_file.get('sizeKB') - else: - # No model file found in this version - version['existsLocally'] = False - - return web.json_response(versions) - except Exception as e: - logger.error(f"Error fetching embedding model versions: {e}") - return web.Response(status=500, text=str(e)) diff --git a/py/routes/lora_routes.py b/py/routes/lora_routes.py index 4e261004..d70a2801 100644 --- a/py/routes/lora_routes.py +++ b/py/routes/lora_routes.py @@ -44,11 +44,6 @@ class LoraRoutes(BaseModelRoutes): app.router.add_get(f'/api/{prefix}/get-trigger-words', self.get_lora_trigger_words) app.router.add_get(f'/api/{prefix}/usage-tips-by-path', self.get_lora_usage_tips_by_path) - # CivitAI integration with LoRA-specific validation - app.router.add_get(f'/api/{prefix}/civitai/versions/{{model_id}}', self.get_civitai_versions_lora) - app.router.add_get(f'/api/{prefix}/civitai/model/version/{{modelVersionId}}', self.get_civitai_model_by_version) - app.router.add_get(f'/api/{prefix}/civitai/model/hash/{{hash}}', self.get_civitai_model_by_hash) - # ComfyUI integration app.router.add_post(f'/api/{prefix}/get_trigger_words', self.get_trigger_words) @@ -76,6 +71,15 @@ class LoraRoutes(BaseModelRoutes): return params + def _validate_civitai_model_type(self, model_type: str) -> bool: + """Validate CivitAI model type for LoRA""" + from ..utils.constants import VALID_LORA_TYPES + return model_type.lower() in VALID_LORA_TYPES + + def _get_expected_model_types(self) -> str: + """Get expected model types string for error messages""" + return "LORA, LoCon, or DORA" + # LoRA-specific route handlers async def get_letter_counts(self, request: web.Request) -> web.Response: """Get count of LoRAs for each letter of the alphabet""" @@ -210,94 +214,6 @@ class LoraRoutes(BaseModelRoutes): 'error': str(e) }, status=500) - # CivitAI integration methods - async def get_civitai_versions_lora(self, request: web.Request) -> web.Response: - """Get available versions for a Civitai LoRA model with local availability info""" - try: - model_id = request.match_info['model_id'] - metadata_provider = await get_default_metadata_provider() - response = await metadata_provider.get_model_versions(model_id) - if not response or not response.get('modelVersions'): - return web.Response(status=404, text="Model not found") - - versions = response.get('modelVersions', []) - model_type = response.get('type', '') - - # Check model type - should be LORA, LoCon, or DORA - from ..utils.constants import VALID_LORA_TYPES - if model_type.lower() not in VALID_LORA_TYPES: - return web.json_response({ - 'error': f"Model type mismatch. Expected LORA or LoCon, got {model_type}" - }, status=400) - - # Check local availability for each version - for version in versions: - # Find the model file (type="Model") in the files list - model_file = next((file for file in version.get('files', []) - if file.get('type') == 'Model'), None) - - if model_file: - sha256 = model_file.get('hashes', {}).get('SHA256') - if sha256: - # Set existsLocally and localPath at the version level - version['existsLocally'] = self.service.has_hash(sha256) - if version['existsLocally']: - version['localPath'] = self.service.get_path_by_hash(sha256) - - # Also set the model file size at the version level for easier access - version['modelSizeKB'] = model_file.get('sizeKB') - else: - # No model file found in this version - version['existsLocally'] = False - - return web.json_response(versions) - except Exception as e: - logger.error(f"Error fetching LoRA model versions: {e}") - return web.Response(status=500, text=str(e)) - - async def get_civitai_model_by_version(self, request: web.Request) -> web.Response: - """Get CivitAI model details by model version ID""" - try: - model_version_id = request.match_info.get('modelVersionId') - - # Get model details from metadata provider - metadata_provider = await get_default_metadata_provider() - model, error_msg = await metadata_provider.get_model_version_info(model_version_id) - - if not model: - # Log warning for failed model retrieval - logger.warning(f"Failed to fetch model version {model_version_id}: {error_msg}") - - # Determine status code based on error message - status_code = 404 if error_msg and "not found" in error_msg.lower() else 500 - - return web.json_response({ - "success": False, - "error": error_msg or "Failed to fetch model information" - }, status=status_code) - - return web.json_response(model) - except Exception as e: - logger.error(f"Error fetching model details: {e}") - return web.json_response({ - "success": False, - "error": str(e) - }, status=500) - - async def get_civitai_model_by_hash(self, request: web.Request) -> web.Response: - """Get CivitAI model details by hash""" - try: - hash = request.match_info.get('hash') - metadata_provider = await get_default_metadata_provider() - model = await metadata_provider.get_model_by_hash(hash) - return web.json_response(model) - except Exception as e: - logger.error(f"Error fetching model details by hash: {e}") - return web.json_response({ - "success": False, - "error": str(e) - }, status=500) - async def get_trigger_words(self, request: web.Request) -> web.Response: """Get trigger words for specified LoRA models""" try: From ded17c1479d5262670e139b45ea3def4e99c4035 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Wed, 17 Sep 2025 22:06:59 +0800 Subject: [PATCH 031/110] feat(routes): add model versions status endpoint and enhance metadata retrieval --- py/routes/embedding_routes.py | 4 +- py/routes/misc_routes.py | 112 ++++++++++++++++++++++++- py/services/civitai_client.py | 3 +- py/services/model_metadata_provider.py | 4 +- 4 files changed, 118 insertions(+), 5 deletions(-) diff --git a/py/routes/embedding_routes.py b/py/routes/embedding_routes.py index 70b5b26b..eefa8bdd 100644 --- a/py/routes/embedding_routes.py +++ b/py/routes/embedding_routes.py @@ -40,11 +40,11 @@ class EmbeddingRoutes(BaseModelRoutes): def _validate_civitai_model_type(self, model_type: str) -> bool: """Validate CivitAI model type for Embedding""" - return model_type.lower() in ['textualinversion', 'embedding'] + return model_type.lower() == 'textualinversion' def _get_expected_model_types(self) -> str: """Get expected model types string for error messages""" - return "TextualInversion/Embedding" + return "TextualInversion" async def get_embedding_info(self, request: web.Request) -> web.Response: """Get detailed information for a specific embedding by name""" diff --git a/py/routes/misc_routes.py b/py/routes/misc_routes.py index 89fadace..5cae7002 100644 --- a/py/routes/misc_routes.py +++ b/py/routes/misc_routes.py @@ -12,7 +12,7 @@ from ..utils.lora_metadata import extract_trained_words from ..config import config from ..utils.constants import SUPPORTED_MEDIA_EXTENSIONS, NODE_TYPES, DEFAULT_NODE_COLOR from ..services.service_registry import ServiceRegistry -from ..services.metadata_service import get_metadata_archive_manager, update_metadata_providers +from ..services.metadata_service import get_metadata_archive_manager, update_metadata_providers, get_metadata_provider from ..services.websocket_manager import ws_manager from ..services.downloader import get_downloader logger = logging.getLogger(__name__) @@ -119,6 +119,9 @@ class MiscRoutes: app.router.add_post('/api/download-metadata-archive', MiscRoutes.download_metadata_archive) app.router.add_post('/api/remove-metadata-archive', MiscRoutes.remove_metadata_archive) app.router.add_get('/api/metadata-archive-status', MiscRoutes.get_metadata_archive_status) + + # Add route for checking model versions in library + app.router.add_get('/api/model-versions-status', MiscRoutes.get_model_versions_status) @staticmethod async def get_settings(request): @@ -832,6 +835,113 @@ class MiscRoutes: 'success': False, 'error': str(e) }, status=500) + + @staticmethod + async def get_model_versions_status(request): + """ + Get all versions of a model from metadata provider and check their library status + + Expects query parameters: + - modelId: int - Civitai model ID (required) + + Returns: + - JSON with model type and versions list, each version includes 'inLibrary' flag + """ + try: + # Get the modelId from query parameters + model_id_str = request.query.get('modelId') + + # Validate modelId parameter (required) + if not model_id_str: + return web.json_response({ + 'success': False, + 'error': 'Missing required parameter: modelId' + }, status=400) + + try: + # Convert modelId to integer + model_id = int(model_id_str) + except ValueError: + return web.json_response({ + 'success': False, + 'error': 'Parameter modelId must be an integer' + }, status=400) + + # Get metadata provider + metadata_provider = await get_metadata_provider() + if not metadata_provider: + return web.json_response({ + 'success': False, + 'error': 'Metadata provider not available' + }, status=503) + + # Get model versions from metadata provider + response = await metadata_provider.get_model_versions(model_id) + if not response or not response.get('modelVersions'): + return web.json_response({ + 'success': False, + 'error': 'Model not found' + }, status=404) + + versions = response.get('modelVersions', []) + model_name = response.get('name', '') + model_type = response.get('type', '').lower() + + # Determine scanner based on model type + scanner = None + normalized_type = None + + if model_type in ['lora', 'locon', 'dora']: + scanner = await ServiceRegistry.get_lora_scanner() + normalized_type = 'lora' + elif model_type == 'checkpoint': + scanner = await ServiceRegistry.get_checkpoint_scanner() + normalized_type = 'checkpoint' + elif model_type == 'textualinversion': + scanner = await ServiceRegistry.get_embedding_scanner() + normalized_type = 'embedding' + else: + return web.json_response({ + 'success': False, + 'error': f'Model type "{model_type}" is not supported' + }, status=400) + + if not scanner: + return web.json_response({ + 'success': False, + 'error': f'Scanner for type "{normalized_type}" is not available' + }, status=503) + + # Get local versions from scanner + local_versions = await scanner.get_model_versions_by_id(model_id) + local_version_ids = set(version['versionId'] for version in local_versions) + + # Add inLibrary flag to each version + enriched_versions = [] + for version in versions: + version_id = version.get('id') + enriched_version = { + 'id': version_id, + 'name': version.get('name', ''), + 'thumbnailUrl': version.get('images')[0]['url'] if version.get('images') else None, + 'inLibrary': version_id in local_version_ids + } + enriched_versions.append(enriched_version) + + return web.json_response({ + 'success': True, + 'modelId': model_id, + 'modelName': model_name, + 'modelType': model_type, + 'versions': enriched_versions + }) + + except Exception as e: + logger.error(f"Failed to get model versions status: {e}", exc_info=True) + return web.json_response({ + 'success': False, + 'error': str(e) + }, status=500) @staticmethod async def open_file_location(request): diff --git a/py/services/civitai_client.py b/py/services/civitai_client.py index e037ba35..463bd036 100644 --- a/py/services/civitai_client.py +++ b/py/services/civitai_client.py @@ -122,7 +122,8 @@ class CivitaiClient: # Also return model type along with versions return { 'modelVersions': result.get('modelVersions', []), - 'type': result.get('type', '') + 'type': result.get('type', ''), + 'name': result.get('name', '') } return None except Exception as e: diff --git a/py/services/model_metadata_provider.py b/py/services/model_metadata_provider.py index 9957b849..ee38f373 100644 --- a/py/services/model_metadata_provider.py +++ b/py/services/model_metadata_provider.py @@ -224,6 +224,7 @@ class SQLiteModelMetadataProvider(ModelMetadataProvider): model_data = json.loads(model_row['data']) model_type = model_row['type'] + model_name = model_row['name'] # Get all versions for this model versions_query = """ @@ -260,7 +261,8 @@ class SQLiteModelMetadataProvider(ModelMetadataProvider): return { 'modelVersions': model_versions, - 'type': model_type + 'type': model_type, + 'name': model_name } async def get_model_version(self, model_id: int = None, version_id: int = None) -> Optional[Dict]: From bdc86ddf1596338c6b010ce783dd3b295216e128 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Thu, 18 Sep 2025 14:50:40 +0800 Subject: [PATCH 032/110] Refactor API endpoints to use '/api/lm/' prefix - Updated all relevant routes in `stats_routes.py` and `update_routes.py` to include the new '/api/lm/' prefix for consistency. - Modified API endpoint configurations in `apiConfig.js` to reflect the new structure, ensuring all CRUD and bulk operations are correctly routed. - Adjusted fetch calls in various components and managers to utilize the updated API paths, including recipe, model, and example image operations. - Ensured all instances of the old API paths were replaced with the new '/api/lm/' prefix across the codebase for uniformity and to prevent broken links. --- py/routes/base_model_routes.py | 78 +++++++-------- py/routes/checkpoint_routes.py | 6 +- py/routes/embedding_routes.py | 2 +- py/routes/example_images_routes.py | 20 ++-- py/routes/lora_routes.py | 8 +- py/routes/misc_routes.py | 28 +++--- py/routes/recipe_routes.py | 36 +++---- py/routes/stats_routes.py | 12 +-- py/routes/update_routes.py | 6 +- static/js/api/apiConfig.js | 94 +++++++++---------- static/js/api/recipeApi.js | 8 +- .../ContextMenu/ModelContextMenuMixin.js | 4 +- .../ContextMenu/RecipeContextMenu.js | 12 +-- static/js/components/DuplicatesManager.js | 4 +- .../js/components/ModelDuplicatesManager.js | 10 +- static/js/components/RecipeCard.js | 6 +- static/js/components/RecipeModal.js | 8 +- static/js/components/alphabet/AlphabetBar.js | 2 +- static/js/components/initialization.js | 2 +- static/js/components/shared/ModelCard.js | 2 +- static/js/components/shared/ModelModal.js | 2 +- static/js/components/shared/RecipeTab.js | 4 +- static/js/components/shared/TriggerWords.js | 2 +- .../components/shared/showcase/MediaUtils.js | 2 +- .../shared/showcase/ShowcaseView.js | 6 +- static/js/managers/ExampleImagesManager.js | 12 +-- static/js/managers/FilterManager.js | 4 +- static/js/managers/SettingsManager.js | 12 +-- static/js/managers/UpdateService.js | 6 +- static/js/managers/import/DownloadManager.js | 2 +- static/js/managers/import/FolderBrowser.js | 4 +- static/js/managers/import/ImageProcessor.js | 6 +- static/js/statistics.js | 12 +-- static/js/utils/uiHelpers.js | 6 +- web/comfyui/autocomplete.js | 4 +- web/comfyui/loras_widget_components.js | 2 +- web/comfyui/loras_widget_events.js | 6 +- web/comfyui/loras_widget_utils.js | 2 +- web/comfyui/ui_utils.js | 2 +- web/comfyui/usage_stats.js | 6 +- 40 files changed, 225 insertions(+), 225 deletions(-) diff --git a/py/routes/base_model_routes.py b/py/routes/base_model_routes.py index 499d4617..2b2f7a7c 100644 --- a/py/routes/base_model_routes.py +++ b/py/routes/base_model_routes.py @@ -48,53 +48,53 @@ class BaseModelRoutes(ABC): prefix: URL prefix (e.g., 'loras', 'checkpoints') """ # Common model management routes - app.router.add_get(f'/api/{prefix}/list', self.get_models) - app.router.add_post(f'/api/{prefix}/delete', self.delete_model) - app.router.add_post(f'/api/{prefix}/exclude', self.exclude_model) - app.router.add_post(f'/api/{prefix}/fetch-civitai', self.fetch_civitai) - app.router.add_post(f'/api/{prefix}/fetch-all-civitai', self.fetch_all_civitai) - app.router.add_post(f'/api/{prefix}/relink-civitai', self.relink_civitai) - app.router.add_post(f'/api/{prefix}/replace-preview', self.replace_preview) - app.router.add_post(f'/api/{prefix}/save-metadata', self.save_metadata) - app.router.add_post(f'/api/{prefix}/add-tags', self.add_tags) - app.router.add_post(f'/api/{prefix}/rename', self.rename_model) - app.router.add_post(f'/api/{prefix}/bulk-delete', self.bulk_delete_models) - app.router.add_post(f'/api/{prefix}/verify-duplicates', self.verify_duplicates) - app.router.add_post(f'/api/{prefix}/move_model', self.move_model) - app.router.add_post(f'/api/{prefix}/move_models_bulk', self.move_models_bulk) - app.router.add_get(f'/api/{prefix}/auto-organize', self.auto_organize_models) - app.router.add_post(f'/api/{prefix}/auto-organize', self.auto_organize_models) - app.router.add_get(f'/api/{prefix}/auto-organize-progress', self.get_auto_organize_progress) + app.router.add_get(f'/api/lm/{prefix}/list', self.get_models) + app.router.add_post(f'/api/lm/{prefix}/delete', self.delete_model) + app.router.add_post(f'/api/lm/{prefix}/exclude', self.exclude_model) + app.router.add_post(f'/api/lm/{prefix}/fetch-civitai', self.fetch_civitai) + app.router.add_post(f'/api/lm/{prefix}/fetch-all-civitai', self.fetch_all_civitai) + app.router.add_post(f'/api/lm/{prefix}/relink-civitai', self.relink_civitai) + app.router.add_post(f'/api/lm/{prefix}/replace-preview', self.replace_preview) + app.router.add_post(f'/api/lm/{prefix}/save-metadata', self.save_metadata) + app.router.add_post(f'/api/lm/{prefix}/add-tags', self.add_tags) + app.router.add_post(f'/api/lm/{prefix}/rename', self.rename_model) + app.router.add_post(f'/api/lm/{prefix}/bulk-delete', self.bulk_delete_models) + app.router.add_post(f'/api/lm/{prefix}/verify-duplicates', self.verify_duplicates) + app.router.add_post(f'/api/lm/{prefix}/move_model', self.move_model) + app.router.add_post(f'/api/lm/{prefix}/move_models_bulk', self.move_models_bulk) + app.router.add_get(f'/api/lm/{prefix}/auto-organize', self.auto_organize_models) + app.router.add_post(f'/api/lm/{prefix}/auto-organize', self.auto_organize_models) + app.router.add_get(f'/api/lm/{prefix}/auto-organize-progress', self.get_auto_organize_progress) # Common query routes - app.router.add_get(f'/api/{prefix}/top-tags', self.get_top_tags) - app.router.add_get(f'/api/{prefix}/base-models', self.get_base_models) - app.router.add_get(f'/api/{prefix}/scan', self.scan_models) - app.router.add_get(f'/api/{prefix}/roots', self.get_model_roots) - app.router.add_get(f'/api/{prefix}/folders', self.get_folders) - app.router.add_get(f'/api/{prefix}/folder-tree', self.get_folder_tree) - app.router.add_get(f'/api/{prefix}/unified-folder-tree', self.get_unified_folder_tree) - app.router.add_get(f'/api/{prefix}/find-duplicates', self.find_duplicate_models) - app.router.add_get(f'/api/{prefix}/find-filename-conflicts', self.find_filename_conflicts) - app.router.add_get(f'/api/{prefix}/get-notes', self.get_model_notes) - app.router.add_get(f'/api/{prefix}/preview-url', self.get_model_preview_url) - app.router.add_get(f'/api/{prefix}/civitai-url', self.get_model_civitai_url) - app.router.add_get(f'/api/{prefix}/metadata', self.get_model_metadata) - app.router.add_get(f'/api/{prefix}/model-description', self.get_model_description) + app.router.add_get(f'/api/lm/{prefix}/top-tags', self.get_top_tags) + app.router.add_get(f'/api/lm/{prefix}/base-models', self.get_base_models) + app.router.add_get(f'/api/lm/{prefix}/scan', self.scan_models) + app.router.add_get(f'/api/lm/{prefix}/roots', self.get_model_roots) + app.router.add_get(f'/api/lm/{prefix}/folders', self.get_folders) + app.router.add_get(f'/api/lm/{prefix}/folder-tree', self.get_folder_tree) + app.router.add_get(f'/api/lm/{prefix}/unified-folder-tree', self.get_unified_folder_tree) + app.router.add_get(f'/api/lm/{prefix}/find-duplicates', self.find_duplicate_models) + app.router.add_get(f'/api/lm/{prefix}/find-filename-conflicts', self.find_filename_conflicts) + app.router.add_get(f'/api/lm/{prefix}/get-notes', self.get_model_notes) + app.router.add_get(f'/api/lm/{prefix}/preview-url', self.get_model_preview_url) + app.router.add_get(f'/api/lm/{prefix}/civitai-url', self.get_model_civitai_url) + app.router.add_get(f'/api/lm/{prefix}/metadata', self.get_model_metadata) + app.router.add_get(f'/api/lm/{prefix}/model-description', self.get_model_description) # Autocomplete route - app.router.add_get(f'/api/{prefix}/relative-paths', self.get_relative_paths) + app.router.add_get(f'/api/lm/{prefix}/relative-paths', self.get_relative_paths) # Common CivitAI integration - app.router.add_get(f'/api/{prefix}/civitai/versions/{{model_id}}', self.get_civitai_versions) - app.router.add_get(f'/api/{prefix}/civitai/model/version/{{modelVersionId}}', self.get_civitai_model_by_version) - app.router.add_get(f'/api/{prefix}/civitai/model/hash/{{hash}}', self.get_civitai_model_by_hash) + app.router.add_get(f'/api/lm/{prefix}/civitai/versions/{{model_id}}', self.get_civitai_versions) + app.router.add_get(f'/api/lm/{prefix}/civitai/model/version/{{modelVersionId}}', self.get_civitai_model_by_version) + app.router.add_get(f'/api/lm/{prefix}/civitai/model/hash/{{hash}}', self.get_civitai_model_by_hash) # Common Download management - app.router.add_post(f'/api/download-model', self.download_model) - app.router.add_get(f'/api/download-model-get', self.download_model_get) - app.router.add_get(f'/api/cancel-download-get', self.cancel_download_get) - app.router.add_get(f'/api/download-progress/{{download_id}}', self.get_download_progress) + app.router.add_post(f'/api/lm/download-model', self.download_model) + app.router.add_get(f'/api/lm/download-model-get', self.download_model_get) + app.router.add_get(f'/api/lm/cancel-download-get', self.cancel_download_get) + app.router.add_get(f'/api/lm/download-progress/{{download_id}}', self.get_download_progress) # Add generic page route app.router.add_get(f'/{prefix}', self.handle_models_page) diff --git a/py/routes/checkpoint_routes.py b/py/routes/checkpoint_routes.py index 712eaafc..95c747e5 100644 --- a/py/routes/checkpoint_routes.py +++ b/py/routes/checkpoint_routes.py @@ -37,11 +37,11 @@ class CheckpointRoutes(BaseModelRoutes): def setup_specific_routes(self, app: web.Application, prefix: str): """Setup Checkpoint-specific routes""" # Checkpoint info by name - app.router.add_get(f'/api/{prefix}/info/{{name}}', self.get_checkpoint_info) + app.router.add_get(f'/api/lm/{prefix}/info/{{name}}', self.get_checkpoint_info) # Checkpoint roots and Unet roots - app.router.add_get(f'/api/{prefix}/checkpoints_roots', self.get_checkpoints_roots) - app.router.add_get(f'/api/{prefix}/unet_roots', self.get_unet_roots) + app.router.add_get(f'/api/lm/{prefix}/checkpoints_roots', self.get_checkpoints_roots) + app.router.add_get(f'/api/lm/{prefix}/unet_roots', self.get_unet_roots) def _validate_civitai_model_type(self, model_type: str) -> bool: """Validate CivitAI model type for Checkpoint""" diff --git a/py/routes/embedding_routes.py b/py/routes/embedding_routes.py index eefa8bdd..29b2f9fd 100644 --- a/py/routes/embedding_routes.py +++ b/py/routes/embedding_routes.py @@ -36,7 +36,7 @@ class EmbeddingRoutes(BaseModelRoutes): def setup_specific_routes(self, app: web.Application, prefix: str): """Setup Embedding-specific routes""" # Embedding info by name - app.router.add_get(f'/api/{prefix}/info/{{name}}', self.get_embedding_info) + app.router.add_get(f'/api/lm/{prefix}/info/{{name}}', self.get_embedding_info) def _validate_civitai_model_type(self, model_type: str) -> bool: """Validate CivitAI model type for Embedding""" diff --git a/py/routes/example_images_routes.py b/py/routes/example_images_routes.py index 9f20b470..07cb0e71 100644 --- a/py/routes/example_images_routes.py +++ b/py/routes/example_images_routes.py @@ -12,16 +12,16 @@ class ExampleImagesRoutes: @staticmethod def setup_routes(app): """Register example images routes""" - app.router.add_post('/api/download-example-images', ExampleImagesRoutes.download_example_images) - app.router.add_post('/api/import-example-images', ExampleImagesRoutes.import_example_images) - app.router.add_get('/api/example-images-status', ExampleImagesRoutes.get_example_images_status) - app.router.add_post('/api/pause-example-images', ExampleImagesRoutes.pause_example_images) - app.router.add_post('/api/resume-example-images', ExampleImagesRoutes.resume_example_images) - app.router.add_post('/api/open-example-images-folder', ExampleImagesRoutes.open_example_images_folder) - app.router.add_get('/api/example-image-files', ExampleImagesRoutes.get_example_image_files) - app.router.add_get('/api/has-example-images', ExampleImagesRoutes.has_example_images) - app.router.add_post('/api/delete-example-image', ExampleImagesRoutes.delete_example_image) - app.router.add_post('/api/force-download-example-images', ExampleImagesRoutes.force_download_example_images) + app.router.add_post('/api/lm/download-example-images', ExampleImagesRoutes.download_example_images) + app.router.add_post('/api/lm/import-example-images', ExampleImagesRoutes.import_example_images) + app.router.add_get('/api/lm/example-images-status', ExampleImagesRoutes.get_example_images_status) + app.router.add_post('/api/lm/pause-example-images', ExampleImagesRoutes.pause_example_images) + app.router.add_post('/api/lm/resume-example-images', ExampleImagesRoutes.resume_example_images) + app.router.add_post('/api/lm/open-example-images-folder', ExampleImagesRoutes.open_example_images_folder) + app.router.add_get('/api/lm/example-image-files', ExampleImagesRoutes.get_example_image_files) + app.router.add_get('/api/lm/has-example-images', ExampleImagesRoutes.has_example_images) + app.router.add_post('/api/lm/delete-example-image', ExampleImagesRoutes.delete_example_image) + app.router.add_post('/api/lm/force-download-example-images', ExampleImagesRoutes.force_download_example_images) @staticmethod async def download_example_images(request): diff --git a/py/routes/lora_routes.py b/py/routes/lora_routes.py index d70a2801..0ddb41ab 100644 --- a/py/routes/lora_routes.py +++ b/py/routes/lora_routes.py @@ -40,12 +40,12 @@ class LoraRoutes(BaseModelRoutes): def setup_specific_routes(self, app: web.Application, prefix: str): """Setup LoRA-specific routes""" # LoRA-specific query routes - app.router.add_get(f'/api/{prefix}/letter-counts', self.get_letter_counts) - app.router.add_get(f'/api/{prefix}/get-trigger-words', self.get_lora_trigger_words) - app.router.add_get(f'/api/{prefix}/usage-tips-by-path', self.get_lora_usage_tips_by_path) + app.router.add_get(f'/api/lm/{prefix}/letter-counts', self.get_letter_counts) + app.router.add_get(f'/api/lm/{prefix}/get-trigger-words', self.get_lora_trigger_words) + app.router.add_get(f'/api/lm/{prefix}/usage-tips-by-path', self.get_lora_usage_tips_by_path) # ComfyUI integration - app.router.add_post(f'/api/{prefix}/get_trigger_words', self.get_trigger_words) + app.router.add_post(f'/api/lm/{prefix}/get_trigger_words', self.get_trigger_words) def _parse_specific_params(self, request: web.Request) -> Dict: """Parse LoRA-specific parameters""" diff --git a/py/routes/misc_routes.py b/py/routes/misc_routes.py index 5cae7002..90b7d578 100644 --- a/py/routes/misc_routes.py +++ b/py/routes/misc_routes.py @@ -91,37 +91,37 @@ class MiscRoutes: app.router.add_get('/api/lm/settings', MiscRoutes.get_settings) app.router.add_post('/api/lm/settings', MiscRoutes.update_settings) - app.router.add_get('/api/health-check', lambda request: web.json_response({'status': 'ok'})) + app.router.add_get('/api/lm/health-check', lambda request: web.json_response({'status': 'ok'})) - app.router.add_post('/api/open-file-location', MiscRoutes.open_file_location) + app.router.add_post('/api/lm/open-file-location', MiscRoutes.open_file_location) # Usage stats routes - app.router.add_post('/api/update-usage-stats', MiscRoutes.update_usage_stats) - app.router.add_get('/api/get-usage-stats', MiscRoutes.get_usage_stats) + app.router.add_post('/api/lm/update-usage-stats', MiscRoutes.update_usage_stats) + app.router.add_get('/api/lm/get-usage-stats', MiscRoutes.get_usage_stats) # Lora code update endpoint - app.router.add_post('/api/update-lora-code', MiscRoutes.update_lora_code) + app.router.add_post('/api/lm/update-lora-code', MiscRoutes.update_lora_code) # Add new route for getting trained words - app.router.add_get('/api/trained-words', MiscRoutes.get_trained_words) + app.router.add_get('/api/lm/trained-words', MiscRoutes.get_trained_words) # Add new route for getting model example files - app.router.add_get('/api/model-example-files', MiscRoutes.get_model_example_files) + app.router.add_get('/api/lm/model-example-files', MiscRoutes.get_model_example_files) # Node registry endpoints - app.router.add_post('/api/register-nodes', MiscRoutes.register_nodes) - app.router.add_get('/api/get-registry', MiscRoutes.get_registry) + app.router.add_post('/api/lm/register-nodes', MiscRoutes.register_nodes) + app.router.add_get('/api/lm/get-registry', MiscRoutes.get_registry) # Add new route for checking if a model exists in the library - app.router.add_get('/api/check-model-exists', MiscRoutes.check_model_exists) + app.router.add_get('/api/lm/check-model-exists', MiscRoutes.check_model_exists) # Add routes for metadata archive database management - app.router.add_post('/api/download-metadata-archive', MiscRoutes.download_metadata_archive) - app.router.add_post('/api/remove-metadata-archive', MiscRoutes.remove_metadata_archive) - app.router.add_get('/api/metadata-archive-status', MiscRoutes.get_metadata_archive_status) + app.router.add_post('/api/lm/download-metadata-archive', MiscRoutes.download_metadata_archive) + app.router.add_post('/api/lm/remove-metadata-archive', MiscRoutes.remove_metadata_archive) + app.router.add_get('/api/lm/metadata-archive-status', MiscRoutes.get_metadata_archive_status) # Add route for checking model versions in library - app.router.add_get('/api/model-versions-status', MiscRoutes.get_model_versions_status) + app.router.add_get('/api/lm/model-versions-status', MiscRoutes.get_model_versions_status) @staticmethod async def get_settings(request): diff --git a/py/routes/recipe_routes.py b/py/routes/recipe_routes.py index 003d869a..0c8843b4 100644 --- a/py/routes/recipe_routes.py +++ b/py/routes/recipe_routes.py @@ -61,46 +61,46 @@ class RecipeRoutes: routes = cls() app.router.add_get('/loras/recipes', routes.handle_recipes_page) - app.router.add_get('/api/recipes', routes.get_recipes) - app.router.add_get('/api/recipe/{recipe_id}', routes.get_recipe_detail) - app.router.add_post('/api/recipes/analyze-image', routes.analyze_recipe_image) - app.router.add_post('/api/recipes/analyze-local-image', routes.analyze_local_image) - app.router.add_post('/api/recipes/save', routes.save_recipe) - app.router.add_delete('/api/recipe/{recipe_id}', routes.delete_recipe) + app.router.add_get('/api/lm/recipes', routes.get_recipes) + app.router.add_get('/api/lm/recipe/{recipe_id}', routes.get_recipe_detail) + app.router.add_post('/api/lm/recipes/analyze-image', routes.analyze_recipe_image) + app.router.add_post('/api/lm/recipes/analyze-local-image', routes.analyze_local_image) + app.router.add_post('/api/lm/recipes/save', routes.save_recipe) + app.router.add_delete('/api/lm/recipe/{recipe_id}', routes.delete_recipe) # Add new filter-related endpoints - app.router.add_get('/api/recipes/top-tags', routes.get_top_tags) - app.router.add_get('/api/recipes/base-models', routes.get_base_models) + app.router.add_get('/api/lm/recipes/top-tags', routes.get_top_tags) + app.router.add_get('/api/lm/recipes/base-models', routes.get_base_models) # Add new sharing endpoints - app.router.add_get('/api/recipe/{recipe_id}/share', routes.share_recipe) - app.router.add_get('/api/recipe/{recipe_id}/share/download', routes.download_shared_recipe) + app.router.add_get('/api/lm/recipe/{recipe_id}/share', routes.share_recipe) + app.router.add_get('/api/lm/recipe/{recipe_id}/share/download', routes.download_shared_recipe) # Add new endpoint for getting recipe syntax - app.router.add_get('/api/recipe/{recipe_id}/syntax', routes.get_recipe_syntax) + app.router.add_get('/api/lm/recipe/{recipe_id}/syntax', routes.get_recipe_syntax) # Add new endpoint for updating recipe metadata (name, tags and source_path) - app.router.add_put('/api/recipe/{recipe_id}/update', routes.update_recipe) + app.router.add_put('/api/lm/recipe/{recipe_id}/update', routes.update_recipe) # Add new endpoint for reconnecting deleted LoRAs - app.router.add_post('/api/recipe/lora/reconnect', routes.reconnect_lora) + app.router.add_post('/api/lm/recipe/lora/reconnect', routes.reconnect_lora) # Add new endpoint for finding duplicate recipes - app.router.add_get('/api/recipes/find-duplicates', routes.find_duplicates) + app.router.add_get('/api/lm/recipes/find-duplicates', routes.find_duplicates) # Add new endpoint for bulk deletion of recipes - app.router.add_post('/api/recipes/bulk-delete', routes.bulk_delete) + app.router.add_post('/api/lm/recipes/bulk-delete', routes.bulk_delete) # Start cache initialization app.on_startup.append(routes._init_cache) - app.router.add_post('/api/recipes/save-from-widget', routes.save_recipe_from_widget) + app.router.add_post('/api/lm/recipes/save-from-widget', routes.save_recipe_from_widget) # Add route to get recipes for a specific Lora - app.router.add_get('/api/recipes/for-lora', routes.get_recipes_for_lora) + app.router.add_get('/api/lm/recipes/for-lora', routes.get_recipes_for_lora) # Add new endpoint for scanning and rebuilding the recipe cache - app.router.add_get('/api/recipes/scan', routes.scan_recipes) + app.router.add_get('/api/lm/recipes/scan', routes.scan_recipes) async def _init_cache(self, app): """Initialize cache on startup""" diff --git a/py/routes/stats_routes.py b/py/routes/stats_routes.py index b61762d1..f8c0aaa4 100644 --- a/py/routes/stats_routes.py +++ b/py/routes/stats_routes.py @@ -507,12 +507,12 @@ class StatsRoutes: app.router.add_get('/statistics', self.handle_stats_page) # Register API routes - app.router.add_get('/api/stats/collection-overview', self.get_collection_overview) - app.router.add_get('/api/stats/usage-analytics', self.get_usage_analytics) - app.router.add_get('/api/stats/base-model-distribution', self.get_base_model_distribution) - app.router.add_get('/api/stats/tag-analytics', self.get_tag_analytics) - app.router.add_get('/api/stats/storage-analytics', self.get_storage_analytics) - app.router.add_get('/api/stats/insights', self.get_insights) + app.router.add_get('/api/lm/stats/collection-overview', self.get_collection_overview) + app.router.add_get('/api/lm/stats/usage-analytics', self.get_usage_analytics) + app.router.add_get('/api/lm/stats/base-model-distribution', self.get_base_model_distribution) + app.router.add_get('/api/lm/stats/tag-analytics', self.get_tag_analytics) + app.router.add_get('/api/lm/stats/storage-analytics', self.get_storage_analytics) + app.router.add_get('/api/lm/stats/insights', self.get_insights) async def _on_startup(self, app): """Initialize services when the app starts""" diff --git a/py/routes/update_routes.py b/py/routes/update_routes.py index bf77baaf..2febfba3 100644 --- a/py/routes/update_routes.py +++ b/py/routes/update_routes.py @@ -17,9 +17,9 @@ class UpdateRoutes: @staticmethod def setup_routes(app): """Register update check routes""" - app.router.add_get('/api/check-updates', UpdateRoutes.check_updates) - app.router.add_get('/api/version-info', UpdateRoutes.get_version_info) - app.router.add_post('/api/perform-update', UpdateRoutes.perform_update) + app.router.add_get('/api/lm/check-updates', UpdateRoutes.check_updates) + app.router.add_get('/api/lm/version-info', UpdateRoutes.get_version_info) + app.router.add_post('/api/lm/perform-update', UpdateRoutes.perform_update) @staticmethod async def check_updates(request): diff --git a/static/js/api/apiConfig.js b/static/js/api/apiConfig.js index 33622dc5..aa168413 100644 --- a/static/js/api/apiConfig.js +++ b/static/js/api/apiConfig.js @@ -55,48 +55,48 @@ export function getApiEndpoints(modelType) { return { // Base CRUD operations - list: `/api/${modelType}/list`, - delete: `/api/${modelType}/delete`, - exclude: `/api/${modelType}/exclude`, - rename: `/api/${modelType}/rename`, - save: `/api/${modelType}/save-metadata`, + list: `/api/lm/${modelType}/list`, + delete: `/api/lm/${modelType}/delete`, + exclude: `/api/lm/${modelType}/exclude`, + rename: `/api/lm/${modelType}/rename`, + save: `/api/lm/${modelType}/save-metadata`, // Bulk operations - bulkDelete: `/api/${modelType}/bulk-delete`, + bulkDelete: `/api/lm/${modelType}/bulk-delete`, // Tag operations - addTags: `/api/${modelType}/add-tags`, + addTags: `/api/lm/${modelType}/add-tags`, // Move operations (now common for all model types that support move) - moveModel: `/api/${modelType}/move_model`, - moveBulk: `/api/${modelType}/move_models_bulk`, + moveModel: `/api/lm/${modelType}/move_model`, + moveBulk: `/api/lm/${modelType}/move_models_bulk`, // CivitAI integration - fetchCivitai: `/api/${modelType}/fetch-civitai`, - fetchAllCivitai: `/api/${modelType}/fetch-all-civitai`, - relinkCivitai: `/api/${modelType}/relink-civitai`, - civitaiVersions: `/api/${modelType}/civitai/versions`, + fetchCivitai: `/api/lm/${modelType}/fetch-civitai`, + fetchAllCivitai: `/api/lm/${modelType}/fetch-all-civitai`, + relinkCivitai: `/api/lm/${modelType}/relink-civitai`, + civitaiVersions: `/api/lm/${modelType}/civitai/versions`, // Preview management - replacePreview: `/api/${modelType}/replace-preview`, + replacePreview: `/api/lm/${modelType}/replace-preview`, // Query operations - scan: `/api/${modelType}/scan`, - topTags: `/api/${modelType}/top-tags`, - baseModels: `/api/${modelType}/base-models`, - roots: `/api/${modelType}/roots`, - folders: `/api/${modelType}/folders`, - folderTree: `/api/${modelType}/folder-tree`, - unifiedFolderTree: `/api/${modelType}/unified-folder-tree`, - duplicates: `/api/${modelType}/find-duplicates`, - conflicts: `/api/${modelType}/find-filename-conflicts`, - verify: `/api/${modelType}/verify-duplicates`, - metadata: `/api/${modelType}/metadata`, - modelDescription: `/api/${modelType}/model-description`, + scan: `/api/lm/${modelType}/scan`, + topTags: `/api/lm/${modelType}/top-tags`, + baseModels: `/api/lm/${modelType}/base-models`, + roots: `/api/lm/${modelType}/roots`, + folders: `/api/lm/${modelType}/folders`, + folderTree: `/api/lm/${modelType}/folder-tree`, + unifiedFolderTree: `/api/lm/${modelType}/unified-folder-tree`, + duplicates: `/api/lm/${modelType}/find-duplicates`, + conflicts: `/api/lm/${modelType}/find-filename-conflicts`, + verify: `/api/lm/${modelType}/verify-duplicates`, + metadata: `/api/lm/${modelType}/metadata`, + modelDescription: `/api/lm/${modelType}/model-description`, // Auto-organize operations - autoOrganize: `/api/${modelType}/auto-organize`, - autoOrganizeProgress: `/api/${modelType}/auto-organize-progress`, + autoOrganize: `/api/lm/${modelType}/auto-organize`, + autoOrganizeProgress: `/api/lm/${modelType}/auto-organize-progress`, // Model-specific endpoints (will be merged with specific configs) specific: {} @@ -108,24 +108,24 @@ export function getApiEndpoints(modelType) { */ export const MODEL_SPECIFIC_ENDPOINTS = { [MODEL_TYPES.LORA]: { - letterCounts: `/api/${MODEL_TYPES.LORA}/letter-counts`, - notes: `/api/${MODEL_TYPES.LORA}/get-notes`, - triggerWords: `/api/${MODEL_TYPES.LORA}/get-trigger-words`, - previewUrl: `/api/${MODEL_TYPES.LORA}/preview-url`, - civitaiUrl: `/api/${MODEL_TYPES.LORA}/civitai-url`, - metadata: `/api/${MODEL_TYPES.LORA}/metadata`, - getTriggerWordsPost: `/api/${MODEL_TYPES.LORA}/get_trigger_words`, - civitaiModelByVersion: `/api/${MODEL_TYPES.LORA}/civitai/model/version`, - civitaiModelByHash: `/api/${MODEL_TYPES.LORA}/civitai/model/hash`, + letterCounts: `/api/lm/${MODEL_TYPES.LORA}/letter-counts`, + notes: `/api/lm/${MODEL_TYPES.LORA}/get-notes`, + triggerWords: `/api/lm/${MODEL_TYPES.LORA}/get-trigger-words`, + previewUrl: `/api/lm/${MODEL_TYPES.LORA}/preview-url`, + civitaiUrl: `/api/lm/${MODEL_TYPES.LORA}/civitai-url`, + metadata: `/api/lm/${MODEL_TYPES.LORA}/metadata`, + getTriggerWordsPost: `/api/lm/${MODEL_TYPES.LORA}/get_trigger_words`, + civitaiModelByVersion: `/api/lm/${MODEL_TYPES.LORA}/civitai/model/version`, + civitaiModelByHash: `/api/lm/${MODEL_TYPES.LORA}/civitai/model/hash`, }, [MODEL_TYPES.CHECKPOINT]: { - info: `/api/${MODEL_TYPES.CHECKPOINT}/info`, - checkpoints_roots: `/api/${MODEL_TYPES.CHECKPOINT}/checkpoints_roots`, - unet_roots: `/api/${MODEL_TYPES.CHECKPOINT}/unet_roots`, - metadata: `/api/${MODEL_TYPES.CHECKPOINT}/metadata`, + info: `/api/lm/${MODEL_TYPES.CHECKPOINT}/info`, + checkpoints_roots: `/api/lm/${MODEL_TYPES.CHECKPOINT}/checkpoints_roots`, + unet_roots: `/api/lm/${MODEL_TYPES.CHECKPOINT}/unet_roots`, + metadata: `/api/lm/${MODEL_TYPES.CHECKPOINT}/metadata`, }, [MODEL_TYPES.EMBEDDING]: { - metadata: `/api/${MODEL_TYPES.EMBEDDING}/metadata`, + metadata: `/api/lm/${MODEL_TYPES.EMBEDDING}/metadata`, } }; @@ -173,11 +173,11 @@ export function getCurrentModelType(explicitType = null) { // Download API endpoints (shared across all model types) export const DOWNLOAD_ENDPOINTS = { - download: '/api/download-model', - downloadGet: '/api/download-model-get', - cancelGet: '/api/cancel-download-get', - progress: '/api/download-progress', - exampleImages: '/api/force-download-example-images' // New endpoint for downloading example images + download: '/api/lm/download-model', + downloadGet: '/api/lm/download-model-get', + cancelGet: '/api/lm/cancel-download-get', + progress: '/api/lm/download-progress', + exampleImages: '/api/lm/force-download-example-images' // New endpoint for downloading example images }; // WebSocket endpoints diff --git a/static/js/api/recipeApi.js b/static/js/api/recipeApi.js index fec0d02f..3b912905 100644 --- a/static/js/api/recipeApi.js +++ b/static/js/api/recipeApi.js @@ -21,7 +21,7 @@ export async function fetchRecipesPage(page = 1, pageSize = 100) { // If we have a specific recipe ID to load if (pageState.customFilter?.active && pageState.customFilter?.recipeId) { // Special case: load specific recipe - const response = await fetch(`/api/recipe/${pageState.customFilter.recipeId}`); + const response = await fetch(`/api/lm/recipe/${pageState.customFilter.recipeId}`); if (!response.ok) { throw new Error(`Failed to load recipe: ${response.statusText}`); @@ -72,7 +72,7 @@ export async function fetchRecipesPage(page = 1, pageSize = 100) { } // Fetch recipes - const response = await fetch(`/api/recipes?${params.toString()}`); + const response = await fetch(`/api/lm/recipes?${params.toString()}`); if (!response.ok) { throw new Error(`Failed to load recipes: ${response.statusText}`); @@ -207,7 +207,7 @@ export async function refreshRecipes() { state.loadingManager.showSimpleLoading('Refreshing recipes...'); // Call the API endpoint to rebuild the recipe cache - const response = await fetch('/api/recipes/scan'); + const response = await fetch('/api/lm/recipes/scan'); if (!response.ok) { const data = await response.json(); @@ -274,7 +274,7 @@ export async function updateRecipeMetadata(filePath, updates) { const basename = filePath.split('/').pop().split('\\').pop(); const recipeId = basename.substring(0, basename.lastIndexOf('.')); - const response = await fetch(`/api/recipe/${recipeId}/update`, { + const response = await fetch(`/api/lm/recipe/${recipeId}/update`, { method: 'PUT', headers: { 'Content-Type': 'application/json', diff --git a/static/js/components/ContextMenu/ModelContextMenuMixin.js b/static/js/components/ContextMenu/ModelContextMenuMixin.js index cd376dd1..3c461a9a 100644 --- a/static/js/components/ContextMenu/ModelContextMenuMixin.js +++ b/static/js/components/ContextMenu/ModelContextMenuMixin.js @@ -125,8 +125,8 @@ export const ModelContextMenuMixin = { state.loadingManager.showSimpleLoading('Re-linking to Civitai...'); const endpoint = this.modelType === 'checkpoint' ? - '/api/checkpoints/relink-civitai' : - '/api/loras/relink-civitai'; + '/api/lm/checkpoints/relink-civitai' : + '/api/lm/loras/relink-civitai'; const response = await fetch(endpoint, { method: 'POST', diff --git a/static/js/components/ContextMenu/RecipeContextMenu.js b/static/js/components/ContextMenu/RecipeContextMenu.js index 351263c7..bb8b8e69 100644 --- a/static/js/components/ContextMenu/RecipeContextMenu.js +++ b/static/js/components/ContextMenu/RecipeContextMenu.js @@ -103,7 +103,7 @@ export class RecipeContextMenu extends BaseContextMenu { return; } - fetch(`/api/recipe/${recipeId}/syntax`) + fetch(`/api/lm/recipe/${recipeId}/syntax`) .then(response => response.json()) .then(data => { if (data.success && data.syntax) { @@ -126,7 +126,7 @@ export class RecipeContextMenu extends BaseContextMenu { return; } - fetch(`/api/recipe/${recipeId}/syntax`) + fetch(`/api/lm/recipe/${recipeId}/syntax`) .then(response => response.json()) .then(data => { if (data.success && data.syntax) { @@ -149,7 +149,7 @@ export class RecipeContextMenu extends BaseContextMenu { } // First get the recipe details to access its LoRAs - fetch(`/api/recipe/${recipeId}`) + fetch(`/api/lm/recipe/${recipeId}`) .then(response => response.json()) .then(recipe => { // Clear any previous filters first @@ -189,7 +189,7 @@ export class RecipeContextMenu extends BaseContextMenu { try { // First get the recipe details - const response = await fetch(`/api/recipe/${recipeId}`); + const response = await fetch(`/api/lm/recipe/${recipeId}`); const recipe = await response.json(); // Get missing LoRAs @@ -209,9 +209,9 @@ export class RecipeContextMenu extends BaseContextMenu { // Determine which endpoint to use based on available data if (lora.modelVersionId) { - endpoint = `/api/loras/civitai/model/version/${lora.modelVersionId}`; + endpoint = `/api/lm/loras/civitai/model/version/${lora.modelVersionId}`; } else if (lora.hash) { - endpoint = `/api/loras/civitai/model/hash/${lora.hash}`; + endpoint = `/api/lm/loras/civitai/model/hash/${lora.hash}`; } else { console.error("Missing both hash and modelVersionId for lora:", lora); return null; diff --git a/static/js/components/DuplicatesManager.js b/static/js/components/DuplicatesManager.js index f49a2d02..a2360c06 100644 --- a/static/js/components/DuplicatesManager.js +++ b/static/js/components/DuplicatesManager.js @@ -13,7 +13,7 @@ export class DuplicatesManager { async findDuplicates() { try { - const response = await fetch('/api/recipes/find-duplicates'); + const response = await fetch('/api/lm/recipes/find-duplicates'); if (!response.ok) { throw new Error('Failed to find duplicates'); } @@ -354,7 +354,7 @@ export class DuplicatesManager { const recipeIds = Array.from(this.selectedForDeletion); // Call API to bulk delete - const response = await fetch('/api/recipes/bulk-delete', { + const response = await fetch('/api/lm/recipes/bulk-delete', { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/static/js/components/ModelDuplicatesManager.js b/static/js/components/ModelDuplicatesManager.js index c8879ce9..33df3779 100644 --- a/static/js/components/ModelDuplicatesManager.js +++ b/static/js/components/ModelDuplicatesManager.js @@ -48,7 +48,7 @@ export class ModelDuplicatesManager { // Method to check for duplicates count using existing endpoint async checkDuplicatesCount() { try { - const endpoint = `/api/${this.modelType}/find-duplicates`; + const endpoint = `/api/lm/${this.modelType}/find-duplicates`; const response = await fetch(endpoint); if (!response.ok) { @@ -104,7 +104,7 @@ export class ModelDuplicatesManager { async findDuplicates() { try { // Determine API endpoint based on model type - const endpoint = `/api/${this.modelType}/find-duplicates`; + const endpoint = `/api/lm/${this.modelType}/find-duplicates`; const response = await fetch(endpoint); if (!response.ok) { @@ -623,7 +623,7 @@ export class ModelDuplicatesManager { const filePaths = Array.from(this.selectedForDeletion); // Call API to bulk delete - const response = await fetch(`/api/${this.modelType}/bulk-delete`, { + const response = await fetch(`/api/lm/${this.modelType}/bulk-delete`, { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -648,7 +648,7 @@ export class ModelDuplicatesManager { // Check if there are still duplicates try { - const endpoint = `/api/${this.modelType}/find-duplicates`; + const endpoint = `/api/lm/${this.modelType}/find-duplicates`; const dupResponse = await fetch(endpoint); if (!dupResponse.ok) { @@ -756,7 +756,7 @@ export class ModelDuplicatesManager { const filePaths = group.models.map(model => model.file_path); // Make API request to verify hashes - const response = await fetch(`/api/${this.modelType}/verify-duplicates`, { + const response = await fetch(`/api/lm/${this.modelType}/verify-duplicates`, { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/static/js/components/RecipeCard.js b/static/js/components/RecipeCard.js index 0eaa68ad..c496a928 100644 --- a/static/js/components/RecipeCard.js +++ b/static/js/components/RecipeCard.js @@ -203,7 +203,7 @@ class RecipeCard { return; } - fetch(`/api/recipe/${recipeId}/syntax`) + fetch(`/api/lm/recipe/${recipeId}/syntax`) .then(response => response.json()) .then(data => { if (data.success && data.syntax) { @@ -299,7 +299,7 @@ class RecipeCard { deleteBtn.disabled = true; // Call API to delete the recipe - fetch(`/api/recipe/${recipeId}`, { + fetch(`/api/lm/recipe/${recipeId}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json' @@ -341,7 +341,7 @@ class RecipeCard { showToast('toast.recipes.preparingForSharing', {}, 'info'); // Call the API to process the image with metadata - fetch(`/api/recipe/${recipeId}/share`) + fetch(`/api/lm/recipe/${recipeId}/share`) .then(response => { if (!response.ok) { throw new Error('Failed to prepare recipe for sharing'); diff --git a/static/js/components/RecipeModal.js b/static/js/components/RecipeModal.js index ffbfa2aa..68d61eb9 100644 --- a/static/js/components/RecipeModal.js +++ b/static/js/components/RecipeModal.js @@ -784,7 +784,7 @@ class RecipeModal { try { // Fetch recipe syntax from backend - const response = await fetch(`/api/recipe/${this.recipeId}/syntax`); + const response = await fetch(`/api/lm/recipe/${this.recipeId}/syntax`); if (!response.ok) { throw new Error(`Failed to get recipe syntax: ${response.statusText}`); @@ -830,9 +830,9 @@ class RecipeModal { // Determine which endpoint to use based on available data if (lora.modelVersionId) { - endpoint = `/api/loras/civitai/model/version/${lora.modelVersionId}`; + endpoint = `/api/lm/loras/civitai/model/version/${lora.modelVersionId}`; } else if (lora.hash) { - endpoint = `/api/loras/civitai/model/hash/${lora.hash}`; + endpoint = `/api/lm/loras/civitai/model/hash/${lora.hash}`; } else { console.error("Missing both hash and modelVersionId for lora:", lora); return null; @@ -1003,7 +1003,7 @@ class RecipeModal { state.loadingManager.showSimpleLoading('Reconnecting LoRA...'); // Call API to reconnect the LoRA - const response = await fetch('/api/recipe/lora/reconnect', { + const response = await fetch('/api/lm/recipe/lora/reconnect', { method: 'POST', headers: { 'Content-Type': 'application/json', diff --git a/static/js/components/alphabet/AlphabetBar.js b/static/js/components/alphabet/AlphabetBar.js index 82113758..2d358156 100644 --- a/static/js/components/alphabet/AlphabetBar.js +++ b/static/js/components/alphabet/AlphabetBar.js @@ -46,7 +46,7 @@ export class AlphabetBar { */ async fetchLetterCounts() { try { - const response = await fetch('/api/loras/letter-counts'); + const response = await fetch('/api/lm/loras/letter-counts'); if (!response.ok) { throw new Error(`Failed to fetch letter counts: ${response.statusText}`); diff --git a/static/js/components/initialization.js b/static/js/components/initialization.js index e7b6818f..9a547a86 100644 --- a/static/js/components/initialization.js +++ b/static/js/components/initialization.js @@ -169,7 +169,7 @@ class InitializationManager { */ pollProgress() { const checkProgress = () => { - fetch('/api/init-status') + fetch('/api/lm/init-status') .then(response => response.json()) .then(data => { this.handleProgressUpdate(data); diff --git a/static/js/components/shared/ModelCard.js b/static/js/components/shared/ModelCard.js index aa3208a0..c17b60fd 100644 --- a/static/js/components/shared/ModelCard.js +++ b/static/js/components/shared/ModelCard.js @@ -186,7 +186,7 @@ async function handleExampleImagesAccess(card, modelType) { const modelHash = card.dataset.sha256; try { - const response = await fetch(`/api/has-example-images?model_hash=${modelHash}`); + const response = await fetch(`/api/lm/has-example-images?model_hash=${modelHash}`); const data = await response.json(); if (data.has_images) { diff --git a/static/js/components/shared/ModelModal.js b/static/js/components/shared/ModelModal.js index 2a1f525b..081b0a46 100644 --- a/static/js/components/shared/ModelModal.js +++ b/static/js/components/shared/ModelModal.js @@ -460,7 +460,7 @@ async function saveNotes(filePath) { */ async function openFileLocation(filePath) { try { - const resp = await fetch('/api/open-file-location', { + const resp = await fetch('/api/lm/open-file-location', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ 'file_path': filePath }) diff --git a/static/js/components/shared/RecipeTab.js b/static/js/components/shared/RecipeTab.js index 78c4e9cc..ffa439c9 100644 --- a/static/js/components/shared/RecipeTab.js +++ b/static/js/components/shared/RecipeTab.js @@ -22,7 +22,7 @@ export function loadRecipesForLora(loraName, sha256) { `; // Fetch recipes that use this Lora by hash - fetch(`/api/recipes/for-lora?hash=${encodeURIComponent(sha256.toLowerCase())}`) + fetch(`/api/lm/recipes/for-lora?hash=${encodeURIComponent(sha256.toLowerCase())}`) .then(response => response.json()) .then(data => { if (!data.success) { @@ -166,7 +166,7 @@ function copyRecipeSyntax(recipeId) { return; } - fetch(`/api/recipe/${recipeId}/syntax`) + fetch(`/api/lm/recipe/${recipeId}/syntax`) .then(response => response.json()) .then(data => { if (data.success && data.syntax) { diff --git a/static/js/components/shared/TriggerWords.js b/static/js/components/shared/TriggerWords.js index 28d1f173..564f5230 100644 --- a/static/js/components/shared/TriggerWords.js +++ b/static/js/components/shared/TriggerWords.js @@ -14,7 +14,7 @@ import { getModelApiClient } from '../../api/modelApiFactory.js'; */ async function fetchTrainedWords(filePath) { try { - const response = await fetch(`/api/trained-words?file_path=${encodeURIComponent(filePath)}`); + const response = await fetch(`/api/lm/trained-words?file_path=${encodeURIComponent(filePath)}`); const data = await response.json(); if (data.success) { diff --git a/static/js/components/shared/showcase/MediaUtils.js b/static/js/components/shared/showcase/MediaUtils.js index 0da17c53..7a56f5ab 100644 --- a/static/js/components/shared/showcase/MediaUtils.js +++ b/static/js/components/shared/showcase/MediaUtils.js @@ -408,7 +408,7 @@ export function initMediaControlHandlers(container) { try { // Call the API to delete the custom example - const response = await fetch('/api/delete-example-image', { + const response = await fetch('/api/lm/delete-example-image', { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/static/js/components/shared/showcase/ShowcaseView.js b/static/js/components/shared/showcase/ShowcaseView.js index b4b96b0f..257753fd 100644 --- a/static/js/components/shared/showcase/ShowcaseView.js +++ b/static/js/components/shared/showcase/ShowcaseView.js @@ -29,7 +29,7 @@ export async function loadExampleImages(images, modelHash) { let localFiles = []; try { - const endpoint = '/api/example-image-files'; + const endpoint = '/api/lm/example-image-files'; const params = `model_hash=${modelHash}`; const response = await fetch(`${endpoint}?${params}`); @@ -374,7 +374,7 @@ async function handleImportFiles(files, modelHash, importContainer) { }); // Call API to import files - const response = await fetch('/api/import-example-images', { + const response = await fetch('/api/lm/import-example-images', { method: 'POST', body: formData }); @@ -386,7 +386,7 @@ async function handleImportFiles(files, modelHash, importContainer) { } // Get updated local files - const updatedFilesResponse = await fetch(`/api/example-image-files?model_hash=${modelHash}`); + const updatedFilesResponse = await fetch(`/api/lm/example-image-files?model_hash=${modelHash}`); const updatedFilesResult = await updatedFilesResponse.json(); if (!updatedFilesResult.success) { diff --git a/static/js/managers/ExampleImagesManager.js b/static/js/managers/ExampleImagesManager.js index 38150749..7cb6d2ac 100644 --- a/static/js/managers/ExampleImagesManager.js +++ b/static/js/managers/ExampleImagesManager.js @@ -172,7 +172,7 @@ export class ExampleImagesManager { async checkDownloadStatus() { try { - const response = await fetch('/api/example-images-status'); + const response = await fetch('/api/lm/example-images-status'); const data = await response.json(); if (data.success) { @@ -236,7 +236,7 @@ export class ExampleImagesManager { const optimize = state.global.settings.optimizeExampleImages; - const response = await fetch('/api/download-example-images', { + const response = await fetch('/api/lm/download-example-images', { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -278,7 +278,7 @@ export class ExampleImagesManager { } try { - const response = await fetch('/api/pause-example-images', { + const response = await fetch('/api/lm/pause-example-images', { method: 'POST' }); @@ -314,7 +314,7 @@ export class ExampleImagesManager { } try { - const response = await fetch('/api/resume-example-images', { + const response = await fetch('/api/lm/resume-example-images', { method: 'POST' }); @@ -358,7 +358,7 @@ export class ExampleImagesManager { async updateProgress() { try { - const response = await fetch('/api/example-images-status'); + const response = await fetch('/api/lm/example-images-status'); const data = await response.json(); if (data.success) { @@ -727,7 +727,7 @@ export class ExampleImagesManager { const outputDir = document.getElementById('exampleImagesPath').value; const optimize = state.global.settings.optimizeExampleImages; - const response = await fetch('/api/download-example-images', { + const response = await fetch('/api/lm/download-example-images', { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/static/js/managers/FilterManager.js b/static/js/managers/FilterManager.js index 12c35c0d..adac4ede 100644 --- a/static/js/managers/FilterManager.js +++ b/static/js/managers/FilterManager.js @@ -66,7 +66,7 @@ export class FilterManager { tagsContainer.innerHTML = '
Loading tags...
'; // Determine the API endpoint based on the page type - const tagsEndpoint = `/api/${this.currentPage}/top-tags?limit=20`; + const tagsEndpoint = `/api/lm/${this.currentPage}/top-tags?limit=20`; const response = await fetch(tagsEndpoint); if (!response.ok) throw new Error('Failed to fetch tags'); @@ -134,7 +134,7 @@ export class FilterManager { if (!baseModelTagsContainer) return; // Set the API endpoint based on current page - const apiEndpoint = `/api/${this.currentPage}/base-models`; + const apiEndpoint = `/api/lm/${this.currentPage}/base-models`; // Fetch base models fetch(apiEndpoint) diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index 33040aac..9de7a7dc 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -429,7 +429,7 @@ export class SettingsManager { if (!defaultLoraRootSelect) return; // Fetch lora roots - const response = await fetch('/api/loras/roots'); + const response = await fetch('/api/lm/loras/roots'); if (!response.ok) { throw new Error('Failed to fetch LoRA roots'); } @@ -468,7 +468,7 @@ export class SettingsManager { if (!defaultCheckpointRootSelect) return; // Fetch checkpoint roots - const response = await fetch('/api/checkpoints/roots'); + const response = await fetch('/api/lm/checkpoints/roots'); if (!response.ok) { throw new Error('Failed to fetch checkpoint roots'); } @@ -507,7 +507,7 @@ export class SettingsManager { if (!defaultEmbeddingRootSelect) return; // Fetch embedding roots - const response = await fetch('/api/embeddings/roots'); + const response = await fetch('/api/lm/embeddings/roots'); if (!response.ok) { throw new Error('Failed to fetch embedding roots'); } @@ -1023,7 +1023,7 @@ export class SettingsManager { async updateMetadataArchiveStatus() { try { - const response = await fetch('/api/metadata-archive-status'); + const response = await fetch('/api/lm/metadata-archive-status'); const data = await response.json(); const statusContainer = document.getElementById('metadataArchiveStatus'); @@ -1152,7 +1152,7 @@ export class SettingsManager { // Wait for WebSocket to be ready await wsReady; - const response = await fetch(`/api/download-metadata-archive?download_id=${encodeURIComponent(actualDownloadId)}`, { + const response = await fetch(`/api/lm/download-metadata-archive?download_id=${encodeURIComponent(actualDownloadId)}`, { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -1215,7 +1215,7 @@ export class SettingsManager { removeBtn.textContent = translate('settings.metadataArchive.removingButton'); } - const response = await fetch('/api/remove-metadata-archive', { + const response = await fetch('/api/lm/remove-metadata-archive', { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/static/js/managers/UpdateService.js b/static/js/managers/UpdateService.js index 5beb0f94..b1d29960 100644 --- a/static/js/managers/UpdateService.js +++ b/static/js/managers/UpdateService.js @@ -97,7 +97,7 @@ export class UpdateService { try { // Call backend API to check for updates with nightly flag - const response = await fetch(`/api/check-updates?nightly=${this.nightlyMode}`); + const response = await fetch(`/api/lm/check-updates?nightly=${this.nightlyMode}`); const data = await response.json(); if (data.success) { @@ -280,7 +280,7 @@ export class UpdateService { // Update progress this.updateProgress(10, translate('update.updateProgress.preparing')); - const response = await fetch('/api/perform-update', { + const response = await fetch('/api/lm/perform-update', { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -444,7 +444,7 @@ export class UpdateService { async checkVersionInfo() { try { // Call API to get current version info - const response = await fetch('/api/version-info'); + const response = await fetch('/api/lm/version-info'); const data = await response.json(); if (data.success) { diff --git a/static/js/managers/import/DownloadManager.js b/static/js/managers/import/DownloadManager.js index ffbefb20..c71e9e31 100644 --- a/static/js/managers/import/DownloadManager.js +++ b/static/js/managers/import/DownloadManager.js @@ -68,7 +68,7 @@ export class DownloadManager { formData.append('metadata', JSON.stringify(completeMetadata)); // Send save request - const response = await fetch('/api/recipes/save', { + const response = await fetch('/api/lm/recipes/save', { method: 'POST', body: formData }); diff --git a/static/js/managers/import/FolderBrowser.js b/static/js/managers/import/FolderBrowser.js index 32f39b80..43cfbada 100644 --- a/static/js/managers/import/FolderBrowser.js +++ b/static/js/managers/import/FolderBrowser.js @@ -100,7 +100,7 @@ export class FolderBrowser { } // Fetch LoRA roots - const rootsResponse = await fetch('/api/loras/roots'); + const rootsResponse = await fetch('/api/lm/loras/roots'); if (!rootsResponse.ok) { throw new Error(`Failed to fetch LoRA roots: ${rootsResponse.status}`); } @@ -120,7 +120,7 @@ export class FolderBrowser { } // Fetch folders - const foldersResponse = await fetch('/api/loras/folders'); + const foldersResponse = await fetch('/api/lm/loras/folders'); if (!foldersResponse.ok) { throw new Error(`Failed to fetch folders: ${foldersResponse.status}`); } diff --git a/static/js/managers/import/ImageProcessor.js b/static/js/managers/import/ImageProcessor.js index 37f4b7ef..66ca0dc2 100644 --- a/static/js/managers/import/ImageProcessor.js +++ b/static/js/managers/import/ImageProcessor.js @@ -62,7 +62,7 @@ export class ImageProcessor { async analyzeImageFromUrl(url) { try { // Call the API with URL data - const response = await fetch('/api/recipes/analyze-image', { + const response = await fetch('/api/lm/recipes/analyze-image', { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -110,7 +110,7 @@ export class ImageProcessor { async analyzeImageFromLocalPath(path) { try { // Call the API with local path data - const response = await fetch('/api/recipes/analyze-local-image', { + const response = await fetch('/api/lm/recipes/analyze-local-image', { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -169,7 +169,7 @@ export class ImageProcessor { formData.append('image', this.importManager.recipeImage); // Upload image for analysis - const response = await fetch('/api/recipes/analyze-image', { + const response = await fetch('/api/lm/recipes/analyze-image', { method: 'POST', body: formData }); diff --git a/static/js/statistics.js b/static/js/statistics.js index 4b79934b..930199aa 100644 --- a/static/js/statistics.js +++ b/static/js/statistics.js @@ -65,12 +65,12 @@ class StatisticsManager { storageAnalytics, insights ] = await Promise.all([ - this.fetchData('/api/stats/collection-overview'), - this.fetchData('/api/stats/usage-analytics'), - this.fetchData('/api/stats/base-model-distribution'), - this.fetchData('/api/stats/tag-analytics'), - this.fetchData('/api/stats/storage-analytics'), - this.fetchData('/api/stats/insights') + this.fetchData('/api/lm/stats/collection-overview'), + this.fetchData('/api/lm/stats/usage-analytics'), + this.fetchData('/api/lm/stats/base-model-distribution'), + this.fetchData('/api/lm/stats/tag-analytics'), + this.fetchData('/api/lm/stats/storage-analytics'), + this.fetchData('/api/lm/stats/insights') ]); this.data = { diff --git a/static/js/utils/uiHelpers.js b/static/js/utils/uiHelpers.js index 2281ecf7..f4e4091a 100644 --- a/static/js/utils/uiHelpers.js +++ b/static/js/utils/uiHelpers.js @@ -370,7 +370,7 @@ export function copyLoraSyntax(card) { export async function sendLoraToWorkflow(loraSyntax, replaceMode = false, syntaxType = 'lora') { try { // Get registry information from the new endpoint - const registryResponse = await fetch('/api/get-registry'); + const registryResponse = await fetch('/api/lm/get-registry'); const registryData = await registryResponse.json(); if (!registryData.success) { @@ -417,7 +417,7 @@ export async function sendLoraToWorkflow(loraSyntax, replaceMode = false, syntax async function sendToSpecificNode(nodeIds, loraSyntax, replaceMode, syntaxType) { try { // Call the backend API to update the lora code - const response = await fetch('/api/update-lora-code', { + const response = await fetch('/api/lm/update-lora-code', { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -676,7 +676,7 @@ initializeMouseTracking(); */ export async function openExampleImagesFolder(modelHash) { try { - const response = await fetch('/api/open-example-images-folder', { + const response = await fetch('/api/lm/open-example-images-folder', { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/web/comfyui/autocomplete.js b/web/comfyui/autocomplete.js index 6e4e8e03..202026ad 100644 --- a/web/comfyui/autocomplete.js +++ b/web/comfyui/autocomplete.js @@ -156,7 +156,7 @@ class AutoComplete { async search(term = '') { try { this.currentSearchTerm = term; - const response = await api.fetchApi(`/${this.modelType}/relative-paths?search=${encodeURIComponent(term)}&limit=${this.options.maxItems}`); + const response = await api.fetchApi(`/lm/${this.modelType}/relative-paths?search=${encodeURIComponent(term)}&limit=${this.options.maxItems}`); const data = await response.json(); if (data.success && data.relative_paths && data.relative_paths.length > 0) { @@ -383,7 +383,7 @@ class AutoComplete { // Get usage tips and extract strength let strength = 1.0; // Default strength try { - const response = await api.fetchApi(`/loras/usage-tips-by-path?relative_path=${encodeURIComponent(relativePath)}`); + const response = await api.fetchApi(`/lm/loras/usage-tips-by-path?relative_path=${encodeURIComponent(relativePath)}`); if (response.ok) { const data = await response.json(); if (data.success && data.usage_tips) { diff --git a/web/comfyui/loras_widget_components.js b/web/comfyui/loras_widget_components.js index fcde1972..fc40dce3 100644 --- a/web/comfyui/loras_widget_components.js +++ b/web/comfyui/loras_widget_components.js @@ -269,7 +269,7 @@ export class PreviewTooltip { this.currentLora = loraName; // Get preview URL - const response = await api.fetchApi(`/loras/preview-url?name=${encodeURIComponent(loraName)}`, { + const response = await api.fetchApi(`/lm/loras/preview-url?name=${encodeURIComponent(loraName)}`, { method: 'GET' }); diff --git a/web/comfyui/loras_widget_events.js b/web/comfyui/loras_widget_events.js index fa0d5633..85564891 100644 --- a/web/comfyui/loras_widget_events.js +++ b/web/comfyui/loras_widget_events.js @@ -491,7 +491,7 @@ export function createContextMenu(x, y, loraName, widget, previewTooltip, render try { // Get Civitai URL from API - const response = await api.fetchApi(`/loras/civitai-url?name=${encodeURIComponent(loraName)}`, { + const response = await api.fetchApi(`/lm/loras/civitai-url?name=${encodeURIComponent(loraName)}`, { method: 'GET' }); @@ -547,7 +547,7 @@ export function createContextMenu(x, y, loraName, widget, previewTooltip, render try { // Get notes from API - const response = await api.fetchApi(`/loras/get-notes?name=${encodeURIComponent(loraName)}`, { + const response = await api.fetchApi(`/lm/loras/get-notes?name=${encodeURIComponent(loraName)}`, { method: 'GET' }); @@ -584,7 +584,7 @@ export function createContextMenu(x, y, loraName, widget, previewTooltip, render try { // Get trigger words from API - const response = await api.fetchApi(`/loras/get-trigger-words?name=${encodeURIComponent(loraName)}`, { + const response = await api.fetchApi(`/lm/loras/get-trigger-words?name=${encodeURIComponent(loraName)}`, { method: 'GET' }); diff --git a/web/comfyui/loras_widget_utils.js b/web/comfyui/loras_widget_utils.js index 1b4193b3..85913c72 100644 --- a/web/comfyui/loras_widget_utils.js +++ b/web/comfyui/loras_widget_utils.js @@ -70,7 +70,7 @@ export async function saveRecipeDirectly() { } // Send the request to the backend API - const response = await fetch('/api/recipes/save-from-widget', { + const response = await fetch('/api/lm/recipes/save-from-widget', { method: 'POST' }); diff --git a/web/comfyui/ui_utils.js b/web/comfyui/ui_utils.js index 524940c8..4996c67a 100644 --- a/web/comfyui/ui_utils.js +++ b/web/comfyui/ui_utils.js @@ -107,7 +107,7 @@ const initializeWidgets = () => { // Fetch version info from the API const fetchVersionInfo = async () => { try { - const response = await fetch('/api/version-info'); + const response = await fetch('/api/lm/version-info'); const data = await response.json(); if (data.success) { diff --git a/web/comfyui/usage_stats.js b/web/comfyui/usage_stats.js index b0844114..b89eaf46 100644 --- a/web/comfyui/usage_stats.js +++ b/web/comfyui/usage_stats.js @@ -38,7 +38,7 @@ app.registerExtension({ async updateUsageStats(promptId) { try { // Call backend endpoint with the prompt_id - const response = await fetch(`/api/update-usage-stats`, { + const response = await fetch(`/api/lm/update-usage-stats`, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -79,7 +79,7 @@ app.registerExtension({ } } - const response = await fetch('/api/register-nodes', { + const response = await fetch('/api/lm/register-nodes', { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -158,7 +158,7 @@ app.registerExtension({ try { // Search for current relative path - const response = await api.fetchApi(`/${modelType}/relative-paths?search=${encodeURIComponent(fileName)}&limit=2`); + const response = await api.fetchApi(`/lm/${modelType}/relative-paths?search=${encodeURIComponent(fileName)}&limit=2`); const data = await response.json(); if (!data.success || !data.relative_paths || data.relative_paths.length === 0) { From bc4cd45fcbba1bf1b1ceb77bfa4c8edb9360c9b6 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Thu, 18 Sep 2025 15:09:32 +0800 Subject: [PATCH 033/110] fix(lora_manager): rename invalid hash folder removal to orphaned folders and update logging --- py/lora_manager.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/py/lora_manager.py b/py/lora_manager.py index 4379a3e1..1a99d508 100644 --- a/py/lora_manager.py +++ b/py/lora_manager.py @@ -368,7 +368,7 @@ class LoraManager: total_folders_checked = 0 empty_folders_removed = 0 - invalid_hash_folders_removed = 0 + orphaned_folders_removed = 0 # Scan the example images directory try: @@ -392,9 +392,8 @@ class LoraManager: # Check if folder name is a valid SHA256 hash (64 hex characters) if len(folder_name) != 64 or not all(c in '0123456789abcdefABCDEF' for c in folder_name): - logger.debug(f"Removing invalid hash folder: {folder_name}") - await cls._remove_folder_safely(folder_path) - invalid_hash_folders_removed += 1 + # Skip non-hash folders to avoid deleting other content + logger.debug(f"Skipping non-hash folder: {folder_name}") continue # Check if hash exists in any of the scanners @@ -407,7 +406,7 @@ class LoraManager: if not hash_exists: logger.debug(f"Removing example images folder for deleted model: {folder_name}") await cls._remove_folder_safely(folder_path) - invalid_hash_folders_removed += 1 + orphaned_folders_removed += 1 continue except Exception as e: @@ -421,11 +420,11 @@ class LoraManager: return # Log final cleanup report - total_removed = empty_folders_removed + invalid_hash_folders_removed + total_removed = empty_folders_removed + orphaned_folders_removed if total_removed > 0: logger.info(f"Example images cleanup completed: checked {total_folders_checked} folders, " - f"removed {empty_folders_removed} empty folders and {invalid_hash_folders_removed} " - f"folders for deleted/invalid models (total: {total_removed} removed)") + f"removed {empty_folders_removed} empty folders and {orphaned_folders_removed} " + f"folders for deleted models (total: {total_removed} removed)") else: logger.debug(f"Example images cleanup completed: checked {total_folders_checked} folders, " f"no cleanup needed") @@ -470,11 +469,5 @@ class LoraManager: try: logger.info("LoRA Manager: Cleaning up services") - # Close CivitaiClient gracefully - civitai_client = await ServiceRegistry.get_service("civitai_client") - if civitai_client: - await civitai_client.close() - logger.info("Closed CivitaiClient connection") - except Exception as e: logger.error(f"Error during cleanup: {e}", exc_info=True) From 46e430ebbbae10a96ac8b2a962dd5bf1b1dfb797 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Thu, 18 Sep 2025 15:45:57 +0800 Subject: [PATCH 034/110] fix(utils): update API endpoint for fetching connected trigger words --- web/comfyui/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/comfyui/utils.js b/web/comfyui/utils.js index 08cbff7a..8060414d 100644 --- a/web/comfyui/utils.js +++ b/web/comfyui/utils.js @@ -183,7 +183,7 @@ export function collectActiveLorasFromChain(node, visited = new Set()) { export function updateConnectedTriggerWords(node, loraNames) { const connectedNodeIds = getConnectedTriggerToggleNodes(node); if (connectedNodeIds.length > 0) { - fetch("/api/loras/get_trigger_words", { + fetch("/api/lm/loras/get_trigger_words", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ From d30fbeb286af6f9f951f578d6093569c888ccdd1 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Thu, 18 Sep 2025 19:22:29 +0800 Subject: [PATCH 035/110] feat(example_images): add dedicated folder check and update settings handling for example images path, see #431 --- py/routes/misc_routes.py | 58 ++++++++++++++++++++- py/utils/example_images_download_manager.py | 39 ++++++++++---- static/js/managers/ExampleImagesManager.js | 17 +----- static/js/managers/SettingsManager.js | 6 +-- 4 files changed, 88 insertions(+), 32 deletions(-) diff --git a/py/routes/misc_routes.py b/py/routes/misc_routes.py index 90b7d578..f8173133 100644 --- a/py/routes/misc_routes.py +++ b/py/routes/misc_routes.py @@ -4,6 +4,7 @@ import sys import threading import asyncio import subprocess +import re from server import PromptServer # type: ignore from aiohttp import web from ..services.settings_manager import settings @@ -85,6 +86,54 @@ node_registry = NodeRegistry() class MiscRoutes: """Miscellaneous routes for various utility functions""" + @staticmethod + def is_dedicated_example_images_folder(folder_path): + """ + Check if a folder is a dedicated example images folder. + + A dedicated folder should either be: + 1. Empty + 2. Only contain .download_progress.json file and/or folders with valid SHA256 hash names (64 hex characters) + + Args: + folder_path (str): Path to the folder to check + + Returns: + bool: True if the folder is dedicated, False otherwise + """ + try: + if not os.path.exists(folder_path) or not os.path.isdir(folder_path): + return False + + items = os.listdir(folder_path) + + # Empty folder is considered dedicated + if not items: + return True + + # Check each item in the folder + for item in items: + item_path = os.path.join(folder_path, item) + + # Allow .download_progress.json file + if item == '.download_progress.json' and os.path.isfile(item_path): + continue + + # Allow folders with valid SHA256 hash names (64 hex characters) + if os.path.isdir(item_path): + # Check if the folder name is a valid SHA256 hash + if re.match(r'^[a-fA-F0-9]{64}$', item): + continue + + # If we encounter anything else, it's not a dedicated folder + return False + + return True + + except Exception as e: + logger.error(f"Error checking if folder is dedicated: {e}") + return False + @staticmethod def setup_routes(app): """Register miscellaneous routes""" @@ -180,7 +229,7 @@ class MiscRoutes: if value == settings.get(key): # No change, skip continue - # Special handling for example_images_path - verify path exists + # Special handling for example_images_path - verify path exists and is dedicated if key == 'example_images_path' and value: if not os.path.exists(value): return web.json_response({ @@ -188,6 +237,13 @@ class MiscRoutes: 'error': f"Path does not exist: {value}" }) + # Check if folder is dedicated for example images + if not MiscRoutes.is_dedicated_example_images_folder(value): + return web.json_response({ + 'success': False, + 'error': "Please set a dedicated folder for example images." + }) + # Path changed - server restart required for new path to take effect old_path = settings.get('example_images_path') if old_path != value: diff --git a/py/utils/example_images_download_manager.py b/py/utils/example_images_download_manager.py index e3f46244..58df8d72 100644 --- a/py/utils/example_images_download_manager.py +++ b/py/utils/example_images_download_manager.py @@ -40,10 +40,10 @@ class DownloadManager: Expects a JSON body with: { - "output_dir": "path/to/output", # Base directory to save example images "optimize": true, # Whether to optimize images (default: true) "model_types": ["lora", "checkpoint"], # Model types to process (default: both) - "delay": 1.0 # Delay between downloads to avoid rate limiting (default: 1.0) + "delay": 1.0, # Delay between downloads to avoid rate limiting (default: 1.0) + "auto_mode": false # Flag to indicate automatic download (default: false) } """ global download_task, is_downloading, download_progress @@ -64,16 +64,30 @@ class DownloadManager: try: # Parse the request body data = await request.json() - output_dir = data.get('output_dir') + auto_mode = data.get('auto_mode', False) optimize = data.get('optimize', True) model_types = data.get('model_types', ['lora', 'checkpoint']) delay = float(data.get('delay', 0.2)) # Default to 0.2 seconds + # Get output directory from settings + from ..services.service_registry import ServiceRegistry + settings_manager = await ServiceRegistry.get_settings_manager() + output_dir = settings_manager.get('example_images_path') + if not output_dir: - return web.json_response({ - 'success': False, - 'error': 'Missing output_dir parameter' - }, status=400) + error_msg = 'Example images path not configured in settings' + if auto_mode: + # For auto mode, just log and return success to avoid showing error toasts + logger.debug(error_msg) + return web.json_response({ + 'success': True, + 'message': 'Example images path not configured, skipping auto download' + }) + else: + return web.json_response({ + 'success': False, + 'error': error_msg + }, status=400) # Create the output directory os.makedirs(output_dir, exist_ok=True) @@ -426,7 +440,6 @@ class DownloadManager: Expects a JSON body with: { "model_hashes": ["hash1", "hash2", ...], # List of model hashes to download - "output_dir": "path/to/output", # Base directory to save example images "optimize": true, # Whether to optimize images (default: true) "model_types": ["lora", "checkpoint"], # Model types to process (default: both) "delay": 1.0 # Delay between downloads (default: 1.0) @@ -444,7 +457,6 @@ class DownloadManager: # Parse the request body data = await request.json() model_hashes = data.get('model_hashes', []) - output_dir = data.get('output_dir') optimize = data.get('optimize', True) model_types = data.get('model_types', ['lora', 'checkpoint']) delay = float(data.get('delay', 0.2)) # Default to 0.2 seconds @@ -454,11 +466,16 @@ class DownloadManager: 'success': False, 'error': 'Missing model_hashes parameter' }, status=400) - + + # Get output directory from settings + from ..services.service_registry import ServiceRegistry + settings_manager = await ServiceRegistry.get_settings_manager() + output_dir = settings_manager.get('example_images_path') + if not output_dir: return web.json_response({ 'success': False, - 'error': 'Missing output_dir parameter' + 'error': 'Example images path not configured in settings' }, status=400) # Create the output directory diff --git a/static/js/managers/ExampleImagesManager.js b/static/js/managers/ExampleImagesManager.js index 7cb6d2ac..1c710040 100644 --- a/static/js/managers/ExampleImagesManager.js +++ b/static/js/managers/ExampleImagesManager.js @@ -100,9 +100,7 @@ export class ExampleImagesManager { this.updateDownloadButtonState(hasPath); try { await settingsManager.saveSetting('example_images_path', pathInput.value); - if (hasPath) { showToast('toast.exampleImages.pathUpdated', {}, 'success'); - } } catch (error) { console.error('Failed to update example images path:', error); showToast('toast.exampleImages.pathUpdateFailed', { message: error.message }, 'error'); @@ -227,13 +225,6 @@ export class ExampleImagesManager { } try { - const outputDir = document.getElementById('exampleImagesPath').value || ''; - - if (!outputDir) { - showToast('toast.exampleImages.enterLocationFirst', {}, 'warning'); - return; - } - const optimize = state.global.settings.optimizeExampleImages; const response = await fetch('/api/lm/download-example-images', { @@ -242,7 +233,6 @@ export class ExampleImagesManager { 'Content-Type': 'application/json' }, body: JSON.stringify({ - output_dir: outputDir, optimize: optimize, model_types: ['lora', 'checkpoint', 'embedding'] // Example types, adjust as needed }) @@ -691,9 +681,8 @@ export class ExampleImagesManager { return false; } - // Check if download path is set - const pathInput = document.getElementById('exampleImagesPath'); - if (!pathInput || !pathInput.value.trim()) { + // Check if download path is set in settings + if (!state.global.settings.example_images_path) { return false; } @@ -724,7 +713,6 @@ export class ExampleImagesManager { try { console.log('Performing auto download check...'); - const outputDir = document.getElementById('exampleImagesPath').value; const optimize = state.global.settings.optimizeExampleImages; const response = await fetch('/api/lm/download-example-images', { @@ -733,7 +721,6 @@ export class ExampleImagesManager { 'Content-Type': 'application/json' }, body: JSON.stringify({ - output_dir: outputDir, optimize: optimize, model_types: ['lora', 'checkpoint', 'embedding'], auto_mode: true // Flag to indicate this is an automatic download diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index 9de7a7dc..6633c3e1 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -140,7 +140,7 @@ export class SettingsManager { proxy_password: '', example_images_path: '', optimizeExampleImages: true, - autoDownloadExampleImages: true + autoDownloadExampleImages: false }; Object.keys(backendDefaults).forEach(key => { @@ -972,10 +972,6 @@ export class SettingsManager { await this.saveSetting('default_embedding_root', value); } else if (settingKey === 'display_density') { await this.saveSetting('displayDensity', value); - - // Also update compactMode for backwards compatibility - state.global.settings.compactMode = (value !== 'default'); - this.saveFrontendSettingsToStorage(); } else if (settingKey === 'card_info_display') { await this.saveSetting('cardInfoDisplay', value); } else if (settingKey === 'proxy_type') { From fb0d6b56411c0033994434bf07f1034540ccc403 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Thu, 18 Sep 2025 19:33:47 +0800 Subject: [PATCH 036/110] feat(docs): add comprehensive documentation for LoRA Manager Civitai Extension, including features, installation, privacy, and usage guidelines --- docs/EventManagementImplementation.md | 182 ---------------- docs/EventManagerDocs.md | 301 -------------------------- docs/LM-Extension-Wiki.md | 176 +++++++++++++++ 3 files changed, 176 insertions(+), 483 deletions(-) delete mode 100644 docs/EventManagementImplementation.md delete mode 100644 docs/EventManagerDocs.md create mode 100644 docs/LM-Extension-Wiki.md diff --git a/docs/EventManagementImplementation.md b/docs/EventManagementImplementation.md deleted file mode 100644 index 6631fc16..00000000 --- a/docs/EventManagementImplementation.md +++ /dev/null @@ -1,182 +0,0 @@ -# Event Management Implementation Summary - -## What Has Been Implemented - -### 1. Enhanced EventManager Class -- **Location**: `static/js/utils/EventManager.js` -- **Features**: - - Priority-based event handling - - Conditional execution based on application state - - Element filtering (target/exclude selectors) - - Mouse button filtering - - Automatic cleanup with cleanup functions - - State tracking for app modes - - Error handling for event handlers - -### 2. BulkManager Integration -- **Location**: `static/js/managers/BulkManager.js` -- **Migrated Events**: - - Global keyboard shortcuts (Ctrl+A, Escape, B key) - - Marquee selection events (mousedown, mousemove, mouseup, contextmenu) - - State synchronization with EventManager -- **Benefits**: - - Centralized priority handling - - Conditional execution based on modal state - - Better coordination with other components - -### 3. UIHelpers Integration -- **Location**: `static/js/utils/uiHelpers.js` -- **Migrated Events**: - - Mouse position tracking for node selector positioning - - Node selector click events (outside clicks and selection) - - State management for node selector -- **Benefits**: - - Reduced direct DOM listeners - - Coordinated state tracking - - Better cleanup - -### 4. ModelCard Integration -- **Location**: `static/js/components/shared/ModelCard.js` -- **Migrated Events**: - - Model card click delegation - - Action button handling (star, globe, copy, etc.) - - Better return value handling for event propagation -- **Benefits**: - - Single event listener for all model cards - - Priority-based execution - - Better event flow control - -### 5. Documentation and Initialization -- **EventManagerDocs.md**: Comprehensive documentation -- **eventManagementInit.js**: Initialization and global handlers -- **Features**: - - Global escape key handling - - Modal state synchronization - - Error handling - - Analytics integration points - - Cleanup on page unload - -## Application States Tracked - -1. **bulkMode**: When bulk selection mode is active -2. **marqueeActive**: When marquee selection is in progress -3. **modalOpen**: When any modal dialog is open -4. **nodeSelectorActive**: When node selector popup is visible - -## Priority Levels Used - -- **250+**: Critical system events (escape keys) -- **200+**: High priority system events (modal close) -- **100-199**: Application-level shortcuts (bulk operations) -- **80-99**: UI interactions (marquee selection) -- **60-79**: Component interactions (model cards) -- **10-49**: Tracking and monitoring -- **1-9**: Analytics and low-priority tasks - -## Event Flow Examples - -### Bulk Mode Toggle (B key) -1. **Priority 100**: BulkManager keyboard handler catches 'b' key -2. Toggles bulk mode state -3. Updates EventManager state -4. Updates UI accordingly -5. Stops propagation (returns true) - -### Marquee Selection -1. **Priority 80**: BulkManager mousedown handler (only in .models-container, excluding cards/buttons) -2. Starts marquee selection -3. **Priority 90**: BulkManager mousemove handler (only when marquee active) -4. Updates selection rectangle -5. **Priority 90**: BulkManager mouseup handler ends selection - -### Model Card Click -1. **Priority 60**: ModelCard delegation handler checks for specific elements -2. If action button: handles action and stops propagation -3. If general card click: continues to other handlers -4. Bulk selection may also handle the event if in bulk mode - -## Remaining Event Listeners (Not Yet Migrated) - -### High Priority for Migration -1. **SearchManager keyboard events** - Global search shortcuts -2. **ModalManager escape handling** - Already integrated with initialization -3. **Scroll-based events** - Back to top, virtual scrolling -4. **Resize events** - Panel positioning, responsive layouts - -### Medium Priority -1. **Form input events** - Tag inputs, settings forms -2. **Component-specific events** - Recipe modal, showcase view -3. **Sidebar events** - Resize handling, toggle events - -### Low Priority (Can Remain As-Is) -1. **VirtualScroller events** - Performance-critical, specialized -2. **Component lifecycle events** - Modal open/close callbacks -3. **One-time setup events** - Theme initialization, etc. - -## Benefits Achieved - -### Performance Improvements -- **Reduced DOM listeners**: From ~15+ individual listeners to ~5 coordinated handlers -- **Conditional execution**: Handlers only run when conditions are met -- **Priority ordering**: Important events handled first -- **Better memory management**: Automatic cleanup prevents leaks - -### Coordination Improvements -- **State synchronization**: All components aware of app state -- **Event flow control**: Proper propagation stopping -- **Conflict resolution**: Priority system prevents conflicts -- **Debugging**: Centralized event handling for easier debugging - -### Code Quality Improvements -- **Consistent patterns**: All event handling follows same patterns -- **Better separation of concerns**: Event logic separated from business logic -- **Error handling**: Centralized error catching and reporting -- **Documentation**: Clear patterns for future development - -## Next Steps (Recommendations) - -### 1. Migrate Search Events -```javascript -// In SearchManager.js -eventManager.addHandler('keydown', 'search-shortcuts', (e) => { - if ((e.ctrlKey || e.metaKey) && e.key === 'f') { - this.focusSearchInput(); - return true; - } -}, { priority: 120 }); -``` - -### 2. Integrate Resize Events -```javascript -// Create ResizeManager -eventManager.addHandler('resize', 'layout-resize', debounce((e) => { - this.updateLayoutDimensions(); -}, 250), { priority: 50 }); -``` - -### 3. Add Debug Mode -```javascript -// In EventManager.js -if (window.DEBUG_EVENTS) { - console.log(`Event ${eventType} handled by ${source} (priority: ${priority})`); -} -``` - -### 4. Create Event Analytics -```javascript -// Track event patterns for optimization -eventManager.addHandler('*', 'analytics', (e) => { - this.trackEventUsage(e.type, performance.now()); -}, { priority: 1 }); -``` - -## Testing Recommendations - -1. **Verify bulk mode interactions** work correctly -2. **Test marquee selection** in various scenarios -3. **Check modal state synchronization** -4. **Verify node selector** positioning and cleanup -5. **Test keyboard shortcuts** don't conflict -6. **Verify proper cleanup** when components are destroyed - -The centralized event management system provides a solid foundation for coordinated, efficient event handling across the application while maintaining good performance and code organization. diff --git a/docs/EventManagerDocs.md b/docs/EventManagerDocs.md deleted file mode 100644 index 2ccc8174..00000000 --- a/docs/EventManagerDocs.md +++ /dev/null @@ -1,301 +0,0 @@ -# Centralized Event Management System - -This document describes the centralized event management system that coordinates event handling across the ComfyUI LoRA Manager application. - -## Overview - -The `EventManager` class provides a centralized way to handle DOM events with priority-based execution, conditional execution based on application state, and proper cleanup mechanisms. - -## Features - -- **Priority-based execution**: Handlers with higher priority run first -- **Conditional execution**: Handlers can be executed based on application state -- **Element filtering**: Handlers can target specific elements or exclude others -- **Automatic cleanup**: Cleanup functions are called when handlers are removed -- **State tracking**: Tracks application states like bulk mode, modal open, etc. - -## Basic Usage - -### Importing - -```javascript -import { eventManager } from './EventManager.js'; -``` - -### Adding Event Handlers - -```javascript -eventManager.addHandler('click', 'myComponent', (event) => { - console.log('Button clicked!'); - return true; // Stop propagation to other handlers -}, { - priority: 100, - targetSelector: '.my-button', - skipWhenModalOpen: true -}); -``` - -### Removing Event Handlers - -```javascript -// Remove specific handler -eventManager.removeHandler('click', 'myComponent'); - -// Remove all handlers for a component -eventManager.removeAllHandlersForSource('myComponent'); -``` - -### Updating Application State - -```javascript -// Set state -eventManager.setState('bulkMode', true); -eventManager.setState('modalOpen', true); - -// Get state -const isBulkMode = eventManager.getState('bulkMode'); -``` - -## Available States - -- `bulkMode`: Whether bulk selection mode is active -- `marqueeActive`: Whether marquee selection is in progress -- `modalOpen`: Whether any modal is currently open -- `nodeSelectorActive`: Whether the node selector popup is active - -## Handler Options - -### Priority -Higher numbers = higher priority. Handlers run in descending priority order. - -```javascript -{ - priority: 100 // High priority -} -``` - -### Conditional Execution - -```javascript -{ - onlyInBulkMode: true, // Only run when bulk mode is active - onlyWhenMarqueeActive: true, // Only run when marquee selection is active - skipWhenModalOpen: true, // Skip when any modal is open - skipWhenNodeSelectorActive: true, // Skip when node selector is active - onlyWhenNodeSelectorActive: true // Only run when node selector is active -} -``` - -### Element Filtering - -```javascript -{ - targetSelector: '.model-card', // Only handle events on matching elements - excludeSelector: 'button, input', // Exclude events from these elements - button: 0 // Only handle specific mouse button (0=left, 1=middle, 2=right) -} -``` - -### Cleanup Functions - -```javascript -{ - cleanup: () => { - // Custom cleanup logic - console.log('Handler cleaned up'); - } -} -``` - -## Integration Examples - -### BulkManager Integration - -```javascript -class BulkManager { - registerEventHandlers() { - // High priority keyboard shortcuts - eventManager.addHandler('keydown', 'bulkManager-keyboard', (e) => { - return this.handleGlobalKeyboard(e); - }, { - priority: 100, - skipWhenModalOpen: true - }); - - // Marquee selection - eventManager.addHandler('mousedown', 'bulkManager-marquee-start', (e) => { - return this.handleMarqueeStart(e); - }, { - priority: 80, - skipWhenModalOpen: true, - targetSelector: '.models-container', - excludeSelector: '.model-card, button, input', - button: 0 - }); - } - - cleanup() { - eventManager.removeAllHandlersForSource('bulkManager-keyboard'); - eventManager.removeAllHandlersForSource('bulkManager-marquee-start'); - } -} -``` - -### Modal Integration - -```javascript -class ModalManager { - showModal(modalId) { - // Update state when modal opens - eventManager.setState('modalOpen', true); - this.displayModal(modalId); - } - - closeModal(modalId) { - // Update state when modal closes - eventManager.setState('modalOpen', false); - this.hideModal(modalId); - } -} -``` - -### Component Event Delegation - -```javascript -export function setupComponentEvents() { - eventManager.addHandler('click', 'myComponent-actions', (event) => { - const button = event.target.closest('.action-button'); - if (!button) return false; - - this.handleAction(button.dataset.action); - return true; // Stop propagation - }, { - priority: 60, - targetSelector: '.component-container' - }); -} -``` - -## Best Practices - -### 1. Use Descriptive Source Names -Use the format `componentName-purposeDescription`: -```javascript -// Good -'bulkManager-marqueeSelection' -'nodeSelector-clickOutside' -'modelCard-delegation' - -// Avoid -'bulk' -'click' -'handler1' -``` - -### 2. Set Appropriate Priorities -- 200+: Critical system events (escape keys, critical modals) -- 100-199: High priority application events (keyboard shortcuts) -- 50-99: Normal UI interactions (buttons, cards) -- 1-49: Low priority events (tracking, analytics) - -### 3. Use Conditional Execution -Instead of checking state inside handlers, use options: -```javascript -// Good -eventManager.addHandler('click', 'bulk-action', handler, { - onlyInBulkMode: true -}); - -// Avoid -eventManager.addHandler('click', 'bulk-action', (e) => { - if (!state.bulkMode) return; - // handler logic -}); -``` - -### 4. Clean Up Properly -Always clean up handlers when components are destroyed: -```javascript -class MyComponent { - constructor() { - this.registerEvents(); - } - - destroy() { - eventManager.removeAllHandlersForSource('myComponent'); - } -} -``` - -### 5. Return Values Matter -- Return `true` to stop event propagation to other handlers -- Return `false` or `undefined` to continue with other handlers - -## Migration Guide - -### From Direct Event Listeners - -**Before:** -```javascript -document.addEventListener('click', (e) => { - if (e.target.closest('.my-button')) { - this.handleClick(e); - } -}); -``` - -**After:** -```javascript -eventManager.addHandler('click', 'myComponent-button', (e) => { - this.handleClick(e); -}, { - targetSelector: '.my-button' -}); -``` - -### From Event Delegation - -**Before:** -```javascript -container.addEventListener('click', (e) => { - const card = e.target.closest('.model-card'); - if (!card) return; - - if (e.target.closest('.action-btn')) { - this.handleAction(e); - } -}); -``` - -**After:** -```javascript -eventManager.addHandler('click', 'container-actions', (e) => { - const card = e.target.closest('.model-card'); - if (!card) return false; - - if (e.target.closest('.action-btn')) { - this.handleAction(e); - return true; - } -}, { - targetSelector: '.container' -}); -``` - -## Performance Benefits - -1. **Reduced DOM listeners**: Single listener per event type instead of multiple -2. **Conditional execution**: Handlers only run when conditions are met -3. **Priority ordering**: Important handlers run first, avoiding unnecessary work -4. **Automatic cleanup**: Prevents memory leaks from orphaned listeners -5. **Centralized debugging**: All event handling flows through one system - -## Debugging - -Enable debug logging to trace event handling: -```javascript -// Add to EventManager.js for debugging -console.log(`Handling ${eventType} event with ${handlers.length} handlers`); -``` - -The event manager provides a foundation for coordinated, efficient event handling across the entire application. diff --git a/docs/LM-Extension-Wiki.md b/docs/LM-Extension-Wiki.md new file mode 100644 index 00000000..272d512b --- /dev/null +++ b/docs/LM-Extension-Wiki.md @@ -0,0 +1,176 @@ +## Overview + +The **LoRA Manager Civitai Extension** is a Browser extension designed to work seamlessly with [LoRA Manager](https://github.com/willmiao/ComfyUI-Lora-Manager) to significantly enhance your browsing experience on [Civitai](https://civitai.com). With this extension, you can: + +✅ Instantly see which models are already present in your local library +✅ Download new models with a single click +✅ Manage downloads efficiently with queue and parallel download support +✅ Keep your downloaded models automatically organized according to your custom settings + +![Civitai Models page](https://github.com/willmiao/ComfyUI-Lora-Manager/blob/main/wiki-images/civitai-models-page.png) + +--- + +## Why Are All Features for Supporters Only? + +I love building tools for the Stable Diffusion and ComfyUI communities, and LoRA Manager is a passion project that I've poured countless hours into. When I created this companion extension, my hope was to offer its core features for free, as a thank-you to all of you. + +Unfortunately, I've reached a point where I need to be realistic. The level of support from the free model has been far lower than what's needed to justify the continuous development and maintenance for both projects. It was a difficult decision, but I've chosen to make the extension's features exclusive to supporters. + +This change is crucial for me to be able to continue dedicating my time to improving the free and open-source LoRA Manager, which I'm committed to keeping available for everyone. + +Your support does more than just unlock a few features—it allows me to keep innovating and ensures the core LoRA Manager project thrives. I'm incredibly grateful for your understanding and any support you can offer. ❤️ + +(_For those who previously supported me on Ko-fi with a one-time donation, I'll be sending out license keys individually as a thank-you._) + + +--- + +## Installation + +### Supported Browsers & Installation Methods + +| Browser | Installation Method | +|--------------------|-------------------------------------------------------------------------------------| +| **Google Chrome** | [Chrome Web Store link](https://chromewebstore.google.com/detail/capigligggeijgmocnaflanlbghnamgm?utm_source=item-share-cb) | +| **Microsoft Edge** | Install via Chrome Web Store (compatible) | +| **Brave Browser** | Install via Chrome Web Store (compatible) | +| **Opera** | Install via Chrome Web Store (compatible) | +| **Firefox** | | + +For non-Chrome browsers (e.g., Microsoft Edge), you can typically install extensions from the Chrome Web Store by following these steps: open the extension’s Chrome Web Store page, click 'Get extension', then click 'Allow' when prompted to enable installations from other stores, and finally click 'Add extension' to complete the installation. + +--- + +## Privacy & Security + +I understand concerns around browser extensions and privacy, and I want to be fully transparent about how the **LM Civitai Extension** works: + +- **Reviewed and Verified** + This extension has been **manually reviewed and approved by the Chrome Web Store**. The Firefox version uses the **exact same code** (only the packaging format differs) and has passed **Mozilla’s Add-on review**. + +- **Minimal Network Access** + The only external server this extension connects to is: + **`https://willmiao.shop`** — used solely for **license validation**. + + It does **not collect, transmit, or store any personal or usage data**. + No browsing history, no user IDs, no analytics, no hidden trackers. + +- **Local-Only Model Detection** + Model detection and LoRA Manager communication all happen **locally** within your browser, directly interacting with your local LoRA Manager backend. + +I value your trust and are committed to keeping your local setup private and secure. If you have any questions, feel free to reach out! + +--- + +## How to Use + +After installing the extension, you'll automatically receive a **7-day trial** to explore all features. + +When the extension is correctly installed and your license is valid: + +- Open **Civitai**, and you'll see visual indicators added by the extension on model cards, showing: + - ✅ Models already present in your local library + - ⬇️ A download button for models not in your library + +Clicking the download button adds the corresponding model version to the download queue, waiting to be downloaded. You can set up to **5 models to download simultaneously**. + +### Visual Indicators Appear On: + +- **Home Page** — Featured models +- **Models Page** +- **Creator Profiles** — If the creator has set their models to be visible +- **Recommended Resources** — On individual model pages + +### Version Buttons on Model Pages + +On a specific model page, visual indicators also appear on version buttons, showing which versions are already in your local library. + +When switching to a specific version by clicking a version button: + +- Clicking the download button will open a dropdown: + - Download via **LoRA Manager** + - Download via **Original Download** (browser download) + +You can check **Remember my choice** to set your preferred default. You can change this setting anytime in the extension's settings. + +![Civitai Model Page](https://github.com/willmiao/ComfyUI-Lora-Manager/blob/main/wiki-images/civitai-model-page.png) + +### Resources on Image Pages (2025-08-05) — now shows in-library indicators for image resources. ‘Import image as recipe’ coming soon! + +![Civitai Image Page](https://github.com/willmiao/ComfyUI-Lora-Manager/blob/main/wiki-images/civitai-image-page.jpg) + +--- + +## Model Download Location & LoRA Manager Settings + +To use the **one-click download function**, you must first set: + +- Your **Default LoRAs Root** +- Your **Default Checkpoints Root** + +These are set within LoRA Manager's settings. + +When everything is configured, downloaded model files will be placed in: + +`//` + + +### Update: Default Path Customization (2025-07-21) + +A new setting to customize the default download path has been added in the nightly version. You can now personalize where models are saved when downloading via the LM Civitai Extension. + +![Default Path Customization](https://github.com/willmiao/ComfyUI-Lora-Manager/blob/main/wiki-images/default-path-customization.png) + +The previous YAML path mapping file will be deprecated—settings will now be unified in settings.json to simplify configuration. + +--- + +## Backend Port Configuration + +If your **ComfyUI** or **LoRA Manager** backend is running on a port **other than the default 8188**, you must configure the backend port in the extension's settings. + +After correctly setting and saving the port, you'll see in the extension's header area: +- A **Healthy** status with the tooltip: `Connected to LoRA Manager on port xxxx` + + +--- + +## Advanced Usage + +### Connecting to a Remote LoRA Manager + +If your LoRA Manager is running on another computer, you can still connect from your browser using port forwarding. + +> **Why can't you set a remote IP directly?** +> +> For privacy and security, the extension only requests access to `http://127.0.0.1/*`. Supporting remote IPs would require much broader permissions, which may be rejected by browser stores and could raise user concerns. + +**Solution: Port Forwarding with `socat`** + +On your browser computer, run: + +`socat TCP-LISTEN:8188,bind=127.0.0.1,fork TCP:REMOTE.IP.ADDRESS.HERE:8188` + +- Replace `REMOTE.IP.ADDRESS.HERE` with the IP of the machine running LoRA Manager. +- Adjust the port if needed. + +This lets the extension connect to `127.0.0.1:8188` as usual, with traffic forwarded to your remote server. + +_Thanks to user **Temikus** for sharing this solution!_ + +--- + +## Roadmap + +The extension will evolve alongside **LoRA Manager** improvements. Planned features include: + +- [x] Support for **additional model types** (e.g., embeddings) +- [ ] One-click **Recipe Import** +- [x] Display of in-library status for all resources in the **Resources Used** section of the image page +- [x] One-click **Auto-organize Models** + +**Stay tuned — and thank you for your support!** + +--- + From 67b274c1b24431d567d65f4479caee1e4397f1de Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Thu, 18 Sep 2025 21:55:21 +0800 Subject: [PATCH 037/110] feat(settings): add 'show_only_sfw' setting to manage content visibility --- py/services/settings_manager.py | 1 + static/js/managers/SettingsManager.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/py/services/settings_manager.py b/py/services/settings_manager.py index ec71104e..adc1fb3a 100644 --- a/py/services/settings_manager.py +++ b/py/services/settings_manager.py @@ -81,6 +81,7 @@ class SettingsManager: return { "civitai_api_key": "", "language": "en", + "show_only_sfw": False, # Show only SFW content "enable_metadata_archive_db": False, # Enable metadata archive database "proxy_enabled": False, # Enable app-level proxy "proxy_host": "", # Proxy host diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index 6633c3e1..8d4da06a 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -43,7 +43,6 @@ export class SettingsManager { // Frontend-only settings that should be stored in localStorage const frontendOnlyKeys = [ 'blurMatureContent', - 'show_only_sfw', 'autoplayOnHover', 'displayDensity', 'cardInfoDisplay', @@ -132,6 +131,7 @@ export class SettingsManager { download_path_templates: { ...DEFAULT_PATH_TEMPLATES }, enable_metadata_archive_db: false, language: 'en', + show_only_sfw: false, proxy_enabled: false, proxy_type: 'http', proxy_host: '', @@ -161,7 +161,6 @@ export class SettingsManager { // Save only frontend-specific settings to localStorage const frontendOnlyKeys = [ 'blurMatureContent', - 'show_only_sfw', 'autoplayOnHover', 'displayDensity', 'cardInfoDisplay', @@ -189,6 +188,7 @@ export class SettingsManager { 'download_path_templates', 'enable_metadata_archive_db', 'language', + 'show_only_sfw', 'proxy_enabled', 'proxy_type', 'proxy_host', From fc6f1bf95be94041f7dd9bf721bcca938f79720c Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Fri, 19 Sep 2025 11:17:19 +0800 Subject: [PATCH 038/110] fix(lora_loader): remove unnecessary string stripping from lora names in loaders, fixes #441 --- py/nodes/lora_loader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/nodes/lora_loader.py b/py/nodes/lora_loader.py index 7ff8c219..d431c263 100644 --- a/py/nodes/lora_loader.py +++ b/py/nodes/lora_loader.py @@ -115,7 +115,7 @@ class LoraManagerLoader: formatted_loras = [] for item in loaded_loras: parts = item.split(":") - lora_name = parts[0].strip() + lora_name = parts[0] strength_parts = parts[1].strip().split(",") if len(strength_parts) > 1: @@ -165,7 +165,7 @@ class LoraManagerTextLoader: loras = [] for match in matches: - lora_name = match[0].strip() + lora_name = match[0] model_strength = float(match[1]) clip_strength = float(match[2]) if match[2] else model_strength From 1610048974203268e1f7eee6a0d51a063d4c9e86 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Fri, 19 Sep 2025 16:36:34 +0800 Subject: [PATCH 039/110] refactor(metadata): update model fetching methods to return error messages alongside results --- py/recipes/base.py | 2 +- py/recipes/parsers/civitai_image.py | 43 ++++++------- py/routes/base_model_routes.py | 13 ++-- py/routes/update_routes.py | 6 +- py/services/civitai_client.py | 83 ++++++------------------ py/services/model_metadata_provider.py | 88 +++++--------------------- py/utils/routes_common.py | 6 +- 7 files changed, 66 insertions(+), 175 deletions(-) diff --git a/py/recipes/base.py b/py/recipes/base.py index 78bb933f..3897c683 100644 --- a/py/recipes/base.py +++ b/py/recipes/base.py @@ -55,7 +55,7 @@ class RecipeMetadataParser(ABC): # Unpack the tuple to get the actual data civitai_info, error_msg = civitai_info_tuple if isinstance(civitai_info_tuple, tuple) else (civitai_info_tuple, None) - if not civitai_info or civitai_info.get("error") == "Model not found": + if not civitai_info or error_msg == "Model not found": # Model not found or deleted lora_entry['isDeleted'] = True lora_entry['thumbnailUrl'] = '/loras_static/images/no-preview.png' diff --git a/py/recipes/parsers/civitai_image.py b/py/recipes/parsers/civitai_image.py index 8e96c99b..31234ab9 100644 --- a/py/recipes/parsers/civitai_image.py +++ b/py/recipes/parsers/civitai_image.py @@ -91,7 +91,7 @@ class CivitaiApiMetadataParser(RecipeMetadataParser): result["base_model"] = metadata["baseModel"] elif "Model hash" in metadata and metadata_provider: model_hash = metadata["Model hash"] - model_info = await metadata_provider.get_model_by_hash(model_hash) + model_info, error = await metadata_provider.get_model_by_hash(model_hash) if model_info: result["base_model"] = model_info.get("baseModel", "") elif "Model" in metadata and isinstance(metadata.get("resources"), list): @@ -100,7 +100,7 @@ class CivitaiApiMetadataParser(RecipeMetadataParser): if resource.get("type") == "model" and resource.get("name") == metadata.get("Model"): # This is likely the checkpoint model if metadata_provider and resource.get("hash"): - model_info = await metadata_provider.get_model_by_hash(resource.get("hash")) + model_info, error = await metadata_provider.get_model_by_hash(resource.get("hash")) if model_info: result["base_model"] = model_info.get("baseModel", "") @@ -201,11 +201,7 @@ class CivitaiApiMetadataParser(RecipeMetadataParser): if version_id and metadata_provider: try: # Use get_model_version_info instead of get_model_version - civitai_info, error = await metadata_provider.get_model_version_info(version_id) - - if error: - logger.warning(f"Error getting model version info: {error}") - continue + civitai_info = await metadata_provider.get_model_version_info(version_id) populated_entry = await self.populate_lora_from_civitai( lora_entry, @@ -267,26 +263,23 @@ class CivitaiApiMetadataParser(RecipeMetadataParser): if version_id and metadata_provider: try: # Use get_model_version_info with the version ID - civitai_info, error = await metadata_provider.get_model_version_info(version_id) + civitai_info = await metadata_provider.get_model_version_info(version_id) - if error: - logger.warning(f"Error getting model version info: {error}") - else: - populated_entry = await self.populate_lora_from_civitai( - lora_entry, - civitai_info, - recipe_scanner, - base_model_counts - ) + populated_entry = await self.populate_lora_from_civitai( + lora_entry, + civitai_info, + recipe_scanner, + base_model_counts + ) + + if populated_entry is None: + continue # Skip invalid LoRA types - if populated_entry is None: - continue # Skip invalid LoRA types - - lora_entry = populated_entry - - # Track this LoRA for deduplication - if version_id: - added_loras[version_id] = len(result["loras"]) + lora_entry = populated_entry + + # Track this LoRA for deduplication + if version_id: + added_loras[version_id] = len(result["loras"]) except Exception as e: logger.error(f"Error fetching Civitai info for model ID {version_id}: {e}") diff --git a/py/routes/base_model_routes.py b/py/routes/base_model_routes.py index 2b2f7a7c..f32af9cd 100644 --- a/py/routes/base_model_routes.py +++ b/py/routes/base_model_routes.py @@ -624,7 +624,7 @@ class BaseModelRoutes(ABC): success = 0 needs_resort = False - # Prepare models to process, only those without CivitAI data or missing tags, description, or creator + # Prepare models to process, only those without CivitAI data enable_metadata_archive_db = settings.get('enable_metadata_archive_db', False) to_process = [ model for model in cache.raw_data @@ -633,9 +633,6 @@ class BaseModelRoutes(ABC): and ( not model.get('civitai') or not model['civitai'].get('id') - # or not model.get('tags') # Skipping tag cause it could be empty legitimately - # or not model.get('modelDescription') - # or not (model.get('civitai') and model['civitai'].get('creator')) ) and ( (enable_metadata_archive_db) @@ -782,7 +779,13 @@ class BaseModelRoutes(ABC): try: hash = request.match_info.get('hash') metadata_provider = await get_default_metadata_provider() - model = await metadata_provider.get_model_by_hash(hash) + model, error = await metadata_provider.get_model_by_hash(hash) + if error: + logger.warning(f"Error getting model by hash: {error}") + return web.json_response({ + "success": False, + "error": error + }, status=404) return web.json_response(model) except Exception as e: logger.error(f"Error fetching model details by hash: {e}") diff --git a/py/routes/update_routes.py b/py/routes/update_routes.py index 2febfba3..a25e085e 100644 --- a/py/routes/update_routes.py +++ b/py/routes/update_routes.py @@ -7,7 +7,7 @@ import shutil import tempfile from aiohttp import web from typing import Dict, List -from ..services.downloader import get_downloader, Downloader +from ..services.downloader import get_downloader logger = logging.getLogger(__name__) @@ -265,7 +265,7 @@ class UpdateRoutes: github_url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/commits/main" try: - downloader = await Downloader.get_instance() + downloader = await get_downloader() success, data = await downloader.make_request('GET', github_url, custom_headers={'Accept': 'application/vnd.github+json'}) if not success: @@ -431,7 +431,7 @@ class UpdateRoutes: github_url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/releases/latest" try: - downloader = await Downloader.get_instance() + downloader = await get_downloader() success, data = await downloader.make_request('GET', github_url, custom_headers={'Accept': 'application/vnd.github+json'}) if not success: diff --git a/py/services/civitai_client.py b/py/services/civitai_client.py index 463bd036..ccadbcb5 100644 --- a/py/services/civitai_client.py +++ b/py/services/civitai_client.py @@ -1,4 +1,3 @@ -from datetime import datetime import os import logging import asyncio @@ -59,17 +58,17 @@ class CivitaiClient: return success, result - async def get_model_by_hash(self, model_hash: str) -> Optional[Dict]: + async def get_model_by_hash(self, model_hash: str) -> Tuple[Optional[Dict], Optional[str]]: try: downloader = await get_downloader() - success, version = await downloader.make_request( + success, result = await downloader.make_request( 'GET', f"{self.base_url}/model-versions/by-hash/{model_hash}", use_auth=True ) if success: # Get model ID from version data - model_id = version.get('modelId') + model_id = result.get('modelId') if model_id: # Fetch additional model metadata success_model, data = await downloader.make_request( @@ -79,17 +78,24 @@ class CivitaiClient: ) if success_model: # Enrich version_info with model data - version['model']['description'] = data.get("description") - version['model']['tags'] = data.get("tags", []) + result['model']['description'] = data.get("description") + result['model']['tags'] = data.get("tags", []) # Add creator from model data - version['creator'] = data.get("creator") + result['creator'] = data.get("creator") - return version - return None + return result, None + + # Handle specific error cases + if "not found" in str(result): + return None, "Model not found" + + # Other error cases + logger.error(f"Failed to fetch model info for {model_hash[:10]}: {result}") + return None, str(result) except Exception as e: logger.error(f"API Error: {str(e)}") - return None + return None, str(e) async def download_preview_image(self, image_url: str, save_path: str): try: @@ -246,8 +252,8 @@ class CivitaiClient: return result, None # Handle specific error cases - if "404" in str(result): - error_msg = f"Model not found (status 404)" + if "not found" in str(result): + error_msg = f"Model not found" logger.warning(f"Model version not found: {version_id} - {error_msg}") return None, error_msg @@ -259,59 +265,6 @@ class CivitaiClient: logger.error(error_msg) return None, error_msg - async def get_model_metadata(self, model_id: str) -> Tuple[Optional[Dict], int]: - """Fetch model metadata (description, tags, and creator info) from Civitai API - - Args: - model_id: The Civitai model ID - - Returns: - Tuple[Optional[Dict], int]: A tuple containing: - - A dictionary with model metadata or None if not found - - The HTTP status code from the request (0 for exceptions) - """ - try: - downloader = await get_downloader() - url = f"{self.base_url}/models/{model_id}" - - success, result = await downloader.make_request( - 'GET', - url, - use_auth=True - ) - - if not success: - # Try to extract status code from error message - status_code = 0 - if "404" in str(result): - status_code = 404 - elif "401" in str(result): - status_code = 401 - elif "403" in str(result): - status_code = 403 - logger.warning(f"Failed to fetch model metadata: {result}") - return None, status_code - - # Extract relevant metadata - metadata = { - "description": result.get("description") or "No model description available", - "tags": result.get("tags", []), - "creator": { - "username": result.get("creator", {}).get("username"), - "image": result.get("creator", {}).get("image") - } - } - - if metadata["description"] or metadata["tags"] or metadata["creator"]["username"]: - return metadata, 200 - else: - logger.warning(f"No metadata found for model {model_id}") - return None, 200 - - except Exception as e: - logger.error(f"Error fetching model metadata: {e}", exc_info=True) - return None, 0 - async def get_image_info(self, image_id: str) -> Optional[Dict]: """Fetch image information from Civitai API diff --git a/py/services/model_metadata_provider.py b/py/services/model_metadata_provider.py index ee38f373..55091118 100644 --- a/py/services/model_metadata_provider.py +++ b/py/services/model_metadata_provider.py @@ -2,7 +2,6 @@ from abc import ABC, abstractmethod import json import aiosqlite import logging -import aiohttp from bs4 import BeautifulSoup from typing import Optional, Dict, Tuple from .downloader import get_downloader @@ -13,7 +12,7 @@ class ModelMetadataProvider(ABC): """Base abstract class for all model metadata providers""" @abstractmethod - async def get_model_by_hash(self, model_hash: str) -> Optional[Dict]: + async def get_model_by_hash(self, model_hash: str) -> Tuple[Optional[Dict], Optional[str]]: """Find model by hash value""" pass @@ -31,11 +30,6 @@ class ModelMetadataProvider(ABC): async def get_model_version_info(self, version_id: str) -> Tuple[Optional[Dict], Optional[str]]: """Fetch model version metadata""" pass - - @abstractmethod - async def get_model_metadata(self, model_id: str) -> Tuple[Optional[Dict], int]: - """Fetch model metadata (description, tags, and creator info)""" - pass class CivitaiModelMetadataProvider(ModelMetadataProvider): """Provider that uses Civitai API for metadata""" @@ -43,7 +37,7 @@ class CivitaiModelMetadataProvider(ModelMetadataProvider): def __init__(self, civitai_client): self.client = civitai_client - async def get_model_by_hash(self, model_hash: str) -> Optional[Dict]: + async def get_model_by_hash(self, model_hash: str) -> Tuple[Optional[Dict], Optional[str]]: return await self.client.get_model_by_hash(model_hash) async def get_model_versions(self, model_id: str) -> Optional[Dict]: @@ -54,16 +48,13 @@ class CivitaiModelMetadataProvider(ModelMetadataProvider): async def get_model_version_info(self, version_id: str) -> Tuple[Optional[Dict], Optional[str]]: return await self.client.get_model_version_info(version_id) - - async def get_model_metadata(self, model_id: str) -> Tuple[Optional[Dict], int]: - return await self.client.get_model_metadata(model_id) class CivArchiveModelMetadataProvider(ModelMetadataProvider): """Provider that uses CivArchive HTML page parsing for metadata""" - async def get_model_by_hash(self, model_hash: str) -> Optional[Dict]: + async def get_model_by_hash(self, model_hash: str) -> Tuple[Optional[Dict], Optional[str]]: """Not supported by CivArchive provider""" - return None + return None, "CivArchive provider does not support hash lookup" async def get_model_versions(self, model_id: str) -> Optional[Dict]: """Not supported by CivArchive provider""" @@ -174,10 +165,6 @@ class CivArchiveModelMetadataProvider(ModelMetadataProvider): async def get_model_version_info(self, version_id: str) -> Tuple[Optional[Dict], Optional[str]]: """Not supported by CivArchive provider - requires both model_id and version_id""" return None, "CivArchive provider requires both model_id and version_id" - - async def get_model_metadata(self, model_id: str) -> Tuple[Optional[Dict], int]: - """Not supported by CivArchive provider""" - return None, 404 class SQLiteModelMetadataProvider(ModelMetadataProvider): """Provider that uses SQLite database for metadata""" @@ -185,7 +172,7 @@ class SQLiteModelMetadataProvider(ModelMetadataProvider): def __init__(self, db_path: str): self.db_path = db_path - async def get_model_by_hash(self, model_hash: str) -> Optional[Dict]: + async def get_model_by_hash(self, model_hash: str) -> Tuple[Optional[Dict], Optional[str]]: """Find model by hash value from SQLite database""" async with aiosqlite.connect(self.db_path) as db: # Look up in model_files table to get model_id and version_id @@ -200,14 +187,15 @@ class SQLiteModelMetadataProvider(ModelMetadataProvider): file_row = await cursor.fetchone() if not file_row: - return None + return None, "Model not found" # Get version details model_id = file_row['model_id'] version_id = file_row['version_id'] # Build response in the same format as Civitai API - return await self._get_version_with_model_data(db, model_id, version_id) + result = await self._get_version_with_model_data(db, model_id, version_id) + return result, None if result else "Error retrieving model data" async def get_model_versions(self, model_id: str) -> Optional[Dict]: """Get all versions of a model from SQLite database""" @@ -324,37 +312,6 @@ class SQLiteModelMetadataProvider(ModelMetadataProvider): version_data = await self._get_version_with_model_data(db, model_id, version_id) return version_data, None - async def get_model_metadata(self, model_id: str) -> Tuple[Optional[Dict], int]: - """Fetch model metadata from SQLite database""" - async with aiosqlite.connect(self.db_path) as db: - db.row_factory = aiosqlite.Row - - # Get model details - model_query = "SELECT name, type, data, username FROM models WHERE id = ?" - cursor = await db.execute(model_query, (model_id,)) - model_row = await cursor.fetchone() - - if not model_row: - return None, 404 - - # Parse data JSON - try: - model_data = json.loads(model_row['data']) - - # Extract relevant metadata - metadata = { - "description": model_data.get("description", "No model description available"), - "tags": model_data.get("tags", []), - "creator": { - "username": model_row['username'] or model_data.get("creator", {}).get("username"), - "image": model_data.get("creator", {}).get("image") - } - } - - return metadata, 200 - except json.JSONDecodeError: - return None, 500 - async def _get_version_with_model_data(self, db, model_id, version_id) -> Optional[Dict]: """Helper to build version data with model information""" # Get version details @@ -409,15 +366,16 @@ class FallbackMetadataProvider(ModelMetadataProvider): def __init__(self, providers: list): self.providers = providers - async def get_model_by_hash(self, model_hash: str) -> Optional[Dict]: + async def get_model_by_hash(self, model_hash: str) -> Tuple[Optional[Dict], Optional[str]]: for provider in self.providers: try: - result = await provider.get_model_by_hash(model_hash) + result, error = await provider.get_model_by_hash(model_hash) if result: - return result - except Exception: + return result, error + except Exception as e: + logger.debug(f"Provider failed for get_model_by_hash: {e}") continue - return None + return None, "Model not found" async def get_model_versions(self, model_id: str) -> Optional[Dict]: for provider in self.providers: @@ -452,17 +410,6 @@ class FallbackMetadataProvider(ModelMetadataProvider): continue return None, "No provider could retrieve the data" - async def get_model_metadata(self, model_id: str) -> Tuple[Optional[Dict], int]: - for provider in self.providers: - try: - result, status = await provider.get_model_metadata(model_id) - if result: - return result, status - except Exception as e: - logger.debug(f"Provider failed for get_model_metadata: {e}") - continue - return None, 404 - class ModelMetadataProviderManager: """Manager for selecting and using model metadata providers""" @@ -485,7 +432,7 @@ class ModelMetadataProviderManager: if is_default or self.default_provider is None: self.default_provider = name - async def get_model_by_hash(self, model_hash: str, provider_name: str = None) -> Optional[Dict]: + async def get_model_by_hash(self, model_hash: str, provider_name: str = None) -> Tuple[Optional[Dict], Optional[str]]: """Find model by hash using specified or default provider""" provider = self._get_provider(provider_name) return await provider.get_model_by_hash(model_hash) @@ -505,11 +452,6 @@ class ModelMetadataProviderManager: provider = self._get_provider(provider_name) return await provider.get_model_version_info(version_id) - async def get_model_metadata(self, model_id: str, provider_name: str = None) -> Tuple[Optional[Dict], int]: - """Fetch model metadata using specified or default provider""" - provider = self._get_provider(provider_name) - return await provider.get_model_metadata(model_id) - def _get_provider(self, provider_name: str = None) -> ModelMetadataProvider: """Get provider by name or default provider""" if provider_name and provider_name in self.providers: diff --git a/py/utils/routes_common.py b/py/utils/routes_common.py index db2f94db..e6bd4ac7 100644 --- a/py/utils/routes_common.py +++ b/py/utils/routes_common.py @@ -215,7 +215,7 @@ class ModelRouteUtils: else: metadata_provider = await get_default_metadata_provider() - civitai_metadata = await metadata_provider.get_model_by_hash(sha256) + civitai_metadata, error = await metadata_provider.get_model_by_hash(sha256) if not civitai_metadata: # Mark as not from CivitAI if not found local_metadata['from_civitai'] = False @@ -387,10 +387,10 @@ class ModelRouteUtils: metadata_provider = await get_default_metadata_provider() # Fetch and update metadata - civitai_metadata = await metadata_provider.get_model_by_hash(local_metadata["sha256"]) + civitai_metadata, error = await metadata_provider.get_model_by_hash(local_metadata["sha256"]) if not civitai_metadata: await ModelRouteUtils.handle_not_found_on_civitai(metadata_path, local_metadata) - return web.json_response({"success": False, "error": "Not found on CivitAI"}, status=404) + return web.json_response({"success": False, "error": error}, status=404) await ModelRouteUtils.update_model_metadata(metadata_path, local_metadata, civitai_metadata, metadata_provider) From f3544b3471e30eee5c3be2a65ec2d87fc7c522d7 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Fri, 19 Sep 2025 22:57:05 +0800 Subject: [PATCH 040/110] refactor(settings): replace getStorageItem with state.global.settings for default root retrieval --- .../shared/showcase/ShowcaseView.js | 14 ++ static/js/managers/DownloadManager.js | 2 +- static/js/managers/ImportManager.js | 2 +- static/js/managers/MoveManager.js | 3 +- static/js/managers/import/FolderBrowser.js | 221 ------------------ 5 files changed, 17 insertions(+), 225 deletions(-) delete mode 100644 static/js/managers/import/FolderBrowser.js diff --git a/static/js/components/shared/showcase/ShowcaseView.js b/static/js/components/shared/showcase/ShowcaseView.js index 257753fd..2830b166 100644 --- a/static/js/components/shared/showcase/ShowcaseView.js +++ b/static/js/components/shared/showcase/ShowcaseView.js @@ -33,6 +33,20 @@ export async function loadExampleImages(images, modelHash) { const params = `model_hash=${modelHash}`; const response = await fetch(`${endpoint}?${params}`); + if (!response.ok) { + // Try to parse error message from backend + let errorMsg = `HTTP error ${response.status}`; + try { + const errorData = await response.json(); + if (errorData && errorData.error) { + errorMsg = errorData.error; + } + } catch (e) { + // Ignore JSON parse error + } + console.warn("Failed to get example files:", errorMsg); + return; + } const result = await response.json(); if (result.success) { diff --git a/static/js/managers/DownloadManager.js b/static/js/managers/DownloadManager.js index 36137785..c84e7a5f 100644 --- a/static/js/managers/DownloadManager.js +++ b/static/js/managers/DownloadManager.js @@ -308,7 +308,7 @@ export class DownloadManager { // Set default root if available const singularType = this.apiClient.modelType.replace(/s$/, ''); const defaultRootKey = `default_${singularType}_root`; - const defaultRoot = getStorageItem('settings', {})[defaultRootKey]; + const defaultRoot = state.global.settings[defaultRootKey]; console.log(`Default root for ${this.apiClient.modelType}:`, defaultRoot); console.log('Available roots:', rootsData.roots); if (defaultRoot && rootsData.roots.includes(defaultRoot)) { diff --git a/static/js/managers/ImportManager.js b/static/js/managers/ImportManager.js index 95d1549d..3aa4de35 100644 --- a/static/js/managers/ImportManager.js +++ b/static/js/managers/ImportManager.js @@ -228,7 +228,7 @@ export class ImportManager { // Set default root if available const defaultRootKey = 'default_lora_root'; - const defaultRoot = getStorageItem('settings', {})[defaultRootKey]; + const defaultRoot = state.global.settings[defaultRootKey]; if (defaultRoot && rootsData.roots.includes(defaultRoot)) { loraRoot.value = defaultRoot; } diff --git a/static/js/managers/MoveManager.js b/static/js/managers/MoveManager.js index 528b2847..1b23a827 100644 --- a/static/js/managers/MoveManager.js +++ b/static/js/managers/MoveManager.js @@ -2,7 +2,6 @@ import { showToast } from '../utils/uiHelpers.js'; import { state, getCurrentPageState } from '../state/index.js'; import { modalManager } from './ModalManager.js'; import { bulkManager } from './BulkManager.js'; -import { getStorageItem } from '../utils/storageHelpers.js'; import { getModelApiClient } from '../api/modelApiFactory.js'; import { FolderTreeManager } from '../components/FolderTreeManager.js'; import { sidebarManager } from '../components/SidebarManager.js'; @@ -87,7 +86,7 @@ class MoveManager { // Set default root if available const settingsKey = `default_${currentPageType.slice(0, -1)}_root`; - const defaultRoot = getStorageItem('settings', {})[settingsKey]; + const defaultRoot = state.global.settings[settingsKey]; if (defaultRoot && rootsData.roots.includes(defaultRoot)) { modelRootSelect.value = defaultRoot; } diff --git a/static/js/managers/import/FolderBrowser.js b/static/js/managers/import/FolderBrowser.js deleted file mode 100644 index 43cfbada..00000000 --- a/static/js/managers/import/FolderBrowser.js +++ /dev/null @@ -1,221 +0,0 @@ -import { showToast } from '../../utils/uiHelpers.js'; -import { translate } from '../../utils/i18nHelpers.js'; -import { getStorageItem } from '../../utils/storageHelpers.js'; - -export class FolderBrowser { - constructor(importManager) { - this.importManager = importManager; - this.folderClickHandler = null; - this.updateTargetPath = this.updateTargetPath.bind(this); - } - - async proceedToLocation() { - // Show the location step with special handling - this.importManager.stepManager.showStep('locationStep'); - - // Double-check after a short delay to ensure the step is visible - setTimeout(() => { - const locationStep = document.getElementById('locationStep'); - if (locationStep.style.display !== 'block' || - window.getComputedStyle(locationStep).display !== 'block') { - // Force display again - locationStep.style.display = 'block'; - - // If still not visible, try with injected style - if (window.getComputedStyle(locationStep).display !== 'block') { - this.importManager.stepManager.injectedStyles = document.createElement('style'); - this.importManager.stepManager.injectedStyles.innerHTML = ` - #locationStep { - display: block !important; - opacity: 1 !important; - visibility: visible !important; - } - `; - document.head.appendChild(this.importManager.stepManager.injectedStyles); - } - } - }, 100); - - try { - // Display missing LoRAs that will be downloaded - const missingLorasList = document.getElementById('missingLorasList'); - if (missingLorasList && this.importManager.downloadableLoRAs.length > 0) { - // Calculate total size - const totalSize = this.importManager.downloadableLoRAs.reduce((sum, lora) => { - return sum + (lora.size ? parseInt(lora.size) : 0); - }, 0); - - // Update total size display - const totalSizeDisplay = document.getElementById('totalDownloadSize'); - if (totalSizeDisplay) { - totalSizeDisplay.textContent = this.importManager.formatFileSize(totalSize); - } - - // Update header to include count of missing LoRAs - const missingLorasHeader = document.querySelector('.summary-header h3'); - if (missingLorasHeader) { - missingLorasHeader.innerHTML = `Missing LoRAs (${this.importManager.downloadableLoRAs.length}) ${this.importManager.formatFileSize(totalSize)}`; - } - - // Generate missing LoRAs list - missingLorasList.innerHTML = this.importManager.downloadableLoRAs.map(lora => { - const sizeDisplay = lora.size ? - this.importManager.formatFileSize(lora.size) : 'Unknown size'; - const baseModel = lora.baseModel ? - `${lora.baseModel}` : ''; - const isEarlyAccess = lora.isEarlyAccess; - - // Early access badge - let earlyAccessBadge = ''; - if (isEarlyAccess) { - earlyAccessBadge = ` - Early Access - `; - } - - return ` -
-
-
${lora.name}
- ${baseModel} - ${earlyAccessBadge} -
-
${sizeDisplay}
-
- `; - }).join(''); - - // Set up toggle for missing LoRAs list - const toggleBtn = document.getElementById('toggleMissingLorasList'); - if (toggleBtn) { - toggleBtn.addEventListener('click', () => { - missingLorasList.classList.toggle('collapsed'); - const icon = toggleBtn.querySelector('i'); - if (icon) { - icon.classList.toggle('fa-chevron-down'); - icon.classList.toggle('fa-chevron-up'); - } - }); - } - } - - // Fetch LoRA roots - const rootsResponse = await fetch('/api/lm/loras/roots'); - if (!rootsResponse.ok) { - throw new Error(`Failed to fetch LoRA roots: ${rootsResponse.status}`); - } - - const rootsData = await rootsResponse.json(); - const loraRoot = document.getElementById('importLoraRoot'); - if (loraRoot) { - loraRoot.innerHTML = rootsData.roots.map(root => - `` - ).join(''); - - // Set default lora root if available - const defaultRoot = getStorageItem('settings', {}).default_lora_root; - if (defaultRoot && rootsData.roots.includes(defaultRoot)) { - loraRoot.value = defaultRoot; - } - } - - // Fetch folders - const foldersResponse = await fetch('/api/lm/loras/folders'); - if (!foldersResponse.ok) { - throw new Error(`Failed to fetch folders: ${foldersResponse.status}`); - } - - const foldersData = await foldersResponse.json(); - const folderBrowser = document.getElementById('importFolderBrowser'); - if (folderBrowser) { - folderBrowser.innerHTML = foldersData.folders.map(folder => - folder ? `
${folder}
` : '' - ).join(''); - } - - // Initialize folder browser after loading data - this.initializeFolderBrowser(); - } catch (error) { - console.error('Error in API calls:', error); - showToast('toast.recipes.folderBrowserError', { message: error.message }, 'error'); - } - } - - initializeFolderBrowser() { - const folderBrowser = document.getElementById('importFolderBrowser'); - if (!folderBrowser) return; - - // Cleanup existing handler if any - this.cleanup(); - - // Create new handler - this.folderClickHandler = (event) => { - const folderItem = event.target.closest('.folder-item'); - if (!folderItem) return; - - if (folderItem.classList.contains('selected')) { - folderItem.classList.remove('selected'); - this.importManager.selectedFolder = ''; - } else { - folderBrowser.querySelectorAll('.folder-item').forEach(f => - f.classList.remove('selected')); - folderItem.classList.add('selected'); - this.importManager.selectedFolder = folderItem.dataset.folder; - } - - // Update path display after folder selection - this.updateTargetPath(); - }; - - // Add the new handler - folderBrowser.addEventListener('click', this.folderClickHandler); - - // Add event listeners for path updates - const loraRoot = document.getElementById('importLoraRoot'); - const newFolder = document.getElementById('importNewFolder'); - - if (loraRoot) loraRoot.addEventListener('change', this.updateTargetPath); - if (newFolder) newFolder.addEventListener('input', this.updateTargetPath); - - // Update initial path - this.updateTargetPath(); - } - - cleanup() { - if (this.folderClickHandler) { - const folderBrowser = document.getElementById('importFolderBrowser'); - if (folderBrowser) { - folderBrowser.removeEventListener('click', this.folderClickHandler); - this.folderClickHandler = null; - } - } - - // Remove path update listeners - const loraRoot = document.getElementById('importLoraRoot'); - const newFolder = document.getElementById('importNewFolder'); - - if (loraRoot) loraRoot.removeEventListener('change', this.updateTargetPath); - if (newFolder) newFolder.removeEventListener('input', this.updateTargetPath); - } - - updateTargetPath() { - const pathDisplay = document.getElementById('importTargetPathDisplay'); - if (!pathDisplay) return; - - const loraRoot = document.getElementById('importLoraRoot')?.value || ''; - const newFolder = document.getElementById('importNewFolder')?.value?.trim() || ''; - - let fullPath = loraRoot || translate('recipes.controls.import.selectLoraRoot', {}, 'Select a LoRA root directory'); - - if (loraRoot) { - if (this.importManager.selectedFolder) { - fullPath += '/' + this.importManager.selectedFolder; - } - if (newFolder) { - fullPath += '/' + newFolder; - } - } - - pathDisplay.innerHTML = `${fullPath}`; - } -} From 3053b13fcb2ff6ae852ae3fe27e44e2ba0edc798 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Fri, 19 Sep 2025 23:22:47 +0800 Subject: [PATCH 041/110] feat(metadata): enhance model processing with CivitAI metadata checks and new fields for archive DB status --- py/routes/base_model_routes.py | 18 +++++----- py/utils/models.py | 2 ++ py/utils/routes_common.py | 35 ++++++++++++------- .../shared/showcase/ShowcaseView.js | 14 -------- 4 files changed, 33 insertions(+), 36 deletions(-) diff --git a/py/routes/base_model_routes.py b/py/routes/base_model_routes.py index f32af9cd..db914960 100644 --- a/py/routes/base_model_routes.py +++ b/py/routes/base_model_routes.py @@ -626,18 +626,16 @@ class BaseModelRoutes(ABC): # Prepare models to process, only those without CivitAI data enable_metadata_archive_db = settings.get('enable_metadata_archive_db', False) + # Filter models that need CivitAI metadata update to_process = [ model for model in cache.raw_data - if ( - model.get('sha256') - and ( - not model.get('civitai') - or not model['civitai'].get('id') - ) - and ( - (enable_metadata_archive_db) - or (not enable_metadata_archive_db and model.get('from_civitai') is True) - ) + if model.get('sha256') + and ( + not model.get('civitai') or not model['civitai'].get('id') + ) + and ( + (enable_metadata_archive_db and not model.get('db_checked', False)) + or (not enable_metadata_archive_db and model.get('from_civitai') is True) ) ] total_to_process = len(to_process) diff --git a/py/utils/models.py b/py/utils/models.py index 9e1dc737..159146d5 100644 --- a/py/utils/models.py +++ b/py/utils/models.py @@ -24,6 +24,8 @@ class BaseModelMetadata: civitai_deleted: bool = False # Whether deleted from Civitai favorite: bool = False # Whether the model is a favorite exclude: bool = False # Whether to exclude this model from the cache + db_checked: bool = False # Whether checked in archive DB + last_checked_at: float = 0 # Last checked timestamp _unknown_fields: Dict[str, Any] = field(default_factory=dict, repr=False, compare=False) # Store unknown fields def __post_init__(self): diff --git a/py/utils/routes_common.py b/py/utils/routes_common.py index e6bd4ac7..d6635118 100644 --- a/py/utils/routes_common.py +++ b/py/utils/routes_common.py @@ -3,6 +3,7 @@ import json import logging from typing import Dict, List, Callable, Awaitable from aiohttp import web +from datetime import datetime from .model_utils import determine_base_model from .constants import PREVIEW_EXTENSIONS, CARD_PREVIEW_WIDTH @@ -82,7 +83,6 @@ class ModelRouteUtils: # Update local metadata with merged civitai data local_metadata['civitai'] = merged_civitai - local_metadata['from_civitai'] = True # Update model-related metadata from civitai_metadata.model if 'model' in civitai_metadata and civitai_metadata['model']: @@ -203,12 +203,11 @@ class ModelRouteUtils: return False metadata_path = os.path.splitext(file_path)[0] + '.metadata.json' - - # Check if model metadata exists - local_metadata = await ModelRouteUtils.load_local_metadata(metadata_path) + enable_metadata_archive_db = settings.get('enable_metadata_archive_db', False) - if model_data.get('from_civitai') is False: - if not settings.get('enable_metadata_archive_db', False): + if model_data.get('civitai_deleted') is True and model_data.get('db_checked') is False: + # If CivitAI deleted flag is set, skip CivitAI API provider + if not enable_metadata_archive_db: return False # Likely deleted from CivitAI, use archive_db if available metadata_provider = await get_metadata_provider('sqlite') @@ -217,11 +216,24 @@ class ModelRouteUtils: civitai_metadata, error = await metadata_provider.get_model_by_hash(sha256) if not civitai_metadata: - # Mark as not from CivitAI if not found - local_metadata['from_civitai'] = False - model_data['from_civitai'] = False - await MetadataManager.save_metadata(file_path, local_metadata) + if error == "Model not found": + model_data['from_civitai'] = False + model_data['civitai_deleted'] = True + model_data['db_checked'] = enable_metadata_archive_db + model_data['last_checked_at'] = datetime.now().timestamp() + + # Remove 'folder' key from model_data if present before saving + data_to_save = model_data.copy() + data_to_save.pop('folder', None) + await MetadataManager.save_metadata(file_path, data_to_save) return False + + model_data['from_civitai'] = True + model_data['civitai_deleted'] = civitai_metadata.get('source') == 'archive_db' + model_data['db_checked'] = enable_metadata_archive_db + + local_metadata = model_data.copy() + local_metadata.pop('folder', None) # Remove 'folder' key if present # Update metadata await ModelRouteUtils.update_model_metadata( @@ -235,8 +247,7 @@ class ModelRouteUtils: update_dict = { 'model_name': local_metadata.get('model_name'), 'preview_url': local_metadata.get('preview_url'), - 'from_civitai': True, - 'civitai': civitai_metadata + 'civitai': local_metadata.get('civitai'), } model_data.update(update_dict) diff --git a/static/js/components/shared/showcase/ShowcaseView.js b/static/js/components/shared/showcase/ShowcaseView.js index 2830b166..257753fd 100644 --- a/static/js/components/shared/showcase/ShowcaseView.js +++ b/static/js/components/shared/showcase/ShowcaseView.js @@ -33,20 +33,6 @@ export async function loadExampleImages(images, modelHash) { const params = `model_hash=${modelHash}`; const response = await fetch(`${endpoint}?${params}`); - if (!response.ok) { - // Try to parse error message from backend - let errorMsg = `HTTP error ${response.status}`; - try { - const errorData = await response.json(); - if (errorData && errorData.error) { - errorMsg = errorData.error; - } - } catch (e) { - // Ignore JSON parse error - } - console.warn("Failed to get example files:", errorMsg); - return; - } const result = await response.json(); if (result.success) { From ab7266f3a46e6f9fe55da7d0b088acdadb177198 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sat, 20 Sep 2025 08:12:14 +0800 Subject: [PATCH 042/110] fix(download_manager): streamline output directory retrieval by using settings directly, fixes #443 --- py/utils/example_images_download_manager.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/py/utils/example_images_download_manager.py b/py/utils/example_images_download_manager.py index 58df8d72..842192f2 100644 --- a/py/utils/example_images_download_manager.py +++ b/py/utils/example_images_download_manager.py @@ -10,6 +10,7 @@ from .example_images_processor import ExampleImagesProcessor from .example_images_metadata import MetadataUpdater from ..services.websocket_manager import ws_manager # Add this import at the top from ..services.downloader import get_downloader +from ..services.settings_manager import settings logger = logging.getLogger(__name__) @@ -70,10 +71,8 @@ class DownloadManager: delay = float(data.get('delay', 0.2)) # Default to 0.2 seconds # Get output directory from settings - from ..services.service_registry import ServiceRegistry - settings_manager = await ServiceRegistry.get_settings_manager() - output_dir = settings_manager.get('example_images_path') - + output_dir = settings.get('example_images_path') + if not output_dir: error_msg = 'Example images path not configured in settings' if auto_mode: @@ -468,9 +467,7 @@ class DownloadManager: }, status=400) # Get output directory from settings - from ..services.service_registry import ServiceRegistry - settings_manager = await ServiceRegistry.get_settings_manager() - output_dir = settings_manager.get('example_images_path') + output_dir = settings.get('example_images_path') if not output_dir: return web.json_response({ From a8d7070832d9eb5496aaeeef4c5ee949c9a7867e Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sat, 20 Sep 2025 21:35:34 +0800 Subject: [PATCH 043/110] feat(civitai): enhance metadata fetching with error handling and cache validation --- py/routes/base_model_routes.py | 58 +++++++++++++++++++++-------- py/utils/example_images_metadata.py | 4 +- py/utils/routes_common.py | 34 ++++++++++------- 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/py/routes/base_model_routes.py b/py/routes/base_model_routes.py index db914960..6c3f11b4 100644 --- a/py/routes/base_model_routes.py +++ b/py/routes/base_model_routes.py @@ -255,20 +255,45 @@ class BaseModelRoutes(ABC): return await ModelRouteUtils.handle_exclude_model(request, self.service.scanner) async def fetch_civitai(self, request: web.Request) -> web.Response: - """Handle CivitAI metadata fetch request""" - response = await ModelRouteUtils.handle_fetch_civitai(request, self.service.scanner) - - # If successful, format the metadata before returning - if response.status == 200: - data = json.loads(response.body.decode('utf-8')) - if data.get("success") and data.get("metadata"): - formatted_metadata = await self.service.format_response(data["metadata"]) - return web.json_response({ - "success": True, - "metadata": formatted_metadata - }) - - return response + """Handle CivitAI metadata fetch request - force refresh model metadata""" + try: + data = await request.json() + file_path = data.get('file_path') + if not file_path: + return web.json_response({"success": False, "error": "File path is required"}, status=400) + + # Get model data from cache + cache = await self.service.scanner.get_cached_data() + model_data = next((item for item in cache.raw_data if item['file_path'] == file_path), None) + + if not model_data: + return web.json_response({"success": False, "error": "Model not found in cache"}, status=404) + + # Check if model has SHA256 hash + if not model_data.get('sha256'): + return web.json_response({"success": False, "error": "No SHA256 hash found"}, status=400) + + # Use fetch_and_update_model to get and update metadata + success, error = await ModelRouteUtils.fetch_and_update_model( + sha256=model_data['sha256'], + file_path=file_path, + model_data=model_data, + update_cache_func=self.service.scanner.update_single_model_cache + ) + + if not success: + return web.json_response({"success": False, "error": error}) + + # Format the updated metadata for response + formatted_metadata = await self.service.format_response(model_data) + return web.json_response({ + "success": True, + "metadata": formatted_metadata + }) + + except Exception as e: + logger.error(f"Error fetching from CivitAI: {e}", exc_info=True) + return web.json_response({"success": False, "error": str(e)}, status=500) async def relink_civitai(self, request: web.Request) -> web.Response: """Handle CivitAI metadata re-linking request""" @@ -652,12 +677,13 @@ class BaseModelRoutes(ABC): for model in to_process: try: original_name = model.get('model_name') - if await ModelRouteUtils.fetch_and_update_model( + result, error = await ModelRouteUtils.fetch_and_update_model( sha256=model['sha256'], file_path=model['file_path'], model_data=model, update_cache_func=self.service.scanner.update_single_model_cache - ): + ) + if result: success += 1 if original_name != model.get('model_name'): needs_resort = True diff --git a/py/utils/example_images_metadata.py b/py/utils/example_images_metadata.py index 496d5ad0..71566bff 100644 --- a/py/utils/example_images_metadata.py +++ b/py/utils/example_images_metadata.py @@ -53,7 +53,7 @@ class MetadataUpdater: async def update_cache_func(old_path, new_path, metadata): return await scanner.update_single_model_cache(old_path, new_path, metadata) - success = await ModelRouteUtils.fetch_and_update_model( + success, error = await ModelRouteUtils.fetch_and_update_model( model_hash, file_path, model_data, @@ -64,7 +64,7 @@ class MetadataUpdater: logger.info(f"Successfully refreshed metadata for {model_name}") return True else: - logger.warning(f"Failed to refresh metadata for {model_name}") + logger.warning(f"Failed to refresh metadata for {model_name}, {error}") return False except Exception as e: diff --git a/py/utils/routes_common.py b/py/utils/routes_common.py index d6635118..b5f6af30 100644 --- a/py/utils/routes_common.py +++ b/py/utils/routes_common.py @@ -184,7 +184,7 @@ class ModelRouteUtils: file_path: str, model_data: dict, update_cache_func: Callable[[str, str, Dict], Awaitable[bool]] - ) -> bool: + ) -> tuple[bool, str]: """Fetch and update metadata for a single model Args: @@ -194,21 +194,22 @@ class ModelRouteUtils: update_cache_func: Function to update the cache with new metadata Returns: - bool: True if successful, False otherwise + tuple[bool, str]: (success, error_message). When success is True, error_message is None. """ try: # Validate input parameters if not isinstance(model_data, dict): - logger.error(f"Invalid model_data type: {type(model_data)}") - return False + error_msg = f"Invalid model_data type: {type(model_data)}" + logger.error(error_msg) + return False, error_msg metadata_path = os.path.splitext(file_path)[0] + '.metadata.json' enable_metadata_archive_db = settings.get('enable_metadata_archive_db', False) - if model_data.get('civitai_deleted') is True and model_data.get('db_checked') is False: + if model_data.get('civitai_deleted') is True: # If CivitAI deleted flag is set, skip CivitAI API provider - if not enable_metadata_archive_db: - return False + if not enable_metadata_archive_db or model_data.get('db_checked') is True: + return False, "CivitAI model is deleted and metadata archive DB is not enabled" # Likely deleted from CivitAI, use archive_db if available metadata_provider = await get_metadata_provider('sqlite') else: @@ -226,11 +227,16 @@ class ModelRouteUtils: data_to_save = model_data.copy() data_to_save.pop('folder', None) await MetadataManager.save_metadata(file_path, data_to_save) - return False + + # For other errors, log and return False with error message + error_msg = f"Error fetching metadata: {error} (model_name={model_data.get('model_name', '')})" + logger.error(error_msg) + return False, error_msg model_data['from_civitai'] = True model_data['civitai_deleted'] = civitai_metadata.get('source') == 'archive_db' model_data['db_checked'] = enable_metadata_archive_db + model_data['last_checked_at'] = datetime.now().timestamp() local_metadata = model_data.copy() local_metadata.pop('folder', None) # Remove 'folder' key if present @@ -254,14 +260,16 @@ class ModelRouteUtils: # Update cache using the provided function await update_cache_func(file_path, file_path, local_metadata) - return True + return True, None except KeyError as e: - logger.error(f"Error fetching CivitAI data - Missing key: {e} in model_data={model_data}") - return False + error_msg = f"Error fetching metadata - Missing key: {e} in model_data={model_data}" + logger.error(error_msg) + return False, error_msg except Exception as e: - logger.error(f"Error fetching CivitAI data: {str(e)}", exc_info=True) # Include stack trace - return False + error_msg = f"Error fetching metadata: {str(e)}" + logger.error(error_msg, exc_info=True) # Include stack trace + return False, error_msg @staticmethod def filter_civitai_data(data: Dict, minimal: bool = False) -> Dict: From 40cbb2155c7e0d458e89fcbd802584ddd8daccab Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sat, 20 Sep 2025 21:43:00 +0800 Subject: [PATCH 044/110] refactor(baseModelApi): comment out failure message handling in bulk metadata refresh --- static/js/api/baseModelApi.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/static/js/api/baseModelApi.js b/static/js/api/baseModelApi.js index 0e77823c..df80d764 100644 --- a/static/js/api/baseModelApi.js +++ b/static/js/api/baseModelApi.js @@ -538,13 +538,13 @@ export class BaseModelApiClient { completionMessage = translate('toast.api.bulkMetadataCompletePartial', { success: successCount, total: totalItems, type: this.apiConfig.config.displayName }, `Refreshed ${successCount} of ${totalItems} ${this.apiConfig.config.displayName}s`); showToast('toast.api.bulkMetadataCompletePartial', { success: successCount, total: totalItems, type: this.apiConfig.config.displayName }, 'warning'); - if (failedItems.length > 0) { - const failureMessage = failedItems.length <= 3 - ? failedItems.map(item => `${item.fileName}: ${item.error}`).join('\n') - : failedItems.slice(0, 3).map(item => `${item.fileName}: ${item.error}`).join('\n') + - `\n(and ${failedItems.length - 3} more)`; - showToast('toast.api.bulkMetadataFailureDetails', { failures: failureMessage }, 'warning', 6000); - } + // if (failedItems.length > 0) { + // const failureMessage = failedItems.length <= 3 + // ? failedItems.map(item => `${item.fileName}: ${item.error}`).join('\n') + // : failedItems.slice(0, 3).map(item => `${item.fileName}: ${item.error}`).join('\n') + + // `\n(and ${failedItems.length - 3} more)`; + // showToast('toast.api.bulkMetadataFailureDetails', { failures: failureMessage }, 'warning', 6000); + // } } else { completionMessage = translate('toast.api.bulkMetadataCompleteNone', { type: this.apiConfig.config.displayName }, `Failed to refresh metadata for any ${this.apiConfig.config.displayName}s`); showToast('toast.api.bulkMetadataCompleteNone', { type: this.apiConfig.config.displayName }, 'error'); From 9e1a2e3bb73a7f299f2e3e254fe8087c789e88af Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sat, 20 Sep 2025 22:03:29 +0800 Subject: [PATCH 045/110] chore(pyproject): bump version to 0.9.4 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1ad4e018..801a705e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui-lora-manager" description = "Revolutionize your workflow with the ultimate LoRA companion for ComfyUI!" -version = "0.9.3" +version = "0.9.4" license = {file = "LICENSE"} dependencies = [ "aiohttp", From 6261f7d18d6883a811fe50ca2332f24b2de201e2 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sat, 20 Sep 2025 23:21:10 +0800 Subject: [PATCH 046/110] Update LM extension wiki --- docs/LM-Extension-Wiki.md | 6 +++++- wiki-images/civarchive-models-page.png | Bin 0 -> 2539770 bytes 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 wiki-images/civarchive-models-page.png diff --git a/docs/LM-Extension-Wiki.md b/docs/LM-Extension-Wiki.md index 272d512b..ddaeac4e 100644 --- a/docs/LM-Extension-Wiki.md +++ b/docs/LM-Extension-Wiki.md @@ -1,6 +1,9 @@ ## Overview -The **LoRA Manager Civitai Extension** is a Browser extension designed to work seamlessly with [LoRA Manager](https://github.com/willmiao/ComfyUI-Lora-Manager) to significantly enhance your browsing experience on [Civitai](https://civitai.com). With this extension, you can: +The **LoRA Manager Civitai Extension** is a Browser extension designed to work seamlessly with [LoRA Manager](https://github.com/willmiao/ComfyUI-Lora-Manager) to significantly enhance your browsing experience on [Civitai](https://civitai.com). +It also supports browsing on [CivArchive](https://civarchive.com/) (formerly CivitaiArchive). + +With this extension, you can: ✅ Instantly see which models are already present in your local library ✅ Download new models with a single click @@ -8,6 +11,7 @@ The **LoRA Manager Civitai Extension** is a Browser extension designed to work s ✅ Keep your downloaded models automatically organized according to your custom settings ![Civitai Models page](https://github.com/willmiao/ComfyUI-Lora-Manager/blob/main/wiki-images/civitai-models-page.png) +![CivArchive Models page](https://github.com/willmiao/ComfyUI-Lora-Manager/blob/main/wiki-images/civarchive-models-page.png) --- diff --git a/wiki-images/civarchive-models-page.png b/wiki-images/civarchive-models-page.png new file mode 100644 index 0000000000000000000000000000000000000000..780add13c97ca04c40210d0cacbfbd9edcef53f8 GIT binary patch literal 2539770 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
  • t3176`1a0&i|*! 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 SCTFJoO}W=zxfLzRj^{_c_||WIJvfT_SZ(Nt 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

    P)9b*g4iK3Y8 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

    a4(*?*Y5y%@M`95xLBF9aDKfD28EBgxCa2~SNQ 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

    WU6-+UTmC?-g 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�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∨>5-EDUq?_h7w%=YTdn;sZ$tgpqJufG;w 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

    ~Y9@IGY-C}wF&8It(vf$nQ@uZu z`$Tf>2;g*wY(B38k9m<;wihZDwl4ls$CKhQ^P=*%?2_BxPS^8rVzaODKa1Croz(5E z+jpYXVneuFnkSQ4koBf%^_y%Ehu5f^W#4d?bq1}nUevmf{o)&LYlEMtcWjTVsVx48 zAe@Al`yc3^8^x!5%K)FxVj+;g)C~H9+c3{c?^JD-x<=pQgapL~Z`!$U@zLuV$1JPQ4Zw`4UAC&n@-X5J;4j^-~h3Bj{$MHT>wB%=cTB^n=8cntzN8e?#1=> zJ->e#hPf=Ra`(xZMgn~*(2(DJV_v!hVdPhAbPG9RBKy=a-gZPJYvhKRG)W zQ!EmTkCs=KV|8^g7Urj8Zt6(D9NT0$G{EM7S+#RE>``9PgWIMKRc_T6^^Ec61}XV~ zI9+@ox$6_@$gaNI4)T(=!2~!Ri^MjJt3QoRl?SOYmx0Z#ZPYm%6I@r)0UFF>adKNY zEH9jm6Upf1M$`1?Mm%(a-5#GU3j-g~@u^9bXI29&pZ0}k6dpXX?J6L=?M9J?I(4FU z3y?dEuHZ>QKAX{t8-Jdaw*1IrC>NDL>f7iF%2PD+X=0VjbA6=4ydU|9zQ`uifb5kX z6X+b8Ar4`4bCbe?3vHS*sl79K4qd%CTy!l;1b`0p_Gw%zD`fFr`w4x zvUAXrjOBwWlOk8=BcNY|FnY7iXOA{LBv%& zFAzXAx1F@1iTgtqi)2$|>mY>CvnTH@HwAhIUt~Jp{YKW{mo{M(mN;@7kRt->ntI4h zY1xkf%yFHFCdf;XM>G;n4lEig#QIK0>VahJ+@k0?7b}ZPail)@XkY27xFWgR2sFW_ zjJd%eX@i`aJdrLgS|^tr$rkS`A2#hIT_nSV7jv|*kNM7gl(*E(PV+AN0LyZv4)v_} z2=XS1BcFI@qdap%6hWm^`p^-)6i;%@H%JHrjXVWjpy6lQQi)gWHcG-4D&2 z3{>7j%Z+2<$NY-2NHGirRKN)iB~TQFIZ@${WV7%)P;q;5cgI2gUB%@tG^uqlP-6Q6 z)F(tXZRuFNz^5IvS4rMTorp}KdIE2G1{bvi#TB2)p5#WOIocmGLNBRbWPohbNNqz7 zr%fy1_70b;=-XgS^SMG%78u6$>2^tZX)WI!SndfYmr48&FQS8H`bpoucu&1;Z1)c0 z^($}0`t~j51#T>q_7#UuBr3e@1C29%vlB7}e5fb-)NU>SC*P^0O4#ilPE`$bkwNS<(LgX^kk%;b3_oRpG^rF4#Z^5&)r;m0+<#+OacY-;9u zVvTqA+v@JS2Hf5pEnU7ZdCI{#4$*N-&(`*K++4dQ-EJ*D`0R(`r$70LXe>63^Hc*} zc0UGuM^<%BUzi82xH??=m&$q|{ZxW58sag=GW&NBr#PF5~WVN_UrUjQeFdRfaw3Y?H#}P&|Af+MjTsM*7LovGh2(59P-#M;ydyN-sE)o-wUF8_N55 zptQR^^Fe;bO1uG&>b)YWuM%$7|M$fUlCx@)b83U!xW-&1;)S_XZgM#hOehXF3viz3 z{WMwY@6jwTpOtW#iH-HGc>Ar(arK?6apUT>xGXo<0bO|PVmyA~iRh`}{mwuBbo};z z`%hwR?XH-*8{HoFXG_u6po$a0=gyq-wb7jVZRwdaxhG1SYgwd~n8{$aK07!>MDJ99 z$Otpxg3?B##*M<`oz!|jDNGqphbg91$x$eL+Da8^e}oN{D`f?x$2-;#m`a;_(a{}Y z%0^?#%CL{Kqf96dGUOdQ9l34~!OD&`n!t=20?M#>YY6US1^P3jA#?)9Wq5$evK3o- zB5M1>wbSpb5wKfPLR;_Y6j=P@Y9+`AucBmoK%@lNr2ze`+(0*Zqx3j&ci?nhD4(K} z?0V{!h2Mr6APpMjV}^GQCpwF+C=96ts6K=XyQx{o-);+-#OU;+qx$o=ni)(9*r5Tv zEnL+uQCi);Yzu$T0zrTZmF-Sd_#}>QVg|xeL>E)#!=@fnkxQ_Wh#UUk8AVWobS51c ze0$g87@+*Q6H#KOq2dvi>)MQ(c(mO=ikDt{E57vN%l;reO1A40x8mjG7)glU%Aao$ zpIKejAO!sNUY#moz!&@a^&2h^J96`i71fXODh}Vv#WS?7El3OZfVfsX0SxrU4P!ns?`r7GkrlIt z>k)7LKcf4M|5F^?{fuPPu4J!xUwp9Ncs`Dv`RlRt)4vu6OP`dY#EEcml?cyi--Edi z#=^(`g$5k)lX}z0_c1-NN7zf|_KSsR%cVl+{s_KPWdt@G&N9IStq|C)e z-WK^=WN?+odOL)nACLUw8JEL7z|`>hkiT~c%e&f#doWzV{j+n)fImo)KkRPkZ>#|6 zFFn(54AOIC7dYit;@)d&e1}gD{$hT<>4{kuQWlq%d=(U@W0|-`H$q26_puIScct5? zZ@t%8=aasd3%}9>1WbO`4RsaAib~d@(iEV>vEa)DTRj=ffR+LI0h8(n8b~ql)Bt-@ zBcRl&r(5j@-b;xRn;=F2pdQThS*+1+OzZ&}$_q~SHYhD@0KAG=5VEr3+eP8Shn>>_u z2`3o0hoD^2Jqmj-FxkokTD5Dqhh-`aZBhRxN6O_mm?q~&9X?Irt5})fQT?)!md&e7 z{xQkGr-k}b`Z*yukbbiAH3H>WqSBJl%W2v2LJq@u6y5~HV#AD;3uFSk%f$oc2!}2^3u!k z^*7&+y;jeYeJrRV$C#U75gmDE`Jwtdk{>r$vG|Uk!w>StgZyrJP7<;poQuMW%OVJM z?g6fNL*XQFJeH*X>otH?UU@M|GATc8z!+3{mH5~I6HfcwkRV{PaA$irZr{BV+%yL5 zpfPp8m@XG{G_I4)1TiN+s8?=N$VCB>MRnuJW(nn-bfy-P4AKuAd=B!xo#U28u zR=hZyCwjfXU;g8#foqt#MuuT?*$D8Ti)NFBVy=kg`sgXi4R{59qD`yB)Hk5A`=_$H z?I&t>L#GUK;yD`2NYhRfQhVSzxgd?-=wFph^?6kPSh9Jc=k(RDyn>fmR3mNXw^%05 zpvg1ayStv_$w_YNT6tK0XZy_4da65RTJbkvs$C3E<6h~kc=|0KnS@>7%|ikC)_e>O zBV$J?(72mICgJ@EO@wI)QvCHkPZC0y5pqkGLa0o=cca^0a|e#hG-==j5Y&W7Ki@{U{aR>;WS|$EjSHP3e@hmQ^BR zN-CMS(=OTBjmvr?ww`P|T)wxgE_LO46xi+10A_?6hH#lSCi4eBT2uDJ#b2~ZlXixz zPbv3?snoE=dcO>d)cS`jan-+Sr;(!~E#r532AB^U$Yv3k%|JlkHjBTvlypxvx<=NynrKx`1VTf!xF= zC>vVXxJMk{Xkf_2=Hau_%#A6zh@3#W_^DhaFZU(jCtT1m>Mfnv-EKFwx3}Z&-Tb~U zH)4I{BhSSPANyD=Eiaj0fLixXS0-gZ0_zl{?Q)dx&=38}d?9xl!b@%p>yPw`QwAqA zWnO_(zg!3Jbp&*I<%7IOpCVl9h1p+2=c?C}U~afe97&H&Su7^=307oSZtN1T7E{ZF zvHUK4LS6Fh^qrku>ArpCm+b&OmlMJB3r(Ly<^(Vs+Mq2u4EhggvLW3kfc2xql!JEY ze#APV-Y89Qu6@33o?XhsYv>}Vf7RoDgN}h*=6y<~_s`H`-m`i6l{ez;%h%%C)f;j1 z`mNaB*pAjtD;_(0K0ffwk43B1jn`g(JKlKXo!DI8713e#$yiugjc$M63&6YWwilxo z78Xqyu2bOKN8SE`2CoYatKKswXQ%|_%K*gpaVs7+%mknCjtYW7s-nPvns1}B(8TU4 zjcHYpC>4ixGr;#X&=M~wC@4C_V?YPf0FRwth^56TGY{XG^{!h96!PKNHw}S&`Bu}> zK{6D(2-$Vb)klw?S%|aCjaZmd{_w9*qyhlK!VGDrIn5mT4r9B#Vtm2?X+eSqL;>sWJ}VlES$J8rL&3`dOHMxV8n*`LV;Q-DA`ol~Tj!y5;LPrrzM;qbe1ysTElKA25N;KxUR+=y=6#cEQS-vkj z5qECiQAf^6bd+#56-XHoPx6glCQOzj;P%x)aAN(!S+x=IuIaDJpnNR;Gl(TFG(gzb zjt^)wn$C->6x_K=Q|)PR%VYxOoFqdg9^9cp8#+sspRjsYuPeFNb_ZI1Rzk}U`q_q- zO4>9PV2^iTCLx^qU!IF8WFFF6*3kXPJkXq+NREnsp%Oc<=DXjHsW<$qKdoe)A_{{^$PB(OLa><8X4$VW%hhF?)C; zj^6$+MRcp5d@yQF)saW(}fr;S~}Y%unG3iuVJsr3Vi(>ErM8&1O2B5Z>C|_IP=qcPwa7)_PjVv{(Cfk>$_n5N~8w zTAp+kKpD4xXoOymY@j|Id91xF8Qf}C(i7#+0)xXd$-;s%ON1H6pGTrBgz*pBWjb|C ztbqRSw1=jK8gF6g3)C1G+<ZU&&JO z5~sMQXOs3U=rbwiaeSG;tBXCJ1f#AL-!))jQb#OcWFLTxS0hfR6aDeswQ zS&~dYzq%wGvQ8WUkRe^@&a=H7AZyc$u%b77PA*7$&o#hp3TGKDzhk8vZ9bz(A3 zC#~cl{mj#Z)X(x655}u%dwv$q3QxX0CS3>QPn%MjdPjR^+{;OS=C4=)J`sO#N|!qJ zL^%a=`bH3^Amekx5186*el?X7rwZ7XhVjlK!@UJWOEhbMlk zd+Zdj7kvf8h2a7$@bVo|7I``0UBe>ZX6I(qZ_mf#A{({J4J48=ZsVe#7lCQpA}}?S zZ9MC$>Tb{gJ9QH5+#G{`f#Dr8k~Vd3|Dw=NA0Ev*7?})L9%LM+Kz-&GHRf}C{UhIb zRubqsgxJ{F@O%q%job{vDOqD!@FgsO8@{x$UwNqEio3k@&!)W3AoYE9mT=WAo+9j! zW_m%MSsu!o;WEOgth`8{v<(DCjw9~{mg5yf%bZu`q%haS&kAN-=gZ5>arWHVID7W2 zzv;ZZwCuV^Hh>p%N_BCC_RDi!#7|HkTHW%epQ0@%4Myd&Y*t(Jg0bS9dM2La0)1&N z($F?}m*McMb5!=H|1II1{&;@Sw9s`N^p8Io(GUU_8mGx;tZGWo;s;M60#5Q^lUO+A z?{p0yI@6!h-=%S00QvB<&13TQ&<`MPv8x~HrL380xdAa0 zSq^!DI75Rp1y@BJCX&z9-|y@u$jJSE7;bo@$8h!qhY?QIRmyHU*k$m+DbZnHk3cT; zvfwM(FFD>Tz%%bz{N==Omb+#*PLH(T%>a5pg}*p|0etO4XA18+R@w%oHG+{D)*pe2 zp--p1f(#3Yv`5_Vg2yHb13uYqM&l#=NTsG{`%g2Dkl}~Vwlem;@O_y?*nK>P19s@L z%*%7T2@9m&e4=)aT=87J!jA*x;~j^lET6b3bvO^6>j9)kJ}DEBBUKhvIfPD!{>AzL zhs1IL*!ma?!svl|Z+$@Fy~)r0JhVLx$R+Fk$SJuQ3wSYBx*K?MNQ*0;*Vor$ZEel{ z5DWP~`I8@y4}S22*6aJy`@k2y-?y$73PT6V!r~^IuDe}M7;{x}%44q|NKa*9lxOmX z#KSrwP4lwKZvK$JUU0)J>s&1U`nDmx;|guoaM*0vQ<{eiqVvy2lr#A{sx}PwG+ppcQ3nwcD|^xn(@)U-&Nn8TC;YFFtOY`4KkB zqeF1W6kL4me&GuYpUk2kq&={X0j|a$I*jo{;$##I!~Vqn)$L$5gh?a%iEgYddIKhF zGVh}?dEcwq+3UugyAb|R%D`$|c%uGcT2J~P}@!4IDU|<4`@2F+E68ge{kLklK zoM!O-<_H`$9uMZ#2xuwJL-mTCrzXW*?08e0S#=_37MpSD{7O9a_-dS6Y{Zh3=Z5f| z6|Qr_X;$tz;e^sme0h0igulxpw>tpRmCe8z=AxXw=Nus>p^_(|Ir$9JiXbWz$`A|Z zD6)_V24@FwPk5o2%&8t<eI87N#IAM=5eX*ms8-doV{X6%iI7E5`UJ4>_F^t& zQ9Yy(Re0*S2o-k(7OeQ^fWg-g5?=M?hOC6}PvM^e&}or3;hd)I0v_liSQHlF;toUj zboP&;t-&B4PXF9jzZKW-O0cNk8W42}W*y;5*wF9y=FjSC@tFz&!0q8vSuffp1qq zNB9C-RyyzQwj6&!e9bNzzPAm-@SVNmL$%doIx}`TX9ouzed3wP2l35;;85=D0JGz( zJJf4uIqE30b2O+Pa_4mNF{mb$WJIT-5H0mo>jzo@Ubt5pR`BstxC)e+1ZmSuR(L|| zk$G2hJgK^%kxwwuA{mH$;i|*UKaRmS{tt0@_5U5yhieW?Fi9iv*6M+`j6Y_CF45H5GVeM z+s}GUm{GXI1B32E822-j&E+fcWYQktJ8o*2`ffOZlP`H;e=pz&&+&8#HB7JglfUUN ze{^9Cx+%MX+3~#~y@G4}>cGW=e92~~tFRRh-c>yc{fYM#bL)IE=zHiLed^( zcs5>H-!@Wogr(9~y7=imeZ4mcqQ?S?#$*%SGy0H{QhLx28dJyYe&;>7CT~Ie#FhNu z$3hDpimCd51IScbR+=RR(x4N0LRVg#pyc~(=ys{QCY@LmNm`|@pMIhR2+N#GTW;#h zrB`{O)R0Cp#DkXTCK$q7e?@O9v?DAS*7QgOeC`F0TNIY?sq2i=)W1DO1el zfKK8g)pha`r{@`8N!A>Te!=Bn)45?l&rB3DR?YhZMK2`*Z#Ok&<4QVC03Wd^46n-O z8^0_f=j}N_@*xY0ObCp=5jAN&y~F0{y^eX*)gjv(AT%D>;bfY|NL;7N0uA*_2?iRg z_)|=?b0Rl&Fd5fw-Vm-Q8VmG=llaZ;jB$tFyH2r_2cShR(rSDmn{lRJ%9!WeCKJpr zitC^8&bA@)_#N?y>*~V4@QR<64>qJ@Q;35qBBgL}|0jILd3Q79_WMlrC#76K#K4OH zzQU6-3$M0_{Ds#p#~*#;<=EWqnEqU`%%VKs6*DmQ(KF*i#zJfmXJRc+sxfiP*hah~ zIg;a2F%HkjS^6p2T*2q7p34HTPnIADlqRPheDxr61`40^7ddwF#$?8xO`2qpX+Skw0um=9FioiW&_GU(SxiisF{%1K>33syYcHZp78KR_t_ha`IsqPG=8K_Ofs*x98M~Jp|P^HoP(JPdz$5n@aSKMP7rRIr-}o zL3$6rAO|d`W!D=UT+l*+(VUW>^sGAJ+2oRZL`I45)H}8}%5QghHjKj9LpE*AGFjnI0YPNQKWUrB-o{fvS;0$|Vi?Sw`8PDgCJmQG<)csF z6hHJ}LVmu{h=uuPEH)Pmxbfp~0}H@hCk`zv4^>ZfUd;==%)_Z}=}SFtV>u|>?v#D# zIys+{df(wN3~^FFs($c7&ifFae)K5w;oZ=WumaM%C%knv(-k|x{)N_2euy z8*t|f8=mo?AGKT&FrO`Pt#*{{%SMUkHzUX6XO6>komcX{U?5U3r$3$v`bhV)sLsKcj-0eKZ^7NHMvnkdY9_K zTwidkbzBh5GNyw+gQAr0{!YZcpy1o+WD`lSy7VOK1^aykVPLPiJP~}k4B)7`@#?^Ty z9!}Gt_57!xp7>?FQ@Ezb{qU!mg2Oo26I0^z-<#GXmuTZ0gzB_A-XNFxD+X;|?<`x; zvt(07%LnNz&;`BCHgXERioRT7EEhyGk6C!OGJ&oBnLZj|PF$dfvIVl0us}G-2Bfeh zplc{!pJ)Xa_3PK-?)n|yvhdt<&&7oc7ox#UKKdb- zedCwfYRZDrW+9U67I}DVosMtb@{Rs!0dfK=QpP+jORoTxv&_UpT!630X8gFunOj0R z$fqHXH^}X_TD}qYP-Q{>vOb22g#m}`N6;Jfq`#^UnCA#1ckMHg@#qX}T<5SGJWP2= zhv)|W$y7O=vTf4qSoArqPTQx!JDrZ8>qTzXAJ3gTr?Q;H*4D1q^+*)jGtQ^EQEn(u z@iG6(jJI3fC*Iin2M=haH$zCgNZ+*Nho2e|@$sjg=m%KnW)c1UG^1YNJ(yc}He;r- z5GU$@*y(ic{Q3AZzxZe4(xoS3d#B|)#pf4SVrq6?Ou{6~iNB%o_SNe#1re5)W2fDY zyPI29uKe8&5eYix4u))`Tp`WCXI2$7FJ@kr!m-MI_QHXayPUFZ%nH~Uq6Wb;{s>YQ zpQsY9t)WuX=2R1tW&jW5#Jo(RAyBAT7!f}PSm00<3@a&egA*0YbxQ1_wQ?++*a^uA zhLxrHSXyk#UXXIMAbZiLGx<*I{L8?;f&$p*`-*Wm!cJiF*}jhQ1k5t zuBQej)i@e6EV!ynVj{{ssWO1WjIWxWk(^N@Qh8`JFguD8Z0v6yC>%`7L;>YMM6j61 zcWiueTIGf5`Q``ZrhHbk6_2nIE6Nj47z4^7bQXSA6ct99!BC#8)6Yg}qIe*1>VN=Y z!tUf<32YYsISt&F;BF0$WFJLGICTr~J!7D!_w2yV-77g5M_}>|rU9pK1?=j`$v~A| z6@M0aaMz4>QG&Pg}14ALLD*?RR(%qXf6)h z1Uh7=dlcL4zCeRe4f5M+ckuM{&p+=08{dB7TMvY%_N+vUADCcbA(-ps-~&ztwIwu} zBw})4cXuaRdpqK#K@7Srb!t*|1V{T^g~rv5>^A4>#=f2taQiw(!C=r)eT-mVczAbu zg##u|xGsZ%0gK51?T<+ob-qHF_BU?oGw-ap3r<9)`$7NAgb#p6=3ULyG0Fe~P<4DK zsTj~5U;QReweL;^d=%$_@!to7K2--2r;Pms*o0C4 zRD4dE@;YA-ZfKWu^~Yd^{(iPG=WC9*?wJ8013kX$h~9^OOFy3zYob-DFHB7<>o5CO zCc-j(bh>KY18JN-S5;nVEPd*ictENl8F@$_=JS1u4p?Y@RGT}SM z7qSXF)PF-mnpu_%UENlu40z&?#iTw1PYoUc>68A9hw~&LI2Ek?TyUmPw)54!ri4@( zD{<0P7w`DpYwWA=sRO1N=Jx=T7~X5r*Z=j;WkKhrq<#}hc62fTNlyoVP04Q=~A9HVR?h#W~d(zeUTni`nSPY(=m~lCX#$+>NI&^v#<~Z?--j7_^+1vGv zK#ZqM$0C2sci^u)aWk=uKjSvqFZkL({}PArOu&!^;KdUfzry(R9BJ}LCEJ?^rKKN! z&J!E?LYgHE!PzKSa`FF!^hw{5|NW*SJ2HeLAN|tbcFbU&BDG(CeNJ0+;@0h(@%H7*(GnlPxr`A_Kk=@}X}(}g z&!ipwL~a_;I9xBmX{OMcx+0Dj>Sf@|Oeg0z7`HPfFo9$_yngUCvV+MiPENRODqND8 z`IzZAx3U=XbJGrYr0D*poKi|T?TIY3rZpo#`qK`vXc-f!Sa{JHap8BMae-xw$rzIS19J>V?lHF}`s-WwWcwO~ir5 z-6v|36RN`#Ky^jl&c%4Z;fZh-M}97}Y>=~^PUA(LYaHI%*o<2@*W>l8>+!~o?O5N{ zIQ$^#^e_zbRLpbHrafm>fah^AkEqV=E;eo3n+Gg^raS@9e1_la9dlnSDrb6Zaw3j+ zf_AMUQrJ2HpA}}3W!;Dl_zyw!U;;lSfani>mlm2K&cxcYQP3k^{%$!2$dZbHh9(zj0$U$bam;bCNq3dEq^5 z^5I>&$$RKO1o)eGnU-}S(=Q=QFfwkQ4wsxaET=OXh31{-1C@3ziYncb2PWeo({n+A zxkc)g#RlruDS@9X`Ut)sz0h3nqCd%SK!VLjo~xq`QFqcUJjYh_(9}iKHsG&t)CcxB zFHmOB!K#hXcEKH5FsGGaahG`156{S8#YKkZL4g{Na#LpfkOd=1T@%_BLSS6j5x>|} zn%d;M43>1m59%Q2n3vlZ+cMY6x0Gu-ZWE&Ic(OK5qk!8@ftrsY>n3F_GD&X9E-%>9 z-mvi_eL;4r0^9|+YHE4$b$_8S^*|Kq4MQtjGKj#ms&>-5zO%pGysoybAGl#t&9UU} z7)oF`v~fW{Or`D6h+Zrn`&-)bXP)aw1Ui&`I3R~j1 z`r_0qrs(mwZ$eSX>4~$DJ7uiVdRK<%Tux}2P4XvH#boRC0Os;1RlkG|0+-tSGsfYC= z^de*`hBRO$)wb&g7tiPk9_&o3;*63Pr z!Pu8ymUp}_!PwvL@|iqXYvH6i>x%He`)RV|@6qs$lp|IC?0hqxc=~Cd(w&zw&{d=A z$jvFwuYUcTvA(qv&-~c4o@jad%C%TJdoIpBekpF62q8lM^}-}Ci)gK%UKP&I3SVdol6 z=QlmW4s9w=%CQ*F9i|L}Gb+m0Cdi}`t4>{ksYvfkfIADmFfPhy?KELpgbg-3i}_|0 zAG}@^?h6_e%`kY`??rR!BrdGX#}j9l;=*zx7H3)DJ@z7YQ-dZJj5&#i%|c>hCSrb; zUA1al%84Hfp(s4Q;)zKL8n%QY&wSGaRA}%pHI0OZ3`_cceEFg1)&|6BU^6gvP|E8% zkeg11T}D3Tr|_KkW$|}b<;I3aGT~KxO7*?p8Pzmv^o!K@QXrx+&NJ z-sO8eEA03Ja2=E*Tu^2m4qP<&h93~tEWWn)PvSFQ_-cIPmFwX(G-&7A7fy;Zb#mx$ z@h1IqM-40^5|}qwIGxqNL*x_fs1dx=rmmm5d?rw(Ug zI__?4co6>Vhd$`CaNPp~aeiLtE%bm^)HBL2)yx2&lK{k>nVnK6v=jYaTjgiLw<|v4 zW9M=Yx}q=bLAHSBgMP=b-vipi=LEuaqTg+cUa|!P`2k))-e=J`7ms~?M(GeexnBe( zhT0uByh|`yWeT4`+%dkZP}}n(^Zgn2F3cZn#L=7oMeM)yw_|eS52A6>=ghfen&ke` zeoSwDHjcmjx8mf@|1_G%x9+R6N9K`vWPY?vm9y1tVVjSB_T-WJT>2CSRwKJ8^p0EP zw4uuF`@!LciRV*sW*FH{SLrjEgDye8$OIF8xzhlu;K}Iko2mLM2KOnjU!t0Rr}d>8 zr-T^(>@M#y_R}AO6$VV~nDy>nCYk69WxO~cU7+ebRqsi!W=3?%fQk2*KQt2!NAEH} zbd?&X8uEOQ$ugyTm@a9S;5ALc*}oX#WZW7#{k%{-?vHVrCH?YD1fG)?j$Z8ayB9Jn z<+va8YApUZeMewF|4LY)SHnFl19eEwI14c*SD+vBOpI5(U}YL9pq@=4{gX>}!OqBO zJf!g#lQzC0SP>Ll;}%6D9%Bvs($O~C#Gg|w?7+< zS#W8P!oW1}!k_%zmgUE%L0I>4J!-7T@Y^S)(}nY?|kmXxOsP1;~0${j|C@eJnn03nwyZBC}gp)-UvmX#FeMH;32-DJ_Kyy zWem#1pBE`K*5Q=!k;e6mjXjB_dPDRc9jXKxS90Yv3ts-dG|q?ASkqC>_0oDK0(i}Bgp|yf1GGM$-=DXOjy9vcyLPLPS^md zu#7inX695E)1m~tum2M){3tKc$Mvk7ncQT)Bj-Jo9%Fm*2M?tQ4=y(*<4j}Lv}NMa zTy(JvB_!NbJ@iqOFC-9EpCB=}N`h~v$*D{r=bVB)A z=BvH2Vc&HPz2q1`eCDyIV_vM>LR_yzo#Pa3ob(cj*Slg>_@ba&Li zd&*BQ+@6fRo=H=jL|H4~r+45_8!(+%&~LS3`_5)uyLLBTd1pOdy}BK@cK4$v-a;Nc zEaOGod%*KnW8is*2lyc?SRl{39)TBt#WV1VzxRvWnaM>5<~C|8rG;f5EH|`<3Y6b< zB|p^-V}DQBtIY61JuzJUG1gBM#|u}7k$_e6NhJcVu=@EXJo%9qMWvY5XB{r( zEM)*Ep25$+JN$Sja99$NAzhcD0O9!gwcJBfNLP6$AwB(HVa?0-kulAZclv$wZ+W?` zh<+KtX{8S17|ws()cUM-K;qSH7=KsXZleHgMt0Tf0WV}`EQhaV#J5=nMaecU2W|j- z6T1vk!(uW;J%j&P8HVMtHS+&K8c?Wuo1fE4!^0T9)tsU!G(_GD^k5nuiy-a;RG%yi zCtWQuoLr?8#?Sh9Z{6N+^j>^yy-KuagN5}n#e@FtYq9mL(l|Wr!ef$Q9$7fZm<51;(+so$y04PLl#q4!PmYSvEJS z474fwAj;32KlA^Gk~Ng2nygRChrGzKF!HF*<@3GRTrg*@Kj-_|V27UO@iL%zd4iaA z4El+B8w>heo&wHWKv?`uV8Qng9nR^oajyag($M32KB2nTYRA^rR@}Y29=C7biJLcW zM610QD=W+K{70XUk9_1Ku`DkPGm*X2 zLvAQ7;S?tOozzQsPaRM;Zrw#^^-VouGIh~%v-Sj@rQd^(NyvV%s^}t{O`6Dle7mAA z-|YuKHpX)W^ttorVsWYI{*3U(RpH$?DIxS5*7e*^2#4e!qicYk&R7rjbH153fT?vf zdM*wb_%qj#dd27cF-WcVY|cM^5sC?>;=;vCV$_xRgMaZa{5{{c3V8MU&A7X@9j$IZ zUVZ(|Si7?kAA0Wjc}xI8}- z4UKU5uIA!Q#HF)K@%XuwSX!Ky5~#+;(NZ;_Ia+~;fnvzXUltT8Ym*(f44#EE%6Eek zoKnQNvISv)aHjF)PB_XZW|luV!tB06+l_z^cIVN3n4gZtjZ5Wn1Eq*Amq-PWj=T^m zwSH!V4~jqeTG+^7(Fvgxay>VK$#DUcq3Kx-yh40(AO(96JMF%pV;+EaIuguWF@T`y zOQ5nNcV7b7!n-WyT7i+lox6GRDhHnF5D-B4`I7rCr8|}@W?zekIavWhH#l7F@z_`aB--!OQ-ANQvZXE!UrLXZc-3IlBz zT;|5bi5%P%ohNBYs6sO)GfJBDmFRBPRmQ?#kB7^NC52Uf)-&y&;r!omNA(L1`K$TW zL7;vo^7U;Hew*<~hqz9oq{&Zi9zF4aAJ2Bl6x?!>FDLT=!qoDh6Y)OX;!%Z1ee{Mx zcuNoX*Ys_0)@OxJ8dZEBY@kJ@)qO@@jxRgQlR#Kc2o`6AJjMx0A+N_Hr$^^8te>o+W%n~yUTV zK`Lr%ipwK>mvyFB%7XkEmsviP_6{!aqS>8*LI^1Vut=C@=x`q3KCQZ9SyH9J>wyM; z-ZH*IMozLJTJ&VhuinJJ3?*Y)pTt1*^wQ0>_-9}IN?cptmP}QBa>EqkzurLOQa=5} z_^pg7C0jTt>WMKX7TGL&IEVx3!z?cDAIfGCL*sF8%Gsw6QyleSJ{_VlPyK{W-m1i; zA>R+qaVg(;>q@3yy?#AjeeG58M$3Gam{YctOI|ReoHIGLV=}o;lCsdtJL-8sJh8OI z^{w*?GiN@UR2(M7m=l?VuatULDRr%!s2}o^Gbha0G|Zes@?wtlRTE+!c$kIfm4#-U zJ+qWmN)m;}q-Zzk7XO6wr%sT?@WhPj%edk}#-?`qiaw`94yn(~fJMGTwL{t~CsGc%rEEuIR&L2^?S>kb7ztV_?a3Lz ztVGDPnolkgh#0b`;)sQ3`5lY2oE)0yw_|^MBevJ>#MLXe<6E!aj&EPS8&@~l(Sjeu zpkDNPNG5qd`-krYlw;f;_lJ_6V3xyuEiz1Q_{!IDniod-I1L3zP|#9Gq(hxDPnP|1 zne#)xQ@YfJulAQ4`qNmctIQvnN-{Z5mHk%st3+`hMqWI?7tTlVC2w*OPX4@-;p8~; zGfX^N_7m6PEt+Fbvia`DR_rVP0UI+^imF3cCpGTKurwq~pIvE1na#U;f@X>>mwt+` zT$G>UQpY7dY$o3+cR|s9)=Q9?B|p*_ualu0L`Vyq1Ww0!k(K;N!}R2x!a2%@4f18OlG>7&9u2>j|2Qw)VnZ zziEa06ebMHDDwdXs`cG_xP2t!RSt*v}sR zUjzJL4K&ZPX1h-wFEwrS^v`9-s&)c6Pf2&1QhiNHfAdw?8nXbRzDYn|B#Ikw1Ih@J zWb%OWsP%!5`)A=btSdbuGwGwbp~d~E{E>Uej3MoWRBap3-f{r&b3wX*d7+lg_^57` z4>*|p1hfarOzH~Zpw0=0zW+H$aQb< zguhic7-aLf>}1^n{xq89M?b;(8n{7Y4E)R57MoX*m3gyl$|uHX#B;gKb38+K`?~Le z571+gZ7i_2xmkF9!#5>So-^mp#p>!Ag~_tHJvdDYpS;W(kmnE5i_9#uT^>E-&wGP0 zkhk8M&VI0$Y&metX43+))i`IA_swLjyhrol=RX?%-oN+n$1nX`zbt0pF7Q1w^Yxq8 zBtU- zZudy|GDw&5B8H-d%;b8e;aj)}z-3A4BcQD?SP(HW0NWFbnk}THMoX>IWHVLsjpHET zIfhSmhg_4Z^2p%@;JHaDrbqplpP7os&z+4+7tX6(GfsmmoxKJl*&-BD_)EZ8EP#jd zB;26ak4~#?!Nxl}8uFZPXppDDo*TFP7~C~9=mS*-pxNlMb2wDG2*TPB31o&AZS1yJ zx=@) z63$F+aOD=0nhd z{EJ)Ra~GqabPl-TKknrJ%pZR~UV7zPbO$Pj^b8h#**A*PmmQOAx#uMC78kg-8QMzm zR2`Z`qKOq>0arBejBunL+=;o<$vWtJmrzHYQTnr4VPdu!8iRUrh*R}*jRo`djhi=B zA1InB%&2e35ATwmzxO3K0vAL`k87V1kaT_xwHZ$7b~LE%cRRsp-~EAT2=uzDhqh?i z65a0s7J6Gd-k8yDZQJg&cZ9c|JCXr{P65*B_F7*2HS{~OJM!zwrk-=+8mRRKKV}D< z{By6N9a7#0!6WltjA$sq059jjk}J>Niv8>VG!o zZ`{wPtJrBQ2K25jsy!GoEP;pa?_d<8I_@_mO%!bg8Fs5LKv%JXF8EO}?vJqZG2Qe} z_w-TYeHJms!&if^Cv2p5G3a3U!d0$pC_~>tU!d<~zzA)rEBelHdewZ0&j68uRt{j$ zbCb>q8TK?JKDJSI@I%ohFUQZg&Qp+a6c8mdW0r|U-1Y-0n5@!M{L; zDdpfDPxfQLn2Wyf5s;hYG9KkB=nTWVtp4Z6d(4<;p#?wk9yj*m&lxx?`#O#ZdD>(e z_nTqat1UyCo*2ZYPD$@U(G|s$h^5}Kjn8RRZL+)t3)~omqrP12KzV*3)G!Z#sx4G_ zHvFw96z!j(I5?b%jk6=6j&iGw_ChMJ!4x z|4JYD)UwCvD1AM9lBUWKh4EyKv8&~$O+jbzT~aaI2+sigDB6J@VVK&6zJwzkPp%e& zD;MiHAuJ$oaLU&v`M3ce(sVet57jS|aw-aunH7C5L6FO(otB$Js;WP*uJCIc3Pd8fG8Ec|lfZMg6& zo12hWWM(3hF;`1t;9G0AjRZ_=!B<}RRhXfn!ZFH#I>Lrx@DjDlNpu!_G4Kl$lBDB$)boP) z^z5?oQkZN*vPs4dJgrQ0KH2pEXFn$~=k1D3J7!;dz?f-nN~O{S+SBK%&UW zK>R1!Fkdr1VKQjB+TA!C$`r#cHQa4VM}A8 zj-YoClcFtr$T?(Ic_&UZ&gOGE%4hOWWgkd3?3G2|TWfLkowa!7ja%`}H}1qMSGMBj zW-r?PoRm#`jpaizriEbKRKI&+_-@QLGDavNPeLIF;XU{(>mRpo9TS~sdzr=<)aQ~0 z{0~j3Uluhu5$o2hxJ;}M7bs<`hE#WK&Pn+S&pScVbiVn3ZCO|HH%};Cc(MdBp5)JF z896L_2}c~{De|S;J&2pP??kKD7cWkE56 zmCb1}5e?tlmcPPT7t_0pQ_AKvOF{Iixa^0lGu;)(vRH5J=dOozuoam1>RdS5J%~#h`20OvX?Y5t|Rf1{U*IwQz|Cd2 z2lOI=da_w|IXdn7)D=VrXI6iz`;ghUw9V6m4^l;&w)@uK*TG9t%0 zFt)g~>`gSR-=QNyw>pMST$BoRp?pY@4W8cYAU@+gI$X|2@HT(w%oytmycZz5Srb8@ zK($QSm*s-L5nI)ylYBG1Bm*Uut!Kvb=;o~D@SWnV?QQAPZH1qV<>i%VE;Jq1y14R9 z-GxtUcATc?MFiNM8__QpnlqoOhZGdj-~VNX&uIvcCv>vxeILzGPP`ZM&2M}oe*M?~ zzwz?RuS$^3N2@c4wYyt!`P!PVOxhcWSThT;qrvRY{Fz^fT{ViYzw%ma?Do71Qk0E_ zvO4Xf|S2ipHeU zotBb5B|Y+BAmzN(k5>0Ex`T<>?H)1=biI${)mzQ^nn*lM*LxSmrSNR&IL zs-Q+_%P38hZXfOU_HLy;F%!GJ!`R&I$L3x?wmSQFQ{bS+6RYzOfTjKd{ob=mqxVx@F>+P6oug6h)Blf$SG3abWzkN5ltvk`(yAz$= z+tE>&cCovyyV2Ra5xwnO(cifp{k^*}XerK~ptTjf_O?31-Gugz(%X(hXy4ma`U%JT z-2##qf+P4+Fmcc~y(h)n6XhBXuH*3aNvey|B|b9m*@z!YC&qs|SkLuL97?v8Yt0Z! zbcitdBf5Y0#)KV%A41wurQ`6gtoaeBiyx%10zC%q{Y8=r+!b-4wr^knAh~-#XwZSq zFy<#|VHl=G|0x?k-b<2uawhqWKADpR%0vA%ZcZdHDJ7@g&#GTT2PsuX-$@(>WC9O_ zB$r5wKEVSbGcmw`#hBQQAG#f&7y6fOKnJ0;z5GpYWbsc5tz^m$*gDHvW`r1E(& zLy&rpVBBpeXcal?{J~uoxqGmyXKd0DA}%NTC7b66)YX8dy|?XKI0l`)*t&aLm84pd z-Y|8PgE(|SFHT68W)jR3Wx^ZUVKWKFz+{@MLRm;E1GgNgB>lJ!mb)*h$z0%NX$C!4 zr6}#D(u_EY&LOBcnU-71%ft-%Nk5v>ph<8tNm|m^^gB3alNb6A6Xu-fn^n3@n&k#I z54^!yz(6erzL_t$_cY#opHgmfw7G305{#3vB-hD99~RVJoHPwBxYe3<2! zZy7Q4Aam(&3`QxBXh6AYc}IY!^714RCqStx`4e9WQJ-EQ(>v1h_m=dY@d4MWqP4h= z6~>e3vPl-+^TepitZ0gpT+3L3a+0kF$ncyH%DfKKQ6mj2Xy08O1GLPYu29qdC+LJD{(Y;nz?~XL45hscl zxH*ZFpQN+Aw5qYhOz^1|A{{DEFSrSZS^06AlkZ=xZ*E4jIp=HS*w{)LJjnw7@Qqwv zz`+C1J9M~)#&9eyGjRiz;R7NMCsYBV$aXY%ivs&E%g88C(nGwXXO}y}^56dYfeZ4b zyfDq&K2*<^k@hR`^ly}g!s*|fn1b+L1XeoOyt~)b@T4cgo7OBixvudlk}jo55=EGt+5=49_cb;32LeDk+%7WN`A{S;$xx$Va_dyF;Z&pR(v z=-J`CP{Lw|fN`sA(qjT@?e?8`<<(c?t#>Z_6rx&!AnBJh$#UfcvuL2P948FC5kPc= z_MUW8KuPAWN_HGyf!VASHIhj?TvPHw>AFWZbyG} zHx739;>ag~cVm*zF7*d-?D2EUekbam5ASMBd}}T4ymKoqzqJ-Gy|ETwdHr^L^U7Ad zv)+llzIaQzjZYH^;gs}03`R7AfTqUC4O?(fg9Rh{EO>C(W);-e_X=ot_||@k>bL$S zTI!$6=``hbT!4NKIsl4~r+KV^6H!`;Q5y3BY1BlW95AX7l zesF$%A^Hk;>-ODPySpLXWzM$~<_58>7vn-&6#)#1D{cP>N`Bx^zXCtuCVp|VkRaxg zJ9V3Svd{9OEJ)C=mX|~rQzlA6LWPNs;<$bnk^d-WOK4C_-7p}%ZKc%4GcQWvti*VW~zIA&EJ{F3M zz1%GPvH+~&Tdt-IMS@YHqE`VL#{ZUU3`zha2y-s~JAqy64@y#Cb0UR1G9qlC@KL z)H<)vZeWUU;Y*+Odnw}l-p$l{0|WoWpX5Q^ne(83;Zx*+ z$9f9QJX=N+6VYzW+eK!62Sb!NJ4r1!{p0^g$O8c;gBkDfp=%UcV6S zQf^50$sa)GA*hW`)Tsa-2Y+4)G4bUfaRR3)OYe*Hp#0efFYxOHi|A@XzZhqO92vz<2PPa%Pd#fo)zpv(W ztN%U?-=w*{em6e%g)hWs{^U<$uhWg`*+y)L(WmC-HR_s)xrL?p*fH-Z5AmHeGSMllaIZ@2+2+9Qx$0{p}y&5f*XEgxPh2!T7 zOUvd41P;t7$t6agP+obB^_i80xb*nhIDf7YD~n9-fE$D4#G@)bq~T6p0)rjvND3H` zP6tKHN}GUhF?U%oRpZ}O9bLVC%O`F5P7eNjt7k%ZaupN;h&0H@f(YRw@FI^H7#7Ng z47gDi$O%tEq+s$-ey4259s}aCLr&#j;+Xo{mVnxAw__LKDZr2K0dp<%t_I?KSK8M! ziRK8jT0ZInfTo-%CR~>~Du96Co5KFC@BsqjDE7KN@9^Z?E-lq#OYsg=cM=`ZkC}Mo z@{Rb+m%kn_y?saioOhgZT^f7gOL;4pPI^N}vAVhx=g#K0rC}#tHpE*94Bw+K{*zON ze_TxjE#y)JU!8*x)HAzbKK$Wl)yZ%Qz7tPeyy$DUHa0c*6s}DC%t_e8mrKp27vkA5 z!-Uebc!{=^cuvHuGMQ6d!}ruL8xq*n%5~`QE|{RivrDPlZmDgwW53IF&wJ5p@A+gf z;1j+rJ(ug9+q*l4*3Ne9ZEr@mwG&+pdb=%w?H%EsS3~#IDdEQMay2wz+Ir6fc6ZO; z5q6#e?1LWP85Zm_*yyW+sVG4!aIsP>ZAA6?*i?;9e-;GoERXJJ$*dJ^b#;kVW8y6GW#hh>v(10 z&Toi6hWG^t%s{84<+%Ex8`n5kcKb2op*QlYv!(e%cddRI(t70y`mM7W<^iN3EFNQi zFsCzfhJH8x?7V8=j4C4vS%1!V_?fMgmh&U7<0LH-N{ZuYRi|v|Fr*v)#w+7gJ$MwS zat&`Q+;1Ew|I(D8ImAz6n?xa4d1DZrhTjs@o2(OfCpWK3DHMu1a3|)yrermOTDGw| zvzNWApQ)X0n+KJ11i9EGH;?z3n#Q5i*oM=AF*h*s@CKS0Thz+cax!AZcuQ3<( z#5j@-pN!GSe@5vXYK+1nz`{aP?e@^PFrHwt3T%Dds_Jt|@0mQgb$891r@2y^+qhhc z0F6L$ztY|P@fRo?(ilwsIj(p@AucywHQ&z5Fa|cxFPa!<>FMLE$@d9pE^&9G$UaL&`AYAm}6&jP2(sn7Y7SKo-_dLM)5a%)rS#|1s6{iYP^*bjfWm{ZD{Ot`Rdhp>D5=`%`5Lj zyW1BU&dMR8V;Nxo)Vp8I1)s9`v=&8VfSP$2gUVEa>g} zQo*ro91kuR$W2Zd`UqqteFkZ9>bFiJ=LC69(t#6;&3uaL+{$8{TV8P8LtD46O61~$ zU%K_*&g`QY>$4b6{%{fTDvE?Q>&gcip7ogR7#xYg4;jxURWEQTaiJ!gzLAtBMStlN z8ZS1~&X~OBJKtTwfzo8+6H>~G-XJG?DVJiao)4q7*N^T_D|YX!$L965*u1tDyEpGd z`_}E~-jTg_Cw8yhitXz+;?9-papTI3c=N5B@zU!z;;XOTjBmWX8E@X{#O=L(e?IC! z$a@i>mX8AdFc_g>YUv+zOLuNI;)D`&V|@M#8C2x~bgwdp1mIQIB6Ju1J!uR$oHCG~ z9FChC{}lJ|&=dBxKAkrCyY5Jp!1{BNisNuRXSiyrdl=9Cq}klO>T-ym{S9@6;g>0? z?RWa|`de>%lRelmzv2a2%2n&9Jwy6Z*0_z3ZFThA{Ak zhkm!~MG~${?Q^RhbE-_3lfG~VM;3`m2R<&9k@5h213am3mpRKznUY7+)M`u8sZ4rT zY0iAwh!!mH)-;$uF7$)0#4{vqT{r$wE%`3}zB@DIxoX?g6vZj>!^Qk1^UKUzG8YUB zQk$0eVglKV5-Nj{O~>9jD!It5N^^qlfB-57X~ z#lqbDgAPD`^{tHZxIdQ%n_*dsUGo7??ApHoZWpR2e&Te2LXeke1Z};E1wBjp1GK}y z&V7bW6jM8JCos+Y;eX~IUe<~8t``qZK`WAHddePeL zXiP3Wd}l81ACHfG^1jIHe*FN_Kq%TLPB#<_wFq*r+IE;z|XZo}i)&=Eh%Lm6GC#N($hxG5(x z-1Q`8U;_%b<+6y)r&pneWe~-ryozIaNq*_$Hj?v1xroc>O`WISa>$NbaG}Na_O4F? zlmFSXXZ>AZ;-G`GkUOkj@re5w;p@$9;ydG9@&g&l?XrW90GmQs9v46R7c=gDKg^Vv z;@67%`!ei2UOC=!g+K!sV_|VQHbhjuQ^ca%+`?i!@zm44()o%8G?Ny z_q>SN?sfgGl?f@LEco(HRpQ;8EN-E^QF+E$h5_}gDwJ;pbL~>9QxhIIQznEZ;Su;; z!PRDgSB=_Ng{T5mOf$U$!w_<_0Bs?wJXzf1IzE_fng!Lyywl=6yXRO`UR_xcW6!AU z5)>@NDv^277QSJ}0}I=9!~l769f1d23P-MlLl8O-2F-Hw!pa~*PvK_k01qY=UUc|0 zaNf0BT?vPlcLH+-1(BHqVNud$FZJs*)hGZD!cabyhu`s<_vsn|e$a_00u=i}pnn!D z?8HokMj$UQ^jW~NyD%5^Sg@y&Ln~jWC0=8Yh{6f|p?iMEjRjP~@GL>DvIBI!EZPqw zs0UvB)idcRZf{?MKMe@?kHwcK)3Md=$2&Lg#>;QM6W29RlL!m;r1%e%jW$YJ)=4UC z;xqXpJkFjuW5KYy+ZBzo-JoP)h=)ReAOvS>lpkaTf0S3k_}VVDg z18+lHXxHg*wZl<%dg>6F;9zqF^rnO4>TNbmnEu6&0YP57tw8__?W#X`n+}wLL9I(V zWw(0<3j%*nMt)p-29L8N_4o*zD?D(EK0FIIcz_N=|ICm2N9(iOpm*>-O4sMU@MYst zjd|^RG}M{-{gHWO9+^kxhtx=NKNMN_@Bfv*Y6x~} zSG@5{|LlH98=Zqwesi(BvTPc8$Fl03N$jq4P%GJoFt$(~70^Kw zcBChwUxGI@^hP>pN4*KT%qQtmY2!h*%9H*e!>A*5X(mW`M*&Pn!t2=+8K!^6t?z6~ z+1b6!7=Utf+8+H3od_DUF_04*ESiBItOAwb4fG*SE%Qka#v6-^O@GRU6QZOIzT`B~ zT#lG)dS|#Nx+Vd1|3n}y@U0KR#D2xL`(6XKX53T8G`QD(VEp?{jq~Y$^cxRF*1hoL z8Pke!qAFT{*#^wdO4Gb*caF!no^NhuQuLdNrp8Q5f(6_SwYS+BpLT5e_M>Sp1kcW> z{fUlf{G^4vgr`^x$$%6wqzvwIBk4=Ys2FlFBB*|i-bN&3?G>X89NqvAUFK8s5~hPC)61` zG3I51EYwx)5BZ(4pV#UmVJ7se3W5g~lV1JDm{pdE5@z-=2JWS!9CJqA2{ z>d`<-SvOg~YAbqPP`>lCNjK_<0Q(Bh2ujgy2o2}WDaM@W!x)>gGrnPgk2!%u$%gUp z36)<{mfKV2Q1(u%7wdP|y%`lAn4M!RCt4Ck?}b9Cqr{!M0vPWjgIpfj1U^HAboqNL!2&#-Jm*GQY2F>KA-h3JfInQQZ#@g1N=VWr^n?%iY<))m)&qhvRk{c7?6{pRg{*k34f*X$-*OG*QP2=!U zy$YPU2a#SOvOZi+{Z#GFgKMRE+fZ4SHFow~g7RZ*d}e+&&Ix9fICBS!v-5FgaZa)k z`O9fw>e(FZ%^GaNzPa9sJKKBigWJ2UXl-|5YkfCv-`R~Dcedm5+HSmcYbV~gwHKG~ zbmH#rAljl22L&jbX(u$HTk_AbZy0+Ra_;$$JX@Z=J3~Is$+p_C>d3l;XybldFX64G zcng`aDEe_|fx`>*NyGta|4w+jO>=lD`(@fW^Cq^7T+;7otzKI z`ppylIeDzC-9P3$+~Ke<_xzlI$z8aI+tWA{a(puBg9O~x!D&8lp$)M)f~(grJboe0 zEiXqCI*0~LBwKf)y{J9aa++S)GEf1h>k@>jaoq|K7)8!uCryx@@~`pyKIJcTr+v@Q zOXdrQJjkNFg^Q9S38(D`mD_EH%?&EMn7Awo@B0=*Xp0VAZ!Tc&mCvMMd#+9NVLr%s zf|GD#{>}cX8@_?gCKl+(rWV4sI(*Wr7jxn_bW`{)zjcT%A-W1Z)25Ij%b#}2{46i^ zMt;bddh$ER17iTK2uFC=YXZ3D)y|oo`zz-~+VBf;^`08BUqQxZ%q=wC1^~-N?D9+* zTq6oE3m#CCmb=Ukzy9`>xW2Zf{wU%DA9^PK>@WVD`YSdoQI3iD{Fh&jw=ch=bTSY0 z3r^cwwku8R%%T~K{2apJkOz7Mx*b>TBlpSL@*kZ;eLr)5%p2!Cams1t+u;-DAt@(q z7hSP;x3P5SFap+B-DIqrMLb3Yv&R#cKd!6X2e}SjBwzgt@V_mx4 zuG;HdeDFgbh^L=^G8R=PHhAKPEYJ3ZoX-XIdV>o*k+yIKX&1AWndijGd_!%^1}F4? z#&Y2OwHLo0n_D|EwRkq}?DpdB=8iY1v?TXge^B!7=jSAA=mS^-T3lYWJYW+k>E?P6 z^kZRoR^d{%07LpKFL0wgJi@=`JJVMYl@fA=zI3!0O3Lz*2A(4J ztg4mo;68C~DL(kbV=+5%=o5j@eBhb*^S}IW$Hk|g*1&lXuf2I$47?S6F^;&>g9~tA z*Je+Z+TYjU!;60+u9VVARXi*CR0@KYow?F3JV|DSRZ`sFy^)*Fn1#7{4X(MOjDc`h zN`6PcAj6AfaET2SUIY*fp=Ty&SbW<*I5B?g7Gc7P2En2?LX+L7EY`ue3(ALk)uClu z4XxgL&Ub&9aG=wtvB4vV#8isJa+Xz$9$xI`* z#b4KMZ^bKbUyawVZpThfi7^lqZk*tDIlxr}Ht*PrK@v31!N8&F9#V7V02?4!kj0-J zIoL!(09d#=x@e_36FSBhULq~1c&IoZe(r;@vb+*kuB`>%AEs^%!i8(9&z)Hv@(hZg z7}s^^iB|-lfD;CDYJ2Pmnwp!HvO177m^6*3VHSGnybyY9P@t_a8On(S1ib~OY!nIa zaw^ZhK8W|cE8+b8ssjx+gu8cAss8*e1-V)5_4g4NK+w^YgmIcD>)$Xv zY(1;L!rwj*$O|vJv~=J59{mCN%>a!)K8;gWSp2+UOY)!HsJZyN9^F>U3!R)+VDXNA z((xppot~b_vkua-4D{0|<_>CqCbclNTseuCGT!e=q~MMj`pGy=_xps;L~Cl;B%R^G zt?EzYGqMw^Up`|ptPJn@p<4j@DMi1cFGnAoQUA@=vB&hQ>OUt{|GiE-CPllZ-g)6k zdafsHq*pL`n+v?DV^Q8*a72&5FZC}xK*y6_yu8=Q&o%Ejge$fHyQZBB1kkDIAP%4J z9JZv9>EI{az|a0ki&|zq7FXIn!DkQXe6J0_2ePFT0PqRV=nttMM)br#j8(k&D_y76 zV?vVwJQMP{_zNF-az?rvivs9-HbRhk_N0K)GdsELIZ#dA1S&DX!oV{p(I~qoCiRY= z%Pzm1oJd+E{w@rZuwPCL<$~7(7k@c@r7-Atd1?|I2*dYi+2A^(aI>+rxDd;WOED|A z^=;aX!cI1qG@5_F;%~_xx?%xY_wpLEA8f$me!YqGGR<_qYxH+B3jgWfd^n50Kk>vF z(OM6J95ca-ES#Y)GZ7=&LqD~pg$9eGGjT?6ZecFYEjD6BW7ehStlmwFwzFz?GqEry z{aSv_d7h`Gb5BHrPqBC*Sox^_nPi`k&dnksZIhdL;7dNca(iRfdOLN&tyojjb9x64 zA9^wa0&v2#F`tv`Eb2F#^RctD8#{Zu@}G^(t<7k4*d&^54Ss@uJn7+A* zC?~i>HGV3h63InGWJ;&kiS6C(SW|y?{nkyvt+>OL!0P9mi{e8DZa@(0l{!=oLWJb0 zFY1lSsVd)nZ7uxj=bYr4;gm13LA*D|#Jvz4mI&NX9VmN}iA+hLPD^#kASv<~9R?RLDqrh47ji}lS;wAy{O$6nmnXvJG= zJ8^lv8`rnGai=x#r>s~&_RU|=3Rx}4eoOdKR^_?-|7Y*NVm(i?JU=Y1_xGl)EMIM_ z&GguvomrB*T#8F_Ed`o|NJ`LyDCj{C)Ptl)36P%kA^{Qv@I`_ML8M*;Q3MT0LJ-Z6 z%bDTq^mO-3Px~&LKJ$8)_v-Wco{0bbXI55qbyv2V&G_HA@%x22apJ^@6DRD?`J-nb z=RV2eue6`1oVNG0bLc1sBtAI2UX z>}T##{n5>XetSNrdU>u>Z}c~$EgYmVyvln{RjD6k?#DwHJnK&$54YMq}8y6$Kw(K11=?F;9>coKbL+`?>r<`@iz5=*WHJ^?N7h;opzIUZkP9|PruRr z%J2Lo^auMu@tA49_Xl5Z-}%mWD;v_PgFD}>D^9kVlIiGt(c4_qEqx@5#No?o6ZZeo zdBx2a=mGMjWK>_Ut=QLFpVDCT6=U&NBmS1&Oy%8k`$*b?#Vg&Q`V}`AxR{bYhUe(P zDffWW>4!6(Ez7i-y!JSg@c#bq{rk^m@%PYgtEb-0qXz_*IOnCe)ACC`JzSaV_q|>0 zjm3Mi@Qdq=cjB0~x4r7~?b}9XnyK>foGf@!UL>i$$S2cC%PdS17Bs@kqz}Ir|5GUf zGB*FUA2fkIWx~7oiNEU=@`QBJ2(5U{3=5yf3?3;Kc|oCqWm)q+(#~e#Hw$OrFHjds zD|ykl+Dg1W!Wi39g{raPNz%r}e;MBO29c|qehSkYbr|o2H%tDeuhF8Hq&-@0aEuPn z>8T!&PfvgpY$E1mv)gi;j5A@S&YOc3_0ZiDCOwE-a*^* z#ILuOA`?BZ=;E)k{KkzJ+8dvGt-WyLdfV9Cs7;BK$8m=GY0473)Rk2Xz< zI?bq`c-V^M8_LU@{J*rc%(!5?{rms^e-!vH-gvov_uV_~&wlV;yLA`YkA9I&c^$r+ zS4kK;%u}}>SaglVgImHDzZl{!8%7@uipgv6h?$$eV^hH9IkH(k=FNDuk!&vC-p#rW zeM!=jz#EJlA30}`&0fG%?kHpVm-mwGT9GO55W&0&^D($|V}5$3Pb1tu+%bWA#y2x*0lea_051&-l{ahD+ zU%%vn=wZ8aZ?~;8hoc3V*xUGsf<#k|o zM#az1p0!tQTx;hjB^xUX?K7|5Xs_S6(zaIS+oR)y_N%}4mG-y(-rsB62S@Gy^B?}l z?Hhmo9bmz9ax9&Z`k$vay((z0e=q3~L8wj)RH|~E%*ezK3}8p-j?v@eGx9!Xz`hcH zufUbj7jO^6Wn(?*l)aY4NumsFNUI>0F|;aQ;^4Cknfu6PKGHf_<3jX-yF5>&#}GCy z4%)HO*$~H0#hu*l^xA&#AlIyHAs|%RZ0HX1(}9z>?Bw^yf(7p$lOHEy<)d`+meB?X z6^5WQu6de%mKjXSHF@hXE z%Q1f9*Y0mO2Q&ty2sad-eH631I}B9czuUg~{kPk<-`dW1cyjR+%GdeaV(K!&rHTb^ zg?ma*m;z7U(cjM7>!($OAKZUX0-id7C{eOC3Pgp73R#^fSCNNDDQgWXth1ssx>tMU zwb$Fb@7)P+y1Oq|#x2c*lh-)VL0-O;#Z=#ymk^@xEaEQTHL8L1O!Jh;l`EHXBKYCn zZabs?k5QPsX4;+M=09jD?|apS3&AS*QS_y+%D>Ou9oHn-hHPW$KuEgEku1Un&BgA*5vYhgJH#mT$k)G6YE{|Eo@ z>(4}?Ovm$&xJkQ)e8bBBKRz{o8BEF53#<8yS<+v2^P_okx*mspJjRbQ)9{lA=EsBZ zqYYipC(gs(_F2ffr!M{uoVs7$gRFgF1wQF&#^bbKncknJS|T{WI~1vF9G)rDybTfpnZS z6F*E~(!V=k8bAj$%i=F(^GPtlp~8o&RYxelf)Q6h8Pru=t#~D<53FkfhW?!FJ;9-_ zq>ku!U1y-%B5+sHA+uATv<{Ff4X))>4~buuIcQ+aGcK7uMiVpdVWB~gDL)@8ed(d~ z-6sdx(nlEh>5{*7WZkAbBW>cC28*ttXLQNXVJbgOcMU4j;|)3+(gQDeL04U}^zG>B zv9;07ozLp@ekXNr>g2DwqdKH)l0hM~jIL~f%s0sOe4JpA_Ld{zH3^bQXa31eA9%UI51OgjPL&PT|)FWpP#n)o0GkZo^HID2(jF!=wF^Nm_GTtzP{GH zMym#}(wx85jduQ&#owX#fCi>;GQR)HZ-hO~h;5~xHsL9ZWsA$NL;jd%ru}>W&wu-w z$ht4RbUF2r76(172kGUw!v$ckZeByL-dIIv-dJhZH^RG~ zZH_kQ$zRcs1HXQP|vGd{WtjLE_@$h5uvwz;tpo|4X9#k;h!(jG8=e*ez4Oqa3p z!lK{Ws$KX_1cN5}?P-@U?NIBHm+!p)F5~Kzw!QPP-Fx^TJmeVAZ<5*O$ES=?)sn~wE|F^R3kjjm2;*+$%$ z;Y3}=j<_FO{4ICF=iN>A{4@Vm&~<(SQl)L}?(a<&-TkK8j^AI$Z=XKP?}&M-cN@Pu z5ALA*t$fJz2N|bY? z1|8)~L=;v&vju0Om2mNN0aGFC1ot+w^#?caW^;{+ixZGf#tR7E^EZAyWBlfMbj*rW zD|JK5bD4U|_1_&IKsLYs>wK#ZrK5sbC5;&rF>r)C+dD@&ZL{s% z)Uk9@$EkKA4g<#vOL8!KhzxiZa_+Ik-@wKM)OdN^n2j}2f0j|1SaV8gw^%n6c=C6R zwx!Gqj}bqck0`hNWEN@v`gM4g)wz;1be=VNr_lKxt^FHqtH$}KNgI8~eC1JLBo!~QJ0LGl>?*UoHNu5o zX== z<+L2uqjiwEBV>E^Csog-)75)zA}U&HlO8womQ!)czru9MHT_SJt$!ad)?X?|-nD*x z#)gl3eO5cL4hW}SygBgZ-3RR(-})Z1;KVQewKv{)z5VWA{!Mf<+RiMzNW1^9{^0BF z+f$3b@{#g7x+6I1m(4xUP5OBwqbKU6pK?EKfO6=%!N*Nt<7!mXX{4cTM%bATga)=< z{p8`!}5)?DNlMC^ovV8{LZB>FG*wcsW=z@(yQoW-+!sve1 zvDSI{%okhF>i3~{#k0O@@mE*5fT!8y?hJdq2{eq);;6rmyqjNlEmLk9>9A5}qKQUu zH%b0anItvd1>Aa0%KXWHxh5RG@Y!LzJB{Hn-?Rq|xeUx^%c6mq9750$4$ z=qc%k=h~IcHS9`TL62UdaphAUoyXJ1bo!ZRod`Ay^+V}hwAKY)ZZr_ZZC(k#(@cH)n zFMPILxq2D>RoxjLpj|s}FFtd#v~9{QE`x7uvpLPLkxoUVK_%WPN2un{E|fa%be0Z3 z_`%!lzxXeHuU)_PLVM|@SK8Zez0D^u1tx3WRn zn`oqk^c=X!6U&T0Y_HY-7T8f>8S7qw3Tj}ns=9m8UM~MlXn5bRk%tp})t^ zvY2oBeK*T0#KFtb4c-=h_`2gVXs@66bxKTZ{fLqH*5M4}zhCmj-z#%F5Ep`j_u|T0 zc6dHOnewEpiq-uG+jPR`8Fbdbp?2HP!DtfK4$9qvTWibh(a`~e>9ux!bEAFnGjFut z{Y$^mX3vfxertc{@BY2Eyt>i;lmFj;-u~bJ!GGLtKis9WU1AXT2*vuS`3+ci?7M^E zn97sIoJ>_1pq;@GRFD?GCDnBgY_DBj&k=y#p6z>B{MX1*D8UOO7a$Hg!!-`xh%OWgdvlZ$2d z@88d^O7l=b@_G-RQigOI5XcXV%R9LuKwQArfsTb%36D~4Bec%_ugu6 zF+hFm=I!?G?Y*{rNEp1wm`-Wc5Peznx6UbaZ~TQ)El`(oZYSoBSnJB9dwXZ_miOk@ zK*kTco7PDc(@AsdV3AHVZGuF0@b&$%QsV3!W@fzRZ9k{O4-U`T&h|ruBDq_~gvleO zaI=EEyT7*!K8xW4m3z6;MPCQf?(mm)4xrUTzo!e`T9@VOalwUG zC*z?p?Ji2cuJ2geMmk2)%M;r3bCmZKDHD&YkyA%9HA36aSbivnaAEeib zi?}ZI5~t$nQm;HGJ$AU2w(8o&V+T85{nPI}6NPf3SpB1Ho*Y(n9S*QyYH0g{=$yl z)4erjr>Ixnm&~vCfyeMGbCGh|Utjw%`*Rn6mE|s!*xx<8cefp&n<&>^>~sKNKO_9~ zqrTHO3vMzXF%0X#VH%GtXc!SMW&0R(O`F6sPW?@uD?fFrN@IVi5l;1c)CBPBIYF4h zV;CO;=kY8jX-2qug?Ys!z=!hB)htQZX{f(PEr)WPG z8!L=|8Xx+Lxs3nf>3>c63?q*6LD?GIkN2vV(i_ot+|0?q-K%Z)_7B_6p4S-G=RjQi zmA}-Vq@DUwO?+2=E^YuK^;P+RO=zZ$Y?Y`iV)_`ug*(fw8FU;p58TvA(K|H8Sh|8+ z17+iBve{8xkvg|7T?BNDrQT_sOLObava3TGr%s11XTj0azru5qr?gGmSz;iW#ovX; z7Jn^p(YorF=qbPM<0hf?6vtF@Lr_i`1^$yH_5#4%84%P zqu2NH;%wVoS!h=`m)i@M*4j%~R&W{jZZ4sRFSM04uVsY4=g%3Rx=Vhs&AZTs&8hp? z*}P{HE|uwqMkkv*Wp?HAm9~4h4<0M+664-S(Cb@2e7D_xu-6XJbG^3Fv5Y#k->$NV z#W$skI+5WR)8CH z+>smLDXu(QAm>SrJn?aQ*lygo8rc)M+u>T+l-v5zfP!-Xj-@jfAfDo#fE0zQAUq2- zHSQ%h{9JfpERLLd>-PQj{)7Egt0glJI52uobRXeZ?s}{^82zmGOd#S}<70t9CFtU9 zn{KEmxmz`6z4O=Oo51N~=Pcw!Yf&%alD_hBObqYShO?32`YDxTzO-Nq&`Y1)kzrLI&z5}*qY&OsJz|xW&(w1=5jm+4S!!BqF$GR<1Hk(t|Cuc7H?lx~xuuY2JBkOdQ z=NUOhm!gY5^>^?7!}h5+-e~Kam!l`FdHphZ%!60ScNgS{3*B67ISm}}Qa=Mfd8J&+ zfwk;_o|M;lyjln~XWVmWLVDY#+z^>-KOjv>FD!3FJ4fcv(bk|+n^m@g+xf|HJ4YTt zBv-*}@%Mm!Wq&st?44h66Xkv6)I%49N#h*qq4O{h$xrhwQ9kE|LMz;QuJ?Q!8+={z z@(O+F=seJ+t;_BD)obnYr7N_d6?9Q$klz@uwq5LC`{X@-^{nxKPAprOmd_&M`qMA- zeCoWG8(PNt>tW^Z9GbMNxu%*QG)`YA7MAro^-IR)Egq3=Smi`qSqB_JKKNSCKI2;N zEAXXyWLsQmJ9L`geCxgT%^$ptoVRak?YF-2X8Y~m`Zd}IvY9sGDZ1bL{Xc2n`u4Yz zr?Nctio6zP+5mY*&XZ=zjeWE;x^CnQQkA@woLLA)w@~NPy18#--MPO7c<3a&=EAVo zdLJJjrtJ0+&gqW1=*S`LnA?@Fh*o8@Eq7XY5NNjB8Sqj+1c-zI6HKSy(@g0g7jJnBn^l@W&u%#X7B3$J455CFFEY-pjdeu^M6Q{163 zwTye3jb^jN%|@-BI;ZlDjo+lC@Mi4UNp6MlMj89jE1ODVTazzW z*H(Eqpjwo9DAjV}9NpCgH5r5=g$6!L+x!omd?Ww}+uTH00s2H?&EjXgRCnmVxM#+_O4aShM*EIS02M(f_$&X@PPrF&4dj=N|FVt&oe#v*-uZL*ioPjnNO<7D``{XY{iE zc=s94lJepKy)w2f8rH@Z_$54A{jxaPKgu%FV=ZfxRhOw2Qb?igQ5K+Cr}&=p(q@c@|Dho z0(ymo3tb8h2buYP4jTN%@@!k4Ic=}LaJjw0fMn<4{Z!Q7`S1RV?H~NNUv2-F|NFnw z{=px9HLx9!KHS|S&;1N?=})7qxRVqfO@)&fe>A!sRlZ0yUCNnNtlIoXy9p0&0i815O$vxOk-oJ!$yj z{_dl8^Ui*IxJN#oC_SIe71>_9tU~2I<=#8)LY^PvHXoW$JAz&ttIKUog@9UIMtE#6 z7)?6>Cs|z+CD;bm8%Qk1hT#BMMa~H%1+CX%=L)068z%3NrcW&RNBSpy3SoUdf z-VHBpB4EHrGABQuZC=3E4eOI{2{9X)%uN`!=ydV^n14@OapbLP6k;CiZCv2%mBb1? z1!M-l-KyBQJ8cmj^XR^lAqr3xP9$V=y>)A+ z-F$Gs;0=LBW~X!vr_|R8`JIH1QV6Vg^v0Z`(^Xh*-ba245O>Z{~j>u=9a?rlFAGC+afd>!nwfpz) z#_sJrXnWiDakUR}9sE9am$xx)@P<2eH}(xb=uH@Ze1#$;GUG|F7BWWH3U-07fq4{D68o`C4FOSEcPCgwsZjY-zS7ok2me(SV z%}<{Coda1_Q%^1$Cs?aY`D{7(7ne$ z-2`1_@Mi~(>DcyiYXYmoe$rH2|A|=-Cv6RMrCS0gVZzM9OAprw-+09%{oVYNz8k~D z^CF9cP3ouH3JbIj!|;k@f?D+H@7)Bf|9YB{R%@CMGYRgt(#CsY9)mMw;?M7?M(+W% z+b7e1QWHLrke$AMC)HEdZlJidve;g}yxQKlzR^B?W39dN!b-bxnX&68LFFBlp zehkFsR~Fjr>Oz~}SZ?#{OKq0-85f3^=j!z3DrpvgjlT=Tuf6diV->;}1KhZNt=+hB zjj`rQyOk@St(%3KSb;a4>~a(&3p;K-W=!owjHiGW8MD3f?mNxz1v}aD;J!P`4^oHL zq8kLPcTbf#9 zCDM|TSJHO4F~FH+>@rUn!zr@lp8$Lo7suq{Njw9byb?^3J0>(D#z}T3kro*Dc_rKm z|OIqUrd_r}8S_i?H$ynt7gQ?B+zUt<>>c zO(az;sjCr}oRkwc+?38Zl2Vtyv{QchPdu&jkwU6j3m3bA2pwu1?c|gB5g&SIY#16s zTgSfg!opHEg18WnMFG-CgIp&#=l9DPClkjp@(WktH^y_d!DEj43{t_>;-?OS45fiy zg(GMrd?GgFiv)HFB9d&8H-f*=fnh0aRVk+tbg`K8cy4q=W#MuS}99h09Ky3 z!E7;dh48dj`>Knywrk7hYwCjj)p>{%+$zEyx`MB^1$q74ewqGQ*`<-^jUfMnfIhM5 zPx5?W#+z9rW8+wW{;pFxfk7pM(*HRZ0Z+`#_^njJ@Y2eRwq57s?(OWh-~Z~@+MVqk zWd3p%OWk;qiD}AZ8=;WJpQ$_Zt1>DJvmkAm)ibcB^9p4rvz7Bse%Io!y0QzG&W{k+ zw4@unV!z<#e(mwWemnJcG;dAY-)koa2kns?jGV+Lp4U4k9&tRKcHpf9`=pKC3;xcb zdf>y&{Vwz=Cp_fx?)x{}-TM!kx1!`ml)l;DIUPUm=X|SkoV$DE4WBPTllAqD<~ND$ zpX3z@KGDHKi&R9t$FIWW4a=6rTHGwQIO(rn{A=!L+S)#fF4bPrX7VoV(RPwUJ>fr| zHI;jrh>QvM6wj2Od{Ss-agktgs`V_;-%o5 zfQRsRJx+&(x587lN8SON4L!uym4}lwiy%HqW#axfZW7R8|dkO{zWECOyQRQ;5q4!@sMm!x>Xm$LNnY!-ZGuG zQ*L^CDlLn8Sm$m-XX_C+X{TsZeC!kb6K)oeLv-B^b(F#M{n^c%u5UQDaY0ZWLD~ID z%oJ96mKW4HavKr4M&^{EgKgB3TGq_p<6At;Q_5hw^g&pnU2*bmxp+$(F}^lFMW03f zk!{7Fjz{?_z994?7`{!P(QWBWgNI$)*~>M|_aELv&Y>$4&5d%ilt(zyZ5O%u(2X(M z+d0v@!}B)J4<0-q?fu+j`_@};x3}JYr`^4CH}mPrQ$M%z_B(I2d-rd*wT-3r`8Pk? zzWC+Ow-;Z!o|{#@pVcd%3Dz;0uys9EEx!4be6$}(}~-WoRvzxrbPB>EQ{BDqD@Vl7La zyE`#Nt5OQTm-h+#^E6YK{^UkM=AGj1D$e)U&Sq&iULmYP;m&2Rnp)0o8LF~*Em^Lk zliBUSJ)L)Oio!k9e&utow_knpjrLo=`UM8W4P|7f{n~H;Zu>X?t$(Ne+yCx=)V}te z_uByj(d0oUHGs9z$WRVay_ejIf`MZpGEsD`fa-*GWpd%1=X*vAODk>d(pK9=@$q`1 zLlhi$U~liD7*Y9NdFu+jOb{VNgZ0}_I4PIAl%ujM_-uqUh7x?$S;8_|^wLHVmciz| zCw~C~`i+Q__JjBCwFmphZFXt3Jz&6aN&|Eu)^CwrzH%*e_B+7t>UY7+>ufjIS98^l z!?pFbmF$Qn2s|k>xY}dL&??grn$<$m5GIYGTh|@k4J?DZsJgJS1k{=KaCg7Gb@Ntx zKi^d*5_m&})HMJe>+s^@p&QGyG`FL3&~AgZG9t2gmX_02ziBJJ6Q$o58yf;aTa6oG z0X^K^mQxSza&`w?b|kH|^^LXMsek42rFQk|<@O?j&zE0(p}q3*i+T4O)Eiq{?Hm~2 z{lQ!95R%DKh1`6~c_I(NUn>48;}W=r$I?$>Py(;qQp`Ph>twZ8bLkJXq8B`;a8@uo z0pSi#G72xdgUI$`{!|C?6;O8m@XFjG{t8pl%P-W0*Nm0malkFg(ng+}X$S7&M45M2 zi1~Y}*J71&%o7O|m|makj#m}_Iw@TO(S=$UcT3r)9W&sqQ@<|clFl|^IPbMn)NgAa zm#bfQvmi_vj^HU5gtHKge{DQ4FD&%Tj$5rQ1;3o`1)iHO4i3FK&2J~{(D_!!>$e{t z-oG3B;K7~t;QpO@=Xu-bd%oj;?>3$CElU2}JU7qHbMxFhD>L*5J3qS=`@_fGiZkL( zyHVunf3(xjBYxTHt7_7SFx_D%`SgrFwz)`Ke?Mk=@#&AzNz$`_JX3M`pCsju=lq}Y zAAaTN$AfFi%K1y&e72_~?BZ43DJ4SQc#b0smsl?=h+vfSKex za0vVw0L41c!m5J=F7*_B!#YmgCQ;n7qz|6zE#3O8O>S8K%*UipF###8sh7|s`CVAc z2s(rgNVT*QJp_Hm!KVvn>SPtS@Gn}B3LK>8FoRCXuk-C=hS!l^Q-jJ%Ul4;#`S~{$ zc43UueR`be!oDQvBKDwH;tY$=2k@FQ#;ADZ2JSziCR7SP+FWXaX@xPxwT;F0>b14@ z`t>#3<#u&zp{=YkmchE%JL9HS#x|~X&AB+sIKrXjFxJ-`ThWfn+-^6sLe-$!$@ z%o~7?j}I8ft+f}fUn9kAd+*j=#(c+_*l}Fo=?PD3lSSImA-eb>V^kNDS5{Zs+UgoQ z@O^Y;#)F%inb6wZ+fSLsWH{OBK9FY_3j$P75 zs}0LCUQwq>`_9jJ@)J-9m;bULnD%|q4(dup5(W_dz6ayfMEq)VZ`rYl*hNe?Uaze! zx3#{>mJlL$xzf|d@M2Ze_1$`QTF}NlrFJZB60wYBf7}c}Qzm6QXDo}1O}QvPt|f;P z2*dL8S-NU#@m3mJD09&*aOPj*H%h^{FsGxzH}!<8+}76OY|%{UMN{MOmPy1V#*&`= zU(Tr~7k&Nqx8rW>*$LWA2ro*{g-rg*<1W^@FjUvt3A6HvJV;rSWv?b_Tryo_S+kL# z<7?eI;g`jR!E4qzuJz=Y__dd>x9g0_tsJRc@|gH3lR5ZqUKgQ-3$y~)(1N(uYjI4~ znK502N+>SS+8GgyKg!|wImWSYm)Vsc|1F@r?s%7RH>{UA9w*QDUF@RB*%(b<>*vIX z3T)HSe;m3Y+C?h*Vbj5%>!e+RP78BRG9S0w5BIXsXdb_7@b0CRnoAIS|2yWUc!dqF zG%lKtLOdIjK10A}9M^|o;#rR$VygXzVri4kwfMb4`KuP0iq=|Th3-%G#gseWpyk={ zp#uglP4_z`j^6>aFHXJ&5XI+7f6CuTGoAFNt zai?+q%=)=W*}nPBZ?>;}?Q8Ap*gyKCKWe}Cd%xHIOYEO~?N8dRTep+9@Vo$~Kv}=y z^!@kWZ|}VGP8LR#Ew*(JK}gdr`v@UUWI+Y_WW?lfM$3s=ysgrqhDFel6Op{t;Fh%E^3I+9`$ke?p^RM(8dlA zO{c@e2YAsdwV3gkHv~cC>fk}V#5qADtvrgba&9>Bu!bfJtZ{O(zWZw~>SOqn8L&0_ z5BOz$E?g6qSenXc8qQM<(MGw;(PKRSbj&zaI>~2}7k+k3^;GosA*Lcu>K5zsgikx~ zRvevrj_E*#PqKf)=rzV=qu#PW1wKXF4nuy{DnF8cjplf)lt3^$&-CVeaYjVEQzI{kdg zT>y#(ML}(a%lpdp?sk4wf3hy!^x{FOEa={UkegbZYxYwo${feEIY@>T70c(mv}tyC zx7+r^2RR|?y3Bj;zuUg|z3;Z~fB$>P$M@R~;a=_h=}&*Uec=mlwpU(xB{#X&=Q(PV zW%``nKEW2eC}avSI6>2&@aq(dk-x@sZhr!%#=fNV;?`~<$2Ye&+l?1r3_rP%W@BSB za@G1WUzc<=(#O2ik8SJT93yWEPoDRNjY0G3=gpz|c>7OXc_V%kI#+qpAM&f)$DUaH zg)hbdwSrAr;gQsJ9M=ympJ~O%G`Y!)IMzqX0*vUJfjZ2f&d96svptwbS)Fv`nY<(8 z3hzJYY^-m#{k;Q- z#QVJ0+d_ad2W?)rw49yIo=%W`H&A{rU)s#~cZdY%o@CPM>}ansrfzH4vNu`(u=I#%KfL9say0?ve*!B)l$QW6XB#qJ&oXL!G+epTa zD0w?d3&ctXr;r;=Kjlta9qBc(`i&oeCPExK*!aheHy4)eaMI}r!^S8M9WU#{1zTio zb`LFx6Aa;%$u`t?QCx4{IZXc66aZpX=%q;s7DL?G2`uO?4_IEqH9m{43b6v#osT{{ zs9#u|<=NBY2stq!jkFg_2b>NbosjT4iL*xz3}>k~C&`5iD)9L1%sfI%v=)K65TTsO z8*tOw!HR>OfE|<_S}EV;Cm?7cALM!@p1n3u)H9eM-0!`JOHRVjBgmtq@|`Xh zg!dW9>}{iHV=3njov^2Uw_Ox|&=-aK0RdmypTh9Z|g}-k6hoA5M^HKjEUg)TE zp%-BD4NeCygq0p-0^Q_7R$Z+IO{J4u44|Gg z#v?_ZYj7wme}#9F47lS#_h}~hb$tEd7VoG#$ydcw#WTbQOz9V0cN_dg*>gHiIFtBA z4^5R_yo(meC-KZRzWG1Qplc?8F&WGPBWX>ObUiF|Q`-%46Zrg93?4!q(uY3Kb;L;| zO(#>~SujF}-o~D0l7CNL@T5xj_(#lG>Kec^mcya~&lwME3DDLe zSv~ttc~_H(zDo+fKfl~wx^}63_SF|M1`oW-pwcCmdhSm>v@jSG@8VYZk-s!GKDMYe zsR80M_Jn6@d|Qx)OqTCWKaryegg=m#j#~|L0p0xe4v#a=rNF5{!@VueO!Hk?2CxSQ zZjNSbPyAKNeraL0EziNPv_Ll${qW{au7aMOU2N;{?@O0f+X7*^{Yo7C;ifM-^SgA# z&!zKRaOtx$m7}gSsl54%jpx%$Dy48Tb>@(e74lhqW}vs@L_NYK&)E1A6L9U$_ICUFpZ|G#|L)zKNlN;E3Z{I0PjU! zD@#p5I{!v`;%4p>I!_i6oUa-$_Gl_9Cwn*9!!|vl7vo2cL z52H(hpNoQ8<+$Ms3yTweOs;s2_L+3}4I8}6;U92QVNc-6tF>c0SVrH=X=%!oE4aHY z`5cI$LHXGh^U)(Ls*V?O`z+BpuPS5_R7n(=)AYT8@cRe zpj)?YqC0v5c`jpwV#V{|=lpunrxs~lOR)Z^oyZc?$Wzw!7-O5Z5EUCJ4lW~}Wr_?Y zUSu0EVt{Qrt=~*8*=0KG$oiX2pJUt5#Hr_{oPz$Zu1cBn}7OM zD($HKH-Gqt?Z5iNf7s9}+WFE(d$h3Lj?NsM(rAIXODC(4^P4~BA=7z9a!si83Z~{?Uf~;W!@J0lyJ6jqafK>O>F}O zVI1CNa_Ww<*C~h+=AO#*>T0h;a3J|$XTN>_t#{ka+jp~2n1w{G11!^@S?&vCd2OKb zh)x=h9XyV=1#<;Va;;Y2*sTYd++QIHfI*u}(A zsbXN(pPlr18(|*I!7+6NzBc@L0Z$4Are)AiUJE`vcdL1;PXdvcu|%Ho&7D``xZ6YuyHUKrA4pbvs2l&t5|;NW7j!Zyk- z@f2hkR8gmct{O{fnq%t}{-}YcTp_MiE+<&TS)3f&<$87AJQ1A}COL#rZ>$eQc zA}$HWcVp!Lf~%5a`pUCJDP;vd-tmtmo;1vYbT&2kZC?g34ru7u{2t`?!~5-_Cxhdb z-PwKsl;`GI89Crd`xn#vqf^pfcJrfa>PN@;QRb6F_|fKPk;k(#N@@Fs^bT_I z*K`;cZpEwT{Le35JyPQErw&yEVQo!D*8;FQkb|g-t6P{~47l3`} z2#Qg!sKNimgp|(?C?^B*=y~cerSp|u*Io3Blvi7SlRTd^!L$A*ZYEabmx-l3h6^Kb z&`BJxptovkfY`0Nh3NxBctwjr!-2=3(PQxQuZ(FOTpFgajz-$agwBXBTz`ajNZlBx z`vh&`07s+mB;Wr30yi!CQuHLt^|($x%xHVDPvZ2Cnn6dEd>PX%FSbi-i|ysjmGtBLz79dc*69!K>*mKt}M3a|OSCSCj*0DjZH_P~nbc~Bm(DUoNdv5Ke zt{Ds5zICf@Y_8J=TJt2;pMU?YcK6{Pdh>Z(TAF9r>nC02qLVvO@6AzW;uy+_9P9V( zciwJSu3X6p1h1kyJ~<+_b!t=qXECqyA8D=Y;(x~?osUEuK5*>hr*WK+G|%yUGi9$O z9sChiGfiHw6kk7Db6yPz4!|^?{9T5p1Ufcm+>)_i@qVTCS(%_)DI(*LA<79CUEOT$ z*v`2Hhzp)ImVkqkukcOkIBl79ezV!{En6qKQOLNASNj%PakHCVU>F-)N#G% zE5v%<1zH2Kj){DhJn6IahCdzjdn(O0_S=ZW5uzvR)!!qP!LFBv_X`aL}KR7c5XO>i*(QI25=%OWy3 zgrEGw^-;K~E5hZU%F9~7;4i(dZLGF0zwr{T--_$>cTOn3M5|1E?lvAh?%1HCe_?89 zkJZ!3SLPag<7vzq7st;?reO?SeNU*34|PBvaN@iR^|mN2aQD1{%Q1M*M|wGqcP_w% zb|;e$Gil0LoAfKB^D6h{rP;OyEyU-}?m>I^?oQh|^xJrk+NJfSwzVRBM#}K6ZBOKa zqw*Lm#gpvum!qDI8EyTe?1!4*l7G~z6V9HB^7K-#Yi#OI+~rxzCho$uOvtX9M6Nj! z5i+qH(MBWPJVLiLqd)B|?X4+H4%qz|Aw`Z&!fW6j<4 zI2dtAyRa}FvzWswA+;SN4#*o()8VT-_7PBZx49k`t^40n&0ic)UI8>)?R$^#daOn%}B<*efxG6 zp1qRO&-fXBLzhhZK1!$=gbj3VTWJnIPvqj z)3y6)iytfBSmm;ftFntRyQ<@!ak!&%Na}y`HZcVc7oK!}%Uken-nyN|q!Cqc@~=Ep z8CIsg>6LK)6_0hdhslST&-8`A3;M{H_`|D_^W7@zO)FlS^ey}bo%ByRjD#ttzi3hz z9oq|WdABJH+%y-l&7<;}g78!mu))a(|0>JS+cHEI<~F^!s^w+!$Okr(-}QYeu?eeZc+_e5$rEPw?l!^J(}N(6SZg z{4X*Hd88S#^CzYC*xM{F-fNEbw56kG{Y+{B^y$yC(SkdKd58+LW|FA&yt();& zu2J07tZu4~Q*`R>!f;*eWDJQl6*1zD=h%!vJwXcY0k6*D=9VRB?s`cb`13{uZ`X7| z_|9z)6FHy!ulKg(lJ8W(?E?DaJ9+S+=%E*h4*@XrW^gzFvZUmKJg!Z{uPr{ zd6IYO(Fq)y8hMaY{Nnl^KjUD#9wGc``|~tUaNtj7tkhkU4;zqIB)bDrVnZV`ILi*l zt(ArL%Js`_oyKvrM+3Tlr=1<|H(vAc?k$vI2i<%u^+an;h{?Dj zs(|;@s=EUj%uojkpWFBM+ItAZy_2(c1U%2dX3^!UY_f3ViN1IbW`Ee`9GG* zH>lEKU7%9&hgK2;jH2N9Rhn#EjH|9z@6m$*re2bPS7Ks%KWu;O^=F<=Ojr+ws$}DT zvy;A%7OR`wi3f$TJ&uVm8MNruEAfeCJyCC!61>C*9Yve(2xY;;$*(DkPBIw)B@q^V zCL6v+28LlO?}GiLEmMdWF1=h9q#K{jClmer3@P0~J-GBQzuA}@Pq5KFh*vy2m0$3w zno&oZ&@1tsip~0Gj zjyurldb^6Qg!U?Jqiahi;#t1ln(~~}iwW!5B%i05r}=+a+%jVMaqQ2}sBgQlIMX)J zrC;1wYOh^cY}YT(x7BsVKweTc5A7s$1|ajPkLaR~>+n0ry4XACH@z6gdd;(SdWs(E z^`+|1%PY&xjkW8`EA4Q1x6Lz-^yKB*`f_`)v(x_DuYW5GP2QO0m~aN2*gEm^ELr%4 z&Wj6+ZGCMWcfP%M>%F$Iv5~fR^Y(4Vr@LwI@}raBRwSGsTr*L|pJ63iYeL2i+m>H` zskU1a$<{{}e{Cox4Xmmq|A!rUBBcg@_B3=ZhjloxCmp5Jmi2@8tW;p1mFYC6)AazPKNPTdDU|O5tviu8S53F)ir^O zDgPp_eBjvKg-FlmufBse-!<3;xHZ1?Ca&7>qyKqMZNGkFvwi;MtLe9-gru>^(iTiB z$DZv4&lTVJZC|-nKXOhQDULLYzrgGlhpdd=K;F&|Ss&K9V^3n?k|J@FEU77sA+1pE)aNS7s^2;x` zOP4Qau4!X)GZXEW-9-c!7yMk>l`EIqwX0XN;QQ)pueMiTeWhK-&w01Z$6=KRneVd= zrd;wv)z>I%)gR@>PW=0?*ILS08~#e-j>0yE<&E_Xw@}SntdQ(W^)Iw9{ME0#O?1J<<=EwkU0U+Rl?RtQ+Ol` z{wb&3xZ`PCWrc?wb=9urS0mal)fy3X-TO7+4B1n5$h(p~;!=yhC4;o42~UYXvfREU z{Ed%st!tkFlkz*SZ{8Z~zy)=!eV}oME}-d7NT}5$Pu>P@!cP9(YWyEN@qb)q8m-3S z(#q#f^GP{3#5QXSSLfH|a^q!s`qWqqvb=&aO+(yRnrSaz*=R3bT5Z?Xm)hl( zxprx}c4E#u5M&U)IPc={BL@1jZ4(Asqw*F|;Af5)U^~VJo{OaU2JFl{pH-8*V4tDEhC-;FsrM?ft{7zyj4-z28-xvOu<-KOq7@wy?(xCB1S zE(+q>WDd_}+DThLNnLCwGYjqH+;1~8cm?S-B41jD7U;RNF2h`2??`*essjG)4Pz1PVz|Df5vtw8{%DX!nv?8n}3+xf$uQH*mb9MN9 z7RqX=zldn!+GrH6p3-%IWZlm5zNi%jk;bHF1ShTwzzQjML@U5NVeH`8-eQhK^Hfp^ z;YE}+1Q_^!>xb{R+q(?j;J<@2cb$MFb_V?CpsjWuJ97$u=np^m-6X_b%{>!cWm5rZ z^L7E%Qn({s#ms*El=?*sM#x#`UbB5j-MY!(kwE5_!G(GOn1hI7Bo~rTDFeI#A!lb4 zv^7XEw?|%5J_mmA@*M8cB6NU%N@;VWz+BruGM$?gNCgutEv#fh=a@EoI&<9SX%~ld z*pFtH7{Hi6_=BHKz%qF1`-A};AmC+jH^gOrP^MO5>2zvB`oii5l_0y5Na9lV6r3LE zp7||hI;vAoufsdIph5YlX~O(ow}kbCv-ABfqSv?i=oqy4Kcan{xmXUp9MF3*UfR1M zBD-3#xz@aQ7|+df^V~c)&&|g(H7t7E(lezmusd-8mVO#P`#4o(#Bg~KU|*=eu6~A% ziI|~SKRzI+XZ@Ts%(vhHn*R8aiOt~%oxrP;ypGO=lNI2gben~FnW4t~hAYD81>#f# zldhy2A3SOx;B)>bY&stQ^~iH#h-)8cm?m)?wBV+E{AwU%SW?FgLZnL`#=%Q^(&@!N z6Dk5!AM9~_cY72n50;)3cY*$H5qR2p%D$M%12f|fpyZ${()`Y*zikurd$W5qfV`ZEI>nx=!y7Ces3K) zfuD}hHIAVTDp)%_QEw0)`iOBr$VFgzRJ_OO3kQDqME@WOxq9ldz!KAAJ+=# z1F#FsQ;ZDqY>ad_uT|>i#r662%B9(Mee;|#BNT>oU{}<(ZswP$vnBjJ;h+vmeK00E zlemlv&Z#S9nB%x}bkJERHMFKv$4B9Hfx+)CI+nA({nXC)fACJbeQy_#i*0#zmAZf@ z;2Ce@Id(&*`IFA?2d}KIv^)3iq1Vsmrl(tXZ)UX^fYoXLvc0 zD7X52;)SzlFSHqCtMpam>g%LbWE#G){L3T}koSn4(0m?*E4=nrJMcVY=Q>=J+!c?`fBWk$2({eM|%mT2#p^7waPOA@neX zv=Bd@DWi*&2(83%K{=D}$}k4;o`B2(7|$*^DnoPP7oJ;MSZ<5i$j!LdIflr8a%4NJD=n~ypz|Wzm(G7H`_q<5YkMXj90Nn zebyVXfo=OqJK$$KO$cr+4kaqCaq1=QBEqQBxcKh%>j$)B`A1CLFtqOtStlpRUHEL3 zdZ6s-{^*D3f!o^hd|QP{{66&t^xs@rXuC&`+V|eyZo70ib0D>~y3n?kTsZ!~n_>U} z|MW>jK~%QAD${N6;AKI{OT6q~gUmBBrL%lAJZV}K@9{xMSAQ4qbJ7WZs#E6jVYN-e zrDHARLMv&CmFlJ2Ssr<#>du!D-?z%qzPuI)<*oRr1e(sakallAcwnP93M2304r~}u zR~YdV2Jwudo3NyxOPS0%&()))TeS1;JhUWTl!%;o&p+4~t*bd-wM_e)6UHi$R$xpYPxb%`@@Mo2Pki-?`J? z`r!|A9qHXWxAN^@Y3U&pZ-dCmUu<3VTz!i3BjW&xeby@dj)x+KO!8eELPz}Ss(B~f z7xUfv&CQK=>GGwvwYAmOH`a5#sC|<%D)V~~&2$17^~C?lZ{pX>UEe6Jae(b0u?W*| ze82P*d@mM&i*}iR)Ar{JTH<1LhaVs(?gx#ymKASN5B*byZYGcQAf9J1h4ZD`JG;3$ zdm6mq%0J)bY0GTN0y%J^--W+B%cqXBVN%(PU-zD%G58>Lk~s20#g74G;@HQMdhk=q zVzA+P!U(^^8pbDW@Bn5G*5FpY#>WbTjD}k>bjs-cr0ISs^9Rh+{62}P()!<46x*|? zvOaFB@6*=1af^qlJr<7^KZ)yOW#Bn+f!@h;@Iw&>G0I&Fz?50p)!`5+a4)WXuJ>UqN^V-ApUpx!@Jw0wSDXQ3nAB&*!ty+s zQ!ZX`Oy!N7ZnBfsxji;vj)A46R{HS|SWB+Epj%ZrY!9|CWYZ(BNj__rFKx6pUVpW{ z{>Ce9V|^7lb&T#=i@%~E7Q;x78e>&mM32-4=Q5eMNLq37z5F#PsqfvMA``{WGHh?} zBEwg~=Ss!|Ud{i*w|+ASJyavBGMl!v9OK_nlG29z(9_Po( z&$d+f6i&sDBk#&{#EtRM_u&xwL{L_D}UA=laJ1MSR-)dj_;uoVZxJc)>YfE6jjK`O&1)W%2M!?v??2`Z8`wy~v(4CK>=Y&=UiCD{TyvOK6 zITfOocS1uOP#TeqmMo^;(^*JU(+mqN!(w|}{T-C(N_pYf=Db2}5u4qJ2<`~}g+&D7 ze*4aMzOU|;4qynQC(U%@PebqVrekN|kB59@C#dk(*ij6)LxBjd*-oH;I&1uaoM(lH zWz|H{@Gl5fJYkr#9bpFb{KUt>xA2O7vw2qddo6<#0uE%O98=#;D7io%I+33OU7W?u zaKnac)@Et7=Q*grGvFgmdW6>9lKq9{y=bRvVx#xAMxME9(M<+Ci<@~AeH=)4T9Ixj zQbj-8>4hy?4hv0<;~+BW%rK;UZl0T;u_?ZP+&*jb$@7T3p0?fp!aNE8gE2nJB*hbX ze9$}zU;DE)PvZEq$KaEjpE}M@t-E2!9eJy~SH@5L{I49InBiCc>C=d>te=EU?9_ka z+1FM7d(o#(n~7h6`NcOumw&nw8&4m)t5@kJ>M}Fvx5+@KNfNqYg``mKBk=srDNe@@?zHO+88 zU__xe1ef4=4)U;WM zu2g~jVYvN8G}3X2vC^g0g?4>wv0dJDEQD^n2u-p%Rky}7($6+1ZO-M{y+%`Gms``g=XVSc%t9>8C`;H@^m@y&9wRrxOvaJ- z3V->+G|Jzk$he7M_(Ut8)aII+1P&~$yq57?4 z_==Uh8Ap{@k`zp%I}R*3k|KIO^p{Sh^BWNu{Bz9j0$etPFD;NK?T5DRM4qR93p24S zYeJI7)k-__7(TXs5do31MB;CKxf6o0DzBz!r5m0xocJlPWs^t1*SsBTT8@?F z#rBz(ueUF~{xV}&;sRj;uRrJr)d%^Z@TfjuEUam=smDlpE#4mT&P~XkoUh;tE4e3c znlC@nJ9Qa+g$q4A4VkeqNnHqZL%QQ-+m-Q^!8JGI=IhqhmuK7hs<(EvY{a+xe$s3M z-t%_2^~L$zc;^Y(oA-Cxo$W(#a6|T7dtqYV&I{kTqFr8yRyS8p}8k${3%x zwGn~TmLI~~j%*{o7k#8lPsd+j3+2;J#$!}qb z|G0HdKC?`=9XDyrEVQ}jFLm!;de?q5h90JymkH&FfDVu!s(}Va$!wXZJA^Jh0;9c{g8q4Uj^N7L@ zKS2-E7}xwQmt?3isi#($2!v+fYrf%q!va`bt8EyjY#z@=Yb@>Zg3eFaiJzdx^W%Qc z)L5Pr23~)A zhj(qmxLNoWp6$Jd%Ln1Fo=?Fq-VPl6lZ1EqeAK0^YyO}Te34d7f6m;ksx)~ckgM8$< zd-bqsQ|nRcDF(Xu>n0xg*&7<(eDm||SAONo?RS3Xx7(*b{YEzE$jg2QULy_pOTTCR zXyhMH5gTBAWqp9U9rAR@8sm(9%yO2zsrRClu!|2oxhsqztF(bhdate4m`2{Hyw20- z_$_&PO047qujoEHJcQp5!ENZ4w%frA5;EX;uXa;>svaWT%4e876W=lyFUoVp-x|Yx zE*z+Rqgy5t4Jf{=XJ_MV>eBkEINFN;i({S%HamOnAd@&Qs4gPN9-;Ko;n6r=y>X@e z^MCiBZTq|T+wI#ov+H(kV>8FmUwGkqTZ0KDs^6lJpo=gqV__6yIzG@_!rfvpe3dkt zxSn))bV%n3PkIRP_<&CT;HaI+m?vj#1xC2Cwb{1s-EH^p-f24zALLs|esev9C2-E*)f5sj-nW@ zxT6H*DR`cG)Darl5oZzDaP#9&CUrN43%h>vcW3t)yk^_o2ixr&rkY<`ZEwGKtGT-z z@zb`pE@hIz>!ama^Q=Wx@hR($ZwHDh>F&m~0p@!o;Ao~YdtJ4w&|#pGfy+{^j+WP@ zgjeynV^Ae$X?YEIuI)2e%mfECS2^1Shr7^w#~tY4Fhc`AA-_`rfWuHy%39>U3yQM1 zo2T4vUD&i7Jv_Tip@~923&HqD`Oy-t5|#MLqdE)YN#D8}KmkmiDy2M}*#R(czIFFO zyLr0?0Ulrp1AK%T0z)AY#YfBgNHyr?Zc7zXaSX2DlT`9px*YyT2q{QS8Lu_LtI>$a^N{qOZQNKguX-mFc13Q``%qj4oUK;CL>#M=_CqaqFS* z;-3)6tNIgr!HWUYFQzH9AE#%2!@vJ7;@ZdKcE8ase9s`uNw%&h*pK^M6Bz1ormuMF z2pMP!%=9{ef05q@jO0!Q_}uHHDx&;M`;_#lNBiOQ#ii#|ik|K%CTZ%ap1akv!s zz0KaR_;vkCJtpt+D9Q926Blul%7o?UuYRl>qkj(@^vG+ES9L!XACov*@KqO6KT{ue zF-8Va*LR#T&tTsH>&UMl^#2#&{z4mR=OWFORqXnFZgo<3mvA$)3yi(y88^5g(+MQ% zl>gDyr4M5{uMJI|Qr~loo6cP{awy2SBklGK{rc!Ib>|IPjty2;SKFn_SK990ar?%% z-)ZmN-EH&Bi-gUz1IAkNCy+@|d~3aJEU%b2c7yb{?%ry5@83^blaJMX#mO;*sD(HD z;hr*JmakK#HPFpSBsW^&k4I#QW2x}D`Zv0`{x0CAairuFD{u{gL|SMi??{94t2|x6 z0;vmputf5I8SoItf-A4`XaVBiYgPU597~gnKRdA4qHiZ)|f7h;yuek+~n=d+0;bOS`v_%2NQ z3axotzl00NNs-H!FQ=aTcBi~**(ZItz<`s}?edKINPpm1!o-vBdVCA*Nn`UU0Qyk| z@R-YHh+0g#zO~kV{qwK37jfk^=~cHV2t<>FDZgIwk3YHB;h=Lh8ncnc=^FV*(@A-y zurN$L(9js3=cHH8+ow1d76&&wJc6H`%p^DX-{$M44#&pTzO-Jgd79fI9EqjqGQ?mZ5=%2j0KG+xCu*18)sEv9ds!9-Z(`YX=XTS@fFm zJi-2FV~U5RN4-nK(3HBU@jWeSjPdoCT@#Z8q#ZVt#~u1z)l<>+%t=^pLqql$FQ-$H zkAA92S!cbE{$2ieK1fq?3KP)c*(0IQM_>I~d+*jAcoV#d=Z2j_`h>{K6O7Z~n$_wBPuRUvHoK^y``6r?(02ev{Xexqg3g z1G~Pl(N@;h+LEVqy(y1y7YjU0G8SoEupE9a?AAM$G%hZzlHPgTRo<69(BeEByfJi< z$QtRU?LYs-UkXNcbX%>lo-KbZ2zSmm8HG)HR~a*1vAX zL*+T~*6?Dq9cpqkj>ofSR@UCzI{g-gPC`o>r^3_SWOLLk)q8%S&k+p0bn&goFz#Bb+qB^d5U z8Iw);95ZNPL85ai-y)}axIgGtS3jRpR^^ZUKbKRm%8BS5@KX+<*$42PMbg1bPq<>K z99~fd(N_FigzE*-?Qq4(JSr{ar=rrIrU zluJ!yVSc7vxxCq4dHF_r<<%SQ@}*7uY>$*Vi;|D`A=B+elc)Y#_?cJHTRUhwk(Ea2 z#(4T`N1tK(p(naPs?7Gg?e-B~)$f5z*F(%|$PKeMt$JPbOJtGq!p~S_VV7rfGmd@M zM;TC=n2YBr&nL_%+vp2LEV7I+Z%egmye@o|e#k{^arYo%7T1a7Mw(jic7qN2uxUFT zFO2mZ&@t&RsK4-TZ$m$}A&JRcV^ANA^*I%!1rPMe@K@)d!s{2uh}9=H4pt8jy$0tI zitu8-vAfLp;Ki$(?Z5Xg{qybe=1SXsaGQ?tHiPIzl%>1v>tFxVc6e}@U4$Nyf8~`| z+5(Kavv<%IR@M;^%MgnJ19p`G@8!*{whjaM4KbQiCM&|c&~s_g0U=DnvkY|i?!ET* z+wZgoUK`DLMj30JcwOFt%w??+?+oGNPVIDXSnDi;-^OZ1rD9<)7k?RDdQGoaeH|XU z8ym5ZtL%!|!ayYPU3VxVn*8VAB1q;mEdY-hJh-ddIKGo4X>AB9TZ5tfw(*1AqkQw& z>w@+@fecOFyLl&*5e~{d?tgG_kcO(Yfw-gANx!%Nci`-fTV!zL54@ia$NXJ5%ayrk zvYswhsQIm$ja51^cdU}8?q6@@<8BLZBVVtNQn__k_dNA3E)IMi?(Sv*_yFbi5je~t z@H06{`Kr#Ona|J~+Nl(IiZwf$5j1mvjT~r2sb;;8f2+V%iATuG*w>8L>hMnN(as0w+K_}QcLXAS%QEe z#_kpjQodvTo|ttC3xwZerGxyBb)y5t#qyqT{YQBmob`zr7)6@Pf9{y3S~1YcxLVtU z!WOr7!CGe9r#zS@8G-DzjJm^`QxQ&l&DC@zxb5`D!f&!EtV}?X;bsd3e0<2aA~zIEUlmqs-HWa za&SQUp4YVfi*D4jH<#wym6ch>nZ8qI>7j*gsf%h*&_{a13-SrPrLOKNP{(Rkf{R$C z`=*N8x#K*>RS)joZkrpc?ey@V%`?VZyRy~hmY3SYy}kCm_wKd*6GmR}rB`@H7D9LV zp(b3s$!Ur9&6p2A$HMm?-fuSb6Ha{_xc21_I2q&E@6C4}Cldkw#pTNrG7|&jR z4C{yY>z1G5nM_8yNf_(6Zt(vYA325-W_TReak}C93Ag8-N5?K1uS5npZZ4dH0)816 z5@+C5BP+x7myo=Xw8n#u>D*ZlT^QUS9i3$Hx_SYlkr%ELaMoekmu2*tcZRL`)DQ5) zPLul4)@wJ0>RVx&0e1~PS*4!qd%x0wJfw{;7$t^Azf45&9BW)4SRQj9o*ljT4H&*j zE7L2_^POYLTpKqW6XH5aC(nV830|YPq$I z&GojvwwlSl;(77XT4$-GU?oim!Vj3lOPe6x;DIU%MvHX_7Pb=m6++#1&2!OvKI4(4_AZ7k;5V^hw*M z-dq&*n#Ih;z*l1dI5ndndctO24Oo+QLe$dv%JP;lpO4+}0_~E9c#*B7RW_S<^<@{< zI?l656TjfYDWRYKJ+2j}f8rJ~efBZBMC2=FwHWwY9?Kco5o6fk^WGL{P;!WW2S=^_ z={Ntp{n@v_-L}2`4tOs9x`D^rL5-#1+G$!%`9 zDIZ38;i9cKEMC8UtzEu+DJOKTE8C>$R(aQNZDYNyuCL|u0*lMbWl1|G|IrR6Ui2!33=)c?`CCVtYM)i!@jR(Ztn?W=Tl&Fi zLs5-iamr59F|_S)hJDP4%e3WZJ&)(|FPtZ)hsQhtuHbu^;;h}eeYf4Yd!Mq>`tde| z?vqgUiJCtpL10NE>j2n5C%^inFZLC9=hC1bv=XP9=PaH!Y}E6>r}zOYr=7rfx=~m2a~}5|JZKLdKFp?%%DUR0`8nV1W)^Qf^_#y- z3yYceCYO>6j!F7lzNDL`o-lkLl$NjDSRmi~eOB=fy?dUz#!MSCMao76H|Ou zRFH3{H((^&4z|`J>YKmjHJQKfazb8o^PYS;_#-7sXIJmT2-0;77x$KsPthmw%lv=p zMZBs#RQ>hm{!>U-d3Dp_lV^XYeuv+*?c5%BJZsW-QC>Irxt?ZSJ5OE0t+U%b|? zpwF+Z`AJUeSN*f(VQta|0w5-Ir-&(birW2fE8INGDE)?Pj63n`b=qxoYV@)i-_)y!{I z>|B3-w`j7k}M35&?pR zSEh)d;>Wv#eeiS93jTt*YVr5zgw7c_hsP*)3?k>|>goe=lA%UbTB$N>2DoWi{K;Sn zLSBmvgwJ5~$VMgv^HpK0G;3=sX^bw&x?^_d;H2&BAGHJXU0TU^OdZHdGmqrEL(fLA zLT8fi06`;#z@7_zaGo%sxSBorUUNi|wFAWyDrvqqL)O zSDuT!F8E3?2P;mXd7{=+1nwqu@ppS~Hfb$%A6L!^p*7>o!U#c`)*Aw;$}bAHH*s_!7f>y24-E z)yu^yiiKOdlklUi?eyX={=_z@TzNs^jD?n^bgA53H29R?Ohtv~;*%0)c3O2E@=3~F z*S<`bQw8zjeMu#PdPzqJK=Dwi%)|{yc(t`9aEG{dC^hn}0~kB)6ZqNqCHUb52f7iC zx>cUq)xvwqribXuR}MO)IrPJI;WrET))!%w7z_%?c#ZH?QIdaaGM43b0lEwO0Jl%>so+Hgo zrkygA@K|&X`Z}LA)xYNPm&#nA4F3HsPdt{Td|1nuF#X~Z$9@r;?hb3*F#xJQzJPS6 z(vP%x`Vcck_tXaOgUATjlqdixcbXrnK~NQ`ig7ab$EfFCkzki&!32|6?P`T zx_g1olcv%ee&LpmF!UF}IbouH=I-HI2(A;s!G}2h{3}|P4Rph>3GAjwVI1pW4Du>$ zOi*e<6I|0L+;~a-xQVY3deF%K0(R+Rp`*Xx`$02sRiAgflg*QisniP>msc5EEHh3j zy-5a7=O3zFh;601J>-fwd zJyLJ#sA%2cJr!7VTR&r@&fdFk-1hc&+dGV>UDd1cSdB4Uh!(H#IWU4UxWMt?rz=l*#gXF|@W+n~ z0~d_Rv%Udo-tHZ>%wrs8y9p0cz>KjR$2d6(AZ3sGf1V`({^Agd$XDbnS+wFLm(>Iv zk;q&0K!UL`d1*;+tem8FVVPfz3G1}S7`J5nKtZcyj;$H%XdT;FPqgRbLqFT}2s)p( zW93m|YNSA!YCrylpKh@0kQx6{xLo<{qASmixy;K_h?A#X>jo;GO-{msg5{sz@GSzB zrzs;zQ&yu_ZqicPjB%o_i`li{<^*c_*G6dTqQ+konK2&eoaiH-Hs6S5jF_vJb0Qb& zGS2npFlB((R?jUjwvDYzZEx>@+#Q$BQSU*bTyYXX3X#cWamUT|nB?t(bB!y>kNAFL zeshkI^*vootuO&tuM9TeDn48rPp7~BCGWk*k*;5TvY>L0Ngs2L!I(| z!m~@K`gj`Kr8sG+^`3W$GTWywNu`Aq&1a&WR7mKlE$cyt19kxBTR^lpwh zY76byc$Cxc%^$;0M~9w_IYJiDc8Rw{S-oNIQQFrDGG!*WsEzriHQKP>i{3vzYd0Sr zv?JP@@?@2ISys;2-bg8C;$r)Wtm%En&)V4LqFaQ=>^GcODZb16lDuR%ajQS4ZPAvW ze3s?2sAYW^m-3{hv2Mvv7vIFyNqdbg+K8)pXlio1h*|WjN#)^Z z2G+lB@Qm!VzT*{~ENkSo;R<8iNja=%Vjdrz5QlcTIMW{Np0=-j;~VXV@4THu4-hAO z>Y<7=!T3vFqi%gJ>$@iJy<8$R`uf7E@S1j0e&Gj(&6RqhJ)4{L&f1n_KkJ%7k9Z_PyCvP{w@%EXl2-OD^2O5!8TSr zg16R!z<2! zqp>VMFO%CUaD#yzi*{0IO@H^#GD|aLytJ%-tLPUQIB1e2{(HJnUvUvO8~EUh=quK1 z5|)Wf3rynk9+?M{)}=fk!Y%-pj>(IEqmGQvPrehbi+X}~vDG%=+KA!Ct1RV-O7H75 z9zTg0^*`FEws0%AFK~;&8BvT|xn9t{-U_yLQm1^C!EWO5+r(avU1J9I`9QX~ z6e7AJ_?1k77YWNc3w?+Dqu-buOS-i zTfW}g+i&~(d*w&{$~(~)CV9Yf==T}F22abEpotNp@h3Fo`NJ_QQ?M>zPM%X=Pq(2c zIkS*RQm_?Fa3>ciw4l zV{hKQ-)`OCX^h1fbj(LUc>31wqu9W&UVouozV-riT5bnuOnX$&o&BBm{{6dc`(Ov9 zYQOCr>F%|&IT#bA*#$?hxtK021+hSTLu+lg`QXEYE;N% z5E(Z+wSgleTG`7>UX6{A;>9wL@yQV0#t&11qr04o`At06ju?&a>>p;)cYR|s3+5_4 z=C!f8nYa$(52z2XNN~Wo#DHT4fizE}_ZnwUS>u(m)!<$`6WA_l(|ppX+_mHG$Cag( z(8NJ!gj!eN4Y$E6Xxz!V};KW=~Y zC*NqhNAR!g5Vr7}%+)wWM&TVLEM-5(A9zD$2DeYxNxnUS@jfK03o{i?NqIMa`d2zy z^`lHg@E*9txY$vwUQ&6Ow{hybz{6J9WJ6-d(fll<6A3j?_r2g>4EBaC80FRgC<85# z?WRgvZYE&)l@46}uW(a0E>#9RggeEv%Y-H}R!u;gx^J!wxv&P`VfTAlR za|;xd@r$|>FbhP%n6^(dA2%KWABgv3*$(DO6S_Sk3L8gby@@b&;|)`Oj_COCupJ&8w6%?mc67YoRyWq$De)FI zw%Y8{T6?f}l<}o`I3{y4`vjeS|L`a>&JDNJ9Q8QESa~_uqkix0w=&i;+gwxYD95_P zOMb3#VJ%oXdSfxmhXULD7v|et?JN0+)g*8u&SG2j?tKEiSZIuB^7-{qkqq^-F6byR;iH z$aC_>*gMrC8qb6~EnZwle5^cfXg=LVB>69!iFvV3!*h~C0Gh*9p*`Vsu)iOEG>-E`nS@kEkhl9sR`|C1xh|#e%=6+Ma*bM$%mHqWmO}$y>GHD=((+lFzK5&=OoFPVl!Jwng>&H=+_d6hp5i18L&tK(LwwWDi;&4rca+6?irhe6WI@-tBmI;g zOURMMrRJhJiI(XYd2^sS-Ch**4El+42f_AvIrDJLfFB0-hvX=cRL zjOQt@pQ(`xOO8$vCdT*jQ)bkHQQ6Rx_FZm;RXB9%?eC+E!N##(Y)is$UilOm5dXj{ z81k(1=7;Eq-g@AIFO~f`w$QHE&csMh>(}{qGgKFn=k?22pvN0VpV8)0j$WRRV~l1Q zj9qCe-PlO*xb1BZ90vXDJ8A)3+?<=P6T#}W;u?H_H{q2jJB+ODMibjfWFa>Cq`2`s z@+ukG^YuOWVk~c!fS+wj+uw~7%c~}7>ZNMp!b&&g-3I#m)vH(AwX0X!rAwPx2p;qB zZoW*bLgyV8}0>gA1g{mOc~vbEAS*OxLNTcZK4Vm;lOYndSI7LD|k zmtSmey!Kjq?bTP?%P+swu3f*HkFn>2<(3}i@;kg|z*j+Eg7Lk+#}ltEy4j#%!3?fI zJ=aptIv9uHyy7R5R|t12)n6v7x)8LHD)>|&vk(gm7s(w&t}fGXA)CA|FDeL2pw>WU zekMy|!J!6Kv$@{NLAioc>$ua8WakP4o^ALx8uRs3wcncY8x1b5dn)_<^f)_DS69S` zd?>%|#|bZTF*h2a111%Q!lzE_&PNIG)UX3z7n0p=>%zT*w55e5Xg1#tp^ZCq78q1| zlEOivSH*1a>}F?NXu@w81+)vdDm^ahj%%Mw@v*_#(2S`7c)ZPM6Nd){Z*>O7$3jG_ zc7)YQZt9YD)Eb!8ntYbR@I}Ud(`(gJ36b~0}K_hi0?L$v+9aj7<>Y(t=WFle3 z6SWAht-25&Y3hWdw3G}o8RY~g`Jhhs+F@#=^MHd>JAE+KdD6r@mgTi9FoVd zuYrC&mw$y9eNFw`JU2gU1GAPS>elyXZ9aJ(G^fXH_rEZoEDvKpna2msH2fbwk7r?? z#PMg3!6!Gr95_Ff0Y21>frOnx zNm?*|%q=s@n(|_VmGJ)lWLPF(%(J@{^f-)|{w^r-3fyVaUx88&PZ&~*Y3#H~9>Ie$ z(oWP19ZRTx8KnN_X|_4^c2E7f*rSFwa2UA_d>_O47sN;^>HMrrZmeO>z(iSJT-$65E1PX` zX^j!be0%TKcE)yEH>MtVl`(q0W4G+Y2mU0GEXZ}JpJ zTs~dOg6F_eEJWd|M%=kp!uwCLNsbQoo{=llY z`)KCI4=uppqjoMF#~8q`v0KFr8HwSPilB&+F@+;k@yJ5l!4Y&i&cd$a z*TlzleC-&;MMg3uuJk;EPF@c!Z&!O8X8KtuhUzCg(R6I3UBYfI*F3}II^&dua#F2&lo{J8{=t<$>219X{t`PEmrbuVi{fABYjAvm$6VZ1 z$1uLP#Vr8i)K7IeSjC*WIfFO{2k0T52w<$fxL9Lf=T7`Il4D*EX00sGHG({=kn5pW zXw&-#r|tgUac*$4O|5!Ox2SfR=Km^b;rY`smCFYWxch^!+0Y=*Ikv~vq^I?$Yb?wl zCa`Ss1Elz;jr)vS{ZVc5vYgVEhv;zn`J8l#%R5HiG{5j0f99EF9k#z=s!bVgSn+|z zr1}^C3=<%UC;f$6<%?%$?_1VfVfD#n<*~^-WggF?jg2zZqS2sx$&bS3gC-kB((dMR zMYG@ebGVG z^+QkAx?#-rB+o}~bvm2A>Zsnwv!+}jsYetq#D`pQMi zlBUI7a9rWqMY?UonJ3Q+P*aJbnj7owl2~qL*Fd=#=4d@%G=AI zH;uPIpc&zJ@7}%k!yo>z-Mo3L-M@Dq9pn)I*|vm!k~%Uk@Ewc8g`apbPIi|XCir}) znItGTW;{>(Y3kko_65cNy>CqZwf^BvMD}CSee^M-?G)e1A4L=2Q}$FsnSsji@wIyq z_kvy*F&=lNYxTDmHtoSWa$Kd~$t(++kXwzq!p7K1M;aB&@F`Mj-Py4o&Zy-o%Ao#2DEN~87)AS?IY{fF)S zJNFpezTfU|d#ZJ&t*>phYnLyz7cOtL8<#iR3!7_gbBW46IcTT5_uJ|A-FAk1zW*Th zZ2w_9-Fwj5;ZEDXf4e=r^=>CFk-`!I`G#tgHiakyTKGr09bs+n4%qUY z8Q@Aog|Y)}PnG85>cscdY(~g5B)>bn5@l_UaIc6EB`3owiYI_Un?a6OAAu`ERwYrf zI2QXHXh90-g$?f|b-zS4nm zVzX-z8^wljtqQt=>2cS_4oMt5Qx2bP_vsvxj}}-wTTmOPOQmNs^X&(3zuzA2QD)N7 z4?uT2O|NWlhp<9cp&(E!i31m#{CJNG9$9?l#X715=&5*V@5WY0soa4Vyf7v~hDqEW zzxakafR1(`#?1hPbPkdfiopk)#b0npp73X*dhb} zT@+H42S&bt``e^Z3Eq!24n^ew24FEQjZo^Y3v_11048F z-XHuYFJ4>&Z6^xtfRm)<#EePYN{@wZrgOuBR{vP?7z66(=DB%po}1_9=Vv1RBaW+2 z)IQZD-s9mtS>(9`q-m;ahF-!(4_ObM<(I@EJ zqfg}Bfk^2swQ;NBlyv}NpIifyxQSc9D<{i0HIXK5r|54V?$5N*e|w&lZ^6_gR={4s z_P;RI3AO2??W=iKm(#CY>$cwGH*o1tKFU0XySBrq0cF8fSE!8x>I>yYXE0xE(V*PI zzMKAHSW3jZ<O9@&LS^Y6LTZHPY6*PlKjf z*n#@NmpIYE`{M8HoY%%>X_z2&)iMS4@pAp5nP-WX^buTkZUb2U_R3}#e#6`7)w)J< zQX(|zbSrAh`=kxw`KK~_c*ywkR`V7q7ZT2o_R+al+M|W_wz7Gt9q#V7Z-4V!?d|vP z<{P4WjE`K@^}53Fg1~ro{CUZnop^uy?H{&>54X{?=kr}jtw@=>i=#CWL7nlQ@tS;> z-)O(U6g~M9zQ?o5Cj|V}p$`tdw(y9y0q>Z?B=8OncE}^rNdntE);zPA9MfGAlzcFr z*3`5$e$o)egjP;;_I9hT&$C9jIUNjs$}-1;!h6&wgpQA~jMZJNHoJ_$u#8}!6CT8M z3~@;N-Y4$CvAI?m2A0!CKk4fRa8G;EDsZ7830(NyU_5?_@v^7G9Z!m1%4FeOv@Hsf zFZ7}Qi{>R4T^ydHZF$N$S0(d4%NR5 z0Fssgek}k413INHyR6YBKPh5CiLd7Yn#jMH$VS+`^#VaR9j2D zo;DD}ae1m!yW&-jwkTcgm!ubA{Hy$Z9?%N^GWDJ^@E5L>_wcqp{H&LYdcJ4;N(M)# zM`>?v95T`I$tg{|PB784WDdX^uhJh1S6+Z-UK75E)!)Mjo&;9bKHNXa<^|_Xoa@Pn zb>y#bTwCHnIn68SPJ15TROhfh@b`0C=O^$t z;l#5&R{^XS;=y<4(9D?^4@J&NJKjAwaE9wf_M_ZzfSl!LIu{4zA1C~6Yq<)axYnri zS}wFps*sC5T>PESvi@g~4Ym27*yN=s_WSmV32(Q^_c5tAI{m~y^&7*aw_L(;o`o!F zgZMr=roA~AXGu=M|Ew*}c^dq*EzJ-%Yu^g4^c7w;en1}g4_o^OfBcR1`(OPUvWIdb zH;#|?+QJ+hcD&af(FdHL9+K`D{Aw=8KHd|;rH9mFr<)6`|9q$V96C;Z%D0kn){SU~ zKYi}+X=9YbTkeJ&vD_=mbrW3Op0`N3oO@kvOY`^KWP7_|Lecg{`ddp|D*ly{*V7w`#=1j|8MO(-~KN3qAY-4k<-%7HbBm)v&Fn) z$OBY>Ydq&*p*MM3oXoj-cm*2yjr%!xH8kXB`RyN1j-aKoOj6m%%|lmm0#mr+Ya6rw zjh>JO?)-3HJWiN%*TrwS)d9MhJo9gaL|PQMi3wSyY4{Pw4aKpdmHB48T@c+ z-NeqcQ}EWxir#_~lGrE82R!DL_c{8=VbgzN2_Zt+(iOG7+ajq$G>4@b^y*Xe1m0|^ zt^OyLlb%skJ6_9brYo4XR|dd zx-PD~q@O$@Z2P;C52h~T8ppwb2f<7%KIUa>gLlrz{}FVgV!YT@s~)ySe{*RKIR#*E zyHrkjbEWh6)>%HQ00eFHQC#`fPfw`xc)O9e9C^cud}?VbZ+Mox&K}9PIU}J3q-3r{Gx42}T2S~1CM0er6 z_@UQ1*1k#q0Ks}qw{0nN8rBcEJGSx@nXW%tU((*szMhiDsXPM=*T+sNOAeb+wlj4B z8yofveP{-E4qah}{%dxY_Ku}?L!;=y-TpkyGs*ojjpA3o^qF?!>Uvvaq_hlYeD7O- z*6!W8)9&4SfU>yS{`|Xdw+GvYbVh!^_psd|OhxO}mtSt5{miE`7#x1mKJ)2Mw@<(E zMtl9Gm)q4#m)h3aTD!8j7JcFP7=}E6AyM$$S-Y^b6ec~Sp(y265J+BqlDpEupL&Jq z7&tPZak1BmK81OYy)GK%)lWFW0Tj46hqj;(?D<)Ks?0h{{ zE6p4%s5EEskvxu2U{yvUY-uDe3K~xl=#F+--*saWrqPw6tPlkrg4Jf=qT5*TJq8D> z!0V-z(e4IJgCa}?-tW`cTph@q5yz9$4odxS{Sks)1!5UoGkF34uZl4bcfWb%gE-rm z0TojnMhTKwaMY^cWB_cLD33y7+ARf$xHeqKN|H)r7&NHG*b+`+Z0GH@;CJqAx3}NB zC5tuMar!RnZPvz0x%ij590Edt5+t$uXQCCGNeiqC?oKcoFSr{nGDhYP(6K{^B}}YF z6#c~&VVQ+~SL`t-41(N=t#CSpZVK_7Acwas-;y+UQvj|D{_Y@@elD0gaidY`SCEN^ zIJy9AiTvJ+gN*&d!wdji8lLcJLA*81n$WB~3I&F`yb@D2Uz&%X< z`*0}F&2#hIJU7qH&(2iepsfE`hKMylv~#deQL9mDx9{!#KPyuxOicA${(rhj82FaL zuk8UJ%T!slrFT?%ZTiya8NJ`7lXa0~Ec_-;^og!l&@X2I&hrG1#PgvWX&hZf+WIV& zr)gV&&0_-B!5zAXx_k7R*vhx!SIWSivbC`5WV;h&4wkx~b&4I65B_4zcLMC`rsAU) zjI`Lwr)=~C%5Mmsr(=9qq!b96cNSTCbzQU?FgZ3BY z81Dnuwz_*Z3K~6@e9`wj#YzOyUFc%r8^dGq zuEPGp8F71-gXbCQpGt`SDj#QZ8l77n&*YJ9(1_}tj@@`USC5zQ3GiRN=auo>!Onwr zytjv*j9xx-){YN$+sq>R^X8>YUOl{fxBcNC{7HMbchvR{58D3G5#tk2H257~Ie@Vi zy7#81trlk6t=l)-?K^i2k9hlz z$U0G@e1Oryw?`+ZIaSLm!Sz!v7+<~$pPDD>vS3EIljh+U^F-e03+G17*E@tOpG2wl zP_&ZQ!v8@IKkyWtnfY_%i{lzM3mdW8iJzYFlz>-0+io=mM=s`VCgbI!qm!I&*mWU0 zbeJ}UmBuGpL%!L%3|=dYyjP&*5}EqGMqO<&HriOOc9gMc+S6$FB@3(kRR+i0hG*dy ztDloY#!+@AZcl6FM5Y4Mu~bg(L0czeZM$_H-%P@kxB5B9Fiw7CF-{uUrh%95<60_U zRz_HPgZH}jnRxJc>d=L2tl$3ide?{d?v?B?&4gqFhP6mo%BP$dG_dZmx+zN^o12f% zi8T|P`7?JT0WX-yGQVFpCg$g{UZEclaL}oW`L-&@&3$> zKrOp?4xf531a!s|#ULIwT$TD&BJ}izIjIT#ZS}pnl2p3;-?+6fP`0>}2s~%Li?UWf zrZEeF7zpFV2v#@Bp1@;2@x+soJ z8aiPuq*hy#qEgE`r8tnuy7pPO78>KKchQ%*q30C(l&$BJ$$MP~I_j_JM4g&8@0~AF z;abWM9;rm@xx09Fx9rn?{$&#re`R_bk*DBs{wFVu@ti-qeg8pwNdKLM7jQGFd~Wrf z67~MxVf+1m__g*Q{HOm}`;Y#=|8@H>{=uKNuYKctwaGy|F*S!Net8AGK&dkIcYUC4 z=TYNJcdbmfd*=8=XLuk0^`QEhJg=CA=gSxmuVhTeRk9JCn}zou&WR zdk-y=X?@nmc=R$eXQXjKig)FbR2iS{s|{4hd&gv{qvDw?0E;t`#V@f%$M%F(7qDIW zZCCLaw+N)J&44HQvOmTRmH-hKZDd4@55ty8y8eI4yWsFXz1SPupCK}F`a8DxbMU4# ztNC0Hsk!ibYP(k;Oc`mYAqD>fA$_&*5H-1NW!X7qkQq(c*j3u1Z+X>I`C~fm(m=4e z^~6rN*QIETnp6d97>7a=+DJb^qOdq7kQ@c ze24a_OrFIt_>q2mGDb4yCQM>z)!$$c;;5&guQ{(Dx9e*9gJf{b(5sB*v(y!yrsha2rTW*JuC;erX1P4 z2z*Nw3Xh5#uKon1q&%eb#>XbUG)?K{my#pK(L4P#uH~4e-^nI4!adNKeh_2dp|LMf zkF@V{)6xWnmhjwUiYqSqWL#u!se_6;k>T_q;YZ#_+m63+eNP?KCYZEb{B%V{2vxPT zy=e=+_1P_P(3Ow0!RiV7^E1-_6B~EKZf!2N&wu8%_NmuiLTTD-+Yj!wz1`jR!V539 zqvJ;mS|3J1lF75+gdqFMSH9AI?bm)Sjrz{*+tNP+Pg~l?>SkM=M+u?g9C*EU{e|{d ze*M?m-~4NTwf)_{{@2^z#{Fmiv45=nQ-Aq4+i!pAQ|-6D_(uEn&%V;W{Kkvz3$I>p zzw+sq+i$%224SCRzxhQ56`y;xeeuoDqR6bacW=JezWtr=wD;bBKb3#|>ecr8Yp=Ig zUwXN{!1MLXm)n&qt8Hx!mZ5#g9GNgeaB2LQyH~l?#G8Y%`COCYA}Li*T$`{9Zw%60 z1SU>)|B#o9vBvj)e;067ejVI-or;qL>97^*WM$J+*vU*PipJ0Nx-JevD|bPLg(75H z+sj0QJ3(qUg$vHBtL_dtN0D1#d{nz4#6jj)d9pJJesHsGK;hwTF`3*2LcY3ulXJ`*v_>$E>;^3T)!D&+5E1Moq%bE5|aUvmU3iZ zZ1bW(=|Joxv137X+RbTG7qWF7Fq3zbT=LFjWLiHNVGZ|0t-EsGdh6YG|Dn4I2{Iq* zco806K$%tKl_GgztCR4V=;92H*_r3S6&koxJKt-tOyW-MM+l(%7d0aJH%D+^~bgD6r%F* zD)B9oyO$KA?()2L?ONMl;P16Q8=LDq;||Nayt#(;diJ&T)wph+5T+lP&jbYdW>L4u zO&&$ZVFul*Y*jZ3TPVPDbz)8wL?hBAt~MPcq1Kg_swfxO%93<&wols#G#Z0}F+fNi zDyg5FXJ&d8KW3k``NhcNN5}Xm^T|?wJo9Yw_~a0N+U7|NKZxazj`7LOC(GmGrT)<| zewhv8IJTZI`q-zLggx<`$sgss`cnqLk3Ka0PsdEB1ioTku7Doo#Uf2pKg}dhtVYzWkBfL^#?ycqxC3?&sK<%>gfX@7CIE?NIkNB!9O)K) zP(3{QnfjJl)IfGJc_0Y+K|Yapu%(+7yitx{C_`Dtq`)&Vqi&qw_2dj?_T)es99pO2 zl}r`(JX3c(Oa4@kbs&$)TPMfu5o594yZ74C%0io4o^AV#iRaO;XQ+$CdB(Z>58GG2 z@vZi!Z{KV8kKMp~#yHwVzu9(ldT8O$uUFfpmGyQN7-ze8+rx+VlTn?L!kT5Td#hGi zZ~_j;$VSK1o(i%|^1bPD(jk!<@8N_Gz_+F|48xzo95Ox=hV3N$W!vD{^6|v$#RT!p z+&RN_C!>U-ui;X}xRrk*hlq;a|$-CTPcaGmJC5z}!VR z7tNfwQf7FKuS4Q_>xzmxpFJo1tnD42w!NdXc0^o9?&c|GWiFn|6rQ$-OdUCH1FoB$ z*OunmrOl;$3d&8-3*=Kj$G(=bXrpn$HQB(9W24vAyxa<@Q&9 z?ThWrmtIIc#B}-=zxf{Dyh%rSRM&j7aAA0lV}i;b7r)S1@01&^!e*uh0Amiqq_xP= z+P>f9C4y~ffp;gnof~lp$O+c8b>Fe4y=^!lDeYZ|nZt^6uB|29Ti0AjUV&NHmuIrc zeg|fDvfl+oKgng=5~q~df?=k)_7fXncDS0r&U^X!-&)Lbf~0SSX`)M5f4<}oEh%Em6JMXsN`vUT{zcaDWT$&P=GHW|6 zFAVSejX92K6I`4-f}e6jTP$>1fUZl6*s-a^Ijs3w;9c#fd_9cP=XRV=(%%zS>-0q{ zOUv*#X({Kt2Pt%yaIt$1wx4rgT(VC@_?z zckkWLJaTSd6pz$f#Wt5^=<7xgnmTdLD3kqigP-K3;_L7od>Y(3uBIJj)D%xrkMLri zO_TS6A%->2Mf(b0R(WkJ@_CJuDyHU1o=M8?rxTojA2`9L!bjPjsR87G`y^hU#AHED z*!Foj)oHJS+;O1~Kl7UOPraN~QjK`n%OHvSLQb`Pd8_De_y^`W0qt!Zp1}5|MBA4K zXx!jrAE%C&4P>T~kHWk1O>g(udHBq6%;V+)^D0WcPf8@bizpv3 zqEmIydFNx83k=JcE@|V+mo*kSK0a!G*Vs=~y3yssjQmDvNn7+5i$&2A9}I5=## z@7!sJ$R{`S_^o0$`I*zs?r!9-n@~*etq`8d*6%R`vgT1n49lch_53we-ioX5pl1OX zw!dQymcAa=l79NxKj$zS@B91vZGC+`b3GdQD0HX(vgUzxlVrxM_**aHkopNK`Pb7_ zoeaE!BmZxZny1+NA2wJv~4ipesz7by|&icZ+z-X``iEIZ?}K-@Bh8_ul%cjzx^|R z>uQ_Nh;O4n}s6Kn0=nY5kV&I(cqluWqfk%d5-n2Kc;wZL_^`Wxajr z#r5_(pSjWg+Lu4oK68Do9o&7pee-L7)V}lWKaWCo{gqeSwO8M08^GOK-D;QDvA|lV z@)uPskB-~C9jpa{AMwf}Xgk@sL+t4G_IJQp zB|J?}B8C&k6;?LrG0?Prle0<{Q7w`}Bohk6Ndr|t18WRQ>_Bb&=|p(9QJ>QRsG#oc zK4`b!e>>L}c#Q-s8|B}fCPy}U;@f}~YCbz;aB!Bv9)6iPqz*iNt*1CSkr<^fi4hXw ztBbPX^&r8HtXH1lg=I;Q8pA|>QH687Gc*>7~EC#i28wkOLT;* zi|yK_Rd{oW0VEb4_Zn{(XIEDlL=(Qbx!g9_=iBAYdD_Bx+gbyjiaVUOaI)Plt(>=O zTZ@hAXfNK_Y}YR@wpTALw3jz#+LiSM;?K9OmD#q5)vf25wz1sW`r>(8TRdy);Iak* z*WlSz*l~IO4C}X`y&kFT;_RdB;-=_j7wOEgpxf4fx3&zdCDJXNv=!{?;tBr12EX;y z8Or6P&PiRhMERX~k$2rCO_imNhmv0tnq_Sdr__y8RN37Je>^wO&_H*{J+Zz&YcmZ$ zdHfX2kIn<(po|*!Con%ck56cxg#VM|F$)P{7gLMJJ zYlxKbm9IUt%6wPq?T5RYK{HWGajyY@{j~TCzruUpZA2mA)FeuoybI5~`I**qBSu{6 z$w@ok?3Z+nFYcKH&4ce_A8lDDf*t%j5iqgD(T(0iS+iri?<997gYJ|tE!2TtOXxMr zPA0{A-O?<5<)%a$MQ3YGUPP}YzJ9_nUFnSSR=qvm7Rtt-UvM;7NB{2D zByyF+a6voavFL;oI;NA@>P4sMq%-r2N$2=Lep5$(biRQ93cB)QuHFhq6RA#=SS}J! z<{5Zt#<=j+M_cQ*TvhzSvuq6TM%iq;sR6V27&aK;J}Z;cD*%?S+(c*|RH7lB;^rvs zaxDJPw@yGbR?eqZ4Ad7L-&aJzd6rWpJY)k0W4m8#-U1y+n(DrWKY43jjz4o8| zgRixF`-}&Gx3;zlX=mE@J}?08CR#rWw6QYRuA!%2UOsCpPGS)zZ;4H~7JMATIF_`1 zdJ9zQ-*~_)-PpL&jfb=knZvRwJ8hEixsyw{!aF?n)T|Tqz^`Is91D`8WhO6+T$SlV zf5s%|_~$Rr71u1~O>qXpB!xE!8XGn>Qd+-!KE`L$I+^MM2K6DmT_89-VXPz^f{iag z>ETOmuws1X%~dWcScCz6n52oRHYKEE=;ukT6q$d@S0`)N7*~1X&Bb(SFC1m5i?NZZ zc#Zz6u%Cvmg=2`D%@ss8Ug`!v>6Ub{#!;RiAI5@B#=|aFDU0;S>XJ5#ISi~k!Dsw@ zKN&aUV&a%DU}J5^g_g9J$~|A&rUmd@!7FQPz-8>e4-XSLizvEDr4g8Ix$1mu9tr;w zlsJ?zGBYv}9Lz(1jCknpSa^)_y~fgoI43+e8Owg|wd?Jl{H-svPhDMa^Wa%%*H2uu znre{*f}=E_(6pD+aAlQzp&Zu7l}0%c4{QCVj$=tr93rM&AA{%*-nrTS;2(ay{rL~xrQ%oX zI!}1V?@1p}?=F6V7C4CeqmqMKlGT zLqy>@3slQXu^v{*!2zs?3p@?%qOS)zmc1$(-C${U0Xv^-iQP1kTL%`L)1>USM`0IH zVtvomm;+Pms+To4wLuqebEr*t^am8{(IfjC(rM9u?RPA@<&BZv762Qs?q6P27b9F; z;x~Ct)TbN3d{}VFIk`lfS{7DZ{C&8+9sW>n^)S&`tg!ee$P3FQOqxEjAs~W_ZOJm_ zS$U1C6_zGEoc^}_!k5yz^L**h%3zD%>4J&=jK5y>iG*7GP2v1s1k3ZJwD`rh(|I~i z9u0}VI6Z4qIg7%;>Dd@1E)oLkp(=DR+=kv7m$9WYiuQk*JJjMkk^lbEhIp}A({57z zVS$T!sxemo;g?h9##KI`w|MBsn*-c9rY_-T0Ofx+xKTH`&YmP`j}zPT!PXVtwPE7$ z=pYBrPEU^|7Km9f!(#03V#*aCAESfS<8z!ANkTUj|f_t)ow-6ZH$*^WJo~!=qSsCP}Cl}qt%|+iAUwXMM(x>h2?YH|69=1JP z@pLXlQ0C_%vE$(~curj4>RJeBkcW|Xg>;%4#(VsEG8$I7KjMXEiG=|-c|v*ZyM3~7 zyrp7iX9v2^_x^%@m@-KZ!|b1|zsN|!?bF2HJ~OHNQ?Q4PKH2?;8N8KoQV*Ymj`+j=98Gc4Cp4dX{gt+gaNB-xm$B_$yL|al zd*f4Yw9QMG+QXgQw!OQD!tC|OhwbvlYWu=xKZ7E**nardJMCNF`9ZsPf46<=jnA}y z?O*xtxBu<`>VMt-r~l)Bz5V^a^Ut(@>UV#${puG!-G22;Z?@n0o!@SM{h$7)+F$=? z{zm)t-}%gZ5=zf3%1>)c2=wJeo|ji55WFtM9X(zyF>`+0w#@I!a$8#_4)KnU4;YXi zWHHtqwmCKqb6M>Q{55c-FW~(VH1UcnJ8YQGcrp)hT>M35VcgYylEL}0lPXKAB%F%^ z=A_ScAcB2Yh6^R0@v;qUBpiB06tLRm^2!K6`t0QMX5$^850zOlxss#6l#rG z*7qpb(4-~@4WBY3u6Gpp;EE-FJ=adqT!FB^PlvKhoz|qOi@-CKIg_yfut6k8{*gtc zPiGFjDO?FR0?99@v7xuZ(rz%q%}$+X(<_k5b_I=J@G~F4WKfUIH?LK?si3W`4e)bE z3&QIRoKFt%p9vppw>FmB`U=W7eyS;^v%R@cymbj4zkY>hcXBSY%Ui4M#`Vp11^-+H zetz1nZLPFdZd?Wq%Kp+!TV0)RYq*=MGwqTKvOG@~cCqX5@j8TBU!v~1UoHC1(&n)| z+xFcZ@4Hu889w~hXfzwNyA9giCUz@!pH@LL42v;{XSXeY{)3YHTk)|2&yjp;&u2=?dZxp{7$o9E_Z8s+GR*~d)D*$+4A z8T0$tCQKEjlp8w4B|v_J!|V~tPxf@RNd9{ z_;0@XQMRJrpwT3xejVRI!%R~0tJe+-I!TA_sYhAgsaH_RbJ0ZqMEal^{vB-e+o`+- zl(Kj0Z75YvH$xVmsnfgI=%j}H<^qI^zm~!8|IYXgVCu)ksH!(nGeg^8&sbi>4&0qU zDCElOH~pSB{4UCQtkPa3jyosjqWEn3v9KFCGSwgFU3kMWFx@$+|LGJUc&4tZ~7EGI-;|{z+?p{HNb;|IHtNqrG$IemgipmeM|4lnNgq&s_k{ z^{u4KVu0o7WvPX@Dr?b5T9jLK!}T4v!pZ{47_;j47>VvxmcRW8v2|U9!JUvIjdJ9VE6rL;_8er|;bwf04=`@9(1q>++!Y5IQJ9vBWcO^A^#K$jj zx^9zS(MMC|=4ZL^Of`(a9;?PhWlU{^@r!InZU|XD$i?1VV~otrVsCHbDQEC2`=m*m z#2PXQ?|yEEGUv-zuC^;zueB?<8=G6%u;c9t^1J2JnASA*mw^c#(szW4mT}mMt4oX# z8XLK#KjG#aI8)&hOPuPVF5F>V7dkjP%gz?bQT%R=nF6Eq5SK)0Qj3WnR7Az;4Q4bo*eK{cwR!34<@UyBKHb)~HrwjPCQ8ms7I^I-4-byA%jF7TPB#3}AN*mv`R=>z z%U}FL`=9+A|3>>?{4f9K?Qi|9zu8`U{WX{q;z6w4?VWb}=B-=_y}P~L_IG!w=#%!s z3)k9bKmXZWUAw)v+m38VR?_lH^1XcZDub9U>}K2C+`z84E0?$0jTf%BEBL#(wz2A> z@MinMXWwYQ`&$e&Zd_{HH{WjWeeciO?){rtq};%&=s7rl;e{7qIJt><>J9a2-c6>HEg{L$!y%QjUmtKc{1LO3Vds@d7cH<#e8F7 zjkxQpDEYJ%-6yT#u_JD8QyYYBAh2lH1pu^Y?fc6;s8+J)UJH>dSC*QV@h zyM!wYt?;zwvAI_H1s?`lt9^mk37b_HqOmJHyW`GH70=Cc^V~c)&&@A~NgqyMtn2^L z*Y|&zQl8a^?B}DfYm%nYeV7^WF7yY|`q%A;8DR#l@#upmc|OGyOv82SeZ(H=%J1TN z#2XQNw0cjN`Xgo5nm<+@FAD=sMq-_~9D|Rth37P#GHAvf`3*a5LYhIN(5sid|0hM# zWDWVadV#VtcL=Jft`iRG zw!<%z!kKW!Pk$}`WLh?vR6csgq9mz!q6#+A`a|FwP=H7occe`$ z^LvUBk4ZgMvU>0Sn!py8<##ZP&guBU0kuK3h$pSYQOiIdI^}zgz^FQ7JOVgv_)ILt zyK)Hp)DUTafUN<%Zs23%H|3hv{}(hW`-^0pg!fh@$3B+Ph2OCmV}d_4Rfi9`p<6-> zgr1=X>5umJ+aY7K=7!i+#yu`tx;djAwd3u(zO?VXf46=0yYIC}bAFb^>qn2;-oai@ zvN{y>rlu`#i#pzKn~RUyYcFo*6l8dWHe#02IkisKZXVUs;e~BK`1y}_o?H zrKcy1xs{y`^-W(-Q9FKc)2o|Y-DsQ5rOGh!x)>Llnp8dySG4gRq01F>72aFM4$^We(!FvtvERd4lXb#PcxB)%R};!RwK`}TfB1PloN@=&p4zp zUghg^PY*6$zr1z%T01(dZ;F`(;+Dqv}fQzf3TK7u6holZ}i6SLeM< z&(-**ug5G^>k}IQ#x;ys;hPHc=N!-72Ya*$-dva>Pv@JCvCaXU9K(yq1$o&%=h2zB zloUv5lp8UqBTszpA2Vj>d4+m(6LU7(6IZb!Zuz8_v`S)e#Mlmk?=v=*bE@nUgI}+y z@j5ZqW%V1%kc*a8Jb+8ws%ia%Q;Gc_n&yEg+bMlgCR_Ek5#ygZD0v%ezV=_ni7}l{ z9)T@SV|`A4A3x;4NzH|gg|*}nysN&P$1!a_-FAGOx*58Z@#JCgu-&FU(uUw=%A3!u zQ8+)LR`Xh>waj8A13EuMK3ErdPl$YX|EzuETiojPTQ&Qlp#-)lLyO{_HUU|HgA>iG@=W;$QKtL=4^vQ?$q_3FWjFgShVx$}})qB#1q$WhGdY>ag8URD^m?Ojr=z7HC$73j^=7T z_Bu3O%E-IC%X^PrejSECbwJx$+M0Chh%owBbG3}2_H9p{3`#nK>W)}?%Eg!OrA4ek5x}MT+rF5 zA^!`|a-8Bp9 zO!FFO`EATO)L7Fsm(n4`MR{0qjQX^!9lsIgo6qvD^8*^?ssZ{5cgWmCj;V4AO1FSq z1SgF6fe#-Ur2?K}e~yL{eR6Yu=YIR#7eCux`_$`c2+Qm1Z4QR^+TxvkPrg2C2M5PA zWc;bDgYE71mw)5e+yCTW{~xvg!N2yewm0AW3{cM7kqcf7w(`vhPt?*d)>l@Lou}>g z&G*{f+c(?(?shwQbeyZqUViQ6_L(=|Y#Uduwe`za+tT`G@||Tc>~~045FX3R44zyB zT3u+Xyl-x-wab?_+cm6yT=k3l9zt!&FzMWIKSFcpufTVfV}@`S ze^)%Q2(7&Gd6D;AyNq(_g7Dgkg24nRNZyf;>q4|bQNE;2(`X!c)Bs&!E92$_Fbb3t z7zD$_3oxJ!3+0SNYt)MkBol=4avGvLRqgOxz=slw$t2}$kTVq4D5h?Uk>}|ldj5Huj35rOG510(B zz@da(2|C?MQ|SXI0>$u)4k<$FY_{#~Q(rs#?WG$pwcq`%-)jHF@BB{t^5;I&t})nL zL-1b$&5cDAGr(l>tAL4Ea;VM)!gV1ZT>$I%9o(JncY5b}_Nwo?>JR)>?x|O=_^1=c z!j^*&KEU_gJ}1wBuPctvsBd@wueB?e)^g(4#Z4DkH#b(>mCKv$`n4Va~s6BXauibxeoAWYmmYSs#&-bDAeHosw!J0oSU`Q^ z)a|rokiMn`rwtc>SIcg!c|zI6Sx+guXuI4ltQ!cULwuq z4btFV!oBQiXTrADv|bJ7wba9{=S$>!$rHu+c}?CrIImLu zw9{MNAOrLP7-QPWPvB2Am9Fx1Kv9E=r<%a)c;?sr%Hty4c%Jf0{1F^~ZRsG!xtIu2 z=g=-hztgROiUS_w38&)5CT;iQS-&wk7`SFMF-4n@GLO@BAwmNeEx2gOJBuCt*+JbT z?}@GW<9+1&Sl;G2e#x_N(TsO>N%g@oL6%bz>U#K(6Ewpbclv!ytO|$HOKkub@6@2Q z@|)n8x5B9+l^KI{kk5PRnZ~)mS=jk?AcOCGFTaW(i-+~{G$VZ~ukN8Si=I!_C;5mk zR$Qe|4U&(W^Ny7bWzVjBPlOz`Q^Fi$WD%G&PD*8Zz{t=l`0_Jxl}W!x@pHn(r)f9W zJ7VioDcv3E`;V7G<`>9hGw-pJ&){VpT6PCfsSokx&-a+}vtBcZLYJQLB&whF@!DqM z9UknoHO3W=&8Uv{XzyV=c=(|0oh`H<-rH~QKP2AFeA_)dY`X`$xv|MSE}`FFUSDem zdk+|s)U8^VZ`^2eYc+PGiaQUJKk+j$#=`+)0N=ySxSg9Jv-L$>k-*PiwKeOwHX<*p zFQZ2B6$5%koaoFZGpI#xD7k4I>!GK!U~OBseBKV%C+k+7EHU3x+#a6x94z za3fR2CuJ!(6eM#*woh*skoHILbFOm6Eq<=@`0TF*3$ZV;N!gf*$06ftzbUQE@O1nURv4PJO@5&<#`;^K zK3!o#=khIsbN0Xg8{<`gIX(%JS80cl6oW-jXCBJWCG`D#k86pf|1VZsXip=tU` zqMkbE*6~pfNM4xZBl^7&mbBts)-pNyFC5#U3!;X5QrPrfK`I+-i`R-4W~e-{`#AK# z1ai`=|L^VYxBuoJ{z?1x_up}t2N8aA2txYx_w21yM?&`Y9q@H!1v&*7z;w-|Gv?;654G_olbJ#~mr|tac zQJceW&OHrUM8-TaWB!bMc%C_>eovvz35j_=M|M9lE$xP?fak3r7lGXjK;KK4pBsp! zy*dBra}KmX&#@Vx^mi@AwT#_{AG%w0E=PnIp^T3g#>7uE7qp!=*062dxlkAP_YaTS z-3Jd+k1nc+n>ZDXD_`+TKSg@^Bv$~_w`9REa<^cQx+<#F9aBVOtD zWlaZ#La(uqIN-+Z@0w}9@e7Cns~h7@r@Kfw{q%9okDublHD|Mn?QCwjonzaK3&2?1 z^O+^u=3?AOZGk${)*|p}T>3vA-po4pI3yrY0 zH38t}s&6Ye$lEU!e(C_?R#q_M8Q92-g#~ZlbOUG|0;|PYU=Vj0Np?ZE;g;X{87cjq zw#OBY{4(ILqStxlv+~N@c)f*Wp8Sj2P=EQE&R35_YV%htv)*-@2{+^QWobDs1J2sXlq>gOP$eg885j;7l`tl@dp2) zPXNE>BTBa@f2?)bpTob&BJu~%Z_$TD+B@&xZQpxaWH=WVp1noI#vMCC(j!$^@^3_Uhg< z6`?NR#0wOFd75{(mHPQITcLx^43r2@!w0_=7~E5y?ku!iGLY%Uj#F8x6y9n@;%QlZ zwX^VDfpp|u1Twr zP&#n2zOtj8cz(Y&15p)QkZ~ungFfl0k#Ed-+6d=^1{@Pp+LYBVd6QqAF4o_&TkqBA zOEGkZ&|JH7`+j@>y<6?&mtJX~`|Ri2=Rf<|_R!4Z~D@{dh)M zHwN|pD4XK+$L+H=zZiM^=olYmK3VFIXP!+S&j!j*)BI=*e{_sbZa!HaA20RCi}g{) z0nf9Lb${>g|4aStqfMYcC6A}&YY*vfnCLf{>PO2C6IDjN$b~9&y~Dk|w!5?4wjVse z-N`AB8a$8wmmb-PC3KfM)mAXfZYcUvN9*La`dso%Sl1V@kK@1~20JF4Mj8j<>M}mt zg%2b2VSG-y{J?>KMxDSP==j+Ez$CGK|Npc1pHIFfS$-du<-NbY{dD)(?U|if?{~Rc zfWQI-cY#0z7!>)Ep*M=qONIUukpL7>1cL&oP$&=!QltP<5)47aVz6e`k85-NEnoF3 zU;2E$=Xrir_x7FX>Ft`GX|nTIS(#5hnI})4JbCh@eGJl;-l4U>uK}<+q644Y3PV4r zKMMoc(ot$6z2CXoFB}NJV3m#{EW?steuYbKqf2Y~Sb|)q{v`P5G z2^GR}^2AM!o-nEFWc91x=QJ02_w=mEmf{1)AQ@cqt_G#06ZH8Sw|J$>u+nT&17OPZwIj$3f2)!`=ncIjl^ zdjpTxsYNdb*2(c<$~rzhi(-f_iN7Yaz(ZWHG2oIK!=?3gK~KAyaD4v!N1BUQhGa72 zDbqhE-m@>iv-z!m_+MR#toy?4m3$X@d3Lm2Tbhn;>mr&Pi8BTjF7+PVq=obWSG{NC zf4sfhw(mV@>yMtat?l)8=hd6=!Vz^zJjSgj=;6D2XYK8W2koDK^_{l9-`eiL6Tkb- z&*wNcTb!9|YpY9HI6m9oZLi%}YF~Wovu*8_o9&PPN*F1nnkEl}z6;sF{ zdBO2-#(-A8w;?Y@k#A<;fwh%|eAiaK9vr~`C!`s7@&#TQtFfYE zW$STl6#km5ajs>PFKnmQr<0ZPuY{4W`Ip5k+ljg5`>61&JmI*-NpfL_tkRNS;&#lE zZz==MF|(8Z`vVusYw_14E-2Sq#<*CYiTb2%kBBFJC!&QtNzgE80t%>VQlw6{P zvQgP)-pZ}iYgGr~Jir6_1~_4%aT+r4WX43wE9$^JeeT|Me(TBzh6Nv=36RF#pe1|@ zV0&t~AQXoL43(&u~PJ3vjJ+*5BwPbY41i(!&KKoVvNLqFw^IPl(+UGgsEPrIRY zL~hGFktzhoG!}IoV_pm+L z-M7?jmbwzBBi%wY<(U!ZuHk%&g zXZ*^E`ZjbecI5OTZr>l;#%zNc`?nMNITzB^2h-2;bDm1Mk?#f)ZXEmaL+H4(vkM$? zDN2~HI8+~2&k{hMI66KGtjJIEG)?^DU4IXa2sfqS)#k*ZlTCz~_s06;w!FODmRD9H zPl~>#GFJ8V5~wD)Z3Ex|Z}cbls=mxa?(S(>G&FtECU4#e9N5{!0lu~aPgr}hET0fb zR>%|Dzc%00q|EZC);3iqf+ySA@o9VV@Ns*1?_t~A*lasnJ8gG+ukCH`V7J==e0{us z*p3g5vM7A24h0{Zj?OLl>i3;G`%xBr>9b-_sgL6}pf5Z;JZk%U2l*DIH%0nw$|28t zdeSm?bP500U&5q+Z!N1l6w^7@OX*tGCPQ{iMKiwsqOfk{5hfc7Q^(X2iChBOpxp1g zcdxB)Y?ZvAUDR!m>VLSbZzV?LAM$6xr}d8^r(Y3S`7tG$-`|ozFQ}^}sBU@RJ_> z0&(90m(MiZR^$RTH_VhIW-jtqFA?7de{m+4=pGY4EZq10F^dEk!XMkaLl+iVM_ z{Si1NA9E`z)*>$XSQpe$7JBKtJY~GJFc-P(T(j?`fi^k>`o*NTdFr<=sh`}G8eFV< zEQunUgsuJ;c_eQc#=FD?e;0clhta0paA#fnJ{6VrHbnX_)?_O*NNk^X)^u=#*Le|!G-Y- zb>^pJK$1V}l&H#Y;%ibg>sZ^BZ)orrPhPTJ`0mz&k1XrFrTEWdu4M7|Z~WA)wz9g) z(`Y-OgMYlfmGAg|^PPM6w;|+I`}CWiX@B`wf3^MWPyAS0S!RH{zlUPNp!gW2fsW1{ z7j|Y&V4R*Dwd+){*BZM!4i-y8TcB~mURn4(V9@O1uL^>@uof4W^37i>@bF-ec9cOu z*onqqL$U54Zok-ULyy2AZ*=cAdPXB)7-{Fcw065~Z*FAq%)w88gSzsly|}awRX%?zVTZ9N`Dkh=+0J=VsFI?ARwAT;%!zL?CGUUQ?aD z3%Td*m;q1*lDx|TE$>QElp9H7+K#UiPQ+f|j)0$v>?F#BS28=;+}*3)9>#@YX+(9x z*yrj@awk1$jIR>zBK#~3vvv*AaG_#92^QrFoK!O0U756Yh}41bjN?gQaZ>4*HqWyA z^BRD{y*e@*aYE7nMKc3%!iuIfSdQSw>iSIvq)U79c)i_!@QAuxXfNJ*Arl|Vi}UT3 zmtJT$udUF*zzv}3_oSpj^6B74pcqDwd=&%X#3x;hk_{^@e9pJ}up^8#9VB^$b4|{v zV0WDlgG!&Xm`bEfG&FdOxL)_X0BgsJLg9AOwzg5gceWAi6KxT}C~e(DAm2Y> zfU(Vc+myWZ^2;x^Teq*%wq~r&;zROMxs^Wrg^oqPP6&pk6{q4Bjk6nyXY0YXlkZXK zIzd5r`Kw*&YMn%LaW@OLLtE`n|HZ;Fe%e4LJ)nn*Q!FrC#7(+9n?`!!N;98v0a0+E zr=7P8$jIwl+5K?`0y%YvhQUeqZCFo!=Tl4KX;n zjoI}BFayogLA4L&mr0Fbe|Q-OOcy`;ih5Kx*ml5?NjmXP{2It;dt=@;+0=&;S7h{c zd1RnO-kOxRgOCvZ1-`iJ@B3l;K6M;*OBa9bBl`&-2jJ>l>cP>2;_{q+T^filSafcW zf6<|AvW~ypdT;(+8t~}fIdHl#=tC(*;oYa{;ST-MxqGkCtvEjP{<6L4>7tRIMNZu0owwqk*AYp5HYZ|T_|1UPiMCV58KuK#@fZD1Sn`6jv%tx%gQx4e z(u15ZB0s`}eSw#@CR>a*F{TdO8RGYKngKNFG|?pq&&d&7-#M5y^K3S-j=TKK%gv{{ zmflT*>WG=dB|j-wlj2S&o#wqezvT(x%+1cC8%=-%<&i$FR+C1uYZ>$mm_Kl&a*~Z|JFacn#JGG z-duur8H1uTt}RSMO9uF9KQOyv4&qfA_{TF09PhcO!Qh*F-+ZS%yn7FtAGVi2^J??c z$y7xfhqlN2yY2jRvTY5<+Q0mrciX@F#*?<~tx?FcQ#S-d>&4lbeCEV)+3xOEd+qvC zyS+Tye&!dy0*|)#&;I-WseS$3hw$)7J8&TcR9tYRdNO8{W~H-JPc(p%6D6OrIO&9i zr67KdRf>s)P_ zs{6u5e}`AhWq&=TPO(%|PW&!Vrg_G>^Ru+2ocg8y39m891Z|kM1KyFPmR}y=ef1l* z+kU)BnGJKSgd3hTE@|tVe%75lqztJEdnf6f*sS(xp2&Ce!e&gx*v5H>G2+#vA$1Rf zjpFZVoH`~S;kw8hOJ4S*ma<$Kz<89Jyv0p<897Bd>nDq7xZbWNEd5TJg8C)X_XQZFSvfbj>)yh?~^V_{)Irz#r3@xi!XvLi}81A6}!D%Lmuz*Z(3{1k%*%Q2u zOXuN}g_&vU#A`!sSGIj0!t2B- zj0z_yb1-@}o0q?r#b0xkt`=3PuMEg_!0_O#a~SYlK34{vq(ObdQZU6~!CKJ#Gml)M zpC9yq@F$lRYUM5KA$24#k#EK1zj$G@C_(u^H{#hB z@1ZZsSH9WbAGH0w{lqa3YY0@?1ZZ}U&EKn)1~Ml+Xxr5{dMV=7z<)%%o{zoZKU=s|qT3U<&$ zoecRvD^cd?Cqn7XxMSzEo%9XrmewWjq4Vt240Sx-wl}xh+uwe>-F^37dvNbT=FlEL ze$pO2eB2&Ce1!X`tv}vqo9pQ1o7?E-TKro(ZF_qcnY|x+XK@$n{IFN4@9iJv8~3}r zSX>u;xBblDqsQ%?ci(My@7--1==sjMS~zcS42|#?Z%R}7MP8`-@?FteGDw-CO*x&v z9_u-V`1vb0(PE*G{MN@K5628{V0!Rqz1;`T;|R{N=wZ?SBq=oIul)4YMzP8wr*Nm~ zQ@u&jO+>;LZ`;=NRDG_^vUq65Z}sYTQP^<%T-~~b5_v>FV4v+GvT!1g=pT&Z*u;KC z{@>l*qYltBz}v%F)6<@kn@S&I9LsIH>K9GaL9?LccXE9XexZkSkk-I<4!qvg0*MHP z?)(ku^%2ZfE&i^bzW|P&+D921QNF4>YtcuBe&w|NobSt)zT5k;t@Ec3rOe?w`@6F0 zF~y5%aj9qfiG1Ie-m2R|*;x${=!lem@&^I{zB-|8cpCwlU3l6&3`LS?01T{Q%>mC0qQ7Z{*~UcN-_Hc zGp;&`^dk(J;#v<6GxWuNqHt|xF`q+RT$n*8rd?6CtO1x7zXyw^CaNEF{UUSK_@j4W z)o0a-;|JI1$KaX;VZyR*M0^*1b+b{AIDH$-+ywP!0jjN~Sl`uzuEy05pGbT4Zu?cQUVE^0fPO+Bq&^8Q+04}CAAYO9%A?QAcd66z zhv>0+9li-K_|wJKCab(H`lP%`oacH|&syc%!rW{d?C%wg!A(wFSy^fG3kz*$XQyrW zy>-g%xWaWQY3$*|8lwwdShfN6W7;l((QhfErKzms4e%jO*3(RAux*g~b6s=7E3=WU zX}z|2@GUHXlRWg}miK!!75QVo`1>0_{bE~R-^>oKrRBA@wsy1Ke(}}zjc>l));D+B zPygi4w!iat{!V-G_N^@BIGN|ds0+Wja!iJ$Qk>ii^WvX@ICfa>UdYG8Rg@Tjmb{_D zqrmMocjVdmx)^*4EC)(1h`DfV9xjMctH@Ue$_i@$P{BH~V|IVwj?np8nN9%Y{rF6~ zaeX!Ty!-asVV+yJZlS2`p{P%{g~i3}9^BtQhB1XS5(Q>|A3W@6VOBeIg}FG|Ax}@w zMqtSJPDoj@T-MSm6zJ9FTV=z6DY7x60ekfl}>3( z6E|<`4*XL`qC(LWAbzmjt8}D-I~~tauzjDa)h0*CZ!QCRd2V*bE0e8f2NZNd4E~nD z=g#f5Ed17{hyyyCandbh_lpa>PRQK5cMnB*t1Yj1)i{F548yl5?OwOMw9u~mjo=&C z+S1|zJm&j4WgOa&KsrhvJ8)g!<=HaEE&9sY{xYyj9C?KLCW5pH%-9;d)k5$yb`+j7 zj{dxNp|}={>)OiRmXMcT{ktqM^tZq%qyaV5$QeZ(m3Z-p~Y-v?kZ8Z`j`w zH!kXwu6kAaw+tkmknQ?KT=DX~eQ4Plpo*ilW)zzLj&|$CtvhCI3_pnE;=UPfG&6!f}tMg0k#@a$|H`w0WZp(}fUca&2UVd@4y?AG>ed`zeI6`_4OB; zGp4Fdtw(K_vhN?!c6p~fb*ZFhM;G%hOmU+jmqW{3g!DdfoFcs^e&?yPxmnuAtQ(zO zh;`DB@i=YQY2TVF=wvBnN}J?e$y8;6@}SD=LZH^g6w8wKZ9Lt`W5=mZ9y;!?{IbZK zv5QvPW4mxC?#GGeq+!Omv~?$^(r1|uVF08+&Kppw$P!x~boSXvYD1J)ZbUI1>2vzm za0vo2Ga;>9gg>XI-2_4yd@f8UHpviBmdA1>CI32V#wprcFZGCzxaIF%|9h&+cjDwL zU9GTr&pTad?l|w}>OxzbnQ4!otha4=!8*5eW5nzEK5$F}^u8a{SY*+te#myrk7wnh zFywRV&3bh*G14Ct#w>&=QeNje7Lb{fo){sWKkIXfcr(Ze$LvlFE6-d=i7Z!c(x&|W z>kjmMyhZ!oKS1_Qv}x;$-2Ij?Jw@hzTtqlHLN*W<-cCMcu4?i3jZeMWJ=MgvvbQT{ zGL)UC41{y*}~MM_d6y>RdZ$M_Ak?5AxH9o7Xp7k~Ypr6@Q|-Q@_d&8WpSo&tQQfd}W0)-NjpVwQ3Kik>zgu$!T2Vhxs0$Q+UO=eM3&_ zKC}2M`x)OuO7<7xsr+(5*Lc-Gd6Oo*4xatVU-ME1n6?&ps~!1HnN@vw$-$gRjGj~N zAbg2m>*AHJIxwEdkY3hS%#UWSYVmh->^0DHvAnKk&W0!ZJ8Tw(2_O2q@VeUBE1_NN z>HNT;Wkm0@w-HY9ob;0qm0MjOLY=yB7%j}T4CibijiUdLknwsbB>Q+V+pTvwe#;1fy-wsG# znL!@?sbBH$JJ`g;9m461?ZL6K`K#v%v!EIciI;~yq>LPt+Zxfs)|M9A^_AspinOP6 z-rRAEJnW)xc$Y9?75bel2%IXZH+>l9+;isbp@W~+biUtBkM;S)mE3$YKj(LM)w@R8 zEbY^_H46{TGG@|s(+15i3%{Pk_nPL~kT;fbRW|RX4NqoV?z46Tzk1s^X~ubP8+E}q zx?A)waI@mleo_#4;c2>jC)3NZ-fyXMu#m8`GjFjvf;R90`J7OR_a8iNfBN-rwwbww zwu4Og=G~3OuZA4gMrI zG+|ZVUT(`LJwMy$8rj=V^J!D?ljicXveAvpgTX;I6)B_Kxb1DW)9}jvfwGgn9XRUO z=>y2g`U+2GT;9v}!c`qTv=c#0$WNH^cV+cj*84m-ncJ^A87O|HPkf?I^h?C} zcDC++WLftEUHtvE&n?r4ZnW24d!v2k$A7x5F0QtB-@Vs1H@4f){oF6KpZS@ep_o>G zePf6k$b>^C5VD9yh11y`S#ebADU~-00~|6KJ~=&xah>EqVL9Zz%)oma@d$9NgiOrw zyoW-vx4V;5A_|IL(NsyZ(*4eji=gHA58+_rli;aLYn{*tU>Y`x*$P6)#{c-qqc)(D zZr{F>qvkTu{QN=$ws)n=pfbn_%G53jmWVnr%Ty;Xdj-v$=Ev4j4*~~wWxt*xxK+c$2vC3oRF;k>^?`RzPwA>Ba^iSdtQHxk)VM}7m>-F&b%d`zWhKso~r z7UyR2J*}D9(VWEfN(N6AcumyoES(JL=KNmn{B-kszUh=!mvZ&F^mNCnr+l3V@SDvl zg$h0u0Ixt$zhgT!ue-W_trmHgmltz7-i2aM3|r5N=#i1GJ}E;6$<%SajRY;COdIBV z|8>0A8~y22jr)w1w$BS!i1#*Wqa*4P*1P71|7qL7kZe6TRc|4CEF-F1mdJKQ*-?GVxzAYP|9B`sz3{U<>f2;)r)09rx;b~uq zEtt5%?aG|N4=+j&=tgU~~ zm@cTN<%R1qP`qV3y2rK7aMjIG!O_8;a8V~$A2-Y^9Z%aKy6C~7S3lRa&l!9Iwe$-o zw`wrl!*#$rq#ah%ztf0YCewJ%f)Mm~^1Nu?mrb2i9J_eJ>iDVW!OJ|CMIa{?(3j1| zaZSpAYk(8-(Z@~S)w5}9()v7nVw+ZPQYUhEdvsaoXFTI%@^NCO9h{A|0dyHaFEr+M zeD30}AFrtaykmfr6)Q*NwixL_rn%BCWZ+-?-LugRE^qmTAvt=Q#05q@J!AUR7e*ZZ z$v^tPU5Tvw+^r?jGCrZLFHTRi<#|um+iu2#r}D$=UTdd5V>GfkM<#9Ed(a-;z1x2>w08*qomd2Gu|^Ne|xGB({iI0OgeDs}Hzr{suZLK4Y_FuoH>@^YO(uahY? z!D2o|e>vNQ7;)-1E4WFaWV1J56^~}&hVii`?aB6LY+(qDSB|gu_Zf#BoU|kIubj$= zS0f;YauRBqDKhj*%K7Q3%++XYTU8G=k?EYu;P|X_6;dT>MS@kVkoMSwcUO zWdT^Y`~_0{Sa`~IEpORhIro$PqmvzdKbrnS8(7@}h%&}M&ezTFO zlMcDtZw^$}I+5!t{*!cDIqY=k3nzo8g1A6W~}Ez!s<2&SSbXD%{jL)*$&JG?eCs zkzvKPeepXZjP@};>L#6uc8q?ry}sSaew9Snj;BMxm@BRA^+P(Ytvqu1>S~P*aUXPr9!j>(z z{O|bQMU~Qns;zW{>-^t=wjaV=+2Zf`r@>Rb+vUTHzE8L8#o}*H{dVrTTfMRXT()7e zP;8GN4FX4h*XXp;4c8tZ%jL=>>QaCINxSG%#3^2KUBGn>H=-VA^Tg4iy$^H*zI>Gf zS;S2{*l} z8X+ljg%el+?#r3+sr>ESKkEPHr7^~oJ#xh6QCZL8+AMG%@uY>jD z?Y>Xd^=2xOOJ7dBdZ2wFOV`$}Q+MQz91*^9uP=YbRsyNNq$!vmWRoiXoz0K=;_v_d zKm6JD`5*u3HakAu{@|;>*M94t{CDk-{^(EJPyg)Cw>RJXwDsI|-Uvtr6n%%9@7o{{ zv-1*Sx^{2K?VQVfuixzF5SuCDc%zp+6h5>RvUPv4A$$1)5wo`4>NexMRw-V z;H<1%-GcBeW+*1Nb5x;GpgM?6r8*e0l3_q`bFtaQG0y^zrFm*D}gJH^NUM# zl;dr4YuB1XAk4P`gJ{9Ii*w)ah>@3Sq2I!=a+4p{PSinWb*SzpB46^hF}QFQCd4T4 z?4VT^Y)~nL>C=d8SjFfLSB||SEU#Ul^z^Zvczw*<-5w4yRN@B*`;=)RblKZ?kzDlc za7NmUgFb*niINu7*9j49;F&O@0cElY+-)im$Yz4+*t!~<^#RTc&_o#GWEoXpG5~-` zUL7qjJZ%fsWm7y;d{Z<+33A|pmA@>sj&bZ{vk**P5j3D|{tjRU?iL}v^`AjJaTV4o zoi6gKG>;R1m4W7~uf77T(f0W9BXH#%@Wow4eI|50f}W@Nogk3+_S5OlOrEvn#p$-T zI>&%@uFcO+wz-8#=sgDjLjaESFrIvFStKa0j6r;N zRCltltnVc7Gq!{}{%37cU6^zVz)kHWPVsA)(t5sZ2`ezbCJ$ZfJsk;k6@RRqT$hjh zXc~ToM=>C7CTXBeCOhGUuf2DCB?{&9c=HqU;Z6AJvb}IVHYV-lav88XS8Hs?IK7Rz z`dmJW`CvMf47hl2+kHC5_uH7`2iDb7I3@)1zF6PU{KfFYcQ@HJNAo+c^*w66N?EOq99&zoPoGFN?f zxFHi;*FJml*K42QGxXAY`XuF)mQF$oyNBE1Dy=)7sl4mGCh_DIO!$QQNj-!XMGv{N z_^Q(MCow`}o`um*C>!5#LKdW=S5p@76#oclCHRkbF8r!t` zt2&XJ3>}ZDXT^Y*6Xd63({2A`r0pFXwE^zYIl4OIik$of&M9p!3wtE<_Lu$}Tv@b| z$AHsY`6N1cS7vFJb{PDMYXYb<(vVpAF2XcDT`wEyr@5-d-_Ks3Pumpk2t2hoGnS2; zj>67PkDI3}+t>;CPqcH0?Du@nclO%-Z@t@Y-n@|wnYTZ60~$(qC+dL1nDv}G+CG_V zzxB`mwEcJg>g#RqXtW(b!!gETH&$2L_2s2}#$_Fu=7jl+D|79YYfG*av^U;-rOi)| zw*8~C_Ah?-op#9B?1XWclkNG2bw@AToqD?yT~i`JI8`B$LJ#@Mn~59~*!IQGvDw7v zd9J(j#-U@%xVL}681bMT9oGrpTG*^HLh%w~;)!X-OSKE%v2u;^j-*n?@sd9iei?hq zQ|2eGv^UDF$pi{8y&_XwMAR{rIA#ncXaHpb3%fI*Z9+#|I*=_^OxIFy^=thpW6KzJ z5xajbk9BRyX7DdejkP)2j-STyGeou(7iF{2MxJ(zDLs@2xVAxg*fB{q4gC{H-Wq^^KiwI}QK$R*#RU+%!K2-kjZDbkk$wgMnjFBHjKpyp5 zjSJK83FPxoK$iKSxwp}}L11xayv_0;d~Zzhf(0|}h;j{Siz`3$heyK8$;-BYtdfa3 zlO#by+Ud$`zQ|u97~M@BgT1576m2PL$K< zU3lN$Up&N!m%KoQlseGgU#0S^s(AmXb`ziY_ zVC8!L#J7!*)^PkGU`MB}3O=&As>R=}@z0Xh{-m?Eht6j6lYV;)`^NN(=yqA;bs=m5 z8SKI@@9bIVTho^+p*s3rHtFjLo6;}uKuf=e?i$DRByCZ-LLEqF+m9RUj$jbm(>}W6 zk@M^Di+I}pOE;1;rLFSLdh!XmOC77D*gyNOO!2Js40?oDSQ+2x1X_OnY4SwmY7b>D zc}-bRo-XdtnD#O)0tc&GFe`mxba9RDE5mGKX&)f%iCaJK;DIO?eHW%@vZ*S%5WF^A z_{Bz_Qdj6;cQu3U{naLNKrnjiM7y@S+Fp9`#r6`i<=W~}=HH<-ZI?a)9aeu`^{i|~ zcc*UD$6PS>Wbo|FR1RQe(U&j}U}bX#ZPWJIp8&QEmaYar(XWZ?xs^f=DSYo@Bj@o} zKUDAHd=DlxuG)#Q@1n4g9l0?FIU=vR_H*~{{r2^5d>fn>veEhNcki}u-P>$C`LsAP z3VfscK&#^KPOkzP@zE7+ja-zPyd%8Q$gk?3_Q}+l zw35%w4qViM&AXrT@Wu)Ii=y{*+uir`4ZKHI+LyTan}uX)1A@^d<(V!&+enSg$wP8s z?Du_{HcWk&UNTA^Gi~+Sb?VZ^Uu6JvA+F#5wz0}z7C2=VVI6;68J}w__Avg(e)0F` zU!G}i|Jk?NZ~yjJ+wcC)@3-sMZ?~WN>7Qx0Z{4QjIS7%Qz>_({u4!CeLu*5|lcTXv zX1kJOchgbn9_7x&15Nm7K(s1tHzuy*@mJtTC*&#nO zH=nZkaeWtl9gt-J0i&G5cw|F57#YP-SSnMwCdKbzfcGAFJ9#iTz@>~w_!U6zTGYz) z8LUw#zs+?*ndA{CgWUZO`WP9KK>V_g3@mSYWk@E!NaMi5Q>UH^9qjMI-0o8vDMc9^ zYX{#*n;xr$WAl_ADhg)d)i#+30k`Y|r2%GFjssB>$#`b0-p1#Es`b zLgmr=kbe{oHn!eA&j`LI7Es)<5FTopRM^R|CL z9qjEw1Fz|TZV+Q1`aFK}7=f}KVUb<-&`~MD}?WfR`7i+RYma?dJ8R zcH`PoyS6gdmKMCaW~Qy(=&zYRY|BdvZGlei)~)MpX>mR~T)Z~Qlh}47e%r~8M7moy zUhlWHy`9}Vb}FyF_F6iigPpDHK$@Wg@>+0}IO&r?n6yc)X={QsU7`!WwzQ5{tTTBf zgB$#ehf`kLX_RQ)M8jti(&(Btla~bawtjha$*K@{u#HDvx_Q^78>YtwpP}EJE1uz1 zlNjIQq-yyWp-Q=p7LzcY>b$)ES(K4qN!d&(H&L*V%w_#Yzm)fh8G-d%;P`#~@M%KDd2{`y&voc`U~ zLf1QpuBd)w+&-^NFw(~uHmptI(%)wQV>mBsVyI$d5(K$k0~O*3D(QW1-=q$DDL!!> zq(sk1+6qseU7Wr@s|iEIJgdm+`yMBpL=>I&>_sB z^?kYhv(^FScQUDy{Ds*3uL)nN9xKiBs_Ix?kSDzM8C5+xT&`Q|CSDv!9(vU#V~YNp zznNr_Mjc(EpQIiOu1JQaJQ^{0N-t4(u4IXp37p7Mjc)SYNj=Sv-trf49f`bM1kK5B7psBxoVHiq)-`)G@# zIXs_eoBOA2V`snZcnS@D@c??cV40KAhsYIhnnXvPg}27=BSD~4qutGARpF7MP^ z!?U`bKlHQAJxz2<<$KEXbiHhfLaqIi|N80{f2~)Ws&t>9@jJZe;HQjRY2RsseiDcB zoHJNG-`{HwzWGkBgLNay((TnYJv-SB_jjn9={Clgbbn(594Ff!eS4?E_M0j1IrPvEH5#Z=W&X5_R(O>Rg)|J!gD5**^dIH`=wO)%NXopS1t)zx{gn z+KFW++g(g5s^D6O;O>ct3 zxzouG+d-Z3GKrH!W5oAUGm&P%azUqd+V>OKjz5f_1tP3BclF<=&U;`Q!$q0?q`3Jh zldNlN(6(`M22RNMy+hjUkO!)M&HJ)zE7a$6xtHVjp=IO|N7Ige=f_9e5^bk$U}8Kw z;W$y6fj{Nx+iez3DN9Z~No)M#8~SSH58`Dbd&a5IZ`4IC!nFW2z6-Zb!cUCRUj4ii zV|#f>8D7^tJISf+DcMnN$M40JwY`juPf=jUu)w5F`;$oKAK6Jh)efM7xQ#e*W&YN` z?<#(^E8;1KlrtTTZ3BL%)ryht9UJ!T)OzVDX}u}O_#b~!xubNLQcrT|Loo(cKQj#K zOxizq#^s;oxkx6@NZXOLlNW9*w*&Nn#~a)5hJBKCY8gxRRYLLd+1jr8fxMAFf#+D) zdqWgCo*1T@NZ|yi|4D0|hD^|Pn@ zkFv0PlpF5$cDM4~-Hr8)wz;vH!!3TR_XxhV@0W(s)_F7ggls}0Zx?$H3ExMD+I4Od zK7F#i)z)3?1%{`7cMk^0a=+P5x)WtpU6;DxC(RZYGJ&oC#?9;P&Wm?)i=B(XZZyiL z@hH}iM6vu*?sA8el1A25S6>>#dbg)#5vo$SBxYT86vmOO%R(kvHVINy_1Y8T$+8tZieS6m)aoaPikUZ0M`p%>oD3 zen@wA#*ZO7H_JQPvie-a2G;ns_*?KTjdEs-da#a_+b&Ag;_szvpTQyeq-BsddCt3T z@weuk%~eNw+YeU%5eowK&VEJDM>kit_&f1A(iVCzef!CF%ZAX@Q3&9bx>6mtaP6OScc<5Ji z+u~I6hCf4-w>bM~zpPC18d`Zl-Q425Z0zL*_#fz=SgeMjFSq^c&wz3pG%xkmfslO#;f(yd- z*Xl>vAY?m%pwYvymd5uML%+32a{g0x!fh*y^L|e8c6;&83+?(EdioTwavP@Y+%*k1 zzNwpn7xm;AN!%=#8^EFi5;!_~mUde018cjbz4gx->xJG$a{->_>)y z`BRqUJ%{G@<=TJ^842}GtKyF4`Jwa-h8C;Z0xAN=7Tw@2IP)<^P6ZNRc0 zlqYMWV#n|NrG7h{#IY=X0^@3fhHolv(nyD-?c!NadG9;jN+-=y5+0P38fi(-%s6!} z^cS|{6w|tI z5m(74Ssa+Fgrsw(%Iv6(=U^p`j&#)-r)fb(u4>~2Gc7cHm3Y!DN%{qpY!z1trsA*bB#c5@<=t!7_81)OZlM7CZIX2qWoV?(SNY5$ zEK2a)0v*)+V(NWn>Wt20vE914+HPK3YIkm~v=?rzwj0+L+sg86PV>6Zt0KFyxI-@$3LU-!t)4Jp84=aZo9K8(W+0y}R$iXZP|A6!~XmWi@`k2`%q!Z#;?O ztnke4;gBBw;@PrE0|;hdM`P(xij3v21z#2A-o=7bbt)#iaD`Fz(z)HU?d8JSHfxgS zvNhZ`cG;EBo=#iv`UPeFhPEa!iEr-wqgAEt)cYQf&QF})#LqvwmQNOcf4EGi8xD<+ zAHGI@z~(Qc3^4FhK)*k^d?fP>I?u)Mg9E<*<~eviWmE{CGRF82cs>XIhe&-j#te~z zS0U@Z_r>4$hiRUdZ}rAc8{=Kr3X5#VRp;vAj zje;%mzLOrkJ|Gt66+iKNK2UFSfT@vfGve5}L)!&j)#C4)*B4ShCYKg|DrL$EpOb@>Z)|G1ok3>`*G7-e+V0(l z?Qm*Ld9zK55Ha&T@KghSv?kvub|elN0d#xcpyjz_yxG z#>5qtZFtybpml$Oq@VPx@7*yt2X38yp)|yorq)m7j0lC!(1G{*Yux7q7Vk+bB^*m> z3n>XBe4L{lqz%2)0% zuI1n-h`cP`H6Po@+WbtrePgX{?d-Hi>pQuw8Ir?a#7TKgR%t+g-HvHqg^=y2Z(fKGR^5@8W67rR{L0boQu81UX4%d_SUhV57DiqILhnq$` ze4w~ijyk90qOk1`$(OmJ;DbNc?PKMCk?{&k@fcju$={2`Uv1@^3JJWj{)#!OZP{ks z*fUM}=HW#@XXOOF2R5vWv|RcsX<~dS;~bhiAPo1h$rR4r`Q2OR2;{A_rL>jG-`KsI zewsMWXY_q(+Bw!3&ROJoZQ=V4n>-13KF59}aXJ_W2m81#yqZECz?v6Be!%ziciNXc zK-tXS_9Z>s%;j_XNq)8$Wt45z@@2kI+>{ZtF^iji*D%^z(uga}>;ko?rS0ancX!&< z%zRs3yMa4LA>I#&$f}*d*Hl_{=I|$7@C|>?=XAp z2=YEaY`4ejPulwWdQJ}et>B}*0l1vC=}|XKOtyu|nYJ`F+m@zh+sYg+`ol79 zczI#A&ChvN>R4M?oNl*nt+ngdS2Dlox4!L$Tqw0&%O+NK$pq;uLCS?9Lpj##YP}9< zl*}nXtE$6*=}hM%Fi}b1f{$`EdLaDiDa{8@p0tM>8;!0ASpx@=Ofg|kY+Dz$ZQOc- zY;mn~WqNp&ic(J4$G{ehX^zvLO8%E_r<`@3S66*rT_LCJX=t8&o|&G2=Sc?)Pa)bz z*TN$_kUqotVI&HEbzTpP_)TTUN|v&|87!?!7gRQt%$HWsO`a!S+GY9~`?P8gH9pW! zouCg@UsCTy`sh6$sY-B9>6-MfAzBm_2~oZU=$q& z*Ns!QAf<{mmA;+qoQFLfoudD|C}+^*oiYoOMTbcM?M@heFMFEy;7Wmum2Q?HYiR4u znn&=Fo0X9z=#Pq@^HX5LNPbR4ok>2qkTH@%{mZPyTiN7yO}%b-fx4fFjB~?kHs_H} zDyd6LFa2pIc!Vp$BgzNMn)mhV=i&NsYW)XitnYG@SYQB8FE)J=*3V)@pA!Ivpn{Re zCNcqjy?OL@7~A_Gi_p0YS{nKKZvV8`5#oR({qsTH#XEwEx6nNCZ8n1PkVM_ybGY)+xzXo!wtr`&}w3~z0KI=-TRMo<+HbpL|>Qbr3mQ+t}Yws zfE1{pHRdI6NU!9FkprYrS`c~HXFlqU`1?Et@1>RD_iZfitViQm?vz^IkatK0{fT>IP;&ia*JLXI{{=p^$Le{v39MmQtlvx!Mw}Pa>|l{wlwo+15UVfQHi5|W@g$Lon{ud zp}Qx@9k7haU%;EEoH;q6QUpB?PQeu{sI~0S^vZItN;#sVJ~*XLMrYdMjhEV|uD{T3 ztz2)nR#)k~Cfl{;>2_@irFLm%AIxH?Mbn`O1+$pq2<4&k&ZPh42%tE+49j0);e=#qA3UBXNy zFuTq}%R56X+c~@vr31eTY=tw>p}l0lgblM{i8l1-q&?QW(=xg`QDLneXjOy5@WkUs zVFjUI*HhLiElzNXukH3U%Cky$wGZ37u5C%b?@2-&!{8g^48wqntMcAkGcsQXZ-4Nf zC+Q^4# zg?)sPYT#0fxuwShcX8Xc?KP279C&~{Vv~mB|Im^bS(=of?r&8At!op zot((^S(cSdC(tiL7yM3knODESk>ZfP-c_As@z}aGywJ?T2B5LhQR-SAX>NI?q(95) zq9bweCvIRDoX~*>V?jWyn#lW&I$xz5CKOuI2t!>x`ak}<&8KvN6Lepnb7CXbMXS;| zyn4-V_jzNFi@)I?^s&$ntC3Bt%f3!~-VK)0DmVwRyi@lQ4mD8=JkVLXY62s?RIqyb zhQ<;QH(D8PZOA;2-mT4Ikh(r;i_aP8lEjn0epjp(kxJ*y1Qm#Tk~t?e2+#H4A@6Cf zxy`3b0HFTwB$PPr<6lQdeYCmLHU=l{piQ*>6ZFo*lWc}OLmyt6hxaB&+br}^H!dEE zMg~!&mV@dVScf;l4^I5RgH)iy9jT!|r-Okr4V|V_M#mXI0*;gQHrZ&JxazMi*mw%m zY{nV;{MP^dzq%4x_vveXt5;qX`;;KxNgRPEmKZ-wE-=oKUewOvqet!WJMXj^#(jrp z$L-b&H`~F+I^$W!J~NB$cxSgAAfqPcm)pPm!_D?j|J}RLwdLlYS8m^d7f;&T@4nOa z2ZuQ+<>uzK>B)9$ah5unY74k;yzvslIb_`6sQt5l{Ri!xM?2vQ$6bf;tW-`T#aQO> z5q>9kd@-jj)%_~^Gvik7n|X!L-=XiE1zjA@>-}!9N~l?J6@fd zWGrR7;5j-wve_8Ei+rF?9Uo|HtHQ_z3&($kb?xAUafZC@>5N)n1*9@r76R4@73}F4 z7b-HjP8w}MV(nofONL?oH&17aohv5v*2;Kg~$uk~AQE`XQ(lxJy2`YjJM zQ+7&4U3tB(A1v9K{JL;?*>{#lnwq}9uF%EY39rl^w+-7CJ*8E0-Msp|^Q~X_KPQ2^ z33|tOw&85*2#vA&!L6>Nqm2H6L&+p?>cT=baU^bN$Un$zwIrF+t*$z>P0_#MWsdx^+d4Wjdrmn{EIxbzf$J8;4gpJUJhJR~krTWq8^kvO2T{ zgneM<2SPjGIq|}ui%Tw8*!B&#j9Gw6-bN|9Yn_X$epXwiH@b1YYz4YZLm9NCj;lIh=kpD;rIUIcK`1Ewzd zU5LPNj+cd{HmMgd}n_F^r91T$TsStp#1Ej&n|VogD!G7 z*ryGTP_^FvGLbo7=Q-`qG}6(wneh#{DyzKVL){^L95!;?v61osd8W==x_3GTpcJf{ zEG(Fp-J-YP>-n-7#*K5{{>c?B{%%gb1zKb6jIyID7OwXGnXjGzV;ADP{tc^a$(V(r z(8AlX?bW<_&e%h`Kxdv9kE%z}T*m3sCufo4v*CTTzcxb_xjh7(*H2;`9PXn#d%NUb zHkwAXxLIQq`9C(Rwio-R_<4ERjSRE=_?5MmK8wG&8TZbp z9)qWs)%MRyNjJCHce?QFXAtJ`&%pPN?HA|$T;d${Lp=KkcrhDvQV&?d?Zd{%&^{_y zKtJ2rw0a#n-7Vymi@vLCi|{>#7^UACgP_iPLzl>i(7W1domQ4|LN2-9FZ9YfE7c0%32Zx8! zFH$y`$IU@|dx!1r-3M)Fm%f6&;lbmr_Rif$`IO2AgOYt0mVlKejH}!-?XaIE3=(xX zn6LR5U;d{2CKLf|bm7ilrphbFIaVWuA$cE8G`@5*rj9u1N(VA@4rIawUh?rd8?yM> zF1*#CQ!Co$=62iKME|2Kyv5cFadiEWMw>K|Vb%>VvsM92^=@^T5&BbcP=1Ppn=U=z zx466tUdjRLB=W=hRSp)ONmNA`ny2bF?=MBj4hr1P?yNuf$g=JSy7)W4`EL8sFMX+f z<;Q+3N8#;6Y#?DI{4!*$6BaaVcRd}`$$4_a@A#^$si4Wc#bpd~=^Q0m4K(RcNgt-9 z0wvlB@2xzaL+H*_r>n#iOfgY!to*pZ)pk`B7-{I#Xe`W-21Gt#7zbEnD)VVv*!KDi za%%S=()Hf&#UUbDwAudj*XLbyR zIashE)QMqtP}%_862U&k@&-OZ-Uf578yk`5*Va-LPZ%-_1n zj&$%=8Ja|?QqVXttPlwz!X@1t3i=`n`u6T_CT(22UZ8V&`PEn2wd>at$Llz9C6`?z z$r% zOveiiy1AnjrE%KpU*I3=VRdzR*cPNssDabd$p`B-;T6)w({s^A=`R< zO4+XT@^KVwf4$4EH}RP)X$uFvLpOZW{VK})T%nYo{G2?cp5*H&F61eX_U(UYZG$BG zWbyZh&sYPO?Z?qPi~skh9G7$X{^amc&9m4&jpgOg%l0qMeD4^1aE$L}o=y4TAzX#I zs*}IZTl~d&CakypyUOqRHm@$ag_!CCe9`+WiaoHqrrk8=wa;Gpyt}=X+d15jcEEtz z(+oA4j9gA1P;y_xV{CKz|VH`r%r`uExkTG_YsRy?Y25rn#pdO|-jLf6GRdpkU& z*PlKKx5B$TaEIVAm3`sxv=LI#WVop7f&lrtIOYigCvY-}gCEcrxDdy5`o*)ihUZ(X zx?Nve*G%Q@r^Fj~Nm0r1tMqVLaZwgLXVbwtTg0?`(PdFB$;8@oafuru4 zNp$ffeI^Rwi(HK+Zon{}G_X7xpFOdgZ!`ki&yM<LVGbL!F8kZQBPY?cwH57JqjS z{ife&zPGyVXGhRmr$*1(wWaws&p2Ryaw?0J(Yq~2XREF+T)={t;}gr-;ipHu@H-BQ zbuo-GWU-rZhjIEkuo6Nu%3S$?Ga39h|Mk@@{(k1hLdF3yjP-F0?e_PN+Qi6NTb=ca zO2!8>^X+hZx4r$fKY|VuZLqW1ZoPD?jUAp4cdN}UUq@E8_VAs%ZEAL=?HrA^fBM^Z z+n?P(h@O6Z^?KWU@;KiO^rX293T`@>q7GJP8AHz2NzY~CdZOPA#djaBw}0`~Z?x?J z@&_VV7hWA52?0Hd#%=QNI!oKUhJ**l0V z&93^6#+l#%TG|A#>!fxqSY-pJ8>XR|GRln(woi5PsynOA1ux1fFJp=?YjcDXW3~$U zC*woHQws8|Q))+yookU877c9671@J_5|s^};#+)D@k)lq_+E$KB(95mS;&IkZeEzh zz1T#fOp_m#t3EqHOrB)uI80o_tMS8|@;1+rh5dWdhmV1gQ(e&0Nh}wBb5$Vkvhb_l zwB6X<&CHc&w|MLXvhoAJe31!I=}MY9^{ecuHj;3xgz-6@jmGK=H4r5}hE&o+-qD30 zY*PwKV-X>8jaN<{_KS0ocVPx)8qeI?~JX^y&2Xaw>2-(_^T7iCz_+En`~e=e(iKPt8S^W6aZU{ig2u3D0*~ z+)eStquP4#1s8Lv#Sl`6OJIvPVdjf9PTHU8go_P4pGYIGS6p$F7ptwNJmTHOJv`XW z!H6|@`o`KC^Z*j?YmpGY?Jl$e3f9HOW8|sxr33We^(X6D9zA;0{`61(l(_G;hYugL?XB&|&b8Gw@?UKWGqkCR>D-7g zjoh0i?+FTWPTw%^!q)U`n?aVHqbD8i?6m4K*fr>3(JMoM{mL0Re^p7JE>9Qw%OGVObD0X|hi7ab&&ykouhrss?2 z+30EE4ePn{nKc42Q7Jt{L-XfQx5fT}GQr@I@F_iE~F5cJ=;6jfxWWgzA zIz`WI<9jf~0BGn%=SRdZnR4O=og-6OpL4*Sqt4K!skfPt#}v)E-UI4$zwICFV0VE} zn|6K~T1Ga|-?%{rs<)%F+MLpV(lL|)H)(HO&G_wGH;63PrzTyv+S=HFMjkRl*NQIC z)4yLEp~s56>g1?AD*b`m^RQMaSAKpSnUlY6fh=Rv?jdqJGD*IGhP((I;`DBBOrnHT zs+MGR!w?pn`D+WvhvlUu#)ZE4(*?hh2e=?>-;stYT|_=SqGK7&SKcR#^l1}3r~LS(LA^JR zieGC;W@egd8~z9_m-iX_YWacEg&RL z{V2MPVcHn|A}Ve2q6;?+des?O2f)uo_!Z6+<5=_VJ~!m`lXakN!h8&yhw zwoI9a2+qVHg8BOFW&|5Z>XNwT?l*+z7nj>SeHay;G6Nts`n9F}4zkX=>Sb2`cV$da z1q|)Z`p5j_?|=GhKh=KxCw~GOLCADIBk4eMLJ)y=in3s5mmQ`M&F@AX9@e)FTriB_ z3c;%IDs~b^;pK^0E4o+KvdaR~e>2t!GkO@!hUugMZYE&-g)s#O@u@)lhNLnK@652W zI#&TJ4%OjBbW|seKf;1%zX$9!3{M!)AEO+2wQnhwwV3GlWgXxvoWn3O80phUkz)GA zrWm`!6JwS&C^Tn;d8dl$*FNDP2<%-}8+ zvZD-mmd|ewD;%5za?&I80pbw@k$jVaJo8->VCT9)(rI1rJ*14*VgKE)!~>=S{H?9c zw#cB(4(xNOPlHx)WZ^sm1O){!NJo~jHtzUkDm>|20(YGHRxzC+{c$_+o50&U`Ig+Z zo44C*Z+r$JGeh~I;|cZR6$H|PPM%?1P7})l$G8qO$LIka4aF|eIS>78wJ40LB` z$WHKzw^vhmzrDPukP@c>incpQOF5j#mDu& za&mOQU}m@Np;PqV{B`kH{iZrC;?tiy=@R|SXVYWtJ4@*|kJ8_?={qp}M1SI3!Y`T- zag0`*o77*czsi6+13}>mt4~vTCJ#J)Kb3wB*Ru7d0JcC$ztVIGpD{ouA17iMh|t%o z*X0^K{7wjI-O2B>xTy1HFls(2OZBPhkq&6YGm|=m_qtZ%5H8L8^84{ciUiRqb*I1x0@>q zZEcdHRiA zY2>1>Cm%c+G_$bKCc$TCd(hUm_S&Dk{iuEO-e&5+Z(t4>sL9JRUFar{N*2l?ecWuF z$xiYMkM=+Org6i76mpC)KRey#W~Pu{BW(wy_pp&|M3vsvZscdLXs*fd>8Y8FC2N9Q zIqJl`0SAFP98(4CE$o7wJT)Ad z7+PF-O}Elt*zg8Uh3hM*{(OOyZlMY-rtr)Aqzw#=e4qIS z<58Ct4qW^?7F_tr!)&`S7xk^PObQpM7-Cf%jd^JV7pFY(o%EQbEqEf(+s@p0;b|Th zg{J*X5@Y50RmRL~%h@1(eRZL|{^IpE4L#qz_o(?T^z=XEn2BNAHBYIt$ZwIA>*WmO z9=Q1Awrw{>NP{dsN>fP!jGPMM!A0H~*mX*kBZY+bsV{GXoAsN(F04>z=5LnJYq%~!xt;I3|YWK=t z-)FuL)Ax}Y;c4vK&BJ$E(+Sr;(R`FwkzMqU&J!x5%&TZdeBzoWx>?$co9ks%%Tu~! z--q)udPF~0RQVO%)US+h84T%B?R6pJ3dejihep2Esc6V%*1h`cV6YdNwz{&Et4^h@ zz(W7Dd1aE8yr~x#2%Q&l0a)w&o(p|j+dK8$!+mt)-9bA>r?I^YD>9jk>oXzBC+NXD z=V+auJx2B)c{+G=tL<-WwS%plHo)%Tw@=%7ve7mlK5pyxAGR%Aoqn3>n{~ zudBX>09@)WeFD#qd?$zp@EZlNr9q#lf7*=-xV#PxsYzig!Gvu&lQePLYFP(IjCEAvl~=?@+}Xm5Y}og7x2 zn4HOa&fD+ZNAH+wn~d+C>@wz6ZegX3dFa=KHs!&9PgkDk!paz)(kF)By4RWxPoGnE z%47Mwn!7+$#CoSk!d7t63|w$y`8m$8k5zX1+CD6sEK>(#8M}LUQQg8`BAXt75uPT_ zg#1NY@;T#h>xTDPcOpgl*yIJ?(jF@u*Y%cHR@?O4d?zE637uRZe&J8dq5r}rgWmWU zTjdOWF1`QQFaG`?|I@z_g~ZNhc*2+GT+N~ahR{2ulKj4}-)?j9H{SrJpmuV*42WGc z4E-e%#@)U$^dTLv3Jzo)5-p8^j@8OcgOd?}CEN7_(rS>!!0=sM!+OPFXgYu3V}=s| zq#z3s@*htM1_r=%pelWKmI?w-YI;BYgL`*Vw%d1Z2Va|n0~MLm2`2NkWD1KYUSYyw zmJHN!agv>a)pvI2X_S=5I1avLeDTS(a=dg0orB9vPSVk+{Q8ZmQZ(FY>Qy4-Pq{)b z@ES)tt;R&yVF^!CF8J3q8Lqj81nWY5@HDn$kNI*4){u!_F{Sm(!GKdmpU1aea z*cpH`aF(V%FD@=JfSyKan&zG1e#7@T3&7b`O_+RR9^o7F5(nsD`Gu36*yM5J`ZcI@ z*7oUq-`n164>u|2(K&+RR{QMdzTD>LmWhwBBL6u?icl^}z(9r1dZiZ}cX3+!1KUo~ z?z28PUlYbE$S(XEZpYUPdIy^-bJnX@1WioVj$HZGa)vzcOVLv6bNQ3LoC=S<2(L~| zeyH@9ZSl#oVc;&!DMRSi#jAYlIlnHSl-+lon+~sgE|{H5{0wx&qj!a6IR2sQ^iS{= zj$w4f)+P0K*@~n2{Qf&$HU7~RO3U_%`NVu;J~2P6#=+lJ$hsf&;;%YXzWJ+OgC02O zPX2ChZnh)JcQ6>BQ`-MmT6L^U+6o7&4x_EUMY(Ng4e&1OffuKn=qvacUO4c>Z?x!F z>TvdL>36DcseaBuld(xe!kYX6KCb<_W;ig+Q<-{I@1Hfv2iV#59370l9>0qP*?>ow zI)u8PanxI?pRRmrViKD^u&mb)SD0}s?l68Ax9HznsZ|)~8C-k3dRvRXeVDGecj*no zO<#{caEwF#c!*=T{-RsO>D(^tDSL@}QmwB)P3p>@^~JMwz@PI1;fa1SPQUM*gmFR3 zt7Tne@&sm1{;I2!uBVS#n6~EwP0H2L+X1Mi@+`i}#!&+L3Av(+v=wKq{8IcUous?) zio%7z|Dzw1xB2voYr=Bul*x47I{@wZA(OHF*3ZF}#q9gj@5BgX|G|m zJ!lW!dDvzd3*6l~Y5&9Te5>8tJ!#v6!}erzC)Y-1qVMFq?G3yR@Sx368LM-3qmy{7 zuB||c@pg1R+P3yj+Px>+?IHDX%5yd=P)GGC6kCJsQR;)b1@WIW4qc%YFeOL$)D%3( z6GrqFsg;HKjLBSB-f)um=q$7@j&8|Mx#ulhPFiK+cybEA<4VSij9HX%)?1xSXKWh2 zuE}dF$u?EDD>0UVM~&~TUoJY7T%c{>k}6|<>y^lvygoQ!%t^Y)1M;wigfA$Ee4p|W z-FDOeGBK%Z!G-60;}beT&=h`8XfDn%ZeOTdmTXrU--TYbRof(d#ljgb zC!a(}do};Mf>S(s2QJpF&!H7Kr=BgmMxy2q`o~il<~8(%!aVz=twq1cD0pA^nJ6Pk z>MQYt)x#9L5cmad$uwh?Oh|P6$=NEwt$GpX`t+7~*R$y7TglLX$Ic4f^u-JIAHJ7H zQ^=z^#`o7&m)h&E+-@uLQ|;^Dc)RV=zO0+1OcwGPwCeK{kB)A+nvrKwn6y6eDD#~U z5ucvRj5p2u8R~5c_I3>HRHHI=etIIO$^C?si=<{MKbwd15@XKYSXaP6oD^(;=Qal7 zSf5VB`VGENldyiWQa*fma5Xnqed@KB<4nUwK?WTa7CmWr;U+I1d79kr8r7Cb*rP z>+D?z9(g-)`4dR^i#X zHfF!Fk4#4oIzHAmO?bU1T#p^fP%QtSf*KfbnUctSw zu+-*}jkCz8#YyBUa?j7od0Jk%D3|4vVpPugB(e)$QtzIiADWq)ZL{;Ul%pp2v*8mf zjWnTB`et8RZ0kVLrCW8wU%9p)>&o_v-}i}3!Z@8N81J{rFm)&OCKrCUw&;6-XIqBY zP@jAR38DrC2W|4z*88L}ocPwAZO^_n;~DfM+mCedmPq->O^43=$s?9~in`0mU*hR{ z2uC){+^&5|_*D4lRrXb6l75VLN-S^9*xlJ{J3Bkw$zS*c7*pWkVI1XWjS)N(E3Inr zSD0y+ytjUAJL%)X=hPd1-Dqj@_|SIk-NyHwjCAv#-tQ9asuq8rOn)g0y7@kB@)Kw1 zWuPWRokRDc@+DX=6uAq+P($KF+79)CmO3NIPM?pq}eO=Gcg*rCpym zr0ARUnO|ot@uck^?zH`*gXoYa@NLO-=$3rE<-r?V7;~Js0kGO}bO-eXEp_0xPUmt0 zc20D&!DHV|m>w!SK1!WNFTlvVU>_cmTxAIxl1|BCj8sF{l&Ut0G{ZzZK!eU7+LMp^ zQ*@(P!znxolRj?2GBt0aL&hbbw{ALhbJgP9Tw7Z$Ij4RvPuC|fgn1Tz_sVD63k@c` zZa-+gvG}7CP`^=%Fk*3W)E1RV@q1f&x?VOY+fFXWOj zRLXdk;5A^hbB0OjV2>1#Fsq6|b>_9}H#?yGkzRVG;xGy~!_q;?3=%7qQ5|3gY`(KH zd6h;&eA8F~#TXIAfoDzh!X&jqbpOdPrjgA|m-kr1#4%y~6iR-Ke|C1dZEeul5X>rI zUi)mrTUc7kAlk)ozuDHO7e6O6ve?Woxd(@!oA45}_}wLqE3Gr&0GKtwxbXVq$&--t#TV{`xm9$s;1B$T`TCH1Ul0B=uuN8D$e*-Om}vZ; z`i#HAGij7M;GNIVHoL1;SR7EvZyr;Yty1_Nr+loCT7lc(@CP9CUS ziG&@NlTOl1c$UGz+7gQDU~i}GjL)}?y`#3Z>kh$v=(f~8{pRPho9T>>eRgWJtt_Dk z&&{;svoYKS2COqc9&KJ5a*hzrB(fGk=l2UhI(#iU`Q{n)4z9K)6wCn%y0~U1Ah_6` zoCJ`m`3>0PvIK63*(X%zh}c@!=F_jeY&(kpYyA%BJ>ll z;)@qf!hBb-Os};raB1$TU&>M8y}xjFM|I&*ZLk#C4%SnacO?AXZ+lhuM^`8#{68_D zm`}_n=7-d%wOoa)`++Y0^3P~lbUpDzM_v28w{@}jd$@nl=`hOVk(zKpckIDOmB99W zfpN6G4ycZ!$pi=QlXv1^y3thWYaJfyE9r~u=NypM1UyPt;%JhJe-4I3EqSC&q~l!& zJ*Lv+-}_AUtLCFF<05cP7Wqv!l@vHKahIHx-ecxUEx-tA2Up(;Vowm|k^!bGcvGOi%hew&h;rUkj z=@$Le=;Z3rE>59Kt55eQe>JsOE3b5Lx;hrNI7ioj zrXXxU^6q)cx;Jem&!Rs{uNuD;Kh@y0*X??}C8Z(*pu}}>YkceQ^5U=hy<;cGNLG+K zuL}<9t74LRhCfYfnZ(TrWKZ8XSwi%-IKR-AmzOg@Zlmb?BjarV+{fGd?f&{!+dE`D zHtNElbUSZHjBCbD4%)T(>2_mrx~?D%itczZw16hkLRVcf3x4L+>EKQnd1}r<`ak|J|H~_pb+4|@%6$^B_yaj2 zuc$m9Qdi%)_oQv@oiL7=f^Ux6&Fk0N_LH4~|MEg}prM!nXBw-d2G*%UHn$&jEBhV2p6@;ghz9 z&JT&Q@ar|@j+!*m2TlrK^A}$5jZ^K>i8~&4Y$1W=EAfzJUHn}3q!n^xKqYVN48jYJ zbDY?a=Z~qMObRnD^p>Wa7~;Li^z|oRPB^>RsXQ^hfp}96@y%F1@)VfxN8~7v;^;T; zyuw(z^z#D3I3~}-W1h_bV>u!zbSb26N^SX+FFY0B7^mo9-TBL~3U``^ z*juM^TNd<-wY{1~{DGA`l2=Utn@;&L>f$f?I)0T-WSTN-(-(nDjqfP46^oH#%7LPp zuCHxfJ{iB#3oDzGMqG*%2yYFy{&4L}mFqkRF!DvCW1d~r0NW4)@)yuPXAVQ~iBoRy z%-imN(qeRj7iA!>^3mJNw9|ezCrXNWpX7&*f(Cl957(lT&tihnQGH&)W2)3v1Sw&jJ`_tUuls z;H^3OW8W!n)kHG4K)t!(Z~M~kH@}Z4mx~R`Gv&LdOT0zQws>fR=DEky`J0Exk*kn% z&z}74P3p7r8*aNR*;{my&s^+KR%P*5{*^Z1R-9#9t+p?2@{KTDj5~E5lDF4Jk_^*%|%%WBV0LJbs^H#-#Y))_m?N+R>iUZ46u7zE8QH4HgqTBrA{MYp4beo%= zZHvTNn453Qi;GzR*1Gtsec{Hf_R{S;?e_JX*cLvAunfbOlx7g;VXL22MHsw$l7a*kn?%r48@ zDJ!y)cB2fmbn-*!C6OeKe?_tw>!7zoT|Tbu&3f%zo=w-=p^=791w3u!Bj;~DMXhcK zp`!!!Z6xqI*Y<6dYKIFCxY;}+|B%LVc{8GXFQ1ywg|GfPXVWO-L@a!Xl@GEgmbCSG z4RaMvHV<{QD!xEwb^V5VqHqom4s)nV>)0teBruc#wfI}Qq&y}q>f~`GUh$OU8`~*x zwYBhzwPS}PrHMA1ko@J@te;QU%k(ZU|LQMgxNNTM|VER-T0XZbuJGsDSNiI z{jTX|+aK&_W1RhqCxO)+l$UNOkmuzk>vc%6(7N1yOdVZ}2t%1KDUer5q;uiLf}M5G zFEU5#kC)+ne_h>HI{OUuE%ZWM#|M7f+BK3H7jSw$l|BwqSPKD1bFx|wrva-~cm+H!RiVqgbSvO`8-#!Z0MrzwCEREFl zfFVlB8);qT>&i>Q8rLFoldt_&-*=Vk`=S95Op{;1jZZgubYYjCpLJs^b?4__7cQ;) zwxGW^hPd{TwKimzpHbc1*vP`@^t9hio@nU;;@}U^`qb zyL_2)`=X;0t~{oU3N7rPQhw81#Jy}PL~2)GAAR!TMaOp)X8Hujb)%(=|MFMyfNk13 zv0oP@t0>@dB7W4wQf#SCTC0xZpug7U|spV(w0}Q zA?lD9aC0^Yc06M_bPXy@pZ?W*qJvo2BF2DX+ zrZPs@!9EJO4H)J)J~}`d*soI?2m7^ZkKdgv=`^u2ukJCzAV=919OR)fToVHN7wTgn zwn8uyM?>p4!AYKeN0ZTLq%u?Y8^Qxd6bGK8obhajm&qNB^{17wWWEcAmuYB_D7{{z zrc%7QMWdrk*REY_o7-D$V{5Ce;jdFFC;1Mq6F0gF3_I}*qRHC^r;@Eu^;CijdkYJ5 z>Bwy((-{bkK|@a~cv8XP%2}I5If$?$z6zK-Xj~jr@p9rork+RGdcBQ`RRkjOND#?Yq0XlTK-UeY3s( zDF+%fod^agcospga97#2{L))`svu>+5K5DQDS20M2urL~fpvcKjp*Z1+O6TZ~D^#K5RF9HJVXomZ*~>`1i>% zbw#?n?>(e5Z|&j34az><-g@h;oQl48_w9UJ?b`L*?e#al&|Z4swRZjbi{P`?=H^%0 z;E>uoRrsg~&XC_k_9{6zlw6i40|cy#o${`Hy1%!d>*f&kp^aB+>$+&4jt)GfCC-pm z0+hNw7oQne9a;o3f6`l?^Oebp))(&kE#bBWEoss=48uypSQSU}3r<~J@=Mx2Jud%( zZ!P{-d+x199Q7BzhV>mTmgIRCD@Qn&PP`$qvZat+=S|qwX@Ry!&CDI zZ=8I2svMZ7%b|Sicq~@)bc~N~K3X10)#0BqV88d&z4`7qT!x=KFc)wCVvMItvTMAv zRnEU?EIz8aOyk~uxH5b%b>Xn{DrDWS|K@MTA2|((g7bb@-|5}+@{N8)u}gMWoZenM z``&>DC2?Sz8%++|0R3WXok7dacH7_GqYrksHE9@x(Je+_%*0-FNchA+aJm?z)F38t z)VY9fSg&`b-?&tU4yEW!S-eU7(dY<$AC}2?^^}T=zncKWsDFxweO&SN{a|D!|>aSs)OPE|0#P+P>Vn(Q7PY;yyiS>*JM8VBU#v z=U^N>@jmG*zu>0ZJxj+Ll!-!1KNN8Q+OG2j#+0f3zGmA=%+cI%%MeB=GQ8M~Cn*aHO~N%jBMX$FmcNPOiGB zrp{M8=*fe$(m%J`0M}c8O24g15a$csJm7?h-@;m5TO&X4L$`G5YiD=R9&Bv4E$HFN z-;v4LEJU~nbBw;r=%C$Pm~JYK;3O~NdHn)*WTT2 z|N3k1w8sO+i{Niv<+@9({Ivl%{zgXI^IMw}-RA8y+d+so&%9lksxe171zr zfrlUp?|2W~!$VIBTDETC1DKZ0R;Wx#gR#hz({Gpv-Bkbp|MW>jK~z6GzKqNva>knc zRgM+U#oQTiT$po0buQyj7h@ggdKyL8IW1ya!)Bud@oDDO?i^S749_{f9?HPP>ox`h z&qZD*?mZzrG3iNZ>z8-5xr`wxuVc?ltOF-9b=>-*Y`|3Jo8KtuG6zAO)b}xM(@wri z4D+XO5ZUtDKztV?O>iO?l_$PW2v$;0)U8Hl9iFFxzOIIA}sat7{ zi>tvOT6bcN_BdX`HGMxx6&4!lw5Kf5s7 z-u%>^_Nf0?@W%-ly1{1W9aUu>bJNb)hp> zc{M?O%}kE8DTOL9rN<0;&m$9E{GD-OlzIfK%;TIhrcGZCA7lZaJdaODk*38%@|`$( z?ehUbW1qI}HT-F}z_89AT=C+sbzSvc^uA2{z8)ouv{63G?~{~!3hNDT9v;Z|<82p- zFDb!!ag#d3p6bgWwZb#s{V&9-8^TA(&BWuN6VZQ)>9d;Ba* z<=3?{>(F$h5eHA~Y3#R!ppHV+3MgECCfGa0?BD6%u zm~!!zzSsrh31sxblqVI7uJXDvDVtNka%o{9-{93cM>q#hTwARL;H9~RHa|<>PMo!6 z!oXp9ajC5?uf%UWpXZ1(158gA`%U1(!9KeAUOPE-^PC&$(52|#_vrTzk^N`z$Z?`4k6cf3qjSxKH_ zjPrhDy>IXAX5n{0Uk^BFU3J-InXvMkSC?mar1GwXUl$<4a*_L<+;wiw{?JxE>x~nH z+ZNK_!)xYKe0i3>L>*s!NBvH}<#X;dy1YyiY>;WfvEN9)Gf9x&2Z#Q9`)!YLk|zOu z?_%OK`DXDqZLs8&v^4*I@z=1x?C{GC3dGf#Myk4iN&w~StdzF@{LTcwWI{at#9#Se zp}o1XlfN@>#jn&qJD8%&q&;QJ4+OPh~7u&D=(ihvm_sd^uzx+#YwV(glFSK9&#h+|H z_wzsBe(WcHroHvWue8_S_78WV%BW}cF zy?V-8vtx`AbYo1UEW#V!2X^A|FB??=W;33GZ>ONOSH3G_7G`IL3%`r#ULFX{=W3L< zU?D%REGg9UmK6vN7@SaMislK6yosDkz^VTrxvGg?l z;#yaPOHAVw5R5hF3xdoG(?1Ul32S4?S>{C^J$jg13;dMH=JsxT^klPbF}}O=(rfMB zgU9XNdk@>e8S;plHE-o@57Bn6o*zuj4|^ejafy3Ey;MKV*Z^L2jiojrbY&334xr_= z9}2BfHVrTJb~Mu@D}Qm7n;t?`?<*egDsXjg%PDMea!e)ZY9qFX9Nl=K>{Twh_*9S12l1-y z**A4BESLPy!P4$*-22F~?gzT~``3QtC5U;k)7!}axFD__k4%woR2(0K@HN0w0h3v* zC`b!a3>%UJ(g}gWMs!XpRSK6&?|dzhv8JnmP1z!Hb;cn+aaA_@Mw>wx!c|iWoq~*t z>fmOlmkIF)1pgFv$v#mGR5_Cc#p^tiapo-pD!5g~Ha)4bvz-NC8EB5vI z5zH#Oc*Mh!3=Vj2(P^L=bO6t5aimkqZtKD*7<=JsS_jQbC?=jDP??oBE*@@dY_bB6L2i9vlA+}Za-~n;HLmgW8@FuLyHOLz^4o~%a1<8C z$+w6RPG|0fgq~gl;I+#x{3={*s7{6?e~U@}(oQ(mhbMpK6TlNk!C#$@*HXN#?ake`IJ?kZc;OZ7tL@h9m)py)e7b$=_0P7o z)td}BrxB*-?a*t^P)f|lLS?{Uo$;JqFc^0t`u(*zugP&D4`oiC$+wm}oU0(62?66t z*{X>3-u4#4X}d7fM)6K?&m+$>z9{-zbNIT@K8*nCIr>6iUDz(h&@Df0sSmtl3hRp1 zu?IZar6Aw}rtRsX92aJ!{m!>OS^T{+^9<>#Wd`r&h*3^67j>8;d`kIG?gonb;&GL}Tf3D)}|}gNakRhE{)Is_T)U?>p=> z?PsHdUM`1t5XbnXA9nH8MS!P2aM9uVQt4&@)VrqX^b{dmw%!z)#>rz$#q&o$j2@v? z-^!KGU3 z(-#bFT?V6=@~(HybNH{f{P%t5FM~h0>6hk3?~6Jk6suo- z-re}>#PWzc@AZ4)*DIg3E|xk0R&*4ia!k2(#B^`^=1MJ}HA^1Hv+~*Ns=8RtDbcdybprMHh6vkwzYoSJZ=bEsJpl zk}IF7Hz!7@KF|o9VfbQ;Npze z;z{4C(|Ciwu6(CQ$4#zY!TJyW{@=Y4S@-J7EIw(EF6{)8bws)Lw|5w`?L^k(T5zZ_ zppHG!yNCGsv%Blw{G692`})s{^iXb#)^;E*Wm@ml#Btro>^HJddTa%!nOp8E|M zQli>79^>l}>LwD$XKq0DH1YbD3uLv(nRt}j2^1$*;U7Kctu0?ROY);1=MZ4X{;DSjtT#yI|z=PCCwgHbnSq_|z#a%C^&(yeh{ zy%TQa5pI>4U)M?c-)AIbz6ZNFH`$gKT-=zg$#=)slsWB>$c~L2J7+?O2j#09IE0_E zRmNeytM=u1+%~CoZb2H!OIi4(F6)K{7lCV$IoI?Px8I;@wspE#dmfr(L4f#Uq#whr zYo2NMj{k_8^2Sw0b!F63tu!UJZ|f&!Q|taEV#%3W9JihokjOhHM)9AWS38W62jSZ! zNixDax40~j_+P-y%Sue10U>PT8Y5W5r>#>I1rzyxHja-?_1pvFMb=@w^kElPmx$ zujXcFQfB3l?Iy*Q=V-ryV!80UfgmS;o&S-)X>-)pNCJ+lguV$$0rB z8%a8y&$RMv|5-R;Iw>5B%*qWg;3EZX--t>pMDxwV|~s}&t&ne?_;EcFm-LK z#`VC3?aIY7^{svpS=_Z6+okZ$U-=+RIoWISg&O#jak$V1J;Rp-1FCJK+bYo)78i3B zviy>|q6`9X)1vrA7A9Zy0vC%W%Yxh71hQ?U=$DCd=}m3Bsl^&|u}N9v4Rs51b8Q~$ zW*ARNDd&`l$}<-ry%yhmJv^d3%%L3Y9(}qe5f8kImj3<-+3o`GfO78eE?3@CjzeV2 z-U)ptvgM4zoGHd=BUA8@<(ryS&MDvIB^o-xWsB|im z$HD3^840k|XPLkoy1tY4<}K`6_;t}_kh+E!iFY{t;;#nu z(6tt*oADfSQr^0GQ;fWh+d7nodwtV%_Az~b=A5#6mi>_Z^(=K39!jR-R|i&dEh?@+ zT)a`A_4dVW%A#%-IQDteyZqbpdgc|$+I(Hikp}Wswa@DF&15G=4@M<^Ly{-*hX8L$ag|--FZ2SzF+wKm)l!k{PFgqKl)Sc$A0o>+n2xcQ|+xU z5%!~BX+QGT7u%=a{B&-EoTNS4Ry`3ceMd(9J~*k?9X5;~7Y}!8I^036VPSQ4>A*HOOHJYwGSABA=A-H(xs4iVJ@vVxu1r%HD zR0~kXx~4pHM3=gQqwvazv_e;&OFxk()7 z*_E?yUXd@&Ti1DgH%zW9%_GP9u`sZ3-M}S&wKk%xtUf?qwp?OQC@yGgLmTx6^%Z`^ zsh{Qbf4O?iyYc`Q@C8s~+TJBzT&x5&gZdY@0~c4a8D_rauW+Zf`xG(V%d{*0LI)z& zGZw#f<)JXw)*jq{(B66H9pr*n>d&{MV`T6F^7)iLl(EFW`~5#``-kw38%zuIP?i;>cO{F}orN1dgy!B7yuz4Od8wR{xA)+G+ls~w+>SS*fdIc>{I!3SaFMIPKg>7K z;Z^?4ArsZXUw-+e$o&!ceVR78v~s;o&df6g5tcf+V-@;8*RsG{UK`H0JY!RzBGf&r zcW4Z=tcLgIW54+O@4tDiuKa>9?&!|yIu&oD^|~GfkqmR_uJ6ME%;K(f!s)B}Czb>0MaP#0`Ey z$@DI+rZOud|0*3Gt$+$02W=<_;H^TXVtjabfWRKK#iiv8+RK7KLu`+Z3iWJ@9{%$Wze{=(xzvZ zp!HPzE(pK&+UxDc^;_UFm&udts7FY9l}{91taV|T6|{Eviz?%u1R`7{i!KN>%3KDF z?Xhut#WHPy@<~U{W!k5W2%~$Bz4ZQB8}R+lj5|~B`JcaXtD-7iZ_P_A`n2)u@n4}A zBhCia6^}`lFpJTf4g|)yma+Whnwk#pTXoAoZ!Y8fy&7d*DZT$IH_wpH#}7}1 z5q^I;V4$Z0-XG&5o3zo(=0oQ3Ow>OYh97{#2h-{MZ~hmx`1_RkaAo*j>Vh8sN@U#+ z<>D`c!`+=){5|$cHo&R>Ik5d+7Jq%E&Xq|tOcpHBmvn33aS3PfAc66<_E@Di7QCcY zA)+(ta*UgSRPT~La4i>MT`^+{&5M3YQ}JrzCwh&G5V%=9aN$?|Mm-NV3m58gr0H?0 z0h@ZHdQ0h)vG_A!e7k>jQ;gwd+32)+5T3zGf z8n4TffA!vP?d-s&}9aeH_6F0e@9SS^AZFV)RVn88><(=oXBcXz;mT zoUgq2*A=PC04_Y|v>|mZEZ;k!>qNLZc(3!S(>p=pBClcM=475@8|mwqAd`u_bHKZ{ zvQmq`3~ZegsKwudw!Y)y?_nkjMyF=Mp{rl?(v_L<_TuV7yR$skR_E$eqhmccc6x=I z<2uJ8SqR3u`00XhKKlc{1m<0B5QhG=X%~ULAF`A$TTbFoen*p3U%pjWCmYYRU|_oxjZB0w2m>pbFX_gee5VX9 z92|h}o|7T)LGfYnro4AZTkzUuPnFNOcokU#4!k=)IgDJEC6z@kV#|-pRa=WNTqroC zZTXF2>(WipwK3c@o<3siLcDAU=jZKHE`B*4J;qJTBb``9GVl-?VOa%9x%@_JKVeCb zu@cAp`OCtTSJf^|kGJLdnYOer+vXhaIbj%?*|+VQ&~eeuan%HEuC8WQUYbX>VcT*h zk!)wQN!x()7qc_7nN-j9?8xUnTsP0q$oTozC3uTJAck(rz&mL<;#d!Qk4-pso#Z95 zgZK4IA&V|1&Z7Z%q$Ty$kMRt*Y?}C8=p|k@pkQsgRAR!7pLCeCGhE00H4l^5{PV4_ z46C}Sh4#uTu5kQOm&v2!>B`^K{;OwAU#F%qJU}t_4`m34_J+&d8f9$yWcX8F^cvnO zOXcNQe+(L4zkRKJ_S3JnjmP)eH{X7ciO)=N2noD%O)bCR=+Ac`IYm9CDG((KBcWG9&?Pwb#hGQXZfY9ZR{L5FqWI-g;=^ zgnWG`ox@)pjP%#wTDn2C5p_p#adTA`J>eU5DBs)17GF{{@)fQ)h4%c#?~iA3sv>P~_*;%x;7`$U?4iyspnYYdgDc4m!<(sB=%A z>dizux|5|booPJTt9y6`ud1{2?iAGh#xI>m8=-x8^4HJAO=yvep7@1Og-~y#D~~;% z5-g4`|AI2E&(Wv!5L>6WNucS7n@8Uz(BP5qi|?!><)(`#yVwKz>-wYyRD))9O>i0A zi+l=)z=clwv+#?j*ZoP}X1u}{k8`BPb79N=S6AG{-eM7>+Ns<#$Reb`!io?pMCRH}FG{;}hqMr_n8}x0Th^ z_VUZGL|;5O+@lTd!7p{|qism}qpVQpP+r+~Lptgz{1|^#m$sMf`fGD>jWJ4>;s@Nw z37ZN0p>Tq;hw?tRt(X>8@J5I^cy)euIx@>!L3O<)!gUG99A5pL+lhd0I`w_?nw^=- zT7fqQc^j-()7!Vyx&yhPGe!?1tz(?D3*fmK!uqWnDB#!dsC2M>bUKyKvApZv^HhYu z$Q!o1UfxJcUDKBpR#}p#on{f4htg4m*F_da7gv*8O*#VmtNy2dUvbLq;)|p2C{KQP zb?dLDiqS2%`F!m&rPKJ<$>FOv&tdsn^) zO~EHRk!w+eIUci4b*(2V!k1Xqcpo_o1{>BY^y$t+quqtFK9d(t2l~YWspc+9*4pUfoh!<6s!eR`N9V@jXLbj5zQu0oD=oC5_OD6FO zx*3$FDA+_(0LtLU#Lezm@N^fM6EDV5G4T2+uZMOb>rmPgo-6QdkYFv0?65zx9_(B^ zI!{Ldd{6yKfK0d&Utwz9^ujK?C3$w|xaB`Nu=Au&$)gmo^IUs9IWbb@RH-4%T3uYM z$rWj>A|lOfNGZE%Ee=mH01TbGFw+^wpHe!)J+|KU%5PnT*eN&A!JW1)1ef4vAnh)0 z6&dn&aA=%``2{+g1v;m>OmNsa+1sfcImwfqmAJ5X6o@PelioqT*WkSS_P5gsFRiU0 zSRbI=PUL$&PTVY_2wb~+`EQ_ zz77nGQz_)f?`%!Rzs^`)rit-g(%17vtP9hJ1&#i{fq7BFTpsLg>OWx)_-wD{0N#B$ z^1jdWvg`X#PX1o0d4_a8et2sB;El5JvUz_wV4kM}-XG&5n=t)l^C9ziChDIH!wU;T-3 z?CUPxm5yM@C7i`WxW>ooSN;z->S0Sq64Nre)i-snX@qOJ2mRGErb`cEx9 zI4E~=(vx!PG!E{u^!fSjp1KS=P}u%J?MqEQ`KQzU5RWVe*c&N=BHzZgj$9z%auak5oB~Bk#G;nu%7zvbm5tGG6Zr zLw-=#7mo1^?>D|yE)_@q)Rl(roGx7yya=n)O$@S$o5>y*-_Xf*i&tvU?Bb((V_;Am zHxhUa+x*;2bl17Ld1&Io?^zZcc4$)@yL)Zh#oxo@Ha0m29@Zgvg3tAZnfB7PrFP53 z--YR%GAh#3meQU=aQ-q|l(6_6ygO(%a#c#Y93S%?VBYoaF*J3N-WHV~Bp%8<@DLYM zS|$hWfA_!m&#y$*eQIs4`(`m?CdNklJA2W;y=qy$_2f<#2%w**+wv`2uyo9Hh=2Fs zi1D3uT4OgS$OnUiOo+I_U~d4ASw`MZp|`ItPBTWD$VAra%5s}z9B189LU5>)ubW%j z%~Qkjstd^SZ{k=+;2cQ+%|J50Cuz*jQu`@I$1mfID{Pmcm+df6Z7IaFEbvF2KJ^nq z$CQP!Xvfchj0`I^M@~(SdQEl^mye^IgWGbcBuzKfHK;UW;L);Ua9|+XuekoP&^Iv$#EaiC?0FQ9p zkZ|m$AmBrJgR%I+>T>(SkG#^xj(6JEzy1*37QP_zFRu9^F+CqvxIh5u?z8goSUeIN zn7|b`Hwbvj*UdIDlzW!`c$T`JOM5|H!!Pti@I4U7!+8-;qttB+=WX}sv~9aN!m1he z;Z-Yc_HZ+VRFF202Um0Lvx~nyPiUoWAIx$uCKz$eP@ z^ufpvWi9V4MACHm0W!GNd|OJ};Y6E8#^q)@@DrZ0%hn_eYa)xwE;`1_ zKa?Rl<4Db0`7F-alttQnLsR@sEZ)cu>FPH`<rd(9kmb3~mS%B^(s4##7dr{g=&f#knVaKDY4KM_)g(LD(-mT=Rii>`jJw`HT7^4bGJxsi}}&P7XWbwv5dXR}eS^L7g7 z`Ev5Nn={SE6e9!|sDj%s(pJ9?O{wR>-k@!5QJ($%l+*MsAnN824!j<|hlhk=-WRuP zDyQUS`YYRb_>6d=hjN$%b`(7KZI_3_=?ctME&lFIeF}Ql^}={y$o)1ka?qy74%)Tl zvG&F*tL>M6_KWS;f9+@5U;WjeZa@0@SKHF`dAtAipR}+3oBz4}>wo#X?SK4#|Eu=T z{`-I4zV5+v~4>rv2h;by+x)^Z^*#sv{A@#Q0ILmM6VbWuKB#Zf=gN6#dh^z;cEj6WX6M0m6h1tNonKgL zcV2j*Ev>ky?CqZu(JP-kdDwP#HffVyO)kH7?Z>*Ltsc1$M_Y`%NF7^0y-r1KS;wjW zk{{|4wfKe=416HTNExdH)XMPH*1~>~|1|Z8-`qb zbCKLlS6cOb<9OoNIP$7>z354K`%cPH`WEfMH28DdC3Wj(4|4@N2)G~^xhFsJGd_PQ zSIKu}b(PIuc(pe^`p+`?UMJ~%H1Ez5ru^(>x$p8`h#lMt>-_wrRyGm`R^{8rxxgWB zv0Yki@HLo!{^g-e-#=B<;=5CkUgye>_0~ z`mw=&#z$_dadX0ov@#!Htz5g_=9gA!v(s6laU&s!W5p5!V5m}cBr@O0TzWMuE5E8b z%U`tp*f0M62cNlBJG!k9O6MK)H6cbPNCVer$KuWo@7m5zacc)6NZ$-bI)d~H4Uf1o zq|5`wI^w<0rO}V5F~xMuWu*w-5dHjF12UHQ)Q+z%y?=xcl|lTbadEW{jF z=suk+X;yZsW+T%&aI}XQG%d@S3XJ8e2<6- z4pyZ_z7;_JD(#F*+T6@klslQ(?<&tAOjQzOcJZ>aQ5ka*$15BZ)(!wkok6ttLyZUl zOX^Nl>&kdeLO1|*kZW0c1$+WUPO_dJ;-`aA@XjFc?KM<56yA0oCr-{%F25Jz$zK%| z>sqR*RES{M0FU+F4+`v5q=`hX#-Nq<3iwh=gdulWS5bU`Cog8Y zn~(dkGd&eA+Ye`+P5CSYb%?8wbw89Rf7jQ$YoEP3w!Yhvxb_e93m>%j>uCo276;2F zHe4OTL7lF@p%D+^rr)VPsPvSAR|7%y74_FLy7o~+mo$NExd`iu8B=IhKi8Xzr>+K0 zz_wp^(5rq@*FBf3zM~GHF4=F+E1W7XO+T12T>s^hzsBhY#ZTK{QRRwH+aoQdD_x&o zzxW%Stn>HQuCn~R!#e5R`%Rn4Bw;76I)Ay9+a;pJ^f+9Y;MNhZKl$6&S59D@TF>YY z@&wi0pZxW?Kl$rKjNjFAQ)SOP*0InFUSXmQj|mVwL&FYdBRQr}KUP<<%vr3Z&a9jM zB(5g-IsO5TN!4AYNsoKt`0Jjn6Lmb}$qOP<*StBAOdZP?6K)2m%>m&H>cW@(2Hey$ z30>H7m;C~I<;wDMHbVM2n8DFW78`c<25n<|uWj#nJ@Fy$XL2KuboTp}e(Tr8-y66q zb2E&KYr#@uS;UpbkoJ&8DO#{)g*X`{iGER`;#Up zr0L)N&;QR?BI{mTooUAhhwb$EpzUt$w81X&h58(u8qK6>>XGq;^tZ_3GB!Td4yng2 z#(6IMil__jo}S7Hszd0C-El#)8{^71i!+mLX=XYTUQT@Z4O;6sm;)w@uhiY=+pKoRv(`VsQ2XzXF z@j7^juk@K5ukR0fJ*R0r*)0HNo3|#(^KHbMD;XgS7ZP-79T|_xvm@t>s~CGJ&&1w| zE92Ohzu7#aZAS1cF15Hn7v%9$xvMV*lf7Tn9@@$)49sf#om75*Gc`HuA*IJBL*_S zb{h+9;X>c)2EqPeuoT!rBs{Zrqm z4rQNh44LRy5`VsnM_dh5OTCw=v^@;R>X&7GPNo}8x^(Hoh=z90&MlC$pu(<0p5@uL zZ!}U9WX>hej4vHDmA?^9hTpsr;-q5Uq@2!Yq_ptP@v+~x+-k>X2W@7Su{pePGT3e> z2Rm*2{IJa+?>_zdr`yC}udP3LM7fkpGTB+10A^-E01ZpvvqgEj13sh7p_?@0eX0ZN z;_?)MY`KJ@zJbN}9-@P6idv)dHq{tHyRHPgXqpn(BMa$IqjA z%6K?G0L<`@mi*I(ura)={ILX?m-9i>vonze$|~{C+(+WU8TeD4q>(F0$UE~Fj`e0f zM(@+PiC@^(t6?d3Q0VaJaLU3VU=XFT=KbjL<7_UOnVD@13yZ|76RO6yKMERviGCSc zb+kvujwo}GBVr!fkWN}f4w;A-&V^d z7+z5BWE~GhTWw!Im%}<(Ax3%Yedq1sN>5#HYTWgDUHd3_$GKnYjDN(nFH>e(cNKqV zi^YV7OC0=l>bJ7BKGYrL3+M5aQ}V70zb@>`%Py$PKORh}&4VR#?NevrMdx?(Sr6Xl zlP_J{3H>7zl`Gb@IwCTMyu{h>{pR{=#!1G_;xGIyob*xnEu&)$>p;3X$Jm!M^NQHa z83VuS$-JctdE^;a1ctRlRu|qsx4Ejt-;;$;Bgc^&N84?FbidtR8E>C{d8Pf*Pk+As zjlc5q?XUdmPqttFxi7ajU%lD90{ZSd-)!%_{jK))+uv+o|N8y*M}NHE);BzSbFKa5 zzx12!fBT>OXYEIS^e5W2>o4V6*qPY{`s*2$l8h}5kB|?iw0}B_Vl`-)l~j3(HZywG z=9lK+iHWwgz1220H`)euw7s>(^G@5@A7sJ!`i+~R?Z)PI>d_k^Jt;go>Mf#=+x-U* z+dlo<(b0aj#m-c_C|Q0K<%GcrDUk?{dy3Q^}N{F63m|1S)x zT{}NJ(H7^X+sfiRcA+iP&(5L0xCY_DFB^n@ueD7LhH+bl-gEUi;&3d>cRVoVM(y&pL1!QYV|_Ati!` zWh&nBecoC=qaref| zSK%pmqON`}7`Y9Xa_aiI4A)Bh4RXRy9|&h=cD~Io zujIPtGZ%fw;Md?SjVy&#q-!Py7ww*B5<78yC_F7&+^+1}kNx8BU-|3}lvITqh+{os zy+2?;jG~}&pjFYZTrN=gU8i*75TgdB5~M1=ie5q{KH?cShQM@rhVfnnBaMuf;_eTV zXoVSgJu?Yk8z4UF@03phOVHH7x1QaJ*X0>phAAuDWTesS>CG(GQZ9EV3Q_6iBhtbi~-2OK91WHQ*Wq1wo#FYs-Mr?jMLlnSqF zaNv1#a6~!=MGSUb)Fw+hSHE3zm_=1PB9)ir#bp$6>KkY(8w-m|xT9@;VJ`W|4-&B^ zzKmu4+3{4pNbd+Z=}4J+fgJ&1N1#iY>=f!f^nq3x*aI^QzjOw1qY%+CP)4sUvNNeG zBc=maI%l^Y`JEHT(+uNSPaLSY$`iS6pc~{_@0QhFHIpc2E7z~*s=D{?-bW!=YwM3U zC=dKiJ??Dn(y))(8*jXx6X4t1du?xP9c}!etu5NYjkE)mZ1OlqX`UGMnk27>u^y+} z&6_W@7hn8TyLRms^mYP;Q6%;0)gZRF>-yzZesl@yzezXP%|vhcCnT0zqkb6|(NvfAcruPjdc!XDGaTP9D$ASNWa(0zHXe zKLCxN*SZcm>1ZiOO?IiUpP=I$pi6Br8sFbRr*elrx{!UX!{0217&oxB(m@>P_vzP_ z+lJTVOzB>lUQbNl4j$R4WP0A&6-CzsraFQqdJ1}nZU#D1oA+XFzte%O2}nCgjM0qQ z>pB9jXx;xF7vC8XGd6-Q23qQW>Nz>}JG6DfORw92c+y4}jvpuZm40Kmesv;sTPJnu z9dUhs$!3sDd|nBq>IQ$p2vKJeCr?I2594JffK3});ieTHnFp5)GN}un1(@UzG**$k;bLeOe;p{|cTujci>igv zzAj6r0TOtKv!US|(i$cWrE7Ey;yDP{CXKY7^rU1>#^nT`GysOWo(s>$>nDo=7#Mwi zmLzQiD@{#b3;i`NadK8%&BsMwd0`SB$<=MdaRC?z(Jj@_QvdLi^`_ptyu6t2YB?@A zL{IlB;=$2r+uGf4o1S>xA7p}HWZcOb(w!Z)#fh_aXL+jKTAgp#Ru|j!>@4~+1LTye z>e+JW5B>98e(S-Bs}aiK27nq+*8;~yTKuLTn@oMx1aQ@bx*;$1)$fx3suq7=S(wZx ziFUTO+QB~X;43$gW<#Y|f}abYX*aeZXzqAyd(TD9;tMD2b7IO#bm%E>?Vy)RXmgeQlLGnE}3qEaO;t!1&4uLFu=5fb7f1xumbylss}7!f~+1H*jRy zqKj5(hvvzzBVfp!4JF8r)LUp}nYu9oM*ftKEsJ?L;W9(~nhbVQ(FKFU@Sn2B1y1FW ztyKOEAB!JjLQj){PH5ufj0=_WaDNgiauqn{<8^HVXjR`xbrDHfBW{#QzLx(PgNZV^ z6ps*7_!K2#!2CggIE-7VyM;Lyedl6lW~Y&%-u46>fMmlA1Sxr5`2Z&TV_7p1N*vpg zY3ih}C$^^A9OGXnEnS$oeA-vPc{mYYyyK!TF0jPA>O=hHC!WFAwwW<&Cg)ugpA3ys zc4Awv;dkYMeG0VF5Ajk~jm3`a&?9sgV2#hCa{-R`AuMljO($&Y-`K(c7inhQ(QyTa zCO3BlcUx)SKV!_xYBCSwb~3ony9_avzvT<9Q~u;-d)E(~#K7o>-gz(lc>F8ZY(fkD zy2SB>zBholKy~f*N?Tl=Yg0%yPVDyBHbdoGxaixXd_VpTM zdBykQ=3L2);k5B_>eK7g)nRN4R4jZ%zkrNWUvbmTrq?->zofEncf*3R-nlJhq>EAZ z7mu#$H7@rO59g=lXG4;a#2G@U{q{T2!nI3LA4FsuL5kRDhr!U*^9=peMSje8Kr{={@H zJPX@?wEw2GyyAPW%AJ|p`Sy%kr7|6-NB3GTvv3@4q*5W!FBpo5-lK z_W9Rtw7>KVKhpl=zxD68-}tM)*na*eKiA&+%uDU1TT5+eZmccNPqfwL`Su#J@khV( z#r6|F@e}PUKk_w(2^Db`-j++vbYq z$+^^}bW_cxh0rdJc!zvMtaxL@bWXlcwtaM>Z+!Dxxo&(DUGMRejkbsG>Fp5n3yW=b zZlT@1_n@tBZ031w?Hcj6+oMNMAhzF$u8k%%z^?F$6KgoGbRLFvR)Bq*h)mRU z;r=tuQ*C9KuEP6Qy4Ak&uM4w9^W(*FHZLnT?4Uy@AHhL*mdCKHr&SkM zAOg3Z1Bb+rH?$57f(sIc@uh9aIF32g#k1)Yb3(r(05?hcZEQE&hR)Q5{hxI;#~9aj z7jbcelN;~U75CBml&vc(OWDAwwT`ddxS7-WE{vaIn`2R13iykocmzkNXI|0KzKcoO zz{4_?En0}1;hK;A;_olLvJfS;U;Ob~KNj6a5r&{VX?Xmp6xh8WR|r=qsYc7M#x266 z`24dj!&VYR?l2wC>0pfq><~*KB|{m5XW>}keYy}njAi91BotE)j7nKCZLUt>S>wc( zWzqDN(KB-f0m8!?c8bvP${wRdPzG`_ze4;NWzO9@_5|*v-$0P(8!%mGk*=23ly5NT zRk_HBEq)ciK($%RS&q*#%Y1<+Hwb4-OD~s-0aRH z&j>ftd0ki(KoI~7PaS*B$O!O`P*N1Wi;GL`1eoqdCmHzyop5&tTF19<+-e(iVk&Na z3)e<^FgR#8Zmd$4QZB^Z_){q}>E#3JL>z{~OUt`76ig{&Sp0d1?N}=fvaTho$u`{# z;N$i?*NADIkjQ*X`4SlXM_hM|cwMvK&oX}(#p@d#-ZyXlhC?HjC_BKp`8I+(NyEE! z=f$?MzSZ`2_S+;q{G)ph>FjE8d3|FmlVmTv`k8c+yN~a-)4lb!I6K+q=+M@#Rom$ah~_4wc8z=MO+ zTKq+SFg|f>ph6I_v&bkW=If8Vos3K<|8%3*b~d<$4yM=Nd5qW@zYD2;V>%ZfviOT0 zbM#i!a7BU0p;M;a~Ux z*Uz|Q!54kB7Jf^Qc7UAIzt~)Jn|iLaW+OhqkB2N&se4=hPSA@hSvrQuq$#{=8sA0t z%p_2q^vb4J-Z@E{6Gi;$s>TWz&y+BFE(jQi^?k3`js}LOLTf?CddPQ+2+yWW{55G; zn>-IFQ#P0a&xsTlfBh!c^3p;U95n}?`h^}|E9~O$&hB2@8yw~vQKREi(E7BEpB=W< z8Fc&A*>-((p)Id0w<#BY883h!_&T0~Mm?>1>ob|BeK+ua?I{*c0s z=S2455d{x@JAMP;X`T&%XK*~VIt47pphAjVBaVLI%C{~)$x{>xIvdkh1vflS-Y(YG z1fmO4wMd=K2hhdJaC|QgnH-iskw@LsU-EGro$ved6Q1R;y-7#MsZKvR>MgSWJk z($pN!;)(+;GFeQ$IA4%SOkx`~+qJ>NVAI$ur!bUD9PIz(@op|9R(ir? zk;lW*5Wo5zH~7{GBiWGnd1tJO>3?TpN}f~+&D-$EhTwkM2K$?gsYlw2FI{WfPu^|6 z`)~eL`=hV^e!Kh5yKQ4*yAAdZ+hFIQje*b;jK5@FZ{$? zZE1R}U0<1NpZ?VC_SsLr*xvfwOYL)SzSutf+6(Pduij{{y>h+1_`+Jdb!!oxqP}f9 zVgf!>$bxD4v*W1|`UdAqW~OUV*w1je5##LasO`}nyk>EF3SLwWQlG6&ObKecC&1d5U(O)0)J0!%9xUMlRWp)#kCl zmyb!8JW_hHq#W|M^3A?ooPCk}!QF40$0%=o7iz^xT%GiDrs2UpeP??>U$D)a(VU3$ zlWsJc#(V=njR)(PG*l#Ik2~xKS zeO0pazKe@V9rLUCQ)L0+;1O+x4r9W3N%+p2_Hy%{ipWT%85$9ZDfs5u!%t1=wTzf9 z7}I&kORvslBP}X!m%fW1`s(uYo5gkF*HeeJn9%Db>Yv6ndhwBS#D#T{%6IiFw7%@R z*;pD_l%M+Y3SQ?xErM;(gDTdUbD;K<(W8+Yd;5c=uT#37{H^|FlD^MA$bN9dK+`Va@|M?9i~Qi{@V<#kwyJo^oY`BYxo zt~?EG&`ESfB#XbPK+CJ+zxNwy_`RB|TKt{A^QHDT{`y~O|GWR>H`}lO!WY_$*SxU? z9c&i8W)zume$V6^}XL({I4-bcm(+KbMwgP*{a(< zPWmo&0bJ`&MzP{MSrEqIPk(etc@R2gqnrBA+-$B}UYIYpzxLnOo^Kw*i+?L_W3*wMkDt zR<|e}uAb8)hj${Aea4@0rAEAYj+d~CXE48E+IkKw(>{~V{Q7Zry{yvYfBw|dA#Z#b z;+5O|)9o$)l1JA!^|Gbh?paG+B`I-jujyx%%{+S`ZU4Z{sNTjp*0y$b+M_2M?GOL> zPusiq9=7}VbKNss;Ad*a=_gX|YC07gIq5VB z>-;K%eRv3l%>Ws<7zpB7(Yi`)!z5?ItFcx`U5u#diJg3uf&@hABwp>>vh$Xys2}29 zq0PCQkCnd0Lw$}hH>t__~|HZGXR$rKj>m)CBkv$sR=cc(Cv^0 zDom9HcaxJP=>SfAl{y7sUHLo$1J^E02V}iauxuii@<Xh1ZT{7A6z7?cJTw-*0!!ldls6DjwdQZXF&U9<)>P84z!Y#$^YwzrWp< zmKLMLSni-^&cv^U+FH0yBU33!U5OKk{p+3+rW^V@7@-q^4uJ!Xx%Syk379$gYbSwU zd{a9#KK*0V4T<8nE^Oxt3BQG8Oc*vNsvU6K;6=m1`SkQ`uHl%?;_plwn`97#|Hh4* z`KGV!!3A0u>b=6llNC>%Y_^4kh4$JDH`)mU){V#aQV$DD%P1NPnfQ?7EF0N{7i-d6 z!R}REr|EcCmKWRN!hDpA_4Ox|aU^ATVx(_l;b(fBOkP?jOmRR@!|E7&A*;U(aR?HQ z9Gssp`igqiBzo0P>Ijqi>HL?C`S)?+lD0Z%@lg&GK6$5G5&cUZea8`;I(#aYkol$U z`i?l-E?#dHxWE7HPZobaF`t-E%>VKYJ;0U7x({>h^Yij}URcTG?t%B}7X_f4(nHEs zw>on}6MdoAv3gz4_U1;u&2_Lp$WCHS7D9lTLAU)^`hm(sd2Rn9E{52N?8}$M9o_gXA8~!?Kn-ChAh8TKGQQ6Lj2Rm%eLy`XI*t=U z40Ie!=X9Baecl;IoQ2=_q2^NMQg5j;mOkWwxeF(((iMKU5~&TX{=M>)FAqe)T$G=w^XT9T)x2t8jHIt^-szXx0f$`Inq{ z?bE&5>nS;rb2ec_qZcOF6q%h2;!+MNE&&$!;CWFq}tv#QM+SZSt7n~DFt{r$i9 zcdta&%^YkXW7PGFM^mr-vs^iO0G_sazisQLfo(URKtCtzsLM`H z%upk34%ll9_q<*2> z6!q`b&pt;6q(Yz=&sK*M#kJu@+IK)SM3ZOaO~;QK%j*Q4S53Nb>VlU%+>cM?b7fN| z>ws?^+1?z($`i(Q@x)uAq)R6Au&GDkkeB=^{Tu^1ZjsLNDSz+_G;wiF-Y^Mi;vsKo zTnjoPF3sJDJlR&47TWc-CB~xj%|&0o>*aNseiEtbuw^BZNp~kZ z_2;Co3%xU5@$3R{g?W<2HsBb%+ImgEXWqlM3jC6T{E450P8-MXGj$?9nUs}=q)+`T zy(AE}`kk7%l3wYvLc6?HDCHrtiuW12TQ}0lG^BORFI2-ao&!dIU8@T^iDw+_IrWeQ zWB5C~K;6kl)t6QtGN4a^8MvhHjW2qWB-Twm$Pa+(WSfj`(qk`=y`za{IMk`Kk8T|H?17-}n!Iwf&91{!8uW{=J`UZ+_v^ z*$lq1wVo4vl5=A8JPXnb(-S!{4?Eb9kPYC?`)m-9pJ`7{E@shyf_nPcMHc%O%Z;R` z+)@M|W&h^J;7a6Nf9>-Hd3!ijKYe)Ku@EBuHxtkkqaG^2u z9V5Q_SDSSI zd^|#3jGUG|N5A6D3H*Ns3y)4sv@uV=&rG#(Tu=W>hqPgvKX6hpc%ruse`U&-8cV#Q z7lwfFi`IsLsaF?idsEd>p~{z}(T}xG_vpj-bJcUvDfx*@FQ15Cl;I8ZyIAPf_Bx5U zNDb-_e-2(qBzX!x5SAx;&Ch!Bx>{v`NP7#U8&;E_@dlpKMc<%5QOCERnX&(M(F-}F z&9_pMZ`GJdv#`rM^_0wI!e^dj_WPfHzd1J^^3J)@T38mQCnxQ z@G-n(-{i&}Wlq`(c?4(t)#}8lXovSHV|n}y!>h_LL(e5sVOO>I`+xdB{AcZ_K7F&T z%)sj>1L$y;IcwXkZNI+B?`AaU>P9Wfs4g=6{Nni$@(x()Ysk4X#-Jm#QTtUlL`^^k zD1j{G#mcML%VCj$J&(rvEbph5hG{O| zcm722-9`M;pSyODc(#EqO%iEvsrTG$nICEJ*BjxPu8XG&j&h9QaS6JRSdl!DpO!~+ zqW%oOI?kGya6C5Fc6RpY6VKbu?qR$4V55EQkH6XO;@*F}-S*Lcj!)G)N*}R(564!? zp)=x@@=-Sa5^k38WyRrt%Bdr+WqMllvf6MrG}Hk^X;<+x2Z0Uz|37>G^{nf%<>^5= zy*JC7?T@QE)n(L%>Q;A)CJ=MG{lB(5py32GOzmM5=x#|6!JkM`re)C&v@8fE(bIv~MmEX*n@0(`i$dMyQjuVdx(k0UR$xJuiEoEKm z^yr}7+}>z+8P9I4yP)j28a`TFX-Dd5vy1eh_03;zswx~Q1Laqimb@1QTK>S>IM%b} z8}FgR^EMQm^4fd+E57*qPk-S?ItV*Q6*3!!9Z)(?%5puqQA&^%qkje?QZex$3{KKv zvp^dP@t=wgQM%2uej}W8f~f{hI$rF&^oyc3tjdDv2h-Ib@#!3S@DxgBM39GnP;=RT9N7 zi?jj&7Z)lIVN$QL4p`!t?<^hR(NTR=-$m-vTA-ktW&o3Ar4d(!rvJ*6{PkCJZL zydG=GYok%R?1VG;g&)jo3^c8~)SEnmUrllnhZCG!k+FL89XA;9zNWtu5ZTi&D!o zuzs(?!PZ+yE$+koN-?_2b-ne(O?LGOh?LT{z0o3~DMwJ!Z zJQY!Gr6y1m^wP`;0PEDUKYZ}8-Me=mn#{I?gWV{VrjaH^Gf<_1ileHnj81R35v+#t zJWREb-u_IV=N|Ye#r*FcZDC-5jT;lj`Q5pP>=FkA|}T&gyjD) zw%^H9%A!yC3iA)&eK|X)!%MHs=iU_0Ja2#Y8vm?DET*mI7mvkHGSNq;?X~k$nqP%- zes&y_YS5@BeICL~$YUCQPx>=L$nRyyx}V45FTG1Bqcz-qV!+M+0Fw?b1Toxk^4kfk zbL2Pr%?|p6C-jcdGt&0~$jMXPKkMRebdS+z5vNj?Nk2kd(-@-85*@a~tT^SG@%19r zG?eG*H}LyJv?-&?;h@$5n);uMzgdVudGmefMCr=`p0ae;TrAVTQCEH1$p1MX(ge$$J zT`eTn1oD`q3*F(7TJ&`Sio6&jn6L2M4V`Nl(IfE=4{b6~^vY*XnOW9D^!`KicfUWm z=fdxy6U`_2Mie7!@L&uwch&A~ueXQyZnc|RTiJ+MHx*U6CIeue{pBxsTesF2;h99d z-iR3&OQgK(YBRB@pRn`;K&pa&gFlC{&i^m}=l|17k#$=aN14o%P^ZAPNzXZcaQx*2 z6J>PFAYVC_%XQ9-r@~|Kho{eM(bmburB^j0uiz~TLE4$N2)vc0+2(b5PGYUEuVgc< z_2np1tSzVfnml&*k$>Os&`6UgTYF_u)PCumr-m$^xegPL2h=0jS!NP!kE7 z%Nz0tH0GCuLc@ud4a3M;T^Bb5?IdP46S#OfPYPsPHdTlO>E$y|C8b{6Ee}s#QDwq# z66TmOpWoBYx08vx9G(F;kgv@W#$((H?X)??o{7O)EV4Q>ruQc+P)0e;dKZ6<-ln^K zbF01c;C_4a!QFQ6=61eAw~<9#uOwU`Z)7O-?0DJ*VNdO@GZtOPZ=Ert-@)EwOt-m4 zI>x|TjLkgh>jJPRXtLO~;=-?|QI={9=)!L%BB772w71QRvoz5tNE}Z}GH6n#a4m;2 zTG?zHrZh&Ee#!yUIFL&kY*JWa>1;&b4U^-LE3|K)OO6zb)P;+`)RprxGE6oH_i(Ru z%=j8!yMp$f2(&(20Cuh*4Ch<}hapT6Hd`2IKAxBvK$+xNcnoye`r^VxhW@vDE~pJ>1J zm;Opy-MWkaaeMsuY1@0e*Y=)bpB=TM{S)+vi*|Z+*-no9Jl1(TJw<*qP(M4SKfu+V zozS+Ci+<|r4B2>m051d28%Uf4zkla;`|59gwf&8M_P^8q*}wJAwYzV;-X1&gdUDw2 z8S!ss^8kG|d?!y>Zrg>tYhSFNC&k=w;`buGfueMtA_l#C+OIcF@X-Fz#|JM(&VAvX zH$OG4K4q;5t8&%;NW!^8$58Z2=C5PUh9U^P*3ulF6GJm#Rctz@*|I? zCr|BH%*SWp+F#i}>KDC*C$A!wC##R6F9N2AAkH(FMcuf$i8#TR1kM` zR!0*j%N0I0W7@ilgZ3HXpjYa`aN+SxaCC~?rr~_h>_R(%2cGR8v}XrLZB|*eeY4FW zd$I`!OwvDz(Zy+-hu#;I<-+W!o4N@OI^buTIqK{R{yW9*1l)2y(R_(7-OfypU*tGQ zd9smOfG>H606?O)NkhD2o{nZ|8^k%8A)Q5Drf*qUXp0*wZDDPx&C*t8km!Q~`{Zl8wtK68dj67rgK`4opswX_p3UDVGc zl&oPUKgKbWWSF4N50FUl&&F)1s64Bd;;0ke|b!(D{9PJ6UuXr{?pnzd2LdsoAA>nyyE9aHj&L6*n2lN zv0HI(ZLPOEH#XvKuP>oT!HWws4F|VATe7{n+-?*8#=Sf3?bjZ*yXahQYRu*nZlB=hx$SN8y0M+b>hlxz@R@dF!^P_rdmV*nWJGPS zbI}-CmOj*t61v2q%#rWJlUh6=i}IVHY+2iPcRXG${$5Z#W9Tf zOB}|yx~3-|9spaeU=o*va?)h+SJ!;P<^nYye&W+%R9@BI(oVul!-{n6lzjb1lETdToGGXAwfOKa3O|3i${gY- zpVhb315z(U);|lqv?1d;9?5N3gq<;laec`=S694(-J2KAB6q#LN&W2X_^`e8=7aX| z!EN+;4^eKko3~!8+pZQ@X*^5xeSX%5yzJjqP^5oK1s>GFEX0|;R94u&dG2*=NsB_g zto`S+<(HZp^^B+W>dM&&QeE>1m9Oa@DzVuYnY8PDct zTH#FwKbXqHYj{=kssVe#V0Z5*^s?iXA*E9W#=vnPE>@S@%3XYZc>i8|=grs9Lyy`+ItEV$Kl=u-_oJ4SN8D3WSbXv)yp`XGOzt9&W%(C@td#!eA$5LT3Nx79~ z+6YG63a0Qw$i#ze_nfA<;$9h)&Sl}d1 zdB>I`{aX8@@4Z_5{m0GN?x)SqUgIyp6cb+CUk(;O)_fYBer7C3qDjJ^8N$!sOyd~z zel{F`Dmo3%Nx&y!{8;lc>Oy_vWyrdp%gNvLDY_LtJz(;mPbM>54boG;o+R<6jH9E2 zocw+E^hrB9Ji?DYnn?DN_FXUY(fo*>s~pK zEj>01SGej)`Q%A|x9)N(!!Y!$(z|OB*g>P;8uf&P@7a(Vh$HVxmq{^M0Gyn-cahKM z@Ez%#gf^`>y9qI$9#O9hJsjlLq@!0>`mA3j-7q!rJ@}D)L7>WBnCRysr1Ukfal%x( zXF>#6wNR(NudPjlZq_tUpFKIZ4DWc&)%vPqh8i><9-W|@o@B9d|L{1s6nQn+{=tcZ zHS%C^xj5HeyR+S1zjr&k`aJ;|oq0;995z+#kLT3A9+rvt(#;7ICscH)?9h;ial@}p zs+dL-n7T&IzdWba^!E6#|LgzyOObVVW?Urii!kKn;=Mc0>$>N{)o=Xnpl=_zCjDwk&bEaz?KIci)IW# zS|={$B^NugsX(BlsfAy8nl?aQPDm>Uq=Wb<1GCA&@gThJ;+kWwCB`_`uWiUYVyVNr z@|iYF98Y_=$ei)rLdlwx1&n=`w&vrza?A;G7j_>&%P+n0kg?UhOkmzv-)NhR1zr4g zA-5KRSK2ybHy3+17{6)P7z4WSYg}Ew{k1{3CmM6TGtZvXat!VSR3_kY{p^opOWUMv zT$3(tMG#Ox;W`)r7mK5#y>Yw zDTDG%TxDbA3|2YDPu?;U`8#jCR%`HC*LU8C0JeEaXow)~Bt_A}z|)ic_UOHL+xNcp z58H=7{7&27dj{@j8Q@wk;5p*vWdE!kKiz33JKzD` z-ud!xwExyW^Ut*3`KSJRyZ8Fr@Hg~4^|YCv&Y~}%{w#N{Bm`$aM^&dPF@%LPi0fjI zn?FJf+Jue^Z-4l~{!5W_`Q~poKM8_al&zRf)-PaP&~{PEjVzx0oySjZ3(-fqpu zzJizZ$9^|>=n6w;3Rb+AQ!Y=0!E=Or^6BxDo%ZzUqqYp~x3{*C=W|)WBZJUE{mk~@ z#I*~M`KGu?>Vmtur~|6I#~?%fwr>^OUn z7g)9>`F8-++miKa+|XYfF;yoOH>AsxrurX^WjEaru^Q!Po%;0+c@ zA4o%W!p#5De#BTj(x(AC8=%0A29R(UYSq)S;fQ|GzQ;x3@SkHM>O~{2@_-vd9UD-P z@SyEvcW00C)_34RQFnQ8YdZ_D5ANP<_wL?kZ@hlLefgcY z+Hd~)SK4oVy&H^9pM^kGVF8(@q zUmF+P^q_8<`ov~D?6b7iRpumYs;+sD&fDYI?&D`2;bx3GiAS9N%>VkO{wl3*z4qr9 z{IuB^9{#FyJ+Q*@AJ3C8O!Z;fo-WT_<|vD4qslI^GS0!lQTym~$n_mR1$4+5#&)LerHqff?70-)mN^8$n#c1dDEY6D6U(HH z!E5rYkkN}G<Y!y8#vJCM}*Wb;d8f0D#o&1l#4GJT?;6ubzkZ|e93ZH_b5w2;H zH_y6u)SqUO6X`X^OQi=9ta-s)aeW8r>PIV{jO;g{c6N7iAHEgtPA@xYX(0Uut}2#J zLbwy%U40j)$GLiKd1l=Rmi2O1sb^(5^9UYuE#sls3 z2X|3CFWSah4K~~n`lsLccDr-ucFIiVbRImT?1cXOG~tERg$nWj4;!J48)1*D zaYvgjhpGH+;KT`e#C%qr`^AMyS@MZ2W@F(y?x_5@3zI2Rh01slsgnb1drF}`Mux6 z-KXu4_^WHHIaTeqqfy_^z`7p`fs35*fWNT8W{wfOswqj{l<}CXsJGQZmwlFLM;@bZ z(TC9JO7=gJU1$xeG8!YW6TQMm ze_n8FQmAO@^MF-(;nDM{w0WMghQt^zapGJ*hh9a`VT!WFA6eifOugOba~CCgomHJg zb&4GePqo>xzBTHV&zYd>u+)Q1BWA)4Y~l*fGL3Nr#32lS!u;Ov2+yWNCs`A(^w=!$ zy5J0M!Y*C6CWZ&D(lm8L`7Afl`g1KP>lfV7|4f%Wpt<7!SR!Ku;W{ZIPUB=t>X-lW zk0*a!*iyf?OfL3%>enlZ4-Svpp$m54=|ZprX-6ZQDD|)3z1d#BcPpQ9QO9=i&o&^9 zQrDgLG@&5Rp%KPKjVsGbp3=vHL|-#L>1;mnxBTj_NmV$92F5q89$G6hk2CGx_&5HI zmm=#t`RnyzLRPo-I#+p{;s+y72ksspgDr^Svn-;YZs_(I|g-0eegyjth?j2Rd! zWdVvY-+ji?UwP-v_V#P{+8yd(jWO`*(qbliT*UR-Oi#Jz%4R3h8OJ5uFya{B@A-Pl zDkp+z8^(14)bQn1pO-Vf%)~kVbBk`sVQh(CHotV5#)75=6>piO7G~|kTugOjpK49p zv0gGk$#WKwDU+KjCX2~_Z!B$y1kxikvAvj&i%`IKtf*@&qYz(Lm}3$x@%wXJWwdxm zOY#!`%mFa)uev2qTp|Xpk>&UBp7lmKvWV5?S#DX-(th;I!Y6UE2-xEnJ(P2)$c(dn z5?<=q7mKGaWt6+K@JrwS@q6#KKmC*cvVHu+@3h&=!#3k}li;>Q-Q2o+zdd~Ijdl$9 z-F;7otRe?jQl4y3ppKjzw4Bn`MOVu^i#tE(DX{9hvN5H*3Fp~m{;Ii&sb^W z;>gUUb2C@%)J2xvopy=rT-&_WUi<3rw6FY=|IN1f##{OJs^6<4W)^Ynb7(QZ2M+D$ z5?Ytcnr-JqaNftwA1)FT03AY!_O45rSj3WFQ~=exwMzH zoNSg()+f9@&G#L=_~*b!pp+?|=)9q&%=VAQu0GJd33>_BeDO2B-%j=9uly7~vmfL+ zR5G5pCgZ}_c$(^Kt38Z9$-K4EkF3jH_ZyoVZGFQV8RpyG-d@|^Ka7mJL`GR2VG%j9 zYb@X@yEN&SEmvwx|5~6BC)OJ5M2T>$Ji7eww#17ahOl)q^&_~*K2{34r-r(L8~ zXx*%%e1xxD_+5Y}>^D6%7McPl8@)P>Er;|__9`~hIofI;Qo(-xF6RBepul1H!WM64&^3e)n_C-ScT z75;&jU9hrmvFwgj4$vp0j~l8^7~lAbICY36=xX2NcU3)IZ(rq=rRsU+b&-vR_MylU zAI4R|IWYnAHNh?_rL!?{2$xhx4+Wn*S66=k=-4RJY~7l zU*k9Iz+GdU>9C*9iYv7)oENNooi;}Kq<7>3anDcDzaM?rt`7Iw25rhywd>3CZF^mv zg!-Z1xVg379^Ag!9^SgyUb}s(y+OObfB$ZKaPMAwc=t|wc<*j|c;`;LPuTsNx7u5; zzt-OH7L@z<+Zzubws&5CBa6Rpzwvr|^9{mYf7o7o?S6Z3|6aRy_jVR{?_h5O-|zdn z2~YW+lj7jK1Wx)7epEMv0g*!o`F^U0(C*y2k<+_w)b@5R-CN+|A*I(JzJ`9h-TYqp z!NEa${OEBSlZ(DC{;G2+4a{R<`~xFg$L{tI{(MU54ZCGFFci#4SFMd;;&!DHd2L^zkdGW#wj;! zo=E(WHhOpuA0{b{Pi)({@*;hreI@Q8;{wMk>Rr!vcIc~)pwCkK`ZvFsF~f%+Jwiq= z1AjiZ2l;8AO{Kmb4|-Q*0s0aTKDtEdQJmL(y`zycrd*6m?r$MDsp&1xrtxX#+#f)Dn+e$Se#)>k2lr+5JPvPy9 zgf}Lws$!{(-uvb~wwOw58tY>yd{%fh%785RRYeoR4?>$}f>ZYolky%{zY2|z8hH>< zIAuqG=_(JI(!r57KEzjXyY%GuUKy=`akq^N ziVA=0=jh1q*&u{1AA?OBfeX@m48S8MSsC0IGaP2}N1T#1;yH4b_2|!h(m;Op=PD#ELK^kLA^M2Adn$&9=I6 zqpfaXZ{8**9r*EnJK2BMu2A3{E<1Sm=+TqxB6;uq4^WyBJTr@Q^w9DAxNYUTYikTF zp`#NI>zl+`YNuWa(%jKQo3Y@SOf2_0)>XB)Gf=6tj@Q;U+r4`asH>Ii^z*8s(GgxS zNDlh`OQDL72j6StWoz5tx#2M{(;3VuZC@=%_5S|^B;c27sBrK^gfk9Y@kuY6+2I-9ZYVr3UL-Rrv|LisX z63izu{iR^>V~y=(+W7i2WBDsk&d-YDPerF+L>@oED8*lfto!HwRxSQsV^A{rMT|bp z@7k0+uD-;@3#2)Hi+zCogwj;`Y(J8XN)!2NPeeaNe|C1tK!?8b1m*wfqepG`*$#uB zLv$){Pbmps{aERn_7g*IQ$I-gi6&jLKqwBRs{U*AMfUXrPQlQKTP8&4g`#itJ}LuC z@D;Quj67>%&wTnMiZF;Y2B2Df?ZYd$(rHF``cv|=4|UNmlRN5s4rKa(x9}Ec=|x$k z9pxB$wzz7f=g^_&oV3B;w7SFiBnEoD7$%bSRuhMzfv~W~&4MyCu6`T6t)~~Sf>l<= z&V>00x8{Y%yKel=iRVt1vJZgs`4(ob(J81$(6crHKmliu^-P?I{I zB&mr%>F^Yt@q|I|?*37}Q|q?{UHo;CbA59w*RVafz17~hd$Zl$-pHq39Bf~u-bY)N z))HKr$uHtB_8946J;)>K*eO-F);nQ7TVMWj;wC0x!Wn#IeE-Hz&@=6C|Lwp1Qe@rI z(KDWAppg@))ERH#qtu%dwa3{cz-!8s30rt)b#oIx|IYSMo3Ug#XFYUs|GchaWwq$OAY!)~t3Y3^y9&)GwnL zvr*m=DR}wqY&Ra*uAB_DJqXh{S!9+cfO*EVG8{0-H~HLrfvGIx7yLTCeP4j*T#)l5 z<@(BEySKgBzVgoN?VUFsv>O|KKY1mxa-43O1;_bJ7BY6$b?l7mrr@0FCSEqx@GK8F zF~8U+J@a{@4y)R6jZaOxFz<=q+8j_5;@~YwA#~(A^mL-h2~fXTujM6il$)8f#0F0{ z6$4W`do_A3zyiB3{7Uy~OV)F_nw%`ADo40+OD0=aR(r`XU(zOeSQbFZ$B9Da#4Pzb z7B+vMwe!$n7Meh?oQ}eFmK8^uwK%HarW*aki)BjTcztl{Ve6)>L~c9*WGS zF)5F;f#*tEK_mGY+`Xyn@kj5rfAojH*B-t1&D@r?G!HW%qg>c^%>2eXUxAnA+U_y( zZE=fn_swk1u7zy-B=EqMKDEf^yDkhTT}J&G$G$Q0cf1!(^_TzUz{H(#Tx*HM(|0Su z`Kpdx%YOv`RjkN-Td-zwz(C?=g;=q;m&UQVd)GYtaBaI6>ZN+ z+7oDTMpHU;4#)Wb@^lvIYwz#A6gl_KTd(&wOYoCS#Rx61v+%a9-8SUBj@NX0rDysd z!p7pS{iTf-U+|Zvz~N7RwC<}9Fa1bAC$y*Y(cf<Febg`l;k2 zZt{QfFzzjY1OA)FV;pLjogSK#jpAmcdbiX}$ z@^NH`b4^>|Y~Lys#ao=R0K$88w)o-V5&3H!QCI5X&RrUitNqiaogV{l>UWVoOV@Aq z>P}n3yh2(zV0`6@bgXMq$uDgSx>JAJ%m+nAl-!K&PyMEDtOL`;)^pXX6wp*zG=pbC zqr4l_my#<*UtM{z;#eQvnCGIeZAji3I{)B{VXDp7dqEwBIv;r^FI?^T`GT>Y-5{cz z@m33YXKV_{w|rfw0K9$QF@1!zGTt$|q43>MWt=RwVcq1UPNKD)dD}v6nW1pXHS4$f zyOP7wQk^f0zq`Acceeeh7dn*)>G&ddKibeLmp~*&Xv!E zeU`=Fn2@h%__7v%|Al|$Uu|veW;;bTN7tfm%pu&Azj8m#ly^!N_oubF_WnxQrhav8 z)6Qs}P&o0dXN{Y}&YnGP?P$L(p)0M-UEyA|Wyrg}v;8>DWQ zXj9(2x$HCGoavsIFW?dNPQUFtgN&Rdk0t6$osA?JGssVFc3W{_7hOla-Wx2pH#geN z?X7nE=62iO+JqOq)sudW@%Q23er~n|>F7;c8*5oSzH|E~JcO>gyORyt>Pm0D{zgs} zySVG3@8Q8g`{<*OGIsX_`fCqgYY*<<5C87(y2)lQi@>fE_*oj22ip$BOa04>x#b93 zI-Gh8@3dECU3A8Y+vQ$l3#7-6@#>`At7{53{yi<$S{kN!z}hN!;lpkx&zL+L+st(1 z$X)f`qs32~Ppu5Z43iZmk;GM<4XW+(vzSY$qBwt=3z4V2hBd%JCQZ5;)2w(ag8qyu(w)lS>ad3CiGejTvR z(C`;&D4w$QL+Mc{VQf3z69j zz*HH_gsik+AST`}It$7LS<6zpj1l~dTUM44z|{CWipYaIw{z$J`sz|9X?LGJsm_GX z!&AwAFX{e+*Adu@?T`QHk8|49&PQe1YnpA8@{#4Y18^WXZ6sxQ!+Ptk^)}CQuKpse z=~aR(uLHfD?xjj6`J2VcCz6vo#r;3 zr&n!wC7K@>S8<=E_L~ec5w>WULD$(uU7=8Z0ld!l-J_08XZ9F0|MEl=BDuK9dm@d*P;1G9nMXTx$D z(&yFu8E_=}NHtRacnH%me@a92k!qy;86hA=U+&^>$?QB$+-dV^ewynvQ(^Qi%3}vz zIlXFFI+)Uxj2WFNeV`M3XSw<09L4{b0puQo$DOA;jFk@=l%lHJ2?T@_%IY`{ym?n~ z0rt=VHsaq=27 z9Y?F~rB0Ube>ri(;3ZeEp$j^3VBb4%vF{s$+my#Lcl^}#DozcOqYL9|29EyMYdZg7 zuKjvn8`!+7PV-NF%RJQg2Q7`9G|5-M0Yp9>E>3dJEB@VkkRy2c2hAa8-mmGZpU>rg zg?^LpgjG7>irY2rTJ%3MDp>Uy7OfMj>T2Fdr1dvX>Xj7afPPYP`-d z>BNh02kz>ePIit3UX6TteqNKffkArl@_m#|e=XQrgb6*&Ys5D%;b^jmg#W@E17+wu zHic%OOS$S=K^4iy7y@0Nal^WwM!|Ihfo0#N9eE|#-jO#EU9@9p;sS)HP}G6v(D(1( z+-z^$L&w~%E1&gOrygZ1Y|FJA;yDbpf*&F1+c_a_UEp7Jave`!-@U3bFpQNye)3o1 z7w;DD8PeL{{yTr?rO3MF)BU#0*u#^e8u>uHPoah1uFV8I?@lgATd!zb_S>KL?l5Lq zY)3Bq?jN-szbSf7eS)(KC2PxG_YA#xcLbuo?_@+RAUVd8Po<-LDId+|`nF68Uz`E& z0RF6&16gX(At{T|i(B9ktnEABLz9mJUg~4;ugSAIB_@Z<7N&L#=D6!jS?dp1e#<5k zCkvg(4vbph^{O-B*Eq}e?bxE)0p!7T62?h(%0M1j6m+Zw05>i8UBSp7cwRdCn2Bx1 zD~{u{kYr|#HIuK`I}=V`=BXT9!QR~1Y`^~HciI=;exu!xri{;qj2tK8(>AhbEAJ6T z8;}N`DschXxQ68&9Gsk=XK%RS^UvJ-e|7lxXy4BXU9`r?D;8V{fM}a5Lh_`fAcHkem(ZjNs5&H4WdnPC~@*r`f zKfVfJyu?v@7oDB>t9mJzp}#?}?ZwGiJKNiDv*)Mq5aryw-B!QwJMH0b{gZ8Wb+vu? z@dw1S9ne6arxS?)$>OiK3V?M^>FgcRC-G*#@`oS3oNJ%o{wYuXhE74NT#fPzk(Y^o zWu9|V&QaO_D3$7zd-Y`ny7)MAW8EkduKV(O*R6UnqtfG?ODQ?lug*o@3R~k`nhU_u z%V-lO8+u;g8fo%uet25w29(JPj(k>w$U8=P;QVeeOhclbW?G2Kmj*;hULMY;jy!K+@3yt z99iXJwLC6$Y>R#~Gc5`nOK0nOfCCu@vJ1an9jw%^Zvx}%e4kOgeStQ2<#m1lnspwM zwu%r%>A(-y@AxVQ^7)4$CzK03E8nt6jQp$(E@h>!I?MC@hqUSK$_C{B5Tc%kGx)0N ztmu#@{o>{=ZKY(O{b|jQozQ<)~aiFA-ps0U%nyYjg&)@AA_ zKbr_~iJv|n*_TaykqYny@uh1~$X8QH%XW|sjXPeiL`oDQ&t8Hy=WO3N*pgjTXx`APCa`Wn37^iKnujN|kH(q-k-gP71 zQh49R-Mwr?ILQGmZ~fGY)3YZ}5~h55@Y+M*Z$?KN@=>~pU*rn57JlVlb&S#%CyT$z z6`!&EO+kvxTRhamCUFW@OycR3Tb6$T zPh4<`U;P6w+f>OiWwdVb4P=Hc(x&v#MV=dN<*Yq^y4Sw(t#{GouiD3tpVEhIP|muo z#4(=MF`e?p^n*j=reE@{@DA?1>=WB@8|BNpxOd-4I8KLD{}V@A4|?EVQDY33_Vuha z|K2vCi?R&_Bg3pKZ*OpOO!V{Uo^HIW>--&acyiZ`xt{v<69j8muMjt#hwt3H;JTC> z7yL{rxzW1d(<@~*E@{<`y@p>}iENcuSuuq=Vd`xqH?1!W5#*tstm67_V#_l$>2~+y z?|)`l_e)*;{cEqUPL;2aPb0HZc^{Q4#q5~zslrcE6~hmL1V+4#pWqO*!g?P3jZPzw z;-|8s5?75mag0Db#g%wO8CQ^Uzem!k}?T^W!8<`d}6>i=#uah>p zR*ZK~_ImI7(#l#p%EXhquD#;L@2IS0x7WqlajX*zD{9;b>rC3f^fIP*y6?H0!z;na z&~MjVA`l!v)Z~@8TLcvy1f>c|FTZu*vjUWexpK)GQgFJPXkmdN$E?bTiUh(3VUfm1 zXRt^|<8?m^gwHY1zk!1Cl`pl?5Lg5`8haI(e(Rq z;^V~I)5jk(5cHa!Bb0ZPH1a%!Oz!IUyS;aBZ{_3nPJBebldd>OUb99NO@aE*#j{hXKQUhhC{MtDJi1eN1q$@4y|l`Z{BZf2EsV z{2h}RL|j zUZ5*`I?+WaZB9N4U)>5&gAV#@g)ZEjVxgSsnclQ=?nHFwxh#4RUbZHF^*2r}62t4( zA$W~4>8~l8N;7lC5+)AW%-H$VxWdw?(`Nw-cuvIl%`GPvofJ`@cAQ~Z`D08`*9Yc0 zw?*&*mM2%e>e-XOe#h3qu7h6}gLC~AxOn5x!`s{K&HK08&FzgWlBpZ3t7bqiqLK+i zPS>uFI_4ifkWVNBKk?BWai*Wu{e4I}o?^h&vgfp8fA(ki-}yKH&6gtUZq9kr5&9kP zF7%7lDRqA8qCY5E1}E?3y)67LEwl#@?l6XN0_Lh692~c2yN7M}1U^c67%R~}yu#0k zImbAjy58LKJ5qHV4P^qH!7Xz^BG+H_W9b%Li_R; z-fUlb`^|Q1n{k;t`;DiKjI_TY6A)4`@Z8L5yCOe5LUu&~q;Usy-#RZL8 zz_H9lKk>^6RqMg&vn=#NJI2Fqw#~C`+Hn4)gRpAjwx^3%cwWw;D2M`+GIu*IH-#?2 zeeyYDF5hE$)R#Q6h=fTj+L>}Mi@Ek0F8JcsA`Nxv!VP7w1<@`OvtVjC<(%^yx5N{N z$V_2LSH{x$Hm)>;HpC4aPt#h*foWXe8ISPEqA_qPF6qRDc;@8-xC^#(bBwoFy$dH;U<;&1->wsSPo9zQv0+c)m#CN5>I^axz@ zhu*qH(~-C3k*<_2-B9&K_D#~0f=-^RjdUKgPK4L%MBfUkG`?J+$*2Rk;iDQd4sGfJ zS#WW5(%R_>QGvd)*0#U!+wH+${HNNDFZ^1&q;B?T-=~L1fpvE7q7Zx&FtfRF?U47A zi`n+gCv|FZnBe>~8s*#M+Gos9f>3#s_1S67CHTjF#)aS2Rj*Y?zPaEa? z5-wj*hH1K)w>aQwBzSTT`Mi}$WAy^BC_O%|d7ZP9)8=h>&XI*C#5aHYSG@-8Y!Xvf z(BFPpStGCGdb-o3mL>X2Z?{$UJQY4-mIvwN)t4*q!%VL3^l*nEmTPbSs6Bc5IPY6G zwsW9FeqV&%E+R?K$kL9V?`bRGmCX*6*F{}VsfTxcULYP7>Vj{se73$J+7I#26O9_DQn=Udg!jDK>5z6Cw9@ydfiHv1Au>CZOT*U{IY8*$Xv)ZOI0vyPy*JqyA3g&*XdznV@=TSD1bR?rr9y94SZScid;IJD$C=bc+&C|7@%Ml7FaIwZJu+j<%cd5R_K4aMzvkGi7H<_L2USKS0{ z6QGVMs0Xa4T&XSO?Oa)`nKAd9vx@VZz=;?%f{#LMuTr_*oT*vgg9Tbr9XxR%3Y z$RXw95i->IZ{?8R|8)&uV{I*AyE{7>)4M?T`s;5*_fk&Su9c6Yj-;1kVat;%pY3yW zn8@NZ0>wG_WLO1dAj=ylGEsf$+e>U97^RVS7`)Ktm z1mj(Cc#nU7x6Nr}4`q$**zvFYG;~A99=7e0F$-A(`uO9=?c49Z-)`KxhhFq74`Jwq;4X}4GQp@ zYc2Bih5QRmJ?-wH0uLXYIKOlWug;X->w27vzplxtmn-MRT$7U7wt1#nQcudn>3XyP zY9KyO>a&~*f5H69FaG}3*H%(!YOflMl{i(Q35yv*aa1@K-w{V*YOK_BuKATIg?v00 za~7e>Q--Wgj6A~>MfA}@S529R0=}SzS#?cATK#Qo!L7$JT^{*2DrR71{DFdDwc|EH z7#?`>>L)oxM)pqeOd^5nv)%m+n$|Wpvta1ruMOG;aeTPfW-d>oSkIBx$sL8N*M02m zALIysn3MRK>?A8EZJe+{dZM)1)p>0KiUn!RyOgJ@8wIBdfs?C%4i!8_Ye(Tgcy3nJ zvXp8=RVqxQpmmqgvfn&npteOLyuZCk`7R~{Y26iYef;PVcwM!dw{B+9Q?mH&q_^IB zt34vjot+5Un_Ko#+YikXuWvw zljriQe5HglO8)VvOPZimX(ZFAk6{M9_(Q`=RK{3I4!@2h;;uRTGv-^0#o zJu9C)i(k@{aO9sXbk&mTQB=m{TH!4%)t{y3lun{c9cBR-7bd90z%c*d1Ko5>&#TGT zT8KqYAWz|r?%iPddiHoWi5$@M`e~^%i}z^hyV< zmRX!H7ze1^O7kq9klyF=FP^E%JUPoESx$La{ibLuKA&9tb#SacUMGKDlypGqgv}AQ zXnNUJ(Y@8}UHmnTd3Y+stHAs|t>64*K$34%`so-KXGqw#)>hhUcW<^g?%!(L>#N~M zucu{@5q=QR;G^Njq!8s7-P1)W%hvr8mbOAX$~oMOyOKr^ft2H08L8}hwYtCafBm;! zimbamFCUq;`gBl$zohdVb>G@CG>Kd%Abn4&kRu zP;e5@>-t=%w9M-Go|?#M8#2(^mcnBqL40rWIbkg5*v`QH!=tvp@7ORAAde#eOcB7u zc@%=&=wycDFIXX_HfYig;hii%STGDlq-?f<;(5y)Poj&D6VCF8lhyL1xrC3XueABz zz9>Q9SwPeIozlI-gLdph6Y#U}N<87(UVG#|IZ}BH8LV}YR*;c%^0h9sHcuCC9S1um ze*5A5eCPM}_Eshz9s4O4OEwZ8H+cF?St<|mN`CMm?IpN*la_Ev@8tP>7Cl_3aAA|Q z#H)5!_|>GY)Q~^zM;KSre*Gr>^rEjW9>lBuVj{-4H`_@9MmNG-5>jla%1u3iU z%+L48V9P{!+MU7HnRM;p*;JyuWBi)MSIVo*lb1|8y$EVwV2$t;TykA=7IAAVMa0B+ zEF64Y$nA38wme|gm?Ec*4o9I#Y&j z(i&59U{crTnv2qiN4Ol=){#7HpI)B=^Y)4}%IrxsCqbGITwU*1@V(3@(Z9zH-Vp2a7BYlSJ z!-!kD;ot$=%+ReWOx^IZ9qb>}MuE_>@<`t!UBO3q!Kqt~`1z-)n3}@VJT<}yEdS|M z!4+Rv(Ate+V`HKDSAR&`fkyI9=4DAA-H$NPbs80(na#;G`!(2xK5(Y3Ltp#iv?KLX zT+xp#CRh1hdefze-8c5a{~({#McbV2-CJ@ zIb%d8ws=Te(&>}7e&K@h1HFo?EGoZIrU~Cmvq?FOQzmh!eCx?u8|6PY2sn>SqfMVm z1*Oka?$mYN_S3|iM`kz|?_%%rLR(r{Y%6QFL)u^3t{cDXZ_#ytxr#3D-295S|E%~8 z-?g@}vEDW}T(q5j-#}O0$Y&XE-nh|j+}Muw`R0wA?bgk*zPs>bdzN?^k4Z#~P0j;g z-b^ZQ3RhmUZCX~xClo%1m2P^~GvUf5+i}`5@g}z|KttP%>l4|ar>+KFGWMZbZ6nfI zoh~|G=x+T=_oA`7vAmocW~6J^5shcvRR3<8dain#vhYvpQC-6HhIc#BaR{Gq4Ro;0 z;|l`#SoJ|B zHbJ@8Wb==2uEI-*T6-41A#wdNNOjj74 zDMLg<{L@d^JSRNQRT0%li%D!OCI~LXQ-J7dA`D# zxp?VLG`~RsO}6a-RPGeA;H#}~&e1?EFmc=!esg;>J3)7zK2F2(SiOVO_4U=<-T(39 z$0(*BLziN+v(poV*J=CGm%i8z81TIQ#v2i6)`Pn=tQ$Ls8n6}ZRZ@Mu-|;Aua=mpOp}oUuYMfn8DM-JMFoy_Tep6LC5ydBhwa2u7Y-iLd5+M1j@*%qdwR?OfOKQ-a`Xpw3H4rnJ^N1> zy@_2fn$bCYYW(Lr4tw0^bU*En$mgdspPsn-c=gtzmpLYH+$!5BbLqO#k)`M4`PybN zJi2fVsB59;IO)9?Kk{HP3r%l|rj7@tfTeG98Q85?LvI6tro4zc|? zdWYpB(g=G_?}!R-pWi1l)%kE8G}jej42HX{0ipVG>BeIsK|OO|>aR@4x4&to#{j`u zd^&DMR}UGqiAV6g9=n*Xtk4oXG2^+)SZ>US{3*tu8ZW#e&DQ zJL#9$3o4QcOo93cK_CP z`|>+)wEMSjv@OQaZfK}ez2;XivMIvFi{AbNyN?g+HiZhy31Gv?BNN@iQZ~TzE{3=u zTBqYc7}{kLkg`T@QeT;^$9l!H8wGL`fg5v`hZ%>0v+$8Q3yeMIy-|wy(3ZTjfDSHB z)@34HntB?y(|59rXBSp; zEprxrVN^RE=?SiLSikY>>D|cgbV#-j(~1va&M}bQMdBHa;Wyh7bu8xLo2%2dd~>z^=3n_MZRhx^{qTp++WiM# zYFnE((x${yJUn$C{-!Y$UX;@eiYB$gN z#XqzdmM|5P1QV9i#g(t8md}onwL9o8AAiu!KX@1Wy>{{J<93D2Si1Li`Mw)B5lE`s7G~+#Ub_zjECa7&=9ZKmkgb^>K#!`dkG_f({8~*S78X2Wup1Ui=atkKa`OtjocV>GE;1zjBrwTZm~{gIJVqQ!3p{0OUDF%= zLm0`+a#PO+SU$@s%E71b3(T2I%6gH7_oPJ*N)Z=+PjI!5o*lRU^uPRj?ce{8|C9Ee z@4uHrCZP^IsEqNuhi*o5V_W17e6Q?PzPVY=Q@hT6Ez_qht!Q1`b>3^Wt*+~?ba$;S z`^h%K#saX5+7nA!7nNLi^O|C1vvkuA{VRt^dijQ}Iw>2P^!E@%hktp?^WdLro~k~y zo{cLXd5Y0bc@)nS7}FQM1E|A$-ULDqNKF1s+voiIi`XSie-=jY!ZrU`UR>xEH^XxJ znYarGvhWOXm3#Wzf64n6UaQpkv>w^=fi=+6(0p17;ojSd=`VUw9 z)9?E%3?7osxa5}&PP)mjHhPq6KG@1`V#K}v>Nos+y7s|L9$ucAzeHa)Y1wrZ4`cpm7?@T_S3PnlUQXG z?WZ9JX1&=Fy~UIIbBplP61;<5TwQF->$FAe;;Q|-eY6Lh>OhzWhDx@|x78nRZfv#9 z&Fy?b@aD~1*xT*at+F?@H*U4H>JGm%4fM=1|9XzELsCReG_;M*_g~?F+s2%^^-*>mUokwr~QiK0R5F~ z!mW7xBcAV;FLZ`>RdR#K$NYKJN}pOYP>;rk;Gz$8MZG3h(pYABNWRfu+GvEUKJTe= z`)Qk(2k`__V++S1wQ1E&Tx0CwI?4Y2QOZJSJAhPqMLx)e{ z5WM@ZjD_fr6Ei$?hyCT5mvZv=ckkCAw*(4uDV4@Mm1%uehu#~LRz{)VhG+1Zc=%A^ zHbMod;b9&cc*QT+He5;O1fZRea24&TEaMPprHO-lHb|UKAN-83^5whn#V>g9EPf_( zcSNp8GER~i$p$S`B>@nH39OXWqvsVS+)^U#tbwZF28fG|^D`H8=*NV4&%SrHAGiIz z{p_IeiWzrRrA(CH>r>pVbEtrIwY#vS|)&n?O;)1D?4dJZs=+qSxcd7pjy1@ghX&Lu3hT=1dR!IfFn~(LIrVq6-_8zq z+6>P~nl^KB)@Gpj)yZMLSERT(r_OeF_uF^B_k%XGyxwM3*4oaqr};SlEHphoI!1u6 zf%8V&ymg1XZ6EM0G@hq!J@M^zB~XFpK$)Rq*bm(3;-vs|ImaJ?2ESM&Ucz&;GhPL< z)$ZPXyY1~>w!NKQs!nynb|^g^jFeE5t~wEdSWkXfXYMqLvfAnGf9t|`2NC9#gq0j? z-Ha#Q?vJ1NDgKim=}T#?(=zo<1M=cI@$D#hFt3>Lj#L&Ov#qlCwhVtO6I7tnsT)d} zJiMN3E{(_gAAH9vOg{T=!kSq5$J>mmnKnN=HGjPMMdb05&F2G)A7@?;hQA8s1V>RC zHqOh%@$*jw%}>TsZRTajy1)6)|E&Vu(}&&)V{GIqkI}{mcLFw%k@Xc$UxuE7R)VDu z;NAX=kxcr(S!Dh!{apG@`pgUThl_(f`qqPXb$rnKSQmhI+tKb`PW^gK)Q(q09r~S8 zSJyP4T%t?b!z|;-EirTwT;>2Qt?*vW)&k6DfFouxyO#L+NMG z)ilvt?W6dO$r=5!3mTXiblPVK7P$72)lVid|2myQI&~}FdGRX6C3J;l^g2HS;)zbL zKFXD`mKWHT+rjKSdR+8QU}T*FsA8l(IO%(V?ZlGRV?S(J$hHrLOOMLH8GpkImhlUQ zH^Yp0!55p`VjP6?>_Ql*1t#9XCzE>G&|1&Zsm-Bs38`bHNjBv9f)F;8y*A5* zD0SuKc1eBg5$6cJp3$DJq8HD!!wXvL;(EJ;CX48o4{mO@*KXfvcW>Tkt1Ii&t8Jz9 zF2^YnrE1cug?82x$lG4T*JtsOueF{I1F7)i<%QSC8Qm&*^dT`fCuys;_7dScr zw!3%Op6wmMN9wUo=+3qc#yPfKBWMFWwaD~r+BOl3+o^+EJoV4*u z*prij>EeG%XI09XGZlMo?W=g$x)HZC+NlfR`R*2ePBtYDaIHtGEA>Tj!{>{PO*4T6UQXVG|KTai z7u}vhIVqQROg8ekCw;&2g}2+=uibB38|%47dn}~X+(F4&Pj!^M;ZHgf9=VYAX*+ZA z!@O%!ak3DS2{PNDZB&@1D_UFDl!JnVCn-yv{&hS9FH`0i;zlk5C#V0HTzFnWCKTO< zJ3n97%w+);oXJR0hAZBdML+Y#1*YG6jw|cO5EiFoPBv{=cKapV%kY4~%Dxe981JD2 za)$h!5Tw$rW~(UqI;W9^Q{d=djBzt6Utp78#i-)(>Tr{AYd-DtOO-D``;`YMBU zBQ9p|cwbstPV=?Sdp%<9AF>D>`e? zzE0Qlpanu>+VG=ga&YZ@ii=XpeDij0VQH&v+<&vZ^V|Q8wt4rB_TGE%BELP&LY`#e z37_vDdX?*EmvisD^?HB%=}ct<{+5Hb8Qlc_P#^J=WZFfPj`RhQ`_66g3p0}f-toJT z8vBGX&mi2uly3a=%Xjyok6{<5Zg#J_QHHp{W!TuLqKPiYV`PQ(Br}k}(8BlHC}Wfp ziQu30Utma!EU;Z_kpcGYUfHW`QBIa#M>{8fvkvct$G{yh11DvVe3AvaNkhe-csYRw z-OMucE5M45s1IrNmxs(#+=ZuniJlDF^0NmL@+kuGAg{qO+a+R34(?TrJxgqVNY zceUksi6b_=GO-n=G2K8xOSUmWjh>ineeSsM8XcC*46=@$vvo1Ts+Rrg#BK4s0HePv zHvwk&>dFdz+XnQaJs<<5vETo-J}%B^6Vd@4Dl&-#<|geu5$OVcWHxZsOLqL`?{R(e zS2%uy)qYQ#tGMB*(mCZ@F{(PLG0bJ;sEa455#MPSSqO{FFE{hs_=hy$RGVfxZGTE* zzC}Ird3oRb{g?m6e-T}=^p^BZ-K3v1vHkHu~E-r>g# zx6+2Mr(FBcQ}oPz#<(8%QO3qU{U`B+WBpK$$SvO8kYS~)9UY;=GG=gmy?@|Av;E9riJ$WNIN{Kdt5_8G_Co4##-VT?83DjQS$~ziPpo)^k>Q? zZuS?(DOrJ^@hy0wQa;Ne?SzF_;`rQc`I{zz<)5VF&u{RGeS`grH{ZH>D4SjMgI@BS zaQK(QkZwY_@Y}t#r?qvj7~c-RxQXWM%<=F+ZY@#fx}naos`7Sz^+r3NSx!5Xg^Lpl zAOBSj-IyQNqE`Fu5iq_@-1t@8JP&sgtIV(b$=~Wc%4#Hv6;zhWN{5Y&TOFq+l}wsa zuAaB1(*!ORUGQz3r6@{78KjsASd&I6V0XC4=*5@{0Vj`Q@_tVT;aH|IG!hd zG|(_G&lxy^lkdSbLdIV&yOK6}=vR%&251_u`*m^Dd-^xlR_M@A(wTc_KEZ7bW;Cvo zJO?y-1$1x=9p)pzv!f08HUN*aAMEet-hM^>CNOVpZ?ugS2An7mo;F=snrEQwcOy^$ z=op;PI|la7)7^X*Lg8(rbD`6#X&l6RWq=)o3&38d;+j{L#OM;&|`w-S+6wcHywSe>?QcVyjZA{5 zq}25mH7OunbDC3nLe`u~-`djc8gJ!u=CL6{?G1u+Ex{KvmAsBuppD4TCwajV9 zSSLnnfK&sTy8ikiHt*mwal6efd0-3AoKgzm`vy)4OGw9|KL=sTc#UnDYWI{)3%`s( zR4D`{GhUgOXdq`4oo;^~^_VZ|7q|={;R?}ttoR+grJzf9)>&tUL z$^7E$YV-%m8zX6^$wM$*kzo~HiaY&`eX^6e$oyeF@oOLD1gJ{+34N*yyZgI4*k|3v zdg|8`z$nJ|>t%E4OqjO(^O+&#FH03(Ov$f7Q=cUiulYN1eFCq}0Kq+m6HZd-%sc zpQTmTt;RUQcXjya8u}SW>tInG5gKGepgJQ1)0}Y8uUnsM@dcVmL#;RNEL1%Cs8A9i z%v2$|59M?WQg+az>b;&baMk(?q2fJd^fQccl6g(%SE+htCN%CCJYNGUKEfCrhhOx} z!pUp{x6^a*M0jM*aLegpw0fAdq&-S=VG)+wg3$AYtIqG0gI+;sU29U@{*bc&2-mvP zOOC@}+)TVP=FrxSI3-tJmWh5#o|&*k*FHQwZAZu( z7hw+>r>w#+uRpxkZfvc$8S-^r&XS2WGSKf79sV4cRoPOek8^O96GDi-tHmc9GqCamA%S6i4%v`8A;cJ& zV6)zF^{M&-3zB6rI&H^EltGuGb4^&e_*N5%8DBH50UCNeV@gjdfqxclNu0$#3?RVW zdap&Yw8Qy6#+xOdUWSaNu)aGXR~tIX7eB|fZ@vDoz4qW9YosYC^70#ECvMjg@+M^dg0?tKIMuf8}rTDA}CT zzJ0Q8+|1=7@Z6%``(4dgyC(chs|7dSEpQepC4Sz61k`aHV;Jv=Q;V-IDAfXP!AO6I zl_n+k%*UC5T9Duc9Gw8Atd=Vzw+79whv9EqwSL2ErZGOWoSaa`3X2D_=6%L`)CH#D z`R*^}1*WH0TU%%sZX6N*%vpQ#;n&+A{rp`0_FFl5l+8HeMsa*f#T$@|F(Z2dO{$~3h{ICDD_UHfEztt}MhAVvHoXg8H)^n`?eyphoBc5$Hu5tt3 zpB~TK4nmaB3;Gyu%4$l+CBB)w@&JIbeQQCCxU z6GZ%JU%9>%xMT6uc!hW*NYZ9g34Z23J|B^d{WQ|~*{jUmsr$)?Vqjn3tfo{F)b8G8 z`>+1sYwh>{tH0mA_k;JUPoiGV&TZebneVFdDi_4zT0V{wy3s3#eu=zV)-Iuc;`*-6 z8Tp3mH`F6Du(beFv`jxF-9f7Ahv$j4T8iG<(wQoLCrC`5tZIMC*-qbScj$ma@3QaC z0v2P2idVcMl#xft+MZwcd)}Hc#^C-~PlVM=cY9pZ^yk3DM4kpO@-jSOqEdXVS%U6! zl#AMIE6{Nb8n077o2zU2rmHs`c_7F+)^Sym`}1%!n`Zm zZKVy_f7w5w&nSw=?P)$+vWtDTv)`UQ z+iy>w?zbmTcCkC{(W7VW(UWKGG0)F-58A;Y<95>8$1g6gwdK`~wzj_AHn(oJt*u*a zYx`E)@Z0HrCdSQgE=DWwCb~X$(?RG-`Bt1cPImf?R8hYU-^}cd|p-#J7j3|ogu?;t3H7atYpWtC97vl@-r@Z z2^*Xzx&{8DK9&8Nfvv86nzC9Qdv|ZYef;Qg)?L)QU6lXegO4NYSJpP;q7-F4MVSxK ziLCS&)*OTVP-9SP+WjJV7@iJ>y4=6&RQ;E_(Aa7^WbZ}OEj{Ql zeAZ2vl`7Y0dfB5`4P~b{gh>=&+8}BIqhMH}p>c=JzxbDHzP^aVH3Q;yY1D=!mM zFUB8AjPS?1ctz0z=4eRb68Xs=dNsX={Bgi^+Zy$!|?wx0gxS;Iz7mP+Dm27CJmS$%KS> ztN6K#!iCp-aNhc&{BFK@@@yxQBrY0nZ{LiLb!%(0PV0Cbfp8E;PaZ#Q8ylN# zgF*Zu0_=@9-^}~t$4}ag8#g6l(F{C>0$Mb~TBp!MJVMK z%UJ2>cT5%$4!OR@@0NgP?QT@5Maa@I+3AiC<7-b(kF&t;gtVu6W%cJet8Sg3tZ%w_ zGFxSz&Niol_uB0(gcYzoX+n?K_K#27_kQ?6`{57YOMN3IGXT(DV9&>*Z@0B8T9YdL6zx*oS$}gx++iq-Pg?r&I z-$Y*6ZmDA<2gplg@~0XDy3K?t;x>aXp0iO4oiF{Q3O;?K z{prckQ9C+3%ntpNDCeHYv=8z6&~mejp5zMo^i9~wMz44y+o$`imuZr59(Xjr`hA)i z{^^I~PWMT@?=h&`f>-hKj5U_!8M%w{Y@I>Qy-khZ-2Wz*1w08j#j$VD-P!0mV}t(l{>us*9`h zsn?HsN?q`L{XXRfV@r?exUu~78+u2c6Q{?^|4w(pHSr7Z?rMlWU~2+FzplST59(3F z_laKL zbadJd(UH9&$ti)G=VNSrnxUHIqXx{Gt`jL8_1 zQF&EYkz>$DqvPVXyl*{t(l}H7#0kF}R#CGM#I6_!U3MTV#Zvi^-`C zB2|4>(8ZY(fkkWap_&rU#V&Q_jJHz=>rc=o#3fGY(T0f^ZoQ>`9n)B5@yoY*#Z?&A z9q~aYyyf@dmZ6KMs23xfs zCh(CrF7RfI>}KM+W>p!a9QWI_p7dSB-*MM-o6CWg`V{xbR>o!EC;ZedJZ5Dlu5`+R zOD*{3vO#2vFo}~{4gTZ_ zZFmltF8-Q*@+Q7F2)Nj(1xjrA3Y^Z*cH8&9_4nG>zxE%scKnF3{2Bi66Ju3*a$$43 zz5ZK&zMagjwQv3DllEI*`fYe+*-Qlv_$q&7HuS%8Gdna8Nf&#^4G?vzTDk71y2@-H zKtkdZCeFT#udu}xJNiNKt+rrV$^u)4k4rv@uS_&D)eK9h6PB`B>V9))*x#u%kTQx%Gc5JdOYbYzxyky_n$Nam&n=JqGPTuHY|DcXTrUOP`{xoT5V+}4>1%i zd{*^cJXbnGx#L-S4cf_zPVl?BQICK?{>~;#_4(s#w#hvn9<$hcmC@+0SB3F8uNQ zvdqQoV!N1Gfo^p(>5nv1c@DW>xoAX2~|B$f7^S&d{p8y=iu)+__l~6roq~a})X-BG*V@wZ8uD+mZEoIdH*Vf-x9{9@XIc;;pS+HcLV511fYk5=Aurrt-n%*$~^bTRrV z{i`h3)-pV?SZVXQ7heNH99xalOYweX|5QYP`c;xkQ&4kE<&S>;Hp32}9CszW7C zn7T9e#O=)F1fqjanW}ey{!2sXxDY$fmB)35tt*pG3jrBQ|G}VX_+ey{7HYw<7|8UN z!Cwg#b@bhYBzgu*C;Nt5+PW{%kXp|Xx87FDTO9jpaOgj%3X8kC&NBNC^dW108 zeb!D6_i_dC90GUdl7`Q~YHe|@-B@2~H`kZj#^Ov{#BZ^kx6ReXcJJ0!+umFXgC8Co z=UPQ~oUM}2BFczD#0gm!p`9#pf^lQRJO4pkJi%*yVQ_Yvm&6!z!j;lgiOzr}n?J_xtI@Oyd5z|qBEh5AIW+sn(-HNcP-UNPeGq$m6n<^Az5Llg6+=*Yct(-71 z4VFLNd)tnmSP!^W7H#5&&c53Q3cu9TB!#%XXsi5Xiw|CzSLT&@WnP(|-Y9bwv(c%1 z@Bd#kN@V-PIpTRWYbM5!*|qSCMcDg&U;9-1P&b;n;HzHXqOW~~(d@mVl|{zW7nJoV zxxTuV({7ua49eX!htB0UZpLD8O;-Au4zEV41>t2k2`<;Bw(@g;?*wLFAnk*wVb!0U zkgWGHh%Q}gGT`!RIdmG+*KX??1Xn+6ziTnB%bgNhcK)SLkG`Zn;B&d^OG9Uf?$rHs zhYm6HEFqeQ`2|Pun3U(*P6q1WKhe>H7wJtq=-W5@887;d_(y-ZE`z4*B}O>`OCfTq(@w{SEZc3+hwBfTjQ1M*^}0+Q z>ejPvO(6ETx>I#s{K0e5m#wi}UkGLp@8@Y=mhpChqhn-JZq4yKzb6jb+U+~H+iUl4 zx0NMmnCfvt!jmNE*T^m>Xw|7Hf(osqH4@_rCuV5Bw8_No6HcjP+e#vm1agL!mLKb) zVXhg^*cBQ`?`}e2;ArHbWR*AlobW9VC%0UP@;ze0K3SLSP(9}08nM$ zSQv>s0a5e4bMt0hkjiTqnzT?w38c%@%}PcPgJO#F;{db^)k+duw!R$gg&mY5O zHp&Eu$WHt%R>oqK)pD1-ARp_dx8X2r@Tdtnvl{K)pJ*FalV=vzf0ggj!c{xjdB6Rm z-~SKV```Y1ZE@z1?9T{gTr01`DVq=9Y+wD|ztO(+?&G%e(MkK_8*ekdb%IfTu-=3V zJ)oO(32$qCrrxuNPkFLI!m=8VXZwO$cm)?|R%1f^jfki@!WXHpdNy#xPd+|l zGkIt85nIIdyDi7-d~#8u9?Bq0>kc+0)}$ChOJsrH2(9 zP2t|>6^UmOWr#36#U~p{QSq5a_T&Zw;G|81v+<=0Mdf{_J>A)DfBYw3Z~x#A|G0hh z=rQyat};y#Vp~E7!kwSB?UyXB+Y#zHaE<5BHjwJAO!R{)u|->+KmaFr=xVblF7DV` z0PgQR6C5-6Eb`+;3$mF53Qa)Zg>cI=o}K4CJUGb0uW>CO-k7TI;*l~V&G0YWuPuMq zhUa?q|8zh%i7)Ku!-YTiUR)~NKGW~`JGba3SZ4A~??q_sT;?je=-Lu}8~m7ScqxmA zH&TA<4=cRUXP17|`%Yc_hqdq{Z_5-~SnhC1mH&A-Bh0!}?%Q7S+Kr)=&$K>P{bIr7 zrK0|sOywO={rP2>GkExvqMX|>evGknsYS{@aVh_3|1a7KF9HoWX8Q3t@BZuQ1`OdF z&w1TBbQnK{;R*kFKan^CkI>Kf^P&cq3U%H))m!x;6i*lpJq{yb| zSISJ_Wf8b+=~%kh$Zsw2@b}XM%1_g04S_tWKFtT%`o-3>JU{VM{>AOOf;O_N+@Xgk z|3-a|@YHegAuMsM*l$`E$7-gvz77u$+Owz6LJPw;H@DJ<3n%in!xWCL z{e^WWujF*FG$a3UWxstLuf3c>uW+u1=$CefK0jBcl)K8~|4JyOd>sDI|9+X~$4kYZ z(u~u7cGen6_(?Ox0Q@9u4f*y3nPsfJK)Ix(?TT1Fyeda)mWa|P^oi*W#;Ov z-Q3=2k3RgM`TexjWv>rX$tyup_@fLmxZK-6?5A;6ByD7V$6*ocL{yrB=aPU`GO zfccFHX}o)IM5Ao&kPbldJ)sdEpZGEDLk8;WsShVBfAHQ1?cfMOg}-d)Rn^kU9hUFC z_rv6K_rZhq;iE@2!RSOIig>hZnQY`+;Elyr;BxLRnf1&>^zoH*j3f&hRhWwZnRd3LAE!w0Xo-}vfp!h0K(S3zj|frk_U@L33F z&2+w(wt1Gu@vHV@)Qag6IBg)VIBV;~!?ZnB0MmYB6}(z-vh7<=`Ko@PJ+TPl?jPRM z#s4`3Owi4cE1Kzcov2uGe`Q{xnWFvA%Y1HX%(4#qc{DErujw*=PRseK1y7k@U|p4D zuBRWBpYk=|hvirO4-(tHkv_}Qc^5A5(#KxVzn*0$<_WsSN%|}M$;fVOT?PHVWU4F247w~S7ePgkJ#`0N#_%S$cN3%1`g?TWUT>2E=dl+&X3$T)sN1fe=*Hi7pJUNk@GE_aejitT zURq@#6ut;<4BS!%$`XAK>w*9gYSJB^5s&8wYU+dz`sQl_7Hb*8cUsGXecp_^QWq(l z3a_s7jfzc{>Px~iyJT8nBCqNBB*HKWnrZ{_>}Eurc$!iBB zCmGdg$An{S;yv%CsJQ%NY?K!>%|;U6D=iNwoLA_vFUuSwn~u&d+ri0sJEd+nmKWRW zcedNDO~2LaSWLRfU(%Oyp?{lZpE1qZWvClH)k(QU;w;b4wyl-L+{7d+R$W>@V^KC9 zp}nPcg5C*0Z(~wso`XxieVU(bgm7q3w;lm+&p{wAe_ZU3S_%+tdzD!y2g0@lFIYDxJ1NX$7*--R+0rH~+3?C=axaZUDF(T7v%8-`p&;opl5IB7Rr`Eth4N9+%Rk^G3}V zSjECIf7|8)ah*$$=fH^Yl*O`1JL_elj|j)QUVz5Hp;HkfUSih^Tf8r(X zOui{DTxsTQZf8g6K_>_8V*gn?-Feb3k9XVL#R+Av)-y~0|E1slU66WN#`-TF_(`Vt zB~SH^m3M91ZuB^(e$Oe$xf>9mdwug67s^_<+RzcAhYxhMlt1!Rn33lt$EANrudI`i zdU-?3w5R(KsM!+`~q#&O&s0UVo2#p z>P*Y@35(9HktXo@>5e$bgYsI2^tR^ho}J+j-1i?pZeRPOKWg9j*0hbd1<3#ia&@d zXthfeot_1=jyc1orM{!4E}6yCewg={Nlb~^pZ2>-EzmfZt?W+8~$Yrdb!$~ z9rJm_7v;e z|IC)Mr{1K2*-1}ja>9+^yZX1%UsrkpkN9q=s`g0@lP15Ucaz&0?itCoj^AvXlojje z8N`3k$b5?;*HlVHOnk9D&hz#q89*hw9}BX|H!(cMhw{@hy5-sTVfjs)WYL*w zbNG)!>U1k%#wr#y?fFH8eO&I*g6{8CGis-TFaCxbA6JCM zo3d7MtsB~mH1-`kGR=kC(m}jo_JT1HvZl95 z*KOotH!nG^@oHy*t!-@Nwo~Uu)b+h>&NUltF=Od4ZmGCJFTYw`MkhlrvmE3f3ofCD zxa3K<8y>1`m>|!ew6ILRk5J$9HvB(-29Evg#3$>NMUk*#ZdJ;F}`<#RHsFy zNNG*H4KF6qgxPqO$z%reh`*g*n4|KG(7+vW28;qDE>(%~n>4`WMtp@<;iD-5VWUwX zmW{w5jf1_h10jPW^Xo7tI4jV=J84L3#_sCY7-wx|sVy_`TU%OeH#SxggfQ^IUb}ba zc3T3rr#gh~t`~XM1=SN6{^<0qouGLm6QX>dk&gn+Yo~H`aTmb3GH}H!85D5f5S-|+ zUBCn{7m2+lT7|=FweH;7Zntl3MyNVDdw8&){M`YmqAE?ZbA-Iybs;_uz+6;4r8PMb zvb?gElfr%s-kmD$vQWYHdcr49cMw$GQQz{x_|y?NedWtvY#)5^0gZOOZQa;z>zf;G zXPsoNUmdNNp{zJ8VLb; zM4o|MlN&UwG$B*`4Kehwcz^C#Wa8M;psdn+Wl# zPSSQH?Fp-PaNQQt8Keytq61%@EMS9+-+LY#M2uV4dD<=^jQPY?9rD-nwLVjVz{-T1 zb(^hk2|6sDL*ms*9rR6-Ypegj2D37wkEnd?KYBc2 z@EiJ?07hBt3(ITtEdtM9@0+B1g^#?9qSXxA)BwEV8Zqg5Se3cw8J{xtub!|~zszDT zx|3HMc`J<9@9M6u^edooJ@LDW-lgBPb>TOse!KO0C{F-SFZ}xKsg>-k?tbatu|BH@ z_@21vlbH;_)`?k$r$bi=O{C_aMwz1L7}QzTs`Gr-A`1&nV(Ip0C!(w);zh5;mb1$4PcHDr9e12NCacAB>#rv87UyQ#3Upg#jOU`PWid^5#sh;#XkYZy zo_iHD)@wbfah}!bDW6G+kZ6exd=Lo;5$dL>PuppxkxnI-tZUn7LZRExligTpeb;R~ zqz7O&dSE^IB}8+!PMj2}MFOv)hCkpba;O+2KBW#E`w82zj<-UIn{l(58X)rJ8e=$5 zH|69U?QzuWIq7wU??hZJv|B*OOl$4l?OW~ct($FYb2A%QYCJ0~p^Mgt`Kx?wcjE+t z^-=B6FzP2=3w~G^?{ZZ%;UrCcgrq(LH>YpGCGm-q{vv73zx#^|?PP3_ah&OuzrI&K z$RlKo3pkGJgeMYX(a=Sj`hIS;;o!)>G2u=E3Z`51Ct}{iI|c;~=_pGUnq72O2HzRoQ@16vgyopgGPqm`ZnlN2&YJF` z&0XxbKmD)%gZ9mT@E^fUPw@lhtog!+##z79zWUexX4^ShY=89kztvv9_my_<*8P+} zr<*Oi`Cx0YUfN2>6sBFy6o2NLXJ}kwQ*G7r!ki2HzzOO7M_gf9e#)Z^Ox^Nci~hEm zs_VcNhfaI@5!1|MLb>WQbqM`0yt-OAq^o`rzHm``t|pX=r^LZ>3B)>@p*_(~jv0SD zdFfokvq$Z8e-~OgPctSitBzid5f*LR9}MxMYWFNIOnP16w-ob$v zAy5Z^*7kD9f3`JQz2*lyO!681UKZ09bK@OtQd#Hbn3IFUHV@j%wAB^D zJ-sErDX%9y0bYJfo*aM=Zu4vHa?V2|@G}3`V7pa{;8oBjasDP-aa6ZWm3N4-ywo1; z?zXS}$sf0GefQmVo~D_)=FpW1>v4XliwX1c=8?3iV3{BEr(Rk6Wv5L#eM_5AcXrd2eQxv#V%9fZZFBM@B_T{c&8O?cCFD%Y488(8KRart zX9rXz?G7F|L*8gFsgP`bfaByvdEByt1bBN8W}o^vY_k`~ZSL|ETZfE1Y~(?sS?Hg| z;9y2Ni>0d9jJcqV!WD-~8hBq^WhX|ivpsmdv6XT>UP&f1B z>1~vL{nr+=U;~6#XW$iY>-ID%#K`;TP%!MUHlby`-^T5`JNwP&YN#fJ=Jm zJVReydfFoKpb9ej3f=CCc6qg=g<9CFMO@_!dRF3KFVQqtwn6>a zPQ!Zq8#+_;D)ASG!BbFt?gD#G>%*NtLpSGnb8)S0E^R=!g|@kR6W&>3{BhNO_};Vj zWQTgA|B|0woAFSUn=K(GGQcseJgZgrrmWNgg#K!^~LkQm5 zw4Kxw<*~_f*9t8vGt1}wQ8f3Ng@bIobhhqWtPM;osA(xF%5!; z_pw86Ocan1+9U9=5#AW%g)6(M4l(so-pRVs_NS@X6)$mPDvo9h%7iaY(~~F0ilWJL zg%>HsvFK2F7#{!NjRLt`1K9P|e_k~ECnOltHgb zal&DFX`%UTsvFx|?e@(Z*^TC@ot>wT+p{N+!^94Vyb{eFCdVjYry$^>FH$E9z$(~I zg6JL`9<|+_y|%NnoBC8i^IHMm{?7N(SluDyw|?z3{qC<5Ip2BrJDFg-bMHRF2;l{u z?qFWq+CZ=Z7d$h-&S2YJI`9t9IlW<>@IC~Toi~+|#_Pm`3*z#T%8?y#gpA6P1Bu86W-bk}#obLv5xv^_o#B~PwpiZLagp1rX6qKcbIn zsT02rsI>9J&BP(DIB5M4}$HVw*t#XhByTt}XM9zZg2HUZF$ zK`-PnUMDDy2OOWIsXAt^u2OeFCvwp?*A6Z&Wm3S6eNHasB<_NflwQ@PUB*xU+US;N zU2I*Q<;3N+Rlmq&5&inLp4VVmVZ;Y_jK{9`Zs(M4W#B#p-YTMR?%JEh-#X`LQ}LP`NS(U!f#^1bE2npzr?a$ z@%J_DWq^Fn48U5;du?-#e4cSfdwWSH-^XHfes_DbJ-D^a_{@oW+X;LoeM3j-Su|B| z-a9zXj`S*vr@F4P@Vi8sOz1j!6dFjig5f03%oOS=k?CoRPSoT*byzf3yhSI*U&$Bg zCoZ~Jf%{g|M)>5NFnGi^6MXrFcZ5f{bsYWL42V$e8CU#zIy1Iyin9yD#>--^@OT!l zGhiMe<1>cfU0M-DHtOnnd0L}nl@s3;0J%U$zit>~7TUYt3Io6PsP`V3TP#PB`WEiQr%IAmc#dR2h_8HFnJ6oU+V`DBK|3%M^&6 zw|uTA{DEb@np)T`c;h5!P7G4k#W`HRdx!NT=tMTz?#v6Dg+s>uAV#**q;N2wnE2Hx zjo{Nw>fJQmYDyLuS6EdhN}IG|OEm*GC8)SP9kn0dlv(_6o#Y#1uB0(c+VCJB*Z7Mu zE?y=Pp7Zs_mQMJXpz4CQbh7(F`-A`N|J5FU|Bu@oV_i3vr{5vn{L(_Z_r+PulL|tMsCInU!7Y{9aFjO3fGBdkjrGM z^BBepY;5uZ*%T9dPWy3F-1*T#n>pTV7kiJ}`QDRk6jxtz)63_=fWCa;FY*H~MM#a+ zORG!y5>ZQ_v2kN3&jxilWejB`fb`Q?M=oq-4#W7$F8#5#WdV%1)27qSyXaEk{KJZ~`WL!eY{@=1*LZNl1)?fZN@bS)|ELf8cX;RHM~~W{{G&f< z-~H})CwWU(WiT0p24?5nn0abO88p*$&U0Ri{uN~Ih5zukU%9qj7l;PWcU;D;qMM`op-WJFY%IKd()LF5)}aH)(fd zG(A72kxtRk%@aTCyXpwjk<2?`w!OidVy;PgWpFQJyp4}domhAD1uiaYUF;Rch*P@S zF#Xw}`d2UY_H#6rXV{CygrCdYKVEy!j{j!U;wLoY6%ERC>3Lvh~sy63hGpBtK ze)BUZ^;wkT@S*5C{`7!ZK25Z~);9bk(dJg$+}g^i;5&Ejv|G1swe9Wgep8j7kXeqL z&F4KVvjj=j@Tk15K26^GMo$1&+lbepM}N@IXZl(FOCIzxL#w0#Zs~hvC-ONk%+oYQ zd(%QR((6idY}#zK*Ro_7hIdGK|j`fwJ-}&yl?W2z$6)yZrpYB&0TUL3)EsYICe0M*E(&F@qSqPhpAa z_2yGt-}Cw_VWi1tHiLO3mK}`@?Q{HLS_h3bgh43dMA?9xdMWiH2Sa;|1%353KyAj>p zGrzFXme#l0JpNbn%k7kr$>G^$d%UyX9zES{PoC|!y~C576h1k-Xa_u>GjhpyiD)RE zL_Rn?YzO=M?d0f)!GCKvw>H}S+c(T(vPm*!{MvDYAMJPhAinX9Z`3ISXuNsj zMmr#E-qXw5puZabe{Ll_TqY0s8rkS*AbK};A)3Z!cZJbK}-`1k4jTt zbO+yu#!(>XP^kxbDBnOM%)ztbQEMwS`{0fp-yk@1!jS;mLMgB23;BCI{zzM`=z06R z->Baxwg8a!8B72~Kg;pTyfUxMEAz^{Jfk*a|2?#wa*+5c`N-hvQ|S+JPZ=!cMhtJ3 z(4Rgly@T;}EA<3sp6ow;#-+2VKBd2B@Ees?i+=_%+G{hx?RoE?+1R%X`;*Lwqf`CV zk52Pqm}o|S^hX&TXgY9naGcF!=xO8hZ++s!8(v(Lb5W(<$AWL!u>g$DGqJp@0|C=P z*O++BBtX}h#&cW;zu=@U<8#HWML_%hF__dwPY{0!qK%oNTgvMn?_+|`4Re`5N}sKg zz;hG@o|6vV2+Y#&E3d-2+>tjt;eamq${+9r_{5S{_7ED-qh}OK1$XdAo?kFkrU@!B z_)O9i98EnKrVeVN!nq=rZsSol zdSEpUuE#jYIEjbNg3Nr;QrMYjQCBh#V7Tz>DOUAH7ct!s>S>iFCyzRA8tYROgAc!= z>$O!68`k8cC=6skNETH`IBIYE}I));Fz<}g3orW20FQy&-R95QFc>*$wPBFij(cmv!W zr#PmRM}%J!l+YL)y$t4tsr z84T^E%6VNWe zf1D_;eyw1}Nb6SpTd!%J%n<)sFoAfU!YD8QB}w3gkFO4>)0g*chUXa?ga_Vew$efYgUYQOjY`MUmOmL`Qd{ypq{e|GH)A&cq@m}$2Jm2%_ z@dsagnn@Ve-{hUR=_~yi)~$RHnUQ)IN7}z_**eO*RX*Rm_0Ahq)S2XY+mQN{H?w5J z3~|j7ql#=vXO*itFwRd-vV%9WDUrr0HFyd;Nz1hOgBAkGy{pJ4AVcXr`ZwH45Nn^j3PrIyoV~^kbg_pF- z55hC2cYc=kCB5nsYR)^_=FF_xTG6-YtSSC08c46i$0bJmj5pE8Lu1nQ25Y|6Z&X|B zAS<8HzjVyZJqis}KcvOJdE;-*LiFP|L3j>TbR zX+B-Fwbiz7_z91#wzj_B{4A03RNdEcujAcG{M>w{?&xV~!lQerBUYbnKMvOXisz(2 zU3v-V`G?f==%v-bGOlfWJQOzMWZ3hb(hq*s>cXZ1XX zQ{wPTwp9Y{k2l7zn1gN_K<03u^4L7|7q8%!x_}?0Kkr7)H;kV?jT;zK84uiCz}4Tr zQkZT)(D*Km^fTtjOI}ijx_L$#`6+*^@Wc1z_4UL%yrFxwgvlOs-p2xyzL>z*GP~e*8GQK`8Ey-X4?p zJGSone|YzHd*l9{Tt`hMAjqr(8V31$y}-=EGJ~*1V9m7My}kDI=?)E(MlTtl!R|i! zVIz>h(aDOHl{Ey{TD}F~uJ)UB04~HHq71ns=+TqM?b+^b21Pf>e-D26hywa%IHTMe~Xht=C}W zx)S`G<-Mp0YfoZ(-7^3)sqN%8Ov!sKBo771-BNZ!poDRdjN%S|+}yswJN3TkE|Xbk zd#gQp?>p`O=6rkY)@oatziLa%tL@-ywtefp-S)j7ehe%Zd;vr!=d~*iiZfDG7V(~r zCFL6n&*JHhz!S=Ddm0v;yHFDcziI41^sTqv!M>gPGAM&D%3!;anxj(-FT<~CZwOo4 zKsr(CbxfqB({|t!+E<&&zyV0pM*e@XeGi*KLGVm#5`}V2*ME~|+m0@2t_5`|wnM?K z`oGTSmHGUcs>N&j%KSXd=bzf2e+)IB9m}5#;U~xVWtw26ERQ@d9WIM`=_`@D?$qoj ze(jfB@U`Eyr>1Kt2$Rmie#v+GH2rjmsSc6JalBlp7#oF5HyNbHRDa<6#2P8#BhH`A zjQ*&fOFJ{cG=MbJ9eY0o=sj!4$etEriyfd1CRe zcvF5@HxiEY+M%aT;7z&H;YDw7!yVzzhxIaya$rXBLzDdZPisG4I?3dk!A#E=9|R0f z!X0^t^Pt0c9*Y^}Ix)-GV_0=9bR2m|oyWmlO*D-r3icyfYc?BsrJsI=WeiC@RMCpJ^TM;^6vK1EY+)(5xIxmz zRTsLnE)WT4B16Lm@xnj@#~v==N&EQsys*COE1K4|&t406frpDz>hQIQX&U*ypc>C* z=Un#)T=5)Z0_!&u(a3toAo7NCC;9cdm*4zckEaxzbdzpQ5<8YWJw0xxXLYI};|SVz zcp3oG?e_L&yL;(U8himU2uds%b2)M5%)zs{KofBGjSW2bl?Fp>Dxvw zwO~sr`s6!R)5G`=T9z$zH$NzCka&g6jtQ@T-NR_@23HvZo|xhS9~Hb+f(m7yep1YTNDa{s+I`zVyZ4Zujrpfj=BWdvL(Tu$ot?JjLJgJJD ziJR#^%THX3Y5hX9&^?<0Mt$L?-5F0FO8;4~CNKhrH1H(MR!0=`T;W?5ailC4C&!s*xI8~b035Zs$y4Vf;z}NB5v{nw(}U7RJQH%v%Z{6mT#kT zP+xUAxHjY|x6H@5%3fjny~%6*tlDe+#r%wG-)y7u1fEwy*NHZ85;w~aF49!j{=;+$ zmo)mpGp0$o$hRm43wBqG#8nu|Xl0-CB0u=S58Kzi_7B>V$4{$|x17iuWw<6dcNjH) z!%yIpTt+>HP~FC^6C+7aQ2PnGf!;1Izq~ zFHZWMdX?uf{l_V7MfgFm@Gn{2`J&fx)%hpwNb{nNzdzrHtG|E4ulx7N6aQgSMhuu& zAMP`**Ylnr=TDrs<6VApW0adaz42gC`4CzWCf|UjWzHucD63gI2b=HgLnCi?9DRNe z!J4)BgujEAJXdq_`OF>9JpqQaz$;o~r6&MPm0LKlrK1b9;99nf^MsYUsyRpi5LRw% zubV-O!qWe^{>8g+F8ld1()xLx>1`A{srwfVg__K7_BLSoYb*(GNB=1r$G?ZC9;xfG z_)8|S(Iv1{CT>|OHI}3ucG>WnuJ8PmdCDR;tE{g1d7zcFiNut_2v47AJF$;4ugE^f z1GV_;n7~gD+SX3ddDVMekaS-CTm*<4S|D3T9R?R{HUvq7)H8I0x7`qx@fz-e8=BWQ z+SZMm?dI(}?e4w%?Z%B;?e6Wn?ZN$r?csxm?GFB%8=JLIXF6bjF_{2TGD0`?rn1so zPjjQ}%6~0%tPN{g`UCrc=o8hihtBw=-;a>B?saVi#iaofq1I%SPbc&n;w?@K z=x2-Yl>8KyNu`yWb_%Y#@i*&ElVO7o|DN+pyo&py%m~pP_LpfS(`Pmk>$;+gh(4zQ zP@FP@J3!~VEFm2uq&o4)+noyNpw21#K+eW z{z)S|s+A}51BaS)a==gmWmIzFP2LOMm>98oi!Qjti6NTT9?OsptZ!~@0kckpE-%$L z*<294ckgaj8t2;K;Zb|^=t+dHLRrvJ0?sbl-qC5>J3ea%C+9hhdyL2&C%gO+j;V&egEBWBP6fd7v6fSz5d$6EJmj^#bqwZ3lg)#hp8M<7&M+=R4p1ZaNJGtV*amGIpLl1L9TNM}SE? z6^i#ics~Qru zk6qlh-&CPeAk_Ces8{`B>sf_6N~G}QK|AvZgHm!_WIgvzdEjP8o;*ojmO(ly)SRS< zVh^sKYF=Jjrye}T+uEI5)c55{+k5nW`{L{O^1TK5<$PwLJ=!~O|HXg#_uKyd5q0lC zM8#dD&jE$jdJ-=zW+I?0Z`xYN6+1RgD1?o#EUc5{F2t|2FMs(f?KZeY&|$6HNm~Sb zb#U^v{9Vt*|78c?XA=bFtif&h^RHV0T?@yd>_`aP_pqbAgbv{1bw$s)FZikaM#;fS z1C&JnTl%C6DPFg` z=pY$e6Nsf(x44$N{yu4XT+^41j0+CZpy<%c`5fM(JlFAtEnLt$gn5lf@*Z`m88k05 z{ao=zc;a_^9lMNB2RuE+eUfgp4Z;({L;+)((%Gi-wCvHriC8deva^hFds=wibe8{G zKPy*1&9vSVni>vG#_n&;z}*R)(yyFouzi7nae?KvyPo`2pCxiq<YF?&hclYL2Tl4cbj43u5Z){NhHFWr8+L3liz5{P% z+QGqLzM+`KZ+@23@0EEf*b~#ME6d?i#~CSu^=o={cPflE{u6wJ~a^zbU zegj(>s9r2xWr9uvVE91Pz=!bRxlDE#N7dVjF6z!Ymmf@9SqhJE@SR(9ETyb4uJQnA z05zUWKhSmVOR%1T}L?6cogbkWy7VtkfHUU1TJ33}C- zsTM3uLXp^r8iSwO1{2Vt$_VAN4 zjpI9+rVaDT_#_JeQ!K5d6_ zCS&(y_+WjNcElKXjYoh!}D>=_?$RXVZKk>07zU=8TD*?d@&7mQ8IG27U8_QbYnde$jX$Q zxJ544?Pkagta^xZcg9gxnKpeM#^=Z}>T$@?>%7W}n)8^>w~Ri2vZ<}7m6g*jr3vAI z8~+3(opFsP7fJ1+IM3bBzFtDqNh}u*uX1Ydhd+F;edjyhX^$Q~Cd~e;_cN9OD_+LU z!j*Na?u}n`18npP-;v|aLyjvs%|q+F%NP?>+H#+J#ywB^k=FS%ZNVLLR})x0U9LeT z?(y+Sa5rwzmp0XDUAF3c)Vp;1aW*jg`5YSZ-v`ZbuOG_v*W@>T{dpMWtel~(%~mDf z&+(vk!%v=U+(0g_Ew7+oAS3BR7ATLOFIZmi8?YV#s#9yyD>9jPKe^{&n-e$dNiXOv zebwcppQiYx`gGB@uidc1o??iw>cby&B2-Q zt|g2FnDA!#OAVox(H-sQ=V3+}f1Lf1<~g*2X+3I4_F~#WC;4>nvF#vwnQg3FQ>9&p zKa()LVSgW)L|eCCnApBBOCtIhBWbHnfmkj!X5t4=lh(RdUafCz(9e2vDEtIG{fEsa zsK_k)Hu52@RU%JSn>%{fH`4$B|MW>jK~&GF-z>zzJ6bmpxOuO}4qY~+&BLE0w#amb zfKnQXT)`wbeWLwc^iAcen;u-;Ro|vPcsh7()eV1Z$k=6MnPZTWzqa)WEb~KmDYy7P z`ie9rkHM=h`qr4Ztolu4L+DQ&<%e*4n)vsy$ul(972ZgbzQeTYkW*!x;D(hZfh(P{ z6Il2q$+RJ%{Gl6topAdh;|k04*&ym|tn^Ef#k4oqAU3JrE$Y{DxrxNZa?|;)3=jul zIL^yhk9@*2Q#gcX`TYb#gy8REcZbRK%Fx8VW8fEALEiSUn(8;sLMQnzbbbNOXiJXy zy=r`KZy(>8Y{pU!`kr+S(hA!;7&mmdIp`3*$@Ly(P8QLjky(hFFui@(+tF-|l3X~_ zD#nP|&;uJ@@tJxX&!wwe$0>VVmY>D`GEFb>XERoSLPt7=mJ~`ig1{%sh+i7TRJxwT0kwrjZBOb&0bcPOi6}k?}R#iA1Br`zRSYBuwi*s%F z$;a&mgI`bot{|{imRG?QWsZSC7!@HFrQ60uez}4xi?7FRckie@d3w;E?i{qe!?SjH zg5r04Nm>P^yLwP20ONJdyZgr|5z@hdxA&>LC=D&a{G+E&+S9$AcI)T6 z)sD|++DDJ~$@`T06BimLTxbXN(T9)Q-Y$6@9=E%9AAqk)lGkS;xDg)irp>iWDBjxn zWtDU4Btn=v0NyNiPS?c1zVf=}%nseze;b>HOwr;Fn9UMS$<&pEF>e)0su3n(&zQCm!7f zKPOmDbG3CWgYxt9W9UTb;g!=<>g~pz_N6cXdKT|3zwOLj{1cw#oj-ycfZK_}cjAwy z;X`=YE`*!OFWfvsJFTC!g2a^uE5O1yxukwwj4oRpcoYigtQ|`4LFS8}A_l&w1Q z)N@WgOAl-+CeOxtWnP(A=9PJ6ep=&%t`fVXHlnomH<7EzVFYuVK`zhG$Fy$!Zhrb* z!su*D4);L~|M*h_a)8j?K0VMwGclgYao-%sMZnv~BJ+V4*$*tbc;b~cy-I`=!m))V z7P$0L^<37d8so&+nPDn_e!|W#y-Gc&+`|;iC@oQ+JMR1|ebOG@zOjdmr1;mf`I)A0 zO<&#zkPa$bNLh%k=|lj1D^@ppiTaBAXHFEMw_w#HGilImCa}A8^H?l{XLnm?(Cr{v zJ&NZHdexm`d5@p*iANki)uCI9C3fW0SLkV3q(M!3*U7|grAg>hbd@;L(Zc(SF<6H< z8AxHTb%|aU%cd(%Q?7V8h}M-Rx^>FV=gK>@@7ZfIk%{$s(43Y@eYz`H9YI$=)5tqj z&QTtDX7HDT%Q{P-)OZ%NO7^@hI(^a>ZH5Iv zw=c)6(=OJQm)geaN?XsuucvqC+p-%?qth0jy6F3C{~()bLo;xw?~p+++TyC8s#)qM z$SfyrwI|zT=Wnd#cQV)Z=EOx^Yg{|gYeF7cr1B}F`m^;uii@{&Eqd~v$3a(M#&ukd zUX2w^^K!iALXE&9V|ux=;kD;cR(SH2i(IqK&+(*f>WLAi<4wooL#`wrnv;`llPl&c}Mm>;5V~Y1!eBkFuw38?bC;2Y<(!#=Isj5c@m- z3NP!=KGgaLwv&7rV=3!pji6JqqUJk9%9Ke>dM)t)A-;22G!>>1%a|(dlDbp=`AC5# z_y|F<8#mj{xBfzV?YIAW`}<$}Mtk?`kJ|72_FsiZ|-S79LR6c6kC!%k7ogS+F-=?_bm@!tc(9 zxR5M7!ZJSqo_;HMMhjm$=ARu`e4CH$A$)KD=_kJMpK;>Tal3%QLpU8z+xrE$T!;g9 z%rl(%d8yOWcJkzLyV!YTNj^8G^c?s`YrCfqwtwjgAw%2jDUiIZ@Q^x_{NEKKdHZtM;60dFgMP|zd75HG zCMmPzp$)ILh38gXu*qWY5_$*n5}C5%GrEZN?|kD}d=rK@gShZ(AMBj4pVu4n-qwvY z%LWE@7xj03HBVf1V*LynWWmWg(-mL-EQY)^ei~(y@>d#LM^!Il;n&SSwE?L5wbH8t zkMw~TD42M4s0sgk8Zj$=ES{8p!*-H{hGnkHVVkj@(jIzU3>wO7sTb1MiW<2{|agfvV%@bej)`ETEC2R-hzP5v5rJ2sD`Cp@V8-Gh(TjcW(iXMIi; z-azi0o*aRTS430Z-mhd6J$37;-z9Gn!VOQtpYlmIV96ukI9_=CEcy(aay}Ka<{G-?@Ks;Km09|ro z3}ztm#2OV`A}n~Osf!x#C~f52uIzkaVj8wh{FIJ!*{h5Z?(4u?o`HD}ciaBnP8NU_ z1QFB@II*4xm6lFON&~M3$gV3giI9TEhF@IHqAd9x-ph7GJ2*Hz1LgsO+v@|!Z*h&z zVYTfaD7+Ec5YzOF3~CNhF7|0~A2IOQ+uvyq?%Zg<_Qf~b@*H^r(;f0IG9Daw<@3kw z$+M5!+2v_l-&${*4BS=z*EZG=R1Vx{+ncXH$fVSh{i8O!xY<5_a@0=Fom8Oipy~11 zaTM?Uy<=#&*sdVV`ROIf&qg~uIEL=-cv*(tUi(bL#m+3(U~dR%2a4|4U6_GJ4oDFW zXh_(jc6ofzPLKB6`SBqP<#l6SC@G{C7??rVE6RPPKtM=jw{|McPD%l!;It!$DdZD) zXO`zofOP>@lZNj0WiYs~LbMu?E-tRNyZ7#bV`nIw<;4{gI_hO_uYKvw*V;0iu(=2y zw7qsTyVAb)?GLg|VD9R;EiWig>3Bism@=MGR{1^xoY6lV017U6I+X{GxVftOjIvWl z+WKaY!c%46awxzS+rx)%w(T3YodN}4XkvN!`Cs0xK}#Q)5C&ON02P{)7}{h|!kc2$ z)8g~pE?^f4SOm}<1L*6WPsX+bv~7bG|J=!_LaUI^<^wGq*%&xXlrY{i*tCt4RxHXw z1?Z6u4x7br%afG@K<<-9|6$FcXjW=vcg$uI0OFw7nn06@Q~=z)L1R>+hm~J!5q} z)!z|0&nOs`&R)~WUSt6QCz3`k=g zz^Egkk2q2709qXq*U4=0NdD**nILB%6r9kdYGKmJQ0j}qUjk3s7OlZQx=8tJeUFk5 zn)>IzD!7#7U*YDDcr`iev$}5S(lUypDxrBd-T=bGJ$%}fCUbXOG9^&Zuqw>wfwpLvPDAhvLal}=6 zlZN+%C$9Ba^bFqWNhs zBkQ_nPiHZvfOc-O_0}Xe&N^O7{g77F)s@}UyS(fqlVwirh9?}KSnlw-JcPfzk;xLu zu(0H01mh3jWD<>fkZ(+*3>a=|z&s^YijGfs#PJU_A=q}BYh}U51>cgp{NR}jbZo_u zC&{c^7k?AgaTGw+l@(mt_gW(lv11z5*Ix&99v#VBL{)Cp;wJn^)KlXaw>hY#%| zYQ3SH!tbD=maJCZ>_DiJKLM>*4AdbvB@}+_qA1Tee&8>+hg$(PUkfjL6lkg zRahZz0mwiX90u>DWQk&#@xvBH@kAbn-ohZr3^J~Vu8z4QJF&_K;bp98TbJfUH(h?A zr};;6@N1%-?!8%zS({ zy?v!TP?J{`GyPOSNj(cwFiB-*L=3G{mU@e( zasSqKTif2q#`fh~ueE!>^*7qR-~5a1KmSkuZadp+?JxcAKMj4CYRm>6<`J49v;3J? zPTz``KQd9SW)jXk9gF5!d2P8VkMt3a&;Ap4!i1YLWjc;d;|dSoSqr$sYDT`kr(NI{tg@vy6klAwTR+xqy*n}PvuTZ| zJW1Xfz&q*dW)(jr=CfgLRB`T24wy^^W0h?#{5tVolicuEa8i!iS2&4m{#2oUr14!D z8&VKA8}rd)6IWb2o+&BCrXk_EU#0z`C%S6N}JTzsbU{etqsm|8XUA-n(^CLBFwB8`;Hk z!tKvawcZAVj^RR*dEuWli9>%HINg$-e-m89!Nn#Qh(E3V%ldrn&tK8ia>vE5|D<&M z`g_q_y5aJW^up5WA44E{>k)q=YI^)(Ch4)^J^Km$u_TM@jXf^>uCCC(!9(8gvx01J z(bv@;8blLu_Kw(~45g&)a|IvjkNzSlf(BL})4 z50RtkqvdgBg>JX;i<^X1p92PdC41b!Qdih-W&wBw`CKwHa!}ccB|+dNKc2_Nvn=?^ zV^h}oS-)ZJ^}f2p-_yXk0f2B9=ST`E?SGY#RTlG!#KN`Db1drIz9)axfnA)_`aFkq zkcui!$Jp>iw^0v;YrYapT0&Fd$}_eNH&iGyjDLn4 z^jo>geB=A+P;Xn?-`zzAp}f?0Zd@}R`Cgy6J#R-R$LZIi&vahVq|N!-1(bYTyi^ek z9_>=xt32gj#s|wbU%mlb0ifA!p%j0h6mFdK}O zF&%H1_+g*(4(#WN{G;q7{gm-tW*3(dB-Mbg<6g%H$~BY76f%dE8OA7k&G^?Q`Qyr1 z!jHntyN%m{v^4XS?=l13wRP|3UvA(2_BS&TVdHiuIUtgM!7G^QjKm*Xr=ZJ9eLD|x z8Khi9y~7jiVLMhh0dI5r76N#w?HwGorznPpG%$AwtU%u6*{p$Oi}Qm@=On*Io2EA!~hua}*osq#~VbA?z&4&&i%N`c8A}Te#9&pV7$c zrJk*SJ6iEJzPP(n=e36qQQmp?WG(gM)o|L6pz9ajeiJ%wv?a!VD+{yj0EPT}-$yzB z;G=eqaPkDO%AMKN_laxjE5cuc6JC{Xt@~kVk6A?3W+2mdSmIi*^19z){=z%&MA&6g zMqbthre#<7g(kQvE&A6tU7(*9T*$Tayz#GHZP7@$oj%wY^8@E=Tx(Ll1{^B;DihU- zUY`tBfu&4_X{XBy&edKE{Dd^!W0LPH^UAz3ugoj+Q=3Ro|0zqA_g!9RB8dJh-+Xc+ zz)2h@ACTcbX8=N6(_On=F!w%2z>&;`by+>_4m;$$&zTG|@9tOrNs)A#bjkJD!^-@q zet=v8yT5eDhqCrBFPh-y@3{;r5Bts^WsDs>u!T?Ia80jZUqe zp&LA}-NILW%)E?0^1Q~`cWt3GkiMqZpxwYrGyJCOF>r(*91BnLF8EXQApU?J-9O<3 zcF*U+dm{bh*BUEL50usD2-A;5Bc4Xs)`j{}V0J4^>5^|8;o_Az?#dTT@ClvF1DK*_ zq#%XWI=*{Wae@1hz0TVMTlwoTm*~@_$%yB0?JWi?+f)v+bMt z;<}I)|CeLDs@cWHWyTbB#j}Hd>Yiu$K-%u@?=em~bbcl}xrCL@)}M=*o>I+cXw-SB z1ScU}cz0almCue5v{rKJ|kn zRIDbQx^bNn8vKHvdOHtp1o2d&S9=dz?Mem_uK$P!&lq3hf`=1k@~2~nlapi0FD&w9 zEG2B8-I(kNW+$^N#yTlT9SjA3BJeZ7Ca0@N)wN zfuuJN((oI3^3-wSH}VcFp1WIes`Bq09_ET5-g$MQF!B@_gFd6L)Fv0wPsURGH2yct zc3EiH5^NI&nvW03Ab5#~@mw5@9KbF79c$|*cG3-bR5UL?!v-&v>loDbhuqkG+TL!BRNs2ZV!lA;CT}n}T}(VA@(xQHGdb#Z4bV9`@DA zAG9*(1bpX&l#_T*!eaRs%X8B6;Nov?m;nF!R%y;Teb3?{;S+tnj~61oz$Lo9;UhodR2izYx)V!zBa`#2A5nT7>%YQ`gI_`t z+QZ6D`}0~ZzYZ*H>+^NK@vb<}nI1k|kS6z(OSMHQva-0;w$?YZi0`6~H?p|UyNJ7t z{4m^WpuPUt`j;0ywQW6?jPUAbWG{5gh6}>STwfi42)4!BQ~Kecb*u}s@`W&YuR7#i zc;`qV=pP=&R@vo6cuqRX{K>}-d=~Lo%Z%F-KC%Iu+lGd4vi+#aZ+c+za1g@$9G^<-(*<1Nu+?t zGt|YI;H*E!xIXLexNl``C8vMg&^d0DimU>!LS(?JI+x!{Z^Q=Y>i^|A7u@pwRogVr zo;m{eNi4Qng%F@4_N7{3{@6NL)!Pb8*q`o&Zopr`Z6w4R^}u=?lI#J*D}oW?DQm6 zeXzHiH4d+Q_Ivaib?}Tu=wmF0xYR~KNoPG2KJ~v0C5}7BroI`U|C6xLYGOJccQg8( zN^>36SNk(fPcu6|}u>P){$)9yHm_7#g}+7 z8z?wG_S);OwWA{h z*Rdy!{dl~)!Q~sT!Cnb%BfujhYNuQ6!mLh61$}X8DLaI6HADm(0^Lr+j>Ard|H9Fx zLjs212XSJ{?7nTfI)L+WWu% zdt7_%wbvg1$4|w*_dgQzi;AN$ro4zQO0JJxETHn~tdJDxi9Vi0P~D-pS!t#NQ5iui z^<2%-oG+bqD(=+rH3zSbo!fUfE|;jQJXMLYBBN)Q)k$U>CT#==1MwWNFgWRigLn8@ zXp0|eIGa4%E#Hx+sz5k@;+;0aOG4xX&)x66>(p^&TkXaQ-S#W+^Z@f)Hx~CRu+<>S zuB^eQAzT{#u$GRS%cVoCDd%a>9shZx;ZAUiz{yu|A4A{5q)jgR(zl>!FQ`xBlL6>~ zdAbXe!4Gm7-7Zc26Dl5l7ScSH3}X~~_7T}HoDHi#0+(14l<)Q+xht)FUI#LYjIa7H zkb~aLx1mH~zw~Q|=$ck90V@NssV^U_NKwphc#a{hTmgIIgon zji-arxr?4POdTT&_E~B@UUcE1per%8~DATeY5Dxt33vI>=NriXlFt)%a1F^@1Uht3sH_?Heqzi@K7@AlTQKDqrM} z+{r2HkO$>YKHbK$07)xjyS!O;_%``NcF^UwN4qgmOlbE%Y7afjdT%=57apOVgKE3* zijeOY=BZZ}u;ng4d2*ccFu3Qo4b_M2U|^DQ_)1C3qCe%y8Oi=*aY18Wjp;8gWbU95 zhJX6{OG0Q!Y`+!Xt&59-)11hKeB`PkY6mMw0TtV)$~$E z6*uQY@s?t^Jo>ZTG~!q9jS5rpM|;l&;@qT@@5DCZO(ymoue=$FFQYA}I_P>zOgV=x zaqQU9xc|QUy#RdT#7Up5b^kLrC!Ehk;3B&{mn8I@8K^#h#Yo=gTvG>m?q0O@!mrGX zk9nvPM|octk%=GOmUioTp88(y?kg)@3N35>W?Ph5+|o~n?rncip!>OCrORr!d~O5o z#R~A$_NzZwzM56{=Rdj-Wue7LDnyS|2hN-A9Gi$eJ9g$`jbuPw_-)8+NM3LSG>gE4 zvU4&Ry5?1{(!0bjRd?fCtp5Ch+`afDe_jBl(^m$PPX>+9kHsH&da=+N`BHTeBXx)F zA=B^lGhLy*@>hA=3B3 zWEogq1D-6Rz+p^o8CIBea{ahFgnzxymk!A=I3&L-Pgv`?)3sBd|mW~Un|zQz}y&> zi*R{cjq<}L9OcUkzCzqE>v#2e7Ey)ikJG`4(mN%eeR~6T>7u@+6;zzu)@pRzr6wq9 z{&POzN6KfuEP1RnO}YT3Otc#nh_X`dIyddHlxRU)MZV`4OktrV?GxE4`8q! zaCUM!=B8$1p3lkXc|~m-Kdh-V<o8apJD z!~1q!74Z84q|*k+)j=}c6>LMWS^rN4q$IyUfWeZ$*(f?hNdmef0rkxLq$7=pPC?8l zGvk0kxyL(qO=O4;bmFP*nMQX-RLsVi%u(%T8XBR@47h$+7{C*j_Sc;UF_XfO&o&mu zL1quY0= zLr}bmk8dvR+`iot8j@~t=+UpK6I+hw-FmZ>l8D2PKPG&_O4@+~SH;d9qjBmK-vW@3 zlF*u&osZ*EEDt^Lgiixo@Q9|fv(0$)(BYVzo{M8AC)IH*#KR9iB)Q&O8m%&|62TMD z4mSo*-nGGXC_^JMhkac{fBoJLodXS8{#`Fc`OecMdRBZ)Traew*b3RD<_T({ELK`1 zHDzK4v);)G`KID)ymCkZ%1imk`Ui6WK^gJuT{kj0Rq(7EuJev|u1F!Bk)gpD8t9Gt zzVd}QxOYcv9~p>|{-qe_#I@?^3tzr3j!e$SOcMcy>Zn18!ttdxUn!?F#h~WVMEDgx z?{q{)Ivk%SKv{2=1#jp;hq4r-!y|Fi4bO_fes!FpBT7o=lucsg_4b5|Oc&kl7t$mz zTUikuyzpD-59x|0vRm?6oszDm8SPW~&4uFCh=**q_)E7u9h{0rx@Fvs48U6a*NN6E z@bm%Lq8qQklL=3MYCrvR2wZqB&mF_LeVh$8AL7j5L7FY&Zt`zF!8M9;OUG`-u+cRtjE7bmJJ@-looc+$^T%S4$?O%DY zT`}jQ^5OXXzAI9J7hOs)gI?D>oeP{r{Hl-a4ww35_P35le@F_1Qw3GeHes zUFV&;&A5r4fEhUHUg9L( zf&i|hX&RUJc2}Hr;n(rY89kn|*>4xGlMe;dUzQCw;>r4vZl!SOm*`n_LY{c*iO+VP z7+Yuz(IefOu|RGP<$7TT(<`2|;p(;u=x2ZQgsfqst*QkGbCV^-CQW`! zqGjnbVo^hFMQ@b82_j91ASi+kopWs>WqxyqjFow=r*3GWfndvt6pcJAC6 zyV)GOZA|0bagBe6oqukNV!Z3g)6xdq78E`gTSYaV;cqBKreRQ(k;y{Fgybz3-+8Y> z_`Uq~EB_qB0`+JL>L0a9g!ao5v>}0>T-;mXvp#y0lY+d%6de@rvKMPWo*-Mb`BJUrgE@0O@K!MBCFV%fs$qOo#1&K!pVO< z-OEX#G%M!930Lak$9+ag%Xw+bV7aSKJJ0ZuTaY=M>|`IFc{kb*aV0Hq^M-o-$sJxG z9P@^3qQOqub@4bkh>!rbw7VWfOQY(Cam>s zI=imB-D%5dPrXxio{L-C&O7Q$KgZ2;u|qBY=Z|Nhp}won=__rx6~D>R>1O}ZvFO8* zOUR@V)#Hw_ap8n-8R3Lpet*9=29%FMm7!h%&BsIl zVpg>B={FYFnL|~5!!vB+gZBUy>o^PpZQ+NSM>j=<&y&207+#_6>zA~JuG9fM2(K#- z@O=Qz;c|1~8PUjFcFY(s~JmkO9x1uJyBwPg|Zg8V4A%>p$%U2vrf+?U8t zydwHmtZ`Yk6}#isyPCEfh`93%I(pR+Y1mEP)TeT5Cb}B3%d)AoA?s7fA@nW!U%Mm2 z(+_$Wr)hHm5t+|;P&_AIgD>lMfmsMe@9WIVl80QAz|^0BzF0iuei(k%GblGWr{0!f z9ZKm~uTuV$u`X2DwkcXD&+cEzyZ9Z`?!0$73KEagh9+r}CnNu=o9w2Y{;Di#^L_!3 zzlC{YB{DB%CUhViH1lwPxoWwwNINHa%I%&rlT$_(ew!LwEX=75H8n2a<|f*+;z?9{ z7JcVtW@1Y68DwF2alUD}(Wm&4E3{wp6zy2~rhg*+l%>>*+9sJ&m^M!oFyH9sK7w}z zI`$54QSY^X?LgQ2Hj1C@xA0e&{~B+)P!IB7;z*aY+n4^4UwDecVL5gtjzn*IQJJAX z@{I#-jHTQkYMjvSONHdcpLal4BVAgX+>GQw=)OZ?oHR;h0ccnAo$aq1?c4^QSHEA4 zl+dNL{o+A~lP>^N3=0KpFd7paSc~aD>-;V+jvBUWY7BB`&+;AmFMn z6j1mLg>G<=-RC_%8M@S(kHe2W8rNKPK%M%$Cu4lwk-}L~)H4q}J31#KlUkLzqIi5w z68=P6CKcu+h-T)cG)QrnUtm(B70tyJyB#}uDo#$%s$2sx!?&$wW?df>8kDmz-B8}@ z0`Tq6dyZOVSP^{U&}7Wb&c^8Is0M+bR$O!QbN&V}oy5`Or{eg@ zspuOR_V_NYf1x@Q!g(T1 zza)p~Egs;MFV_Nqi!Bru6xq5cDwL4*4n!0n`FC$cUi_c>&yEnDLm-(&oPhr69Ud9D zqBbEm=r9=2F|l;Rb=SuBZR2u8$<6DnM}`~m$U_gru4Hd6@ei7k}8xD2et!x6fK0`pSHhNK&N7z{h=hTc=IhoDJIP&mB}h$FzhT?1LJz&f~n~vunDPrW&!M#GRZr5$8Y|4i#v2gN2-hJc(e|MSz^E}sjLFxtU%nSLHm8a!+%bOP=6Vx z^W?CZpEeXbx)Z^j2mD&EV!XxXPbQV2QSu0%%<#3(svp(1!+E?QD+@#mD|)XoE@%vZ z-pw}|v2$_+ntC#b0kU*{PBrD?o8sqP8Fy49uW$f4vsvErydHM@-3oNPU2X3|!4v5w zS=D8sAtz=vUedT=W_re_w4fyuTr3JPk3>HDMgL*x&jSNEEa$ROiAy0IAF>pl@+6Vy z%|^>%jhFb`50eyJxy^=ICUnIbsyF3Fp%}ukIOyDn#uPhwMlVeU(ZF_Sk$KMr1&zlU z3n?-tP6)$kkB0b#vQn=sVwjfVeV@FfZ3#_bIkULMhFfu)Pl(UVGs(A@=_+@$Nlv8s z`ew%NqK_${yyU`fE@F~i-K4;HlIxsDMjEku$3*PgvnzIOpYYgdY*aK<-r0EI%?FCp z;}PZEJSbw=R5}nqt;psIkBUFrhEjxR%!LKUMVh57C8;#Q~G+xiB5;bUx`CLWfDBo;D;MDr%to`Q_Hs8Q3%&T`fy17 zOIylb%8TsRNY3rgrsDPKQU0*Yx8(>HJwp?{z|n3vClGH!rpFt22*~)-3CUAKiNBB; z(?{dJFT6hn8#6JnSL6NdBQd}ynI`td_zhnl<5zz}Jn{J9c<)`m7`NSWd+gnRzH`ORP5RS@_*BiUys|EnC(&~>NKq8GH4i~JIg%9z!X@ltmVSIwkB#)E&{(@cB1 zdv2mUryI1-JZ1uaTj?=&(3p_$EZV1~8z||Cw z7>nB~f99p+AM=nhV*S;;Bt9s}JD*$?0+h${ADUsV!CL3W!VA!mIBu)pHAA|v@3=M3#MWQw~ycA~X!8y<^YW7}e^!DcBIe^syI zIeKDD7JoSj%)8Df6p#fgF*`qJSyWFnqDxHA%(z~v9t+KR=70w@fj>d`le(cESzw3% zGoSq6Dg7yrW(py7K#yZTr970*bKpXULT5%UsLgYOWsU`joAIEeF$8hlGM-xtr@K6z zfoiU_@B?oA{0Ps%U#0!>&*g>ySPNZ?-F?1IwE=W*xf55)gAPBMe+!zwi=FGhodqY9 zhV$Wv%%k~HX{5Z)cIG}xiTK)Q^gy9MnTVVcpZRtJWS(!=1ljbW_u@awXZb|h*vSj> zNNI7aOtx{gU)sNTkFf|>ATwt5xV7~4uoygSR+DL6)A?oLmp)uF3e?ML$CR{Af8@ca zw3R;PWK-+v1>^LC|Mt6*26hw6Ei=J+D7Fe&KbcSZGpOsnOJPl4IZ=<6St@sySsK}r zH44*)cFWwj51nyJpLGz8BRK8L311d*ms<7Hix^I&Ng!VJ>^y)Ar%%?<|p!(PI}Z`1*0;FFK;FZ9~qAp zq@F1k;0;@%lXWX1C4MMh^GSUv@3kFU9%7PaK_JUm@?NkTy4}06yp_FJFEVsmzy$yU zk|a(xatdmpqs{^MI^hBBc!wg18_EzJ683CBbRv0*xSQbJNW4{%z@);fJL#Jxlm>3D zNL3OI5jPYApvFZUq-nqU(Qy)IR+KYa>;PeiKi?6CxEahQ(-h{xe~CXk&wlYY=A**x- zQ1=qcMcgMKO#z6h((UUPbJs)$; zrTE%ok1L&4?Ag7`bWpWPXfAsfA{`Npo=FGa;m^(u6dDGbT!pRo?7H>U5R^^jq;XgJ zqm)=Nky659FDI5*09|CqTvN)F?D{7^QdX76`PmtVLvgXGUloqtbqsNpK{`gRmoQO; z9ssCZ2vtlb9jv5@CkQjKZ9J~M_GQhkpO zjm7@m`{Y-gQOXKf;ZXiDaR=e~+y%xag?#5$1>N;y;6oJT6TYZ}mmJt+yQpc@K>+Bu zi~Cy0w%uv_sl3u`O1pQ{%8meg#!34Ys!W(y;0j!UD{uui4(dTHcRg68Kat#(Fx7yi z6-(+nSEQHdpWdVAN${%Evq2HZLEh<`Fwr4-QB%tJi9YGV3-VM43IM({ ze}#VQAYh#lEP2eqw8}ugiVp04jG-@KNK?;X>EF_1K|pmPvmI|KuhSxf0uQ7r$i3a) z7IYYpFn*tXcGgbqgOw-j_Cq|S&y`7!4?0{Mi(7e@S70)c+A+B<);ErTa>G3rTsSp^ z7Qx_8=_qfUmV!3Cvp!Ml7E~%Oliah!I8z?x2>4E((yXRbDNk6-tZ`-egsxxd zG1L({oy;26x|S?8zM39b`4rk`80c5)DC^1k(_o$?!rhay@<&(}_(`LVTR6=@UEvQP zEa-2PGSMu(m^is^jD-$X9N?+ykHwT_k!@c3@ATZPH+fFZ%*B+D1z@Hc>S>Wd>7PSG z=%tBynkd_H2URYa<{yRe;uSJNW}Rfkorw=mws!L#pt9K@>>02^r7h5L-Fj$G%2Qt2 zo)TkHYfklYYHCXL!e>(Q%EblrNoOmsMIKc>jt&h(gE|qlTz+}P3q`LqGrx&OEFg`H zkH`4LHgCGb@BHk%H{5c%m|7MU^m7c(4{<_EJ3*rqPmVtcBi>UPe4Vq~DdP@KEhjIr zK+Rage4{{>to5`QQ3Iq&`i!->@rk;a(>Q^JUv6}g#G&Fn_Gt_bYdkulvTH2H0!eS? zxXLZ!92{gJx=e=2&+y2wHwo|DwmlB)-WmILY>Qnx#$#e^#N$^cZ5ZQr-*QD8BH!&X zuHy3;%d#NbTw-yT|0+l7#184(zuxD997IzX{c>W^)D)WARfzg59~6XmXpgG9j6?5u zHZ6rp%S}%q@?V;qI3=!32RrMID;<&S$ye#_H{~6ska#i3H#E@S+}x44_x?{r??5v~Ch|Mk zT(LO1_qy1A%PXR>`{sD;p?l)XANg3k`c>bn@%}D{Cx4Dd@smTy*QqxqpOt6PFy$rw z^}g6~t68cW09Y7umMKcz`T)>Igqm=llkd4&75n)PTvRQLR;1i?^!Uc6X2Cju5+MW*NF+Df~>WT z7pL^2x;ou|zH?hH_0sLf&$xHHDUZm_d@ncs6pNmb3F?DYcl8QX?4H-@M?aCg!cEU! z1eQ#~o{Po2>yvCl2Buz7^8>OtMm?v_km-6s7@3C5fDa4Qd^yi5yxXGM9clO`3YqYt z7XtNc0!jEg9pZAhBFBlBKe^db0QSi~HT8}PS!O-!-SqTy96fq8o;Z9s4hxSTKOWQS z_qYO@Q>Q+8%A#!6{xeUB2TNUJqI>b(d)_mr3a@3`U9?{o>-apx%=E11XQ3}N z#Se@1tya_YByLW6!YhmuycjPXBX7DYhJ~nyAZsdrI0&2M!#01h&IxZsTckIieKjT ziBW$iRx&mYJ@!cK+qc)>MtgrbeK9M=7+Ugv zWOO*b_Rs?{J~9|r?Uhof9${1ijVaOlp+^tTMduH?kY5p~ z`?)F`iJ~FxPUST%=$IMU37HJqw`ZR^B6S#)LCOUD!1}wt*09P-XQ5Gg#bcv#GRZySL2X&t=CC_H=g>y8>GVkhoh( zbG2NS0ONEcCEseeur!{Ex**O~X%zRZg$tv@xq$wC*%PH5+-i6#>f)(|RF17LAz#rK z)L*dp%hk_D^(Fe3I?X!hK54C+g>(T~t3F2m;+{g!IpA6!D`2m>Teo|5F=r<}??J)> z)iiWjE7aI(GMH=A-6*WeoAau&t6%Tv3z@f7{*+EFf1=7=?e639IlZo*ry3`dYEDO{ zpK;fFn{s!$?sjp7MrDwM{$rnVlaT{@-k%8-3A&LGy{y{Lg*m`ngK&pTbIB^RLZJm^ z&%b=u&*fI$DYMI#zWv_1KD>>eE_4L>Pmp1Nnnu3P_p8F40dhf?0eGjLJkS)>I6HR9 zCPh`_!wo)%KYX>W^mX)TPcjTpm!h@()GRr$^s^jO`Ex3YbG9`fr=+7#&CW`HUsU~b z9cfNT6L=k(B=k}==0#;Q^}k&7&0GN`uQJiyF;&un`Rw;XHgkFs^t9)-nC~bI z&o+s_z9U}jn9^yt3OoVAxPfw(df|lcq-ZrgJ7>C}@5)K;szdQiuktfE*b@`O{V^ii zQC(h~DuO>Jsd-j@T^@}~75C8ah{i$_F*-8l2_A0XVbdv-xYk$wa}{PeMNeq&@7v-c zC%;oR+q_3QwC7+EihMHWS}flvX7Qo$f{?3x4ls8*}XRx5qMU?^p19d4AM)X z+ZO)x-hCVo`onH{Q|hi`FJWb;{L2nUI=JBv{?xOeM$LcMq&&KPs-MJ5vPb6GmB}CV z&R9nE;c zOP*xn7qCo1Pm%+CyU;ul#~%Nr>UA=9UA@<1?`4fw$M)S6+irSQ3~aw99{&7C;hSZjZs?ai{HxI$0oHrU{f(h?^I(Kx4+mS%*yGX*?>vbwItxZ3V@Oj1mripx$$8 zj&*V5DTxMq)VJ7A521WwPf#L&Nr|K zj5)v+&azvMs2tw>-N?^WF+V|KEaZ|Tnh{8yH#5Ek)S;Mp-T z5j)1jN8&R!Ox2UUwXdVjFvHkf-sA~pcjXSSs3Qq!P!qCcj(99L-QbfR{8_$v}7j#N>Rxd`NJ+pq3P5q zR(Vc0dy&VKV=5b_-r2qMD@lCxG{&_ZM6YmPBurhSq9Y+fV$q*tlOdTT6wzds4e8x= zMw!$;+#gD|!T-3^FOp~a2cIxi8m;*S>Gs?lq;bU5j7)A+<@?>N!$4yeYLkxK1VVo~ zBz<8JH|YSp8yw_Tp&`iy^|#9JnEIn}^+nsp$71)6ZE?-P{c*#=1Kv!zcjwO7w`Xtc z-nBb+?ARH*ckh*Mt+3EWEyvs}1zvzHeX@@KER{8I8I-Fd2O+4ap>`SU!;&MLI zM}`q^I6YkCY<_Fo3$J#kxh|d!h)uriEz`M}(6evfzRb}kAS*Co`}Xbewik@JfdR?< z*gM1o=-}vN32P;Y=kkt9M%W-IK79YlxaaVEJU-P_W7>4qE*hZJ?cX*W&%0_YzW#>o zDGVeaD4_+g1mVge%qT%2=37)J35uO#j?=cndyXu{*QQotss*Dv+DjTJ`;HNHAkAa3 zZ)`Dk?A{j--2b@hdpI8b+QYGT&$f8c3!f8T_}s_irC;}Tv3vW@m>8dktFOOaisOQK zq(A=bvk%56zWi7`c5Kp}$`zn3^~TkEw#PTzdN98GCAXyFCVsQ9>S~)*0E2e-hqOg? z9(4FQ5X}i01af0&P)h%a_~3{BJm#01svkKcc*WD%LQ`ycf`T;o(K+@o=t!m2Veo~3 zwkaM~zUUB}>H(NAs}r9LV6r2XA0d9)`L7AC1)|J4~gk2l!S(C-zGaL_+cpCD9Q!3zu}+&j1_asxDZy z2uc6A=@_07aG_MO%v!^wTw%DCU?sEIf%9z_7YfT7uxy2_`}gm9m+~*^sR2&RH)Ev* za#c}&--%6X6c859>8R7eF)H5oee~n;=`Vaa4jn$?{_0W!7FMByuVmBUnEsCbYO$5K z#xOZ$5S{4{={I>#x!u39SfD;nFVo*82K1{}@826QyW_d>J>T>V?ss7+_$oJgWx2Zf ztnyMdf9HK4j=%WyJ@N3NC#1(+TJ`^A0wQ|@ovE=c$C%>2_3GVm+l>d}rt7a${1egW7e8y9Ld{Z@VrTi4n=lvS)?%;x zNteT;c|;BnmZdciuv=WLx z=bNoKHaQg!9XcG-b8~L<)AI`&hs?y$sd-aiq`xP&jSa^Bog*@be5(_aO^?p?#*u~I zm=T+=Q^cn=^os_gz00w?p|Yq$o0@BiUrxo;?3}BDNkbMPMjFF0%A^ttyT~k01JuZ}b8yeSG0Qv1C>*ZNVdZFJL5(`mJ97+Iv3~ z@BhSS=$*xxfp{=AvVfH*&Y^k>4Em%GD--tdo3}f4=X_ zN#AA3J|>w-2OzBHwD>97Md?iB3m)*oH@XsIQQtzwSeINdKE{1PGL|uLPBbI`F?*PJ zmV1xFe8XG+`IgAJ7d-b_m*#KF?<@|xPJC)6gQvLlgHag<(bU*aS;rQwUkH+C+ zCp@;llmMA^aMyUe?73IP8(w{TY~Qgf#>Tga4f-MvD?tBT#N|+hI^md|nu=3gi#$CY z3(aQy;ivD7Pu%xJJbr5SlA5br576Uw4fn^byGP^Y*X$Hu=Nv6_xqK(l&4G4hzAL;( zk-Lih{`(HaXC6Bqhoom*>h#!BK(1)aG``S`mrJjD_Oot@ap`X(;z8OOdIy^)I3+!& z@ztz!y?L4Q(gkPcW~6_BY}jjhfoNoG%>B^eqetV!e4dU^^I0rP#`UV7XTFdH zL1bmk>zwkzhA<8QF?YuzA>Zov%^ZD==o=c2-a$47H8l2V#By&VaywXV1X%@&v&#D_ zbAI9{e|k$~-N!%s`SPR`&cKc}ZvU6P{j30Nsvs) z@K_8FjY*DiFt9~Kl?-aeU;{rrF)SG~dHjSoCQNLfh{@?m>1%^AG&-v1oiQ*xD!Dck zLn9MP2Az%#R_g1NZmw5KPAOmhezp31HuO;z@<;l}yR=J|sXVIy9j}XLu$qf3M}U+q z-SCx9{poqhx^CFBXHT(h4*JH%#(uik&kHzWe&+$cW0Hl=yr&RNd%9a`@E?^lC<69a zVPwEW=W=wq6?c8|iMadFOiVQqOb&L*0QsGoUx@pT%*0oon28&9kHqlcnh8J*uQNkrY5Ij$BupRwXZ!UrIHf-(M7ftPK*Bn^Lw5k>Axki?mOP_dO90MJU;E~6Tb_5J|GvUeA>WK*ZAS( z)p%5j_|N{zZ^S1*`vocD(_MYZr30p)`WLR9VtN-{mi~%?U~Y)&_yg&WvhUM?kwJp` z*g~jF60C1bO~>cI`at~E7w?VRo^_+Y&zX?rGL0yEFWo`x4(ytUt9EaXojZ2; z1{yv?BW_o{l37Pxprhx3IdD&Vw(<0A8LJmnZ(1db*5d`aRXJH`_e!( zm;2)LQ~hzc)f=s%XJ2Z7jAOIr?6St`qWknLw?NIBEGp;+iLfWn+AZ>=6Sqf!mP}n2JE*7#Fipi(e8=e=Kw%`_g2i3pL2% zFauuFm5^3=xhssXbH=~YhYi@&mKr&1oI$ec9mtq*eX;ShBAGwTj zBbQ7@{^IYwZ%gFdKFM~M+hsRV)l&p&iDKJ}Hy3RPPdtGNM^y0(m!jN^2nzgMdG(Mc6h{u%qQ=t~4CD=}9CeP^1$d;jDE zTO#Xz>}@|@o`Ch4vPQku^w?JAeB^77#M}O-ACKSr-QSC&M~;~Omm1JUk4XplNA_BCvC8{ALi&GUDb=3H?Zzzo=nWoHL^yAOyNCx7AMvldY9{m zxN(DoZy4$mA8TyOW-S(%kx`s-=kuU^%X-(Iy)in$qOZojv$NLO&~x&}1HPBe?G>$T z3yK$Aj`~f#QZh|(u?dhcsiTz!Q*kX6w`^wXd5Ac6=>7|qb$mwWd;m@P!l6{6cYNEP z6%0Tmqn}a%#vgt-rALRw`(MBNXdIeq+1I5GhonIL)~6r0oys&~SK;e(1$JWn*?qHd ze6B;Y%MoT4dgIfN%v%9LDDW)-PJ=%9(8Dn{u`TA*0N{)5+a}`V$>Z@0fB5Nm_{gae z`U;#09(dwJ{GY$~iSk5K6qC7;m9|%eYjLm}CXY-Ma;*?F1xay0X9?4E2n)o4$l<+d0Ie`)!C1rv*k5MoKEz&d;J^K) zUyJ*{_Lyu};B3HcKnn|;+D)DUDlg&YD=Iah_QaZg46rNlI~x)3onbt2r!Wj~3Ck{K z{4CIZ;bEnbS25<8je)mMc^J8RFi*85<}lIvTS=2Z9`7+xf<@hLQ!nx2hQQ`5d3hpXiW|3Kur5%td~ACRo*8SSA0b{i#<%vz!xJ8u5RWukoZFWsByuSB(qJB~eqY${L1?i>fNV30PNv@(&>La8P2~+c^PQjh!UJ*a#AJ!_(ueyW zJ0AbrFa4>?NuNlKcJ+mQ1$~t#-`#D*|M>?Wi-#`bxv9seoAH}pdct*{JX!d{i@m99 z8hR~9CGQyr)_&VmKH8Ve^Jh{`K?^OhI< zvkAenO2C2$3!J>;B;w4>Ow2Xs-B&LNIi1^-uE%E@STNz+{G853cFn3!pP8BV$-M3p z+EqVvy}Q0U@&MEe#9}TmE5E*K-?EPreO&XKIwr`8W8{VY6(pT5JCD`iUwI&|Cj;{O z<B#uxATqV1OheC6TC;(z_c-!!kaH&hAuuO7+I==&_@vq9-U{o3!x z1CL!EDiSdbXBJcr329wr@kWbDKx+I&j*(AM~&q{-5vdNeb*`1!xhWhWqcIgUv)Qb{XD%Xfcj*KiD$>rkX2pY^g6Ee)Owqd|aQ% zBuXO|o9cvC8X-24LNgj4_`+lH(BaNe_$zRBc<_mn@dux}H++e>+7>c075B13&)@b? zLt|!^_Qxdt65kz0Nt~6^mfvOBv2&LPtoA0Q(Gwb&3d4kxm%5Cyr46b-O}#U!3p)8>1adTb2z#fY&thJ|blWPyXp!=By&`C;LO#S+O+cpKf0 z2_(D23+%#XAf1@Yq-@GVDlq0z`Mf|QJ(7(h@XZ>mg455%f0ZlAXX(b(_5p4YFsX{J ziQdfhijz}Q!6M0^>VY}TW^2*7D18^dL;d|RI>f?npRYoFWUlYBS@^B6Bzi0k4w>|P zn{aq&C`L!PikuCe)Cm*53o)s&!Gh}gat9WGf8&ootbUL2OtPw*0SqDwZGtwyRnPdn z0vm^~e(g~F=AVDe^2R60id^wYTfp)~@=njRQx;A8do|vq%_24!7vhb7st=!(LpPDD zPXVinkRO&E>Z5S*X-4@YHWn&!QW5!?V&Q1*(~6`#}(k?*SHv^Aw2W9}~s& zg_5bvd9ASdMemfd!y`+%y4BwcmYgPx$G}n+h^Lm>B9FolccsA=KwD2!8P4^y|87&+ zdGzt)acXMDZkH2$^=n7sf4ujTYRlrQo&m}Cp%~&ji#`3ZytonzE%jSso8S72&&K_a zA1k3QUtj_FBM%=Jn`Hf;2|o1D;VTQjn}kDClcL+hYTD==QoLlM*m=Rt3&8muX*QI3 z@wY7easx^Kp!6`cLu3P+(pUhdj%MfbTcTXw%UpbOVKL@3ZsSG{p9~(#12?4Coagoz zzT?a(x74AKpDcRi#t>wq5Ph;>%2Q;a{1%ziUObdLeiyy?n+w1xTNMsjE1B!h2N7O~ za8rnsDLmWc5Bt`G^L)l%d9S3~b|G20>zD4jtQLMNeD&eS;@AK5BUyK)#5q?>zuT$X z-~I3>>%ML#O z*t9wo7RuP!B~nx2^z#y~bnXlU?md2aEqb2|76!ISDVZ}5FmW(HH!tO8C>}p_IGR#c zxDxzJk53oh7Y2XpZ~aZ6MR{K*kz%qKo15EmC)vbSWH;W zyFf(0ZMRumNX>qW!t9QNPDG|BMpSlB_!)KC&cY zg012f(Y+gpaV=iTkdxe^wv=d%8e$qvQ0oX;La6P83d#U}J=4o^UGg_g!FxO-rp zdR?6$DlD%2!Q<4u9+XG@8QUIKL4Dgn>zNzC_5A8ziDzp7xQ+_`FIs3g(cqYj`-~)ekkHiKt4Vi~LV@$~+u;h-~ zC$g-{7TRhZ^AP|U=uIh#ht17)r!rJ8ND10)$`T|V@{+{}S@n;(h^3VUjfYD(-jNKZ z#+pm|DYWCMi@cn4gZG&nbQmE&Zd>RT%0V)e4eq(X>nj6sSH6jLna>vW_1oRweIJyZ zA%F5qIyqk^e`K{P8CwDFTR@UZ`mIGT0CXeuV6!IU4HPsPkuQDdIw^#Z_o?B zBaKl%FD_CuR(HCr(=I~Q~F&1mW!-wU2?HDjjP zlw9ExzJoD5JQ9P73;8lHe_Va)1z?1X3nr3@HYNEa=Rn_ZQ2;sM8)489m1n@W z&#>^!0x+`C3%^o26$hJzIsB1k%HB2)@hhg|k^RX4#P)ia+H0m+?THcZeeWOJ{c?o& zfAaGxWhpnbpf2g7N}Xc=@Mpi|_s<0QqmO>hJYNAe^xU`G0z4Y=r=Pf|yuC1ZrpdY? zjUmni$S~xdWgtkK)ITsis5KV(kc;vi*-`z}XZ^E0Wb-cH9X3CgxLN$Y@unMN-@d(Z z!wuKRD_;H$@yb`cBEIuGUK8K+irWF@tFXRmO&Zq$(F?cLyRYQCxv5@JxVblB~M|PYtA^os$5|4Cpnm_xGn#fS32!Q=Vs-j(O;NMKs@}I{A>X{ zvt%2@Tggc^)0ahxm1syW^MsrDiW9#)=k->-Wn&*3Gtkut%T-tXJ{7_SQ?3DASXj(c zA@aurAKz%b$?2H# z<(w#e)bYz+O@}YK=~h4v&w6}S;?b!o-x}j@+Nx|!XwEbjVtx^wT7G+1Vz7TDMh7_o z%qfZ9m|ipyE<5NQ7>Lo~VSnR$fXNThg~cebl5YcIA?b3y?s+Xdz)2Vu&kW+h5HIS7 zllfFMdEk+)IW6-{)9D^~?6B#GysOuWdfij<$Y?=>Op-hD5#hCh$zrQa#1D(Wym5u( zqJ!m};%t9IlUn0cE_KJdo&`nEmBws@mK&$qnc$OONy=DUX~hbH0Ga4?k-_=xH^$SL zWSou0r0%^qGFjmDH!oF){@ww{hy27u{yL-uPoMk}Hw!y@lpCjmd(`$MT=bl2ZUxkF z^Vu;cO?~SFDB9aDlW+W9u5kaOhgGlYSNjHIu&<$7k-Vc0CHI#WSlm+Ee*E&(Y1f0p zGfm6;s^7|zMnV2RKHd3V;f266P1Zd&IjLsO0U#FK*mPI)FJWE$MTf&2;^eOoosZi$ zs0J2Tk!cO-fXE{1qB-A+nYp=`nx2WN**WPft(a{sc;gGFiAP39V{B~PpAVUvn~xJG zPWr?!dZBNZQUArJ7W7G9`3zd8tNK>>l8(8d zM!6-PiUkzKlLM;~+aRhBxc95~%6@sm1CKu8x}x6D(=Fr61_Y2c|Ines#rNe8UzN^= zDnL8(xCek0l3UH2_lag(0nap92XCDTYX4HllKeW*Wp`c3u$)N*YTqOmd+~-AZm5$x za*mV0Tz9``&z`vHrW@myTW;1^W+WCDTCvcYkCEXe^icj}G66U|JY;WH z0BF|=S=%bmj=TIwRjt_rYw9fr*u`Ej{VOI5_l#o|$kFfG0<)lfD=&4Tk)QJ=Q_plN zskG!^HN&N;e-3*|!?`B*Piyb1d3Q6iuEXbRgi4VlJnB>%@#F z1wBzXU|Mr}gOeaW{iaG_akx$-!jN7ZE>}a($!`mtkG6`=B;Cp1aAOfuiRJ=xqAIww z@0Iq%5PY7xA%1$JkDMy1s%sL4Yj9};^5XpPp82=)MdCznU4^*mZ>s=`bEVhh)O5_v zx1yKtI;otDQ|9JHx4FDl8|c$mr7K(M61G6r zslLa?Mm_mFfSxTUf6s5Rsd`?Ffvo;b!s)tIZA0tp2OE)h=N@+f>(Opg<18lK#VeHA z3yErgxfua@n0?{JkbA4@dOclgL$dE&b0??QPltA=husWa0n<$kmRCN@fpMOHk|$Lr z$({D5e>r(A`rBD;)dGir*cD0=%kj$9?noOxlzTlsNjMj6&dQgk)#;hjITJ81=2O3A{>mqRW!5<@(BGVveo?P~9%>8; z`R?>U^s64wy?8e)cNT$>A>5=m>ua5xG0jO}u6`B*4Z;tPNY@*5KQ=u*6SMMv?5ph(6i z56HW+Df8U&)A`}g<))012cpYn;6i2HY45@Hfj4r+^wA6o?_(ex6b|o2)yB&R1X~v^lfP zT&ve@j;;W_Wc{oFJXbAsF5iwt7|`~Bs;dC@BcOe{jS6r}y-6S^^q2Wo(_>2^#0l&P>NFYfgHv&n(7XKA5CXmYu1}YG!m6DJGv|W=38vSgm z6(;DmUocq6{6xHTM|mzV@v@&dr=Y>lT0#1b7u`^75jVc*{G=@1TMjIi+q>#Jr+_zK z`83jh^s@2tv_ZJx_3Je13MpJR6z7`{#%>vtAN_Z6`|WomzUr;B4-yz!0e(=r9<>*L1qye^1G z-?|R13Ht`JP}92o-^FibavKJkS{07Q`g3n4gzlcW2g^xdp8#&jY>69}qruKXwP){0 zM0gbzt#Mbt#z2s|^x#>@z_$G?vtm0~O1|=t&@BiP(=A`F_r8N3sJ7b_dBwde{ACR0 zwSRnPOqAz@@p$P!KDR=6x~zM1yz)7fC&%N~S8TF(f06*D#cg5}aN`@*md_;Xtw^5U zKdcK|BuY)c?MJyuK>YNh>rF-|9`oJ<@mun1Ikn@?cw*MWs#w*WP)Me3K-rC)yQ64r48!h9F`_J5V zF9uNEu5vMBHBAGXPbHj9wrxPiYlGskzm#p3gX_sQ^(ANSo0Q&p6Er_vM!i9S1u4^s-``Hq~eQiiLR+Zas38T&I-) zbY|n^R)HsKPUF)X;tl7VbdjI66NOtO>ly22BK+ zl6H?d_1+7WWpT=NB|jyo-xHo$DS-b-z#Ok;7|T5QV2;W@<<2I!nioZzdxE0{E6uHgv^Pe2N z$g7v6>1XFfeSq!UCNWTA*$T-1`m{cjxvFz6fUYC!-hM}?{oioM=J~EbqaRr}5G(3e zmlxDm&b6Y2{MYkl7lS+>d74gl4v?<#kIpFTH`kW8Le}LXZ=#qW9ZUPT7;tu3e>NR( z9XQ*(-s2ySe`}hhEQ2po53jo2RDA4bYFP2(Mi#Qx0Oa&FyVB*_dKM=0Z<2vt{FRP| zyy2Vs+`us?-W(as#a?u_{+_-V_7&yBmKmJ><(3x~e~+Jy{T=a#)mDT#R0sy^??4@M4jpK#Hfz+9w6fugSB>?)8y(@?g|I5x|=mDgTzi1;{$& z!5ZG$igk$!$#Z2r!u67}9=_ZR&@Q)jU1Bq`?#*#@xEm@5wao|BWi^y2EZ9a{ORI3QL=mQOA`PQXUk! z06$93_$E^MK`z!c21g^nUW2C$MJ^30e2>>M;O$*IcSgTA^X3LNTpyAO72TyKv%kUJ+Hi2F~-yy06nz2gCZ26Q8olm<{~(pdoB40IN0+!&qz ze-|HH``L|dAy~^V1?5}MFnCV?Mag*zfC+RW!Q0~v2w&=t8f*=;stSR)BYW%Ov2fHB^H*r zRxk%hHkr62J-;uCl>F5;?|gveohLZi<;bo^CLbjvDAuJ7$&Z7Yv(~b#2|J_UGfVr)&K9mRH%S3z(V(mXv7AA zez*NiL0zP2%W2^{`dGIdtUBx2^wP7ByS5fQrV=ewcs+m^@F@KreErnJ+4b5D%07)b zfAp<|!gswj{&ZDzXCI^HLeo@y@xwU0BR=D>XC5b?3AoLGc2^{bn3E++gMDA6+MB_}$66#6SR%D1qy?S2aKW90Fi~e8DMafgX??ylG`o*pYa{P=P z8H7ykm778=P{_x(u%zDQj$<%86N}Im-vw<$sMke&PA5Y@2c`&AaswV zZLiNZMbGk_i@@nlzLEEQcYdqj9q%cV+TC)X_TB4jwmO%r%LS1s$vR}fS?0RV0oHf9 z8N&;|bJ3igiTT;tXsM5-UN!?&{&vqt{@ahPy*9ctHt&pY&nBxk+LpHtD*y36c_sCM z;{24uS!MlMb-)gsYhLf|Z><}>-x0snomP9U27ex0<+4vLzc`9SpwMahJLj}sPTL7Dtb#2|J_UGFVcIkavvo6trY{%Z@QRTnv z)a}OMNm`e9ie(+`#`EIl7uW`U4u0nC#SwOAlXV-N%RJ}2-Wg?P<+YE;Zz0^OtUHg5 zq^4_Eo60_=LsR%I`;?BG^=yT!Z82p_LH#O^R=owk&6e~m=_*6R9AfK@kC(nPD-TcE`s?xZ;`?6zz47KZ z{Ybpx8(tRI96abTIh$vYrQFcKch@_4O)D``I-c{*(+3#uUocdKfJ&(=^R z07V5BR=U{TZnmBmbawn`!1mg+oJdpoUtR>n>dE;E?}*oJ@$#%Y|>sm*hINoX!B|gc2SN1{HN*39w8<%A=0@%iz`B!3kycB737M% z1;x(*xAHvyv6BWS?Eye3?My7P(=j(mRIrfGY#H!xlmmhvyA_t==KQBuC)$bWGJzZR zvl{PwQ5{=#X4nANbptjj^_RDA3=USB3{ZiqY1vu$rZbjw}Is&3i7255hEqI6wZ z{f^hSm7tBnh03}o6E-jFHX-ZVle9-pQwra5(90to9=hvMNkl=HLU~46*9D!^BDsis z1)gqzte1?I63q3p$bH<9u0681`xNZ_x=s7t0yuA3SM|ZEIMQapGDu}G^V-iOUtho} z5ku)*=&x%3Bob^6&by3Vu;b30oG)fJjP$LeRy9 zUt1>%*V%{#RQa*0uiiRY*Q+}4!j$+C+OV;J`e(^(aiLj!Z4$aCkffKLZQS(s*VYNZ z_4U$ojk`_T#wQ93(r` zzWq-Ad;Ps&l2Lq;kNoma;m~_9`Jv}f$J8$#T<0wGGC?R)a-v^}_A(;2`-1W*|FTPD z+As3EF7^_SQL@>$1}IA8HQ8alD9dI;WyUA|w+1>gJ?EwBSUShi`HuX6_NyO$S%hjd z*zB?uP{*O_SN}_QpRGQ;&Q-12Y}Ezp%DOU1Eq;65Z&|tZ8@NGZQT=LbemvC`N_D zvN!tlPP*No!VC>GjGP8mw`|}xf|HYzF+DvSQ`6J_&M#?=jEu(U=%`N|pE!9kPM$jD z#b4@IlFmA#7k$|T;Y}!#K+Gvxw&i>t&xklLS}T3@zP6mw`#Pt%LL9Uk^h;!L(KDY) zfJ-6udI$@z=k9sLErIiwbyXjXlaF@7ZPB^}kn-KO>;qKr&b;dRm4EBjCC)?E`PPK< zn>z=*KI1MNUI)vIEr2bTb>}gcX*g|O?<_L2ZiH_0-(B&j7xY(esNWnEUK4-0jTJV7 z_snyJ?^5655gyHV)ofQx4J$Wv6zUHgl%6s;lpEDXMuubO&Ykwl1}@UxzkhGsa`R2G zZ|@$Dm(kTY%{!nx_!CR=+m9(x%IyWM`8kQNh1fPR7B9H{w)nyCe`CD)&2Nf3?s$R6 zL2L>`MzisAUSo0Vj?QAqp!1C)SIW_a7Za4Dt%2@caa0^crXm649Mb0C5EXJsbS zS0-#wse9l^*=2KqP!;b2zGC$}l**ms!*TOcSi-7%?|MFkNfBw%uS6t2mx+YQY|BcNLrrFhx61i^JLRWUSw}*cGT}*+b({$F z$+oovmJPz$WL+By->Hwi;8VX>;K>2Wc`vk-NljzXU$9%rWx9YqM*V<)n11gVE*Lf~ z>*@foT$i+JA?5AazfOMX!{X^GU(Ro%3q_=iwI4Ic#9ALW3L7gUgW-A#PVJJDfvYyc zuuGa<)vFhZ>gkjA$r%s0*Y*!3?DCa&hfA1DWRQ@YgKjZx)~+6KC)d*GMt($ATM^fBxQ^^cnncmEQtaIxjAH5bE8{ zoaWWA!UJn~RD(_ydslko-mmbDp%`d1eB!rXCW{TUTNWbv<(Igbc{`}8xwLhzzVeQd4TvA2w~R=O&6FAFqvu8z9osUdnBL&1cUuKhvok*R%MuPWWPCVk4AC!+gsiRHqeUg^GS6SCofII_+rkhWg5USGY1vd-fK z)d6+u%>g~4{ZcEIed3(m?wf%2DXa0ky+HXt_r|&^2QL&ln;#9Ouh{g)KG7i=TR`v|EbLjLE4i~!$}79NM`kd zJd5uPOrqJO0z`9KYau`}|5-7kKvcB^N`yNsDFXIy_J7VA9n$SHTr znZ)HK;=)vWSXz)><6f=@CLY}6-y0wd5N_s3h_{q+u9o)AHAe-l&l!obwOqW@2c)(84tBfam%w2I3u~8;eFC6N|ymdCw*SV@S zi)&|-b#Hm+x8{Nf{8l$_o#!?8t>#=b=VzliC!C*C{bk+dC$c(ooEw4mDXaGQdjsD~ ztQ%=B7`8~(6@UXPPnd7P+9uBvF1oA(&NQ!wyXaM~L%sjc3cq#BIoIjNuU=gXk~(hM zYHmUrCYW@ti>m(Ihh$;mfIs;$Iy4+(jS=Y}jToX`_DM(VXzx@{aT^14Ku#s!>*4anLxP&bpgE4B?9WIMW0K6zTm zx(l7xy8y`bt~yWO;jbzRc=G0hHt(hBIedk2IE_6mpSpMxS;HgzOH^!T=DKGbc}CWa zjgR>~@{`Sf=wvMNvUyhm&6`tJgw^yx2gcuiw-_TDCy$K`dn3!t)T9@MZ@m7x_}=e* zUHs4w|4h(Z{wwv6k&m;}fG#7cLgkkdR0d6&!ph%Mz=;qhZS$TB|O(f$p995 z>vQ*@dOfK8@5#nK?&GgYN9Vm|g#U_J+&b@MDqJ0ixPz(o;)nMrrk5j}zGJYn%dm6W zZ7r;kb#*6L9n92IV&{2EWGjK4Z=LI51RK~8apnosO~Mw*I%^hGH*&Hvd$e#KQi@)exv^Df77KYUb-6o|9nGex_xJs4N zx&woa7#tdofyR&q(kuw~`Wk3H)q!ruWTO|Cl@?c8<$${`5R^@N9>6nc29#xfWsCgC zx!C3I7v>82DX6@yGB=9I5+)D35O>nwDmXbk9rFu|qGM+PJ9XaWSP(9fXO(G0gZqYP z1AU+wx!^SRR>J8wRGno4vB28X!dofp5OeSo-@{^z!FYe6)$(LWej{r$kegV#ud-vZ z^X!Wfn~;NNg-pBZb?s~QH%SxvJEVQP&x1e3i*<~3A#l;;UWK;a%W3QJ)4!{~?idx> z$07(iW73vQN~hg0u>qjnt-x&jN#-Db>;|ocv_T_we)eaZekl($0_@a<{ZU`C>d}iL zOZZKh)vF*5OSLJC$Hta9Yy-i+!jZ2s@#fE_C;r)>KR)BISH%sQg++3FG&+QpZ1jViS!5D zZZNFAV{2iZ(~=vQt6DAV$_)pCx@b~Ajd4CF;+mZJ1?T2sp*ipRqjE6$R^aB~9r3!- z77}Pr=V%jWImEI#*cw^a2Jwjb7_;yTJbfW>v1Q#^=k++5SZJ5BtbTL8dlM$SSigII z=Dzt%khDzQ$_pQ~LAASVf9PAC&3In?mCnX3FvHT{#)gOe4d7uGfCn1>25^JTeR|L7 zU*e_>Gyi<@E|^vdm*j>DIe99MA3x@etBj>Ro+Y?sm*=(=ry@0S0+!3d&FRi?86 zAW$}2`x<1uhkRCHSFXc4oA57_@xb})#62^to@Cq%Tzg<|4D>9;K(BbA?4TVV8;@(Q zxh{rAMvJeF!%JTBV(+4XN5B1SNY||JgsYC=ws80-fn4nNs$K?EvS;jx?0JDQ8T!#lmw zn#I=$;}m}Dix`95;!)ZN#^oJ-dEsq)?0KKc9s$}&;c#&mv~0lB&`emHkIx31)t zvHXf`r!VL!a8+fVgxWTA-m;Kl(erbO*Zp|i*Jk6ha5&dgNc5JPzV;eWT!8fIsmf3Kypn8}WFScTE z5UOngG@c@#-q?pMDp&uVZBgPK?>YSh{#HQMV>S)cxp=Vlf#ylKF%}JrpH0BiLGGOn zcg2T%tz^;j&N@adn-jX~CvV`{{CtVWZL~q@M=5`h6{4%!WNt{2<|Mg@yJZZr1o~qU zRarhgToB*Nq)6V4|S>(D_ic4t+d*sfQ z!3v<~1z&I4OTLvxHHk;f$oXRtSVoqC+$+DhBje#Gz`3c4-WCD!%`sEfik9#B4y4b4 z){M_{b9SF6J%>3_vn5c!2|d2%JLa8l>93uuI-{&>FNmBD=W`;CjZh1%rp!d@g++e& zfalG?Ti*HGmg9VL5m}ex@3Xaua&w4md1J%Y!FkI%f%&4?0iI!)&Cg#xjbz;>=JneB za@Xd}TBk36>kZ|*n44d$x2%&sg`D%ea5aTFZ-u?K!94kE9b~W(BSXV6(kP3+Y|K#m zN)f>WEC5$s5jXdZdT*5f>=#qkT4zJ>6}jsG1vbx3X9wb|X=Go0 zI%fK3!mWVK%Q}zM%Atqu4OCmXE|HM(9<%m+9Zbq?44zKw5>@xuJow}<^ney^tm7T# zYc>Z@7g@K_dA-x1j(yuF)9WV8&2Mz63%`s>k#p_7qck)4t8BPX4^p5lkC%&8Fx0>_)|-AzxCFe<2B#*ZE^eaZ}(|pia=g+vA3e)5DU2sjxF(G z!sa=89bk76C8J`PY@oAfpBQunrCTmML6{N{z~Q{0?tV#p_uKD^AN?=&dl}{G0kEEA zJHz*97=+e|!u;@h-AUNl#cC|Vc+(1HofMH-JNhjDc~<=PI=KYaD@WEe#`XkMclpof zDmr%b63=gY!T=#smF^3fn7r}Yt7An<1rh>y|+nLP6@KMAyoD0WCE3nt7OPVJWo#3c=O7ljM5b7BOyMcO)P zSeQwiNEW0#NSR={U|#RWJl*1s03oSo@4!}CZW|T}{8L`}$=yy4u75)E1$eQ+mhxK2 z0NYBbOt9V2T&mFBp5eXde8;>_M1yrQx_w2_8aQ3n)k(q}0IlWE^WG)ARnRTR>tyWoq{($1_0t8vm|%xAOXW54xmtP-0BG@m%bifhSM4 zZ5-+(Y5it$TNhKm^WM5(Rj{6>@np?wU$<)ad3&?cW(V8?78UA-3OJ1gH%`+^W%8hv zt59dAW<6QQ!Yz7T4+|q~q?0EWc>6pE?(;-ltGO5p^2DvBc{>Z6_ZDNRwG@kbx7b>w z(MlgmYV6euxh>t{>`Ih->yn{LmZkh*#XPtN7VCtdd1# z0&wlET-|=!Nv@-IP%oi+vDAB*>~p2*K>gTo4tX@r&1+bIFZ5dk&z`bt-qH|!sbN#%grX( z7&CTHv>~^0vJpRyq12NbvFoSy(6Xy4mwk2qqQ;c+A#@K;+a`Y1wI>*bc9Rofy&=Wp z<+?G4u=mlQ=TZTLa$6q4YQ% z2tp!X=Pu+rL%w&{r!o!5KF}jm`5S8t#LkJa*gm%TjrkQ;wR!Pa=R4-z`d%I5t@*xc z8%~#Xr+wDKxPiroGr+=fE9REwV?J6jztW5a$vRNIWUQpv-vsPlCC95ix4KPq&ntDx z-+g1vM!~1M+H+G|BkRn9Y)nu?flaN4h%ZK*UwdROY~ zOyiKV0d0?K;36j-q->TN}m(j-jF}N;~T%jBQZ8M7NaA>-jp`1b~-jR z6cbzvtuSNqH_<;F<0IqJAtR2RI1z`B9PvUgf{YV!j3i z$(N<*Tb8LdrIajJK?JbPErPxk$v8GWBA3bJI;j6=K>nW}Y>BLEe-n4SEE;d|x`ZJ6 zN_v^vZ(?Q-m*ytmBCboUueWUeV8PN#ziNG8U0mim^-aRlL)L9#Uhgz08y6JL^Tp*; zGUszs7;S#JHRpEUV4SHYIVgpLPwXI07?(2UqWLqfWSqI8vDh+v*wcvCA~!8H#Fs;= z52VJ57jp;r4A1ZofrPm^X0h2)n_rF_uDvey?%op(xeX6BJm%$QCl-KxXif5rjVu1f zISIr6D19=~IqSF9xpBd*0$oq(Vy-Nfvxo>-MeD6;cw+#T_uIXbpfJ`sE$t`zPapHBe%F|u($nj3O z67P%OyuB=TD8AM25?7c1OmI3~*19nOy8aD+6?fnLSMd`s9hJM%KA-QzNdOEFjjJ*C zixz6EY6YA^7#nNEp1s~$vMKQ34yIZIZ++|A;vfB^pDa%uSl@paU$tMIf!9F!`RU(* z79WUr{*B_j0CY-!r{~GguBZC`uK3Yk_{%uCJQ^?ghlRGs{xW`Mlh+5LL@qC>-7TpT zlLBY<(%=#0J=J%i96Q%HOGq*3ErJlf%qy;F)6l3l7G%=C7Z!VBeqp6xvA33tO;31bh1+h;+zPlBJ_j6&H5Bxuz-q!eo4DH*{pPkN+4W(Uu_l+UIz zv8X!ZYRP4F3@EdF56KJCO2iW{Dgy$IZW^VUtGTcq1M8f&Wg`8o^5z0g=dS}*iO)g1;y$l$Vm>u+CRw*Nz#vz&Xb*_r z5wEKQlYd+$XE&q7*U9M%zS`^xJeiOiYqF1`zohT*W+0*d+HyK4LiJAlK=vW&wkc@$ ziEB{NSl0deeQVyK_jI-OuJD<1?NiZNJ{lkVj_dsH-cPP((zkyyTA`XEgRL(so$gD+$?OUjDolSdX_2QyAs;|v)t54*E2ftY4MhK?XVegvygF! z43ya&v!0o&w%)fb zCnPvqKF$ukJzU)2r|Qf3AQ24iNn8Bu&eN5F!r&In|>RePh49u7H&I5HntJJKXSl^OqMvy#^nfh5l>dmIS7(2A$MDkjM zKdaoSxFkd$+$w0H?}}~=`pM6d#wcuV#C=intXFv(7QqJkp@sabiT4f;DsN(S7SA^U zo$bT3NT?aY9RVyBLkZp4dLt z8{hEi=g0TFmW*3o5(c3G3^>@pJJZXz@E`LWA(v zz0TwNyZ_;fV@!TK^f}uYm8(#54khOYE`+wFjk`ZlBcrit6o*_}VfBp(TIHWjR*V5z ziC~d;S-dIjL#31{nTb8)$~YM(f*m(WCiPXA(9&bzg_ghj#+W!a$Vk4bPJ@%~;{U~k zdE?SzQ%+6QJLa5ZtYoUpmBl%|lRxP|o={{gt+;!HUR)M((^+RhSmS2N4o(d7PA{_# zNK-Un}K&da=7HZgUrQcn}8QrzXR8ne|_i*TgU>mX=OM0*#cQ-S)&M3=FnK+ zY0Tu+%|gc0mFWVTm38aN`ZjdvQ{TS%=RRP$_SjqNwfDm53b<_L zmkw#FfbevdbD5qQ9h6CkJ1XrngOMro&91wAq_6eEK}F*Z6LL&IFz-V?L4 zb8+hAshF9bmW*18UAuP2_MJPUf3Oi#GkP~U6LU?zZ!LLbXu$0g?Rk&^}S zQxP5^|0!Rvt5g=Spy-DTwd_+HGU6_c(x&_pUj9}w^aTPk40N8(1SPMhV|l+NfUGMU zQo3OEhWK@$ZU$u0?jvV7fY9{~>fCs>aj1*Exk(BKFKuDjWbyBcM^6@O8<>kb`yq_n zGZgReQV&!ovX`(E6}2SJH`b-_k3|~)KtBmN1b`$ zRPD;tgvDt0xJlNr=|x6Dv8>4OMq_wVvQV0cT-ng9aj|qmCH9{NGav+_;z z#$aFEaKp9n>TiBk{KQZEKjZn&e{M9T7cMN$D=sz>&nxbQn3|oD9+Gv-M3Uw`&c^l4CBJLLWWCJ@+3l9iLY(N)0&6VhS1V}qFe{qe8g_gF@D z8N$E%kvlaQPzQ>F&)`A~R}~G&@o)a*!SwhHf`9q?=c(V%g}t%yiMa2fhvL!455+6K z@f%}!bR_=4&;3d9xiR<`|Kg|p(d{4mvChZT&j!En3qK!+4jqc0`l+8TF6RSpil2Yq zKZrZy6Y=j}{kHgT#r0yszj@2cBw!nAV|>UQaVX)`GcRi@>AAzWni7_3lkAvAuzAu; z=3^(0#>0<2s`o7VYLF^^Ee(kIo*lOZkQ^O>d@5OmxA5(k(zxiW=!laOFAWV&2Zab{53U(( zYw%2XCgtz?v%|h7u|mz;xnQlV>s9A-A<&8K@`H0x^l~oyMqw?DHcJz}6T6W)b<#mBOJ9fG*sm?C3kouTp0As!UWQ+J+&*po-EEB}m z-8887Af3T_hG$_%9tf8Hd2$>b`&uwdnY$`~b<7`o$A8=sS@-q3S)}fbks;}l(jliM z>z+6=6OSC7iDT0(>$Q8w8?kTKnChlCCMHI$Z%R>(9fSSxn-7=BEPkhH4UKKBRh{@+TE&k%UezyJThKpK~bvtevDJMluS#~jCNfAVMS zZ=-N=#;<~Z{u}Y>H(VbN{ML)(4gX7VyU6hVU;I~))?+-VYS|*X+OGG!L$=V$Q*N+m zDmf*0FPb8L)K=ZRCF9)Au`7}~4#tgfFa5OTMKS5W8EfjL`gF#$eXdix+ZkPlem=*5 zJ{@Hp2s?{2y-JdJ`aOxrJ5OxtJ!5I}2h*RJijxIjHa>gPfX3Hkn#B=~hGox%7Ozmt z<(q!=C$~n<-Enh>#gPt+Cb$Cw-3MViJ$zvyKUPjTr64l z_TT=4iEbPvp`J0Ti&Nmort4H zkHq}keC*hMWdnT{^;c}lT7B_kZ~}B=jzC-()LCc z$uJF#BtII#hQ&U<7e1hIQe!lh`-ft&cTlpD4YU0Ui)?nWUH*Ua_J6e{vhMEB-eWr( zf^y5^=HP`dcxka+p76*2xpw;WS?Ui(zN8`a?upm@`2X8)pDFOsU;H;H5h^(&mJTl& zM3%W5O28Q+>7r|B{WYRiPn76GJ}mQb9`z@{V9h=q4t98$$u$J zc-LAIU$WNVen)ahewp7-UX_38N{AnBtm+@=jiE+=3`s7XI&nPq?AaCH_L^^r=ihOA z-2CjDz1U0I6Vhe)&iR1kQtjva`Wuo}Y^*`&6YmR2qoSpc+?-}XNjvF^=x)oBu}kvT z?{PKj1GDqbB ztc$U};u!^$cs+*B@Jafzw3?y?KT%!%>bIfDRp-4_{WL*5AqASFo4*Tf?r2(O>x z^2j{f4r37H3jETJ+lvqhIT4U@2)DZ*n3X_g7fwQzPn!W`-KMWYc?QAeDSG)sVc9lb zD2@15&)@hPe?1OLR=)bx-+Wel)0_UfuaWuXU;dT&@|V9{VmJ@@-oG9Hujls1Xa2`O zi1%!6tpB9JdC`#>!mhg5Y%J^5CAbQ@(=eRoL)#s?pi=2$OjDi04 zwXc4q>Ka~1H|idH^1w>`?)yGubE9xk^tkVNbNsz$_r=}6_K)KCFTNUQ7?DoQcZY_D z`5qAi-kxYQ24ZAn#DmBuo;V!GHDILOv8#DxWJtP?sIIoj$=wmrv0riU9owmy*_dfA z#_`z&55CQx(qVin%VHUXY7o6`cp$Dlus06w-5oo&jrm(h3FuG!2nlrBcl(X(*8iw$ z%oGS|;sZAat^P9nYICjIT1-u|+XR2_gP+(ES$EYSr&pv$bKR^Y+w5#BPRz{52~Jo` z@8x>3ZDWI>>WIOCz8D)CR(n@^(o^?LjK$}U=SIWJ4WQ=kz6F)HKlW{J#J)Wvv19vC zEYD2JzEiYciU0A3U%4#Hz8)a=-ta9i6R(K>$^wyPpm?2j0mXjv{U3Y!%RRxHe(>+a zORst~{`^h95g#mW7ZYe>Z+h*kWy|p)G|V1Vv=x1!Xs;Bcj*Jk!18QB?=di=*D>G?mek_T99AuX;<<)jO7)ddlk zgEX8M*%#0c<`Bg7GZ`cEL`lZBsL{9zIJuHXB!Es=9q@89jbIPGH8nCdr?c_x15 z6u4D_@8xaZzQg^``#${1q{(FnTnYKQmpwNpg$-j>02|3( zc|*C@-+WRzMF0;A-+$j>n;V6TBkTTp{Lqix83zu1ApZKVeW*T+UkF zKl{L6Y>BLU+uQzbc|sCfvTq80@&ErW%iqfp;DhH! zkH7sr-zGW;lCAx((t_t-`h!1r|GrVUD06l3=6KWFUKUqB{^#)nzxsjVcJX0pe#UJZ zxdThFX$9V5AsC8!!B@|g1L#cXNrfltiQYbLrIKlRMW{07h=^rtyiScBMPLtaI`L<~tduL2g21 zgB)SzhGHMpL#y9C5yk$ z-ARQ~8JT%2uoMFHgcuzeM5OOPv6mk!!6?nk@xaN&m~LKvlVw-!9E-1i_I{V$LIWC9 zL;oebE|h_0H1&8Xq=kqG>CJ-)YOy& z=2zmtf&GQ9XGZ+K|NVa+zxu2HR|$Q-@WJ@Ccm6{B((iw^JYQTmuwx`%dh=cl6lq)V z7Ynr@17MUY9Fy;CiXT0&gf4bKl&!>($x|^kGox_qR%Y;-X6_q^zM&_*G(5@|>Qo3cT6`Q=Ikt_@|dWf@WZ>A$^U62BfYUH&T##cf3f z4+@tGsPaobmG)<^EdD;}uz89;17HnNE|f+o>%MG-@?3!5_r33ZQYim>aXC-;!2cCL z`?LS`X|wPPoEIHW3$(dd7#Md0kLQl^Nl4=yfc~`=vhG{I>pNnJ+e)OUH@*1Vlx$_9 z5~-T~1w&)^1@3b&g_y!G-v5vnpDsI~4^-a*Ss64lq2UwI0w_&C<-XNax;)|91N-6| z?|fmBg8G&l|E=r#c_lveg)hg+$^0(vM&P38aUcBkc;`Fc6~FiNP~$vsY>1Zz2Q)w( z8J6y34%1+DB$$qyI&~_ZIC9jdG+3Y=lY2u0-{l3ah+c`IM#Fx&7L`-Ir_}x?rAtrF zYjC~9w}Yi43Hd-qOZwb`+BR43Z66(sYxnPsgZp;Hw(+rOG#H=)_?ID?1D!g^9r7JF z@q2lf-r<9EgGclxc>|rS>)l$^zta#suBKDXiogHiPi~2+y7%BE0F^tKz#~b*IXi<3ebRKIE~g366Wpk2-&( z{|@W%9@>Z=aa+>ZSKb^?TMn@xAvfv_Kb*EDG;5wtPZneq8=jp`zQw11JUaYR>GPZi z+{hbVS-X-6SKW49nR{4{ zCf__|?t>e|^qx6}yB~NwPHtju>QaWiV~zN_tG2@|3GfU2VIE26dk#-Zx7c{UcX4Fh zXXE$o`h|GsuRR^MxFlS?V|%>(rt90J&4FJ*5!p2GuQ&^Ev+id4)F7$P;feR1DAL{Y zZE|9)-r~ed>7Te02a7Xu@~3QgFHDV;@WpUuGPhO7qYWWB z?Eyc8WjR^#`SUok^Onz(u+gH*Q_S~$@FQCy>)!UZA1_Z%DXp7;_rL#xaa6kY7C%IM;M4cS(UY4U z&pyR-b#ZsR=fD13{Or?c;g#vX7pMP77jg3mCEXC~XZ0y>-D+XAo zRUCXXy~ar%h>V)9<71~!#+(nHWRkhGSe!B5#?D6VJk*AaCC|B;fEy4dG?u>k=9}Xh z@c`vMrFx#6Jn3}Mt)6)B%NH!`&Uf*5ORjx>71#)T`wI`oE1!Kp z;&MQIg`$PX(jcaX>jhE~vv~7g3K&{(Ugskrtoq>E=lh;`G>)Cjk5h2UgekrSnf@UA zB7w?~O2=Gj!$%Vp3d2Ka_$|!5yz<_oWu)HQ=qFe2>CJkG+I*oI~R$cr2zyGKI5Y5?{ zSQ5^1W$fH^^h$SOM>xtW0v|ojn|zS<1hi~U^P_+D`S{b1e2S;b3#6yS5(5DGAL+i* zWBf@1(^-11`!e-mOzK{y@crNU>iEuAz0CbH;9BR;m7nlOAN*+i+8_Q|dAb4{frj*? z?L$McYu649>W1Bxhew8D+xWIvT3Cw5pLil3`PyTim}V#Q#Kf2vBo{TfZVV{wj_v-2 zTT8O-$cf1~a_nRrIXNBky(7`HykNiZ?1J8NB6voF;#h3Pb-O3x>+g6@yzthW;_3r? zJ=u={L%*V8t8BpZf`+hP!l~+SKIwrUD|IsMo+s}JDZ}r*u!8^c+=(;oyy#*fLw(ob zv5t?w_pjf%C9>{C+nVYQ2BI<4AN|rnk4?_RgNIJW(J8*`v=TeV2IJ~|+oZp0KtI}u zT@%|prW@#4iaVcoZQMH<@jpI(sKj{r!0y3TykJiw4jveb(Xn3Dsr2*aiuh|KX6Hq- z)=E4yH4uOG=;eRSJ@BUQd{w;ml`j?p>CgPn97gguoJT+So)3L0e)$ic9w*E$CHS#7 zenCyW<y#=;94QSi6 zThC!xX36fku+G9NbI6!1mU4oOxjAleVKbjUnWlGah(XRROYcKpt9}-xQ&M-m{k<_b zJmgbzEXuSL58u0Hj(U8cFUA{#F*H=JdhYMb({)_`JjgYvdLGDd@B`rQu*+QJo9M`A z^^1Jg(Tgkt3NttqeM6%XF4AlJ1|>=dV_7;^a|t<%Oyb{4{M7&U@3%zO-Tm3m+b#;} z|K<-^z3Z2LIsU`H|NoY!%M0H6ecus3@a?ZEw9S5sE)x1DQ})EK{qYCloxl0}vS0r2 z_kQrZrQ3b8%CBDAG)P`*bDk`}@<$(x|M-9XL25p-ZX}4|P5o6o7OJ;FWc*y;H-AuzKFXSS1j+|x913kzY z%0IUk`azmaUoZJUHj~@b{RlVM81lE(DI04N(=#(JN1xLB$R|JLMg9jLd`NK*#OFTr zN9QH$y5XW;`~2)}Md>y{_})nh5R}&>3$e>`}y6*DdTULJ7u z?(z8HS3XA~L>+M1<(Yr{OJ+j>Ke&A;?mImDj5z&!U}7k~>oyjCRr6}Z?DqJ}kAFOF zyy>RcyKleg#Jd{~Y>zKId~8#vf1k;4V8>{D&x@~7r=@naB*t2%BNyNGFi;lnC9_$$ z=5FM|fBd6u(jH}#ni$8YrhQ!??b#E5ZmS4G2|3~v?}LwAUZ;Om?p~FTKF1RuDD?w_ zg~oJXY4po|QGHP9EiWs$_Tc{bo8R}>T{MuWst}?=u-Vow0pn zD8@%dV*550U-{HV%hztALmfYHBA$5SNK8vd8yOyp@$oTF!13+f<)vl}4>e+9d?I=^ z7@n5yd}?++PO9xqH5X!ju_p%mbCaGo@~P717ns~$kmA>hUE?Eh{Z;#7-<}=bt<0%n zCiukIu3Oir>a~LTU2WVtn&PrdaNC#OWi#Iy<=-P96gRsgIp7!MNQS9qE)1_h$B;ah zai%*ifB2D4Z;7ni*I10+0lq8M=ShIc>G?Q5ITv#plMbj}CWiZCVsy~om0~fTx*{)w zeJi5d&Un=eZ-`GnG#SUHE}t>WaPM;5dBbo#=em8dV~h<0;v6cR`f4!zUDyu)t4TO6Pq~w`%H&h zt~(e%@s{s19ic0vwA?_R$dXqAB101CV|Za%P-KQiebz(xAszUa<5gK!vb}l?>qs(z z8W-}%8(9eF=MumE=Sg7VA}o``TwBWclKNjguC`rcTZb-r;m3kX4G)hXcYUSmBJO;e zDc`ecjKdQizxHH42>Yvl^nopra|ieD%DfqszS1B+08z4$0o|s*w@>~XK2ty{KXHmV0YV2&eOBp@CTSb zWp(@IzutL4-odhd*oey98t+&z@f@7PI5zv|J@fPEgHBg%o|9|#BX_<>PMh}}njIBV zW?k%cJho=eKsLM}$2@nrXcG8m|i$#0|}_-sz)^j2cp3S6(RLDJu{^-Ni#-AhJD)l`Om*S_U+#j z+qP|w-Me?|{d5ct4g1RHCFy8V3{L6vWbfee)FG!Nh`toh?p9H0-f=IeYX zlW=y|1GjB8IFzP$e53uk>#tMZ4*DAC#~ytojy&?<1>M_^G<51038n7C-#TTUsWCv9Z{i2(&tw5tv~qsxbCX`CG-_I6Yzb#iIJfg)Sz)G`lMI~ugy?gvX48{(gYwtk-xJH?(Rq!-X5~IBbB={N z>q^P13DvTaa!umOtSS$w6IPuu+q&zx8{74~VjZrdH|9I*X!Y4{ifcu2dSOHE_^F8B zV)p`!?dWg?C2v+e8`Ev8fOPvL=V-Sr(Qjs6;}Fq}*33;c!;OI$9vq0#Mp^h(xtS&7 zJ5z&=exGdlr$6wrxaq+5662)}!+k69(t~|*^VQp9=XUX>%E@By)LhG(30h4ymM%rl zKu-+l-S@xZ*0^TxWg_R-fg2?E{@xqE!>6%4#*xVwXi>cDK2rR%$e2U?1OELV`c7XF zeFe@9&${-i_{ksr!L~f9G6lT@b3ydAEK!?Bwxq0KVoh#ph70oFa-FcTWkq8^{Hbox zTaY<~b6k=^iYs*#^pi6F#2@Jpx89SU(@~rrs|r1~#PoZv16CVY;FMic>9x!g9)}v0 zP8n}wa;g_uN*NXH(pUL(&NT0!c&+n0_2=K0Z_oCHY03A zKk}c+P;Y2cU%~|DK%)^2A;49Ql=Zt_eP`_1waspq1F(7JZ@&6=_puAA3sXk4a9<>Z zXPB&RaMQ4RY$EmjO#iNSs`mB+cU%)! zO^lS#SKw@L?arO?w_f%V>lxOY;4cx>vQG$IY45nT`OrVwXKyU4k@m3Zw7)Ep@C@q5 zw=p?QMtfypgZ9hGGp=>!`<4Sj7E<8hCCSKM{g5->xGNEZdo5-n}PAMn+{qSKndG$2ZL5bDTG zM3jeoO{X_J&>OeyABjPAYV!*#F|SIYBfL}qLCQCNUvcYI8VKJKBMm+xZT>Q2!2ncz zmYZ_HDLrQNhRS@~fiW?9#9WJsn@g+gX98+}_e3MU?%Ij?_UG)1k->f`& zDjt38vAFq`TVmU`ZPAoMG1y;raHt`R9pXjL+8^Vi!!g@j61EE6t^jmhkwCk7|E~D{ zZ@n}6x!PF+Qg-TP8`GoyEv-n=k`O|(tJm^@2K@2QcG=)jna8H4VxE&;_QDSVojxJI z<8UC-l1)6!4=e7N9gyHm$?uo=a~%3dT{?L2$$Q5wnP4T@bxjBsQFvF<@IUORn93b- zI}eV+|6F#(VOPCF%-r+v{Fdw{qyyLrAob1X;OPbDTZYS_>}P^2G%Nhbzv{2~Tm`3onXKeGF9b2N7POwib65Y8`VI>z%fYu;Zh!U-K2bNPKAeezOHH?N zpR=?WJy!ZvMv)Vmf(#1O$)(4ni2FB44i0J{;$8RRUem<>E-hdHcGccp@v1xTh#z_F zYhrYG$c>S*R0NVMWXdqj^gKM=h*#eE!f0p!H#0XM(+s>shbxdk%WU-J!Y|iqLfcVx zGD~lRhMdBMUZ+k?#*rgOVrFK}*JW`Ui^1uF+9Yk0@6hhpF&@JsqtVouVrphSPR`E7 z$vF*-eWOyJ>k*!HJ&A9b%wu7K%lh_gAB$_R+7o+rZufVDSzNC5h)I>%foVZjy;XVc=-)Oam&@?{uZ>f>1e8c=UNLs@y5noPD2m&^~dmFpXjnZ z_V2$ozU8HNxV_KJw_eAc7Fm&@{LJU=4nPp$6|bJJo@_wf<^0jwd;X_-njKy*970ApP%P8fL7Av5&~{4 zxO&$_e9H^2i?_V`1u@*<1dwP7Ez*nYg2O2+$a{mwB8zfMF{nP`>#p4%{URarb+eN5 zmsq8&?#FogqxBcB8FL@>p(0d(F+-Hk@+qQ{#;~QVE z{(ML}_*9%adCGablz@e^XI*nJzV9_JkAL$2_4f;dmW7P-OLh=beq$P16-{k7DVivh+hYp~}^67+$iSfAh znrq@+zwmPxEbA`nH-G=yH7Q`IG%L8ue@-;WD!Qan=`O{j@O5IuArHL6N`=~wkO&-K zda+wQLE%nI_UzE)R|# zdM5yJI>HiH0fLh!y%e*v`-$D0`K>(f1TBgrbfj^35FvYAfTN7;NZ|Tfj?32p%v^IJ zrlfp7arA^w&rWRL5sMm(<2Ivrj~_o7Q&Ln%#pJEUm6&ZV`df7HZ)*ul+~M&|rT~ zWzGS^kLMWsA6;a{2{qzBwiMC<-R(Oe#=AEV!99p(3iJ9PJeOKFgn`&8wVowx8X3NtiX zQQ?+*_>M7Ya77j01yEentIU39L^4ID`M;+xe)A(Iw&Xh^Tk*}`D{uv_z!iA1V5`3Q z`}UvtSFymN@62?xrcXs{YSP~p?QzE-Pm;Uzr&v8%P|{gzc0&&z%(JXVp63pCWV)of z@||(`bdL0+S?M+>Pff=$4Y-dSI}yia&NZ9vHwFiCF$?_&{ezw9=vc%-57XD5J3##n z8G+MKzR414c=3td=ICPTa{$~c(&4b6-6<;WrRS0ZeK~!b%io*234k6+SguXXD-^kQ ztQvvTIiIc z16&Koep<>q+!*oz5Bu!&w0L61@sjqE>b^|{=RZ@div|F?H99N0PLVI{-R)aH6JOSt+=qJ#`bRz$z8H@X=)7O())cXM6 zI+H$EuS;hvz{xNugzi(Xt^&EGz0lCWPC> zV?EKNJ+8E3&(4WBuzyz!4h_YrnYnoUF8f-#jV%vkFS5>t?}#|u8F<7cX@|2^h~~YaTLz~i>bFN6A#pb$1XzJ41Ulzb3+I% zTWy;bE?Uw)bJ3*uCocW7yRc9B;@Ll&rB-Vux&WI0ukZ7==v{;UEe3ToIf&3a9YQ)a*5pM>d-Jx?+ zXS5f-zvnS8{-LQ5S=Z>7tY{3VeIjcF;e5K8pAOp|6)U* z%<1b{j`5NH*t=&mt~)Rm`*%nd#Xz){#Y1WrlhX^5!86{#%L34l@-?b_?%sKI?7jL~ zF|uu!#yNSFTQBrgS)5-ngY!z==sDXBuPbk*JSq=%$AiDEid}K}wbHBn;E5JTs&|&P zc+36+a5%lQ7u#?vJXONwTiPakC_9hXdFyBS5N&}X4l|3@Uh1HPkSEF}5B!z9GlupU zi!!#$$=Et`2w=m#w~ul%8MYWt9C{><9lc+)J{d_Ij-(9tTPYjP~Y~H7O8BpJ` zZ8WAQkHx~&LQF3|Od^ff~rluZ@Yj3(SH1c-7#)c$Mjy@g}>QneE zQ19^eI5xegdK-?uh2yU8zJXEI`J~D<6r)$&8Yd^GaV705=$Y@(g? z1NSkm2PO~c%Tqs4K+6w#bQ{1A-?ntzPCx6engC;O>VdXqHwC9|=$ouJIKOgNhBE&o zmvzR%1&}qYA6}IozMsAff6G(yy4>*PFqDCM<$;_NPU*Yv0J6{E0V$wNCBji^@aPYg zk+T2bKmFHRBIoXW!L#y#a?wr|4{Z@Z)+0yIT{!7af3#=M?%1_!mt;!6`ij|@pPMlq zJx?RKw!Dq5^qNQQ;OjWv#xOn=Y0t&vG8ca|)D4^~xa>XhXSi$84%CFv0403ZzcM;uQ79 zcLbF$`Gs86BZ$t!1}RQAA|E{uq%i&z%3{l5fb1icCY7uR2nTJL>+2Iu8q#5gM31HA z9>>Q)hx*;a6UQgxit2d_~)Ju!7sddacJ_|Lu;<);f@Ztcbdw(DtcIs;`}%ew2tBB`v3qKk_Aaw{Ov*-csi|+`=DR z-990`>*i` z@=ty;|CEV5$ORc8L{=E(mV7G2ucCqy=xH-*!z^IVx8}{8e8boA(+~w7&nW#Ir*!z+ z-}{wJ@QFR1#XEk6k8Db2_YcM*V-;w#oTqw`t%PThxtCj08Y9s&FeJYXwQ=cEeM7O( zqi2=3mh)fzho9RLS@+q`f6jJOP4&JWY%J!DgXc0!U6FD^(jePN)~Dqy0sD{qtiP%(5AhhCbxX8|F$b!@z)L~z{$?~ z-);B*Gz#cJ0jnS0k)!gaJSQT+=wGs(QD@|f7pf-=!Vy==2Ywv01z$eb#Q9G@Q=!eP z#4T%v6PiSrg`Rq(-bjOb^d?@7D+lP4MLRT|R#UQq^#JvugqTwwM!yk~EhFRG6;~s^ zdf$Wb$xq!Kk5A6Uz{qyr&O?_xKd1I5IrG4S_iB85B<7lG_tTT!n7O#3aj?`w^!k6)|qxw_!oNwozzw+D-Su*KYl9y9cQ%?U?FM7dw$+~Vh z-*5hQxb^~oB5?%-%q+^8kt~#i?kq9Ob2d-Hlm;L-E5tIr%MK<`JU;y=hO$Y=O^2rF z<;@II{rHLub?T%EVu!i%nls`^cTD0-B>WnbFvWBjo{6iZ;dI=gb>i&A(ebkiJsFuo z*-W5H#l0P_D~_7?)ozmSB`*ER9lD9pitr#(ga!?+A;pr;l^p<>bF*_L916g)-TFCE zEu|R&LXKc?6gu(`%~9^TE4?9w+moh>U+u|ux~O?6-K6d6Q@TvZdGeJy(}0u7Sd`7N zu~82i@JEAYQTW8EsW^V@gcR8maqm~}jU!TGufF!WxZ%c|TvirAnUu@CNs%4S>z+xM z`n7OXe3XT}E=s9(UC1-^g13CNlglhLuOuD)EYnvyDXvOuBCLL@LPuP@$wDUjS@cFJ zu9FWLCqlEl*MG;Uzg+C++Dql9@|xU9n>-{RD^2k!WvS1KO#(xL2U^Jg==iqSwqutS zE9x7;d+g}pICA)qI*6XQ>cIYZ&U0^b-fP)W?rPqcU~FGorLL*Z$(5V;KgV1McT@P+pqJba$|Rys~hQMI>r*d-Dwuc z_j0$HX=S>KN6$%zoRqapaGK;X{at~l7r36g@KS`eWw6aIKH^eVq+1 zEc8{evC`=5fA>z2RkBmEK!5KNq;j4om1mXjIuP0065v%TS` zD=#_eM&CgB=@XI`*$1a-KYpz4@&ec^ZdgmdCBHRn8wDu%`0~%r85jA&jsH0)sZTs- zoIKHe)xm-N8nRELAI*ujoUG)T0O>dTzuFIG+C-gpkxewgt?S)72o1YU5Jdxel10Z+ z;_OD(t^MdhV0Y!ibwu5_b%w0-TJO18QDJ$mNIV6r-)`)FUlG1zXD&nFp^;G!+-#1G zYtT4gJ&MJ%W#zs5y0~`u@{AsU-rmk{DVHb8uqy>9OiC_ep?BrUEH~JpU!{%tK<~_t z&P$0CQ)!b1by^qc>|bu#4ss!VXlT%S^pFOpo`hv0jlr$nF=;z8H0*1hPoBt)YlLMW z%K?vI%(5^63QcMOrPet=sQ0z3S-y<#;pQqz;GCyk?Wq}9rD1s z4HF!F{c4*moQsa2>)y1IUyXg6v$-h2so1&sR?M}y+A#HR#>Ujg?DU+kr)9Dp9iPQt zk6{!Sd`AUI!;WE%rN&28pW+V|7@4*N;U&gnhzejubMtW`xK6EjeD(0bvM62 zewt2yN&c3Fv{9~fZ48gb;BdpdgWMg^U~k(*Blhhci-SAIVw=)e;;|%m#^uRVb6!Y+ zXOOSRFUD?6>ayso=2Pk{X-Ao$k;`b_qTMJDE_bP4*Li81g=diYm9Hw|ugz=bA823F zkbC7(%YyPuUAAR|&GO9n(fy5{vC}5$lR&@EF=oAv7vu_IUqP(*$P}&yX3UB|_hr>z zL3zvmQzkOjV-e(#DiVLrv&$)2SK8x>;+i>eEI$9qkH&rX-Ysg)NAJ=?jH{jw?B5?d zckNVNF2~Nj2gP$s;-^y@gOA3*(2m%D!!5Dv0OM)pt2wDYb|H=&eK^J?J6p5O=#!in zR$b36Hlu%RTQnO3%1eKoI&wHTp|NAWb* zQ{s273*prSat6k5;EnYx|JAZOdgnwu(yd!Sh%0#;D)kl#PBy4=wf2$WwTNvNK8T1#g#|yt2T~T#^_}eUAHRQ16*|roU&Qo$D7@b}zI-MfyUWe#u7i%p zG*5J%h?Bqtu~Xj$mEG#gItUxrK>p7^Ou2)ZkD8~#2P#X=2i|!{L>ZKpkrDGuSp4FN zHjIOxg^EUb;NSssuj8?6`_34Zo{A2SA83}cfCZ1zSIDiFwWjarFpJ&v(UZ$i-DUUK zKo5k%jXb8I^h}V#8?;4G`C@@Ln+%IFgXXcpAvO;U`aNZZhZ?Wy3JRfPA2rVPU z>rVnesrB&5hpZ{r8N7~spp5V$Z4g2UJO(U3Rhrv5{01Mjc@=sVy0)SHUN7LQWagTz zpzv`)Ajg;qwysNv?ib3H_{z`z>%6P^_8<1*Z}qPO)^ocOwLWcoKHE3%9anYFcL{0l zen*--v+!QmM^=X@Pu-3Jhn8Q`cXR^US=-+ldwrLA#-8oY?y4^%5fwAz)w9Fl&U5;! z;nO|aJl^PctDMg=5xlDg<;JZ{v}M}n>>Qgr)t1z5a}#9tjilp^XhLrQQoMBo59yF> zT7+##8nSsabtBe^GC$lh#qA#p>aWO?HwZD_VBCSeV8osHS3I62j@%59r+%~0Dy}?w z-UB+o%={ImHow~vG3NCwjX`KLrJbO2;D_)n^~;lNhEjh_zX=XWwxQGUuFf%$cQ&w5 z4#Ke+iw*Xauga~eo49YNZ4y-e*GK9QlzyUT%r^R2MNkCY2ygakJk^|=jdAJG!^-Q$ z1l7oe1A{70$Sfj+P$*EO)OiT~{T3EvG4%{_=u}XgA)w`;D8ueMCVS-UcPK_yGVEU+ zgeu(1lq!afqE7IjT(diZ3Uuc}h0Bc!%z81DReb2?%ZH3`6W7sAzdMj%Z;Egkbkr;`z0&` zl?CtqL6ugw5JPJCd~=Gja6+TEmy;$dF)=(CyT;hTt3ji1R1L9@JTzz3p|cBXMl_m= z*_mU?&usMe!|+YT(~O~EcKnJRln4_YqOhMK2Md+#kmyq#^$VG#%H1-{G1H_zQpoUK ztbUDxxH^p5oac%N(PCg=C{9dI#nDqIe7f{G&v}lIyfayX;=nElu3GCI9MFK169=Tr zM2u)5p@p(E&yE$>naWM>%HR!1K?f@*-CXD51)s1`-dUhlB<@VTi&MNsqvsi3@W4!A zP*74ihL>~F#>%kMG#jYia}Y%RyE4s#hylICFFeLzPw^|09yE%`3aGf|MURF2J{!!% zpupcDa$P6(%I}K8_KDsjyY|N5#LnnJVH0f!2YTYMuRRE=n^67H<4?2KqU0$4=W$`C=thj;@0%@U(*3A-1u&UsAB93})Di0ctmGyfi6! zPUxnyvAC~-3#7w_(zxi*RmSry=Y|2@Y*8{+vV3_(vRu9Ta*^p?=u=Su?0R8S&s8r-y%EelPqFyP;gnbUvmQyDHR`Db0@Z&k@l4u=*a>>mLdkSOZ zXEXC|(_!f&Grw)@4(~pc0bpvJ=;j(WiQj}$;Fi(z)rT)HC`Qu|L>DMX&Z}J(`eGJq zTS~hdeezN0ck+Wj>-U}rpI02xIYdj!%3zL(SdRrvnTRI3t!PVn3o2g={t^;rOYsnA zi}aH_T#ueiRyn|xUYVfsDb+%{txWN7t@B0cD2yA->-?04{-u7dXY@QJ=kU~|>n|Vl zlmlsWCiJl6y9}?_8jSar4V2;p)gQOwG-qdAb`}TwG(Z)Z8Q#N-q5tnx4}@kT)9B{u}hEJ!?Za(SQ)e4xKH`N?iXkB67!xkq*pU8YdH1iAu^ zN>A~KvWd_e8*vw2??x7swhAae`D;qv&7k|Mprp0Zh#u6v z0zjuaHUOzgu*zJ@U{+AU%tySlJ&T%d@@qb<;nbG(oXrULF0{LN!n~1gmSujQ?nd!F zbz)hAte_nT87sQ&F_$12;Qoqn9P&ot^82yWo5E5yxk1-O!YQt#Q|6KUryNzj$+O_FR71e#P%KgBu56+6o+F;X}4Olas9P>VxXrPbCZ)X zvTdhIz_-qzpV|Qvh13mnbRP}P3mrrVFLKJ_{ziEtoat(mU(+AjL6hVc!sXap93eN4 zS26Vxx;qZ@K;bRYQl9LWbd2O7>FatUU(nm}QiJ?5&kL?o)#nOhXWmnuG`-L(yXTOI z!_V*y@scOa!FI^5eFxQ>`pxj8R=uX4&9CtaYInbYCDv1oYWb1%q~n`NF<2{3^V&`*1j-HQcA=SJ{TJVDx zNLByTp`PKFHXW1#?VGqw<6_re2c25x3%kqcM?IJH$wy~Vhjxs+_(Hm6E+z?Cq)|H^ z9BBBk(4ctDhlct%&8t3Kc21`^^d6J;%PD$vPFiCw1gniSkzL{s?CSs6e8^^roKvOE zP|lCT}tigQyWI@&#n5nq-{A(v$>bv70({;+Y zpu;QaFa0KV+|r>07q~5EDuq{sl9?X2sLXAz)ebF4v-mL<`jC%|AfIh_H1%DAp8Vf7 zy@MO!N%t?s4gc+MtDdX9x}O=HR@>~h`(aI5^k*_ldE7=y8uDh^fR!#8u4C^uE4n82 z=jTjVm~`m&>$pn1Mg^jpPHXFW18tpR5*tdr@GGq8 z5f7VE{0&^WCuV(sj@J>BcHtv{_ewX@;@}|tI}4_aF*MdudnX)=y}9s9Ivo5%wxBaK z?2nDj+<3xTQT9>L$c6NKkTQ~P?OSRdYT2{z)p%U**~G#oX>XPm;(qMdQRl@AzRD{L zx|EYNNeH<_xQT7sVw+?$o=JfKSwN=0g=zX)^cJ3L|7ST=?3Pb5eM{^*2p_r6sAeH( zwfot*=%DLfG7nND$KZPLAoFm6kP5gM20OxD1+N`#4giZ?`iqrjP|w)i2xLcrs0~6i zcL!46W!UUIYUOzFW|K}SI}&#+ML|V5O~ijzYK_kez$Lz{bkZOWFw?5i0 zX)k~ZQ{5dmsC4W{?tV}D#ch?p>R0ru&uJHmF+50A94ydbr%}*Z^Boo#S2|=2GzMaL zl%w$y8XCgz{b1H`m!(v4)y~AII&w9nrGrs8dRl7Z`^m=HkLkWLG~ z11JmG@R?jdu(0C&M9k6l-_~zF`uN!DWw>4z(tQ-`Y`A>dPz6jGI zJqCC=(8Hb+wjMKJT*BLhYlZ!Pk!Nx z(KkFEeT{9=S{{hyodeQ>n@cySf>}O26rYLMFe;Yvo^0t`d&?3zZGg1v;c) z&dE3cm!yyBhyO}LOj$r^q*wW@^f29SO(W%ja85hzIS3#=g%vMm{25QXgCbMp$2m|q z`KNrK^HJjxb|wvo=?YwdD{uv_z(ye_zl%I~*OZfSmi3b1d8(yMloy$sgL?XvVxERY zPow{nA5Vx7k7Tq5|9ZyE1>l0EPmm+}wUt(@)=JNvgZhDVOO@MB^bZ7)Erar$m~QkZ z?%CQueDmKXVT9=eD18Vz6934EpoVha==d@5i?)I$gFUgwizZ9Km8fi<%d5Z`kTF2j zAVP8ClQ>Ni#beqRx_Z)D?(~`2*9qmvCfIf_H0`ptk%bV4ktzQ3tjJhRI2S84|QppEB;#h)NSe@ z)h?6p@Pq7ij6yivn0WKV120QGCeOn?qNUs!oX)Y}s{u7SI>X48%Bc~oY&|hK#lr8& zn35HSuP;k z0B*{!$^u8jb5&<@y~wO}Q)%eakA5c}K*zEl#cVVAj`CI>^D`!!225g1+z11zE@U$H za9oZ@@0GX8+nw|~h`%iZjc+IqJKMPujPfw1Wy2w-1WhySP$|hL9bNS#J$-gzC8nlZ zs;{{?a-8eKXEdhCF@qNj=Gmb>9kViXe4{c8`5`3$MmsFR^1WvkURhX0CXk$ID;WW! zi4{;;43Ijz4ECQ_`8=y=YHi?r6aU#yaK$ zyD7X(%8>P(Jd_I&DNh{EepTm2xj{2{K|E4V>RR!{zwb?5};xt_|ZTC}!XEJRS zLGHCqDxXnjo-h~k-s5`nLdMaOJvR*GGif=0lCgfqUh?aOUh@=w)ZQhh>xKd^gcrZi z%Y7ZZSNgQN*y#KhnmJA7b?YGI4u6*T^kLZ0L&RG-@!G34-7lVL$W1&$ew1Hm?+IJS z!^AE(SB!W*3SMJDiA5x?gJs?*<0h#Lg9s&@?bzTS@g)5n?kPW1C&)S3WzG85GqTun zlXtTFz3o+A$X-m4HrAF0Higu=>oA|G_oT1tg8E?bmrYpI2X#^Eh}#@^M?EE~4$X5V zUd0D}yf{|)fPR&{!FTyC`K~SFO58r=BEI%#N+idjw}NF@_}zI-p21C(W4cm@DSvb0 z7WAxTG+hdPaL>HxeVcx~PgCBL-sG#8&@S_-aw!j$o^C@nJK=1%pNhCu^Gw+FzQ!T9 z%tNPMjkw#6`{~&6U)@Ta*yYe&u2rVqXG1hdl2K9mr#rNo7NJ ziGR^W+8ZWlPx6!X+2Ik(OSg^E1`AJPX1i1vQ1rR%fQfpu4E?2Q4!)u7(wCQda~-<= zFtYyOAv2)5Th1@ zU+^9`2h)50Rgeq*D{oSEVLoH;j`++#*fjm$rsKn0`>Z(Ap7c&L-=zmEXNO7~V()~> zdPDz7w=9dFU8miMfB98JR2S$rA+xsQ`c8j-b{wWXVdW+d_Cvc;+wtP9fQ_Ael8E-j zc#|-hSFH5md3y(CcDbQ}%P%CIb-=~ZKldX_FZq-!-dWVm8$i-u#)%t!J>TZVZ!YTQ z0xzY*4@r3;y8vN3i@%u;Iw0kAypB6JH;s*r#kTF+eF~Uo%0w7s4sw(HPv29h`o#os%!NaCOdTfWfrY%v>}G7ea0drbO9do@p;$=xOX#~}hVZ4cOXVt+&f1}5 zr&2md`!8Ya7kkEw-S0~pm~{fs3YpzYT&v&i(&a4U;$TyC3b=jtKq_$G(Z@FJNwxkF*7|AlarI#7!{r?q1k;w z!=X|8TWECp4Az9XBbWRytFex`!Lxgm-55*~(1^#!)ex1&+}wQ3%yL3C?{TM0RxlJ^ zsY!?_M+gk);Bpr`fr&wXI9KJu^-z@w@&F$wKRLK66V&o!-k=VJxYq#~`S*ZL=z1&I z<{9EvcqgyCxPFNTULs!eRCm~X_MlN=lMlOjFnO%zCHaYZmYw&|Ty!3i(Bo7`uV_E0 zf!2@|G6qXl3Kj0eiOCoq;VP~kDPWX87kiD0&%9dFBz^K$O|TANFrkH_Eg*h{%oXhd zU*|ji6r93Q%=wp8+PkJZA3AyfNO3b#~lV00a4E>2y6|Z*? zm$Y&svBqCa$|t-6SKtaMT=2d~#RLUR!^xtmyA&$%gsDI8kB_IOFXH(Bg z%P-rQ?ur4cbs@)(H#;~fd!-AKRqpuBI0=N29`s&14F1y*y8+;wn{z7}ww22?t`N__&)30{w#D1Wy=~BY@U8&D5)Ap*D$gYSTFMT%p5_PCY z=b>Hi=YgbQ-Cyw&Cvmf2#=wom-orn_P| z++B$fNRR}lxD_o@C>3aFDJ|6H_Es-#snT0YTj~@kQlPlI1VRWQMu@v?vTn)#f8Uws zdG}4AcFDcH_w(nxJNumH_?a_j&djmL^B2B&Phpp|z3d@_1t<^Ig(qRDi?=K|j|NKc zEs{_;>P4Ns&Abg!<|2f*vkb9Nvazr*&mg9FDsvq&l6Z(TLyv?Bx;mK)$ek!-&9Zv3CRg+d~GO13Kg+3-zTev<+yAiMe<((U83QRm=H#h1S}c zZ`&F>Y;#?cZP?OaTedYx_lkuaWa{Q-(K4rg9S3Ry#SIEn9h3pTe7%(v7Wj9+(V5^6 z_%rEFNzl1yGhd)k+VJDTl4Ae%74+u3!)cp5Un4z#oD0<zi9X1Ur9JYhQ8z$`d>n?j5kid z;3nY*_+fWHHU=j&t?=|!2k2VqNpp*|lRQ8{s&ncu*?1CRUH=he(!w3PYMq@1b>zw7 zVBO|5Ht(e;Y}5K>;&1h~==G(xZgZVAHMCe|soG>`i)~!H&p&M{dOxT%C)AZ20#6!>REnau}?N~ z>MO;s*Uxd0-~&9nU$}YODJL4zH+&@ch8AeY@C?HSY1&KCBCPAK|f6j)>=n54_BB zPv|RXjKxGf70zj2`6_4Cl716?z|)eQy7|pq%FoLu_dR9cA&f!(9pap*yLV{)`IzVY zj?+aNr$j%T@L}0iqm^Q-F4ivI#3`HjYysaSXR`|5{w@`dDpdG9r9*fJ+FbPrBOXir z(Al|pL%fske(n&x22W(p5Ky@Yr?SO7UDDrFymX>fLZD*g%bkhph)3U~zXHnD|GR9V zkj``5uGp%(f+`LPD%}pX2aB-6If?A-P}nx5(k>pxoL1uRhX`b6Qw;M&P7^90bl`HW zc%=6Yh0%zrQYJSyIPE6%sPN3ksW8@|zSpI+3KXtLeX>NnR1G663v+q-s$P-t-Pl~E z;kTD5zF)7Y>gUN`qA(Rj;=gR_z?;oq9$)1Ll#$b!aHogrrigk*nQ|zCbqH^OZ&Q>X zc&3kn%V-OQ7tMfk@}T`FiudOvY|5j9C;kKAtpM-~yVD~50@|nlc^@HU{JL`98qA?P zofL>qUVcjvHy2Uoq&_LF0J6pn6x2}wiaG@yO4ARSMCs@hJ|@EhpgceWqLmgDSnrzN zR@0-e+OSM5S0H>KONjPVhIWPLD*g1vBhmvHHZsH-uiKu`6>9MM~TL8e@2epQ>L4~_yw+ahxGrOjqpsH|5HFadh04aJRp@H6P_!)foEjK+#EJ> za!OonF8+b6-lp+^n_<9R`%e0CfoMnVDSA@sB6IbBrJvs=JSz~l9znlkk|~4#FuVu7 zuqf#_bl^h-hwOL}E+DZd;k@4q=o`+T@sr)-GBzlf~>=vpI=o&ny=;PXi)UJvCP3)9qz`1nzt2t#-dj5#R2k23=9BHh7F zHvUf9)Qs|yFSRB|<*x$esX+PS83lquwNatkLR?rO;)n6?8mBHPG0|ane}+Y&l$YKa z5A)Oy@?}R}&v9l-e+a$NH);y_1PJLzeezuC!xg{3}zQN=u!lXV=&iExu6^3NCU9FKBECfM20?m7oDLI(?<-q#u9 zrE`fF&@8H!_)o5tl$N+o%L1+6Kq5Zno2%MbZwlQi{pPrjiHgfcN=Tu!tklu> zNcN!*INk^+pcx(HBK#x&r~m=~LPPo9wgJgb-a?8mCOLw;!3TV3M9*}wNmhU27Xo*< zyHF0E1sUPm-4qTGp@$%tx+i(79Hi+Wdm3JU$x~%fxNs-0NIUF_Tjm|1vD;1@6b%T; zi2^sJ=L0aN}mU<8-Enm2)7HYMkA~6JY(v(0& z|32YF?Kz5HDn-9oodblhd)*g#MeM}|TpO+UqPs#d<(#g#hOn!%U4wg`1kfU@EHAg# zW_3=b+qbsH<8sAgF{g}Kq*eN{JyF{Do&^AINk0@+a1A3+8K4D~!4*!*%F}69Zelb}r`XBULCh$j zFD4zRQ@G<6?dxp}{sbX-iZKb_<<-?zR#71a&ftYkP-L~e`&h5qzP7Ed!OF|4ZQJ%n z;l5Dyjve}(i1!_wdWP~!IfLHlpFHCfzUriR@X16~&=@V6;#2>4C$63_KJRZ3Fm}?C z#h>JnkPb4G-9dJR zrHt{O6yhE8j(NwtW8N|UkU{9}9%JF5lAqwGvcZZo6W=NSW<1H_@wqCCQ> zo=lKs>PVO*+^%s1Jk>sd+8MVWaFDWeX*}VvUi&+!EDgv)Cr5i*eN${%t8)0AaBY^ z8>i(2qF$t`r`~f2Z`a zJgcrQ77cO5G`sr?Ew_N{phfRY8mnL(QYKoO+pI<9XOR#V%c78P>P2tMFH+c;@OE9p z+YUO5z7p-2Lg3ZgUeBO2`f0q=&M9B=1wNi?Yo{ltyGVz4(f*0MrzdyPR$6}5F7)X% ziXTt(op}1Bnfj!cLuC#Lx%RT{{8#dz(E6~*Hzk1>8bf0rZ(sj4`GtN zT)c(T{`t0c%{tq@ZJXMqNdyXgC_mM!hzY!=7TeLb)2b_Kti3DW$|?t0V{?%;HI-Or zPJtDa7Fbn}O3UpkwAO9gZS%Sf*3`gN`%Jv`P+!Qioq5I9srGH{V(PEZ8pM+t8XAMP z#m`hd)rGo&lhA!>Z^yOsTksip3!F0<$EFl`qQWX};1ZmLKJ4Kg|H?kzU1e1RJ|N8ULWPFcjE0a<9we7 z6Y1VfWxy1;0ipEo_?{nQ7}wo1G0o&G^|c&6NyYqAfp1nS79S|i7ca`?lVBR#lz@ZE zpRc$~ggV}pk*cS9!B3f_RwB6?-}UrmV))0-kk6c^5?n-oO6FC35jE0@Tp|wcLZi}A zKUBVe%ccUyt)AdB<|dPVnYhumzDTcr<}@X`jQJnEci=8)6HgU%w077I+>^F+nM!$j zyXhTX+1>^%Ku3@oJW%D_DW<7%`a9T`AL({9xBJ!Yc?!egZ&6{1_$!mc1XnyEnk#wp zWtX%gwuuL{so(fF&6TlAndA$;A}Pv4RHMO zJg!XD_^+Aoi``Zx}HA&w?tV+|)=p=rECf$l7W9(vE5iwFlgiliBb#=P3$6pA?4`6IOc^ zmx%`RMLUe`s*8vLn#&cQyl;52q6FvDr01`0;sI^Q<`C^4RmL~U5cVt}QBOEEYBwnU zcB23Q|MW>jK~()u$j;M?H1)R&pi=}$sIZ-4?>j{vJAL6-@2ZlzhJ$}jNm+Z_C@#j^ zhzUy4(HqEP{3Mtt%|I7_2OOb7U?imn*?senM9AU}DA z4j(;_xR{I{g&haQ4=?Hyw$#rtE@z>`Ay*xT1>y8|DAI?Q`Mctye^8$tLQ=b!QTq=1 zFE_4e%+z~&*p4{{-@GArpEn0>1(IR-)KsC|B-7^s^lgQOhVs-mU=4b4(&(bi=r6K& zun?QCdP-MySpZPF+)zci*=$r%?deVi0$kt|wZ<$MN$ zI)f9@IU7G*E)Wl(3~VAREi3WOsU>CTxkbLIwbd7hyZjJib91xT6F%S4(yS*kNz%sz zJN$N)cB`l?6YuS?@`?%v@VIa+o>Rb|h`}XebS5L89g}h3Y2fHNbcs?nmj?VQ!0dO1!dgY-sxtpD% z_jFnW2Cf!C;fZU)V$w6cmJ0j^Bcr}Bzyu!xaOri=f)vkAA8M0M;nv$oP0}oU1>!bNK1bBV^{b{ zKjQdKU&7<&VIr?g9tngpDY~J~;89O@@vzWaR$gJH6_tMSSBR6&lrLskZrkhXZR?gg zDfDf&Z24+ymg1qRD!tg%2`y27p52Oe&{*^r;YE3ZGx9|d)x&{?Q7m`om$EM(aCz4w zeDrf#P1=S$s0;7<;YaKYtqYt7(1spfb*6ktdG+VXQwC@uUYxZ?8k9?e00V&wJp#8g zYB@Xeg6W~BM~}GgnEzcS8MC_~asR($-c$#{|Ga_TvtZ8*>Hq7@n{b`Dcbm75hrgf4 z{|2*rJ^%YkDK4GxWIe@uyJZ&K!!LL^cE&DvIZwuul(%<-Po{cW0X}Yc+^lzZi*S){ zGKQ!<^rwFs72x|m4q=dQ;yrUh(*rZ6ke;4Ch7i{O`7`R`qe?iXhF5@rNPkK(lb5F@ zcP|f5rSJI&2%AYyPZS9z=#anI>_*ublW=E2i8MJ~#4A#w`mn`hnaX{Dy9K1OVaVYCG8S&}9&M=RNZKT&nZO%hZe$c7eoiPnn=6WMJ?WWuo2vWDVHNk=(7eQ;!v%@~pI^+^Q?9q}x0K*kbMNqGjQZNd`V^!|Cl-(Kl0ee!@s8vcZ$qV4Pv$gw49_cK7R2)oLkT z)6d_qNtGLx=nq9|Z@(!?4F>HnLBS_?&^cJ3WdWG6foogYFu=(l7C`tUjyizTSXo7h z)znmo{#d}txAL+QtCpU@_sQ9z&jN2@Nrk83Z7nF^)+o^%3%|uh(&0pCd7M_uFATX{ zCFP&DpYr3KI`Zy%7*E=bw$13#3a^0FD|C_w>-C3jED^!0rCR3N-1qp4-?sTa*VJB|1VY)~c?n(KSM_Lx@=;2SjbMtn~&rzF7hbdHkL;Lo$f}BoUv0|CEwV*euElVp! zj(qc1I^Wif*4|ua4VyQJrV6dBvX3=1v|2-bt8tp4t1IZFrKR0AuGwmBb#-PP+r>wU zZD&D+wRDtN%Z_r}kw;s$s|M6jdGqb&f0o)#t~#1pW_LDhkEk- zWKl3dA``(k~?`7-JZ0U(3}bTkAj!U%SWD+m2!cr zH^c66GvKKx4JU~toa_!s+LLGw)4@Dyn}{d#%{eiJwSW!}9V5__1ea;dCdYNrSFsl1R` z{CmChL;7Fx^hI9e8TC8pwOO(WX;Y{8wr5-g4ZRhp|8p{!XQ5~;u6M7nN{s_W#ifEW zfBNa+JT_^@0wppJ{fLbdAwR0@&PxL)elR9|(g!n7QJwdzJ;>|+6((tq)Ofq-rxr{4 zq}majP)`Mf-@1IDu(T7hn$P=+ua;F*`ezaqC^inL-?N~^N%?3=y&L3s}J0^{nP<~i5Ci;Xw-{eQ!^k1Yy zzX`l`gYzJQq;6^lp3Yl8t#>{$wrqT6T#m)sIPi$xjLywFH)0`IjUPYW1`i(Mw_-Ik)LVW1 zc25UX6Q2!;+`t8HocF;e!Mlw2Px_?tOXV_5w5Mo7@4L4d##`I}y|szh3D9nDPU3&m z{QVyH4;bpe01G~xx%rcZgVA*lZ1IH7V(@f(#xKH>)-Hm^TLJ?{2;)9*$Snqz5T-po zVLY8E8xZcwBNbTEF!(3=k(Lj(sap~b0Y0^Rz6|6ZKGKMC>E(yH3%Cn}b!qfI0t#nM4FTFF}CpgtH5PI2_!J;pV zzW~Ys$^`X7C@GZ?fq>!oqAawJKLcCoK%sw*KT3#uHh#ewZHT}?hYkf@?Lix5;ok>U z#UnfuW4=hMrz>dc{G6VM6TS#&ahf8S3lnw`*Ofmp3l~_N=7P?Aa)7j)K_uz&L{S2; zd;S50i*iNyU@Vc2D}M=uf1;2mJOesHTS-~Dm}{B*%|G(q)Y$BGZ_snas@1k}^Hx3A zYOn|eoc8g)#ZQs2`-F?v3Hp*-7rUr~#{8RC$zTG)6L#nSaU)ztc+tBa;ZG2yL;FG7 zL=GBOejYx;rjVxP<@5HEoBl<4!hLt4#^03(v=ELd#Jel59!39f);oFQsMP%Z9rM4- z&{Em(f7Sf&sKft`Qv7$C>>B>{TK@eIf6HXY{;#F*KVkmoN|}z)KHlo*W3(XT6UNn) zXKUPmk2^mX_&7tDUBP*~(v0yt;>uM|#tJ=2Q{ZEzhl{X;L#gobM0IvHFGv*`-cvh< zaGsXp=_S(kCu2k8BMW~XCY~uoehRJOCBW0hwPNY7k?##rHg9G zXcpy=EtPYactI|T1;ey1grr=QIVlf7JyP&`?B*t53=TOX1;V5dVKVsfciJYN?&f(V z=_GbaoVqdCQhwraQwVam%cN=ggx|fay8|+j(@d0wi6WmgWx_~qK6xd)VM6YcJ2Diq zlH?SZ>lDuG=k7r-$W1Pv$xixF_v|p;@p#gn-d1V@6RQX5n^b&u$ z>wkh9>QDPe+mWW{BbhMji6XtziX}gDViVw$XPJ~`PX8(+S3udoNeMXh+t}FX`IMEG zT6I;mPqdSFb90N!sVLONlCN1rcKw~Yqtq%-CiuJ@a*uD;CX?fo9XZNLF_o+Z*cCSV zi|B#0B*QvB9p9l>h2Eg2>YKqo?X713cmqd?pWf5<;~iXvdxVYtoy6s-yrZv%j2MfB zk(c*Vp7>|Mo-&j(=$U#)8C99kZ<3QRTzTl<(33pQhRlizwM%KaZu)F2jMzV zIj{@gzp1JI!AUzmrN%YS09Z>a;^NV=7aT+PSJEU;3Qrs*Dpn zK^j1n?8B291%P?81>R9`i1{ z_e*$*_)Tnz2%SFqNR%Nq4-0&9THze%2SFEM~c?a)l z+O#|LBHZgqd7PKvt~T*Sc+p3s$&)sUGIn-}4xmKBD<(hJ?a3!igLrxd?}sIHw|%Ow zbFw$eCK^%QT$fiEu1RMDfiHZ!zrqogF%vh!LYqGBMc&Y6#K%ACiQgVG;u#^2$dD|w ztGZA>#*COlDsW(O7y}Ln&jd2xB4_Mz`2|nm*niFwV&NAa2Ed1y^hJM%l?A=XD6FE% zEpZ3$@^c!XZS)Mhceg>bXVMmmMLeGyAPu>teJ#QY{9QPAx={??({M@JZihzI20q{7 z3s>zi49VP&RdKi-A)Qn5@B{_F(2kxg_L5IaTim2T{Cwfl zC&&whR{;xn@H6Pq7krTo!MDa7a4IiPi^TcS9xVPA;qRWpDn)e!dFF0U)AXl9;52x$ z@WPY&;O9?p6z$?b7@kQQ`g0R$CUul0JI%iZkq>m2l!LgmrKkC3Q1G_|2+1FM@o>xXQ{ZpVOpmysS#t`?~0Y@xpK7 z5G^?$@cJq(GF5V!dL^ac$tlzxPeq>2H1m1o-LHJ8tkg_lKWTyZ^feT>GEnKI51)q?$$ePxTG( z-l=xTw6_AX*vI$BdFF{96id!5si@L$T`Dj7v$ULau*6{Z_i)$$BwVyjb{VrFcqot*op>HQSA0W#0(bF# z7J6Cq=R|&i^bAhrGbY5z=CsV7fYK5bDZ!ut928v^-$2B;OxYu-+a2%NaUh zGU)+64v0y>BgoqqiS?8m(V4sz9+`!5h29((Qi?t`rz0oh})kFY)vDjot~W^fSS2eJhY1`3EK z(!!n%AtZY^1ZMfuX=t<uY`>^nt7tkkPRZmsP*t-g_~$?~nLs)to*&|xw_ zg>*%bO`sh6?@;HX6Vch7f%Alk${_giEnlvp!;Re?6&2+!K)V2>vio;})#>OU-sX`p_0rA*-#f`2RmyE{sN z?CFGBW^ork0eB8K+88^Fr@<&9??@AOuan$T1vr#d>MB1^Cm4~Zr@}`4fv_{VQsURG z6#7oWiF-}5QDeq9z8S!_*EhJZ)&_lbiB1$LlupWmVw!~)r}ubw9Lf$|u)BzIA{Z!Z zm6bLLT5)BSIJA`<_3*gC<6wG(@1|d`qqi$8vpaldfK{5Qe|DKtJb50@ynB2v=sV^e^NxAPykq`Brc0Pyq2BIdWv=sdU^ZFGf#^L_XOP z8{<#{_47KACnFM*F>#^;rOf>q!vryDsjz}{61ci&jqd_?S(q`N2}=(r{D5c2liWM> zOd<7id;g`}vq)B{eMfSu!rJvNEDPyvLN7$Hfr_2#2+({ERCc0=R z7W0^}j&=@eApflJ(2D59FIgVrrrJd?Hc+{ENDSDv~%=% zHJRFt2?Hi9)K|HpGq1$TN-C^KkXKY{Ir!xiSc`P1cCWAS)ULiEU1xhkqcwxiF5y>c z0Z<`?&T$gzMG!*U;-Q+kK3M@+zDMJPLHQL9#=GTT^#)$f7*n8NPk2j%qu`I zqpg(=3l8$zxf8nRva;eFtFFwm9u=J6D^!|hRb>TM%0x~b1ifnp$n^*6ng@alMXfJZuxH)Y_Jj&-`xOO$6V-EwJb7C8S zhY()=l#~AKecH=Fee}f5^AGnZQ`89>B~Lc*`e|RaKi}qE_}X0cGwGDAE!NstZ)Jt~ z)~jc=_2^M!CB>p2_3y2l8=w9zZ;Hf^+)#;w-aSZA%xt+r+323xUgnSXnZD|)@o)Ezoi zH)H`Ul?%LGyzN+Ir|rNoxD$?&u?swU`_d-fPKnO!ZqRhXZvDyH|h9yiOECuw7tEpp);kO(rKC& z{LN)2@^wGz1RdyI?p`we&HJy3&9=nRtb_ zFfO@_BYc1t5W|M7So9TRAr0^#KjM*=&jraZCh{4PLJtobiLgF@K$`O7={Url8y8f^ z;0LO&!ue;fzzbpYjJ_{_cT4yQX_1cp#aKcZ0c}pW6i8EX9nYR0IE}p0w(~{01e}g& z4+rQisiW}1{3bFX{hzpO7-HOo*SEF^xcWAs1*iSAp6;f4itn_waI#oDS!uG^8w&Wu_lM`=WR7MEE$JA2MieZh?824xYr+)7F-tW3DzWN=Y&iOZ`l zZ~8_lf%-S~P&e{=XZW)6ak}%qK_88N`hVI8*BPDEU;Hm);34o?+8DkB?&aWZ=eM)S ztyOK%f?P*K=NDLES-BMmw>#Ait-@!Uoc-jlQjSHy6cW1i>?8lA6iFduPsY2n&eo4H{Z#R?G8T^0pFPy_YHJ-LZ zVi6xr@#efjZrS+scZbvtx1|Iz2GEC+QfI*9yPZ-bZuG^s00rj%9tb_6Ir*ZC+nhTPINNN^m{ z^$wj97CxHliqeJHkWk7-a9^8)l2m$RNc8Iy1ALn(4AD>b!cSC0>73TUKR%#%gf4a*sx(%TU#r> z*5-AFpRo{3xmhP8T*xu-CyfMp_qysm<^p0)#_KLTI8RQ%WhEL8AIDeVDg&wIuNb`2 zh2IqZl_syey!b#UEJAVxElGo~Ps35u2KHCxn{>alEJCad_$<178{dH;CAu zau1t3hMT|8d1xHMgc}5e8-q)PNjpapkAKR8B4bVcFz%nE>1h)Ndy=O2HN8R#r5g0c z?t6$09=ErYH!1oJ+mdu5?*Mm@d)PfK;`1)MyAdw2(PKiq zIgIN)@-sq(9wK}Vtjfa$H-tcT4vFAl7<59e4;B|u-g(w4p_J>Ta`K98aR1)wbTEQ0 ztKVMdlN21S_iswM!lE+3bc7q<6|Z!-c8tlXl9EE}QC+FdOg1?Z2+FLy907@4j&Y

    9KMZ(xR%1WKuzhchbao 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

    Yq6nC7IWu_Q#>Tlx1wP?Tazd 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 Lco&8rLALKp+Lo9b0rRgJ*NC! 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

    U0!4m+EW7xHNu zYkEp;#C*X32$a>}yx5b#|#Io{VrLd~6MClnp7c#Uh_`HRZc6XfZiHtv zARNYZL|udcWb$E&*HcUu3L z!tR#jAmFu|oALZ$O>}7dH7}9X5B2bojlTl7Nd-JK{yv0<@DM)LkTd0+@%u@(dcH4+ zIBpdOqyF|Q*<&J>2L&+d2fXo^zMOUO&e0blr`^Mqk2Y&koC=pWP!& z*+7gpKUuh)Jj3?n_jdU+*X-UknZD(@@|wf_{P#j-9st#%dxz) zpm^rI9pL=TRFs$Iea0_oq438rw76KZF@U&g#r&}i8j8X0-u@`Ib;xx_vDg}o4B%>W zn0!irQB*0*i<#zP@|9k-1SyzQjJ_D2aVyJqi(fwruBwoYVb|w0WZ-Mgu)@re#^mIr z>z$d6Fqs%!&HO2T@=jR3VapZ_B(t-#Hb&F@C`-u;fRccF(#XGsA+)hdNJ<;Tiz<5g&SX?k>EiRgb0^b0;_+jKd=g( zrmR8Hx3(CKbz9Nf)f&eR^~b5>hvUr2qq+{qaXkwHELbp4vur&^D2(MUf3*vU^2smz&1s?P3))Sbq;J};2rx9z zCooC?;C`AFPFyJuc04N%<=%0oSc#vXI&z`mwn|-JN!7qb5&yj{eZI;F;F!(v1%M65|xk?A3(x6)Xgrqd~kb#Zz7KV zr5B?96KsKcUr@S@11&NA>P;o%R-t&#%6_?dAV|>|4s7MGw=TXqp4Z1?%ijUw`2`uykAKN_N~ zttWo(-@XzfcV?o#p)DF~H{-b{PsQVpo{YKa$$0Vk=i`kZy%jSHi_z59B_69bN-Iok z5$zNmtE*!*3(6!>Z}O=ACnD#ZVyxI;mEYQmX&$r~dN?pRXhSMAv%Fl2(UB2PbQ==S z*3#Y`=PzH6()yOq@$4Nu9G9=(^vXsi=wQei8XAhmmSQX}r`3D4wc`22(~%a&TFxh9 zbxtze7QIq3Dd4KDJYs-Y$2?9kIfdMq0)N?Dm``YZ*!NxPrHvF2$g;1Zcsk-|A^?^C)w)xzMyoQ z23lkCwd*`2ul!Ew=GTu42W9-daN&)3{f+O%?a`}}3994hiKD_Z#;6%TUQ#N ziJi3M^juR%Lny4$;EgVJ7=DS9^fJ^I&Cs}6qi`Z*7}FqV)#5R^_p=X?o7vTe)|vOJFmYRlIo(dYbbv3_PLmm z+(}(?jw-ttjE{~+S65G*eB=@NR>gn&xBgZfJ9gZ4|NU296|LHev9U49Q_JRAOUq?X zNSv5T#}v&-2CNq^%-QA_FR`L{LUP}9HUYOrVV7wsrI~0-l4=sDr1s;wAMg&K@7~Yl z0Kbg`_zJp2Qn|juIJTiG7Ow2*PzbDhzU$~{cX%dWdXOS*J(GmP>BsSAydVCiZFo9> zfKT)ST!a5Jo)J)hKgJ_u6nIJV>$;|VWMT0mte#mhs7KWylaKUHv>Uu*{9zke^X{af zD=6xCxhhPx#zTn)ikq>Ecal9!x+O=5&#e0T--u}G!{cB)(GRRu&hdv@jnn%`G6jx5ZyxUWswZ7xcyc0eF;x^(DEyh8_i( z4jl|~Bx5)`vau5zeH1+o0n@}?H=)0ySE7T!5Q(9UcgUyE10R{Bcs*fWh{iKp@q3d0 ziufk=5wz;o+5K}sb^|MSFW@iW%xC@pv{bVKk!w)4>|lrgso z85GcGyuwy-=Y5O!xJ|_a4WL}9e?e;{lj$2K9TXJ4QGKkbjxERQBJi76JakadXXRr=8wq{!}nxO^Qq|yQdA9I1UZ=7!3~TJ#sV?#_&TA>GH@w z=Qr6g(DJu%2>pYPcN6{=B?~hSp>N6C)?1@14(b}+4?H`#4G#T5>(`@HqyBQhKq+s` zZpBwms7$UG)rYR;0~kMCYgACW^Dh-vai8Avyi?^n@X+}C5FWxq_|!tqoUb1Fa;(ce zDEv47(W&_6lU?yU?@nhv9}JuU9BYeFJAcE^iHIHyAQl`1Ls_gzit?Pi^OFQi4fb~# ze|2rR+xW`>&(#bOgFaUVcm@bL59kbz*>mof-)G6)7xH#Wf>sicD&em8nFDf#BA49H z+wJO_3yp#9mBv~ul~C5Fl@=&8SRGd1(CBkgyq&c2 z(kWrQx|XxrV3J{g*&1vk=I7>YD23UgZD35-Ru+}!oboO~YkSix5z|atwoh4AUP{UM zrMMR6)2a~|r}_DLRf)W6OjV;8S>mT&s8PPbs7hN~P!MAVb2UF- zip5eXN@BLCS8y5@-79SM$0}fi7??g<1^h|nPg^v@7_v=su_&fa{cuKt&aCprHaLW* zPatHFHcVlY7#dbiuc*F^lQgUHV`1NrW>jMQ#h^?(lP3&jo)xHeT3lH4H@w5~EzF_~ z%Zd;tob!)aZS57}x`&ZQdHIgY^4{9rD_;*1I0Lv@ZF0D&#ra760)}!2qj#XPFQvYg z`ePn6@9TLv|HVJ~-ht4%8Lwj51@pRlz*!(8sfkiseE<-YJlcq>a#P<8YDZT3+K({$ zvv8&N7H(=_x``Vh08ojA>+}Ow>DG!7$Fbd*SIAdy`E03Y9vzOueVuXYn687pQRJ|n z^_5s&n2pl>Of1e!#r*VS%ui0loba(+T2fzL3eJ2)VaJwGtiEg%9cRU6Q-f%CY{cTS z(iUDN0atmG(1K!}!XeyxqJr{IN$4B75J%m3hP!c?c0{R@=py03Ph1iZ(~2-=#=5@L zKM;0||5;rVe}0!=iErmEl?^Cw)Uz_>cpbOmLRmnbiN}J!ZW)X6HcS%}lF&{#g7c=b zjk)J9hn+O{LWaY4L&DcQzI2t#qD%3TgA`{TH`m-RzogH0zqNo?5ypbDzXJ#d^&&15 zg%bEh=fN)oX#Ak_iEdU!tAx$grh@R4)#SCpiDE`;p<6XEw@~uxKWG){aAqLNXZjFy zyx81i8jGRW8AaOrRHk;QXFK=HGr4*u`4?(Fp~+dALtxAC^X* zFQTL0WzQe{8E<#P?eMK!6;b{cm+(*Y5gISNX9A57II4uVO!e9*Eyu{U>oI!mTDo{Xh<1lpG6Kmwx)6?Vn zm|vKS>FKFh7H>hE!$*$A#Oz|sm)2rzdOk|48`0X;8@KO_1!sM;lM99gXu#b3qUg40 zhj^paHTv{sG&eKOi!WJM9VmSih|pXn2AcO%9kGfR{tu#h7wfUEzCS*CM|38{@2adS$C*bTje-7t8x+kZ`a>XyN@3Trgi&)ve7F#*Y^{oa~PG^7gwVsI!CT|Nm*Bok4`7^tEyE#6u(m?4&^bCzLXPkX_?2K>Zi^t@3~@F;30c9 z$WLL}zMfT$7=KZD`$~VYzrx_m{xIpZPPC{b+E5(>1HJKA|MUMWjvgJ3vSi4CzTWuu zZ~vQ^S6j^98j0!gJJH|O7@vLqbbS5GFU04bel*q>W}+Y-^5WTdk>LHx$=elOlS zFBw#^AAjtLxP0?YOwTQv4;&sEv|P#rkS~Av%i>YS;<@LamwUm6-e39qzY;(H^FJTo zfAuxVW3#a+*$bKN_Q-9~zxn7A-8=XG`>`UPgKfQMMLUpZk)1FEQ4!P?yW1qbRV5W2 zPyA?OzDabOGLcba0F|*ePfPb0 zcr!z7O)Y$UF<0^n=eF0?DULdoQQwL5`#zm3D*TqKsY^!RTHV*yEC1pxDPL2g z>fxzB9UG^9kpvzHKB}&+s--v9mS}RNb=e6vBPor*b%v7@y_L`1EF<4E5_e#^(A(f zx+z}h?H~To=gzJzm%Z~9=VZgX%rCNQn)smRV)XS7c)~tB64|$*R(+H{#Dp<)Ag!&f zE*pygXczd6oVK~h`r$hp>%@D|hd3h4@}Urz6_w7L`ZFsn;bl3G9UcOnh5ipe!o(kp zo!)6deZZ?g6%T3Ce{#bwybiJ~^n?5{`HcRF{s`WK$tKKQ%_my$z3H~&fR00>m2th_ zCf|w+!*`9w809$iH~Op`hF^6ZpW)l6vK7_$i=w-%_AM6J-K)+MdJE_s)bZHvIqf#4 zdp)NW%*1MPVA|1)kz0IM($%DVq0jR9zT&OC+E@3vuGhOkDy;RvN{6kF(WBuw3XrSy zi*k9K)DzD1gEHd}&!u*yZP5!*1vu&=_a_{6m2}JKQ4}Zd^k=z01Nx{d7aB!6)U%$5 zi|_4-kGkf)o!)a*U4j>`5JgG84bVh|q1`srCeTXqPI;5=RAYtkls2{j-?BiO)J`}6 z-6OccS=F!&j3xA6zJuRjoF@(P?YdMs^Zd~_E;T<9SBg(Lt_OjSO6#VVx1+TXak4wr zD|yLXsy!akoqzpe_ddPnIn{n8{LC7EAtW?XuAF=b58)yF`w8^*m1q8PY}XevpAU!s z{kM)re_J8`$5%!(pAU!ark<#~{s)O@W(4yf0MXKhzmFMbPV2nwGfb46x2aLgW>7TH zRT_V58!-MR!!H9C?{i}>gBJ`}8n|IHQdvD{eAu3CTC)7JT}C*V)SJT*_Ni3n7A`7q5Dvre)Mr~!7M&Q zZI_IJ6boe>xPu~rvrpE_rC47nNub7vydF(z>w<(lj8JS5xLRJ0#f4JL&MkQ6H0RAR zTb^?t8=8t@iVD%wKNyWo&C%N48P$a*Ge&7E*2LUUq2LI(gHeiAvQ2ejqE?q;UBVq{ zl$Peb0t}@eOfSj?Z!^0hVP70n$>;7?nR#LxXe(?~AQ-&XmZAj*wtDuraxi7!A}fDc z@r%+ECJe?B#;m2a!&?QSBp|Qopkdy@X*G;-g>4iO45)Vu!T1CC7sNR8ZCh)*XYQe7 zn3|rn@s>00%3}Uu_E;r{G1s$URY%kV?_iK%7|mR&EodL`0igz_lW$;-3u3@I_l|nx z8@5l(aft7zWBfV$*i5R*o%(3K4cBbXsvz<0<@s1a5cvth)Y@u%p{qaTjXbIy_QP>2 zr!s%?PeXb|g8cI5O8Do$_T2-abu;^{{M`%o`v~dm2pAb1r2eafOsu9eJyB7>N7se& zLDUE%761`y@Q}ZasKWQ^*a*&!s@|5sxwR6VEsZwzK7R689PVq2MoEDv<5rg?JdcmX z%+!RpMrQ)Viu~4uXW$k66r5y*B`dF3AddhZ2;6LS}jMPuQb##h0(a+ScNHx*Y zy=|Y`!?!z-D?oF4ou7S1+Rz^2Cp|0f+y>Cn)CLKd%prfp0T7Rk&{;y2Ik+#*?d!km zcMl#bJaO^IJN_zy?*Q)szxRKN!{1fh``_{THo4?&d}D0G@as5KKHlNoB>KY2aJCC$ zg?eXei>hDkXj;W;sLdFkm{GfKnx>*4XM5Tf(J_<>oJoaZr&{=fVxgXu9ZH0q9hybo zzy}mGv;%Y&oXTh5+vvN&%5o+Kz;EbTS7JaQ-awHeoVDSlj$IC#JzJgkC?zRB<;Y9S zIEII7CI8X?;XnUe)HbKx7k*Mu=qbkJcdlknfO6@)-3`vxJwQIQ*37TjZ)cHh@eY92 zeSq;7)Wq>a-J%5X+q;76NBFS|%BRBZEhOLXeD|>+|CpGl!}~<`QPXhQ1p09v_XYgZ zJAOT8$@!}C=5KMLF!qOLG4Trn2-^?0p{NkvHc&S!>(L{AV5qY%`n&t$*zjR*d)V94 z6?5}*@%B6K#9Qya8(n=p@x)V4L{C#ql;@_s5*9_KnzoY0S`gFgAK8CN#E*Kq$Wj z(S(u>vwc0?D#N-BJr^!rj*-zZ?>tj2euwk>Jh4xW#aLj)upP=^R*!IYWLiN)i*D(P z5?S8f<`bhAIFq+AkBkZIT|uqxLPejb^xlC=PiH1wEByVm`}l#de}71MI4(L@_YEYM}4ic ztHa|5XGPz>c}u)gS-2v;S@?`Gf_5ewLKVpu>~4fXIJFUYVCyZ0-;7S;=>O^h4g}8B z=s|3o@JN0Fs5*aeD0soOQG4(%$X;HZr2!dS<9l$CV`?;7#(G9~iC*1A{7rS*iq@H37wkY~={ z{^A$E5GRfwi{JhBx8vP+&PGxF|HnW2VVaC9UZA(7C7yobc$|KuKVE$LczouW6QY^r zs23k`<^2os`m1lm*|*Qfc)2Q$ojDWjJ$=zC_oE-5jn=ld`07`GF0Nm>V&m`06DQ)* z<;(GNzwkB7Y#8>TcbwXaQF{{!~@-{Xi^@uzQvhqY<) zpKhHG47_ZCTwjpCoTPj8Pw|cI&C%7{p}yD^?d>hFs|`jk(%r4~aT)^5pS2G&B%TKlymP^wNvbJ1`WV`QjJj)S1&h4z2IdP!v1bqPe{_ zS~}aJRj%048qIAjQEV&5Yd^YiAhhmh!T3w+9Luw^v=ndt@QoN355ewnOo&FFfJb5H z5DdQDf^qR3h z$%Pn`*DUiPx5Bfqdb6y&aAX9lenEH)pBOo9I28{AzB9>>-ei4}CqE=P6S~4N9MBJp zp72@b!4$72x>5%5QiP{Z^PAIp=NuZN_*H;Jo0SILj5B%jNj{#8tH2n3C2dD*lW3jf zwpLtIAzH*6;W#qK#$O?8V}Tu=Fb1>Q7vnFhbXh2&a_L$xKV);t2yaGaNXJIsVzb&p z{A5#;>)hKs)7Mo#R=HZQBtFh(0J9=kWlp*#)v4k)Em2tNfpY6d|8iLzv?pQk^Q1g| zlVtJ~&S{Y^IqHKt=RVh!cmlnyd_g^`^5hsJ)0pZN!YUKxAzC}aazlUS69E_Qleb(dZbNM*5ZftQozWFHQi0V}NOJf6Xz)uy#|CB7XjXkpa z^q%M4dddOg?Zsd6KltR!S@def9dmszJ4U*Z+$UpXD>(f z@|2%H2~n&BnEOvkWTADe{B;caNik_q!uY2_i~%2^g7Y$9a#{I{B8S1=PW~`cX;8;F znFa^1degI+9XakjXk;!Q^z!@4ca<&=15jQwdVcy~K!{IQeI*8q@6sOwZBq0nMiE0n zrijL&EFulje_hgdnZpoAUh*>K&nbUduJnzCE4x&#{mPdEiUNPFD~v%N6VE8a8IWOk zl&xqf7Nft9v(TEn5_WE8&UtQcZHuNtQ?xX<#@70F92z(#;c7S<#O>%Y=aV8F|REzdJ96%_(fSVEx~ziZYh>ZE3qkol&zlo2M@*3 zlc(a)v11avJIv5y@I-OQmZ7y)4kqI*$_tpR($a#N(`{yBDlZeGx1&~hVb(I|KVqc9 zpv!r5<4V3in&5%$5u22D@QTN zV$|@KPO1h~Ta*ItJ6f&xq&3_V5?&kEdRMQ(j8a)z$j zsn}9iGlzuZ8R5jnI)$fyfw|->|CaA^#xn^> z@>^N8K!G0yUr*ksRXMh*;-=d9t<@#B|0jXx`cK7Q|J?s9-WtCYOKW!BnC zbQckiuZOE4QwxWQ%l-;hv9o8~kE zs)avz3j!K1bk9s*XbpYcf|=wGVYl2yG#6^(_~C(g_K8#R$k9Rd*OgdWn2*srV{vD6 z)Z5k}M6aX7T-R8@imVNF=WXHAR!yvJSL>;K%t|joz-e zjxE`0ly~K2U5-4XMq;KbeSs_fxnM=PED*WIl49LsfWEY`Pwx=ksFQSF8bwc641@F| z6#sx}Zx#>V-v!j`9zW+ncupN6h@&Sn?&y#FbI*6Yr%%uVJUfhTapcMA*+0?#obRtp z?Y=m-uYaQNPM=sDk$&XoxU)~lCz(ifw+C`Be_k0!x)^lNx8#Bl!1U`(`VO(CiIvuOi%b5>toZVJ}^LZc0-&KU^ zZ24ryUx50WUR4{q{&D!`@nv-eKj7D35;yqTgSWok^(TA~h0v9I!f^Gk{_ciUniS?k z9r)=qQ-16+sJP7@?(+FSaNiL)cP`6*pt|ro@plB%AJ=rBgJM!a;Tbq*7xdc{&(z(~ zE?#ReZe70~&p!58%ukF)&H8e@@Z{rh{$)FM z_!)L)@kAT-AE@@G_*(NT;+{fkHKIoM)*6%mlg44 z9Nj_vG&Cii6J87+3;M#gmuZz46MDqQs9um6z$fBo>qK}HcpCaYE0)u)DvXzj$3l@u zzXt^vGnkmPBtCIrepWOHo^w%Q^)2*X2@s}5d?xL%qI@%kvASkMaipzrYlB6TZbv;s z`xs;4JK>{UAL5IkMV{mb$|-LsNNI13)zGebNnLV7Z>K#UvI?xEJwqLXA-`1 zTm|5=krkCKt+*2Y=#|hr@zcUt%8l$|`rt|s27sIT%!Xg%KpKz12l^_sgFkWVa*9_k zQRt^_l#_#==D3RScZ~=HTy~7V9llcFnL(QB#d>g zd?i9t`RpD4?$|0jbO1lD>fr9|b~ePilnckb|Fa-Kmsq?d^%4s_u*j`g1*J zE{EiMFHpyc2TZUZj^}=rVe|N*hhTW!hHp6KpwjZ=>vi*J1E>+!X(e>J}P)vstQd?`Nv zg_mv6ec{Dts0j~8EhE?#``xp?9EXX2TspN^;Go_y-5c>IZ{;<3k{h?A#I#!SQU z_|04G%HV^;$I;bQH@3yf*!kF)yX`(swKmjO#o^(hXi+^34GzTN!-t~x(9wA0%o!ht z&`@l)+fv|y>ZVS0gsV|~u~>r1+uwQR;(^e*Pm}RC$8IP{B|sL@CCyJy#jCG;FSgW= z*2*ie5#c|^Gjlc3Bq$qS9xL z%#wZAlkA6HlH({64}iRxR&ZjlMb3fZWALT_`zl@nJqu@r(+$XnSJp$1#WT>a;BAoS z0puNwzR(T)nD|OxrH#Eyi!#HGaO`|%W2oy0`XX8kBdNS3YU=K39xd%;r@kv+=sP>$ z6~HO^HRv9BtyMV1ieC)AKI@l0iQ$*ALE+N2&&hC&qif&*fDe z)+ZPBMs^qv%oWhgdESg%b)Xi`#t9l zsJ!L_eh!tw756v>YG1Qgxj=_Mf}98XEDSC|y62Ir)5>1u&nf?Rmr1$0H}Cw3qqxiO z1Dw8gI^5@1;v|nYsAu=>?QPN1)g?i7J*GK}SAuL&0%2WEeKZytqpjE$+Z)@_)6pA; zhL4Kzl%PaD5FVB9WcXDXB{0I!R&A|G&RdDK#kr_PAyz9~DlNvH+t=gr#S6OLiVM2l zx^+v8ZF97=v_)q}j|6AsLHXHGJ_}97=^h8|2o4AdO5BP-l$aPXRDlw{8f^fcnwb^zFM(E!E5=|Hhl);&ZkkofjB)!bP7DyN zz=a`0i14;R@^4f;Z1IBt13s{7k#DD`XJ|be(cm2>CMF%8m1|tR>RL^J0+sK)Ws&NJ zHqN)P=6i$`&lc2s483eU&Dm4*IdGBi)CY!S!sdRtpj4JWMr5_Lx8!Cu_LflfosH!f z-TY)*v7jXU@4o(D`u_j<_HX*SA2dtgIn&zV{G|Soy{LeD`KyGVzN4aqufF;@KE1}@ z?1%cM4e6`kMs2l(C-n!)&oe>*MoON|WGlRBlft81LTN9OtG==k_0`+a-`yThJ$@=4 zKXuG!s?Lm$#Hjk_{6Z-fN@e5j+WJhfmb%Fbg#aJ(O1u_n^jSkEV82axV0_b zD?HyIAghfewRoi${RIstXRT64Z25_3x-8sAD57i@&~%TGQY}Z@E>fhoUyiT#e|8 z8pe6$J#YPSDgeW82Kl!i{^!ojcm9?(P4Q=u`n_M}nS21qvSXljozgz_X@f>0ZKh$U z`60tN{A}RS!&a5>xvtLU;ATU6Ti_An`;|!?cC+S#Q4$+&&BWl{8cT^~cF0hvV|q>v8qQNKDQz z#j&XM zkX;^7r?rS5VD$}!A|56Op~T1FIXN}yl^>(xz0|SAH;|_4K;_0LwY34?wI;rwp+jTJ zhWh3f+an4741^ymA%?=lNZu)_%~wGN;XSKzNW+M}gX~H? z!{MZS%>8xU!R{Hq$xUkhNGsTJuZwc z#5)(R#qF_4Ptg0^=U$G^&UVYCtSrX3(caz>Z~pklas1RtZwH%JqSnOCTen?DtLv+A z?)-Vnk?`KLlFwMJwzRx#z5?ULqGUZAS5>zg;#C>ekgYIseC=yriz`>IWPBl&>Z-g8 z@Y=`QycTs>iP!t#_}(x8PdKoG)r-(1+65VtGi8@K3Q2FF@4fA9-nzA`tJC$<(b3`E zz5jg>zUc4oivbLlM~35=>h6ffn!dgs(^5sN^izVC*Hy25JsolS^ds@uW2Y5Y zr;WXB?XA(Hc>DT$qqnzP>9qN%rN#z!vBEG^tu))?=+Q$lFwh;t!vpd76OYF8&p#DE z|J5(WvoE|5$4-#;a2!2$B!&+kib0KghldZvp+ked9~dC7z0u!0pfviTtGica>QdSr z>dUS18<*?i?a{=~KPY@$UENlBKFT-VFl}IXXlkr?f9+H~U|cI=`0DEQZWGJmM^}YA ziz{Wz*&D*wO}dpjEp!1t2*P*2d*MK6U2gnM{e6G;(*nkJ`U?g`CeV;JlX&SBH6orr z`oU{)`}#E-J3WzVUA&BVly&hfoW;%reHIb4sC_ZYavaR&X41Xv^dZHDA&@g@+0B7T z?*Il$$Q-f(Mmr|Dd$NY|Wc{T4Y}k}T|H9E&#D^SFtvx*_-p^fByYlqTk>ZiE*& z#uCO2{E%9AuJWrFJ!?dUW5R|i0mE-gLqW1Zv*ouI^-FeOLVg1$*@3A^d2SMp_$l&`})I)jl)wm9)E8lYNZX z;uXER(k_WE>X&!WW_VEAROQKa#JNrZx!qA|%(a17-;lQJi1*0x)Dv;Zfpg##@8H=} zUiG~b);+QL9{mL0%E=2Fmjmh3)=pSJJE4!@(UTjM4!Q!;OM2K^j~j$bIt1!39m_^O z%Iv7Nz9zgB@1T13gh$1No|dq6@@I@HFPB`O>*Ax?W*q(8+`@wD96fs)i>?))jOn_5 z=j%b?PO- z2>*TpeSPiZpGar&eh3VAHpBueVFVwS$T9-d-FhVv&QCxTD*+(@A`5)fI4f!0e#T!0 zN({X)2etJY%ow~1Vsz}sK$e7se3ljrl8vJbs=D_KeC5eZLFV#j-tYC}y4QJ7$wn6E zFJ;nTVYb2nFbO;NE=n>0q}669pSe$d$ryuwa+EpyRFL1N1oOP+ik;nj=gb88<30Xd z$v@*q<#m6jFVbIDR<1CLvYh6s!MpSdfP_woiHR}>uHdeef&*e++$Jm{bWJFb7jvqe} zPd@!r6dIevKh;QBUY4M<8SPzN(bC!J6&E$ag|?1P321F*l9(Bo7-IoSKr|@2u9O!o zOqJ&6Rrjl6W-(Tx+%Ne&rWOhCFxxOjY+r1~TWQ@Hy<_EMLt~n`jic=V>V`CVCLRO> zj9UvOX8(r`z{};8m|t2F&NfJx?e#qjKP!|mP=FK6)P&)MiD$b~j99776K)GbjMoS# zgr$rqTR{<+Jd~SkOSY)EnF+}3NtiE}AJ9mO0PfmQm%R&U0L& z?ZE-ug2E$&5H1JeLf9b<%1;`sv{_R;oHc_&6yq;vGgE(WY%RtjZSgT7R}zjcO~?P~ z`@iDr{eX6Pu|vYKn90-^oz6w`%pR0C^zrgIJsLP*-@t5eyGWQvn zR_K}xU=r%orZCvh8hGr~{|T39017^|jT>vF= ztr0EZOvClE`he=3v(B1}Em2f|r0=l$(n6YmJTo4!4VK$Lv<=)tIS(y`uG1HiK{y%o z*rJ`V)CUFxL|iLc^WTBpSg4OY9`cmqWR~dN&j0#xko=l%cYzSp zYxd+T0&=>dl!L~k?YL9>fn#kF;F~1mZ?21Otgrfe&k&cu3r=hb8(9fhF0t(;#-)M; zu_pO)#+=4~MaArKaFy@bsewraYr->VB{S(47MESOi1gq9V=jtf=xa?4lUOo;@I)EL zttrh^C8(#%kh(#v44w0;!?~zIobb@_t*w^6h4NEFuCy;$Z_UDAx{fhH%;e%07$sDoA-3BOqcugOfhMfxYtRPipXdd-XjF#fBg!dw|?wjmv z0&OwxBZmTsbK>cnOaSTc>s7x+0az8?;@jxc8|&)j>Z@#Zs?o@2VOjyDXXtxbWdeu` zMJlv)4SW>sgs&kSb?Grp_h}4B6VdQzg(UTbk&1UrmV;k`Ke0Rk{a2+zAvotA8bw^> zF&{^$a=zgP-lksEkP-YI0KmAE z!iU5Cq8$9jsVMxE=o~Ql>UHH91@&&u>ACy&-VcY|_zQdzI#*vi8*NS9QN3A=+U<_G zd38SCc=dMt@CR?latgx)g(?vUh8)g2g{Qzk%&`+pNML6qaZJLE+St(ZmfSX`qixA4;?y|n6e0?q z0~j4ph;LW%Rx(+wcrf*CB=S0p(25Vd!u-Up9fdmh2>P#Zu!i#?*Twy*O;mq2{@U84 z{%!*{{cPJbN?kx>?2`HbvJL#(itbm1(vttSXakHYjKSV?IyO{Bp}G2%^6RouKcvf9 zhn(FhUP^LfS7&uBug^twgYwx>8}D8?r#je-V}}pLmp=1++_-o)rf*-0=bw2be&HLR ziO>GrlhM$&9;Lg|dtCJ3tm|J;A@XJb?}v!S*={?V`e!+7e6Cu3%ME^gf( z@z%1`^rC3UqWIa?j*gfWtvmVX>9~3Ow%Z{YAE-YCaX^Z8ltX}@0hSD+*h+4 z8tRE7!*Yk(<8v>biW5iL7W8 zg7A*rxeC$QNu0>N)jk{d@y8$4Sl1JW4-ZCb`=IKrJzCm&qPEbYI>soazFOO)vTOXx z9Pw>wY}jUe5Pi-k9WdeaZ@;?YZAw234nkLl;j;F<-;8E;rDkQNL4B>vq$~Bc*5+o7 zt)dC)#~3Ro#_mW)oAJ?G^V2g5SBkYICe@c?bx~vT(yEP%KYTN7`wV;%T32cO<^SI$ zPz>@$e=!bg42PaEF@Je}E?)cIcVe})tTA4Gk~P^43w&l$>HPen<-YcgPT>Z-yP=;- z24q}bW*aA)n!IH@yhOgblERZN#y#>ux~%#o51#a;E4&NiyLB~+FY!wn>vhjj5$J)^ zj&O;uLZ=1~0PkQ!p=cg*4)Mb~`0Q=*8=T3?H^fOcF;$F#S@mnHxh6J3Begm)u|d04*B#?xe6 zCoGe!h!IG5L>x>oPx{`}7AXr*VbWH-^7A(|s=uMlDJ!wT{-ySYZ_fEu;<2urNigz< z*QPB=1N|3Q>zy+^c{hNo4=&Uwtb6H{Uoc|Ct>kd|wa~P=DpyJH+tg62(f;koSp+EVORlmA`d0 zQ3sQN(HBO<#$PcN1>K{-5o6&QUA`tGnHdHT(z!7>J>$q<J#YP58(fBPpOos>2%Wd4{?1J>S3! zRbKaZoD;=0#gneY4I=~e_V&8ICnv_lP;$;}+9nkPF^pwzmjtrj!Dwl0^?g%AF{;Gu z)euhYf$+5M8I>4)6{m!IgqsbvcV3!}()4IdjNXacH?MoUWoBreIC(OjeeO9M53gOn z5z{ksv9^MNhph%1qJtUUef`nZ*B9MAy=J=6kJuos@~kTzRu_A}G&u~-OA-bo71-!7 zEup=%D0wT;GM=_mqpi?yH~K_W2JFgx1Z@bJne+x7!c! zHa$p>J7Ai^jnWqdF#g#`?W-p<&lck3>jiT9+fd(Q(go`#Y9ve|+_Bn&v(nfapGh*D zySlwzj{2&#I5ylFKmUd2BAk*VN}WF#M|D(f?3h zgO5x;V1*`z0?)#x4k-(Q4;@&K7yu}rsE_-t8GqHyidRu7-|DYSP3UTAjwT5;s}hj6 zB)Hd$-fV6tKwV>IR8F*ta;Fu{lswe{lPxTYDZiva|8d;pMUJhJ>>*l2ddi6v_Au@&Jw6^$`N`g<-)!9Ad2ciZ!Vv~qgBdn`=Qx#juTHeD>O*N2 zIQvO-bz?0Vc$qy8?zM_`Fs@*5soGkNp3XM4=Sr$S3HkHOCDDrNm|0wmrE*EQwi$&+ zXkdfVW?OO$$~A5;lpmZ+2d%2DZxqdE_A?VtR@6_`j;deKkMY3DW8sc4#BIjJ9{L8f zP7xS)jYJfmc7X=U*+4_d6`u5kA)=vWpBuO0Gpmy!f-NR#&!nW^j=?|qc+}J@&5r>e zmDW|MP9}fvVrmh7d~+`(bOR^VR?4?~iEi!m#`Hsu=Z;Tc6v+Wv_rS*AED!wV$r%^3 zyZkNS{!AI{orT~1C^-W$>^yu3D8BoE)92y>u_ufBm z<>TM}@BbfOUBSdJR%HGBSHBu9dcO4D`=*nN<+YfeFU6AR?2VDJnAaFyRV)5LV>VE5%yHi&+j)8`WuG;J#JuGCe(I8raj@Bbr$2_~E~DV}DvLB)X$KGr5i{ z+e|~l*H)8KcTHouB2}9R_();gf0YT-FZ@0PvfiFOeJ~K^T|i+4!++w;PmRu1i|&v9 z+eGIobMAUiw;vfkiSaiF=-kTkl<>VP=4Mvo!ueZq=N5(r$xc1pYTL9M#d4_}m)^gr zcjCw4VFYw*R!~v`+L<;sFQn4tlf=w}5?tA1h!UEJJs_+?nWtc!Vj^qmD^PY1?|PT0 z265;|KpNY^`DFjy5Uy@TcUNm1KXJ%zV5lqFJ2cj+Tg{c!*Ohs42j{?a1fSg~Tu#Pk zMXK+4M~*Q(YcO)UjJqj4##oL8YKrd87U6t*ay{+dlDD_FL$1@SHT(Ly)o+`W*^O9H z<*lgyZHbA6_h#ZL6LzC&Mc;|eJ^5%H8tjXsM-D|tS0PTEIu`BS9Wg2ywQoTFM-N9= zM=@q6N1~^_$%ex}^{2iOFMsyw=;~>TnW>Q|FU&`2b~zfVT4Qyq7=QS~cjMQ8|GP0R zTDP$Rzq=+H*BmRNVbBqd1^W8ezZQf2eahEHlq4ITednDhE1%!|`Zr8x8bo{EJ^M~v zxFB3sJuq2hOmY@-U}~2%{xYHF)Txtk=gz43n6<2Z^u{*|sdj=UfaUpw_QV^ecVMdV zgU|_p8&+ZcVWUSm*oZKKKwPpGk@5knHYRn_`Dc_u(J zVb7Cx3hfHVcDhPeG6p5449F)rKb(eG`RU?`fxMIRHs~4?|K=;=D?dcV1{{R0uDVWR z&e?wyjp|Mf^%3lzfl+&Ib|J>c#w>5&7`Yv1&%Pa_x9^zmy>jt#TzLOtjNW1!^N|>l zyCd1{&aFE!azoEkX`(jpNod`t$@mK{=DIb;O|EWB^_`oSF2uWUy+vb6CS#oE_%CFK zt(XzMVGu`O($UfB_6DC}yr8cDU6Fc%-(W!iJD|Dm(LWTP0Ptn5OZ~(Dpr2vF3%m^8 z=%Z*Wwwgv?XdXgt{8v7pGZ^^Y`4k`eHs}%)mh=7( zuapeGX<-5eJrXAm){R1!T^8y~be#A#en1`IHEjfzW83F^yJif(?97DRR*-8d)QaC^ zwQpmzizXJu1F>~8tMVJz*+smOjlH4|@OYlwCcY;({=(y+Lqun_bB_}~u?rr4=ye)E|A_}m_gvFAauwlHTV`PZUP0do%R6~N zLQ@z~49X{Go=(m(wepkND$z5(p}xVzL?`h}G~3Tko5TR{C)fXy1bU2=F8pCGquU^^ zmV*9+UxZEQ2hOK7sAuRNu2FTyyIh}0*%?ci5Jh;}nRmoa?v{izjlw-9A`my_xz_iU z*n$c85I6{0r>+^ld?t-6lr`1QZrh|9$(}3j?Qg$(;i2*OAv}bK@TrE?(|`KD1Z*$- zCtn&eq2*9@;1{3niO)UK7VnLe;_rQD#C{(LBIbol|9XcQeq5qh38=9Tf}t$du8QwU zgPlhp#mtsNtoY5HSNnS9Z!-QeNO>lf24D}&Fggt08bEl5@s2z(Fy{k$eqZUA`{(z2 z9gtsP4jEVhGn#wuEB!Q1s}$)uH#jf|>&An)g*o3#$Tb6iz>&x2i{S43TiDli*DoI< zvS$yB`8DPHK^&mF>|RWb>JFO0{G}R$0YdZ>_D$Nw^ln!FeomQxh>eJ{lvpZ$*1ss|4ax65NkQtM1u8 z>*}@ZX=|M2l_)JSTTOzU1j<84jzqJBI(c}IX7(foDOUfY$Vb_UDlZ9{!qMfDS1ehT2G^*Q#AvTsXh_>6 z*TtHI#3cz8F!ib;w2!@+>!64G6y5r1Cgao!yg{exy0$-=uhbW9-3Yh_D1*-fJAYimn zVlWF(nRD5ZhB-HgwDL29&8({)z&UW5xRVEp}B*O2lDE`tO2CVVe{fMtQP?kW~$f^F5kgSC4gbBKmPwJj` zrVaS(8GWefB7F|UyZRQZI+>};qzeQpw%wwDt4<@80Ye_bz9nedO`c3Tz%kKAk;)r7 zOD0ra)rn^T>kk^7&Rj?3qwf@iQ2B3y%KHkCH@Tn>pb+K!9n%}Xu|gZg16x10w>Ep*W}h*oc$P%xLTj$rMG2S5}hJNw!J#~6F93-t{`?Im%dOvT-z#)WfxP7^z#T>3`#)WQydQle z;B)6Si=+ZbC8uS?j7=q(IQ@=r>i?|T)Po->TBau zGcmKc?6ZDXx5W3TA1*=kQRbn*RDXkf!ZV=UV$x4-ZNZ9D_%9TZ^eJy!r-HOJ)<%C% zr;SBy`+4}tVfDK@?+C)gH*dMW&Q|TB2aH|NO#yu}@ewMs#w#lk^$w*XE4|zo<nLS+k9?{zO7S9l;5dwvoBT@4DKu~C>{~)01*$1{` z_)k2xFHYxh&~$F(x6eDrl{r@}*nJ#0DC6(U#B|)eJ{z}hElSQ{^>>xVsU}^E8o#<@ zc4jfoy>ltXM^|ENU1N&cjWN#(UbUkq8HuilGjTrngO@VUrUK(V{m*@H_sS|GE2R~u zX%lz>>{Bt~{N$x^P&|)@=s0w!J)V2!(RlWm)A872$K%n{C!(jfQ*u#FOw5&|Tv}F6 zgq!*fqk)aT!gZ5CvPGUe0ZTZnd{pUbTBdjGs#LYT7X5vl@#6DO#?w!qiBpd%jZ-J$ z)X8IUQjY5*CyvG=Cr`wY;X~2Y*{-rwM_Dq+0;?C<&O?d8N7UAC#qr~V@x?E`9M3)b zcs%>;lX2qs;rPtwo{!-phpZoX>ggv{jz^=Ty%@(1_s3&O@9SUvVhjy-$4f6i9j${M zF?0KRG^jk)8{!c*>tl3kDb8NK9slxo|1g%6-sE^mGTo-PFRoXgYiVn-(ec~g{=Fzl zKK#blzb;;4!@C&#!5@AnN-OK}g)e;3t1;=*9Je!a=T6MbNxoBAI5NjOJL%r?Ff>CB zo)#Gn*@=d_tEu#03|B>>>mV#NBp(l`-<-DuzyS7dF z)mLCUSB$lFx@Vm1lDk zqce0{G!m9yVW5f7NNBg|J^cy&h4MQ$JFha-OI}SAm6(jgWFK@9>?ExQ0@`PpWl z>!M`mGP`pvmZG#&iX}bIYs~z6XA^Ee2z+8)o$}mq?jKoS!CA)WUKop*fW!`Jw{A_w z*!Z2eaeYKI=T=<0cquMlysUek@5IRMkr?syPK;szzA+kGOpop8e}(hv2k-*$ z?cgL=aN^C^UWw)T*;t`}G1dzom^d&sH63%}L7=Z}>&-D?=y8w_lH5T5OmdxN13km% z6HhYg=3y}WCOI2G4@B<+_i}?IazaTo6uk^}heNJd7S1gxO>{fZ2Ix0iA18WFy40@v zw`EhwAyhR#>bS&(oD8j}yR%akIw0~$IY^(l*lo>uRX?%3pN%;<_$m53eFjoa383%j z2yFcIieLP;Z3t$Y=T^}^jKAyv*wj=||4yrTp)+2gD}KegAC-}`aW?kq*}7bu!my1z z^^!Yw?t_1-_M{@wAziKWC2qar-bQTo1$Y4TZ)zNcO$K1oK3yp*-|NTq#SeZSC*`0P zu0t?aSK2C3%M1wbcnM>aAsP8YXVbUNAMxwzd*uPTp5#cix317PkIzmENU5an$s1#E z?kifG;Tt<#Hb#cNrZ4jRe=vMfTDPWQ>CZip@X~SsbxS=^fBq*Q z*>lCc{q1)zJT(43gop4DKGm>x>QCI4fK|fn*;UV=fzZ}zkm+cyjpIFy@%_v5@n`<_ z*(}tD!S<)u_*)~!3Zkz8$V`<60+)UmtoUirRSrf2#gLUha{0X#MKB5Zy~rmd z)J72;3>73*iEt&mR>*UY*dvczhyp6hV`UMeBf=LWsqcAASDwAn00E14`jmm0@F$&V$~>iO#$3R>!TjhRW)Fp2{+zDlA7+AYcCYt1m7jCc zV4h$oQ6!*tgxNsggR#MY$2n?j^`#67|HPD4)kjxrcRYFO=_t*uc;#%6pFQl8bv)>gzYtx6D_ z6r9POhLvZEWO@1$~4Fly5MYC@80 zQuTuZ69d?^1k6U2eRXY9%x;qe#--R;RoW^S?F$3Pj8C?#<~z2nMtR!N)otUhjb+Lw z>0v-XxZ@e786)=W?5y*k*sQ>`Qk41?9#ck)*Q+Wc!Zq!Qa*{BMCFMhDx3;#4fv&TE zd4(;jg@X#mxvJbROAzPE*4j2?C?7uOlDw-vF>n!gp@H~A0d6R z6~bfFLOI=ftVr7diJqzs2uqpGX!D(Z6f_FeYti4+5uf|aOEwU{fByZLn3z_3vW@w+ z@K4=2lZJfOj;=g1sUfWZ79CT)sTLK#B6dD;0)jUsT5#kOAz?6h9DXmmeTuLM5 zt1`*_{r-@`rCPG!t1^H~^e5i={3qcMUMSO4B{r0@%K&ZOCVC64ZEF#|Hl3|iq}4Gy zwA8MkC~-X+?kvSk^CsOwrku=)WVa(lpl;#O!`BK&$!Qy5AYfoIH1d{&|_QKCb{m8 z*68c)5%1IF-Be2ADOd%!D1H*Y4*rM9Ic)PvpJU|=ye4B4{f#jUp4!SS(NNAOrCu=f zLQ7Cm(x)*-6vgv(b#z2mXIFG|w0k8PJY1@G=u~a2l+)S0fG3ZtEYM#jm9R>eeB#dv zzg+RdE*9hkh1=NFM2su{D2~UcF#K+Mavk&o#U}h3G7CFt)Yq{RrrML>pg+qQFUl6s z?6|@XD;TMneF%?6dR9`awkaPglRa@ybwOArOcrzgj(V2A!zqb_<8HJCBN7aKocO`FWQbGctkX)B_4TXIGWn)V|`&fY9*&_l{R8= zZZ&S*nTy|g?Tz?5|M(AMY)<`3{qAsgSG0(hG!=_6GBOg6KmJ&pJAclriD#y#RhE|| zpI&pHuN7aqEV<{oXP>k2XlZfD?e&L$_=jA)wZ0Ypa!me!R=9ceGdnY5*)LzARSDoX zdJHCoLmN@n!~a4TkVjH$>er1WO>NJ z8>d}*5)Vf*`L?ade9Mb7#=RxUg#CRz(cRT)noSnLv`yhMXRUJ_0LIo8R=`VEpPO5d zT)P+(sDxwF5s#WWaR5PAC6$aq}7dQB$KnFEuK6=l1OwxphPCW{ljt z8DqlvJGXAft?M`9+U3h~S3D8+kIE;rn)+ZkC|zCm`~Og5NE!#>0l)+6l9UI|IHpnD zztxzlY{RXw*z`mEFEmJvmz?ga*Q#Qp<=<1|uj&Ck1iCoJeDHooc9N z)6{Lzks7xzXW?R;#LI#YRtUp0@I909;cM7Y2|U2?@8bZJHj`m2LsNK~ zR`M)6fsl6^1KdcH(9&W68~=n8gaB9&`4dOWj64t4AcQv{JhdvIF2lC z11{mzmguYCE3IpgKVb=zuIL}&-4c!Sv&v%Gi-LlaJZFB%B}CMZZ;32h&K9=#C?`SQ>?)Tn(EQ`zOxlDd5Jm8wZ-zg#M zlNCQ{LW|Rfv{-u25qhcZ(>;zhM*dDZaC8w0t!9mbElKFE_B%PJp2Pe0)b3r2=`%xrjIPYyra z&U5z1eGYk;dqMdlkD0Si#dGe*mp1C@nZX%HxnSOXFUD@y=&<`8U#7Il!`*rH6@|f0 z7##k);qLw>zh>WN<;&kEr)PP4#erWcEb0M0Ajq*QqO`;c({!#H;p(gFC0q|gf7eh< zjm^ZNf#K-r=&>;|F?Fg}l~tUJ+cVg<1_o7etx8CnpPPx5(xTdh?d)2kudm-}qs-!5 zv>P{W#GN~L{3%Q&Td|^eY;Eg^Znk>v?vCabw(IGTa41Go?LRX+Yn))4=8nz|D-wwS z1tBwgnF)9O+7*>|D;hbwL`>{$33}kj%=AjX1OvGe#_;B0jCY~nSux!7Ets(?Tz0WMtAiA z6aWYgC|^<3^32EJDFTFXP;v1L<4s)PDBpqy;0bYp2WiDyTFH`xlJrdbuc72n9L=nj zQJqki;QQ<&eX*sy-w(cX>uh{!_~{*GVT%O+k8AjCQl7ui(eJw2Vfgoew;@*fDxLi+ zu6AlH+V5ZflkXk~t@|X#-@JbVrk7bZ5I$8(Gy5p#Xj@iQHi}lJt@>E4juHXklCux% z-Nw`nP10CXjxT@VWz|M{u_NuecLqIX`=Mg|lHImcC>)w@Cd^ks0ES->crP{^-ts233q zfk*M?LajgdcdVRI82Q&Rp@q1eH{vEh3d1w`#g8;GFF1~!K=%iPPG6Nrlr(Alf|epg z(ep_n8Oi;^&ncX8;Wi@=X}t4Whk-t19tQ&8g>fc}Gs}q|b73nz$W`QZe@Jm8U`$c_ zx%u>sUJ;e?PmXxjp^s`aj2<)sD|nllIO|RIq_E7;M?o+*&rSuRAGHOq@+gq{rk3+SJqrO3SSnKU+m&)rgE85MZ0JerD48k?aYVd+9xX-L-+8m<{ zyB9!%t(>9gDgxhuyZ%;v2)r`#C;)8+T?4Oph6b|rE$1Sxl%bWBSmE{C^Q99XxE<<2 z(z=b(T1@<&!cz#rcDmdJ;J|)hgX><9UuRp>fzZ1BjK9QpkHbH6={L()mb61SY<|D{ zj&{L+$1n5eCdK^W;CLPXuG@W)ZgXHKk9)%H1H9P@mqkKe4UU!{{R-C{LigJntjH4& zMKIx7lj^WlIL6q@Bsln}f_Rumj~Eu_~Tves(%)t2X12qeBYA>cXv9 zT3Cu`oRw13kSl(A#H)_N`mDqAUWQwtQal#67m&pIun8;nzH! z@<%>deTG6S(N)HoWB^!DzEIk;gMwH4saP!yb?U!Oo=C?eLX>%TM#tj%^&9$LeN^wt zE32mM)!T`NdlH7erT>A0u3PX^|0pK&?d46bJnaD;Gv+vnM-1!aQ1p{7voYFPoR_F&cF#u_VfB&SNwU)LBXj>!2Z(-aRZSf zv-9P+Gd>rkg=O~(VS2Q+v88aI&x`Hr?T}NRJKAEtv|#?QP4Ti)jn&4Dg{nAyq(6GQ ziy=}J1-0{Lc_yYOZbf@zd(7URkFh%o@f-j4d-0Ec=gp{Ti#T$8Fbdl>@o4{%sA(<6 zxr-O#i6nvwsk(h~2eKD?^&1Y_Eg#;)0!xhR)Jv&Bo!%`U~I z3m4<;kKc;-&%GBH&Yz37e)OaG;SXMqSHJhYc;ofgT~j74yfwDcbwf(bd(gEkygdUrjwr-HfrulPC3#9ku9Z@CY@cInWKp zo@(81!Z>l; zx_OC7`09(z#TIY-On*d215VrU3y)#_4t_qqPV6Fucge*s9_W4OjM0!wro8Bxe0v2g zG)8eG*;M0>#+!VHCdy-a%2-Gr(0ke;zg8k-j-TlrjwY7xj!S-~oeD!8dqN;}#)r_r zI`WlbBb>wH^hbV-R~qp><`F-6RzKvAaBeHVOKD^YIxJn(Vf3fioBuBAi_fz#T5*#l8LQcP~6N{yv0<@DM(= z08!rPdnUFUJ2RiV;s5oQAB)F_it+cpbH~p)q5a&6wwPR8i(mX(Z`(hIz2Wyl_57`< zyYt}sb9 zDtJIo&i>gwar>G-JNNlBV5Urv3=DD_bh+l?xCi{Z zlU6pcnK8-lck^W?fqe5`gCq<>TJ@XW^PH}Hmoq*U-|uyfE8Qz}s(byhogc!Z&%Dj* z72~X8iWA2liT2j+n4X-8M^B!Su-hT#m4Q;_avAiyxo!rtN{qzj8Z##)49-hXTUxME zqe;vzib0H@iwg^K5)O489~*bxVVq$oZ`~QSGNoFKW#8aX3=IuOYinyXqFlo%9A&#R zddK%LK`=a}h1p?pT zN89sEd^!H+-!CmKIZxDS!l}g2B3PhM;GRB6{3s&V6vxW?s%ZkNor{f4QC7a$u6OPD zKx{Pb&rkwOYvsF?g@63SXFisa5a_FKjOSasgg4|l?_QK`xBr3bToZ7g%IznIQGcbJ ztW47Lr@{D}6~yUt2Mw@sOYP_x;<{oWrR_Ko5M~_VATK3-J<&$dCH0X|*$Q>l@!S(f zVyM46-aY%CSE;P8gA*vIs=VTUQ~ie(MeAEAtPqkFr}0)!vX_1Z$YmETTR9}--7!H>xqgs0s|O<()H zfjsi(_fAqZMVu;U_WVHLcqkW2UX_ddlAbb1Um`*17GdZ^Ddt3r!9DUxpCTV_Prg?e z>XNt*3c!>Ue~LYMl4eR~$H`kY;xeSX?g!4D;~`E9sk&D&k`h7n4$fiZfbJ3!BM5B{ zesZ?&#`=oBtMaN}#z>SH(=+qYRBRPp4ACrbjJP(V*ihqhf{B}zd#nOvwQqGzy;t}y zudG{uU10YD;bczF0McYtANUUamw4=S>kAF~K22C*;tlN%xE=Hj_y&yyH&Z>x>DFVn zZt!8%qt8Lrw-|!-nQ0&B2(&*r81)@Z>0uu@NLp9EJs&f#UQdlE*staCI=Kh-35?fI z+W5O4q?*kkg{cgiZiUBaP15bo)!}%~oxzx&-G2x`KOP83XP1}y$iU}Wp7QVMZl-a< zB@8SmXSiou=3~c>#>mKR<0&+zdTS$wdOG6&@;Cl^v^G@5>#uw#Iy>6LJI#55!;@zo z^?ARXx&Pj|tFgSX9%s+L7ej{*MT^GcZ+-O_VtpA!xp)cjGBe`u=1S#QSDmuuJ-pV+ z+J=>roY@X^e&#h#u<#`80!ZI2CYPOS@a!73ixUAz}DD|UFNCO-mDg+J`(Lh z(Vr&Oxt@dvU}i&IO)QrdqfU8hQCe)BZ6mzWOL;-I*a$@z`S$ep2MWSJb*!5Qf_vlS z%Z?`pqR`QpJobTuq;t!nbCa)Kce>Pdo^x{cVI{sF9F*~QZhBsMV02(ig!f2146=r0 zMveE3FBnp(bzzY6&(%DT{CRfS)EA9Q+-J_pdhQhfqmRp<#f704<0xrh08a5IT;w}D z;jFjytghEH6Qru*&`@U#4Yo&fGh30f;HTPEX^O9Z{p<1m`{!*085&|Ip_({<{zClRSHGq{I2RL>Q*qgXI92> zbP)7xMKa!&=qD?hSuuY7`c3bY#a6^@LwxPpjktdGW?a2;-9}&P?arMs(c*RE57rRN zTN+20D0KPCjktDWB<2@Nu_8WVadBB=7At#~?2yHg>FK{1#i5%?u1$t9_(ispo>Ci4 zPK-*fxf2s=lTnSQ95Xc~*?(Sic|mSTvNPiXhGfRhGV-cq=QZ(_YzGZ~mIhyn&88lg ze=i)guC6e9IohuL8`TSyoMZ}ch2}C&sQ)EeqBhNNi}o_89%<<8Q?N*FrLnEpb|AFw zFaIz8=So%If4nF@G9+9~R~1JNJQl9VdFx;Ge_oWAO6vEL3rfpz?#Dllo0l%ds%T0* zlSCB*I+yvmMe`cO*3#DM$tUaLRaV!Q6<6w?7&GY?7{Z_{923Enw5d17-Mk%u)VEW< zcn?3pI2W2ld%5pKa_EtSNB=&u38soq&Ok-Xwv0imB<6*08i{Y~lG z&a3wIu^GxMyN}TF-gQfkK1n{n0p-MWduvm5z&6g}wV0+QG8naDW@=O)waRw^o=SP( ztXQ^q_5@vt;>G%!wB0k4bDGonzQ|K)<$vN&&~-s;$iMXpy0?K>{?N*N<*wx^UAf0U z8G*BV95kM1mDS(5ZsD~OEpxc+9qo-DD9n4VrcJ)$m)aq}?l@{j-x7vr0N*@5;!5!m zK>zeHp8cnHqEU$+%a8o&nj+J)zV}BCOB<$0u#2vUmJKf)(h=Q=UzByT6b85IJAT!FgyXQRe37y>$6y_$OcRPi(Q= zKRDpC;BHIshau-&U(P8)Be#iCM&-aji_zOkN_~&f8G#DnU_(q73>t=H1bhs)2>kf7 z%8a~`S5`%1AWqD8I(wM7SqaT|7<(xr`A+SEL8a{a1z*_eh%`BC1_lW{pv+wPhE>Qg zjMNA9fbfDJVfo(MBT5)zMG9%*$P4~fCaBFgBXCxAx3p4@R;7o4T01`HynGO#82n#- z`)~UCag~I?U|qq&Q>Bt=ugirj917pvd){M!qCHZZSb_Ix1IUZ28^ORhsw-`V5(MRT zL2X!&5Z1tqUIaTi`Zim#>y_SBN$9JN-tN|T>hUvi^ZIowO4!DEX?ab8WwqK7gRhcN zf8JDjh?+i6SAr-)a6W-0(HB+{CprWE_?$8DUf&_uf{M_UTrdW&lzY<&>fNi8YuVKS zVK{BMzJ>6rBv1~~Mzl+@*chGa=S2yo3A>d)g~RZMAnxth^}u)hupK%5H}^weayUOH zK|W0cP;h;l+MACPt;Xe$KjVxO3g;Qt*?auxujzY4x!rLny-&iL?y~0;Cw`=BAiXRI z-+y9IbmVU*?F^Sy3jgKffCC9WG|jxQ3P)BEP#ve@<{rli7oKTT7hP><1wq#4Ru+n$ zpkP6vSIsz5X!0}4KvjnG#EL$~X$&NcE6^$G(uP~nMB3FtqVSWM%uIe@buMEn_35o> z<;W}e$fO_e4tiJ;%|@|9d8ihEG_9!6)m4S3(gkm5<%({zKbVKnZ{PpnQ?A6L(>_QJ(X@nDU?F?q0~tmxKH0 zPq8F<`ju{9pa{I@HoM{p{f2gfqx6m5p5A!!$tUBAcnvFRpso5t`SzKYUx@$i|Nb}Q zzxl8KZ_zCthV9ee{NWG9=QPE_d@0^OdtN=PHm;A3#N^Dh4W!*|9dT@MII7k*Lj+QM zU6ts%`l0$K9n>pCR9!wtTm2Wlhnw$I` zXTh~;%x61T&S$Jrf4Va|YMzCOAQ*v|{D(qvW1TG#MT3+N`VVR5Mo^E@$|GY1yNJL$ zLIdEP*fD@r(Y@ls+Lbmvb9Q>ljxdBhbZAJtPMi8Cyw9R}IliNg3-#F+i@L`c0zgyf z)2z^8n`+9Ij|I>K;)NF3>5r8aJ{MSHlX4%!gM)EsU{GUiI<5m6!?(~m;!b=d6A=^N z4lOg^tvrA(grO1mhPq|EOLS;kSSE{ zX+i16Y<72lI4C-|bVGFRQwnM^IrXPtyjfM7u{x78oz>oYmyEMqFk%gX0F?_7xM*Kfy_OIKr7@?>dlHiid!)E(AUHpWKv zBb9w|ej!?#TO~hD#qa&WYjNeqc)a-8FUOTD*OkZFIDPt2%X3$5j>OE|Vm$TKlkxpm zz894eHt2m^VZFH{q@&OheB-V7;Sb)7SHAcC`0jUJiC16wLHywLH{;D8y&dnpdp@pR zxgpxDK7vt2m`i&6t!Ru|TG@!%g;JDsU0&Vr?k;xX1K}5OoEeOqi@XE9B=6?qg@csS znCfTcS!MGsFj<+HMC4V9;3=z`^^RStxG%^b=XZotT$pwmrav0Z`Xsu##_4maXZkp_ zL48`Cot>LlS&ebdW0&sfXN+OHMmUv$@y&k8F}7|)EDj2Y>HwpA5J)%(n9>Lval&Oi z3!Tl+)YEQi-?{Pen7Ta@Yr-wgn`TD_9I^$w$T11Ot|1vPQFv``ttlS*F~&ONQBiWq zwrLe^I^xUyR0%^1!K*Zei?S>18n{R9gvZDu$QQ`CE9H{nSyw!2FFB0N>>jczn!xtw zRg$j@wUSws2A|X3_5P!+m&jr;NNAR)b zxDCC=!!$P0KTMD0XIzu3(mh)`yYYCIV={hndZ+NvNE?1dQ*ik`w1{`qGZE;?^^LOu zSl{BPG3qXNx&Lnb*)vzgSrJqYKV7r5EJrFFFMY3c()P{Z0lE_$GNx)v^sh?zQNvCc zY}u``u25i``o?H3HbzSe6C-PVY*DeXUc9QtF*S32^_HCKUUkr*dSrDqlkY`-lm;?t zGSV}S)1nxPZE#0tqcUMgPCI;HR8~gy;il?@aR^?UNzrTK@0XU!8i(fX(BGOih>wQX z^-(0?wRvIHx6(pK+EQ#btpmv$7p|*@9vnUit$U=4mPqaFwx*r3wsKpf%g+ovT>1MD z9>PQTa1f#0IP}@<;cocm6Wu=7>wYt4_5%Cv1NWUxc;R10_41SnE0AA52_W!((it|; zx(8kP%Nf9F+OkrWbnW0`Rw#3bwx8ms0W5HRs;39?~4BDz$ zZz}{tPJUS_h5`k~c79LEhcKB9aEAKZ{ZX5Y@{~Q1Gl>?!5pJe54DnSBp3<1$?qW(kw#mGwTt<>4%tVG(b zvfLQqSV5(>k#yKlyB&`|dLo+ZtK#a_>#?xN*`>mlO;ncEv8wjvyyFdZ`i-r1;V=p# za1jBNnf4gr(nJH&QUa!X2!#l}2q|p0i=aaKR2#xE&O)H_?ro^Rvn`Bl1TTq{rB6fic4~;-W4v=%dU=@rn|Sv}osT z;SduMsOuz@V)&2%EILfN7Z*$34wlul9qrAc&vi*rDO}?$EBepkQpq#u8ycHcr{OLC z#Q+57!ZYb1DWFxiN}n--iAGGgL8&=AH|JF&C~T;2vX~SK;AFxb{P;;%#e@>Z|FlbL zSL%`Sy7^!@2wHdNH{XlZsb%NYKfc}#sXy!k`+2M2KglzH z_m9uDn%$@O=_%E+?|efm(5nSIFXYR8rYz&xyrkdz=fi<-9|(wlmygO}zxv&;oP^8$ zE8jyi*fNxrM;JQ4@cGZj+i$)l++X!-Q6^Z?*NzVl#5-@k9;3Ie#4mp1tMO<5gFh92 z_wW4OxP5yx9)IkK7#=zli*xgF;qsN36rQtEw7a(_4)yg%oBCK`t2*YycQ9FPNj%=V z@YV)e{c)zdw|W*Ygo22bsq|Zp>0pIbeWv_kWvh2dQGV$=HUz7`L;qQY%eApi>56yj z?CkOi6(+2)0v81$+6ldfdR!`ZvzPi7@~g=^G*-U3fss0N+TS zXk)@RsqUfCj180(zq07WX0>PwxF?RiNj!I}_~ONdMUTtX1&xhW;#CNvHs0+u`vDcs zKehWo;VPjLztcDT!WVbHIPB*Sf`g!Qw|^_qInu2xAvt@{-n$nLZsjj!0zc^AnWGJN z9C=QTQO5U5F1b{e{MnNXbb}EW#X9e;WM>TJey`IzoWsdE9Js@nX8ae9=@~~J={_MY zeNFwt69w0{gsUrY?b?`k3wZnO3vu?n%W?hAjPnU; zx}+~BUI^ZXory|5zx6gw^lD^eEJkjROQxFA^F&;`dRubbt+;fNt$-)Q+et>NVRxhe zmq2L0f_PQ>!?yZ#Npjj`%*`*wYp=Z-Z=byox9?2GrAt?0|NMHqbN+U8^dE`e{qA>SO>zIRZ+t0E9XlE4-nkU-oVya$jn(n; z=U$EC^G5-nX~5$D@y)j`!Yu&$R2-t=n8$ab*W@v48rgp)CKqg&gJ+F;0i5-KCQqfDID@HQWy7KNCqPM&yK7ea|L!)RHJ2n(FZiq&T z-aG%Q!)-k?vB>;SE#&w%1K@aiS^$&Y$cEYz3ZK|NBKJR;X*c1>Y;=eGitjq)k=rK3M@ zpS^I^Qk=v3$IVvnE=mD1N3QjQ=@N{ zHO9O8^aDOJv6+5?+>m&H6_3L?kHC1G%XG+0@D$`FpG4l$+G5^mdU7hsEb3QVikyis z7=B5Qi3=F&FvyW^GU6wL9O)#y&FD9MSINO=G2YUD*Ccb01L%XhYI<;3n%$Gfluz=< z_WIyV8Xpob1wHU2B7IhPM%dAW`tdbwz*-yD}{&+|KOD?_7a6gMbeV^U~{>{RF5b)M= zp1&pil!v?e`c53XaWS4!Z-7GX+!JT!Zv1rh@miE!@6pYAXFSRw2i;W@?zEjE zQXAo+yr7BY1$ZS|W17RWg5~!-g0tY6SN$q|XaPqeF`;Y43k4_d{;R1t4x5} zP#F05eDb?T8P~DeP1p6Uv~@ITEe*azX6}K5rgeYj@v0bVt20hAp@8zHwo%^wPbK4k zbno}v6J{THxb5>pcnA;SQw>$6$=DE)-7XX}pIsR4EW|gT?2iBN#Xb|z4|4y4{>>RnHZwn0L&Q^ zwPH|e3TYM-TR&q6w$WE%cbH@iAU1?}z-7Qsj017z%tr2ypZ&!Y?ahDwoCe<9A&Bku zV@SRi@FflyMZ!3`ED6V*-RmtLS$fHHmqFRhBhF|3=J(G3o-iug?z_a4?Sf9=_gNa}}yMciL*X8`oq6X-OIC1o({CmU*CZnE(v7I^)Mu;)R@ar=g z#Y~{=Z`DAG;KEAEl7!)@i7~I5V#^y8ZWv~-UA-0~BO^8@O-{{-ajA=wryq+mPd=qs zS)JPG0h#xJ85y;Ib601~O-$I(+}_qECVAb;N*LSKqg{EKQ<<8K!}J4I27@aI063tsy}%Cy8N#4kBz=^_#D}oWcF^RX zcwm@e6nW-*(gjEhK!`!0K;WQ%09@(MT!{}Q0tRN30(I(xdEI09M!-l$zir0_gUMNb ztEvMG=(%x)xG?6_ES6*bP)BU5AO9qwQ+V?=;iqS&3g_q_35?)&)F0>K(4Xz{zw8;M z#m+n9_ICWMfA;+Yp>>~V+vgqnpmK4a{*}Gd|L~{2X^ZU*n0Vn5bT#` zF}vBlS-}xv46YaIL;|~LI|fFc7+*|}36jxDr+mU&F!&?n2qK(2g zUn6dgqSmC-_N4w2NP0 zyH+Ob^mn$!|MD;W`S_>5`m6E&`xg{PO|-VQ$8*m<8{M6qF+DREOB#pk)ei>x2YlA= z7854KKcd82URw#)yNCf(iRj0fG9H>pA5|FowpSa8p3|Q<#6Qq~;BgelVaYef2rE8C zh1uE;-kdgqN9a^uSZxolcl78H8?%>}*?~lTO5aeOtKu`@BT{3FuT%W=!*o`?`VZc! zUzA+bn(2t>1$CEJxK){tV{BQNoA>$0e8Z6`jz{0Yce+eUhocLa@Ymhl z9gFiEtHBCDVZXj%>|nwQ#F&4{<%3mQ0)%CHpwiT_#HrL%kc`3FvwrRZj02?Fq|$GG>8ago8&SEV!TWo-x)+ z`@38gk6rGU@CH1!(>-I>R`t5ZTE<<)uI@KCyBt@qj>fz1Vf4Ke=g!}VYuCr(&ZO|t zc~ayWSL-yk!QY@iEvcjO3}3vY^6 znTVS=Mq+kyLUge+&OCA=*cGO&rA2+LC#ppkA$8N@Z~v>m@n6N{{8qH|9gXk*=*O`p z9{KT8L-CETd?~J8ycR$B(YrBI+KwZS4C&jBIQ#ay(bv}#U-;bT)i1@n&&$XSHU3SBO%~zB{M-&7%$RfVR%KxK7hK* z?sPS6H7^N%q|wpxh(mCnzS|FP;s41C+abf((*6K)jXr=2B)JUqEWXOJv-0O{$K^zg z6e^|1Jw_b(H25{f3S%z#i0(l7+)|@p1m<`Fj_QCH1lTo20L9{+&o@@c&QKl2(pW> z^dsN%J@rkUDT3O?u~<6%rPwO$?mm{oLF(!Xi??I&?B7!vs2}<-InQVTMbJIY<=OI+?|1d8&}z%=sUxOm`nmnoZdsTl zN2PFnu6(cj;^(m|i#x^XmN4XP@?rSQ+e8Diu>9}yUF9>kN;#!LQO5q|N*%yiv^hOE~C0ocCKjJI$<4xX-_J-`2A!yPmz>v%-@H z@QMitq`4t{@ED*vBpkb4flrDs(Q{qlBaPFFZ$ydMNZiSZYr&fuhf#f73qOhsn+weeSs z6^38m!gk(rxsDXC7cQbAGS?dmu0OZkTKZ zgPDP_63xmr)$2fizZK{+Gc&O)0lwJS7KaCqMn`9FG&B|!mX)C>z+BLj0E$2fxywt7 zZoi_w#~`#Jrk0f+OY`$FGd*b|0EXqJ=Ef+ANxpjda@rbN%=p6mf|#VOc;=ZGqPuS( z+B+q{*VIL^wbhI`z}8zZISAA(N&{veLn;cj&9$=br)-cw!RQ&_to~Kop@b{z83QrK zO*f~qj*^a*7x=*}fiEZyxiVwBr4^%cYCqZ$V=j4M%WDh^e2-xm28#3fm?6&UWwxq@ zX`_#zG+oveh71OtI%E4oW`(nDBC*3Lvg+21qT)n|NDLfIV`|V`_@E8R0|sjppG!+6 z`EN&0Pq)*v0a*Bu;~wG72xi}6;LhVBjr=`I39k7wS1QS8&?p|lBh1rpdCzL&6kowi zI*MUtg>R`Y!6W(>3e{%iv!pz(9qx8Hep2vR;prg8=1iDy_Nm>h9>_nqup<~(^b-rx z`TMMH^uU|=*Z=Ib1EF;XZTv+B;hD3#(h4l)TlWY8WF3Ph%4i$Aw>Cs$)Lxsb(a~HN zFF*H0)NZfExpOySdWN%zBw*^hb(9Gz^ZF+Jffe4uMd4sN;}C_sB9&tsGH3)dhFOJ$ z!05AulqZyh&}=JXlt0=6l15%pP*R1|HxoqY$MiM)_@TxU-b=@b|5 zQeIHiq^D$HP3bC_eO)f$X%5Lhl^>S_>D~`2^HvF!{*~{zC;#+$96;HjHS~wdu=fMX zklIUe3s=Cw6kk#_Q15Bhbiz-JDku!tR&SH7ombWswqD~jD@ZT`RhiC$2TX>+NP=RP zIzZV#S{QX$K}TMR55*0*2hC>-XeQ%;a}7*5fbQrX1ueTIFw=f*Begqe<;n%(MTk#= zH7^qwFVwC{xt6uWHtj^9Z0zL8_yuiNz10?Cvr4pD`P2*kqwVp2z5B_*oqzpaEZ=17 zRplnje`|O>^8^Wg-4wa%&O1Zxr^uiP4G+wqfwZx&pLvi`q zH8l897M)`$wc$mPIYaCvv>8a_ytAa)ngnP0`Epsd&^Bdd%{mWidS};P(K$x$O_#CRw*k# zd^0;eE#6Ty1l~jWfj{KDM$Ueu@|kGJO28&ouZhoU5WivtS)Ily6r2iAp4gQp^=r=Y z*7&D-vJx`bu|Pa>p~=Gvd=e{T;91QJshwDLJX4yF^43a}*O-vUsv-qe988L0BBbe{ z+@kp2v57I&V^ZK_2We9MvD(;2Hpp#ZIAJW;{i@;zUD=6;{IP1fpn9FA%)%ozk?Ofw zyf$N`G7n8tzM*0n!X@0(U+Nz@J$n%F2fIL2>BsHX{u8EiBfojhbk1o4ltlpQ?#bCl zf`c>u&O2|!fbw^Dq~NMC#s*BT7)ldv=VT6^0lJ1CW0s9Ra<#;RQ@Gs7i-Htdv1|BE z-+_>hi!_N(e<^MKk(TcjSDpGAMq5={bv1nwUY|*wRdT}rbriwkuM~joB$=S494Rlt zS^A9lxn%qWrxcGITT$}}o?-O0Oz10kUN7|J=nae>D;l$vj_`ABl}V>et`Og`!S={Z z=2Z@rA5kdvPn8wJ9jiqnO|qb!4-F5AURK4F>U&M$dwUN>qxxW5OEHcO56AOQJrPay z;sMmZP8>fLHKL_3z!P`I%lWS31Su5l zP0i5C$uD<&1CIysQ`mVNyKl*Lnus!ZWdr{pKn(I8E$HAx%L{?>Od(BRU{f zOrTj7eKa3UTH?V(?lq2ZcQSQCF)fFS-bHDGLjWEf9Q8!?Fy5o*gN9RAHNuA`(el=oMjLzETAIXraPBXY14Tde&J##*=wFfT ztZ%Kg-jziSu8%CA$@ojZ2JgVdbWf##hwkgTCb?_ZnHI<;`Ahhk--Ek^_xD*?f3K2J z(HZ!TFcp6L0dJjV7A_CJ`yFk+8&7`kNfy+rF1(UYj(jOET=|y#ITbyF8#J1p^Rbw= z@pD!dPY}=IhCSq+A|a&xkqMk9sJC9xhp8*xIgk41Ud?El39kqSb0mrvMP;~0`=R#% zXP_701mglRJDcQ>cuCFqNym?DYMfxFjpgnq$lP6UkhJbkKeipGdX!J_3wlNyL(g0n zshqyr0qNdt!##De5B$s-e_i<*KxEUv_z)h#L-_X*a-vi{do4D59*gb9PCw@Wv3&K) zeEixQ<0hUT<_NnVfvujo9EG$0APt~dnje=S?gb4$J46at<@d=S@GMsYc_5#6=e5%Ko65m8<$d>=D`}_nE6cn4-L8LZY+Kn* zCSX1}Cyg`S78e%G{31NFJ@WCxk3>&Le-!FiA<-x%upp*FOsE)UR)$zJ2BRUyq0!?P zf_-8nU`k7i64=+uUIol*5R_Mw6XS9H`ZceZV2hpc@d-1_&prQQw0HGHM-S)hiUBXS zM02q@$`Y;-Vz1x05nUbauD`|x1A#v%kcIG&KO zzGNnc*~n}O#_C-d)aj|2G}}|S1H;6OIL;yA3}Vjk#X!6vVS;+YNINz*=G842aLEgX zh$V$t(RTo=gxMmIdSv!DvriEwFk+Jq{3EzIIXU68c)2HC;saIK89h4HN2%*^SU zuY`k9L8ze)5Qx~ah%`wLBQM|KNSE((;GTRFAK@q){R+SjhaatVEhoMNP{>r z{^Dn5UCb(HcVgTxGlS4PjM}KsAOU70`nT(1q9}Zk(D9Ri{_48;`Q{F_pUP}x2jC_>tqb@Ih6vDAkhp7 zEf%O;WXB2KQ8zZg>ILm!=R71wT6~ime|d{vB{+XspW#X$z!4|;R<;!;-P0#YSswaV z-`Ytd!z<#bh!05j2}c3)=WqO!AeHA{*iCEqeO|Ww-V>Yjh>%F>NUw5C1n9pxzUSZX z=W^hlIDD_VqbW>V2q!;iEx3X3Yz2*Q#B@bCw6?-5!W>9-_b+hoJo&12&-3J8prTUsZf|+>GI8Y{-IH#J z!o9Pt!+ga8#sq~$nTt|qTex4RXtzqEu{bjxwZg|@Q!(E9;akzs))rs<+~;DTuh$dp zmc{?P{m#2FJv(nj6owF1qp;dk9aFqib1biNCfKaEcw?vFCDL46GR@7;G}{ng$i#_- z`9A~-{^^Otm^fOlno|+R5@-Y0HHLb5B7Dndo>BhPTHec@8H*Z#UG)VrG408 z20qcWLH&`HV)(;5xPQrkPc$J_xW0}87QViqyfKlfTJaXmH^JY*2bGpo4)Lw7cYW(I zNB1a1p>@zg(=F8{lSi0L1kJ`6j8dJ+OiW;cK#`V5LB=`pgAH{}?$@0CN&L_yR#8Jg zn9R4VHiL%EmFDd@?!-!H<(+ehIr4;Zuu}^Y_BbbWLE)h=;vB_HP%;F)t>O+l7pb3D&xHPJP|nM6(q^~l7Px1(wY9|U${ z+<_dAOX3|`9~JI({A75#Md;kGWpoapEWW18CxL^aa|_cm&JKN*T9rg*Tw?_#Js8dh z+(ylcT$J<5lqHQna`H>OK`NpRK7Q7>70xuH!jUkz;~~nBA|Qt;m)z6fOl1;1*1Hz~nv(sxL_%x<#6L(lg~q`An1A z(rz5ii|{gSNuHO1`zq5JsZ7F?92`JNYZT$j8P&C@+RIfh@;PbKHw3p6&sSJ7sKOK~&d zSOKzlIyyRHT|5&jt}!a*_(l65AG7;bL1O@u)axWSZz%&P?nxbb3LPd>&~(~~-M=<8 z#&BllHaMrenI?h%a%xqQ7XAu1jdw^L&_lA6N@RS{chFIAs*W^upC(687dXPDa^+v< z^@d}zl6qamTS}YiH}yMx>+kiGIm&F~o}x)m6@{70vE2V`Y&P{|ehCgrSJyOiK90Wo z-@BYU6Fq#-xF`8aSL8a=1&uv6zR7t-CWd+U75ZJyi*ujqX1RWM+h@RS`v9<)*8Q}N zzd+tDsr{0}54{rg!TILfl2zY(`^Rzd+&Pc^gi87v$+40#F#fXQkzIwD^aXx0so8j< z=)s|MJeMByJ$w|=Ah*E(aHYB~YCpFl z0fkRHL`MOTC#gGVCAg-K{cYYa!SxhZ^5Y7Ri~gIP2Ei4^BX*=BE}z$~Fz62H8?;9* z%R7F>!34_M*=w=V^LT7DwEJBS2Sw{nbZp08ej)7^25n3Dqui_M^Eyud)RJo|yUJ(h zeeQoZR2qK)!hclwxW->F_aQulhwuu;CVJe?1!{pB&1@iAI^OQex zg-PK&513n+J(P2thkIw_R+N{Qyb^*LWW&RUqqC!1A_ZqBp~RAKXT5G>aA7KJKoBzl zBbv@(VYVS#25wt7#g@O$s0QP8kanTCMWqmU@JFWbeVqtDJ%B7{4Q5p(p1u0CljS1vN z%nph}m|Ga6iHQm4g)k`eU;;*zN77$g-;BkjWijqe(Ohg*_^nu2EGeH2F>*&`8JmdC zuAZn>oz~P9Vrh9LX6F~9y|dfG15DNmbt*;&p#=s7fr^52E*^D=F`2fYoXL=Y5K~e; zs@>EA>uZ~0#v4?JYr*R4jrFaVoS0Ueb-}s6)GO_YafH<|c{wQ$!UB09PAet!2OjvH z(n5IQTgnVG#xuCWI}9^?$20l!IfRM}MP|w)=i_ZyQPfdv_cn;EI$CGeztZw~H_A)@ zyLU3->|lZ3@x?+>f<~eVl5${|l{d_pUdy2J?_M`H+2T04)s0mOb@=1WNiQ_=6HH84M9b>-~;zg@Q^OK?y?ut4Z{|@{$XlrbBwUGgDt4;JatO z>SHT%1k@LfF#gEb>>G!;8wd-|?+Ck@GR8&&)jM>9=bUC+7}Pu8>o2d1EP3Da%X{DX zn{>TD?3Xhj#k2EQ5l8Old-=P(0`iX|k2w%3fBztm%A~LK3E%Qe0ihFI-R|~co3afX zM^LnIjym*;F-1)mWemako{2DyS9l9uVuuC{!YE8O6@cy1P=eG7j|T@2MgPD+^!N40 zjA-4&*qGWvxly_(d06SkL=(OvZ$5KcW%br=!j)PHzxm8`#t;J8&`bWaGJr4c_liVb zDkk-p#yYTM7stqbDkly_j?Y?hoLh18pZwVMap0ghZz*od_sJlY=w9~__61c<-cR;k z_l1gAZmayc@)Laz9W#HVF&2XY{fWN7Bm`Ev(qB8;+k{lrF+aN`UaZS}&C#O+;uo6Z z%$XC>+tV3uzWJv4v&T+99w#3;E`F|4t}6xy`fPmUTs)5DV6q-O6Et{LeX~J)LT68R zG_|zQnY}~Ftm0o*Kdck|=iE2Oe^wXK3*fH{g|uZLTLhwzuMz$iMGLz*8&iF(tF0pr z^$$dk_?cGm0xja1TAP}qD1N82wKWEMd!s|?b%=jxm+KJk($U)Dom^NU%uW&*IO(Fe zdhu8q9@MWmcA`D%#baTx##nBHipRWd`7@D`aX|f@Zytptg+OX>Jj0tUC zH6$9dCZ24gylUlWlj3Cs54#G$!=OC##3!{=q9?UBT0{S7H+UrTq~d8A8)>sm(H~Y5 zV_08?KNQ`0?DUy9cI2qH^R}{2VVMxPqWU+jQylDIfME-scM+aXX{@U(@TEo7T~nbk zmc^?sFO}5J$*|t5`Ynndt5LeF5Eu3FpK81bt_n#d5H~A*tH}r7Rizz2qDpcR$%p7))rx4$ zN^Gt!h=y@A&4SX?^Y%gvREmZO#;evb$s`Ce8!`v z)<(=O&UtcsOIwR+k?Wj3r2Y=x=RB1-6;}hrNoRI4K_%^OLOsFbGa&^&nJ`SoW0$QO z$w8pb2DDkxGZ~kBu<8#HsaD8SO9Y}p-t|CZ!LsDl2G02uedfxf6A%_&3EpZ;G^$p4 z!m-VBjcDiA>bfWC71}$ZBtCdqbZu!U!AH8dWWaqe)i0SMu{B*KAL_ep^+}G3A+w3lPoAr)n3&P1IuR8j|Ejw!m75jz ztE%6B|A0QC_R%;hQWr~$^KtFU70ZR-3KJ152k3n=bTRRPqZcr`B15tQQY{PJ6dmFn zG9IfZc}J&)2V+tL{t93RHt^1}77vOH-46T$_xU8-{HQN<9_X#WG{*aN^*`hvJ~xk| z8~Q!6FY#bt^+eS)P&huzC!jSn89W3B{0`iOUL>b4j4MnU1ApkRP!Igk%Ty^nrnD8s zw{>u?Z*xNw8|%eaFtMk`_wC}n*pV(b{<07P125^?u#2oKXG5+0a(OqOgpe=3$-{X< z0u7}6CgWaKciHuBm&)w-dw@Fi*qA+kQZTKp0FqS7{MeBP%Zc|m%9ZZXJ$RQ%+C$GN z66!^L)@{k|G7Z_}$Y%H9Ce>@PIq|qH@^7Gj>obkqZkrnM2x;fE`p0S;?!}!5S1gMwtnr?Rr~~jqx5Ul(06$CH!!Pt) z{3oVM2Mxm9_zO>OdS{=68~V?#KkM*t+vkVy5FWyPp>lBZptmv?RZF9>Iru{6doWOV z^M8oisq;IuBn_|!M`6X1eBv24(7Fd*`CHqddtDh=ZA{x4c<){L%j{<2NeoIVcVb}D z{f^ULnlX8|e-23)PmIE@vNvNyGXK56_ZT94&HMlcRDb8cEFRzGkkX~SQaLIDr6P-v(VUi|;q`?DZRlk3hCJF(t~8~4V(Wkgn1F14Tvr~*(R z$R^0{W|M4on@x{~W3$*SGU-JoJ;-d{WO~$?9wf7wXN`?yHqyw{qiOYwW@$F5W^-wv zL4p9W6qZ75sLHC`Gxj}h+*tMh{mTTY%uJudBqEiI*if!`l`1RJQf4ZcGWj;ydSr3-}Je<7@AS`wf6G77mS-2 zk1;r4P-XQp3PcRr7^M~$m(2hrjKC#U)3lHhY+PMhS~`Uz+r-;21J7RHP75!U-c?jK$?0>5zy16)(3VDnb%?!K^{zz~CB> z`3{_kGa(h@ImS0ulyW{XM)uL3S{yB{$KKNq&Yu2B-EZ~Q<7vUqN^13SixX*UX*~W&eq>|~ep%_N#FF}!ffg<>U0^6%NQT(U^$Kb2rhJn|UHssOE zumS)vM@h%t;YqZ0Wv5EEc1O@;W~#7Gg6qBw6{ug3s{jWMfqGwU(k0r!Dz$R~yH>2WNfO8o2K`5sEQaC0-=S{=wo*K~BS(+5i@a4JqoL!uB9A{-fE7m4F)KhX|yrK~8py422WnTz3vae?*)EvUbe(AX;aptQZpM0nTh z2^W-8X;^QO?LZk3>h!7FP3@yZY^V{;(97Adq3|uy36~srk*>l_(2k=TfU)1abeErlHTDbMuwgYt@~KpK7Y^^h~xM! zzwHct$PvdEK|(i=wenZ4`YIoOoU5XB*5i?N0$&skT`8%jFEk!RO>qNh9Jb8gsGde(>6r%P#Mj_(Hb0X3`3){@V065>erx-PDEg4=|v(X5~ho`jHKHdau-N zsAfBB#-Wsf1P>K{PxC7C-mgwC0=jN)A zC*ywf|NQINe0xcye6XB6J#NWA%6-z6znu;`x3kI$PI|h$@Pj|n%G7{e(p9eR(-`VB zZa9YG75t=0PK!{DLFxGtyz0EqYmQa4r93pJ`m3_DBT2>ujKS&jr6W{M;Wj8&IC!LY zhm=QA=(F%QtR(AaWtwoDWawAa(PhzdjvZNk!p$?uBje3HF5 zsZ%~@6-ZY_i;*$Osp^aO7Z+ksvdUBQ^Kp4%B;LDuJ$mbX@!U(Fir@O3zZDacV{sxm z_7DE?KaQsQ$kga~yz%yXv9QsKrzOw6`Sv@}R9|FQrk%ZZ+`4mD{$5;r_DcN97k^be zT`jKPxEW7hyB7P({Eau?j$1eH#Psy6CsW>A7EUVN`;yr>XY`q8pNj#>S__^yoZHI+ zYx*$q5ADrSDt4-tt4Cc07kH`($-d)buSMV1o!FlLjg0n$+_OLUPh))j2Wmq>jQYz{4f+Y~P6@dfGWua814kI^ z3m%xa)jb9tCVkuJF1hPa%=Te@?1|92pU28y>T9~dEieE+gm|1)xr7rp-hC&&@@Ib* z&7rzi0s|LzF2UH#&L+Tw-O;E6<0iO#!WJjbH9?a46FBiL%z^4bQ{P_ zz?Scjr);#=Ud8^sZOF&yxe`!_>!op1k=B_%G9PrKt4ilK`z4KP}Jk4E`yeucuyd{SCO8-<2ya zaXa5V>~nmn($O;=lq)UoXRiLq_;vyk?@wLz?(}_!`(Sv|Si9}irl7c_OM2)C;lr8O2>zk> z%$4INs!B7*2o`{-5YCseoN{}28s%*~mRBiMGAhC~ai4Jp9EOLc#Aq z$GT3U)V+B(y0`Ae(S=t&l&C$n)1XlM_Ww0{?|#d96p#BPgz&?hhMgzEP&RwTgz=!! zi1C+n%y9RM(eKwF(XRoK?ViP?u z3LJEmH)8=@lr7H>yTS;R!9DMjGwcleFej0zigzq1!9=7W!WAJ1*x?BCVC+?QdhcX& z04!NlrSzSjDYs#r_2Ih=%X;w29)_c;rv(UkwoO&AnC47_RSpdLdo5-v?pMk$F)`5_ zpL+I1pY_|`IgA<3R~l%LWfoCawpHegUxYo*e&mhV8!N_8Hd;Z2fW<1zgI4TpuE%@t zyzQ-d_I7uo*=+di-@*EjnVIR?InQPtmaslPeZh=#y*Xk=^hiuH2Hwq$jc6-Y% z9EPryr3EoL5-<vJAxy| zB+5h|V3r~6Nquasf|^ z5%FzE(iM*ZnKoy3J7;(9t36t3GmOe8JqHFkC-@+mA{qO47vtdSOd`@x;Q0D)b=BgT zzMAT<{x4Xhz+enFtY~{x!)=dJoqh!y%r*NcxXcws`a#356$oOG|Ky*(`b22m>O;m~ zB~;yXI0aGmhaI#0iB7GGr(a|Eg^A9YpeV6b|6Y033l(FHK7X_uvr|LyJAdcbRq3O6 z^*gV{!s1r!wna1a&*}{Dk{{Cxw`mFz{DUV}4qWAFG*WUI(>)5;+(v?vN_F}^>zRKg z?K1wU2=Xd-9}}j4iSiI$gWJX-@JH_~c#5VX$ap*N-FcRPm!oo zR(eTS39nx8oznI>lzPwVBz96@l_9G=pbfldYeEz&C>2Npdc!tkC~BdD^ns=2)wp@< zcC2r=Jc`x^MGN(3;|?%XU|%m|+Ym)j`N1jGiE^npD3?9%QYZh(>4CQ4zIZ{;Fm&m; zW;GsgMW{!BE;vGd;4EXv-u>;^TiA@T&&`ua_0=bIDkFy9wQt|50+gPUtkQKwescGV zZ2W}=e5fOBzg9fcw8zV~fWg4bUnhE7KUy2Zx4o z%VE(H6p5@>80^#7qibC}58DXNPEL3=Fh)8dtJN5b;Ndv>L!Dgl24Vmj zFMfel0Pv>J74!avoxr31rRtmaJlIFEeQ1MgDspSl7;ePo)|SSOw#TtOr4QXn`llfM zK-Zux&@qoAbbPrU)qAAgi1Cq8Pf)~2LYl0$hBu=Aqz4^j5(rnX8dl!$S)}E2gY|9F z0hDc|+;<$i-_%UBFYP4SIv zb3Z8l1_OUh^lx%}!Yi3a#5*JZ!0Y6>=Pk)htnz?|0Z*NL{&1~=5`_hl^Fwo4@&+vAwww zd+UqQH_#n_?_d9W@teQ(8*%ZO%lhCjzV_uW2h)uQ)nD%2x*PXbwqyR;m*W27a!gLo z#`Wv($3OVj|Bd*{SN~G{Lqq+jFRosDHlBO_`S||#UW?`Rjd#l;2D;g;mq8THj;AM>*TEfQ^`55fzwvjUSikcm#6>g_%+xWenO zGZuXp-fLuJ#JmnNG@J=r!b7w1IL;t9tgG}<-b0hvvEWcN0HXqkK>FS~Trhy|gl7fb zfZ4pW-ecs4-X5s^Oyl(2Y%~>?Iu<6_EXEiOfA36nI8Kaf2ieg6@pi|&2SJM=iFW-R7HCoz8StEvUEgUV@`r0iK}Ial+;e%4j>WkN0VYhQhfwqqQ^(cc{I71T;go%whe zzTzjRbw9UlpY?CjCI^hTEsG7hg};COwXenf+qa;Eo^*!pWUrOG2yCf;kp`3D8M~2f z4v{g`me42ob|yEoO4@RZ(zWaYthrYr$bdW}kATBT^O%s9a&h(__!IGNiU%&yKFGfC zRl6z=_v{#ej>S@<@R9z_WHcsz_!te9#gpeH>rh6H$-&61Bq17>f2b4hOaoMw0t=yQ z>fFF##lrW977nUz7|4gzf5yezk2LC{7kVD(vtiggoyvf$>pr10tXGv!+EcEnUnxdT zuE}R9W6D8i;i~W~lsp%Ox$TJ8@l45qrN4Q=JC^@D-}!|vyvWz({YN?8Dptn-7|!Ek z`L6odL3Vk=v+1KBiL0m6jPhIKlm37sFoKTYfi*=3_h@sB_eBpvg6KMu{;KH>Z^lY} zwL!VH~+J0#cxF@ACcFSaAGT;2tzsCC&7rZs|=tTh|FO0 zX^HWO699R22kf* zmEVJPhc6ChtJ4+OcGf%NYe02nU?jOu&j5>015{R6e7)}Zo-*X%OL|U+6-^|gFdTI$ z%obOk%eyQ`zH@QpT`v6>fs5EMx{BeiPcRcIkl+-Ou>b7%{bp~cVolnm9XkzZDm=4poBm% zw)MfjxO3~K(`36VRwu#;egCx|#?0)jVS*rl0JZIHoEx#Tljp9YG&G!5R+N0S2ue>3 zw8tmiV%Xc!l;DaI0^SNCf|b1+n_J#Og&A@dEYuFvc}VZp*3$S3(*;w5A+@!~YHHO* z0s^x)G4}FY9~xG^g0}<$m^`*^Azd4)l^+Te6f!725T3yeJQ18!`$EuT8jtb74|3sT~uWUun^@TW|9FC(QHq86@Zc>^3?e1D! z6bw*Am_hDBIR%rf2+A)Fzx1=tz6K1qFV_^XsSiG%nJAD~;Q!};^t~rS>wXgBFMZcW zMim?YmOyF0!NJ0ruEex4PHC~aQxU9e!uTr0iGGa3-G}iTzy3;$jWyzH5|lSL_tduC z!rwh_Zw-73T|tR}pu&}QCd{jygj1}pN2v9=aL_DZEzgW*&WdCUbS6(AKw1e7j0JNW z{8Umr1~_1faN(Kh7H*lLuKo?KT46{YiSuqlL!e3r80bphb-VF~a6MZg>Zrs~U7(5n z4zTeq|B_DfP4)$x^Wsy39^pBK=@jl!ezGb#W3fssXKy3CKv}6LN;dTcc`J{|L*Xc! z@Cp|Ez%Qktdz5{S;QS~HILCdKwK&T8@H1X1Rw0y@`sTd_JKZ~J%HjMa2#RJF!-|64 zrxE<97fRh?!&cv%6WXGX=OEKQ+STUDtqPip!?3gLA{5_zd9fcbDUx|J&DM>&?X~gtV*c6LwF`_`64Y;!0UR zBrU)G;Gc22a`~K&s|~v(Re8`1m*MG4*pGK-5q-zcNBPQ~;X&fQaj0^}1^@Y>`n1r5 z>Y49!JyO5#Wv3cFj0_Kp$Eb@AVlZh%kKQ#!e~!hUj1LV8vG&E|9>=rSE?JQ`IW}Sg z#OC^jkAE2GuZzxz7a8m_-ER&K#-aEac3`3JL0{ofS}mnFJ|1oLhYj^XCh&L_Jatgn z8SCL4Fmkf`pYDZn@r2c2@_icP2YS0>tXYq_>4}&eVaw)$7*bh>RZf(O-m+4CgDvhj z_m)*Tj7J;`lEz-q5>*-+CZycR(;4ZK^#5L-K|fT3lKZ&zIY6ALx72TG2ubyqurP zHj~4G6%(a)F=VTpqs@_+7#{JFAwE_^Jn7EPw!cY*qROOrJK}E-B=e*qFw5yO>0LUW z{KmiOAIIf)oz7{TexCPxcQ<4GwS|h#eX=uvIpg>3|KjVh@zzq6Y?fA)@OvD0XHTEp zJxSv)B`WlaR2Yxc$Ke=9UMl#`jO9{ z7JtC%U($0~6%Tm{{*AGg0-Ap`@2EbZ=R>_Obdgp2ijnou5A}df@|-^Ll~Kc6SL;gI z_?)=YQ`4ebyYYL!_jlvH>+i&yufHBwo|=g9>CyPrFMTmycf-8ZEG#T~)&9LZ_iV^qSYDQ#(-kYLE2dMPh^z9hOGZToGf%1VQf~NW_%Gm- z@RnD_%sZ;TLn|^gVrP5DyHK?y6M8bPU}J#jHT(~-HJs&=$4hu|jwv+ah{-!@KencZ z@5P`1kI1TDRxBq!#JAA%oD9SF>9Re+56=F@AO$Xvr&l_SfW!s=h3Mad5( z|4|MSHNMLyDEZ+lT@51#R(WUIzCwTbM(@ohL*E^yd#?0ddC0r_jju{WKLcCuNB!P6 zqt$r&17`p~t{Yr^BcA@||0$YF-vi;3H&%U+cc?iqw|vC4@`TY>nY`?Ns&UC%KMT&5 z!Sx~S!ng=K4S48lCnFP2gx3A+jlYyrUgZTQ#X&CBOg8pzil6zjfBwf_Aiy&_#4*7b z`ig#IdrM=b_<#BkxQhcm;2SVuS3z)xewVaXxb1dG%)#>=ya1l|=X-cGbSI4O$VA8| zo_waVaegp*Cw9WxRk}N^wq<5?Jn%SdHBR@Y9Vmxa+AB@+fj=P)Cd{<=QWmBSU3SG! zz683ezOLsiW6GZF&;VZrwBSnE7o?$n)07_>8W7LeP``vf>+>W%j@KAa9XM|o{PCCp zKZXtf-bD4HUs!Hb`uUvKa*ua8_*RW#+^T%%JwsJK`(O7;CxPJb2R(7}$`Ae1S3mO0 zdq12$f0*+(dHabR$s6}N5}|#3^-n&y82nV_$#R{2L>+)JxRPky?D!nY3%C2;2 zcW{}VAQ>0Y-=JfJC#bbnVto60><>-He*cKS`nYcTWI6uB+3WG!pPGz5K(q*6+x);UPH6v^IY7+ z-{v#b$jbPyitiBDGs7JQN0gb(iuOm1Ug#2kB zhH)Mmj4aOxX&73sUcM$_cS20G1k2`FjE?DE41pDz24@O>tmZ^?M-RlcEbP-Yl7%1pai*p;K4d_(&Zmv3+@ zf-@_sDGx?$n7Wc@sW*YP=l1@i%&E(NJ2z z+=9G?7jQKD!D+wKwbV1O3C9vvlo%MFxX&wscESw*<$v~rCqnCf660@%BrUQ*QT28| zR@v!?tc0fzQWs!=@|`nf>iyku?ectl=F`u{JMX+1_wO$VuUf)E2^PII8(~Q^J?fjx zjBB3PmBIjh(MlH4TDDzAyhI6cVyy^9uS$uCVpDBOr$%_#=UG0DVHk?jcg`rba7SAD zhBSzeV${k_+Em{`eUA?L&33eRSygW1GRij8LhdTMrci^+xQ=b-_R~M%v@eeG5hI0C z^)cY5et~cXJ>x7SCYaz*hO(LsoFgf(CQupp#TkTPN=bNe593m>;&^X6W~attbA35BRu^NSuiFZ| zP52Jc(jUG3uD)Sq=tztW_xU{7t&R2ASX+%@@i`nt!SNDXTRZXMr$6oEB!UcbFd~HX~g(2=g>07bSb}~m{H$@ZgOs! z&x99WP_GYoOF_1v=DagjDYsj@?yK}!jKHjTU`GNBDbQ1BD|CQ$3}`ZL0dD||f*jtNT~(N92d{&1`-mMVL{l&*!F!?ng11Ay zXoxQ@d>)hFj*qjwpkL5#$|)e3HbOhR#jDCuXs%k?zAk>2dcZ^8ynRdbD^~_G=I#qE zyoIW+-AbSFf>+5UYDS zwmpEWiE_#;x?pzgiYBUSgcnt-f;^6lC5IJS<*eOwh9;U*5d3@PoWblQG%G zC3q0U#rO;U(x3a?C&mA%e|X#HszfNN;q~BKNQCsjM^6rO-&45C2(RC-enx8(Sr-)EN1_Qd90Y21?HY>OQuL2w~A_G&x;TeG^am^zV26WUmZP5WH zdJc-F9aeO&TlCVCH$`6<8{oI0iN-9>Ayya$VJ7*qC4HG3jO=6MuiBZ(a>zhlrB1tL zGe=Fd9D@QzVT|1vp(q#;vH8z%$9&hN*${;k_F z`Nlttx$pgF(brzn*eYBXI7->wUdU5=P6H6_E>D|h)7F7uEVobcASsISl;c!u8qhwJQ!qVXNaQD^icwgJH2x;N z02ZJnlXO`5@AG}-k^e^qB}0i{V`5%Y^l_vizKqFv>c30|&egtjP|Be`0PYD+)~oVP zY4YA)_uh7zF!!H)N7?wEPUC0NDp#e+73Zt}`Qe@7)BF8MIvLLahQ3_Y?~3Q0uX6tF zc>XZww}Q{3VpY`Q(GEP&N6Nu@oPMuhzWP9Vl!H2S)Po>D3BQn`4QstuPj>s|_)Oc= zpP_@7bz?`x`_ec*q4t@67{~Du^zpWcr8!?W6qwpT=UI6|=L(+je zISw&imo4xavsi$_1b!xGvp9wG{F^=dF}M2d7(CvIz1nyj^giAs=HbJ&cxC@P@mulj z7_FVerOTH!ezHqnHMv0b5em5OhB1W#-ayU&`JAqLM?CHw_k-@-_z;*4~NO-%_ZEHZy0tQI3jmA8beW#?9!t`>p7I>wk>?*Zx1zvvETM zK}8%ZpXq&k;`ca?0qjXIls~EQ7iD#)@z(|`7!wVOr_6|a=ly9}xz9U?rNEI))dw5{ zbjP=y@p0vw8r)qCf_J=H5$IT%f@)%%CjW(IF@`7Q;)GnZ+deN)B^;+)k%U-}Ae z6hj9vGLwOkMT}&x-qrdCO`0z6nDiai^F(; zVH1W3BPHkF!A!x#vl<52VY~%zSW&UOx*nqvf-%No#N<0XY0w5%3JM1)AN9g;!Z{h> zGh1Q7uwz(eMjnbm(m|l(8yGZJZouG^_VV(wl?SAWAVGYT3L6_6R`MZmkhhua%8@VS zAaA}wk-@n!+glq7%X5TbBuRrjVFo!*1_#4QOCCuWM*sp&q*WN6Vt__rkvNh{P2!O+ z=~5obTW4wJ7qso_=^hcrr zLOVOo(j4#Vji;kGUhe9PU+J#J6lcDw?*kJv&@ixqZxK59lrmQsYo@nc@sy8t!mtVc zBV>EEkG$K@*L+4W{Fi_HL)Wi3^7yz882zLxe}SDnaa1l=`W69_Hsl@!oehx+8|>?j zf!>JEyl^c>oAtQy-uuG0H8J?1{x<0Ih@hcXBIp4Q`^%fxw_q1ow~LaQ)(;q4Gg|~N4kiIZZq90 zD8H*_$0neV9J0Nkty%7TOI+aOhsx1zrR}&{h^h+XZ{!VM!35!)v&x}0R^Ed52W<=0 zO$pFGr%6d29UWM>vH?TiU`QnkpH-%~O3t*`0+u}Qz$=un;1+^3ihssa@UqZ&N@>qe zb)RWvANIC>sz2{}h89|o z`Ju%1s$UDCv;%midkRq%jJOGNur|k}jF<07DV14Z7LTGO!W+(rW@3Qr&seT&=Am&` zI9C%bz_3A^?(VX(Z`aBeR!FnTZ*gfw!s)h+OjF~NhBby9CNXi|*XGuy&kN=#0s6Nx zaQ>9j#ZdV>`*C@8TM1B%zqAE0GM-Cs$0M*L#D;PA#hjqvi3@;>2>G>qUUqM+$MRR+ ziS6slakQOE;w}`PDmxE{JNwbPwH|BVxfOT+;D>SR|NGt8y~&x9RT^B&?b*!}bx(Zd zFW*;be3G;taP)UBRhl12&B6KZ@xepH$Bg`lXb;zkXSxVizp1W%ekd;Qc!{!JSfH^M z9%D=Nu;mFSQ{y9X(%y^tsfp-2+4n@A+c&Srwab^{>gA_neRWm5(PnI{Z^YQxxOp1Y7^Bi+?^RXiShm~wATRS#zjOg1`ATgaM707J!%1SGE zI<{vX9;oFilEJp+d~7lJ+>hwj_6fGyb83|vw{7&j z@!x+xc5aHtulhsvQ$3bc)A96R$R~48%J|z_+wnNT_${mxe~`O{u$l_KAh&g7TxMbr zV^`U#l|12Ja|~DK(T_$D-IrCrk9Nc>W506rc01-C6pC?=@r0G1#So-)^uAj>vt?xU zHT1d|qnA~RLsQQWddqq?(ik~p> zL_S3|&&79?S-hh89Rq_@sDaWJoYH`-S1Qz?c#{`ics{=RFTbpGkJR_OV`^d~CTAP* zZ~fc9A5TC3Ote`wD_S=%`u6Ud@2aov$BJZ&=<1LE;s5vNasAGE{NC^W9o3^2FMjG% zK8lBa`OMX8p4j`vU;Q;-Uw{1_@gDVf_50t8n&=Vy#Fpsgie%Rdl23OWQlfZhDBx@$qOVO=KeI5A{xCf5On;h(1tfw@n2a+6~#s zGO=N#_vSBvk9ZHq0S};c7;PnEH=1I3dL>uxo8Ca@pzSmu-^1f7fKM#*vP+d^BDL!z ztE@c{iL)S?tlW-9vte37TOvdIe0u#skC36+ImSB@=zU9L7`s3)L6Q}_jiCXTlkow( z$Z{vH!xtmVVH6{6TuzWw$#^e31((@=9NwIFme&|D!GF_QzM;od_W(@}7}^*v*g&sO zjlLCb5!wCBFwup98|Uv-JHuFb>NWvy6JMRW`>4`fd^dW2@Q2ZL_w{Pw1p|(FXm+_G z#=&OPHm*nW?pI^#&3_m(Km0GEzW$C%N?8@d=_y5uL4FAy_eIKK-j%Yr%vo+$@l!>@ zvd=+Z@|~jQ_$~M|p{cj8E4F)wp9rn{g)#mj_o@!`ceZ?9x_`%pUt}|OhtrTLJU;er zZ}h>@kx?fA4gl}ed8F(Itzta2p-uP%U`t*FN@c7s?O*gi&1TbbAKxRRkQZ@jJB+`` zI9n>i-aZqkYm%o2RBk1BoI9>j24p_y26Ph{8NB!E|GjD;fO6ny zN1Bqp&!jmfIDm8D!;pBG2`1qUiud7K8G!40hL$rv8E2FLeZaeS32)g=F?W^I)#F4N zFLL|_=iG~Xy0Tm2BGGC<2t>!3>+iwQr)I_H-#roC+l))hEG zou~?RhSyElFvbfv6b{|Tu<8km!Yj^g@9#%{!H#>%!9;~LM2nT8^+d`a2aO|d`T=P| zPto-LwX0>(QGfqrM{|pIiTO%=c|t zkA#kiabDmQFZ_-;CW!Xc!25`_p0q>Ud=d=hPs8}jh?3|2 zCLJ}iQo*J3-tRi@Er`mMXB=VWxdiiE;&!^zu!;fTw|rk-F#wl%46Mn}pXFEDu!NnJ z8Ru*D&W8I2Anid>Hfq4DhcO_&p zt5RhZd>0p&PU~)lOE5+-g*iuv#z@6hpsTB^N~6olK30n{lbJ1)+1i=2`LV9eWkMi@W<0KZ_0VA@gG0Xvkc#78lRL7MlR@j^Qk!!hAJlQvfX zjzW*`C^tUaIgM7V^uRdGJ$WF6Pfd<{WeCsY%{$sT1#XnPf~msjC#)(dFd|RNk5G@1 z4_ES{&1nPD#8Y0vuhxd+mA-nsB%$fK-dbGj>5CD;6xh(Fo_$&gC6puESqW9;E{<{- z*Oh;PhYggvW}U!iJric1@GMu(+4|a_zV$?C-6M^^B-QDCIlZwbnguXFR-IXJ*IXj#lNEf_vJNv72Y5rFPr(K2n{tPehe)cbdw8|q`qZDAp zn&De{R{jnR)>JQMeCwUyZi9xB)^5Dt8xRpgxt6G}w8RpXY!(`P-hJyNMj{s@MI(T+s#@|n*lBlDYV*P>iOP-W{? zzJq4$?eBR)3KM%gxkqilR+n4as@lS3tqe)9c(xgi-+n3_0%6JP+s~HZHOQ);*=lej}@Pkgdu-_c_%jC zxF5@3doLFLOH+%jP}Zo;#c|kS3V!IT#s^9ogQ$H3UdOK zyxbRe;#Hkbg4X?1jK6BD1ciU9`>F=qbD^U+&wT#zj);#L`9q==Tq?Mw5z76;eO1rp zTH3RCa6uF^y49)rg)i_>l>gvhFZOn~V^_S+_R4a6?!_15%EgITTegtk z_^?gUw=^>5mhYk$DjzHVQ0Nb9T$vspjk%dA^|>jPVN(2^_z%$&l=H-A(%O{5YXk6& zy*APg4YA^u)rsog8Y7@VY&SSOGOVyPx&j;eKYbs%>RlBCA8%K!^hbr0HXxiF2ImG7 z4+AdWu<9+1T6y*@{jWaQ6wG^-mh!J-1nG%pBaOeni``*{RhNzJJg*gA6CMwm0v%=2 z9CVq!!xq9UrT)E&A23`gykv z(OR~L9#tC*W9051h+*-VGiqBD!}ph$RJOzo&ibXU$Uzvwws*G7`&C$H9*c8Jdxpn7 z!4kfR@fi6isc<@Qj-N9ud>nW7eR2N&^z*!jB%X!~9=P`EZfw4_6ia`7Bkuo;cjERR zzZrM_ndsf0y&X$me?KWozir;g{V{<%bVv_N{33%{Dtl@sCcIn;T{IMOpj8+3viR=LE(%H zK|f3$J?ljoEt4y*`E4fusgIb?A`idMx)8<~>0>oiHdfuv&s~U5zwoJePcq)b#IUk$ ztFZg=g;!pR=RbWV{_gMnw))6X>`HFoJn@zLOL711V%)#K8e6;K-M{f_{KePbjN#FN z_@Dm=|9;HP&Zxidc~S~I3c7{ojpkiY0zO}N3(XX7?iR3)gZd3nVpPf*B)U*TU)Y6ULIx8%0ZM&Hvb-%txc%RPaVDS6|> zeZa{}`i)zs`j&hxlK@iy?q9Ic;P;h}{YN4v@OPrGy60Wb*8Qm6`))L@|7ncA{olpZ z+y6-ZzmCy&{@WP4`6n^7^lJ3)-q*Lnb*169^Iz86e2V~Kez;2WG*1Abb|}~6XNy1k zo_o^G^NN*^qGMxOk0-;^{UWXWRn^4*+>dYkw?@1^^4tS9R@fOHC;4M3qfiq4Syr3@_ft0VVz>+ZQZG@W`f8ljFrh}59|6ymM zq`&OSCVHfP#fsl8mEl0&)x>+y=R!PMPpH2rE@L`%V?qiz4lUtZ+R77zR3^rDR_Q}( zQy+nhtrvhro<0Ge=ZVLn&)_@!+lXjUQ!rttmXT(|N8&J{5IW9L9`s-IG{}1xeK8th zkmH$t?sr_}ZJbvBDL6;jJ$6ut%9VG1FPQ4)^etugy~2R1kG7cO2@nKArQe^t16|Le!U4?d@>-T`aw zf!8D4&(rt|OwZl9J9p>qv0WihomUtR6FL#z9Bd!-WdP3mYVfGO?Y#a^*%b!vVMn;% zRqs3FJ^alXJoCO2zW5^Oo?T13$yb9_XMFvf-ly+O_rbUscIHaC&-{a7B~D>pxx$2S zk3yX5X}Y>cVS&*2(x+dNfW%7C9Sg!J%=&t3Vl>5IhyftF&l81F!04+%o%<7AF^Zt9 z^XiSm{b;wgC7bWX*hn*WBsjC}Gltjk@yVE&o{erX0{sILnw77OtV4C5r9|lwFkoD^ zHaFzA!~nMqPZ;Cf-A$*1Fo^Pt)w|n@gR6;AVN1LmwDbHk3<2~H7$lT}ob|i6w;#*P zE8Ygk%6esL7^#A+4B3^SyuP^^Gcz-)H;T&Mc<=oiE)y`LeK7)~?PZ;IodsY(XcZXg9%rgQ$&nP%iLh?P|5QZ=9jDoN*Ii8uP ze9Ow@`}gnLXgo49VnKzx$OlI_LO=0Jc@V}?egX^1MtyjXr>RgONp{l@mWC zj3DGF4-2{#ZB*f0Ps+gcQ6Bh#&yR}ZcPhsN{*d#x&KSuj?c5h1@s}_8SN$p)k6??^ zjO}-62UXij4Ve3!VUM95exJn{GUwqtH)O#Qh(?%%r`8|!R!r#`{5YQeXy{%VD! z@Rs_c;GvHoD2p?T1_|QX4l0BCYP+rSC~eoD_5~hFUl{3o(sdikbLE+P`mvQN{s2Kpak-cG zwt^}LTMH`KSC!iL`qEdN=}qNrJQlr^*yQq#H0m~vjSe?#1Rfo2o(k2IMy zzDYXWB1BaMJL+Qvsb0}vDWi?a zv<7f=4KOaBh;HO|lZ0U`;k?0SW61Q`t8?@{_lZ9!#=6`tzNg-zuf$7*Lci)ZpftgQ zT+xJr8zsoW5pAZnui61`T#~22z`L{&eJ+)ROcoG5-e(In6|9*E`i!@(otwL8JYHB@j@x(c#PZ5&tgdZ1jIH(AL1K(E zJ%<`@Ukl;j2SD{RaFYYT`d5}!nGv}2o#XPpIO6G&@2l}&9tR#0X5pSc`Yz2`ePgA* z5fZ1X^Hl`F;Xzv9x79CkN@f*MQw_{~#AwK=W^D#3uc}mBoCNONG7}R*K&Nn$R8FLrrG=3k%n)(fA z)UvfO$|w^~^;NEnDHv7el-33LiDB`F&;!wdf&QMjI6o5;<0COTG8`8#&Wn#?yk|#& zn);u{4bcD=f{umk<5}jm~13S2g$L#4-orXo11qW8%cm;32 z#+bv{6(7?aAB(-?!)S}fvufkbx8Cv*2UDu&UTe?%2Z~wvo6U_)(>>q;jmU|7xvepV z7RIk3!H=U$pl2vi**&Hy9&Al~+yUc`%4=nwV2q(3`Z^>UH8(pO@@PiPl^WUBQNQNg5^##tCH6K}pmwfEuC%6`v zQ?{&{zxTBY$@KUh9s~mcd^x-UGzsHyuhU|TQ;Lr7FO?>fhA~@Z+2JqXGt>vTDlKnY zs&6@}aB+c)Xx`Ubkw6%%94_}u3|>prk9`sMGH=X*c8 zuKMkA59s~A@=~9cthp!og+5I?QD1g*fHrvx=7dJlRC)Lg z!@J@k3Y_r7^o_oCxIATp=5Y3K;z#DeSV1xe;`5lKsh6Jc)(cHg-FiifMnn%-5muAj z-RsrgtO^})yD`pi<~);d)M$bOyxoz{GlpuwBd`TNG5|6HlkO?lvGT)FCJc?pWzay3 zYm^Ea$f`$HV3H4GfzU1|^QivNJ?a45JxM{;VMRAb*9cKuubfB$eqne*ZcrNmi>x)( zH(WZe$>Udi4J8FQq@~P#{!vDm}ri+|yL{@NY-(d)ZDl zz6l>|1N1@h)cqI>oh>4mzaicHUU{4UQ@RY==v0WPYvwK5p&R&Qu6k59$_p=edBv|X zO}*cPo=F9V=CcKNdnS!j0228nbOsGS$T9Nz16P3+xWt5t_2re=S>K30)t@u-(Z3*8 z6dXW4@v29CiwuX1<@0t)M`@;vN;Zj4jPKw)j{H1f85ov!qAbEsWG-YpPxMjW@y>U= z<}7VdxqY?s-oc5FwqcheaLqKY>&>VNE*f^NorSg?XeV!{{`x(O>Q zeao0YpWsT_J?TJsrU!p%0IpoS0&K^wsit^+Z>2cQCAhIPK3Ic zr~WkZM|-F7VXnlhTxa^7Wp#Bc@A}Fo-B3W~c}=T0nt$@9#Lwes_y$;~aosDf)dm2-_0IXd1`8p!(eg&Zq^S-1w{laJXm$XcPJ6})%MJU_H0TEb$Y+w zHq(Mpcw=MT1}C;BVY`n!GgQL9m>i5q+gsbQyR#ir(=*Nk;~|3L`sNlj@v1`%(kYB4ghl@=>5_QlA+u)-AGy?am0)No+@HNz~AQQ4~zl`iM6 zp-hAEV5^h$jZF)=C~eZ{D4|yQpm04@J%AtW%RLGY44@cI&y1|cQ6J=B;yKdjp zuT|a;b$SKEKhfA_lZ zm9wqY)@l=0NVaXjBh}2S%2b}8gd6YzZa@+e2ps}9xaK)X5{4C@eoh%MNLwbZ@NTcQ zW98U>Tlc#=>D8y8B?vOKI>L|py6~+gfoEj6VPgWyMSNKyo-^}lY0BUtx~$p8Zag~I?=m9DEyC@jalU1HhxS|Dm@U{KfT1Lyjuyt;S6R^ykDseG2&V>Kkt+dBKTZRuDE2rDe99AeQ2CtQ4=e+_J0X+6>NbuX?o`jU4a{YjW(vv+~;;> z3D43GiAx5&vy#nFB^TiAo-Kz_xJz_5pZPXv9`&GZqPeOc>7gj6&(WUj#=z>Dx%rEt zHxr86BU-oN_m*N^;|bfCGvlALec9OnoPdV2YHx6$t~}YwDkmC{C%9p{ z2hQMK!gOw5*G(bvr}Y8$lvS_=zTlRln6@EQ6H_qKx0zZ=v4WQ$GraRJU5Q`$a%*>b z^8{R$!Uc4WpW6k*2{=wgO895%~;!_vn-FM!#vYm4w=`$#NR@XP9zut%=J>OYb z^QsiDEK&ZfhCz`D{bsdqqh5>Isfl=Mb|x-PjVZ73n3@<9Pct4DW~Rhnj6fjt&5^>U z&1*3kjGa`VE%50$^A~~%e1mxq^+5~}jAZab@FW-+IB#-7{Tn`tl`l-1gGORJK*@e` zcr4mHq;iP{i;h@kP`YeUiW0xhR;S&Z;U^mFt(}>;G-&=4zyN-Dv&{|8?A(aKp_*v{ z6V9NejA0xZg29+=Q=u>3dS2hP+16T6f_H$%dG#CPsOrKIB=AkeNK)_|x=fu}^=l=e z0E=OGYH})04o+gM$@$D9UhNA_X8dET=4+P

    fGjx+{TBpOdnXYc`ps{P-u1+n|K-Gtb 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

    CyP~zw{yiK{X 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�~L++buxA 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℘5|#7<~g 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 E~N_dK3tf+bqZ4^Hduo12i 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 z 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

    N*}2-$(iXcryJ{y5 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]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

    4&qQf{Q>IPjjHUNC#V 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�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

    {knMSe%WvO2nkE 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 z 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�b}(;4Y0(tSj0*-Xyn7nW>Z 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%0Dz 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

    h|o)53MQ=Ox{BinVvTMObR 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�Vu0@5L2_#G$>GiJRs9ie23Hcmza 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 z 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 R;@ Date: Sun, 21 Sep 2025 16:40:07 +0800 Subject: [PATCH 047/110] feat(docs): add comprehensive repository guidelines and project structure documentation --- AGENTS.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..740491c5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,19 @@ +# Repository Guidelines + +## Project Structure & Module Organization +ComfyUI LoRA Manager pairs a Python backend with lightweight browser scripts. Backend modules live in `py/`, organized by responsibility: HTTP entry points under `routes/`, feature logic in `services/`, reusable helpers within `utils/`, and custom nodes in `nodes/`. Front-end widgets that extend the ComfyUI interface sit in `web/comfyui/`, while static images and templates are in `static/` and `templates/`. Shared localization files are stored in `locales/`, with workflow examples under `example_workflows/`. Tests currently reside alongside the source (`test_i18n.py`) until a dedicated `tests/` folder is introduced. + +## Build, Test, and Development Commands +Install dependencies with `pip install -r requirements.txt` from the repo root. Launch the standalone server for iterative work via `python standalone.py --port 8188`; ComfyUI users can also load the extension directly through ComfyUI's custom node manager. Run backend checks with `python -m pytest test_i18n.py`, and target new test files explicitly (e.g. `python -m pytest tests/test_recipes.py` once added). Use `python scripts/sync_translation_keys.py` to reconcile locale keys after updating UI strings. + +## Coding Style & Naming Conventions +Follow PEP 8 with four-space indentation and descriptive snake_case module/function names, mirroring files such as `py/services/settings_manager.py`. Classes remain PascalCase, constants UPPER_SNAKE_CASE, and loggers retrieved via `logging.getLogger(__name__)`. Prefer explicit type hints for new public APIs and docstrings that clarify side effects. JavaScript in `web/comfyui/` is modern ES modules; keep imports relative, favor camelCase functions, and mirror existing file suffixes like `_widget.js` for UI components. + +## Testing Guidelines +Extend pytest coverage by co-locating tests near the code under test or in `tests/` with names like `test_.py`. When introducing new routes or services, add regression cases that mock ComfyUI dependencies (see the standalone mocking helpers in `standalone.py`). Prioritize deterministic fixtures for filesystem interactions and ensure translations include coverage when adding new locale keys. Always run `python -m pytest` before submitting work. + +## Commit & Pull Request Guidelines +Commits follow the conventional pattern seen in `git log` (`feat(scope):`, `fix(scope):`, `chore(scope):`). Keep messages imperative and scoped to a single change. Pull requests should summarize the problem, detail the solution, list manual test evidence, and link any GitHub issues. Include UI screenshots or GIFs when front-end behavior changes, and call out migration steps (e.g., settings updates) in the PR description. + +## Configuration & Localization Tips +Sample configuration defaults live in `settings.json.example`; copy it to `settings.json` and adjust model directories before running the standalone server. Whenever you add UI text, update `locales/.json` and run the translation sync script. Store reference assets in `civitai/` or `docs/` rather than mixing them with production templates, keeping the runtime folders (`static/`, `templates/`) deploy-ready. From 56e4b24b0785d61951feab460f62861ddc237e20 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Sun, 21 Sep 2025 17:15:24 +0800 Subject: [PATCH 048/110] test(routes): clean smoke test module --- docs/architecture/model_routes.md | 85 +++++++ tests/conftest.py | 154 +++++++++++++ tests/routes/test_base_model_routes_smoke.py | 228 +++++++++++++++++++ 3 files changed, 467 insertions(+) create mode 100644 docs/architecture/model_routes.md create mode 100644 tests/conftest.py create mode 100644 tests/routes/test_base_model_routes_smoke.py diff --git a/docs/architecture/model_routes.md b/docs/architecture/model_routes.md new file mode 100644 index 00000000..d32420dd --- /dev/null +++ b/docs/architecture/model_routes.md @@ -0,0 +1,85 @@ +# Base model route architecture + +The `BaseModelRoutes` controller centralizes HTTP endpoints that every model type +(LoRAs, checkpoints, embeddings, etc.) share. Each handler either forwards the +request to the injected service, delegates to a utility in +`ModelRouteUtils`, or orchestrates long‑running operations via helper services +such as the download or WebSocket managers. The table below lists every handler +exposed in `py/routes/base_model_routes.py`, the collaborators it leans on, and +any cache or WebSocket side effects implemented in +`py/utils/routes_common.py`. + +## Handler catalogue + +| Endpoint(s) | Handler | Purpose | Collaborators | Cache / WebSocket side effects | +| --- | --- | --- | --- | --- | +| `/{prefix}` | `handle_models_page` | Renders the HTML page for a model type, populating the template from cached scanner data when available. | `settings`, `server_i18n`, `service.scanner.get_cached_data()` | Reads scanner cache to build folder list; flags initialization state without mutating cache. | +| `/api/lm/{prefix}/list` | `get_models` | Returns paginated model metadata. | `service.get_paginated_data()`, `service.format_response()` | None (read-only). | +| `/api/lm/{prefix}/delete` | `delete_model` | Removes a single model from disk and cache. | `ModelRouteUtils.handle_delete_model()` | Deletes files, prunes `scanner.get_cached_data().raw_data`, calls `cache.resort()`, and updates `scanner._hash_index`. | +| `/api/lm/{prefix}/exclude` | `exclude_model` | Marks a model as excluded so it no longer appears in listings. | `ModelRouteUtils.handle_exclude_model()` | Updates metadata, decrements `scanner._tags_count`, removes cache entry and hash index entry, and appends to `scanner._excluded_models`. | +| `/api/lm/{prefix}/fetch-civitai` | `fetch_civitai` | Fetches metadata for a specific model from CivitAI. | `ModelRouteUtils.fetch_and_update_model()` | Uses scanner cache to find the target record and updates it via `scanner.update_single_model_cache`. | +| `/api/lm/{prefix}/fetch-all-civitai` | `fetch_all_civitai` | Bulk refreshes metadata for models missing CivitAI info. | `ModelRouteUtils.fetch_and_update_model()`, `ws_manager.broadcast()` | Streams progress to all clients, updates cache entries, optionally resorts cached data. | +| `/api/lm/{prefix}/relink-civitai` | `relink_civitai` | Re-associates a local file with a CivitAI entry. | `ModelRouteUtils.handle_relink_civitai()` | Updates metadata, refreshes cache via `scanner.update_single_model_cache`. | +| `/api/lm/{prefix}/replace-preview` | `replace_preview` | Replaces the preview asset attached to a model. | `ModelRouteUtils.handle_replace_preview()` | Writes new preview file, updates metadata, and calls `scanner.update_preview_in_cache()`. | +| `/api/lm/{prefix}/save-metadata` | `save_metadata` | Persists edits to model metadata. | `ModelRouteUtils.handle_save_metadata()` | Saves metadata file and syncs the cache entry. | +| `/api/lm/{prefix}/add-tags` | `add_tags` | Adds or increments tags for a model. | `ModelRouteUtils.handle_add_tags()` | Mutates metadata, increments `scanner._tags_count`, and updates the cached model. | +| `/api/lm/{prefix}/rename` | `rename_model` | Renames a model and its related assets. | `ModelRouteUtils.handle_rename_model()` | Renames files on disk, updates cache indices, refreshes metadata. | +| `/api/lm/{prefix}/bulk-delete` | `bulk_delete_models` | Deletes multiple models in one request. | `ModelRouteUtils.handle_bulk_delete_models()` | Delegates to `scanner.bulk_delete_models()` which removes disk assets and cache records in bulk. | +| `/api/lm/{prefix}/verify-duplicates` | `verify_duplicates` | Confirms that a list of files share the same hash. | `ModelRouteUtils.handle_verify_duplicates()` | Recalculates hashes, updates metadata, and patches cache entries when stored hashes change. | +| `/api/lm/{prefix}/top-tags` | `get_top_tags` | Returns the most frequently used tags. | `service.get_top_tags()` | None (read-only). | +| `/api/lm/{prefix}/base-models` | `get_base_models` | Lists base models referenced by this model type. | `service.get_base_models()` | None (read-only). | +| `/api/lm/{prefix}/scan` | `scan_models` | Triggers a rescan of the filesystem. | `service.scan_models()` | Scanner rebuilds its cache as part of the service workflow. | +| `/api/lm/{prefix}/roots` | `get_model_roots` | Enumerates root directories searched for this model type. | `service.get_model_roots()` | None (read-only). | +| `/api/lm/{prefix}/folders` | `get_folders` | Returns cached folder summaries. | `service.scanner.get_cached_data()` | Reads cached structure without mutation. | +| `/api/lm/{prefix}/folder-tree` | `get_folder_tree` | Builds a nested folder tree of cached items. | `service.scanner.get_cached_data()` | Reads cache; does not mutate. | +| `/api/lm/{prefix}/unified-folder-tree` | `get_unified_folder_tree` | Returns a tree aggregating all roots. | `service.scanner.get_cached_data()` | Reads cache; does not mutate. | +| `/api/lm/{prefix}/find-duplicates` | `find_duplicate_models` | Finds duplicate hashes within the cache. | `service.scanner.get_duplicates()`, `service.scanner.get_hash_by_filename()` | Uses cache data to assemble duplicate groups; no mutation. | +| `/api/lm/{prefix}/find-filename-conflicts` | `find_filename_conflicts` | Groups models that share a filename across directories. | `service.scanner.get_filename_conflicts()`, `service.get_path_by_hash()` | Reads cache while formatting results. | +| `/api/lm/{prefix}/get-notes` | `get_model_notes` | Retrieves saved notes for a model. | `service.get_model_notes()` | None (read-only). | +| `/api/lm/{prefix}/preview-url` | `get_model_preview_url` | Resolves the static preview URL for a model. | `service.get_model_preview_url()` | None (read-only). | +| `/api/lm/{prefix}/civitai-url` | `get_model_civitai_url` | Returns the CivitAI permalink for a model. | `service.get_model_civitai_url()` | None (read-only). | +| `/api/lm/{prefix}/metadata` | `get_model_metadata` | Loads the raw metadata payload for a model. | `service.get_model_metadata()` | None (read-only). | +| `/api/lm/{prefix}/model-description` | `get_model_description` | Returns a formatted description for the UI. | `service.get_model_description()` | None (read-only). | +| `/api/lm/{prefix}/relative-paths` | `get_relative_paths` | Provides filesystem auto-complete suggestions. | `service.get_relative_paths()` | None (read-only). | +| `/api/lm/{prefix}/civitai/versions/{model_id}` | `get_civitai_versions` | Lists remote versions and indicates which exist locally. | `get_default_metadata_provider()`, `self.service.has_hash()`, `self.service.get_path_by_hash()` | Read-only; consults cache/service indices to mark local availability. | +| `/api/lm/{prefix}/civitai/model/version/{modelVersionId}` | `get_civitai_model_by_version` | Fetches detailed metadata for a specific CivitAI version. | `get_default_metadata_provider()` | None (read-only). | +| `/api/lm/{prefix}/civitai/model/hash/{hash}` | `get_civitai_model_by_hash` | Fetches CivitAI details using a hash. | `get_default_metadata_provider()` | None (read-only). | +| `/api/lm/download-model` (POST) & `/api/lm/download-model-get` (GET) | `download_model`, `download_model_get` | Starts a download through the shared download manager. | `ModelRouteUtils.handle_download_model()`, `ServiceRegistry.get_download_manager()` | The helper broadcasts download progress via `ws_manager.broadcast_download_progress()` and stores state in `ws_manager._download_progress`. | +| `/api/lm/cancel-download-get` | `cancel_download_get` | Cancels an active download. | `ModelRouteUtils.handle_cancel_download()` | Broadcasts a cancellation message via `ws_manager.broadcast_download_progress()` and prunes download progress entries. | +| `/api/lm/download-progress/{download_id}` | `get_download_progress` | Reports cached download progress for a download ID. | `ws_manager.get_download_progress()` | Read-only view of cached progress. | +| `/api/lm/{prefix}/move_model` | `move_model` | Moves a model to a new folder. | `ModelMoveService.move_model()` | File operations performed by the injected service may update scanner caches downstream. | +| `/api/lm/{prefix}/move_models_bulk` | `move_models_bulk` | Bulk move models to a new location. | `ModelMoveService.move_models_bulk()` | File operations delegated to the service. | +| `/api/lm/{prefix}/auto-organize` (GET/POST) | `auto_organize_models` | Launches auto-organization for models, optionally limited to selected files. | `ModelFileService.auto_organize_models()`, `ws_manager.get_auto_organize_lock()`, `WebSocketProgressCallback` | Uses a shared asyncio lock, streams progress through `ws_manager.broadcast_auto_organize_progress()`, and relies on `ws_manager.is_auto_organize_running()` state. | +| `/api/lm/{prefix}/auto-organize-progress` | `get_auto_organize_progress` | Polls the latest auto-organize progress snapshot. | `ws_manager.get_auto_organize_progress()` | Read-only view of the WebSocket manager’s cached progress. | + +## Shared utility side effects + +The delegated helpers in `ModelRouteUtils` encapsulate most cache and +WebSocket mutations. The smoke tests in this repository exercise the +following contracts from `py/utils/routes_common.py`: + +* `handle_delete_model` removes matching records from + `scanner.get_cached_data().raw_data`, awaits `cache.resort()`, and calls + `scanner._hash_index.remove_by_path()` when an index is present before + returning a success payload. +* `handle_replace_preview` writes a new preview file, persists metadata via + `MetadataManager.save_metadata()`, and then invokes + `scanner.update_preview_in_cache()` with the normalized preview path and + NSFW level so downstream requests surface the updated asset. +* `handle_download_model` acquires the shared download manager from + `ServiceRegistry`, injects a WebSocket progress callback, and relies on + `ws_manager.broadcast_download_progress()` to update the cached progress map + that `get_download_progress` later reads. +* `handle_bulk_delete_models`, `handle_add_tags`, `handle_exclude_model`, and + `handle_verify_duplicates` all mutate scanner-maintained collections (hash + indices, tag counts, exclusion lists, or cached metadata) so route handlers + can stay thin while cache consistency remains centralized in the utility + module. +* `ws_manager.broadcast_auto_organize_progress()` stores the latest progress + snapshot consumed by `get_auto_organize_progress`, while + `ws_manager.broadcast()` is used to notify clients during CivitAI bulk + refreshes and other background operations. + +Keeping these side effects in mind is essential when refactoring route logic: +any replacement must continue to honor the implicit contracts the utilities +expect from scanners, caches, and the WebSocket manager. diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..0ec41c73 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,154 @@ +from dataclasses import dataclass, field +from typing import Any, Dict, List, Optional, Sequence + +import pytest + + +@dataclass +class MockHashIndex: + """Minimal hash index stub mirroring the scanner contract.""" + + removed_paths: List[str] = field(default_factory=list) + + def remove_by_path(self, path: str) -> None: + self.removed_paths.append(path) + + +class MockCache: + """Cache object with the attributes consumed by ``ModelRouteUtils``.""" + + def __init__(self, items: Optional[Sequence[Dict[str, Any]]] = None): + self.raw_data: List[Dict[str, Any]] = list(items or []) + self.resort_calls = 0 + + async def resort(self) -> None: + self.resort_calls += 1 + # ``ModelRouteUtils`` expects the coroutine interface but does not + # rely on the return value. + + +class MockScanner: + """Scanner double that exposes the attributes used by route utilities.""" + + def __init__(self, cache: Optional[MockCache] = None, hash_index: Optional[MockHashIndex] = None): + self._cache = cache or MockCache() + self._hash_index = hash_index or MockHashIndex() + self._tags_count: Dict[str, int] = {} + self._excluded_models: List[str] = [] + self.updated_models: List[Dict[str, Any]] = [] + self.preview_updates: List[Dict[str, Any]] = [] + self.bulk_deleted: List[Sequence[str]] = [] + + async def get_cached_data(self, force_refresh: bool = False): + return self._cache + + async def update_single_model_cache(self, original_path: str, new_path: str, metadata: Dict[str, Any]) -> bool: + self.updated_models.append({ + "original_path": original_path, + "new_path": new_path, + "metadata": metadata, + }) + for item in self._cache.raw_data: + if item.get("file_path") == original_path: + item.update(metadata) + return True + + async def update_preview_in_cache(self, model_path: str, preview_path: str, nsfw_level: int) -> bool: + self.preview_updates.append({ + "model_path": model_path, + "preview_path": preview_path, + "nsfw_level": nsfw_level, + }) + for item in self._cache.raw_data: + if item.get("file_path") == model_path: + item["preview_url"] = preview_path + item["preview_nsfw_level"] = nsfw_level + return True + + async def bulk_delete_models(self, file_paths: Sequence[str]) -> Dict[str, Any]: + self.bulk_deleted.append(tuple(file_paths)) + self._cache.raw_data = [item for item in self._cache.raw_data if item.get("file_path") not in file_paths] + await self._cache.resort() + for path in file_paths: + self._hash_index.remove_by_path(path) + return {"success": True, "deleted": list(file_paths)} + + +class MockModelService: + """Service stub consumed by the shared routes.""" + + def __init__(self, scanner: MockScanner): + self.scanner = scanner + self.model_type = "test-model" + self.paginated_items: List[Dict[str, Any]] = [] + self.formatted: List[Dict[str, Any]] = [] + + async def get_paginated_data(self, **params: Any) -> Dict[str, Any]: + items = [dict(item) for item in self.paginated_items] + total = len(items) + page = params.get("page", 1) + page_size = params.get("page_size", 20) + return { + "items": items, + "total": total, + "page": page, + "page_size": page_size, + "total_pages": max(1, (total + page_size - 1) // page_size), + } + + async def format_response(self, item: Dict[str, Any]) -> Dict[str, Any]: + formatted = {**item, "formatted": True} + self.formatted.append(formatted) + return formatted + + # Convenience helpers used by assorted routes. They are no-ops for the + # smoke tests but document the expected surface area of the real services. + def get_model_roots(self) -> List[str]: + return ["."] + + async def scan_models(self, *_, **__): # pragma: no cover - behaviour exercised via mocks + return None + + async def get_model_notes(self, *_args, **_kwargs): # pragma: no cover + return None + + async def get_model_preview_url(self, *_args, **_kwargs): # pragma: no cover + return "" + + async def get_model_civitai_url(self, *_args, **_kwargs): # pragma: no cover + return {"civitai_url": ""} + + async def get_model_metadata(self, *_args, **_kwargs): # pragma: no cover + return {} + + async def get_model_description(self, *_args, **_kwargs): # pragma: no cover + return "" + + async def get_relative_paths(self, *_args, **_kwargs): # pragma: no cover + return [] + + def has_hash(self, *_args, **_kwargs): # pragma: no cover + return False + + def get_path_by_hash(self, *_args, **_kwargs): # pragma: no cover + return "" + + +@pytest.fixture +def mock_hash_index() -> MockHashIndex: + return MockHashIndex() + + +@pytest.fixture +def mock_cache() -> MockCache: + return MockCache() + + +@pytest.fixture +def mock_scanner(mock_cache: MockCache, mock_hash_index: MockHashIndex) -> MockScanner: + return MockScanner(cache=mock_cache, hash_index=mock_hash_index) + + +@pytest.fixture +def mock_service(mock_scanner: MockScanner) -> MockModelService: + return MockModelService(scanner=mock_scanner) diff --git a/tests/routes/test_base_model_routes_smoke.py b/tests/routes/test_base_model_routes_smoke.py new file mode 100644 index 00000000..f6674c08 --- /dev/null +++ b/tests/routes/test_base_model_routes_smoke.py @@ -0,0 +1,228 @@ +import asyncio +import importlib.util +import json +import os +import sys +from pathlib import Path + +import types + +folder_paths_stub = types.SimpleNamespace(get_folder_paths=lambda *_: []) +sys.modules.setdefault("folder_paths", folder_paths_stub) + +import pytest +from aiohttp import FormData, web +from aiohttp.test_utils import TestClient, TestServer + +REPO_ROOT = Path(__file__).resolve().parents[2] +PY_PACKAGE_PATH = REPO_ROOT / "py" + +spec = importlib.util.spec_from_file_location( + "py_local", + PY_PACKAGE_PATH / "__init__.py", + submodule_search_locations=[str(PY_PACKAGE_PATH)], +) +py_local = importlib.util.module_from_spec(spec) +assert spec.loader is not None # for mypy/static analyzers +spec.loader.exec_module(py_local) +sys.modules.setdefault("py_local", py_local) + +from py_local.routes.base_model_routes import BaseModelRoutes +from py_local.services.service_registry import ServiceRegistry +from py_local.services.websocket_manager import ws_manager +from py_local.utils.routes_common import ExifUtils +from py_local.config import config + + +class DummyRoutes(BaseModelRoutes): + template_name = "dummy.html" + + def setup_specific_routes(self, app: web.Application, prefix: str) -> None: # pragma: no cover - no extra routes in smoke tests + return None + + +async def create_test_client(service) -> TestClient: + routes = DummyRoutes(service) + app = web.Application() + routes.setup_routes(app, "test-models") + + server = TestServer(app) + client = TestClient(server) + await client.start_server() + return client + + +@pytest.fixture(autouse=True) +def reset_ws_manager_state(): + ws_manager.cleanup_auto_organize_progress() + ws_manager._download_progress.clear() + yield + ws_manager.cleanup_auto_organize_progress() + ws_manager._download_progress.clear() + + +@pytest.fixture +def download_manager_stub(): + class FakeDownloadManager: + def __init__(self): + self.calls = [] + + async def download_from_civitai(self, **kwargs): + self.calls.append(kwargs) + await kwargs["progress_callback"](42) + return {"success": True, "path": "/tmp/model.safetensors"} + + stub = FakeDownloadManager() + previous = ServiceRegistry._services.get("download_manager") + asyncio.run(ServiceRegistry.register_service("download_manager", stub)) + try: + yield stub + finally: + if previous is not None: + ServiceRegistry._services["download_manager"] = previous + else: + ServiceRegistry._services.pop("download_manager", None) + + +def test_list_models_returns_formatted_items(mock_service, mock_scanner): + mock_service.paginated_items = [{"file_path": "/tmp/demo.safetensors", "name": "Demo"}] + + async def scenario(): + client = await create_test_client(mock_service) + try: + response = await client.get("/api/lm/test-models/list") + payload = await response.json() + + assert response.status == 200 + assert payload["items"] == [{"file_path": "/tmp/demo.safetensors", "name": "Demo", "formatted": True}] + assert payload["total"] == 1 + assert mock_service.formatted == payload["items"] + finally: + await client.close() + + asyncio.run(scenario()) + + +def test_delete_model_updates_cache_and_hash_index(mock_service, mock_scanner, tmp_path: Path): + model_path = tmp_path / "sample.safetensors" + model_path.write_bytes(b"model") + mock_scanner._cache.raw_data = [{"file_path": str(model_path)}] + + async def scenario(): + client = await create_test_client(mock_service) + try: + response = await client.post( + "/api/lm/test-models/delete", + json={"file_path": str(model_path)}, + ) + payload = await response.json() + + assert response.status == 200 + assert payload["success"] is True + assert mock_scanner._cache.raw_data == [] + assert mock_scanner._cache.resort_calls == 1 + assert mock_scanner._hash_index.removed_paths == [str(model_path)] + finally: + await client.close() + + asyncio.run(scenario()) + assert not model_path.exists() + + +def test_replace_preview_writes_file_and_updates_cache( + mock_service, + mock_scanner, + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, +): + model_path = tmp_path / "preview-model.safetensors" + model_path.write_bytes(b"model") + metadata_path = tmp_path / "preview-model.metadata.json" + metadata_path.write_text(json.dumps({"file_path": str(model_path)})) + + mock_scanner._cache.raw_data = [{"file_path": str(model_path)}] + + monkeypatch.setattr( + ExifUtils, + "optimize_image", + staticmethod(lambda image_data, **_: (image_data, ".webp")), + ) + monkeypatch.setattr( + config, + "get_preview_static_url", + lambda preview_path: f"/static/{Path(preview_path).name}", + ) + + form = FormData() + form.add_field("preview_file", b"binary-data", filename="preview.png", content_type="image/png") + form.add_field("model_path", str(model_path)) + form.add_field("nsfw_level", "2") + + async def scenario(): + client = await create_test_client(mock_service) + try: + response = await client.post("/api/lm/test-models/replace-preview", data=form) + payload = await response.json() + + expected_preview = str((tmp_path / "preview-model.webp")).replace(os.sep, "/") + assert response.status == 200 + assert payload["success"] is True + assert payload["preview_url"] == "/static/preview-model.webp" + assert Path(expected_preview).exists() + assert mock_scanner.preview_updates[-1]["preview_path"] == expected_preview + + updated_metadata = json.loads(metadata_path.read_text()) + assert updated_metadata["preview_url"] == expected_preview + assert updated_metadata["preview_nsfw_level"] == 2 + finally: + await client.close() + + asyncio.run(scenario()) + + +def test_download_model_invokes_download_manager( + mock_service, + download_manager_stub, + tmp_path: Path, +): + async def scenario(): + client = await create_test_client(mock_service) + try: + response = await client.post( + "/api/lm/download-model", + json={"model_id": 1, "model_root": str(tmp_path)}, + ) + payload = await response.json() + + assert response.status == 200 + assert payload["success"] is True + assert download_manager_stub.calls + + call_args = download_manager_stub.calls[0] + assert call_args["model_id"] == 1 + assert call_args["download_id"] == payload["download_id"] + progress = ws_manager.get_download_progress(payload["download_id"]) + assert progress is not None + assert progress["progress"] == 42 + ws_manager.cleanup_download_progress(payload["download_id"]) + finally: + await client.close() + + asyncio.run(scenario()) + + +def test_auto_organize_progress_returns_latest_snapshot(mock_service): + async def scenario(): + client = await create_test_client(mock_service) + try: + await ws_manager.broadcast_auto_organize_progress({"status": "processing", "percent": 50}) + + response = await client.get("/api/lm/test-models/auto-organize-progress") + payload = await response.json() + + assert response.status == 200 + assert payload == {"success": True, "progress": {"status": "processing", "percent": 50}} + finally: + await client.close() + + asyncio.run(scenario()) From 1022b07f64c1684a2ea26d6572384a24b480a602 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sun, 21 Sep 2025 19:56:38 +0800 Subject: [PATCH 049/110] feat: enhance model metadata provider with import error handling and mock setup for tests --- py/services/model_metadata_provider.py | 56 ++++++++++++++++++++------ pytest.ini | 8 ++++ run_tests.py | 46 +++++++++++++++++++++ tests/conftest.py | 35 ++++++++++++++++ 4 files changed, 133 insertions(+), 12 deletions(-) create mode 100644 pytest.ini create mode 100644 run_tests.py diff --git a/py/services/model_metadata_provider.py b/py/services/model_metadata_provider.py index 55091118..1a36d353 100644 --- a/py/services/model_metadata_provider.py +++ b/py/services/model_metadata_provider.py @@ -1,11 +1,41 @@ from abc import ABC, abstractmethod import json -import aiosqlite import logging -from bs4 import BeautifulSoup -from typing import Optional, Dict, Tuple +from typing import Optional, Dict, Tuple, Any from .downloader import get_downloader +try: + from bs4 import BeautifulSoup +except ImportError as exc: + BeautifulSoup = None # type: ignore[assignment] + _BS4_IMPORT_ERROR = exc +else: + _BS4_IMPORT_ERROR = None + +try: + import aiosqlite +except ImportError as exc: + aiosqlite = None # type: ignore[assignment] + _AIOSQLITE_IMPORT_ERROR = exc +else: + _AIOSQLITE_IMPORT_ERROR = None + +def _require_beautifulsoup() -> Any: + if BeautifulSoup is None: + raise RuntimeError( + "BeautifulSoup (bs4) is required for CivArchiveModelMetadataProvider. " + "Install it with 'pip install beautifulsoup4'." + ) from _BS4_IMPORT_ERROR + return BeautifulSoup + +def _require_aiosqlite() -> Any: + if aiosqlite is None: + raise RuntimeError( + "aiosqlite is required for SQLiteModelMetadataProvider. " + "Install it with 'pip install aiosqlite'." + ) from _AIOSQLITE_IMPORT_ERROR + return aiosqlite + logger = logging.getLogger(__name__) class ModelMetadataProvider(ABC): @@ -78,7 +108,8 @@ class CivArchiveModelMetadataProvider(ModelMetadataProvider): html_content = await response.text() # Parse HTML to extract JSON data - soup = BeautifulSoup(html_content, 'html.parser') + soup_parser = _require_beautifulsoup() + soup = soup_parser(html_content, 'html.parser') script_tag = soup.find('script', {'id': '__NEXT_DATA__', 'type': 'application/json'}) if not script_tag: @@ -171,10 +202,11 @@ class SQLiteModelMetadataProvider(ModelMetadataProvider): def __init__(self, db_path: str): self.db_path = db_path + self._aiosqlite = _require_aiosqlite() async def get_model_by_hash(self, model_hash: str) -> Tuple[Optional[Dict], Optional[str]]: """Find model by hash value from SQLite database""" - async with aiosqlite.connect(self.db_path) as db: + async with self._aiosqlite.connect(self.db_path) as db: # Look up in model_files table to get model_id and version_id query = """ SELECT model_id, version_id @@ -182,7 +214,7 @@ class SQLiteModelMetadataProvider(ModelMetadataProvider): WHERE sha256 = ? LIMIT 1 """ - db.row_factory = aiosqlite.Row + db.row_factory = self._aiosqlite.Row cursor = await db.execute(query, (model_hash.upper(),)) file_row = await cursor.fetchone() @@ -199,8 +231,8 @@ class SQLiteModelMetadataProvider(ModelMetadataProvider): async def get_model_versions(self, model_id: str) -> Optional[Dict]: """Get all versions of a model from SQLite database""" - async with aiosqlite.connect(self.db_path) as db: - db.row_factory = aiosqlite.Row + async with self._aiosqlite.connect(self.db_path) as db: + db.row_factory = self._aiosqlite.Row # First check if model exists model_query = "SELECT * FROM models WHERE id = ?" @@ -258,8 +290,8 @@ class SQLiteModelMetadataProvider(ModelMetadataProvider): if not model_id and not version_id: return None - async with aiosqlite.connect(self.db_path) as db: - db.row_factory = aiosqlite.Row + async with self._aiosqlite.connect(self.db_path) as db: + db.row_factory = self._aiosqlite.Row # Case 1: Only version_id is provided if model_id is None and version_id is not None: @@ -295,8 +327,8 @@ class SQLiteModelMetadataProvider(ModelMetadataProvider): async def get_model_version_info(self, version_id: str) -> Tuple[Optional[Dict], Optional[str]]: """Fetch model version metadata from SQLite database""" - async with aiosqlite.connect(self.db_path) as db: - db.row_factory = aiosqlite.Row + async with self._aiosqlite.connect(self.db_path) as db: + db.row_factory = self._aiosqlite.Row # Get version details version_query = "SELECT model_id FROM model_versions WHERE id = ?" diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000..44f4dc04 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,8 @@ +[pytest] +addopts = -v --import-mode=importlib +testpaths = tests +python_files = test_*.py +python_classes = Test* +python_functions = test_* +# Skip problematic directories to avoid import conflicts +norecursedirs = .git .tox dist build *.egg __pycache__ py \ No newline at end of file diff --git a/run_tests.py b/run_tests.py new file mode 100644 index 00000000..627c77bc --- /dev/null +++ b/run_tests.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +""" +Test runner script for ComfyUI-Lora-Manager. + +This script runs pytest from the tests directory to avoid import issues +with the root __init__.py file. +""" +import subprocess +import sys +import os +from pathlib import Path + +def main(): + """Run pytest from the tests directory to avoid import issues.""" + # Get the script directory + script_dir = Path(__file__).parent.absolute() + tests_dir = script_dir / "tests" + + if not tests_dir.exists(): + print(f"Error: Tests directory not found at {tests_dir}") + return 1 + + # Change to tests directory + original_cwd = os.getcwd() + os.chdir(tests_dir) + + try: + # Build pytest command + cmd = [ + sys.executable, "-m", "pytest", + "-v", + "--rootdir=.", + ] + sys.argv[1:] # Pass any additional arguments + + print(f"Running: {' '.join(cmd)}") + print(f"Working directory: {tests_dir}") + + # Run pytest + result = subprocess.run(cmd, cwd=tests_dir) + return result.returncode + finally: + # Restore original working directory + os.chdir(original_cwd) + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tests/conftest.py b/tests/conftest.py index 0ec41c73..dfe99691 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,8 +1,43 @@ +import types from dataclasses import dataclass, field from typing import Any, Dict, List, Optional, Sequence +from unittest import mock +import sys import pytest +# Mock ComfyUI modules before any imports from the main project +server_mock = types.SimpleNamespace() +server_mock.PromptServer = mock.MagicMock() +sys.modules['server'] = server_mock + +folder_paths_mock = types.SimpleNamespace() +folder_paths_mock.get_folder_paths = mock.MagicMock(return_value=[]) +folder_paths_mock.folder_names_and_paths = {} +sys.modules['folder_paths'] = folder_paths_mock + +# Mock other ComfyUI modules that might be imported +comfy_mock = types.SimpleNamespace() +comfy_mock.utils = types.SimpleNamespace() +comfy_mock.model_management = types.SimpleNamespace() +comfy_mock.comfy_types = types.SimpleNamespace() +comfy_mock.comfy_types.IO = mock.MagicMock() +sys.modules['comfy'] = comfy_mock +sys.modules['comfy.utils'] = comfy_mock.utils +sys.modules['comfy.model_management'] = comfy_mock.model_management +sys.modules['comfy.comfy_types'] = comfy_mock.comfy_types + +execution_mock = types.SimpleNamespace() +execution_mock.PromptExecutor = mock.MagicMock() +sys.modules['execution'] = execution_mock + +# Mock ComfyUI nodes module +nodes_mock = types.SimpleNamespace() +nodes_mock.LoraLoader = mock.MagicMock() +nodes_mock.SaveImage = mock.MagicMock() +nodes_mock.NODE_CLASS_MAPPINGS = {} +sys.modules['nodes'] = nodes_mock + @dataclass class MockHashIndex: From 24090e60776cb39eb4401d1f66a017ee5e15ac83 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Sun, 21 Sep 2025 20:34:45 +0800 Subject: [PATCH 050/110] docs(routes): map base model dependencies and contracts --- __init__.py | 39 ++-- docs/architecture/model_routes.md | 178 ++++++++++++------- py/__init__.py | 12 ++ tests/routes/test_base_model_routes_smoke.py | 11 ++ 4 files changed, 162 insertions(+), 78 deletions(-) diff --git a/__init__.py b/__init__.py index cf317063..5223fc45 100644 --- a/__init__.py +++ b/__init__.py @@ -1,13 +1,32 @@ -from .py.lora_manager import LoraManager -from .py.nodes.lora_loader import LoraManagerLoader, LoraManagerTextLoader -from .py.nodes.trigger_word_toggle import TriggerWordToggle -from .py.nodes.lora_stacker import LoraStacker -from .py.nodes.save_image import SaveImage -from .py.nodes.debug_metadata import DebugMetadata -from .py.nodes.wanvideo_lora_select import WanVideoLoraSelect -from .py.nodes.wanvideo_lora_select_from_text import WanVideoLoraSelectFromText -# Import metadata collector to install hooks on startup -from .py.metadata_collector import init as init_metadata_collector +try: # pragma: no cover - import fallback for pytest collection + from .py.lora_manager import LoraManager + from .py.nodes.lora_loader import LoraManagerLoader, LoraManagerTextLoader + from .py.nodes.trigger_word_toggle import TriggerWordToggle + from .py.nodes.lora_stacker import LoraStacker + from .py.nodes.save_image import SaveImage + from .py.nodes.debug_metadata import DebugMetadata + from .py.nodes.wanvideo_lora_select import WanVideoLoraSelect + from .py.nodes.wanvideo_lora_select_from_text import WanVideoLoraSelectFromText + from .py.metadata_collector import init as init_metadata_collector +except ImportError: # pragma: no cover - allows running under pytest without package install + import importlib + import pathlib + import sys + + package_root = pathlib.Path(__file__).resolve().parent + if str(package_root) not in sys.path: + sys.path.append(str(package_root)) + + LoraManager = importlib.import_module("py.lora_manager").LoraManager + LoraManagerLoader = importlib.import_module("py.nodes.lora_loader").LoraManagerLoader + LoraManagerTextLoader = importlib.import_module("py.nodes.lora_loader").LoraManagerTextLoader + TriggerWordToggle = importlib.import_module("py.nodes.trigger_word_toggle").TriggerWordToggle + LoraStacker = importlib.import_module("py.nodes.lora_stacker").LoraStacker + SaveImage = importlib.import_module("py.nodes.save_image").SaveImage + DebugMetadata = importlib.import_module("py.nodes.debug_metadata").DebugMetadata + WanVideoLoraSelect = importlib.import_module("py.nodes.wanvideo_lora_select").WanVideoLoraSelect + WanVideoLoraSelectFromText = importlib.import_module("py.nodes.wanvideo_lora_select_from_text").WanVideoLoraSelectFromText + init_metadata_collector = importlib.import_module("py.metadata_collector").init NODE_CLASS_MAPPINGS = { LoraManagerLoader.NAME: LoraManagerLoader, diff --git a/docs/architecture/model_routes.md b/docs/architecture/model_routes.md index d32420dd..00329299 100644 --- a/docs/architecture/model_routes.md +++ b/docs/architecture/model_routes.md @@ -9,77 +9,119 @@ exposed in `py/routes/base_model_routes.py`, the collaborators it leans on, and any cache or WebSocket side effects implemented in `py/utils/routes_common.py`. +## Contents + +- [Handler catalogue](#handler-catalogue) +- [Dependency map and contracts](#dependency-map-and-contracts) + - [Cache and metadata mutations](#cache-and-metadata-mutations) + - [Download and WebSocket flows](#download-and-websocket-flows) + - [Read-only queries](#read-only-queries) + - [Template rendering and initialization](#template-rendering-and-initialization) + ## Handler catalogue -| Endpoint(s) | Handler | Purpose | Collaborators | Cache / WebSocket side effects | -| --- | --- | --- | --- | --- | -| `/{prefix}` | `handle_models_page` | Renders the HTML page for a model type, populating the template from cached scanner data when available. | `settings`, `server_i18n`, `service.scanner.get_cached_data()` | Reads scanner cache to build folder list; flags initialization state without mutating cache. | -| `/api/lm/{prefix}/list` | `get_models` | Returns paginated model metadata. | `service.get_paginated_data()`, `service.format_response()` | None (read-only). | -| `/api/lm/{prefix}/delete` | `delete_model` | Removes a single model from disk and cache. | `ModelRouteUtils.handle_delete_model()` | Deletes files, prunes `scanner.get_cached_data().raw_data`, calls `cache.resort()`, and updates `scanner._hash_index`. | -| `/api/lm/{prefix}/exclude` | `exclude_model` | Marks a model as excluded so it no longer appears in listings. | `ModelRouteUtils.handle_exclude_model()` | Updates metadata, decrements `scanner._tags_count`, removes cache entry and hash index entry, and appends to `scanner._excluded_models`. | -| `/api/lm/{prefix}/fetch-civitai` | `fetch_civitai` | Fetches metadata for a specific model from CivitAI. | `ModelRouteUtils.fetch_and_update_model()` | Uses scanner cache to find the target record and updates it via `scanner.update_single_model_cache`. | -| `/api/lm/{prefix}/fetch-all-civitai` | `fetch_all_civitai` | Bulk refreshes metadata for models missing CivitAI info. | `ModelRouteUtils.fetch_and_update_model()`, `ws_manager.broadcast()` | Streams progress to all clients, updates cache entries, optionally resorts cached data. | -| `/api/lm/{prefix}/relink-civitai` | `relink_civitai` | Re-associates a local file with a CivitAI entry. | `ModelRouteUtils.handle_relink_civitai()` | Updates metadata, refreshes cache via `scanner.update_single_model_cache`. | -| `/api/lm/{prefix}/replace-preview` | `replace_preview` | Replaces the preview asset attached to a model. | `ModelRouteUtils.handle_replace_preview()` | Writes new preview file, updates metadata, and calls `scanner.update_preview_in_cache()`. | -| `/api/lm/{prefix}/save-metadata` | `save_metadata` | Persists edits to model metadata. | `ModelRouteUtils.handle_save_metadata()` | Saves metadata file and syncs the cache entry. | -| `/api/lm/{prefix}/add-tags` | `add_tags` | Adds or increments tags for a model. | `ModelRouteUtils.handle_add_tags()` | Mutates metadata, increments `scanner._tags_count`, and updates the cached model. | -| `/api/lm/{prefix}/rename` | `rename_model` | Renames a model and its related assets. | `ModelRouteUtils.handle_rename_model()` | Renames files on disk, updates cache indices, refreshes metadata. | -| `/api/lm/{prefix}/bulk-delete` | `bulk_delete_models` | Deletes multiple models in one request. | `ModelRouteUtils.handle_bulk_delete_models()` | Delegates to `scanner.bulk_delete_models()` which removes disk assets and cache records in bulk. | -| `/api/lm/{prefix}/verify-duplicates` | `verify_duplicates` | Confirms that a list of files share the same hash. | `ModelRouteUtils.handle_verify_duplicates()` | Recalculates hashes, updates metadata, and patches cache entries when stored hashes change. | -| `/api/lm/{prefix}/top-tags` | `get_top_tags` | Returns the most frequently used tags. | `service.get_top_tags()` | None (read-only). | -| `/api/lm/{prefix}/base-models` | `get_base_models` | Lists base models referenced by this model type. | `service.get_base_models()` | None (read-only). | -| `/api/lm/{prefix}/scan` | `scan_models` | Triggers a rescan of the filesystem. | `service.scan_models()` | Scanner rebuilds its cache as part of the service workflow. | -| `/api/lm/{prefix}/roots` | `get_model_roots` | Enumerates root directories searched for this model type. | `service.get_model_roots()` | None (read-only). | -| `/api/lm/{prefix}/folders` | `get_folders` | Returns cached folder summaries. | `service.scanner.get_cached_data()` | Reads cached structure without mutation. | -| `/api/lm/{prefix}/folder-tree` | `get_folder_tree` | Builds a nested folder tree of cached items. | `service.scanner.get_cached_data()` | Reads cache; does not mutate. | -| `/api/lm/{prefix}/unified-folder-tree` | `get_unified_folder_tree` | Returns a tree aggregating all roots. | `service.scanner.get_cached_data()` | Reads cache; does not mutate. | -| `/api/lm/{prefix}/find-duplicates` | `find_duplicate_models` | Finds duplicate hashes within the cache. | `service.scanner.get_duplicates()`, `service.scanner.get_hash_by_filename()` | Uses cache data to assemble duplicate groups; no mutation. | -| `/api/lm/{prefix}/find-filename-conflicts` | `find_filename_conflicts` | Groups models that share a filename across directories. | `service.scanner.get_filename_conflicts()`, `service.get_path_by_hash()` | Reads cache while formatting results. | -| `/api/lm/{prefix}/get-notes` | `get_model_notes` | Retrieves saved notes for a model. | `service.get_model_notes()` | None (read-only). | -| `/api/lm/{prefix}/preview-url` | `get_model_preview_url` | Resolves the static preview URL for a model. | `service.get_model_preview_url()` | None (read-only). | -| `/api/lm/{prefix}/civitai-url` | `get_model_civitai_url` | Returns the CivitAI permalink for a model. | `service.get_model_civitai_url()` | None (read-only). | -| `/api/lm/{prefix}/metadata` | `get_model_metadata` | Loads the raw metadata payload for a model. | `service.get_model_metadata()` | None (read-only). | -| `/api/lm/{prefix}/model-description` | `get_model_description` | Returns a formatted description for the UI. | `service.get_model_description()` | None (read-only). | -| `/api/lm/{prefix}/relative-paths` | `get_relative_paths` | Provides filesystem auto-complete suggestions. | `service.get_relative_paths()` | None (read-only). | -| `/api/lm/{prefix}/civitai/versions/{model_id}` | `get_civitai_versions` | Lists remote versions and indicates which exist locally. | `get_default_metadata_provider()`, `self.service.has_hash()`, `self.service.get_path_by_hash()` | Read-only; consults cache/service indices to mark local availability. | -| `/api/lm/{prefix}/civitai/model/version/{modelVersionId}` | `get_civitai_model_by_version` | Fetches detailed metadata for a specific CivitAI version. | `get_default_metadata_provider()` | None (read-only). | -| `/api/lm/{prefix}/civitai/model/hash/{hash}` | `get_civitai_model_by_hash` | Fetches CivitAI details using a hash. | `get_default_metadata_provider()` | None (read-only). | -| `/api/lm/download-model` (POST) & `/api/lm/download-model-get` (GET) | `download_model`, `download_model_get` | Starts a download through the shared download manager. | `ModelRouteUtils.handle_download_model()`, `ServiceRegistry.get_download_manager()` | The helper broadcasts download progress via `ws_manager.broadcast_download_progress()` and stores state in `ws_manager._download_progress`. | -| `/api/lm/cancel-download-get` | `cancel_download_get` | Cancels an active download. | `ModelRouteUtils.handle_cancel_download()` | Broadcasts a cancellation message via `ws_manager.broadcast_download_progress()` and prunes download progress entries. | -| `/api/lm/download-progress/{download_id}` | `get_download_progress` | Reports cached download progress for a download ID. | `ws_manager.get_download_progress()` | Read-only view of cached progress. | -| `/api/lm/{prefix}/move_model` | `move_model` | Moves a model to a new folder. | `ModelMoveService.move_model()` | File operations performed by the injected service may update scanner caches downstream. | -| `/api/lm/{prefix}/move_models_bulk` | `move_models_bulk` | Bulk move models to a new location. | `ModelMoveService.move_models_bulk()` | File operations delegated to the service. | -| `/api/lm/{prefix}/auto-organize` (GET/POST) | `auto_organize_models` | Launches auto-organization for models, optionally limited to selected files. | `ModelFileService.auto_organize_models()`, `ws_manager.get_auto_organize_lock()`, `WebSocketProgressCallback` | Uses a shared asyncio lock, streams progress through `ws_manager.broadcast_auto_organize_progress()`, and relies on `ws_manager.is_auto_organize_running()` state. | -| `/api/lm/{prefix}/auto-organize-progress` | `get_auto_organize_progress` | Polls the latest auto-organize progress snapshot. | `ws_manager.get_auto_organize_progress()` | Read-only view of the WebSocket manager’s cached progress. | +The routes exposed by `BaseModelRoutes` combine HTTP wiring with a handful of +shared helper classes. Services surface filesystem and metadata operations, +`ModelRouteUtils` bundles cache-sensitive mutations, and `ws_manager` +coordinates fan-out to browser clients. The tables below expand the existing +catalogue into explicit dependency maps and invariants so refactors can reason +about the expectations each collaborator must uphold. -## Shared utility side effects +## Dependency map and contracts -The delegated helpers in `ModelRouteUtils` encapsulate most cache and -WebSocket mutations. The smoke tests in this repository exercise the -following contracts from `py/utils/routes_common.py`: +### Cache and metadata mutations -* `handle_delete_model` removes matching records from - `scanner.get_cached_data().raw_data`, awaits `cache.resort()`, and calls - `scanner._hash_index.remove_by_path()` when an index is present before - returning a success payload. -* `handle_replace_preview` writes a new preview file, persists metadata via - `MetadataManager.save_metadata()`, and then invokes - `scanner.update_preview_in_cache()` with the normalized preview path and - NSFW level so downstream requests surface the updated asset. -* `handle_download_model` acquires the shared download manager from - `ServiceRegistry`, injects a WebSocket progress callback, and relies on - `ws_manager.broadcast_download_progress()` to update the cached progress map - that `get_download_progress` later reads. -* `handle_bulk_delete_models`, `handle_add_tags`, `handle_exclude_model`, and - `handle_verify_duplicates` all mutate scanner-maintained collections (hash - indices, tag counts, exclusion lists, or cached metadata) so route handlers - can stay thin while cache consistency remains centralized in the utility - module. -* `ws_manager.broadcast_auto_organize_progress()` stores the latest progress - snapshot consumed by `get_auto_organize_progress`, while - `ws_manager.broadcast()` is used to notify clients during CivitAI bulk - refreshes and other background operations. +| Endpoint(s) | Delegate(s) | State touched | Invariants / contracts | +| --- | --- | --- | --- | +| `/api/lm/{prefix}/delete` | `ModelRouteUtils.handle_delete_model()` | Removes files from disk, prunes `scanner._cache.raw_data`, awaits `scanner._cache.resort()`, calls `scanner._hash_index.remove_by_path()`. | Cache and hash index must no longer reference the deleted path; resort must complete before responding to keep pagination deterministic. | +| `/api/lm/{prefix}/exclude` | `ModelRouteUtils.handle_exclude_model()` | Mutates metadata records, `scanner._cache.raw_data`, `scanner._hash_index`, `scanner._tags_count`, and `scanner._excluded_models`. | Excluded models remain discoverable via exclusion list while being hidden from listings; tag counts stay balanced after removal. | +| `/api/lm/{prefix}/fetch-civitai` | `ModelRouteUtils.fetch_and_update_model()` | Reads `scanner._cache.raw_data`, writes metadata JSON through `MetadataManager`, syncs cache via `scanner.update_single_model_cache`. | Requires a cached SHA256 hash; cache entries must reflect merged metadata before formatted response is returned. | +| `/api/lm/{prefix}/fetch-all-civitai` | `ModelRouteUtils.fetch_and_update_model()`, `ws_manager.broadcast()` | Iterates over cache, updates metadata files and cache records, optionally awaits `scanner._cache.resort()`. | Progress broadcasts follow started → processing → completed; if any model name changes, cache resort must run once before completion broadcast. | +| `/api/lm/{prefix}/relink-civitai` | `ModelRouteUtils.handle_relink_civitai()` | Updates metadata on disk and resynchronizes the cache entry. | The new association must propagate to `scanner.update_single_model_cache` so duplicate resolution and listings reflect the change immediately. | +| `/api/lm/{prefix}/replace-preview` | `ModelRouteUtils.handle_replace_preview()` | Writes optimized preview file, persists metadata via `MetadataManager`, updates cache with `scanner.update_preview_in_cache()`. | Preview path stored in metadata and cache must match the normalized file system path; NSFW level integer is synchronized across metadata and cache. | +| `/api/lm/{prefix}/save-metadata` | `ModelRouteUtils.handle_save_metadata()` | Writes metadata JSON and ensures cache entry mirrors the latest content. | Metadata persistence must be atomic—cache data should match on-disk metadata before response emits success. | +| `/api/lm/{prefix}/add-tags` | `ModelRouteUtils.handle_add_tags()` | Updates metadata tags, increments `scanner._tags_count`, and patches cached item. | Tag frequency map remains in sync with cache and metadata after increments. | +| `/api/lm/{prefix}/rename` | `ModelRouteUtils.handle_rename_model()` | Renames files, metadata, previews; updates cache indices and hash mappings. | File moves succeed or rollback as a unit so cache state never points to a missing file; hash index entries track the new path. | +| `/api/lm/{prefix}/bulk-delete` | `ModelRouteUtils.handle_bulk_delete_models()` | Delegates to `scanner.bulk_delete_models()` to delete files, trim cache, resort, and drop hash index entries. | Every requested path is removed from cache and index; resort happens once after bulk deletion. | +| `/api/lm/{prefix}/verify-duplicates` | `ModelRouteUtils.handle_verify_duplicates()` | Recomputes hashes, updates metadata and cached entries if discrepancies found. | Hash metadata stored in cache must mirror recomputed values to guarantee future duplicate checks operate on current data. | +| `/api/lm/{prefix}/scan` | `service.scan_models()` | Rescans filesystem, rebuilding scanner cache. | Scanner replaces its cache atomically so subsequent requests observe a consistent snapshot. | +| `/api/lm/{prefix}/move_model` | `ModelMoveService.move_model()` | Moves files/directories and notifies scanner via service layer conventions. | Move operations respect filesystem invariants (target path exists, metadata follows file) and emit success/failure without leaving partial moves. | +| `/api/lm/{prefix}/move_models_bulk` | `ModelMoveService.move_models_bulk()` | Batch move behavior as above. | Aggregated result enumerates successes/failures while preserving per-model atomicity. | +| `/api/lm/{prefix}/auto-organize` (GET/POST) | `ModelFileService.auto_organize_models()`, `ws_manager.get_auto_organize_lock()`, `WebSocketProgressCallback` | Writes organized files, updates metadata, and streams progress snapshots. | Only one auto-organize job may run; lock must guard reentrancy and WebSocket updates must include latest progress payload consumed by polling route. | -Keeping these side effects in mind is essential when refactoring route logic: -any replacement must continue to honor the implicit contracts the utilities -expect from scanners, caches, and the WebSocket manager. +### Download and WebSocket flows + +| Endpoint(s) | Delegate(s) | State touched | Invariants / contracts | +| --- | --- | --- | --- | +| `/api/lm/download-model` (POST) & `/api/lm/download-model-get` (GET) | `ModelRouteUtils.handle_download_model()`, `ServiceRegistry.get_download_manager()` | Schedules downloads, registers `ws_manager.broadcast_download_progress()` callback that stores progress in `ws_manager._download_progress`. | Download IDs remain stable across POST/GET helpers; every progress callback persists a timestamped entry so `/download-progress` and WebSocket clients share consistent snapshots. | +| `/api/lm/cancel-download-get` | `ModelRouteUtils.handle_cancel_download()` | Signals download manager, prunes `ws_manager._download_progress`, and emits cancellation broadcast. | Cancel requests must tolerate missing IDs gracefully while ensuring cached progress is removed once cancellation succeeds. | +| `/api/lm/download-progress/{download_id}` | `ws_manager.get_download_progress()` | Reads cached progress dictionary. | Returns `404` when progress is absent; successful payload surfaces the numeric `progress` stored during broadcasts. | +| `/api/lm/{prefix}/fetch-all-civitai` | `ws_manager.broadcast()` | Broadcast loop described above. | Broadcast cadence cannot skip completion/error messages so clients know when to clear UI spinners. | +| `/api/lm/{prefix}/auto-organize-progress` | `ws_manager.get_auto_organize_progress()` | Reads cached progress snapshot. | Route returns cached payload verbatim; absence yields `404` to signal idle state. | + +### Read-only queries + +| Endpoint(s) | Delegate(s) | State touched | Invariants / contracts | +| --- | --- | --- | --- | +| `/api/lm/{prefix}/list` | `service.get_paginated_data()`, `service.format_response()` | Reads service-managed pagination data. | Formatting must be applied to every item before response; pagination metadata echoes service result. | +| `/api/lm/{prefix}/top-tags` | `service.get_top_tags()` | Reads aggregated tag counts. | Limit parameter bounded to `[1, 100]`; response always wraps tags in `{success: True}` envelope. | +| `/api/lm/{prefix}/base-models` | `service.get_base_models()` | Reads service data. | Same limit handling as tags. | +| `/api/lm/{prefix}/roots` | `service.get_model_roots()` | Reads configured roots. | Always returns `{success: True, roots: [...]}`. | +| `/api/lm/{prefix}/folders` | `service.scanner.get_cached_data()` | Reads folder summaries from cache. | Cache access must tolerate initialization phases by surfacing errors via HTTP 500. | +| `/api/lm/{prefix}/folder-tree` | `service.get_folder_tree()` | Reads derived tree for requested root. | Rejects missing `model_root` with HTTP 400. | +| `/api/lm/{prefix}/unified-folder-tree` | `service.get_unified_folder_tree()` | Aggregated folder tree. | Returns `{success: True, tree: ...}` or 500 on error. | +| `/api/lm/{prefix}/find-duplicates` | `service.find_duplicate_hashes()`, `service.scanner.get_cached_data()`, `service.get_path_by_hash()` | Reads cache and hash index to format duplicates. | Only returns groups with more than one resolved model. | +| `/api/lm/{prefix}/find-filename-conflicts` | `service.find_duplicate_filenames()`, `service.scanner.get_cached_data()`, `service.scanner.get_hash_by_filename()` | Similar read-only assembly. | Includes resolved main index entry when available; empty `models` groups are omitted. | +| `/api/lm/{prefix}/get-notes` | `service.get_model_notes()` | Reads persisted notes. | Missing notes produce HTTP 404 with explicit error message. | +| `/api/lm/{prefix}/preview-url` | `service.get_model_preview_url()` | Resolves static URL. | Successful responses wrap URL in `{success: True}`; missing preview yields 404 error payload. | +| `/api/lm/{prefix}/civitai-url` | `service.get_model_civitai_url()` | Returns remote permalink info. | Response envelope matches preview pattern. | +| `/api/lm/{prefix}/metadata` | `service.get_model_metadata()` | Reads metadata JSON. | Responds with raw metadata dict or 500 on failure. | +| `/api/lm/{prefix}/model-description` | `service.get_model_description()` | Returns formatted description string. | Always JSON with success boolean. | +| `/api/lm/{prefix}/relative-paths` | `service.get_relative_paths()` | Resolves filesystem suggestions. | Maintains read-only contract. | +| `/api/lm/{prefix}/civitai/versions/{model_id}` | `get_default_metadata_provider()`, `service.has_hash()`, `service.get_path_by_hash()` | Reads remote API, cross-references cache. | Versions payload includes `existsLocally`/`localPath` only when hashes match local indices. | +| `/api/lm/{prefix}/civitai/model/version/{modelVersionId}` | `get_default_metadata_provider()` | Remote metadata lookup. | Errors propagate as JSON with `{success: False}` payload. | +| `/api/lm/{prefix}/civitai/model/hash/{hash}` | `get_default_metadata_provider()` | Remote metadata lookup. | Missing hashes return 404 with `{success: False}`. | + +### Template rendering and initialization + +| Endpoint(s) | Delegate(s) | State touched | Invariants / contracts | +| --- | --- | --- | --- | +| `/{prefix}` | `handle_models_page` | Reads configuration via `settings`, sets locale with `server_i18n`, pulls cached folders through `service.scanner.get_cached_data()`, renders Jinja template. | Template rendering must tolerate scanner initialization by flagging `is_initializing`; i18n filter is attached exactly once per environment to avoid duplicate registration errors. | + +### Contract sequences + +The following high-level sequences show how the collaborating services work +together for the most stateful operations: + +``` +delete_model request + → BaseModelRoutes.delete_model + → ModelRouteUtils.handle_delete_model + → filesystem delete + metadata cleanup + → scanner._cache.raw_data prune + → await scanner._cache.resort() + → scanner._hash_index.remove_by_path() +``` + +``` +replace_preview request + → BaseModelRoutes.replace_preview + → ModelRouteUtils.handle_replace_preview + → ExifUtils.optimize_image / config.get_preview_static_url + → MetadataManager.save_metadata + → scanner.update_preview_in_cache(model_path, preview_path, nsfw_level) +``` + +``` +download_model request + → BaseModelRoutes.download_model + → ModelRouteUtils.handle_download_model + → ServiceRegistry.get_download_manager().download_from_civitai(..., progress_callback) + → ws_manager.broadcast_download_progress(download_id, data) + → ws_manager._download_progress[download_id] updated with timestamp + → /api/lm/download-progress/{id} polls ws_manager.get_download_progress +``` + +These contracts complement the tables above: if any collaborator changes its +behavior, the invariants called out here must continue to hold for the routes +to remain predictable. diff --git a/py/__init__.py b/py/__init__.py index e69de29b..54e9a3f4 100644 --- a/py/__init__.py +++ b/py/__init__.py @@ -0,0 +1,12 @@ +"""Project namespace package.""" + +# pytest's internal compatibility layer still imports ``py.path.local`` from the +# historical ``py`` dependency. Because this project reuses the ``py`` package +# name, we expose a minimal shim so ``py.path.local`` resolves to ``pathlib.Path`` +# during test runs without pulling in the external dependency. +from pathlib import Path +from types import SimpleNamespace + +path = SimpleNamespace(local=Path) + +__all__ = ["path"] diff --git a/tests/routes/test_base_model_routes_smoke.py b/tests/routes/test_base_model_routes_smoke.py index f6674c08..bccd83a9 100644 --- a/tests/routes/test_base_model_routes_smoke.py +++ b/tests/routes/test_base_model_routes_smoke.py @@ -170,6 +170,8 @@ def test_replace_preview_writes_file_and_updates_cache( assert payload["preview_url"] == "/static/preview-model.webp" assert Path(expected_preview).exists() assert mock_scanner.preview_updates[-1]["preview_path"] == expected_preview + assert mock_scanner._cache.raw_data[0]["preview_url"] == expected_preview + assert mock_scanner._cache.raw_data[0]["preview_nsfw_level"] == 2 updated_metadata = json.loads(metadata_path.read_text()) assert updated_metadata["preview_url"] == expected_preview @@ -204,6 +206,15 @@ def test_download_model_invokes_download_manager( progress = ws_manager.get_download_progress(payload["download_id"]) assert progress is not None assert progress["progress"] == 42 + assert "timestamp" in progress + + progress_response = await client.get( + f"/api/lm/download-progress/{payload['download_id']}" + ) + progress_payload = await progress_response.json() + + assert progress_response.status == 200 + assert progress_payload == {"success": True, "progress": 42} ws_manager.cleanup_download_progress(payload["download_id"]) finally: await client.close() From 0e93a6bcb098b8c73787bfcd33213f66af217f6c Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Sun, 21 Sep 2025 20:52:08 +0800 Subject: [PATCH 051/110] refactor(routes): extract registrar and handlers --- py/routes/base_model_routes.py | 1249 +++--------------- py/routes/checkpoint_routes.py | 19 +- py/routes/embedding_routes.py | 13 +- py/routes/handlers/model_handlers.py | 802 +++++++++++ py/routes/lora_routes.py | 25 +- py/routes/model_route_registrar.py | 99 ++ tests/routes/test_base_model_routes_smoke.py | 2 +- 7 files changed, 1106 insertions(+), 1103 deletions(-) create mode 100644 py/routes/handlers/model_handlers.py create mode 100644 py/routes/model_route_registrar.py diff --git a/py/routes/base_model_routes.py b/py/routes/base_model_routes.py index 6c3f11b4..458a5e87 100644 --- a/py/routes/base_model_routes.py +++ b/py/routes/base_model_routes.py @@ -1,1095 +1,200 @@ -from abc import ABC, abstractmethod -import asyncio -import os -import json +from __future__ import annotations + import logging -from aiohttp import web -from typing import Dict +from abc import ABC, abstractmethod +from typing import Callable, Dict, Mapping import jinja2 +from aiohttp import web -from ..utils.routes_common import ModelRouteUtils -from ..services.websocket_manager import ws_manager -from ..services.settings_manager import settings -from ..services.server_i18n import server_i18n -from ..services.model_file_service import ModelFileService, ModelMoveService -from ..services.websocket_progress_callback import WebSocketProgressCallback -from ..services.metadata_service import get_default_metadata_provider from ..config import config +from ..services.metadata_service import get_default_metadata_provider +from ..services.model_file_service import ModelFileService, ModelMoveService +from ..services.settings_manager import settings as default_settings +from ..services.websocket_manager import ws_manager as default_ws_manager +from ..services.websocket_progress_callback import WebSocketProgressCallback +from ..services.server_i18n import server_i18n as default_server_i18n +from ..utils.routes_common import ModelRouteUtils +from .model_route_registrar import COMMON_ROUTE_DEFINITIONS, ModelRouteRegistrar +from .handlers.model_handlers import ( + ModelAutoOrganizeHandler, + ModelCivitaiHandler, + ModelDownloadHandler, + ModelHandlerSet, + ModelListingHandler, + ModelManagementHandler, + ModelMoveHandler, + ModelPageView, + ModelQueryHandler, +) logger = logging.getLogger(__name__) + class BaseModelRoutes(ABC): - """Base route controller for all model types""" - - def __init__(self, service): - """Initialize the route controller - - Args: - service: Model service instance (LoraService, CheckpointService, etc.) - """ - self.service = service - self.model_type = service.model_type + """Base route controller for all model types.""" + + template_name: str | None = None + + def __init__( + self, + service=None, + *, + settings_service=default_settings, + ws_manager=default_ws_manager, + server_i18n=default_server_i18n, + metadata_provider_factory=get_default_metadata_provider, + ) -> None: + self.service = None + self.model_type = "" + self._settings = settings_service + self._ws_manager = ws_manager + self._server_i18n = server_i18n + self._metadata_provider_factory = metadata_provider_factory + self.template_env = jinja2.Environment( loader=jinja2.FileSystemLoader(config.templates_path), - autoescape=True + autoescape=True, ) - - # Initialize file services with dependency injection + + self.model_file_service: ModelFileService | None = None + self.model_move_service: ModelMoveService | None = None + self.websocket_progress_callback = WebSocketProgressCallback() + + self._handler_set: ModelHandlerSet | None = None + self._handler_mapping: Dict[str, Callable[[web.Request], web.StreamResponse]] | None = None + + if service is not None: + self.attach_service(service) + + def attach_service(self, service) -> None: + """Attach a model service and rebuild handler dependencies.""" + self.service = service + self.model_type = service.model_type self.model_file_service = ModelFileService(service.scanner, service.model_type) self.model_move_service = ModelMoveService(service.scanner) - self.websocket_progress_callback = WebSocketProgressCallback() - - def setup_routes(self, app: web.Application, prefix: str): - """Setup common routes for the model type - - Args: - app: aiohttp application - prefix: URL prefix (e.g., 'loras', 'checkpoints') - """ - # Common model management routes - app.router.add_get(f'/api/lm/{prefix}/list', self.get_models) - app.router.add_post(f'/api/lm/{prefix}/delete', self.delete_model) - app.router.add_post(f'/api/lm/{prefix}/exclude', self.exclude_model) - app.router.add_post(f'/api/lm/{prefix}/fetch-civitai', self.fetch_civitai) - app.router.add_post(f'/api/lm/{prefix}/fetch-all-civitai', self.fetch_all_civitai) - app.router.add_post(f'/api/lm/{prefix}/relink-civitai', self.relink_civitai) - app.router.add_post(f'/api/lm/{prefix}/replace-preview', self.replace_preview) - app.router.add_post(f'/api/lm/{prefix}/save-metadata', self.save_metadata) - app.router.add_post(f'/api/lm/{prefix}/add-tags', self.add_tags) - app.router.add_post(f'/api/lm/{prefix}/rename', self.rename_model) - app.router.add_post(f'/api/lm/{prefix}/bulk-delete', self.bulk_delete_models) - app.router.add_post(f'/api/lm/{prefix}/verify-duplicates', self.verify_duplicates) - app.router.add_post(f'/api/lm/{prefix}/move_model', self.move_model) - app.router.add_post(f'/api/lm/{prefix}/move_models_bulk', self.move_models_bulk) - app.router.add_get(f'/api/lm/{prefix}/auto-organize', self.auto_organize_models) - app.router.add_post(f'/api/lm/{prefix}/auto-organize', self.auto_organize_models) - app.router.add_get(f'/api/lm/{prefix}/auto-organize-progress', self.get_auto_organize_progress) - - # Common query routes - app.router.add_get(f'/api/lm/{prefix}/top-tags', self.get_top_tags) - app.router.add_get(f'/api/lm/{prefix}/base-models', self.get_base_models) - app.router.add_get(f'/api/lm/{prefix}/scan', self.scan_models) - app.router.add_get(f'/api/lm/{prefix}/roots', self.get_model_roots) - app.router.add_get(f'/api/lm/{prefix}/folders', self.get_folders) - app.router.add_get(f'/api/lm/{prefix}/folder-tree', self.get_folder_tree) - app.router.add_get(f'/api/lm/{prefix}/unified-folder-tree', self.get_unified_folder_tree) - app.router.add_get(f'/api/lm/{prefix}/find-duplicates', self.find_duplicate_models) - app.router.add_get(f'/api/lm/{prefix}/find-filename-conflicts', self.find_filename_conflicts) - app.router.add_get(f'/api/lm/{prefix}/get-notes', self.get_model_notes) - app.router.add_get(f'/api/lm/{prefix}/preview-url', self.get_model_preview_url) - app.router.add_get(f'/api/lm/{prefix}/civitai-url', self.get_model_civitai_url) - app.router.add_get(f'/api/lm/{prefix}/metadata', self.get_model_metadata) - app.router.add_get(f'/api/lm/{prefix}/model-description', self.get_model_description) - - # Autocomplete route - app.router.add_get(f'/api/lm/{prefix}/relative-paths', self.get_relative_paths) + self._handler_set = None + self._handler_mapping = None - # Common CivitAI integration - app.router.add_get(f'/api/lm/{prefix}/civitai/versions/{{model_id}}', self.get_civitai_versions) - app.router.add_get(f'/api/lm/{prefix}/civitai/model/version/{{modelVersionId}}', self.get_civitai_model_by_version) - app.router.add_get(f'/api/lm/{prefix}/civitai/model/hash/{{hash}}', self.get_civitai_model_by_hash) + def _ensure_handler_mapping(self) -> Mapping[str, Callable[[web.Request], web.StreamResponse]]: + if self._handler_mapping is None: + handler_set = self._create_handler_set() + self._handler_set = handler_set + self._handler_mapping = handler_set.to_route_mapping() + return self._handler_mapping + + def _create_handler_set(self) -> ModelHandlerSet: + service = self._ensure_service() + page_view = ModelPageView( + template_env=self.template_env, + template_name=self.template_name or "", + service=service, + settings_service=self._settings, + server_i18n=self._server_i18n, + logger=logger, + ) + listing = ModelListingHandler( + service=service, + parse_specific_params=self._parse_specific_params, + logger=logger, + ) + management = ModelManagementHandler(service=service, logger=logger) + query = ModelQueryHandler(service=service, logger=logger) + download = ModelDownloadHandler(ws_manager=self._ws_manager, logger=logger) + civitai = ModelCivitaiHandler( + service=service, + settings_service=self._settings, + ws_manager=self._ws_manager, + logger=logger, + metadata_provider_factory=self._metadata_provider_factory, + validate_model_type=self._validate_civitai_model_type, + expected_model_types=self._get_expected_model_types, + find_model_file=self._find_model_file, + ) + move = ModelMoveHandler(move_service=self._ensure_move_service(), logger=logger) + auto_organize = ModelAutoOrganizeHandler( + file_service=self._ensure_file_service(), + progress_callback=self.websocket_progress_callback, + ws_manager=self._ws_manager, + logger=logger, + ) + return ModelHandlerSet( + page_view=page_view, + listing=listing, + management=management, + query=query, + download=download, + civitai=civitai, + move=move, + auto_organize=auto_organize, + ) + + @property + def route_handlers(self) -> Mapping[str, Callable[[web.Request], web.StreamResponse]]: + return self._ensure_handler_mapping() + + def setup_routes(self, app: web.Application, prefix: str) -> None: + registrar = ModelRouteRegistrar(app) + handler_lookup = { + definition.handler_name: self._make_handler_proxy(definition.handler_name) + for definition in COMMON_ROUTE_DEFINITIONS + } + registrar.register_common_routes(prefix, handler_lookup) + self.setup_specific_routes(registrar, prefix) - # Common Download management - app.router.add_post(f'/api/lm/download-model', self.download_model) - app.router.add_get(f'/api/lm/download-model-get', self.download_model_get) - app.router.add_get(f'/api/lm/cancel-download-get', self.cancel_download_get) - app.router.add_get(f'/api/lm/download-progress/{{download_id}}', self.get_download_progress) - - # Add generic page route - app.router.add_get(f'/{prefix}', self.handle_models_page) - - # Setup model-specific routes - self.setup_specific_routes(app, prefix) - @abstractmethod - def setup_specific_routes(self, app: web.Application, prefix: str): - """Setup model-specific routes - to be implemented by subclasses""" - pass - - async def handle_models_page(self, request: web.Request) -> web.Response: - """ - Generic handler for model pages (e.g., /loras, /checkpoints). - Subclasses should set self.template_env and template_name. - """ - try: - # Check if the scanner is initializing - is_initializing = ( - self.service.scanner._cache is None or - (hasattr(self.service.scanner, 'is_initializing') and callable(self.service.scanner.is_initializing) and self.service.scanner.is_initializing()) or - (hasattr(self.service.scanner, '_is_initializing') and self.service.scanner._is_initializing) - ) + def setup_specific_routes(self, registrar: ModelRouteRegistrar, prefix: str) -> None: + """Setup model-specific routes.""" + raise NotImplementedError - template_name = getattr(self, "template_name", None) - if not self.template_env or not template_name: - return web.Response(text="Template environment or template name not set", status=500) - - # Get user's language setting - user_language = settings.get('language', 'en') - - # Set server-side i18n locale - server_i18n.set_locale(user_language) - - # Add i18n filter to the template environment if not already added - if not hasattr(self.template_env, '_i18n_filter_added'): - self.template_env.filters['t'] = server_i18n.create_template_filter() - self.template_env._i18n_filter_added = True - - # Prepare template context - template_context = { - 'is_initializing': is_initializing, - 'settings': settings, - 'request': request, - 'folders': [], - 't': server_i18n.get_translation, - } - - if not is_initializing: - try: - cache = await self.service.scanner.get_cached_data(force_refresh=False) - template_context['folders'] = getattr(cache, "folders", []) - except Exception as cache_error: - logger.error(f"Error loading cache data: {cache_error}") - template_context['is_initializing'] = True - - rendered = self.template_env.get_template(template_name).render(**template_context) - - return web.Response( - text=rendered, - content_type='text/html' - ) - except Exception as e: - logger.error(f"Error handling models page: {e}", exc_info=True) - return web.Response( - text="Error loading models page", - status=500 - ) - - async def get_models(self, request: web.Request) -> web.Response: - """Get paginated model data""" - try: - # Parse common query parameters - params = self._parse_common_params(request) - - # Get data from service - result = await self.service.get_paginated_data(**params) - - # Format response items - formatted_result = { - 'items': [await self.service.format_response(item) for item in result['items']], - 'total': result['total'], - 'page': result['page'], - 'page_size': result['page_size'], - 'total_pages': result['total_pages'] - } - - return web.json_response(formatted_result) - - except Exception as e: - logger.error(f"Error in get_{self.model_type}s: {e}", exc_info=True) - return web.json_response({"error": str(e)}, status=500) - - def _parse_common_params(self, request: web.Request) -> Dict: - """Parse common query parameters""" - # Parse basic pagination and sorting - page = int(request.query.get('page', '1')) - page_size = min(int(request.query.get('page_size', '20')), 100) - sort_by = request.query.get('sort_by', 'name') - folder = request.query.get('folder', None) - search = request.query.get('search', None) - fuzzy_search = request.query.get('fuzzy_search', 'false').lower() == 'true' - - # Parse filter arrays - base_models = request.query.getall('base_model', []) - tags = request.query.getall('tag', []) - favorites_only = request.query.get('favorites_only', 'false').lower() == 'true' - - # Parse search options - search_options = { - 'filename': request.query.get('search_filename', 'true').lower() == 'true', - 'modelname': request.query.get('search_modelname', 'true').lower() == 'true', - 'tags': request.query.get('search_tags', 'false').lower() == 'true', - 'creator': request.query.get('search_creator', 'false').lower() == 'true', - 'recursive': request.query.get('recursive', 'true').lower() == 'true', - } - - # Parse hash filters if provided - hash_filters = {} - if 'hash' in request.query: - hash_filters['single_hash'] = request.query['hash'] - elif 'hashes' in request.query: - try: - hash_list = json.loads(request.query['hashes']) - if isinstance(hash_list, list): - hash_filters['multiple_hashes'] = hash_list - except (json.JSONDecodeError, TypeError): - pass - - return { - 'page': page, - 'page_size': page_size, - 'sort_by': sort_by, - 'folder': folder, - 'search': search, - 'fuzzy_search': fuzzy_search, - 'base_models': base_models, - 'tags': tags, - 'search_options': search_options, - 'hash_filters': hash_filters, - 'favorites_only': favorites_only, - # Add model-specific parameters - **self._parse_specific_params(request) - } - def _parse_specific_params(self, request: web.Request) -> Dict: - """Parse model-specific parameters - to be overridden by subclasses""" + """Parse model-specific parameters - to be overridden by subclasses.""" return {} - - # Common route handlers - async def delete_model(self, request: web.Request) -> web.Response: - """Handle model deletion request""" - return await ModelRouteUtils.handle_delete_model(request, self.service.scanner) - - async def exclude_model(self, request: web.Request) -> web.Response: - """Handle model exclusion request""" - return await ModelRouteUtils.handle_exclude_model(request, self.service.scanner) - - async def fetch_civitai(self, request: web.Request) -> web.Response: - """Handle CivitAI metadata fetch request - force refresh model metadata""" - try: - data = await request.json() - file_path = data.get('file_path') - if not file_path: - return web.json_response({"success": False, "error": "File path is required"}, status=400) - # Get model data from cache - cache = await self.service.scanner.get_cached_data() - model_data = next((item for item in cache.raw_data if item['file_path'] == file_path), None) - - if not model_data: - return web.json_response({"success": False, "error": "Model not found in cache"}, status=404) - - # Check if model has SHA256 hash - if not model_data.get('sha256'): - return web.json_response({"success": False, "error": "No SHA256 hash found"}, status=400) - - # Use fetch_and_update_model to get and update metadata - success, error = await ModelRouteUtils.fetch_and_update_model( - sha256=model_data['sha256'], - file_path=file_path, - model_data=model_data, - update_cache_func=self.service.scanner.update_single_model_cache - ) - - if not success: - return web.json_response({"success": False, "error": error}) - - # Format the updated metadata for response - formatted_metadata = await self.service.format_response(model_data) - return web.json_response({ - "success": True, - "metadata": formatted_metadata - }) - - except Exception as e: - logger.error(f"Error fetching from CivitAI: {e}", exc_info=True) - return web.json_response({"success": False, "error": str(e)}, status=500) - - async def relink_civitai(self, request: web.Request) -> web.Response: - """Handle CivitAI metadata re-linking request""" - return await ModelRouteUtils.handle_relink_civitai(request, self.service.scanner) - - async def replace_preview(self, request: web.Request) -> web.Response: - """Handle preview image replacement""" - return await ModelRouteUtils.handle_replace_preview(request, self.service.scanner) - - async def save_metadata(self, request: web.Request) -> web.Response: - """Handle saving metadata updates""" - return await ModelRouteUtils.handle_save_metadata(request, self.service.scanner) - - async def add_tags(self, request: web.Request) -> web.Response: - """Handle adding tags to model metadata""" - return await ModelRouteUtils.handle_add_tags(request, self.service.scanner) - - async def rename_model(self, request: web.Request) -> web.Response: - """Handle renaming a model file and its associated files""" - return await ModelRouteUtils.handle_rename_model(request, self.service.scanner) - - async def bulk_delete_models(self, request: web.Request) -> web.Response: - """Handle bulk deletion of models""" - return await ModelRouteUtils.handle_bulk_delete_models(request, self.service.scanner) - - async def verify_duplicates(self, request: web.Request) -> web.Response: - """Handle verification of duplicate model hashes""" - return await ModelRouteUtils.handle_verify_duplicates(request, self.service.scanner) - - async def get_top_tags(self, request: web.Request) -> web.Response: - """Handle request for top tags sorted by frequency""" - try: - limit = int(request.query.get('limit', '20')) - if limit < 1 or limit > 100: - limit = 20 - - top_tags = await self.service.get_top_tags(limit) - - return web.json_response({ - 'success': True, - 'tags': top_tags - }) - - except Exception as e: - logger.error(f"Error getting top tags: {str(e)}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': 'Internal server error' - }, status=500) - - async def get_base_models(self, request: web.Request) -> web.Response: - """Get base models used in models""" - try: - limit = int(request.query.get('limit', '20')) - if limit < 1 or limit > 100: - limit = 20 - - base_models = await self.service.get_base_models(limit) - - return web.json_response({ - 'success': True, - 'base_models': base_models - }) - except Exception as e: - logger.error(f"Error retrieving base models: {e}") - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def scan_models(self, request: web.Request) -> web.Response: - """Force a rescan of model files""" - try: - full_rebuild = request.query.get('full_rebuild', 'false').lower() == 'true' - - await self.service.scan_models(force_refresh=True, rebuild_cache=full_rebuild) - return web.json_response({ - "status": "success", - "message": f"{self.model_type.capitalize()} scan completed" - }) - except Exception as e: - logger.error(f"Error in scan_{self.model_type}s: {e}", exc_info=True) - return web.json_response({"error": str(e)}, status=500) - - async def get_model_roots(self, request: web.Request) -> web.Response: - """Return the model root directories""" - try: - roots = self.service.get_model_roots() - return web.json_response({ - "success": True, - "roots": roots - }) - except Exception as e: - logger.error(f"Error getting {self.model_type} roots: {e}", exc_info=True) - return web.json_response({ - "success": False, - "error": str(e) - }, status=500) - - async def get_folders(self, request: web.Request) -> web.Response: - """Get all folders in the cache""" - try: - cache = await self.service.scanner.get_cached_data() - return web.json_response({ - 'folders': cache.folders - }) - except Exception as e: - logger.error(f"Error getting folders: {e}") - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def get_folder_tree(self, request: web.Request) -> web.Response: - """Get hierarchical folder tree structure for download modal""" - try: - model_root = request.query.get('model_root') - if not model_root: - return web.json_response({ - 'success': False, - 'error': 'model_root parameter is required' - }, status=400) - - folder_tree = await self.service.get_folder_tree(model_root) - return web.json_response({ - 'success': True, - 'tree': folder_tree - }) - except Exception as e: - logger.error(f"Error getting folder tree: {e}") - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def get_unified_folder_tree(self, request: web.Request) -> web.Response: - """Get unified folder tree across all model roots""" - try: - unified_tree = await self.service.get_unified_folder_tree() - return web.json_response({ - 'success': True, - 'tree': unified_tree - }) - except Exception as e: - logger.error(f"Error getting unified folder tree: {e}") - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def find_duplicate_models(self, request: web.Request) -> web.Response: - """Find models with duplicate SHA256 hashes""" - try: - # Get duplicate hashes from service - duplicates = self.service.find_duplicate_hashes() - - # Format the response - result = [] - cache = await self.service.scanner.get_cached_data() - - for sha256, paths in duplicates.items(): - group = { - "hash": sha256, - "models": [] - } - # Find matching models for each path - for path in paths: - model = next((m for m in cache.raw_data if m['file_path'] == path), None) - if model: - group["models"].append(await self.service.format_response(model)) - - # Add the primary model too - primary_path = self.service.get_path_by_hash(sha256) - if primary_path and primary_path not in paths: - primary_model = next((m for m in cache.raw_data if m['file_path'] == primary_path), None) - if primary_model: - group["models"].insert(0, await self.service.format_response(primary_model)) - - if len(group["models"]) > 1: # Only include if we found multiple models - result.append(group) - - return web.json_response({ - "success": True, - "duplicates": result, - "count": len(result) - }) - except Exception as e: - logger.error(f"Error finding duplicate {self.model_type}s: {e}", exc_info=True) - return web.json_response({ - "success": False, - "error": str(e) - }, status=500) - - async def find_filename_conflicts(self, request: web.Request) -> web.Response: - """Find models with conflicting filenames""" - try: - # Get duplicate filenames from service - duplicates = self.service.find_duplicate_filenames() - - # Format the response - result = [] - cache = await self.service.scanner.get_cached_data() - - for filename, paths in duplicates.items(): - group = { - "filename": filename, - "models": [] - } - # Find matching models for each path - for path in paths: - model = next((m for m in cache.raw_data if m['file_path'] == path), None) - if model: - group["models"].append(await self.service.format_response(model)) - - # Find the model from the main index too - hash_val = self.service.scanner.get_hash_by_filename(filename) - if hash_val: - main_path = self.service.get_path_by_hash(hash_val) - if main_path and main_path not in paths: - main_model = next((m for m in cache.raw_data if m['file_path'] == main_path), None) - if main_model: - group["models"].insert(0, await self.service.format_response(main_model)) - - if group["models"]: - result.append(group) - - return web.json_response({ - "success": True, - "conflicts": result, - "count": len(result) - }) - except Exception as e: - logger.error(f"Error finding filename conflicts for {self.model_type}s: {e}", exc_info=True) - return web.json_response({ - "success": False, - "error": str(e) - }, status=500) - - # Download management methods - async def download_model(self, request: web.Request) -> web.Response: - """Handle model download request""" - return await ModelRouteUtils.handle_download_model(request) - - async def download_model_get(self, request: web.Request) -> web.Response: - """Handle model download request via GET method""" - try: - # Extract query parameters - model_id = request.query.get('model_id') - if not model_id: - return web.Response( - status=400, - text="Missing required parameter: Please provide 'model_id'" - ) - - # Get optional parameters - model_version_id = request.query.get('model_version_id') - download_id = request.query.get('download_id') - use_default_paths = request.query.get('use_default_paths', 'false').lower() == 'true' - source = request.query.get('source') # Optional source parameter - - # Create a data dictionary that mimics what would be received from a POST request - data = { - 'model_id': model_id - } - - # Add optional parameters only if they are provided - if model_version_id: - data['model_version_id'] = model_version_id - - if download_id: - data['download_id'] = download_id - - data['use_default_paths'] = use_default_paths - - # Add source parameter if provided - if source: - data['source'] = source - - # Create a mock request object with the data - future = asyncio.get_event_loop().create_future() - future.set_result(data) - - mock_request = type('MockRequest', (), { - 'json': lambda self=None: future - })() - - # Call the existing download handler - return await ModelRouteUtils.handle_download_model(mock_request) - - except Exception as e: - error_message = str(e) - logger.error(f"Error downloading model via GET: {error_message}", exc_info=True) - return web.Response(status=500, text=error_message) - - async def cancel_download_get(self, request: web.Request) -> web.Response: - """Handle GET request for cancelling a download by download_id""" - try: - download_id = request.query.get('download_id') - if not download_id: - return web.json_response({ - 'success': False, - 'error': 'Download ID is required' - }, status=400) - - # Create a mock request with match_info for compatibility - mock_request = type('MockRequest', (), { - 'match_info': {'download_id': download_id} - })() - return await ModelRouteUtils.handle_cancel_download(mock_request) - except Exception as e: - logger.error(f"Error cancelling download via GET: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def get_download_progress(self, request: web.Request) -> web.Response: - """Handle request for download progress by download_id""" - try: - # Get download_id from URL path - download_id = request.match_info.get('download_id') - if not download_id: - return web.json_response({ - 'success': False, - 'error': 'Download ID is required' - }, status=400) - - progress_data = ws_manager.get_download_progress(download_id) - - if progress_data is None: - return web.json_response({ - 'success': False, - 'error': 'Download ID not found' - }, status=404) - - return web.json_response({ - 'success': True, - 'progress': progress_data.get('progress', 0) - }) - except Exception as e: - logger.error(f"Error getting download progress: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def fetch_all_civitai(self, request: web.Request) -> web.Response: - """Fetch CivitAI metadata for all models in the background""" - try: - cache = await self.service.scanner.get_cached_data() - total = len(cache.raw_data) - processed = 0 - success = 0 - needs_resort = False - - # Prepare models to process, only those without CivitAI data - enable_metadata_archive_db = settings.get('enable_metadata_archive_db', False) - # Filter models that need CivitAI metadata update - to_process = [ - model for model in cache.raw_data - if model.get('sha256') - and ( - not model.get('civitai') or not model['civitai'].get('id') - ) - and ( - (enable_metadata_archive_db and not model.get('db_checked', False)) - or (not enable_metadata_archive_db and model.get('from_civitai') is True) - ) - ] - total_to_process = len(to_process) - - # Send initial progress - await ws_manager.broadcast({ - 'status': 'started', - 'total': total_to_process, - 'processed': 0, - 'success': 0 - }) - - # Process each model - for model in to_process: - try: - original_name = model.get('model_name') - result, error = await ModelRouteUtils.fetch_and_update_model( - sha256=model['sha256'], - file_path=model['file_path'], - model_data=model, - update_cache_func=self.service.scanner.update_single_model_cache - ) - if result: - success += 1 - if original_name != model.get('model_name'): - needs_resort = True - - processed += 1 - - # Send progress update - await ws_manager.broadcast({ - 'status': 'processing', - 'total': total_to_process, - 'processed': processed, - 'success': success, - 'current_name': model.get('model_name', 'Unknown') - }) - - except Exception as e: - logger.error(f"Error fetching CivitAI data for {model['file_path']}: {e}") - - if needs_resort: - await cache.resort() - - # Send completion message - await ws_manager.broadcast({ - 'status': 'completed', - 'total': total_to_process, - 'processed': processed, - 'success': success - }) - - return web.json_response({ - "success": True, - "message": f"Successfully updated {success} of {processed} processed {self.model_type}s (total: {total})" - }) - - except Exception as e: - # Send error message - await ws_manager.broadcast({ - 'status': 'error', - 'error': str(e) - }) - logger.error(f"Error in fetch_all_civitai for {self.model_type}s: {e}") - return web.Response(text=str(e), status=500) - - async def get_civitai_versions(self, request: web.Request) -> web.Response: - """Get available versions for a Civitai model with local availability info""" - try: - model_id = request.match_info['model_id'] - metadata_provider = await get_default_metadata_provider() - response = await metadata_provider.get_model_versions(model_id) - if not response or not response.get('modelVersions'): - return web.Response(status=404, text="Model not found") - - versions = response.get('modelVersions', []) - model_type = response.get('type', '') - - # Check model type - allow subclasses to override validation - if not self._validate_civitai_model_type(model_type): - return web.json_response({ - 'error': f"Model type mismatch. Expected {self._get_expected_model_types()}, got {model_type}" - }, status=400) - - # Check local availability for each version - for version in versions: - # Find the model file (type="Model" and primary=true) in the files list - model_file = self._find_model_file(version.get('files', [])) - - if model_file: - sha256 = model_file.get('hashes', {}).get('SHA256') - if sha256: - # Set existsLocally and localPath at the version level - version['existsLocally'] = self.service.has_hash(sha256) - if version['existsLocally']: - version['localPath'] = self.service.get_path_by_hash(sha256) - - # Also set the model file size at the version level for easier access - version['modelSizeKB'] = model_file.get('sizeKB') - else: - # No model file found in this version - version['existsLocally'] = False - - return web.json_response(versions) - except Exception as e: - logger.error(f"Error fetching {self.model_type} model versions: {e}") - return web.Response(status=500, text=str(e)) - - async def get_civitai_model_by_version(self, request: web.Request) -> web.Response: - """Get CivitAI model details by model version ID""" - try: - model_version_id = request.match_info.get('modelVersionId') - - # Get model details from metadata provider - metadata_provider = await get_default_metadata_provider() - model, error_msg = await metadata_provider.get_model_version_info(model_version_id) - - if not model: - # Log warning for failed model retrieval - logger.warning(f"Failed to fetch model version {model_version_id}: {error_msg}") - - # Determine status code based on error message - status_code = 404 if error_msg and "not found" in error_msg.lower() else 500 - - return web.json_response({ - "success": False, - "error": error_msg or "Failed to fetch model information" - }, status=status_code) - - return web.json_response(model) - except Exception as e: - logger.error(f"Error fetching model details: {e}") - return web.json_response({ - "success": False, - "error": str(e) - }, status=500) - - async def get_civitai_model_by_hash(self, request: web.Request) -> web.Response: - """Get CivitAI model details by hash""" - try: - hash = request.match_info.get('hash') - metadata_provider = await get_default_metadata_provider() - model, error = await metadata_provider.get_model_by_hash(hash) - if error: - logger.warning(f"Error getting model by hash: {error}") - return web.json_response({ - "success": False, - "error": error - }, status=404) - return web.json_response(model) - except Exception as e: - logger.error(f"Error fetching model details by hash: {e}") - return web.json_response({ - "success": False, - "error": str(e) - }, status=500) - def _validate_civitai_model_type(self, model_type: str) -> bool: - """Validate CivitAI model type - to be overridden by subclasses""" - return True # Default: accept all types - - def _get_expected_model_types(self) -> str: - """Get expected model types string for error messages - to be overridden by subclasses""" - return "any model type" - - def _find_model_file(self, files: list) -> dict: - """Find the appropriate model file from the files list - can be overridden by subclasses""" - # Find the primary model file (type="Model" and primary=true) in the files list - return next((file for file in files if file.get('type') == 'Model' and file.get('primary') == True), None) - - # Common model move handlers - async def move_model(self, request: web.Request) -> web.Response: - """Handle model move request""" - try: - data = await request.json() - file_path = data.get('file_path') - target_path = data.get('target_path') - - if not file_path or not target_path: - return web.Response(text='File path and target path are required', status=400) - - result = await self.model_move_service.move_model(file_path, target_path) - - if result['success']: - return web.json_response(result) - else: - return web.json_response(result, status=500) - - except Exception as e: - logger.error(f"Error moving model: {e}", exc_info=True) - return web.Response(text=str(e), status=500) + """Validate CivitAI model type - to be overridden by subclasses.""" + return True + + def _get_expected_model_types(self) -> str: + """Get expected model types string for error messages - to be overridden by subclasses.""" + return "any model type" + + def _find_model_file(self, files): + """Find the appropriate model file from the files list - can be overridden by subclasses.""" + return next((file for file in files if file.get("type") == "Model" and file.get("primary") is True), None) + + def get_handler(self, name: str) -> Callable[[web.Request], web.StreamResponse]: + """Expose handlers for subclasses or tests.""" + return self._ensure_handler_mapping()[name] + + @property + def utils(self) -> ModelRouteUtils: # pragma: no cover - compatibility shim + return ModelRouteUtils + + def _ensure_service(self): + if self.service is None: + raise RuntimeError("Model service has not been attached") + return self.service + + def _ensure_file_service(self) -> ModelFileService: + if self.model_file_service is None: + service = self._ensure_service() + self.model_file_service = ModelFileService(service.scanner, service.model_type) + return self.model_file_service + + def _ensure_move_service(self) -> ModelMoveService: + if self.model_move_service is None: + service = self._ensure_service() + self.model_move_service = ModelMoveService(service.scanner) + return self.model_move_service + + def _make_handler_proxy(self, name: str) -> Callable[[web.Request], web.StreamResponse]: + async def proxy(request: web.Request) -> web.StreamResponse: + try: + handler = self.get_handler(name) + except RuntimeError: + return web.json_response({"success": False, "error": "Service not ready"}, status=503) + return await handler(request) + + return proxy - async def move_models_bulk(self, request: web.Request) -> web.Response: - """Handle bulk model move request""" - try: - data = await request.json() - file_paths = data.get('file_paths', []) - target_path = data.get('target_path') - - if not file_paths or not target_path: - return web.Response(text='File paths and target path are required', status=400) - - result = await self.model_move_service.move_models_bulk(file_paths, target_path) - return web.json_response(result) - - except Exception as e: - logger.error(f"Error moving models in bulk: {e}", exc_info=True) - return web.Response(text=str(e), status=500) - - async def auto_organize_models(self, request: web.Request) -> web.Response: - """Auto-organize all models or a specific set of models based on current settings""" - try: - # Check if auto-organize is already running - if ws_manager.is_auto_organize_running(): - return web.json_response({ - 'success': False, - 'error': 'Auto-organize is already running. Please wait for it to complete.' - }, status=409) - - # Acquire lock to prevent concurrent auto-organize operations - auto_organize_lock = await ws_manager.get_auto_organize_lock() - - if auto_organize_lock.locked(): - return web.json_response({ - 'success': False, - 'error': 'Auto-organize is already running. Please wait for it to complete.' - }, status=409) - - # Get specific file paths from request if this is a POST with selected models - file_paths = None - if request.method == 'POST': - try: - data = await request.json() - file_paths = data.get('file_paths') - except Exception: - pass # Continue with all models if no valid JSON - - async with auto_organize_lock: - # Use the service layer for business logic - result = await self.model_file_service.auto_organize_models( - file_paths=file_paths, - progress_callback=self.websocket_progress_callback - ) - - return web.json_response(result.to_dict()) - - except Exception as e: - logger.error(f"Error in auto_organize_models: {e}", exc_info=True) - - # Send error message via WebSocket - await ws_manager.broadcast_auto_organize_progress({ - 'type': 'auto_organize_progress', - 'status': 'error', - 'error': str(e) - }) - - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def get_auto_organize_progress(self, request: web.Request) -> web.Response: - """Get current auto-organize progress for polling""" - try: - progress_data = ws_manager.get_auto_organize_progress() - - if progress_data is None: - return web.json_response({ - 'success': False, - 'error': 'No auto-organize operation in progress' - }, status=404) - - return web.json_response({ - 'success': True, - 'progress': progress_data - }) - except Exception as e: - logger.error(f"Error getting auto-organize progress: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def get_model_notes(self, request: web.Request) -> web.Response: - """Get notes for a specific model file""" - try: - model_name = request.query.get('name') - if not model_name: - return web.Response(text=f'{self.model_type.capitalize()} file name is required', status=400) - - notes = await self.service.get_model_notes(model_name) - if notes is not None: - return web.json_response({ - 'success': True, - 'notes': notes - }) - else: - return web.json_response({ - 'success': False, - 'error': f'{self.model_type.capitalize()} not found in cache' - }, status=404) - - except Exception as e: - logger.error(f"Error getting {self.model_type} notes: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def get_model_preview_url(self, request: web.Request) -> web.Response: - """Get the static preview URL for a model file""" - try: - model_name = request.query.get('name') - if not model_name: - return web.Response(text=f'{self.model_type.capitalize()} file name is required', status=400) - - preview_url = await self.service.get_model_preview_url(model_name) - if preview_url: - return web.json_response({ - 'success': True, - 'preview_url': preview_url - }) - else: - return web.json_response({ - 'success': False, - 'error': f'No preview URL found for the specified {self.model_type}' - }, status=404) - - except Exception as e: - logger.error(f"Error getting {self.model_type} preview URL: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def get_model_civitai_url(self, request: web.Request) -> web.Response: - """Get the Civitai URL for a model file""" - try: - model_name = request.query.get('name') - if not model_name: - return web.Response(text=f'{self.model_type.capitalize()} file name is required', status=400) - - result = await self.service.get_model_civitai_url(model_name) - if result['civitai_url']: - return web.json_response({ - 'success': True, - **result - }) - else: - return web.json_response({ - 'success': False, - 'error': f'No Civitai data found for the specified {self.model_type}' - }, status=404) - - except Exception as e: - logger.error(f"Error getting {self.model_type} Civitai URL: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def get_model_metadata(self, request: web.Request) -> web.Response: - """Get filtered CivitAI metadata for a model by file path""" - try: - file_path = request.query.get('file_path') - if not file_path: - return web.Response(text='File path is required', status=400) - - metadata = await self.service.get_model_metadata(file_path) - if metadata is not None: - return web.json_response({ - 'success': True, - 'metadata': metadata - }) - else: - return web.json_response({ - 'success': False, - 'error': f'{self.model_type.capitalize()} not found or no CivitAI metadata available' - }, status=404) - - except Exception as e: - logger.error(f"Error getting {self.model_type} metadata: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def get_model_description(self, request: web.Request) -> web.Response: - """Get model description by file path""" - try: - file_path = request.query.get('file_path') - if not file_path: - return web.Response(text='File path is required', status=400) - - description = await self.service.get_model_description(file_path) - if description is not None: - return web.json_response({ - 'success': True, - 'description': description - }) - else: - return web.json_response({ - 'success': False, - 'error': f'{self.model_type.capitalize()} not found or no description available' - }, status=404) - - except Exception as e: - logger.error(f"Error getting {self.model_type} description: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def get_relative_paths(self, request: web.Request) -> web.Response: - """Get model relative file paths for autocomplete functionality""" - try: - search = request.query.get('search', '').strip() - limit = min(int(request.query.get('limit', '15')), 50) # Max 50 items - - matching_paths = await self.service.search_relative_paths(search, limit) - - return web.json_response({ - 'success': True, - 'relative_paths': matching_paths - }) - - except Exception as e: - logger.error(f"Error getting relative paths for autocomplete: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) \ No newline at end of file diff --git a/py/routes/checkpoint_routes.py b/py/routes/checkpoint_routes.py index 95c747e5..ad4c538a 100644 --- a/py/routes/checkpoint_routes.py +++ b/py/routes/checkpoint_routes.py @@ -2,9 +2,9 @@ import logging from aiohttp import web from .base_model_routes import BaseModelRoutes +from .model_route_registrar import ModelRouteRegistrar from ..services.checkpoint_service import CheckpointService from ..services.service_registry import ServiceRegistry -from ..services.metadata_service import get_default_metadata_provider from ..config import config logger = logging.getLogger(__name__) @@ -14,8 +14,7 @@ class CheckpointRoutes(BaseModelRoutes): def __init__(self): """Initialize Checkpoint routes with Checkpoint service""" - # Service will be initialized later via setup_routes - self.service = None + super().__init__() self.template_name = "checkpoints.html" async def initialize_services(self): @@ -23,8 +22,8 @@ class CheckpointRoutes(BaseModelRoutes): checkpoint_scanner = await ServiceRegistry.get_checkpoint_scanner() self.service = CheckpointService(checkpoint_scanner) - # Initialize parent with the service - super().__init__(self.service) + # Attach service dependencies + self.attach_service(self.service) def setup_routes(self, app: web.Application): """Setup Checkpoint routes""" @@ -34,14 +33,14 @@ class CheckpointRoutes(BaseModelRoutes): # Setup common routes with 'checkpoints' prefix (includes page route) super().setup_routes(app, 'checkpoints') - def setup_specific_routes(self, app: web.Application, prefix: str): + def setup_specific_routes(self, registrar: ModelRouteRegistrar, prefix: str): """Setup Checkpoint-specific routes""" # Checkpoint info by name - app.router.add_get(f'/api/lm/{prefix}/info/{{name}}', self.get_checkpoint_info) - + registrar.add_prefixed_route('GET', '/api/lm/{prefix}/info/{name}', prefix, self.get_checkpoint_info) + # Checkpoint roots and Unet roots - app.router.add_get(f'/api/lm/{prefix}/checkpoints_roots', self.get_checkpoints_roots) - app.router.add_get(f'/api/lm/{prefix}/unet_roots', self.get_unet_roots) + registrar.add_prefixed_route('GET', '/api/lm/{prefix}/checkpoints_roots', prefix, self.get_checkpoints_roots) + registrar.add_prefixed_route('GET', '/api/lm/{prefix}/unet_roots', prefix, self.get_unet_roots) def _validate_civitai_model_type(self, model_type: str) -> bool: """Validate CivitAI model type for Checkpoint""" diff --git a/py/routes/embedding_routes.py b/py/routes/embedding_routes.py index 29b2f9fd..d7d361ce 100644 --- a/py/routes/embedding_routes.py +++ b/py/routes/embedding_routes.py @@ -2,9 +2,9 @@ import logging from aiohttp import web from .base_model_routes import BaseModelRoutes +from .model_route_registrar import ModelRouteRegistrar from ..services.embedding_service import EmbeddingService from ..services.service_registry import ServiceRegistry -from ..services.metadata_service import get_default_metadata_provider logger = logging.getLogger(__name__) @@ -13,8 +13,7 @@ class EmbeddingRoutes(BaseModelRoutes): def __init__(self): """Initialize Embedding routes with Embedding service""" - # Service will be initialized later via setup_routes - self.service = None + super().__init__() self.template_name = "embeddings.html" async def initialize_services(self): @@ -22,8 +21,8 @@ class EmbeddingRoutes(BaseModelRoutes): embedding_scanner = await ServiceRegistry.get_embedding_scanner() self.service = EmbeddingService(embedding_scanner) - # Initialize parent with the service - super().__init__(self.service) + # Attach service dependencies + self.attach_service(self.service) def setup_routes(self, app: web.Application): """Setup Embedding routes""" @@ -33,10 +32,10 @@ class EmbeddingRoutes(BaseModelRoutes): # Setup common routes with 'embeddings' prefix (includes page route) super().setup_routes(app, 'embeddings') - def setup_specific_routes(self, app: web.Application, prefix: str): + def setup_specific_routes(self, registrar: ModelRouteRegistrar, prefix: str): """Setup Embedding-specific routes""" # Embedding info by name - app.router.add_get(f'/api/lm/{prefix}/info/{{name}}', self.get_embedding_info) + registrar.add_prefixed_route('GET', '/api/lm/{prefix}/info/{name}', prefix, self.get_embedding_info) def _validate_civitai_model_type(self, model_type: str) -> bool: """Validate CivitAI model type for Embedding""" diff --git a/py/routes/handlers/model_handlers.py b/py/routes/handlers/model_handlers.py new file mode 100644 index 00000000..66a7123a --- /dev/null +++ b/py/routes/handlers/model_handlers.py @@ -0,0 +1,802 @@ +"""Handlers for base model routes.""" +from __future__ import annotations + +import asyncio +import json +import logging +from dataclasses import dataclass +from typing import Awaitable, Callable, Dict, Iterable, Mapping, Optional + +from aiohttp import web +import jinja2 + +from ...services.model_file_service import ModelFileService, ModelMoveService +from ...services.websocket_progress_callback import WebSocketProgressCallback +from ...services.websocket_manager import WebSocketManager +from ...services.settings_manager import SettingsManager +from ...utils.routes_common import ModelRouteUtils + + +class ModelPageView: + """Render the HTML view for model listings.""" + + def __init__( + self, + *, + template_env: jinja2.Environment, + template_name: str, + service, + settings_service: SettingsManager, + server_i18n, + logger: logging.Logger, + ) -> None: + self._template_env = template_env + self._template_name = template_name + self._service = service + self._settings = settings_service + self._server_i18n = server_i18n + self._logger = logger + + async def handle(self, request: web.Request) -> web.Response: + try: + is_initializing = ( + self._service.scanner._cache is None + or ( + hasattr(self._service.scanner, "is_initializing") + and callable(self._service.scanner.is_initializing) + and self._service.scanner.is_initializing() + ) + or ( + hasattr(self._service.scanner, "_is_initializing") + and self._service.scanner._is_initializing + ) + ) + + if not self._template_env or not self._template_name: + return web.Response( + text="Template environment or template name not set", + status=500, + ) + + user_language = self._settings.get("language", "en") + self._server_i18n.set_locale(user_language) + + if not hasattr(self._template_env, "_i18n_filter_added"): + self._template_env.filters["t"] = self._server_i18n.create_template_filter() + self._template_env._i18n_filter_added = True # type: ignore[attr-defined] + + template_context = { + "is_initializing": is_initializing, + "settings": self._settings, + "request": request, + "folders": [], + "t": self._server_i18n.get_translation, + } + + if not is_initializing: + try: + cache = await self._service.scanner.get_cached_data(force_refresh=False) + template_context["folders"] = getattr(cache, "folders", []) + except Exception as cache_error: # pragma: no cover - logging path + self._logger.error("Error loading cache data: %s", cache_error) + template_context["is_initializing"] = True + + rendered = self._template_env.get_template(self._template_name).render(**template_context) + return web.Response(text=rendered, content_type="text/html") + except Exception as exc: # pragma: no cover - logging path + self._logger.error("Error handling models page: %s", exc, exc_info=True) + return web.Response(text="Error loading models page", status=500) + + +class ModelListingHandler: + """Provide paginated model listings.""" + + def __init__( + self, + *, + service, + parse_specific_params: Callable[[web.Request], Dict], + logger: logging.Logger, + ) -> None: + self._service = service + self._parse_specific_params = parse_specific_params + self._logger = logger + + async def get_models(self, request: web.Request) -> web.Response: + try: + params = self._parse_common_params(request) + result = await self._service.get_paginated_data(**params) + formatted_result = { + "items": [await self._service.format_response(item) for item in result["items"]], + "total": result["total"], + "page": result["page"], + "page_size": result["page_size"], + "total_pages": result["total_pages"], + } + return web.json_response(formatted_result) + except Exception as exc: + self._logger.error("Error retrieving %ss: %s", self._service.model_type, exc, exc_info=True) + return web.json_response({"error": str(exc)}, status=500) + + def _parse_common_params(self, request: web.Request) -> Dict: + page = int(request.query.get("page", "1")) + page_size = min(int(request.query.get("page_size", "20")), 100) + sort_by = request.query.get("sort_by", "name") + folder = request.query.get("folder") + search = request.query.get("search") + fuzzy_search = request.query.get("fuzzy_search", "false").lower() == "true" + + base_models = request.query.getall("base_model", []) + tags = request.query.getall("tag", []) + favorites_only = request.query.get("favorites_only", "false").lower() == "true" + + search_options = { + "filename": request.query.get("search_filename", "true").lower() == "true", + "modelname": request.query.get("search_modelname", "true").lower() == "true", + "tags": request.query.get("search_tags", "false").lower() == "true", + "creator": request.query.get("search_creator", "false").lower() == "true", + "recursive": request.query.get("recursive", "true").lower() == "true", + } + + hash_filters: Dict[str, object] = {} + if "hash" in request.query: + hash_filters["single_hash"] = request.query["hash"] + elif "hashes" in request.query: + try: + hash_list = json.loads(request.query["hashes"]) + if isinstance(hash_list, list): + hash_filters["multiple_hashes"] = hash_list + except (json.JSONDecodeError, TypeError): + pass + + return { + "page": page, + "page_size": page_size, + "sort_by": sort_by, + "folder": folder, + "search": search, + "fuzzy_search": fuzzy_search, + "base_models": base_models, + "tags": tags, + "search_options": search_options, + "hash_filters": hash_filters, + "favorites_only": favorites_only, + **self._parse_specific_params(request), + } + + +class ModelManagementHandler: + """Handle mutation operations on models.""" + + def __init__(self, *, service, logger: logging.Logger) -> None: + self._service = service + self._logger = logger + + async def delete_model(self, request: web.Request) -> web.Response: + return await ModelRouteUtils.handle_delete_model(request, self._service.scanner) + + async def exclude_model(self, request: web.Request) -> web.Response: + return await ModelRouteUtils.handle_exclude_model(request, self._service.scanner) + + async def fetch_civitai(self, request: web.Request) -> web.Response: + try: + data = await request.json() + file_path = data.get("file_path") + if not file_path: + return web.json_response({"success": False, "error": "File path is required"}, status=400) + + cache = await self._service.scanner.get_cached_data() + model_data = next((item for item in cache.raw_data if item["file_path"] == file_path), None) + if not model_data: + return web.json_response({"success": False, "error": "Model not found in cache"}, status=404) + if not model_data.get("sha256"): + return web.json_response({"success": False, "error": "No SHA256 hash found"}, status=400) + + success, error = await ModelRouteUtils.fetch_and_update_model( + sha256=model_data["sha256"], + file_path=file_path, + model_data=model_data, + update_cache_func=self._service.scanner.update_single_model_cache, + ) + if not success: + return web.json_response({"success": False, "error": error}) + + formatted_metadata = await self._service.format_response(model_data) + return web.json_response({"success": True, "metadata": formatted_metadata}) + except Exception as exc: + self._logger.error("Error fetching from CivitAI: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def relink_civitai(self, request: web.Request) -> web.Response: + return await ModelRouteUtils.handle_relink_civitai(request, self._service.scanner) + + async def replace_preview(self, request: web.Request) -> web.Response: + return await ModelRouteUtils.handle_replace_preview(request, self._service.scanner) + + async def save_metadata(self, request: web.Request) -> web.Response: + return await ModelRouteUtils.handle_save_metadata(request, self._service.scanner) + + async def add_tags(self, request: web.Request) -> web.Response: + return await ModelRouteUtils.handle_add_tags(request, self._service.scanner) + + async def rename_model(self, request: web.Request) -> web.Response: + return await ModelRouteUtils.handle_rename_model(request, self._service.scanner) + + async def bulk_delete_models(self, request: web.Request) -> web.Response: + return await ModelRouteUtils.handle_bulk_delete_models(request, self._service.scanner) + + async def verify_duplicates(self, request: web.Request) -> web.Response: + return await ModelRouteUtils.handle_verify_duplicates(request, self._service.scanner) + + +class ModelQueryHandler: + """Serve read-only model queries.""" + + def __init__(self, *, service, logger: logging.Logger) -> None: + self._service = service + self._logger = logger + + async def get_top_tags(self, request: web.Request) -> web.Response: + try: + limit = int(request.query.get("limit", "20")) + if limit < 1 or limit > 100: + limit = 20 + top_tags = await self._service.get_top_tags(limit) + return web.json_response({"success": True, "tags": top_tags}) + except Exception as exc: + self._logger.error("Error getting top tags: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": "Internal server error"}, status=500) + + async def get_base_models(self, request: web.Request) -> web.Response: + try: + limit = int(request.query.get("limit", "20")) + if limit < 1 or limit > 100: + limit = 20 + base_models = await self._service.get_base_models(limit) + return web.json_response({"success": True, "base_models": base_models}) + except Exception as exc: + self._logger.error("Error retrieving base models: %s", exc) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def scan_models(self, request: web.Request) -> web.Response: + try: + full_rebuild = request.query.get("full_rebuild", "false").lower() == "true" + await self._service.scan_models(force_refresh=True, rebuild_cache=full_rebuild) + return web.json_response({"status": "success", "message": f"{self._service.model_type.capitalize()} scan completed"}) + except Exception as exc: + self._logger.error("Error scanning %ss: %s", self._service.model_type, exc, exc_info=True) + return web.json_response({"error": str(exc)}, status=500) + + async def get_model_roots(self, request: web.Request) -> web.Response: + try: + roots = self._service.get_model_roots() + return web.json_response({"success": True, "roots": roots}) + except Exception as exc: + self._logger.error("Error getting %s roots: %s", self._service.model_type, exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_folders(self, request: web.Request) -> web.Response: + try: + cache = await self._service.scanner.get_cached_data() + return web.json_response({"folders": cache.folders}) + except Exception as exc: + self._logger.error("Error getting folders: %s", exc) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_folder_tree(self, request: web.Request) -> web.Response: + try: + model_root = request.query.get("model_root") + if not model_root: + return web.json_response({"success": False, "error": "model_root parameter is required"}, status=400) + folder_tree = await self._service.get_folder_tree(model_root) + return web.json_response({"success": True, "tree": folder_tree}) + except Exception as exc: + self._logger.error("Error getting folder tree: %s", exc) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_unified_folder_tree(self, request: web.Request) -> web.Response: + try: + unified_tree = await self._service.get_unified_folder_tree() + return web.json_response({"success": True, "tree": unified_tree}) + except Exception as exc: + self._logger.error("Error getting unified folder tree: %s", exc) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def find_duplicate_models(self, request: web.Request) -> web.Response: + try: + duplicates = self._service.find_duplicate_hashes() + result = [] + cache = await self._service.scanner.get_cached_data() + for sha256, paths in duplicates.items(): + group = {"hash": sha256, "models": []} + for path in paths: + model = next((m for m in cache.raw_data if m["file_path"] == path), None) + if model: + group["models"].append(await self._service.format_response(model)) + primary_path = self._service.get_path_by_hash(sha256) + if primary_path and primary_path not in paths: + primary_model = next((m for m in cache.raw_data if m["file_path"] == primary_path), None) + if primary_model: + group["models"].insert(0, await self._service.format_response(primary_model)) + if len(group["models"]) > 1: + result.append(group) + return web.json_response({"success": True, "duplicates": result, "count": len(result)}) + except Exception as exc: + self._logger.error("Error finding duplicate %ss: %s", self._service.model_type, exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def find_filename_conflicts(self, request: web.Request) -> web.Response: + try: + duplicates = self._service.find_duplicate_filenames() + result = [] + cache = await self._service.scanner.get_cached_data() + for filename, paths in duplicates.items(): + group = {"filename": filename, "models": []} + for path in paths: + model = next((m for m in cache.raw_data if m["file_path"] == path), None) + if model: + group["models"].append(await self._service.format_response(model)) + hash_val = self._service.scanner.get_hash_by_filename(filename) + if hash_val: + main_path = self._service.get_path_by_hash(hash_val) + if main_path and main_path not in paths: + main_model = next((m for m in cache.raw_data if m["file_path"] == main_path), None) + if main_model: + group["models"].insert(0, await self._service.format_response(main_model)) + if group["models"]: + result.append(group) + return web.json_response({"success": True, "conflicts": result, "count": len(result)}) + except Exception as exc: + self._logger.error("Error finding filename conflicts for %ss: %s", self._service.model_type, exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_model_notes(self, request: web.Request) -> web.Response: + try: + model_name = request.query.get("name") + if not model_name: + return web.Response(text=f"{self._service.model_type.capitalize()} file name is required", status=400) + notes = await self._service.get_model_notes(model_name) + if notes is not None: + return web.json_response({"success": True, "notes": notes}) + return web.json_response({"success": False, "error": f"{self._service.model_type.capitalize()} not found in cache"}, status=404) + except Exception as exc: + self._logger.error("Error getting %s notes: %s", self._service.model_type, exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_model_preview_url(self, request: web.Request) -> web.Response: + try: + model_name = request.query.get("name") + if not model_name: + return web.Response(text=f"{self._service.model_type.capitalize()} file name is required", status=400) + preview_url = await self._service.get_model_preview_url(model_name) + if preview_url: + return web.json_response({"success": True, "preview_url": preview_url}) + return web.json_response({"success": False, "error": f"No preview URL found for the specified {self._service.model_type}"}, status=404) + except Exception as exc: + self._logger.error("Error getting %s preview URL: %s", self._service.model_type, exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_model_civitai_url(self, request: web.Request) -> web.Response: + try: + model_name = request.query.get("name") + if not model_name: + return web.Response(text=f"{self._service.model_type.capitalize()} file name is required", status=400) + result = await self._service.get_model_civitai_url(model_name) + if result["civitai_url"]: + return web.json_response({"success": True, **result}) + return web.json_response({"success": False, "error": f"No Civitai data found for the specified {self._service.model_type}"}, status=404) + except Exception as exc: + self._logger.error("Error getting %s Civitai URL: %s", self._service.model_type, exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_model_metadata(self, request: web.Request) -> web.Response: + try: + file_path = request.query.get("file_path") + if not file_path: + return web.Response(text="File path is required", status=400) + metadata = await self._service.get_model_metadata(file_path) + if metadata is not None: + return web.json_response({"success": True, "metadata": metadata}) + return web.json_response({"success": False, "error": f"{self._service.model_type.capitalize()} not found or no CivitAI metadata available"}, status=404) + except Exception as exc: + self._logger.error("Error getting %s metadata: %s", self._service.model_type, exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_model_description(self, request: web.Request) -> web.Response: + try: + file_path = request.query.get("file_path") + if not file_path: + return web.Response(text="File path is required", status=400) + description = await self._service.get_model_description(file_path) + if description is not None: + return web.json_response({"success": True, "description": description}) + return web.json_response({"success": False, "error": f"{self._service.model_type.capitalize()} not found or no description available"}, status=404) + except Exception as exc: + self._logger.error("Error getting %s description: %s", self._service.model_type, exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_relative_paths(self, request: web.Request) -> web.Response: + try: + search = request.query.get("search", "").strip() + limit = min(int(request.query.get("limit", "15")), 50) + matching_paths = await self._service.search_relative_paths(search, limit) + return web.json_response({"success": True, "relative_paths": matching_paths}) + except Exception as exc: + self._logger.error("Error getting relative paths for autocomplete: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + +class ModelDownloadHandler: + """Coordinate downloads and progress reporting.""" + + def __init__(self, *, ws_manager: WebSocketManager, logger: logging.Logger) -> None: + self._ws_manager = ws_manager + self._logger = logger + + async def download_model(self, request: web.Request) -> web.Response: + return await ModelRouteUtils.handle_download_model(request) + + async def download_model_get(self, request: web.Request) -> web.Response: + try: + model_id = request.query.get("model_id") + if not model_id: + return web.Response(status=400, text="Missing required parameter: Please provide 'model_id'") + + model_version_id = request.query.get("model_version_id") + download_id = request.query.get("download_id") + use_default_paths = request.query.get("use_default_paths", "false").lower() == "true" + source = request.query.get("source") + + data = {"model_id": model_id, "use_default_paths": use_default_paths} + if model_version_id: + data["model_version_id"] = model_version_id + if download_id: + data["download_id"] = download_id + if source: + data["source"] = source + + loop = asyncio.get_event_loop() + future = loop.create_future() + future.set_result(data) + + mock_request = type("MockRequest", (), {"json": lambda self=None: future})() + return await ModelRouteUtils.handle_download_model(mock_request) + except Exception as exc: + self._logger.error("Error downloading model via GET: %s", exc, exc_info=True) + return web.Response(status=500, text=str(exc)) + + async def cancel_download_get(self, request: web.Request) -> web.Response: + try: + download_id = request.query.get("download_id") + if not download_id: + return web.json_response({"success": False, "error": "Download ID is required"}, status=400) + mock_request = type("MockRequest", (), {"match_info": {"download_id": download_id}})() + return await ModelRouteUtils.handle_cancel_download(mock_request) + except Exception as exc: + self._logger.error("Error cancelling download via GET: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_download_progress(self, request: web.Request) -> web.Response: + try: + download_id = request.match_info.get("download_id") + if not download_id: + return web.json_response({"success": False, "error": "Download ID is required"}, status=400) + progress_data = self._ws_manager.get_download_progress(download_id) + if progress_data is None: + return web.json_response({"success": False, "error": "Download ID not found"}, status=404) + return web.json_response({"success": True, "progress": progress_data.get("progress", 0)}) + except Exception as exc: + self._logger.error("Error getting download progress: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + +class ModelCivitaiHandler: + """CivitAI integration endpoints.""" + + def __init__( + self, + *, + service, + settings_service: SettingsManager, + ws_manager: WebSocketManager, + logger: logging.Logger, + metadata_provider_factory: Callable[[], Awaitable], + validate_model_type: Callable[[str], bool], + expected_model_types: Callable[[], str], + find_model_file: Callable[[Iterable[Mapping[str, object]]], Optional[Mapping[str, object]]], + ) -> None: + self._service = service + self._settings = settings_service + self._ws_manager = ws_manager + self._logger = logger + self._metadata_provider_factory = metadata_provider_factory + self._validate_model_type = validate_model_type + self._expected_model_types = expected_model_types + self._find_model_file = find_model_file + + async def fetch_all_civitai(self, request: web.Request) -> web.Response: + try: + cache = await self._service.scanner.get_cached_data() + total = len(cache.raw_data) + processed = 0 + success = 0 + needs_resort = False + + enable_metadata_archive_db = self._settings.get("enable_metadata_archive_db", False) + to_process = [ + model + for model in cache.raw_data + if model.get("sha256") + and (not model.get("civitai") or not model["civitai"].get("id")) + and ( + (enable_metadata_archive_db and not model.get("db_checked", False)) + or (not enable_metadata_archive_db and model.get("from_civitai") is True) + ) + ] + total_to_process = len(to_process) + + await self._ws_manager.broadcast({ + "status": "started", + "total": total_to_process, + "processed": 0, + "success": 0, + }) + + for model in to_process: + try: + original_name = model.get("model_name") + result, error = await ModelRouteUtils.fetch_and_update_model( + sha256=model["sha256"], + file_path=model["file_path"], + model_data=model, + update_cache_func=self._service.scanner.update_single_model_cache, + ) + if result: + success += 1 + if original_name != model.get("model_name"): + needs_resort = True + processed += 1 + await self._ws_manager.broadcast({ + "status": "processing", + "total": total_to_process, + "processed": processed, + "success": success, + "current_name": model.get("model_name", "Unknown"), + }) + except Exception as exc: # pragma: no cover - logging path + self._logger.error("Error fetching CivitAI data for %s: %s", model["file_path"], exc) + + if needs_resort: + await cache.resort() + + await self._ws_manager.broadcast({ + "status": "completed", + "total": total_to_process, + "processed": processed, + "success": success, + }) + + return web.json_response({ + "success": True, + "message": f"Successfully updated {success} of {processed} processed {self._service.model_type}s (total: {total})", + }) + except Exception as exc: + await self._ws_manager.broadcast({"status": "error", "error": str(exc)}) + self._logger.error("Error in fetch_all_civitai for %ss: %s", self._service.model_type, exc) + return web.Response(text=str(exc), status=500) + + async def get_civitai_versions(self, request: web.Request) -> web.Response: + try: + model_id = request.match_info["model_id"] + metadata_provider = await self._metadata_provider_factory() + response = await metadata_provider.get_model_versions(model_id) + if not response or not response.get("modelVersions"): + return web.Response(status=404, text="Model not found") + + versions = response.get("modelVersions", []) + model_type = response.get("type", "") + if not self._validate_model_type(model_type): + return web.json_response( + {"error": f"Model type mismatch. Expected {self._expected_model_types()}, got {model_type}"}, + status=400, + ) + + for version in versions: + model_file = self._find_model_file(version.get("files", [])) if isinstance(version.get("files"), Iterable) else None + if model_file: + hashes = model_file.get("hashes", {}) if isinstance(model_file, Mapping) else {} + sha256 = hashes.get("SHA256") if isinstance(hashes, Mapping) else None + if sha256: + version["existsLocally"] = self._service.has_hash(sha256) + if version["existsLocally"]: + version["localPath"] = self._service.get_path_by_hash(sha256) + version["modelSizeKB"] = model_file.get("sizeKB") if isinstance(model_file, Mapping) else None + else: + version["existsLocally"] = False + return web.json_response(versions) + except Exception as exc: + self._logger.error("Error fetching %s model versions: %s", self._service.model_type, exc) + return web.Response(status=500, text=str(exc)) + + async def get_civitai_model_by_version(self, request: web.Request) -> web.Response: + try: + model_version_id = request.match_info.get("modelVersionId") + metadata_provider = await self._metadata_provider_factory() + model, error_msg = await metadata_provider.get_model_version_info(model_version_id) + if not model: + self._logger.warning("Failed to fetch model version %s: %s", model_version_id, error_msg) + status_code = 404 if error_msg and "not found" in error_msg.lower() else 500 + return web.json_response({"success": False, "error": error_msg or "Failed to fetch model information"}, status=status_code) + return web.json_response(model) + except Exception as exc: + self._logger.error("Error fetching model details: %s", exc) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_civitai_model_by_hash(self, request: web.Request) -> web.Response: + try: + hash_value = request.match_info.get("hash") + metadata_provider = await self._metadata_provider_factory() + model, error = await metadata_provider.get_model_by_hash(hash_value) + if error: + self._logger.warning("Error getting model by hash: %s", error) + return web.json_response({"success": False, "error": error}, status=404) + return web.json_response(model) + except Exception as exc: + self._logger.error("Error fetching model details by hash: %s", exc) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + +class ModelMoveHandler: + """Move model files between folders.""" + + def __init__(self, *, move_service: ModelMoveService, logger: logging.Logger) -> None: + self._move_service = move_service + self._logger = logger + + async def move_model(self, request: web.Request) -> web.Response: + try: + data = await request.json() + file_path = data.get("file_path") + target_path = data.get("target_path") + if not file_path or not target_path: + return web.Response(text="File path and target path are required", status=400) + result = await self._move_service.move_model(file_path, target_path) + status = 200 if result.get("success") else 500 + return web.json_response(result, status=status) + except Exception as exc: + self._logger.error("Error moving model: %s", exc, exc_info=True) + return web.Response(text=str(exc), status=500) + + async def move_models_bulk(self, request: web.Request) -> web.Response: + try: + data = await request.json() + file_paths = data.get("file_paths", []) + target_path = data.get("target_path") + if not file_paths or not target_path: + return web.Response(text="File paths and target path are required", status=400) + result = await self._move_service.move_models_bulk(file_paths, target_path) + return web.json_response(result) + except Exception as exc: + self._logger.error("Error moving models in bulk: %s", exc, exc_info=True) + return web.Response(text=str(exc), status=500) + + +class ModelAutoOrganizeHandler: + """Manage auto-organize operations.""" + + def __init__( + self, + *, + file_service: ModelFileService, + progress_callback: WebSocketProgressCallback, + ws_manager: WebSocketManager, + logger: logging.Logger, + ) -> None: + self._file_service = file_service + self._progress_callback = progress_callback + self._ws_manager = ws_manager + self._logger = logger + + async def auto_organize_models(self, request: web.Request) -> web.Response: + try: + if self._ws_manager.is_auto_organize_running(): + return web.json_response( + {"success": False, "error": "Auto-organize is already running. Please wait for it to complete."}, + status=409, + ) + + auto_organize_lock = await self._ws_manager.get_auto_organize_lock() + if auto_organize_lock.locked(): + return web.json_response( + {"success": False, "error": "Auto-organize is already running. Please wait for it to complete."}, + status=409, + ) + + file_paths = None + if request.method == "POST": + try: + data = await request.json() + file_paths = data.get("file_paths") + except Exception: # pragma: no cover - permissive path + pass + + async with auto_organize_lock: + result = await self._file_service.auto_organize_models( + file_paths=file_paths, + progress_callback=self._progress_callback, + ) + return web.json_response(result.to_dict()) + except Exception as exc: + self._logger.error("Error in auto_organize_models: %s", exc, exc_info=True) + await self._ws_manager.broadcast_auto_organize_progress( + {"type": "auto_organize_progress", "status": "error", "error": str(exc)} + ) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_auto_organize_progress(self, request: web.Request) -> web.Response: + try: + progress_data = self._ws_manager.get_auto_organize_progress() + if progress_data is None: + return web.json_response({"success": False, "error": "No auto-organize operation in progress"}, status=404) + return web.json_response({"success": True, "progress": progress_data}) + except Exception as exc: + self._logger.error("Error getting auto-organize progress: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + +@dataclass +class ModelHandlerSet: + """Aggregate concrete handlers into a flat mapping.""" + + page_view: ModelPageView + listing: ModelListingHandler + management: ModelManagementHandler + query: ModelQueryHandler + download: ModelDownloadHandler + civitai: ModelCivitaiHandler + move: ModelMoveHandler + auto_organize: ModelAutoOrganizeHandler + + def to_route_mapping(self) -> Dict[str, Callable[[web.Request], Awaitable[web.Response]]]: + return { + "handle_models_page": self.page_view.handle, + "get_models": self.listing.get_models, + "delete_model": self.management.delete_model, + "exclude_model": self.management.exclude_model, + "fetch_civitai": self.management.fetch_civitai, + "fetch_all_civitai": self.civitai.fetch_all_civitai, + "relink_civitai": self.management.relink_civitai, + "replace_preview": self.management.replace_preview, + "save_metadata": self.management.save_metadata, + "add_tags": self.management.add_tags, + "rename_model": self.management.rename_model, + "bulk_delete_models": self.management.bulk_delete_models, + "verify_duplicates": self.management.verify_duplicates, + "get_top_tags": self.query.get_top_tags, + "get_base_models": self.query.get_base_models, + "scan_models": self.query.scan_models, + "get_model_roots": self.query.get_model_roots, + "get_folders": self.query.get_folders, + "get_folder_tree": self.query.get_folder_tree, + "get_unified_folder_tree": self.query.get_unified_folder_tree, + "find_duplicate_models": self.query.find_duplicate_models, + "find_filename_conflicts": self.query.find_filename_conflicts, + "download_model": self.download.download_model, + "download_model_get": self.download.download_model_get, + "cancel_download_get": self.download.cancel_download_get, + "get_download_progress": self.download.get_download_progress, + "get_civitai_versions": self.civitai.get_civitai_versions, + "get_civitai_model_by_version": self.civitai.get_civitai_model_by_version, + "get_civitai_model_by_hash": self.civitai.get_civitai_model_by_hash, + "move_model": self.move.move_model, + "move_models_bulk": self.move.move_models_bulk, + "auto_organize_models": self.auto_organize.auto_organize_models, + "get_auto_organize_progress": self.auto_organize.get_auto_organize_progress, + "get_model_notes": self.query.get_model_notes, + "get_model_preview_url": self.query.get_model_preview_url, + "get_model_civitai_url": self.query.get_model_civitai_url, + "get_model_metadata": self.query.get_model_metadata, + "get_model_description": self.query.get_model_description, + "get_relative_paths": self.query.get_relative_paths, + } + diff --git a/py/routes/lora_routes.py b/py/routes/lora_routes.py index 0ddb41ab..ee6bc151 100644 --- a/py/routes/lora_routes.py +++ b/py/routes/lora_routes.py @@ -5,9 +5,9 @@ from typing import Dict from server import PromptServer # type: ignore from .base_model_routes import BaseModelRoutes +from .model_route_registrar import ModelRouteRegistrar from ..services.lora_service import LoraService from ..services.service_registry import ServiceRegistry -from ..services.metadata_service import get_default_metadata_provider from ..utils.utils import get_lora_info logger = logging.getLogger(__name__) @@ -17,8 +17,7 @@ class LoraRoutes(BaseModelRoutes): def __init__(self): """Initialize LoRA routes with LoRA service""" - # Service will be initialized later via setup_routes - self.service = None + super().__init__() self.template_name = "loras.html" async def initialize_services(self): @@ -26,26 +25,26 @@ class LoraRoutes(BaseModelRoutes): lora_scanner = await ServiceRegistry.get_lora_scanner() self.service = LoraService(lora_scanner) - # Initialize parent with the service - super().__init__(self.service) + # Attach service dependencies + self.attach_service(self.service) def setup_routes(self, app: web.Application): """Setup LoRA routes""" # Schedule service initialization on app startup app.on_startup.append(lambda _: self.initialize_services()) - + # Setup common routes with 'loras' prefix (includes page route) super().setup_routes(app, 'loras') - - def setup_specific_routes(self, app: web.Application, prefix: str): + + def setup_specific_routes(self, registrar: ModelRouteRegistrar, prefix: str): """Setup LoRA-specific routes""" # LoRA-specific query routes - app.router.add_get(f'/api/lm/{prefix}/letter-counts', self.get_letter_counts) - app.router.add_get(f'/api/lm/{prefix}/get-trigger-words', self.get_lora_trigger_words) - app.router.add_get(f'/api/lm/{prefix}/usage-tips-by-path', self.get_lora_usage_tips_by_path) - + registrar.add_prefixed_route('GET', '/api/lm/{prefix}/letter-counts', prefix, self.get_letter_counts) + registrar.add_prefixed_route('GET', '/api/lm/{prefix}/get-trigger-words', prefix, self.get_lora_trigger_words) + registrar.add_prefixed_route('GET', '/api/lm/{prefix}/usage-tips-by-path', prefix, self.get_lora_usage_tips_by_path) + # ComfyUI integration - app.router.add_post(f'/api/lm/{prefix}/get_trigger_words', self.get_trigger_words) + registrar.add_prefixed_route('POST', '/api/lm/{prefix}/get_trigger_words', prefix, self.get_trigger_words) def _parse_specific_params(self, request: web.Request) -> Dict: """Parse LoRA-specific parameters""" diff --git a/py/routes/model_route_registrar.py b/py/routes/model_route_registrar.py new file mode 100644 index 00000000..96f65fc5 --- /dev/null +++ b/py/routes/model_route_registrar.py @@ -0,0 +1,99 @@ +"""Route registrar for model endpoints.""" +from __future__ import annotations + +from dataclasses import dataclass +from typing import Callable, Iterable, Mapping + +from aiohttp import web + + +@dataclass(frozen=True) +class RouteDefinition: + """Declarative definition for a HTTP route.""" + + method: str + path_template: str + handler_name: str + + def build_path(self, prefix: str) -> str: + return self.path_template.replace("{prefix}", prefix) + + +COMMON_ROUTE_DEFINITIONS: tuple[RouteDefinition, ...] = ( + RouteDefinition("GET", "/api/lm/{prefix}/list", "get_models"), + RouteDefinition("POST", "/api/lm/{prefix}/delete", "delete_model"), + RouteDefinition("POST", "/api/lm/{prefix}/exclude", "exclude_model"), + RouteDefinition("POST", "/api/lm/{prefix}/fetch-civitai", "fetch_civitai"), + RouteDefinition("POST", "/api/lm/{prefix}/fetch-all-civitai", "fetch_all_civitai"), + RouteDefinition("POST", "/api/lm/{prefix}/relink-civitai", "relink_civitai"), + RouteDefinition("POST", "/api/lm/{prefix}/replace-preview", "replace_preview"), + RouteDefinition("POST", "/api/lm/{prefix}/save-metadata", "save_metadata"), + RouteDefinition("POST", "/api/lm/{prefix}/add-tags", "add_tags"), + RouteDefinition("POST", "/api/lm/{prefix}/rename", "rename_model"), + RouteDefinition("POST", "/api/lm/{prefix}/bulk-delete", "bulk_delete_models"), + RouteDefinition("POST", "/api/lm/{prefix}/verify-duplicates", "verify_duplicates"), + RouteDefinition("POST", "/api/lm/{prefix}/move_model", "move_model"), + RouteDefinition("POST", "/api/lm/{prefix}/move_models_bulk", "move_models_bulk"), + RouteDefinition("GET", "/api/lm/{prefix}/auto-organize", "auto_organize_models"), + RouteDefinition("POST", "/api/lm/{prefix}/auto-organize", "auto_organize_models"), + RouteDefinition("GET", "/api/lm/{prefix}/auto-organize-progress", "get_auto_organize_progress"), + RouteDefinition("GET", "/api/lm/{prefix}/top-tags", "get_top_tags"), + RouteDefinition("GET", "/api/lm/{prefix}/base-models", "get_base_models"), + RouteDefinition("GET", "/api/lm/{prefix}/scan", "scan_models"), + RouteDefinition("GET", "/api/lm/{prefix}/roots", "get_model_roots"), + RouteDefinition("GET", "/api/lm/{prefix}/folders", "get_folders"), + RouteDefinition("GET", "/api/lm/{prefix}/folder-tree", "get_folder_tree"), + RouteDefinition("GET", "/api/lm/{prefix}/unified-folder-tree", "get_unified_folder_tree"), + RouteDefinition("GET", "/api/lm/{prefix}/find-duplicates", "find_duplicate_models"), + RouteDefinition("GET", "/api/lm/{prefix}/find-filename-conflicts", "find_filename_conflicts"), + RouteDefinition("GET", "/api/lm/{prefix}/get-notes", "get_model_notes"), + RouteDefinition("GET", "/api/lm/{prefix}/preview-url", "get_model_preview_url"), + RouteDefinition("GET", "/api/lm/{prefix}/civitai-url", "get_model_civitai_url"), + RouteDefinition("GET", "/api/lm/{prefix}/metadata", "get_model_metadata"), + RouteDefinition("GET", "/api/lm/{prefix}/model-description", "get_model_description"), + RouteDefinition("GET", "/api/lm/{prefix}/relative-paths", "get_relative_paths"), + RouteDefinition("GET", "/api/lm/{prefix}/civitai/versions/{model_id}", "get_civitai_versions"), + RouteDefinition("GET", "/api/lm/{prefix}/civitai/model/version/{modelVersionId}", "get_civitai_model_by_version"), + RouteDefinition("GET", "/api/lm/{prefix}/civitai/model/hash/{hash}", "get_civitai_model_by_hash"), + RouteDefinition("POST", "/api/lm/download-model", "download_model"), + RouteDefinition("GET", "/api/lm/download-model-get", "download_model_get"), + RouteDefinition("GET", "/api/lm/cancel-download-get", "cancel_download_get"), + RouteDefinition("GET", "/api/lm/download-progress/{download_id}", "get_download_progress"), + RouteDefinition("GET", "/{prefix}", "handle_models_page"), +) + + +class ModelRouteRegistrar: + """Bind declarative definitions to an aiohttp router.""" + + _METHOD_MAP = { + "GET": "add_get", + "POST": "add_post", + "PUT": "add_put", + "DELETE": "add_delete", + } + + def __init__(self, app: web.Application) -> None: + self._app = app + + def register_common_routes( + self, + prefix: str, + handler_lookup: Mapping[str, Callable[[web.Request], object]], + *, + definitions: Iterable[RouteDefinition] = COMMON_ROUTE_DEFINITIONS, + ) -> None: + for definition in definitions: + self._bind_route(definition.method, definition.build_path(prefix), handler_lookup[definition.handler_name]) + + def add_route(self, method: str, path: str, handler: Callable) -> None: + self._bind_route(method, path, handler) + + def add_prefixed_route(self, method: str, path_template: str, prefix: str, handler: Callable) -> None: + self._bind_route(method, path_template.replace("{prefix}", prefix), handler) + + def _bind_route(self, method: str, path: str, handler: Callable) -> None: + add_method_name = self._METHOD_MAP[method.upper()] + add_method = getattr(self._app.router, add_method_name) + add_method(path, handler) + diff --git a/tests/routes/test_base_model_routes_smoke.py b/tests/routes/test_base_model_routes_smoke.py index bccd83a9..2b9ed805 100644 --- a/tests/routes/test_base_model_routes_smoke.py +++ b/tests/routes/test_base_model_routes_smoke.py @@ -37,7 +37,7 @@ from py_local.config import config class DummyRoutes(BaseModelRoutes): template_name = "dummy.html" - def setup_specific_routes(self, app: web.Application, prefix: str) -> None: # pragma: no cover - no extra routes in smoke tests + def setup_specific_routes(self, registrar, prefix: str) -> None: # pragma: no cover - no extra routes in smoke tests return None From fec85bcc08f45f954022c9f7ef0b68604be6b1a8 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sun, 21 Sep 2025 22:45:11 +0800 Subject: [PATCH 052/110] refactor: unify standalone mode check using environment variable --- py/config.py | 5 ++--- py/metadata_collector/__init__.py | 4 +--- py/metadata_collector/metadata_processor.py | 4 ++-- py/routes/misc_routes.py | 2 +- py/routes/recipe_routes.py | 2 +- py/utils/usage_stats.py | 3 +-- run_tests.py | 4 ++++ standalone.py | 3 +++ 8 files changed, 15 insertions(+), 12 deletions(-) diff --git a/py/config.py b/py/config.py index 1bdfe2bb..a15d0141 100644 --- a/py/config.py +++ b/py/config.py @@ -3,12 +3,11 @@ import platform import folder_paths # type: ignore from typing import List import logging -import sys import json import urllib.parse -# Check if running in standalone mode -standalone_mode = 'nodes' not in sys.modules +# Use an environment variable to control standalone mode +standalone_mode = os.environ.get("HF_HUB_DISABLE_TELEMETRY", "0") == "0" logger = logging.getLogger(__name__) diff --git a/py/metadata_collector/__init__.py b/py/metadata_collector/__init__.py index 29f377e9..d71bf49f 100644 --- a/py/metadata_collector/__init__.py +++ b/py/metadata_collector/__init__.py @@ -1,9 +1,7 @@ import os -import importlib -import sys # Check if running in standalone mode -standalone_mode = 'nodes' not in sys.modules +standalone_mode = os.environ.get("HF_HUB_DISABLE_TELEMETRY", "0") == "0" if not standalone_mode: from .metadata_hook import MetadataHook diff --git a/py/metadata_collector/metadata_processor.py b/py/metadata_collector/metadata_processor.py index 437677d7..3532ceba 100644 --- a/py/metadata_collector/metadata_processor.py +++ b/py/metadata_collector/metadata_processor.py @@ -1,9 +1,9 @@ import json -import sys +import os from .constants import IMAGES # Check if running in standalone mode -standalone_mode = 'nodes' not in sys.modules +standalone_mode = os.environ.get("HF_HUB_DISABLE_TELEMETRY", "0") == "0" from .constants import MODELS, PROMPTS, SAMPLING, LORAS, SIZE, IS_SAMPLER diff --git a/py/routes/misc_routes.py b/py/routes/misc_routes.py index f8173133..b7598d97 100644 --- a/py/routes/misc_routes.py +++ b/py/routes/misc_routes.py @@ -18,7 +18,7 @@ from ..services.websocket_manager import ws_manager from ..services.downloader import get_downloader logger = logging.getLogger(__name__) -standalone_mode = 'nodes' not in sys.modules +standalone_mode = os.environ.get("HF_HUB_DISABLE_TELEMETRY", "0") == "0" # Node registry for tracking active workflow nodes class NodeRegistry: diff --git a/py/routes/recipe_routes.py b/py/routes/recipe_routes.py index 0c8843b4..21214d99 100644 --- a/py/routes/recipe_routes.py +++ b/py/routes/recipe_routes.py @@ -21,7 +21,7 @@ from ..services.server_i18n import server_i18n from ..config import config # Check if running in standalone mode -standalone_mode = 'nodes' not in sys.modules +standalone_mode = os.environ.get("HF_HUB_DISABLE_TELEMETRY", "0") == "0" from ..services.service_registry import ServiceRegistry # Add ServiceRegistry import from ..services.downloader import get_downloader diff --git a/py/utils/usage_stats.py b/py/utils/usage_stats.py index 1466ee21..fc9d4d72 100644 --- a/py/utils/usage_stats.py +++ b/py/utils/usage_stats.py @@ -1,6 +1,5 @@ import os import json -import sys import time import asyncio import logging @@ -12,7 +11,7 @@ from ..config import config from ..services.service_registry import ServiceRegistry # Check if running in standalone mode -standalone_mode = 'nodes' not in sys.modules +standalone_mode = os.environ.get("HF_HUB_DISABLE_TELEMETRY", "0") == "0" if not standalone_mode: from ..metadata_collector.metadata_registry import MetadataRegistry diff --git a/run_tests.py b/run_tests.py index 627c77bc..af5f96ff 100644 --- a/run_tests.py +++ b/run_tests.py @@ -10,6 +10,10 @@ import sys import os from pathlib import Path +# Set environment variable to indicate standalone mode +# HF_HUB_DISABLE_TELEMETRY is from ComfyUI main.py +standalone_mode = os.environ.get("HF_HUB_DISABLE_TELEMETRY", "0") == "0" + def main(): """Run pytest from the tests directory to avoid import issues.""" # Get the script directory diff --git a/standalone.py b/standalone.py index f38a89fc..a6259851 100644 --- a/standalone.py +++ b/standalone.py @@ -4,6 +4,9 @@ import sys import json from py.middleware.cache_middleware import cache_control +# Set environment variable to indicate standalone mode +os.environ["COMFYUI_LORA_MANAGER_STANDALONE"] = "1" + # Create mock modules for py/nodes directory - add this before any other imports def mock_nodes_directory(): """Create mock modules for all Python files in the py/nodes directory""" From 2d00cfdd319fb9d5750db77e7231cef680fc3c05 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sun, 21 Sep 2025 23:13:30 +0800 Subject: [PATCH 053/110] refactor: enhance BaseModelService initialization and improve filtering logic --- py/services/base_model_service.py | 261 +++++++-------------- py/services/model_query.py | 196 ++++++++++++++++ tests/services/test_base_model_service.py | 269 ++++++++++++++++++++++ 3 files changed, 552 insertions(+), 174 deletions(-) create mode 100644 py/services/model_query.py create mode 100644 tests/services/test_base_model_service.py diff --git a/py/services/base_model_service.py b/py/services/base_model_service.py index ed1fc930..0b4aaf99 100644 --- a/py/services/base_model_service.py +++ b/py/services/base_model_service.py @@ -5,98 +5,88 @@ import os from ..utils.models import BaseModelMetadata from ..utils.routes_common import ModelRouteUtils -from ..utils.constants import NSFW_LEVELS -from .settings_manager import settings -from ..utils.utils import fuzzy_match +from .model_query import FilterCriteria, ModelCacheRepository, ModelFilterSet, SearchStrategy, SettingsProvider +from .settings_manager import settings as default_settings logger = logging.getLogger(__name__) class BaseModelService(ABC): """Base service class for all model types""" - def __init__(self, model_type: str, scanner, metadata_class: Type[BaseModelMetadata]): - """Initialize the service - + def __init__( + self, + model_type: str, + scanner, + metadata_class: Type[BaseModelMetadata], + *, + cache_repository: Optional[ModelCacheRepository] = None, + filter_set: Optional[ModelFilterSet] = None, + search_strategy: Optional[SearchStrategy] = None, + settings_provider: Optional[SettingsProvider] = None, + ): + """Initialize the service. + Args: - model_type: Type of model (lora, checkpoint, etc.) - scanner: Model scanner instance - metadata_class: Metadata class for this model type + model_type: Type of model (lora, checkpoint, etc.). + scanner: Model scanner instance. + metadata_class: Metadata class for this model type. + cache_repository: Custom repository for cache access (primarily for tests). + filter_set: Filter component controlling folder/tag/favorites logic. + search_strategy: Search component for fuzzy/text matching. + settings_provider: Settings object; defaults to the global settings manager. """ self.model_type = model_type self.scanner = scanner self.metadata_class = metadata_class + self.settings = settings_provider or default_settings + self.cache_repository = cache_repository or ModelCacheRepository(scanner) + self.filter_set = filter_set or ModelFilterSet(self.settings) + self.search_strategy = search_strategy or SearchStrategy() - async def get_paginated_data(self, page: int, page_size: int, sort_by: str = 'name', - folder: str = None, search: str = None, fuzzy_search: bool = False, - base_models: list = None, tags: list = None, - search_options: dict = None, hash_filters: dict = None, - favorites_only: bool = False, **kwargs) -> Dict: - """Get paginated and filtered model data - - Args: - page: Page number (1-based) - page_size: Number of items per page - sort_by: Sort criteria, e.g. 'name', 'name:asc', 'name:desc', 'date', 'date:asc', 'date:desc' - folder: Folder filter - search: Search term - fuzzy_search: Whether to use fuzzy search - base_models: List of base models to filter by - tags: List of tags to filter by - search_options: Search options dict - hash_filters: Hash filtering options - favorites_only: Filter for favorites only - **kwargs: Additional model-specific filters - - Returns: - Dict containing paginated results - """ - cache = await self.scanner.get_cached_data() + async def get_paginated_data( + self, + page: int, + page_size: int, + sort_by: str = 'name', + folder: str = None, + search: str = None, + fuzzy_search: bool = False, + base_models: list = None, + tags: list = None, + search_options: dict = None, + hash_filters: dict = None, + favorites_only: bool = False, + **kwargs, + ) -> Dict: + """Get paginated and filtered model data""" + sort_params = self.cache_repository.parse_sort(sort_by) + sorted_data = await self.cache_repository.fetch_sorted(sort_params) - # Parse sort_by into sort_key and order - if ':' in sort_by: - sort_key, order = sort_by.split(':', 1) - sort_key = sort_key.strip() - order = order.strip().lower() - if order not in ('asc', 'desc'): - order = 'asc' - else: - sort_key = sort_by.strip() - order = 'asc' - - # Get default search options if not provided - if search_options is None: - search_options = { - 'filename': True, - 'modelname': True, - 'tags': False, - 'recursive': True, - } - - # Get the base data set using new sort logic - filtered_data = await cache.get_sorted_data(sort_key, order) - - # Apply hash filtering if provided (highest priority) if hash_filters: - filtered_data = await self._apply_hash_filters(filtered_data, hash_filters) - - # Jump to pagination for hash filters + filtered_data = await self._apply_hash_filters(sorted_data, hash_filters) return self._paginate(filtered_data, page, page_size) - - # Apply common filters + filtered_data = await self._apply_common_filters( - filtered_data, folder, base_models, tags, favorites_only, search_options + sorted_data, + folder=folder, + base_models=base_models, + tags=tags, + favorites_only=favorites_only, + search_options=search_options, ) - - # Apply search filtering + if search: filtered_data = await self._apply_search_filters( - filtered_data, search, fuzzy_search, search_options + filtered_data, + search, + fuzzy_search, + search_options, ) - - # Apply model-specific filters + filtered_data = await self._apply_specific_filters(filtered_data, **kwargs) - + return self._paginate(filtered_data, page, page_size) + async def _apply_hash_filters(self, data: List[Dict], hash_filters: Dict) -> List[Dict]: """Apply hash-based filtering""" @@ -120,113 +110,36 @@ class BaseModelService(ABC): return data - async def _apply_common_filters(self, data: List[Dict], folder: str = None, - base_models: list = None, tags: list = None, - favorites_only: bool = False, search_options: dict = None) -> List[Dict]: + async def _apply_common_filters( + self, + data: List[Dict], + folder: str = None, + base_models: list = None, + tags: list = None, + favorites_only: bool = False, + search_options: dict = None, + ) -> List[Dict]: """Apply common filters that work across all model types""" - # Apply SFW filtering if enabled in settings - if settings.get('show_only_sfw', False): - data = [ - item for item in data - if not item.get('preview_nsfw_level') or item.get('preview_nsfw_level') < NSFW_LEVELS['R'] - ] - - # Apply favorites filtering if enabled - if favorites_only: - data = [ - item for item in data - if item.get('favorite', False) is True - ] - - # Apply folder filtering - if folder is not None: - if search_options and search_options.get('recursive', True): - # Recursive folder filtering - include all subfolders - # Ensure we match exact folder or its subfolders by checking path boundaries - if folder == "": - # Empty folder means root - include all items - pass # Don't filter anything - else: - # Add trailing slash to ensure we match folder boundaries correctly - folder_with_separator = folder + "/" - data = [ - item for item in data - if (item['folder'] == folder or - item['folder'].startswith(folder_with_separator)) - ] - else: - # Exact folder filtering - data = [ - item for item in data - if item['folder'] == folder - ] - - # Apply base model filtering - if base_models and len(base_models) > 0: - data = [ - item for item in data - if item.get('base_model') in base_models - ] - - # Apply tag filtering - if tags and len(tags) > 0: - data = [ - item for item in data - if any(tag in item.get('tags', []) for tag in tags) - ] - - return data + normalized_options = self.search_strategy.normalize_options(search_options) + criteria = FilterCriteria( + folder=folder, + base_models=base_models, + tags=tags, + favorites_only=favorites_only, + search_options=normalized_options, + ) + return self.filter_set.apply(data, criteria) - async def _apply_search_filters(self, data: List[Dict], search: str, - fuzzy_search: bool, search_options: dict) -> List[Dict]: + async def _apply_search_filters( + self, + data: List[Dict], + search: str, + fuzzy_search: bool, + search_options: dict, + ) -> List[Dict]: """Apply search filtering""" - search_results = [] - - for item in data: - # Search by file name - if search_options.get('filename', True): - if fuzzy_search: - if fuzzy_match(item.get('file_name', ''), search): - search_results.append(item) - continue - elif search.lower() in item.get('file_name', '').lower(): - search_results.append(item) - continue - - # Search by model name - if search_options.get('modelname', True): - if fuzzy_search: - if fuzzy_match(item.get('model_name', ''), search): - search_results.append(item) - continue - elif search.lower() in item.get('model_name', '').lower(): - search_results.append(item) - continue - - # Search by tags - if search_options.get('tags', False) and 'tags' in item: - if any((fuzzy_match(tag, search) if fuzzy_search else search.lower() in tag.lower()) - for tag in item['tags']): - search_results.append(item) - continue - - # Search by creator - civitai = item.get('civitai') - creator_username = '' - if civitai and isinstance(civitai, dict): - creator = civitai.get('creator') - if creator and isinstance(creator, dict): - creator_username = creator.get('username', '') - if search_options.get('creator', False) and creator_username: - if fuzzy_search: - if fuzzy_match(creator_username, search): - search_results.append(item) - continue - elif search.lower() in creator_username.lower(): - search_results.append(item) - continue - - return search_results + normalized_options = self.search_strategy.normalize_options(search_options) + return self.search_strategy.apply(data, search, normalized_options, fuzzy_search) async def _apply_specific_filters(self, data: List[Dict], **kwargs) -> List[Dict]: """Apply model-specific filters - to be overridden by subclasses if needed""" diff --git a/py/services/model_query.py b/py/services/model_query.py new file mode 100644 index 00000000..08ca652f --- /dev/null +++ b/py/services/model_query.py @@ -0,0 +1,196 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, Protocol, Callable + +from ..utils.constants import NSFW_LEVELS +from ..utils.utils import fuzzy_match as default_fuzzy_match + + +class SettingsProvider(Protocol): + """Protocol describing the SettingsManager contract used by query helpers.""" + + def get(self, key: str, default: Any = None) -> Any: + ... + + +@dataclass(frozen=True) +class SortParams: + """Normalized representation of sorting instructions.""" + + key: str + order: str + + +@dataclass(frozen=True) +class FilterCriteria: + """Container for model list filtering options.""" + + folder: Optional[str] = None + base_models: Optional[Sequence[str]] = None + tags: Optional[Sequence[str]] = None + favorites_only: bool = False + search_options: Optional[Dict[str, Any]] = None + + +class ModelCacheRepository: + """Adapter around scanner cache access and sort normalisation.""" + + def __init__(self, scanner) -> None: + self._scanner = scanner + + async def get_cache(self): + """Return the underlying cache instance from the scanner.""" + return await self._scanner.get_cached_data() + + async def fetch_sorted(self, params: SortParams) -> List[Dict[str, Any]]: + """Fetch cached data pre-sorted according to ``params``.""" + cache = await self.get_cache() + return await cache.get_sorted_data(params.key, params.order) + + @staticmethod + def parse_sort(sort_by: str) -> SortParams: + """Parse an incoming sort string into key/order primitives.""" + if not sort_by: + return SortParams(key="name", order="asc") + + if ":" in sort_by: + raw_key, raw_order = sort_by.split(":", 1) + sort_key = raw_key.strip().lower() or "name" + order = raw_order.strip().lower() + else: + sort_key = sort_by.strip().lower() or "name" + order = "asc" + + if order not in ("asc", "desc"): + order = "asc" + + return SortParams(key=sort_key, order=order) + + +class ModelFilterSet: + """Applies common filtering rules to the model collection.""" + + def __init__(self, settings: SettingsProvider, nsfw_levels: Optional[Dict[str, int]] = None) -> None: + self._settings = settings + self._nsfw_levels = nsfw_levels or NSFW_LEVELS + + def apply(self, data: Iterable[Dict[str, Any]], criteria: FilterCriteria) -> List[Dict[str, Any]]: + """Return items that satisfy the provided criteria.""" + items = list(data) + + if self._settings.get("show_only_sfw", False): + threshold = self._nsfw_levels.get("R", 0) + items = [ + item for item in items + if not item.get("preview_nsfw_level") or item.get("preview_nsfw_level") < threshold + ] + + if criteria.favorites_only: + items = [item for item in items if item.get("favorite", False)] + + folder = criteria.folder + options = criteria.search_options or {} + recursive = bool(options.get("recursive", True)) + if folder is not None: + if recursive: + if folder: + folder_with_sep = f"{folder}/" + items = [ + item for item in items + if item.get("folder") == folder or item.get("folder", "").startswith(folder_with_sep) + ] + else: + items = [item for item in items if item.get("folder") == folder] + + base_models = criteria.base_models or [] + if base_models: + base_model_set = set(base_models) + items = [item for item in items if item.get("base_model") in base_model_set] + + tags = criteria.tags or [] + if tags: + tag_set = set(tags) + items = [ + item for item in items + if any(tag in tag_set for tag in item.get("tags", [])) + ] + + return items + + +class SearchStrategy: + """Encapsulates text and fuzzy matching behaviour for model queries.""" + + DEFAULT_OPTIONS: Dict[str, Any] = { + "filename": True, + "modelname": True, + "tags": False, + "recursive": True, + "creator": False, + } + + def __init__(self, fuzzy_matcher: Optional[Callable[[str, str], bool]] = None) -> None: + self._fuzzy_match = fuzzy_matcher or default_fuzzy_match + + def normalize_options(self, options: Optional[Dict[str, Any]]) -> Dict[str, Any]: + """Merge provided options with defaults without mutating input.""" + normalized = dict(self.DEFAULT_OPTIONS) + if options: + normalized.update(options) + return normalized + + def apply( + self, + data: Iterable[Dict[str, Any]], + search_term: str, + options: Dict[str, Any], + fuzzy: bool = False, + ) -> List[Dict[str, Any]]: + """Return items matching the search term using the configured strategy.""" + if not search_term: + return list(data) + + search_lower = search_term.lower() + results: List[Dict[str, Any]] = [] + + for item in data: + if options.get("filename", True): + candidate = item.get("file_name", "") + if self._matches(candidate, search_term, search_lower, fuzzy): + results.append(item) + continue + + if options.get("modelname", True): + candidate = item.get("model_name", "") + if self._matches(candidate, search_term, search_lower, fuzzy): + results.append(item) + continue + + if options.get("tags", False): + tags = item.get("tags", []) or [] + if any(self._matches(tag, search_term, search_lower, fuzzy) for tag in tags): + results.append(item) + continue + + if options.get("creator", False): + creator_username = "" + civitai = item.get("civitai") + if isinstance(civitai, dict): + creator = civitai.get("creator") + if isinstance(creator, dict): + creator_username = creator.get("username", "") + if creator_username and self._matches(creator_username, search_term, search_lower, fuzzy): + results.append(item) + continue + + return results + + def _matches(self, candidate: str, search_term: str, search_lower: str, fuzzy: bool) -> bool: + if not candidate: + return False + + candidate_lower = candidate.lower() + if fuzzy: + return self._fuzzy_match(candidate, search_term) + return search_lower in candidate_lower diff --git a/tests/services/test_base_model_service.py b/tests/services/test_base_model_service.py new file mode 100644 index 00000000..4acfcc49 --- /dev/null +++ b/tests/services/test_base_model_service.py @@ -0,0 +1,269 @@ +import pytest + +from py.services.base_model_service import BaseModelService +from py.services.model_query import ModelCacheRepository, ModelFilterSet, SearchStrategy, SortParams +from py.utils.models import BaseModelMetadata + + +class StubSettings: + def __init__(self, values): + self._values = dict(values) + + def get(self, key, default=None): + return self._values.get(key, default) + + +class DummyService(BaseModelService): + async def format_response(self, model_data): + return model_data + + +class StubRepository: + def __init__(self, data): + self._data = list(data) + self.parse_sort_calls = [] + self.fetch_sorted_calls = [] + + def parse_sort(self, sort_by): + params = ModelCacheRepository.parse_sort(sort_by) + self.parse_sort_calls.append(sort_by) + return params + + async def fetch_sorted(self, params): + self.fetch_sorted_calls.append(params) + return list(self._data) + + +class StubFilterSet: + def __init__(self, result): + self.result = list(result) + self.calls = [] + + def apply(self, data, criteria): + self.calls.append((list(data), criteria)) + return list(self.result) + + +class StubSearchStrategy: + def __init__(self, search_result): + self.search_result = list(search_result) + self.normalize_calls = [] + self.apply_calls = [] + + def normalize_options(self, options): + self.normalize_calls.append(options) + normalized = {"recursive": True} + if options: + normalized.update(options) + return normalized + + def apply(self, data, search_term, options, fuzzy): + self.apply_calls.append((list(data), search_term, options, fuzzy)) + return list(self.search_result) + + +@pytest.mark.asyncio +async def test_get_paginated_data_uses_injected_collaborators(): + data = [ + {"model_name": "Alpha", "folder": "root"}, + {"model_name": "Beta", "folder": "root"}, + ] + repository = StubRepository(data) + filter_set = StubFilterSet([{"model_name": "Filtered"}]) + search_strategy = StubSearchStrategy([{"model_name": "SearchResult"}]) + settings = StubSettings({}) + + service = DummyService( + model_type="stub", + scanner=object(), + metadata_class=BaseModelMetadata, + cache_repository=repository, + filter_set=filter_set, + search_strategy=search_strategy, + settings_provider=settings, + ) + + response = await service.get_paginated_data( + page=1, + page_size=5, + sort_by="name:desc", + folder="root", + search="query", + fuzzy_search=True, + base_models=["base"], + tags=["tag"], + search_options={"recursive": False}, + favorites_only=True, + ) + + assert repository.parse_sort_calls == ["name:desc"] + assert repository.fetch_sorted_calls and isinstance(repository.fetch_sorted_calls[0], SortParams) + sort_params = repository.fetch_sorted_calls[0] + assert sort_params.key == "name" and sort_params.order == "desc" + + assert filter_set.calls, "FilterSet should be invoked" + call_data, criteria = filter_set.calls[0] + assert call_data == data + assert criteria.folder == "root" + assert criteria.base_models == ["base"] + assert criteria.tags == ["tag"] + assert criteria.favorites_only is True + assert criteria.search_options.get("recursive") is False + + assert search_strategy.normalize_calls == [{"recursive": False}, {"recursive": False}] + assert search_strategy.apply_calls == [([{"model_name": "Filtered"}], "query", {"recursive": False}, True)] + + assert response["items"] == search_strategy.search_result + assert response["total"] == len(search_strategy.search_result) + assert response["page"] == 1 + assert response["page_size"] == 5 + + +class FakeCache: + def __init__(self, items): + self.items = list(items) + + async def get_sorted_data(self, sort_key, order): + if sort_key == "name": + data = sorted(self.items, key=lambda x: x["model_name"].lower()) + if order == "desc": + data.reverse() + else: + data = list(self.items) + return data + + +class FakeScanner: + def __init__(self, cache): + self._cache = cache + + async def get_cached_data(self, *_, **__): + return self._cache + + +@pytest.mark.asyncio +async def test_get_paginated_data_filters_and_searches_combination(): + items = [ + { + "model_name": "Alpha", + "file_name": "alpha.safetensors", + "folder": "root/sub", + "tags": ["tag1"], + "base_model": "v1", + "favorite": True, + "preview_nsfw_level": 0, + }, + { + "model_name": "Beta", + "file_name": "beta.safetensors", + "folder": "root", + "tags": ["tag2"], + "base_model": "v2", + "favorite": False, + "preview_nsfw_level": 999, + }, + { + "model_name": "Gamma", + "file_name": "gamma.safetensors", + "folder": "root/sub2", + "tags": ["tag1", "tag3"], + "base_model": "v1", + "favorite": True, + "preview_nsfw_level": 0, + "civitai": {"creator": {"username": "artist"}}, + }, + ] + + cache = FakeCache(items) + scanner = FakeScanner(cache) + settings = StubSettings({"show_only_sfw": True}) + + service = DummyService( + model_type="stub", + scanner=scanner, + metadata_class=BaseModelMetadata, + cache_repository=ModelCacheRepository(scanner), + filter_set=ModelFilterSet(settings), + search_strategy=SearchStrategy(), + settings_provider=settings, + ) + + response = await service.get_paginated_data( + page=1, + page_size=1, + sort_by="name:asc", + folder="root", + search="artist", + base_models=["v1"], + tags=["tag1"], + search_options={"creator": True, "tags": True}, + favorites_only=True, + ) + + assert response["items"] == [items[2]] + assert response["total"] == 1 + assert response["page"] == 1 + assert response["page_size"] == 1 + assert response["total_pages"] == 1 + + +class PassThroughFilterSet: + def __init__(self): + self.calls = [] + + def apply(self, data, criteria): + self.calls.append(criteria) + return list(data) + + +class NoSearchStrategy: + def __init__(self): + self.normalize_calls = [] + self.apply_called = False + + def normalize_options(self, options): + self.normalize_calls.append(options) + return {"recursive": True} + + def apply(self, *args, **kwargs): + self.apply_called = True + pytest.fail("Search should not be invoked when no search term is provided") + + +@pytest.mark.asyncio +async def test_get_paginated_data_paginates_without_search(): + items = [ + {"model_name": name, "folder": "root"} + for name in ["Alpha", "Beta", "Gamma", "Delta", "Epsilon"] + ] + + repository = StubRepository(items) + filter_set = PassThroughFilterSet() + search_strategy = NoSearchStrategy() + settings = StubSettings({}) + + service = DummyService( + model_type="stub", + scanner=object(), + metadata_class=BaseModelMetadata, + cache_repository=repository, + filter_set=filter_set, + search_strategy=search_strategy, + settings_provider=settings, + ) + + response = await service.get_paginated_data( + page=2, + page_size=2, + sort_by="name:asc", + ) + + assert repository.parse_sort_calls == ["name:asc"] + assert len(repository.fetch_sorted_calls) == 1 + assert filter_set.calls and filter_set.calls[0].favorites_only is False + assert search_strategy.apply_called is False + assert response["items"] == items[2:4] + assert response["total"] == len(items) + assert response["page"] == 2 + assert response["page_size"] == 2 + assert response["total_pages"] == 3 From 21772feaddad2a6393ac79bc7432f6ae458dea35 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Sun, 21 Sep 2025 23:34:46 +0800 Subject: [PATCH 054/110] refactor(routes): extract route utilities into services --- py/routes/base_model_routes.py | 45 ++- py/routes/handlers/model_handlers.py | 230 +++++++++++- py/services/download_coordinator.py | 100 +++++ py/services/metadata_sync_service.py | 355 ++++++++++++++++++ py/services/preview_asset_service.py | 168 +++++++++ py/services/tag_update_service.py | 47 +++ py/utils/example_images_metadata.py | 36 +- pytest.ini | 3 + tests/conftest.py | 9 + tests/services/test_base_model_service.py | 33 +- tests/services/test_route_support_services.py | 273 ++++++++++++++ 11 files changed, 1269 insertions(+), 30 deletions(-) create mode 100644 py/services/download_coordinator.py create mode 100644 py/services/metadata_sync_service.py create mode 100644 py/services/preview_asset_service.py create mode 100644 py/services/tag_update_service.py create mode 100644 tests/services/test_route_support_services.py diff --git a/py/routes/base_model_routes.py b/py/routes/base_model_routes.py index 458a5e87..65103ece 100644 --- a/py/routes/base_model_routes.py +++ b/py/routes/base_model_routes.py @@ -8,12 +8,20 @@ import jinja2 from aiohttp import web from ..config import config -from ..services.metadata_service import get_default_metadata_provider +from ..services.download_coordinator import DownloadCoordinator +from ..services.downloader import get_downloader +from ..services.metadata_service import get_default_metadata_provider, get_metadata_provider +from ..services.metadata_sync_service import MetadataSyncService from ..services.model_file_service import ModelFileService, ModelMoveService +from ..services.preview_asset_service import PreviewAssetService +from ..services.server_i18n import server_i18n as default_server_i18n +from ..services.service_registry import ServiceRegistry from ..services.settings_manager import settings as default_settings +from ..services.tag_update_service import TagUpdateService from ..services.websocket_manager import ws_manager as default_ws_manager from ..services.websocket_progress_callback import WebSocketProgressCallback -from ..services.server_i18n import server_i18n as default_server_i18n +from ..utils.exif_utils import ExifUtils +from ..utils.metadata_manager import MetadataManager from ..utils.routes_common import ModelRouteUtils from .model_route_registrar import COMMON_ROUTE_DEFINITIONS, ModelRouteRegistrar from .handlers.model_handlers import ( @@ -64,6 +72,24 @@ class BaseModelRoutes(ABC): self._handler_set: ModelHandlerSet | None = None self._handler_mapping: Dict[str, Callable[[web.Request], web.StreamResponse]] | None = None + self._preview_service = PreviewAssetService( + metadata_manager=MetadataManager, + downloader_factory=get_downloader, + exif_utils=ExifUtils, + ) + self._metadata_sync_service = MetadataSyncService( + metadata_manager=MetadataManager, + preview_service=self._preview_service, + settings=settings_service, + default_metadata_provider_factory=metadata_provider_factory, + metadata_provider_selector=get_metadata_provider, + ) + self._tag_update_service = TagUpdateService(metadata_manager=MetadataManager) + self._download_coordinator = DownloadCoordinator( + ws_manager=self._ws_manager, + download_manager_factory=ServiceRegistry.get_download_manager, + ) + if service is not None: self.attach_service(service) @@ -98,9 +124,19 @@ class BaseModelRoutes(ABC): parse_specific_params=self._parse_specific_params, logger=logger, ) - management = ModelManagementHandler(service=service, logger=logger) + management = ModelManagementHandler( + service=service, + logger=logger, + metadata_sync=self._metadata_sync_service, + preview_service=self._preview_service, + tag_update_service=self._tag_update_service, + ) query = ModelQueryHandler(service=service, logger=logger) - download = ModelDownloadHandler(ws_manager=self._ws_manager, logger=logger) + download = ModelDownloadHandler( + ws_manager=self._ws_manager, + logger=logger, + download_coordinator=self._download_coordinator, + ) civitai = ModelCivitaiHandler( service=service, settings_service=self._settings, @@ -110,6 +146,7 @@ class BaseModelRoutes(ABC): validate_model_type=self._validate_civitai_model_type, expected_model_types=self._get_expected_model_types, find_model_file=self._find_model_file, + metadata_sync=self._metadata_sync_service, ) move = ModelMoveHandler(move_service=self._ensure_move_service(), logger=logger) auto_organize = ModelAutoOrganizeHandler( diff --git a/py/routes/handlers/model_handlers.py b/py/routes/handlers/model_handlers.py index 66a7123a..5f9eaf3b 100644 --- a/py/routes/handlers/model_handlers.py +++ b/py/routes/handlers/model_handlers.py @@ -4,16 +4,23 @@ from __future__ import annotations import asyncio import json import logging +import os from dataclasses import dataclass from typing import Awaitable, Callable, Dict, Iterable, Mapping, Optional from aiohttp import web import jinja2 +from ...config import config +from ...services.download_coordinator import DownloadCoordinator +from ...services.metadata_sync_service import MetadataSyncService from ...services.model_file_service import ModelFileService, ModelMoveService -from ...services.websocket_progress_callback import WebSocketProgressCallback -from ...services.websocket_manager import WebSocketManager +from ...services.preview_asset_service import PreviewAssetService from ...services.settings_manager import SettingsManager +from ...services.tag_update_service import TagUpdateService +from ...services.websocket_manager import WebSocketManager +from ...services.websocket_progress_callback import WebSocketProgressCallback +from ...utils.file_utils import calculate_sha256 from ...utils.routes_common import ModelRouteUtils @@ -168,9 +175,20 @@ class ModelListingHandler: class ModelManagementHandler: """Handle mutation operations on models.""" - def __init__(self, *, service, logger: logging.Logger) -> None: + def __init__( + self, + *, + service, + logger: logging.Logger, + metadata_sync: MetadataSyncService, + preview_service: PreviewAssetService, + tag_update_service: TagUpdateService, + ) -> None: self._service = service self._logger = logger + self._metadata_sync = metadata_sync + self._preview_service = preview_service + self._tag_update_service = tag_update_service async def delete_model(self, request: web.Request) -> web.Response: return await ModelRouteUtils.handle_delete_model(request, self._service.scanner) @@ -192,7 +210,7 @@ class ModelManagementHandler: if not model_data.get("sha256"): return web.json_response({"success": False, "error": "No SHA256 hash found"}, status=400) - success, error = await ModelRouteUtils.fetch_and_update_model( + success, error = await self._metadata_sync.fetch_and_update_model( sha256=model_data["sha256"], file_path=file_path, model_data=model_data, @@ -208,16 +226,144 @@ class ModelManagementHandler: return web.json_response({"success": False, "error": str(exc)}, status=500) async def relink_civitai(self, request: web.Request) -> web.Response: - return await ModelRouteUtils.handle_relink_civitai(request, self._service.scanner) + try: + data = await request.json() + file_path = data.get("file_path") + model_id = data.get("model_id") + model_version_id = data.get("model_version_id") + + if not file_path or model_id is None: + return web.json_response( + {"success": False, "error": "Both file_path and model_id are required"}, + status=400, + ) + + metadata_path = os.path.splitext(file_path)[0] + ".metadata.json" + local_metadata = await self._metadata_sync.load_local_metadata(metadata_path) + + updated_metadata = await self._metadata_sync.relink_metadata( + file_path=file_path, + metadata=local_metadata, + model_id=int(model_id), + model_version_id=int(model_version_id) if model_version_id else None, + ) + + await self._service.scanner.update_single_model_cache( + file_path, file_path, updated_metadata + ) + + message = ( + f"Model successfully re-linked to Civitai model {model_id}" + + (f" version {model_version_id}" if model_version_id else "") + ) + return web.json_response( + {"success": True, "message": message, "hash": updated_metadata.get("sha256", "")} + ) + except Exception as exc: + self._logger.error("Error re-linking to CivitAI: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) async def replace_preview(self, request: web.Request) -> web.Response: - return await ModelRouteUtils.handle_replace_preview(request, self._service.scanner) + try: + reader = await request.multipart() + + field = await reader.next() + if field is None or field.name != "preview_file": + raise ValueError("Expected 'preview_file' field") + content_type = field.headers.get("Content-Type", "image/png") + content_disposition = field.headers.get("Content-Disposition", "") + + original_filename = None + import re + + match = re.search(r'filename="(.*?)"', content_disposition) + if match: + original_filename = match.group(1) + + preview_data = await field.read() + + field = await reader.next() + if field is None or field.name != "model_path": + raise ValueError("Expected 'model_path' field") + model_path = (await field.read()).decode() + + nsfw_level = 0 + field = await reader.next() + if field and field.name == "nsfw_level": + try: + nsfw_level = int((await field.read()).decode()) + except (ValueError, TypeError): + self._logger.warning("Invalid NSFW level format, using default 0") + + result = await self._preview_service.replace_preview( + model_path=model_path, + preview_data=preview_data, + content_type=content_type, + original_filename=original_filename, + nsfw_level=nsfw_level, + update_preview_in_cache=self._service.scanner.update_preview_in_cache, + metadata_loader=self._metadata_sync.load_local_metadata, + ) + + return web.json_response( + { + "success": True, + "preview_url": config.get_preview_static_url(result["preview_path"]), + "preview_nsfw_level": result["preview_nsfw_level"], + } + ) + except Exception as exc: + self._logger.error("Error replacing preview: %s", exc, exc_info=True) + return web.Response(text=str(exc), status=500) async def save_metadata(self, request: web.Request) -> web.Response: - return await ModelRouteUtils.handle_save_metadata(request, self._service.scanner) + try: + data = await request.json() + file_path = data.get("file_path") + if not file_path: + return web.Response(text="File path is required", status=400) + + metadata_updates = {k: v for k, v in data.items() if k != "file_path"} + + await self._metadata_sync.save_metadata_updates( + file_path=file_path, + updates=metadata_updates, + metadata_loader=self._metadata_sync.load_local_metadata, + update_cache=self._service.scanner.update_single_model_cache, + ) + + if "model_name" in metadata_updates: + cache = await self._service.scanner.get_cached_data() + await cache.resort() + + return web.json_response({"success": True}) + except Exception as exc: + self._logger.error("Error saving metadata: %s", exc, exc_info=True) + return web.Response(text=str(exc), status=500) async def add_tags(self, request: web.Request) -> web.Response: - return await ModelRouteUtils.handle_add_tags(request, self._service.scanner) + try: + data = await request.json() + file_path = data.get("file_path") + new_tags = data.get("tags", []) + + if not file_path: + return web.Response(text="File path is required", status=400) + + if not isinstance(new_tags, list): + return web.Response(text="Tags must be a list", status=400) + + tags = await self._tag_update_service.add_tags( + file_path=file_path, + new_tags=new_tags, + metadata_loader=self._metadata_sync.load_local_metadata, + update_cache=self._service.scanner.update_single_model_cache, + ) + + return web.json_response({"success": True, "tags": tags}) + except Exception as exc: + self._logger.error("Error adding tags: %s", exc, exc_info=True) + return web.Response(text=str(exc), status=500) async def rename_model(self, request: web.Request) -> web.Response: return await ModelRouteUtils.handle_rename_model(request, self._service.scanner) @@ -226,7 +372,27 @@ class ModelManagementHandler: return await ModelRouteUtils.handle_bulk_delete_models(request, self._service.scanner) async def verify_duplicates(self, request: web.Request) -> web.Response: - return await ModelRouteUtils.handle_verify_duplicates(request, self._service.scanner) + try: + data = await request.json() + file_paths = data.get("file_paths", []) + + if not file_paths: + return web.json_response( + {"success": False, "error": "No file paths provided for verification"}, + status=400, + ) + + results = await self._metadata_sync.verify_duplicate_hashes( + file_paths=file_paths, + metadata_loader=self._metadata_sync.load_local_metadata, + hash_calculator=calculate_sha256, + update_cache=self._service.scanner.update_single_model_cache, + ) + + return web.json_response({"success": True, **results}) + except Exception as exc: + self._logger.error("Error verifying duplicate models: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) class ModelQueryHandler: @@ -429,12 +595,39 @@ class ModelQueryHandler: class ModelDownloadHandler: """Coordinate downloads and progress reporting.""" - def __init__(self, *, ws_manager: WebSocketManager, logger: logging.Logger) -> None: + def __init__( + self, + *, + ws_manager: WebSocketManager, + logger: logging.Logger, + download_coordinator: DownloadCoordinator, + ) -> None: self._ws_manager = ws_manager self._logger = logger + self._download_coordinator = download_coordinator async def download_model(self, request: web.Request) -> web.Response: - return await ModelRouteUtils.handle_download_model(request) + try: + payload = await request.json() + result = await self._download_coordinator.schedule_download(payload) + if not result.get("success", False): + return web.json_response(result, status=500) + return web.json_response(result) + except ValueError as exc: + return web.json_response({"success": False, "error": str(exc)}, status=400) + except Exception as exc: + error_message = str(exc) + if "401" in error_message: + self._logger.warning("Early access error (401): %s", error_message) + return web.json_response( + { + "success": False, + "error": "Early Access Restriction: This model requires purchase. Please buy early access on Civitai.com.", + }, + status=401, + ) + self._logger.error("Error downloading model: %s", error_message) + return web.json_response({"success": False, "error": error_message}, status=500) async def download_model_get(self, request: web.Request) -> web.Response: try: @@ -460,7 +653,12 @@ class ModelDownloadHandler: future.set_result(data) mock_request = type("MockRequest", (), {"json": lambda self=None: future})() - return await ModelRouteUtils.handle_download_model(mock_request) + result = await self._download_coordinator.schedule_download(data) + if not result.get("success", False): + return web.json_response(result, status=500) + return web.json_response(result) + except ValueError as exc: + return web.json_response({"success": False, "error": str(exc)}, status=400) except Exception as exc: self._logger.error("Error downloading model via GET: %s", exc, exc_info=True) return web.Response(status=500, text=str(exc)) @@ -470,8 +668,8 @@ class ModelDownloadHandler: download_id = request.query.get("download_id") if not download_id: return web.json_response({"success": False, "error": "Download ID is required"}, status=400) - mock_request = type("MockRequest", (), {"match_info": {"download_id": download_id}})() - return await ModelRouteUtils.handle_cancel_download(mock_request) + result = await self._download_coordinator.cancel_download(download_id) + return web.json_response(result) except Exception as exc: self._logger.error("Error cancelling download via GET: %s", exc, exc_info=True) return web.json_response({"success": False, "error": str(exc)}, status=500) @@ -504,6 +702,7 @@ class ModelCivitaiHandler: validate_model_type: Callable[[str], bool], expected_model_types: Callable[[], str], find_model_file: Callable[[Iterable[Mapping[str, object]]], Optional[Mapping[str, object]]], + metadata_sync: MetadataSyncService, ) -> None: self._service = service self._settings = settings_service @@ -513,6 +712,7 @@ class ModelCivitaiHandler: self._validate_model_type = validate_model_type self._expected_model_types = expected_model_types self._find_model_file = find_model_file + self._metadata_sync = metadata_sync async def fetch_all_civitai(self, request: web.Request) -> web.Response: try: @@ -545,7 +745,7 @@ class ModelCivitaiHandler: for model in to_process: try: original_name = model.get("model_name") - result, error = await ModelRouteUtils.fetch_and_update_model( + result, error = await self._metadata_sync.fetch_and_update_model( sha256=model["sha256"], file_path=model["file_path"], model_data=model, diff --git a/py/services/download_coordinator.py b/py/services/download_coordinator.py new file mode 100644 index 00000000..4cf866e5 --- /dev/null +++ b/py/services/download_coordinator.py @@ -0,0 +1,100 @@ +"""Service wrapper for coordinating download lifecycle events.""" + +from __future__ import annotations + +import logging +from typing import Any, Awaitable, Callable, Dict, Optional + + +logger = logging.getLogger(__name__) + + +class DownloadCoordinator: + """Manage download scheduling, cancellation and introspection.""" + + def __init__( + self, + *, + ws_manager, + download_manager_factory: Callable[[], Awaitable], + ) -> None: + self._ws_manager = ws_manager + self._download_manager_factory = download_manager_factory + + async def schedule_download(self, payload: Dict[str, Any]) -> Dict[str, Any]: + """Schedule a download using the provided payload.""" + + download_manager = await self._download_manager_factory() + + download_id = payload.get("download_id") or self._ws_manager.generate_download_id() + payload.setdefault("download_id", download_id) + + async def progress_callback(progress: Any) -> None: + await self._ws_manager.broadcast_download_progress( + download_id, + { + "status": "progress", + "progress": progress, + "download_id": download_id, + }, + ) + + model_id = self._parse_optional_int(payload.get("model_id"), "model_id") + model_version_id = self._parse_optional_int( + payload.get("model_version_id"), "model_version_id" + ) + + if model_id is None and model_version_id is None: + raise ValueError( + "Missing required parameter: Please provide either 'model_id' or 'model_version_id'" + ) + + result = await download_manager.download_from_civitai( + model_id=model_id, + model_version_id=model_version_id, + save_dir=payload.get("model_root"), + relative_path=payload.get("relative_path", ""), + use_default_paths=payload.get("use_default_paths", False), + progress_callback=progress_callback, + download_id=download_id, + source=payload.get("source"), + ) + + result["download_id"] = download_id + return result + + async def cancel_download(self, download_id: str) -> Dict[str, Any]: + """Cancel an active download and emit a broadcast event.""" + + download_manager = await self._download_manager_factory() + result = await download_manager.cancel_download(download_id) + + await self._ws_manager.broadcast_download_progress( + download_id, + { + "status": "cancelled", + "progress": 0, + "download_id": download_id, + "message": "Download cancelled by user", + }, + ) + + return result + + async def list_active_downloads(self) -> Dict[str, Any]: + """Return the active download map from the underlying manager.""" + + download_manager = await self._download_manager_factory() + return await download_manager.get_active_downloads() + + def _parse_optional_int(self, value: Any, field: str) -> Optional[int]: + """Parse an optional integer from user input.""" + + if value is None or value == "": + return None + + try: + return int(value) + except (TypeError, ValueError) as exc: + raise ValueError(f"Invalid {field}: Must be an integer") from exc + diff --git a/py/services/metadata_sync_service.py b/py/services/metadata_sync_service.py new file mode 100644 index 00000000..aaf2f248 --- /dev/null +++ b/py/services/metadata_sync_service.py @@ -0,0 +1,355 @@ +"""Services for synchronising metadata with remote providers.""" + +from __future__ import annotations + +import json +import logging +import os +from datetime import datetime +from typing import Any, Awaitable, Callable, Dict, Iterable, Optional + +from ..services.settings_manager import SettingsManager +from ..utils.model_utils import determine_base_model + +logger = logging.getLogger(__name__) + + +class MetadataProviderProtocol: + """Subset of metadata provider interface consumed by the sync service.""" + + async def get_model_by_hash(self, sha256: str) -> tuple[Optional[Dict[str, Any]], Optional[str]]: + ... + + async def get_model_version( + self, model_id: int, model_version_id: Optional[int] + ) -> Optional[Dict[str, Any]]: + ... + + +class MetadataSyncService: + """High level orchestration for metadata synchronisation flows.""" + + def __init__( + self, + *, + metadata_manager, + preview_service, + settings: SettingsManager, + default_metadata_provider_factory: Callable[[], Awaitable[MetadataProviderProtocol]], + metadata_provider_selector: Callable[[str], Awaitable[MetadataProviderProtocol]], + ) -> None: + self._metadata_manager = metadata_manager + self._preview_service = preview_service + self._settings = settings + self._get_default_provider = default_metadata_provider_factory + self._get_provider = metadata_provider_selector + + async def load_local_metadata(self, metadata_path: str) -> Dict[str, Any]: + """Load metadata JSON from disk, returning an empty structure when missing.""" + + if not os.path.exists(metadata_path): + return {} + + try: + with open(metadata_path, "r", encoding="utf-8") as handle: + return json.load(handle) + except Exception as exc: # pragma: no cover - defensive logging + logger.error("Error loading metadata from %s: %s", metadata_path, exc) + return {} + + async def mark_not_found_on_civitai( + self, metadata_path: str, local_metadata: Dict[str, Any] + ) -> None: + """Persist the not-found flag for a metadata payload.""" + + local_metadata["from_civitai"] = False + await self._metadata_manager.save_metadata(metadata_path, local_metadata) + + @staticmethod + def is_civitai_api_metadata(meta: Dict[str, Any]) -> bool: + """Determine if the metadata originated from the CivitAI public API.""" + + if not isinstance(meta, dict): + return False + files = meta.get("files") + images = meta.get("images") + source = meta.get("source") + return bool(files) and bool(images) and source != "archive_db" + + async def update_model_metadata( + self, + metadata_path: str, + local_metadata: Dict[str, Any], + civitai_metadata: Dict[str, Any], + metadata_provider: Optional[MetadataProviderProtocol] = None, + ) -> Dict[str, Any]: + """Merge remote metadata into the local record and persist the result.""" + + existing_civitai = local_metadata.get("civitai") or {} + + if ( + civitai_metadata.get("source") == "archive_db" + and self.is_civitai_api_metadata(existing_civitai) + ): + logger.info( + "Skip civitai update for %s (%s)", + local_metadata.get("model_name", ""), + existing_civitai.get("name", ""), + ) + else: + merged_civitai = existing_civitai.copy() + merged_civitai.update(civitai_metadata) + + if civitai_metadata.get("source") == "archive_db": + model_name = civitai_metadata.get("model", {}).get("name", "") + version_name = civitai_metadata.get("name", "") + logger.info( + "Recovered metadata from archive_db for deleted model: %s (%s)", + model_name, + version_name, + ) + + if "trainedWords" in existing_civitai: + existing_trained = existing_civitai.get("trainedWords", []) + new_trained = civitai_metadata.get("trainedWords", []) + merged_trained = list(set(existing_trained + new_trained)) + merged_civitai["trainedWords"] = merged_trained + + local_metadata["civitai"] = merged_civitai + + if "model" in civitai_metadata and civitai_metadata["model"]: + model_data = civitai_metadata["model"] + + if model_data.get("name"): + local_metadata["model_name"] = model_data["name"] + + if not local_metadata.get("modelDescription") and model_data.get("description"): + local_metadata["modelDescription"] = model_data["description"] + + if not local_metadata.get("tags") and model_data.get("tags"): + local_metadata["tags"] = model_data["tags"] + + if model_data.get("creator") and not local_metadata.get("civitai", {}).get( + "creator" + ): + local_metadata.setdefault("civitai", {})["creator"] = model_data["creator"] + + local_metadata["base_model"] = determine_base_model( + civitai_metadata.get("baseModel") + ) + + await self._preview_service.ensure_preview_for_metadata( + metadata_path, local_metadata, civitai_metadata.get("images", []) + ) + + await self._metadata_manager.save_metadata(metadata_path, local_metadata) + return local_metadata + + async def fetch_and_update_model( + self, + *, + sha256: str, + file_path: str, + model_data: Dict[str, Any], + update_cache_func: Callable[[str, str, Dict[str, Any]], Awaitable[bool]], + ) -> tuple[bool, Optional[str]]: + """Fetch metadata for a model and update both disk and cache state.""" + + if not isinstance(model_data, dict): + error = f"Invalid model_data type: {type(model_data)}" + logger.error(error) + return False, error + + metadata_path = os.path.splitext(file_path)[0] + ".metadata.json" + enable_archive = self._settings.get("enable_metadata_archive_db", False) + + try: + if model_data.get("civitai_deleted") is True: + if not enable_archive or model_data.get("db_checked") is True: + return ( + False, + "CivitAI model is deleted and metadata archive DB is not enabled", + ) + metadata_provider = await self._get_provider("sqlite") + else: + metadata_provider = await self._get_default_provider() + + civitai_metadata, error = await metadata_provider.get_model_by_hash(sha256) + if not civitai_metadata: + if error == "Model not found": + model_data["from_civitai"] = False + model_data["civitai_deleted"] = True + model_data["db_checked"] = enable_archive + model_data["last_checked_at"] = datetime.now().timestamp() + + data_to_save = model_data.copy() + data_to_save.pop("folder", None) + await self._metadata_manager.save_metadata(file_path, data_to_save) + + error_msg = ( + f"Error fetching metadata: {error} (model_name={model_data.get('model_name', '')})" + ) + logger.error(error_msg) + return False, error_msg + + model_data["from_civitai"] = True + model_data["civitai_deleted"] = civitai_metadata.get("source") == "archive_db" + model_data["db_checked"] = enable_archive + model_data["last_checked_at"] = datetime.now().timestamp() + + local_metadata = model_data.copy() + local_metadata.pop("folder", None) + + await self.update_model_metadata( + metadata_path, + local_metadata, + civitai_metadata, + metadata_provider, + ) + + update_payload = { + "model_name": local_metadata.get("model_name"), + "preview_url": local_metadata.get("preview_url"), + "civitai": local_metadata.get("civitai"), + } + model_data.update(update_payload) + + await update_cache_func(file_path, file_path, local_metadata) + return True, None + except KeyError as exc: + error_msg = f"Error fetching metadata - Missing key: {exc} in model_data={model_data}" + logger.error(error_msg) + return False, error_msg + except Exception as exc: # pragma: no cover - error path + error_msg = f"Error fetching metadata: {exc}" + logger.error(error_msg, exc_info=True) + return False, error_msg + + async def fetch_metadata_by_sha( + self, sha256: str, metadata_provider: Optional[MetadataProviderProtocol] = None + ) -> tuple[Optional[Dict[str, Any]], Optional[str]]: + """Fetch metadata for a SHA256 hash from the configured provider.""" + + provider = metadata_provider or await self._get_default_provider() + return await provider.get_model_by_hash(sha256) + + async def relink_metadata( + self, + *, + file_path: str, + metadata: Dict[str, Any], + model_id: int, + model_version_id: Optional[int], + ) -> Dict[str, Any]: + """Relink a local metadata record to a specific CivitAI model version.""" + + provider = await self._get_default_provider() + civitai_metadata = await provider.get_model_version(model_id, model_version_id) + if not civitai_metadata: + raise ValueError( + f"Model version not found on CivitAI for ID: {model_id}" + + (f" with version: {model_version_id}" if model_version_id else "") + ) + + primary_model_file: Optional[Dict[str, Any]] = None + for file_info in civitai_metadata.get("files", []): + if file_info.get("primary", False) and file_info.get("type") == "Model": + primary_model_file = file_info + break + + if primary_model_file and primary_model_file.get("hashes", {}).get("SHA256"): + metadata["sha256"] = primary_model_file["hashes"]["SHA256"].lower() + + metadata_path = os.path.splitext(file_path)[0] + ".metadata.json" + await self.update_model_metadata( + metadata_path, + metadata, + civitai_metadata, + provider, + ) + + return metadata + + async def save_metadata_updates( + self, + *, + file_path: str, + updates: Dict[str, Any], + metadata_loader: Callable[[str], Awaitable[Dict[str, Any]]], + update_cache: Callable[[str, str, Dict[str, Any]], Awaitable[bool]], + ) -> Dict[str, Any]: + """Apply metadata updates and persist to disk and cache.""" + + metadata_path = os.path.splitext(file_path)[0] + ".metadata.json" + metadata = await metadata_loader(metadata_path) + + for key, value in updates.items(): + if isinstance(value, dict) and isinstance(metadata.get(key), dict): + metadata[key].update(value) + else: + metadata[key] = value + + await self._metadata_manager.save_metadata(file_path, metadata) + await update_cache(file_path, file_path, metadata) + + if "model_name" in updates: + logger.debug("Metadata update touched model_name; cache resort required") + + return metadata + + async def verify_duplicate_hashes( + self, + *, + file_paths: Iterable[str], + metadata_loader: Callable[[str], Awaitable[Dict[str, Any]]], + hash_calculator: Callable[[str], Awaitable[str]], + update_cache: Callable[[str, str, Dict[str, Any]], Awaitable[bool]], + ) -> Dict[str, Any]: + """Verify a collection of files share the same SHA256 hash.""" + + file_paths = list(file_paths) + if not file_paths: + raise ValueError("No file paths provided for verification") + + results = { + "verified_as_duplicates": True, + "mismatched_files": [], + "new_hash_map": {}, + } + + expected_hash: Optional[str] = None + first_metadata_path = os.path.splitext(file_paths[0])[0] + ".metadata.json" + first_metadata = await metadata_loader(first_metadata_path) + if first_metadata and "sha256" in first_metadata: + expected_hash = first_metadata["sha256"].lower() + + for path in file_paths: + if not os.path.exists(path): + continue + + try: + actual_hash = await hash_calculator(path) + metadata_path = os.path.splitext(path)[0] + ".metadata.json" + metadata = await metadata_loader(metadata_path) + stored_hash = metadata.get("sha256", "").lower() + + if not expected_hash: + expected_hash = stored_hash + + if actual_hash != expected_hash: + results["verified_as_duplicates"] = False + results["mismatched_files"].append(path) + results["new_hash_map"][path] = actual_hash + + if actual_hash != stored_hash: + metadata["sha256"] = actual_hash + await self._metadata_manager.save_metadata(path, metadata) + await update_cache(path, path, metadata) + except Exception as exc: # pragma: no cover - defensive path + logger.error("Error verifying hash for %s: %s", path, exc) + results["mismatched_files"].append(path) + results["new_hash_map"][path] = "error_calculating_hash" + results["verified_as_duplicates"] = False + + return results + diff --git a/py/services/preview_asset_service.py b/py/services/preview_asset_service.py new file mode 100644 index 00000000..42baadac --- /dev/null +++ b/py/services/preview_asset_service.py @@ -0,0 +1,168 @@ +"""Service for processing preview assets for models.""" + +from __future__ import annotations + +import logging +import os +from typing import Awaitable, Callable, Dict, Optional, Sequence + +from ..utils.constants import CARD_PREVIEW_WIDTH, PREVIEW_EXTENSIONS + +logger = logging.getLogger(__name__) + + +class PreviewAssetService: + """Manage fetching and persisting preview assets.""" + + def __init__( + self, + *, + metadata_manager, + downloader_factory: Callable[[], Awaitable], + exif_utils, + ) -> None: + self._metadata_manager = metadata_manager + self._downloader_factory = downloader_factory + self._exif_utils = exif_utils + + async def ensure_preview_for_metadata( + self, + metadata_path: str, + local_metadata: Dict[str, object], + images: Sequence[Dict[str, object]] | None, + ) -> None: + """Ensure preview assets exist for the supplied metadata entry.""" + + if local_metadata.get("preview_url") and os.path.exists( + str(local_metadata["preview_url"]) + ): + return + + if not images: + return + + first_preview = images[0] + base_name = os.path.splitext(os.path.splitext(os.path.basename(metadata_path))[0])[0] + preview_dir = os.path.dirname(metadata_path) + is_video = first_preview.get("type") == "video" + + if is_video: + extension = ".mp4" + preview_path = os.path.join(preview_dir, base_name + extension) + downloader = await self._downloader_factory() + success, result = await downloader.download_file( + first_preview["url"], preview_path, use_auth=False + ) + if success: + local_metadata["preview_url"] = preview_path.replace(os.sep, "/") + local_metadata["preview_nsfw_level"] = first_preview.get("nsfwLevel", 0) + else: + extension = ".webp" + preview_path = os.path.join(preview_dir, base_name + extension) + downloader = await self._downloader_factory() + success, content, _headers = await downloader.download_to_memory( + first_preview["url"], use_auth=False + ) + if not success: + return + + try: + optimized_data, _ = self._exif_utils.optimize_image( + image_data=content, + target_width=CARD_PREVIEW_WIDTH, + format="webp", + quality=85, + preserve_metadata=False, + ) + with open(preview_path, "wb") as handle: + handle.write(optimized_data) + except Exception as exc: # pragma: no cover - defensive path + logger.error("Error optimizing preview image: %s", exc) + try: + with open(preview_path, "wb") as handle: + handle.write(content) + except Exception as save_exc: + logger.error("Error saving preview image: %s", save_exc) + return + + local_metadata["preview_url"] = preview_path.replace(os.sep, "/") + local_metadata["preview_nsfw_level"] = first_preview.get("nsfwLevel", 0) + + async def replace_preview( + self, + *, + model_path: str, + preview_data: bytes, + content_type: str, + original_filename: Optional[str], + nsfw_level: int, + update_preview_in_cache: Callable[[str, str, int], Awaitable[bool]], + metadata_loader: Callable[[str], Awaitable[Dict[str, object]]], + ) -> Dict[str, object]: + """Replace an existing preview asset for a model.""" + + base_name = os.path.splitext(os.path.basename(model_path))[0] + folder = os.path.dirname(model_path) + + extension, optimized_data = await self._convert_preview( + preview_data, content_type, original_filename + ) + + for ext in PREVIEW_EXTENSIONS: + existing_preview = os.path.join(folder, base_name + ext) + if os.path.exists(existing_preview): + try: + os.remove(existing_preview) + except Exception as exc: # pragma: no cover - defensive path + logger.warning( + "Failed to delete existing preview %s: %s", existing_preview, exc + ) + + preview_path = os.path.join(folder, base_name + extension).replace(os.sep, "/") + with open(preview_path, "wb") as handle: + handle.write(optimized_data) + + metadata_path = os.path.splitext(model_path)[0] + ".metadata.json" + metadata = await metadata_loader(metadata_path) + metadata["preview_url"] = preview_path + metadata["preview_nsfw_level"] = nsfw_level + await self._metadata_manager.save_metadata(model_path, metadata) + + await update_preview_in_cache(model_path, preview_path, nsfw_level) + + return {"preview_path": preview_path, "preview_nsfw_level": nsfw_level} + + async def _convert_preview( + self, data: bytes, content_type: str, original_filename: Optional[str] + ) -> tuple[str, bytes]: + """Convert preview bytes to the persisted representation.""" + + if content_type.startswith("video/"): + extension = self._resolve_video_extension(content_type, original_filename) + return extension, data + + original_ext = (original_filename or "").lower() + if original_ext.endswith(".gif") or content_type.lower() == "image/gif": + return ".gif", data + + optimized_data, _ = self._exif_utils.optimize_image( + image_data=data, + target_width=CARD_PREVIEW_WIDTH, + format="webp", + quality=85, + preserve_metadata=False, + ) + return ".webp", optimized_data + + def _resolve_video_extension(self, content_type: str, original_filename: Optional[str]) -> str: + """Infer the best extension for a video preview.""" + + if original_filename: + extension = os.path.splitext(original_filename)[1].lower() + if extension in {".mp4", ".webm", ".mov", ".avi"}: + return extension + + if "webm" in content_type: + return ".webm" + return ".mp4" + diff --git a/py/services/tag_update_service.py b/py/services/tag_update_service.py new file mode 100644 index 00000000..d560e7d6 --- /dev/null +++ b/py/services/tag_update_service.py @@ -0,0 +1,47 @@ +"""Service for updating tag collections on metadata records.""" + +from __future__ import annotations + +import os + +from typing import Awaitable, Callable, Dict, List, Sequence + + +class TagUpdateService: + """Encapsulate tag manipulation for models.""" + + def __init__(self, *, metadata_manager) -> None: + self._metadata_manager = metadata_manager + + async def add_tags( + self, + *, + file_path: str, + new_tags: Sequence[str], + metadata_loader: Callable[[str], Awaitable[Dict[str, object]]], + update_cache: Callable[[str, str, Dict[str, object]], Awaitable[bool]], + ) -> List[str]: + """Add tags to a metadata entry while keeping case-insensitive uniqueness.""" + + base, _ = os.path.splitext(file_path) + metadata_path = f"{base}.metadata.json" + metadata = await metadata_loader(metadata_path) + + existing_tags = list(metadata.get("tags", [])) + existing_lower = [tag.lower() for tag in existing_tags] + + tags_added: List[str] = [] + for tag in new_tags: + if isinstance(tag, str) and tag.strip(): + normalized = tag.strip() + if normalized.lower() not in existing_lower: + existing_tags.append(normalized) + existing_lower.append(normalized.lower()) + tags_added.append(normalized) + + metadata["tags"] = existing_tags + await self._metadata_manager.save_metadata(file_path, metadata) + await update_cache(file_path, file_path, metadata) + + return existing_tags + diff --git a/py/utils/example_images_metadata.py b/py/utils/example_images_metadata.py index 71566bff..66db05a3 100644 --- a/py/utils/example_images_metadata.py +++ b/py/utils/example_images_metadata.py @@ -1,14 +1,34 @@ import logging import os import re -from ..utils.metadata_manager import MetadataManager -from ..utils.routes_common import ModelRouteUtils + +from ..recipes.constants import GEN_PARAM_KEYS +from ..services.metadata_service import get_default_metadata_provider, get_metadata_provider +from ..services.metadata_sync_service import MetadataSyncService +from ..services.preview_asset_service import PreviewAssetService +from ..services.settings_manager import settings +from ..services.downloader import get_downloader from ..utils.constants import SUPPORTED_MEDIA_EXTENSIONS from ..utils.exif_utils import ExifUtils -from ..recipes.constants import GEN_PARAM_KEYS +from ..utils.metadata_manager import MetadataManager logger = logging.getLogger(__name__) +_preview_service = PreviewAssetService( + metadata_manager=MetadataManager, + downloader_factory=get_downloader, + exif_utils=ExifUtils, +) + +_metadata_sync_service = MetadataSyncService( + metadata_manager=MetadataManager, + preview_service=_preview_service, + settings=settings, + default_metadata_provider_factory=get_default_metadata_provider, + metadata_provider_selector=get_metadata_provider, +) + + class MetadataUpdater: """Handles updating model metadata related to example images""" @@ -53,11 +73,11 @@ class MetadataUpdater: async def update_cache_func(old_path, new_path, metadata): return await scanner.update_single_model_cache(old_path, new_path, metadata) - success, error = await ModelRouteUtils.fetch_and_update_model( - model_hash, - file_path, - model_data, - update_cache_func + success, error = await _metadata_sync_service.fetch_and_update_model( + sha256=model_hash, + file_path=file_path, + model_data=model_data, + update_cache_func=update_cache_func, ) if success: diff --git a/pytest.ini b/pytest.ini index 44f4dc04..6f82885c 100644 --- a/pytest.ini +++ b/pytest.ini @@ -4,5 +4,8 @@ testpaths = tests python_files = test_*.py python_classes = Test* python_functions = test_* +# Register async marker for coroutine-style tests +markers = + asyncio: execute test within asyncio event loop # Skip problematic directories to avoid import conflicts norecursedirs = .git .tox dist build *.egg __pycache__ py \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index dfe99691..818aeb9b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,8 @@ import types from dataclasses import dataclass, field from typing import Any, Dict, List, Optional, Sequence +import asyncio +import inspect from unittest import mock import sys @@ -39,6 +41,13 @@ nodes_mock.NODE_CLASS_MAPPINGS = {} sys.modules['nodes'] = nodes_mock +def pytest_pyfunc_call(pyfuncitem): + if inspect.iscoroutinefunction(pyfuncitem.function): + asyncio.run(pyfuncitem.obj(**pyfuncitem.funcargs)) + return True + return None + + @dataclass class MockHashIndex: """Minimal hash index stub mirroring the scanner contract.""" diff --git a/tests/services/test_base_model_service.py b/tests/services/test_base_model_service.py index 4acfcc49..c3fdc884 100644 --- a/tests/services/test_base_model_service.py +++ b/tests/services/test_base_model_service.py @@ -1,8 +1,35 @@ import pytest -from py.services.base_model_service import BaseModelService -from py.services.model_query import ModelCacheRepository, ModelFilterSet, SearchStrategy, SortParams -from py.utils.models import BaseModelMetadata +import importlib +import importlib.util +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +if str(ROOT) not in sys.path: + sys.path.insert(0, str(ROOT)) + + +def import_from(module_name: str): + existing = sys.modules.get("py") + if existing is None or getattr(existing, "__file__", "") != str(ROOT / "py/__init__.py"): + sys.modules.pop("py", None) + spec = importlib.util.spec_from_file_location("py", ROOT / "py/__init__.py") + module = importlib.util.module_from_spec(spec) + assert spec and spec.loader + spec.loader.exec_module(module) # type: ignore[union-attr] + module.__path__ = [str(ROOT / "py")] + sys.modules["py"] = module + return importlib.import_module(module_name) + + +BaseModelService = import_from("py.services.base_model_service").BaseModelService +model_query_module = import_from("py.services.model_query") +ModelCacheRepository = model_query_module.ModelCacheRepository +ModelFilterSet = model_query_module.ModelFilterSet +SearchStrategy = model_query_module.SearchStrategy +SortParams = model_query_module.SortParams +BaseModelMetadata = import_from("py.utils.models").BaseModelMetadata class StubSettings: diff --git a/tests/services/test_route_support_services.py b/tests/services/test_route_support_services.py new file mode 100644 index 00000000..978438c3 --- /dev/null +++ b/tests/services/test_route_support_services.py @@ -0,0 +1,273 @@ +import asyncio +import json +import os +import sys +from pathlib import Path +from typing import Any, Dict, List + +ROOT = Path(__file__).resolve().parents[2] +if str(ROOT) not in sys.path: + sys.path.insert(0, str(ROOT)) + +import importlib +import importlib.util + +import pytest + + +def import_from(module_name: str): + existing = sys.modules.get("py") + if existing is None or getattr(existing, "__file__", "") != str(ROOT / "py/__init__.py"): + sys.modules.pop("py", None) + spec = importlib.util.spec_from_file_location("py", ROOT / "py/__init__.py") + module = importlib.util.module_from_spec(spec) + assert spec and spec.loader + spec.loader.exec_module(module) # type: ignore[union-attr] + module.__path__ = [str(ROOT / "py")] + sys.modules["py"] = module + return importlib.import_module(module_name) + + +DownloadCoordinator = import_from("py.services.download_coordinator").DownloadCoordinator +MetadataSyncService = import_from("py.services.metadata_sync_service").MetadataSyncService +PreviewAssetService = import_from("py.services.preview_asset_service").PreviewAssetService +TagUpdateService = import_from("py.services.tag_update_service").TagUpdateService + + +class DummySettings: + def __init__(self, values: Dict[str, Any] | None = None) -> None: + self._values = values or {} + + def get(self, key: str, default: Any = None) -> Any: + return self._values.get(key, default) + + +class RecordingMetadataManager: + def __init__(self) -> None: + self.saved: List[tuple[str, Dict[str, Any]]] = [] + + async def save_metadata(self, path: str, metadata: Dict[str, Any]) -> bool: + self.saved.append((path, json.loads(json.dumps(metadata)))) + metadata_path = path if path.endswith(".metadata.json") else f"{os.path.splitext(path)[0]}.metadata.json" + Path(metadata_path).write_text(json.dumps(metadata)) + return True + + +class RecordingPreviewService: + def __init__(self) -> None: + self.calls: List[tuple[str, List[Dict[str, Any]]]] = [] + + async def ensure_preview_for_metadata( + self, metadata_path: str, local_metadata: Dict[str, Any], images + ) -> None: + self.calls.append((metadata_path, list(images or []))) + local_metadata["preview_url"] = "preview.webp" + local_metadata["preview_nsfw_level"] = 1 + + +class DummyProvider: + def __init__(self, payload: Dict[str, Any]) -> None: + self.payload = payload + + async def get_model_by_hash(self, sha256: str): + return self.payload, None + + async def get_model_version(self, model_id: int, model_version_id: int | None): + return self.payload + + +class FakeExifUtils: + @staticmethod + def optimize_image(**kwargs): + return kwargs["image_data"], {} + + +def test_metadata_sync_merges_remote_fields(tmp_path: Path) -> None: + manager = RecordingMetadataManager() + preview = RecordingPreviewService() + provider = DummyProvider({ + "baseModel": "SD15", + "model": {"name": "Merged", "description": "desc", "tags": ["tag"], "creator": {"username": "user"}}, + "trainedWords": ["word"], + "images": [{"url": "http://example", "nsfwLevel": 2, "type": "image"}], + }) + + service = MetadataSyncService( + metadata_manager=manager, + preview_service=preview, + settings=DummySettings(), + default_metadata_provider_factory=lambda: asyncio.sleep(0, result=provider), + metadata_provider_selector=lambda _name=None: asyncio.sleep(0, result=provider), + ) + + metadata_path = str(tmp_path / "model.metadata.json") + local_metadata = {"civitai": {"trainedWords": ["existing"]}} + + updated = asyncio.run(service.update_model_metadata(metadata_path, local_metadata, provider.payload)) + + assert updated["model_name"] == "Merged" + assert updated["modelDescription"] == "desc" + assert set(updated["civitai"]["trainedWords"]) == {"existing", "word"} + assert manager.saved + assert preview.calls + + +def test_metadata_sync_fetch_and_update_updates_cache(tmp_path: Path) -> None: + manager = RecordingMetadataManager() + preview = RecordingPreviewService() + provider = DummyProvider({ + "baseModel": "SDXL", + "model": {"name": "Updated"}, + "images": [], + }) + + update_cache_calls: List[Dict[str, Any]] = [] + + async def update_cache(original: str, new: str, metadata: Dict[str, Any]) -> bool: + update_cache_calls.append({"original": original, "metadata": metadata}) + return True + + service = MetadataSyncService( + metadata_manager=manager, + preview_service=preview, + settings=DummySettings(), + default_metadata_provider_factory=lambda: asyncio.sleep(0, result=provider), + metadata_provider_selector=lambda _name=None: asyncio.sleep(0, result=provider), + ) + + model_data = {"sha256": "abc", "file_path": str(tmp_path / "model.safetensors")} + success, error = asyncio.run( + service.fetch_and_update_model( + sha256="abc", + file_path=str(tmp_path / "model.safetensors"), + model_data=model_data, + update_cache_func=update_cache, + ) + ) + + assert success is True + assert error is None + assert update_cache_calls + assert manager.saved + + +def test_preview_asset_service_replace_preview(tmp_path: Path) -> None: + metadata_path = tmp_path / "sample.metadata.json" + metadata_path.write_text(json.dumps({})) + + async def metadata_loader(path: str) -> Dict[str, Any]: + return json.loads(Path(path).read_text()) + + manager = RecordingMetadataManager() + + service = PreviewAssetService( + metadata_manager=manager, + downloader_factory=lambda: asyncio.sleep(0, result=None), + exif_utils=FakeExifUtils(), + ) + + preview_calls: List[Dict[str, Any]] = [] + + async def update_preview(model_path: str, preview_path: str, nsfw: int) -> bool: + preview_calls.append({"model_path": model_path, "preview_path": preview_path, "nsfw": nsfw}) + return True + + model_path = str(tmp_path / "sample.safetensors") + Path(model_path).write_bytes(b"model") + + result = asyncio.run( + service.replace_preview( + model_path=model_path, + preview_data=b"image-bytes", + content_type="image/png", + original_filename="preview.png", + nsfw_level=2, + update_preview_in_cache=update_preview, + metadata_loader=metadata_loader, + ) + ) + + assert result["preview_nsfw_level"] == 2 + assert preview_calls + saved_metadata = json.loads(metadata_path.read_text()) + assert saved_metadata["preview_nsfw_level"] == 2 + + +def test_download_coordinator_emits_progress() -> None: + class WSStub: + def __init__(self) -> None: + self.progress_events: List[Dict[str, Any]] = [] + self.counter = 0 + + def generate_download_id(self) -> str: + self.counter += 1 + return f"dl-{self.counter}" + + async def broadcast_download_progress(self, download_id: str, payload: Dict[str, Any]) -> None: + self.progress_events.append({"id": download_id, **payload}) + + class DownloadManagerStub: + def __init__(self) -> None: + self.calls: List[Dict[str, Any]] = [] + + async def download_from_civitai(self, **kwargs) -> Dict[str, Any]: + self.calls.append(kwargs) + await kwargs["progress_callback"](10) + return {"success": True} + + async def cancel_download(self, download_id: str) -> Dict[str, Any]: + return {"success": True, "download_id": download_id} + + async def get_active_downloads(self) -> Dict[str, Any]: + return {"active": []} + + ws_stub = WSStub() + manager_stub = DownloadManagerStub() + + coordinator = DownloadCoordinator( + ws_manager=ws_stub, + download_manager_factory=lambda: asyncio.sleep(0, result=manager_stub), + ) + + result = asyncio.run(coordinator.schedule_download({"model_id": 1})) + + assert result["success"] is True + assert manager_stub.calls + assert ws_stub.progress_events + + cancel_result = asyncio.run(coordinator.cancel_download(result["download_id"])) + assert cancel_result["success"] is True + + active = asyncio.run(coordinator.list_active_downloads()) + assert active == {"active": []} + + +def test_tag_update_service_adds_unique_tags(tmp_path: Path) -> None: + metadata_path = tmp_path / "model.metadata.json" + metadata_path.write_text(json.dumps({"tags": ["Existing"]})) + + async def loader(path: str) -> Dict[str, Any]: + return json.loads(Path(path).read_text()) + + manager = RecordingMetadataManager() + + service = TagUpdateService(metadata_manager=manager) + + cache_updates: List[Dict[str, Any]] = [] + + async def update_cache(original: str, new: str, metadata: Dict[str, Any]) -> bool: + cache_updates.append(metadata) + return True + + tags = asyncio.run( + service.add_tags( + file_path=str(tmp_path / "model.safetensors"), + new_tags=["New", "existing"], + metadata_loader=loader, + update_cache=update_cache, + ) + ) + + assert tags == ["Existing", "New"] + assert manager.saved + assert cache_updates From 8cf99dd928a69ecf3176f9e12d0c4ebce51dd339 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Sun, 21 Sep 2025 23:39:21 +0800 Subject: [PATCH 055/110] refactor(tests): remove deprecated test runner script --- run_tests.py | 50 -------------------------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 run_tests.py diff --git a/run_tests.py b/run_tests.py deleted file mode 100644 index af5f96ff..00000000 --- a/run_tests.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python3 -""" -Test runner script for ComfyUI-Lora-Manager. - -This script runs pytest from the tests directory to avoid import issues -with the root __init__.py file. -""" -import subprocess -import sys -import os -from pathlib import Path - -# Set environment variable to indicate standalone mode -# HF_HUB_DISABLE_TELEMETRY is from ComfyUI main.py -standalone_mode = os.environ.get("HF_HUB_DISABLE_TELEMETRY", "0") == "0" - -def main(): - """Run pytest from the tests directory to avoid import issues.""" - # Get the script directory - script_dir = Path(__file__).parent.absolute() - tests_dir = script_dir / "tests" - - if not tests_dir.exists(): - print(f"Error: Tests directory not found at {tests_dir}") - return 1 - - # Change to tests directory - original_cwd = os.getcwd() - os.chdir(tests_dir) - - try: - # Build pytest command - cmd = [ - sys.executable, "-m", "pytest", - "-v", - "--rootdir=.", - ] + sys.argv[1:] # Pass any additional arguments - - print(f"Running: {' '.join(cmd)}") - print(f"Working directory: {tests_dir}") - - # Run pytest - result = subprocess.run(cmd, cwd=tests_dir) - return result.returncode - finally: - # Restore original working directory - os.chdir(original_cwd) - -if __name__ == "__main__": - sys.exit(main()) From c063854b511be529e8a4ef8b70c28b2d557d7db3 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Mon, 22 Sep 2025 05:25:27 +0800 Subject: [PATCH 056/110] feat(routes): extract orchestration use cases --- py/routes/base_model_routes.py | 27 ++- py/routes/handlers/model_handlers.py | 153 +++++--------- py/services/use_cases/__init__.py | 25 +++ .../use_cases/auto_organize_use_case.py | 56 +++++ .../bulk_metadata_refresh_use_case.py | 122 +++++++++++ .../use_cases/download_model_use_case.py | 37 ++++ py/services/websocket_progress_callback.py | 30 ++- tests/routes/test_base_model_routes_smoke.py | 80 ++++++++ tests/services/test_use_cases.py | 191 ++++++++++++++++++ 9 files changed, 609 insertions(+), 112 deletions(-) create mode 100644 py/services/use_cases/__init__.py create mode 100644 py/services/use_cases/auto_organize_use_case.py create mode 100644 py/services/use_cases/bulk_metadata_refresh_use_case.py create mode 100644 py/services/use_cases/download_model_use_case.py create mode 100644 tests/services/test_use_cases.py diff --git a/py/routes/base_model_routes.py b/py/routes/base_model_routes.py index 65103ece..872dca8b 100644 --- a/py/routes/base_model_routes.py +++ b/py/routes/base_model_routes.py @@ -19,7 +19,15 @@ from ..services.service_registry import ServiceRegistry from ..services.settings_manager import settings as default_settings from ..services.tag_update_service import TagUpdateService from ..services.websocket_manager import ws_manager as default_ws_manager -from ..services.websocket_progress_callback import WebSocketProgressCallback +from ..services.use_cases import ( + AutoOrganizeUseCase, + BulkMetadataRefreshUseCase, + DownloadModelUseCase, +) +from ..services.websocket_progress_callback import ( + WebSocketBroadcastCallback, + WebSocketProgressCallback, +) from ..utils.exif_utils import ExifUtils from ..utils.metadata_manager import MetadataManager from ..utils.routes_common import ModelRouteUtils @@ -68,6 +76,7 @@ class BaseModelRoutes(ABC): self.model_file_service: ModelFileService | None = None self.model_move_service: ModelMoveService | None = None self.websocket_progress_callback = WebSocketProgressCallback() + self.metadata_progress_callback = WebSocketBroadcastCallback() self._handler_set: ModelHandlerSet | None = None self._handler_mapping: Dict[str, Callable[[web.Request], web.StreamResponse]] | None = None @@ -132,11 +141,19 @@ class BaseModelRoutes(ABC): tag_update_service=self._tag_update_service, ) query = ModelQueryHandler(service=service, logger=logger) + download_use_case = DownloadModelUseCase(download_coordinator=self._download_coordinator) download = ModelDownloadHandler( ws_manager=self._ws_manager, logger=logger, + download_use_case=download_use_case, download_coordinator=self._download_coordinator, ) + metadata_refresh_use_case = BulkMetadataRefreshUseCase( + service=service, + metadata_sync=self._metadata_sync_service, + settings_service=self._settings, + logger=logger, + ) civitai = ModelCivitaiHandler( service=service, settings_service=self._settings, @@ -147,10 +164,16 @@ class BaseModelRoutes(ABC): expected_model_types=self._get_expected_model_types, find_model_file=self._find_model_file, metadata_sync=self._metadata_sync_service, + metadata_refresh_use_case=metadata_refresh_use_case, + metadata_progress_callback=self.metadata_progress_callback, ) move = ModelMoveHandler(move_service=self._ensure_move_service(), logger=logger) - auto_organize = ModelAutoOrganizeHandler( + auto_organize_use_case = AutoOrganizeUseCase( file_service=self._ensure_file_service(), + lock_provider=self._ws_manager, + ) + auto_organize = ModelAutoOrganizeHandler( + use_case=auto_organize_use_case, progress_callback=self.websocket_progress_callback, ws_manager=self._ws_manager, logger=logger, diff --git a/py/routes/handlers/model_handlers.py b/py/routes/handlers/model_handlers.py index 5f9eaf3b..ba0628c6 100644 --- a/py/routes/handlers/model_handlers.py +++ b/py/routes/handlers/model_handlers.py @@ -14,10 +14,19 @@ import jinja2 from ...config import config from ...services.download_coordinator import DownloadCoordinator from ...services.metadata_sync_service import MetadataSyncService -from ...services.model_file_service import ModelFileService, ModelMoveService +from ...services.model_file_service import ModelMoveService from ...services.preview_asset_service import PreviewAssetService from ...services.settings_manager import SettingsManager from ...services.tag_update_service import TagUpdateService +from ...services.use_cases import ( + AutoOrganizeInProgressError, + AutoOrganizeUseCase, + BulkMetadataRefreshUseCase, + DownloadModelEarlyAccessError, + DownloadModelUseCase, + DownloadModelValidationError, + MetadataRefreshProgressReporter, +) from ...services.websocket_manager import WebSocketManager from ...services.websocket_progress_callback import WebSocketProgressCallback from ...utils.file_utils import calculate_sha256 @@ -600,33 +609,29 @@ class ModelDownloadHandler: *, ws_manager: WebSocketManager, logger: logging.Logger, + download_use_case: DownloadModelUseCase, download_coordinator: DownloadCoordinator, ) -> None: self._ws_manager = ws_manager self._logger = logger + self._download_use_case = download_use_case self._download_coordinator = download_coordinator async def download_model(self, request: web.Request) -> web.Response: try: payload = await request.json() - result = await self._download_coordinator.schedule_download(payload) + result = await self._download_use_case.execute(payload) if not result.get("success", False): return web.json_response(result, status=500) return web.json_response(result) - except ValueError as exc: + except DownloadModelValidationError as exc: return web.json_response({"success": False, "error": str(exc)}, status=400) + except DownloadModelEarlyAccessError as exc: + self._logger.warning("Early access error: %s", exc) + return web.json_response({"success": False, "error": str(exc)}, status=401) except Exception as exc: error_message = str(exc) - if "401" in error_message: - self._logger.warning("Early access error (401): %s", error_message) - return web.json_response( - { - "success": False, - "error": "Early Access Restriction: This model requires purchase. Please buy early access on Civitai.com.", - }, - status=401, - ) - self._logger.error("Error downloading model: %s", error_message) + self._logger.error("Error downloading model: %s", error_message, exc_info=True) return web.json_response({"success": False, "error": error_message}, status=500) async def download_model_get(self, request: web.Request) -> web.Response: @@ -653,12 +658,15 @@ class ModelDownloadHandler: future.set_result(data) mock_request = type("MockRequest", (), {"json": lambda self=None: future})() - result = await self._download_coordinator.schedule_download(data) + result = await self._download_use_case.execute(data) if not result.get("success", False): return web.json_response(result, status=500) return web.json_response(result) - except ValueError as exc: + except DownloadModelValidationError as exc: return web.json_response({"success": False, "error": str(exc)}, status=400) + except DownloadModelEarlyAccessError as exc: + self._logger.warning("Early access error: %s", exc) + return web.json_response({"success": False, "error": str(exc)}, status=401) except Exception as exc: self._logger.error("Error downloading model via GET: %s", exc, exc_info=True) return web.Response(status=500, text=str(exc)) @@ -703,6 +711,8 @@ class ModelCivitaiHandler: expected_model_types: Callable[[], str], find_model_file: Callable[[Iterable[Mapping[str, object]]], Optional[Mapping[str, object]]], metadata_sync: MetadataSyncService, + metadata_refresh_use_case: BulkMetadataRefreshUseCase, + metadata_progress_callback: MetadataRefreshProgressReporter, ) -> None: self._service = service self._settings = settings_service @@ -713,75 +723,16 @@ class ModelCivitaiHandler: self._expected_model_types = expected_model_types self._find_model_file = find_model_file self._metadata_sync = metadata_sync + self._metadata_refresh_use_case = metadata_refresh_use_case + self._metadata_progress_callback = metadata_progress_callback async def fetch_all_civitai(self, request: web.Request) -> web.Response: try: - cache = await self._service.scanner.get_cached_data() - total = len(cache.raw_data) - processed = 0 - success = 0 - needs_resort = False - - enable_metadata_archive_db = self._settings.get("enable_metadata_archive_db", False) - to_process = [ - model - for model in cache.raw_data - if model.get("sha256") - and (not model.get("civitai") or not model["civitai"].get("id")) - and ( - (enable_metadata_archive_db and not model.get("db_checked", False)) - or (not enable_metadata_archive_db and model.get("from_civitai") is True) - ) - ] - total_to_process = len(to_process) - - await self._ws_manager.broadcast({ - "status": "started", - "total": total_to_process, - "processed": 0, - "success": 0, - }) - - for model in to_process: - try: - original_name = model.get("model_name") - result, error = await self._metadata_sync.fetch_and_update_model( - sha256=model["sha256"], - file_path=model["file_path"], - model_data=model, - update_cache_func=self._service.scanner.update_single_model_cache, - ) - if result: - success += 1 - if original_name != model.get("model_name"): - needs_resort = True - processed += 1 - await self._ws_manager.broadcast({ - "status": "processing", - "total": total_to_process, - "processed": processed, - "success": success, - "current_name": model.get("model_name", "Unknown"), - }) - except Exception as exc: # pragma: no cover - logging path - self._logger.error("Error fetching CivitAI data for %s: %s", model["file_path"], exc) - - if needs_resort: - await cache.resort() - - await self._ws_manager.broadcast({ - "status": "completed", - "total": total_to_process, - "processed": processed, - "success": success, - }) - - return web.json_response({ - "success": True, - "message": f"Successfully updated {success} of {processed} processed {self._service.model_type}s (total: {total})", - }) + result = await self._metadata_refresh_use_case.execute_with_error_handling( + progress_callback=self._metadata_progress_callback + ) + return web.json_response(result) except Exception as exc: - await self._ws_manager.broadcast({"status": "error", "error": str(exc)}) self._logger.error("Error in fetch_all_civitai for %ss: %s", self._service.model_type, exc) return web.Response(text=str(exc), status=500) @@ -887,31 +838,18 @@ class ModelAutoOrganizeHandler: def __init__( self, *, - file_service: ModelFileService, + use_case: AutoOrganizeUseCase, progress_callback: WebSocketProgressCallback, ws_manager: WebSocketManager, logger: logging.Logger, ) -> None: - self._file_service = file_service + self._use_case = use_case self._progress_callback = progress_callback self._ws_manager = ws_manager self._logger = logger async def auto_organize_models(self, request: web.Request) -> web.Response: try: - if self._ws_manager.is_auto_organize_running(): - return web.json_response( - {"success": False, "error": "Auto-organize is already running. Please wait for it to complete."}, - status=409, - ) - - auto_organize_lock = await self._ws_manager.get_auto_organize_lock() - if auto_organize_lock.locked(): - return web.json_response( - {"success": False, "error": "Auto-organize is already running. Please wait for it to complete."}, - status=409, - ) - file_paths = None if request.method == "POST": try: @@ -920,17 +858,24 @@ class ModelAutoOrganizeHandler: except Exception: # pragma: no cover - permissive path pass - async with auto_organize_lock: - result = await self._file_service.auto_organize_models( - file_paths=file_paths, - progress_callback=self._progress_callback, - ) - return web.json_response(result.to_dict()) + result = await self._use_case.execute( + file_paths=file_paths, + progress_callback=self._progress_callback, + ) + return web.json_response(result.to_dict()) + except AutoOrganizeInProgressError: + return web.json_response( + {"success": False, "error": "Auto-organize is already running. Please wait for it to complete."}, + status=409, + ) except Exception as exc: self._logger.error("Error in auto_organize_models: %s", exc, exc_info=True) - await self._ws_manager.broadcast_auto_organize_progress( - {"type": "auto_organize_progress", "status": "error", "error": str(exc)} - ) + try: + await self._progress_callback.on_progress( + {"type": "auto_organize_progress", "status": "error", "error": str(exc)} + ) + except Exception: # pragma: no cover - defensive reporting + pass return web.json_response({"success": False, "error": str(exc)}, status=500) async def get_auto_organize_progress(self, request: web.Request) -> web.Response: diff --git a/py/services/use_cases/__init__.py b/py/services/use_cases/__init__.py new file mode 100644 index 00000000..986f0f57 --- /dev/null +++ b/py/services/use_cases/__init__.py @@ -0,0 +1,25 @@ +"""Application-level orchestration services for model routes.""" + +from .auto_organize_use_case import ( + AutoOrganizeInProgressError, + AutoOrganizeUseCase, +) +from .bulk_metadata_refresh_use_case import ( + BulkMetadataRefreshUseCase, + MetadataRefreshProgressReporter, +) +from .download_model_use_case import ( + DownloadModelEarlyAccessError, + DownloadModelUseCase, + DownloadModelValidationError, +) + +__all__ = [ + "AutoOrganizeInProgressError", + "AutoOrganizeUseCase", + "BulkMetadataRefreshUseCase", + "MetadataRefreshProgressReporter", + "DownloadModelEarlyAccessError", + "DownloadModelUseCase", + "DownloadModelValidationError", +] diff --git a/py/services/use_cases/auto_organize_use_case.py b/py/services/use_cases/auto_organize_use_case.py new file mode 100644 index 00000000..0914739f --- /dev/null +++ b/py/services/use_cases/auto_organize_use_case.py @@ -0,0 +1,56 @@ +"""Auto-organize use case orchestrating concurrency and progress handling.""" + +from __future__ import annotations + +import asyncio +from typing import Optional, Protocol, Sequence + +from ..model_file_service import AutoOrganizeResult, ModelFileService, ProgressCallback + + +class AutoOrganizeLockProvider(Protocol): + """Minimal protocol for objects exposing auto-organize locking primitives.""" + + def is_auto_organize_running(self) -> bool: + """Return ``True`` when an auto-organize operation is in-flight.""" + + async def get_auto_organize_lock(self) -> asyncio.Lock: + """Return the asyncio lock guarding auto-organize operations.""" + + +class AutoOrganizeInProgressError(RuntimeError): + """Raised when an auto-organize run is already active.""" + + +class AutoOrganizeUseCase: + """Coordinate auto-organize execution behind a shared lock.""" + + def __init__( + self, + *, + file_service: ModelFileService, + lock_provider: AutoOrganizeLockProvider, + ) -> None: + self._file_service = file_service + self._lock_provider = lock_provider + + async def execute( + self, + *, + file_paths: Optional[Sequence[str]] = None, + progress_callback: Optional[ProgressCallback] = None, + ) -> AutoOrganizeResult: + """Run the auto-organize routine guarded by a shared lock.""" + + if self._lock_provider.is_auto_organize_running(): + raise AutoOrganizeInProgressError("Auto-organize is already running") + + lock = await self._lock_provider.get_auto_organize_lock() + if lock.locked(): + raise AutoOrganizeInProgressError("Auto-organize is already running") + + async with lock: + return await self._file_service.auto_organize_models( + file_paths=list(file_paths) if file_paths is not None else None, + progress_callback=progress_callback, + ) diff --git a/py/services/use_cases/bulk_metadata_refresh_use_case.py b/py/services/use_cases/bulk_metadata_refresh_use_case.py new file mode 100644 index 00000000..6a809955 --- /dev/null +++ b/py/services/use_cases/bulk_metadata_refresh_use_case.py @@ -0,0 +1,122 @@ +"""Use case encapsulating the bulk metadata refresh orchestration.""" + +from __future__ import annotations + +import logging +from typing import Any, Dict, Optional, Protocol, Sequence + +from ..metadata_sync_service import MetadataSyncService + + +class MetadataRefreshProgressReporter(Protocol): + """Protocol for progress reporters used during metadata refresh.""" + + async def on_progress(self, payload: Dict[str, Any]) -> None: + """Handle a metadata refresh progress update.""" + + +class BulkMetadataRefreshUseCase: + """Coordinate bulk metadata refreshes with progress emission.""" + + def __init__( + self, + *, + service, + metadata_sync: MetadataSyncService, + settings_service, + logger: Optional[logging.Logger] = None, + ) -> None: + self._service = service + self._metadata_sync = metadata_sync + self._settings = settings_service + self._logger = logger or logging.getLogger(__name__) + + async def execute( + self, + *, + progress_callback: Optional[MetadataRefreshProgressReporter] = None, + ) -> Dict[str, Any]: + """Refresh metadata for all qualifying models.""" + + cache = await self._service.scanner.get_cached_data() + total_models = len(cache.raw_data) + + enable_metadata_archive_db = self._settings.get("enable_metadata_archive_db", False) + to_process: Sequence[Dict[str, Any]] = [ + model + for model in cache.raw_data + if model.get("sha256") + and (not model.get("civitai") or not model["civitai"].get("id")) + and ( + (enable_metadata_archive_db and not model.get("db_checked", False)) + or (not enable_metadata_archive_db and model.get("from_civitai") is True) + ) + ] + + total_to_process = len(to_process) + processed = 0 + success = 0 + needs_resort = False + + async def emit(status: str, **extra: Any) -> None: + if progress_callback is None: + return + payload = {"status": status, "total": total_to_process, "processed": processed, "success": success} + payload.update(extra) + await progress_callback.on_progress(payload) + + await emit("started") + + for model in to_process: + try: + original_name = model.get("model_name") + result, _ = await self._metadata_sync.fetch_and_update_model( + sha256=model["sha256"], + file_path=model["file_path"], + model_data=model, + update_cache_func=self._service.scanner.update_single_model_cache, + ) + if result: + success += 1 + if original_name != model.get("model_name"): + needs_resort = True + processed += 1 + await emit( + "processing", + processed=processed, + success=success, + current_name=model.get("model_name", "Unknown"), + ) + except Exception as exc: # pragma: no cover - logging path + processed += 1 + self._logger.error( + "Error fetching CivitAI data for %s: %s", + model.get("file_path"), + exc, + ) + + if needs_resort: + await cache.resort() + + await emit("completed", processed=processed, success=success) + + message = ( + "Successfully updated " + f"{success} of {processed} processed {self._service.model_type}s (total: {total_models})" + ) + + return {"success": True, "message": message, "processed": processed, "updated": success, "total": total_models} + + async def execute_with_error_handling( + self, + *, + progress_callback: Optional[MetadataRefreshProgressReporter] = None, + ) -> Dict[str, Any]: + """Wrapper providing progress notification on unexpected failures.""" + + try: + return await self.execute(progress_callback=progress_callback) + except Exception as exc: + if progress_callback is not None: + await progress_callback.on_progress({"status": "error", "error": str(exc)}) + raise diff --git a/py/services/use_cases/download_model_use_case.py b/py/services/use_cases/download_model_use_case.py new file mode 100644 index 00000000..5aa25bda --- /dev/null +++ b/py/services/use_cases/download_model_use_case.py @@ -0,0 +1,37 @@ +"""Use case for scheduling model downloads with consistent error handling.""" + +from __future__ import annotations + +from typing import Any, Dict + +from ..download_coordinator import DownloadCoordinator + + +class DownloadModelValidationError(ValueError): + """Raised when incoming payload validation fails.""" + + +class DownloadModelEarlyAccessError(RuntimeError): + """Raised when the download is gated behind Civitai early access.""" + + +class DownloadModelUseCase: + """Coordinate download scheduling through the coordinator service.""" + + def __init__(self, *, download_coordinator: DownloadCoordinator) -> None: + self._download_coordinator = download_coordinator + + async def execute(self, payload: Dict[str, Any]) -> Dict[str, Any]: + """Schedule a download and normalize error conditions.""" + + try: + return await self._download_coordinator.schedule_download(payload) + except ValueError as exc: + raise DownloadModelValidationError(str(exc)) from exc + except Exception as exc: # pragma: no cover - defensive logging path + message = str(exc) + if "401" in message: + raise DownloadModelEarlyAccessError( + "Early Access Restriction: This model requires purchase. Please buy early access on Civitai.com." + ) from exc + raise diff --git a/py/services/websocket_progress_callback.py b/py/services/websocket_progress_callback.py index 1a390f30..21423044 100644 --- a/py/services/websocket_progress_callback.py +++ b/py/services/websocket_progress_callback.py @@ -1,11 +1,29 @@ -from typing import Dict, Any +"""Progress callback implementations backed by the shared WebSocket manager.""" + +from typing import Any, Dict, Protocol + from .model_file_service import ProgressCallback from .websocket_manager import ws_manager -class WebSocketProgressCallback(ProgressCallback): - """WebSocket implementation of progress callback""" - +class ProgressReporter(Protocol): + """Protocol representing an async progress callback.""" + async def on_progress(self, progress_data: Dict[str, Any]) -> None: - """Send progress data via WebSocket""" - await ws_manager.broadcast_auto_organize_progress(progress_data) \ No newline at end of file + """Handle a progress update payload.""" + + +class WebSocketProgressCallback(ProgressCallback): + """WebSocket implementation of progress callback.""" + + async def on_progress(self, progress_data: Dict[str, Any]) -> None: + """Send progress data via WebSocket.""" + await ws_manager.broadcast_auto_organize_progress(progress_data) + + +class WebSocketBroadcastCallback: + """Generic WebSocket progress callback broadcasting to all clients.""" + + async def on_progress(self, progress_data: Dict[str, Any]) -> None: + """Send the provided payload to all connected clients.""" + await ws_manager.broadcast(progress_data) diff --git a/tests/routes/test_base_model_routes_smoke.py b/tests/routes/test_base_model_routes_smoke.py index 2b9ed805..25ebaabc 100644 --- a/tests/routes/test_base_model_routes_smoke.py +++ b/tests/routes/test_base_model_routes_smoke.py @@ -28,6 +28,7 @@ spec.loader.exec_module(py_local) sys.modules.setdefault("py_local", py_local) from py_local.routes.base_model_routes import BaseModelRoutes +from py_local.services.model_file_service import AutoOrganizeResult from py_local.services.service_registry import ServiceRegistry from py_local.services.websocket_manager import ws_manager from py_local.utils.routes_common import ExifUtils @@ -222,6 +223,25 @@ def test_download_model_invokes_download_manager( asyncio.run(scenario()) +def test_download_model_requires_identifier(mock_service, download_manager_stub): + async def scenario(): + client = await create_test_client(mock_service) + try: + response = await client.post( + "/api/lm/download-model", + json={"model_root": "/tmp"}, + ) + payload = await response.json() + + assert response.status == 400 + assert payload["success"] is False + assert "Missing required" in payload["error"] + finally: + await client.close() + + asyncio.run(scenario()) + + def test_auto_organize_progress_returns_latest_snapshot(mock_service): async def scenario(): client = await create_test_client(mock_service) @@ -235,5 +255,65 @@ def test_auto_organize_progress_returns_latest_snapshot(mock_service): assert payload == {"success": True, "progress": {"status": "processing", "percent": 50}} finally: await client.close() + + asyncio.run(scenario()) + + +def test_auto_organize_route_emits_progress(mock_service, monkeypatch: pytest.MonkeyPatch): + async def fake_auto_organize(self, file_paths=None, progress_callback=None): + result = AutoOrganizeResult() + result.total = 1 + result.processed = 1 + result.success_count = 1 + result.skipped_count = 0 + result.failure_count = 0 + result.operation_type = "bulk" + if progress_callback is not None: + await progress_callback.on_progress({"type": "auto_organize_progress", "status": "started"}) + await progress_callback.on_progress({"type": "auto_organize_progress", "status": "completed"}) + return result + + monkeypatch.setattr( + py_local.services.model_file_service.ModelFileService, + "auto_organize_models", + fake_auto_organize, + ) + + async def scenario(): + client = await create_test_client(mock_service) + try: + response = await client.post("/api/lm/test-models/auto-organize", json={"file_paths": []}) + payload = await response.json() + + assert response.status == 200 + assert payload["success"] is True + + progress = ws_manager.get_auto_organize_progress() + assert progress is not None + assert progress["status"] == "completed" + finally: + await client.close() + + asyncio.run(scenario()) + + +def test_auto_organize_conflict_when_running(mock_service): + async def scenario(): + client = await create_test_client(mock_service) + try: + await ws_manager.broadcast_auto_organize_progress( + {"type": "auto_organize_progress", "status": "started"} + ) + + response = await client.post("/api/lm/test-models/auto-organize") + payload = await response.json() + + assert response.status == 409 + assert payload == { + "success": False, + "error": "Auto-organize is already running. Please wait for it to complete.", + } + finally: + await client.close() asyncio.run(scenario()) diff --git a/tests/services/test_use_cases.py b/tests/services/test_use_cases.py new file mode 100644 index 00000000..64057fc6 --- /dev/null +++ b/tests/services/test_use_cases.py @@ -0,0 +1,191 @@ +import asyncio +import logging +from dataclasses import dataclass +from typing import Any, Dict, List, Optional + +import pytest + +from py_local.services.model_file_service import AutoOrganizeResult +from py_local.services.use_cases import ( + AutoOrganizeInProgressError, + AutoOrganizeUseCase, + BulkMetadataRefreshUseCase, + DownloadModelEarlyAccessError, + DownloadModelUseCase, + DownloadModelValidationError, +) +from tests.conftest import MockModelService, MockScanner + + +class StubLockProvider: + def __init__(self) -> None: + self._lock = asyncio.Lock() + self.running = False + + def is_auto_organize_running(self) -> bool: + return self.running + + async def get_auto_organize_lock(self) -> asyncio.Lock: + return self._lock + + +class StubFileService: + def __init__(self) -> None: + self.calls: List[Dict[str, Any]] = [] + + async def auto_organize_models( + self, + *, + file_paths: Optional[List[str]] = None, + progress_callback=None, + ) -> AutoOrganizeResult: + result = AutoOrganizeResult() + result.total = len(file_paths or []) + self.calls.append({"file_paths": file_paths, "progress_callback": progress_callback}) + return result + + +class StubMetadataSync: + def __init__(self) -> None: + self.calls: List[Dict[str, Any]] = [] + + async def fetch_and_update_model(self, **kwargs: Any): + self.calls.append(kwargs) + model_data = kwargs["model_data"] + model_data["model_name"] = model_data.get("model_name", "model") + "-updated" + return True, None + + +@dataclass +class StubSettings: + enable_metadata_archive_db: bool = False + + def get(self, key: str, default: Any = None) -> Any: + if key == "enable_metadata_archive_db": + return self.enable_metadata_archive_db + return default + + +class ProgressCollector: + def __init__(self) -> None: + self.events: List[Dict[str, Any]] = [] + + async def on_progress(self, payload: Dict[str, Any]) -> None: + self.events.append(payload) + + +class StubDownloadCoordinator: + def __init__(self, *, error: Optional[str] = None) -> None: + self.error = error + self.payloads: List[Dict[str, Any]] = [] + + async def schedule_download(self, payload: Dict[str, Any]) -> Dict[str, Any]: + self.payloads.append(payload) + if self.error == "validation": + raise ValueError("Missing required parameter: Please provide either 'model_id' or 'model_version_id'") + if self.error == "401": + raise RuntimeError("401 Unauthorized") + return {"success": True, "download_id": "abc123"} + + +async def test_auto_organize_use_case_executes_with_lock() -> None: + file_service = StubFileService() + lock_provider = StubLockProvider() + use_case = AutoOrganizeUseCase(file_service=file_service, lock_provider=lock_provider) + + result = await use_case.execute(file_paths=["model1"], progress_callback=None) + + assert isinstance(result, AutoOrganizeResult) + assert file_service.calls[0]["file_paths"] == ["model1"] + + +async def test_auto_organize_use_case_rejects_when_running() -> None: + file_service = StubFileService() + lock_provider = StubLockProvider() + lock_provider.running = True + use_case = AutoOrganizeUseCase(file_service=file_service, lock_provider=lock_provider) + + with pytest.raises(AutoOrganizeInProgressError): + await use_case.execute(file_paths=None, progress_callback=None) + + +async def test_bulk_metadata_refresh_emits_progress_and_updates_cache() -> None: + scanner = MockScanner() + scanner._cache.raw_data = [ + { + "file_path": "model1.safetensors", + "sha256": "hash", + "from_civitai": True, + "model_name": "Demo", + } + ] + service = MockModelService(scanner) + metadata_sync = StubMetadataSync() + settings = StubSettings() + progress = ProgressCollector() + + use_case = BulkMetadataRefreshUseCase( + service=service, + metadata_sync=metadata_sync, + settings_service=settings, + logger=logging.getLogger("test"), + ) + + result = await use_case.execute_with_error_handling(progress_callback=progress) + + assert result["success"] is True + assert progress.events[0]["status"] == "started" + assert progress.events[-1]["status"] == "completed" + assert metadata_sync.calls + assert scanner._cache.resort_calls == 1 + + +async def test_bulk_metadata_refresh_reports_errors() -> None: + class FailingScanner(MockScanner): + async def get_cached_data(self, force_refresh: bool = False): + raise RuntimeError("boom") + + service = MockModelService(FailingScanner()) + metadata_sync = StubMetadataSync() + settings = StubSettings() + progress = ProgressCollector() + + use_case = BulkMetadataRefreshUseCase( + service=service, + metadata_sync=metadata_sync, + settings_service=settings, + logger=logging.getLogger("test"), + ) + + with pytest.raises(RuntimeError): + await use_case.execute_with_error_handling(progress_callback=progress) + + assert progress.events + assert progress.events[-1]["status"] == "error" + assert progress.events[-1]["error"] == "boom" + + +async def test_download_model_use_case_raises_validation_error() -> None: + coordinator = StubDownloadCoordinator(error="validation") + use_case = DownloadModelUseCase(download_coordinator=coordinator) + + with pytest.raises(DownloadModelValidationError): + await use_case.execute({}) + + +async def test_download_model_use_case_raises_early_access() -> None: + coordinator = StubDownloadCoordinator(error="401") + use_case = DownloadModelUseCase(download_coordinator=coordinator) + + with pytest.raises(DownloadModelEarlyAccessError): + await use_case.execute({"model_id": 1}) + + +async def test_download_model_use_case_returns_result() -> None: + coordinator = StubDownloadCoordinator() + use_case = DownloadModelUseCase(download_coordinator=coordinator) + + result = await use_case.execute({"model_id": 1}) + + assert result["success"] is True + assert result["download_id"] == "abc123" From 66a3f3f59a0c80113b9ec25c6eb88381ba7b12db Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 22 Sep 2025 05:37:24 +0800 Subject: [PATCH 057/110] refactor(tests): enhance async test handling in pytest_pyfunc_call --- tests/conftest.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 818aeb9b..006a1adc 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -42,8 +42,30 @@ sys.modules['nodes'] = nodes_mock def pytest_pyfunc_call(pyfuncitem): - if inspect.iscoroutinefunction(pyfuncitem.function): - asyncio.run(pyfuncitem.obj(**pyfuncitem.funcargs)) + """Allow bare async tests to run without pytest.mark.asyncio.""" + test_function = pyfuncitem.function + if inspect.iscoroutinefunction(test_function): + func = pyfuncitem.obj + signature = inspect.signature(func) + accepted_kwargs: Dict[str, Any] = {} + for name, parameter in signature.parameters.items(): + if parameter.kind is inspect.Parameter.VAR_POSITIONAL: + continue + if parameter.kind is inspect.Parameter.VAR_KEYWORD: + accepted_kwargs = dict(pyfuncitem.funcargs) + break + if name in pyfuncitem.funcargs: + accepted_kwargs[name] = pyfuncitem.funcargs[name] + + original_policy = asyncio.get_event_loop_policy() + policy = pyfuncitem.funcargs.get("event_loop_policy") + if policy is not None and policy is not original_policy: + asyncio.set_event_loop_policy(policy) + try: + asyncio.run(func(**accepted_kwargs)) + finally: + if policy is not None and policy is not original_policy: + asyncio.set_event_loop_policy(original_policy) return True return None @@ -196,3 +218,5 @@ def mock_scanner(mock_cache: MockCache, mock_hash_index: MockHashIndex) -> MockS @pytest.fixture def mock_service(mock_scanner: MockScanner) -> MockModelService: return MockModelService(scanner=mock_scanner) + + From 1c4096f3d5836b53fd73e6d5a7c6678890e2902e Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 22 Sep 2025 06:28:30 +0800 Subject: [PATCH 058/110] test(routes): add tests for service readiness and error handling in download model --- docs/architecture/model_routes.md | 189 ++++++++----------- tests/routes/test_base_model_routes_smoke.py | 71 +++++++ 2 files changed, 152 insertions(+), 108 deletions(-) diff --git a/docs/architecture/model_routes.md b/docs/architecture/model_routes.md index 00329299..564ba010 100644 --- a/docs/architecture/model_routes.md +++ b/docs/architecture/model_routes.md @@ -1,127 +1,100 @@ # Base model route architecture -The `BaseModelRoutes` controller centralizes HTTP endpoints that every model type -(LoRAs, checkpoints, embeddings, etc.) share. Each handler either forwards the -request to the injected service, delegates to a utility in -`ModelRouteUtils`, or orchestrates long‑running operations via helper services -such as the download or WebSocket managers. The table below lists every handler -exposed in `py/routes/base_model_routes.py`, the collaborators it leans on, and -any cache or WebSocket side effects implemented in -`py/utils/routes_common.py`. +The model routing stack now splits HTTP wiring, orchestration logic, and +business rules into discrete layers. The goal is to make it obvious where a +new collaborator should live and which contract it must honour. The diagram +below captures the end-to-end flow for a typical request: -## Contents +```mermaid +graph TD + subgraph HTTP + A[ModelRouteRegistrar] -->|binds| B[BaseModelRoutes handler proxy] + end + subgraph Application + B --> C[ModelHandlerSet] + C --> D1[Handlers] + D1 --> E1[Use cases] + E1 --> F1[Services / scanners] + end + subgraph Side Effects + F1 --> G1[Cache & metadata] + F1 --> G2[Filesystem] + F1 --> G3[WebSocket state] + end +``` -- [Handler catalogue](#handler-catalogue) -- [Dependency map and contracts](#dependency-map-and-contracts) - - [Cache and metadata mutations](#cache-and-metadata-mutations) - - [Download and WebSocket flows](#download-and-websocket-flows) - - [Read-only queries](#read-only-queries) - - [Template rendering and initialization](#template-rendering-and-initialization) +Every box maps to a concrete module: -## Handler catalogue +| Layer | Module(s) | Responsibility | +| --- | --- | --- | +| Registrar | `py/routes/model_route_registrar.py` | Declarative list of routes shared by every model type and helper methods for binding them to an `aiohttp` application. | +| Route controller | `py/routes/base_model_routes.py` | Constructs the handler graph, injects shared services, exposes proxies that surface `503 Service not ready` when the model service has not been attached. | +| Handler set | `py/routes/handlers/model_handlers.py` | Thin HTTP adapters grouped by concern (page rendering, listings, mutations, queries, downloads, CivitAI integration, move operations, auto-organize). | +| Use cases | `py/services/use_cases/*.py` | Encapsulate long-running flows (`DownloadModelUseCase`, `BulkMetadataRefreshUseCase`, `AutoOrganizeUseCase`). They normalise validation errors and concurrency constraints before returning control to the handlers. | +| Services | `py/services/*.py` | Existing services and scanners that mutate caches, write metadata, move files, and broadcast WebSocket updates. | -The routes exposed by `BaseModelRoutes` combine HTTP wiring with a handful of -shared helper classes. Services surface filesystem and metadata operations, -`ModelRouteUtils` bundles cache-sensitive mutations, and `ws_manager` -coordinates fan-out to browser clients. The tables below expand the existing -catalogue into explicit dependency maps and invariants so refactors can reason -about the expectations each collaborator must uphold. +## Handler responsibilities & contracts -## Dependency map and contracts +`ModelHandlerSet` flattens the handler objects into the exact callables used by +the registrar. The table below highlights the separation of concerns within +the set and the invariants that must hold after each handler returns. -### Cache and metadata mutations - -| Endpoint(s) | Delegate(s) | State touched | Invariants / contracts | +| Handler | Key endpoints | Collaborators | Contracts | | --- | --- | --- | --- | -| `/api/lm/{prefix}/delete` | `ModelRouteUtils.handle_delete_model()` | Removes files from disk, prunes `scanner._cache.raw_data`, awaits `scanner._cache.resort()`, calls `scanner._hash_index.remove_by_path()`. | Cache and hash index must no longer reference the deleted path; resort must complete before responding to keep pagination deterministic. | -| `/api/lm/{prefix}/exclude` | `ModelRouteUtils.handle_exclude_model()` | Mutates metadata records, `scanner._cache.raw_data`, `scanner._hash_index`, `scanner._tags_count`, and `scanner._excluded_models`. | Excluded models remain discoverable via exclusion list while being hidden from listings; tag counts stay balanced after removal. | -| `/api/lm/{prefix}/fetch-civitai` | `ModelRouteUtils.fetch_and_update_model()` | Reads `scanner._cache.raw_data`, writes metadata JSON through `MetadataManager`, syncs cache via `scanner.update_single_model_cache`. | Requires a cached SHA256 hash; cache entries must reflect merged metadata before formatted response is returned. | -| `/api/lm/{prefix}/fetch-all-civitai` | `ModelRouteUtils.fetch_and_update_model()`, `ws_manager.broadcast()` | Iterates over cache, updates metadata files and cache records, optionally awaits `scanner._cache.resort()`. | Progress broadcasts follow started → processing → completed; if any model name changes, cache resort must run once before completion broadcast. | -| `/api/lm/{prefix}/relink-civitai` | `ModelRouteUtils.handle_relink_civitai()` | Updates metadata on disk and resynchronizes the cache entry. | The new association must propagate to `scanner.update_single_model_cache` so duplicate resolution and listings reflect the change immediately. | -| `/api/lm/{prefix}/replace-preview` | `ModelRouteUtils.handle_replace_preview()` | Writes optimized preview file, persists metadata via `MetadataManager`, updates cache with `scanner.update_preview_in_cache()`. | Preview path stored in metadata and cache must match the normalized file system path; NSFW level integer is synchronized across metadata and cache. | -| `/api/lm/{prefix}/save-metadata` | `ModelRouteUtils.handle_save_metadata()` | Writes metadata JSON and ensures cache entry mirrors the latest content. | Metadata persistence must be atomic—cache data should match on-disk metadata before response emits success. | -| `/api/lm/{prefix}/add-tags` | `ModelRouteUtils.handle_add_tags()` | Updates metadata tags, increments `scanner._tags_count`, and patches cached item. | Tag frequency map remains in sync with cache and metadata after increments. | -| `/api/lm/{prefix}/rename` | `ModelRouteUtils.handle_rename_model()` | Renames files, metadata, previews; updates cache indices and hash mappings. | File moves succeed or rollback as a unit so cache state never points to a missing file; hash index entries track the new path. | -| `/api/lm/{prefix}/bulk-delete` | `ModelRouteUtils.handle_bulk_delete_models()` | Delegates to `scanner.bulk_delete_models()` to delete files, trim cache, resort, and drop hash index entries. | Every requested path is removed from cache and index; resort happens once after bulk deletion. | -| `/api/lm/{prefix}/verify-duplicates` | `ModelRouteUtils.handle_verify_duplicates()` | Recomputes hashes, updates metadata and cached entries if discrepancies found. | Hash metadata stored in cache must mirror recomputed values to guarantee future duplicate checks operate on current data. | -| `/api/lm/{prefix}/scan` | `service.scan_models()` | Rescans filesystem, rebuilding scanner cache. | Scanner replaces its cache atomically so subsequent requests observe a consistent snapshot. | -| `/api/lm/{prefix}/move_model` | `ModelMoveService.move_model()` | Moves files/directories and notifies scanner via service layer conventions. | Move operations respect filesystem invariants (target path exists, metadata follows file) and emit success/failure without leaving partial moves. | -| `/api/lm/{prefix}/move_models_bulk` | `ModelMoveService.move_models_bulk()` | Batch move behavior as above. | Aggregated result enumerates successes/failures while preserving per-model atomicity. | -| `/api/lm/{prefix}/auto-organize` (GET/POST) | `ModelFileService.auto_organize_models()`, `ws_manager.get_auto_organize_lock()`, `WebSocketProgressCallback` | Writes organized files, updates metadata, and streams progress snapshots. | Only one auto-organize job may run; lock must guard reentrancy and WebSocket updates must include latest progress payload consumed by polling route. | +| `ModelPageView` | `/{prefix}` | `SettingsManager`, `server_i18n`, Jinja environment, `service.scanner` | Template is rendered with `is_initializing` flag when caches are cold; i18n filter is registered exactly once per environment instance. | +| `ModelListingHandler` | `/api/lm/{prefix}/list` | `service.get_paginated_data`, `service.format_response` | Listings respect pagination query parameters and cap `page_size` at 100; every item is formatted before response. | +| `ModelManagementHandler` | Mutations (delete, exclude, metadata, preview, tags, rename, bulk delete, duplicate verification) | `ModelRouteUtils`, `MetadataSyncService`, `PreviewAssetService`, `TagUpdateService`, scanner cache/index | Cache state mirrors filesystem changes: deletes prune cache & hash index, preview replacements synchronise metadata and cache NSFW levels, metadata saves trigger cache resort when names change. | +| `ModelQueryHandler` | Read-only queries (top tags, folders, duplicates, metadata, URLs) | Service query helpers & scanner cache | Outputs always wrapped in `{"success": True}` when no error; duplicate/filename grouping omits empty entries; invalid parameters (e.g. missing `model_root`) return HTTP 400. | +| `ModelDownloadHandler` | `/api/lm/download-model`, `/download-model-get`, `/download-progress/{id}`, `/cancel-download-get` | `DownloadModelUseCase`, `DownloadCoordinator`, `WebSocketManager` | Payload validation errors become HTTP 400 without mutating download progress cache; early-access failures surface as HTTP 401; successful downloads cache progress snapshots that back both WebSocket broadcasts and polling endpoints. | +| `ModelCivitaiHandler` | CivitAI metadata routes | `MetadataSyncService`, metadata provider factory, `BulkMetadataRefreshUseCase` | `fetch_all_civitai` streams progress via `WebSocketBroadcastCallback`; version lookups validate model type before returning; local availability fields derive from hash lookups without mutating cache state. | +| `ModelMoveHandler` | `move_model`, `move_models_bulk` | `ModelMoveService` | Moves execute atomically per request; bulk operations aggregate success/failure per file set. | +| `ModelAutoOrganizeHandler` | `/api/lm/{prefix}/auto-organize` (GET/POST), `/auto-organize-progress` | `AutoOrganizeUseCase`, `WebSocketProgressCallback`, `WebSocketManager` | Enforces single-flight execution using the shared lock; progress broadcasts remain available to polling clients until explicitly cleared; conflicts return HTTP 409 with a descriptive error. | -### Download and WebSocket flows +## Use case boundaries -| Endpoint(s) | Delegate(s) | State touched | Invariants / contracts | +Each use case exposes a narrow asynchronous API that hides the underlying +services. Their error mapping is essential for predictable HTTP responses. + +| Use case | Entry point | Dependencies | Guarantees | | --- | --- | --- | --- | -| `/api/lm/download-model` (POST) & `/api/lm/download-model-get` (GET) | `ModelRouteUtils.handle_download_model()`, `ServiceRegistry.get_download_manager()` | Schedules downloads, registers `ws_manager.broadcast_download_progress()` callback that stores progress in `ws_manager._download_progress`. | Download IDs remain stable across POST/GET helpers; every progress callback persists a timestamped entry so `/download-progress` and WebSocket clients share consistent snapshots. | -| `/api/lm/cancel-download-get` | `ModelRouteUtils.handle_cancel_download()` | Signals download manager, prunes `ws_manager._download_progress`, and emits cancellation broadcast. | Cancel requests must tolerate missing IDs gracefully while ensuring cached progress is removed once cancellation succeeds. | -| `/api/lm/download-progress/{download_id}` | `ws_manager.get_download_progress()` | Reads cached progress dictionary. | Returns `404` when progress is absent; successful payload surfaces the numeric `progress` stored during broadcasts. | -| `/api/lm/{prefix}/fetch-all-civitai` | `ws_manager.broadcast()` | Broadcast loop described above. | Broadcast cadence cannot skip completion/error messages so clients know when to clear UI spinners. | -| `/api/lm/{prefix}/auto-organize-progress` | `ws_manager.get_auto_organize_progress()` | Reads cached progress snapshot. | Route returns cached payload verbatim; absence yields `404` to signal idle state. | +| `DownloadModelUseCase` | `execute(payload)` | `DownloadCoordinator.schedule_download` | Translates `ValueError` into `DownloadModelValidationError` for HTTP 400, recognises early-access errors (`"401"` in message) and surfaces them as `DownloadModelEarlyAccessError`, forwards success dictionaries untouched. | +| `AutoOrganizeUseCase` | `execute(file_paths, progress_callback)` | `ModelFileService.auto_organize_models`, `WebSocketManager` lock | Guarded by `ws_manager` lock + status checks; raises `AutoOrganizeInProgressError` before invoking the file service when another run is already active. | +| `BulkMetadataRefreshUseCase` | `execute_with_error_handling(progress_callback)` | `MetadataSyncService`, `SettingsManager`, `WebSocketBroadcastCallback` | Iterates through cached models, applies metadata sync, emits progress snapshots that handlers broadcast unchanged. | -### Read-only queries +## Maintaining legacy contracts -| Endpoint(s) | Delegate(s) | State touched | Invariants / contracts | -| --- | --- | --- | --- | -| `/api/lm/{prefix}/list` | `service.get_paginated_data()`, `service.format_response()` | Reads service-managed pagination data. | Formatting must be applied to every item before response; pagination metadata echoes service result. | -| `/api/lm/{prefix}/top-tags` | `service.get_top_tags()` | Reads aggregated tag counts. | Limit parameter bounded to `[1, 100]`; response always wraps tags in `{success: True}` envelope. | -| `/api/lm/{prefix}/base-models` | `service.get_base_models()` | Reads service data. | Same limit handling as tags. | -| `/api/lm/{prefix}/roots` | `service.get_model_roots()` | Reads configured roots. | Always returns `{success: True, roots: [...]}`. | -| `/api/lm/{prefix}/folders` | `service.scanner.get_cached_data()` | Reads folder summaries from cache. | Cache access must tolerate initialization phases by surfacing errors via HTTP 500. | -| `/api/lm/{prefix}/folder-tree` | `service.get_folder_tree()` | Reads derived tree for requested root. | Rejects missing `model_root` with HTTP 400. | -| `/api/lm/{prefix}/unified-folder-tree` | `service.get_unified_folder_tree()` | Aggregated folder tree. | Returns `{success: True, tree: ...}` or 500 on error. | -| `/api/lm/{prefix}/find-duplicates` | `service.find_duplicate_hashes()`, `service.scanner.get_cached_data()`, `service.get_path_by_hash()` | Reads cache and hash index to format duplicates. | Only returns groups with more than one resolved model. | -| `/api/lm/{prefix}/find-filename-conflicts` | `service.find_duplicate_filenames()`, `service.scanner.get_cached_data()`, `service.scanner.get_hash_by_filename()` | Similar read-only assembly. | Includes resolved main index entry when available; empty `models` groups are omitted. | -| `/api/lm/{prefix}/get-notes` | `service.get_model_notes()` | Reads persisted notes. | Missing notes produce HTTP 404 with explicit error message. | -| `/api/lm/{prefix}/preview-url` | `service.get_model_preview_url()` | Resolves static URL. | Successful responses wrap URL in `{success: True}`; missing preview yields 404 error payload. | -| `/api/lm/{prefix}/civitai-url` | `service.get_model_civitai_url()` | Returns remote permalink info. | Response envelope matches preview pattern. | -| `/api/lm/{prefix}/metadata` | `service.get_model_metadata()` | Reads metadata JSON. | Responds with raw metadata dict or 500 on failure. | -| `/api/lm/{prefix}/model-description` | `service.get_model_description()` | Returns formatted description string. | Always JSON with success boolean. | -| `/api/lm/{prefix}/relative-paths` | `service.get_relative_paths()` | Resolves filesystem suggestions. | Maintains read-only contract. | -| `/api/lm/{prefix}/civitai/versions/{model_id}` | `get_default_metadata_provider()`, `service.has_hash()`, `service.get_path_by_hash()` | Reads remote API, cross-references cache. | Versions payload includes `existsLocally`/`localPath` only when hashes match local indices. | -| `/api/lm/{prefix}/civitai/model/version/{modelVersionId}` | `get_default_metadata_provider()` | Remote metadata lookup. | Errors propagate as JSON with `{success: False}` payload. | -| `/api/lm/{prefix}/civitai/model/hash/{hash}` | `get_default_metadata_provider()` | Remote metadata lookup. | Missing hashes return 404 with `{success: False}`. | +The refactor preserves the invariants called out in the previous architecture +notes. The most critical ones are reiterated here to emphasise the +collaboration points: -### Template rendering and initialization +1. **Cache mutations** – Delete, exclude, rename, and bulk delete operations are + channelled through `ModelManagementHandler`. The handler delegates to + `ModelRouteUtils` or `MetadataSyncService`, and the scanner cache is mutated + in-place before the handler returns. The accompanying tests assert that + `scanner._cache.raw_data` and `scanner._hash_index` stay in sync after each + mutation. +2. **Preview updates** – `PreviewAssetService.replace_preview` writes the new + asset, `MetadataSyncService` persists the JSON metadata, and + `scanner.update_preview_in_cache` mirrors the change. The handler returns + the static URL produced by `config.get_preview_static_url`, keeping browser + clients in lockstep with disk state. +3. **Download progress** – `DownloadCoordinator.schedule_download` generates the + download identifier, registers a WebSocket progress callback, and caches the + latest numeric progress via `WebSocketManager`. Both `download_model` + responses and `/download-progress/{id}` polling read from the same cache to + guarantee consistent progress reporting across transports. -| Endpoint(s) | Delegate(s) | State touched | Invariants / contracts | -| --- | --- | --- | --- | -| `/{prefix}` | `handle_models_page` | Reads configuration via `settings`, sets locale with `server_i18n`, pulls cached folders through `service.scanner.get_cached_data()`, renders Jinja template. | Template rendering must tolerate scanner initialization by flagging `is_initializing`; i18n filter is attached exactly once per environment to avoid duplicate registration errors. | +## Extending the stack -### Contract sequences +To add a new shared route: -The following high-level sequences show how the collaborating services work -together for the most stateful operations: +1. Declare it in `COMMON_ROUTE_DEFINITIONS` using a unique handler name. +2. Implement the corresponding coroutine on one of the handlers inside + `ModelHandlerSet` (or introduce a new handler class when the concern does not + fit existing ones). +3. Inject additional dependencies in `BaseModelRoutes._create_handler_set` by + wiring services or use cases through the constructor parameters. -``` -delete_model request - → BaseModelRoutes.delete_model - → ModelRouteUtils.handle_delete_model - → filesystem delete + metadata cleanup - → scanner._cache.raw_data prune - → await scanner._cache.resort() - → scanner._hash_index.remove_by_path() -``` - -``` -replace_preview request - → BaseModelRoutes.replace_preview - → ModelRouteUtils.handle_replace_preview - → ExifUtils.optimize_image / config.get_preview_static_url - → MetadataManager.save_metadata - → scanner.update_preview_in_cache(model_path, preview_path, nsfw_level) -``` - -``` -download_model request - → BaseModelRoutes.download_model - → ModelRouteUtils.handle_download_model - → ServiceRegistry.get_download_manager().download_from_civitai(..., progress_callback) - → ws_manager.broadcast_download_progress(download_id, data) - → ws_manager._download_progress[download_id] updated with timestamp - → /api/lm/download-progress/{id} polls ws_manager.get_download_progress -``` - -These contracts complement the tables above: if any collaborator changes its -behavior, the invariants called out here must continue to hold for the routes -to remain predictable. +Model-specific routes should continue to be registered inside the subclass +implementation of `setup_specific_routes`, reusing the shared registrar where +possible. diff --git a/tests/routes/test_base_model_routes_smoke.py b/tests/routes/test_base_model_routes_smoke.py index 25ebaabc..136bd0a8 100644 --- a/tests/routes/test_base_model_routes_smoke.py +++ b/tests/routes/test_base_model_routes_smoke.py @@ -67,12 +67,24 @@ def download_manager_stub(): class FakeDownloadManager: def __init__(self): self.calls = [] + self.error = None + self.cancelled = [] + self.active_downloads = {} async def download_from_civitai(self, **kwargs): self.calls.append(kwargs) + if self.error is not None: + raise self.error await kwargs["progress_callback"](42) return {"success": True, "path": "/tmp/model.safetensors"} + async def cancel_download(self, download_id): + self.cancelled.append(download_id) + return {"success": True, "download_id": download_id} + + async def get_active_downloads(self): + return self.active_downloads + stub = FakeDownloadManager() previous = ServiceRegistry._services.get("download_manager") asyncio.run(ServiceRegistry.register_service("download_manager", stub)) @@ -104,6 +116,21 @@ def test_list_models_returns_formatted_items(mock_service, mock_scanner): asyncio.run(scenario()) +def test_routes_return_service_not_ready_when_unattached(): + async def scenario(): + client = await create_test_client(None) + try: + response = await client.get("/api/lm/test-models/list") + payload = await response.json() + + assert response.status == 503 + assert payload == {"success": False, "error": "Service not ready"} + finally: + await client.close() + + asyncio.run(scenario()) + + def test_delete_model_updates_cache_and_hash_index(mock_service, mock_scanner, tmp_path: Path): model_path = tmp_path / "sample.safetensors" model_path.write_bytes(b"model") @@ -242,6 +269,50 @@ def test_download_model_requires_identifier(mock_service, download_manager_stub) asyncio.run(scenario()) +def test_download_model_maps_validation_errors(mock_service, download_manager_stub): + download_manager_stub.error = ValueError("Invalid relative path") + + async def scenario(): + client = await create_test_client(mock_service) + try: + response = await client.post( + "/api/lm/download-model", + json={"model_version_id": 123}, + ) + payload = await response.json() + + assert response.status == 400 + assert payload == {"success": False, "error": "Invalid relative path"} + assert ws_manager._download_progress == {} + finally: + await client.close() + + asyncio.run(scenario()) + + +def test_download_model_maps_early_access_errors(mock_service, download_manager_stub): + download_manager_stub.error = RuntimeError("401 early access") + + async def scenario(): + client = await create_test_client(mock_service) + try: + response = await client.post( + "/api/lm/download-model", + json={"model_id": 4}, + ) + payload = await response.json() + + assert response.status == 401 + assert payload == { + "success": False, + "error": "Early Access Restriction: This model requires purchase. Please buy early access on Civitai.com.", + } + finally: + await client.close() + + asyncio.run(scenario()) + + def test_auto_organize_progress_returns_latest_snapshot(mock_service): async def scenario(): client = await create_test_client(mock_service) From 08baf884d3e4b050034f3690f006550d6f376037 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Mon, 22 Sep 2025 08:28:30 +0800 Subject: [PATCH 059/110] refactor(routes): migrate lifecycle mutations to service --- docs/architecture/model_routes.md | 10 +- py/routes/base_model_routes.py | 20 ++ py/routes/handlers/model_handlers.py | 83 ++++++- py/services/model_lifecycle_service.py | 245 ++++++++++++++++++ py/services/model_scanner.py | 7 +- py/utils/routes_common.py | 327 +------------------------ 6 files changed, 352 insertions(+), 340 deletions(-) create mode 100644 py/services/model_lifecycle_service.py diff --git a/docs/architecture/model_routes.md b/docs/architecture/model_routes.md index 564ba010..a9fbf967 100644 --- a/docs/architecture/model_routes.md +++ b/docs/architecture/model_routes.md @@ -43,7 +43,7 @@ the set and the invariants that must hold after each handler returns. | --- | --- | --- | --- | | `ModelPageView` | `/{prefix}` | `SettingsManager`, `server_i18n`, Jinja environment, `service.scanner` | Template is rendered with `is_initializing` flag when caches are cold; i18n filter is registered exactly once per environment instance. | | `ModelListingHandler` | `/api/lm/{prefix}/list` | `service.get_paginated_data`, `service.format_response` | Listings respect pagination query parameters and cap `page_size` at 100; every item is formatted before response. | -| `ModelManagementHandler` | Mutations (delete, exclude, metadata, preview, tags, rename, bulk delete, duplicate verification) | `ModelRouteUtils`, `MetadataSyncService`, `PreviewAssetService`, `TagUpdateService`, scanner cache/index | Cache state mirrors filesystem changes: deletes prune cache & hash index, preview replacements synchronise metadata and cache NSFW levels, metadata saves trigger cache resort when names change. | +| `ModelManagementHandler` | Mutations (delete, exclude, metadata, preview, tags, rename, bulk delete, duplicate verification) | `ModelLifecycleService`, `MetadataSyncService`, `PreviewAssetService`, `TagUpdateService`, scanner cache/index | Cache state mirrors filesystem changes: deletes prune cache & hash index, preview replacements synchronise metadata and cache NSFW levels, metadata saves trigger cache resort when names change. | | `ModelQueryHandler` | Read-only queries (top tags, folders, duplicates, metadata, URLs) | Service query helpers & scanner cache | Outputs always wrapped in `{"success": True}` when no error; duplicate/filename grouping omits empty entries; invalid parameters (e.g. missing `model_root`) return HTTP 400. | | `ModelDownloadHandler` | `/api/lm/download-model`, `/download-model-get`, `/download-progress/{id}`, `/cancel-download-get` | `DownloadModelUseCase`, `DownloadCoordinator`, `WebSocketManager` | Payload validation errors become HTTP 400 without mutating download progress cache; early-access failures surface as HTTP 401; successful downloads cache progress snapshots that back both WebSocket broadcasts and polling endpoints. | | `ModelCivitaiHandler` | CivitAI metadata routes | `MetadataSyncService`, metadata provider factory, `BulkMetadataRefreshUseCase` | `fetch_all_civitai` streams progress via `WebSocketBroadcastCallback`; version lookups validate model type before returning; local availability fields derive from hash lookups without mutating cache state. | @@ -69,10 +69,10 @@ collaboration points: 1. **Cache mutations** – Delete, exclude, rename, and bulk delete operations are channelled through `ModelManagementHandler`. The handler delegates to - `ModelRouteUtils` or `MetadataSyncService`, and the scanner cache is mutated - in-place before the handler returns. The accompanying tests assert that - `scanner._cache.raw_data` and `scanner._hash_index` stay in sync after each - mutation. + `ModelLifecycleService` or `MetadataSyncService`, and the scanner cache is + mutated in-place before the handler returns. The accompanying tests assert + that `scanner._cache.raw_data` and `scanner._hash_index` stay in sync after + each mutation. 2. **Preview updates** – `PreviewAssetService.replace_preview` writes the new asset, `MetadataSyncService` persists the JSON metadata, and `scanner.update_preview_in_cache` mirrors the change. The handler returns diff --git a/py/routes/base_model_routes.py b/py/routes/base_model_routes.py index 872dca8b..35415331 100644 --- a/py/routes/base_model_routes.py +++ b/py/routes/base_model_routes.py @@ -13,6 +13,7 @@ from ..services.downloader import get_downloader from ..services.metadata_service import get_default_metadata_provider, get_metadata_provider from ..services.metadata_sync_service import MetadataSyncService from ..services.model_file_service import ModelFileService, ModelMoveService +from ..services.model_lifecycle_service import ModelLifecycleService from ..services.preview_asset_service import PreviewAssetService from ..services.server_i18n import server_i18n as default_server_i18n from ..services.service_registry import ServiceRegistry @@ -75,6 +76,7 @@ class BaseModelRoutes(ABC): self.model_file_service: ModelFileService | None = None self.model_move_service: ModelMoveService | None = None + self.model_lifecycle_service: ModelLifecycleService | None = None self.websocket_progress_callback = WebSocketProgressCallback() self.metadata_progress_callback = WebSocketBroadcastCallback() @@ -108,6 +110,12 @@ class BaseModelRoutes(ABC): self.model_type = service.model_type self.model_file_service = ModelFileService(service.scanner, service.model_type) self.model_move_service = ModelMoveService(service.scanner) + self.model_lifecycle_service = ModelLifecycleService( + scanner=service.scanner, + metadata_manager=MetadataManager, + metadata_loader=self._metadata_sync_service.load_local_metadata, + recipe_scanner_factory=ServiceRegistry.get_recipe_scanner, + ) self._handler_set = None self._handler_mapping = None @@ -139,6 +147,7 @@ class BaseModelRoutes(ABC): metadata_sync=self._metadata_sync_service, preview_service=self._preview_service, tag_update_service=self._tag_update_service, + lifecycle_service=self._ensure_lifecycle_service(), ) query = ModelQueryHandler(service=service, logger=logger) download_use_case = DownloadModelUseCase(download_coordinator=self._download_coordinator) @@ -248,6 +257,17 @@ class BaseModelRoutes(ABC): self.model_move_service = ModelMoveService(service.scanner) return self.model_move_service + def _ensure_lifecycle_service(self) -> ModelLifecycleService: + if self.model_lifecycle_service is None: + service = self._ensure_service() + self.model_lifecycle_service = ModelLifecycleService( + scanner=service.scanner, + metadata_manager=MetadataManager, + metadata_loader=self._metadata_sync_service.load_local_metadata, + recipe_scanner_factory=ServiceRegistry.get_recipe_scanner, + ) + return self.model_lifecycle_service + def _make_handler_proxy(self, name: str) -> Callable[[web.Request], web.StreamResponse]: async def proxy(request: web.Request) -> web.StreamResponse: try: diff --git a/py/routes/handlers/model_handlers.py b/py/routes/handlers/model_handlers.py index ba0628c6..a6fe4091 100644 --- a/py/routes/handlers/model_handlers.py +++ b/py/routes/handlers/model_handlers.py @@ -30,7 +30,6 @@ from ...services.use_cases import ( from ...services.websocket_manager import WebSocketManager from ...services.websocket_progress_callback import WebSocketProgressCallback from ...utils.file_utils import calculate_sha256 -from ...utils.routes_common import ModelRouteUtils class ModelPageView: @@ -192,18 +191,44 @@ class ModelManagementHandler: metadata_sync: MetadataSyncService, preview_service: PreviewAssetService, tag_update_service: TagUpdateService, + lifecycle_service, ) -> None: self._service = service self._logger = logger self._metadata_sync = metadata_sync self._preview_service = preview_service self._tag_update_service = tag_update_service + self._lifecycle_service = lifecycle_service async def delete_model(self, request: web.Request) -> web.Response: - return await ModelRouteUtils.handle_delete_model(request, self._service.scanner) + try: + data = await request.json() + file_path = data.get("file_path") + if not file_path: + return web.Response(text="Model path is required", status=400) + + result = await self._lifecycle_service.delete_model(file_path) + return web.json_response(result) + except ValueError as exc: + return web.json_response({"success": False, "error": str(exc)}, status=400) + except Exception as exc: + self._logger.error("Error deleting model: %s", exc, exc_info=True) + return web.Response(text=str(exc), status=500) async def exclude_model(self, request: web.Request) -> web.Response: - return await ModelRouteUtils.handle_exclude_model(request, self._service.scanner) + try: + data = await request.json() + file_path = data.get("file_path") + if not file_path: + return web.Response(text="Model path is required", status=400) + + result = await self._lifecycle_service.exclude_model(file_path) + return web.json_response(result) + except ValueError as exc: + return web.json_response({"success": False, "error": str(exc)}, status=400) + except Exception as exc: + self._logger.error("Error excluding model: %s", exc, exc_info=True) + return web.Response(text=str(exc), status=500) async def fetch_civitai(self, request: web.Request) -> web.Response: try: @@ -375,10 +400,58 @@ class ModelManagementHandler: return web.Response(text=str(exc), status=500) async def rename_model(self, request: web.Request) -> web.Response: - return await ModelRouteUtils.handle_rename_model(request, self._service.scanner) + try: + data = await request.json() + file_path = data.get("file_path") + new_file_name = data.get("new_file_name") + + if not file_path or not new_file_name: + return web.json_response( + { + "success": False, + "error": "File path and new file name are required", + }, + status=400, + ) + + result = await self._lifecycle_service.rename_model( + file_path=file_path, new_file_name=new_file_name + ) + + return web.json_response( + { + **result, + "new_preview_path": config.get_preview_static_url( + result.get("new_preview_path") + ), + } + ) + except ValueError as exc: + return web.json_response({"success": False, "error": str(exc)}, status=400) + except Exception as exc: + self._logger.error("Error renaming model: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) async def bulk_delete_models(self, request: web.Request) -> web.Response: - return await ModelRouteUtils.handle_bulk_delete_models(request, self._service.scanner) + try: + data = await request.json() + file_paths = data.get("file_paths", []) + if not file_paths: + return web.json_response( + { + "success": False, + "error": "No file paths provided for deletion", + }, + status=400, + ) + + result = await self._lifecycle_service.bulk_delete_models(file_paths) + return web.json_response(result) + except ValueError as exc: + return web.json_response({"success": False, "error": str(exc)}, status=400) + except Exception as exc: + self._logger.error("Error in bulk delete: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) async def verify_duplicates(self, request: web.Request) -> web.Response: try: diff --git a/py/services/model_lifecycle_service.py b/py/services/model_lifecycle_service.py new file mode 100644 index 00000000..9aa87b04 --- /dev/null +++ b/py/services/model_lifecycle_service.py @@ -0,0 +1,245 @@ +"""Service routines for model lifecycle mutations.""" + +from __future__ import annotations + +import logging +import os +from typing import Awaitable, Callable, Dict, Iterable, List, Optional + +from ..services.service_registry import ServiceRegistry +from ..utils.constants import PREVIEW_EXTENSIONS + +logger = logging.getLogger(__name__) + + +async def delete_model_artifacts(target_dir: str, file_name: str) -> List[str]: + """Delete the primary model artefacts within ``target_dir``.""" + + patterns = [ + f"{file_name}.safetensors", + f"{file_name}.metadata.json", + ] + for ext in PREVIEW_EXTENSIONS: + patterns.append(f"{file_name}{ext}") + + deleted: List[str] = [] + main_file = patterns[0] + main_path = os.path.join(target_dir, main_file).replace(os.sep, "/") + + if os.path.exists(main_path): + os.remove(main_path) + deleted.append(main_path) + else: + logger.warning("Model file not found: %s", main_file) + + for pattern in patterns[1:]: + path = os.path.join(target_dir, pattern) + if os.path.exists(path): + try: + os.remove(path) + deleted.append(pattern) + except Exception as exc: # pragma: no cover - defensive path + logger.warning("Failed to delete %s: %s", pattern, exc) + + return deleted + + +class ModelLifecycleService: + """Co-ordinate destructive and mutating model operations.""" + + def __init__( + self, + *, + scanner, + metadata_manager, + metadata_loader: Callable[[str], Awaitable[Dict[str, object]]], + recipe_scanner_factory: Callable[[], Awaitable] | None = None, + ) -> None: + self._scanner = scanner + self._metadata_manager = metadata_manager + self._metadata_loader = metadata_loader + self._recipe_scanner_factory = ( + recipe_scanner_factory or ServiceRegistry.get_recipe_scanner + ) + + async def delete_model(self, file_path: str) -> Dict[str, object]: + """Delete a model file and associated artefacts.""" + + if not file_path: + raise ValueError("Model path is required") + + target_dir = os.path.dirname(file_path) + file_name = os.path.splitext(os.path.basename(file_path))[0] + + deleted_files = await delete_model_artifacts(target_dir, file_name) + + cache = await self._scanner.get_cached_data() + cache.raw_data = [item for item in cache.raw_data if item["file_path"] != file_path] + await cache.resort() + + if hasattr(self._scanner, "_hash_index") and self._scanner._hash_index: + self._scanner._hash_index.remove_by_path(file_path) + + return {"success": True, "deleted_files": deleted_files} + + async def exclude_model(self, file_path: str) -> Dict[str, object]: + """Mark a model as excluded and prune cache references.""" + + if not file_path: + raise ValueError("Model path is required") + + metadata_path = os.path.splitext(file_path)[0] + ".metadata.json" + metadata = await self._metadata_loader(metadata_path) + metadata["exclude"] = True + + await self._metadata_manager.save_metadata(file_path, metadata) + + cache = await self._scanner.get_cached_data() + model_to_remove = next( + (item for item in cache.raw_data if item["file_path"] == file_path), + None, + ) + + if model_to_remove: + for tag in model_to_remove.get("tags", []): + if tag in getattr(self._scanner, "_tags_count", {}): + self._scanner._tags_count[tag] = max( + 0, self._scanner._tags_count[tag] - 1 + ) + if self._scanner._tags_count[tag] == 0: + del self._scanner._tags_count[tag] + + if hasattr(self._scanner, "_hash_index") and self._scanner._hash_index: + self._scanner._hash_index.remove_by_path(file_path) + + cache.raw_data = [ + item for item in cache.raw_data if item["file_path"] != file_path + ] + await cache.resort() + + excluded = getattr(self._scanner, "_excluded_models", None) + if isinstance(excluded, list): + excluded.append(file_path) + + message = f"Model {os.path.basename(file_path)} excluded" + return {"success": True, "message": message} + + async def bulk_delete_models(self, file_paths: Iterable[str]) -> Dict[str, object]: + """Delete a collection of models via the scanner bulk operation.""" + + file_paths = list(file_paths) + if not file_paths: + raise ValueError("No file paths provided for deletion") + + return await self._scanner.bulk_delete_models(file_paths) + + async def rename_model( + self, *, file_path: str, new_file_name: str + ) -> Dict[str, object]: + """Rename a model and its companion artefacts.""" + + if not file_path or not new_file_name: + raise ValueError("File path and new file name are required") + + invalid_chars = {"/", "\\", ":", "*", "?", '"', "<", ">", "|"} + if any(char in new_file_name for char in invalid_chars): + raise ValueError("Invalid characters in file name") + + target_dir = os.path.dirname(file_path) + old_file_name = os.path.splitext(os.path.basename(file_path))[0] + new_file_path = os.path.join(target_dir, f"{new_file_name}.safetensors").replace( + os.sep, "/" + ) + + if os.path.exists(new_file_path): + raise ValueError("A file with this name already exists") + + patterns = [ + f"{old_file_name}.safetensors", + f"{old_file_name}.metadata.json", + f"{old_file_name}.metadata.json.bak", + ] + for ext in PREVIEW_EXTENSIONS: + patterns.append(f"{old_file_name}{ext}") + + existing_files: List[tuple[str, str]] = [] + for pattern in patterns: + path = os.path.join(target_dir, pattern) + if os.path.exists(path): + existing_files.append((path, pattern)) + + metadata_path = os.path.join(target_dir, f"{old_file_name}.metadata.json") + metadata: Optional[Dict[str, object]] = None + hash_value: Optional[str] = None + + if os.path.exists(metadata_path): + metadata = await self._metadata_loader(metadata_path) + hash_value = metadata.get("sha256") if isinstance(metadata, dict) else None + + renamed_files: List[str] = [] + new_metadata_path: Optional[str] = None + new_preview: Optional[str] = None + + for old_path, pattern in existing_files: + ext = self._get_multipart_ext(pattern) + new_path = os.path.join(target_dir, f"{new_file_name}{ext}").replace( + os.sep, "/" + ) + os.rename(old_path, new_path) + renamed_files.append(new_path) + + if ext == ".metadata.json": + new_metadata_path = new_path + + if metadata and new_metadata_path: + metadata["file_name"] = new_file_name + metadata["file_path"] = new_file_path + + if metadata.get("preview_url"): + old_preview = str(metadata["preview_url"]) + ext = self._get_multipart_ext(old_preview) + new_preview = os.path.join(target_dir, f"{new_file_name}{ext}").replace( + os.sep, "/" + ) + metadata["preview_url"] = new_preview + + await self._metadata_manager.save_metadata(new_file_path, metadata) + + if metadata: + await self._scanner.update_single_model_cache( + file_path, new_file_path, metadata + ) + + if hash_value and getattr(self._scanner, "model_type", "") == "lora": + recipe_scanner = await self._recipe_scanner_factory() + if recipe_scanner: + try: + await recipe_scanner.update_lora_filename_by_hash( + hash_value, new_file_name + ) + except Exception as exc: # pragma: no cover - defensive logging + logger.error( + "Error updating recipe references for %s: %s", + file_path, + exc, + ) + + return { + "success": True, + "new_file_path": new_file_path, + "new_preview_path": new_preview, + "renamed_files": renamed_files, + "reload_required": False, + } + + @staticmethod + def _get_multipart_ext(filename: str) -> str: + """Return the extension for files with compound suffixes.""" + + parts = filename.split(".") + if len(parts) == 3: + return "." + ".".join(parts[-2:]) + if len(parts) >= 4: + return "." + ".".join(parts[-3:]) + return os.path.splitext(filename)[1] + diff --git a/py/services/model_scanner.py b/py/services/model_scanner.py index f0ae3177..51aa4507 100644 --- a/py/services/model_scanner.py +++ b/py/services/model_scanner.py @@ -13,6 +13,7 @@ from ..utils.metadata_manager import MetadataManager from .model_cache import ModelCache from .model_hash_index import ModelHashIndex from ..utils.constants import PREVIEW_EXTENSIONS +from .model_lifecycle_service import delete_model_artifacts from .service_registry import ServiceRegistry from .websocket_manager import ws_manager @@ -1040,10 +1041,8 @@ class ModelScanner: target_dir = os.path.dirname(file_path) file_name = os.path.splitext(os.path.basename(file_path))[0] - # Delete all associated files for the model - from ..utils.routes_common import ModelRouteUtils - deleted_files = await ModelRouteUtils.delete_model_files( - target_dir, + deleted_files = await delete_model_artifacts( + target_dir, file_name ) diff --git a/py/utils/routes_common.py b/py/utils/routes_common.py index b5f6af30..84e2fc9d 100644 --- a/py/utils/routes_common.py +++ b/py/utils/routes_common.py @@ -1,7 +1,7 @@ import os import json import logging -from typing import Dict, List, Callable, Awaitable +from typing import Dict, Callable, Awaitable from aiohttp import web from datetime import datetime @@ -284,104 +284,6 @@ class ModelRouteUtils: ] return {k: data[k] for k in fields if k in data} - @staticmethod - async def delete_model_files(target_dir: str, file_name: str) -> List[str]: - """Delete model and associated files - - Args: - target_dir: Directory containing the model files - file_name: Base name of the model file without extension - - Returns: - List of deleted file paths - """ - patterns = [ - f"{file_name}.safetensors", # Required - f"{file_name}.metadata.json", - ] - - # Add all preview file extensions - for ext in PREVIEW_EXTENSIONS: - patterns.append(f"{file_name}{ext}") - - deleted = [] - main_file = patterns[0] - main_path = os.path.join(target_dir, main_file).replace(os.sep, '/') - - if os.path.exists(main_path): - # Delete file - os.remove(main_path) - deleted.append(main_path) - else: - logger.warning(f"Model file not found: {main_file}") - - # Delete optional files - for pattern in patterns[1:]: - path = os.path.join(target_dir, pattern) - if os.path.exists(path): - try: - os.remove(path) - deleted.append(pattern) - except Exception as e: - logger.warning(f"Failed to delete {pattern}: {e}") - - return deleted - - @staticmethod - def get_multipart_ext(filename): - """Get extension that may have multiple parts like .metadata.json or .metadata.json.bak""" - parts = filename.split(".") - if len(parts) == 3: # If contains 2-part extension - return "." + ".".join(parts[-2:]) # Take the last two parts, like ".metadata.json" - elif len(parts) >= 4: # If contains 3-part or more extensions - return "." + ".".join(parts[-3:]) # Take the last three parts, like ".metadata.json.bak" - return os.path.splitext(filename)[1] # Otherwise take the regular extension, like ".safetensors" - - # New common endpoint handlers - - @staticmethod - async def handle_delete_model(request: web.Request, scanner) -> web.Response: - """Handle model deletion request - - Args: - request: The aiohttp request - scanner: The model scanner instance with cache management methods - - Returns: - web.Response: The HTTP response - """ - try: - data = await request.json() - file_path = data.get('file_path') - if not file_path: - return web.Response(text='Model path is required', status=400) - - target_dir = os.path.dirname(file_path) - file_name = os.path.splitext(os.path.basename(file_path))[0] - - deleted_files = await ModelRouteUtils.delete_model_files( - target_dir, - file_name - ) - - # Remove from cache - cache = await scanner.get_cached_data() - cache.raw_data = [item for item in cache.raw_data if item['file_path'] != file_path] - await cache.resort() - - # Update hash index if available - if hasattr(scanner, '_hash_index') and scanner._hash_index: - scanner._hash_index.remove_by_path(file_path) - - return web.json_response({ - 'success': True, - 'deleted_files': deleted_files - }) - - except Exception as e: - logger.error(f"Error deleting model: {e}", exc_info=True) - return web.Response(text=str(e), status=500) - @staticmethod async def handle_fetch_civitai(request: web.Request, scanner) -> web.Response: """Handle CivitAI metadata fetch request @@ -544,64 +446,6 @@ class ModelRouteUtils: logger.error(f"Error replacing preview: {e}", exc_info=True) return web.Response(text=str(e), status=500) - @staticmethod - async def handle_exclude_model(request: web.Request, scanner) -> web.Response: - """Handle model exclusion request - - Args: - request: The aiohttp request - scanner: The model scanner instance with cache management methods - - Returns: - web.Response: The HTTP response - """ - try: - data = await request.json() - file_path = data.get('file_path') - if not file_path: - return web.Response(text='Model path is required', status=400) - - # Update metadata to mark as excluded - metadata_path = os.path.splitext(file_path)[0] + '.metadata.json' - metadata = await ModelRouteUtils.load_local_metadata(metadata_path) - metadata['exclude'] = True - - # Save updated metadata - await MetadataManager.save_metadata(file_path, metadata) - - # Update cache - cache = await scanner.get_cached_data() - - # Find and remove model from cache - model_to_remove = next((item for item in cache.raw_data if item['file_path'] == file_path), None) - if model_to_remove: - # Update tags count - for tag in model_to_remove.get('tags', []): - if tag in scanner._tags_count: - scanner._tags_count[tag] = max(0, scanner._tags_count[tag] - 1) - if scanner._tags_count[tag] == 0: - del scanner._tags_count[tag] - - # Remove from hash index if available - if hasattr(scanner, '_hash_index') and scanner._hash_index: - scanner._hash_index.remove_by_path(file_path) - - # Remove from cache data - cache.raw_data = [item for item in cache.raw_data if item['file_path'] != file_path] - await cache.resort() - - # Add to excluded models list - scanner._excluded_models.append(file_path) - - return web.json_response({ - 'success': True, - 'message': f"Model {os.path.basename(file_path)} excluded" - }) - - except Exception as e: - logger.error(f"Error excluding model: {e}", exc_info=True) - return web.Response(text=str(e), status=500) - @staticmethod async def handle_download_model(request: web.Request) -> web.Response: """Handle model download request""" @@ -755,44 +599,6 @@ class ModelRouteUtils: 'error': str(e) }, status=500) - @staticmethod - async def handle_bulk_delete_models(request: web.Request, scanner) -> web.Response: - """Handle bulk deletion of models - - Args: - request: The aiohttp request - scanner: The model scanner instance with cache management methods - - Returns: - web.Response: The HTTP response - """ - try: - data = await request.json() - file_paths = data.get('file_paths', []) - - if not file_paths: - return web.json_response({ - 'success': False, - 'error': 'No file paths provided for deletion' - }, status=400) - - # Use the scanner's bulk delete method to handle all cache and file operations - result = await scanner.bulk_delete_models(file_paths) - - return web.json_response({ - 'success': result.get('success', False), - 'total_deleted': result.get('total_deleted', 0), - 'total_attempted': result.get('total_attempted', len(file_paths)), - 'results': result.get('results', []) - }) - - except Exception as e: - logger.error(f"Error in bulk delete: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - @staticmethod async def handle_relink_civitai(request: web.Request, scanner) -> web.Response: """Handle CivitAI metadata re-linking request by model ID and/or version ID @@ -948,137 +754,6 @@ class ModelRouteUtils: 'error': str(e) }, status=500) - @staticmethod - async def handle_rename_model(request: web.Request, scanner) -> web.Response: - """Handle renaming a model file and its associated files - - Args: - request: The aiohttp request - scanner: The model scanner instance - - Returns: - web.Response: The HTTP response - """ - try: - data = await request.json() - file_path = data.get('file_path') - new_file_name = data.get('new_file_name') - - if not file_path or not new_file_name: - return web.json_response({ - 'success': False, - 'error': 'File path and new file name are required' - }, status=400) - - # Validate the new file name (no path separators or invalid characters) - invalid_chars = ['/', '\\', ':', '*', '?', '"', '<', '>', '|'] - if any(char in new_file_name for char in invalid_chars): - return web.json_response({ - 'success': False, - 'error': 'Invalid characters in file name' - }, status=400) - - # Get the directory and current file name - target_dir = os.path.dirname(file_path) - old_file_name = os.path.splitext(os.path.basename(file_path))[0] - - # Check if the target file already exists - new_file_path = os.path.join(target_dir, f"{new_file_name}.safetensors").replace(os.sep, '/') - if os.path.exists(new_file_path): - return web.json_response({ - 'success': False, - 'error': 'A file with this name already exists' - }, status=400) - - # Define the patterns for associated files - patterns = [ - f"{old_file_name}.safetensors", # Required - f"{old_file_name}.metadata.json", - f"{old_file_name}.metadata.json.bak", - ] - - # Add all preview file extensions - for ext in PREVIEW_EXTENSIONS: - patterns.append(f"{old_file_name}{ext}") - - # Find all matching files - existing_files = [] - for pattern in patterns: - path = os.path.join(target_dir, pattern) - if os.path.exists(path): - existing_files.append((path, pattern)) - - # Get the hash from the main file to update hash index - hash_value = None - metadata = None - metadata_path = os.path.join(target_dir, f"{old_file_name}.metadata.json") - - if os.path.exists(metadata_path): - metadata = await ModelRouteUtils.load_local_metadata(metadata_path) - hash_value = metadata.get('sha256') - logger.info(f"hash_value: {hash_value}, metadata_path: {metadata_path}, metadata: {metadata}") - # Rename all files - renamed_files = [] - new_metadata_path = None - new_preview = None - - for old_path, pattern in existing_files: - # Get the file extension like .safetensors or .metadata.json - ext = ModelRouteUtils.get_multipart_ext(pattern) - - # Create the new path - new_path = os.path.join(target_dir, f"{new_file_name}{ext}").replace(os.sep, '/') - - # Rename the file - os.rename(old_path, new_path) - renamed_files.append(new_path) - - # Keep track of metadata path for later update - if ext == '.metadata.json': - new_metadata_path = new_path - - # Update the metadata file with new file name and paths - if new_metadata_path and metadata: - # Update file_name, file_path and preview_url in metadata - metadata['file_name'] = new_file_name - metadata['file_path'] = new_file_path - - # Update preview_url if it exists - if 'preview_url' in metadata and metadata['preview_url']: - old_preview = metadata['preview_url'] - ext = ModelRouteUtils.get_multipart_ext(old_preview) - new_preview = os.path.join(target_dir, f"{new_file_name}{ext}").replace(os.sep, '/') - metadata['preview_url'] = new_preview - - # Save updated metadata - await MetadataManager.save_metadata(new_file_path, metadata) - - # Update the scanner cache - if metadata: - await scanner.update_single_model_cache(file_path, new_file_path, metadata) - - # Update recipe files and cache if hash is available and recipe_scanner exists - if hash_value and hasattr(scanner, 'update_lora_filename_by_hash'): - recipe_scanner = await ServiceRegistry.get_recipe_scanner() - if recipe_scanner: - recipes_updated, cache_updated = await recipe_scanner.update_lora_filename_by_hash(hash_value, new_file_name) - logger.info(f"Updated {recipes_updated} recipe files and {cache_updated} cache entries for renamed model") - - return web.json_response({ - 'success': True, - 'new_file_path': new_file_path, - 'new_preview_path': config.get_preview_static_url(new_preview), - 'renamed_files': renamed_files, - 'reload_required': False - }) - - except Exception as e: - logger.error(f"Error renaming model: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - @staticmethod async def handle_save_metadata(request: web.Request, scanner) -> web.Response: """Handle saving metadata updates From c3b9c73541b96c416d9e9d8dfc7e38704b6d2b54 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 22 Sep 2025 09:09:40 +0800 Subject: [PATCH 060/110] refactor: remove ModelRouteUtils usage and implement filtering directly in services --- py/routes/base_model_routes.py | 5 ----- py/services/base_model_service.py | 15 +++++++++++++-- py/services/checkpoint_service.py | 5 ++--- py/services/embedding_service.py | 5 ++--- py/services/lora_service.py | 3 +-- py/utils/example_images_metadata.py | 1 - py/utils/routes_common.py | 2 +- tests/conftest.py | 4 ++-- 8 files changed, 21 insertions(+), 19 deletions(-) diff --git a/py/routes/base_model_routes.py b/py/routes/base_model_routes.py index 35415331..84b9f43f 100644 --- a/py/routes/base_model_routes.py +++ b/py/routes/base_model_routes.py @@ -31,7 +31,6 @@ from ..services.websocket_progress_callback import ( ) from ..utils.exif_utils import ExifUtils from ..utils.metadata_manager import MetadataManager -from ..utils.routes_common import ModelRouteUtils from .model_route_registrar import COMMON_ROUTE_DEFINITIONS, ModelRouteRegistrar from .handlers.model_handlers import ( ModelAutoOrganizeHandler, @@ -236,10 +235,6 @@ class BaseModelRoutes(ABC): """Expose handlers for subclasses or tests.""" return self._ensure_handler_mapping()[name] - @property - def utils(self) -> ModelRouteUtils: # pragma: no cover - compatibility shim - return ModelRouteUtils - def _ensure_service(self): if self.service is None: raise RuntimeError("Model service has not been attached") diff --git a/py/services/base_model_service.py b/py/services/base_model_service.py index 0b4aaf99..2c2c0ad8 100644 --- a/py/services/base_model_service.py +++ b/py/services/base_model_service.py @@ -4,7 +4,6 @@ import logging import os from ..utils.models import BaseModelMetadata -from ..utils.routes_common import ModelRouteUtils from .model_query import FilterCriteria, ModelCacheRepository, ModelFilterSet, SearchStrategy, SettingsProvider from .settings_manager import settings as default_settings @@ -197,6 +196,18 @@ class BaseModelService(ABC): """Get model root directories""" return self.scanner.get_model_roots() + def filter_civitai_data(self, data: Dict, minimal: bool = False) -> Dict: + """Filter relevant fields from CivitAI data""" + if not data: + return {} + + fields = ["id", "modelId", "name", "trainedWords"] if minimal else [ + "id", "modelId", "name", "createdAt", "updatedAt", + "publishedAt", "trainedWords", "baseModel", "description", + "model", "images", "customImages", "creator" + ] + return {k: data[k] for k in fields if k in data} + async def get_folder_tree(self, model_root: str) -> Dict: """Get hierarchical folder tree for a specific model root""" cache = await self.scanner.get_cached_data() @@ -307,7 +318,7 @@ class BaseModelService(ABC): for model in cache.raw_data: if model.get('file_path') == file_path: - return ModelRouteUtils.filter_civitai_data(model.get("civitai", {})) + return self.filter_civitai_data(model.get("civitai", {})) return None diff --git a/py/services/checkpoint_service.py b/py/services/checkpoint_service.py index ef3dc4a8..2f7b8a96 100644 --- a/py/services/checkpoint_service.py +++ b/py/services/checkpoint_service.py @@ -1,11 +1,10 @@ import os import logging -from typing import Dict, List, Optional +from typing import Dict from .base_model_service import BaseModelService from ..utils.models import CheckpointMetadata from ..config import config -from ..utils.routes_common import ModelRouteUtils logger = logging.getLogger(__name__) @@ -38,7 +37,7 @@ class CheckpointService(BaseModelService): "notes": checkpoint_data.get("notes", ""), "model_type": checkpoint_data.get("model_type", "checkpoint"), "favorite": checkpoint_data.get("favorite", False), - "civitai": ModelRouteUtils.filter_civitai_data(checkpoint_data.get("civitai", {}), minimal=True) + "civitai": self.filter_civitai_data(checkpoint_data.get("civitai", {}), minimal=True) } def find_duplicate_hashes(self) -> Dict: diff --git a/py/services/embedding_service.py b/py/services/embedding_service.py index bab067d9..46396fc5 100644 --- a/py/services/embedding_service.py +++ b/py/services/embedding_service.py @@ -1,11 +1,10 @@ import os import logging -from typing import Dict, List, Optional +from typing import Dict from .base_model_service import BaseModelService from ..utils.models import EmbeddingMetadata from ..config import config -from ..utils.routes_common import ModelRouteUtils logger = logging.getLogger(__name__) @@ -38,7 +37,7 @@ class EmbeddingService(BaseModelService): "notes": embedding_data.get("notes", ""), "model_type": embedding_data.get("model_type", "embedding"), "favorite": embedding_data.get("favorite", False), - "civitai": ModelRouteUtils.filter_civitai_data(embedding_data.get("civitai", {}), minimal=True) + "civitai": self.filter_civitai_data(embedding_data.get("civitai", {}), minimal=True) } def find_duplicate_hashes(self) -> Dict: diff --git a/py/services/lora_service.py b/py/services/lora_service.py index d1e522a3..551c4d3c 100644 --- a/py/services/lora_service.py +++ b/py/services/lora_service.py @@ -5,7 +5,6 @@ from typing import Dict, List, Optional from .base_model_service import BaseModelService from ..utils.models import LoraMetadata from ..config import config -from ..utils.routes_common import ModelRouteUtils logger = logging.getLogger(__name__) @@ -38,7 +37,7 @@ class LoraService(BaseModelService): "usage_tips": lora_data.get("usage_tips", ""), "notes": lora_data.get("notes", ""), "favorite": lora_data.get("favorite", False), - "civitai": ModelRouteUtils.filter_civitai_data(lora_data.get("civitai", {}), minimal=True) + "civitai": self.filter_civitai_data(lora_data.get("civitai", {}), minimal=True) } async def _apply_specific_filters(self, data: List[Dict], **kwargs) -> List[Dict]: diff --git a/py/utils/example_images_metadata.py b/py/utils/example_images_metadata.py index 66db05a3..8820b49b 100644 --- a/py/utils/example_images_metadata.py +++ b/py/utils/example_images_metadata.py @@ -69,7 +69,6 @@ class MetadataUpdater: # Track that we're refreshing this model download_progress['refreshed_models'].add(model_hash) - # Use ModelRouteUtils to refresh metadata async def update_cache_func(old_path, new_path, metadata): return await scanner.update_single_model_cache(old_path, new_path, metadata) diff --git a/py/utils/routes_common.py b/py/utils/routes_common.py index 84e2fc9d..642bfcad 100644 --- a/py/utils/routes_common.py +++ b/py/utils/routes_common.py @@ -18,7 +18,7 @@ from ..services.settings_manager import settings logger = logging.getLogger(__name__) - +# TODO: retire this class class ModelRouteUtils: """Shared utilities for model routes (LoRAs, Checkpoints, etc.)""" diff --git a/tests/conftest.py b/tests/conftest.py index 006a1adc..58263c8a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -81,7 +81,7 @@ class MockHashIndex: class MockCache: - """Cache object with the attributes consumed by ``ModelRouteUtils``.""" + """Cache object with the attributes.""" def __init__(self, items: Optional[Sequence[Dict[str, Any]]] = None): self.raw_data: List[Dict[str, Any]] = list(items or []) @@ -89,7 +89,7 @@ class MockCache: async def resort(self) -> None: self.resort_calls += 1 - # ``ModelRouteUtils`` expects the coroutine interface but does not + # expects the coroutine interface but does not # rely on the return value. From b92e7aa446392eaa95270ab37c5eb18517384c29 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Mon, 22 Sep 2025 12:15:12 +0800 Subject: [PATCH 061/110] chore(routes): dedupe os import --- py/routes/base_recipe_routes.py | 109 +++++++++++++++++ py/routes/recipe_route_registrar.py | 64 ++++++++++ py/routes/recipe_routes.py | 181 +++++++++------------------- 3 files changed, 227 insertions(+), 127 deletions(-) create mode 100644 py/routes/base_recipe_routes.py create mode 100644 py/routes/recipe_route_registrar.py diff --git a/py/routes/base_recipe_routes.py b/py/routes/base_recipe_routes.py new file mode 100644 index 00000000..e2b726da --- /dev/null +++ b/py/routes/base_recipe_routes.py @@ -0,0 +1,109 @@ +"""Base infrastructure shared across recipe routes.""" +from __future__ import annotations + +import logging +from typing import Callable, Mapping + +import jinja2 +from aiohttp import web + +from ..config import config +from ..services.server_i18n import server_i18n +from ..services.service_registry import ServiceRegistry +from ..services.settings_manager import settings +from .recipe_route_registrar import ROUTE_DEFINITIONS + +logger = logging.getLogger(__name__) + + +class BaseRecipeRoutes: + """Common dependency and startup wiring for recipe routes.""" + + _HANDLER_NAMES: tuple[str, ...] = tuple( + definition.handler_name for definition in ROUTE_DEFINITIONS + ) + + def __init__(self) -> None: + self.recipe_scanner = None + self.lora_scanner = None + self.civitai_client = None + self.settings = settings + self.server_i18n = server_i18n + self.template_env = jinja2.Environment( + loader=jinja2.FileSystemLoader(config.templates_path), + autoescape=True, + ) + + self._i18n_registered = False + self._startup_hooks_registered = False + self._handler_mapping: dict[str, Callable] | None = None + + async def attach_dependencies(self, app: web.Application | None = None) -> None: + """Resolve shared services from the registry.""" + + await self._ensure_services() + self._ensure_i18n_filter() + + async def ensure_dependencies_ready(self) -> None: + """Ensure dependencies are available for request handlers.""" + + if self.recipe_scanner is None or self.civitai_client is None: + await self.attach_dependencies() + + def register_startup_hooks(self, app: web.Application) -> None: + """Register startup hooks once for dependency wiring.""" + + if self._startup_hooks_registered: + return + + app.on_startup.append(self.attach_dependencies) + app.on_startup.append(self.prewarm_cache) + self._startup_hooks_registered = True + + async def prewarm_cache(self, app: web.Application | None = None) -> None: + """Pre-load recipe and LoRA caches on startup.""" + + try: + await self.attach_dependencies(app) + + if self.lora_scanner is not None: + await self.lora_scanner.get_cached_data() + hash_index = getattr(self.lora_scanner, "_hash_index", None) + if hash_index is not None and hasattr(hash_index, "_hash_to_path"): + _ = len(hash_index._hash_to_path) + + if self.recipe_scanner is not None: + await self.recipe_scanner.get_cached_data(force_refresh=True) + except Exception as exc: + logger.error("Error pre-warming recipe cache: %s", exc, exc_info=True) + + def to_route_mapping(self) -> Mapping[str, Callable]: + """Return a mapping of handler name to coroutine for registrar binding.""" + + if self._handler_mapping is None: + owner = self.get_handler_owner() + self._handler_mapping = { + name: getattr(owner, name) for name in self._HANDLER_NAMES + } + return self._handler_mapping + + # Internal helpers ------------------------------------------------- + + async def _ensure_services(self) -> None: + if self.recipe_scanner is None: + self.recipe_scanner = await ServiceRegistry.get_recipe_scanner() + self.lora_scanner = getattr(self.recipe_scanner, "_lora_scanner", None) + + if self.civitai_client is None: + self.civitai_client = await ServiceRegistry.get_civitai_client() + + def _ensure_i18n_filter(self) -> None: + if not self._i18n_registered: + self.template_env.filters["t"] = self.server_i18n.create_template_filter() + self._i18n_registered = True + + def get_handler_owner(self): + """Return the object supplying bound handler coroutines.""" + + return self + diff --git a/py/routes/recipe_route_registrar.py b/py/routes/recipe_route_registrar.py new file mode 100644 index 00000000..471edf19 --- /dev/null +++ b/py/routes/recipe_route_registrar.py @@ -0,0 +1,64 @@ +"""Route registrar for recipe endpoints.""" +from __future__ import annotations + +from dataclasses import dataclass +from typing import Callable, Mapping + +from aiohttp import web + + +@dataclass(frozen=True) +class RouteDefinition: + """Declarative definition for a recipe HTTP route.""" + + method: str + path: str + handler_name: str + + +ROUTE_DEFINITIONS: tuple[RouteDefinition, ...] = ( + RouteDefinition("GET", "/loras/recipes", "render_page"), + RouteDefinition("GET", "/api/lm/recipes", "list_recipes"), + RouteDefinition("GET", "/api/lm/recipe/{recipe_id}", "get_recipe"), + RouteDefinition("POST", "/api/lm/recipes/analyze-image", "analyze_uploaded_image"), + RouteDefinition("POST", "/api/lm/recipes/analyze-local-image", "analyze_local_image"), + RouteDefinition("POST", "/api/lm/recipes/save", "save_recipe"), + RouteDefinition("DELETE", "/api/lm/recipe/{recipe_id}", "delete_recipe"), + RouteDefinition("GET", "/api/lm/recipes/top-tags", "get_top_tags"), + RouteDefinition("GET", "/api/lm/recipes/base-models", "get_base_models"), + RouteDefinition("GET", "/api/lm/recipe/{recipe_id}/share", "share_recipe"), + RouteDefinition("GET", "/api/lm/recipe/{recipe_id}/share/download", "download_shared_recipe"), + RouteDefinition("GET", "/api/lm/recipe/{recipe_id}/syntax", "get_recipe_syntax"), + RouteDefinition("PUT", "/api/lm/recipe/{recipe_id}/update", "update_recipe"), + RouteDefinition("POST", "/api/lm/recipe/lora/reconnect", "reconnect_lora"), + RouteDefinition("GET", "/api/lm/recipes/find-duplicates", "find_duplicates"), + RouteDefinition("POST", "/api/lm/recipes/bulk-delete", "bulk_delete"), + RouteDefinition("POST", "/api/lm/recipes/save-from-widget", "save_recipe_from_widget"), + RouteDefinition("GET", "/api/lm/recipes/for-lora", "get_recipes_for_lora"), + RouteDefinition("GET", "/api/lm/recipes/scan", "scan_recipes"), +) + + +class RecipeRouteRegistrar: + """Bind declarative recipe definitions to an aiohttp router.""" + + _METHOD_MAP = { + "GET": "add_get", + "POST": "add_post", + "PUT": "add_put", + "DELETE": "add_delete", + } + + def __init__(self, app: web.Application) -> None: + self._app = app + + def register_routes(self, handler_lookup: Mapping[str, Callable[[web.Request], object]]) -> None: + for definition in ROUTE_DEFINITIONS: + handler = handler_lookup[definition.handler_name] + self._bind_route(definition.method, definition.path, handler) + + def _bind_route(self, method: str, path: str, handler: Callable) -> None: + add_method_name = self._METHOD_MAP[method.upper()] + add_method = getattr(self._app.router, add_method_name) + add_method(path, handler) + diff --git a/py/routes/recipe_routes.py b/py/routes/recipe_routes.py index 21214d99..dcd0751a 100644 --- a/py/routes/recipe_routes.py +++ b/py/routes/recipe_routes.py @@ -1,7 +1,6 @@ import os import time import base64 -import jinja2 import numpy as np from PIL import Image import io @@ -12,20 +11,18 @@ import tempfile import json import asyncio import sys + +from .base_recipe_routes import BaseRecipeRoutes +from .recipe_route_registrar import RecipeRouteRegistrar from ..utils.exif_utils import ExifUtils from ..recipes import RecipeParserFactory from ..utils.constants import CARD_PREVIEW_WIDTH - -from ..services.settings_manager import settings -from ..services.server_i18n import server_i18n from ..config import config +from ..services.downloader import get_downloader # Check if running in standalone mode standalone_mode = os.environ.get("HF_HUB_DISABLE_TELEMETRY", "0") == "0" -from ..services.service_registry import ServiceRegistry # Add ServiceRegistry import -from ..services.downloader import get_downloader - # Only import MetadataRegistry in non-standalone mode if not standalone_mode: # Import metadata_collector functions and classes conditionally @@ -35,111 +32,35 @@ if not standalone_mode: logger = logging.getLogger(__name__) -class RecipeRoutes: - """API route handlers for Recipe management""" - def __init__(self): - # Initialize service references as None, will be set during async init - self.recipe_scanner = None - self.civitai_client = None - self.template_env = jinja2.Environment( - loader=jinja2.FileSystemLoader(config.templates_path), - autoescape=True - ) - - # Pre-warm the cache - self._init_cache_task = None - - async def init_services(self): - """Initialize services from ServiceRegistry""" - self.recipe_scanner = await ServiceRegistry.get_recipe_scanner() - self.civitai_client = await ServiceRegistry.get_civitai_client() +class RecipeRoutes(BaseRecipeRoutes): + """API route handlers for Recipe management.""" @classmethod def setup_routes(cls, app: web.Application): - """Register API routes""" + """Register API routes using the declarative registrar.""" + routes = cls() - app.router.add_get('/loras/recipes', routes.handle_recipes_page) + registrar = RecipeRouteRegistrar(app) + registrar.register_routes(routes.to_route_mapping()) + routes.register_startup_hooks(app) - app.router.add_get('/api/lm/recipes', routes.get_recipes) - app.router.add_get('/api/lm/recipe/{recipe_id}', routes.get_recipe_detail) - app.router.add_post('/api/lm/recipes/analyze-image', routes.analyze_recipe_image) - app.router.add_post('/api/lm/recipes/analyze-local-image', routes.analyze_local_image) - app.router.add_post('/api/lm/recipes/save', routes.save_recipe) - app.router.add_delete('/api/lm/recipe/{recipe_id}', routes.delete_recipe) - - # Add new filter-related endpoints - app.router.add_get('/api/lm/recipes/top-tags', routes.get_top_tags) - app.router.add_get('/api/lm/recipes/base-models', routes.get_base_models) - - # Add new sharing endpoints - app.router.add_get('/api/lm/recipe/{recipe_id}/share', routes.share_recipe) - app.router.add_get('/api/lm/recipe/{recipe_id}/share/download', routes.download_shared_recipe) - - # Add new endpoint for getting recipe syntax - app.router.add_get('/api/lm/recipe/{recipe_id}/syntax', routes.get_recipe_syntax) - - # Add new endpoint for updating recipe metadata (name, tags and source_path) - app.router.add_put('/api/lm/recipe/{recipe_id}/update', routes.update_recipe) - - # Add new endpoint for reconnecting deleted LoRAs - app.router.add_post('/api/lm/recipe/lora/reconnect', routes.reconnect_lora) - - # Add new endpoint for finding duplicate recipes - app.router.add_get('/api/lm/recipes/find-duplicates', routes.find_duplicates) - - # Add new endpoint for bulk deletion of recipes - app.router.add_post('/api/lm/recipes/bulk-delete', routes.bulk_delete) - - # Start cache initialization - app.on_startup.append(routes._init_cache) - - app.router.add_post('/api/lm/recipes/save-from-widget', routes.save_recipe_from_widget) - - # Add route to get recipes for a specific Lora - app.router.add_get('/api/lm/recipes/for-lora', routes.get_recipes_for_lora) - - # Add new endpoint for scanning and rebuilding the recipe cache - app.router.add_get('/api/lm/recipes/scan', routes.scan_recipes) - - async def _init_cache(self, app): - """Initialize cache on startup""" + async def render_page(self, request: web.Request) -> web.Response: + """Handle GET /loras/recipes request.""" try: - # Initialize services first - await self.init_services() - - # Now that services are initialized, get the lora scanner - lora_scanner = self.recipe_scanner._lora_scanner - - # Get lora cache to ensure it's initialized - lora_cache = await lora_scanner.get_cached_data() - - # Verify hash index is built - if hasattr(lora_scanner, '_hash_index'): - hash_index_size = len(lora_scanner._hash_index._hash_to_path) if hasattr(lora_scanner._hash_index, '_hash_to_path') else 0 - - # Now that lora scanner is initialized, initialize recipe cache - await self.recipe_scanner.get_cached_data(force_refresh=True) - except Exception as e: - logger.error(f"Error pre-warming recipe cache: {e}", exc_info=True) + await self.ensure_dependencies_ready() - async def handle_recipes_page(self, request: web.Request) -> web.Response: - """Handle GET /loras/recipes request""" - try: - # Ensure services are initialized - await self.init_services() - # 获取用户语言设置 - user_language = settings.get('language', 'en') - + user_language = self.settings.get('language', 'en') + # 设置服务端i18n语言 - server_i18n.set_locale(user_language) - + self.server_i18n.set_locale(user_language) + # 为模板环境添加i18n过滤器 if not hasattr(self.template_env, '_i18n_filter_added'): - self.template_env.filters['t'] = server_i18n.create_template_filter() + self._ensure_i18n_filter() self.template_env._i18n_filter_added = True - + # Skip initialization check and directly try to get cached data try: # Recipe scanner will initialize cache if needed @@ -148,10 +69,10 @@ class RecipeRoutes: rendered = template.render( recipes=[], # Frontend will load recipes via API is_initializing=False, - settings=settings, + settings=self.settings, request=request, # 添加服务端翻译函数 - t=server_i18n.get_translation, + t=self.server_i18n.get_translation, ) except Exception as cache_error: logger.error(f"Error loading recipe cache data: {cache_error}") @@ -159,10 +80,10 @@ class RecipeRoutes: template = self.template_env.get_template('recipes.html') rendered = template.render( is_initializing=True, - settings=settings, + settings=self.settings, request=request, # 添加服务端翻译函数 - t=server_i18n.get_translation, + t=self.server_i18n.get_translation, ) logger.info("Recipe cache error, returning initialization page") @@ -178,11 +99,11 @@ class RecipeRoutes: status=500 ) - async def get_recipes(self, request: web.Request) -> web.Response: - """API endpoint for getting paginated recipes""" + async def list_recipes(self, request: web.Request) -> web.Response: + """API endpoint for getting paginated recipes.""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() # Get query parameters with defaults page = int(request.query.get('page', '1')) @@ -250,11 +171,11 @@ class RecipeRoutes: logger.error(f"Error retrieving recipes: {e}", exc_info=True) return web.json_response({"error": str(e)}, status=500) - async def get_recipe_detail(self, request: web.Request) -> web.Response: - """Get detailed information about a specific recipe""" + async def get_recipe(self, request: web.Request) -> web.Response: + """Get detailed information about a specific recipe.""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() recipe_id = request.match_info['recipe_id'] @@ -305,12 +226,12 @@ class RecipeRoutes: from datetime import datetime return datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S') - async def analyze_recipe_image(self, request: web.Request) -> web.Response: - """Analyze an uploaded image or URL for recipe metadata""" + async def analyze_uploaded_image(self, request: web.Request) -> web.Response: + """Analyze an uploaded image or URL for recipe metadata.""" temp_path = None try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() # Check if request contains multipart data (image) or JSON data (url) content_type = request.headers.get('Content-Type', '') @@ -480,7 +401,7 @@ class RecipeRoutes: """Analyze a local image file for recipe metadata""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() # Get JSON data from request data = await request.json() @@ -573,7 +494,7 @@ class RecipeRoutes: """Save a recipe to the recipes folder""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() reader = await request.multipart() @@ -779,7 +700,7 @@ class RecipeRoutes: """Delete a recipe by ID""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() recipe_id = request.match_info['recipe_id'] @@ -829,7 +750,7 @@ class RecipeRoutes: """Get top tags used in recipes""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() # Get limit parameter with default limit = int(request.query.get('limit', '20')) @@ -864,7 +785,7 @@ class RecipeRoutes: """Get base models used in recipes""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() # Get all recipes from cache cache = await self.recipe_scanner.get_cached_data() @@ -895,7 +816,7 @@ class RecipeRoutes: """Process a recipe image for sharing by adding metadata to EXIF""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() recipe_id = request.match_info['recipe_id'] @@ -957,7 +878,7 @@ class RecipeRoutes: """Serve a processed recipe image for download""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() recipe_id = request.match_info['recipe_id'] @@ -1016,7 +937,7 @@ class RecipeRoutes: """Save a recipe from the LoRAs widget""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() # Get metadata using the metadata collector instead of workflow parsing raw_metadata = get_metadata() @@ -1216,7 +1137,7 @@ class RecipeRoutes: """Generate recipe syntax for LoRAs in the recipe, looking up proper file names using hash_index""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() recipe_id = request.match_info['recipe_id'] @@ -1299,7 +1220,7 @@ class RecipeRoutes: """Update recipe metadata (name and tags)""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() recipe_id = request.match_info['recipe_id'] data = await request.json() @@ -1329,7 +1250,7 @@ class RecipeRoutes: """Reconnect a deleted LoRA in a recipe to a local LoRA file""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() # Parse request data data = await request.json() @@ -1438,7 +1359,7 @@ class RecipeRoutes: """Get recipes that use a specific Lora""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() lora_hash = request.query.get('hash') @@ -1487,7 +1408,7 @@ class RecipeRoutes: """API endpoint for scanning and rebuilding the recipe cache""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() # Force refresh the recipe cache logger.info("Manually triggering recipe cache rebuild") @@ -1508,7 +1429,7 @@ class RecipeRoutes: """Find all duplicate recipes based on fingerprints""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() # Get all duplicate recipes duplicate_groups = await self.recipe_scanner.find_all_duplicate_recipes() @@ -1566,7 +1487,7 @@ class RecipeRoutes: """Delete multiple recipes by ID""" try: # Ensure services are initialized - await self.init_services() + await self.ensure_dependencies_ready() # Parse request data data = await request.json() @@ -1650,3 +1571,9 @@ class RecipeRoutes: 'success': False, 'error': str(e) }, status=500) + + # Legacy method aliases retained for compatibility with existing imports. + handle_recipes_page = render_page + get_recipes = list_recipes + get_recipe_detail = get_recipe + analyze_recipe_image = analyze_uploaded_image From 3220cfb79c1a6fb01d4a7131339c10b565d1f85a Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Mon, 22 Sep 2025 12:41:37 +0800 Subject: [PATCH 062/110] test(recipe-routes): add scaffolding baseline --- docs/architecture/recipe_routes.md | 50 ++++ py/routes/recipe_routes.py | 5 - tests/routes/test_recipe_route_scaffolding.py | 229 ++++++++++++++++++ 3 files changed, 279 insertions(+), 5 deletions(-) create mode 100644 docs/architecture/recipe_routes.md create mode 100644 tests/routes/test_recipe_route_scaffolding.py diff --git a/docs/architecture/recipe_routes.md b/docs/architecture/recipe_routes.md new file mode 100644 index 00000000..28684fad --- /dev/null +++ b/docs/architecture/recipe_routes.md @@ -0,0 +1,50 @@ +# Recipe route scaffolding + +The recipe HTTP stack is being migrated to mirror the shared model routing +architecture. The first phase extracts the registrar/controller scaffolding so +future handler sets can plug into a stable surface area. The stack now mirrors +the same separation of concerns described in +`docs/architecture/model_routes.md`: + +```mermaid +graph TD + subgraph HTTP + A[RecipeRouteRegistrar] -->|binds| B[BaseRecipeRoutes handler owner] + end + subgraph Application + B --> C[Recipe handler set] + C --> D[Async handlers] + D --> E[Services / scanners] + end +``` + +## Responsibilities + +| Layer | Module(s) | Responsibility | +| --- | --- | --- | +| Registrar | `py/routes/recipe_route_registrar.py` | Declarative list of every recipe endpoint and helper that binds them to an `aiohttp` application. | +| Base controller | `py/routes/base_recipe_routes.py` | Lazily resolves shared services, registers the server-side i18n filter exactly once, pre-warms caches on startup, and exposes a `{handler_name: coroutine}` mapping used by the registrar. | +| Handler set (upcoming) | `py/routes/handlers/recipe_handlers.py` (planned) | Will group HTTP handlers by concern (page rendering, listings, mutations, queries, sharing) and surface them to `BaseRecipeRoutes.get_handler_owner()`. | + +`RecipeRoutes` subclasses the base controller to keep compatibility with the +existing monolithic handlers. Once the handler set is extracted the subclass +will simply provide the concrete owner returned by `get_handler_owner()`. + +## High-level test baseline + +The new smoke suite in `tests/routes/test_recipe_route_scaffolding.py` +guarantees the registrar/controller contract remains intact: + +* `BaseRecipeRoutes.attach_dependencies` resolves registry services only once + and protects the i18n filter from duplicate registration. +* Startup hooks are appended exactly once so cache pre-warming and dependency + resolution run during application boot. +* `BaseRecipeRoutes.to_route_mapping()` uses the handler owner as the source of + callables, enabling the upcoming handler set without touching the registrar. +* `RecipeRouteRegistrar` binds every declarative route to the aiohttp router. +* `RecipeRoutes.setup_routes` wires the registrar and startup hooks together so + future refactors can swap in the handler set without editing callers. + +These guardrails mirror the expectations in the model route architecture and +provide confidence that future refactors can focus on handlers and use cases +without breaking HTTP wiring. diff --git a/py/routes/recipe_routes.py b/py/routes/recipe_routes.py index dcd0751a..55208552 100644 --- a/py/routes/recipe_routes.py +++ b/py/routes/recipe_routes.py @@ -56,11 +56,6 @@ class RecipeRoutes(BaseRecipeRoutes): # 设置服务端i18n语言 self.server_i18n.set_locale(user_language) - # 为模板环境添加i18n过滤器 - if not hasattr(self.template_env, '_i18n_filter_added'): - self._ensure_i18n_filter() - self.template_env._i18n_filter_added = True - # Skip initialization check and directly try to get cached data try: # Recipe scanner will initialize cache if needed diff --git a/tests/routes/test_recipe_route_scaffolding.py b/tests/routes/test_recipe_route_scaffolding.py new file mode 100644 index 00000000..1f0e723d --- /dev/null +++ b/tests/routes/test_recipe_route_scaffolding.py @@ -0,0 +1,229 @@ +"""Smoke tests for the recipe routing scaffolding. + +The cases keep the registrar/controller contract aligned with +``docs/architecture/recipe_routes.md`` so future refactors can focus on handler +logic. +""" + +from __future__ import annotations + +import asyncio +import importlib.util +import sys +import types +from collections import Counter +from pathlib import Path +from typing import Any, Awaitable, Callable, Dict + +import pytest +from aiohttp import web + + +REPO_ROOT = Path(__file__).resolve().parents[2] +PY_PACKAGE_PATH = REPO_ROOT / "py" + +spec = importlib.util.spec_from_file_location( + "py_local", + PY_PACKAGE_PATH / "__init__.py", + submodule_search_locations=[str(PY_PACKAGE_PATH)], +) +py_local = importlib.util.module_from_spec(spec) +assert spec.loader is not None +spec.loader.exec_module(py_local) +sys.modules.setdefault("py_local", py_local) + +base_routes_module = importlib.import_module("py_local.routes.base_recipe_routes") +recipe_routes_module = importlib.import_module("py_local.routes.recipe_routes") +registrar_module = importlib.import_module("py_local.routes.recipe_route_registrar") + + +@pytest.fixture(autouse=True) +def reset_service_registry(monkeypatch: pytest.MonkeyPatch): + """Ensure each test starts from a clean registry state.""" + + services_module = importlib.import_module("py_local.services.service_registry") + registry = services_module.ServiceRegistry + previous_services = dict(registry._services) + previous_locks = dict(registry._locks) + registry._services.clear() + registry._locks.clear() + try: + yield + finally: + registry._services = previous_services + registry._locks = previous_locks + + +def _make_stub_scanner(): + class _StubScanner: + def __init__(self): + self._cache = types.SimpleNamespace() + + async def _lora_get_cached_data(): # pragma: no cover - smoke hook + return None + + self._lora_scanner = types.SimpleNamespace( + get_cached_data=_lora_get_cached_data, + _hash_index=types.SimpleNamespace(_hash_to_path={}), + ) + + async def get_cached_data(self, force_refresh: bool = False): + return self._cache + + return _StubScanner() + + +def test_attach_dependencies_resolves_services_once(monkeypatch: pytest.MonkeyPatch): + base_module = base_routes_module + services_module = importlib.import_module("py_local.services.service_registry") + registry = services_module.ServiceRegistry + server_i18n = importlib.import_module("py_local.services.server_i18n").server_i18n + + scanner = _make_stub_scanner() + civitai_client = object() + filter_calls = Counter() + + async def fake_get_recipe_scanner(): + return scanner + + async def fake_get_civitai_client(): + return civitai_client + + def fake_create_filter(): + filter_calls["create_filter"] += 1 + return object() + + monkeypatch.setattr(registry, "get_recipe_scanner", fake_get_recipe_scanner) + monkeypatch.setattr(registry, "get_civitai_client", fake_get_civitai_client) + monkeypatch.setattr(server_i18n, "create_template_filter", fake_create_filter) + + async def scenario(): + routes = base_module.BaseRecipeRoutes() + + await routes.attach_dependencies() + await routes.attach_dependencies() # idempotent + + assert routes.recipe_scanner is scanner + assert routes.lora_scanner is scanner._lora_scanner + assert routes.civitai_client is civitai_client + assert routes.template_env.filters["t"] is not None + assert filter_calls["create_filter"] == 1 + + asyncio.run(scenario()) + + +def test_register_startup_hooks_appends_once(): + routes = base_routes_module.BaseRecipeRoutes() + + app = web.Application() + routes.register_startup_hooks(app) + routes.register_startup_hooks(app) + + startup_bound_to_routes = [ + callback for callback in app.on_startup if getattr(callback, "__self__", None) is routes + ] + + assert routes.attach_dependencies in startup_bound_to_routes + assert routes.prewarm_cache in startup_bound_to_routes + assert len(startup_bound_to_routes) == 2 + + +def test_to_route_mapping_uses_handler_owner(monkeypatch: pytest.MonkeyPatch): + class DummyOwner: + async def render_page(self, request): + return web.Response(text="ok") + + async def list_recipes(self, request): # pragma: no cover - invoked via mapping + return web.json_response({}) + + class DummyRoutes(base_routes_module.BaseRecipeRoutes): + def get_handler_owner(self): # noqa: D401 - simple override for test + return DummyOwner() + + monkeypatch.setattr( + base_routes_module.BaseRecipeRoutes, + "_HANDLER_NAMES", + ("render_page", "list_recipes"), + ) + + routes = DummyRoutes() + mapping = routes.to_route_mapping() + + assert set(mapping.keys()) == {"render_page", "list_recipes"} + assert asyncio.iscoroutinefunction(mapping["render_page"]) + # Cached mapping reused on subsequent calls + assert routes.to_route_mapping() is mapping + + +def test_recipe_route_registrar_binds_every_route(): + class FakeRouter: + def __init__(self): + self.calls: list[tuple[str, str, Callable[..., Awaitable[Any]]]] = [] + + def add_get(self, path, handler): + self.calls.append(("GET", path, handler)) + + def add_post(self, path, handler): + self.calls.append(("POST", path, handler)) + + def add_put(self, path, handler): + self.calls.append(("PUT", path, handler)) + + def add_delete(self, path, handler): + self.calls.append(("DELETE", path, handler)) + + class FakeApp: + def __init__(self): + self.router = FakeRouter() + + app = FakeApp() + registrar = registrar_module.RecipeRouteRegistrar(app) + + handler_mapping = { + definition.handler_name: object() + for definition in registrar_module.ROUTE_DEFINITIONS + } + + registrar.register_routes(handler_mapping) + + assert { + (method, path) + for method, path, _ in app.router.calls + } == {(d.method, d.path) for d in registrar_module.ROUTE_DEFINITIONS} + + +def test_recipe_routes_setup_routes_uses_registrar(monkeypatch: pytest.MonkeyPatch): + registered_mappings: list[Dict[str, Callable[..., Awaitable[Any]]]] = [] + + class DummyRegistrar: + def __init__(self, app): + self.app = app + + def register_routes(self, mapping): + registered_mappings.append(mapping) + + monkeypatch.setattr(recipe_routes_module, "RecipeRouteRegistrar", DummyRegistrar) + + expected_mapping = {name: object() for name in ("render_page", "list_recipes")} + + def fake_to_route_mapping(self): + return expected_mapping + + monkeypatch.setattr(base_routes_module.BaseRecipeRoutes, "to_route_mapping", fake_to_route_mapping) + monkeypatch.setattr( + base_routes_module.BaseRecipeRoutes, + "_HANDLER_NAMES", + tuple(expected_mapping.keys()), + ) + + app = web.Application() + recipe_routes_module.RecipeRoutes.setup_routes(app) + + assert registered_mappings == [expected_mapping] + recipe_callbacks = { + cb + for cb in app.on_startup + if isinstance(getattr(cb, "__self__", None), recipe_routes_module.RecipeRoutes) + } + assert {type(cb.__self__) for cb in recipe_callbacks} == {recipe_routes_module.RecipeRoutes} + assert {cb.__name__ for cb in recipe_callbacks} == {"attach_dependencies", "prewarm_cache"} From d033a374dd72fe81821e7b9d520e8a53e7c5c302 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Mon, 22 Sep 2025 12:57:37 +0800 Subject: [PATCH 063/110] refactor(routes): split recipe handlers into dedicated classes --- py/routes/base_recipe_routes.py | 73 +- py/routes/handlers/recipe_handlers.py | 1347 ++++++++++++++ py/routes/recipe_routes.py | 1561 +---------------- tests/routes/test_recipe_route_scaffolding.py | 35 +- 4 files changed, 1440 insertions(+), 1576 deletions(-) create mode 100644 py/routes/handlers/recipe_handlers.py diff --git a/py/routes/base_recipe_routes.py b/py/routes/base_recipe_routes.py index e2b726da..59d4e7ec 100644 --- a/py/routes/base_recipe_routes.py +++ b/py/routes/base_recipe_routes.py @@ -11,6 +11,15 @@ from ..config import config from ..services.server_i18n import server_i18n from ..services.service_registry import ServiceRegistry from ..services.settings_manager import settings +from .handlers.recipe_handlers import ( + RecipeAnalysisHandler, + RecipeHandlerSet, + RecipeListingHandler, + RecipeManagementHandler, + RecipePageView, + RecipeQueryHandler, + RecipeSharingHandler, +) from .recipe_route_registrar import ROUTE_DEFINITIONS logger = logging.getLogger(__name__) @@ -23,6 +32,8 @@ class BaseRecipeRoutes: definition.handler_name for definition in ROUTE_DEFINITIONS ) + template_name: str = "recipes.html" + def __init__(self) -> None: self.recipe_scanner = None self.lora_scanner = None @@ -36,6 +47,7 @@ class BaseRecipeRoutes: self._i18n_registered = False self._startup_hooks_registered = False + self._handler_set: RecipeHandlerSet | None = None self._handler_mapping: dict[str, Callable] | None = None async def attach_dependencies(self, app: web.Application | None = None) -> None: @@ -81,10 +93,9 @@ class BaseRecipeRoutes: """Return a mapping of handler name to coroutine for registrar binding.""" if self._handler_mapping is None: - owner = self.get_handler_owner() - self._handler_mapping = { - name: getattr(owner, name) for name in self._HANDLER_NAMES - } + handler_set = self._create_handler_set() + self._handler_set = handler_set + self._handler_mapping = handler_set.to_route_mapping() return self._handler_mapping # Internal helpers ------------------------------------------------- @@ -105,5 +116,57 @@ class BaseRecipeRoutes: def get_handler_owner(self): """Return the object supplying bound handler coroutines.""" - return self + if self._handler_set is None: + self._handler_set = self._create_handler_set() + return self._handler_set + + def _create_handler_set(self) -> RecipeHandlerSet: + recipe_scanner_getter = lambda: self.recipe_scanner + civitai_client_getter = lambda: self.civitai_client + + page_view = RecipePageView( + ensure_dependencies_ready=self.ensure_dependencies_ready, + settings_service=self.settings, + server_i18n=self.server_i18n, + template_env=self.template_env, + template_name=self.template_name, + recipe_scanner_getter=recipe_scanner_getter, + logger=logger, + ) + listing = RecipeListingHandler( + ensure_dependencies_ready=self.ensure_dependencies_ready, + recipe_scanner_getter=recipe_scanner_getter, + logger=logger, + ) + query = RecipeQueryHandler( + ensure_dependencies_ready=self.ensure_dependencies_ready, + recipe_scanner_getter=recipe_scanner_getter, + format_recipe_file_url=listing.format_recipe_file_url, + logger=logger, + ) + management = RecipeManagementHandler( + ensure_dependencies_ready=self.ensure_dependencies_ready, + recipe_scanner_getter=recipe_scanner_getter, + logger=logger, + ) + analysis = RecipeAnalysisHandler( + ensure_dependencies_ready=self.ensure_dependencies_ready, + recipe_scanner_getter=recipe_scanner_getter, + civitai_client_getter=civitai_client_getter, + logger=logger, + ) + sharing = RecipeSharingHandler( + ensure_dependencies_ready=self.ensure_dependencies_ready, + recipe_scanner_getter=recipe_scanner_getter, + logger=logger, + ) + + return RecipeHandlerSet( + page_view=page_view, + listing=listing, + query=query, + management=management, + analysis=analysis, + sharing=sharing, + ) diff --git a/py/routes/handlers/recipe_handlers.py b/py/routes/handlers/recipe_handlers.py new file mode 100644 index 00000000..8d8f96bf --- /dev/null +++ b/py/routes/handlers/recipe_handlers.py @@ -0,0 +1,1347 @@ +"""Dedicated handler objects for recipe-related routes.""" +from __future__ import annotations + +import asyncio +import base64 +import io +import json +import logging +import os +import tempfile +import time +from dataclasses import dataclass +from typing import Any, Awaitable, Callable, Dict, Mapping, Optional + +import numpy as np +from aiohttp import web +from PIL import Image + +from ...config import config +from ...recipes import RecipeParserFactory +from ...services.downloader import get_downloader +from ...services.server_i18n import server_i18n as default_server_i18n +from ...services.settings_manager import SettingsManager +from ...utils.constants import CARD_PREVIEW_WIDTH +from ...utils.exif_utils import ExifUtils + +# Check if running in standalone mode +standalone_mode = os.environ.get("HF_HUB_DISABLE_TELEMETRY", "0") == "0" + +if not standalone_mode: + from ...metadata_collector import get_metadata + from ...metadata_collector.metadata_processor import MetadataProcessor + from ...metadata_collector.metadata_registry import MetadataRegistry +else: # pragma: no cover - optional dependency path + get_metadata = None # type: ignore[assignment] + MetadataProcessor = None # type: ignore[assignment] + MetadataRegistry = None # type: ignore[assignment] + +Logger = logging.Logger +EnsureDependenciesCallable = Callable[[], Awaitable[None]] +RecipeScannerGetter = Callable[[], Any] +CivitaiClientGetter = Callable[[], Any] + + +@dataclass(frozen=True) +class RecipeHandlerSet: + """Group of handlers providing recipe route implementations.""" + + page_view: "RecipePageView" + listing: "RecipeListingHandler" + query: "RecipeQueryHandler" + management: "RecipeManagementHandler" + analysis: "RecipeAnalysisHandler" + sharing: "RecipeSharingHandler" + + def to_route_mapping(self) -> Mapping[str, Callable[[web.Request], Awaitable[web.StreamResponse]]]: + """Expose handler coroutines keyed by registrar handler names.""" + + return { + "render_page": self.page_view.render_page, + "list_recipes": self.listing.list_recipes, + "get_recipe": self.listing.get_recipe, + "analyze_uploaded_image": self.analysis.analyze_uploaded_image, + "analyze_local_image": self.analysis.analyze_local_image, + "save_recipe": self.management.save_recipe, + "delete_recipe": self.management.delete_recipe, + "get_top_tags": self.query.get_top_tags, + "get_base_models": self.query.get_base_models, + "share_recipe": self.sharing.share_recipe, + "download_shared_recipe": self.sharing.download_shared_recipe, + "get_recipe_syntax": self.query.get_recipe_syntax, + "update_recipe": self.management.update_recipe, + "reconnect_lora": self.management.reconnect_lora, + "find_duplicates": self.query.find_duplicates, + "bulk_delete": self.management.bulk_delete, + "save_recipe_from_widget": self.management.save_recipe_from_widget, + "get_recipes_for_lora": self.query.get_recipes_for_lora, + "scan_recipes": self.query.scan_recipes, + } + + +class RecipePageView: + """Render the recipe shell page.""" + + def __init__( + self, + *, + ensure_dependencies_ready: EnsureDependenciesCallable, + settings_service: SettingsManager, + server_i18n=default_server_i18n, + template_env, + template_name: str, + recipe_scanner_getter: RecipeScannerGetter, + logger: Logger, + ) -> None: + self._ensure_dependencies_ready = ensure_dependencies_ready + self._settings = settings_service + self._server_i18n = server_i18n + self._template_env = template_env + self._template_name = template_name + self._recipe_scanner_getter = recipe_scanner_getter + self._logger = logger + + async def render_page(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: # pragma: no cover - defensive guard + raise RuntimeError("Recipe scanner not available") + + user_language = self._settings.get("language", "en") + self._server_i18n.set_locale(user_language) + + try: + await recipe_scanner.get_cached_data(force_refresh=False) + rendered = self._template_env.get_template(self._template_name).render( + recipes=[], + is_initializing=False, + settings=self._settings, + request=request, + t=self._server_i18n.get_translation, + ) + except Exception as cache_error: # pragma: no cover - logging path + self._logger.error("Error loading recipe cache data: %s", cache_error) + rendered = self._template_env.get_template(self._template_name).render( + is_initializing=True, + settings=self._settings, + request=request, + t=self._server_i18n.get_translation, + ) + return web.Response(text=rendered, content_type="text/html") + except Exception as exc: # pragma: no cover - logging path + self._logger.error("Error handling recipes request: %s", exc, exc_info=True) + return web.Response(text="Error loading recipes page", status=500) + + +class RecipeListingHandler: + """Provide listing and detail APIs for recipes.""" + + def __init__( + self, + *, + ensure_dependencies_ready: EnsureDependenciesCallable, + recipe_scanner_getter: RecipeScannerGetter, + logger: Logger, + ) -> None: + self._ensure_dependencies_ready = ensure_dependencies_ready + self._recipe_scanner_getter = recipe_scanner_getter + self._logger = logger + + async def list_recipes(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + page = int(request.query.get("page", "1")) + page_size = int(request.query.get("page_size", "20")) + sort_by = request.query.get("sort_by", "date") + search = request.query.get("search") + + search_options = { + "title": request.query.get("search_title", "true").lower() == "true", + "tags": request.query.get("search_tags", "true").lower() == "true", + "lora_name": request.query.get("search_lora_name", "true").lower() == "true", + "lora_model": request.query.get("search_lora_model", "true").lower() == "true", + } + + filters: Dict[str, list[str]] = {} + base_models = request.query.get("base_models") + if base_models: + filters["base_model"] = base_models.split(",") + + tags = request.query.get("tags") + if tags: + filters["tags"] = tags.split(",") + + lora_hash = request.query.get("lora_hash") + + result = await recipe_scanner.get_paginated_data( + page=page, + page_size=page_size, + sort_by=sort_by, + search=search, + filters=filters, + search_options=search_options, + lora_hash=lora_hash, + ) + + for item in result.get("items", []): + file_path = item.get("file_path") + if file_path: + item["file_url"] = self.format_recipe_file_url(file_path) + else: + item.setdefault("file_url", "/loras_static/images/no-preview.png") + item.setdefault("loras", []) + item.setdefault("base_model", "") + + return web.json_response(result) + except Exception as exc: + self._logger.error("Error retrieving recipes: %s", exc, exc_info=True) + return web.json_response({"error": str(exc)}, status=500) + + async def get_recipe(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + recipe_id = request.match_info["recipe_id"] + recipe = await recipe_scanner.get_recipe_by_id(recipe_id) + + if not recipe: + return web.json_response({"error": "Recipe not found"}, status=404) + return web.json_response(recipe) + except Exception as exc: + self._logger.error("Error retrieving recipe details: %s", exc, exc_info=True) + return web.json_response({"error": str(exc)}, status=500) + + def format_recipe_file_url(self, file_path: str) -> str: + try: + recipes_dir = os.path.join(config.loras_roots[0], "recipes").replace(os.sep, "/") + normalized_path = file_path.replace(os.sep, "/") + if normalized_path.startswith(recipes_dir): + relative_path = os.path.relpath(file_path, config.loras_roots[0]).replace(os.sep, "/") + return f"/loras_static/root1/preview/{relative_path}" + + file_name = os.path.basename(file_path) + return f"/loras_static/root1/preview/recipes/{file_name}" + except Exception as exc: # pragma: no cover - logging path + self._logger.error("Error formatting recipe file URL: %s", exc, exc_info=True) + return "/loras_static/images/no-preview.png" + + +class RecipeQueryHandler: + """Provide read-only insights on recipe data.""" + + def __init__( + self, + *, + ensure_dependencies_ready: EnsureDependenciesCallable, + recipe_scanner_getter: RecipeScannerGetter, + format_recipe_file_url: Callable[[str], str], + logger: Logger, + ) -> None: + self._ensure_dependencies_ready = ensure_dependencies_ready + self._recipe_scanner_getter = recipe_scanner_getter + self._format_recipe_file_url = format_recipe_file_url + self._logger = logger + + async def get_top_tags(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + limit = int(request.query.get("limit", "20")) + cache = await recipe_scanner.get_cached_data() + + tag_counts: Dict[str, int] = {} + for recipe in getattr(cache, "raw_data", []): + for tag in recipe.get("tags", []) or []: + tag_counts[tag] = tag_counts.get(tag, 0) + 1 + + sorted_tags = [{"tag": tag, "count": count} for tag, count in tag_counts.items()] + sorted_tags.sort(key=lambda entry: entry["count"], reverse=True) + return web.json_response({"success": True, "tags": sorted_tags[:limit]}) + except Exception as exc: + self._logger.error("Error retrieving top tags: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_base_models(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + cache = await recipe_scanner.get_cached_data() + + base_model_counts: Dict[str, int] = {} + for recipe in getattr(cache, "raw_data", []): + base_model = recipe.get("base_model") + if base_model: + base_model_counts[base_model] = base_model_counts.get(base_model, 0) + 1 + + sorted_models = [{"name": model, "count": count} for model, count in base_model_counts.items()] + sorted_models.sort(key=lambda entry: entry["count"], reverse=True) + return web.json_response({"success": True, "base_models": sorted_models}) + except Exception as exc: + self._logger.error("Error retrieving base models: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_recipes_for_lora(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + lora_hash = request.query.get("hash") + if not lora_hash: + return web.json_response({"success": False, "error": "Lora hash is required"}, status=400) + + cache = await recipe_scanner.get_cached_data() + matching_recipes = [] + for recipe in getattr(cache, "raw_data", []): + for lora in recipe.get("loras", []): + if lora.get("hash", "").lower() == lora_hash.lower(): + matching_recipes.append(recipe) + break + + lora_scanner = getattr(recipe_scanner, "_lora_scanner", None) + for recipe in matching_recipes: + for lora in recipe.get("loras", []): + hash_value = (lora.get("hash") or "").lower() + if hash_value and lora_scanner is not None: + lora["inLibrary"] = lora_scanner.has_hash(hash_value) + lora["preview_url"] = lora_scanner.get_preview_url_by_hash(hash_value) + lora["localPath"] = lora_scanner.get_path_by_hash(hash_value) + if recipe.get("file_path"): + recipe["file_url"] = self._format_recipe_file_url(recipe["file_path"]) + else: + recipe["file_url"] = "/loras_static/images/no-preview.png" + + return web.json_response({"success": True, "recipes": matching_recipes}) + except Exception as exc: + self._logger.error("Error getting recipes for Lora: %s", exc) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def scan_recipes(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + self._logger.info("Manually triggering recipe cache rebuild") + await recipe_scanner.get_cached_data(force_refresh=True) + return web.json_response({"success": True, "message": "Recipe cache refreshed successfully"}) + except Exception as exc: + self._logger.error("Error refreshing recipe cache: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def find_duplicates(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + duplicate_groups = await recipe_scanner.find_all_duplicate_recipes() + response_data = [] + + for fingerprint, recipe_ids in duplicate_groups.items(): + if len(recipe_ids) <= 1: + continue + + recipes = [] + for recipe_id in recipe_ids: + recipe = await recipe_scanner.get_recipe_by_id(recipe_id) + if recipe: + recipes.append( + { + "id": recipe.get("id"), + "title": recipe.get("title"), + "file_url": recipe.get("file_url") + or self._format_recipe_file_url(recipe.get("file_path", "")), + "modified": recipe.get("modified"), + "created_date": recipe.get("created_date"), + "lora_count": len(recipe.get("loras", [])), + } + ) + + if len(recipes) >= 2: + recipes.sort(key=lambda entry: entry.get("modified", 0), reverse=True) + response_data.append( + { + "fingerprint": fingerprint, + "count": len(recipes), + "recipes": recipes, + } + ) + + response_data.sort(key=lambda entry: entry["count"], reverse=True) + return web.json_response({"success": True, "duplicate_groups": response_data}) + except Exception as exc: + self._logger.error("Error finding duplicate recipes: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def get_recipe_syntax(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + recipe_id = request.match_info["recipe_id"] + cache = await recipe_scanner.get_cached_data() + recipe = next( + (r for r in getattr(cache, "raw_data", []) if str(r.get("id", "")) == recipe_id), + None, + ) + if not recipe: + return web.json_response({"error": "Recipe not found"}, status=404) + + loras = recipe.get("loras", []) + if not loras: + return web.json_response({"error": "No LoRAs found in this recipe"}, status=400) + + lora_scanner = getattr(recipe_scanner, "_lora_scanner", None) + hash_index = getattr(lora_scanner, "_hash_index", None) + + lora_syntax_parts = [] + for lora in loras: + if lora.get("isDeleted", False): + continue + hash_value = (lora.get("hash") or "").lower() + if not hash_value or lora_scanner is None or not lora_scanner.has_hash(hash_value): + continue + + file_name = None + if hash_value and hash_index is not None and hasattr(hash_index, "_hash_to_path"): + file_path = hash_index._hash_to_path.get(hash_value) + if file_path: + file_name = os.path.splitext(os.path.basename(file_path))[0] + + if not file_name and lora.get("modelVersionId") and lora_scanner is not None: + all_loras = await lora_scanner.get_cached_data() + for cached_lora in getattr(all_loras, "raw_data", []): + civitai_info = cached_lora.get("civitai") + if civitai_info and civitai_info.get("id") == lora.get("modelVersionId"): + file_name = os.path.splitext(os.path.basename(cached_lora["path"]))[0] + break + + if not file_name: + file_name = lora.get("file_name", "unknown-lora") + + strength = lora.get("strength", 1.0) + lora_syntax_parts.append(f"") + + return web.json_response({"success": True, "syntax": " ".join(lora_syntax_parts)}) + except Exception as exc: + self._logger.error("Error generating recipe syntax: %s", exc, exc_info=True) + return web.json_response({"error": str(exc)}, status=500) + + +class RecipeManagementHandler: + """Handle create/update/delete style recipe operations.""" + + def __init__( + self, + *, + ensure_dependencies_ready: EnsureDependenciesCallable, + recipe_scanner_getter: RecipeScannerGetter, + logger: Logger, + exif_utils=ExifUtils, + card_preview_width: int = CARD_PREVIEW_WIDTH, + metadata_collector: Optional[Callable[[], Any]] = get_metadata, + metadata_processor_cls: Optional[type] = MetadataProcessor, + metadata_registry_cls: Optional[type] = MetadataRegistry, + standalone_mode: bool = standalone_mode, + ) -> None: + self._ensure_dependencies_ready = ensure_dependencies_ready + self._recipe_scanner_getter = recipe_scanner_getter + self._logger = logger + self._exif_utils = exif_utils + self._card_preview_width = card_preview_width + self._metadata_collector = metadata_collector + self._metadata_processor_cls = metadata_processor_cls + self._metadata_registry_cls = metadata_registry_cls + self._standalone_mode = standalone_mode + + async def save_recipe(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + reader = await request.multipart() + + image: Optional[bytes] = None + image_base64: Optional[str] = None + name: Optional[str] = None + tags: list[str] = [] + metadata: Dict[str, Any] | None = None + + while True: + field = await reader.next() + if field is None: + break + + if field.name == "image": + image_chunks = bytearray() + while True: + chunk = await field.read_chunk() + if not chunk: + break + image_chunks.extend(chunk) + image = bytes(image_chunks) + elif field.name == "image_base64": + image_base64 = await field.text() + elif field.name == "name": + name = await field.text() + elif field.name == "tags": + tags_text = await field.text() + try: + parsed_tags = json.loads(tags_text) + tags = parsed_tags if isinstance(parsed_tags, list) else [] + except Exception: + tags = [] + elif field.name == "metadata": + metadata_text = await field.text() + try: + metadata = json.loads(metadata_text) + except Exception: + metadata = {} + + missing_fields = [] + if not name: + missing_fields.append("name") + if not metadata: + missing_fields.append("metadata") + if missing_fields: + return web.json_response( + {"error": f"Missing required fields: {', '.join(missing_fields)}"}, + status=400, + ) + + if image is None: + if image_base64: + try: + if "," in image_base64: + image_base64 = image_base64.split(",", 1)[1] + image = base64.b64decode(image_base64) + except Exception as exc: + return web.json_response({"error": f"Invalid base64 image data: {exc}"}, status=400) + else: + return web.json_response({"error": "No image data provided"}, status=400) + + recipes_dir = recipe_scanner.recipes_dir + os.makedirs(recipes_dir, exist_ok=True) + + import uuid + + recipe_id = str(uuid.uuid4()) + optimized_image, extension = self._exif_utils.optimize_image( + image_data=image, + target_width=self._card_preview_width, + format="webp", + quality=85, + preserve_metadata=True, + ) + + image_filename = f"{recipe_id}{extension}" + image_path = os.path.join(recipes_dir, image_filename) + with open(image_path, "wb") as file_obj: + file_obj.write(optimized_image) + + current_time = time.time() + loras_data = [] + for lora in metadata.get("loras", []): + loras_data.append( + { + "file_name": lora.get("file_name", "") + or ( + os.path.splitext(os.path.basename(lora.get("localPath", "")))[0] + if lora.get("localPath") + else "" + ), + "hash": (lora.get("hash") or "").lower(), + "strength": float(lora.get("weight", 1.0)), + "modelVersionId": lora.get("id", 0), + "modelName": lora.get("name", ""), + "modelVersionName": lora.get("version", ""), + "isDeleted": lora.get("isDeleted", False), + "exclude": lora.get("exclude", False), + } + ) + + gen_params = metadata.get("gen_params", {}) + if not gen_params and "raw_metadata" in metadata: + raw_metadata = metadata.get("raw_metadata", {}) + gen_params = { + "prompt": raw_metadata.get("prompt", ""), + "negative_prompt": raw_metadata.get("negative_prompt", ""), + "checkpoint": raw_metadata.get("checkpoint", {}), + "steps": raw_metadata.get("steps", ""), + "sampler": raw_metadata.get("sampler", ""), + "cfg_scale": raw_metadata.get("cfg_scale", ""), + "seed": raw_metadata.get("seed", ""), + "size": raw_metadata.get("size", ""), + "clip_skip": raw_metadata.get("clip_skip", ""), + } + + from ...utils.utils import calculate_recipe_fingerprint + + fingerprint = calculate_recipe_fingerprint(loras_data) + + recipe_data = { + "id": recipe_id, + "file_path": image_path, + "title": name, + "modified": current_time, + "created_date": current_time, + "base_model": metadata.get("base_model", ""), + "loras": loras_data, + "gen_params": gen_params, + "fingerprint": fingerprint, + } + + if tags: + recipe_data["tags"] = tags + + if metadata.get("source_path"): + recipe_data["source_path"] = metadata.get("source_path") + + json_filename = f"{recipe_id}.recipe.json" + json_path = os.path.join(recipes_dir, json_filename) + with open(json_path, "w", encoding="utf-8") as file_obj: + json.dump(recipe_data, file_obj, indent=4, ensure_ascii=False) + + self._exif_utils.append_recipe_metadata(image_path, recipe_data) + + matching_recipes = [] + if fingerprint: + matching_recipes = await recipe_scanner.find_recipes_by_fingerprint(fingerprint) + if recipe_id in matching_recipes: + matching_recipes.remove(recipe_id) + + cache = getattr(recipe_scanner, "_cache", None) + if cache is not None: + cache.raw_data.append(recipe_data) + asyncio.create_task(cache.resort()) + self._logger.info("Added recipe %s to cache", recipe_id) + + return web.json_response( + { + "success": True, + "recipe_id": recipe_id, + "image_path": image_path, + "json_path": json_path, + "matching_recipes": matching_recipes, + } + ) + except Exception as exc: + self._logger.error("Error saving recipe: %s", exc, exc_info=True) + return web.json_response({"error": str(exc)}, status=500) + + async def delete_recipe(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + recipe_id = request.match_info["recipe_id"] + recipes_dir = recipe_scanner.recipes_dir + if not recipes_dir or not os.path.exists(recipes_dir): + return web.json_response({"error": "Recipes directory not found"}, status=404) + + recipe_json_path = os.path.join(recipes_dir, f"{recipe_id}.recipe.json") + if not os.path.exists(recipe_json_path): + return web.json_response({"error": "Recipe not found"}, status=404) + + with open(recipe_json_path, "r", encoding="utf-8") as file_obj: + recipe_data = json.load(file_obj) + + image_path = recipe_data.get("file_path") + os.remove(recipe_json_path) + self._logger.info("Deleted recipe JSON file: %s", recipe_json_path) + + if image_path and os.path.exists(image_path): + os.remove(image_path) + self._logger.info("Deleted recipe image: %s", image_path) + + cache = getattr(recipe_scanner, "_cache", None) + if cache is not None: + cache.raw_data = [ + item for item in cache.raw_data if str(item.get("id", "")) != recipe_id + ] + asyncio.create_task(cache.resort()) + self._logger.info("Removed recipe %s from cache", recipe_id) + + return web.json_response({"success": True, "message": "Recipe deleted successfully"}) + except Exception as exc: + self._logger.error("Error deleting recipe: %s", exc, exc_info=True) + return web.json_response({"error": str(exc)}, status=500) + + async def update_recipe(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + recipe_id = request.match_info["recipe_id"] + data = await request.json() + + if not any( + key in data for key in ("title", "tags", "source_path", "preview_nsfw_level") + ): + return web.json_response( + { + "error": ( + "At least one field to update must be provided (title or tags or " + "source_path or preview_nsfw_level)" + ) + }, + status=400, + ) + + success = await recipe_scanner.update_recipe_metadata(recipe_id, data) + if not success: + return web.json_response({"error": "Recipe not found or update failed"}, status=404) + + return web.json_response({"success": True, "recipe_id": recipe_id, "updates": data}) + except Exception as exc: + self._logger.error("Error updating recipe: %s", exc, exc_info=True) + return web.json_response({"error": str(exc)}, status=500) + + async def reconnect_lora(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + data = await request.json() + required_fields = ["recipe_id", "lora_index", "target_name"] + for field in required_fields: + if field not in data: + return web.json_response({"error": f"Missing required field: {field}"}, status=400) + + recipe_id = data["recipe_id"] + lora_index = int(data["lora_index"]) + target_name = data["target_name"] + + recipe_path = os.path.join(recipe_scanner.recipes_dir, f"{recipe_id}.recipe.json") + if not os.path.exists(recipe_path): + return web.json_response({"error": "Recipe not found"}, status=404) + + lora_scanner = getattr(recipe_scanner, "_lora_scanner", None) + target_lora = None if lora_scanner is None else await lora_scanner.get_model_info_by_name(target_name) + if not target_lora: + return web.json_response({"error": f"Local LoRA not found with name: {target_name}"}, status=404) + + with open(recipe_path, "r", encoding="utf-8") as file_obj: + recipe_data = json.load(file_obj) + + loras = recipe_data.get("loras", []) + lora = loras[lora_index] if lora_index < len(loras) else None + if lora is None: + return web.json_response({"error": "LoRA index out of range in recipe"}, status=404) + + lora["isDeleted"] = False + lora["exclude"] = False + lora["file_name"] = target_name + if "sha256" in target_lora: + lora["hash"] = target_lora["sha256"].lower() + if target_lora.get("civitai"): + lora["modelName"] = target_lora["civitai"]["model"]["name"] + lora["modelVersionName"] = target_lora["civitai"]["name"] + lora["modelVersionId"] = target_lora["civitai"]["id"] + + from ...utils.utils import calculate_recipe_fingerprint + + recipe_data["fingerprint"] = calculate_recipe_fingerprint(recipe_data.get("loras", [])) + + with open(recipe_path, "w", encoding="utf-8") as file_obj: + json.dump(recipe_data, file_obj, indent=4, ensure_ascii=False) + + updated_lora = dict(lora) + updated_lora["inLibrary"] = True + updated_lora["preview_url"] = config.get_preview_static_url(target_lora["preview_url"]) + updated_lora["localPath"] = target_lora["file_path"] + + cache = getattr(recipe_scanner, "_cache", None) + if cache is not None: + for cache_item in cache.raw_data: + if cache_item.get("id") == recipe_id: + cache_item["loras"] = recipe_data["loras"] + cache_item["fingerprint"] = recipe_data["fingerprint"] + asyncio.create_task(cache.resort()) + break + + image_path = recipe_data.get("file_path") + if image_path and os.path.exists(image_path): + self._exif_utils.append_recipe_metadata(image_path, recipe_data) + + matching_recipes = [] + if "fingerprint" in recipe_data: + matching_recipes = await recipe_scanner.find_recipes_by_fingerprint(recipe_data["fingerprint"]) + if recipe_id in matching_recipes: + matching_recipes.remove(recipe_id) + + return web.json_response( + { + "success": True, + "recipe_id": recipe_id, + "updated_lora": updated_lora, + "matching_recipes": matching_recipes, + } + ) + except Exception as exc: + self._logger.error("Error reconnecting LoRA: %s", exc, exc_info=True) + return web.json_response({"error": str(exc)}, status=500) + + async def bulk_delete(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + data = await request.json() + recipe_ids = data.get("recipe_ids", []) + if not recipe_ids: + return web.json_response( + {"success": False, "error": "No recipe IDs provided"}, + status=400, + ) + + recipes_dir = recipe_scanner.recipes_dir + if not recipes_dir or not os.path.exists(recipes_dir): + return web.json_response( + {"success": False, "error": "Recipes directory not found"}, + status=404, + ) + + deleted_recipes: list[str] = [] + failed_recipes: list[Dict[str, Any]] = [] + + for recipe_id in recipe_ids: + recipe_json_path = os.path.join(recipes_dir, f"{recipe_id}.recipe.json") + if not os.path.exists(recipe_json_path): + failed_recipes.append({"id": recipe_id, "reason": "Recipe not found"}) + continue + + try: + with open(recipe_json_path, "r", encoding="utf-8") as file_obj: + recipe_data = json.load(file_obj) + image_path = recipe_data.get("file_path") + os.remove(recipe_json_path) + if image_path and os.path.exists(image_path): + os.remove(image_path) + deleted_recipes.append(recipe_id) + except Exception as exc: + failed_recipes.append({"id": recipe_id, "reason": str(exc)}) + + cache = getattr(recipe_scanner, "_cache", None) + if deleted_recipes and cache is not None: + cache.raw_data = [item for item in cache.raw_data if item.get("id") not in deleted_recipes] + asyncio.create_task(cache.resort()) + self._logger.info("Removed %s recipes from cache", len(deleted_recipes)) + + return web.json_response( + { + "success": True, + "deleted": deleted_recipes, + "failed": failed_recipes, + "total_deleted": len(deleted_recipes), + "total_failed": len(failed_recipes), + } + ) + except Exception as exc: + self._logger.error("Error performing bulk delete: %s", exc, exc_info=True) + return web.json_response({"success": False, "error": str(exc)}, status=500) + + async def save_recipe_from_widget(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + if self._metadata_collector is None or self._metadata_processor_cls is None: + return web.json_response({"error": "Metadata collection not available"}, status=400) + + raw_metadata = self._metadata_collector() + metadata_dict = self._metadata_processor_cls.to_dict(raw_metadata) + if not metadata_dict: + return web.json_response({"error": "No generation metadata found"}, status=400) + + if not self._standalone_mode and self._metadata_registry_cls is not None: + metadata_registry = self._metadata_registry_cls() + latest_image = metadata_registry.get_first_decoded_image() + else: + latest_image = None + + if latest_image is None: + return web.json_response( + {"error": "No recent images found to use for recipe. Try generating an image first."}, + status=400, + ) + + self._logger.debug("Image type: %s", type(latest_image)) + + try: + if isinstance(latest_image, tuple): + tensor_image = latest_image[0] if latest_image else None + if tensor_image is None: + return web.json_response({"error": "Empty image tuple received"}, status=400) + else: + tensor_image = latest_image + + if hasattr(tensor_image, "shape"): + shape_info = tensor_image.shape + self._logger.debug("Tensor shape: %s, dtype: %s", shape_info, tensor_image.dtype) + + import torch # type: ignore[import-not-found] + + if isinstance(tensor_image, torch.Tensor): + image_np = tensor_image.cpu().numpy() + else: + image_np = np.array(tensor_image) + + while len(image_np.shape) > 3: + image_np = image_np[0] + + if image_np.dtype in (np.float32, np.float64) and image_np.max() <= 1.0: + image_np = (image_np * 255).astype(np.uint8) + + if len(image_np.shape) == 3 and image_np.shape[2] == 3: + pil_image = Image.fromarray(image_np) + img_byte_arr = io.BytesIO() + pil_image.save(img_byte_arr, format="PNG") + image_bytes = img_byte_arr.getvalue() + else: + return web.json_response( + {"error": f"Cannot handle this data shape: {image_np.shape}, {image_np.dtype}"}, + status=400, + ) + except Exception as exc: + self._logger.error("Error processing image data: %s", exc, exc_info=True) + return web.json_response({"error": f"Error processing image: {exc}"}, status=400) + + lora_stack = metadata_dict.get("loras", "") + import re + + lora_matches = re.findall(r"]+)>", lora_stack) + if not lora_matches: + return web.json_response({"error": "No LoRAs found in the generation metadata"}, status=400) + + loras_for_name = lora_matches[:3] + recipe_name_parts = [] + for name, strength in loras_for_name: + recipe_name_parts.append(f"{name.strip()}-{float(strength):.2f}") + recipe_name = "_".join(recipe_name_parts) + + recipe_name = recipe_name or "recipe" + + recipes_dir = recipe_scanner.recipes_dir + os.makedirs(recipes_dir, exist_ok=True) + + import uuid + + recipe_id = str(uuid.uuid4()) + image_filename = f"{recipe_id}.png" + image_path = os.path.join(recipes_dir, image_filename) + with open(image_path, "wb") as file_obj: + file_obj.write(image_bytes) + + loras_data = [] + lora_scanner = getattr(recipe_scanner, "_lora_scanner", None) + base_model_counts: Dict[str, int] = {} + + for name, strength in lora_matches: + lora_info = None + if lora_scanner is not None: + lora_info = await lora_scanner.get_model_info_by_name(name) + lora_data = { + "file_name": name, + "strength": float(strength), + "hash": (lora_info.get("sha256") or "").lower() if lora_info else "", + "modelVersionId": lora_info.get("civitai", {}).get("id") if lora_info else 0, + "modelName": lora_info.get("civitai", {}).get("model", {}).get("name") if lora_info else "", + "modelVersionName": lora_info.get("civitai", {}).get("name") if lora_info else "", + "isDeleted": False, + "exclude": False, + } + loras_data.append(lora_data) + + if lora_info and "base_model" in lora_info: + base_model = lora_info["base_model"] + base_model_counts[base_model] = base_model_counts.get(base_model, 0) + 1 + + most_common_base_model = "" + if base_model_counts: + most_common_base_model = max(base_model_counts.items(), key=lambda item: item[1])[0] + + recipe_data = { + "id": recipe_id, + "file_path": image_path, + "title": recipe_name, + "modified": time.time(), + "created_date": time.time(), + "base_model": most_common_base_model, + "loras": loras_data, + "checkpoint": metadata_dict.get("checkpoint", ""), + "gen_params": { + key: value + for key, value in metadata_dict.items() + if key not in ["checkpoint", "loras"] + }, + "loras_stack": lora_stack, + } + + json_filename = f"{recipe_id}.recipe.json" + json_path = os.path.join(recipes_dir, json_filename) + with open(json_path, "w", encoding="utf-8") as file_obj: + json.dump(recipe_data, file_obj, indent=4, ensure_ascii=False) + + self._exif_utils.append_recipe_metadata(image_path, recipe_data) + + cache = getattr(recipe_scanner, "_cache", None) + if cache is not None: + cache.raw_data.append(recipe_data) + asyncio.create_task(cache.resort()) + self._logger.info("Added recipe %s to cache", recipe_id) + + return web.json_response( + { + "success": True, + "recipe_id": recipe_id, + "image_path": image_path, + "json_path": json_path, + "recipe_name": recipe_name, + } + ) + except Exception as exc: + self._logger.error("Error saving recipe from widget: %s", exc, exc_info=True) + return web.json_response({"error": str(exc)}, status=500) + + +class RecipeAnalysisHandler: + """Analyze images to extract recipe metadata.""" + + def __init__( + self, + *, + ensure_dependencies_ready: EnsureDependenciesCallable, + recipe_scanner_getter: RecipeScannerGetter, + civitai_client_getter: CivitaiClientGetter, + logger: Logger, + exif_utils=ExifUtils, + recipe_parser_factory=RecipeParserFactory, + downloader_factory=get_downloader, + ) -> None: + self._ensure_dependencies_ready = ensure_dependencies_ready + self._recipe_scanner_getter = recipe_scanner_getter + self._civitai_client_getter = civitai_client_getter + self._logger = logger + self._exif_utils = exif_utils + self._recipe_parser_factory = recipe_parser_factory + self._downloader_factory = downloader_factory + + async def analyze_uploaded_image(self, request: web.Request) -> web.Response: + temp_path: Optional[str] = None + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + civitai_client = self._civitai_client_getter() + if recipe_scanner is None or civitai_client is None: + raise RuntimeError("Required services unavailable") + + content_type = request.headers.get("Content-Type", "") + is_url_mode = False + metadata: Optional[Dict[str, Any]] = None + + if "multipart/form-data" in content_type: + reader = await request.multipart() + field = await reader.next() + if field is None or field.name != "image": + return web.json_response({"error": "No image field found", "loras": []}, status=400) + + with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_file: + while True: + chunk = await field.read_chunk() + if not chunk: + break + temp_file.write(chunk) + temp_path = temp_file.name + elif "application/json" in content_type: + data = await request.json() + url = data.get("url") + is_url_mode = True + if not url: + return web.json_response({"error": "No URL provided", "loras": []}, status=400) + + import re + + civitai_image_match = re.match(r"https://civitai\.com/images/(\d+)", url) + if civitai_image_match: + image_id = civitai_image_match.group(1) + image_info = await civitai_client.get_image_info(image_id) + if not image_info: + return web.json_response( + {"error": "Failed to fetch image information from Civitai", "loras": []}, + status=400, + ) + image_url = image_info.get("url") + if not image_url: + return web.json_response( + {"error": "No image URL found in Civitai response", "loras": []}, + status=400, + ) + + downloader = await self._downloader_factory() + with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_file: + temp_path = temp_file.name + + success, result = await downloader.download_file( + image_url, + temp_path, + use_auth=False, + ) + if not success: + return web.json_response( + {"error": f"Failed to download image from URL: {result}", "loras": []}, + status=400, + ) + metadata = image_info.get("meta") if "meta" in image_info else None + else: + return web.json_response({"error": "Unsupported content type", "loras": []}, status=400) + + if metadata is None and temp_path: + metadata = self._exif_utils.extract_image_metadata(temp_path) + + if not metadata: + response: Dict[str, Any] = {"error": "No metadata found in this image", "loras": []} + if is_url_mode and temp_path: + with open(temp_path, "rb") as image_file: + response["image_base64"] = base64.b64encode(image_file.read()).decode("utf-8") + return web.json_response(response, status=200) + + parser = self._recipe_parser_factory.create_parser(metadata) + if parser is None: + response = {"error": "No parser found for this image", "loras": []} + if is_url_mode and temp_path: + with open(temp_path, "rb") as image_file: + response["image_base64"] = base64.b64encode(image_file.read()).decode("utf-8") + return web.json_response(response, status=200) + + result = await parser.parse_metadata(metadata, recipe_scanner=recipe_scanner) + + if is_url_mode and temp_path: + with open(temp_path, "rb") as image_file: + result["image_base64"] = base64.b64encode(image_file.read()).decode("utf-8") + + if "error" in result and not result.get("loras"): + return web.json_response(result, status=200) + + from ...utils.utils import calculate_recipe_fingerprint + + fingerprint = calculate_recipe_fingerprint(result.get("loras", [])) + result["fingerprint"] = fingerprint + + matching_recipes = [] + if fingerprint: + matching_recipes = await recipe_scanner.find_recipes_by_fingerprint(fingerprint) + + result["matching_recipes"] = matching_recipes + return web.json_response(result) + except Exception as exc: + self._logger.error("Error analyzing recipe image: %s", exc, exc_info=True) + return web.json_response({"error": str(exc), "loras": []}, status=500) + finally: + if temp_path and os.path.exists(temp_path): + try: + os.unlink(temp_path) + except Exception as cleanup_exc: # pragma: no cover - logging path + self._logger.error("Error deleting temporary file: %s", cleanup_exc) + + async def analyze_local_image(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + data = await request.json() + file_path = data.get("path") + if not file_path: + return web.json_response({"error": "No file path provided", "loras": []}, status=400) + + file_path = os.path.normpath(file_path.strip('"').strip("'")) + if not os.path.isfile(file_path): + return web.json_response({"error": "File not found", "loras": []}, status=404) + + metadata = self._exif_utils.extract_image_metadata(file_path) + if not metadata: + with open(file_path, "rb") as image_file: + image_base64 = base64.b64encode(image_file.read()).decode("utf-8") + return web.json_response( + {"error": "No metadata found in this image", "loras": [], "image_base64": image_base64}, + status=200, + ) + + parser = self._recipe_parser_factory.create_parser(metadata) + if parser is None: + with open(file_path, "rb") as image_file: + image_base64 = base64.b64encode(image_file.read()).decode("utf-8") + return web.json_response( + {"error": "No parser found for this image", "loras": [], "image_base64": image_base64}, + status=200, + ) + + result = await parser.parse_metadata(metadata, recipe_scanner=recipe_scanner) + with open(file_path, "rb") as image_file: + result["image_base64"] = base64.b64encode(image_file.read()).decode("utf-8") + + if "error" in result and not result.get("loras"): + return web.json_response(result, status=200) + + from ...utils.utils import calculate_recipe_fingerprint + + fingerprint = calculate_recipe_fingerprint(result.get("loras", [])) + result["fingerprint"] = fingerprint + + matching_recipes = [] + if fingerprint: + matching_recipes = await recipe_scanner.find_recipes_by_fingerprint(fingerprint) + result["matching_recipes"] = matching_recipes + + return web.json_response(result) + except Exception as exc: + self._logger.error("Error analyzing local image: %s", exc, exc_info=True) + return web.json_response({"error": str(exc), "loras": []}, status=500) + + +class RecipeSharingHandler: + """Serve endpoints related to recipe sharing.""" + + def __init__( + self, + *, + ensure_dependencies_ready: EnsureDependenciesCallable, + recipe_scanner_getter: RecipeScannerGetter, + logger: Logger, + ) -> None: + self._ensure_dependencies_ready = ensure_dependencies_ready + self._recipe_scanner_getter = recipe_scanner_getter + self._logger = logger + self._shared_recipes: Dict[str, Dict[str, Any]] = {} + + async def share_recipe(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + recipe_id = request.match_info["recipe_id"] + cache = await recipe_scanner.get_cached_data() + recipe = next( + (r for r in getattr(cache, "raw_data", []) if str(r.get("id", "")) == recipe_id), + None, + ) + if not recipe: + return web.json_response({"error": "Recipe not found"}, status=404) + + image_path = recipe.get("file_path") + if not image_path or not os.path.exists(image_path): + return web.json_response({"error": "Recipe image not found"}, status=404) + + import shutil + + ext = os.path.splitext(image_path)[1] + with tempfile.NamedTemporaryFile(suffix=ext, delete=False) as temp_file: + temp_path = temp_file.name + shutil.copy2(image_path, temp_path) + processed_path = temp_path + + timestamp = int(time.time()) + url_path = f"/api/recipe/{recipe_id}/share/download?t={timestamp}" + self._shared_recipes[recipe_id] = { + "path": processed_path, + "timestamp": timestamp, + "expires": time.time() + 300, + } + self._cleanup_shared_recipes() + + filename = f"recipe_{recipe.get('title', '').replace(' ', '_').lower()}{ext}" + return web.json_response({"success": True, "download_url": url_path, "filename": filename}) + except Exception as exc: + self._logger.error("Error sharing recipe: %s", exc, exc_info=True) + return web.json_response({"error": str(exc)}, status=500) + + async def download_shared_recipe(self, request: web.Request) -> web.Response: + try: + await self._ensure_dependencies_ready() + recipe_scanner = self._recipe_scanner_getter() + if recipe_scanner is None: + raise RuntimeError("Recipe scanner unavailable") + + recipe_id = request.match_info["recipe_id"] + shared_info = self._shared_recipes.get(recipe_id) + if not shared_info: + return web.json_response({"error": "Shared recipe not found or expired"}, status=404) + + file_path = shared_info["path"] + if not os.path.exists(file_path): + return web.json_response({"error": "Shared recipe file not found"}, status=404) + + cache = await recipe_scanner.get_cached_data() + recipe = next( + (r for r in getattr(cache, "raw_data", []) if str(r.get("id", "")) == recipe_id), + None, + ) + filename_base = ( + f"recipe_{recipe.get('title', '').replace(' ', '_').lower()}" + if recipe + else recipe_id + ) + ext = os.path.splitext(file_path)[1] + download_filename = f"{filename_base}{ext}" + + return web.FileResponse( + file_path, + headers={"Content-Disposition": f'attachment; filename="{download_filename}"'}, + ) + except Exception as exc: + self._logger.error("Error downloading shared recipe: %s", exc, exc_info=True) + return web.json_response({"error": str(exc)}, status=500) + + def _cleanup_shared_recipes(self) -> None: + current_time = time.time() + expired_ids = [ + recipe_id + for recipe_id, info in self._shared_recipes.items() + if current_time > info.get("expires", 0) + ] + + for recipe_id in expired_ids: + try: + file_path = self._shared_recipes[recipe_id]["path"] + if os.path.exists(file_path): + os.unlink(file_path) + except Exception as exc: # pragma: no cover - logging path + self._logger.error("Error cleaning up shared recipe %s: %s", recipe_id, exc) + finally: + self._shared_recipes.pop(recipe_id, None) diff --git a/py/routes/recipe_routes.py b/py/routes/recipe_routes.py index 55208552..2c233d01 100644 --- a/py/routes/recipe_routes.py +++ b/py/routes/recipe_routes.py @@ -1,41 +1,16 @@ -import os -import time -import base64 -import numpy as np -from PIL import Image -import io -import logging +"""Concrete recipe route configuration.""" + from aiohttp import web -from typing import Dict -import tempfile -import json -import asyncio -import sys from .base_recipe_routes import BaseRecipeRoutes from .recipe_route_registrar import RecipeRouteRegistrar -from ..utils.exif_utils import ExifUtils -from ..recipes import RecipeParserFactory -from ..utils.constants import CARD_PREVIEW_WIDTH -from ..config import config -from ..services.downloader import get_downloader - -# Check if running in standalone mode -standalone_mode = os.environ.get("HF_HUB_DISABLE_TELEMETRY", "0") == "0" - -# Only import MetadataRegistry in non-standalone mode -if not standalone_mode: - # Import metadata_collector functions and classes conditionally - from ..metadata_collector import get_metadata # Add MetadataCollector import - from ..metadata_collector.metadata_processor import MetadataProcessor # Add MetadataProcessor import - from ..metadata_collector.metadata_registry import MetadataRegistry - -logger = logging.getLogger(__name__) class RecipeRoutes(BaseRecipeRoutes): """API route handlers for Recipe management.""" + template_name = "recipes.html" + @classmethod def setup_routes(cls, app: web.Application): """Register API routes using the declarative registrar.""" @@ -44,1531 +19,3 @@ class RecipeRoutes(BaseRecipeRoutes): registrar = RecipeRouteRegistrar(app) registrar.register_routes(routes.to_route_mapping()) routes.register_startup_hooks(app) - - async def render_page(self, request: web.Request) -> web.Response: - """Handle GET /loras/recipes request.""" - try: - await self.ensure_dependencies_ready() - - # 获取用户语言设置 - user_language = self.settings.get('language', 'en') - - # 设置服务端i18n语言 - self.server_i18n.set_locale(user_language) - - # Skip initialization check and directly try to get cached data - try: - # Recipe scanner will initialize cache if needed - await self.recipe_scanner.get_cached_data(force_refresh=False) - template = self.template_env.get_template('recipes.html') - rendered = template.render( - recipes=[], # Frontend will load recipes via API - is_initializing=False, - settings=self.settings, - request=request, - # 添加服务端翻译函数 - t=self.server_i18n.get_translation, - ) - except Exception as cache_error: - logger.error(f"Error loading recipe cache data: {cache_error}") - # Still keep error handling - show initializing page on error - template = self.template_env.get_template('recipes.html') - rendered = template.render( - is_initializing=True, - settings=self.settings, - request=request, - # 添加服务端翻译函数 - t=self.server_i18n.get_translation, - ) - logger.info("Recipe cache error, returning initialization page") - - return web.Response( - text=rendered, - content_type='text/html' - ) - - except Exception as e: - logger.error(f"Error handling recipes request: {e}", exc_info=True) - return web.Response( - text="Error loading recipes page", - status=500 - ) - - async def list_recipes(self, request: web.Request) -> web.Response: - """API endpoint for getting paginated recipes.""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - # Get query parameters with defaults - page = int(request.query.get('page', '1')) - page_size = int(request.query.get('page_size', '20')) - sort_by = request.query.get('sort_by', 'date') - search = request.query.get('search', None) - - # Get search options (renamed for better clarity) - search_title = request.query.get('search_title', 'true').lower() == 'true' - search_tags = request.query.get('search_tags', 'true').lower() == 'true' - search_lora_name = request.query.get('search_lora_name', 'true').lower() == 'true' - search_lora_model = request.query.get('search_lora_model', 'true').lower() == 'true' - - # Get filter parameters - base_models = request.query.get('base_models', None) - tags = request.query.get('tags', None) - - # New parameter: get LoRA hash filter - lora_hash = request.query.get('lora_hash', None) - - # Parse filter parameters - filters = {} - if base_models: - filters['base_model'] = base_models.split(',') - if tags: - filters['tags'] = tags.split(',') - - # Add search options to filters - search_options = { - 'title': search_title, - 'tags': search_tags, - 'lora_name': search_lora_name, - 'lora_model': search_lora_model - } - - # Get paginated data with the new lora_hash parameter - result = await self.recipe_scanner.get_paginated_data( - page=page, - page_size=page_size, - sort_by=sort_by, - search=search, - filters=filters, - search_options=search_options, - lora_hash=lora_hash - ) - - # Format the response data with static URLs for file paths - for item in result['items']: - # Always ensure file_url is set - if 'file_path' in item: - item['file_url'] = self._format_recipe_file_url(item['file_path']) - else: - item['file_url'] = '/loras_static/images/no-preview.png' - - # 确保 loras 数组存在 - if 'loras' not in item: - item['loras'] = [] - - # 确保有 base_model 字段 - if 'base_model' not in item: - item['base_model'] = "" - - return web.json_response(result) - except Exception as e: - logger.error(f"Error retrieving recipes: {e}", exc_info=True) - return web.json_response({"error": str(e)}, status=500) - - async def get_recipe(self, request: web.Request) -> web.Response: - """Get detailed information about a specific recipe.""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - recipe_id = request.match_info['recipe_id'] - - # Use the new get_recipe_by_id method from recipe_scanner - recipe = await self.recipe_scanner.get_recipe_by_id(recipe_id) - - if not recipe: - return web.json_response({"error": "Recipe not found"}, status=404) - - return web.json_response(recipe) - except Exception as e: - logger.error(f"Error retrieving recipe details: {e}", exc_info=True) - return web.json_response({"error": str(e)}, status=500) - - def _format_recipe_file_url(self, file_path: str) -> str: - """Format file path for recipe image as a URL""" - try: - # Return the file URL directly for the first lora root's preview - recipes_dir = os.path.join(config.loras_roots[0], "recipes").replace(os.sep, '/') - if file_path.replace(os.sep, '/').startswith(recipes_dir): - relative_path = os.path.relpath(file_path, config.loras_roots[0]).replace(os.sep, '/') - return f"/loras_static/root1/preview/{relative_path}" - - # If not in recipes dir, try to create a valid URL from the file path - file_name = os.path.basename(file_path) - return f"/loras_static/root1/preview/recipes/{file_name}" - except Exception as e: - logger.error(f"Error formatting recipe file URL: {e}", exc_info=True) - return '/loras_static/images/no-preview.png' # Return default image on error - - def _format_recipe_data(self, recipe: Dict) -> Dict: - """Format recipe data for API response""" - formatted = {**recipe} # Copy all fields - - # Format file paths to URLs - if 'file_path' in formatted: - formatted['file_url'] = self._format_recipe_file_url(formatted['file_path']) - - # Format dates for display - for date_field in ['created_date', 'modified']: - if date_field in formatted: - formatted[f"{date_field}_formatted"] = self._format_timestamp(formatted[date_field]) - - return formatted - - def _format_timestamp(self, timestamp: float) -> str: - """Format timestamp for display""" - from datetime import datetime - return datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S') - - async def analyze_uploaded_image(self, request: web.Request) -> web.Response: - """Analyze an uploaded image or URL for recipe metadata.""" - temp_path = None - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - # Check if request contains multipart data (image) or JSON data (url) - content_type = request.headers.get('Content-Type', '') - - is_url_mode = False - metadata = None # Initialize metadata variable - - if 'multipart/form-data' in content_type: - # Handle image upload - reader = await request.multipart() - field = await reader.next() - - if field.name != 'image': - return web.json_response({ - "error": "No image field found", - "loras": [] - }, status=400) - - # Create a temporary file to store the uploaded image - with tempfile.NamedTemporaryFile(delete=False, suffix='.jpg') as temp_file: - while True: - chunk = await field.read_chunk() - if not chunk: - break - temp_file.write(chunk) - temp_path = temp_file.name - - elif 'application/json' in content_type: - # Handle URL input - data = await request.json() - url = data.get('url') - is_url_mode = True - - if not url: - return web.json_response({ - "error": "No URL provided", - "loras": [] - }, status=400) - - # Check if this is a Civitai image URL - import re - civitai_image_match = re.match(r'https://civitai\.com/images/(\d+)', url) - - if civitai_image_match: - # Extract image ID and fetch image info using get_image_info - image_id = civitai_image_match.group(1) - image_info = await self.civitai_client.get_image_info(image_id) - - if not image_info: - return web.json_response({ - "error": "Failed to fetch image information from Civitai", - "loras": [] - }, status=400) - - # Get image URL from response - image_url = image_info.get('url') - if not image_url: - return web.json_response({ - "error": "No image URL found in Civitai response", - "loras": [] - }, status=400) - - # Download image using unified downloader - downloader = await get_downloader() - # Create a temporary file to save the downloaded image - with tempfile.NamedTemporaryFile(delete=False, suffix='.jpg') as temp_file: - temp_path = temp_file.name - - success, result = await downloader.download_file( - image_url, - temp_path, - use_auth=False # Image downloads typically don't need auth - ) - - if not success: - return web.json_response({ - "error": f"Failed to download image from URL: {result}", - "loras": [] - }, status=400) - - # Use meta field from image_info as metadata - if 'meta' in image_info: - metadata = image_info['meta'] - - # If metadata wasn't obtained from Civitai API, extract it from the image - if metadata is None: - # Extract metadata from the image using ExifUtils - metadata = ExifUtils.extract_image_metadata(temp_path) - - # If no metadata found, return a more specific error - if not metadata: - result = { - "error": "No metadata found in this image", - "loras": [] # Return empty loras array to prevent client-side errors - } - - # For URL mode, include the image data as base64 - if is_url_mode and temp_path: - with open(temp_path, "rb") as image_file: - result["image_base64"] = base64.b64encode(image_file.read()).decode('utf-8') - - return web.json_response(result, status=200) - - # Use the parser factory to get the appropriate parser - parser = RecipeParserFactory.create_parser(metadata) - - if parser is None: - result = { - "error": "No parser found for this image", - "loras": [] # Return empty loras array to prevent client-side errors - } - - # For URL mode, include the image data as base64 - if is_url_mode and temp_path: - with open(temp_path, "rb") as image_file: - result["image_base64"] = base64.b64encode(image_file.read()).decode('utf-8') - - return web.json_response(result, status=200) - - # Parse the metadata - result = await parser.parse_metadata( - metadata, - recipe_scanner=self.recipe_scanner - ) - - # For URL mode, include the image data as base64 - if is_url_mode and temp_path: - with open(temp_path, "rb") as image_file: - result["image_base64"] = base64.b64encode(image_file.read()).decode('utf-8') - - # Check for errors - if "error" in result and not result.get("loras"): - return web.json_response(result, status=200) - - # Calculate fingerprint from parsed loras - from ..utils.utils import calculate_recipe_fingerprint - fingerprint = calculate_recipe_fingerprint(result.get("loras", [])) - - # Add fingerprint to result - result["fingerprint"] = fingerprint - - # Find matching recipes with the same fingerprint - matching_recipes = [] - if fingerprint: - matching_recipes = await self.recipe_scanner.find_recipes_by_fingerprint(fingerprint) - - # Add matching recipes to result - result["matching_recipes"] = matching_recipes - - return web.json_response(result) - - except Exception as e: - logger.error(f"Error analyzing recipe image: {e}", exc_info=True) - return web.json_response({ - "error": str(e), - "loras": [] # Return empty loras array to prevent client-side errors - }, status=500) - finally: - # Clean up the temporary file in the finally block - if temp_path and os.path.exists(temp_path): - try: - os.unlink(temp_path) - except Exception as e: - logger.error(f"Error deleting temporary file: {e}") - - async def analyze_local_image(self, request: web.Request) -> web.Response: - """Analyze a local image file for recipe metadata""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - # Get JSON data from request - data = await request.json() - file_path = data.get('path') - - if not file_path: - return web.json_response({ - 'error': 'No file path provided', - 'loras': [] - }, status=400) - - # Normalize file path for cross-platform compatibility - file_path = os.path.normpath(file_path.strip('"').strip("'")) - - # Validate that the file exists - if not os.path.isfile(file_path): - return web.json_response({ - 'error': 'File not found', - 'loras': [] - }, status=404) - - # Extract metadata from the image using ExifUtils - metadata = ExifUtils.extract_image_metadata(file_path) - - # If no metadata found, return error - if not metadata: - # Get base64 image data - with open(file_path, "rb") as image_file: - image_base64 = base64.b64encode(image_file.read()).decode('utf-8') - - return web.json_response({ - "error": "No metadata found in this image", - "loras": [], # Return empty loras array to prevent client-side errors - "image_base64": image_base64 - }, status=200) - - # Use the parser factory to get the appropriate parser - parser = RecipeParserFactory.create_parser(metadata) - - if parser is None: - # Get base64 image data - with open(file_path, "rb") as image_file: - image_base64 = base64.b64encode(image_file.read()).decode('utf-8') - - return web.json_response({ - "error": "No parser found for this image", - "loras": [], # Return empty loras array to prevent client-side errors - "image_base64": image_base64 - }, status=200) - - # Parse the metadata - result = await parser.parse_metadata( - metadata, - recipe_scanner=self.recipe_scanner - ) - - # Add base64 image data to result - with open(file_path, "rb") as image_file: - result["image_base64"] = base64.b64encode(image_file.read()).decode('utf-8') - - # Check for errors - if "error" in result and not result.get("loras"): - return web.json_response(result, status=200) - - # Calculate fingerprint from parsed loras - from ..utils.utils import calculate_recipe_fingerprint - fingerprint = calculate_recipe_fingerprint(result.get("loras", [])) - - # Add fingerprint to result - result["fingerprint"] = fingerprint - - # Find matching recipes with the same fingerprint - matching_recipes = [] - if fingerprint: - matching_recipes = await self.recipe_scanner.find_recipes_by_fingerprint(fingerprint) - - # Add matching recipes to result - result["matching_recipes"] = matching_recipes - - return web.json_response(result) - - except Exception as e: - logger.error(f"Error analyzing local image: {e}", exc_info=True) - return web.json_response({ - 'error': str(e), - 'loras': [] # Return empty loras array to prevent client-side errors - }, status=500) - - async def save_recipe(self, request: web.Request) -> web.Response: - """Save a recipe to the recipes folder""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - reader = await request.multipart() - - # Process form data - image = None - image_base64 = None - image_url = None - name = None - tags = [] - metadata = None - - while True: - field = await reader.next() - if field is None: - break - - if field.name == 'image': - # Read image data - image_data = b'' - while True: - chunk = await field.read_chunk() - if not chunk: - break - image_data += chunk - image = image_data - - elif field.name == 'image_base64': - # Get base64 image data - image_base64 = await field.text() - - elif field.name == 'image_url': - # Get image URL - image_url = await field.text() - - elif field.name == 'name': - name = await field.text() - - elif field.name == 'tags': - tags_text = await field.text() - try: - tags = json.loads(tags_text) - except: - tags = [] - - elif field.name == 'metadata': - metadata_text = await field.text() - try: - metadata = json.loads(metadata_text) - except: - metadata = {} - - missing_fields = [] - if not name: - missing_fields.append("name") - if not metadata: - missing_fields.append("metadata") - if missing_fields: - return web.json_response({"error": f"Missing required fields: {', '.join(missing_fields)}"}, status=400) - - # Handle different image sources - if not image: - if image_base64: - # Convert base64 to binary - try: - # Remove potential data URL prefix - if ',' in image_base64: - image_base64 = image_base64.split(',', 1)[1] - image = base64.b64decode(image_base64) - except Exception as e: - return web.json_response({"error": f"Invalid base64 image data: {str(e)}"}, status=400) - else: - return web.json_response({"error": "No image data provided"}, status=400) - - # Create recipes directory if it doesn't exist - recipes_dir = self.recipe_scanner.recipes_dir - os.makedirs(recipes_dir, exist_ok=True) - - # Generate UUID for the recipe - import uuid - recipe_id = str(uuid.uuid4()) - - # Optimize the image (resize and convert to WebP) - optimized_image, extension = ExifUtils.optimize_image( - image_data=image, - target_width=CARD_PREVIEW_WIDTH, - format='webp', - quality=85, - preserve_metadata=True - ) - - # Save the optimized image - image_filename = f"{recipe_id}{extension}" - image_path = os.path.join(recipes_dir, image_filename) - with open(image_path, 'wb') as f: - f.write(optimized_image) - - # Create the recipe data structure - current_time = time.time() - - # Format loras data according to the recipe.json format - loras_data = [] - for lora in metadata.get("loras", []): - # Modified: Always include deleted LoRAs in the recipe metadata - # Even if they're marked to be excluded, we still keep their identifying information - # The exclude flag will only be used to determine if they should be included in recipe syntax - - # Convert frontend lora format to recipe format - lora_entry = { - "file_name": lora.get("file_name", "") or os.path.splitext(os.path.basename(lora.get("localPath", "")))[0] if lora.get("localPath") else "", - "hash": lora.get("hash", "").lower() if lora.get("hash") else "", - "strength": float(lora.get("weight", 1.0)), - "modelVersionId": lora.get("id", 0), - "modelName": lora.get("name", ""), - "modelVersionName": lora.get("version", ""), - "isDeleted": lora.get("isDeleted", False), # Preserve deletion status in saved recipe - "exclude": lora.get("exclude", False) # Add exclude flag to the recipe - } - loras_data.append(lora_entry) - - # Format gen_params according to the recipe.json format - gen_params = metadata.get("gen_params", {}) - if not gen_params and "raw_metadata" in metadata: - # Extract from raw metadata if available - raw_metadata = metadata.get("raw_metadata", {}) - gen_params = { - "prompt": raw_metadata.get("prompt", ""), - "negative_prompt": raw_metadata.get("negative_prompt", ""), - "checkpoint": raw_metadata.get("checkpoint", {}), - "steps": raw_metadata.get("steps", ""), - "sampler": raw_metadata.get("sampler", ""), - "cfg_scale": raw_metadata.get("cfg_scale", ""), - "seed": raw_metadata.get("seed", ""), - "size": raw_metadata.get("size", ""), - "clip_skip": raw_metadata.get("clip_skip", "") - } - - # Calculate recipe fingerprint - from ..utils.utils import calculate_recipe_fingerprint - fingerprint = calculate_recipe_fingerprint(loras_data) - - # Create the recipe data structure - recipe_data = { - "id": recipe_id, - "file_path": image_path, - "title": name, - "modified": current_time, - "created_date": current_time, - "base_model": metadata.get("base_model", ""), - "loras": loras_data, - "gen_params": gen_params, - "fingerprint": fingerprint - } - - # Add tags if provided - if tags: - recipe_data["tags"] = tags - - # Add source_path if provided in metadata - if metadata.get("source_path"): - recipe_data["source_path"] = metadata.get("source_path") - - # Save the recipe JSON - json_filename = f"{recipe_id}.recipe.json" - json_path = os.path.join(recipes_dir, json_filename) - with open(json_path, 'w', encoding='utf-8') as f: - json.dump(recipe_data, f, indent=4, ensure_ascii=False) - - # Add recipe metadata to the image - ExifUtils.append_recipe_metadata(image_path, recipe_data) - - # Check for duplicates - matching_recipes = [] - if fingerprint: - matching_recipes = await self.recipe_scanner.find_recipes_by_fingerprint(fingerprint) - # Remove current recipe from matches - if recipe_id in matching_recipes: - matching_recipes.remove(recipe_id) - - # Simplified cache update approach - # Instead of trying to update the cache directly, just set it to None - # to force a refresh on the next get_cached_data call - if self.recipe_scanner._cache is not None: - # Add the recipe to the raw data if the cache exists - # This is a simple direct update without locks or timeouts - self.recipe_scanner._cache.raw_data.append(recipe_data) - # Schedule a background task to resort the cache - asyncio.create_task(self.recipe_scanner._cache.resort()) - logger.info(f"Added recipe {recipe_id} to cache") - - return web.json_response({ - 'success': True, - 'recipe_id': recipe_id, - 'image_path': image_path, - 'json_path': json_path, - 'matching_recipes': matching_recipes - }) - - except Exception as e: - logger.error(f"Error saving recipe: {e}", exc_info=True) - return web.json_response({"error": str(e)}, status=500) - - async def delete_recipe(self, request: web.Request) -> web.Response: - """Delete a recipe by ID""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - recipe_id = request.match_info['recipe_id'] - - # Get recipes directory - recipes_dir = self.recipe_scanner.recipes_dir - if not recipes_dir or not os.path.exists(recipes_dir): - return web.json_response({"error": "Recipes directory not found"}, status=404) - - # Find recipe JSON file - recipe_json_path = os.path.join(recipes_dir, f"{recipe_id}.recipe.json") - if not os.path.exists(recipe_json_path): - return web.json_response({"error": "Recipe not found"}, status=404) - - # Load recipe data to get image path - with open(recipe_json_path, 'r', encoding='utf-8') as f: - recipe_data = json.load(f) - - # Get image path - image_path = recipe_data.get('file_path') - - # Delete recipe JSON file - os.remove(recipe_json_path) - logger.info(f"Deleted recipe JSON file: {recipe_json_path}") - - # Delete recipe image if it exists - if image_path and os.path.exists(image_path): - os.remove(image_path) - logger.info(f"Deleted recipe image: {image_path}") - - # Simplified cache update approach - if self.recipe_scanner._cache is not None: - # Remove the recipe from raw_data if it exists - self.recipe_scanner._cache.raw_data = [ - r for r in self.recipe_scanner._cache.raw_data - if str(r.get('id', '')) != recipe_id - ] - # Schedule a background task to resort the cache - asyncio.create_task(self.recipe_scanner._cache.resort()) - logger.info(f"Removed recipe {recipe_id} from cache") - - return web.json_response({"success": True, "message": "Recipe deleted successfully"}) - except Exception as e: - logger.error(f"Error deleting recipe: {e}", exc_info=True) - return web.json_response({"error": str(e)}, status=500) - - async def get_top_tags(self, request: web.Request) -> web.Response: - """Get top tags used in recipes""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - # Get limit parameter with default - limit = int(request.query.get('limit', '20')) - - # Get all recipes from cache - cache = await self.recipe_scanner.get_cached_data() - - # Count tag occurrences - tag_counts = {} - for recipe in cache.raw_data: - if 'tags' in recipe and recipe['tags']: - for tag in recipe['tags']: - tag_counts[tag] = tag_counts.get(tag, 0) + 1 - - # Sort tags by count and limit results - sorted_tags = [{'tag': tag, 'count': count} for tag, count in tag_counts.items()] - sorted_tags.sort(key=lambda x: x['count'], reverse=True) - top_tags = sorted_tags[:limit] - - return web.json_response({ - 'success': True, - 'tags': top_tags - }) - except Exception as e: - logger.error(f"Error retrieving top tags: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def get_base_models(self, request: web.Request) -> web.Response: - """Get base models used in recipes""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - # Get all recipes from cache - cache = await self.recipe_scanner.get_cached_data() - - # Count base model occurrences - base_model_counts = {} - for recipe in cache.raw_data: - if 'base_model' in recipe and recipe['base_model']: - base_model = recipe['base_model'] - base_model_counts[base_model] = base_model_counts.get(base_model, 0) + 1 - - # Sort base models by count - sorted_models = [{'name': model, 'count': count} for model, count in base_model_counts.items()] - sorted_models.sort(key=lambda x: x['count'], reverse=True) - - return web.json_response({ - 'success': True, - 'base_models': sorted_models - }) - except Exception as e: - logger.error(f"Error retrieving base models: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e)} - , status=500) - - async def share_recipe(self, request: web.Request) -> web.Response: - """Process a recipe image for sharing by adding metadata to EXIF""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - recipe_id = request.match_info['recipe_id'] - - # Get all recipes from cache - cache = await self.recipe_scanner.get_cached_data() - - # Find the specific recipe - recipe = next((r for r in cache.raw_data if str(r.get('id', '')) == recipe_id), None) - - if not recipe: - return web.json_response({"error": "Recipe not found"}, status=404) - - # Get the image path - image_path = recipe.get('file_path') - if not image_path or not os.path.exists(image_path): - return web.json_response({"error": "Recipe image not found"}, status=404) - - # Create a temporary copy of the image to modify - import tempfile - import shutil - - # Create temp file with same extension - ext = os.path.splitext(image_path)[1] - with tempfile.NamedTemporaryFile(suffix=ext, delete=False) as temp_file: - temp_path = temp_file.name - - # Copy the original image to temp file - shutil.copy2(image_path, temp_path) - processed_path = temp_path - - # Create a URL for the processed image - # Use a timestamp to prevent caching - timestamp = int(time.time()) - url_path = f"/api/recipe/{recipe_id}/share/download?t={timestamp}" - - # Store the temp path in a dictionary to serve later - if not hasattr(self, '_shared_recipes'): - self._shared_recipes = {} - - self._shared_recipes[recipe_id] = { - 'path': processed_path, - 'timestamp': timestamp, - 'expires': time.time() + 300 # Expire after 5 minutes - } - - # Clean up old entries - self._cleanup_shared_recipes() - - return web.json_response({ - 'success': True, - 'download_url': url_path, - 'filename': f"recipe_{recipe.get('title', '').replace(' ', '_').lower()}{ext}" - }) - except Exception as e: - logger.error(f"Error sharing recipe: {e}", exc_info=True) - return web.json_response({"error": str(e)}, status=500) - - async def download_shared_recipe(self, request: web.Request) -> web.Response: - """Serve a processed recipe image for download""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - recipe_id = request.match_info['recipe_id'] - - # Check if we have this shared recipe - if not hasattr(self, '_shared_recipes') or recipe_id not in self._shared_recipes: - return web.json_response({"error": "Shared recipe not found or expired"}, status=404) - - shared_info = self._shared_recipes[recipe_id] - file_path = shared_info['path'] - - if not os.path.exists(file_path): - return web.json_response({"error": "Shared recipe file not found"}, status=404) - - # Get recipe to determine filename - cache = await self.recipe_scanner.get_cached_data() - recipe = next((r for r in cache.raw_data if str(r.get('id', '')) == recipe_id), None) - - # Set filename for download - filename = f"recipe_{recipe.get('title', '').replace(' ', '_').lower() if recipe else recipe_id}" - ext = os.path.splitext(file_path)[1] - download_filename = f"{filename}{ext}" - - # Serve the file - return web.FileResponse( - file_path, - headers={ - 'Content-Disposition': f'attachment; filename="{download_filename}"' - } - ) - except Exception as e: - logger.error(f"Error downloading shared recipe: {e}", exc_info=True) - return web.json_response({"error": str(e)}, status=500) - - def _cleanup_shared_recipes(self): - """Clean up expired shared recipes""" - if not hasattr(self, '_shared_recipes'): - return - - current_time = time.time() - expired_ids = [rid for rid, info in self._shared_recipes.items() - if current_time > info.get('expires', 0)] - - for rid in expired_ids: - try: - # Delete the temporary file - file_path = self._shared_recipes[rid]['path'] - if os.path.exists(file_path): - os.unlink(file_path) - - # Remove from dictionary - del self._shared_recipes[rid] - except Exception as e: - logger.error(f"Error cleaning up shared recipe {rid}: {e}") - - async def save_recipe_from_widget(self, request: web.Request) -> web.Response: - """Save a recipe from the LoRAs widget""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - # Get metadata using the metadata collector instead of workflow parsing - raw_metadata = get_metadata() - metadata_dict = MetadataProcessor.to_dict(raw_metadata) - - # Check if we have valid metadata - if not metadata_dict: - return web.json_response({"error": "No generation metadata found"}, status=400) - - # Get the most recent image from metadata registry instead of temp directory - if not standalone_mode: - metadata_registry = MetadataRegistry() - latest_image = metadata_registry.get_first_decoded_image() - else: - latest_image = None - - if latest_image is None: - return web.json_response({"error": "No recent images found to use for recipe. Try generating an image first."}, status=400) - - # Convert the image data to bytes - handle tuple and tensor cases - logger.debug(f"Image type: {type(latest_image)}") - - try: - # Handle the tuple case first - if isinstance(latest_image, tuple): - # Extract the tensor from the tuple - if len(latest_image) > 0: - tensor_image = latest_image[0] - else: - return web.json_response({"error": "Empty image tuple received"}, status=400) - else: - tensor_image = latest_image - - # Get the shape info for debugging - if hasattr(tensor_image, 'shape'): - shape_info = tensor_image.shape - logger.debug(f"Tensor shape: {shape_info}, dtype: {tensor_image.dtype}") - - import torch - - # Convert tensor to numpy array - if isinstance(tensor_image, torch.Tensor): - image_np = tensor_image.cpu().numpy() - else: - image_np = np.array(tensor_image) - - # Handle different tensor shapes - # Case: (1, 1, H, W, 3) or (1, H, W, 3) - batch or multi-batch - if len(image_np.shape) > 3: - # Remove batch dimensions until we get to (H, W, 3) - while len(image_np.shape) > 3: - image_np = image_np[0] - - # If values are in [0, 1] range, convert to [0, 255] - if image_np.dtype == np.float32 or image_np.dtype == np.float64: - if image_np.max() <= 1.0: - image_np = (image_np * 255).astype(np.uint8) - - # Ensure image is in the right format (HWC with RGB channels) - if len(image_np.shape) == 3 and image_np.shape[2] == 3: - pil_image = Image.fromarray(image_np) - img_byte_arr = io.BytesIO() - pil_image.save(img_byte_arr, format='PNG') - image = img_byte_arr.getvalue() - else: - return web.json_response({"error": f"Cannot handle this data shape: {image_np.shape}, {image_np.dtype}"}, status=400) - except Exception as e: - logger.error(f"Error processing image data: {str(e)}", exc_info=True) - return web.json_response({"error": f"Error processing image: {str(e)}"}, status=400) - - # Get the lora stack from the metadata - lora_stack = metadata_dict.get("loras", "") - - # Parse the lora stack format: " ..." - import re - lora_matches = re.findall(r']+)>', lora_stack) - - # Check if any loras were found - if not lora_matches: - return web.json_response({"error": "No LoRAs found in the generation metadata"}, status=400) - - # Generate recipe name from the first 3 loras (or less if fewer are available) - loras_for_name = lora_matches[:3] # Take at most 3 loras for the name - - recipe_name_parts = [] - for lora_name, lora_strength in loras_for_name: - # Get the basename without path or extension - basename = os.path.basename(lora_name) - basename = os.path.splitext(basename)[0] - recipe_name_parts.append(f"{basename}:{lora_strength}") - - recipe_name = " ".join(recipe_name_parts) - - # Create recipes directory if it doesn't exist - recipes_dir = self.recipe_scanner.recipes_dir - os.makedirs(recipes_dir, exist_ok=True) - - # Generate UUID for the recipe - import uuid - recipe_id = str(uuid.uuid4()) - - # Optimize the image (resize and convert to WebP) - optimized_image, extension = ExifUtils.optimize_image( - image_data=image, - target_width=CARD_PREVIEW_WIDTH, - format='webp', - quality=85, - preserve_metadata=True - ) - - # Save the optimized image - image_filename = f"{recipe_id}{extension}" - image_path = os.path.join(recipes_dir, image_filename) - with open(image_path, 'wb') as f: - f.write(optimized_image) - - # Format loras data from the lora stack - loras_data = [] - - for lora_name, lora_strength in lora_matches: - try: - # Get lora info from scanner - lora_info = await self.recipe_scanner._lora_scanner.get_model_info_by_name(lora_name) - - # Create lora entry - lora_entry = { - "file_name": lora_name, - "hash": lora_info.get("sha256", "").lower() if lora_info else "", - "strength": float(lora_strength), - "modelVersionId": lora_info.get("civitai", {}).get("id", 0) if lora_info else 0, - "modelName": lora_info.get("civitai", {}).get("model", {}).get("name", "") if lora_info else lora_name, - "modelVersionName": lora_info.get("civitai", {}).get("name", "") if lora_info else "", - "isDeleted": False - } - loras_data.append(lora_entry) - except Exception as e: - logger.warning(f"Error processing LoRA {lora_name}: {e}") - - # Get base model from lora scanner for the available loras - base_model_counts = {} - for lora in loras_data: - lora_info = await self.recipe_scanner._lora_scanner.get_model_info_by_name(lora.get("file_name", "")) - if lora_info and "base_model" in lora_info: - base_model = lora_info["base_model"] - base_model_counts[base_model] = base_model_counts.get(base_model, 0) + 1 - - # Get most common base model - most_common_base_model = "" - if base_model_counts: - most_common_base_model = max(base_model_counts.items(), key=lambda x: x[1])[0] - - # Create the recipe data structure - recipe_data = { - "id": recipe_id, - "file_path": image_path, - "title": recipe_name, # Use generated recipe name - "modified": time.time(), - "created_date": time.time(), - "base_model": most_common_base_model, - "loras": loras_data, - "checkpoint": metadata_dict.get("checkpoint", ""), - "gen_params": {key: value for key, value in metadata_dict.items() - if key not in ['checkpoint', 'loras']}, - "loras_stack": lora_stack # Include the original lora stack string - } - - # Save the recipe JSON - json_filename = f"{recipe_id}.recipe.json" - json_path = os.path.join(recipes_dir, json_filename) - with open(json_path, 'w', encoding='utf-8') as f: - json.dump(recipe_data, f, indent=4, ensure_ascii=False) - - # Add recipe metadata to the image - ExifUtils.append_recipe_metadata(image_path, recipe_data) - - # Update cache - if self.recipe_scanner._cache is not None: - # Add the recipe to the raw data if the cache exists - self.recipe_scanner._cache.raw_data.append(recipe_data) - # Schedule a background task to resort the cache - asyncio.create_task(self.recipe_scanner._cache.resort()) - logger.info(f"Added recipe {recipe_id} to cache") - - return web.json_response({ - 'success': True, - 'recipe_id': recipe_id, - 'image_path': image_path, - 'json_path': json_path, - 'recipe_name': recipe_name # Include the generated recipe name in the response - }) - - except Exception as e: - logger.error(f"Error saving recipe from widget: {e}", exc_info=True) - return web.json_response({"error": str(e)}, status=500) - - async def get_recipe_syntax(self, request: web.Request) -> web.Response: - """Generate recipe syntax for LoRAs in the recipe, looking up proper file names using hash_index""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - recipe_id = request.match_info['recipe_id'] - - # Get all recipes from cache - cache = await self.recipe_scanner.get_cached_data() - - # Find the specific recipe - recipe = next((r for r in cache.raw_data if str(r.get('id', '')) == recipe_id), None) - - if not recipe: - return web.json_response({"error": "Recipe not found"}, status=404) - - # Get the loras from the recipe - loras = recipe.get('loras', []) - - if not loras: - return web.json_response({"error": "No LoRAs found in this recipe"}, status=400) - - # Generate recipe syntax for all LoRAs that: - # 1. Are in the library (not deleted) OR - # 2. Are deleted but not marked for exclusion - lora_syntax_parts = [] - - # Access the hash_index from lora_scanner - hash_index = self.recipe_scanner._lora_scanner._hash_index - - for lora in loras: - # Skip loras that are deleted AND marked for exclusion - if lora.get("isDeleted", False): - continue - - if not self.recipe_scanner._lora_scanner.has_hash(lora.get("hash", "")): - continue - - # Get the strength - strength = lora.get("strength", 1.0) - - # Try to find the actual file name for this lora - file_name = None - hash_value = lora.get("hash", "").lower() - - if hash_value and hasattr(hash_index, "_hash_to_path"): - # Look up the file path from the hash - file_path = hash_index._hash_to_path.get(hash_value) - - if file_path: - # Extract the file name without extension from the path - file_name = os.path.splitext(os.path.basename(file_path))[0] - - # If hash lookup failed, fall back to modelVersionId lookup - if not file_name and lora.get("modelVersionId"): - # Search for files with matching modelVersionId - all_loras = await self.recipe_scanner._lora_scanner.get_cached_data() - for cached_lora in all_loras.raw_data: - if not cached_lora.get("civitai"): - continue - if cached_lora.get("civitai", {}).get("id") == lora.get("modelVersionId"): - file_name = os.path.splitext(os.path.basename(cached_lora["path"]))[0] - break - - # If all lookups failed, use the file_name from the recipe - if not file_name: - file_name = lora.get("file_name", "unknown-lora") - - # Add to syntax parts - lora_syntax_parts.append(f"") - - # Join the LoRA syntax parts - lora_syntax = " ".join(lora_syntax_parts) - - return web.json_response({ - 'success': True, - 'syntax': lora_syntax - }) - except Exception as e: - logger.error(f"Error generating recipe syntax: {e}", exc_info=True) - return web.json_response({"error": str(e)}, status=500) - - async def update_recipe(self, request: web.Request) -> web.Response: - """Update recipe metadata (name and tags)""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - recipe_id = request.match_info['recipe_id'] - data = await request.json() - - # Validate required fields - if 'title' not in data and 'tags' not in data and 'source_path' not in data and 'preview_nsfw_level' not in data: - return web.json_response({ - "error": "At least one field to update must be provided (title or tags or source_path or preview_nsfw_level)" - }, status=400) - - # Use the recipe scanner's update method - success = await self.recipe_scanner.update_recipe_metadata(recipe_id, data) - - if not success: - return web.json_response({"error": "Recipe not found or update failed"}, status=404) - - return web.json_response({ - "success": True, - "recipe_id": recipe_id, - "updates": data - }) - except Exception as e: - logger.error(f"Error updating recipe: {e}", exc_info=True) - return web.json_response({"error": str(e)}, status=500) - - async def reconnect_lora(self, request: web.Request) -> web.Response: - """Reconnect a deleted LoRA in a recipe to a local LoRA file""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - # Parse request data - data = await request.json() - - # Validate required fields - required_fields = ['recipe_id', 'lora_index', 'target_name'] - for field in required_fields: - if field not in data: - return web.json_response({ - "error": f"Missing required field: {field}" - }, status=400) - - recipe_id = data['recipe_id'] - lora_index = int(data['lora_index']) - target_name = data['target_name'] - - # Get recipe scanner - scanner = self.recipe_scanner - lora_scanner = scanner._lora_scanner - - # Check if recipe exists - recipe_path = os.path.join(scanner.recipes_dir, f"{recipe_id}.recipe.json") - if not os.path.exists(recipe_path): - return web.json_response({"error": "Recipe not found"}, status=404) - - # Find target LoRA by name - target_lora = await lora_scanner.get_model_info_by_name(target_name) - if not target_lora: - return web.json_response({"error": f"Local LoRA not found with name: {target_name}"}, status=404) - - # Load recipe data - with open(recipe_path, 'r', encoding='utf-8') as f: - recipe_data = json.load(f) - - lora = recipe_data.get("loras", [])[lora_index] if lora_index < len(recipe_data.get('loras', [])) else None - - if lora is None: - return web.json_response({"error": "LoRA index out of range in recipe"}, status=404) - - # Update LoRA data - lora['isDeleted'] = False - lora['exclude'] = False - lora['file_name'] = target_name - - # Update with information from the target LoRA - if 'sha256' in target_lora: - lora['hash'] = target_lora['sha256'].lower() - if target_lora.get("civitai"): - lora['modelName'] = target_lora['civitai']['model']['name'] - lora['modelVersionName'] = target_lora['civitai']['name'] - lora['modelVersionId'] = target_lora['civitai']['id'] - - updated_lora = dict(lora) # Make a copy for response - - # Recalculate recipe fingerprint after updating LoRA - from ..utils.utils import calculate_recipe_fingerprint - recipe_data['fingerprint'] = calculate_recipe_fingerprint(recipe_data.get('loras', [])) - - # Save updated recipe - with open(recipe_path, 'w', encoding='utf-8') as f: - json.dump(recipe_data, f, indent=4, ensure_ascii=False) - - updated_lora['inLibrary'] = True - updated_lora['preview_url'] = config.get_preview_static_url(target_lora['preview_url']) - updated_lora['localPath'] = target_lora['file_path'] - - # Update in cache if it exists - if scanner._cache is not None: - for cache_item in scanner._cache.raw_data: - if cache_item.get('id') == recipe_id: - # Replace loras array with updated version - cache_item['loras'] = recipe_data['loras'] - # Update fingerprint in cache - cache_item['fingerprint'] = recipe_data['fingerprint'] - - # Resort the cache - asyncio.create_task(scanner._cache.resort()) - break - - # Update EXIF metadata if image exists - image_path = recipe_data.get('file_path') - if image_path and os.path.exists(image_path): - from ..utils.exif_utils import ExifUtils - ExifUtils.append_recipe_metadata(image_path, recipe_data) - - # Find other recipes with the same fingerprint - matching_recipes = [] - if 'fingerprint' in recipe_data: - matching_recipes = await scanner.find_recipes_by_fingerprint(recipe_data['fingerprint']) - # Remove current recipe from matches - if recipe_id in matching_recipes: - matching_recipes.remove(recipe_id) - - return web.json_response({ - "success": True, - "recipe_id": recipe_id, - "updated_lora": updated_lora, - "matching_recipes": matching_recipes - }) - - except Exception as e: - logger.error(f"Error reconnecting LoRA: {e}", exc_info=True) - return web.json_response({"error": str(e)}, status=500) - - async def get_recipes_for_lora(self, request: web.Request) -> web.Response: - """Get recipes that use a specific Lora""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - lora_hash = request.query.get('hash') - - # Hash is required - if not lora_hash: - return web.json_response({'success': False, 'error': 'Lora hash is required'}, status=400) - - # Log the search parameters - logger.debug(f"Getting recipes for Lora by hash: {lora_hash}") - - # Get all recipes from cache - cache = await self.recipe_scanner.get_cached_data() - - # Filter recipes that use this Lora by hash - matching_recipes = [] - for recipe in cache.raw_data: - # Check if any of the recipe's loras match this hash - loras = recipe.get('loras', []) - for lora in loras: - if lora.get('hash', '').lower() == lora_hash.lower(): - matching_recipes.append(recipe) - break # No need to check other loras in this recipe - - # Process the recipes similar to get_paginated_data to ensure all needed data is available - for recipe in matching_recipes: - # Add inLibrary information for each lora - if 'loras' in recipe: - for lora in recipe['loras']: - if 'hash' in lora and lora['hash']: - lora['inLibrary'] = self.recipe_scanner._lora_scanner.has_hash(lora['hash'].lower()) - lora['preview_url'] = self.recipe_scanner._lora_scanner.get_preview_url_by_hash(lora['hash'].lower()) - lora['localPath'] = self.recipe_scanner._lora_scanner.get_path_by_hash(lora['hash'].lower()) - - # Ensure file_url is set (needed by frontend) - if 'file_path' in recipe: - recipe['file_url'] = self._format_recipe_file_url(recipe['file_path']) - else: - recipe['file_url'] = '/loras_static/images/no-preview.png' - - return web.json_response({'success': True, 'recipes': matching_recipes}) - except Exception as e: - logger.error(f"Error getting recipes for Lora: {str(e)}") - return web.json_response({'success': False, 'error': str(e)}, status=500) - - async def scan_recipes(self, request: web.Request) -> web.Response: - """API endpoint for scanning and rebuilding the recipe cache""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - # Force refresh the recipe cache - logger.info("Manually triggering recipe cache rebuild") - await self.recipe_scanner.get_cached_data(force_refresh=True) - - return web.json_response({ - 'success': True, - 'message': 'Recipe cache refreshed successfully' - }) - except Exception as e: - logger.error(f"Error refreshing recipe cache: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def find_duplicates(self, request: web.Request) -> web.Response: - """Find all duplicate recipes based on fingerprints""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - # Get all duplicate recipes - duplicate_groups = await self.recipe_scanner.find_all_duplicate_recipes() - - # Create response data with additional recipe information - response_data = [] - - for fingerprint, recipe_ids in duplicate_groups.items(): - # Skip groups with only one recipe (not duplicates) - if len(recipe_ids) <= 1: - continue - - # Get recipe details for each recipe in the group - recipes = [] - for recipe_id in recipe_ids: - recipe = await self.recipe_scanner.get_recipe_by_id(recipe_id) - if recipe: - # Add only needed fields to keep response size manageable - recipes.append({ - 'id': recipe.get('id'), - 'title': recipe.get('title'), - 'file_url': recipe.get('file_url') or self._format_recipe_file_url(recipe.get('file_path', '')), - 'modified': recipe.get('modified'), - 'created_date': recipe.get('created_date'), - 'lora_count': len(recipe.get('loras', [])), - }) - - # Only include groups with at least 2 valid recipes - if len(recipes) >= 2: - # Sort recipes by modified date (newest first) - recipes.sort(key=lambda x: x.get('modified', 0), reverse=True) - - response_data.append({ - 'fingerprint': fingerprint, - 'count': len(recipes), - 'recipes': recipes - }) - - # Sort groups by count (highest first) - response_data.sort(key=lambda x: x['count'], reverse=True) - - return web.json_response({ - 'success': True, - 'duplicate_groups': response_data - }) - - except Exception as e: - logger.error(f"Error finding duplicate recipes: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - async def bulk_delete(self, request: web.Request) -> web.Response: - """Delete multiple recipes by ID""" - try: - # Ensure services are initialized - await self.ensure_dependencies_ready() - - # Parse request data - data = await request.json() - recipe_ids = data.get('recipe_ids', []) - - if not recipe_ids: - return web.json_response({ - 'success': False, - 'error': 'No recipe IDs provided' - }, status=400) - - # Get recipes directory - recipes_dir = self.recipe_scanner.recipes_dir - if not recipes_dir or not os.path.exists(recipes_dir): - return web.json_response({ - 'success': False, - 'error': 'Recipes directory not found' - }, status=404) - - # Track deleted and failed recipes - deleted_recipes = [] - failed_recipes = [] - - # Process each recipe ID - for recipe_id in recipe_ids: - # Find recipe JSON file - recipe_json_path = os.path.join(recipes_dir, f"{recipe_id}.recipe.json") - - if not os.path.exists(recipe_json_path): - failed_recipes.append({ - 'id': recipe_id, - 'reason': 'Recipe not found' - }) - continue - - try: - # Load recipe data to get image path - with open(recipe_json_path, 'r', encoding='utf-8') as f: - recipe_data = json.load(f) - - # Get image path - image_path = recipe_data.get('file_path') - - # Delete recipe JSON file - os.remove(recipe_json_path) - - # Delete recipe image if it exists - if image_path and os.path.exists(image_path): - os.remove(image_path) - - deleted_recipes.append(recipe_id) - - except Exception as e: - failed_recipes.append({ - 'id': recipe_id, - 'reason': str(e) - }) - - # Update cache if any recipes were deleted - if deleted_recipes and self.recipe_scanner._cache is not None: - # Remove deleted recipes from raw_data - self.recipe_scanner._cache.raw_data = [ - r for r in self.recipe_scanner._cache.raw_data - if r.get('id') not in deleted_recipes - ] - # Resort the cache - asyncio.create_task(self.recipe_scanner._cache.resort()) - logger.info(f"Removed {len(deleted_recipes)} recipes from cache") - - return web.json_response({ - 'success': True, - 'deleted': deleted_recipes, - 'failed': failed_recipes, - 'total_deleted': len(deleted_recipes), - 'total_failed': len(failed_recipes) - }) - - except Exception as e: - logger.error(f"Error performing bulk delete: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - # Legacy method aliases retained for compatibility with existing imports. - handle_recipes_page = render_page - get_recipes = list_recipes - get_recipe_detail = get_recipe - analyze_recipe_image = analyze_uploaded_image diff --git a/tests/routes/test_recipe_route_scaffolding.py b/tests/routes/test_recipe_route_scaffolding.py index 1f0e723d..59765d36 100644 --- a/tests/routes/test_recipe_route_scaffolding.py +++ b/tests/routes/test_recipe_route_scaffolding.py @@ -128,31 +128,38 @@ def test_register_startup_hooks_appends_once(): assert len(startup_bound_to_routes) == 2 -def test_to_route_mapping_uses_handler_owner(monkeypatch: pytest.MonkeyPatch): - class DummyOwner: - async def render_page(self, request): - return web.Response(text="ok") +def test_to_route_mapping_uses_handler_set(): + class DummyHandlerSet: + def __init__(self): + self.calls = 0 - async def list_recipes(self, request): # pragma: no cover - invoked via mapping - return web.json_response({}) + def to_route_mapping(self): + self.calls += 1 + + async def render_page(request): # pragma: no cover - simple coroutine + return web.Response(text="ok") + + return {"render_page": render_page} class DummyRoutes(base_routes_module.BaseRecipeRoutes): - def get_handler_owner(self): # noqa: D401 - simple override for test - return DummyOwner() + def __init__(self): + super().__init__() + self.created = 0 - monkeypatch.setattr( - base_routes_module.BaseRecipeRoutes, - "_HANDLER_NAMES", - ("render_page", "list_recipes"), - ) + def _create_handler_set(self): # noqa: D401 - simple override for test + self.created += 1 + return DummyHandlerSet() routes = DummyRoutes() mapping = routes.to_route_mapping() - assert set(mapping.keys()) == {"render_page", "list_recipes"} + assert set(mapping.keys()) == {"render_page"} assert asyncio.iscoroutinefunction(mapping["render_page"]) # Cached mapping reused on subsequent calls assert routes.to_route_mapping() is mapping + # Handler set cached for get_handler_owner callers + assert isinstance(routes.get_handler_owner(), DummyHandlerSet) + assert routes.created == 1 def test_recipe_route_registrar_binds_every_route(): From 097a68ad1862e26cf7f423d19569c8a126e5a64d Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Mon, 22 Sep 2025 13:25:21 +0800 Subject: [PATCH 064/110] refactor(recipes): introduce dedicated services for handlers --- py/routes/base_recipe_routes.py | 45 + py/routes/handlers/recipe_handlers.py | 905 ++++----------------- py/services/recipes/__init__.py | 23 + py/services/recipes/analysis_service.py | 289 +++++++ py/services/recipes/errors.py | 22 + py/services/recipes/persistence_service.py | 467 +++++++++++ py/services/recipes/sharing_service.py | 113 +++ tests/services/test_recipe_services.py | 146 ++++ 8 files changed, 1274 insertions(+), 736 deletions(-) create mode 100644 py/services/recipes/__init__.py create mode 100644 py/services/recipes/analysis_service.py create mode 100644 py/services/recipes/errors.py create mode 100644 py/services/recipes/persistence_service.py create mode 100644 py/services/recipes/sharing_service.py create mode 100644 tests/services/test_recipe_services.py diff --git a/py/routes/base_recipe_routes.py b/py/routes/base_recipe_routes.py index 59d4e7ec..4447bb7b 100644 --- a/py/routes/base_recipe_routes.py +++ b/py/routes/base_recipe_routes.py @@ -2,15 +2,25 @@ from __future__ import annotations import logging +import os from typing import Callable, Mapping import jinja2 from aiohttp import web from ..config import config +from ..recipes import RecipeParserFactory +from ..services.downloader import get_downloader +from ..services.recipes import ( + RecipeAnalysisService, + RecipePersistenceService, + RecipeSharingService, +) from ..services.server_i18n import server_i18n from ..services.service_registry import ServiceRegistry from ..services.settings_manager import settings +from ..utils.constants import CARD_PREVIEW_WIDTH +from ..utils.exif_utils import ExifUtils from .handlers.recipe_handlers import ( RecipeAnalysisHandler, RecipeHandlerSet, @@ -124,6 +134,37 @@ class BaseRecipeRoutes: recipe_scanner_getter = lambda: self.recipe_scanner civitai_client_getter = lambda: self.civitai_client + standalone_mode = os.environ.get("HF_HUB_DISABLE_TELEMETRY", "0") == "0" + if not standalone_mode: + from ..metadata_collector import get_metadata # type: ignore[import-not-found] + from ..metadata_collector.metadata_processor import ( # type: ignore[import-not-found] + MetadataProcessor, + ) + from ..metadata_collector.metadata_registry import ( # type: ignore[import-not-found] + MetadataRegistry, + ) + else: # pragma: no cover - optional dependency path + get_metadata = None # type: ignore[assignment] + MetadataProcessor = None # type: ignore[assignment] + MetadataRegistry = None # type: ignore[assignment] + + analysis_service = RecipeAnalysisService( + exif_utils=ExifUtils, + recipe_parser_factory=RecipeParserFactory, + downloader_factory=get_downloader, + metadata_collector=get_metadata, + metadata_processor_cls=MetadataProcessor, + metadata_registry_cls=MetadataRegistry, + standalone_mode=standalone_mode, + logger=logger, + ) + persistence_service = RecipePersistenceService( + exif_utils=ExifUtils, + card_preview_width=CARD_PREVIEW_WIDTH, + logger=logger, + ) + sharing_service = RecipeSharingService(logger=logger) + page_view = RecipePageView( ensure_dependencies_ready=self.ensure_dependencies_ready, settings_service=self.settings, @@ -148,17 +189,21 @@ class BaseRecipeRoutes: ensure_dependencies_ready=self.ensure_dependencies_ready, recipe_scanner_getter=recipe_scanner_getter, logger=logger, + persistence_service=persistence_service, + analysis_service=analysis_service, ) analysis = RecipeAnalysisHandler( ensure_dependencies_ready=self.ensure_dependencies_ready, recipe_scanner_getter=recipe_scanner_getter, civitai_client_getter=civitai_client_getter, logger=logger, + analysis_service=analysis_service, ) sharing = RecipeSharingHandler( ensure_dependencies_ready=self.ensure_dependencies_ready, recipe_scanner_getter=recipe_scanner_getter, logger=logger, + sharing_service=sharing_service, ) return RecipeHandlerSet( diff --git a/py/routes/handlers/recipe_handlers.py b/py/routes/handlers/recipe_handlers.py index 8d8f96bf..35f4c088 100644 --- a/py/routes/handlers/recipe_handlers.py +++ b/py/routes/handlers/recipe_handlers.py @@ -1,40 +1,25 @@ """Dedicated handler objects for recipe-related routes.""" from __future__ import annotations -import asyncio -import base64 -import io import json import logging import os -import tempfile -import time from dataclasses import dataclass from typing import Any, Awaitable, Callable, Dict, Mapping, Optional -import numpy as np from aiohttp import web -from PIL import Image from ...config import config -from ...recipes import RecipeParserFactory -from ...services.downloader import get_downloader from ...services.server_i18n import server_i18n as default_server_i18n from ...services.settings_manager import SettingsManager -from ...utils.constants import CARD_PREVIEW_WIDTH -from ...utils.exif_utils import ExifUtils - -# Check if running in standalone mode -standalone_mode = os.environ.get("HF_HUB_DISABLE_TELEMETRY", "0") == "0" - -if not standalone_mode: - from ...metadata_collector import get_metadata - from ...metadata_collector.metadata_processor import MetadataProcessor - from ...metadata_collector.metadata_registry import MetadataRegistry -else: # pragma: no cover - optional dependency path - get_metadata = None # type: ignore[assignment] - MetadataProcessor = None # type: ignore[assignment] - MetadataRegistry = None # type: ignore[assignment] +from ...services.recipes import ( + RecipeAnalysisService, + RecipeDownloadError, + RecipeNotFoundError, + RecipePersistenceService, + RecipeSharingService, + RecipeValidationError, +) Logger = logging.Logger EnsureDependenciesCallable = Callable[[], Awaitable[None]] @@ -457,22 +442,14 @@ class RecipeManagementHandler: ensure_dependencies_ready: EnsureDependenciesCallable, recipe_scanner_getter: RecipeScannerGetter, logger: Logger, - exif_utils=ExifUtils, - card_preview_width: int = CARD_PREVIEW_WIDTH, - metadata_collector: Optional[Callable[[], Any]] = get_metadata, - metadata_processor_cls: Optional[type] = MetadataProcessor, - metadata_registry_cls: Optional[type] = MetadataRegistry, - standalone_mode: bool = standalone_mode, + persistence_service: RecipePersistenceService, + analysis_service: RecipeAnalysisService, ) -> None: self._ensure_dependencies_ready = ensure_dependencies_ready self._recipe_scanner_getter = recipe_scanner_getter self._logger = logger - self._exif_utils = exif_utils - self._card_preview_width = card_preview_width - self._metadata_collector = metadata_collector - self._metadata_processor_cls = metadata_processor_cls - self._metadata_registry_cls = metadata_registry_cls - self._standalone_mode = standalone_mode + self._persistence_service = persistence_service + self._analysis_service = analysis_service async def save_recipe(self, request: web.Request) -> web.Response: try: @@ -482,171 +459,19 @@ class RecipeManagementHandler: raise RuntimeError("Recipe scanner unavailable") reader = await request.multipart() + payload = await self._parse_save_payload(reader) - image: Optional[bytes] = None - image_base64: Optional[str] = None - name: Optional[str] = None - tags: list[str] = [] - metadata: Dict[str, Any] | None = None - - while True: - field = await reader.next() - if field is None: - break - - if field.name == "image": - image_chunks = bytearray() - while True: - chunk = await field.read_chunk() - if not chunk: - break - image_chunks.extend(chunk) - image = bytes(image_chunks) - elif field.name == "image_base64": - image_base64 = await field.text() - elif field.name == "name": - name = await field.text() - elif field.name == "tags": - tags_text = await field.text() - try: - parsed_tags = json.loads(tags_text) - tags = parsed_tags if isinstance(parsed_tags, list) else [] - except Exception: - tags = [] - elif field.name == "metadata": - metadata_text = await field.text() - try: - metadata = json.loads(metadata_text) - except Exception: - metadata = {} - - missing_fields = [] - if not name: - missing_fields.append("name") - if not metadata: - missing_fields.append("metadata") - if missing_fields: - return web.json_response( - {"error": f"Missing required fields: {', '.join(missing_fields)}"}, - status=400, - ) - - if image is None: - if image_base64: - try: - if "," in image_base64: - image_base64 = image_base64.split(",", 1)[1] - image = base64.b64decode(image_base64) - except Exception as exc: - return web.json_response({"error": f"Invalid base64 image data: {exc}"}, status=400) - else: - return web.json_response({"error": "No image data provided"}, status=400) - - recipes_dir = recipe_scanner.recipes_dir - os.makedirs(recipes_dir, exist_ok=True) - - import uuid - - recipe_id = str(uuid.uuid4()) - optimized_image, extension = self._exif_utils.optimize_image( - image_data=image, - target_width=self._card_preview_width, - format="webp", - quality=85, - preserve_metadata=True, - ) - - image_filename = f"{recipe_id}{extension}" - image_path = os.path.join(recipes_dir, image_filename) - with open(image_path, "wb") as file_obj: - file_obj.write(optimized_image) - - current_time = time.time() - loras_data = [] - for lora in metadata.get("loras", []): - loras_data.append( - { - "file_name": lora.get("file_name", "") - or ( - os.path.splitext(os.path.basename(lora.get("localPath", "")))[0] - if lora.get("localPath") - else "" - ), - "hash": (lora.get("hash") or "").lower(), - "strength": float(lora.get("weight", 1.0)), - "modelVersionId": lora.get("id", 0), - "modelName": lora.get("name", ""), - "modelVersionName": lora.get("version", ""), - "isDeleted": lora.get("isDeleted", False), - "exclude": lora.get("exclude", False), - } - ) - - gen_params = metadata.get("gen_params", {}) - if not gen_params and "raw_metadata" in metadata: - raw_metadata = metadata.get("raw_metadata", {}) - gen_params = { - "prompt": raw_metadata.get("prompt", ""), - "negative_prompt": raw_metadata.get("negative_prompt", ""), - "checkpoint": raw_metadata.get("checkpoint", {}), - "steps": raw_metadata.get("steps", ""), - "sampler": raw_metadata.get("sampler", ""), - "cfg_scale": raw_metadata.get("cfg_scale", ""), - "seed": raw_metadata.get("seed", ""), - "size": raw_metadata.get("size", ""), - "clip_skip": raw_metadata.get("clip_skip", ""), - } - - from ...utils.utils import calculate_recipe_fingerprint - - fingerprint = calculate_recipe_fingerprint(loras_data) - - recipe_data = { - "id": recipe_id, - "file_path": image_path, - "title": name, - "modified": current_time, - "created_date": current_time, - "base_model": metadata.get("base_model", ""), - "loras": loras_data, - "gen_params": gen_params, - "fingerprint": fingerprint, - } - - if tags: - recipe_data["tags"] = tags - - if metadata.get("source_path"): - recipe_data["source_path"] = metadata.get("source_path") - - json_filename = f"{recipe_id}.recipe.json" - json_path = os.path.join(recipes_dir, json_filename) - with open(json_path, "w", encoding="utf-8") as file_obj: - json.dump(recipe_data, file_obj, indent=4, ensure_ascii=False) - - self._exif_utils.append_recipe_metadata(image_path, recipe_data) - - matching_recipes = [] - if fingerprint: - matching_recipes = await recipe_scanner.find_recipes_by_fingerprint(fingerprint) - if recipe_id in matching_recipes: - matching_recipes.remove(recipe_id) - - cache = getattr(recipe_scanner, "_cache", None) - if cache is not None: - cache.raw_data.append(recipe_data) - asyncio.create_task(cache.resort()) - self._logger.info("Added recipe %s to cache", recipe_id) - - return web.json_response( - { - "success": True, - "recipe_id": recipe_id, - "image_path": image_path, - "json_path": json_path, - "matching_recipes": matching_recipes, - } + result = await self._persistence_service.save_recipe( + recipe_scanner=recipe_scanner, + image_bytes=payload["image_bytes"], + image_base64=payload["image_base64"], + name=payload["name"], + tags=payload["tags"], + metadata=payload["metadata"], ) + return web.json_response(result.payload, status=result.status) + except RecipeValidationError as exc: + return web.json_response({"error": str(exc)}, status=400) except Exception as exc: self._logger.error("Error saving recipe: %s", exc, exc_info=True) return web.json_response({"error": str(exc)}, status=500) @@ -659,34 +484,12 @@ class RecipeManagementHandler: raise RuntimeError("Recipe scanner unavailable") recipe_id = request.match_info["recipe_id"] - recipes_dir = recipe_scanner.recipes_dir - if not recipes_dir or not os.path.exists(recipes_dir): - return web.json_response({"error": "Recipes directory not found"}, status=404) - - recipe_json_path = os.path.join(recipes_dir, f"{recipe_id}.recipe.json") - if not os.path.exists(recipe_json_path): - return web.json_response({"error": "Recipe not found"}, status=404) - - with open(recipe_json_path, "r", encoding="utf-8") as file_obj: - recipe_data = json.load(file_obj) - - image_path = recipe_data.get("file_path") - os.remove(recipe_json_path) - self._logger.info("Deleted recipe JSON file: %s", recipe_json_path) - - if image_path and os.path.exists(image_path): - os.remove(image_path) - self._logger.info("Deleted recipe image: %s", image_path) - - cache = getattr(recipe_scanner, "_cache", None) - if cache is not None: - cache.raw_data = [ - item for item in cache.raw_data if str(item.get("id", "")) != recipe_id - ] - asyncio.create_task(cache.resort()) - self._logger.info("Removed recipe %s from cache", recipe_id) - - return web.json_response({"success": True, "message": "Recipe deleted successfully"}) + result = await self._persistence_service.delete_recipe( + recipe_scanner=recipe_scanner, recipe_id=recipe_id + ) + return web.json_response(result.payload, status=result.status) + except RecipeNotFoundError as exc: + return web.json_response({"error": str(exc)}, status=404) except Exception as exc: self._logger.error("Error deleting recipe: %s", exc, exc_info=True) return web.json_response({"error": str(exc)}, status=500) @@ -700,25 +503,14 @@ class RecipeManagementHandler: recipe_id = request.match_info["recipe_id"] data = await request.json() - - if not any( - key in data for key in ("title", "tags", "source_path", "preview_nsfw_level") - ): - return web.json_response( - { - "error": ( - "At least one field to update must be provided (title or tags or " - "source_path or preview_nsfw_level)" - ) - }, - status=400, - ) - - success = await recipe_scanner.update_recipe_metadata(recipe_id, data) - if not success: - return web.json_response({"error": "Recipe not found or update failed"}, status=404) - - return web.json_response({"success": True, "recipe_id": recipe_id, "updates": data}) + result = await self._persistence_service.update_recipe( + recipe_scanner=recipe_scanner, recipe_id=recipe_id, updates=data + ) + return web.json_response(result.payload, status=result.status) + except RecipeValidationError as exc: + return web.json_response({"error": str(exc)}, status=400) + except RecipeNotFoundError as exc: + return web.json_response({"error": str(exc)}, status=404) except Exception as exc: self._logger.error("Error updating recipe: %s", exc, exc_info=True) return web.json_response({"error": str(exc)}, status=500) @@ -731,81 +523,21 @@ class RecipeManagementHandler: raise RuntimeError("Recipe scanner unavailable") data = await request.json() - required_fields = ["recipe_id", "lora_index", "target_name"] - for field in required_fields: + for field in ("recipe_id", "lora_index", "target_name"): if field not in data: - return web.json_response({"error": f"Missing required field: {field}"}, status=400) + raise RecipeValidationError(f"Missing required field: {field}") - recipe_id = data["recipe_id"] - lora_index = int(data["lora_index"]) - target_name = data["target_name"] - - recipe_path = os.path.join(recipe_scanner.recipes_dir, f"{recipe_id}.recipe.json") - if not os.path.exists(recipe_path): - return web.json_response({"error": "Recipe not found"}, status=404) - - lora_scanner = getattr(recipe_scanner, "_lora_scanner", None) - target_lora = None if lora_scanner is None else await lora_scanner.get_model_info_by_name(target_name) - if not target_lora: - return web.json_response({"error": f"Local LoRA not found with name: {target_name}"}, status=404) - - with open(recipe_path, "r", encoding="utf-8") as file_obj: - recipe_data = json.load(file_obj) - - loras = recipe_data.get("loras", []) - lora = loras[lora_index] if lora_index < len(loras) else None - if lora is None: - return web.json_response({"error": "LoRA index out of range in recipe"}, status=404) - - lora["isDeleted"] = False - lora["exclude"] = False - lora["file_name"] = target_name - if "sha256" in target_lora: - lora["hash"] = target_lora["sha256"].lower() - if target_lora.get("civitai"): - lora["modelName"] = target_lora["civitai"]["model"]["name"] - lora["modelVersionName"] = target_lora["civitai"]["name"] - lora["modelVersionId"] = target_lora["civitai"]["id"] - - from ...utils.utils import calculate_recipe_fingerprint - - recipe_data["fingerprint"] = calculate_recipe_fingerprint(recipe_data.get("loras", [])) - - with open(recipe_path, "w", encoding="utf-8") as file_obj: - json.dump(recipe_data, file_obj, indent=4, ensure_ascii=False) - - updated_lora = dict(lora) - updated_lora["inLibrary"] = True - updated_lora["preview_url"] = config.get_preview_static_url(target_lora["preview_url"]) - updated_lora["localPath"] = target_lora["file_path"] - - cache = getattr(recipe_scanner, "_cache", None) - if cache is not None: - for cache_item in cache.raw_data: - if cache_item.get("id") == recipe_id: - cache_item["loras"] = recipe_data["loras"] - cache_item["fingerprint"] = recipe_data["fingerprint"] - asyncio.create_task(cache.resort()) - break - - image_path = recipe_data.get("file_path") - if image_path and os.path.exists(image_path): - self._exif_utils.append_recipe_metadata(image_path, recipe_data) - - matching_recipes = [] - if "fingerprint" in recipe_data: - matching_recipes = await recipe_scanner.find_recipes_by_fingerprint(recipe_data["fingerprint"]) - if recipe_id in matching_recipes: - matching_recipes.remove(recipe_id) - - return web.json_response( - { - "success": True, - "recipe_id": recipe_id, - "updated_lora": updated_lora, - "matching_recipes": matching_recipes, - } + result = await self._persistence_service.reconnect_lora( + recipe_scanner=recipe_scanner, + recipe_id=data["recipe_id"], + lora_index=int(data["lora_index"]), + target_name=data["target_name"], ) + return web.json_response(result.payload, status=result.status) + except RecipeValidationError as exc: + return web.json_response({"error": str(exc)}, status=400) + except RecipeNotFoundError as exc: + return web.json_response({"error": str(exc)}, status=404) except Exception as exc: self._logger.error("Error reconnecting LoRA: %s", exc, exc_info=True) return web.json_response({"error": str(exc)}, status=500) @@ -819,54 +551,14 @@ class RecipeManagementHandler: data = await request.json() recipe_ids = data.get("recipe_ids", []) - if not recipe_ids: - return web.json_response( - {"success": False, "error": "No recipe IDs provided"}, - status=400, - ) - - recipes_dir = recipe_scanner.recipes_dir - if not recipes_dir or not os.path.exists(recipes_dir): - return web.json_response( - {"success": False, "error": "Recipes directory not found"}, - status=404, - ) - - deleted_recipes: list[str] = [] - failed_recipes: list[Dict[str, Any]] = [] - - for recipe_id in recipe_ids: - recipe_json_path = os.path.join(recipes_dir, f"{recipe_id}.recipe.json") - if not os.path.exists(recipe_json_path): - failed_recipes.append({"id": recipe_id, "reason": "Recipe not found"}) - continue - - try: - with open(recipe_json_path, "r", encoding="utf-8") as file_obj: - recipe_data = json.load(file_obj) - image_path = recipe_data.get("file_path") - os.remove(recipe_json_path) - if image_path and os.path.exists(image_path): - os.remove(image_path) - deleted_recipes.append(recipe_id) - except Exception as exc: - failed_recipes.append({"id": recipe_id, "reason": str(exc)}) - - cache = getattr(recipe_scanner, "_cache", None) - if deleted_recipes and cache is not None: - cache.raw_data = [item for item in cache.raw_data if item.get("id") not in deleted_recipes] - asyncio.create_task(cache.resort()) - self._logger.info("Removed %s recipes from cache", len(deleted_recipes)) - - return web.json_response( - { - "success": True, - "deleted": deleted_recipes, - "failed": failed_recipes, - "total_deleted": len(deleted_recipes), - "total_failed": len(failed_recipes), - } + result = await self._persistence_service.bulk_delete( + recipe_scanner=recipe_scanner, recipe_ids=recipe_ids ) + return web.json_response(result.payload, status=result.status) + except RecipeValidationError as exc: + return web.json_response({"success": False, "error": str(exc)}, status=400) + except RecipeNotFoundError as exc: + return web.json_response({"success": False, "error": str(exc)}, status=404) except Exception as exc: self._logger.error("Error performing bulk delete: %s", exc, exc_info=True) return web.json_response({"success": False, "error": str(exc)}, status=500) @@ -878,164 +570,71 @@ class RecipeManagementHandler: if recipe_scanner is None: raise RuntimeError("Recipe scanner unavailable") - if self._metadata_collector is None or self._metadata_processor_cls is None: - return web.json_response({"error": "Metadata collection not available"}, status=400) - - raw_metadata = self._metadata_collector() - metadata_dict = self._metadata_processor_cls.to_dict(raw_metadata) - if not metadata_dict: - return web.json_response({"error": "No generation metadata found"}, status=400) - - if not self._standalone_mode and self._metadata_registry_cls is not None: - metadata_registry = self._metadata_registry_cls() - latest_image = metadata_registry.get_first_decoded_image() - else: - latest_image = None - - if latest_image is None: - return web.json_response( - {"error": "No recent images found to use for recipe. Try generating an image first."}, - status=400, - ) - - self._logger.debug("Image type: %s", type(latest_image)) - - try: - if isinstance(latest_image, tuple): - tensor_image = latest_image[0] if latest_image else None - if tensor_image is None: - return web.json_response({"error": "Empty image tuple received"}, status=400) - else: - tensor_image = latest_image - - if hasattr(tensor_image, "shape"): - shape_info = tensor_image.shape - self._logger.debug("Tensor shape: %s, dtype: %s", shape_info, tensor_image.dtype) - - import torch # type: ignore[import-not-found] - - if isinstance(tensor_image, torch.Tensor): - image_np = tensor_image.cpu().numpy() - else: - image_np = np.array(tensor_image) - - while len(image_np.shape) > 3: - image_np = image_np[0] - - if image_np.dtype in (np.float32, np.float64) and image_np.max() <= 1.0: - image_np = (image_np * 255).astype(np.uint8) - - if len(image_np.shape) == 3 and image_np.shape[2] == 3: - pil_image = Image.fromarray(image_np) - img_byte_arr = io.BytesIO() - pil_image.save(img_byte_arr, format="PNG") - image_bytes = img_byte_arr.getvalue() - else: - return web.json_response( - {"error": f"Cannot handle this data shape: {image_np.shape}, {image_np.dtype}"}, - status=400, - ) - except Exception as exc: - self._logger.error("Error processing image data: %s", exc, exc_info=True) - return web.json_response({"error": f"Error processing image: {exc}"}, status=400) - - lora_stack = metadata_dict.get("loras", "") - import re - - lora_matches = re.findall(r"]+)>", lora_stack) - if not lora_matches: - return web.json_response({"error": "No LoRAs found in the generation metadata"}, status=400) - - loras_for_name = lora_matches[:3] - recipe_name_parts = [] - for name, strength in loras_for_name: - recipe_name_parts.append(f"{name.strip()}-{float(strength):.2f}") - recipe_name = "_".join(recipe_name_parts) - - recipe_name = recipe_name or "recipe" - - recipes_dir = recipe_scanner.recipes_dir - os.makedirs(recipes_dir, exist_ok=True) - - import uuid - - recipe_id = str(uuid.uuid4()) - image_filename = f"{recipe_id}.png" - image_path = os.path.join(recipes_dir, image_filename) - with open(image_path, "wb") as file_obj: - file_obj.write(image_bytes) - - loras_data = [] - lora_scanner = getattr(recipe_scanner, "_lora_scanner", None) - base_model_counts: Dict[str, int] = {} - - for name, strength in lora_matches: - lora_info = None - if lora_scanner is not None: - lora_info = await lora_scanner.get_model_info_by_name(name) - lora_data = { - "file_name": name, - "strength": float(strength), - "hash": (lora_info.get("sha256") or "").lower() if lora_info else "", - "modelVersionId": lora_info.get("civitai", {}).get("id") if lora_info else 0, - "modelName": lora_info.get("civitai", {}).get("model", {}).get("name") if lora_info else "", - "modelVersionName": lora_info.get("civitai", {}).get("name") if lora_info else "", - "isDeleted": False, - "exclude": False, - } - loras_data.append(lora_data) - - if lora_info and "base_model" in lora_info: - base_model = lora_info["base_model"] - base_model_counts[base_model] = base_model_counts.get(base_model, 0) + 1 - - most_common_base_model = "" - if base_model_counts: - most_common_base_model = max(base_model_counts.items(), key=lambda item: item[1])[0] - - recipe_data = { - "id": recipe_id, - "file_path": image_path, - "title": recipe_name, - "modified": time.time(), - "created_date": time.time(), - "base_model": most_common_base_model, - "loras": loras_data, - "checkpoint": metadata_dict.get("checkpoint", ""), - "gen_params": { - key: value - for key, value in metadata_dict.items() - if key not in ["checkpoint", "loras"] - }, - "loras_stack": lora_stack, - } - - json_filename = f"{recipe_id}.recipe.json" - json_path = os.path.join(recipes_dir, json_filename) - with open(json_path, "w", encoding="utf-8") as file_obj: - json.dump(recipe_data, file_obj, indent=4, ensure_ascii=False) - - self._exif_utils.append_recipe_metadata(image_path, recipe_data) - - cache = getattr(recipe_scanner, "_cache", None) - if cache is not None: - cache.raw_data.append(recipe_data) - asyncio.create_task(cache.resort()) - self._logger.info("Added recipe %s to cache", recipe_id) - - return web.json_response( - { - "success": True, - "recipe_id": recipe_id, - "image_path": image_path, - "json_path": json_path, - "recipe_name": recipe_name, - } + analysis = await self._analysis_service.analyze_widget_metadata( + recipe_scanner=recipe_scanner ) + metadata = analysis.payload.get("metadata") + image_bytes = analysis.payload.get("image_bytes") + if not metadata or image_bytes is None: + raise RecipeValidationError("Unable to extract metadata from widget") + + result = await self._persistence_service.save_recipe_from_widget( + recipe_scanner=recipe_scanner, + metadata=metadata, + image_bytes=image_bytes, + ) + return web.json_response(result.payload, status=result.status) + except RecipeValidationError as exc: + return web.json_response({"error": str(exc)}, status=400) except Exception as exc: self._logger.error("Error saving recipe from widget: %s", exc, exc_info=True) return web.json_response({"error": str(exc)}, status=500) + async def _parse_save_payload(self, reader) -> dict[str, Any]: + image_bytes: Optional[bytes] = None + image_base64: Optional[str] = None + name: Optional[str] = None + tags: list[str] = [] + metadata: Optional[Dict[str, Any]] = None + + while True: + field = await reader.next() + if field is None: + break + if field.name == "image": + image_chunks = bytearray() + while True: + chunk = await field.read_chunk() + if not chunk: + break + image_chunks.extend(chunk) + image_bytes = bytes(image_chunks) + elif field.name == "image_base64": + image_base64 = await field.text() + elif field.name == "name": + name = await field.text() + elif field.name == "tags": + tags_text = await field.text() + try: + parsed_tags = json.loads(tags_text) + tags = parsed_tags if isinstance(parsed_tags, list) else [] + except Exception: + tags = [] + elif field.name == "metadata": + metadata_text = await field.text() + try: + metadata = json.loads(metadata_text) + except Exception: + metadata = {} + + return { + "image_bytes": image_bytes, + "image_base64": image_base64, + "name": name, + "tags": tags, + "metadata": metadata, + } + class RecipeAnalysisHandler: """Analyze images to extract recipe metadata.""" @@ -1047,20 +646,15 @@ class RecipeAnalysisHandler: recipe_scanner_getter: RecipeScannerGetter, civitai_client_getter: CivitaiClientGetter, logger: Logger, - exif_utils=ExifUtils, - recipe_parser_factory=RecipeParserFactory, - downloader_factory=get_downloader, + analysis_service: RecipeAnalysisService, ) -> None: self._ensure_dependencies_ready = ensure_dependencies_ready self._recipe_scanner_getter = recipe_scanner_getter self._civitai_client_getter = civitai_client_getter self._logger = logger - self._exif_utils = exif_utils - self._recipe_parser_factory = recipe_parser_factory - self._downloader_factory = downloader_factory + self._analysis_service = analysis_service async def analyze_uploaded_image(self, request: web.Request) -> web.Response: - temp_path: Optional[str] = None try: await self._ensure_dependencies_ready() recipe_scanner = self._recipe_scanner_getter() @@ -1069,112 +663,42 @@ class RecipeAnalysisHandler: raise RuntimeError("Required services unavailable") content_type = request.headers.get("Content-Type", "") - is_url_mode = False - metadata: Optional[Dict[str, Any]] = None - if "multipart/form-data" in content_type: reader = await request.multipart() field = await reader.next() if field is None or field.name != "image": - return web.json_response({"error": "No image field found", "loras": []}, status=400) + raise RecipeValidationError("No image field found") + image_chunks = bytearray() + while True: + chunk = await field.read_chunk() + if not chunk: + break + image_chunks.extend(chunk) + result = await self._analysis_service.analyze_uploaded_image( + image_bytes=bytes(image_chunks), + recipe_scanner=recipe_scanner, + ) + return web.json_response(result.payload, status=result.status) - with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_file: - while True: - chunk = await field.read_chunk() - if not chunk: - break - temp_file.write(chunk) - temp_path = temp_file.name - elif "application/json" in content_type: + if "application/json" in content_type: data = await request.json() - url = data.get("url") - is_url_mode = True - if not url: - return web.json_response({"error": "No URL provided", "loras": []}, status=400) + result = await self._analysis_service.analyze_remote_image( + url=data.get("url"), + recipe_scanner=recipe_scanner, + civitai_client=civitai_client, + ) + return web.json_response(result.payload, status=result.status) - import re - - civitai_image_match = re.match(r"https://civitai\.com/images/(\d+)", url) - if civitai_image_match: - image_id = civitai_image_match.group(1) - image_info = await civitai_client.get_image_info(image_id) - if not image_info: - return web.json_response( - {"error": "Failed to fetch image information from Civitai", "loras": []}, - status=400, - ) - image_url = image_info.get("url") - if not image_url: - return web.json_response( - {"error": "No image URL found in Civitai response", "loras": []}, - status=400, - ) - - downloader = await self._downloader_factory() - with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_file: - temp_path = temp_file.name - - success, result = await downloader.download_file( - image_url, - temp_path, - use_auth=False, - ) - if not success: - return web.json_response( - {"error": f"Failed to download image from URL: {result}", "loras": []}, - status=400, - ) - metadata = image_info.get("meta") if "meta" in image_info else None - else: - return web.json_response({"error": "Unsupported content type", "loras": []}, status=400) - - if metadata is None and temp_path: - metadata = self._exif_utils.extract_image_metadata(temp_path) - - if not metadata: - response: Dict[str, Any] = {"error": "No metadata found in this image", "loras": []} - if is_url_mode and temp_path: - with open(temp_path, "rb") as image_file: - response["image_base64"] = base64.b64encode(image_file.read()).decode("utf-8") - return web.json_response(response, status=200) - - parser = self._recipe_parser_factory.create_parser(metadata) - if parser is None: - response = {"error": "No parser found for this image", "loras": []} - if is_url_mode and temp_path: - with open(temp_path, "rb") as image_file: - response["image_base64"] = base64.b64encode(image_file.read()).decode("utf-8") - return web.json_response(response, status=200) - - result = await parser.parse_metadata(metadata, recipe_scanner=recipe_scanner) - - if is_url_mode and temp_path: - with open(temp_path, "rb") as image_file: - result["image_base64"] = base64.b64encode(image_file.read()).decode("utf-8") - - if "error" in result and not result.get("loras"): - return web.json_response(result, status=200) - - from ...utils.utils import calculate_recipe_fingerprint - - fingerprint = calculate_recipe_fingerprint(result.get("loras", [])) - result["fingerprint"] = fingerprint - - matching_recipes = [] - if fingerprint: - matching_recipes = await recipe_scanner.find_recipes_by_fingerprint(fingerprint) - - result["matching_recipes"] = matching_recipes - return web.json_response(result) + raise RecipeValidationError("Unsupported content type") + except RecipeValidationError as exc: + return web.json_response({"error": str(exc), "loras": []}, status=400) + except RecipeDownloadError as exc: + return web.json_response({"error": str(exc), "loras": []}, status=400) + except RecipeNotFoundError as exc: + return web.json_response({"error": str(exc), "loras": []}, status=404) except Exception as exc: self._logger.error("Error analyzing recipe image: %s", exc, exc_info=True) return web.json_response({"error": str(exc), "loras": []}, status=500) - finally: - if temp_path and os.path.exists(temp_path): - try: - os.unlink(temp_path) - except Exception as cleanup_exc: # pragma: no cover - logging path - self._logger.error("Error deleting temporary file: %s", cleanup_exc) async def analyze_local_image(self, request: web.Request) -> web.Response: try: @@ -1184,50 +708,15 @@ class RecipeAnalysisHandler: raise RuntimeError("Recipe scanner unavailable") data = await request.json() - file_path = data.get("path") - if not file_path: - return web.json_response({"error": "No file path provided", "loras": []}, status=400) - - file_path = os.path.normpath(file_path.strip('"').strip("'")) - if not os.path.isfile(file_path): - return web.json_response({"error": "File not found", "loras": []}, status=404) - - metadata = self._exif_utils.extract_image_metadata(file_path) - if not metadata: - with open(file_path, "rb") as image_file: - image_base64 = base64.b64encode(image_file.read()).decode("utf-8") - return web.json_response( - {"error": "No metadata found in this image", "loras": [], "image_base64": image_base64}, - status=200, - ) - - parser = self._recipe_parser_factory.create_parser(metadata) - if parser is None: - with open(file_path, "rb") as image_file: - image_base64 = base64.b64encode(image_file.read()).decode("utf-8") - return web.json_response( - {"error": "No parser found for this image", "loras": [], "image_base64": image_base64}, - status=200, - ) - - result = await parser.parse_metadata(metadata, recipe_scanner=recipe_scanner) - with open(file_path, "rb") as image_file: - result["image_base64"] = base64.b64encode(image_file.read()).decode("utf-8") - - if "error" in result and not result.get("loras"): - return web.json_response(result, status=200) - - from ...utils.utils import calculate_recipe_fingerprint - - fingerprint = calculate_recipe_fingerprint(result.get("loras", [])) - result["fingerprint"] = fingerprint - - matching_recipes = [] - if fingerprint: - matching_recipes = await recipe_scanner.find_recipes_by_fingerprint(fingerprint) - result["matching_recipes"] = matching_recipes - - return web.json_response(result) + result = await self._analysis_service.analyze_local_image( + file_path=data.get("path"), + recipe_scanner=recipe_scanner, + ) + return web.json_response(result.payload, status=result.status) + except RecipeValidationError as exc: + return web.json_response({"error": str(exc), "loras": []}, status=400) + except RecipeNotFoundError as exc: + return web.json_response({"error": str(exc), "loras": []}, status=404) except Exception as exc: self._logger.error("Error analyzing local image: %s", exc, exc_info=True) return web.json_response({"error": str(exc), "loras": []}, status=500) @@ -1242,11 +731,12 @@ class RecipeSharingHandler: ensure_dependencies_ready: EnsureDependenciesCallable, recipe_scanner_getter: RecipeScannerGetter, logger: Logger, + sharing_service: RecipeSharingService, ) -> None: self._ensure_dependencies_ready = ensure_dependencies_ready self._recipe_scanner_getter = recipe_scanner_getter self._logger = logger - self._shared_recipes: Dict[str, Dict[str, Any]] = {} + self._sharing_service = sharing_service async def share_recipe(self, request: web.Request) -> web.Response: try: @@ -1256,42 +746,17 @@ class RecipeSharingHandler: raise RuntimeError("Recipe scanner unavailable") recipe_id = request.match_info["recipe_id"] - cache = await recipe_scanner.get_cached_data() - recipe = next( - (r for r in getattr(cache, "raw_data", []) if str(r.get("id", "")) == recipe_id), - None, + result = await self._sharing_service.share_recipe( + recipe_scanner=recipe_scanner, recipe_id=recipe_id ) - if not recipe: - return web.json_response({"error": "Recipe not found"}, status=404) - - image_path = recipe.get("file_path") - if not image_path or not os.path.exists(image_path): - return web.json_response({"error": "Recipe image not found"}, status=404) - - import shutil - - ext = os.path.splitext(image_path)[1] - with tempfile.NamedTemporaryFile(suffix=ext, delete=False) as temp_file: - temp_path = temp_file.name - shutil.copy2(image_path, temp_path) - processed_path = temp_path - - timestamp = int(time.time()) - url_path = f"/api/recipe/{recipe_id}/share/download?t={timestamp}" - self._shared_recipes[recipe_id] = { - "path": processed_path, - "timestamp": timestamp, - "expires": time.time() + 300, - } - self._cleanup_shared_recipes() - - filename = f"recipe_{recipe.get('title', '').replace(' ', '_').lower()}{ext}" - return web.json_response({"success": True, "download_url": url_path, "filename": filename}) + return web.json_response(result.payload, status=result.status) + except RecipeNotFoundError as exc: + return web.json_response({"error": str(exc)}, status=404) except Exception as exc: self._logger.error("Error sharing recipe: %s", exc, exc_info=True) return web.json_response({"error": str(exc)}, status=500) - async def download_shared_recipe(self, request: web.Request) -> web.Response: + async def download_shared_recipe(self, request: web.Request) -> web.StreamResponse: try: await self._ensure_dependencies_ready() recipe_scanner = self._recipe_scanner_getter() @@ -1299,49 +764,17 @@ class RecipeSharingHandler: raise RuntimeError("Recipe scanner unavailable") recipe_id = request.match_info["recipe_id"] - shared_info = self._shared_recipes.get(recipe_id) - if not shared_info: - return web.json_response({"error": "Shared recipe not found or expired"}, status=404) - - file_path = shared_info["path"] - if not os.path.exists(file_path): - return web.json_response({"error": "Shared recipe file not found"}, status=404) - - cache = await recipe_scanner.get_cached_data() - recipe = next( - (r for r in getattr(cache, "raw_data", []) if str(r.get("id", "")) == recipe_id), - None, + download_info = await self._sharing_service.prepare_download( + recipe_scanner=recipe_scanner, recipe_id=recipe_id ) - filename_base = ( - f"recipe_{recipe.get('title', '').replace(' ', '_').lower()}" - if recipe - else recipe_id - ) - ext = os.path.splitext(file_path)[1] - download_filename = f"{filename_base}{ext}" - return web.FileResponse( - file_path, - headers={"Content-Disposition": f'attachment; filename="{download_filename}"'}, + download_info.file_path, + headers={ + "Content-Disposition": f'attachment; filename="{download_info.download_filename}"' + }, ) + except RecipeNotFoundError as exc: + return web.json_response({"error": str(exc)}, status=404) except Exception as exc: self._logger.error("Error downloading shared recipe: %s", exc, exc_info=True) return web.json_response({"error": str(exc)}, status=500) - - def _cleanup_shared_recipes(self) -> None: - current_time = time.time() - expired_ids = [ - recipe_id - for recipe_id, info in self._shared_recipes.items() - if current_time > info.get("expires", 0) - ] - - for recipe_id in expired_ids: - try: - file_path = self._shared_recipes[recipe_id]["path"] - if os.path.exists(file_path): - os.unlink(file_path) - except Exception as exc: # pragma: no cover - logging path - self._logger.error("Error cleaning up shared recipe %s: %s", recipe_id, exc) - finally: - self._shared_recipes.pop(recipe_id, None) diff --git a/py/services/recipes/__init__.py b/py/services/recipes/__init__.py new file mode 100644 index 00000000..8009b7c3 --- /dev/null +++ b/py/services/recipes/__init__.py @@ -0,0 +1,23 @@ +"""Recipe service layer implementations.""" + +from .analysis_service import RecipeAnalysisService +from .persistence_service import RecipePersistenceService +from .sharing_service import RecipeSharingService +from .errors import ( + RecipeServiceError, + RecipeValidationError, + RecipeNotFoundError, + RecipeDownloadError, + RecipeConflictError, +) + +__all__ = [ + "RecipeAnalysisService", + "RecipePersistenceService", + "RecipeSharingService", + "RecipeServiceError", + "RecipeValidationError", + "RecipeNotFoundError", + "RecipeDownloadError", + "RecipeConflictError", +] diff --git a/py/services/recipes/analysis_service.py b/py/services/recipes/analysis_service.py new file mode 100644 index 00000000..77d80e34 --- /dev/null +++ b/py/services/recipes/analysis_service.py @@ -0,0 +1,289 @@ +"""Services responsible for recipe metadata analysis.""" +from __future__ import annotations + +import base64 +import io +import os +import re +import tempfile +from dataclasses import dataclass +from typing import Any, Callable, Optional + +import numpy as np +from PIL import Image + +from ...utils.utils import calculate_recipe_fingerprint +from .errors import ( + RecipeDownloadError, + RecipeNotFoundError, + RecipeServiceError, + RecipeValidationError, +) + + +@dataclass(frozen=True) +class AnalysisResult: + """Return payload from analysis operations.""" + + payload: dict[str, Any] + status: int = 200 + + +class RecipeAnalysisService: + """Extract recipe metadata from various image sources.""" + + def __init__( + self, + *, + exif_utils, + recipe_parser_factory, + downloader_factory: Callable[[], Any], + metadata_collector: Optional[Callable[[], Any]] = None, + metadata_processor_cls: Optional[type] = None, + metadata_registry_cls: Optional[type] = None, + standalone_mode: bool = False, + logger, + ) -> None: + self._exif_utils = exif_utils + self._recipe_parser_factory = recipe_parser_factory + self._downloader_factory = downloader_factory + self._metadata_collector = metadata_collector + self._metadata_processor_cls = metadata_processor_cls + self._metadata_registry_cls = metadata_registry_cls + self._standalone_mode = standalone_mode + self._logger = logger + + async def analyze_uploaded_image( + self, + *, + image_bytes: bytes | None, + recipe_scanner, + ) -> AnalysisResult: + """Analyze an uploaded image payload.""" + + if not image_bytes: + raise RecipeValidationError("No image data provided") + + temp_path = self._write_temp_file(image_bytes) + try: + metadata = self._exif_utils.extract_image_metadata(temp_path) + if not metadata: + return AnalysisResult({"error": "No metadata found in this image", "loras": []}) + + return await self._parse_metadata( + metadata, + recipe_scanner=recipe_scanner, + image_path=None, + include_image_base64=False, + ) + finally: + self._safe_cleanup(temp_path) + + async def analyze_remote_image( + self, + *, + url: str | None, + recipe_scanner, + civitai_client, + ) -> AnalysisResult: + """Analyze an image accessible via URL, including Civitai integration.""" + + if not url: + raise RecipeValidationError("No URL provided") + + if civitai_client is None: + raise RecipeServiceError("Civitai client unavailable") + + temp_path = self._create_temp_path() + metadata: Optional[dict[str, Any]] = None + try: + civitai_match = re.match(r"https://civitai\.com/images/(\d+)", url) + if civitai_match: + image_info = await civitai_client.get_image_info(civitai_match.group(1)) + if not image_info: + raise RecipeDownloadError("Failed to fetch image information from Civitai") + image_url = image_info.get("url") + if not image_url: + raise RecipeDownloadError("No image URL found in Civitai response") + await self._download_image(image_url, temp_path) + metadata = image_info.get("meta") if "meta" in image_info else None + else: + await self._download_image(url, temp_path) + + if metadata is None: + metadata = self._exif_utils.extract_image_metadata(temp_path) + + if not metadata: + return self._metadata_not_found_response(temp_path) + + return await self._parse_metadata( + metadata, + recipe_scanner=recipe_scanner, + image_path=temp_path, + include_image_base64=True, + ) + finally: + self._safe_cleanup(temp_path) + + async def analyze_local_image( + self, + *, + file_path: str | None, + recipe_scanner, + ) -> AnalysisResult: + """Analyze a file already present on disk.""" + + if not file_path: + raise RecipeValidationError("No file path provided") + + normalized_path = os.path.normpath(file_path.strip('"').strip("'")) + if not os.path.isfile(normalized_path): + raise RecipeNotFoundError("File not found") + + metadata = self._exif_utils.extract_image_metadata(normalized_path) + if not metadata: + return self._metadata_not_found_response(normalized_path) + + return await self._parse_metadata( + metadata, + recipe_scanner=recipe_scanner, + image_path=normalized_path, + include_image_base64=True, + ) + + async def analyze_widget_metadata(self, *, recipe_scanner) -> AnalysisResult: + """Analyse the most recent generation metadata for widget saves.""" + + if self._metadata_collector is None or self._metadata_processor_cls is None: + raise RecipeValidationError("Metadata collection not available") + + raw_metadata = self._metadata_collector() + metadata_dict = self._metadata_processor_cls.to_dict(raw_metadata) + if not metadata_dict: + raise RecipeValidationError("No generation metadata found") + + latest_image = None + if not self._standalone_mode and self._metadata_registry_cls is not None: + metadata_registry = self._metadata_registry_cls() + latest_image = metadata_registry.get_first_decoded_image() + + if latest_image is None: + raise RecipeValidationError( + "No recent images found to use for recipe. Try generating an image first." + ) + + image_bytes = self._convert_tensor_to_png_bytes(latest_image) + if image_bytes is None: + raise RecipeValidationError("Cannot handle this data shape from metadata registry") + + return AnalysisResult( + { + "metadata": metadata_dict, + "image_bytes": image_bytes, + } + ) + + # Internal helpers ------------------------------------------------- + + async def _parse_metadata( + self, + metadata: dict[str, Any], + *, + recipe_scanner, + image_path: Optional[str], + include_image_base64: bool, + ) -> AnalysisResult: + parser = self._recipe_parser_factory.create_parser(metadata) + if parser is None: + payload = {"error": "No parser found for this image", "loras": []} + if include_image_base64 and image_path: + payload["image_base64"] = self._encode_file(image_path) + return AnalysisResult(payload) + + result = await parser.parse_metadata(metadata, recipe_scanner=recipe_scanner) + + if include_image_base64 and image_path: + result["image_base64"] = self._encode_file(image_path) + + if "error" in result and not result.get("loras"): + return AnalysisResult(result) + + fingerprint = calculate_recipe_fingerprint(result.get("loras", [])) + result["fingerprint"] = fingerprint + + matching_recipes: list[str] = [] + if fingerprint: + matching_recipes = await recipe_scanner.find_recipes_by_fingerprint(fingerprint) + result["matching_recipes"] = matching_recipes + + return AnalysisResult(result) + + async def _download_image(self, url: str, temp_path: str) -> None: + downloader = await self._downloader_factory() + success, result = await downloader.download_file(url, temp_path, use_auth=False) + if not success: + raise RecipeDownloadError(f"Failed to download image from URL: {result}") + + def _metadata_not_found_response(self, path: str) -> AnalysisResult: + payload: dict[str, Any] = {"error": "No metadata found in this image", "loras": []} + if os.path.exists(path): + payload["image_base64"] = self._encode_file(path) + return AnalysisResult(payload) + + def _write_temp_file(self, data: bytes) -> str: + with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_file: + temp_file.write(data) + return temp_file.name + + def _create_temp_path(self) -> str: + with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_file: + return temp_file.name + + def _safe_cleanup(self, path: Optional[str]) -> None: + if path and os.path.exists(path): + try: + os.unlink(path) + except Exception as exc: # pragma: no cover - defensive logging + self._logger.error("Error deleting temporary file: %s", exc) + + def _encode_file(self, path: str) -> str: + with open(path, "rb") as image_file: + return base64.b64encode(image_file.read()).decode("utf-8") + + def _convert_tensor_to_png_bytes(self, latest_image: Any) -> Optional[bytes]: + try: + if isinstance(latest_image, tuple): + tensor_image = latest_image[0] if latest_image else None + if tensor_image is None: + return None + else: + tensor_image = latest_image + + if hasattr(tensor_image, "shape"): + self._logger.debug( + "Tensor shape: %s, dtype: %s", tensor_image.shape, getattr(tensor_image, "dtype", None) + ) + + import torch # type: ignore[import-not-found] + + if isinstance(tensor_image, torch.Tensor): + image_np = tensor_image.cpu().numpy() + else: + image_np = np.array(tensor_image) + + while len(image_np.shape) > 3: + image_np = image_np[0] + + if image_np.dtype in (np.float32, np.float64) and image_np.max() <= 1.0: + image_np = (image_np * 255).astype(np.uint8) + + if len(image_np.shape) == 3 and image_np.shape[2] == 3: + pil_image = Image.fromarray(image_np) + img_byte_arr = io.BytesIO() + pil_image.save(img_byte_arr, format="PNG") + return img_byte_arr.getvalue() + except Exception as exc: # pragma: no cover - defensive logging path + self._logger.error("Error processing image data: %s", exc, exc_info=True) + return None + + return None diff --git a/py/services/recipes/errors.py b/py/services/recipes/errors.py new file mode 100644 index 00000000..9e5d9720 --- /dev/null +++ b/py/services/recipes/errors.py @@ -0,0 +1,22 @@ +"""Shared exceptions for recipe services.""" +from __future__ import annotations + + +class RecipeServiceError(Exception): + """Base exception for recipe service failures.""" + + +class RecipeValidationError(RecipeServiceError): + """Raised when a request payload fails validation.""" + + +class RecipeNotFoundError(RecipeServiceError): + """Raised when a recipe resource cannot be located.""" + + +class RecipeDownloadError(RecipeServiceError): + """Raised when remote recipe assets cannot be downloaded.""" + + +class RecipeConflictError(RecipeServiceError): + """Raised when a conflicting recipe state is detected.""" diff --git a/py/services/recipes/persistence_service.py b/py/services/recipes/persistence_service.py new file mode 100644 index 00000000..945680df --- /dev/null +++ b/py/services/recipes/persistence_service.py @@ -0,0 +1,467 @@ +"""Services encapsulating recipe persistence workflows.""" +from __future__ import annotations + +import asyncio +import base64 +import json +import os +import re +import time +import uuid +from dataclasses import dataclass +from typing import Any, Dict, Iterable, Optional + +from ...config import config +from ...utils.utils import calculate_recipe_fingerprint +from .errors import RecipeNotFoundError, RecipeValidationError + + +@dataclass(frozen=True) +class PersistenceResult: + """Return payload from persistence operations.""" + + payload: dict[str, Any] + status: int = 200 + + +class RecipePersistenceService: + """Coordinate recipe persistence tasks across storage and caches.""" + + def __init__( + self, + *, + exif_utils, + card_preview_width: int, + logger, + ) -> None: + self._exif_utils = exif_utils + self._card_preview_width = card_preview_width + self._logger = logger + + async def save_recipe( + self, + *, + recipe_scanner, + image_bytes: bytes | None, + image_base64: str | None, + name: str | None, + tags: Iterable[str], + metadata: Optional[dict[str, Any]], + ) -> PersistenceResult: + """Persist a user uploaded recipe.""" + + missing_fields = [] + if not name: + missing_fields.append("name") + if metadata is None: + missing_fields.append("metadata") + if missing_fields: + raise RecipeValidationError( + f"Missing required fields: {', '.join(missing_fields)}" + ) + + resolved_image_bytes = self._resolve_image_bytes(image_bytes, image_base64) + recipes_dir = recipe_scanner.recipes_dir + os.makedirs(recipes_dir, exist_ok=True) + + recipe_id = str(uuid.uuid4()) + optimized_image, extension = self._exif_utils.optimize_image( + image_data=resolved_image_bytes, + target_width=self._card_preview_width, + format="webp", + quality=85, + preserve_metadata=True, + ) + image_filename = f"{recipe_id}{extension}" + image_path = os.path.join(recipes_dir, image_filename) + with open(image_path, "wb") as file_obj: + file_obj.write(optimized_image) + + current_time = time.time() + loras_data = [self._normalise_lora_entry(lora) for lora in metadata.get("loras", [])] + + gen_params = metadata.get("gen_params", {}) + if not gen_params and "raw_metadata" in metadata: + raw_metadata = metadata.get("raw_metadata", {}) + gen_params = { + "prompt": raw_metadata.get("prompt", ""), + "negative_prompt": raw_metadata.get("negative_prompt", ""), + "checkpoint": raw_metadata.get("checkpoint", {}), + "steps": raw_metadata.get("steps", ""), + "sampler": raw_metadata.get("sampler", ""), + "cfg_scale": raw_metadata.get("cfg_scale", ""), + "seed": raw_metadata.get("seed", ""), + "size": raw_metadata.get("size", ""), + "clip_skip": raw_metadata.get("clip_skip", ""), + } + + fingerprint = calculate_recipe_fingerprint(loras_data) + recipe_data: Dict[str, Any] = { + "id": recipe_id, + "file_path": image_path, + "title": name, + "modified": current_time, + "created_date": current_time, + "base_model": metadata.get("base_model", ""), + "loras": loras_data, + "gen_params": gen_params, + "fingerprint": fingerprint, + } + + tags_list = list(tags) + if tags_list: + recipe_data["tags"] = tags_list + + if metadata.get("source_path"): + recipe_data["source_path"] = metadata.get("source_path") + + json_filename = f"{recipe_id}.recipe.json" + json_path = os.path.join(recipes_dir, json_filename) + with open(json_path, "w", encoding="utf-8") as file_obj: + json.dump(recipe_data, file_obj, indent=4, ensure_ascii=False) + + self._exif_utils.append_recipe_metadata(image_path, recipe_data) + + matching_recipes = await self._find_matching_recipes(recipe_scanner, fingerprint, exclude_id=recipe_id) + await self._update_cache(recipe_scanner, recipe_data) + + return PersistenceResult( + { + "success": True, + "recipe_id": recipe_id, + "image_path": image_path, + "json_path": json_path, + "matching_recipes": matching_recipes, + } + ) + + async def delete_recipe(self, *, recipe_scanner, recipe_id: str) -> PersistenceResult: + """Delete an existing recipe.""" + + recipes_dir = recipe_scanner.recipes_dir + if not recipes_dir or not os.path.exists(recipes_dir): + raise RecipeNotFoundError("Recipes directory not found") + + recipe_json_path = os.path.join(recipes_dir, f"{recipe_id}.recipe.json") + if not os.path.exists(recipe_json_path): + raise RecipeNotFoundError("Recipe not found") + + with open(recipe_json_path, "r", encoding="utf-8") as file_obj: + recipe_data = json.load(file_obj) + + image_path = recipe_data.get("file_path") + os.remove(recipe_json_path) + if image_path and os.path.exists(image_path): + os.remove(image_path) + + await self._remove_from_cache(recipe_scanner, recipe_id) + return PersistenceResult({"success": True, "message": "Recipe deleted successfully"}) + + async def update_recipe(self, *, recipe_scanner, recipe_id: str, updates: dict[str, Any]) -> PersistenceResult: + """Update persisted metadata for a recipe.""" + + if not any(key in updates for key in ("title", "tags", "source_path", "preview_nsfw_level")): + raise RecipeValidationError( + "At least one field to update must be provided (title or tags or source_path or preview_nsfw_level)" + ) + + success = await recipe_scanner.update_recipe_metadata(recipe_id, updates) + if not success: + raise RecipeNotFoundError("Recipe not found or update failed") + + return PersistenceResult({"success": True, "recipe_id": recipe_id, "updates": updates}) + + async def reconnect_lora( + self, + *, + recipe_scanner, + recipe_id: str, + lora_index: int, + target_name: str, + ) -> PersistenceResult: + """Reconnect a LoRA entry within an existing recipe.""" + + recipe_path = os.path.join(recipe_scanner.recipes_dir, f"{recipe_id}.recipe.json") + if not os.path.exists(recipe_path): + raise RecipeNotFoundError("Recipe not found") + + lora_scanner = getattr(recipe_scanner, "_lora_scanner", None) + target_lora = None if lora_scanner is None else await lora_scanner.get_model_info_by_name(target_name) + if not target_lora: + raise RecipeNotFoundError(f"Local LoRA not found with name: {target_name}") + + with open(recipe_path, "r", encoding="utf-8") as file_obj: + recipe_data = json.load(file_obj) + + loras = recipe_data.get("loras", []) + if lora_index >= len(loras): + raise RecipeNotFoundError("LoRA index out of range in recipe") + + lora = loras[lora_index] + lora["isDeleted"] = False + lora["exclude"] = False + lora["file_name"] = target_name + if "sha256" in target_lora: + lora["hash"] = target_lora["sha256"].lower() + if target_lora.get("civitai"): + lora["modelName"] = target_lora["civitai"]["model"]["name"] + lora["modelVersionName"] = target_lora["civitai"]["name"] + lora["modelVersionId"] = target_lora["civitai"]["id"] + + recipe_data["fingerprint"] = calculate_recipe_fingerprint(recipe_data.get("loras", [])) + + with open(recipe_path, "w", encoding="utf-8") as file_obj: + json.dump(recipe_data, file_obj, indent=4, ensure_ascii=False) + + updated_lora = dict(lora) + updated_lora["inLibrary"] = True + updated_lora["preview_url"] = config.get_preview_static_url(target_lora["preview_url"]) + updated_lora["localPath"] = target_lora["file_path"] + + await self._refresh_cache_after_update(recipe_scanner, recipe_id, recipe_data) + + image_path = recipe_data.get("file_path") + if image_path and os.path.exists(image_path): + self._exif_utils.append_recipe_metadata(image_path, recipe_data) + + matching_recipes = [] + if "fingerprint" in recipe_data: + matching_recipes = await recipe_scanner.find_recipes_by_fingerprint(recipe_data["fingerprint"]) + if recipe_id in matching_recipes: + matching_recipes.remove(recipe_id) + + return PersistenceResult( + { + "success": True, + "recipe_id": recipe_id, + "updated_lora": updated_lora, + "matching_recipes": matching_recipes, + } + ) + + async def bulk_delete( + self, + *, + recipe_scanner, + recipe_ids: Iterable[str], + ) -> PersistenceResult: + """Delete multiple recipes in a single request.""" + + recipe_ids = list(recipe_ids) + if not recipe_ids: + raise RecipeValidationError("No recipe IDs provided") + + recipes_dir = recipe_scanner.recipes_dir + if not recipes_dir or not os.path.exists(recipes_dir): + raise RecipeNotFoundError("Recipes directory not found") + + deleted_recipes: list[str] = [] + failed_recipes: list[dict[str, Any]] = [] + + for recipe_id in recipe_ids: + recipe_json_path = os.path.join(recipes_dir, f"{recipe_id}.recipe.json") + if not os.path.exists(recipe_json_path): + failed_recipes.append({"id": recipe_id, "reason": "Recipe not found"}) + continue + + try: + with open(recipe_json_path, "r", encoding="utf-8") as file_obj: + recipe_data = json.load(file_obj) + image_path = recipe_data.get("file_path") + os.remove(recipe_json_path) + if image_path and os.path.exists(image_path): + os.remove(image_path) + deleted_recipes.append(recipe_id) + except Exception as exc: + failed_recipes.append({"id": recipe_id, "reason": str(exc)}) + + if deleted_recipes: + await self._bulk_remove_from_cache(recipe_scanner, deleted_recipes) + + return PersistenceResult( + { + "success": True, + "deleted": deleted_recipes, + "failed": failed_recipes, + "total_deleted": len(deleted_recipes), + "total_failed": len(failed_recipes), + } + ) + + async def save_recipe_from_widget( + self, + *, + recipe_scanner, + metadata: dict[str, Any], + image_bytes: bytes, + ) -> PersistenceResult: + """Save a recipe constructed from widget metadata.""" + + if not metadata: + raise RecipeValidationError("No generation metadata found") + + recipes_dir = recipe_scanner.recipes_dir + os.makedirs(recipes_dir, exist_ok=True) + + recipe_id = str(uuid.uuid4()) + image_filename = f"{recipe_id}.png" + image_path = os.path.join(recipes_dir, image_filename) + with open(image_path, "wb") as file_obj: + file_obj.write(image_bytes) + + lora_stack = metadata.get("loras", "") + lora_matches = re.findall(r"]+)>", lora_stack) + if not lora_matches: + raise RecipeValidationError("No LoRAs found in the generation metadata") + + lora_scanner = getattr(recipe_scanner, "_lora_scanner", None) + loras_data = [] + base_model_counts: Dict[str, int] = {} + + for name, strength in lora_matches: + lora_info = None + if lora_scanner is not None: + lora_info = await lora_scanner.get_model_info_by_name(name) + lora_data = { + "file_name": name, + "strength": float(strength), + "hash": (lora_info.get("sha256") or "").lower() if lora_info else "", + "modelVersionId": lora_info.get("civitai", {}).get("id") if lora_info else 0, + "modelName": lora_info.get("civitai", {}).get("model", {}).get("name") if lora_info else "", + "modelVersionName": lora_info.get("civitai", {}).get("name") if lora_info else "", + "isDeleted": False, + "exclude": False, + } + loras_data.append(lora_data) + + if lora_info and "base_model" in lora_info: + base_model = lora_info["base_model"] + base_model_counts[base_model] = base_model_counts.get(base_model, 0) + 1 + + recipe_name = self._derive_recipe_name(lora_matches) + most_common_base_model = ( + max(base_model_counts.items(), key=lambda item: item[1])[0] if base_model_counts else "" + ) + + recipe_data = { + "id": recipe_id, + "file_path": image_path, + "title": recipe_name, + "modified": time.time(), + "created_date": time.time(), + "base_model": most_common_base_model, + "loras": loras_data, + "checkpoint": metadata.get("checkpoint", ""), + "gen_params": { + key: value + for key, value in metadata.items() + if key not in ["checkpoint", "loras"] + }, + "loras_stack": lora_stack, + } + + json_filename = f"{recipe_id}.recipe.json" + json_path = os.path.join(recipes_dir, json_filename) + with open(json_path, "w", encoding="utf-8") as file_obj: + json.dump(recipe_data, file_obj, indent=4, ensure_ascii=False) + + self._exif_utils.append_recipe_metadata(image_path, recipe_data) + await self._update_cache(recipe_scanner, recipe_data) + + return PersistenceResult( + { + "success": True, + "recipe_id": recipe_id, + "image_path": image_path, + "json_path": json_path, + "recipe_name": recipe_name, + } + ) + + # Helper methods --------------------------------------------------- + + def _resolve_image_bytes(self, image_bytes: bytes | None, image_base64: str | None) -> bytes: + if image_bytes is not None: + return image_bytes + if image_base64: + try: + payload = image_base64.split(",", 1)[1] if "," in image_base64 else image_base64 + return base64.b64decode(payload) + except Exception as exc: # pragma: no cover - validation guard + raise RecipeValidationError(f"Invalid base64 image data: {exc}") from exc + raise RecipeValidationError("No image data provided") + + def _normalise_lora_entry(self, lora: dict[str, Any]) -> dict[str, Any]: + return { + "file_name": lora.get("file_name", "") + or ( + os.path.splitext(os.path.basename(lora.get("localPath", "")))[0] + if lora.get("localPath") + else "" + ), + "hash": (lora.get("hash") or "").lower(), + "strength": float(lora.get("weight", 1.0)), + "modelVersionId": lora.get("id", 0), + "modelName": lora.get("name", ""), + "modelVersionName": lora.get("version", ""), + "isDeleted": lora.get("isDeleted", False), + "exclude": lora.get("exclude", False), + } + + async def _find_matching_recipes( + self, + recipe_scanner, + fingerprint: str | None, + *, + exclude_id: Optional[str] = None, + ) -> list[str]: + if not fingerprint: + return [] + matches = await recipe_scanner.find_recipes_by_fingerprint(fingerprint) + if exclude_id and exclude_id in matches: + matches.remove(exclude_id) + return matches + + async def _update_cache(self, recipe_scanner, recipe_data: dict[str, Any]) -> None: + cache = getattr(recipe_scanner, "_cache", None) + if cache is not None: + cache.raw_data.append(recipe_data) + asyncio.create_task(cache.resort()) + self._logger.info("Added recipe %s to cache", recipe_data.get("id")) + + async def _remove_from_cache(self, recipe_scanner, recipe_id: str) -> None: + cache = getattr(recipe_scanner, "_cache", None) + if cache is not None: + cache.raw_data = [item for item in cache.raw_data if str(item.get("id", "")) != recipe_id] + asyncio.create_task(cache.resort()) + self._logger.info("Removed recipe %s from cache", recipe_id) + + async def _bulk_remove_from_cache(self, recipe_scanner, recipe_ids: Iterable[str]) -> None: + cache = getattr(recipe_scanner, "_cache", None) + if cache is not None: + recipe_ids_set = set(recipe_ids) + cache.raw_data = [item for item in cache.raw_data if item.get("id") not in recipe_ids_set] + asyncio.create_task(cache.resort()) + self._logger.info("Removed %s recipes from cache", len(recipe_ids_set)) + + async def _refresh_cache_after_update( + self, + recipe_scanner, + recipe_id: str, + recipe_data: dict[str, Any], + ) -> None: + cache = getattr(recipe_scanner, "_cache", None) + if cache is not None: + for cache_item in cache.raw_data: + if cache_item.get("id") == recipe_id: + cache_item.update({ + "loras": recipe_data.get("loras", []), + "fingerprint": recipe_data.get("fingerprint"), + }) + asyncio.create_task(cache.resort()) + break + + def _derive_recipe_name(self, lora_matches: list[tuple[str, str]]) -> str: + recipe_name_parts = [f"{name.strip()}-{float(strength):.2f}" for name, strength in lora_matches[:3]] + recipe_name = "_".join(recipe_name_parts) + return recipe_name or "recipe" diff --git a/py/services/recipes/sharing_service.py b/py/services/recipes/sharing_service.py new file mode 100644 index 00000000..7c365bba --- /dev/null +++ b/py/services/recipes/sharing_service.py @@ -0,0 +1,113 @@ +"""Services handling recipe sharing and downloads.""" +from __future__ import annotations + +import os +import shutil +import tempfile +import time +from dataclasses import dataclass +from typing import Any, Dict + +from .errors import RecipeNotFoundError + + +@dataclass(frozen=True) +class SharingResult: + """Return payload for share operations.""" + + payload: dict[str, Any] + status: int = 200 + + +@dataclass(frozen=True) +class DownloadInfo: + """Information required to stream a shared recipe file.""" + + file_path: str + download_filename: str + + +class RecipeSharingService: + """Prepare temporary recipe downloads with TTL cleanup.""" + + def __init__(self, *, ttl_seconds: int = 300, logger) -> None: + self._ttl_seconds = ttl_seconds + self._logger = logger + self._shared_recipes: Dict[str, Dict[str, Any]] = {} + + async def share_recipe(self, *, recipe_scanner, recipe_id: str) -> SharingResult: + """Prepare a temporary downloadable copy of a recipe image.""" + + cache = await recipe_scanner.get_cached_data() + recipe = next( + (r for r in getattr(cache, "raw_data", []) if str(r.get("id", "")) == recipe_id), + None, + ) + if not recipe: + raise RecipeNotFoundError("Recipe not found") + + image_path = recipe.get("file_path") + if not image_path or not os.path.exists(image_path): + raise RecipeNotFoundError("Recipe image not found") + + ext = os.path.splitext(image_path)[1] + with tempfile.NamedTemporaryFile(suffix=ext, delete=False) as temp_file: + temp_path = temp_file.name + + shutil.copy2(image_path, temp_path) + timestamp = int(time.time()) + self._shared_recipes[recipe_id] = { + "path": temp_path, + "timestamp": timestamp, + "expires": time.time() + self._ttl_seconds, + } + self._cleanup_shared_recipes() + + safe_title = recipe.get("title", "").replace(" ", "_").lower() + filename = f"recipe_{safe_title}{ext}" if safe_title else f"recipe_{recipe_id}{ext}" + url_path = f"/api/recipe/{recipe_id}/share/download?t={timestamp}" + return SharingResult({"success": True, "download_url": url_path, "filename": filename}) + + async def prepare_download(self, *, recipe_scanner, recipe_id: str) -> DownloadInfo: + """Return file path and filename for a prepared shared recipe.""" + + shared_info = self._shared_recipes.get(recipe_id) + if not shared_info or time.time() > shared_info.get("expires", 0): + self._cleanup_entry(recipe_id) + raise RecipeNotFoundError("Shared recipe not found or expired") + + file_path = shared_info["path"] + if not os.path.exists(file_path): + self._cleanup_entry(recipe_id) + raise RecipeNotFoundError("Shared recipe file not found") + + cache = await recipe_scanner.get_cached_data() + recipe = next( + (r for r in getattr(cache, "raw_data", []) if str(r.get("id", "")) == recipe_id), + None, + ) + filename_base = ( + f"recipe_{recipe.get('title', '').replace(' ', '_').lower()}" if recipe else recipe_id + ) + ext = os.path.splitext(file_path)[1] + download_filename = f"{filename_base}{ext}" + return DownloadInfo(file_path=file_path, download_filename=download_filename) + + def _cleanup_shared_recipes(self) -> None: + for recipe_id in list(self._shared_recipes.keys()): + shared = self._shared_recipes.get(recipe_id) + if not shared: + continue + if time.time() > shared.get("expires", 0): + self._cleanup_entry(recipe_id) + + def _cleanup_entry(self, recipe_id: str) -> None: + shared_info = self._shared_recipes.pop(recipe_id, None) + if not shared_info: + return + file_path = shared_info.get("path") + if file_path and os.path.exists(file_path): + try: + os.unlink(file_path) + except Exception as exc: # pragma: no cover - defensive logging + self._logger.error("Error cleaning up shared recipe %s: %s", recipe_id, exc) diff --git a/tests/services/test_recipe_services.py b/tests/services/test_recipe_services.py new file mode 100644 index 00000000..e57abf2f --- /dev/null +++ b/tests/services/test_recipe_services.py @@ -0,0 +1,146 @@ +import logging +import os +from types import SimpleNamespace + +import pytest + +from py.services.recipes.analysis_service import RecipeAnalysisService +from py.services.recipes.errors import RecipeDownloadError, RecipeNotFoundError +from py.services.recipes.persistence_service import RecipePersistenceService + + +class DummyExifUtils: + def optimize_image(self, image_data, target_width, format, quality, preserve_metadata): + return image_data, ".webp" + + def append_recipe_metadata(self, image_path, recipe_data): + self.appended = (image_path, recipe_data) + + def extract_image_metadata(self, path): + return {} + + +@pytest.mark.asyncio +async def test_analyze_remote_image_download_failure_cleans_temp(tmp_path, monkeypatch): + exif_utils = DummyExifUtils() + + class DummyFactory: + def create_parser(self, metadata): + return None + + async def downloader_factory(): + class Downloader: + async def download_file(self, url, path, use_auth=False): + return False, "failure" + + return Downloader() + + service = RecipeAnalysisService( + exif_utils=exif_utils, + recipe_parser_factory=DummyFactory(), + downloader_factory=downloader_factory, + metadata_collector=None, + metadata_processor_cls=None, + metadata_registry_cls=None, + standalone_mode=False, + logger=logging.getLogger("test"), + ) + + temp_path = tmp_path / "temp.jpg" + + def create_temp_path(): + temp_path.write_bytes(b"") + return str(temp_path) + + monkeypatch.setattr(service, "_create_temp_path", create_temp_path) + + with pytest.raises(RecipeDownloadError): + await service.analyze_remote_image( + url="https://example.com/image.jpg", + recipe_scanner=SimpleNamespace(), + civitai_client=SimpleNamespace(), + ) + + assert not temp_path.exists(), "temporary file should be cleaned after failure" + + +@pytest.mark.asyncio +async def test_analyze_local_image_missing_file(tmp_path): + async def downloader_factory(): + return SimpleNamespace() + + service = RecipeAnalysisService( + exif_utils=DummyExifUtils(), + recipe_parser_factory=SimpleNamespace(create_parser=lambda metadata: None), + downloader_factory=downloader_factory, + metadata_collector=None, + metadata_processor_cls=None, + metadata_registry_cls=None, + standalone_mode=False, + logger=logging.getLogger("test"), + ) + + with pytest.raises(RecipeNotFoundError): + await service.analyze_local_image( + file_path=str(tmp_path / "missing.png"), + recipe_scanner=SimpleNamespace(), + ) + + +@pytest.mark.asyncio +async def test_save_recipe_reports_duplicates(tmp_path): + exif_utils = DummyExifUtils() + + class DummyCache: + def __init__(self): + self.raw_data = [] + + async def resort(self): + pass + + class DummyScanner: + def __init__(self, root): + self.recipes_dir = str(root) + self._cache = DummyCache() + self.last_fingerprint = None + + async def find_recipes_by_fingerprint(self, fingerprint): + self.last_fingerprint = fingerprint + return ["existing"] + + scanner = DummyScanner(tmp_path) + service = RecipePersistenceService( + exif_utils=exif_utils, + card_preview_width=512, + logger=logging.getLogger("test"), + ) + + metadata = { + "base_model": "sd", + "loras": [ + { + "file_name": "sample", + "hash": "abc123", + "weight": 0.5, + "id": 1, + "name": "Sample", + "version": "v1", + "isDeleted": False, + "exclude": False, + } + ], + } + + result = await service.save_recipe( + recipe_scanner=scanner, + image_bytes=b"image-bytes", + image_base64=None, + name="My Recipe", + tags=["tag"], + metadata=metadata, + ) + + assert result.payload["matching_recipes"] == ["existing"] + assert scanner.last_fingerprint is not None + assert os.path.exists(result.payload["json_path"]) + assert scanner._cache.raw_data From b91f06405dcd62253c3c31e30262b5c3275e048f Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 22 Sep 2025 13:42:36 +0800 Subject: [PATCH 065/110] feat: support clip strength in LoRA usage tips, fixes #401 --- locales/de.json | 1 + locales/en.json | 1 + locales/es.json | 1 + locales/fr.json | 1 + locales/ja.json | 1 + locales/ko.json | 1 + locales/ru.json | 1 + locales/zh-CN.json | 1 + locales/zh-TW.json | 1 + .../components/ContextMenu/LoraContextMenu.js | 7 ++-- static/js/components/shared/ModelCard.js | 5 +-- static/js/components/shared/ModelModal.js | 1 + static/js/managers/BulkManager.js | 8 ++-- static/js/utils/uiHelpers.js | 42 ++++++++++++++++++- web/comfyui/autocomplete.js | 37 +++++++++++++--- 15 files changed, 90 insertions(+), 19 deletions(-) diff --git a/locales/de.json b/locales/de.json index bcff9fc9..09ce4dec 100644 --- a/locales/de.json +++ b/locales/de.json @@ -727,6 +727,7 @@ "strengthMin": "Stärke Min", "strengthMax": "Stärke Max", "strength": "Stärke", + "clipStrength": "Clip-Stärke", "clipSkip": "Clip Skip", "valuePlaceholder": "Wert", "add": "Hinzufügen" diff --git a/locales/en.json b/locales/en.json index 237755c0..35d59115 100644 --- a/locales/en.json +++ b/locales/en.json @@ -727,6 +727,7 @@ "strengthMin": "Strength Min", "strengthMax": "Strength Max", "strength": "Strength", + "clipStrength": "Clip Strength", "clipSkip": "Clip Skip", "valuePlaceholder": "Value", "add": "Add" diff --git a/locales/es.json b/locales/es.json index a4a8f401..a674b713 100644 --- a/locales/es.json +++ b/locales/es.json @@ -727,6 +727,7 @@ "strengthMin": "Fuerza mínima", "strengthMax": "Fuerza máxima", "strength": "Fuerza", + "clipStrength": "Fuerza de Clip", "clipSkip": "Clip Skip", "valuePlaceholder": "Valor", "add": "Añadir" diff --git a/locales/fr.json b/locales/fr.json index b492d805..519f5ec5 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -727,6 +727,7 @@ "strengthMin": "Force Min", "strengthMax": "Force Max", "strength": "Force", + "clipStrength": "Force Clip", "clipSkip": "Clip Skip", "valuePlaceholder": "Valeur", "add": "Ajouter" diff --git a/locales/ja.json b/locales/ja.json index f2f889d4..5670b167 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -727,6 +727,7 @@ "strengthMin": "強度最小", "strengthMax": "強度最大", "strength": "強度", + "clipStrength": "クリップ強度", "clipSkip": "Clip Skip", "valuePlaceholder": "値", "add": "追加" diff --git a/locales/ko.json b/locales/ko.json index 4f329b89..90bbbb75 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -727,6 +727,7 @@ "strengthMin": "최소 강도", "strengthMax": "최대 강도", "strength": "강도", + "clipStrength": "클립 강도", "clipSkip": "클립 스킵", "valuePlaceholder": "값", "add": "추가" diff --git a/locales/ru.json b/locales/ru.json index a0e78b34..08112670 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -727,6 +727,7 @@ "strengthMin": "Мин. сила", "strengthMax": "Макс. сила", "strength": "Сила", + "clipStrength": "Сила клипа", "clipSkip": "Clip Skip", "valuePlaceholder": "Значение", "add": "Добавить" diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 9b713351..6ef426c9 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -727,6 +727,7 @@ "strengthMin": "最小强度", "strengthMax": "最大强度", "strength": "强度", + "clipStrength": "Clip 强度", "clipSkip": "Clip Skip", "valuePlaceholder": "数值", "add": "添加" diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 1c70b7c3..70e769d1 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -727,6 +727,7 @@ "strengthMin": "最小強度", "strengthMax": "最大強度", "strength": "強度", + "clipStrength": "Clip 強度", "clipSkip": "Clip Skip", "valuePlaceholder": "數值", "add": "新增" diff --git a/static/js/components/ContextMenu/LoraContextMenu.js b/static/js/components/ContextMenu/LoraContextMenu.js index ee7634b6..4b72cafa 100644 --- a/static/js/components/ContextMenu/LoraContextMenu.js +++ b/static/js/components/ContextMenu/LoraContextMenu.js @@ -1,7 +1,7 @@ import { BaseContextMenu } from './BaseContextMenu.js'; import { ModelContextMenuMixin } from './ModelContextMenuMixin.js'; import { getModelApiClient, resetAndReload } from '../../api/modelApiFactory.js'; -import { copyLoraSyntax, sendLoraToWorkflow } from '../../utils/uiHelpers.js'; +import { copyLoraSyntax, sendLoraToWorkflow, buildLoraSyntax } from '../../utils/uiHelpers.js'; import { showExcludeModal, showDeleteModal } from '../../utils/modalUtils.js'; import { moveManager } from '../../managers/MoveManager.js'; @@ -70,9 +70,8 @@ export class LoraContextMenu extends BaseContextMenu { sendLoraToWorkflow(replaceMode) { const card = this.currentCard; const usageTips = JSON.parse(card.dataset.usage_tips || '{}'); - const strength = usageTips.strength || 1; - const loraSyntax = ``; - + const loraSyntax = buildLoraSyntax(card.dataset.file_name, usageTips); + sendLoraToWorkflow(loraSyntax, replaceMode, 'lora'); } } diff --git a/static/js/components/shared/ModelCard.js b/static/js/components/shared/ModelCard.js index c17b60fd..ba8db595 100644 --- a/static/js/components/shared/ModelCard.js +++ b/static/js/components/shared/ModelCard.js @@ -1,4 +1,4 @@ -import { showToast, openCivitai, copyToClipboard, copyLoraSyntax, sendLoraToWorkflow, openExampleImagesFolder } from '../../utils/uiHelpers.js'; +import { showToast, openCivitai, copyToClipboard, copyLoraSyntax, sendLoraToWorkflow, openExampleImagesFolder, buildLoraSyntax } from '../../utils/uiHelpers.js'; import { state, getCurrentPageState } from '../../state/index.js'; import { showModelModal } from './ModelModal.js'; import { toggleShowcase } from './showcase/ShowcaseView.js'; @@ -155,8 +155,7 @@ async function toggleFavorite(card) { function handleSendToWorkflow(card, replaceMode, modelType) { if (modelType === MODEL_TYPES.LORA) { const usageTips = JSON.parse(card.dataset.usage_tips || '{}'); - const strength = usageTips.strength || 1; - const loraSyntax = ``; + const loraSyntax = buildLoraSyntax(card.dataset.file_name, usageTips); sendLoraToWorkflow(loraSyntax, replaceMode, 'lora'); } else { // Checkpoint send functionality - to be implemented diff --git a/static/js/components/shared/ModelModal.js b/static/js/components/shared/ModelModal.js index 081b0a46..b0032f3b 100644 --- a/static/js/components/shared/ModelModal.js +++ b/static/js/components/shared/ModelModal.js @@ -271,6 +271,7 @@ function renderLoraSpecificContent(lora, escapedWords) { + diff --git a/static/js/managers/BulkManager.js b/static/js/managers/BulkManager.js index 1dade6ff..f6fdf7c8 100644 --- a/static/js/managers/BulkManager.js +++ b/static/js/managers/BulkManager.js @@ -1,5 +1,5 @@ import { state, getCurrentPageState } from '../state/index.js'; -import { showToast, copyToClipboard, sendLoraToWorkflow } from '../utils/uiHelpers.js'; +import { showToast, copyToClipboard, sendLoraToWorkflow, buildLoraSyntax } from '../utils/uiHelpers.js'; import { updateCardsForBulkMode } from '../components/shared/ModelCard.js'; import { modalManager } from './ModalManager.js'; import { getModelApiClient, resetAndReload } from '../api/modelApiFactory.js'; @@ -321,8 +321,7 @@ export class BulkManager { if (metadata) { const usageTips = JSON.parse(metadata.usageTips || '{}'); - const strength = usageTips.strength || 1; - loraSyntaxes.push(``); + loraSyntaxes.push(buildLoraSyntax(metadata.fileName, usageTips)); } else { missingLoras.push(filepath); } @@ -361,8 +360,7 @@ export class BulkManager { if (metadata) { const usageTips = JSON.parse(metadata.usageTips || '{}'); - const strength = usageTips.strength || 1; - loraSyntaxes.push(``); + loraSyntaxes.push(buildLoraSyntax(metadata.fileName, usageTips)); } else { missingLoras.push(filepath); } diff --git a/static/js/utils/uiHelpers.js b/static/js/utils/uiHelpers.js index f4e4091a..3aed6942 100644 --- a/static/js/utils/uiHelpers.js +++ b/static/js/utils/uiHelpers.js @@ -295,10 +295,48 @@ export function getNSFWLevelName(level) { return 'Unknown'; } +function parseUsageTipNumber(value) { + if (typeof value === 'number' && Number.isFinite(value)) { + return value; + } + + if (typeof value === 'string') { + const parsed = parseFloat(value); + if (Number.isFinite(parsed)) { + return parsed; + } + } + + return null; +} + +export function getLoraStrengthsFromUsageTips(usageTips = {}) { + const parsedStrength = parseUsageTipNumber(usageTips.strength); + const clipStrengthSource = usageTips.clip_strength ?? usageTips.clipStrength; + const parsedClipStrength = parseUsageTipNumber(clipStrengthSource); + + return { + strength: parsedStrength !== null ? parsedStrength : 1, + hasStrength: parsedStrength !== null, + clipStrength: parsedClipStrength, + hasClipStrength: parsedClipStrength !== null, + }; +} + +export function buildLoraSyntax(fileName, usageTips = {}) { + const { strength, hasStrength, clipStrength, hasClipStrength } = getLoraStrengthsFromUsageTips(usageTips); + + if (hasClipStrength) { + const modelStrength = hasStrength ? strength : 1; + return ``; + } + + return ``; +} + export function copyLoraSyntax(card) { const usageTips = JSON.parse(card.dataset.usage_tips || "{}"); - const strength = usageTips.strength || 1; - const baseSyntax = ``; + const baseSyntax = buildLoraSyntax(card.dataset.file_name, usageTips); // Check if trigger words should be included const includeTriggerWords = state.global.settings.includeTriggerWords; diff --git a/web/comfyui/autocomplete.js b/web/comfyui/autocomplete.js index 202026ad..790c062a 100644 --- a/web/comfyui/autocomplete.js +++ b/web/comfyui/autocomplete.js @@ -2,6 +2,19 @@ import { api } from "../../scripts/api.js"; import { app } from "../../scripts/app.js"; import { TextAreaCaretHelper } from "./textarea_caret_helper.js"; +function parseUsageTipNumber(value) { + if (typeof value === 'number' && Number.isFinite(value)) { + return value; + } + if (typeof value === 'string') { + const parsed = parseFloat(value); + if (Number.isFinite(parsed)) { + return parsed; + } + } + return null; +} + class AutoComplete { constructor(inputElement, modelType = 'loras', options = {}) { this.inputElement = inputElement; @@ -380,8 +393,10 @@ class AutoComplete { // Extract just the filename for LoRA name const fileName = relativePath.split(/[/\\]/).pop().replace(/\.(safetensors|ckpt|pt|bin)$/i, ''); - // Get usage tips and extract strength + // Get usage tips and extract strength information let strength = 1.0; // Default strength + let hasStrength = false; + let clipStrength = null; try { const response = await api.fetchApi(`/lm/loras/usage-tips-by-path?relative_path=${encodeURIComponent(relativePath)}`); if (response.ok) { @@ -389,8 +404,18 @@ class AutoComplete { if (data.success && data.usage_tips) { try { const usageTips = JSON.parse(data.usage_tips); - if (usageTips.strength && typeof usageTips.strength === 'number') { - strength = usageTips.strength; + const parsedStrength = parseUsageTipNumber(usageTips.strength); + if (parsedStrength !== null) { + strength = parsedStrength; + hasStrength = true; + } + const clipSource = usageTips.clip_strength ?? usageTips.clipStrength; + const parsedClipStrength = parseUsageTipNumber(clipSource); + if (parsedClipStrength !== null) { + clipStrength = parsedClipStrength; + if (!hasStrength) { + strength = 1.0; + } } } catch (parseError) { console.warn('Failed to parse usage tips JSON:', parseError); @@ -401,8 +426,10 @@ class AutoComplete { console.warn('Failed to fetch usage tips:', error); } - // Format the LoRA code with strength - const loraCode = `, `; + // Format the LoRA code with strength values + const loraCode = clipStrength !== null + ? `, ` + : `, `; const currentValue = this.inputElement.value; const caretPos = this.getCaretPosition(); From 42872e6d2de7f12f003deafa92aeafbee31d9737 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Mon, 22 Sep 2025 13:45:40 +0800 Subject: [PATCH 066/110] feat(recipes): expose recipe scanner mutation apis --- py/routes/handlers/recipe_handlers.py | 67 +----- py/services/recipe_cache.py | 146 +++++++----- py/services/recipe_scanner.py | 255 +++++++++++++++++++-- py/services/recipes/persistence_service.py | 91 +------- py/services/recipes/sharing_service.py | 12 +- tests/services/test_recipe_scanner.py | 185 +++++++++++++++ tests/services/test_recipe_services.py | 4 + 7 files changed, 532 insertions(+), 228 deletions(-) create mode 100644 tests/services/test_recipe_scanner.py diff --git a/py/routes/handlers/recipe_handlers.py b/py/routes/handlers/recipe_handlers.py index 35f4c088..aa912477 100644 --- a/py/routes/handlers/recipe_handlers.py +++ b/py/routes/handlers/recipe_handlers.py @@ -290,27 +290,7 @@ class RecipeQueryHandler: if not lora_hash: return web.json_response({"success": False, "error": "Lora hash is required"}, status=400) - cache = await recipe_scanner.get_cached_data() - matching_recipes = [] - for recipe in getattr(cache, "raw_data", []): - for lora in recipe.get("loras", []): - if lora.get("hash", "").lower() == lora_hash.lower(): - matching_recipes.append(recipe) - break - - lora_scanner = getattr(recipe_scanner, "_lora_scanner", None) - for recipe in matching_recipes: - for lora in recipe.get("loras", []): - hash_value = (lora.get("hash") or "").lower() - if hash_value and lora_scanner is not None: - lora["inLibrary"] = lora_scanner.has_hash(hash_value) - lora["preview_url"] = lora_scanner.get_preview_url_by_hash(hash_value) - lora["localPath"] = lora_scanner.get_path_by_hash(hash_value) - if recipe.get("file_path"): - recipe["file_url"] = self._format_recipe_file_url(recipe["file_path"]) - else: - recipe["file_url"] = "/loras_static/images/no-preview.png" - + matching_recipes = await recipe_scanner.get_recipes_for_lora(lora_hash) return web.json_response({"success": True, "recipes": matching_recipes}) except Exception as exc: self._logger.error("Error getting recipes for Lora: %s", exc) @@ -384,50 +364,15 @@ class RecipeQueryHandler: raise RuntimeError("Recipe scanner unavailable") recipe_id = request.match_info["recipe_id"] - cache = await recipe_scanner.get_cached_data() - recipe = next( - (r for r in getattr(cache, "raw_data", []) if str(r.get("id", "")) == recipe_id), - None, - ) - if not recipe: + try: + syntax_parts = await recipe_scanner.get_recipe_syntax_tokens(recipe_id) + except RecipeNotFoundError: return web.json_response({"error": "Recipe not found"}, status=404) - loras = recipe.get("loras", []) - if not loras: + if not syntax_parts: return web.json_response({"error": "No LoRAs found in this recipe"}, status=400) - lora_scanner = getattr(recipe_scanner, "_lora_scanner", None) - hash_index = getattr(lora_scanner, "_hash_index", None) - - lora_syntax_parts = [] - for lora in loras: - if lora.get("isDeleted", False): - continue - hash_value = (lora.get("hash") or "").lower() - if not hash_value or lora_scanner is None or not lora_scanner.has_hash(hash_value): - continue - - file_name = None - if hash_value and hash_index is not None and hasattr(hash_index, "_hash_to_path"): - file_path = hash_index._hash_to_path.get(hash_value) - if file_path: - file_name = os.path.splitext(os.path.basename(file_path))[0] - - if not file_name and lora.get("modelVersionId") and lora_scanner is not None: - all_loras = await lora_scanner.get_cached_data() - for cached_lora in getattr(all_loras, "raw_data", []): - civitai_info = cached_lora.get("civitai") - if civitai_info and civitai_info.get("id") == lora.get("modelVersionId"): - file_name = os.path.splitext(os.path.basename(cached_lora["path"]))[0] - break - - if not file_name: - file_name = lora.get("file_name", "unknown-lora") - - strength = lora.get("strength", 1.0) - lora_syntax_parts.append(f"") - - return web.json_response({"success": True, "syntax": " ".join(lora_syntax_parts)}) + return web.json_response({"success": True, "syntax": " ".join(syntax_parts)}) except Exception as exc: self._logger.error("Error generating recipe syntax: %s", exc, exc_info=True) return web.json_response({"error": str(exc)}, status=500) diff --git a/py/services/recipe_cache.py b/py/services/recipe_cache.py index b1f52246..ac28b3aa 100644 --- a/py/services/recipe_cache.py +++ b/py/services/recipe_cache.py @@ -1,5 +1,5 @@ import asyncio -from typing import List, Dict +from typing import Iterable, List, Dict, Optional from dataclasses import dataclass from operator import itemgetter from natsort import natsorted @@ -10,77 +10,115 @@ class RecipeCache: raw_data: List[Dict] sorted_by_name: List[Dict] sorted_by_date: List[Dict] - + def __post_init__(self): self._lock = asyncio.Lock() async def resort(self, name_only: bool = False): """Resort all cached data views""" async with self._lock: - self.sorted_by_name = natsorted( - self.raw_data, - key=lambda x: x.get('title', '').lower() # Case-insensitive sort - ) - if not name_only: - self.sorted_by_date = sorted( - self.raw_data, - key=itemgetter('created_date', 'file_path'), - reverse=True - ) - - async def update_recipe_metadata(self, recipe_id: str, metadata: Dict) -> bool: + self._resort_locked(name_only=name_only) + + async def update_recipe_metadata(self, recipe_id: str, metadata: Dict, *, resort: bool = True) -> bool: """Update metadata for a specific recipe in all cached data - + Args: recipe_id: The ID of the recipe to update metadata: The new metadata - + Returns: bool: True if the update was successful, False if the recipe wasn't found """ + async with self._lock: + for item in self.raw_data: + if str(item.get('id')) == str(recipe_id): + item.update(metadata) + if resort: + self._resort_locked() + return True + return False # Recipe not found + + async def add_recipe(self, recipe_data: Dict, *, resort: bool = False) -> None: + """Add a new recipe to the cache.""" - # Update in raw_data - for item in self.raw_data: - if item.get('id') == recipe_id: - item.update(metadata) - break - else: - return False # Recipe not found - - # Resort to reflect changes - await self.resort() - return True - - async def add_recipe(self, recipe_data: Dict) -> None: - """Add a new recipe to the cache - - Args: - recipe_data: The recipe data to add - """ async with self._lock: self.raw_data.append(recipe_data) - await self.resort() + if resort: + self._resort_locked() + + async def remove_recipe(self, recipe_id: str, *, resort: bool = False) -> Optional[Dict]: + """Remove a recipe from the cache by ID. - async def remove_recipe(self, recipe_id: str) -> bool: - """Remove a recipe from the cache by ID - Args: recipe_id: The ID of the recipe to remove - + Returns: - bool: True if the recipe was found and removed, False otherwise + The removed recipe data if found, otherwise ``None``. """ - # Find the recipe in raw_data - recipe_index = next((i for i, recipe in enumerate(self.raw_data) - if recipe.get('id') == recipe_id), None) - - if recipe_index is None: - return False - - # Remove from raw_data - self.raw_data.pop(recipe_index) - - # Resort to update sorted lists - await self.resort() - - return True \ No newline at end of file + + async with self._lock: + for index, recipe in enumerate(self.raw_data): + if str(recipe.get('id')) == str(recipe_id): + removed = self.raw_data.pop(index) + if resort: + self._resort_locked() + return removed + return None + + async def bulk_remove(self, recipe_ids: Iterable[str], *, resort: bool = False) -> List[Dict]: + """Remove multiple recipes from the cache.""" + + id_set = {str(recipe_id) for recipe_id in recipe_ids} + if not id_set: + return [] + + async with self._lock: + removed = [item for item in self.raw_data if str(item.get('id')) in id_set] + if not removed: + return [] + + self.raw_data = [item for item in self.raw_data if str(item.get('id')) not in id_set] + if resort: + self._resort_locked() + return removed + + async def replace_recipe(self, recipe_id: str, new_data: Dict, *, resort: bool = False) -> bool: + """Replace cached data for a recipe.""" + + async with self._lock: + for index, recipe in enumerate(self.raw_data): + if str(recipe.get('id')) == str(recipe_id): + self.raw_data[index] = new_data + if resort: + self._resort_locked() + return True + return False + + async def get_recipe(self, recipe_id: str) -> Optional[Dict]: + """Return a shallow copy of a cached recipe.""" + + async with self._lock: + for recipe in self.raw_data: + if str(recipe.get('id')) == str(recipe_id): + return dict(recipe) + return None + + async def snapshot(self) -> List[Dict]: + """Return a copy of all cached recipes.""" + + async with self._lock: + return [dict(item) for item in self.raw_data] + + def _resort_locked(self, *, name_only: bool = False) -> None: + """Sort cached views. Caller must hold ``_lock``.""" + + self.sorted_by_name = natsorted( + self.raw_data, + key=lambda x: x.get('title', '').lower() + ) + if not name_only: + self.sorted_by_date = sorted( + self.raw_data, + key=itemgetter('created_date', 'file_path'), + reverse=True + ) \ No newline at end of file diff --git a/py/services/recipe_scanner.py b/py/services/recipe_scanner.py index ca5a20ac..9a82b237 100644 --- a/py/services/recipe_scanner.py +++ b/py/services/recipe_scanner.py @@ -3,13 +3,14 @@ import logging import asyncio import json import time -from typing import List, Dict, Optional, Any, Tuple +from typing import Any, Dict, Iterable, List, Optional, Set, Tuple from ..config import config from .recipe_cache import RecipeCache from .service_registry import ServiceRegistry from .lora_scanner import LoraScanner from .metadata_service import get_default_metadata_provider -from ..utils.utils import fuzzy_match +from .recipes.errors import RecipeNotFoundError +from ..utils.utils import calculate_recipe_fingerprint, fuzzy_match from natsort import natsorted import sys @@ -46,6 +47,8 @@ class RecipeScanner: self._initialization_lock = asyncio.Lock() self._initialization_task: Optional[asyncio.Task] = None self._is_initializing = False + self._mutation_lock = asyncio.Lock() + self._resort_tasks: Set[asyncio.Task] = set() if lora_scanner: self._lora_scanner = lora_scanner self._initialized = True @@ -191,6 +194,22 @@ class RecipeScanner: # Clean up the event loop loop.close() + def _schedule_resort(self, *, name_only: bool = False) -> None: + """Schedule a background resort of the recipe cache.""" + + if not self._cache: + return + + async def _resort_wrapper() -> None: + try: + await self._cache.resort(name_only=name_only) + except Exception as exc: # pragma: no cover - defensive logging + logger.error("Recipe Scanner: error resorting cache: %s", exc, exc_info=True) + + task = asyncio.create_task(_resort_wrapper()) + self._resort_tasks.add(task) + task.add_done_callback(lambda finished: self._resort_tasks.discard(finished)) + @property def recipes_dir(self) -> str: """Get path to recipes directory""" @@ -255,7 +274,45 @@ class RecipeScanner: # Return the cache (may be empty or partially initialized) return self._cache or RecipeCache(raw_data=[], sorted_by_name=[], sorted_by_date=[]) - + + async def refresh_cache(self, force: bool = False) -> RecipeCache: + """Public helper to refresh or return the recipe cache.""" + + return await self.get_cached_data(force_refresh=force) + + async def add_recipe(self, recipe_data: Dict[str, Any]) -> None: + """Add a recipe to the in-memory cache.""" + + if not recipe_data: + return + + cache = await self.get_cached_data() + await cache.add_recipe(recipe_data, resort=False) + self._schedule_resort() + + async def remove_recipe(self, recipe_id: str) -> bool: + """Remove a recipe from the cache by ID.""" + + if not recipe_id: + return False + + cache = await self.get_cached_data() + removed = await cache.remove_recipe(recipe_id, resort=False) + if removed is None: + return False + + self._schedule_resort() + return True + + async def bulk_remove(self, recipe_ids: Iterable[str]) -> int: + """Remove multiple recipes from the cache.""" + + cache = await self.get_cached_data() + removed = await cache.bulk_remove(recipe_ids, resort=False) + if removed: + self._schedule_resort() + return len(removed) + async def scan_all_recipes(self) -> List[Dict]: """Scan all recipe JSON files and return metadata""" recipes = [] @@ -326,7 +383,6 @@ class RecipeScanner: # Calculate and update fingerprint if missing if 'loras' in recipe_data and 'fingerprint' not in recipe_data: - from ..utils.utils import calculate_recipe_fingerprint fingerprint = calculate_recipe_fingerprint(recipe_data['loras']) recipe_data['fingerprint'] = fingerprint @@ -497,9 +553,36 @@ class RecipeScanner: logger.error(f"Error getting base model for lora: {e}") return None + def _enrich_lora_entry(self, lora: Dict[str, Any]) -> Dict[str, Any]: + """Populate convenience fields for a LoRA entry.""" + + if not lora or not self._lora_scanner: + return lora + + hash_value = (lora.get('hash') or '').lower() + if not hash_value: + return lora + + try: + lora['inLibrary'] = self._lora_scanner.has_hash(hash_value) + lora['preview_url'] = self._lora_scanner.get_preview_url_by_hash(hash_value) + lora['localPath'] = self._lora_scanner.get_path_by_hash(hash_value) + except Exception as exc: # pragma: no cover - defensive logging + logger.debug("Error enriching lora entry %s: %s", hash_value, exc) + + return lora + + async def get_local_lora(self, name: str) -> Optional[Dict[str, Any]]: + """Lookup a local LoRA model by name.""" + + if not self._lora_scanner or not name: + return None + + return await self._lora_scanner.get_model_info_by_name(name) + async def get_paginated_data(self, page: int, page_size: int, sort_by: str = 'date', search: str = None, filters: dict = None, search_options: dict = None, lora_hash: str = None, bypass_filters: bool = True): """Get paginated and filtered recipe data - + Args: page: Current page number (1-based) page_size: Number of items per page @@ -598,16 +681,12 @@ class RecipeScanner: # Get paginated items paginated_items = filtered_data[start_idx:end_idx] - + # Add inLibrary information for each lora for item in paginated_items: if 'loras' in item: - for lora in item['loras']: - if 'hash' in lora and lora['hash']: - lora['inLibrary'] = self._lora_scanner.has_hash(lora['hash'].lower()) - lora['preview_url'] = self._lora_scanner.get_preview_url_by_hash(lora['hash'].lower()) - lora['localPath'] = self._lora_scanner.get_path_by_hash(lora['hash'].lower()) - + item['loras'] = [self._enrich_lora_entry(dict(lora)) for lora in item['loras']] + result = { 'items': paginated_items, 'total': total_items, @@ -653,13 +732,8 @@ class RecipeScanner: # Add lora metadata if 'loras' in formatted_recipe: - for lora in formatted_recipe['loras']: - if 'hash' in lora and lora['hash']: - lora_hash = lora['hash'].lower() - lora['inLibrary'] = self._lora_scanner.has_hash(lora_hash) - lora['preview_url'] = self._lora_scanner.get_preview_url_by_hash(lora_hash) - lora['localPath'] = self._lora_scanner.get_path_by_hash(lora_hash) - + formatted_recipe['loras'] = [self._enrich_lora_entry(dict(lora)) for lora in formatted_recipe['loras']] + return formatted_recipe def _format_file_url(self, file_path: str) -> str: @@ -717,26 +791,159 @@ class RecipeScanner: # Save updated recipe with open(recipe_json_path, 'w', encoding='utf-8') as f: json.dump(recipe_data, f, indent=4, ensure_ascii=False) - + # Update the cache if it exists if self._cache is not None: - await self._cache.update_recipe_metadata(recipe_id, metadata) - + await self._cache.update_recipe_metadata(recipe_id, metadata, resort=False) + self._schedule_resort() + # If the recipe has an image, update its EXIF metadata from ..utils.exif_utils import ExifUtils image_path = recipe_data.get('file_path') if image_path and os.path.exists(image_path): ExifUtils.append_recipe_metadata(image_path, recipe_data) - + return True except Exception as e: import logging logging.getLogger(__name__).error(f"Error updating recipe metadata: {e}", exc_info=True) return False + async def update_lora_entry( + self, + recipe_id: str, + lora_index: int, + *, + target_name: str, + target_lora: Optional[Dict[str, Any]] = None, + ) -> Tuple[Dict[str, Any], Dict[str, Any]]: + """Update a specific LoRA entry within a recipe. + + Returns the updated recipe data and the refreshed LoRA metadata. + """ + + if target_name is None: + raise ValueError("target_name must be provided") + + recipe_json_path = os.path.join(self.recipes_dir, f"{recipe_id}.recipe.json") + if not os.path.exists(recipe_json_path): + raise RecipeNotFoundError("Recipe not found") + + async with self._mutation_lock: + with open(recipe_json_path, 'r', encoding='utf-8') as file_obj: + recipe_data = json.load(file_obj) + + loras = recipe_data.get('loras', []) + if lora_index >= len(loras): + raise RecipeNotFoundError("LoRA index out of range in recipe") + + lora_entry = loras[lora_index] + lora_entry['isDeleted'] = False + lora_entry['exclude'] = False + lora_entry['file_name'] = target_name + + if target_lora is not None: + sha_value = target_lora.get('sha256') or target_lora.get('sha') + if sha_value: + lora_entry['hash'] = sha_value.lower() + + civitai_info = target_lora.get('civitai') or {} + if civitai_info: + lora_entry['modelName'] = civitai_info.get('model', {}).get('name', '') + lora_entry['modelVersionName'] = civitai_info.get('name', '') + lora_entry['modelVersionId'] = civitai_info.get('id') + + recipe_data['fingerprint'] = calculate_recipe_fingerprint(recipe_data.get('loras', [])) + recipe_data['modified'] = time.time() + + with open(recipe_json_path, 'w', encoding='utf-8') as file_obj: + json.dump(recipe_data, file_obj, indent=4, ensure_ascii=False) + + cache = await self.get_cached_data() + replaced = await cache.replace_recipe(recipe_id, recipe_data, resort=False) + if not replaced: + await cache.add_recipe(recipe_data, resort=False) + self._schedule_resort() + + updated_lora = dict(lora_entry) + if target_lora is not None: + preview_url = target_lora.get('preview_url') + if preview_url: + updated_lora['preview_url'] = config.get_preview_static_url(preview_url) + if target_lora.get('file_path'): + updated_lora['localPath'] = target_lora['file_path'] + + updated_lora = self._enrich_lora_entry(updated_lora) + return recipe_data, updated_lora + + async def get_recipes_for_lora(self, lora_hash: str) -> List[Dict[str, Any]]: + """Return recipes that reference a given LoRA hash.""" + + if not lora_hash: + return [] + + normalized_hash = lora_hash.lower() + cache = await self.get_cached_data() + matching_recipes: List[Dict[str, Any]] = [] + + for recipe in cache.raw_data: + loras = recipe.get('loras', []) + if any((entry.get('hash') or '').lower() == normalized_hash for entry in loras): + recipe_copy = {**recipe} + recipe_copy['loras'] = [self._enrich_lora_entry(dict(entry)) for entry in loras] + recipe_copy['file_url'] = self._format_file_url(recipe.get('file_path')) + matching_recipes.append(recipe_copy) + + return matching_recipes + + async def get_recipe_syntax_tokens(self, recipe_id: str) -> List[str]: + """Build LoRA syntax tokens for a recipe.""" + + cache = await self.get_cached_data() + recipe = await cache.get_recipe(recipe_id) + if recipe is None: + raise RecipeNotFoundError("Recipe not found") + + loras = recipe.get('loras', []) + if not loras: + return [] + + lora_cache = None + if self._lora_scanner is not None: + lora_cache = await self._lora_scanner.get_cached_data() + + syntax_parts: List[str] = [] + for lora in loras: + if lora.get('isDeleted', False): + continue + + file_name = None + hash_value = (lora.get('hash') or '').lower() + if hash_value and self._lora_scanner is not None and hasattr(self._lora_scanner, '_hash_index'): + file_path = self._lora_scanner._hash_index.get_path(hash_value) + if file_path: + file_name = os.path.splitext(os.path.basename(file_path))[0] + + if not file_name and lora.get('modelVersionId') and lora_cache is not None: + for cached_lora in getattr(lora_cache, 'raw_data', []): + civitai_info = cached_lora.get('civitai') + if civitai_info and civitai_info.get('id') == lora.get('modelVersionId'): + cached_path = cached_lora.get('path') or cached_lora.get('file_path') + if cached_path: + file_name = os.path.splitext(os.path.basename(cached_path))[0] + break + + if not file_name: + file_name = lora.get('file_name', 'unknown-lora') + + strength = lora.get('strength', 1.0) + syntax_parts.append(f"") + + return syntax_parts + async def update_lora_filename_by_hash(self, hash_value: str, new_file_name: str) -> Tuple[int, int]: """Update file_name in all recipes that contain a LoRA with the specified hash. - + Args: hash_value: The SHA256 hash value of the LoRA new_file_name: The new file_name to set diff --git a/py/services/recipes/persistence_service.py b/py/services/recipes/persistence_service.py index 945680df..078ac906 100644 --- a/py/services/recipes/persistence_service.py +++ b/py/services/recipes/persistence_service.py @@ -1,7 +1,6 @@ """Services encapsulating recipe persistence workflows.""" from __future__ import annotations -import asyncio import base64 import json import os @@ -123,7 +122,7 @@ class RecipePersistenceService: self._exif_utils.append_recipe_metadata(image_path, recipe_data) matching_recipes = await self._find_matching_recipes(recipe_scanner, fingerprint, exclude_id=recipe_id) - await self._update_cache(recipe_scanner, recipe_data) + await recipe_scanner.add_recipe(recipe_data) return PersistenceResult( { @@ -154,7 +153,7 @@ class RecipePersistenceService: if image_path and os.path.exists(image_path): os.remove(image_path) - await self._remove_from_cache(recipe_scanner, recipe_id) + await recipe_scanner.remove_recipe(recipe_id) return PersistenceResult({"success": True, "message": "Recipe deleted successfully"}) async def update_recipe(self, *, recipe_scanner, recipe_id: str, updates: dict[str, Any]) -> PersistenceResult: @@ -185,40 +184,16 @@ class RecipePersistenceService: if not os.path.exists(recipe_path): raise RecipeNotFoundError("Recipe not found") - lora_scanner = getattr(recipe_scanner, "_lora_scanner", None) - target_lora = None if lora_scanner is None else await lora_scanner.get_model_info_by_name(target_name) + target_lora = await recipe_scanner.get_local_lora(target_name) if not target_lora: raise RecipeNotFoundError(f"Local LoRA not found with name: {target_name}") - with open(recipe_path, "r", encoding="utf-8") as file_obj: - recipe_data = json.load(file_obj) - - loras = recipe_data.get("loras", []) - if lora_index >= len(loras): - raise RecipeNotFoundError("LoRA index out of range in recipe") - - lora = loras[lora_index] - lora["isDeleted"] = False - lora["exclude"] = False - lora["file_name"] = target_name - if "sha256" in target_lora: - lora["hash"] = target_lora["sha256"].lower() - if target_lora.get("civitai"): - lora["modelName"] = target_lora["civitai"]["model"]["name"] - lora["modelVersionName"] = target_lora["civitai"]["name"] - lora["modelVersionId"] = target_lora["civitai"]["id"] - - recipe_data["fingerprint"] = calculate_recipe_fingerprint(recipe_data.get("loras", [])) - - with open(recipe_path, "w", encoding="utf-8") as file_obj: - json.dump(recipe_data, file_obj, indent=4, ensure_ascii=False) - - updated_lora = dict(lora) - updated_lora["inLibrary"] = True - updated_lora["preview_url"] = config.get_preview_static_url(target_lora["preview_url"]) - updated_lora["localPath"] = target_lora["file_path"] - - await self._refresh_cache_after_update(recipe_scanner, recipe_id, recipe_data) + recipe_data, updated_lora = await recipe_scanner.update_lora_entry( + recipe_id, + lora_index, + target_name=target_name, + target_lora=target_lora, + ) image_path = recipe_data.get("file_path") if image_path and os.path.exists(image_path): @@ -276,7 +251,7 @@ class RecipePersistenceService: failed_recipes.append({"id": recipe_id, "reason": str(exc)}) if deleted_recipes: - await self._bulk_remove_from_cache(recipe_scanner, deleted_recipes) + await recipe_scanner.bulk_remove(deleted_recipes) return PersistenceResult( { @@ -314,14 +289,11 @@ class RecipePersistenceService: if not lora_matches: raise RecipeValidationError("No LoRAs found in the generation metadata") - lora_scanner = getattr(recipe_scanner, "_lora_scanner", None) loras_data = [] base_model_counts: Dict[str, int] = {} for name, strength in lora_matches: - lora_info = None - if lora_scanner is not None: - lora_info = await lora_scanner.get_model_info_by_name(name) + lora_info = await recipe_scanner.get_local_lora(name) lora_data = { "file_name": name, "strength": float(strength), @@ -366,7 +338,7 @@ class RecipePersistenceService: json.dump(recipe_data, file_obj, indent=4, ensure_ascii=False) self._exif_utils.append_recipe_metadata(image_path, recipe_data) - await self._update_cache(recipe_scanner, recipe_data) + await recipe_scanner.add_recipe(recipe_data) return PersistenceResult( { @@ -422,45 +394,6 @@ class RecipePersistenceService: matches.remove(exclude_id) return matches - async def _update_cache(self, recipe_scanner, recipe_data: dict[str, Any]) -> None: - cache = getattr(recipe_scanner, "_cache", None) - if cache is not None: - cache.raw_data.append(recipe_data) - asyncio.create_task(cache.resort()) - self._logger.info("Added recipe %s to cache", recipe_data.get("id")) - - async def _remove_from_cache(self, recipe_scanner, recipe_id: str) -> None: - cache = getattr(recipe_scanner, "_cache", None) - if cache is not None: - cache.raw_data = [item for item in cache.raw_data if str(item.get("id", "")) != recipe_id] - asyncio.create_task(cache.resort()) - self._logger.info("Removed recipe %s from cache", recipe_id) - - async def _bulk_remove_from_cache(self, recipe_scanner, recipe_ids: Iterable[str]) -> None: - cache = getattr(recipe_scanner, "_cache", None) - if cache is not None: - recipe_ids_set = set(recipe_ids) - cache.raw_data = [item for item in cache.raw_data if item.get("id") not in recipe_ids_set] - asyncio.create_task(cache.resort()) - self._logger.info("Removed %s recipes from cache", len(recipe_ids_set)) - - async def _refresh_cache_after_update( - self, - recipe_scanner, - recipe_id: str, - recipe_data: dict[str, Any], - ) -> None: - cache = getattr(recipe_scanner, "_cache", None) - if cache is not None: - for cache_item in cache.raw_data: - if cache_item.get("id") == recipe_id: - cache_item.update({ - "loras": recipe_data.get("loras", []), - "fingerprint": recipe_data.get("fingerprint"), - }) - asyncio.create_task(cache.resort()) - break - def _derive_recipe_name(self, lora_matches: list[tuple[str, str]]) -> str: recipe_name_parts = [f"{name.strip()}-{float(strength):.2f}" for name, strength in lora_matches[:3]] recipe_name = "_".join(recipe_name_parts) diff --git a/py/services/recipes/sharing_service.py b/py/services/recipes/sharing_service.py index 7c365bba..47ab9718 100644 --- a/py/services/recipes/sharing_service.py +++ b/py/services/recipes/sharing_service.py @@ -38,11 +38,7 @@ class RecipeSharingService: async def share_recipe(self, *, recipe_scanner, recipe_id: str) -> SharingResult: """Prepare a temporary downloadable copy of a recipe image.""" - cache = await recipe_scanner.get_cached_data() - recipe = next( - (r for r in getattr(cache, "raw_data", []) if str(r.get("id", "")) == recipe_id), - None, - ) + recipe = await recipe_scanner.get_recipe_by_id(recipe_id) if not recipe: raise RecipeNotFoundError("Recipe not found") @@ -81,11 +77,7 @@ class RecipeSharingService: self._cleanup_entry(recipe_id) raise RecipeNotFoundError("Shared recipe file not found") - cache = await recipe_scanner.get_cached_data() - recipe = next( - (r for r in getattr(cache, "raw_data", []) if str(r.get("id", "")) == recipe_id), - None, - ) + recipe = await recipe_scanner.get_recipe_by_id(recipe_id) filename_base = ( f"recipe_{recipe.get('title', '').replace(' ', '_').lower()}" if recipe else recipe_id ) diff --git a/tests/services/test_recipe_scanner.py b/tests/services/test_recipe_scanner.py new file mode 100644 index 00000000..63c18f25 --- /dev/null +++ b/tests/services/test_recipe_scanner.py @@ -0,0 +1,185 @@ +import asyncio +import json +from pathlib import Path +from types import SimpleNamespace + +import pytest + +from py.config import config +from py.services.recipe_scanner import RecipeScanner +from py.utils.utils import calculate_recipe_fingerprint + + +class StubHashIndex: + def __init__(self) -> None: + self._hash_to_path: dict[str, str] = {} + + def get_path(self, hash_value: str) -> str | None: + return self._hash_to_path.get(hash_value) + + +class StubLoraScanner: + def __init__(self) -> None: + self._hash_index = StubHashIndex() + self._hash_meta: dict[str, dict[str, str]] = {} + self._models_by_name: dict[str, dict] = {} + self._cache = SimpleNamespace(raw_data=[]) + + async def get_cached_data(self): + return self._cache + + def has_hash(self, hash_value: str) -> bool: + return hash_value.lower() in self._hash_meta + + def get_preview_url_by_hash(self, hash_value: str) -> str: + meta = self._hash_meta.get(hash_value.lower()) + return meta.get("preview_url", "") if meta else "" + + def get_path_by_hash(self, hash_value: str) -> str | None: + meta = self._hash_meta.get(hash_value.lower()) + return meta.get("path") if meta else None + + async def get_model_info_by_name(self, name: str): + return self._models_by_name.get(name) + + def register_model(self, name: str, info: dict) -> None: + self._models_by_name[name] = info + hash_value = (info.get("sha256") or "").lower() + if hash_value: + self._hash_meta[hash_value] = { + "path": info.get("file_path", ""), + "preview_url": info.get("preview_url", ""), + } + self._hash_index._hash_to_path[hash_value] = info.get("file_path", "") + self._cache.raw_data.append({ + "sha256": info.get("sha256", ""), + "path": info.get("file_path", ""), + "civitai": info.get("civitai", {}), + }) + + +@pytest.fixture +def recipe_scanner(tmp_path: Path, monkeypatch): + RecipeScanner._instance = None + monkeypatch.setattr(config, "loras_roots", [str(tmp_path)]) + stub = StubLoraScanner() + scanner = RecipeScanner(lora_scanner=stub) + asyncio.run(scanner.refresh_cache(force=True)) + yield scanner, stub + RecipeScanner._instance = None + + +async def test_add_recipe_during_concurrent_reads(recipe_scanner): + scanner, _ = recipe_scanner + + initial_recipe = { + "id": "one", + "file_path": "path/a.png", + "title": "First", + "modified": 1.0, + "created_date": 1.0, + "loras": [], + } + await scanner.add_recipe(initial_recipe) + + new_recipe = { + "id": "two", + "file_path": "path/b.png", + "title": "Second", + "modified": 2.0, + "created_date": 2.0, + "loras": [], + } + + async def reader_task(): + for _ in range(5): + cache = await scanner.get_cached_data() + _ = [item["id"] for item in cache.raw_data] + await asyncio.sleep(0) + + await asyncio.gather(reader_task(), reader_task(), scanner.add_recipe(new_recipe)) + await asyncio.sleep(0) + cache = await scanner.get_cached_data() + + assert {item["id"] for item in cache.raw_data} == {"one", "two"} + assert len(cache.sorted_by_name) == len(cache.raw_data) + + +async def test_remove_recipe_during_reads(recipe_scanner): + scanner, _ = recipe_scanner + + recipe_ids = ["alpha", "beta", "gamma"] + for index, recipe_id in enumerate(recipe_ids): + await scanner.add_recipe({ + "id": recipe_id, + "file_path": f"path/{recipe_id}.png", + "title": recipe_id, + "modified": float(index), + "created_date": float(index), + "loras": [], + }) + + async def reader_task(): + for _ in range(5): + cache = await scanner.get_cached_data() + _ = list(cache.sorted_by_date) + await asyncio.sleep(0) + + await asyncio.gather(reader_task(), scanner.remove_recipe("beta")) + await asyncio.sleep(0) + cache = await scanner.get_cached_data() + + assert {item["id"] for item in cache.raw_data} == {"alpha", "gamma"} + + +async def test_update_lora_entry_updates_cache_and_file(tmp_path: Path, recipe_scanner): + scanner, stub = recipe_scanner + recipes_dir = Path(config.loras_roots[0]) / "recipes" + recipes_dir.mkdir(parents=True, exist_ok=True) + + recipe_id = "recipe-1" + recipe_path = recipes_dir / f"{recipe_id}.recipe.json" + recipe_data = { + "id": recipe_id, + "file_path": str(tmp_path / "image.png"), + "title": "Original", + "modified": 0.0, + "created_date": 0.0, + "loras": [ + {"file_name": "old", "strength": 1.0, "hash": "", "isDeleted": True, "exclude": True}, + ], + } + recipe_path.write_text(json.dumps(recipe_data)) + + await scanner.add_recipe(dict(recipe_data)) + + target_hash = "abc123" + target_info = { + "sha256": target_hash, + "file_path": str(tmp_path / "loras" / "target.safetensors"), + "preview_url": "preview.png", + "civitai": {"id": 42, "name": "v1", "model": {"name": "Target"}}, + } + stub.register_model("target", target_info) + + updated_recipe, updated_lora = await scanner.update_lora_entry( + recipe_id, + 0, + target_name="target", + target_lora=target_info, + ) + + assert updated_lora["inLibrary"] is True + assert updated_lora["localPath"] == target_info["file_path"] + assert updated_lora["hash"] == target_hash + + with recipe_path.open("r", encoding="utf-8") as file_obj: + persisted = json.load(file_obj) + + expected_fingerprint = calculate_recipe_fingerprint(persisted["loras"]) + assert persisted["fingerprint"] == expected_fingerprint + + cache = await scanner.get_cached_data() + cached_recipe = next(item for item in cache.raw_data if item["id"] == recipe_id) + assert cached_recipe["loras"][0]["hash"] == target_hash + assert cached_recipe["fingerprint"] == expected_fingerprint diff --git a/tests/services/test_recipe_services.py b/tests/services/test_recipe_services.py index e57abf2f..81a15424 100644 --- a/tests/services/test_recipe_services.py +++ b/tests/services/test_recipe_services.py @@ -108,6 +108,10 @@ async def test_save_recipe_reports_duplicates(tmp_path): self.last_fingerprint = fingerprint return ["existing"] + async def add_recipe(self, recipe_data): + self._cache.raw_data.append(recipe_data) + await self._cache.resort() + scanner = DummyScanner(tmp_path) service = RecipePersistenceService( exif_utils=exif_utils, From f7cffd2eba724d3b419f01db62fa5c28efe8c642 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Mon, 22 Sep 2025 14:15:24 +0800 Subject: [PATCH 067/110] test(recipes): add route smoke tests and docs --- README.md | 26 +++ docs/architecture/recipe_routes.md | 103 ++++++--- tests/routes/test_recipe_routes.py | 330 +++++++++++++++++++++++++++++ 3 files changed, 427 insertions(+), 32 deletions(-) create mode 100644 tests/routes/test_recipe_routes.py diff --git a/README.md b/README.md index 7e932acc..f9c1806b 100644 --- a/README.md +++ b/README.md @@ -233,6 +233,32 @@ You can now run LoRA Manager independently from ComfyUI: This standalone mode provides a lightweight option for managing your model and recipe collection without needing to run the full ComfyUI environment, making it useful even for users who primarily use other stable diffusion interfaces. +## Developer notes + +The REST layer is split into modular registrars, controllers, and handler sets +to simplify maintenance: + +* `py/routes/recipe_route_registrar.py` holds the declarative endpoint list. +* `py/routes/base_recipe_routes.py` wires shared services/templates and returns + the handler mapping consumed by `RecipeRouteRegistrar`. +* `py/routes/handlers/recipe_handlers.py` groups HTTP adapters by concern (page + rendering, listings, queries, mutations, sharing) and delegates business rules + to services in `py/services/recipes/`. + +To add a new recipe endpoint: + +1. Declare the route in `ROUTE_DEFINITIONS` with a unique handler name. +2. Implement the coroutine on the appropriate handler class or introduce a new + handler when the concern does not fit existing ones. +3. Inject additional collaborators in + `BaseRecipeRoutes._create_handler_set` (for example a new service or factory) + so the handler can access its dependencies. + +The end-to-end wiring is documented in +[`docs/architecture/recipe_routes.md`](docs/architecture/recipe_routes.md), and +the integration suite in `tests/routes/test_recipe_routes.py` smoke-tests the +primary endpoints. + --- ## Contributing diff --git a/docs/architecture/recipe_routes.md b/docs/architecture/recipe_routes.md index 28684fad..0bdb7c90 100644 --- a/docs/architecture/recipe_routes.md +++ b/docs/architecture/recipe_routes.md @@ -1,50 +1,89 @@ -# Recipe route scaffolding +# Recipe route architecture -The recipe HTTP stack is being migrated to mirror the shared model routing -architecture. The first phase extracts the registrar/controller scaffolding so -future handler sets can plug into a stable surface area. The stack now mirrors -the same separation of concerns described in -`docs/architecture/model_routes.md`: +The recipe routing stack now mirrors the modular model route design. HTTP +bindings, controller wiring, handler orchestration, and business rules live in +separate layers so new behaviours can be added without re-threading the entire +feature. The diagram below outlines the flow for a typical request: ```mermaid graph TD subgraph HTTP - A[RecipeRouteRegistrar] -->|binds| B[BaseRecipeRoutes handler owner] + A[RecipeRouteRegistrar] -->|binds| B[RecipeRoutes controller] end subgraph Application - B --> C[Recipe handler set] - C --> D[Async handlers] - D --> E[Services / scanners] + B --> C[RecipeHandlerSet] + C --> D1[Handlers] + D1 --> E1[Use cases] + E1 --> F1[Services / scanners] + end + subgraph Side Effects + F1 --> G1[Cache & fingerprint index] + F1 --> G2[Metadata files] + F1 --> G3[Temporary shares] end ``` -## Responsibilities +## Layer responsibilities | Layer | Module(s) | Responsibility | | --- | --- | --- | -| Registrar | `py/routes/recipe_route_registrar.py` | Declarative list of every recipe endpoint and helper that binds them to an `aiohttp` application. | -| Base controller | `py/routes/base_recipe_routes.py` | Lazily resolves shared services, registers the server-side i18n filter exactly once, pre-warms caches on startup, and exposes a `{handler_name: coroutine}` mapping used by the registrar. | -| Handler set (upcoming) | `py/routes/handlers/recipe_handlers.py` (planned) | Will group HTTP handlers by concern (page rendering, listings, mutations, queries, sharing) and surface them to `BaseRecipeRoutes.get_handler_owner()`. | +| Registrar | `py/routes/recipe_route_registrar.py` | Declarative list of every recipe endpoint and helper methods that bind them to an `aiohttp` application. | +| Controller | `py/routes/base_recipe_routes.py`, `py/routes/recipe_routes.py` | Lazily resolves scanners/clients from the service registry, wires shared templates/i18n, instantiates `RecipeHandlerSet`, and exposes a `{handler_name: coroutine}` mapping for the registrar. | +| Handler set | `py/routes/handlers/recipe_handlers.py` | Thin HTTP adapters grouped by concern (page view, listings, queries, mutations, sharing). They normalise responses and translate service exceptions into HTTP status codes. | +| Services & scanners | `py/services/recipes/*.py`, `py/services/recipe_scanner.py`, `py/services/service_registry.py` | Concrete business logic: metadata parsing, persistence, sharing, fingerprint/index maintenance, and cache refresh. | -`RecipeRoutes` subclasses the base controller to keep compatibility with the -existing monolithic handlers. Once the handler set is extracted the subclass -will simply provide the concrete owner returned by `get_handler_owner()`. +## Handler responsibilities & invariants -## High-level test baseline +`RecipeHandlerSet` flattens purpose-built handler objects into the callables the +registrar binds. Each handler is responsible for a narrow concern and enforces a +set of invariants before returning: -The new smoke suite in `tests/routes/test_recipe_route_scaffolding.py` -guarantees the registrar/controller contract remains intact: +| Handler | Key endpoints | Collaborators | Contracts | +| --- | --- | --- | --- | +| `RecipePageView` | `/loras/recipes` | `SettingsManager`, `server_i18n`, Jinja environment, recipe scanner getter | Template rendered with `is_initializing` flag when caches are still warming; i18n filter registered exactly once per environment instance. | +| `RecipeListingHandler` | `/api/lm/recipes`, `/api/lm/recipe/{id}` | `recipe_scanner.get_paginated_data`, `recipe_scanner.get_recipe_by_id` | Listings respect pagination and search filters; every item receives a `file_url` fallback even when metadata is incomplete; missing recipes become HTTP 404. | +| `RecipeQueryHandler` | Tag/base-model stats, syntax, LoRA lookups | Recipe scanner cache, `format_recipe_file_url` helper | Cache snapshots are reused without forcing refresh; duplicate lookups collapse groups by fingerprint; syntax lookups return helpful errors when LoRAs are absent. | +| `RecipeManagementHandler` | Save, update, reconnect, bulk delete, widget ingest | `RecipePersistenceService`, `RecipeAnalysisService`, recipe scanner | Persistence results propagate HTTP status codes; fingerprint/index updates flow through the scanner before returning; validation errors surface as HTTP 400 without touching disk. | +| `RecipeAnalysisHandler` | Uploaded/local/remote analysis | `RecipeAnalysisService`, `civitai_client`, recipe scanner | Unsupported content types map to HTTP 400; download errors (`RecipeDownloadError`) are not retried; every response includes a `loras` array for client compatibility. | +| `RecipeSharingHandler` | Share + download | `RecipeSharingService`, recipe scanner | Share responses provide a stable download URL and filename; expired shares surface as HTTP 404; downloads stream via `web.FileResponse` with attachment headers. | -* `BaseRecipeRoutes.attach_dependencies` resolves registry services only once - and protects the i18n filter from duplicate registration. -* Startup hooks are appended exactly once so cache pre-warming and dependency - resolution run during application boot. -* `BaseRecipeRoutes.to_route_mapping()` uses the handler owner as the source of - callables, enabling the upcoming handler set without touching the registrar. -* `RecipeRouteRegistrar` binds every declarative route to the aiohttp router. -* `RecipeRoutes.setup_routes` wires the registrar and startup hooks together so - future refactors can swap in the handler set without editing callers. +## Use case boundaries + +The dedicated services encapsulate long-running work so handlers stay thin. + +| Use case | Entry point | Dependencies | Guarantees | +| --- | --- | --- | --- | +| `RecipeAnalysisService` | `analyze_uploaded_image`, `analyze_remote_image`, `analyze_local_image`, `analyze_widget_metadata` | `ExifUtils`, `RecipeParserFactory`, downloader factory, optional metadata collector/processor | Normalises missing/invalid payloads into `RecipeValidationError`; generates consistent fingerprint data to keep duplicate detection stable; temporary files are cleaned up after every analysis path. | +| `RecipePersistenceService` | `save_recipe`, `delete_recipe`, `update_recipe`, `reconnect_lora`, `bulk_delete`, `save_recipe_from_widget` | `ExifUtils`, recipe scanner, card preview sizing constants | Writes images/JSON metadata atomically; updates scanner caches and hash indices before returning; recalculates fingerprints whenever LoRA assignments change. | +| `RecipeSharingService` | `share_recipe`, `prepare_download` | `tempfile`, recipe scanner | Copies originals to TTL-managed temp files; metadata lookups re-use the scanner; expired shares trigger cleanup and `RecipeNotFoundError`. | + +## Maintaining critical invariants + +* **Cache updates** – Mutations (`save`, `delete`, `bulk_delete`, `update`) call + back into the recipe scanner to mutate the in-memory cache and fingerprint + index before returning a response. Tests assert that these methods are invoked + even when stubbing persistence. +* **Fingerprint management** – `RecipePersistenceService` recomputes + fingerprints whenever LoRA metadata changes and duplicate lookups use those + fingerprints to group recipes. Handlers bubble the resulting IDs so clients + can merge duplicates without an extra fetch. +* **Metadata synchronisation** – Saving or reconnecting a recipe updates the + JSON sidecar, refreshes embedded metadata via `ExifUtils`, and instructs the + scanner to resort its cache. Sharing relies on this metadata to generate + filenames and ensure downloads stay in sync with on-disk state. + +## Extending the stack + +1. Declare the new endpoint in `ROUTE_DEFINITIONS` with a unique handler name. +2. Implement the coroutine on an existing handler or introduce a new handler + class inside `py/routes/handlers/recipe_handlers.py` when the concern does + not fit existing ones. +3. Wire additional collaborators inside + `BaseRecipeRoutes._create_handler_set` (inject new services or factories) and + expose helper getters on the handler owner if the handler needs to share + utilities. + +Integration tests in `tests/routes/test_recipe_routes.py` exercise the listing, +mutation, analysis-error, and sharing paths end-to-end, ensuring the controller +and handler wiring remains valid as new capabilities are added. -These guardrails mirror the expectations in the model route architecture and -provide confidence that future refactors can focus on handlers and use cases -without breaking HTTP wiring. diff --git a/tests/routes/test_recipe_routes.py b/tests/routes/test_recipe_routes.py new file mode 100644 index 00000000..467cb5b5 --- /dev/null +++ b/tests/routes/test_recipe_routes.py @@ -0,0 +1,330 @@ +"""Integration smoke tests for the recipe route stack.""" +from __future__ import annotations + +import json +from contextlib import asynccontextmanager +from dataclasses import dataclass +from pathlib import Path +from types import SimpleNamespace +from typing import Any, AsyncIterator, Dict, List, Optional + +from aiohttp import FormData, web +from aiohttp.test_utils import TestClient, TestServer + +from py.config import config +from py.routes import base_recipe_routes +from py.routes.recipe_routes import RecipeRoutes +from py.services.recipes import RecipeValidationError +from py.services.service_registry import ServiceRegistry + + +@dataclass +class RecipeRouteHarness: + """Container exposing the aiohttp client and stubbed collaborators.""" + + client: TestClient + scanner: "StubRecipeScanner" + analysis: "StubAnalysisService" + persistence: "StubPersistenceService" + sharing: "StubSharingService" + tmp_dir: Path + + +class StubRecipeScanner: + """Minimal scanner double with the surface used by the handlers.""" + + def __init__(self, base_dir: Path) -> None: + self.recipes_dir = str(base_dir / "recipes") + self.listing_items: List[Dict[str, Any]] = [] + self.cached_raw: List[Dict[str, Any]] = [] + self.recipes: Dict[str, Dict[str, Any]] = {} + self.removed: List[str] = [] + + async def _noop_get_cached_data(force_refresh: bool = False) -> None: # noqa: ARG001 - signature mirrors real scanner + return None + + self._lora_scanner = SimpleNamespace( # mimic BaseRecipeRoutes expectations + get_cached_data=_noop_get_cached_data, + _hash_index=SimpleNamespace(_hash_to_path={}), + ) + + async def get_cached_data(self, force_refresh: bool = False) -> SimpleNamespace: # noqa: ARG002 - flag unused by stub + return SimpleNamespace(raw_data=list(self.cached_raw)) + + async def get_paginated_data(self, **params: Any) -> Dict[str, Any]: + items = [dict(item) for item in self.listing_items] + page = int(params.get("page", 1)) + page_size = int(params.get("page_size", 20)) + return { + "items": items, + "total": len(items), + "page": page, + "page_size": page_size, + "total_pages": max(1, (len(items) + page_size - 1) // max(page_size, 1)), + } + + async def get_recipe_by_id(self, recipe_id: str) -> Optional[Dict[str, Any]]: + return self.recipes.get(recipe_id) + + async def remove_recipe(self, recipe_id: str) -> None: + self.removed.append(recipe_id) + self.recipes.pop(recipe_id, None) + + +class StubAnalysisService: + """Captures calls made by analysis routes while returning canned responses.""" + + instances: List["StubAnalysisService"] = [] + + def __init__(self, **_: Any) -> None: + self.raise_for_uploaded: Optional[Exception] = None + self.raise_for_remote: Optional[Exception] = None + self.raise_for_local: Optional[Exception] = None + self.upload_calls: List[bytes] = [] + self.remote_calls: List[Optional[str]] = [] + self.local_calls: List[Optional[str]] = [] + self.result = SimpleNamespace(payload={"loras": []}, status=200) + StubAnalysisService.instances.append(self) + + async def analyze_uploaded_image(self, *, image_bytes: bytes | None, recipe_scanner) -> SimpleNamespace: # noqa: D401 - mirrors real signature + if self.raise_for_uploaded: + raise self.raise_for_uploaded + self.upload_calls.append(image_bytes or b"") + return self.result + + async def analyze_remote_image(self, *, url: Optional[str], recipe_scanner, civitai_client) -> SimpleNamespace: # noqa: D401 + if self.raise_for_remote: + raise self.raise_for_remote + self.remote_calls.append(url) + return self.result + + async def analyze_local_image(self, *, file_path: Optional[str], recipe_scanner) -> SimpleNamespace: # noqa: D401 + if self.raise_for_local: + raise self.raise_for_local + self.local_calls.append(file_path) + return self.result + + async def analyze_widget_metadata(self, *, recipe_scanner) -> SimpleNamespace: + return SimpleNamespace(payload={"metadata": {}, "image_bytes": b""}, status=200) + + +class StubPersistenceService: + """Stub for persistence operations to avoid filesystem writes.""" + + instances: List["StubPersistenceService"] = [] + + def __init__(self, **_: Any) -> None: + self.save_calls: List[Dict[str, Any]] = [] + self.delete_calls: List[str] = [] + self.save_result = SimpleNamespace(payload={"success": True, "recipe_id": "stub-id"}, status=200) + self.delete_result = SimpleNamespace(payload={"success": True}, status=200) + StubPersistenceService.instances.append(self) + + async def save_recipe(self, *, recipe_scanner, image_bytes, image_base64, name, tags, metadata) -> SimpleNamespace: # noqa: D401 + self.save_calls.append( + { + "recipe_scanner": recipe_scanner, + "image_bytes": image_bytes, + "image_base64": image_base64, + "name": name, + "tags": list(tags), + "metadata": metadata, + } + ) + return self.save_result + + async def delete_recipe(self, *, recipe_scanner, recipe_id: str) -> SimpleNamespace: + self.delete_calls.append(recipe_id) + await recipe_scanner.remove_recipe(recipe_id) + return self.delete_result + + async def update_recipe(self, *, recipe_scanner, recipe_id: str, updates: Dict[str, Any]) -> SimpleNamespace: # pragma: no cover - unused by smoke tests + return SimpleNamespace(payload={"success": True, "recipe_id": recipe_id, "updates": updates}, status=200) + + async def reconnect_lora(self, *, recipe_scanner, recipe_id: str, lora_index: int, target_name: str) -> SimpleNamespace: # pragma: no cover + return SimpleNamespace(payload={"success": True}, status=200) + + async def bulk_delete(self, *, recipe_scanner, recipe_ids: List[str]) -> SimpleNamespace: # pragma: no cover + return SimpleNamespace(payload={"success": True, "deleted": recipe_ids}, status=200) + + async def save_recipe_from_widget(self, *, recipe_scanner, metadata: Dict[str, Any], image_bytes: bytes) -> SimpleNamespace: # pragma: no cover + return SimpleNamespace(payload={"success": True}, status=200) + + +class StubSharingService: + """Share service stub recording requests and returning canned responses.""" + + instances: List["StubSharingService"] = [] + + def __init__(self, *, ttl_seconds: int = 300, logger) -> None: # noqa: ARG002 - ttl unused in stub + self.share_calls: List[str] = [] + self.download_calls: List[str] = [] + self.share_result = SimpleNamespace( + payload={"success": True, "download_url": "/share/stub", "filename": "recipe.png"}, + status=200, + ) + self.download_info = SimpleNamespace(file_path="", download_filename="") + StubSharingService.instances.append(self) + + async def share_recipe(self, *, recipe_scanner, recipe_id: str) -> SimpleNamespace: + self.share_calls.append(recipe_id) + return self.share_result + + async def prepare_download(self, *, recipe_scanner, recipe_id: str) -> SimpleNamespace: + self.download_calls.append(recipe_id) + return self.download_info + + +@asynccontextmanager +async def recipe_harness(monkeypatch, tmp_path: Path) -> AsyncIterator[RecipeRouteHarness]: + """Context manager that yields a fully wired recipe route harness.""" + + StubAnalysisService.instances.clear() + StubPersistenceService.instances.clear() + StubSharingService.instances.clear() + + scanner = StubRecipeScanner(tmp_path) + + async def fake_get_recipe_scanner(): + return scanner + + async def fake_get_civitai_client(): + return object() + + monkeypatch.setattr(ServiceRegistry, "get_recipe_scanner", fake_get_recipe_scanner) + monkeypatch.setattr(ServiceRegistry, "get_civitai_client", fake_get_civitai_client) + monkeypatch.setattr(base_recipe_routes, "RecipeAnalysisService", StubAnalysisService) + monkeypatch.setattr(base_recipe_routes, "RecipePersistenceService", StubPersistenceService) + monkeypatch.setattr(base_recipe_routes, "RecipeSharingService", StubSharingService) + monkeypatch.setattr(config, "loras_roots", [str(tmp_path)], raising=False) + + app = web.Application() + RecipeRoutes.setup_routes(app) + + server = TestServer(app) + client = TestClient(server) + await client.start_server() + + harness = RecipeRouteHarness( + client=client, + scanner=scanner, + analysis=StubAnalysisService.instances[-1], + persistence=StubPersistenceService.instances[-1], + sharing=StubSharingService.instances[-1], + tmp_dir=tmp_path, + ) + + try: + yield harness + finally: + await client.close() + StubAnalysisService.instances.clear() + StubPersistenceService.instances.clear() + StubSharingService.instances.clear() + + +async def test_list_recipes_provides_file_urls(monkeypatch, tmp_path: Path) -> None: + async with recipe_harness(monkeypatch, tmp_path) as harness: + recipe_path = harness.tmp_dir / "recipes" / "demo.png" + harness.scanner.listing_items = [ + { + "id": "recipe-1", + "file_path": str(recipe_path), + "title": "Demo", + "loras": [], + } + ] + harness.scanner.cached_raw = list(harness.scanner.listing_items) + + response = await harness.client.get("/api/lm/recipes") + payload = await response.json() + + assert response.status == 200 + assert payload["items"][0]["file_url"].endswith("demo.png") + assert payload["items"][0]["loras"] == [] + + +async def test_save_and_delete_recipe_round_trip(monkeypatch, tmp_path: Path) -> None: + async with recipe_harness(monkeypatch, tmp_path) as harness: + form = FormData() + form.add_field("image", b"stub", filename="sample.png", content_type="image/png") + form.add_field("name", "Test Recipe") + form.add_field("tags", json.dumps(["tag-a"])) + form.add_field("metadata", json.dumps({"loras": []})) + form.add_field("image_base64", "aW1hZ2U=") + + harness.persistence.save_result = SimpleNamespace( + payload={"success": True, "recipe_id": "saved-id"}, + status=201, + ) + + save_response = await harness.client.post("/api/lm/recipes/save", data=form) + save_payload = await save_response.json() + + assert save_response.status == 201 + assert save_payload["recipe_id"] == "saved-id" + assert harness.persistence.save_calls[-1]["name"] == "Test Recipe" + + harness.persistence.delete_result = SimpleNamespace(payload={"success": True}, status=200) + + delete_response = await harness.client.delete("/api/lm/recipe/saved-id") + delete_payload = await delete_response.json() + + assert delete_response.status == 200 + assert delete_payload["success"] is True + assert harness.persistence.delete_calls == ["saved-id"] + + +async def test_analyze_uploaded_image_error_path(monkeypatch, tmp_path: Path) -> None: + async with recipe_harness(monkeypatch, tmp_path) as harness: + harness.analysis.raise_for_uploaded = RecipeValidationError("No image data provided") + + form = FormData() + form.add_field("image", b"", filename="empty.png", content_type="image/png") + + response = await harness.client.post("/api/lm/recipes/analyze-image", data=form) + payload = await response.json() + + assert response.status == 400 + assert payload["error"] == "No image data provided" + assert payload["loras"] == [] + + +async def test_share_and_download_recipe(monkeypatch, tmp_path: Path) -> None: + async with recipe_harness(monkeypatch, tmp_path) as harness: + recipe_id = "share-me" + download_path = harness.tmp_dir / "recipes" / "share.png" + download_path.parent.mkdir(parents=True, exist_ok=True) + download_path.write_bytes(b"stub") + + harness.scanner.recipes[recipe_id] = { + "id": recipe_id, + "title": "Shared", + "file_path": str(download_path), + } + + harness.sharing.share_result = SimpleNamespace( + payload={"success": True, "download_url": "/api/share", "filename": "share.png"}, + status=200, + ) + harness.sharing.download_info = SimpleNamespace( + file_path=str(download_path), + download_filename="share.png", + ) + + share_response = await harness.client.get(f"/api/lm/recipe/{recipe_id}/share") + share_payload = await share_response.json() + + assert share_response.status == 200 + assert share_payload["filename"] == "share.png" + assert harness.sharing.share_calls == [recipe_id] + + download_response = await harness.client.get(f"/api/lm/recipe/{recipe_id}/share/download") + body = await download_response.read() + + assert download_response.status == 200 + assert download_response.headers["Content-Disposition"] == 'attachment; filename="share.png"' + assert body == b"stub" + + download_path.unlink(missing_ok=True) + From e0aba6c49abe973acbf2ead5a5d5a5a8beaeb804 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Tue, 23 Sep 2025 10:41:56 +0800 Subject: [PATCH 068/110] test(example-images): add route regression harness --- tests/routes/test_example_images_routes.py | 220 +++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 tests/routes/test_example_images_routes.py diff --git a/tests/routes/test_example_images_routes.py b/tests/routes/test_example_images_routes.py new file mode 100644 index 00000000..d64e1d7f --- /dev/null +++ b/tests/routes/test_example_images_routes.py @@ -0,0 +1,220 @@ +from contextlib import asynccontextmanager +from dataclasses import dataclass +from typing import Any, List, Tuple + +from aiohttp import web +from aiohttp.test_utils import TestClient, TestServer +import pytest + +from py.routes import example_images_routes +from py.routes.example_images_routes import ExampleImagesRoutes + + +@dataclass +class ExampleImagesHarness: + """Container exposing the aiohttp client and stubbed collaborators.""" + + client: TestClient + download_manager: Any + processor: Any + file_manager: Any + + +@asynccontextmanager +async def example_images_app(monkeypatch: pytest.MonkeyPatch) -> ExampleImagesHarness: + """Yield an ExampleImagesRoutes app wired with stubbed collaborators.""" + + class StubDownloadManager: + calls: List[Tuple[str, Any]] = [] + + @staticmethod + async def start_download(request): + payload = await request.json() + StubDownloadManager.calls.append(("start_download", payload)) + return web.json_response({"operation": "start_download", "payload": payload}) + + @staticmethod + async def get_status(request): + StubDownloadManager.calls.append(("get_status", dict(request.query))) + return web.json_response({"operation": "get_status"}) + + @staticmethod + async def pause_download(request): + StubDownloadManager.calls.append(("pause_download", None)) + return web.json_response({"operation": "pause_download"}) + + @staticmethod + async def resume_download(request): + StubDownloadManager.calls.append(("resume_download", None)) + return web.json_response({"operation": "resume_download"}) + + @staticmethod + async def start_force_download(request): + payload = await request.json() + StubDownloadManager.calls.append(("start_force_download", payload)) + return web.json_response({"operation": "start_force_download", "payload": payload}) + + class StubExampleImagesProcessor: + calls: List[Tuple[str, Any]] = [] + + @staticmethod + async def import_images(request): + payload = await request.json() + StubExampleImagesProcessor.calls.append(("import_images", payload)) + return web.json_response({"operation": "import_images", "payload": payload}) + + @staticmethod + async def delete_custom_image(request): + payload = await request.json() + StubExampleImagesProcessor.calls.append(("delete_custom_image", payload)) + return web.json_response({"operation": "delete_custom_image", "payload": payload}) + + class StubExampleImagesFileManager: + calls: List[Tuple[str, Any]] = [] + + @staticmethod + async def open_folder(request): + payload = await request.json() + StubExampleImagesFileManager.calls.append(("open_folder", payload)) + return web.json_response({"operation": "open_folder", "payload": payload}) + + @staticmethod + async def get_files(request): + StubExampleImagesFileManager.calls.append(("get_files", dict(request.query))) + return web.json_response({"operation": "get_files", "query": dict(request.query)}) + + @staticmethod + async def has_images(request): + StubExampleImagesFileManager.calls.append(("has_images", dict(request.query))) + return web.json_response({"operation": "has_images", "query": dict(request.query)}) + + monkeypatch.setattr(example_images_routes, "DownloadManager", StubDownloadManager) + monkeypatch.setattr(example_images_routes, "ExampleImagesProcessor", StubExampleImagesProcessor) + monkeypatch.setattr(example_images_routes, "ExampleImagesFileManager", StubExampleImagesFileManager) + + app = web.Application() + ExampleImagesRoutes.setup_routes(app) + + server = TestServer(app) + client = TestClient(server) + await client.start_server() + + try: + yield ExampleImagesHarness( + client=client, + download_manager=StubDownloadManager, + processor=StubExampleImagesProcessor, + file_manager=StubExampleImagesFileManager, + ) + finally: + await client.close() + + +@pytest.mark.parametrize( + "endpoint, payload", + [ + ("/api/lm/download-example-images", {"model_types": ["lora"], "optimize": False}), + ("/api/lm/force-download-example-images", {"model_hashes": ["abc123"]}), + ], +) +async def test_download_routes_delegate_to_manager(endpoint, payload, monkeypatch: pytest.MonkeyPatch): + async with example_images_app(monkeypatch) as harness: + response = await harness.client.post(endpoint, json=payload) + body = await response.json() + + assert response.status == 200 + assert body["payload"] == payload + assert body["operation"].startswith("start") + + expected_call = body["operation"], payload + assert expected_call in harness.download_manager.calls + + +async def test_status_route_returns_manager_payload(monkeypatch: pytest.MonkeyPatch): + async with example_images_app(monkeypatch) as harness: + response = await harness.client.get( + "/api/lm/example-images-status", params={"detail": "true"} + ) + body = await response.json() + + assert response.status == 200 + assert body == {"operation": "get_status"} + assert harness.download_manager.calls == [("get_status", {"detail": "true"})] + + +async def test_pause_and_resume_routes_delegate(monkeypatch: pytest.MonkeyPatch): + async with example_images_app(monkeypatch) as harness: + pause_response = await harness.client.post("/api/lm/pause-example-images") + resume_response = await harness.client.post("/api/lm/resume-example-images") + + assert pause_response.status == 200 + assert await pause_response.json() == {"operation": "pause_download"} + assert resume_response.status == 200 + assert await resume_response.json() == {"operation": "resume_download"} + + assert harness.download_manager.calls[-2:] == [ + ("pause_download", None), + ("resume_download", None), + ] + + +async def test_import_route_delegates_to_processor(monkeypatch: pytest.MonkeyPatch): + payload = {"model_hash": "abc123", "files": ["/path/image.png"]} + async with example_images_app(monkeypatch) as harness: + response = await harness.client.post( + "/api/lm/import-example-images", json=payload + ) + body = await response.json() + + assert response.status == 200 + assert body == {"operation": "import_images", "payload": payload} + assert harness.processor.calls == [("import_images", payload)] + + +async def test_delete_route_delegates_to_processor(monkeypatch: pytest.MonkeyPatch): + payload = {"model_hash": "abc123", "short_id": "xyz"} + async with example_images_app(monkeypatch) as harness: + response = await harness.client.post( + "/api/lm/delete-example-image", json=payload + ) + body = await response.json() + + assert response.status == 200 + assert body == {"operation": "delete_custom_image", "payload": payload} + assert harness.processor.calls == [("delete_custom_image", payload)] + + +async def test_file_routes_delegate_to_file_manager(monkeypatch: pytest.MonkeyPatch): + open_payload = {"model_hash": "abc123"} + files_params = {"model_hash": "def456"} + + async with example_images_app(monkeypatch) as harness: + open_response = await harness.client.post( + "/api/lm/open-example-images-folder", json=open_payload + ) + files_response = await harness.client.get( + "/api/lm/example-image-files", params=files_params + ) + has_response = await harness.client.get( + "/api/lm/has-example-images", params=files_params + ) + + assert open_response.status == 200 + assert files_response.status == 200 + assert has_response.status == 200 + + assert await open_response.json() == {"operation": "open_folder", "payload": open_payload} + assert await files_response.json() == { + "operation": "get_files", + "query": files_params, + } + assert await has_response.json() == { + "operation": "has_images", + "query": files_params, + } + + assert harness.file_manager.calls == [ + ("open_folder", open_payload), + ("get_files", files_params), + ("has_images", files_params), + ] From 613cd81152302bde5bf534f4014291a5bb02e50d Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Tue, 23 Sep 2025 11:12:05 +0800 Subject: [PATCH 069/110] refactor(routes): add registrar for example images --- py/routes/example_images_route_registrar.py | 61 +++++++++++++++++++++ py/routes/example_images_routes.py | 46 ++++++++++------ tests/routes/test_example_images_routes.py | 16 +++++- 3 files changed, 106 insertions(+), 17 deletions(-) create mode 100644 py/routes/example_images_route_registrar.py diff --git a/py/routes/example_images_route_registrar.py b/py/routes/example_images_route_registrar.py new file mode 100644 index 00000000..d0f1fab0 --- /dev/null +++ b/py/routes/example_images_route_registrar.py @@ -0,0 +1,61 @@ +"""Route registrar for example image endpoints.""" +from __future__ import annotations + +from dataclasses import dataclass +from typing import Callable, Iterable, Mapping + +from aiohttp import web + + +@dataclass(frozen=True) +class RouteDefinition: + """Declarative configuration for a HTTP route.""" + + method: str + path: str + handler_name: str + + +ROUTE_DEFINITIONS: tuple[RouteDefinition, ...] = ( + RouteDefinition("POST", "/api/lm/download-example-images", "download_example_images"), + RouteDefinition("POST", "/api/lm/import-example-images", "import_example_images"), + RouteDefinition("GET", "/api/lm/example-images-status", "get_example_images_status"), + RouteDefinition("POST", "/api/lm/pause-example-images", "pause_example_images"), + RouteDefinition("POST", "/api/lm/resume-example-images", "resume_example_images"), + RouteDefinition("POST", "/api/lm/open-example-images-folder", "open_example_images_folder"), + RouteDefinition("GET", "/api/lm/example-image-files", "get_example_image_files"), + RouteDefinition("GET", "/api/lm/has-example-images", "has_example_images"), + RouteDefinition("POST", "/api/lm/delete-example-image", "delete_example_image"), + RouteDefinition("POST", "/api/lm/force-download-example-images", "force_download_example_images"), +) + + +class ExampleImagesRouteRegistrar: + """Bind declarative example image routes to an aiohttp router.""" + + _METHOD_MAP = { + "GET": "add_get", + "POST": "add_post", + "PUT": "add_put", + "DELETE": "add_delete", + } + + def __init__(self, app: web.Application) -> None: + self._app = app + + def register_routes( + self, + handler_lookup: Mapping[str, Callable[[web.Request], object]], + *, + definitions: Iterable[RouteDefinition] = ROUTE_DEFINITIONS, + ) -> None: + """Register each route definition using the supplied handlers.""" + + for definition in definitions: + handler = handler_lookup[definition.handler_name] + self._bind_route(definition.method, definition.path, handler) + + def _bind_route(self, method: str, path: str, handler: Callable[[web.Request], object]) -> None: + add_method_name = self._METHOD_MAP[method.upper()] + add_method = getattr(self._app.router, add_method_name) + add_method(path, handler) diff --git a/py/routes/example_images_routes.py b/py/routes/example_images_routes.py index 07cb0e71..193cfe1d 100644 --- a/py/routes/example_images_routes.py +++ b/py/routes/example_images_routes.py @@ -1,4 +1,9 @@ import logging +from typing import Callable + +from aiohttp import web + +from .example_images_route_registrar import ExampleImagesRouteRegistrar from ..utils.example_images_download_manager import DownloadManager from ..utils.example_images_processor import ExampleImagesProcessor from ..utils.example_images_file_manager import ExampleImagesFileManager @@ -6,22 +11,31 @@ from ..services.websocket_manager import ws_manager logger = logging.getLogger(__name__) + class ExampleImagesRoutes: """Routes for example images related functionality""" - + @staticmethod - def setup_routes(app): - """Register example images routes""" - app.router.add_post('/api/lm/download-example-images', ExampleImagesRoutes.download_example_images) - app.router.add_post('/api/lm/import-example-images', ExampleImagesRoutes.import_example_images) - app.router.add_get('/api/lm/example-images-status', ExampleImagesRoutes.get_example_images_status) - app.router.add_post('/api/lm/pause-example-images', ExampleImagesRoutes.pause_example_images) - app.router.add_post('/api/lm/resume-example-images', ExampleImagesRoutes.resume_example_images) - app.router.add_post('/api/lm/open-example-images-folder', ExampleImagesRoutes.open_example_images_folder) - app.router.add_get('/api/lm/example-image-files', ExampleImagesRoutes.get_example_image_files) - app.router.add_get('/api/lm/has-example-images', ExampleImagesRoutes.has_example_images) - app.router.add_post('/api/lm/delete-example-image', ExampleImagesRoutes.delete_example_image) - app.router.add_post('/api/lm/force-download-example-images', ExampleImagesRoutes.force_download_example_images) + def setup_routes(app: web.Application) -> None: + """Register example images routes using the registrar.""" + + registrar = ExampleImagesRouteRegistrar(app) + registrar.register_routes(ExampleImagesRoutes._route_mapping()) + + @staticmethod + def _route_mapping() -> dict[str, Callable[[web.Request], object]]: + return { + "download_example_images": ExampleImagesRoutes.download_example_images, + "import_example_images": ExampleImagesRoutes.import_example_images, + "get_example_images_status": ExampleImagesRoutes.get_example_images_status, + "pause_example_images": ExampleImagesRoutes.pause_example_images, + "resume_example_images": ExampleImagesRoutes.resume_example_images, + "open_example_images_folder": ExampleImagesRoutes.open_example_images_folder, + "get_example_image_files": ExampleImagesRoutes.get_example_image_files, + "has_example_images": ExampleImagesRoutes.has_example_images, + "delete_example_image": ExampleImagesRoutes.delete_example_image, + "force_download_example_images": ExampleImagesRoutes.force_download_example_images, + } @staticmethod async def download_example_images(request): @@ -42,7 +56,7 @@ class ExampleImagesRoutes: async def resume_example_images(request): """Resume the example images download""" return await DownloadManager.resume_download(request) - + @staticmethod async def open_example_images_folder(request): """Open the example images folder for a specific model""" @@ -57,7 +71,7 @@ class ExampleImagesRoutes: async def import_example_images(request): """Import local example images for a model""" return await ExampleImagesProcessor.import_images(request) - + @staticmethod async def has_example_images(request): """Check if example images folder exists and is not empty for a model""" @@ -71,4 +85,4 @@ class ExampleImagesRoutes: @staticmethod async def force_download_example_images(request): """Force download example images for specific models""" - return await DownloadManager.start_force_download(request) \ No newline at end of file + return await DownloadManager.start_force_download(request) diff --git a/tests/routes/test_example_images_routes.py b/tests/routes/test_example_images_routes.py index d64e1d7f..dac40ee9 100644 --- a/tests/routes/test_example_images_routes.py +++ b/tests/routes/test_example_images_routes.py @@ -1,6 +1,6 @@ from contextlib import asynccontextmanager from dataclasses import dataclass -from typing import Any, List, Tuple +from typing import Any, List, Set, Tuple from aiohttp import web from aiohttp.test_utils import TestClient, TestServer @@ -8,6 +8,7 @@ import pytest from py.routes import example_images_routes from py.routes.example_images_routes import ExampleImagesRoutes +from py.routes.example_images_route_registrar import ROUTE_DEFINITIONS @dataclass @@ -110,6 +111,19 @@ async def example_images_app(monkeypatch: pytest.MonkeyPatch) -> ExampleImagesHa await client.close() +async def test_setup_routes_registers_all_definitions(monkeypatch: pytest.MonkeyPatch): + async with example_images_app(monkeypatch) as harness: + registered: Set[tuple[str, str]] = { + (route.method, route.resource.canonical) + for route in harness.client.app.router.routes() + if route.resource.canonical + } + + expected = {(definition.method, definition.path) for definition in ROUTE_DEFINITIONS} + + assert expected <= registered + + @pytest.mark.parametrize( "endpoint, payload", [ From 85f79cd8d184028908e3e95bba8ec593be4330ad Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Tue, 23 Sep 2025 11:12:08 +0800 Subject: [PATCH 070/110] refactor(routes): introduce example images controller --- py/routes/example_images_routes.py | 121 +++---- py/routes/handlers/example_images_handlers.py | 83 +++++ tests/routes/test_example_images_routes.py | 329 +++++++++++++----- 3 files changed, 371 insertions(+), 162 deletions(-) create mode 100644 py/routes/handlers/example_images_handlers.py diff --git a/py/routes/example_images_routes.py b/py/routes/example_images_routes.py index 193cfe1d..829760c2 100644 --- a/py/routes/example_images_routes.py +++ b/py/routes/example_images_routes.py @@ -1,88 +1,69 @@ +from __future__ import annotations + import logging -from typing import Callable +from typing import Callable, Mapping from aiohttp import web from .example_images_route_registrar import ExampleImagesRouteRegistrar +from .handlers.example_images_handlers import ( + ExampleImagesDownloadHandler, + ExampleImagesFileHandler, + ExampleImagesHandlerSet, + ExampleImagesManagementHandler, +) from ..utils.example_images_download_manager import DownloadManager -from ..utils.example_images_processor import ExampleImagesProcessor from ..utils.example_images_file_manager import ExampleImagesFileManager -from ..services.websocket_manager import ws_manager +from ..utils.example_images_processor import ExampleImagesProcessor logger = logging.getLogger(__name__) class ExampleImagesRoutes: - """Routes for example images related functionality""" + """Route controller for example image endpoints.""" - @staticmethod - def setup_routes(app: web.Application) -> None: - """Register example images routes using the registrar.""" + def __init__( + self, + *, + download_manager=DownloadManager, + processor=ExampleImagesProcessor, + file_manager=ExampleImagesFileManager, + ) -> None: + self._download_manager = download_manager + self._processor = processor + self._file_manager = file_manager + self._handler_set: ExampleImagesHandlerSet | None = None + self._handler_mapping: Mapping[str, Callable[[web.Request], web.StreamResponse]] | None = None + + @classmethod + def setup_routes(cls, app: web.Application) -> None: + """Register routes on the given aiohttp application using default wiring.""" + + controller = cls() + controller.register(app) + + def register(self, app: web.Application) -> None: + """Bind the controller's handlers to the aiohttp router.""" registrar = ExampleImagesRouteRegistrar(app) - registrar.register_routes(ExampleImagesRoutes._route_mapping()) + registrar.register_routes(self.to_route_mapping()) - @staticmethod - def _route_mapping() -> dict[str, Callable[[web.Request], object]]: - return { - "download_example_images": ExampleImagesRoutes.download_example_images, - "import_example_images": ExampleImagesRoutes.import_example_images, - "get_example_images_status": ExampleImagesRoutes.get_example_images_status, - "pause_example_images": ExampleImagesRoutes.pause_example_images, - "resume_example_images": ExampleImagesRoutes.resume_example_images, - "open_example_images_folder": ExampleImagesRoutes.open_example_images_folder, - "get_example_image_files": ExampleImagesRoutes.get_example_image_files, - "has_example_images": ExampleImagesRoutes.has_example_images, - "delete_example_image": ExampleImagesRoutes.delete_example_image, - "force_download_example_images": ExampleImagesRoutes.force_download_example_images, - } + def to_route_mapping(self) -> Mapping[str, Callable[[web.Request], web.StreamResponse]]: + """Return the registrar-compatible mapping of handler names to callables.""" - @staticmethod - async def download_example_images(request): - """Download example images for models from Civitai""" - return await DownloadManager.start_download(request) + if self._handler_mapping is None: + handler_set = self._build_handler_set() + self._handler_set = handler_set + self._handler_mapping = handler_set.to_route_mapping() + return self._handler_mapping - @staticmethod - async def get_example_images_status(request): - """Get the current status of example images download""" - return await DownloadManager.get_status(request) - - @staticmethod - async def pause_example_images(request): - """Pause the example images download""" - return await DownloadManager.pause_download(request) - - @staticmethod - async def resume_example_images(request): - """Resume the example images download""" - return await DownloadManager.resume_download(request) - - @staticmethod - async def open_example_images_folder(request): - """Open the example images folder for a specific model""" - return await ExampleImagesFileManager.open_folder(request) - - @staticmethod - async def get_example_image_files(request): - """Get list of example image files for a specific model""" - return await ExampleImagesFileManager.get_files(request) - - @staticmethod - async def import_example_images(request): - """Import local example images for a model""" - return await ExampleImagesProcessor.import_images(request) - - @staticmethod - async def has_example_images(request): - """Check if example images folder exists and is not empty for a model""" - return await ExampleImagesFileManager.has_images(request) - - @staticmethod - async def delete_example_image(request): - """Delete a custom example image for a model""" - return await ExampleImagesProcessor.delete_custom_image(request) - - @staticmethod - async def force_download_example_images(request): - """Force download example images for specific models""" - return await DownloadManager.start_force_download(request) + def _build_handler_set(self) -> ExampleImagesHandlerSet: + logger.debug("Building ExampleImagesHandlerSet with %s, %s, %s", self._download_manager, self._processor, self._file_manager) + download_handler = ExampleImagesDownloadHandler(self._download_manager) + management_handler = ExampleImagesManagementHandler(self._processor) + file_handler = ExampleImagesFileHandler(self._file_manager) + return ExampleImagesHandlerSet( + download=download_handler, + management=management_handler, + files=file_handler, + ) diff --git a/py/routes/handlers/example_images_handlers.py b/py/routes/handlers/example_images_handlers.py new file mode 100644 index 00000000..3d960338 --- /dev/null +++ b/py/routes/handlers/example_images_handlers.py @@ -0,0 +1,83 @@ +"""Handler set for example image routes.""" +from __future__ import annotations + +from dataclasses import dataclass +from typing import Callable, Mapping + +from aiohttp import web + + +class ExampleImagesDownloadHandler: + """HTTP adapters for download-related example image endpoints.""" + + def __init__(self, download_manager) -> None: + self._download_manager = download_manager + + async def download_example_images(self, request: web.Request) -> web.StreamResponse: + return await self._download_manager.start_download(request) + + async def get_example_images_status(self, request: web.Request) -> web.StreamResponse: + return await self._download_manager.get_status(request) + + async def pause_example_images(self, request: web.Request) -> web.StreamResponse: + return await self._download_manager.pause_download(request) + + async def resume_example_images(self, request: web.Request) -> web.StreamResponse: + return await self._download_manager.resume_download(request) + + async def force_download_example_images(self, request: web.Request) -> web.StreamResponse: + return await self._download_manager.start_force_download(request) + + +class ExampleImagesManagementHandler: + """HTTP adapters for import/delete endpoints.""" + + def __init__(self, processor) -> None: + self._processor = processor + + async def import_example_images(self, request: web.Request) -> web.StreamResponse: + return await self._processor.import_images(request) + + async def delete_example_image(self, request: web.Request) -> web.StreamResponse: + return await self._processor.delete_custom_image(request) + + +class ExampleImagesFileHandler: + """HTTP adapters for filesystem-centric endpoints.""" + + def __init__(self, file_manager) -> None: + self._file_manager = file_manager + + async def open_example_images_folder(self, request: web.Request) -> web.StreamResponse: + return await self._file_manager.open_folder(request) + + async def get_example_image_files(self, request: web.Request) -> web.StreamResponse: + return await self._file_manager.get_files(request) + + async def has_example_images(self, request: web.Request) -> web.StreamResponse: + return await self._file_manager.has_images(request) + + +@dataclass(frozen=True) +class ExampleImagesHandlerSet: + """Aggregate of handlers exposed to the registrar.""" + + download: ExampleImagesDownloadHandler + management: ExampleImagesManagementHandler + files: ExampleImagesFileHandler + + def to_route_mapping(self) -> Mapping[str, Callable[[web.Request], web.StreamResponse]]: + """Flatten handler methods into the registrar mapping.""" + + return { + "download_example_images": self.download.download_example_images, + "get_example_images_status": self.download.get_example_images_status, + "pause_example_images": self.download.pause_example_images, + "resume_example_images": self.download.resume_example_images, + "force_download_example_images": self.download.force_download_example_images, + "import_example_images": self.management.import_example_images, + "delete_example_image": self.management.delete_example_image, + "open_example_images_folder": self.files.open_example_images_folder, + "get_example_image_files": self.files.get_example_image_files, + "has_example_images": self.files.has_example_images, + } diff --git a/tests/routes/test_example_images_routes.py b/tests/routes/test_example_images_routes.py index dac40ee9..b9806dae 100644 --- a/tests/routes/test_example_images_routes.py +++ b/tests/routes/test_example_images_routes.py @@ -1,14 +1,21 @@ +from __future__ import annotations + from contextlib import asynccontextmanager from dataclasses import dataclass -from typing import Any, List, Set, Tuple +from typing import Any, List, Tuple from aiohttp import web from aiohttp.test_utils import TestClient, TestServer import pytest -from py.routes import example_images_routes -from py.routes.example_images_routes import ExampleImagesRoutes from py.routes.example_images_route_registrar import ROUTE_DEFINITIONS +from py.routes.example_images_routes import ExampleImagesRoutes +from py.routes.handlers.example_images_handlers import ( + ExampleImagesDownloadHandler, + ExampleImagesFileHandler, + ExampleImagesHandlerSet, + ExampleImagesManagementHandler, +) @dataclass @@ -16,85 +23,88 @@ class ExampleImagesHarness: """Container exposing the aiohttp client and stubbed collaborators.""" client: TestClient - download_manager: Any - processor: Any - file_manager: Any + download_manager: "StubDownloadManager" + processor: "StubExampleImagesProcessor" + file_manager: "StubExampleImagesFileManager" + controller: ExampleImagesRoutes + + +class StubDownloadManager: + def __init__(self) -> None: + self.calls: List[Tuple[str, Any]] = [] + + async def start_download(self, request: web.Request) -> web.StreamResponse: + payload = await request.json() + self.calls.append(("start_download", payload)) + return web.json_response({"operation": "start_download", "payload": payload}) + + async def get_status(self, request: web.Request) -> web.StreamResponse: + self.calls.append(("get_status", dict(request.query))) + return web.json_response({"operation": "get_status"}) + + async def pause_download(self, request: web.Request) -> web.StreamResponse: + self.calls.append(("pause_download", None)) + return web.json_response({"operation": "pause_download"}) + + async def resume_download(self, request: web.Request) -> web.StreamResponse: + self.calls.append(("resume_download", None)) + return web.json_response({"operation": "resume_download"}) + + async def start_force_download(self, request: web.Request) -> web.StreamResponse: + payload = await request.json() + self.calls.append(("start_force_download", payload)) + return web.json_response({"operation": "start_force_download", "payload": payload}) + + +class StubExampleImagesProcessor: + def __init__(self) -> None: + self.calls: List[Tuple[str, Any]] = [] + + async def import_images(self, request: web.Request) -> web.StreamResponse: + payload = await request.json() + self.calls.append(("import_images", payload)) + return web.json_response({"operation": "import_images", "payload": payload}) + + async def delete_custom_image(self, request: web.Request) -> web.StreamResponse: + payload = await request.json() + self.calls.append(("delete_custom_image", payload)) + return web.json_response({"operation": "delete_custom_image", "payload": payload}) + + +class StubExampleImagesFileManager: + def __init__(self) -> None: + self.calls: List[Tuple[str, Any]] = [] + + async def open_folder(self, request: web.Request) -> web.StreamResponse: + payload = await request.json() + self.calls.append(("open_folder", payload)) + return web.json_response({"operation": "open_folder", "payload": payload}) + + async def get_files(self, request: web.Request) -> web.StreamResponse: + self.calls.append(("get_files", dict(request.query))) + return web.json_response({"operation": "get_files", "query": dict(request.query)}) + + async def has_images(self, request: web.Request) -> web.StreamResponse: + self.calls.append(("has_images", dict(request.query))) + return web.json_response({"operation": "has_images", "query": dict(request.query)}) @asynccontextmanager -async def example_images_app(monkeypatch: pytest.MonkeyPatch) -> ExampleImagesHarness: +async def example_images_app() -> ExampleImagesHarness: """Yield an ExampleImagesRoutes app wired with stubbed collaborators.""" - class StubDownloadManager: - calls: List[Tuple[str, Any]] = [] + download_manager = StubDownloadManager() + processor = StubExampleImagesProcessor() + file_manager = StubExampleImagesFileManager() - @staticmethod - async def start_download(request): - payload = await request.json() - StubDownloadManager.calls.append(("start_download", payload)) - return web.json_response({"operation": "start_download", "payload": payload}) - - @staticmethod - async def get_status(request): - StubDownloadManager.calls.append(("get_status", dict(request.query))) - return web.json_response({"operation": "get_status"}) - - @staticmethod - async def pause_download(request): - StubDownloadManager.calls.append(("pause_download", None)) - return web.json_response({"operation": "pause_download"}) - - @staticmethod - async def resume_download(request): - StubDownloadManager.calls.append(("resume_download", None)) - return web.json_response({"operation": "resume_download"}) - - @staticmethod - async def start_force_download(request): - payload = await request.json() - StubDownloadManager.calls.append(("start_force_download", payload)) - return web.json_response({"operation": "start_force_download", "payload": payload}) - - class StubExampleImagesProcessor: - calls: List[Tuple[str, Any]] = [] - - @staticmethod - async def import_images(request): - payload = await request.json() - StubExampleImagesProcessor.calls.append(("import_images", payload)) - return web.json_response({"operation": "import_images", "payload": payload}) - - @staticmethod - async def delete_custom_image(request): - payload = await request.json() - StubExampleImagesProcessor.calls.append(("delete_custom_image", payload)) - return web.json_response({"operation": "delete_custom_image", "payload": payload}) - - class StubExampleImagesFileManager: - calls: List[Tuple[str, Any]] = [] - - @staticmethod - async def open_folder(request): - payload = await request.json() - StubExampleImagesFileManager.calls.append(("open_folder", payload)) - return web.json_response({"operation": "open_folder", "payload": payload}) - - @staticmethod - async def get_files(request): - StubExampleImagesFileManager.calls.append(("get_files", dict(request.query))) - return web.json_response({"operation": "get_files", "query": dict(request.query)}) - - @staticmethod - async def has_images(request): - StubExampleImagesFileManager.calls.append(("has_images", dict(request.query))) - return web.json_response({"operation": "has_images", "query": dict(request.query)}) - - monkeypatch.setattr(example_images_routes, "DownloadManager", StubDownloadManager) - monkeypatch.setattr(example_images_routes, "ExampleImagesProcessor", StubExampleImagesProcessor) - monkeypatch.setattr(example_images_routes, "ExampleImagesFileManager", StubExampleImagesFileManager) + controller = ExampleImagesRoutes( + download_manager=download_manager, + processor=processor, + file_manager=file_manager, + ) app = web.Application() - ExampleImagesRoutes.setup_routes(app) + controller.register(app) server = TestServer(app) client = TestClient(server) @@ -103,17 +113,18 @@ async def example_images_app(monkeypatch: pytest.MonkeyPatch) -> ExampleImagesHa try: yield ExampleImagesHarness( client=client, - download_manager=StubDownloadManager, - processor=StubExampleImagesProcessor, - file_manager=StubExampleImagesFileManager, + download_manager=download_manager, + processor=processor, + file_manager=file_manager, + controller=controller, ) finally: await client.close() -async def test_setup_routes_registers_all_definitions(monkeypatch: pytest.MonkeyPatch): - async with example_images_app(monkeypatch) as harness: - registered: Set[tuple[str, str]] = { +async def test_setup_routes_registers_all_definitions(): + async with example_images_app() as harness: + registered = { (route.method, route.resource.canonical) for route in harness.client.app.router.routes() if route.resource.canonical @@ -131,8 +142,8 @@ async def test_setup_routes_registers_all_definitions(monkeypatch: pytest.Monkey ("/api/lm/force-download-example-images", {"model_hashes": ["abc123"]}), ], ) -async def test_download_routes_delegate_to_manager(endpoint, payload, monkeypatch: pytest.MonkeyPatch): - async with example_images_app(monkeypatch) as harness: +async def test_download_routes_delegate_to_manager(endpoint, payload): + async with example_images_app() as harness: response = await harness.client.post(endpoint, json=payload) body = await response.json() @@ -144,8 +155,8 @@ async def test_download_routes_delegate_to_manager(endpoint, payload, monkeypatc assert expected_call in harness.download_manager.calls -async def test_status_route_returns_manager_payload(monkeypatch: pytest.MonkeyPatch): - async with example_images_app(monkeypatch) as harness: +async def test_status_route_returns_manager_payload(): + async with example_images_app() as harness: response = await harness.client.get( "/api/lm/example-images-status", params={"detail": "true"} ) @@ -156,8 +167,8 @@ async def test_status_route_returns_manager_payload(monkeypatch: pytest.MonkeyPa assert harness.download_manager.calls == [("get_status", {"detail": "true"})] -async def test_pause_and_resume_routes_delegate(monkeypatch: pytest.MonkeyPatch): - async with example_images_app(monkeypatch) as harness: +async def test_pause_and_resume_routes_delegate(): + async with example_images_app() as harness: pause_response = await harness.client.post("/api/lm/pause-example-images") resume_response = await harness.client.post("/api/lm/resume-example-images") @@ -172,9 +183,9 @@ async def test_pause_and_resume_routes_delegate(monkeypatch: pytest.MonkeyPatch) ] -async def test_import_route_delegates_to_processor(monkeypatch: pytest.MonkeyPatch): +async def test_import_route_delegates_to_processor(): payload = {"model_hash": "abc123", "files": ["/path/image.png"]} - async with example_images_app(monkeypatch) as harness: + async with example_images_app() as harness: response = await harness.client.post( "/api/lm/import-example-images", json=payload ) @@ -185,9 +196,9 @@ async def test_import_route_delegates_to_processor(monkeypatch: pytest.MonkeyPat assert harness.processor.calls == [("import_images", payload)] -async def test_delete_route_delegates_to_processor(monkeypatch: pytest.MonkeyPatch): +async def test_delete_route_delegates_to_processor(): payload = {"model_hash": "abc123", "short_id": "xyz"} - async with example_images_app(monkeypatch) as harness: + async with example_images_app() as harness: response = await harness.client.post( "/api/lm/delete-example-image", json=payload ) @@ -198,11 +209,11 @@ async def test_delete_route_delegates_to_processor(monkeypatch: pytest.MonkeyPat assert harness.processor.calls == [("delete_custom_image", payload)] -async def test_file_routes_delegate_to_file_manager(monkeypatch: pytest.MonkeyPatch): +async def test_file_routes_delegate_to_file_manager(): open_payload = {"model_hash": "abc123"} files_params = {"model_hash": "def456"} - async with example_images_app(monkeypatch) as harness: + async with example_images_app() as harness: open_response = await harness.client.post( "/api/lm/open-example-images-folder", json=open_payload ) @@ -232,3 +243,137 @@ async def test_file_routes_delegate_to_file_manager(monkeypatch: pytest.MonkeyPa ("get_files", files_params), ("has_images", files_params), ] + + +@pytest.mark.asyncio +async def test_download_handler_methods_delegate() -> None: + class Recorder: + def __init__(self) -> None: + self.calls: List[Tuple[str, Any]] = [] + + async def start_download(self, request) -> str: + self.calls.append(("start_download", request)) + return "download" + + async def get_status(self, request) -> str: + self.calls.append(("get_status", request)) + return "status" + + async def pause_download(self, request) -> str: + self.calls.append(("pause_download", request)) + return "pause" + + async def resume_download(self, request) -> str: + self.calls.append(("resume_download", request)) + return "resume" + + async def start_force_download(self, request) -> str: + self.calls.append(("start_force_download", request)) + return "force" + + recorder = Recorder() + handler = ExampleImagesDownloadHandler(recorder) + request = object() + + assert await handler.download_example_images(request) == "download" + assert await handler.get_example_images_status(request) == "status" + assert await handler.pause_example_images(request) == "pause" + assert await handler.resume_example_images(request) == "resume" + assert await handler.force_download_example_images(request) == "force" + + expected = [ + ("start_download", request), + ("get_status", request), + ("pause_download", request), + ("resume_download", request), + ("start_force_download", request), + ] + assert recorder.calls == expected + + +@pytest.mark.asyncio +async def test_management_handler_methods_delegate() -> None: + class Recorder: + def __init__(self) -> None: + self.calls: List[Tuple[str, Any]] = [] + + async def import_images(self, request) -> str: + self.calls.append(("import_images", request)) + return "import" + + async def delete_custom_image(self, request) -> str: + self.calls.append(("delete_custom_image", request)) + return "delete" + + recorder = Recorder() + handler = ExampleImagesManagementHandler(recorder) + request = object() + + assert await handler.import_example_images(request) == "import" + assert await handler.delete_example_image(request) == "delete" + assert recorder.calls == [ + ("import_images", request), + ("delete_custom_image", request), + ] + + +@pytest.mark.asyncio +async def test_file_handler_methods_delegate() -> None: + class Recorder: + def __init__(self) -> None: + self.calls: List[Tuple[str, Any]] = [] + + async def open_folder(self, request) -> str: + self.calls.append(("open_folder", request)) + return "open" + + async def get_files(self, request) -> str: + self.calls.append(("get_files", request)) + return "files" + + async def has_images(self, request) -> str: + self.calls.append(("has_images", request)) + return "has" + + recorder = Recorder() + handler = ExampleImagesFileHandler(recorder) + request = object() + + assert await handler.open_example_images_folder(request) == "open" + assert await handler.get_example_image_files(request) == "files" + assert await handler.has_example_images(request) == "has" + assert recorder.calls == [ + ("open_folder", request), + ("get_files", request), + ("has_images", request), + ] + + +def test_handler_set_route_mapping_includes_all_handlers() -> None: + download = ExampleImagesDownloadHandler(object()) + management = ExampleImagesManagementHandler(object()) + files = ExampleImagesFileHandler(object()) + handler_set = ExampleImagesHandlerSet( + download=download, + management=management, + files=files, + ) + + mapping = handler_set.to_route_mapping() + + expected_keys = { + "download_example_images", + "get_example_images_status", + "pause_example_images", + "resume_example_images", + "force_download_example_images", + "import_example_images", + "delete_example_image", + "open_example_images_folder", + "get_example_image_files", + "has_example_images", + } + + assert mapping.keys() == expected_keys + for key in expected_keys: + assert callable(mapping[key]) From d4770502399b9f149f0481109f079954dfcc75f2 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Tue, 23 Sep 2025 11:19:36 +0800 Subject: [PATCH 071/110] feat: add global context menu with actions and integration --- .../ContextMenu/GlobalContextMenu.js | 24 +++++++++ static/js/components/ContextMenu/index.js | 6 +++ static/js/core.js | 6 ++- static/js/utils/eventManagementInit.js | 51 +++++++++++-------- templates/components/context_menu.html | 12 +++++ 5 files changed, 78 insertions(+), 21 deletions(-) create mode 100644 static/js/components/ContextMenu/GlobalContextMenu.js diff --git a/static/js/components/ContextMenu/GlobalContextMenu.js b/static/js/components/ContextMenu/GlobalContextMenu.js new file mode 100644 index 00000000..6015efee --- /dev/null +++ b/static/js/components/ContextMenu/GlobalContextMenu.js @@ -0,0 +1,24 @@ +import { BaseContextMenu } from './BaseContextMenu.js'; + +export class GlobalContextMenu extends BaseContextMenu { + constructor() { + super('globalContextMenu'); + } + + showMenu(x, y) { + super.showMenu(x, y, null); + } + + handleMenuAction(action, menuItem) { + switch (action) { + case 'placeholder-one': + case 'placeholder-two': + case 'placeholder-three': + console.info(`Global context menu action triggered: ${action}`); + break; + default: + console.warn(`Unhandled global context menu action: ${action}`); + break; + } + } +} diff --git a/static/js/components/ContextMenu/index.js b/static/js/components/ContextMenu/index.js index b6be6ccf..7d01c0f6 100644 --- a/static/js/components/ContextMenu/index.js +++ b/static/js/components/ContextMenu/index.js @@ -2,12 +2,14 @@ export { LoraContextMenu } from './LoraContextMenu.js'; export { RecipeContextMenu } from './RecipeContextMenu.js'; export { CheckpointContextMenu } from './CheckpointContextMenu.js'; export { EmbeddingContextMenu } from './EmbeddingContextMenu.js'; +export { GlobalContextMenu } from './GlobalContextMenu.js'; export { ModelContextMenuMixin } from './ModelContextMenuMixin.js'; import { LoraContextMenu } from './LoraContextMenu.js'; import { RecipeContextMenu } from './RecipeContextMenu.js'; import { CheckpointContextMenu } from './CheckpointContextMenu.js'; import { EmbeddingContextMenu } from './EmbeddingContextMenu.js'; +import { GlobalContextMenu } from './GlobalContextMenu.js'; // Factory method to create page-specific context menu instances export function createPageContextMenu(pageType) { @@ -23,4 +25,8 @@ export function createPageContextMenu(pageType) { default: return null; } +} + +export function createGlobalContextMenu() { + return new GlobalContextMenu(); } \ No newline at end of file diff --git a/static/js/core.js b/static/js/core.js index c2ad6cdb..40eb50b0 100644 --- a/static/js/core.js +++ b/static/js/core.js @@ -16,7 +16,7 @@ import { migrateStorageItems } from './utils/storageHelpers.js'; import { i18n } from './i18n/index.js'; import { onboardingManager } from './managers/OnboardingManager.js'; import { BulkContextMenu } from './components/ContextMenu/BulkContextMenu.js'; -import { createPageContextMenu } from './components/ContextMenu/index.js'; +import { createPageContextMenu, createGlobalContextMenu } from './components/ContextMenu/index.js'; import { initializeEventManagement } from './utils/eventManagementInit.js'; // Core application class @@ -116,6 +116,10 @@ export class AppCore { initializeContextMenus(pageType) { // Create page-specific context menu window.pageContextMenu = createPageContextMenu(pageType); + + if (!window.globalContextMenuInstance) { + window.globalContextMenuInstance = createGlobalContextMenu(); + } } } diff --git a/static/js/utils/eventManagementInit.js b/static/js/utils/eventManagementInit.js index ba9908b9..98055f43 100644 --- a/static/js/utils/eventManagementInit.js +++ b/static/js/utils/eventManagementInit.js @@ -86,29 +86,39 @@ function setupPageUnloadCleanup() { function registerContextMenuEvents() { eventManager.addHandler('contextmenu', 'contextMenu-coordination', (e) => { const card = e.target.closest('.model-card'); - if (!card) { - // Hide all menus if not right-clicking on a card - window.pageContextMenu?.hideMenu(); - window.bulkManager?.bulkContextMenu?.hideMenu(); + const pageContent = e.target.closest('.page-content'); + + if (!pageContent) { + window.globalContextMenuInstance?.hideMenu(); return false; } - - e.preventDefault(); - - // Hide all menus first - window.pageContextMenu?.hideMenu(); - window.bulkManager?.bulkContextMenu?.hideMenu(); - - // Determine which menu to show based on bulk mode and selection state - if (state.bulkMode && card.classList.contains('selected')) { - // Show bulk menu for selected cards in bulk mode - window.bulkManager?.bulkContextMenu?.showMenu(e.clientX, e.clientY, card); - } else if (!state.bulkMode) { - // Show regular menu when not in bulk mode - window.pageContextMenu?.showMenu(e.clientX, e.clientY, card); + + if (card) { + e.preventDefault(); + + // Hide all menus first + window.pageContextMenu?.hideMenu(); + window.bulkManager?.bulkContextMenu?.hideMenu(); + window.globalContextMenuInstance?.hideMenu(); + + // Determine which menu to show based on bulk mode and selection state + if (state.bulkMode && card.classList.contains('selected')) { + // Show bulk menu for selected cards in bulk mode + window.bulkManager?.bulkContextMenu?.showMenu(e.clientX, e.clientY, card); + } else if (!state.bulkMode) { + // Show regular menu when not in bulk mode + window.pageContextMenu?.showMenu(e.clientX, e.clientY, card); + } + } else { + e.preventDefault(); + + window.pageContextMenu?.hideMenu(); + window.bulkManager?.bulkContextMenu?.hideMenu(); + window.globalContextMenuInstance?.hideMenu(); + + window.globalContextMenuInstance?.showMenu(e.clientX, e.clientY, null); } - // Don't show any menu for unselected cards in bulk mode - + return true; // Stop propagation }, { priority: 200, // Higher priority than bulk manager events @@ -125,6 +135,7 @@ function registerGlobalClickHandlers() { if (!e.target.closest('.context-menu')) { window.pageContextMenu?.hideMenu(); window.bulkManager?.bulkContextMenu?.hideMenu(); + window.globalContextMenuInstance?.hideMenu(); } return false; // Allow other handlers to process }, { diff --git a/templates/components/context_menu.html b/templates/components/context_menu.html index b47ed57a..d5ace040 100644 --- a/templates/components/context_menu.html +++ b/templates/components/context_menu.html @@ -84,6 +84,18 @@ +

    +

    {{ t('modals.contentRating.title') }}

    From aaad270822c16b9acac418d5f0161b15d49a7d29 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Tue, 23 Sep 2025 11:47:12 +0800 Subject: [PATCH 072/110] feat(example-images): add use case orchestration --- py/routes/example_images_routes.py | 10 +- py/routes/handlers/example_images_handlers.py | 80 ++++++++- py/services/use_cases/__init__.py | 12 ++ .../use_cases/example_images/__init__.py | 19 ++ .../download_example_images_use_case.py | 42 +++++ .../import_example_images_use_case.py | 86 +++++++++ py/utils/example_images_download_manager.py | 170 ++++++++---------- py/utils/example_images_processor.py | 151 +++++----------- tests/routes/test_example_images_routes.py | 148 +++++++++------ tests/services/test_use_cases.py | 126 +++++++++++++ 10 files changed, 582 insertions(+), 262 deletions(-) create mode 100644 py/services/use_cases/example_images/__init__.py create mode 100644 py/services/use_cases/example_images/download_example_images_use_case.py create mode 100644 py/services/use_cases/example_images/import_example_images_use_case.py diff --git a/py/routes/example_images_routes.py b/py/routes/example_images_routes.py index 829760c2..44effa3b 100644 --- a/py/routes/example_images_routes.py +++ b/py/routes/example_images_routes.py @@ -12,6 +12,10 @@ from .handlers.example_images_handlers import ( ExampleImagesHandlerSet, ExampleImagesManagementHandler, ) +from ..services.use_cases.example_images import ( + DownloadExampleImagesUseCase, + ImportExampleImagesUseCase, +) from ..utils.example_images_download_manager import DownloadManager from ..utils.example_images_file_manager import ExampleImagesFileManager from ..utils.example_images_processor import ExampleImagesProcessor @@ -59,8 +63,10 @@ class ExampleImagesRoutes: def _build_handler_set(self) -> ExampleImagesHandlerSet: logger.debug("Building ExampleImagesHandlerSet with %s, %s, %s", self._download_manager, self._processor, self._file_manager) - download_handler = ExampleImagesDownloadHandler(self._download_manager) - management_handler = ExampleImagesManagementHandler(self._processor) + download_use_case = DownloadExampleImagesUseCase(download_manager=self._download_manager) + download_handler = ExampleImagesDownloadHandler(download_use_case, self._download_manager) + import_use_case = ImportExampleImagesUseCase(processor=self._processor) + management_handler = ExampleImagesManagementHandler(import_use_case, self._processor) file_handler = ExampleImagesFileHandler(self._file_manager) return ExampleImagesHandlerSet( download=download_handler, diff --git a/py/routes/handlers/example_images_handlers.py b/py/routes/handlers/example_images_handlers.py index 3d960338..fd39de04 100644 --- a/py/routes/handlers/example_images_handlers.py +++ b/py/routes/handlers/example_images_handlers.py @@ -6,37 +6,101 @@ from typing import Callable, Mapping from aiohttp import web +from ...services.use_cases.example_images import ( + DownloadExampleImagesConfigurationError, + DownloadExampleImagesInProgressError, + DownloadExampleImagesUseCase, + ImportExampleImagesUseCase, + ImportExampleImagesValidationError, +) +from ...utils.example_images_download_manager import ( + DownloadConfigurationError, + DownloadInProgressError, + DownloadNotRunningError, + ExampleImagesDownloadError, +) +from ...utils.example_images_processor import ExampleImagesImportError + class ExampleImagesDownloadHandler: """HTTP adapters for download-related example image endpoints.""" - def __init__(self, download_manager) -> None: + def __init__( + self, + download_use_case: DownloadExampleImagesUseCase, + download_manager, + ) -> None: + self._download_use_case = download_use_case self._download_manager = download_manager async def download_example_images(self, request: web.Request) -> web.StreamResponse: - return await self._download_manager.start_download(request) + try: + payload = await request.json() + result = await self._download_use_case.execute(payload) + return web.json_response(result) + except DownloadExampleImagesInProgressError as exc: + response = { + 'success': False, + 'error': str(exc), + 'status': exc.progress, + } + return web.json_response(response, status=400) + except DownloadExampleImagesConfigurationError as exc: + return web.json_response({'success': False, 'error': str(exc)}, status=400) + except ExampleImagesDownloadError as exc: + return web.json_response({'success': False, 'error': str(exc)}, status=500) async def get_example_images_status(self, request: web.Request) -> web.StreamResponse: - return await self._download_manager.get_status(request) + result = await self._download_manager.get_status(request) + return web.json_response(result) async def pause_example_images(self, request: web.Request) -> web.StreamResponse: - return await self._download_manager.pause_download(request) + try: + result = await self._download_manager.pause_download(request) + return web.json_response(result) + except DownloadNotRunningError as exc: + return web.json_response({'success': False, 'error': str(exc)}, status=400) async def resume_example_images(self, request: web.Request) -> web.StreamResponse: - return await self._download_manager.resume_download(request) + try: + result = await self._download_manager.resume_download(request) + return web.json_response(result) + except DownloadNotRunningError as exc: + return web.json_response({'success': False, 'error': str(exc)}, status=400) async def force_download_example_images(self, request: web.Request) -> web.StreamResponse: - return await self._download_manager.start_force_download(request) + try: + payload = await request.json() + result = await self._download_manager.start_force_download(payload) + return web.json_response(result) + except DownloadInProgressError as exc: + response = { + 'success': False, + 'error': str(exc), + 'status': exc.progress_snapshot, + } + return web.json_response(response, status=400) + except DownloadConfigurationError as exc: + return web.json_response({'success': False, 'error': str(exc)}, status=400) + except ExampleImagesDownloadError as exc: + return web.json_response({'success': False, 'error': str(exc)}, status=500) class ExampleImagesManagementHandler: """HTTP adapters for import/delete endpoints.""" - def __init__(self, processor) -> None: + def __init__(self, import_use_case: ImportExampleImagesUseCase, processor) -> None: + self._import_use_case = import_use_case self._processor = processor async def import_example_images(self, request: web.Request) -> web.StreamResponse: - return await self._processor.import_images(request) + try: + result = await self._import_use_case.execute(request) + return web.json_response(result) + except ImportExampleImagesValidationError as exc: + return web.json_response({'success': False, 'error': str(exc)}, status=400) + except ExampleImagesImportError as exc: + return web.json_response({'success': False, 'error': str(exc)}, status=500) async def delete_example_image(self, request: web.Request) -> web.StreamResponse: return await self._processor.delete_custom_image(request) diff --git a/py/services/use_cases/__init__.py b/py/services/use_cases/__init__.py index 986f0f57..8a43318c 100644 --- a/py/services/use_cases/__init__.py +++ b/py/services/use_cases/__init__.py @@ -13,6 +13,13 @@ from .download_model_use_case import ( DownloadModelUseCase, DownloadModelValidationError, ) +from .example_images import ( + DownloadExampleImagesConfigurationError, + DownloadExampleImagesInProgressError, + DownloadExampleImagesUseCase, + ImportExampleImagesUseCase, + ImportExampleImagesValidationError, +) __all__ = [ "AutoOrganizeInProgressError", @@ -22,4 +29,9 @@ __all__ = [ "DownloadModelEarlyAccessError", "DownloadModelUseCase", "DownloadModelValidationError", + "DownloadExampleImagesConfigurationError", + "DownloadExampleImagesInProgressError", + "DownloadExampleImagesUseCase", + "ImportExampleImagesUseCase", + "ImportExampleImagesValidationError", ] diff --git a/py/services/use_cases/example_images/__init__.py b/py/services/use_cases/example_images/__init__.py new file mode 100644 index 00000000..820de618 --- /dev/null +++ b/py/services/use_cases/example_images/__init__.py @@ -0,0 +1,19 @@ +"""Example image specific use case exports.""" + +from .download_example_images_use_case import ( + DownloadExampleImagesUseCase, + DownloadExampleImagesInProgressError, + DownloadExampleImagesConfigurationError, +) +from .import_example_images_use_case import ( + ImportExampleImagesUseCase, + ImportExampleImagesValidationError, +) + +__all__ = [ + "DownloadExampleImagesUseCase", + "DownloadExampleImagesInProgressError", + "DownloadExampleImagesConfigurationError", + "ImportExampleImagesUseCase", + "ImportExampleImagesValidationError", +] diff --git a/py/services/use_cases/example_images/download_example_images_use_case.py b/py/services/use_cases/example_images/download_example_images_use_case.py new file mode 100644 index 00000000..e9a51e13 --- /dev/null +++ b/py/services/use_cases/example_images/download_example_images_use_case.py @@ -0,0 +1,42 @@ +"""Use case coordinating example image downloads.""" + +from __future__ import annotations + +from typing import Any, Dict + +from ....utils.example_images_download_manager import ( + DownloadConfigurationError, + DownloadInProgressError, + ExampleImagesDownloadError, +) + + +class DownloadExampleImagesInProgressError(RuntimeError): + """Raised when a download is already running.""" + + def __init__(self, progress: Dict[str, Any]) -> None: + super().__init__("Download already in progress") + self.progress = progress + + +class DownloadExampleImagesConfigurationError(ValueError): + """Raised when settings prevent downloads from starting.""" + + +class DownloadExampleImagesUseCase: + """Validate payloads and trigger the download manager.""" + + def __init__(self, *, download_manager) -> None: + self._download_manager = download_manager + + async def execute(self, payload: Dict[str, Any]) -> Dict[str, Any]: + """Start a download and translate manager errors.""" + + try: + return await self._download_manager.start_download(payload) + except DownloadInProgressError as exc: + raise DownloadExampleImagesInProgressError(exc.progress_snapshot) from exc + except DownloadConfigurationError as exc: + raise DownloadExampleImagesConfigurationError(str(exc)) from exc + except ExampleImagesDownloadError: + raise diff --git a/py/services/use_cases/example_images/import_example_images_use_case.py b/py/services/use_cases/example_images/import_example_images_use_case.py new file mode 100644 index 00000000..547b2f4e --- /dev/null +++ b/py/services/use_cases/example_images/import_example_images_use_case.py @@ -0,0 +1,86 @@ +"""Use case for importing example images.""" + +from __future__ import annotations + +import os +import tempfile +from contextlib import suppress +from typing import Any, Dict, List + +from aiohttp import web + +from ....utils.example_images_processor import ( + ExampleImagesImportError, + ExampleImagesProcessor, + ExampleImagesValidationError, +) + + +class ImportExampleImagesValidationError(ValueError): + """Raised when request validation fails.""" + + +class ImportExampleImagesUseCase: + """Parse upload payloads and delegate to the processor service.""" + + def __init__(self, *, processor: ExampleImagesProcessor) -> None: + self._processor = processor + + async def execute(self, request: web.Request) -> Dict[str, Any]: + model_hash: str | None = None + files_to_import: List[str] = [] + temp_files: List[str] = [] + + try: + if request.content_type and "multipart/form-data" in request.content_type: + reader = await request.multipart() + + first_field = await reader.next() + if first_field and first_field.name == "model_hash": + model_hash = await first_field.text() + else: + # Support clients that send files first and hash later + if first_field is not None: + await self._collect_upload_file(first_field, files_to_import, temp_files) + + async for field in reader: + if field.name == "model_hash" and not model_hash: + model_hash = await field.text() + elif field.name == "files": + await self._collect_upload_file(field, files_to_import, temp_files) + else: + data = await request.json() + model_hash = data.get("model_hash") + files_to_import = list(data.get("file_paths", [])) + + result = await self._processor.import_images(model_hash, files_to_import) + return result + except ExampleImagesValidationError as exc: + raise ImportExampleImagesValidationError(str(exc)) from exc + except ExampleImagesImportError: + raise + finally: + for path in temp_files: + with suppress(Exception): + os.remove(path) + + async def _collect_upload_file( + self, + field: Any, + files_to_import: List[str], + temp_files: List[str], + ) -> None: + """Persist an uploaded file to disk and add it to the import list.""" + + filename = field.filename or "upload" + file_ext = os.path.splitext(filename)[1].lower() + + with tempfile.NamedTemporaryFile(suffix=file_ext, delete=False) as tmp_file: + temp_files.append(tmp_file.name) + while True: + chunk = await field.read_chunk() + if not chunk: + break + tmp_file.write(chunk) + + files_to_import.append(tmp_file.name) diff --git a/py/utils/example_images_download_manager.py b/py/utils/example_images_download_manager.py index 842192f2..7df0c6fb 100644 --- a/py/utils/example_images_download_manager.py +++ b/py/utils/example_images_download_manager.py @@ -3,7 +3,6 @@ import os import asyncio import json import time -from aiohttp import web from ..services.service_registry import ServiceRegistry from ..utils.metadata_manager import MetadataManager from .example_images_processor import ExampleImagesProcessor @@ -12,6 +11,30 @@ from ..services.websocket_manager import ws_manager # Add this import at the to from ..services.downloader import get_downloader from ..services.settings_manager import settings + +class ExampleImagesDownloadError(RuntimeError): + """Base error for example image download operations.""" + + +class DownloadInProgressError(ExampleImagesDownloadError): + """Raised when a download is already running.""" + + def __init__(self, progress_snapshot: dict) -> None: + super().__init__("Download already in progress") + self.progress_snapshot = progress_snapshot + + +class DownloadNotRunningError(ExampleImagesDownloadError): + """Raised when pause/resume is requested without an active download.""" + + def __init__(self, message: str = "No download in progress") -> None: + super().__init__(message) + + +class DownloadConfigurationError(ExampleImagesDownloadError): + """Raised when configuration prevents starting a download.""" + + logger = logging.getLogger(__name__) # Download status tracking @@ -31,11 +54,21 @@ download_progress = { 'failed_models': set() # Track models that failed to download after metadata refresh } + +def _serialize_progress() -> dict: + """Return a JSON-serialisable snapshot of the current progress.""" + + snapshot = download_progress.copy() + snapshot['processed_models'] = list(download_progress['processed_models']) + snapshot['refreshed_models'] = list(download_progress['refreshed_models']) + snapshot['failed_models'] = list(download_progress['failed_models']) + return snapshot + class DownloadManager: """Manages downloading example images for models""" @staticmethod - async def start_download(request): + async def start_download(options: dict): """ Start downloading example images for models @@ -50,25 +83,14 @@ class DownloadManager: global download_task, is_downloading, download_progress if is_downloading: - # Create a copy for JSON serialization - response_progress = download_progress.copy() - response_progress['processed_models'] = list(download_progress['processed_models']) - response_progress['refreshed_models'] = list(download_progress['refreshed_models']) - response_progress['failed_models'] = list(download_progress['failed_models']) - - return web.json_response({ - 'success': False, - 'error': 'Download already in progress', - 'status': response_progress - }, status=400) - + raise DownloadInProgressError(_serialize_progress()) + try: - # Parse the request body - data = await request.json() + data = options or {} auto_mode = data.get('auto_mode', False) optimize = data.get('optimize', True) model_types = data.get('model_types', ['lora', 'checkpoint']) - delay = float(data.get('delay', 0.2)) # Default to 0.2 seconds + delay = float(data.get('delay', 0.2)) # Default to 0.2 seconds # Get output directory from settings output_dir = settings.get('example_images_path') @@ -78,15 +100,11 @@ class DownloadManager: if auto_mode: # For auto mode, just log and return success to avoid showing error toasts logger.debug(error_msg) - return web.json_response({ + return { 'success': True, 'message': 'Example images path not configured, skipping auto download' - }) - else: - return web.json_response({ - 'success': False, - 'error': error_msg - }, status=400) + } + raise DownloadConfigurationError(error_msg) # Create the output directory os.makedirs(output_dir, exist_ok=True) @@ -129,41 +147,29 @@ class DownloadManager: ) ) - # Create a copy for JSON serialization - response_progress = download_progress.copy() - response_progress['processed_models'] = list(download_progress['processed_models']) - response_progress['refreshed_models'] = list(download_progress['refreshed_models']) - response_progress['failed_models'] = list(download_progress['failed_models']) - - return web.json_response({ + return { 'success': True, 'message': 'Download started', - 'status': response_progress - }) - + 'status': _serialize_progress() + } + except Exception as e: logger.error(f"Failed to start example images download: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) + raise ExampleImagesDownloadError(str(e)) from e @staticmethod async def get_status(request): """Get the current status of example images download""" global download_progress - + # Create a copy of the progress dict with the set converted to a list for JSON serialization - response_progress = download_progress.copy() - response_progress['processed_models'] = list(download_progress['processed_models']) - response_progress['refreshed_models'] = list(download_progress['refreshed_models']) - response_progress['failed_models'] = list(download_progress['failed_models']) - - return web.json_response({ + response_progress = _serialize_progress() + + return { 'success': True, 'is_downloading': is_downloading, 'status': response_progress - }) + } @staticmethod async def pause_download(request): @@ -171,17 +177,14 @@ class DownloadManager: global download_progress if not is_downloading: - return web.json_response({ - 'success': False, - 'error': 'No download in progress' - }, status=400) - + raise DownloadNotRunningError() + download_progress['status'] = 'paused' - - return web.json_response({ + + return { 'success': True, 'message': 'Download paused' - }) + } @staticmethod async def resume_download(request): @@ -189,23 +192,19 @@ class DownloadManager: global download_progress if not is_downloading: - return web.json_response({ - 'success': False, - 'error': 'No download in progress' - }, status=400) - + raise DownloadNotRunningError() + if download_progress['status'] == 'paused': download_progress['status'] = 'running' - - return web.json_response({ + + return { 'success': True, 'message': 'Download resumed' - }) - else: - return web.json_response({ - 'success': False, - 'error': f"Download is in '{download_progress['status']}' state, cannot resume" - }, status=400) + } + + raise DownloadNotRunningError( + f"Download is in '{download_progress['status']}' state, cannot resume" + ) @staticmethod async def _download_all_example_images(output_dir, optimize, model_types, delay): @@ -432,7 +431,7 @@ class DownloadManager: logger.error(f"Failed to save progress file: {e}") @staticmethod - async def start_force_download(request): + async def start_force_download(options: dict): """ Force download example images for specific models @@ -447,33 +446,23 @@ class DownloadManager: global download_task, is_downloading, download_progress if is_downloading: - return web.json_response({ - 'success': False, - 'error': 'Download already in progress' - }, status=400) + raise DownloadInProgressError(_serialize_progress()) try: - # Parse the request body - data = await request.json() + data = options or {} model_hashes = data.get('model_hashes', []) optimize = data.get('optimize', True) model_types = data.get('model_types', ['lora', 'checkpoint']) - delay = float(data.get('delay', 0.2)) # Default to 0.2 seconds - + delay = float(data.get('delay', 0.2)) # Default to 0.2 seconds + if not model_hashes: - return web.json_response({ - 'success': False, - 'error': 'Missing model_hashes parameter' - }, status=400) - + raise DownloadConfigurationError('Missing model_hashes parameter') + # Get output directory from settings output_dir = settings.get('example_images_path') - + if not output_dir: - return web.json_response({ - 'success': False, - 'error': 'Example images path not configured in settings' - }, status=400) + raise DownloadConfigurationError('Example images path not configured in settings') # Create the output directory os.makedirs(output_dir, exist_ok=True) @@ -506,20 +495,17 @@ class DownloadManager: # Set download status to not downloading is_downloading = False - return web.json_response({ + return { 'success': True, 'message': 'Force download completed', 'result': result - }) + } except Exception as e: # Set download status to not downloading is_downloading = False logger.error(f"Failed during forced example images download: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) + raise ExampleImagesDownloadError(str(e)) from e @staticmethod async def _download_specific_models_example_images_sync(model_hashes, output_dir, optimize, model_types, delay): diff --git a/py/utils/example_images_processor.py b/py/utils/example_images_processor.py index f1cfd2bf..7f108ef9 100644 --- a/py/utils/example_images_processor.py +++ b/py/utils/example_images_processor.py @@ -1,7 +1,6 @@ import logging import os import re -import tempfile import random import string from aiohttp import web @@ -13,6 +12,14 @@ from ..utils.metadata_manager import MetadataManager logger = logging.getLogger(__name__) + +class ExampleImagesImportError(RuntimeError): + """Base error for example image import operations.""" + + +class ExampleImagesValidationError(ExampleImagesImportError): + """Raised when input validation fails.""" + class ExampleImagesProcessor: """Processes and manipulates example images""" @@ -299,90 +306,29 @@ class ExampleImagesProcessor: return False @staticmethod - async def import_images(request): - """ - Import local example images - - Accepts: - - multipart/form-data form with model_hash and files fields - or - - JSON request with model_hash and file_paths - - Returns: - - Success status and list of imported files - """ + async def import_images(model_hash: str, files_to_import: list[str]): + """Import local example images for a model.""" + + if not model_hash: + raise ExampleImagesValidationError('Missing model_hash parameter') + + if not files_to_import: + raise ExampleImagesValidationError('No files provided to import') + try: - model_hash = None - files_to_import = [] - temp_files_to_cleanup = [] - - # Check if it's a multipart form-data request (direct file upload) - if request.content_type and 'multipart/form-data' in request.content_type: - reader = await request.multipart() - - # First get model_hash - field = await reader.next() - if field.name == 'model_hash': - model_hash = await field.text() - - # Then process all files - while True: - field = await reader.next() - if field is None: - break - - if field.name == 'files': - # Create a temporary file with appropriate suffix for type detection - file_name = field.filename - file_ext = os.path.splitext(file_name)[1].lower() - - with tempfile.NamedTemporaryFile(suffix=file_ext, delete=False) as tmp_file: - temp_path = tmp_file.name - temp_files_to_cleanup.append(temp_path) # Track for cleanup - - # Write chunks to the temporary file - while True: - chunk = await field.read_chunk() - if not chunk: - break - tmp_file.write(chunk) - - # Add to the list of files to process - files_to_import.append(temp_path) - else: - # Parse JSON request (legacy method using file paths) - data = await request.json() - model_hash = data.get('model_hash') - files_to_import = data.get('file_paths', []) - - if not model_hash: - return web.json_response({ - 'success': False, - 'error': 'Missing model_hash parameter' - }, status=400) - - if not files_to_import: - return web.json_response({ - 'success': False, - 'error': 'No files provided to import' - }, status=400) - # Get example images path example_images_path = settings.get('example_images_path') if not example_images_path: - return web.json_response({ - 'success': False, - 'error': 'No example images path configured' - }, status=400) - + raise ExampleImagesValidationError('No example images path configured') + # Find the model and get current metadata lora_scanner = await ServiceRegistry.get_lora_scanner() checkpoint_scanner = await ServiceRegistry.get_checkpoint_scanner() embedding_scanner = await ServiceRegistry.get_embedding_scanner() - + model_data = None scanner = None - + # Check both scanners to find the model for scan_obj in [lora_scanner, checkpoint_scanner, embedding_scanner]: cache = await scan_obj.get_cached_data() @@ -393,21 +339,20 @@ class ExampleImagesProcessor: break if model_data: break - + if not model_data: - return web.json_response({ - 'success': False, - 'error': f"Model with hash {model_hash} not found in cache" - }, status=404) - + raise ExampleImagesImportError( + f"Model with hash {model_hash} not found in cache" + ) + # Create model folder model_folder = os.path.join(example_images_path, model_hash) os.makedirs(model_folder, exist_ok=True) - + imported_files = [] errors = [] newly_imported_paths = [] - + # Process each file path for file_path in files_to_import: try: @@ -415,26 +360,26 @@ class ExampleImagesProcessor: if not os.path.isfile(file_path): errors.append(f"File not found: {file_path}") continue - + # Check if file type is supported file_ext = os.path.splitext(file_path)[1].lower() - if not (file_ext in SUPPORTED_MEDIA_EXTENSIONS['images'] or + if not (file_ext in SUPPORTED_MEDIA_EXTENSIONS['images'] or file_ext in SUPPORTED_MEDIA_EXTENSIONS['videos']): errors.append(f"Unsupported file type: {file_path}") continue - + # Generate new filename using short ID instead of UUID short_id = ExampleImagesProcessor.generate_short_id() new_filename = f"custom_{short_id}{file_ext}" - + dest_path = os.path.join(model_folder, new_filename) - + # Copy the file import shutil shutil.copy2(file_path, dest_path) # Store both the dest_path and the short_id newly_imported_paths.append((dest_path, short_id)) - + # Add to imported files list imported_files.append({ 'name': new_filename, @@ -444,39 +389,31 @@ class ExampleImagesProcessor: }) except Exception as e: errors.append(f"Error importing {file_path}: {str(e)}") - + # Update metadata with new example images regular_images, custom_images = await MetadataUpdater.update_metadata_after_import( - model_hash, + model_hash, model_data, scanner, newly_imported_paths ) - - return web.json_response({ + + return { 'success': len(imported_files) > 0, - 'message': f'Successfully imported {len(imported_files)} files' + + 'message': f'Successfully imported {len(imported_files)} files' + (f' with {len(errors)} errors' if errors else ''), 'files': imported_files, 'errors': errors, 'regular_images': regular_images, 'custom_images': custom_images, "model_file_path": model_data.get('file_path', ''), - }) - + } + + except ExampleImagesImportError: + raise except Exception as e: logger.error(f"Failed to import example images: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - finally: - # Clean up temporary files - for temp_file in temp_files_to_cleanup: - try: - os.remove(temp_file) - except Exception as e: - logger.error(f"Failed to remove temporary file {temp_file}: {e}") + raise ExampleImagesImportError(str(e)) from e @staticmethod async def delete_custom_image(request): diff --git a/tests/routes/test_example_images_routes.py b/tests/routes/test_example_images_routes.py index b9806dae..e921e744 100644 --- a/tests/routes/test_example_images_routes.py +++ b/tests/routes/test_example_images_routes.py @@ -1,5 +1,6 @@ from __future__ import annotations +import json from contextlib import asynccontextmanager from dataclasses import dataclass from typing import Any, List, Tuple @@ -33,37 +34,35 @@ class StubDownloadManager: def __init__(self) -> None: self.calls: List[Tuple[str, Any]] = [] - async def start_download(self, request: web.Request) -> web.StreamResponse: - payload = await request.json() + async def start_download(self, payload: Any) -> dict: self.calls.append(("start_download", payload)) - return web.json_response({"operation": "start_download", "payload": payload}) + return {"operation": "start_download", "payload": payload} - async def get_status(self, request: web.Request) -> web.StreamResponse: + async def get_status(self, request: web.Request) -> dict: self.calls.append(("get_status", dict(request.query))) - return web.json_response({"operation": "get_status"}) + return {"operation": "get_status"} - async def pause_download(self, request: web.Request) -> web.StreamResponse: + async def pause_download(self, request: web.Request) -> dict: self.calls.append(("pause_download", None)) - return web.json_response({"operation": "pause_download"}) + return {"operation": "pause_download"} - async def resume_download(self, request: web.Request) -> web.StreamResponse: + async def resume_download(self, request: web.Request) -> dict: self.calls.append(("resume_download", None)) - return web.json_response({"operation": "resume_download"}) + return {"operation": "resume_download"} - async def start_force_download(self, request: web.Request) -> web.StreamResponse: - payload = await request.json() + async def start_force_download(self, payload: Any) -> dict: self.calls.append(("start_force_download", payload)) - return web.json_response({"operation": "start_force_download", "payload": payload}) + return {"operation": "start_force_download", "payload": payload} class StubExampleImagesProcessor: def __init__(self) -> None: self.calls: List[Tuple[str, Any]] = [] - async def import_images(self, request: web.Request) -> web.StreamResponse: - payload = await request.json() + async def import_images(self, model_hash: str, files: List[str]) -> dict: + payload = {"model_hash": model_hash, "file_paths": files} self.calls.append(("import_images", payload)) - return web.json_response({"operation": "import_images", "payload": payload}) + return {"operation": "import_images", "payload": payload} async def delete_custom_image(self, request: web.Request) -> web.StreamResponse: payload = await request.json() @@ -184,7 +183,7 @@ async def test_pause_and_resume_routes_delegate(): async def test_import_route_delegates_to_processor(): - payload = {"model_hash": "abc123", "files": ["/path/image.png"]} + payload = {"model_hash": "abc123", "file_paths": ["/path/image.png"]} async with example_images_app() as harness: response = await harness.client.post( "/api/lm/import-example-images", json=payload @@ -193,7 +192,8 @@ async def test_import_route_delegates_to_processor(): assert response.status == 200 assert body == {"operation": "import_images", "payload": payload} - assert harness.processor.calls == [("import_images", payload)] + expected_call = ("import_images", payload) + assert expected_call in harness.processor.calls async def test_delete_route_delegates_to_processor(): @@ -251,70 +251,91 @@ async def test_download_handler_methods_delegate() -> None: def __init__(self) -> None: self.calls: List[Tuple[str, Any]] = [] - async def start_download(self, request) -> str: - self.calls.append(("start_download", request)) - return "download" - - async def get_status(self, request) -> str: + async def get_status(self, request) -> dict: self.calls.append(("get_status", request)) - return "status" + return {"status": "ok"} - async def pause_download(self, request) -> str: + async def pause_download(self, request) -> dict: self.calls.append(("pause_download", request)) - return "pause" + return {"status": "paused"} - async def resume_download(self, request) -> str: + async def resume_download(self, request) -> dict: self.calls.append(("resume_download", request)) - return "resume" + return {"status": "running"} - async def start_force_download(self, request) -> str: - self.calls.append(("start_force_download", request)) - return "force" + async def start_force_download(self, payload) -> dict: + self.calls.append(("start_force_download", payload)) + return {"status": "force", "payload": payload} + + class StubDownloadUseCase: + def __init__(self) -> None: + self.payloads: List[Any] = [] + + async def execute(self, payload: dict) -> dict: + self.payloads.append(payload) + return {"status": "started", "payload": payload} + + class DummyRequest: + def __init__(self, payload: dict) -> None: + self._payload = payload + self.query = {} + + async def json(self) -> dict: + return self._payload recorder = Recorder() - handler = ExampleImagesDownloadHandler(recorder) - request = object() + use_case = StubDownloadUseCase() + handler = ExampleImagesDownloadHandler(use_case, recorder) + request = DummyRequest({"foo": "bar"}) - assert await handler.download_example_images(request) == "download" - assert await handler.get_example_images_status(request) == "status" - assert await handler.pause_example_images(request) == "pause" - assert await handler.resume_example_images(request) == "resume" - assert await handler.force_download_example_images(request) == "force" + download_response = await handler.download_example_images(request) + assert json.loads(download_response.text) == {"status": "started", "payload": {"foo": "bar"}} + status_response = await handler.get_example_images_status(request) + assert json.loads(status_response.text) == {"status": "ok"} + pause_response = await handler.pause_example_images(request) + assert json.loads(pause_response.text) == {"status": "paused"} + resume_response = await handler.resume_example_images(request) + assert json.loads(resume_response.text) == {"status": "running"} + force_response = await handler.force_download_example_images(request) + assert json.loads(force_response.text) == {"status": "force", "payload": {"foo": "bar"}} - expected = [ - ("start_download", request), + assert use_case.payloads == [{"foo": "bar"}] + assert recorder.calls == [ ("get_status", request), ("pause_download", request), ("resume_download", request), - ("start_force_download", request), + ("start_force_download", {"foo": "bar"}), ] - assert recorder.calls == expected @pytest.mark.asyncio async def test_management_handler_methods_delegate() -> None: + class StubImportUseCase: + def __init__(self) -> None: + self.requests: List[Any] = [] + + async def execute(self, request: Any) -> dict: + self.requests.append(request) + return {"status": "imported"} + class Recorder: def __init__(self) -> None: self.calls: List[Tuple[str, Any]] = [] - async def import_images(self, request) -> str: - self.calls.append(("import_images", request)) - return "import" - async def delete_custom_image(self, request) -> str: self.calls.append(("delete_custom_image", request)) return "delete" recorder = Recorder() - handler = ExampleImagesManagementHandler(recorder) + use_case = StubImportUseCase() + handler = ExampleImagesManagementHandler(use_case, recorder) request = object() - assert await handler.import_example_images(request) == "import" + import_response = await handler.import_example_images(request) + assert json.loads(import_response.text) == {"status": "imported"} assert await handler.delete_example_image(request) == "delete" - assert recorder.calls == [ - ("import_images", request), - ("delete_custom_image", request), - ] + assert use_case.requests == [request] + assert recorder.calls == [("delete_custom_image", request)] @pytest.mark.asyncio @@ -350,8 +371,29 @@ async def test_file_handler_methods_delegate() -> None: def test_handler_set_route_mapping_includes_all_handlers() -> None: - download = ExampleImagesDownloadHandler(object()) - management = ExampleImagesManagementHandler(object()) + class DummyUseCase: + async def execute(self, payload): + return payload + + class DummyManager: + async def get_status(self, request): + return {} + + async def pause_download(self, request): + return {} + + async def resume_download(self, request): + return {} + + async def start_force_download(self, payload): + return payload + + class DummyProcessor: + async def delete_custom_image(self, request): + return {} + + download = ExampleImagesDownloadHandler(DummyUseCase(), DummyManager()) + management = ExampleImagesManagementHandler(DummyUseCase(), DummyProcessor()) files = ExampleImagesFileHandler(object()) handler_set = ExampleImagesHandlerSet( download=download, diff --git a/tests/services/test_use_cases.py b/tests/services/test_use_cases.py index 64057fc6..cfd0f10c 100644 --- a/tests/services/test_use_cases.py +++ b/tests/services/test_use_cases.py @@ -10,9 +10,23 @@ from py_local.services.use_cases import ( AutoOrganizeInProgressError, AutoOrganizeUseCase, BulkMetadataRefreshUseCase, + DownloadExampleImagesConfigurationError, + DownloadExampleImagesInProgressError, + DownloadExampleImagesUseCase, DownloadModelEarlyAccessError, DownloadModelUseCase, DownloadModelValidationError, + ImportExampleImagesUseCase, + ImportExampleImagesValidationError, +) +from py_local.utils.example_images_download_manager import ( + DownloadConfigurationError, + DownloadInProgressError, + ExampleImagesDownloadError, +) +from py_local.utils.example_images_processor import ( + ExampleImagesImportError, + ExampleImagesValidationError, ) from tests.conftest import MockModelService, MockScanner @@ -88,6 +102,38 @@ class StubDownloadCoordinator: return {"success": True, "download_id": "abc123"} +class StubExampleImagesDownloadManager: + def __init__(self) -> None: + self.payloads: List[Dict[str, Any]] = [] + self.error: Optional[str] = None + self.progress_snapshot = {"status": "running"} + + async def start_download(self, payload: Dict[str, Any]) -> Dict[str, Any]: + self.payloads.append(payload) + if self.error == "in_progress": + raise DownloadInProgressError(self.progress_snapshot) + if self.error == "configuration": + raise DownloadConfigurationError("path missing") + if self.error == "generic": + raise ExampleImagesDownloadError("boom") + return {"success": True, "message": "ok"} + + +class StubExampleImagesProcessor: + def __init__(self) -> None: + self.calls: List[Dict[str, Any]] = [] + self.error: Optional[str] = None + self.response: Dict[str, Any] = {"success": True} + + async def import_images(self, model_hash: str, files: List[str]) -> Dict[str, Any]: + self.calls.append({"model_hash": model_hash, "files": files}) + if self.error == "validation": + raise ExampleImagesValidationError("missing") + if self.error == "generic": + raise ExampleImagesImportError("boom") + return self.response + + async def test_auto_organize_use_case_executes_with_lock() -> None: file_service = StubFileService() lock_provider = StubLockProvider() @@ -189,3 +235,83 @@ async def test_download_model_use_case_returns_result() -> None: assert result["success"] is True assert result["download_id"] == "abc123" + + +async def test_download_example_images_use_case_triggers_manager() -> None: + manager = StubExampleImagesDownloadManager() + use_case = DownloadExampleImagesUseCase(download_manager=manager) + + payload = {"optimize": True} + result = await use_case.execute(payload) + + assert manager.payloads == [payload] + assert result == {"success": True, "message": "ok"} + + +async def test_download_example_images_use_case_maps_in_progress() -> None: + manager = StubExampleImagesDownloadManager() + manager.error = "in_progress" + use_case = DownloadExampleImagesUseCase(download_manager=manager) + + with pytest.raises(DownloadExampleImagesInProgressError) as exc: + await use_case.execute({}) + + assert exc.value.progress == manager.progress_snapshot + + +async def test_download_example_images_use_case_maps_configuration() -> None: + manager = StubExampleImagesDownloadManager() + manager.error = "configuration" + use_case = DownloadExampleImagesUseCase(download_manager=manager) + + with pytest.raises(DownloadExampleImagesConfigurationError): + await use_case.execute({}) + + +async def test_download_example_images_use_case_propagates_generic_error() -> None: + manager = StubExampleImagesDownloadManager() + manager.error = "generic" + use_case = DownloadExampleImagesUseCase(download_manager=manager) + + with pytest.raises(ExampleImagesDownloadError): + await use_case.execute({}) + + +class DummyJsonRequest: + def __init__(self, payload: Dict[str, Any]) -> None: + self._payload = payload + self.content_type = "application/json" + + async def json(self) -> Dict[str, Any]: + return self._payload + + +async def test_import_example_images_use_case_delegates() -> None: + processor = StubExampleImagesProcessor() + use_case = ImportExampleImagesUseCase(processor=processor) + + request = DummyJsonRequest({"model_hash": "abc", "file_paths": ["/tmp/file"]}) + result = await use_case.execute(request) + + assert processor.calls == [{"model_hash": "abc", "files": ["/tmp/file"]}] + assert result == {"success": True} + + +async def test_import_example_images_use_case_maps_validation_error() -> None: + processor = StubExampleImagesProcessor() + processor.error = "validation" + use_case = ImportExampleImagesUseCase(processor=processor) + request = DummyJsonRequest({"model_hash": None, "file_paths": []}) + + with pytest.raises(ImportExampleImagesValidationError): + await use_case.execute(request) + + +async def test_import_example_images_use_case_propagates_generic_error() -> None: + processor = StubExampleImagesProcessor() + processor.error = "generic" + use_case = ImportExampleImagesUseCase(processor=processor) + request = DummyJsonRequest({"model_hash": "abc", "file_paths": ["/tmp/file"]}) + + with pytest.raises(ExampleImagesImportError): + await use_case.execute(request) From 679cfb5c69d6e83e263b8b87fc5a0fe5f294d80a Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Tue, 23 Sep 2025 13:07:11 +0800 Subject: [PATCH 073/110] refactor(example-images): encapsulate download manager state --- py/routes/example_images_routes.py | 9 +- py/utils/example_images_download_manager.py | 465 +++++++++----------- py/utils/example_images_metadata.py | 14 +- 3 files changed, 225 insertions(+), 263 deletions(-) diff --git a/py/routes/example_images_routes.py b/py/routes/example_images_routes.py index 44effa3b..d5d34218 100644 --- a/py/routes/example_images_routes.py +++ b/py/routes/example_images_routes.py @@ -16,7 +16,10 @@ from ..services.use_cases.example_images import ( DownloadExampleImagesUseCase, ImportExampleImagesUseCase, ) -from ..utils.example_images_download_manager import DownloadManager +from ..utils.example_images_download_manager import ( + DownloadManager, + get_default_download_manager, +) from ..utils.example_images_file_manager import ExampleImagesFileManager from ..utils.example_images_processor import ExampleImagesProcessor @@ -29,11 +32,11 @@ class ExampleImagesRoutes: def __init__( self, *, - download_manager=DownloadManager, + download_manager: DownloadManager | None = None, processor=ExampleImagesProcessor, file_manager=ExampleImagesFileManager, ) -> None: - self._download_manager = download_manager + self._download_manager = download_manager or get_default_download_manager() self._processor = processor self._file_manager = file_manager self._handler_set: ExampleImagesHandlerSet | None = None diff --git a/py/utils/example_images_download_manager.py b/py/utils/example_images_download_manager.py index 7df0c6fb..e538f50a 100644 --- a/py/utils/example_images_download_manager.py +++ b/py/utils/example_images_download_manager.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import logging import os import asyncio @@ -37,165 +39,150 @@ class DownloadConfigurationError(ExampleImagesDownloadError): logger = logging.getLogger(__name__) -# Download status tracking -download_task = None -is_downloading = False -download_progress = { - 'total': 0, - 'completed': 0, - 'current_model': '', - 'status': 'idle', # idle, running, paused, completed, error - 'errors': [], - 'last_error': None, - 'start_time': None, - 'end_time': None, - 'processed_models': set(), # Track models that have been processed - 'refreshed_models': set(), # Track models that had metadata refreshed - 'failed_models': set() # Track models that failed to download after metadata refresh -} +class _DownloadProgress(dict): + """Mutable mapping maintaining download progress with set-aware serialisation.""" -def _serialize_progress() -> dict: - """Return a JSON-serialisable snapshot of the current progress.""" + def __init__(self) -> None: + super().__init__() + self.reset() - snapshot = download_progress.copy() - snapshot['processed_models'] = list(download_progress['processed_models']) - snapshot['refreshed_models'] = list(download_progress['refreshed_models']) - snapshot['failed_models'] = list(download_progress['failed_models']) - return snapshot + def reset(self) -> None: + """Reset the progress dictionary to its initial state.""" + + self.update( + total=0, + completed=0, + current_model='', + status='idle', + errors=[], + last_error=None, + start_time=None, + end_time=None, + processed_models=set(), + refreshed_models=set(), + failed_models=set(), + ) + + def snapshot(self) -> dict: + """Return a JSON-serialisable snapshot of the current progress.""" + + snapshot = dict(self) + snapshot['processed_models'] = list(self['processed_models']) + snapshot['refreshed_models'] = list(self['refreshed_models']) + snapshot['failed_models'] = list(self['failed_models']) + return snapshot class DownloadManager: - """Manages downloading example images for models""" - - @staticmethod - async def start_download(options: dict): - """ - Start downloading example images for models - - Expects a JSON body with: - { - "optimize": true, # Whether to optimize images (default: true) - "model_types": ["lora", "checkpoint"], # Model types to process (default: both) - "delay": 1.0, # Delay between downloads to avoid rate limiting (default: 1.0) - "auto_mode": false # Flag to indicate automatic download (default: false) - } - """ - global download_task, is_downloading, download_progress - - if is_downloading: - raise DownloadInProgressError(_serialize_progress()) + """Manages downloading example images for models.""" + + def __init__(self) -> None: + self._download_task: asyncio.Task | None = None + self._is_downloading = False + self._progress = _DownloadProgress() + + async def start_download(self, options: dict): + """Start downloading example images for models.""" + + if self._is_downloading: + raise DownloadInProgressError(self._progress.snapshot()) try: data = options or {} auto_mode = data.get('auto_mode', False) optimize = data.get('optimize', True) model_types = data.get('model_types', ['lora', 'checkpoint']) - delay = float(data.get('delay', 0.2)) # Default to 0.2 seconds - - # Get output directory from settings + delay = float(data.get('delay', 0.2)) + output_dir = settings.get('example_images_path') if not output_dir: error_msg = 'Example images path not configured in settings' if auto_mode: - # For auto mode, just log and return success to avoid showing error toasts logger.debug(error_msg) return { 'success': True, 'message': 'Example images path not configured, skipping auto download' } raise DownloadConfigurationError(error_msg) - - # Create the output directory + os.makedirs(output_dir, exist_ok=True) - - # Initialize progress tracking - download_progress['total'] = 0 - download_progress['completed'] = 0 - download_progress['current_model'] = '' - download_progress['status'] = 'running' - download_progress['errors'] = [] - download_progress['last_error'] = None - download_progress['start_time'] = time.time() - download_progress['end_time'] = None - - # Get the processed models list from a file if it exists + + self._progress.reset() + self._progress['status'] = 'running' + self._progress['start_time'] = time.time() + self._progress['end_time'] = None + progress_file = os.path.join(output_dir, '.download_progress.json') if os.path.exists(progress_file): try: with open(progress_file, 'r', encoding='utf-8') as f: saved_progress = json.load(f) - download_progress['processed_models'] = set(saved_progress.get('processed_models', [])) - download_progress['failed_models'] = set(saved_progress.get('failed_models', [])) - logger.debug(f"Loaded previous progress, {len(download_progress['processed_models'])} models already processed, {len(download_progress['failed_models'])} models marked as failed") + self._progress['processed_models'] = set(saved_progress.get('processed_models', [])) + self._progress['failed_models'] = set(saved_progress.get('failed_models', [])) + logger.debug( + "Loaded previous progress, %s models already processed, %s models marked as failed", + len(self._progress['processed_models']), + len(self._progress['failed_models']), + ) except Exception as e: logger.error(f"Failed to load progress file: {e}") - download_progress['processed_models'] = set() - download_progress['failed_models'] = set() + self._progress['processed_models'] = set() + self._progress['failed_models'] = set() else: - download_progress['processed_models'] = set() - download_progress['failed_models'] = set() - - # Start the download task - is_downloading = True - download_task = asyncio.create_task( - DownloadManager._download_all_example_images( - output_dir, - optimize, + self._progress['processed_models'] = set() + self._progress['failed_models'] = set() + + self._is_downloading = True + self._download_task = asyncio.create_task( + self._download_all_example_images( + output_dir, + optimize, model_types, delay ) ) - + return { 'success': True, 'message': 'Download started', - 'status': _serialize_progress() + 'status': self._progress.snapshot() } except Exception as e: logger.error(f"Failed to start example images download: {e}", exc_info=True) raise ExampleImagesDownloadError(str(e)) from e - @staticmethod - async def get_status(request): - """Get the current status of example images download""" - global download_progress - - # Create a copy of the progress dict with the set converted to a list for JSON serialization - response_progress = _serialize_progress() + async def get_status(self, request): + """Get the current status of example images download.""" return { 'success': True, - 'is_downloading': is_downloading, - 'status': response_progress + 'is_downloading': self._is_downloading, + 'status': self._progress.snapshot(), } - @staticmethod - async def pause_download(request): - """Pause the example images download""" - global download_progress - - if not is_downloading: + async def pause_download(self, request): + """Pause the example images download.""" + + if not self._is_downloading: raise DownloadNotRunningError() - download_progress['status'] = 'paused' + self._progress['status'] = 'paused' return { 'success': True, 'message': 'Download paused' } - @staticmethod - async def resume_download(request): - """Resume the example images download""" - global download_progress - - if not is_downloading: + async def resume_download(self, request): + """Resume the example images download.""" + + if not self._is_downloading: raise DownloadNotRunningError() - if download_progress['status'] == 'paused': - download_progress['status'] = 'running' + if self._progress['status'] == 'paused': + self._progress['status'] = 'running' return { 'success': True, @@ -203,15 +190,12 @@ class DownloadManager: } raise DownloadNotRunningError( - f"Download is in '{download_progress['status']}' state, cannot resume" + f"Download is in '{self._progress['status']}' state, cannot resume" ) - @staticmethod - async def _download_all_example_images(output_dir, optimize, model_types, delay): - """Download example images for all models""" - global is_downloading, download_progress - - # Get unified downloader + async def _download_all_example_images(self, output_dir, optimize, model_types, delay): + """Download example images for all models.""" + downloader = await get_downloader() try: @@ -239,59 +223,58 @@ class DownloadManager: all_models.append((scanner_type, model, scanner)) # Update total count - download_progress['total'] = len(all_models) - logger.debug(f"Found {download_progress['total']} models to process") + self._progress['total'] = len(all_models) + logger.debug(f"Found {self._progress['total']} models to process") # Process each model for i, (scanner_type, model, scanner) in enumerate(all_models): # Main logic for processing model is here, but actual operations are delegated to other classes - was_remote_download = await DownloadManager._process_model( - scanner_type, model, scanner, + was_remote_download = await self._process_model( + scanner_type, model, scanner, output_dir, optimize, downloader ) # Update progress - download_progress['completed'] += 1 + self._progress['completed'] += 1 # Only add delay after remote download of models, and not after processing the last model - if was_remote_download and i < len(all_models) - 1 and download_progress['status'] == 'running': + if was_remote_download and i < len(all_models) - 1 and self._progress['status'] == 'running': await asyncio.sleep(delay) # Mark as completed - download_progress['status'] = 'completed' - download_progress['end_time'] = time.time() - logger.debug(f"Example images download completed: {download_progress['completed']}/{download_progress['total']} models processed") + self._progress['status'] = 'completed' + self._progress['end_time'] = time.time() + logger.debug(f"Example images download completed: {self._progress['completed']}/{self._progress['total']} models processed") except Exception as e: error_msg = f"Error during example images download: {str(e)}" logger.error(error_msg, exc_info=True) - download_progress['errors'].append(error_msg) - download_progress['last_error'] = error_msg - download_progress['status'] = 'error' - download_progress['end_time'] = time.time() + self._progress['errors'].append(error_msg) + self._progress['last_error'] = error_msg + self._progress['status'] = 'error' + self._progress['end_time'] = time.time() finally: # Save final progress to file try: - DownloadManager._save_progress(output_dir) + self._save_progress(output_dir) except Exception as e: logger.error(f"Failed to save progress file: {e}") - + # Set download status to not downloading - is_downloading = False + self._is_downloading = False + self._download_task = None - @staticmethod - async def _process_model(scanner_type, model, scanner, output_dir, optimize, downloader): - """Process a single model download""" - global download_progress - + async def _process_model(self, scanner_type, model, scanner, output_dir, optimize, downloader): + """Process a single model download.""" + # Check if download is paused - while download_progress['status'] == 'paused': + while self._progress['status'] == 'paused': await asyncio.sleep(1) - + # Check if download should continue - if download_progress['status'] != 'running': - logger.info(f"Download stopped: {download_progress['status']}") + if self._progress['status'] != 'running': + logger.info(f"Download stopped: {self._progress['status']}") return False # Return False to indicate no remote download happened model_hash = model.get('sha256', '').lower() @@ -301,15 +284,15 @@ class DownloadManager: try: # Update current model info - download_progress['current_model'] = f"{model_name} ({model_hash[:8]})" + self._progress['current_model'] = f"{model_name} ({model_hash[:8]})" # Skip if already in failed models - if model_hash in download_progress['failed_models']: + if model_hash in self._progress['failed_models']: logger.debug(f"Skipping known failed model: {model_name}") return False # Skip if already processed AND directory exists with files - if model_hash in download_progress['processed_models']: + if model_hash in self._progress['processed_models']: model_dir = os.path.join(output_dir, model_hash) has_files = os.path.exists(model_dir) and any(os.listdir(model_dir)) if has_files: @@ -318,7 +301,7 @@ class DownloadManager: else: logger.info(f"Model {model_name} marked as processed but folder empty or missing, reprocessing") # Remove from processed models since we need to reprocess - download_progress['processed_models'].discard(model_hash) + self._progress['processed_models'].discard(model_hash) # Create model directory model_dir = os.path.join(output_dir, model_hash) @@ -334,7 +317,7 @@ class DownloadManager: await MetadataUpdater.update_metadata_from_local_examples( model_hash, model, scanner_type, scanner, model_dir ) - download_progress['processed_models'].add(model_hash) + self._progress['processed_models'].add(model_hash) return False # Return False to indicate no remote download happened # If no local images, try to download from remote @@ -346,57 +329,55 @@ class DownloadManager: ) # If metadata is stale, try to refresh it - if is_stale and model_hash not in download_progress['refreshed_models']: + if is_stale and model_hash not in self._progress['refreshed_models']: await MetadataUpdater.refresh_model_metadata( - model_hash, model_name, scanner_type, scanner + model_hash, model_name, scanner_type, scanner, self._progress ) - + # Get the updated model data updated_model = await MetadataUpdater.get_updated_model( model_hash, scanner ) - + if updated_model and updated_model.get('civitai', {}).get('images'): # Retry download with updated metadata updated_images = updated_model.get('civitai', {}).get('images', []) success, _ = await ExampleImagesProcessor.download_model_images( model_hash, model_name, updated_images, model_dir, optimize, downloader ) - - download_progress['refreshed_models'].add(model_hash) + + self._progress['refreshed_models'].add(model_hash) # Mark as processed if successful, or as failed if unsuccessful after refresh if success: - download_progress['processed_models'].add(model_hash) + self._progress['processed_models'].add(model_hash) else: # If we refreshed metadata and still failed, mark as permanently failed - if model_hash in download_progress['refreshed_models']: - download_progress['failed_models'].add(model_hash) + if model_hash in self._progress['refreshed_models']: + self._progress['failed_models'].add(model_hash) logger.info(f"Marking model {model_name} as failed after metadata refresh") return True # Return True to indicate a remote download happened else: # No civitai data or images available, mark as failed to avoid future attempts - download_progress['failed_models'].add(model_hash) + self._progress['failed_models'].add(model_hash) logger.debug(f"No civitai images available for model {model_name}, marking as failed") # Save progress periodically - if download_progress['completed'] % 10 == 0 or download_progress['completed'] == download_progress['total'] - 1: - DownloadManager._save_progress(output_dir) + if self._progress['completed'] % 10 == 0 or self._progress['completed'] == self._progress['total'] - 1: + self._save_progress(output_dir) return False # Default return if no conditions met except Exception as e: error_msg = f"Error processing model {model.get('model_name')}: {str(e)}" logger.error(error_msg, exc_info=True) - download_progress['errors'].append(error_msg) - download_progress['last_error'] = error_msg + self._progress['errors'].append(error_msg) + self._progress['last_error'] = error_msg return False # Return False on exception - @staticmethod - def _save_progress(output_dir): - """Save download progress to file""" - global download_progress + def _save_progress(self, output_dir): + """Save download progress to file.""" try: progress_file = os.path.join(output_dir, '.download_progress.json') @@ -411,11 +392,11 @@ class DownloadManager: # Create new progress data progress_data = { - 'processed_models': list(download_progress['processed_models']), - 'refreshed_models': list(download_progress['refreshed_models']), - 'failed_models': list(download_progress['failed_models']), - 'completed': download_progress['completed'], - 'total': download_progress['total'], + 'processed_models': list(self._progress['processed_models']), + 'refreshed_models': list(self._progress['refreshed_models']), + 'failed_models': list(self._progress['failed_models']), + 'completed': self._progress['completed'], + 'total': self._progress['total'], 'last_update': time.time() } @@ -430,70 +411,46 @@ class DownloadManager: except Exception as e: logger.error(f"Failed to save progress file: {e}") - @staticmethod - async def start_force_download(options: dict): - """ - Force download example images for specific models - - Expects a JSON body with: - { - "model_hashes": ["hash1", "hash2", ...], # List of model hashes to download - "optimize": true, # Whether to optimize images (default: true) - "model_types": ["lora", "checkpoint"], # Model types to process (default: both) - "delay": 1.0 # Delay between downloads (default: 1.0) - } - """ - global download_task, is_downloading, download_progress + async def start_force_download(self, options: dict): + """Force download example images for specific models.""" - if is_downloading: - raise DownloadInProgressError(_serialize_progress()) + if self._is_downloading: + raise DownloadInProgressError(self._progress.snapshot()) try: data = options or {} model_hashes = data.get('model_hashes', []) optimize = data.get('optimize', True) model_types = data.get('model_types', ['lora', 'checkpoint']) - delay = float(data.get('delay', 0.2)) # Default to 0.2 seconds + delay = float(data.get('delay', 0.2)) if not model_hashes: raise DownloadConfigurationError('Missing model_hashes parameter') - # Get output directory from settings output_dir = settings.get('example_images_path') if not output_dir: raise DownloadConfigurationError('Example images path not configured in settings') - - # Create the output directory + os.makedirs(output_dir, exist_ok=True) - - # Initialize progress tracking - download_progress['total'] = len(model_hashes) - download_progress['completed'] = 0 - download_progress['current_model'] = '' - download_progress['status'] = 'running' - download_progress['errors'] = [] - download_progress['last_error'] = None - download_progress['start_time'] = time.time() - download_progress['end_time'] = None - download_progress['processed_models'] = set() - download_progress['refreshed_models'] = set() - download_progress['failed_models'] = set() - # Set download status to downloading - is_downloading = True + self._progress.reset() + self._progress['total'] = len(model_hashes) + self._progress['status'] = 'running' + self._progress['start_time'] = time.time() + self._progress['end_time'] = None - # Execute the download function directly instead of creating a background task - result = await DownloadManager._download_specific_models_example_images_sync( + self._is_downloading = True + + result = await self._download_specific_models_example_images_sync( model_hashes, - output_dir, - optimize, + output_dir, + optimize, model_types, delay ) - # Set download status to not downloading - is_downloading = False + self._is_downloading = False return { 'success': True, @@ -502,17 +459,13 @@ class DownloadManager: } except Exception as e: - # Set download status to not downloading - is_downloading = False + self._is_downloading = False logger.error(f"Failed during forced example images download: {e}", exc_info=True) raise ExampleImagesDownloadError(str(e)) from e - @staticmethod - async def _download_specific_models_example_images_sync(model_hashes, output_dir, optimize, model_types, delay): - """Download example images for specific models only - synchronous version""" - global download_progress - - # Get unified downloader + async def _download_specific_models_example_images_sync(self, model_hashes, output_dir, optimize, model_types, delay): + """Download example images for specific models only - synchronous version.""" + downloader = await get_downloader() try: @@ -540,14 +493,14 @@ class DownloadManager: models_to_process.append((scanner_type, model, scanner)) # Update total count based on found models - download_progress['total'] = len(models_to_process) - logger.debug(f"Found {download_progress['total']} models to process") + self._progress['total'] = len(models_to_process) + logger.debug(f"Found {self._progress['total']} models to process") # Send initial progress via WebSocket await ws_manager.broadcast({ 'type': 'example_images_progress', 'processed': 0, - 'total': download_progress['total'], + 'total': self._progress['total'], 'status': 'running', 'current_model': '' }) @@ -556,8 +509,8 @@ class DownloadManager: success_count = 0 for i, (scanner_type, model, scanner) in enumerate(models_to_process): # Force process this model regardless of previous status - was_successful = await DownloadManager._process_specific_model( - scanner_type, model, scanner, + was_successful = await self._process_specific_model( + scanner_type, model, scanner, output_dir, optimize, downloader ) @@ -565,55 +518,55 @@ class DownloadManager: success_count += 1 # Update progress - download_progress['completed'] += 1 + self._progress['completed'] += 1 # Send progress update via WebSocket await ws_manager.broadcast({ 'type': 'example_images_progress', - 'processed': download_progress['completed'], - 'total': download_progress['total'], + 'processed': self._progress['completed'], + 'total': self._progress['total'], 'status': 'running', - 'current_model': download_progress['current_model'] + 'current_model': self._progress['current_model'] }) # Only add delay after remote download, and not after processing the last model - if was_successful and i < len(models_to_process) - 1 and download_progress['status'] == 'running': + if was_successful and i < len(models_to_process) - 1 and self._progress['status'] == 'running': await asyncio.sleep(delay) # Mark as completed - download_progress['status'] = 'completed' - download_progress['end_time'] = time.time() - logger.debug(f"Forced example images download completed: {download_progress['completed']}/{download_progress['total']} models processed") + self._progress['status'] = 'completed' + self._progress['end_time'] = time.time() + logger.debug(f"Forced example images download completed: {self._progress['completed']}/{self._progress['total']} models processed") # Send final progress via WebSocket await ws_manager.broadcast({ 'type': 'example_images_progress', - 'processed': download_progress['completed'], - 'total': download_progress['total'], + 'processed': self._progress['completed'], + 'total': self._progress['total'], 'status': 'completed', 'current_model': '' }) return { - 'total': download_progress['total'], - 'processed': download_progress['completed'], + 'total': self._progress['total'], + 'processed': self._progress['completed'], 'successful': success_count, - 'errors': download_progress['errors'] + 'errors': self._progress['errors'] } except Exception as e: error_msg = f"Error during forced example images download: {str(e)}" logger.error(error_msg, exc_info=True) - download_progress['errors'].append(error_msg) - download_progress['last_error'] = error_msg - download_progress['status'] = 'error' - download_progress['end_time'] = time.time() + self._progress['errors'].append(error_msg) + self._progress['last_error'] = error_msg + self._progress['status'] = 'error' + self._progress['end_time'] = time.time() # Send error status via WebSocket await ws_manager.broadcast({ 'type': 'example_images_progress', - 'processed': download_progress['completed'], - 'total': download_progress['total'], + 'processed': self._progress['completed'], + 'total': self._progress['total'], 'status': 'error', 'error': error_msg, 'current_model': '' @@ -625,18 +578,16 @@ class DownloadManager: # No need to close any sessions since we use the global downloader pass - @staticmethod - async def _process_specific_model(scanner_type, model, scanner, output_dir, optimize, downloader): - """Process a specific model for forced download, ignoring previous download status""" - global download_progress - + async def _process_specific_model(self, scanner_type, model, scanner, output_dir, optimize, downloader): + """Process a specific model for forced download, ignoring previous download status.""" + # Check if download is paused - while download_progress['status'] == 'paused': + while self._progress['status'] == 'paused': await asyncio.sleep(1) # Check if download should continue - if download_progress['status'] != 'running': - logger.info(f"Download stopped: {download_progress['status']}") + if self._progress['status'] != 'running': + logger.info(f"Download stopped: {self._progress['status']}") return False model_hash = model.get('sha256', '').lower() @@ -646,7 +597,7 @@ class DownloadManager: try: # Update current model info - download_progress['current_model'] = f"{model_name} ({model_hash[:8]})" + self._progress['current_model'] = f"{model_name} ({model_hash[:8]})" # Create model directory model_dir = os.path.join(output_dir, model_hash) @@ -662,7 +613,7 @@ class DownloadManager: await MetadataUpdater.update_metadata_from_local_examples( model_hash, model, scanner_type, scanner, model_dir ) - download_progress['processed_models'].add(model_hash) + self._progress['processed_models'].add(model_hash) return False # Return False to indicate no remote download happened # If no local images, try to download from remote @@ -674,9 +625,9 @@ class DownloadManager: ) # If metadata is stale, try to refresh it - if is_stale and model_hash not in download_progress['refreshed_models']: + if is_stale and model_hash not in self._progress['refreshed_models']: await MetadataUpdater.refresh_model_metadata( - model_hash, model_name, scanner_type, scanner + model_hash, model_name, scanner_type, scanner, self._progress ) # Get the updated model data @@ -694,18 +645,18 @@ class DownloadManager: # Combine failed images from both attempts failed_images.extend(additional_failed_images) - download_progress['refreshed_models'].add(model_hash) + self._progress['refreshed_models'].add(model_hash) # For forced downloads, remove failed images from metadata if failed_images: # Create a copy of images excluding failed ones - await DownloadManager._remove_failed_images_from_metadata( + await self._remove_failed_images_from_metadata( model_hash, model_name, failed_images, scanner ) # Mark as processed if success or failed_images: # Mark as processed if we successfully downloaded some images or removed failed ones - download_progress['processed_models'].add(model_hash) + self._progress['processed_models'].add(model_hash) return True # Return True to indicate a remote download happened else: @@ -715,12 +666,11 @@ class DownloadManager: except Exception as e: error_msg = f"Error processing model {model.get('model_name')}: {str(e)}" logger.error(error_msg, exc_info=True) - download_progress['errors'].append(error_msg) - download_progress['last_error'] = error_msg + self._progress['errors'].append(error_msg) + self._progress['last_error'] = error_msg return False # Return False on exception - @staticmethod - async def _remove_failed_images_from_metadata(model_hash, model_name, failed_images, scanner): + async def _remove_failed_images_from_metadata(self, model_hash, model_name, failed_images, scanner): """Remove failed images from model metadata""" try: # Get current model data @@ -762,4 +712,13 @@ class DownloadManager: await scanner.update_single_model_cache(file_path, file_path, model_data) except Exception as e: - logger.error(f"Error removing failed images from metadata for {model_name}: {e}", exc_info=True) \ No newline at end of file + logger.error(f"Error removing failed images from metadata for {model_name}: {e}", exc_info=True) + + +default_download_manager = DownloadManager() + + +def get_default_download_manager() -> DownloadManager: + """Return the singleton download manager used by default routes.""" + + return default_download_manager diff --git a/py/utils/example_images_metadata.py b/py/utils/example_images_metadata.py index 8820b49b..780eb43b 100644 --- a/py/utils/example_images_metadata.py +++ b/py/utils/example_images_metadata.py @@ -33,7 +33,7 @@ class MetadataUpdater: """Handles updating model metadata related to example images""" @staticmethod - async def refresh_model_metadata(model_hash, model_name, scanner_type, scanner): + async def refresh_model_metadata(model_hash, model_name, scanner_type, scanner, progress: dict | None = None): """Refresh model metadata from CivitAI Args: @@ -45,8 +45,6 @@ class MetadataUpdater: Returns: bool: True if metadata was successfully refreshed, False otherwise """ - from ..utils.example_images_download_manager import download_progress - try: # Find the model in the scanner cache cache = await scanner.get_cached_data() @@ -67,7 +65,8 @@ class MetadataUpdater: return False # Track that we're refreshing this model - download_progress['refreshed_models'].add(model_hash) + if progress is not None: + progress['refreshed_models'].add(model_hash) async def update_cache_func(old_path, new_path, metadata): return await scanner.update_single_model_cache(old_path, new_path, metadata) @@ -85,12 +84,13 @@ class MetadataUpdater: else: logger.warning(f"Failed to refresh metadata for {model_name}, {error}") return False - + except Exception as e: error_msg = f"Error refreshing metadata for {model_name}: {str(e)}" logger.error(error_msg, exc_info=True) - download_progress['errors'].append(error_msg) - download_progress['last_error'] = error_msg + if progress is not None: + progress['errors'].append(error_msg) + progress['last_error'] = error_msg return False @staticmethod From 43fcce63613560b5877067b2c11ba54551b66515 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Tue, 23 Sep 2025 14:40:43 +0800 Subject: [PATCH 074/110] refactor(example-images): inject websocket manager --- py/lora_manager.py | 2 +- py/routes/example_images_routes.py | 9 +- py/utils/example_images_download_manager.py | 291 ++++++++++++-------- standalone.py | 2 +- tests/routes/test_example_images_routes.py | 12 +- 5 files changed, 191 insertions(+), 125 deletions(-) diff --git a/py/lora_manager.py b/py/lora_manager.py index 1a99d508..ed37f27d 100644 --- a/py/lora_manager.py +++ b/py/lora_manager.py @@ -166,7 +166,7 @@ class LoraManager: RecipeRoutes.setup_routes(app) UpdateRoutes.setup_routes(app) MiscRoutes.setup_routes(app) - ExampleImagesRoutes.setup_routes(app) + ExampleImagesRoutes.setup_routes(app, ws_manager=ws_manager) # Setup WebSocket routes that are shared across all model types app.router.add_get('/ws/fetch-progress', ws_manager.handle_connection) diff --git a/py/routes/example_images_routes.py b/py/routes/example_images_routes.py index d5d34218..5073410d 100644 --- a/py/routes/example_images_routes.py +++ b/py/routes/example_images_routes.py @@ -32,21 +32,24 @@ class ExampleImagesRoutes: def __init__( self, *, + ws_manager, download_manager: DownloadManager | None = None, processor=ExampleImagesProcessor, file_manager=ExampleImagesFileManager, ) -> None: - self._download_manager = download_manager or get_default_download_manager() + if ws_manager is None: + raise ValueError("ws_manager is required") + self._download_manager = download_manager or get_default_download_manager(ws_manager) self._processor = processor self._file_manager = file_manager self._handler_set: ExampleImagesHandlerSet | None = None self._handler_mapping: Mapping[str, Callable[[web.Request], web.StreamResponse]] | None = None @classmethod - def setup_routes(cls, app: web.Application) -> None: + def setup_routes(cls, app: web.Application, *, ws_manager) -> None: """Register routes on the given aiohttp application using default wiring.""" - controller = cls() + controller = cls(ws_manager=ws_manager) controller.register(app) def register(self, app: web.Application) -> None: diff --git a/py/utils/example_images_download_manager.py b/py/utils/example_images_download_manager.py index e538f50a..9ddf03a4 100644 --- a/py/utils/example_images_download_manager.py +++ b/py/utils/example_images_download_manager.py @@ -5,11 +5,12 @@ import os import asyncio import json import time +from typing import Any, Dict + from ..services.service_registry import ServiceRegistry from ..utils.metadata_manager import MetadataManager from .example_images_processor import ExampleImagesProcessor from .example_images_metadata import MetadataUpdater -from ..services.websocket_manager import ws_manager # Add this import at the top from ..services.downloader import get_downloader from ..services.settings_manager import settings @@ -76,82 +77,90 @@ class _DownloadProgress(dict): class DownloadManager: """Manages downloading example images for models.""" - def __init__(self) -> None: + def __init__(self, *, ws_manager, state_lock: asyncio.Lock | None = None) -> None: self._download_task: asyncio.Task | None = None self._is_downloading = False self._progress = _DownloadProgress() + self._ws_manager = ws_manager + self._state_lock = state_lock or asyncio.Lock() async def start_download(self, options: dict): """Start downloading example images for models.""" - if self._is_downloading: - raise DownloadInProgressError(self._progress.snapshot()) + async with self._state_lock: + if self._is_downloading: + raise DownloadInProgressError(self._progress.snapshot()) - try: - data = options or {} - auto_mode = data.get('auto_mode', False) - optimize = data.get('optimize', True) - model_types = data.get('model_types', ['lora', 'checkpoint']) - delay = float(data.get('delay', 0.2)) + try: + data = options or {} + auto_mode = data.get('auto_mode', False) + optimize = data.get('optimize', True) + model_types = data.get('model_types', ['lora', 'checkpoint']) + delay = float(data.get('delay', 0.2)) - output_dir = settings.get('example_images_path') + output_dir = settings.get('example_images_path') - if not output_dir: - error_msg = 'Example images path not configured in settings' - if auto_mode: - logger.debug(error_msg) - return { - 'success': True, - 'message': 'Example images path not configured, skipping auto download' - } - raise DownloadConfigurationError(error_msg) + if not output_dir: + error_msg = 'Example images path not configured in settings' + if auto_mode: + logger.debug(error_msg) + return { + 'success': True, + 'message': 'Example images path not configured, skipping auto download' + } + raise DownloadConfigurationError(error_msg) - os.makedirs(output_dir, exist_ok=True) + os.makedirs(output_dir, exist_ok=True) - self._progress.reset() - self._progress['status'] = 'running' - self._progress['start_time'] = time.time() - self._progress['end_time'] = None + self._progress.reset() + self._progress['status'] = 'running' + self._progress['start_time'] = time.time() + self._progress['end_time'] = None - progress_file = os.path.join(output_dir, '.download_progress.json') - if os.path.exists(progress_file): - try: - with open(progress_file, 'r', encoding='utf-8') as f: - saved_progress = json.load(f) - self._progress['processed_models'] = set(saved_progress.get('processed_models', [])) - self._progress['failed_models'] = set(saved_progress.get('failed_models', [])) - logger.debug( - "Loaded previous progress, %s models already processed, %s models marked as failed", - len(self._progress['processed_models']), - len(self._progress['failed_models']), - ) - except Exception as e: - logger.error(f"Failed to load progress file: {e}") + progress_file = os.path.join(output_dir, '.download_progress.json') + if os.path.exists(progress_file): + try: + with open(progress_file, 'r', encoding='utf-8') as f: + saved_progress = json.load(f) + self._progress['processed_models'] = set(saved_progress.get('processed_models', [])) + self._progress['failed_models'] = set(saved_progress.get('failed_models', [])) + logger.debug( + "Loaded previous progress, %s models already processed, %s models marked as failed", + len(self._progress['processed_models']), + len(self._progress['failed_models']), + ) + except Exception as e: + logger.error(f"Failed to load progress file: {e}") + self._progress['processed_models'] = set() + self._progress['failed_models'] = set() + else: self._progress['processed_models'] = set() self._progress['failed_models'] = set() - else: - self._progress['processed_models'] = set() - self._progress['failed_models'] = set() - self._is_downloading = True - self._download_task = asyncio.create_task( - self._download_all_example_images( - output_dir, - optimize, - model_types, - delay + self._is_downloading = True + self._download_task = asyncio.create_task( + self._download_all_example_images( + output_dir, + optimize, + model_types, + delay + ) ) - ) - return { - 'success': True, - 'message': 'Download started', - 'status': self._progress.snapshot() - } + snapshot = self._progress.snapshot() + except Exception as e: + self._is_downloading = False + self._download_task = None + logger.error(f"Failed to start example images download: {e}", exc_info=True) + raise ExampleImagesDownloadError(str(e)) from e - except Exception as e: - logger.error(f"Failed to start example images download: {e}", exc_info=True) - raise ExampleImagesDownloadError(str(e)) from e + await self._broadcast_progress(status='running') + + return { + 'success': True, + 'message': 'Download started', + 'status': snapshot + } async def get_status(self, request): """Get the current status of example images download.""" @@ -165,10 +174,13 @@ class DownloadManager: async def pause_download(self, request): """Pause the example images download.""" - if not self._is_downloading: - raise DownloadNotRunningError() + async with self._state_lock: + if not self._is_downloading: + raise DownloadNotRunningError() - self._progress['status'] = 'paused' + self._progress['status'] = 'paused' + + await self._broadcast_progress(status='paused') return { 'success': True, @@ -178,20 +190,23 @@ class DownloadManager: async def resume_download(self, request): """Resume the example images download.""" - if not self._is_downloading: - raise DownloadNotRunningError() + async with self._state_lock: + if not self._is_downloading: + raise DownloadNotRunningError() - if self._progress['status'] == 'paused': - self._progress['status'] = 'running' + if self._progress['status'] == 'paused': + self._progress['status'] = 'running' + else: + raise DownloadNotRunningError( + f"Download is in '{self._progress['status']}' state, cannot resume" + ) - return { - 'success': True, - 'message': 'Download resumed' - } + await self._broadcast_progress(status='running') - raise DownloadNotRunningError( - f"Download is in '{self._progress['status']}' state, cannot resume" - ) + return { + 'success': True, + 'message': 'Download resumed' + } async def _download_all_example_images(self, output_dir, optimize, model_types, delay): """Download example images for all models.""" @@ -225,6 +240,7 @@ class DownloadManager: # Update total count self._progress['total'] = len(all_models) logger.debug(f"Found {self._progress['total']} models to process") + await self._broadcast_progress(status='running') # Process each model for i, (scanner_type, model, scanner) in enumerate(all_models): @@ -236,6 +252,7 @@ class DownloadManager: # Update progress self._progress['completed'] += 1 + await self._broadcast_progress(status='running') # Only add delay after remote download of models, and not after processing the last model if was_remote_download and i < len(all_models) - 1 and self._progress['status'] == 'running': @@ -244,8 +261,13 @@ class DownloadManager: # Mark as completed self._progress['status'] = 'completed' self._progress['end_time'] = time.time() - logger.debug(f"Example images download completed: {self._progress['completed']}/{self._progress['total']} models processed") - + logger.debug( + "Example images download completed: %s/%s models processed", + self._progress['completed'], + self._progress['total'], + ) + await self._broadcast_progress(status='completed') + except Exception as e: error_msg = f"Error during example images download: {str(e)}" logger.error(error_msg, exc_info=True) @@ -253,7 +275,8 @@ class DownloadManager: self._progress['last_error'] = error_msg self._progress['status'] = 'error' self._progress['end_time'] = time.time() - + await self._broadcast_progress(status='error', extra={'error': error_msg}) + finally: # Save final progress to file try: @@ -262,8 +285,9 @@ class DownloadManager: logger.error(f"Failed to save progress file: {e}") # Set download status to not downloading - self._is_downloading = False - self._download_task = None + async with self._state_lock: + self._is_downloading = False + self._download_task = None async def _process_model(self, scanner_type, model, scanner, output_dir, optimize, downloader): """Process a single model download.""" @@ -285,6 +309,7 @@ class DownloadManager: try: # Update current model info self._progress['current_model'] = f"{model_name} ({model_hash[:8]})" + await self._broadcast_progress(status='running') # Skip if already in failed models if model_hash in self._progress['failed_models']: @@ -414,10 +439,10 @@ class DownloadManager: async def start_force_download(self, options: dict): """Force download example images for specific models.""" - if self._is_downloading: - raise DownloadInProgressError(self._progress.snapshot()) + async with self._state_lock: + if self._is_downloading: + raise DownloadInProgressError(self._progress.snapshot()) - try: data = options or {} model_hashes = data.get('model_hashes', []) optimize = data.get('optimize', True) @@ -442,6 +467,9 @@ class DownloadManager: self._is_downloading = True + await self._broadcast_progress(status='running') + + try: result = await self._download_specific_models_example_images_sync( model_hashes, output_dir, @@ -450,7 +478,8 @@ class DownloadManager: delay ) - self._is_downloading = False + async with self._state_lock: + self._is_downloading = False return { 'success': True, @@ -459,8 +488,10 @@ class DownloadManager: } except Exception as e: - self._is_downloading = False + async with self._state_lock: + self._is_downloading = False logger.error(f"Failed during forced example images download: {e}", exc_info=True) + await self._broadcast_progress(status='error', extra={'error': str(e)}) raise ExampleImagesDownloadError(str(e)) from e async def _download_specific_models_example_images_sync(self, model_hashes, output_dir, optimize, model_types, delay): @@ -495,15 +526,9 @@ class DownloadManager: # Update total count based on found models self._progress['total'] = len(models_to_process) logger.debug(f"Found {self._progress['total']} models to process") - + # Send initial progress via WebSocket - await ws_manager.broadcast({ - 'type': 'example_images_progress', - 'processed': 0, - 'total': self._progress['total'], - 'status': 'running', - 'current_model': '' - }) + await self._broadcast_progress(status='running') # Process each model success_count = 0 @@ -519,15 +544,9 @@ class DownloadManager: # Update progress self._progress['completed'] += 1 - + # Send progress update via WebSocket - await ws_manager.broadcast({ - 'type': 'example_images_progress', - 'processed': self._progress['completed'], - 'total': self._progress['total'], - 'status': 'running', - 'current_model': self._progress['current_model'] - }) + await self._broadcast_progress(status='running') # Only add delay after remote download, and not after processing the last model if was_successful and i < len(models_to_process) - 1 and self._progress['status'] == 'running': @@ -536,16 +555,14 @@ class DownloadManager: # Mark as completed self._progress['status'] = 'completed' self._progress['end_time'] = time.time() - logger.debug(f"Forced example images download completed: {self._progress['completed']}/{self._progress['total']} models processed") - + logger.debug( + "Forced example images download completed: %s/%s models processed", + self._progress['completed'], + self._progress['total'], + ) + # Send final progress via WebSocket - await ws_manager.broadcast({ - 'type': 'example_images_progress', - 'processed': self._progress['completed'], - 'total': self._progress['total'], - 'status': 'completed', - 'current_model': '' - }) + await self._broadcast_progress(status='completed') return { 'total': self._progress['total'], @@ -561,16 +578,9 @@ class DownloadManager: self._progress['last_error'] = error_msg self._progress['status'] = 'error' self._progress['end_time'] = time.time() - + # Send error status via WebSocket - await ws_manager.broadcast({ - 'type': 'example_images_progress', - 'processed': self._progress['completed'], - 'total': self._progress['total'], - 'status': 'error', - 'error': error_msg, - 'current_model': '' - }) + await self._broadcast_progress(status='error', extra={'error': error_msg}) raise @@ -598,6 +608,7 @@ class DownloadManager: try: # Update current model info self._progress['current_model'] = f"{model_name} ({model_hash[:8]})" + await self._broadcast_progress(status='running') # Create model directory model_dir = os.path.join(output_dir, model_hash) @@ -714,11 +725,53 @@ class DownloadManager: except Exception as e: logger.error(f"Error removing failed images from metadata for {model_name}: {e}", exc_info=True) + async def _broadcast_progress( + self, + *, + status: str | None = None, + extra: Dict[str, Any] | None = None, + ) -> None: + payload = self._build_progress_payload(status=status, extra=extra) + try: + await self._ws_manager.broadcast(payload) + except Exception as exc: # pragma: no cover - defensive logging + logger.warning("Failed to broadcast example image progress: %s", exc) -default_download_manager = DownloadManager() + def _build_progress_payload( + self, + *, + status: str | None = None, + extra: Dict[str, Any] | None = None, + ) -> Dict[str, Any]: + payload: Dict[str, Any] = { + 'type': 'example_images_progress', + 'processed': self._progress['completed'], + 'total': self._progress['total'], + 'status': status or self._progress['status'], + 'current_model': self._progress['current_model'], + } + + if self._progress['errors']: + payload['errors'] = list(self._progress['errors']) + if self._progress['last_error']: + payload['last_error'] = self._progress['last_error'] + + if extra: + payload.update(extra) + + return payload -def get_default_download_manager() -> DownloadManager: +_default_download_manager: DownloadManager | None = None + + +def get_default_download_manager(ws_manager) -> DownloadManager: """Return the singleton download manager used by default routes.""" - return default_download_manager + global _default_download_manager + if ( + _default_download_manager is None + or getattr(_default_download_manager, "_ws_manager", None) is not ws_manager + ): + _default_download_manager = DownloadManager(ws_manager=ws_manager) + return _default_download_manager diff --git a/standalone.py b/standalone.py index a6259851..95c45ca7 100644 --- a/standalone.py +++ b/standalone.py @@ -421,7 +421,7 @@ class StandaloneLoraManager(LoraManager): RecipeRoutes.setup_routes(app) UpdateRoutes.setup_routes(app) MiscRoutes.setup_routes(app) - ExampleImagesRoutes.setup_routes(app) + ExampleImagesRoutes.setup_routes(app, ws_manager=ws_manager) # Setup WebSocket routes that are shared across all model types app.router.add_get('/ws/fetch-progress', ws_manager.handle_connection) diff --git a/tests/routes/test_example_images_routes.py b/tests/routes/test_example_images_routes.py index e921e744..9a316499 100644 --- a/tests/routes/test_example_images_routes.py +++ b/tests/routes/test_example_images_routes.py @@ -3,7 +3,7 @@ from __future__ import annotations import json from contextlib import asynccontextmanager from dataclasses import dataclass -from typing import Any, List, Tuple +from typing import Any, Dict, List, Tuple from aiohttp import web from aiohttp.test_utils import TestClient, TestServer @@ -88,6 +88,14 @@ class StubExampleImagesFileManager: return web.json_response({"operation": "has_images", "query": dict(request.query)}) +class StubWebSocketManager: + def __init__(self) -> None: + self.broadcast_calls: List[Dict[str, Any]] = [] + + async def broadcast(self, payload: Dict[str, Any]) -> None: + self.broadcast_calls.append(payload) + + @asynccontextmanager async def example_images_app() -> ExampleImagesHarness: """Yield an ExampleImagesRoutes app wired with stubbed collaborators.""" @@ -95,8 +103,10 @@ async def example_images_app() -> ExampleImagesHarness: download_manager = StubDownloadManager() processor = StubExampleImagesProcessor() file_manager = StubExampleImagesFileManager() + ws_manager = StubWebSocketManager() controller = ExampleImagesRoutes( + ws_manager=ws_manager, download_manager=download_manager, processor=processor, file_manager=file_manager, From e128c80eb12b976a6bb272828cccc84338163e68 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Tue, 23 Sep 2025 14:58:35 +0800 Subject: [PATCH 075/110] test(services): add async example image download tests --- ...t_example_images_download_manager_async.py | 228 ++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 tests/services/test_example_images_download_manager_async.py diff --git a/tests/services/test_example_images_download_manager_async.py b/tests/services/test_example_images_download_manager_async.py new file mode 100644 index 00000000..7eef56fb --- /dev/null +++ b/tests/services/test_example_images_download_manager_async.py @@ -0,0 +1,228 @@ +from __future__ import annotations + +import asyncio +from types import SimpleNamespace + +import pytest + +from py.services.settings_manager import settings +from py.utils import example_images_download_manager as download_module + + +class RecordingWebSocketManager: + """Collects broadcast payloads for assertions.""" + + def __init__(self) -> None: + self.payloads: list[dict] = [] + + async def broadcast(self, payload: dict) -> None: + self.payloads.append(payload) + + +class StubScanner: + """Scanner double returning predetermined cache contents.""" + + def __init__(self, models: list[dict]) -> None: + self._cache = SimpleNamespace(raw_data=models) + + async def get_cached_data(self): + return self._cache + + +def _patch_scanner(monkeypatch: pytest.MonkeyPatch, scanner: StubScanner) -> None: + async def _get_lora_scanner(cls): + return scanner + + monkeypatch.setattr( + download_module.ServiceRegistry, + "get_lora_scanner", + classmethod(_get_lora_scanner), + ) + + +@pytest.mark.usefixtures("tmp_path") +async def test_start_download_rejects_parallel_runs(monkeypatch: pytest.MonkeyPatch, tmp_path): + ws_manager = RecordingWebSocketManager() + manager = download_module.DownloadManager(ws_manager=ws_manager) + + monkeypatch.setitem(settings.settings, "example_images_path", str(tmp_path)) + + model = { + "sha256": "abc123", + "model_name": "Example", + "file_path": str(tmp_path / "example.safetensors"), + "file_name": "example.safetensors", + } + _patch_scanner(monkeypatch, StubScanner([model])) + + started = asyncio.Event() + release = asyncio.Event() + + async def fake_process_local_examples(*_args, **_kwargs): + started.set() + await release.wait() + return True + + async def fake_update_metadata(*_args, **_kwargs): + return True + + async def fake_get_downloader(): + return object() + + monkeypatch.setattr( + download_module.ExampleImagesProcessor, + "process_local_examples", + staticmethod(fake_process_local_examples), + ) + monkeypatch.setattr( + download_module.MetadataUpdater, + "update_metadata_from_local_examples", + staticmethod(fake_update_metadata), + ) + monkeypatch.setattr(download_module, "get_downloader", fake_get_downloader) + + try: + result = await manager.start_download({"model_types": ["lora"], "delay": 0}) + assert result["success"] is True + + await asyncio.wait_for(started.wait(), timeout=1) + + with pytest.raises(download_module.DownloadInProgressError) as exc: + await manager.start_download({"model_types": ["lora"], "delay": 0}) + + snapshot = exc.value.progress_snapshot + assert snapshot["status"] == "running" + assert snapshot["current_model"] == "Example (abc123)" + + statuses = [payload["status"] for payload in ws_manager.payloads] + assert "running" in statuses + + finally: + release.set() + if manager._download_task is not None: + await asyncio.wait_for(manager._download_task, timeout=1) + + +@pytest.mark.usefixtures("tmp_path") +async def test_pause_resume_blocks_processing(monkeypatch: pytest.MonkeyPatch, tmp_path): + ws_manager = RecordingWebSocketManager() + manager = download_module.DownloadManager(ws_manager=ws_manager) + + monkeypatch.setitem(settings.settings, "example_images_path", str(tmp_path)) + + models = [ + { + "sha256": "hash-one", + "model_name": "Model One", + "file_path": str(tmp_path / "model-one.safetensors"), + "file_name": "model-one.safetensors", + "civitai": {"images": [{"url": "https://example.com/one.png"}]}, + }, + { + "sha256": "hash-two", + "model_name": "Model Two", + "file_path": str(tmp_path / "model-two.safetensors"), + "file_name": "model-two.safetensors", + "civitai": {"images": [{"url": "https://example.com/two.png"}]}, + }, + ] + _patch_scanner(monkeypatch, StubScanner(models)) + + async def fake_process_local_examples(*_args, **_kwargs): + return False + + async def fake_update_metadata(*_args, **_kwargs): + return True + + first_call_started = asyncio.Event() + first_release = asyncio.Event() + second_call_started = asyncio.Event() + call_order: list[str] = [] + + async def fake_download_model_images(model_hash, *_args, **_kwargs): + call_order.append(model_hash) + if len(call_order) == 1: + first_call_started.set() + await first_release.wait() + else: + second_call_started.set() + return True, False + + async def fake_get_downloader(): + class _Downloader: + async def download_to_memory(self, *_a, **_kw): + return True, b"", {} + + return _Downloader() + + monkeypatch.setattr( + download_module.ExampleImagesProcessor, + "process_local_examples", + staticmethod(fake_process_local_examples), + ) + monkeypatch.setattr( + download_module.MetadataUpdater, + "update_metadata_from_local_examples", + staticmethod(fake_update_metadata), + ) + monkeypatch.setattr( + download_module.ExampleImagesProcessor, + "download_model_images", + staticmethod(fake_download_model_images), + ) + monkeypatch.setattr(download_module, "get_downloader", fake_get_downloader) + + original_sleep = download_module.asyncio.sleep + pause_gate = asyncio.Event() + resume_gate = asyncio.Event() + + async def fake_sleep(delay: float): + if delay == 1: + pause_gate.set() + await resume_gate.wait() + else: + await original_sleep(delay) + + monkeypatch.setattr(download_module.asyncio, "sleep", fake_sleep) + + try: + await manager.start_download({"model_types": ["lora"], "delay": 0}) + + await asyncio.wait_for(first_call_started.wait(), timeout=1) + + await manager.pause_download({}) + + first_release.set() + + await asyncio.wait_for(pause_gate.wait(), timeout=1) + assert manager._progress["status"] == "paused" + assert not second_call_started.is_set() + + statuses = [payload["status"] for payload in ws_manager.payloads] + paused_index = statuses.index("paused") + + await asyncio.sleep(0) + assert not second_call_started.is_set() + + await manager.resume_download({}) + resume_gate.set() + + await asyncio.wait_for(second_call_started.wait(), timeout=1) + + if manager._download_task is not None: + await asyncio.wait_for(manager._download_task, timeout=1) + + statuses_after = [payload["status"] for payload in ws_manager.payloads] + running_after = next( + i for i, status in enumerate(statuses_after[paused_index + 1 :], start=paused_index + 1) if status == "running" + ) + assert running_after > paused_index + assert "completed" in statuses_after[running_after:] + assert call_order == ["hash-one", "hash-two"] + + finally: + first_release.set() + resume_gate.set() + if manager._download_task is not None: + await asyncio.wait_for(manager._download_task, timeout=1) + monkeypatch.setattr(download_module.asyncio, "sleep", original_sleep) From 3eacf9558a21c6be5feda5152d27cd5b0c437c82 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Tue, 23 Sep 2025 15:39:56 +0800 Subject: [PATCH 076/110] docs: remove outdated developer notes and add example image route architecture documentation --- README.md | 26 ------ docs/architecture/example_images_routes.md | 93 ++++++++++++++++++++++ 2 files changed, 93 insertions(+), 26 deletions(-) create mode 100644 docs/architecture/example_images_routes.md diff --git a/README.md b/README.md index f9c1806b..7e932acc 100644 --- a/README.md +++ b/README.md @@ -233,32 +233,6 @@ You can now run LoRA Manager independently from ComfyUI: This standalone mode provides a lightweight option for managing your model and recipe collection without needing to run the full ComfyUI environment, making it useful even for users who primarily use other stable diffusion interfaces. -## Developer notes - -The REST layer is split into modular registrars, controllers, and handler sets -to simplify maintenance: - -* `py/routes/recipe_route_registrar.py` holds the declarative endpoint list. -* `py/routes/base_recipe_routes.py` wires shared services/templates and returns - the handler mapping consumed by `RecipeRouteRegistrar`. -* `py/routes/handlers/recipe_handlers.py` groups HTTP adapters by concern (page - rendering, listings, queries, mutations, sharing) and delegates business rules - to services in `py/services/recipes/`. - -To add a new recipe endpoint: - -1. Declare the route in `ROUTE_DEFINITIONS` with a unique handler name. -2. Implement the coroutine on the appropriate handler class or introduce a new - handler when the concern does not fit existing ones. -3. Inject additional collaborators in - `BaseRecipeRoutes._create_handler_set` (for example a new service or factory) - so the handler can access its dependencies. - -The end-to-end wiring is documented in -[`docs/architecture/recipe_routes.md`](docs/architecture/recipe_routes.md), and -the integration suite in `tests/routes/test_recipe_routes.py` smoke-tests the -primary endpoints. - --- ## Contributing diff --git a/docs/architecture/example_images_routes.md b/docs/architecture/example_images_routes.md new file mode 100644 index 00000000..128530f6 --- /dev/null +++ b/docs/architecture/example_images_routes.md @@ -0,0 +1,93 @@ +# Example image route architecture + +The example image routing stack mirrors the layered model route stack described in +[`docs/architecture/model_routes.md`](model_routes.md). HTTP wiring, controller setup, +handler orchestration, and long-running workflows now live in clearly separated modules so +we can extend download/import behaviour without touching the entire feature surface. + +```mermaid +graph TD + subgraph HTTP + A[ExampleImagesRouteRegistrar] -->|binds| B[ExampleImagesRoutes controller] + end + subgraph Application + B --> C[ExampleImagesHandlerSet] + C --> D1[Handlers] + D1 --> E1[Use cases] + E1 --> F1[Download manager / processor / file manager] + end + subgraph Side Effects + F1 --> G1[Filesystem] + F1 --> G2[Model metadata] + F1 --> G3[WebSocket progress] + end +``` + +## Layer responsibilities + +| Layer | Module(s) | Responsibility | +| --- | --- | --- | +| Registrar | `py/routes/example_images_route_registrar.py` | Declarative catalogue of every example image endpoint plus helpers that bind them to an `aiohttp` router. Keeps HTTP concerns symmetrical with the model registrar. | +| Controller | `py/routes/example_images_routes.py` | Lazily constructs `ExampleImagesHandlerSet`, injects defaults for the download manager, processor, and file manager, and exposes the registrar-ready mapping just like `BaseModelRoutes`. | +| Handler set | `py/routes/handlers/example_images_handlers.py` | Groups HTTP adapters by concern (downloads, imports/deletes, filesystem access). Each handler translates domain errors into HTTP responses and defers to a use case or utility service. | +| Use cases | `py/services/use_cases/example_images/*.py` | Encapsulate orchestration for downloads and imports. They validate input, translate concurrency/configuration errors, and keep handler logic declarative. | +| Supporting services | `py/utils/example_images_download_manager.py`, `py/utils/example_images_processor.py`, `py/utils/example_images_file_manager.py` | Execute long-running work: pull assets from Civitai, persist uploads, clean metadata, expose filesystem actions with guardrails, and broadcast progress snapshots. | + +## Handler responsibilities & invariants + +`ExampleImagesHandlerSet` flattens the handler objects into the `{"handler_name": coroutine}` +mapping consumed by the registrar. The table below outlines how each handler collaborates +with the use cases and utilities. + +| Handler | Key endpoints | Collaborators | Contracts | +| --- | --- | --- | --- | +| `ExampleImagesDownloadHandler` | `/api/lm/download-example-images`, `/api/lm/example-images-status`, `/api/lm/pause-example-images`, `/api/lm/resume-example-images`, `/api/lm/force-download-example-images` | `DownloadExampleImagesUseCase`, `DownloadManager` | Delegates payload validation and concurrency checks to the use case; progress/status endpoints expose the same snapshot used for WebSocket broadcasts; pause/resume surface `DownloadNotRunningError` as HTTP 400 instead of 500. | +| `ExampleImagesManagementHandler` | `/api/lm/import-example-images`, `/api/lm/delete-example-image` | `ImportExampleImagesUseCase`, `ExampleImagesProcessor` | Multipart uploads are streamed to disk via the use case; validation failures return HTTP 400 with no filesystem side effects; deletion funnels through the processor to prune metadata and cached images consistently. | +| `ExampleImagesFileHandler` | `/api/lm/open-example-images-folder`, `/api/lm/example-image-files`, `/api/lm/has-example-images` | `ExampleImagesFileManager` | Centralises filesystem access, enforcing settings-based root paths and returning HTTP 400/404 for missing configuration or folders; responses always include `success`/`has_images` booleans for UI consumption. | + +## Use case boundaries + +| Use case | Entry point | Dependencies | Guarantees | +| --- | --- | --- | --- | +| `DownloadExampleImagesUseCase` | `execute(payload)` | `DownloadManager.start_download`, download configuration errors | Raises `DownloadExampleImagesInProgressError` when the manager reports an active job, rewraps configuration errors into `DownloadExampleImagesConfigurationError`, and lets `ExampleImagesDownloadError` bubble as 500s so handlers do not duplicate logging. | +| `ImportExampleImagesUseCase` | `execute(request)` | `ExampleImagesProcessor.import_images`, temporary file helpers | Supports multipart or JSON payloads, normalises file paths into a single list, cleans up temp files even on failure, and maps validation issues to `ImportExampleImagesValidationError` for HTTP 400 responses. | + +## Maintaining critical invariants + +* **Shared progress snapshots** - The download handler returns the same snapshot built by + `DownloadManager`, guaranteeing parity between HTTP polling endpoints and WebSocket + progress events. +* **Safe filesystem access** - All folder/file actions flow through + `ExampleImagesFileManager`, which validates the configured example image root and ensures + responses never leak absolute paths outside the allowed directory. +* **Metadata hygiene** - Import/delete operations run through `ExampleImagesProcessor`, + which updates model metadata via `MetadataManager` and notifies the relevant scanners so + cache state stays in sync. + +## Migration notes + +The refactor brings the example image stack in line with the model/recipe stacks: + +1. `ExampleImagesRouteRegistrar` now owns the declarative route list. Downstream projects + should rely on `ExampleImagesRoutes.to_route_mapping()` instead of manually wiring + handler callables. +2. `ExampleImagesRoutes` caches its `ExampleImagesHandlerSet` just like + `BaseModelRoutes`. If you previously instantiated handlers directly, inject custom + collaborators via the controller constructor (`download_manager`, `processor`, + `file_manager`) to keep test seams predictable. +3. Tests that mocked `ExampleImagesRoutes.setup_routes` should switch to patching + `DownloadExampleImagesUseCase`/`ImportExampleImagesUseCase` at import time. The handlers + expect those abstractions to surface validation/concurrency errors, and bypassing them + will skip the HTTP-friendly error mapping. + +## Extending the stack + +1. Add the endpoint to `ROUTE_DEFINITIONS` with a unique `handler_name`. +2. Expose the coroutine on an existing handler class (or create a new handler and extend + `ExampleImagesHandlerSet`). +3. Wire additional services or factories inside `_build_handler_set` on + `ExampleImagesRoutes`, mirroring how the model stack introduces new use cases. + +`tests/routes/test_example_images_routes.py` exercises registrar binding, download pause +flows, and import validations. Use it as a template when introducing new handler +collaborators or error mappings. From 8c9bb358247635fe4dd94bbad96c7f10a7e3f8c4 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Tue, 23 Sep 2025 19:25:02 +0800 Subject: [PATCH 077/110] Update tests/services/test_base_model_service.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tests/services/test_base_model_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/services/test_base_model_service.py b/tests/services/test_base_model_service.py index c3fdc884..fc28a54e 100644 --- a/tests/services/test_base_model_service.py +++ b/tests/services/test_base_model_service.py @@ -1,4 +1,4 @@ -import pytest +import pytest import importlib import importlib.util From 6054d95e8518bb6b7a1f701f4992e660b162c055 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Tue, 23 Sep 2025 19:25:12 +0800 Subject: [PATCH 078/110] Update py/services/model_query.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- py/services/model_query.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/services/model_query.py b/py/services/model_query.py index 08ca652f..df7bb67a 100644 --- a/py/services/model_query.py +++ b/py/services/model_query.py @@ -1,4 +1,4 @@ -from __future__ import annotations +from __future__ import annotations from dataclasses import dataclass from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, Protocol, Callable From 8aa76ce5c1ca0d37268331524b27af445dffd3a3 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Tue, 23 Sep 2025 20:28:32 +0800 Subject: [PATCH 079/110] feat(settings): centralize frontend settings on backend --- py/routes/misc_routes.py | 13 +- py/services/settings_manager.py | 88 ++++- static/js/api/baseModelApi.js | 2 +- static/js/components/RecipeCard.js | 2 +- static/js/components/shared/ModelCard.js | 4 +- .../shared/showcase/ShowcaseView.js | 2 +- static/js/core.js | 2 +- static/js/managers/ExampleImagesManager.js | 10 +- static/js/managers/OnboardingManager.js | 3 - static/js/managers/SettingsManager.js | 331 +++++------------- static/js/state/index.js | 45 ++- static/js/utils/VirtualScroller.js | 2 +- static/js/utils/uiHelpers.js | 2 +- 13 files changed, 225 insertions(+), 281 deletions(-) diff --git a/py/routes/misc_routes.py b/py/routes/misc_routes.py index b7598d97..3a6439da 100644 --- a/py/routes/misc_routes.py +++ b/py/routes/misc_routes.py @@ -179,7 +179,7 @@ class MiscRoutes: # Define keys that should be synced from backend to frontend sync_keys = [ 'civitai_api_key', - 'default_lora_root', + 'default_lora_root', 'default_checkpoint_root', 'default_embedding_root', 'base_model_path_mappings', @@ -193,8 +193,15 @@ class MiscRoutes: 'proxy_username', 'proxy_password', 'example_images_path', - 'optimizeExampleImages', - 'autoDownloadExampleImages' + 'optimize_example_images', + 'auto_download_example_images', + 'blur_mature_content', + 'autoplay_on_hover', + 'display_density', + 'card_info_display', + 'include_trigger_words', + 'show_only_sfw', + 'compact_mode' ] # Build response with only the keys that should be synced diff --git a/py/services/settings_manager.py b/py/services/settings_manager.py index adc1fb3a..1db42eb7 100644 --- a/py/services/settings_manager.py +++ b/py/services/settings_manager.py @@ -5,10 +5,41 @@ from typing import Any, Dict logger = logging.getLogger(__name__) + +DEFAULT_SETTINGS: Dict[str, Any] = { + "civitai_api_key": "", + "language": "en", + "show_only_sfw": False, + "enable_metadata_archive_db": False, + "proxy_enabled": False, + "proxy_host": "", + "proxy_port": "", + "proxy_username": "", + "proxy_password": "", + "proxy_type": "http", + "default_lora_root": "", + "default_checkpoint_root": "", + "default_embedding_root": "", + "base_model_path_mappings": {}, + "download_path_templates": {}, + "example_images_path": "", + "optimize_example_images": True, + "auto_download_example_images": False, + "blur_mature_content": True, + "autoplay_on_hover": False, + "display_density": "default", + "card_info_display": "always", + "include_trigger_words": False, + "compact_mode": False, +} + + class SettingsManager: def __init__(self): self.settings_file = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'settings.json') self.settings = self._load_settings() + self._migrate_setting_keys() + self._ensure_default_settings() self._migrate_download_path_template() self._auto_set_default_roots() self._check_environment_variables() @@ -23,11 +54,49 @@ class SettingsManager: logger.error(f"Error loading settings: {e}") return self._get_default_settings() + def _ensure_default_settings(self) -> None: + """Ensure all default settings keys exist""" + updated = False + for key, value in self._get_default_settings().items(): + if key not in self.settings: + if isinstance(value, dict): + self.settings[key] = value.copy() + else: + self.settings[key] = value + updated = True + if updated: + self._save_settings() + + def _migrate_setting_keys(self) -> None: + """Migrate legacy camelCase setting keys to snake_case""" + key_migrations = { + 'optimizeExampleImages': 'optimize_example_images', + 'autoDownloadExampleImages': 'auto_download_example_images', + 'blurMatureContent': 'blur_mature_content', + 'autoplayOnHover': 'autoplay_on_hover', + 'displayDensity': 'display_density', + 'cardInfoDisplay': 'card_info_display', + 'includeTriggerWords': 'include_trigger_words', + 'compactMode': 'compact_mode', + } + + updated = False + for old_key, new_key in key_migrations.items(): + if old_key in self.settings: + if new_key not in self.settings: + self.settings[new_key] = self.settings[old_key] + del self.settings[old_key] + updated = True + + if updated: + logger.info("Migrated legacy setting keys to snake_case") + self._save_settings() + def _migrate_download_path_template(self): """Migrate old download_path_template to new download_path_templates""" old_template = self.settings.get('download_path_template') templates = self.settings.get('download_path_templates') - + # If old template exists and new templates don't exist, migrate if old_template is not None and not templates: logger.info("Migrating download_path_template to download_path_templates") @@ -78,18 +147,11 @@ class SettingsManager: def _get_default_settings(self) -> Dict[str, Any]: """Return default settings""" - return { - "civitai_api_key": "", - "language": "en", - "show_only_sfw": False, # Show only SFW content - "enable_metadata_archive_db": False, # Enable metadata archive database - "proxy_enabled": False, # Enable app-level proxy - "proxy_host": "", # Proxy host - "proxy_port": "", # Proxy port - "proxy_username": "", # Proxy username (optional) - "proxy_password": "", # Proxy password (optional) - "proxy_type": "http" # Proxy type: http, https, socks4, socks5 - } + defaults = DEFAULT_SETTINGS.copy() + # Ensure nested dicts are independent copies + defaults['base_model_path_mappings'] = {} + defaults['download_path_templates'] = {} + return defaults def get(self, key: str, default: Any = None) -> Any: """Get setting value""" diff --git a/static/js/api/baseModelApi.js b/static/js/api/baseModelApi.js index df80d764..2d24efe4 100644 --- a/static/js/api/baseModelApi.js +++ b/static/js/api/baseModelApi.js @@ -945,7 +945,7 @@ export class BaseModelApiClient { } // Determine optimize setting - const optimize = state.global?.settings?.optimizeExampleImages ?? true; + const optimize = state.global?.settings?.optimize_example_images ?? true; // Make the API request to start the download process const response = await fetch(DOWNLOAD_ENDPOINTS.exampleImages, { diff --git a/static/js/components/RecipeCard.js b/static/js/components/RecipeCard.js index c496a928..94db918d 100644 --- a/static/js/components/RecipeCard.js +++ b/static/js/components/RecipeCard.js @@ -46,7 +46,7 @@ class RecipeCard { // NSFW blur logic - similar to LoraCard const nsfwLevel = this.recipe.preview_nsfw_level !== undefined ? this.recipe.preview_nsfw_level : 0; - const shouldBlur = state.settings.blurMatureContent && nsfwLevel > NSFW_LEVELS.PG13; + const shouldBlur = state.settings.blur_mature_content && nsfwLevel > NSFW_LEVELS.PG13; if (shouldBlur) { card.classList.add('nsfw-content'); diff --git a/static/js/components/shared/ModelCard.js b/static/js/components/shared/ModelCard.js index ba8db595..2a3c0d2f 100644 --- a/static/js/components/shared/ModelCard.js +++ b/static/js/components/shared/ModelCard.js @@ -405,7 +405,7 @@ export function createModelCard(model, modelType) { card.dataset.nsfwLevel = nsfwLevel; // Determine if the preview should be blurred based on NSFW level and user settings - const shouldBlur = state.settings.blurMatureContent && nsfwLevel > NSFW_LEVELS.PG13; + const shouldBlur = state.settings.blur_mature_content && nsfwLevel > NSFW_LEVELS.PG13; if (shouldBlur) { card.classList.add('nsfw-content'); } @@ -433,7 +433,7 @@ export function createModelCard(model, modelType) { } // Check if autoplayOnHover is enabled for video previews - const autoplayOnHover = state.global?.settings?.autoplayOnHover || false; + const autoplayOnHover = state.global?.settings?.autoplay_on_hover || false; const isVideo = previewUrl.endsWith('.mp4'); const videoAttrs = autoplayOnHover ? 'controls muted loop' : 'controls autoplay muted loop'; diff --git a/static/js/components/shared/showcase/ShowcaseView.js b/static/js/components/shared/showcase/ShowcaseView.js index 257753fd..91a6fec0 100644 --- a/static/js/components/shared/showcase/ShowcaseView.js +++ b/static/js/components/shared/showcase/ShowcaseView.js @@ -155,7 +155,7 @@ function renderMediaItem(img, index, exampleFiles) { // Check if media should be blurred const nsfwLevel = img.nsfwLevel !== undefined ? img.nsfwLevel : 0; - const shouldBlur = state.settings.blurMatureContent && nsfwLevel > NSFW_LEVELS.PG13; + const shouldBlur = state.settings.blur_mature_content && nsfwLevel > NSFW_LEVELS.PG13; // Determine NSFW warning text based on level let nsfwText = "Mature Content"; diff --git a/static/js/core.js b/static/js/core.js index c2ad6cdb..1fa66e4b 100644 --- a/static/js/core.js +++ b/static/js/core.js @@ -74,7 +74,7 @@ export class AppCore { // Initialize the help manager helpManager.initialize(); - const cardInfoDisplay = state.global.settings.cardInfoDisplay || 'always'; + const cardInfoDisplay = state.global.settings.card_info_display || 'always'; document.body.classList.toggle('hover-reveal', cardInfoDisplay === 'hover'); initializeEventManagement(); diff --git a/static/js/managers/ExampleImagesManager.js b/static/js/managers/ExampleImagesManager.js index 1c710040..d2a05fef 100644 --- a/static/js/managers/ExampleImagesManager.js +++ b/static/js/managers/ExampleImagesManager.js @@ -63,7 +63,7 @@ export class ExampleImagesManager { } // Setup auto download if enabled - if (state.global.settings.autoDownloadExampleImages) { + if (state.global.settings.auto_download_example_images) { this.setupAutoDownload(); } @@ -106,7 +106,7 @@ export class ExampleImagesManager { showToast('toast.exampleImages.pathUpdateFailed', { message: error.message }, 'error'); } // Setup or clear auto download based on path availability - if (state.global.settings.autoDownloadExampleImages) { + if (state.global.settings.auto_download_example_images) { if (hasPath) { this.setupAutoDownload(); } else { @@ -225,7 +225,7 @@ export class ExampleImagesManager { } try { - const optimize = state.global.settings.optimizeExampleImages; + const optimize = state.global.settings.optimize_example_images; const response = await fetch('/api/lm/download-example-images', { method: 'POST', @@ -677,7 +677,7 @@ export class ExampleImagesManager { canAutoDownload() { // Check if auto download is enabled - if (!state.global.settings.autoDownloadExampleImages) { + if (!state.global.settings.auto_download_example_images) { return false; } @@ -713,7 +713,7 @@ export class ExampleImagesManager { try { console.log('Performing auto download check...'); - const optimize = state.global.settings.optimizeExampleImages; + const optimize = state.global.settings.optimize_example_images; const response = await fetch('/api/lm/download-example-images', { method: 'POST', diff --git a/static/js/managers/OnboardingManager.js b/static/js/managers/OnboardingManager.js index 047cd000..ecfdf3e7 100644 --- a/static/js/managers/OnboardingManager.js +++ b/static/js/managers/OnboardingManager.js @@ -182,9 +182,6 @@ export class OnboardingManager { // Update state state.global.settings.language = languageCode; - // Save to localStorage - setStorageItem('settings', state.global.settings); - // Save to backend const response = await fetch('/api/lm/settings', { method: 'POST', diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index 8d4da06a..edc66526 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -1,8 +1,7 @@ import { modalManager } from './ModalManager.js'; import { showToast } from '../utils/uiHelpers.js'; -import { state } from '../state/index.js'; +import { state, createDefaultSettings } from '../state/index.js'; import { resetAndReload } from '../api/modelApiFactory.js'; -import { setStorageItem, getStorageItem } from '../utils/storageHelpers.js'; import { DOWNLOAD_PATH_TEMPLATES, MAPPABLE_BASE_MODELS, PATH_TEMPLATE_PLACEHOLDERS, DEFAULT_PATH_TEMPLATES } from '../utils/constants.js'; import { translate } from '../utils/i18nHelpers.js'; @@ -14,7 +13,9 @@ export class SettingsManager { // Add initialization to sync with modal state this.currentPage = document.body.dataset.page || 'loras'; - + + this.backendSettingKeys = new Set(Object.keys(createDefaultSettings())); + // Start initialization but don't await here to avoid blocking constructor this.initializationPromise = this.initializeSettings(); @@ -29,177 +30,74 @@ export class SettingsManager { } async initializeSettings() { - // Load frontend-only settings from localStorage - this.loadFrontendSettingsFromStorage(); - + // Reset to defaults before syncing + state.global.settings = createDefaultSettings(); + // Sync settings from backend to frontend await this.syncSettingsFromBackend(); } - loadFrontendSettingsFromStorage() { - // Get saved settings from localStorage - const savedSettings = getStorageItem('settings'); - - // Frontend-only settings that should be stored in localStorage - const frontendOnlyKeys = [ - 'blurMatureContent', - 'autoplayOnHover', - 'displayDensity', - 'cardInfoDisplay', - 'includeTriggerWords' - ]; - - // Apply saved frontend settings to state if available - if (savedSettings) { - const frontendSettings = {}; - frontendOnlyKeys.forEach(key => { - if (savedSettings[key] !== undefined) { - frontendSettings[key] = savedSettings[key]; - } - }); - state.global.settings = { ...state.global.settings, ...frontendSettings }; - } - - // Initialize default values for frontend settings if they don't exist - if (state.global.settings.blurMatureContent === undefined) { - state.global.settings.blurMatureContent = true; - } - - if (state.global.settings.show_only_sfw === undefined) { - state.global.settings.show_only_sfw = false; - } - - if (state.global.settings.autoplayOnHover === undefined) { - state.global.settings.autoplayOnHover = false; - } - - if (state.global.settings.cardInfoDisplay === undefined) { - state.global.settings.cardInfoDisplay = 'always'; - } - - if (state.global.settings.displayDensity === undefined) { - // Migrate legacy compactMode if it exists - if (state.global.settings.compactMode === true) { - state.global.settings.displayDensity = 'compact'; - } else { - state.global.settings.displayDensity = 'default'; - } - } - - if (state.global.settings.includeTriggerWords === undefined) { - state.global.settings.includeTriggerWords = false; - } - - // Save updated frontend settings to localStorage - this.saveFrontendSettingsToStorage(); - } - async syncSettingsFromBackend() { try { const response = await fetch('/api/lm/settings'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } - + const data = await response.json(); if (data.success && data.settings) { - // Merge backend settings with current state - state.global.settings = { ...state.global.settings, ...data.settings }; - - // Set defaults for backend settings if they're null/undefined - this.setBackendSettingDefaults(); - + state.global.settings = this.mergeSettingsWithDefaults(data.settings); console.log('Settings synced from backend'); } else { console.error('Failed to sync settings from backend:', data.error); + state.global.settings = this.mergeSettingsWithDefaults(); } } catch (error) { console.error('Failed to sync settings from backend:', error); - // Set defaults if backend sync fails - this.setBackendSettingDefaults(); + state.global.settings = this.mergeSettingsWithDefaults(); } + + this.applyFrontendSettings(); } - setBackendSettingDefaults() { - // Set defaults for backend settings - const backendDefaults = { - civitai_api_key: '', - default_lora_root: '', - default_checkpoint_root: '', - default_embedding_root: '', - base_model_path_mappings: {}, - download_path_templates: { ...DEFAULT_PATH_TEMPLATES }, - enable_metadata_archive_db: false, - language: 'en', - show_only_sfw: false, - proxy_enabled: false, - proxy_type: 'http', - proxy_host: '', - proxy_port: '', - proxy_username: '', - proxy_password: '', - example_images_path: '', - optimizeExampleImages: true, - autoDownloadExampleImages: false - }; + mergeSettingsWithDefaults(backendSettings = {}) { + const defaults = createDefaultSettings(); + const merged = { ...defaults, ...backendSettings }; - Object.keys(backendDefaults).forEach(key => { - if (state.global.settings[key] === undefined || state.global.settings[key] === null) { - state.global.settings[key] = backendDefaults[key]; + const baseMappings = backendSettings?.base_model_path_mappings; + if (baseMappings && typeof baseMappings === 'object' && !Array.isArray(baseMappings)) { + merged.base_model_path_mappings = baseMappings; + } else { + merged.base_model_path_mappings = defaults.base_model_path_mappings; + } + + let templates = backendSettings?.download_path_templates; + if (typeof templates === 'string') { + try { + const parsed = JSON.parse(templates); + if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) { + templates = parsed; + } + } catch (parseError) { + console.warn('Failed to parse download_path_templates string from backend, using defaults'); + templates = null; } - }); + } - // Ensure all model types have templates - Object.keys(DEFAULT_PATH_TEMPLATES).forEach(modelType => { - if (!state.global.settings.download_path_templates[modelType]) { - state.global.settings.download_path_templates[modelType] = DEFAULT_PATH_TEMPLATES[modelType]; - } - }); - } + if (!templates || typeof templates !== 'object' || Array.isArray(templates)) { + templates = {}; + } - saveFrontendSettingsToStorage() { - // Save only frontend-specific settings to localStorage - const frontendOnlyKeys = [ - 'blurMatureContent', - 'autoplayOnHover', - 'displayDensity', - 'cardInfoDisplay', - 'includeTriggerWords' - ]; + merged.download_path_templates = { ...DEFAULT_PATH_TEMPLATES, ...templates }; - const frontendSettings = {}; - frontendOnlyKeys.forEach(key => { - if (state.global.settings[key] !== undefined) { - frontendSettings[key] = state.global.settings[key]; - } - }); + Object.keys(merged).forEach(key => this.backendSettingKeys.add(key)); - setStorageItem('settings', frontendSettings); + return merged; } // Helper method to determine if a setting should be saved to backend isBackendSetting(settingKey) { - const backendKeys = [ - 'civitai_api_key', - 'default_lora_root', - 'default_checkpoint_root', - 'default_embedding_root', - 'base_model_path_mappings', - 'download_path_templates', - 'enable_metadata_archive_db', - 'language', - 'show_only_sfw', - 'proxy_enabled', - 'proxy_type', - 'proxy_host', - 'proxy_port', - 'proxy_username', - 'proxy_password', - 'example_images_path', - 'optimizeExampleImages', - 'autoDownloadExampleImages' - ]; - return backendKeys.includes(settingKey); + return this.backendSettingKeys.has(settingKey); } // Helper method to save setting based on whether it's frontend or backend @@ -207,36 +105,35 @@ export class SettingsManager { // Update state state.global.settings[settingKey] = value; - if (this.isBackendSetting(settingKey)) { - // Save to backend - try { - const payload = {}; - payload[settingKey] = value; + if (!this.isBackendSetting(settingKey)) { + return; + } - const response = await fetch('/api/lm/settings', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(payload) - }); + // Save to backend + try { + const payload = {}; + payload[settingKey] = value; - if (!response.ok) { - throw new Error('Failed to save setting to backend'); - } + const response = await fetch('/api/lm/settings', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(payload) + }); - // Parse response and check for success - const data = await response.json(); - if (data.success === false) { - throw new Error(data.error || 'Failed to save setting to backend'); - } - } catch (error) { - console.error(`Failed to save backend setting ${settingKey}:`, error); - throw error; + if (!response.ok) { + throw new Error('Failed to save setting to backend'); } - } else { - // Save frontend settings to localStorage - this.saveFrontendSettingsToStorage(); + + // Parse response and check for success + const data = await response.json(); + if (data.success === false) { + throw new Error(data.error || 'Failed to save setting to backend'); + } + } catch (error) { + console.error(`Failed to save backend setting ${settingKey}:`, error); + throw error; } } @@ -298,43 +195,42 @@ export class SettingsManager { // Set frontend settings from state const blurMatureContentCheckbox = document.getElementById('blurMatureContent'); if (blurMatureContentCheckbox) { - blurMatureContentCheckbox.checked = state.global.settings.blurMatureContent; + blurMatureContentCheckbox.checked = state.global.settings.blur_mature_content ?? true; } - + const showOnlySFWCheckbox = document.getElementById('showOnlySFW'); if (showOnlySFWCheckbox) { - // Sync with state (backend will set this via template) - state.global.settings.show_only_sfw = showOnlySFWCheckbox.checked; + showOnlySFWCheckbox.checked = state.global.settings.show_only_sfw ?? false; } - + // Set video autoplay on hover setting const autoplayOnHoverCheckbox = document.getElementById('autoplayOnHover'); if (autoplayOnHoverCheckbox) { - autoplayOnHoverCheckbox.checked = state.global.settings.autoplayOnHover || false; + autoplayOnHoverCheckbox.checked = state.global.settings.autoplay_on_hover || false; } - + // Set display density setting const displayDensitySelect = document.getElementById('displayDensity'); if (displayDensitySelect) { - displayDensitySelect.value = state.global.settings.displayDensity || 'default'; + displayDensitySelect.value = state.global.settings.display_density || 'default'; } - + // Set card info display setting const cardInfoDisplaySelect = document.getElementById('cardInfoDisplay'); if (cardInfoDisplaySelect) { - cardInfoDisplaySelect.value = state.global.settings.cardInfoDisplay || 'always'; + cardInfoDisplaySelect.value = state.global.settings.card_info_display || 'always'; } // Set optimize example images setting const optimizeExampleImagesCheckbox = document.getElementById('optimizeExampleImages'); if (optimizeExampleImagesCheckbox) { - optimizeExampleImagesCheckbox.checked = state.global.settings.optimizeExampleImages || false; + optimizeExampleImagesCheckbox.checked = state.global.settings.optimize_example_images ?? true; } // Set auto download example images setting const autoDownloadExampleImagesCheckbox = document.getElementById('autoDownloadExampleImages'); if (autoDownloadExampleImagesCheckbox) { - autoDownloadExampleImagesCheckbox.checked = state.global.settings.autoDownloadExampleImages || false; + autoDownloadExampleImagesCheckbox.checked = state.global.settings.auto_download_example_images || false; } // Load download path templates @@ -343,7 +239,7 @@ export class SettingsManager { // Set include trigger words setting const includeTriggerWordsCheckbox = document.getElementById('includeTriggerWords'); if (includeTriggerWordsCheckbox) { - includeTriggerWordsCheckbox.checked = state.global.settings.includeTriggerWords || false; + includeTriggerWordsCheckbox.checked = state.global.settings.include_trigger_words || false; } // Load metadata archive settings @@ -883,38 +779,17 @@ export class SettingsManager { if (!element) return; const value = element.checked; - + try { - // Update frontend state with mapped keys - if (settingKey === 'blur_mature_content') { - await this.saveSetting('blurMatureContent', value); - } else if (settingKey === 'show_only_sfw') { - await this.saveSetting('show_only_sfw', value); - } else if (settingKey === 'autoplay_on_hover') { - await this.saveSetting('autoplayOnHover', value); - } else if (settingKey === 'optimize_example_images') { - await this.saveSetting('optimizeExampleImages', value); - } else if (settingKey === 'auto_download_example_images') { - await this.saveSetting('autoDownloadExampleImages', value); - } else if (settingKey === 'compact_mode') { - await this.saveSetting('compactMode', value); - } else if (settingKey === 'include_trigger_words') { - await this.saveSetting('includeTriggerWords', value); - } else if (settingKey === 'enable_metadata_archive_db') { - await this.saveSetting('enable_metadata_archive_db', value); - } else if (settingKey === 'proxy_enabled') { - await this.saveSetting('proxy_enabled', value); - - // Toggle visibility of proxy settings group + await this.saveSetting(settingKey, value); + + if (settingKey === 'proxy_enabled') { const proxySettingsGroup = document.getElementById('proxySettingsGroup'); if (proxySettingsGroup) { proxySettingsGroup.style.display = value ? 'block' : 'none'; } - } else { - // For any other settings that might be added in the future - await this.saveSetting(settingKey, value); } - + // Refresh metadata archive status when enable setting changes if (settingKey === 'enable_metadata_archive_db') { await this.updateMetadataArchiveStatus(); @@ -941,16 +816,11 @@ export class SettingsManager { // Recalculate layout when compact mode changes if (settingKey === 'compact_mode' && state.virtualScroller) { state.virtualScroller.calculateLayout(); - showToast('toast.settings.compactModeToggled', { - state: value ? 'toast.settings.compactModeEnabled' : 'toast.settings.compactModeDisabled' + showToast('toast.settings.compactModeToggled', { + state: value ? 'toast.settings.compactModeEnabled' : 'toast.settings.compactModeDisabled' }, 'success'); } - // Special handling for metadata archive settings - if (settingKey === 'enable_metadata_archive_db') { - await this.updateMetadataArchiveStatus(); - } - } catch (error) { showToast('toast.settings.settingSaveFailed', { message: error.message }, 'error'); } @@ -964,23 +834,8 @@ export class SettingsManager { try { // Update frontend state with mapped keys - if (settingKey === 'default_lora_root') { - await this.saveSetting('default_lora_root', value); - } else if (settingKey === 'default_checkpoint_root') { - await this.saveSetting('default_checkpoint_root', value); - } else if (settingKey === 'default_embedding_root') { - await this.saveSetting('default_embedding_root', value); - } else if (settingKey === 'display_density') { - await this.saveSetting('displayDensity', value); - } else if (settingKey === 'card_info_display') { - await this.saveSetting('cardInfoDisplay', value); - } else if (settingKey === 'proxy_type') { - await this.saveSetting('proxy_type', value); - } else { - // For any other settings that might be added in the future - await this.saveSetting(settingKey, value); - } - + await this.saveSetting(settingKey, value); + // Apply frontend settings immediately this.applyFrontendSettings(); @@ -1347,7 +1202,7 @@ export class SettingsManager { applyFrontendSettings() { // Apply autoplay setting to existing videos in card previews - const autoplayOnHover = state.global.settings.autoplayOnHover; + const autoplayOnHover = state.global.settings.autoplay_on_hover; document.querySelectorAll('.card-preview video').forEach(video => { // Remove previous event listeners by cloning and replacing the element const videoParent = video.parentElement; @@ -1377,17 +1232,17 @@ export class SettingsManager { // Apply display density class to grid const grid = document.querySelector('.card-grid'); if (grid) { - const density = state.global.settings.displayDensity || 'default'; - + const density = state.global.settings.display_density || 'default'; + // Remove all density classes first grid.classList.remove('default-density', 'medium-density', 'compact-density'); - + // Add the appropriate density class grid.classList.add(`${density}-density`); } - + // Apply card info display setting - const cardInfoDisplay = state.global.settings.cardInfoDisplay || 'always'; + const cardInfoDisplay = state.global.settings.card_info_display || 'always'; document.body.classList.toggle('hover-reveal', cardInfoDisplay === 'hover'); } } diff --git a/static/js/state/index.js b/static/js/state/index.js index 9e48e86f..6f0cedd1 100644 --- a/static/js/state/index.js +++ b/static/js/state/index.js @@ -1,20 +1,43 @@ // Create the new hierarchical state structure import { getStorageItem, getMapFromStorage } from '../utils/storageHelpers.js'; import { MODEL_TYPES } from '../api/apiConfig.js'; +import { DEFAULT_PATH_TEMPLATES } from '../utils/constants.js'; -// Load only frontend settings from localStorage with defaults -// Backend settings will be loaded by SettingsManager from the backend -const savedSettings = getStorageItem('settings', { - blurMatureContent: true, +const DEFAULT_SETTINGS_BASE = Object.freeze({ + civitai_api_key: '', + language: 'en', show_only_sfw: false, - cardInfoDisplay: 'always', - autoplayOnHover: false, - displayDensity: 'default', - optimizeExampleImages: true, - autoDownloadExampleImages: true, - includeTriggerWords: false + enable_metadata_archive_db: false, + proxy_enabled: false, + proxy_type: 'http', + proxy_host: '', + proxy_port: '', + proxy_username: '', + proxy_password: '', + default_lora_root: '', + default_checkpoint_root: '', + default_embedding_root: '', + base_model_path_mappings: {}, + download_path_templates: {}, + example_images_path: '', + optimize_example_images: true, + auto_download_example_images: false, + blur_mature_content: true, + autoplay_on_hover: false, + display_density: 'default', + card_info_display: 'always', + include_trigger_words: false, + compact_mode: false, }); +export function createDefaultSettings() { + return { + ...DEFAULT_SETTINGS_BASE, + base_model_path_mappings: {}, + download_path_templates: { ...DEFAULT_PATH_TEMPLATES }, + }; +} + // Load preview versions from localStorage for each model type const loraPreviewVersions = getMapFromStorage('loras_preview_versions'); const checkpointPreviewVersions = getMapFromStorage('checkpoints_preview_versions'); @@ -23,7 +46,7 @@ const embeddingPreviewVersions = getMapFromStorage('embeddings_preview_versions' export const state = { // Global state global: { - settings: savedSettings, + settings: createDefaultSettings(), loadingManager: null, observer: null, }, diff --git a/static/js/utils/VirtualScroller.js b/static/js/utils/VirtualScroller.js index 57f46c06..e25da266 100644 --- a/static/js/utils/VirtualScroller.js +++ b/static/js/utils/VirtualScroller.js @@ -102,7 +102,7 @@ export class VirtualScroller { const availableContentWidth = containerWidth - paddingLeft - paddingRight; // Get display density setting - const displayDensity = state.global.settings?.displayDensity || 'default'; + const displayDensity = state.global.settings?.display_density || 'default'; // Set exact column counts and grid widths to match CSS container widths let maxColumns, maxGridWidth; diff --git a/static/js/utils/uiHelpers.js b/static/js/utils/uiHelpers.js index 3aed6942..3e02d086 100644 --- a/static/js/utils/uiHelpers.js +++ b/static/js/utils/uiHelpers.js @@ -339,7 +339,7 @@ export function copyLoraSyntax(card) { const baseSyntax = buildLoraSyntax(card.dataset.file_name, usageTips); // Check if trigger words should be included - const includeTriggerWords = state.global.settings.includeTriggerWords; + const includeTriggerWords = state.global.settings.include_trigger_words; if (!includeTriggerWords) { const message = translate('uiHelpers.lora.syntaxCopied', {}, 'LoRA syntax copied to clipboard'); From 656f1755fd6fe1b17dd01d3e5d864c527f069910 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Tue, 23 Sep 2025 20:35:35 +0800 Subject: [PATCH 080/110] feat: add cleanup example image folders functionality and UI integration --- locales/de.json | 9 + locales/en.json | 9 + locales/es.json | 9 + locales/fr.json | 9 + locales/ja.json | 9 + locales/ko.json | 9 + locales/ru.json | 9 + locales/zh-CN.json | 9 + locales/zh-TW.json | 9 + py/lora_manager.py | 135 ++-------- py/routes/example_images_route_registrar.py | 1 + py/routes/example_images_routes.py | 9 +- py/routes/handlers/example_images_handlers.py | 14 +- py/services/example_images_cleanup_service.py | 246 ++++++++++++++++++ .../ContextMenu/GlobalContextMenu.js | 63 ++++- templates/components/context_menu.html | 12 +- tests/routes/test_example_images_routes.py | 47 +++- .../test_example_images_cleanup_service.py | 86 ++++++ 18 files changed, 568 insertions(+), 126 deletions(-) create mode 100644 py/services/example_images_cleanup_service.py create mode 100644 tests/services/test_example_images_cleanup_service.py diff --git a/locales/de.json b/locales/de.json index 09ce4dec..6f00b0ac 100644 --- a/locales/de.json +++ b/locales/de.json @@ -122,6 +122,15 @@ "noRemoteImagesAvailable": "Keine Remote-Beispielbilder für dieses Modell auf Civitai verfügbar" } }, + "globalContextMenu": { + "cleanupExampleImages": { + "label": "Clean up example image folders", + "success": "Moved {count} folder(s) to the deleted folder", + "none": "No example image folders needed cleanup", + "partial": "Cleanup completed with {failures} folder(s) skipped", + "error": "Failed to clean example image folders: {message}" + } + }, "header": { "appTitle": "LoRA Manager", "navigation": { diff --git a/locales/en.json b/locales/en.json index 35d59115..13890105 100644 --- a/locales/en.json +++ b/locales/en.json @@ -122,6 +122,15 @@ "noRemoteImagesAvailable": "No remote example images available for this model on Civitai" } }, + "globalContextMenu": { + "cleanupExampleImages": { + "label": "Clean up example image folders", + "success": "Moved {count} folder(s) to the deleted folder", + "none": "No example image folders needed cleanup", + "partial": "Cleanup completed with {failures} folder(s) skipped", + "error": "Failed to clean example image folders: {message}" + } + }, "header": { "appTitle": "LoRA Manager", "navigation": { diff --git a/locales/es.json b/locales/es.json index a674b713..fa32a89a 100644 --- a/locales/es.json +++ b/locales/es.json @@ -122,6 +122,15 @@ "noRemoteImagesAvailable": "No hay imágenes de ejemplo remotas disponibles para este modelo en Civitai" } }, + "globalContextMenu": { + "cleanupExampleImages": { + "label": "Clean up example image folders", + "success": "Moved {count} folder(s) to the deleted folder", + "none": "No example image folders needed cleanup", + "partial": "Cleanup completed with {failures} folder(s) skipped", + "error": "Failed to clean example image folders: {message}" + } + }, "header": { "appTitle": "LoRA Manager", "navigation": { diff --git a/locales/fr.json b/locales/fr.json index 519f5ec5..a4f7eeba 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -122,6 +122,15 @@ "noRemoteImagesAvailable": "Aucune image d'exemple distante disponible pour ce modèle sur Civitai" } }, + "globalContextMenu": { + "cleanupExampleImages": { + "label": "Clean up example image folders", + "success": "Moved {count} folder(s) to the deleted folder", + "none": "No example image folders needed cleanup", + "partial": "Cleanup completed with {failures} folder(s) skipped", + "error": "Failed to clean example image folders: {message}" + } + }, "header": { "appTitle": "LoRA Manager", "navigation": { diff --git a/locales/ja.json b/locales/ja.json index 5670b167..16c95020 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -122,6 +122,15 @@ "noRemoteImagesAvailable": "このモデルのCivitaiでのリモート例画像は利用できません" } }, + "globalContextMenu": { + "cleanupExampleImages": { + "label": "Clean up example image folders", + "success": "Moved {count} folder(s) to the deleted folder", + "none": "No example image folders needed cleanup", + "partial": "Cleanup completed with {failures} folder(s) skipped", + "error": "Failed to clean example image folders: {message}" + } + }, "header": { "appTitle": "LoRA Manager", "navigation": { diff --git a/locales/ko.json b/locales/ko.json index 90bbbb75..28b4e0d6 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -122,6 +122,15 @@ "noRemoteImagesAvailable": "Civitai에서 이 모델의 원격 예시 이미지를 사용할 수 없습니다" } }, + "globalContextMenu": { + "cleanupExampleImages": { + "label": "Clean up example image folders", + "success": "Moved {count} folder(s) to the deleted folder", + "none": "No example image folders needed cleanup", + "partial": "Cleanup completed with {failures} folder(s) skipped", + "error": "Failed to clean example image folders: {message}" + } + }, "header": { "appTitle": "LoRA Manager", "navigation": { diff --git a/locales/ru.json b/locales/ru.json index 08112670..b07d77cd 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -122,6 +122,15 @@ "noRemoteImagesAvailable": "Нет удаленных примеров изображений для этой модели на Civitai" } }, + "globalContextMenu": { + "cleanupExampleImages": { + "label": "Clean up example image folders", + "success": "Moved {count} folder(s) to the deleted folder", + "none": "No example image folders needed cleanup", + "partial": "Cleanup completed with {failures} folder(s) skipped", + "error": "Failed to clean example image folders: {message}" + } + }, "header": { "appTitle": "LoRA Manager", "navigation": { diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 6ef426c9..867c5c55 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -122,6 +122,15 @@ "noRemoteImagesAvailable": "此模型在 Civitai 上没有远程示例图片" } }, + "globalContextMenu": { + "cleanupExampleImages": { + "label": "Clean up example image folders", + "success": "Moved {count} folder(s) to the deleted folder", + "none": "No example image folders needed cleanup", + "partial": "Cleanup completed with {failures} folder(s) skipped", + "error": "Failed to clean example image folders: {message}" + } + }, "header": { "appTitle": "LoRA 管理器", "navigation": { diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 70e769d1..9d285079 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -122,6 +122,15 @@ "noRemoteImagesAvailable": "此模型在 Civitai 上無遠端範例圖片" } }, + "globalContextMenu": { + "cleanupExampleImages": { + "label": "Clean up example image folders", + "success": "Moved {count} folder(s) to the deleted folder", + "none": "No example image folders needed cleanup", + "partial": "Cleanup completed with {failures} folder(s) skipped", + "error": "Failed to clean example image folders: {message}" + } + }, "header": { "appTitle": "LoRA 管理器", "navigation": { diff --git a/py/lora_manager.py b/py/lora_manager.py index ed37f27d..98f1a00e 100644 --- a/py/lora_manager.py +++ b/py/lora_manager.py @@ -16,6 +16,7 @@ from .services.service_registry import ServiceRegistry from .services.settings_manager import settings from .utils.example_images_migration import ExampleImagesMigration from .services.websocket_manager import ws_manager +from .services.example_images_cleanup_service import ExampleImagesCleanupService logger = logging.getLogger(__name__) @@ -240,7 +241,6 @@ class LoraManager: # Run post-initialization tasks post_tasks = [ asyncio.create_task(cls._cleanup_backup_files(), name='cleanup_bak_files'), - asyncio.create_task(cls._cleanup_example_images_folders(), name='cleanup_example_images'), # Add more post-initialization tasks here as needed # asyncio.create_task(cls._another_post_task(), name='another_task'), ] @@ -352,116 +352,37 @@ class LoraManager: @classmethod async def _cleanup_example_images_folders(cls): - """Clean up invalid or empty folders in example images directory""" + """Invoke the example images cleanup service for manual execution.""" try: - example_images_path = settings.get('example_images_path') - if not example_images_path or not os.path.exists(example_images_path): - logger.debug("Example images path not configured or doesn't exist, skipping cleanup") - return - - logger.debug(f"Starting cleanup of example images folders in: {example_images_path}") - - # Get all scanner instances to check hash validity - lora_scanner = await ServiceRegistry.get_lora_scanner() - checkpoint_scanner = await ServiceRegistry.get_checkpoint_scanner() - embedding_scanner = await ServiceRegistry.get_embedding_scanner() - - total_folders_checked = 0 - empty_folders_removed = 0 - orphaned_folders_removed = 0 - - # Scan the example images directory - try: - with os.scandir(example_images_path) as it: - for entry in it: - if not entry.is_dir(follow_symlinks=False): - continue - - folder_name = entry.name - folder_path = entry.path - total_folders_checked += 1 - - try: - # Check if folder is empty - is_empty = cls._is_folder_empty(folder_path) - if is_empty: - logger.debug(f"Removing empty example images folder: {folder_name}") - await cls._remove_folder_safely(folder_path) - empty_folders_removed += 1 - continue - - # Check if folder name is a valid SHA256 hash (64 hex characters) - if len(folder_name) != 64 or not all(c in '0123456789abcdefABCDEF' for c in folder_name): - # Skip non-hash folders to avoid deleting other content - logger.debug(f"Skipping non-hash folder: {folder_name}") - continue - - # Check if hash exists in any of the scanners - hash_exists = ( - lora_scanner.has_hash(folder_name) or - checkpoint_scanner.has_hash(folder_name) or - embedding_scanner.has_hash(folder_name) - ) - - if not hash_exists: - logger.debug(f"Removing example images folder for deleted model: {folder_name}") - await cls._remove_folder_safely(folder_path) - orphaned_folders_removed += 1 - continue + service = ExampleImagesCleanupService() + result = await service.cleanup_example_image_folders() - except Exception as e: - logger.error(f"Error processing example images folder {folder_name}: {e}") - - # Yield control periodically - await asyncio.sleep(0.01) - - except Exception as e: - logger.error(f"Error scanning example images directory: {e}") - return - - # Log final cleanup report - total_removed = empty_folders_removed + orphaned_folders_removed - if total_removed > 0: - logger.info(f"Example images cleanup completed: checked {total_folders_checked} folders, " - f"removed {empty_folders_removed} empty folders and {orphaned_folders_removed} " - f"folders for deleted models (total: {total_removed} removed)") + if result.get('success'): + logger.debug( + "Manual example images cleanup completed: moved=%s", + result.get('moved_total'), + ) + elif result.get('partial_success'): + logger.warning( + "Manual example images cleanup partially succeeded: moved=%s failures=%s", + result.get('moved_total'), + result.get('move_failures'), + ) else: - logger.debug(f"Example images cleanup completed: checked {total_folders_checked} folders, " - f"no cleanup needed") - - except Exception as e: + logger.debug( + "Manual example images cleanup skipped or failed: %s", + result.get('error', 'no changes'), + ) + + return result + + except Exception as e: # pragma: no cover - defensive guard logger.error(f"Error during example images cleanup: {e}", exc_info=True) - - @classmethod - def _is_folder_empty(cls, folder_path: str) -> bool: - """Check if a folder is empty - - Args: - folder_path: Path to the folder to check - - Returns: - bool: True if folder is empty, False otherwise - """ - try: - with os.scandir(folder_path) as it: - return not any(it) - except Exception as e: - logger.debug(f"Error checking if folder is empty {folder_path}: {e}") - return False - - @classmethod - async def _remove_folder_safely(cls, folder_path: str): - """Safely remove a folder and all its contents - - Args: - folder_path: Path to the folder to remove - """ - try: - import shutil - loop = asyncio.get_event_loop() - await loop.run_in_executor(None, shutil.rmtree, folder_path) - except Exception as e: - logger.warning(f"Failed to remove folder {folder_path}: {e}") + return { + 'success': False, + 'error': str(e), + 'error_code': 'unexpected_error', + } @classmethod async def _cleanup(cls, app): diff --git a/py/routes/example_images_route_registrar.py b/py/routes/example_images_route_registrar.py index d0f1fab0..aa12c3b1 100644 --- a/py/routes/example_images_route_registrar.py +++ b/py/routes/example_images_route_registrar.py @@ -27,6 +27,7 @@ ROUTE_DEFINITIONS: tuple[RouteDefinition, ...] = ( RouteDefinition("GET", "/api/lm/has-example-images", "has_example_images"), RouteDefinition("POST", "/api/lm/delete-example-image", "delete_example_image"), RouteDefinition("POST", "/api/lm/force-download-example-images", "force_download_example_images"), + RouteDefinition("POST", "/api/lm/cleanup-example-image-folders", "cleanup_example_image_folders"), ) diff --git a/py/routes/example_images_routes.py b/py/routes/example_images_routes.py index 5073410d..aed4e0fd 100644 --- a/py/routes/example_images_routes.py +++ b/py/routes/example_images_routes.py @@ -22,6 +22,7 @@ from ..utils.example_images_download_manager import ( ) from ..utils.example_images_file_manager import ExampleImagesFileManager from ..utils.example_images_processor import ExampleImagesProcessor +from ..services.example_images_cleanup_service import ExampleImagesCleanupService logger = logging.getLogger(__name__) @@ -36,12 +37,14 @@ class ExampleImagesRoutes: download_manager: DownloadManager | None = None, processor=ExampleImagesProcessor, file_manager=ExampleImagesFileManager, + cleanup_service: ExampleImagesCleanupService | None = None, ) -> None: if ws_manager is None: raise ValueError("ws_manager is required") self._download_manager = download_manager or get_default_download_manager(ws_manager) self._processor = processor self._file_manager = file_manager + self._cleanup_service = cleanup_service or ExampleImagesCleanupService() self._handler_set: ExampleImagesHandlerSet | None = None self._handler_mapping: Mapping[str, Callable[[web.Request], web.StreamResponse]] | None = None @@ -72,7 +75,11 @@ class ExampleImagesRoutes: download_use_case = DownloadExampleImagesUseCase(download_manager=self._download_manager) download_handler = ExampleImagesDownloadHandler(download_use_case, self._download_manager) import_use_case = ImportExampleImagesUseCase(processor=self._processor) - management_handler = ExampleImagesManagementHandler(import_use_case, self._processor) + management_handler = ExampleImagesManagementHandler( + import_use_case, + self._processor, + self._cleanup_service, + ) file_handler = ExampleImagesFileHandler(self._file_manager) return ExampleImagesHandlerSet( download=download_handler, diff --git a/py/routes/handlers/example_images_handlers.py b/py/routes/handlers/example_images_handlers.py index fd39de04..111013e2 100644 --- a/py/routes/handlers/example_images_handlers.py +++ b/py/routes/handlers/example_images_handlers.py @@ -89,9 +89,10 @@ class ExampleImagesDownloadHandler: class ExampleImagesManagementHandler: """HTTP adapters for import/delete endpoints.""" - def __init__(self, import_use_case: ImportExampleImagesUseCase, processor) -> None: + def __init__(self, import_use_case: ImportExampleImagesUseCase, processor, cleanup_service) -> None: self._import_use_case = import_use_case self._processor = processor + self._cleanup_service = cleanup_service async def import_example_images(self, request: web.Request) -> web.StreamResponse: try: @@ -105,6 +106,16 @@ class ExampleImagesManagementHandler: async def delete_example_image(self, request: web.Request) -> web.StreamResponse: return await self._processor.delete_custom_image(request) + async def cleanup_example_image_folders(self, request: web.Request) -> web.StreamResponse: + result = await self._cleanup_service.cleanup_example_image_folders() + + if result.get('success') or result.get('partial_success'): + return web.json_response(result, status=200) + + error_code = result.get('error_code') + status = 400 if error_code in {'path_not_configured', 'path_not_found'} else 500 + return web.json_response(result, status=status) + class ExampleImagesFileHandler: """HTTP adapters for filesystem-centric endpoints.""" @@ -141,6 +152,7 @@ class ExampleImagesHandlerSet: "force_download_example_images": self.download.force_download_example_images, "import_example_images": self.management.import_example_images, "delete_example_image": self.management.delete_example_image, + "cleanup_example_image_folders": self.management.cleanup_example_image_folders, "open_example_images_folder": self.files.open_example_images_folder, "get_example_image_files": self.files.get_example_image_files, "has_example_images": self.files.has_example_images, diff --git a/py/services/example_images_cleanup_service.py b/py/services/example_images_cleanup_service.py new file mode 100644 index 00000000..671f3d8a --- /dev/null +++ b/py/services/example_images_cleanup_service.py @@ -0,0 +1,246 @@ +"""Service for cleaning up example image folders.""" + +from __future__ import annotations + +import asyncio +import logging +import os +import shutil +from dataclasses import dataclass +from pathlib import Path +from typing import Dict, List + +from .service_registry import ServiceRegistry +from .settings_manager import settings + + +logger = logging.getLogger(__name__) + + +@dataclass(slots=True) +class CleanupResult: + """Structured result returned from cleanup operations.""" + + success: bool + checked_folders: int + moved_empty_folders: int + moved_orphaned_folders: int + skipped_non_hash: int + move_failures: int + errors: List[str] + deleted_root: str | None + partial_success: bool + + def to_dict(self) -> Dict[str, object]: + """Convert the dataclass to a serialisable dictionary.""" + + data = { + "success": self.success, + "checked_folders": self.checked_folders, + "moved_empty_folders": self.moved_empty_folders, + "moved_orphaned_folders": self.moved_orphaned_folders, + "moved_total": self.moved_empty_folders + self.moved_orphaned_folders, + "skipped_non_hash": self.skipped_non_hash, + "move_failures": self.move_failures, + "errors": self.errors, + "deleted_root": self.deleted_root, + "partial_success": self.partial_success, + } + + return data + + +class ExampleImagesCleanupService: + """Encapsulates logic for cleaning example image folders.""" + + DELETED_FOLDER_NAME = "_deleted" + + def __init__(self, deleted_folder_name: str | None = None) -> None: + self._deleted_folder_name = deleted_folder_name or self.DELETED_FOLDER_NAME + + async def cleanup_example_image_folders(self) -> Dict[str, object]: + """Clean empty or orphaned example image folders by moving them under a deleted bucket.""" + + example_images_path = settings.get("example_images_path") + if not example_images_path: + logger.debug("Cleanup skipped: example images path not configured") + return { + "success": False, + "error": "Example images path is not configured.", + "error_code": "path_not_configured", + } + + example_root = Path(example_images_path) + if not example_root.exists(): + logger.debug("Cleanup skipped: example images path missing -> %s", example_root) + return { + "success": False, + "error": "Example images path does not exist.", + "error_code": "path_not_found", + } + + try: + lora_scanner = await ServiceRegistry.get_lora_scanner() + checkpoint_scanner = await ServiceRegistry.get_checkpoint_scanner() + embedding_scanner = await ServiceRegistry.get_embedding_scanner() + except Exception as exc: # pragma: no cover - defensive guard + logger.error("Failed to acquire scanners for cleanup: %s", exc, exc_info=True) + return { + "success": False, + "error": f"Failed to load model scanners: {exc}", + "error_code": "scanner_initialization_failed", + } + + deleted_bucket = example_root / self._deleted_folder_name + deleted_bucket.mkdir(exist_ok=True) + + checked_folders = 0 + moved_empty = 0 + moved_orphaned = 0 + skipped_non_hash = 0 + move_failures = 0 + errors: List[str] = [] + + for entry in os.scandir(example_root): + if not entry.is_dir(follow_symlinks=False): + continue + + if entry.name == self._deleted_folder_name: + continue + + checked_folders += 1 + folder_path = Path(entry.path) + + try: + if self._is_folder_empty(folder_path): + if await self._remove_empty_folder(folder_path): + moved_empty += 1 + else: + move_failures += 1 + continue + + if not self._is_hash_folder(entry.name): + skipped_non_hash += 1 + continue + + hash_exists = ( + lora_scanner.has_hash(entry.name) + or checkpoint_scanner.has_hash(entry.name) + or embedding_scanner.has_hash(entry.name) + ) + + if not hash_exists: + if await self._move_folder(folder_path, deleted_bucket): + moved_orphaned += 1 + else: + move_failures += 1 + + except Exception as exc: # pragma: no cover - filesystem guard + move_failures += 1 + error_message = f"{entry.name}: {exc}" + errors.append(error_message) + logger.error("Error processing example images folder %s: %s", folder_path, exc, exc_info=True) + + partial_success = move_failures > 0 and (moved_empty > 0 or moved_orphaned > 0) + success = move_failures == 0 and not errors + + result = CleanupResult( + success=success, + checked_folders=checked_folders, + moved_empty_folders=moved_empty, + moved_orphaned_folders=moved_orphaned, + skipped_non_hash=skipped_non_hash, + move_failures=move_failures, + errors=errors, + deleted_root=str(deleted_bucket), + partial_success=partial_success, + ) + + summary = result.to_dict() + if success: + logger.info( + "Example images cleanup complete: checked=%s, moved_empty=%s, moved_orphaned=%s", + checked_folders, + moved_empty, + moved_orphaned, + ) + elif partial_success: + logger.warning( + "Example images cleanup partially complete: moved=%s, failures=%s", + summary["moved_total"], + move_failures, + ) + else: + logger.error( + "Example images cleanup failed: move_failures=%s, errors=%s", + move_failures, + errors, + ) + + return summary + + @staticmethod + def _is_folder_empty(folder_path: Path) -> bool: + try: + with os.scandir(folder_path) as iterator: + return not any(iterator) + except FileNotFoundError: + return True + except OSError as exc: # pragma: no cover - defensive guard + logger.debug("Failed to inspect folder %s: %s", folder_path, exc) + return False + + @staticmethod + def _is_hash_folder(name: str) -> bool: + if len(name) != 64: + return False + hex_chars = set("0123456789abcdefABCDEF") + return all(char in hex_chars for char in name) + + async def _remove_empty_folder(self, folder_path: Path) -> bool: + loop = asyncio.get_running_loop() + + try: + await loop.run_in_executor( + None, + shutil.rmtree, + str(folder_path), + ) + logger.debug("Removed empty example images folder %s", folder_path) + return True + except Exception as exc: # pragma: no cover - filesystem guard + logger.error("Failed to remove empty example images folder %s: %s", folder_path, exc, exc_info=True) + return False + + async def _move_folder(self, folder_path: Path, deleted_bucket: Path) -> bool: + destination = self._build_destination(folder_path.name, deleted_bucket) + loop = asyncio.get_running_loop() + + try: + await loop.run_in_executor( + None, + shutil.move, + str(folder_path), + str(destination), + ) + logger.debug("Moved example images folder %s -> %s", folder_path, destination) + return True + except Exception as exc: # pragma: no cover - filesystem guard + logger.error( + "Failed to move example images folder %s to %s: %s", + folder_path, + destination, + exc, + exc_info=True, + ) + return False + + def _build_destination(self, folder_name: str, deleted_bucket: Path) -> Path: + destination = deleted_bucket / folder_name + suffix = 1 + + while destination.exists(): + destination = deleted_bucket / f"{folder_name}_{suffix}" + suffix += 1 + + return destination diff --git a/static/js/components/ContextMenu/GlobalContextMenu.js b/static/js/components/ContextMenu/GlobalContextMenu.js index 6015efee..58785aba 100644 --- a/static/js/components/ContextMenu/GlobalContextMenu.js +++ b/static/js/components/ContextMenu/GlobalContextMenu.js @@ -1,24 +1,75 @@ import { BaseContextMenu } from './BaseContextMenu.js'; +import { showToast } from '../../utils/uiHelpers.js'; export class GlobalContextMenu extends BaseContextMenu { constructor() { super('globalContextMenu'); + this._cleanupInProgress = false; } - showMenu(x, y) { - super.showMenu(x, y, null); + showMenu(x, y, origin = null) { + const contextOrigin = origin || { type: 'global' }; + super.showMenu(x, y, contextOrigin); } handleMenuAction(action, menuItem) { switch (action) { - case 'placeholder-one': - case 'placeholder-two': - case 'placeholder-three': - console.info(`Global context menu action triggered: ${action}`); + case 'cleanup-example-images-folders': + this.cleanupExampleImagesFolders(menuItem).catch((error) => { + console.error('Failed to trigger example images cleanup:', error); + }); break; default: console.warn(`Unhandled global context menu action: ${action}`); break; } } + + async cleanupExampleImagesFolders(menuItem) { + if (this._cleanupInProgress) { + return; + } + + this._cleanupInProgress = true; + menuItem?.classList.add('disabled'); + + try { + const response = await fetch('/api/lm/cleanup-example-image-folders', { + method: 'POST', + }); + + let payload; + try { + payload = await response.json(); + } catch (parseError) { + payload = { error: 'Unexpected response format.' }; + } + + if (response.ok && (payload.success || payload.partial_success)) { + const movedTotal = payload.moved_total || 0; + + if (movedTotal > 0) { + showToast('globalContextMenu.cleanupExampleImages.success', { count: movedTotal }, 'success'); + } else { + showToast('globalContextMenu.cleanupExampleImages.none', {}, 'info'); + } + + if (payload.partial_success) { + showToast( + 'globalContextMenu.cleanupExampleImages.partial', + { failures: payload.move_failures ?? 0 }, + 'warning', + ); + } + } else { + const message = payload?.error || 'Unknown error'; + showToast('globalContextMenu.cleanupExampleImages.error', { message }, 'error'); + } + } catch (error) { + showToast('globalContextMenu.cleanupExampleImages.error', { message: error.message || 'Unknown error' }, 'error'); + } finally { + this._cleanupInProgress = false; + menuItem?.classList.remove('disabled'); + } + } } diff --git a/templates/components/context_menu.html b/templates/components/context_menu.html index d5ace040..3d96e6cc 100644 --- a/templates/components/context_menu.html +++ b/templates/components/context_menu.html @@ -85,14 +85,8 @@
    -
    - Global action one -
    -
    - Global action two -
    -
    - Global action three +
    + {{ t('globalContextMenu.cleanupExampleImages.label') }}
    @@ -115,4 +109,4 @@
    -
    \ No newline at end of file +
    diff --git a/tests/routes/test_example_images_routes.py b/tests/routes/test_example_images_routes.py index 9a316499..1cc57eb0 100644 --- a/tests/routes/test_example_images_routes.py +++ b/tests/routes/test_example_images_routes.py @@ -27,6 +27,7 @@ class ExampleImagesHarness: download_manager: "StubDownloadManager" processor: "StubExampleImagesProcessor" file_manager: "StubExampleImagesFileManager" + cleanup_service: "StubExampleImagesCleanupService" controller: ExampleImagesRoutes @@ -88,6 +89,21 @@ class StubExampleImagesFileManager: return web.json_response({"operation": "has_images", "query": dict(request.query)}) +class StubExampleImagesCleanupService: + def __init__(self) -> None: + self.calls: List[Dict[str, Any]] = [] + self.result: Dict[str, Any] = { + "success": True, + "moved_total": 0, + "moved_empty_folders": 0, + "moved_orphaned_folders": 0, + } + + async def cleanup_example_image_folders(self) -> Dict[str, Any]: + self.calls.append({}) + return self.result + + class StubWebSocketManager: def __init__(self) -> None: self.broadcast_calls: List[Dict[str, Any]] = [] @@ -103,6 +119,7 @@ async def example_images_app() -> ExampleImagesHarness: download_manager = StubDownloadManager() processor = StubExampleImagesProcessor() file_manager = StubExampleImagesFileManager() + cleanup_service = StubExampleImagesCleanupService() ws_manager = StubWebSocketManager() controller = ExampleImagesRoutes( @@ -110,6 +127,7 @@ async def example_images_app() -> ExampleImagesHarness: download_manager=download_manager, processor=processor, file_manager=file_manager, + cleanup_service=cleanup_service, ) app = web.Application() @@ -125,6 +143,7 @@ async def example_images_app() -> ExampleImagesHarness: download_manager=download_manager, processor=processor, file_manager=file_manager, + cleanup_service=cleanup_service, controller=controller, ) finally: @@ -255,6 +274,23 @@ async def test_file_routes_delegate_to_file_manager(): ] +async def test_cleanup_route_delegates_to_service(): + async with example_images_app() as harness: + harness.cleanup_service.result = { + "success": True, + "moved_total": 2, + "moved_empty_folders": 1, + "moved_orphaned_folders": 1, + } + + response = await harness.client.post("/api/lm/cleanup-example-image-folders") + body = await response.json() + + assert response.status == 200 + assert body == harness.cleanup_service.result + assert len(harness.cleanup_service.calls) == 1 + + @pytest.mark.asyncio async def test_download_handler_methods_delegate() -> None: class Recorder: @@ -337,15 +373,20 @@ async def test_management_handler_methods_delegate() -> None: return "delete" recorder = Recorder() + cleanup_service = StubExampleImagesCleanupService() use_case = StubImportUseCase() - handler = ExampleImagesManagementHandler(use_case, recorder) + handler = ExampleImagesManagementHandler(use_case, recorder, cleanup_service) request = object() import_response = await handler.import_example_images(request) assert json.loads(import_response.text) == {"status": "imported"} assert await handler.delete_example_image(request) == "delete" + cleanup_service.result = {"success": True} + cleanup_response = await handler.cleanup_example_image_folders(request) + assert json.loads(cleanup_response.text) == {"success": True} assert use_case.requests == [request] assert recorder.calls == [("delete_custom_image", request)] + assert len(cleanup_service.calls) == 1 @pytest.mark.asyncio @@ -403,7 +444,8 @@ def test_handler_set_route_mapping_includes_all_handlers() -> None: return {} download = ExampleImagesDownloadHandler(DummyUseCase(), DummyManager()) - management = ExampleImagesManagementHandler(DummyUseCase(), DummyProcessor()) + cleanup_service = StubExampleImagesCleanupService() + management = ExampleImagesManagementHandler(DummyUseCase(), DummyProcessor(), cleanup_service) files = ExampleImagesFileHandler(object()) handler_set = ExampleImagesHandlerSet( download=download, @@ -421,6 +463,7 @@ def test_handler_set_route_mapping_includes_all_handlers() -> None: "force_download_example_images", "import_example_images", "delete_example_image", + "cleanup_example_image_folders", "open_example_images_folder", "get_example_image_files", "has_example_images", diff --git a/tests/services/test_example_images_cleanup_service.py b/tests/services/test_example_images_cleanup_service.py new file mode 100644 index 00000000..8256557a --- /dev/null +++ b/tests/services/test_example_images_cleanup_service.py @@ -0,0 +1,86 @@ +from __future__ import annotations + +from pathlib import Path + +import pytest + +from py.services.example_images_cleanup_service import ExampleImagesCleanupService +from py.services.service_registry import ServiceRegistry +from py.services.settings_manager import settings + + +class StubScanner: + def __init__(self, valid_hashes: set[str] | None = None) -> None: + self._valid_hashes = valid_hashes or set() + + def has_hash(self, value: str) -> bool: + return value in self._valid_hashes + + +@pytest.mark.asyncio +async def test_cleanup_moves_empty_and_orphaned(tmp_path, monkeypatch): + service = ExampleImagesCleanupService() + + previous_path = settings.get('example_images_path') + settings.settings['example_images_path'] = str(tmp_path) + + try: + empty_folder = tmp_path / 'empty_folder' + empty_folder.mkdir() + + orphan_hash = 'a' * 64 + orphan_folder = tmp_path / orphan_hash + orphan_folder.mkdir() + (orphan_folder / 'image.png').write_text('data', encoding='utf-8') + + valid_hash = 'b' * 64 + valid_folder = tmp_path / valid_hash + valid_folder.mkdir() + (valid_folder / 'image.png').write_text('data', encoding='utf-8') + + matching_scanner = StubScanner({valid_hash}) + empty_scanner = StubScanner() + + async def get_matching_scanner(*_args, **_kwargs): + return matching_scanner + + async def get_empty_scanner(*_args, **_kwargs): + return empty_scanner + + monkeypatch.setattr(ServiceRegistry, 'get_lora_scanner', get_matching_scanner) + monkeypatch.setattr(ServiceRegistry, 'get_checkpoint_scanner', get_empty_scanner) + monkeypatch.setattr(ServiceRegistry, 'get_embedding_scanner', get_empty_scanner) + + result = await service.cleanup_example_image_folders() + + deleted_bucket = Path(result['deleted_root']) + assert result['success'] is True + assert result['moved_total'] == 2 + assert not empty_folder.exists() + assert not (deleted_bucket / 'empty_folder').exists() + assert (deleted_bucket / orphan_hash).exists() + assert not orphan_folder.exists() + assert valid_folder.exists() + + finally: + if previous_path is None: + settings.settings.pop('example_images_path', None) + else: + settings.settings['example_images_path'] = previous_path + + +@pytest.mark.asyncio +async def test_cleanup_handles_missing_path(monkeypatch): + service = ExampleImagesCleanupService() + + previous_path = settings.get('example_images_path') + settings.settings.pop('example_images_path', None) + + try: + result = await service.cleanup_example_image_folders() + finally: + if previous_path is not None: + settings.settings['example_images_path'] = previous_path + + assert result['success'] is False + assert result['error_code'] == 'path_not_configured' From 454536d6310f51425eea848e2395abfb7de741c7 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Tue, 23 Sep 2025 20:47:33 +0800 Subject: [PATCH 081/110] test(i18n): migrate localization tests into pytest suite --- test_i18n.py => tests/i18n/test_i18n.py | 129 +++++++++++++++--------- 1 file changed, 83 insertions(+), 46 deletions(-) rename test_i18n.py => tests/i18n/test_i18n.py (93%) diff --git a/test_i18n.py b/tests/i18n/test_i18n.py similarity index 93% rename from test_i18n.py rename to tests/i18n/test_i18n.py index f05ed6c9..1adf0dc9 100644 --- a/test_i18n.py +++ b/tests/i18n/test_i18n.py @@ -4,27 +4,31 @@ Test script to verify the updated i18n system works correctly. This tests both JavaScript loading and Python server-side functionality. """ -import os -import sys -import json -import re import glob -from typing import Set, Dict, List, Tuple, Any +import json +import os +import re +import sys +from pathlib import Path +from typing import Any, Dict, List, Set -# Add the parent directory to the path so we can import the modules -sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +ROOT_DIR = Path(__file__).resolve().parents[2] +if str(ROOT_DIR) not in sys.path: + sys.path.insert(0, str(ROOT_DIR)) -def test_json_files_exist(): + +def check_json_files_exist() -> bool: """Test that all JSON locale files exist and are valid JSON.""" print("Testing JSON locale files...") - return test_json_structure_validation() + return check_json_structure_validation() -def test_locale_files_structural_consistency(): + +def check_locale_files_structural_consistency() -> bool: """Test that all locale files have identical structure, line counts, and formatting.""" print("\nTesting locale files structural consistency...") - locales_dir = os.path.join(os.path.dirname(__file__), 'locales') - if not os.path.exists(locales_dir): + locales_dir = ROOT_DIR / 'locales' + if not locales_dir.exists(): print("❌ Locales directory does not exist!") return False @@ -50,7 +54,7 @@ def test_locale_files_structural_consistency(): success = True # Load and parse the reference file - reference_path = os.path.join(locales_dir, reference_file) + reference_path = locales_dir / reference_file try: with open(reference_path, 'r', encoding='utf-8') as f: reference_lines = f.readlines() @@ -69,7 +73,7 @@ def test_locale_files_structural_consistency(): # Compare each locale file with the reference for locale_file in locale_files[1:]: # Skip reference file - locale_path = os.path.join(locales_dir, locale_file) + locale_path = locales_dir / locale_file locale_name = locale_file.replace('.json', '') try: @@ -368,15 +372,15 @@ def normalize_structural_chars(structural_chars: str) -> str: return normalized.strip() -def test_locale_files_formatting_consistency(): +def check_locale_files_formatting_consistency() -> bool: """Test that all locale files have identical formatting (whitespace, indentation, etc.).""" print("\nTesting locale files formatting consistency...") - locales_dir = os.path.join(os.path.dirname(__file__), 'locales') + locales_dir = ROOT_DIR / 'locales' expected_locales = ['en', 'zh-CN', 'zh-TW', 'ja', 'ru', 'de', 'fr', 'es', 'ko'] # Read reference file (en.json) - reference_path = os.path.join(locales_dir, 'en.json') + reference_path = locales_dir / 'en.json' try: with open(reference_path, 'r', encoding='utf-8') as f: reference_lines = f.readlines() @@ -388,7 +392,7 @@ def test_locale_files_formatting_consistency(): # Compare each locale file for locale in expected_locales[1:]: # Skip 'en' as it's the reference - locale_path = os.path.join(locales_dir, f'{locale}.json') + locale_path = locales_dir / f'{locale}.json' if not os.path.exists(locale_path): print(f"❌ {locale}.json does not exist!") @@ -450,15 +454,15 @@ def test_locale_files_formatting_consistency(): return success -def test_locale_key_ordering(): +def check_locale_key_ordering() -> bool: """Test that all locale files maintain the same key ordering as the reference.""" print("\nTesting locale files key ordering...") - locales_dir = os.path.join(os.path.dirname(__file__), 'locales') + locales_dir = ROOT_DIR / 'locales' expected_locales = ['en', 'zh-CN', 'zh-TW', 'ja', 'ru', 'de', 'fr', 'es', 'ko'] # Load reference file - reference_path = os.path.join(locales_dir, 'en.json') + reference_path = locales_dir / 'en.json' try: with open(reference_path, 'r', encoding='utf-8') as f: reference_data = json.load(f, object_pairs_hook=lambda x: x) # Preserve order @@ -471,7 +475,7 @@ def test_locale_key_ordering(): success = True for locale in expected_locales[1:]: # Skip 'en' as it's the reference - locale_path = os.path.join(locales_dir, f'{locale}.json') + locale_path = locales_dir / f'{locale}.json' if not os.path.exists(locale_path): continue @@ -524,7 +528,7 @@ def get_key_order(data: Any, path: str = '') -> List[str]: return keys -def test_server_i18n(): +def check_server_i18n() -> bool: """Test the Python server-side i18n system.""" print("\nTesting Python server-side i18n...") @@ -579,14 +583,14 @@ def test_server_i18n(): traceback.print_exc() return False -def test_translation_completeness(): +def check_translation_completeness() -> bool: """Test that all languages have the same translation keys.""" print("\nTesting translation completeness...") - locales_dir = os.path.join(os.path.dirname(__file__), 'locales') + locales_dir = ROOT_DIR / 'locales' # Load English as reference - with open(os.path.join(locales_dir, 'en.json'), 'r', encoding='utf-8') as f: + with open(locales_dir / 'en.json', 'r', encoding='utf-8') as f: en_data = json.load(f) en_keys = get_all_translation_keys(en_data) @@ -596,7 +600,7 @@ def test_translation_completeness(): locales = ['zh-CN', 'zh-TW', 'ja', 'ru', 'de', 'fr', 'es', 'ko'] for locale in locales: - with open(os.path.join(locales_dir, f'{locale}.json'), 'r', encoding='utf-8') as f: + with open(locales_dir / f'{locale}.json', 'r', encoding='utf-8') as f: locale_data = json.load(f) locale_keys = get_all_translation_keys(locale_data) @@ -739,13 +743,13 @@ def get_all_translation_keys(data: dict, prefix: str = '', include_containers: b return keys -def test_static_code_analysis(): +def check_static_code_analysis() -> bool: """Test static code analysis to detect missing translation keys.""" # print("\nTesting static code analysis for translation keys...") # Load English translations as reference - locales_dir = os.path.join(os.path.dirname(__file__), 'locales') - with open(os.path.join(locales_dir, 'en.json'), 'r', encoding='utf-8') as f: + locales_dir = ROOT_DIR / 'locales' + with open(locales_dir / 'en.json', 'r', encoding='utf-8') as f: en_data = json.load(f) available_keys = get_all_translation_keys(en_data) @@ -771,7 +775,7 @@ def test_static_code_analysis(): } # Extract keys from JavaScript files - js_dir = os.path.join(os.path.dirname(__file__), 'static', 'js') + js_dir = ROOT_DIR / 'static' / 'js' js_files = [] if os.path.exists(js_dir): # Recursively find all JS files @@ -788,14 +792,14 @@ def test_static_code_analysis(): file_keys = file_keys - false_positives js_keys.update(file_keys) if file_keys: - rel_path = os.path.relpath(js_file, os.path.dirname(__file__)) + rel_path = os.path.relpath(js_file, ROOT_DIR) js_files_with_keys.append((rel_path, len(file_keys))) # print(f" Found {len(file_keys)} keys in {rel_path}") # print(f"Total unique keys found in JavaScript files: {len(js_keys)}") # Extract keys from HTML template files - templates_dir = os.path.join(os.path.dirname(__file__), 'templates') + templates_dir = ROOT_DIR / 'templates' html_files = [] if os.path.exists(templates_dir): html_files = glob.glob(os.path.join(templates_dir, '*.html')) @@ -810,7 +814,7 @@ def test_static_code_analysis(): file_keys = file_keys - false_positives html_keys.update(file_keys) if file_keys: - rel_path = os.path.relpath(html_file, os.path.dirname(__file__)) + rel_path = os.path.relpath(html_file, ROOT_DIR) html_files_with_keys.append((rel_path, len(file_keys))) # print(f" Found {len(file_keys)} keys in {rel_path}") @@ -884,12 +888,12 @@ def test_static_code_analysis(): return success -def test_json_structure_validation(): +def check_json_structure_validation() -> bool: """Test JSON file structure and syntax validation.""" print("\nTesting JSON file structure and syntax validation...") - locales_dir = os.path.join(os.path.dirname(__file__), 'locales') - if not os.path.exists(locales_dir): + locales_dir = ROOT_DIR / 'locales' + if not locales_dir.exists(): print("❌ Locales directory does not exist!") return False @@ -897,8 +901,8 @@ def test_json_structure_validation(): success = True for locale in expected_locales: - file_path = os.path.join(locales_dir, f'{locale}.json') - if not os.path.exists(file_path): + file_path = locales_dir / f'{locale}.json' + if not file_path.exists(): print(f"❌ {locale}.json does not exist!") success = False continue @@ -957,6 +961,39 @@ def test_json_structure_validation(): return success + +def test_json_files_are_valid(): + assert check_json_files_exist() + + +def test_locale_structures_match_reference(): + assert check_locale_files_structural_consistency() + + +def test_locale_formatting_matches_reference(): + assert check_locale_files_formatting_consistency() + + +def test_locale_key_order_matches_reference(): + assert check_locale_key_ordering() + + +def test_server_side_i18n_behaves_as_expected(): + assert check_server_i18n() + + +def test_translations_are_complete(): + assert check_translation_completeness() + + +def test_static_code_analysis_is_clean(): + assert check_static_code_analysis() + + +def test_json_structure_validation(): + assert check_json_structure_validation() + + def main(): """Run all tests.""" print("🚀 Testing updated i18n system...\n") @@ -964,31 +1001,31 @@ def main(): success = True # Test JSON files structure and syntax - if not test_json_files_exist(): + if not check_json_files_exist(): success = False # Test comprehensive structural consistency - if not test_locale_files_structural_consistency(): + if not check_locale_files_structural_consistency(): success = False # Test formatting consistency - if not test_locale_files_formatting_consistency(): + if not check_locale_files_formatting_consistency(): success = False # Test key ordering - if not test_locale_key_ordering(): + if not check_locale_key_ordering(): success = False # Test server i18n - if not test_server_i18n(): + if not check_server_i18n(): success = False # Test translation completeness - if not test_translation_completeness(): + if not check_translation_completeness(): success = False # Test static code analysis - if not test_static_code_analysis(): + if not check_static_code_analysis(): success = False print(f"\n{'🎉 All tests passed!' if success else '❌ Some tests failed!'}") From cd3e32bf4bb6e1ebedf01fe0b8208c1294a3a3ea Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Tue, 23 Sep 2025 20:49:44 +0800 Subject: [PATCH 082/110] feat(context-menu): add example image download entry --- locales/de.json | 5 ++++ locales/en.json | 5 ++++ locales/es.json | 5 ++++ locales/fr.json | 5 ++++ locales/ja.json | 5 ++++ locales/ko.json | 5 ++++ locales/ru.json | 5 ++++ locales/zh-CN.json | 5 ++++ locales/zh-TW.json | 5 ++++ .../ContextMenu/GlobalContextMenu.js | 29 +++++++++++++++++++ templates/components/context_menu.html | 3 ++ 11 files changed, 77 insertions(+) diff --git a/locales/de.json b/locales/de.json index 6f00b0ac..c6c31b35 100644 --- a/locales/de.json +++ b/locales/de.json @@ -123,6 +123,11 @@ } }, "globalContextMenu": { + "downloadExampleImages": { + "label": "[TODO: Translate] Download example images", + "missingPath": "[TODO: Translate] Set a download location before downloading example images.", + "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + }, "cleanupExampleImages": { "label": "Clean up example image folders", "success": "Moved {count} folder(s) to the deleted folder", diff --git a/locales/en.json b/locales/en.json index 13890105..608393f4 100644 --- a/locales/en.json +++ b/locales/en.json @@ -123,6 +123,11 @@ } }, "globalContextMenu": { + "downloadExampleImages": { + "label": "Download example images", + "missingPath": "Set a download location before downloading example images.", + "unavailable": "Example image downloads aren't available yet. Try again after the page finishes loading." + }, "cleanupExampleImages": { "label": "Clean up example image folders", "success": "Moved {count} folder(s) to the deleted folder", diff --git a/locales/es.json b/locales/es.json index fa32a89a..195af423 100644 --- a/locales/es.json +++ b/locales/es.json @@ -123,6 +123,11 @@ } }, "globalContextMenu": { + "downloadExampleImages": { + "label": "[TODO: Translate] Download example images", + "missingPath": "[TODO: Translate] Set a download location before downloading example images.", + "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + }, "cleanupExampleImages": { "label": "Clean up example image folders", "success": "Moved {count} folder(s) to the deleted folder", diff --git a/locales/fr.json b/locales/fr.json index a4f7eeba..7da19b5b 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -123,6 +123,11 @@ } }, "globalContextMenu": { + "downloadExampleImages": { + "label": "[TODO: Translate] Download example images", + "missingPath": "[TODO: Translate] Set a download location before downloading example images.", + "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + }, "cleanupExampleImages": { "label": "Clean up example image folders", "success": "Moved {count} folder(s) to the deleted folder", diff --git a/locales/ja.json b/locales/ja.json index 16c95020..9124d133 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -123,6 +123,11 @@ } }, "globalContextMenu": { + "downloadExampleImages": { + "label": "[TODO: Translate] Download example images", + "missingPath": "[TODO: Translate] Set a download location before downloading example images.", + "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + }, "cleanupExampleImages": { "label": "Clean up example image folders", "success": "Moved {count} folder(s) to the deleted folder", diff --git a/locales/ko.json b/locales/ko.json index 28b4e0d6..db319db1 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -123,6 +123,11 @@ } }, "globalContextMenu": { + "downloadExampleImages": { + "label": "[TODO: Translate] Download example images", + "missingPath": "[TODO: Translate] Set a download location before downloading example images.", + "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + }, "cleanupExampleImages": { "label": "Clean up example image folders", "success": "Moved {count} folder(s) to the deleted folder", diff --git a/locales/ru.json b/locales/ru.json index b07d77cd..ac33a1c1 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -123,6 +123,11 @@ } }, "globalContextMenu": { + "downloadExampleImages": { + "label": "[TODO: Translate] Download example images", + "missingPath": "[TODO: Translate] Set a download location before downloading example images.", + "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + }, "cleanupExampleImages": { "label": "Clean up example image folders", "success": "Moved {count} folder(s) to the deleted folder", diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 867c5c55..a54f9bdb 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -123,6 +123,11 @@ } }, "globalContextMenu": { + "downloadExampleImages": { + "label": "[TODO: Translate] Download example images", + "missingPath": "[TODO: Translate] Set a download location before downloading example images.", + "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + }, "cleanupExampleImages": { "label": "Clean up example image folders", "success": "Moved {count} folder(s) to the deleted folder", diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 9d285079..c18338a0 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -123,6 +123,11 @@ } }, "globalContextMenu": { + "downloadExampleImages": { + "label": "[TODO: Translate] Download example images", + "missingPath": "[TODO: Translate] Set a download location before downloading example images.", + "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + }, "cleanupExampleImages": { "label": "Clean up example image folders", "success": "Moved {count} folder(s) to the deleted folder", diff --git a/static/js/components/ContextMenu/GlobalContextMenu.js b/static/js/components/ContextMenu/GlobalContextMenu.js index 58785aba..deeacff9 100644 --- a/static/js/components/ContextMenu/GlobalContextMenu.js +++ b/static/js/components/ContextMenu/GlobalContextMenu.js @@ -1,5 +1,6 @@ import { BaseContextMenu } from './BaseContextMenu.js'; import { showToast } from '../../utils/uiHelpers.js'; +import { state } from '../../state/index.js'; export class GlobalContextMenu extends BaseContextMenu { constructor() { @@ -19,12 +20,40 @@ export class GlobalContextMenu extends BaseContextMenu { console.error('Failed to trigger example images cleanup:', error); }); break; + case 'download-example-images': + this.downloadExampleImages(menuItem).catch((error) => { + console.error('Failed to trigger example images download:', error); + }); + break; default: console.warn(`Unhandled global context menu action: ${action}`); break; } } + async downloadExampleImages(menuItem) { + const exampleImagesManager = window.exampleImagesManager; + + if (!exampleImagesManager) { + showToast('globalContextMenu.downloadExampleImages.unavailable', {}, 'error'); + return; + } + + const downloadPath = state?.global?.settings?.example_images_path; + if (!downloadPath) { + showToast('globalContextMenu.downloadExampleImages.missingPath', {}, 'warning'); + return; + } + + menuItem?.classList.add('disabled'); + + try { + await exampleImagesManager.handleDownloadButton(); + } finally { + menuItem?.classList.remove('disabled'); + } + } + async cleanupExampleImagesFolders(menuItem) { if (this._cleanupInProgress) { return; diff --git a/templates/components/context_menu.html b/templates/components/context_menu.html index 3d96e6cc..a575e1a8 100644 --- a/templates/components/context_menu.html +++ b/templates/components/context_menu.html @@ -85,6 +85,9 @@
    +
    + {{ t('globalContextMenu.downloadExampleImages.label') }} +
    {{ t('globalContextMenu.cleanupExampleImages.label') }}
    From 4d2c60d59b84ddc2221f33f82c588f54c21728a9 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Tue, 23 Sep 2025 22:00:20 +0800 Subject: [PATCH 083/110] fix(settings): persist language preference --- static/js/managers/SettingsManager.js | 32 ++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index edc66526..4c9b90b4 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -1151,13 +1151,15 @@ export class SettingsManager { async saveLanguageSetting() { const element = document.getElementById('languageSelect'); if (!element) return; - + const selectedLanguage = element.value; - + try { // Use the universal save method for language (frontend-only setting) await this.saveSetting('language', selectedLanguage); - + + this.persistLanguageToLocalStorage(selectedLanguage); + // Reload the page to apply the new language window.location.reload(); @@ -1166,6 +1168,30 @@ export class SettingsManager { } } + persistLanguageToLocalStorage(language) { + const STORAGE_PREFIX = 'lora_manager_'; + + try { + const storageKey = `${STORAGE_PREFIX}settings`; + const currentSettings = localStorage.getItem(storageKey); + let parsedSettings = {}; + + if (currentSettings) { + try { + parsedSettings = JSON.parse(currentSettings) || {}; + } catch (parseError) { + console.warn('Failed to parse existing settings from localStorage, resetting to defaults'); + parsedSettings = {}; + } + } + + parsedSettings.language = language; + localStorage.setItem(storageKey, JSON.stringify(parsedSettings)); + } catch (error) { + console.warn('Failed to persist language preference to localStorage:', error); + } + } + toggleInputVisibility(button) { const input = button.parentElement.querySelector('input'); const icon = button.querySelector('i'); From e5b712c082befcf0f3729a0dbba3a01056541d83 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Tue, 23 Sep 2025 22:00:31 +0800 Subject: [PATCH 084/110] fix(i18n): sync language with state settings --- static/js/i18n/index.js | 38 ++++++----------------- static/js/managers/SettingsManager.js | 44 +++++++++++---------------- 2 files changed, 27 insertions(+), 55 deletions(-) diff --git a/static/js/i18n/index.js b/static/js/i18n/index.js index 4e2a8259..79b79c08 100644 --- a/static/js/i18n/index.js +++ b/static/js/i18n/index.js @@ -1,3 +1,5 @@ +import { state } from '../state/index.js'; + /** * Internationalization (i18n) system for LoRA Manager * Uses user-selected language from settings with fallback to English @@ -123,26 +125,12 @@ class I18nManager { * @returns {string} Language code */ getLanguageFromSettings() { - // Check localStorage for user-selected language - const STORAGE_PREFIX = 'lora_manager_'; - let userLanguage = null; - - try { - const settings = localStorage.getItem(STORAGE_PREFIX + 'settings'); - if (settings) { - const parsedSettings = JSON.parse(settings); - userLanguage = parsedSettings.language; - } - } catch (e) { - console.warn('Failed to parse settings from localStorage:', e); + const language = state?.global?.settings?.language; + + if (language && this.availableLocales[language]) { + return language; } - - // If user has selected a language, use it - if (userLanguage && this.availableLocales[userLanguage]) { - return userLanguage; - } - - // Fallback to English + return 'en'; } @@ -165,18 +153,10 @@ class I18nManager { this.readyPromise = this.initializeWithLocale(languageCode); await this.readyPromise; - // Save to localStorage - const STORAGE_PREFIX = 'lora_manager_'; - const currentSettings = localStorage.getItem(STORAGE_PREFIX + 'settings'); - let settings = {}; - - if (currentSettings) { - settings = JSON.parse(currentSettings); + if (state?.global?.settings) { + state.global.settings.language = languageCode; } - settings.language = languageCode; - localStorage.setItem(STORAGE_PREFIX + 'settings', JSON.stringify(settings)); - console.log(`Language changed to: ${languageCode}`); // Dispatch event to notify components of language change diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index 4c9b90b4..b6ffe6c2 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -4,6 +4,7 @@ import { state, createDefaultSettings } from '../state/index.js'; import { resetAndReload } from '../api/modelApiFactory.js'; import { DOWNLOAD_PATH_TEMPLATES, MAPPABLE_BASE_MODELS, PATH_TEMPLATE_PLACEHOLDERS, DEFAULT_PATH_TEMPLATES } from '../utils/constants.js'; import { translate } from '../utils/i18nHelpers.js'; +import { i18n } from '../i18n/index.js'; export class SettingsManager { constructor() { @@ -57,9 +58,26 @@ export class SettingsManager { state.global.settings = this.mergeSettingsWithDefaults(); } + await this.applyLanguageSetting(); this.applyFrontendSettings(); } + async applyLanguageSetting() { + const desiredLanguage = state?.global?.settings?.language; + + if (!desiredLanguage) { + return; + } + + try { + if (i18n.getCurrentLocale() !== desiredLanguage) { + await i18n.setLanguage(desiredLanguage); + } + } catch (error) { + console.warn('Failed to apply language from settings:', error); + } + } + mergeSettingsWithDefaults(backendSettings = {}) { const defaults = createDefaultSettings(); const merged = { ...defaults, ...backendSettings }; @@ -1158,8 +1176,6 @@ export class SettingsManager { // Use the universal save method for language (frontend-only setting) await this.saveSetting('language', selectedLanguage); - this.persistLanguageToLocalStorage(selectedLanguage); - // Reload the page to apply the new language window.location.reload(); @@ -1168,30 +1184,6 @@ export class SettingsManager { } } - persistLanguageToLocalStorage(language) { - const STORAGE_PREFIX = 'lora_manager_'; - - try { - const storageKey = `${STORAGE_PREFIX}settings`; - const currentSettings = localStorage.getItem(storageKey); - let parsedSettings = {}; - - if (currentSettings) { - try { - parsedSettings = JSON.parse(currentSettings) || {}; - } catch (parseError) { - console.warn('Failed to parse existing settings from localStorage, resetting to defaults'); - parsedSettings = {}; - } - } - - parsedSettings.language = language; - localStorage.setItem(storageKey, JSON.stringify(parsedSettings)); - } catch (error) { - console.warn('Failed to persist language preference to localStorage:', error); - } - } - toggleInputVisibility(button) { const input = button.parentElement.querySelector('input'); const icon = button.querySelector('i'); From dde7cf71c64f74a9d2365255f4c56d6c0407a361 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Tue, 23 Sep 2025 22:24:57 +0800 Subject: [PATCH 085/110] fix(locales): translate global context menu entries for downloading example images --- locales/de.json | 16 ++++++++-------- locales/es.json | 16 ++++++++-------- locales/fr.json | 16 ++++++++-------- locales/ja.json | 16 ++++++++-------- locales/ko.json | 16 ++++++++-------- locales/ru.json | 16 ++++++++-------- locales/zh-CN.json | 16 ++++++++-------- locales/zh-TW.json | 16 ++++++++-------- 8 files changed, 64 insertions(+), 64 deletions(-) diff --git a/locales/de.json b/locales/de.json index c6c31b35..34bed5e5 100644 --- a/locales/de.json +++ b/locales/de.json @@ -124,16 +124,16 @@ }, "globalContextMenu": { "downloadExampleImages": { - "label": "[TODO: Translate] Download example images", - "missingPath": "[TODO: Translate] Set a download location before downloading example images.", - "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + "label": "Beispielbilder herunterladen", + "missingPath": "Bitte legen Sie einen Speicherort fest, bevor Sie Beispielbilder herunterladen.", + "unavailable": "Beispielbild-Downloads sind noch nicht verfügbar. Versuchen Sie es erneut, nachdem die Seite vollständig geladen ist." }, "cleanupExampleImages": { - "label": "Clean up example image folders", - "success": "Moved {count} folder(s) to the deleted folder", - "none": "No example image folders needed cleanup", - "partial": "Cleanup completed with {failures} folder(s) skipped", - "error": "Failed to clean example image folders: {message}" + "label": "Beispielbild-Ordner bereinigen", + "success": "{count} Ordner wurden in den Papierkorb verschoben", + "none": "Keine Beispielbild-Ordner mussten bereinigt werden", + "partial": "Bereinigung abgeschlossen, {failures} Ordner übersprungen", + "error": "Fehler beim Bereinigen der Beispielbild-Ordner: {message}" } }, "header": { diff --git a/locales/es.json b/locales/es.json index 195af423..4c77b163 100644 --- a/locales/es.json +++ b/locales/es.json @@ -124,16 +124,16 @@ }, "globalContextMenu": { "downloadExampleImages": { - "label": "[TODO: Translate] Download example images", - "missingPath": "[TODO: Translate] Set a download location before downloading example images.", - "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + "label": "Descargar imágenes de ejemplo", + "missingPath": "Establece una ubicación de descarga antes de descargar imágenes de ejemplo.", + "unavailable": "Las descargas de imágenes de ejemplo aún no están disponibles. Intenta de nuevo después de que la página termine de cargar." }, "cleanupExampleImages": { - "label": "Clean up example image folders", - "success": "Moved {count} folder(s) to the deleted folder", - "none": "No example image folders needed cleanup", - "partial": "Cleanup completed with {failures} folder(s) skipped", - "error": "Failed to clean example image folders: {message}" + "label": "Limpiar carpetas de imágenes de ejemplo", + "success": "Se movieron {count} carpeta(s) a la carpeta de eliminados", + "none": "No hay carpetas de imágenes de ejemplo que necesiten limpieza", + "partial": "Limpieza completada con {failures} carpeta(s) omitidas", + "error": "No se pudieron limpiar las carpetas de imágenes de ejemplo: {message}" } }, "header": { diff --git a/locales/fr.json b/locales/fr.json index 7da19b5b..fe9a37bf 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -124,16 +124,16 @@ }, "globalContextMenu": { "downloadExampleImages": { - "label": "[TODO: Translate] Download example images", - "missingPath": "[TODO: Translate] Set a download location before downloading example images.", - "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + "label": "Télécharger les images d'exemple", + "missingPath": "Définissez un emplacement de téléchargement avant de télécharger les images d'exemple.", + "unavailable": "Le téléchargement des images d'exemple n'est pas encore disponible. Réessayez après le chargement complet de la page." }, "cleanupExampleImages": { - "label": "Clean up example image folders", - "success": "Moved {count} folder(s) to the deleted folder", - "none": "No example image folders needed cleanup", - "partial": "Cleanup completed with {failures} folder(s) skipped", - "error": "Failed to clean example image folders: {message}" + "label": "Nettoyer les dossiers d'images d'exemple", + "success": "{count} dossier(s) déplacé(s) vers le dossier supprimé", + "none": "Aucun dossier d'images d'exemple à nettoyer", + "partial": "Nettoyage terminé avec {failures} dossier(s) ignoré(s)", + "error": "Échec du nettoyage des dossiers d'images d'exemple : {message}" } }, "header": { diff --git a/locales/ja.json b/locales/ja.json index 9124d133..b0d48ea2 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -124,16 +124,16 @@ }, "globalContextMenu": { "downloadExampleImages": { - "label": "[TODO: Translate] Download example images", - "missingPath": "[TODO: Translate] Set a download location before downloading example images.", - "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + "label": "例画像をダウンロード", + "missingPath": "例画像をダウンロードする前にダウンロード場所を設定してください。", + "unavailable": "例画像のダウンロードはまだ利用できません。ページの読み込みが完了してから再度お試しください。" }, "cleanupExampleImages": { - "label": "Clean up example image folders", - "success": "Moved {count} folder(s) to the deleted folder", - "none": "No example image folders needed cleanup", - "partial": "Cleanup completed with {failures} folder(s) skipped", - "error": "Failed to clean example image folders: {message}" + "label": "例画像フォルダをクリーンアップ", + "success": "{count} 個のフォルダを削除フォルダに移動しました", + "none": "クリーンアップが必要な例画像フォルダはありません", + "partial": "クリーンアップが完了しましたが、{failures} 個のフォルダはスキップされました", + "error": "例画像フォルダのクリーンアップに失敗しました:{message}" } }, "header": { diff --git a/locales/ko.json b/locales/ko.json index db319db1..3772ca87 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -124,16 +124,16 @@ }, "globalContextMenu": { "downloadExampleImages": { - "label": "[TODO: Translate] Download example images", - "missingPath": "[TODO: Translate] Set a download location before downloading example images.", - "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + "label": "예시 이미지 다운로드", + "missingPath": "예시 이미지를 다운로드하기 전에 다운로드 위치를 설정하세요.", + "unavailable": "예시 이미지 다운로드는 아직 사용할 수 없습니다. 페이지 로딩이 완료된 후 다시 시도하세요." }, "cleanupExampleImages": { - "label": "Clean up example image folders", - "success": "Moved {count} folder(s) to the deleted folder", - "none": "No example image folders needed cleanup", - "partial": "Cleanup completed with {failures} folder(s) skipped", - "error": "Failed to clean example image folders: {message}" + "label": "예시 이미지 폴더 정리", + "success": "{count}개의 폴더가 삭제 폴더로 이동되었습니다", + "none": "정리가 필요한 예시 이미지 폴더가 없습니다", + "partial": "정리가 완료되었으나 {failures}개의 폴더가 건너뛰어졌습니다", + "error": "예시 이미지 폴더 정리에 실패했습니다: {message}" } }, "header": { diff --git a/locales/ru.json b/locales/ru.json index ac33a1c1..6eb08a83 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -124,16 +124,16 @@ }, "globalContextMenu": { "downloadExampleImages": { - "label": "[TODO: Translate] Download example images", - "missingPath": "[TODO: Translate] Set a download location before downloading example images.", - "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + "label": "Загрузить примеры изображений", + "missingPath": "Укажите место загрузки перед загрузкой примеров изображений.", + "unavailable": "Загрузка примеров изображений пока недоступна. Попробуйте снова после полной загрузки страницы." }, "cleanupExampleImages": { - "label": "Clean up example image folders", - "success": "Moved {count} folder(s) to the deleted folder", - "none": "No example image folders needed cleanup", - "partial": "Cleanup completed with {failures} folder(s) skipped", - "error": "Failed to clean example image folders: {message}" + "label": "Очистить папки с примерами изображений", + "success": "Перемещено {count} папок в папку удалённых", + "none": "Нет папок с примерами изображений, требующих очистки", + "partial": "Очистка завершена, пропущено {failures} папок", + "error": "Не удалось очистить папки с примерами изображений: {message}" } }, "header": { diff --git a/locales/zh-CN.json b/locales/zh-CN.json index a54f9bdb..b88e94fe 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -124,16 +124,16 @@ }, "globalContextMenu": { "downloadExampleImages": { - "label": "[TODO: Translate] Download example images", - "missingPath": "[TODO: Translate] Set a download location before downloading example images.", - "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + "label": "下载示例图片", + "missingPath": "请先设置下载位置后再下载示例图片。", + "unavailable": "示例图片下载当前不可用。请在页面加载完成后重试。" }, "cleanupExampleImages": { - "label": "Clean up example image folders", - "success": "Moved {count} folder(s) to the deleted folder", - "none": "No example image folders needed cleanup", - "partial": "Cleanup completed with {failures} folder(s) skipped", - "error": "Failed to clean example image folders: {message}" + "label": "清理示例图片文件夹", + "success": "已将 {count} 个文件夹移动到已删除文件夹", + "none": "没有需要清理的示例图片文件夹", + "partial": "清理完成,有 {failures} 个文件夹跳过", + "error": "清理示例图片文件夹失败:{message}" } }, "header": { diff --git a/locales/zh-TW.json b/locales/zh-TW.json index c18338a0..1c0b7c50 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -124,16 +124,16 @@ }, "globalContextMenu": { "downloadExampleImages": { - "label": "[TODO: Translate] Download example images", - "missingPath": "[TODO: Translate] Set a download location before downloading example images.", - "unavailable": "[TODO: Translate] Example image downloads aren't available yet. Try again after the page finishes loading." + "label": "下載範例圖片", + "missingPath": "請先設定下載位置再下載範例圖片。", + "unavailable": "範例圖片下載目前尚不可用。請在頁面載入完成後再試一次。" }, "cleanupExampleImages": { - "label": "Clean up example image folders", - "success": "Moved {count} folder(s) to the deleted folder", - "none": "No example image folders needed cleanup", - "partial": "Cleanup completed with {failures} folder(s) skipped", - "error": "Failed to clean example image folders: {message}" + "label": "清理範例圖片資料夾", + "success": "已將 {count} 個資料夾移至已刪除資料夾", + "none": "沒有需要清理的範例圖片資料夾", + "partial": "清理完成,有 {failures} 個資料夾略過", + "error": "清理範例圖片資料夾失敗:{message}" } }, "header": { From ae145de2f231bfe4bd6a9f3633730df98cda24e9 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Tue, 23 Sep 2025 23:05:55 +0800 Subject: [PATCH 086/110] feat(tests): add frontend automated testing setup with Vitest and jsdom --- .gitignore | 2 + docs/frontend-testing-roadmap.md | 23 + package-lock.json | 2572 ++++++++++++++++++++++++++++++ package.json | 14 + static/js/state/index.test.js | 53 + tests/frontend/setup.js | 16 + vitest.config.js | 17 + 7 files changed, 2697 insertions(+) create mode 100644 docs/frontend-testing-roadmap.md create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 static/js/state/index.test.js create mode 100644 tests/frontend/setup.js create mode 100644 vitest.config.js diff --git a/.gitignore b/.gitignore index 7b15029e..bae77cab 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ py/run_test.py .vscode/ cache/ civitai/ +node_modules/ +coverage/ diff --git a/docs/frontend-testing-roadmap.md b/docs/frontend-testing-roadmap.md new file mode 100644 index 00000000..628b5b1e --- /dev/null +++ b/docs/frontend-testing-roadmap.md @@ -0,0 +1,23 @@ +# Frontend Automation Testing Roadmap + +This roadmap tracks the planned rollout of automated testing for the ComfyUI LoRA Manager frontend. Each phase builds on the infrastructure introduced in this change set and records progress so future contributors can quickly identify the next tasks. + +## Phase Overview + +| Phase | Goal | Primary Focus | Status | Notes | +| --- | --- | --- | --- | --- | +| Phase 0 | Establish baseline tooling | Add Node test runner, jsdom environment, and seed smoke tests | ✅ Complete | Vitest + jsdom configured, example state tests committed | +| Phase 1 | Cover state management logic | Unit test selectors, derived data helpers, and storage utilities under `static/js/state` and `static/js/utils` | 🟡 In Progress | Prioritize deterministic scenarios for `storageHelpers`, `AppState` derivatives, and regression cases for migrations | +| Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | ⚪ Not Started | Requires DOM fixtures from `templates/*.html` and stubbing of manager modules | +| Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | ⚪ Not Started | Consider shared helpers for mocking API modules and storage | +| Phase 4 | Interaction-level regression tests | Exercise template fragments, modals, and menus to ensure UI wiring remains intact | ⚪ Not Started | Evaluate Playwright component testing or happy-path DOM snapshots | +| Phase 5 | Continuous integration & coverage | Integrate frontend tests into CI workflow and track coverage metrics | ⚪ Not Started | Align reporting directories with backend coverage for unified reporting | + +## Next Steps Checklist + +- [ ] Expand unit tests for `storageHelpers` covering migrations and namespace behavior. +- [ ] Document DOM fixture strategy for reproducing template structures in tests. +- [ ] Prototype AppCore initialization test that verifies manager bootstrapping with stubbed dependencies. +- [ ] Evaluate integrating coverage reporting once test surface grows (> 20 specs). + +Maintaining this roadmap alongside code changes will make it easier to append new automated test tasks and update their progress. diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..875f7d6a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2572 @@ +{ + "name": "comfyui-lora-manager-frontend", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "comfyui-lora-manager-frontend", + "version": "0.1.0", + "devDependencies": { + "jsdom": "^24.0.0", + "vitest": "^1.6.0" + } + }, + "node_modules/@asamuzakjp/css-color": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", + "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.3", + "@csstools/css-color-parser": "^3.0.9", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.1.0", + "@csstools/css-calc": "^2.1.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.2.tgz", + "integrity": "sha512-o3pcKzJgSGt4d74lSZ+OCnHwkKBeAbFDmbEm5gg70eA8VkyCuC/zV9TwBnmw6VjDlRdF4Pshfb+WE9E6XY1PoQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.2.tgz", + "integrity": "sha512-cqFSWO5tX2vhC9hJTK8WAiPIm4Q8q/cU8j2HQA0L3E1uXvBYbOZMhE2oFL8n2pKB5sOCHY6bBuHaRwG7TkfJyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.2.tgz", + "integrity": "sha512-vngduywkkv8Fkh3wIZf5nFPXzWsNsVu1kvtLETWxTFf/5opZmflgVSeLgdHR56RQh71xhPhWoOkEBvbehwTlVA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.2.tgz", + "integrity": "sha512-h11KikYrUCYTrDj6h939hhMNlqU2fo/X4NB0OZcys3fya49o1hmFaczAiJWVAFgrM1NCP6RrO7lQKeVYSKBPSQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.2.tgz", + "integrity": "sha512-/eg4CI61ZUkLXxMHyVlmlGrSQZ34xqWlZNW43IAU4RmdzWEx0mQJ2mN/Cx4IHLVZFL6UBGAh+/GXhgvGb+nVxw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.2.tgz", + "integrity": "sha512-QOWgFH5X9+p+S1NAfOqc0z8qEpJIoUHf7OWjNUGOeW18Mx22lAUOiA9b6r2/vpzLdfxi/f+VWsYjUOMCcYh0Ng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.2.tgz", + "integrity": "sha512-kDWSPafToDd8LcBYd1t5jw7bD5Ojcu12S3uT372e5HKPzQt532vW+rGFFOaiR0opxePyUkHrwz8iWYEyH1IIQA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.2.tgz", + "integrity": "sha512-gKm7Mk9wCv6/rkzwCiUC4KnevYhlf8ztBrDRT9g/u//1fZLapSRc+eDZj2Eu2wpJ+0RzUKgtNijnVIB4ZxyL+w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.2.tgz", + "integrity": "sha512-66lA8vnj5mB/rtDNwPgrrKUOtCLVQypkyDa2gMfOefXK6rcZAxKLO9Fy3GkW8VkPnENv9hBkNOFfGLf6rNKGUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.2.tgz", + "integrity": "sha512-s+OPucLNdJHvuZHuIz2WwncJ+SfWHFEmlC5nKMUgAelUeBUnlB4wt7rXWiyG4Zn07uY2Dd+SGyVa9oyLkVGOjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.2.tgz", + "integrity": "sha512-8wTRM3+gVMDLLDdaT6tKmOE3lJyRy9NpJUS/ZRWmLCmOPIJhVyXwjBo+XbrrwtV33Em1/eCTd5TuGJm4+DmYjw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.2.tgz", + "integrity": "sha512-6yqEfgJ1anIeuP2P/zhtfBlDpXUb80t8DpbYwXQ3bQd95JMvUaqiX+fKqYqUwZXqdJDd8xdilNtsHM2N0cFm6A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.2.tgz", + "integrity": "sha512-sshYUiYVSEI2B6dp4jMncwxbrUqRdNApF2c3bhtLAU0qA8Lrri0p0NauOsTWh3yCCCDyBOjESHMExonp7Nzc0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.2.tgz", + "integrity": "sha512-duBLgd+3pqC4MMwBrKkFxaZerUxZcYApQVC5SdbF5/e/589GwVvlRUnyqMFbM8iUSb1BaoX/3fRL7hB9m2Pj8Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.2.tgz", + "integrity": "sha512-tzhYJJidDUVGMgVyE+PmxENPHlvvqm1KILjjZhB8/xHYqAGeizh3GBGf9u6WdJpZrz1aCpIIHG0LgJgH9rVjHQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.2.tgz", + "integrity": "sha512-opH8GSUuVcCSSyHHcl5hELrmnk4waZoVpgn/4FDao9iyE4WpQhyWJ5ryl5M3ocp4qkRuHfyXnGqg8M9oKCEKRA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.2.tgz", + "integrity": "sha512-LSeBHnGli1pPKVJ79ZVJgeZWWZXkEe/5o8kcn23M8eMKCUANejchJbF/JqzM4RRjOJfNRhKJk8FuqL1GKjF5oQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.2.tgz", + "integrity": "sha512-uPj7MQ6/s+/GOpolavm6BPo+6CbhbKYyZHUDvZ/SmJM7pfDBgdGisFX3bY/CBDMg2ZO4utfhlApkSfZ92yXw7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.2.tgz", + "integrity": "sha512-Z9MUCrSgIaUeeHAiNkm3cQyst2UhzjPraR3gYYfOjAuZI7tcFRTOD+4cHLPoS/3qinchth+V56vtqz1Tv+6KPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.2.tgz", + "integrity": "sha512-+GnYBmpjldD3XQd+HMejo+0gJGwYIOfFeoBQv32xF/RUIvccUz20/V6Otdv+57NE70D5pa8W/jVGDoGq0oON4A==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.2.tgz", + "integrity": "sha512-ApXFKluSB6kDQkAqZOKXBjiaqdF1BlKi+/eqnYe9Ee7U2K3pUDKsIyr8EYm/QDHTJIM+4X+lI0gJc3TTRhd+dA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.2.tgz", + "integrity": "sha512-ARz+Bs8kY6FtitYM96PqPEVvPXqEZmPZsSkXvyX19YzDqkCaIlhCieLLMI5hxO9SRZ2XtCtm8wxhy0iJ2jxNfw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitest/expect": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.1.tgz", + "integrity": "sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "1.6.1", + "@vitest/utils": "1.6.1", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.1.tgz", + "integrity": "sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "1.6.1", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.1.tgz", + "integrity": "sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.1.tgz", + "integrity": "sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.1.tgz", + "integrity": "sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssstyle": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", + "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^3.2.0", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cssstyle/node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsdom": { + "version": "24.1.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.3.tgz", + "integrity": "sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.0.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.4", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/local-pkg": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz", + "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mlly": "^1.7.3", + "pkg-types": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/magic-string": { + "version": "0.30.19", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", + "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mlly": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" + } + }, + "node_modules/mlly/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nwsapi": { + "version": "2.2.22", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.22.tgz", + "integrity": "sha512-ujSMe1OWVn55euT1ihwCI1ZcAaAU3nxUiDwfDQldc51ZXaB9m2AyOn6/jh1BLe2t/G8xd6uKG1UBF2aZJeg2SQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/pkg-types/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.52.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.2.tgz", + "integrity": "sha512-I25/2QgoROE1vYV+NQ1En9T9UFB9Cmfm2CJ83zZOlaDpvz29wGQSZXWKw7MiNXau7wYgB/T9fVIdIuEQ+KbiiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.52.2", + "@rollup/rollup-android-arm64": "4.52.2", + "@rollup/rollup-darwin-arm64": "4.52.2", + "@rollup/rollup-darwin-x64": "4.52.2", + "@rollup/rollup-freebsd-arm64": "4.52.2", + "@rollup/rollup-freebsd-x64": "4.52.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.2", + "@rollup/rollup-linux-arm-musleabihf": "4.52.2", + "@rollup/rollup-linux-arm64-gnu": "4.52.2", + "@rollup/rollup-linux-arm64-musl": "4.52.2", + "@rollup/rollup-linux-loong64-gnu": "4.52.2", + "@rollup/rollup-linux-ppc64-gnu": "4.52.2", + "@rollup/rollup-linux-riscv64-gnu": "4.52.2", + "@rollup/rollup-linux-riscv64-musl": "4.52.2", + "@rollup/rollup-linux-s390x-gnu": "4.52.2", + "@rollup/rollup-linux-x64-gnu": "4.52.2", + "@rollup/rollup-linux-x64-musl": "4.52.2", + "@rollup/rollup-openharmony-arm64": "4.52.2", + "@rollup/rollup-win32-arm64-msvc": "4.52.2", + "@rollup/rollup-win32-ia32-msvc": "4.52.2", + "@rollup/rollup-win32-x64-gnu": "4.52.2", + "@rollup/rollup-win32-x64-msvc": "4.52.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "dev": true, + "license": "MIT" + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-literal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.1.tgz", + "integrity": "sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", + "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/vite": { + "version": "5.4.20", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.20.tgz", + "integrity": "sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.1.tgz", + "integrity": "sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.1.tgz", + "integrity": "sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "1.6.1", + "@vitest/runner": "1.6.1", + "@vitest/snapshot": "1.6.1", + "@vitest/spy": "1.6.1", + "@vitest/utils": "1.6.1", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.3", + "vite": "^5.0.0", + "vite-node": "1.6.1", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.6.1", + "@vitest/ui": "1.6.1", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/yocto-queue": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", + "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..6f4a7229 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "comfyui-lora-manager-frontend", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "test": "vitest run", + "test:watch": "vitest" + }, + "devDependencies": { + "jsdom": "^24.0.0", + "vitest": "^1.6.0" + } +} diff --git a/static/js/state/index.test.js b/static/js/state/index.test.js new file mode 100644 index 00000000..da9221ea --- /dev/null +++ b/static/js/state/index.test.js @@ -0,0 +1,53 @@ +import { describe, it, expect, beforeEach } from 'vitest'; +import { createDefaultSettings, getCurrentPageState, initPageState, setCurrentPageType, state } from './index.js'; +import { MODEL_TYPES } from '../api/apiConfig.js'; +import { DEFAULT_PATH_TEMPLATES } from '../utils/constants.js'; + +describe('state module', () => { + beforeEach(() => { + // Reset to default page before each assertion + state.currentPageType = MODEL_TYPES.LORA; + }); + + it('creates default settings with immutable template copies', () => { + const defaultSettings = createDefaultSettings(); + + expect(defaultSettings).toMatchObject({ + civitai_api_key: '', + language: 'en', + blur_mature_content: true + }); + + expect(defaultSettings.download_path_templates).toEqual(DEFAULT_PATH_TEMPLATES); + + // ensure nested objects are new references so tests can safely mutate + expect(defaultSettings.download_path_templates).not.toBe(DEFAULT_PATH_TEMPLATES); + expect(defaultSettings.base_model_path_mappings).toEqual({}); + expect(Object.isFrozen(defaultSettings)).toBe(false); + }); + + it('switches current page type when valid', () => { + const didSwitch = setCurrentPageType(MODEL_TYPES.CHECKPOINT); + + expect(didSwitch).toBe(true); + expect(state.currentPageType).toBe(MODEL_TYPES.CHECKPOINT); + expect(getCurrentPageState()).toBe(state.pages[MODEL_TYPES.CHECKPOINT]); + }); + + it('rejects switching to an unknown page type', () => { + state.currentPageType = MODEL_TYPES.LORA; + + const didSwitch = setCurrentPageType('invalid-page'); + + expect(didSwitch).toBe(false); + expect(state.currentPageType).toBe(MODEL_TYPES.LORA); + }); + + it('initializes and returns state for a known page', () => { + const pageState = initPageState(MODEL_TYPES.EMBEDDING); + + expect(pageState).toBeDefined(); + expect(pageState).toBe(state.pages[MODEL_TYPES.EMBEDDING]); + expect(state.currentPageType).toBe(MODEL_TYPES.EMBEDDING); + }); +}); diff --git a/tests/frontend/setup.js b/tests/frontend/setup.js new file mode 100644 index 00000000..d575c568 --- /dev/null +++ b/tests/frontend/setup.js @@ -0,0 +1,16 @@ +import { afterEach, beforeEach } from 'vitest'; + +beforeEach(() => { + // Ensure storage is clean before each test to avoid cross-test pollution + localStorage.clear(); + sessionStorage.clear(); + + // Reset DOM state for modules that rely on body attributes + document.body.innerHTML = ''; + document.body.dataset.page = ''; +}); + +afterEach(() => { + // Clean any dynamically attached globals by tests + delete document.body.dataset.page; +}); diff --git a/vitest.config.js b/vitest.config.js new file mode 100644 index 00000000..f0dd3877 --- /dev/null +++ b/vitest.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + environment: 'jsdom', + globals: true, + setupFiles: ['tests/frontend/setup.js'], + include: [ + 'static/js/**/*.test.js', + 'tests/frontend/**/*.test.js' + ], + coverage: { + enabled: false, + reportsDirectory: 'coverage/frontend' + } + } +}); From 4653c273e32497833f77ffe42065e3597d2b073f Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Wed, 24 Sep 2025 05:20:39 +0800 Subject: [PATCH 087/110] test(frontend): add storage and core initialization specs --- docs/frontend-testing-roadmap.md | 8 +- static/js/core.test.js | 277 +++++++++++++++++++++++++ static/js/utils/storageHelpers.test.js | 142 +++++++++++++ 3 files changed, 423 insertions(+), 4 deletions(-) create mode 100644 static/js/core.test.js create mode 100644 static/js/utils/storageHelpers.test.js diff --git a/docs/frontend-testing-roadmap.md b/docs/frontend-testing-roadmap.md index 628b5b1e..e39e7c03 100644 --- a/docs/frontend-testing-roadmap.md +++ b/docs/frontend-testing-roadmap.md @@ -7,17 +7,17 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR | Phase | Goal | Primary Focus | Status | Notes | | --- | --- | --- | --- | --- | | Phase 0 | Establish baseline tooling | Add Node test runner, jsdom environment, and seed smoke tests | ✅ Complete | Vitest + jsdom configured, example state tests committed | -| Phase 1 | Cover state management logic | Unit test selectors, derived data helpers, and storage utilities under `static/js/state` and `static/js/utils` | 🟡 In Progress | Prioritize deterministic scenarios for `storageHelpers`, `AppState` derivatives, and regression cases for migrations | -| Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | ⚪ Not Started | Requires DOM fixtures from `templates/*.html` and stubbing of manager modules | +| Phase 1 | Cover state management logic | Unit test selectors, derived data helpers, and storage utilities under `static/js/state` and `static/js/utils` | ✅ Complete | Storage helpers and state selectors now exercised via deterministic suites | +| Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | 🟡 In Progress | AppCore initialization specs landed; expand to additional page wiring and scroll hooks | | Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | ⚪ Not Started | Consider shared helpers for mocking API modules and storage | | Phase 4 | Interaction-level regression tests | Exercise template fragments, modals, and menus to ensure UI wiring remains intact | ⚪ Not Started | Evaluate Playwright component testing or happy-path DOM snapshots | | Phase 5 | Continuous integration & coverage | Integrate frontend tests into CI workflow and track coverage metrics | ⚪ Not Started | Align reporting directories with backend coverage for unified reporting | ## Next Steps Checklist -- [ ] Expand unit tests for `storageHelpers` covering migrations and namespace behavior. +- [x] Expand unit tests for `storageHelpers` covering migrations and namespace behavior. - [ ] Document DOM fixture strategy for reproducing template structures in tests. -- [ ] Prototype AppCore initialization test that verifies manager bootstrapping with stubbed dependencies. +- [x] Prototype AppCore initialization test that verifies manager bootstrapping with stubbed dependencies. - [ ] Evaluate integrating coverage reporting once test surface grows (> 20 specs). Maintaining this roadmap alongside code changes will make it easier to append new automated test tasks and update their progress. diff --git a/static/js/core.test.js b/static/js/core.test.js new file mode 100644 index 00000000..e39d5af0 --- /dev/null +++ b/static/js/core.test.js @@ -0,0 +1,277 @@ +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; + +const migrateStorageItemsMock = vi.fn(); +const initializeInfiniteScrollMock = vi.fn(); +const initThemeMock = vi.fn(); +const initBackToTopMock = vi.fn(); +const initializeEventManagementMock = vi.fn(); +const createPageContextMenuMock = vi.fn().mockReturnValue('page-menu'); +const createGlobalContextMenuMock = vi.fn().mockReturnValue('global-menu'); +const bulkManagerInitializeMock = vi.fn(); +const setBulkContextMenuMock = vi.fn(); +const helpManagerInitializeMock = vi.fn(); +const updateServiceInitializeMock = vi.fn(); +const bannerServiceInitializeMock = vi.fn(); +const isBannerVisibleMock = vi.fn().mockReturnValue(false); +const onboardingStartMock = vi.fn(); +const settingsWaitMock = vi.fn().mockResolvedValue(); +const i18nWaitMock = vi.fn().mockResolvedValue(); +const i18nLocaleMock = vi.fn().mockReturnValue('en'); + +const mockState = { + currentPageType: 'loras', + global: { + settings: { + card_info_display: 'hover' + } + } +}; + +const mockModalManager = { initialize: vi.fn() }; +const mockBulkManager = { + initialize: bulkManagerInitializeMock, + setBulkContextMenu: setBulkContextMenuMock +}; +const mockHelpManager = { initialize: helpManagerInitializeMock }; +const mockUpdateService = { initialize: updateServiceInitializeMock }; +const mockBannerService = { + initialize: bannerServiceInitializeMock, + isBannerVisible: isBannerVisibleMock +}; +const mockOnboardingManager = { start: onboardingStartMock }; +const mockSettingsManager = { waitForInitialization: settingsWaitMock }; +const mockMoveManager = {}; +const mockI18n = { + waitForReady: i18nWaitMock, + getCurrentLocale: i18nLocaleMock +}; + +const loadingManagerInstances = []; +const HeaderManagerInstances = []; +const bulkContextMenuInstances = []; +const exampleImagesManagerInitializeMock = vi.fn(); + +const LoadingManagerMock = vi.fn(() => { + const instance = { id: Symbol('LoadingManager') }; + loadingManagerInstances.push(instance); + return instance; +}); + +const HeaderManagerMock = vi.fn(() => { + const instance = { id: Symbol('HeaderManager') }; + HeaderManagerInstances.push(instance); + return instance; +}); + +const BulkContextMenuMock = vi.fn(() => { + const instance = { id: Symbol('BulkContextMenu') }; + bulkContextMenuInstances.push(instance); + return instance; +}); + +const ExampleImagesManagerMock = vi.fn(() => { + const instance = { initialize: exampleImagesManagerInitializeMock }; + globalThis.exampleImagesManager = instance; + return instance; +}); + +vi.stubGlobal('exampleImagesManager', null); + +vi.mock('./utils/storageHelpers.js', () => ({ + migrateStorageItems: migrateStorageItemsMock +})); + +vi.mock('./state/index.js', () => ({ + state: mockState +})); + +vi.mock('./managers/LoadingManager.js', () => ({ + LoadingManager: LoadingManagerMock +})); + +vi.mock('./managers/ModalManager.js', () => ({ + ModalManager: vi.fn(), + modalManager: mockModalManager +})); + +vi.mock('./managers/UpdateService.js', () => ({ + updateService: mockUpdateService +})); + +vi.mock('./components/Header.js', () => ({ + HeaderManager: HeaderManagerMock +})); + +vi.mock('./managers/SettingsManager.js', () => ({ + settingsManager: mockSettingsManager +})); + +vi.mock('./managers/MoveManager.js', () => ({ + moveManager: mockMoveManager +})); + +vi.mock('./managers/BulkManager.js', () => ({ + bulkManager: mockBulkManager +})); + +vi.mock('./managers/ExampleImagesManager.js', () => ({ + ExampleImagesManager: ExampleImagesManagerMock +})); + +vi.mock('./managers/HelpManager.js', () => ({ + helpManager: mockHelpManager +})); + +vi.mock('./managers/BannerService.js', () => ({ + bannerService: mockBannerService +})); + +vi.mock('./utils/uiHelpers.js', () => ({ + initTheme: initThemeMock, + initBackToTop: initBackToTopMock +})); + +vi.mock('./utils/infiniteScroll.js', () => ({ + initializeInfiniteScroll: initializeInfiniteScrollMock +})); + +vi.mock('./i18n/index.js', () => ({ + i18n: mockI18n +})); + +vi.mock('./managers/OnboardingManager.js', () => ({ + onboardingManager: mockOnboardingManager +})); + +vi.mock('./components/ContextMenu/BulkContextMenu.js', () => ({ + BulkContextMenu: BulkContextMenuMock +})); + +vi.mock('./components/ContextMenu/index.js', () => ({ + createPageContextMenu: createPageContextMenuMock, + createGlobalContextMenu: createGlobalContextMenuMock +})); + +vi.mock('./utils/eventManagementInit.js', () => ({ + initializeEventManagement: initializeEventManagementMock +})); + +beforeEach(() => { + vi.clearAllMocks(); + document.body.innerHTML = ''; + document.body.removeAttribute('data-page'); + mockState.currentPageType = 'loras'; + mockState.global.settings.card_info_display = 'hover'; + isBannerVisibleMock.mockReturnValue(false); + loadingManagerInstances.length = 0; + HeaderManagerInstances.length = 0; + bulkContextMenuInstances.length = 0; + delete window.pageContextMenu; + delete window.globalContextMenuInstance; +}); + +afterEach(() => { + vi.useRealTimers(); +}); + +const loadCoreModule = async () => { + vi.resetModules(); + return import('./core.js'); +}; + +describe('AppCore module bootstrapping', () => { + it('registers storage migration on DOMContentLoaded', async () => { + const addEventListenerSpy = vi.spyOn(document, 'addEventListener'); + await loadCoreModule(); + + expect(addEventListenerSpy).toHaveBeenCalledWith('DOMContentLoaded', expect.any(Function)); + const listener = addEventListenerSpy.mock.calls.find(([event]) => event === 'DOMContentLoaded')[1]; + listener(); + expect(migrateStorageItemsMock).toHaveBeenCalledTimes(1); + }); + + it('initializes managers, UI helpers, and onboarding sequence', async () => { + vi.useFakeTimers(); + const { AppCore } = await loadCoreModule(); + const appCore = new AppCore(); + + document.body.dataset.page = 'loras'; + + const result = await appCore.initialize(); + + expect(result).toBe(appCore); + expect(i18nWaitMock).toHaveBeenCalled(); + expect(i18nLocaleMock).toHaveBeenCalled(); + expect(settingsWaitMock).toHaveBeenCalled(); + + expect(LoadingManagerMock).toHaveBeenCalledTimes(1); + const loadingInstance = LoadingManagerMock.mock.results[0].value; + expect(mockState.loadingManager).toBe(loadingInstance); + + expect(mockModalManager.initialize).toHaveBeenCalled(); + expect(updateServiceInitializeMock).toHaveBeenCalled(); + expect(bannerServiceInitializeMock).toHaveBeenCalled(); + expect(window.modalManager).toBe(mockModalManager); + expect(window.settingsManager).toBe(mockSettingsManager); + expect(window.bulkManager).toBe(mockBulkManager); + expect(window.helpManager).toBe(mockHelpManager); + + expect(HeaderManagerMock).toHaveBeenCalledTimes(1); + expect(initThemeMock).toHaveBeenCalled(); + expect(initBackToTopMock).toHaveBeenCalled(); + + expect(bulkManagerInitializeMock).toHaveBeenCalled(); + expect(BulkContextMenuMock).toHaveBeenCalledTimes(1); + expect(setBulkContextMenuMock).toHaveBeenCalledWith(bulkContextMenuInstances[0]); + + expect(ExampleImagesManagerMock).toHaveBeenCalledTimes(1); + expect(exampleImagesManagerInitializeMock).toHaveBeenCalled(); + expect(helpManagerInitializeMock).toHaveBeenCalled(); + + expect(document.body.classList.contains('hover-reveal')).toBe(true); + expect(initializeEventManagementMock).toHaveBeenCalled(); + + vi.runAllTimers(); + expect(onboardingStartMock).toHaveBeenCalled(); + }); + + it('skips bulk manager when recipes page is active', async () => { + const { AppCore } = await loadCoreModule(); + const appCore = new AppCore(); + mockState.currentPageType = 'recipes'; + + await appCore.initialize(); + + expect(bulkManagerInitializeMock).not.toHaveBeenCalled(); + expect(BulkContextMenuMock).not.toHaveBeenCalled(); + expect(setBulkContextMenuMock).not.toHaveBeenCalled(); + }); + + it('initializes page features with context menus and infinite scroll', async () => { + const { AppCore } = await loadCoreModule(); + const appCore = new AppCore(); + document.body.dataset.page = 'loras'; + + appCore.initializeContextMenus = vi.fn(appCore.initializeContextMenus.bind(appCore)); + + appCore.initializePageFeatures(); + + expect(appCore.initializeContextMenus).toHaveBeenCalledWith('loras'); + expect(initializeInfiniteScrollMock).toHaveBeenCalledWith('loras'); + expect(createPageContextMenuMock).toHaveBeenCalledWith('loras'); + expect(window.pageContextMenu).toBe('page-menu'); + expect(createGlobalContextMenuMock).toHaveBeenCalled(); + expect(window.globalContextMenuInstance).toBe('global-menu'); + }); + + it('does not reinitialize once initialized', async () => { + const { AppCore } = await loadCoreModule(); + const appCore = new AppCore(); + + await appCore.initialize(); + await appCore.initialize(); + + expect(i18nWaitMock).toHaveBeenCalledTimes(1); + expect(settingsWaitMock).toHaveBeenCalledTimes(1); + }); +}); diff --git a/static/js/utils/storageHelpers.test.js b/static/js/utils/storageHelpers.test.js new file mode 100644 index 00000000..ed19b967 --- /dev/null +++ b/static/js/utils/storageHelpers.test.js @@ -0,0 +1,142 @@ +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; +import * as storageHelpers from './storageHelpers.js'; + +const { + getStorageItem, + setStorageItem, + removeStorageItem, + getSessionItem, + setSessionItem, + removeSessionItem, + migrateStorageItems +} = storageHelpers; + +const createFakeStorage = () => { + const store = new Map(); + return { + getItem: vi.fn((key) => (store.has(key) ? store.get(key) : null)), + setItem: vi.fn((key, value) => { + store.set(key, value); + }), + removeItem: vi.fn((key) => { + store.delete(key); + }), + clear: vi.fn(() => { + store.clear(); + }), + key: vi.fn((index) => Array.from(store.keys())[index] ?? null), + get length() { + return store.size; + }, + _store: store + }; +}; + +let localStorageMock; +let sessionStorageMock; +let consoleLogMock; + +beforeEach(() => { + localStorageMock = createFakeStorage(); + sessionStorageMock = createFakeStorage(); + vi.stubGlobal('localStorage', localStorageMock); + vi.stubGlobal('sessionStorage', sessionStorageMock); + consoleLogMock = vi.spyOn(console, 'log').mockImplementation(() => {}); +}); + +afterEach(() => { + vi.unstubAllGlobals(); + vi.restoreAllMocks(); +}); + +describe('storageHelpers namespace utilities', () => { + it('returns parsed JSON for prefixed localStorage items', () => { + localStorage.setItem('lora_manager_preferences', JSON.stringify({ theme: 'dark' })); + + const result = getStorageItem('preferences'); + + expect(result).toEqual({ theme: 'dark' }); + expect(localStorage.getItem).toHaveBeenCalledWith('lora_manager_preferences'); + }); + + it('falls back to legacy keys and migrates them to the namespace', () => { + localStorage.setItem('legacy_key', 'value'); + + const value = getStorageItem('legacy_key'); + + expect(value).toBe('value'); + expect(localStorage.getItem('lora_manager_legacy_key')).toBe('value'); + }); + + it('serializes objects when setting prefixed localStorage values', () => { + const data = { ids: [1, 2, 3] }; + + setStorageItem('data', data); + + expect(localStorage.setItem).toHaveBeenCalledWith('lora_manager_data', JSON.stringify(data)); + expect(localStorage.getItem('lora_manager_data')).toEqual(JSON.stringify(data)); + }); + + it('removes both prefixed and legacy localStorage entries', () => { + localStorage.setItem('lora_manager_temp', '123'); + localStorage.setItem('temp', '456'); + + removeStorageItem('temp'); + + expect(localStorage.getItem('lora_manager_temp')).toBeNull(); + expect(localStorage.getItem('temp')).toBeNull(); + }); + + it('returns parsed JSON for session storage items', () => { + sessionStorage.setItem('lora_manager_session', JSON.stringify({ page: 'loras' })); + + const session = getSessionItem('session'); + + expect(session).toEqual({ page: 'loras' }); + }); + + it('stores primitives in session storage directly', () => { + setSessionItem('token', 'abc123'); + + expect(sessionStorage.setItem).toHaveBeenCalledWith('lora_manager_token', 'abc123'); + expect(sessionStorage.getItem('lora_manager_token')).toBe('abc123'); + }); + + it('removes session storage entries by namespace', () => { + sessionStorage.setItem('lora_manager_flag', '1'); + + removeSessionItem('flag'); + + expect(sessionStorage.getItem('lora_manager_flag')).toBeNull(); + }); +}); + +describe('migrateStorageItems', () => { + it('migrates known keys and logs completion', () => { + const setStorageSpy = vi.spyOn(storageHelpers, 'setStorageItem'); + localStorage.setItem('theme', '"light"'); + localStorage.setItem('loras_filters', JSON.stringify({ sort: 'asc' })); + localStorage.setItem('nsfwBlurLevel', '3'); + + migrateStorageItems(); + + expect(setStorageSpy).toHaveBeenCalledTimes(3); + expect(localStorage.getItem('lora_manager_theme')).toBe('light'); + expect(localStorage.getItem('lora_manager_loras_filters')).toBe(JSON.stringify({ sort: 'asc' })); + expect(localStorage.getItem('loras_filters')).toBeNull(); + expect(localStorage.getItem('lora_manager_nsfwBlurLevel')).toBe('3'); + expect(localStorage.getItem('nsfwBlurLevel')).toBeNull(); + expect(localStorage.getItem('lora_manager_migration_completed')).toBe('true'); + expect(consoleLogMock).toHaveBeenCalledWith('Lora Manager: Storage migration completed'); + }); + + it('skips migration when already completed and logs notice', () => { + const setStorageSpy = vi.spyOn(storageHelpers, 'setStorageItem'); + localStorage.setItem('lora_manager_migration_completed', 'true'); + + migrateStorageItems(); + + expect(setStorageSpy).not.toHaveBeenCalled(); + expect(consoleLogMock).toHaveBeenCalledWith('Lora Manager: Storage migration already completed'); + }); +}); From 4b4b8fe3c1c7a6ce9944ac7de8595032be603436 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Wed, 24 Sep 2025 05:41:30 +0800 Subject: [PATCH 088/110] refactor: remove unused ModelRouteUtils class and its methods --- py/utils/routes_common.py | 868 -------------------------------------- 1 file changed, 868 deletions(-) delete mode 100644 py/utils/routes_common.py diff --git a/py/utils/routes_common.py b/py/utils/routes_common.py deleted file mode 100644 index 642bfcad..00000000 --- a/py/utils/routes_common.py +++ /dev/null @@ -1,868 +0,0 @@ -import os -import json -import logging -from typing import Dict, Callable, Awaitable -from aiohttp import web -from datetime import datetime - -from .model_utils import determine_base_model -from .constants import PREVIEW_EXTENSIONS, CARD_PREVIEW_WIDTH -from ..config import config -from ..services.service_registry import ServiceRegistry -from ..services.downloader import get_downloader -from ..utils.exif_utils import ExifUtils -from ..utils.metadata_manager import MetadataManager -from ..services.websocket_manager import ws_manager -from ..services.metadata_service import get_default_metadata_provider, get_metadata_provider -from ..services.settings_manager import settings - -logger = logging.getLogger(__name__) - -# TODO: retire this class -class ModelRouteUtils: - """Shared utilities for model routes (LoRAs, Checkpoints, etc.)""" - - @staticmethod - async def load_local_metadata(metadata_path: str) -> Dict: - """Load local metadata file""" - if os.path.exists(metadata_path): - try: - with open(metadata_path, 'r', encoding='utf-8') as f: - return json.load(f) - except Exception as e: - logger.error(f"Error loading metadata from {metadata_path}: {e}") - return {} - - @staticmethod - async def handle_not_found_on_civitai(metadata_path: str, local_metadata: Dict) -> None: - """Handle case when model is not found on CivitAI""" - local_metadata['from_civitai'] = False - await MetadataManager.save_metadata(metadata_path, local_metadata) - - @staticmethod - def is_civitai_api_metadata(meta: dict) -> bool: - """ - Determine if the given civitai metadata is from the civitai API. - Returns True if both 'files' and 'images' exist and are non-empty, - and the 'source' is not 'archive_db'. - """ - if not isinstance(meta, dict): - return False - files = meta.get('files') - images = meta.get('images') - source = meta.get('source') - return bool(files) and bool(images) and source != 'archive_db' - - @staticmethod - async def update_model_metadata(metadata_path: str, local_metadata: Dict, - civitai_metadata: Dict, metadata_provider=None) -> None: - """Update local metadata with CivitAI data""" - # Save existing trainedWords and customImages if they exist - existing_civitai = local_metadata.get('civitai') or {} # Use empty dict if None - - # Check if we should skip the update to avoid overwriting richer data - if civitai_metadata.get('source') == 'archive_db' and ModelRouteUtils.is_civitai_api_metadata(existing_civitai): - logger.info(f"Skip civitai update for {local_metadata.get('model_name', '')} ({existing_civitai.get('name', '')})") - else: - # Create a new civitai metadata by updating existing with new - merged_civitai = existing_civitai.copy() - merged_civitai.update(civitai_metadata) - - if civitai_metadata.get('source') == 'archive_db': - model_name = civitai_metadata.get('model', {}).get('name', '') - version_name = civitai_metadata.get('name', '') - logger.info(f"Recovered metadata from archive_db for deleted model: {model_name} ({version_name})") - - # Special handling for trainedWords - ensure we don't lose any existing trained words - if 'trainedWords' in existing_civitai: - existing_trained_words = existing_civitai.get('trainedWords', []) - new_trained_words = civitai_metadata.get('trainedWords', []) - # Use a set to combine words without duplicates, then convert back to list - merged_trained_words = list(set(existing_trained_words + new_trained_words)) - merged_civitai['trainedWords'] = merged_trained_words - - # Update local metadata with merged civitai data - local_metadata['civitai'] = merged_civitai - - # Update model-related metadata from civitai_metadata.model - if 'model' in civitai_metadata and civitai_metadata['model']: - model_data = civitai_metadata['model'] - - # Update model name if available and not already set - if model_data.get('name'): - local_metadata['model_name'] = model_data['name'] - - # Update modelDescription if missing or empty in local_metadata - if not local_metadata.get('modelDescription') and model_data.get('description'): - local_metadata['modelDescription'] = model_data['description'] - - # Update tags if missing or empty in local_metadata - if not local_metadata.get('tags') and model_data.get('tags'): - local_metadata['tags'] = model_data['tags'] - - # Update creator in civitai metadata if missing - if model_data.get('creator') and not local_metadata.get('civitai', {}).get('creator'): - if 'civitai' not in local_metadata: - local_metadata['civitai'] = {} - local_metadata['civitai']['creator'] = model_data['creator'] - - # Update base model - local_metadata['base_model'] = determine_base_model(civitai_metadata.get('baseModel')) - - # Update preview if needed - if not local_metadata.get('preview_url') or not os.path.exists(local_metadata['preview_url']): - first_preview = next((img for img in civitai_metadata.get('images', [])), None) - if (first_preview): - # Determine if content is video or image - is_video = first_preview['type'] == 'video' - - if is_video: - # For videos use .mp4 extension - preview_ext = '.mp4' - else: - # For images use .webp extension - preview_ext = '.webp' - - base_name = os.path.splitext(os.path.splitext(os.path.basename(metadata_path))[0])[0] - preview_filename = base_name + preview_ext - preview_path = os.path.join(os.path.dirname(metadata_path), preview_filename) - - if is_video: - # Download video as is using downloader - downloader = await get_downloader() - success, result = await downloader.download_file( - first_preview['url'], - preview_path, - use_auth=False - ) - if success: - local_metadata['preview_url'] = preview_path.replace(os.sep, '/') - local_metadata['preview_nsfw_level'] = first_preview.get('nsfwLevel', 0) - else: - # For images, download and then optimize to WebP using downloader - downloader = await get_downloader() - success, content, headers = await downloader.download_to_memory( - first_preview['url'], - use_auth=False - ) - if success: - try: - # Optimize and convert to WebP - optimized_data, _ = ExifUtils.optimize_image( - image_data=content, # Use downloaded content directly - target_width=CARD_PREVIEW_WIDTH, - format='webp', - quality=85, - preserve_metadata=False - ) - - # Save the optimized WebP image - with open(preview_path, 'wb') as f: - f.write(optimized_data) - - # Update metadata - local_metadata['preview_url'] = preview_path.replace(os.sep, '/') - local_metadata['preview_nsfw_level'] = first_preview.get('nsfwLevel', 0) - - except Exception as e: - logger.error(f"Error optimizing preview image: {e}") - # If optimization fails, save the original content - try: - with open(preview_path, 'wb') as f: - f.write(content) - local_metadata['preview_url'] = preview_path.replace(os.sep, '/') - local_metadata['preview_nsfw_level'] = first_preview.get('nsfwLevel', 0) - except Exception as save_error: - logger.error(f"Error saving preview image: {save_error}") - - # Save updated metadata - await MetadataManager.save_metadata(metadata_path, local_metadata) - - @staticmethod - async def fetch_and_update_model( - sha256: str, - file_path: str, - model_data: dict, - update_cache_func: Callable[[str, str, Dict], Awaitable[bool]] - ) -> tuple[bool, str]: - """Fetch and update metadata for a single model - - Args: - sha256: SHA256 hash of the model file - file_path: Path to the model file - model_data: The model object in cache to update - update_cache_func: Function to update the cache with new metadata - - Returns: - tuple[bool, str]: (success, error_message). When success is True, error_message is None. - """ - try: - # Validate input parameters - if not isinstance(model_data, dict): - error_msg = f"Invalid model_data type: {type(model_data)}" - logger.error(error_msg) - return False, error_msg - - metadata_path = os.path.splitext(file_path)[0] + '.metadata.json' - enable_metadata_archive_db = settings.get('enable_metadata_archive_db', False) - - if model_data.get('civitai_deleted') is True: - # If CivitAI deleted flag is set, skip CivitAI API provider - if not enable_metadata_archive_db or model_data.get('db_checked') is True: - return False, "CivitAI model is deleted and metadata archive DB is not enabled" - # Likely deleted from CivitAI, use archive_db if available - metadata_provider = await get_metadata_provider('sqlite') - else: - metadata_provider = await get_default_metadata_provider() - - civitai_metadata, error = await metadata_provider.get_model_by_hash(sha256) - if not civitai_metadata: - if error == "Model not found": - model_data['from_civitai'] = False - model_data['civitai_deleted'] = True - model_data['db_checked'] = enable_metadata_archive_db - model_data['last_checked_at'] = datetime.now().timestamp() - - # Remove 'folder' key from model_data if present before saving - data_to_save = model_data.copy() - data_to_save.pop('folder', None) - await MetadataManager.save_metadata(file_path, data_to_save) - - # For other errors, log and return False with error message - error_msg = f"Error fetching metadata: {error} (model_name={model_data.get('model_name', '')})" - logger.error(error_msg) - return False, error_msg - - model_data['from_civitai'] = True - model_data['civitai_deleted'] = civitai_metadata.get('source') == 'archive_db' - model_data['db_checked'] = enable_metadata_archive_db - model_data['last_checked_at'] = datetime.now().timestamp() - - local_metadata = model_data.copy() - local_metadata.pop('folder', None) # Remove 'folder' key if present - - # Update metadata - await ModelRouteUtils.update_model_metadata( - metadata_path, - local_metadata, - civitai_metadata, - metadata_provider - ) - - # Update cache object directly using safe .get() method - update_dict = { - 'model_name': local_metadata.get('model_name'), - 'preview_url': local_metadata.get('preview_url'), - 'civitai': local_metadata.get('civitai'), - } - model_data.update(update_dict) - - # Update cache using the provided function - await update_cache_func(file_path, file_path, local_metadata) - - return True, None - - except KeyError as e: - error_msg = f"Error fetching metadata - Missing key: {e} in model_data={model_data}" - logger.error(error_msg) - return False, error_msg - except Exception as e: - error_msg = f"Error fetching metadata: {str(e)}" - logger.error(error_msg, exc_info=True) # Include stack trace - return False, error_msg - - @staticmethod - def filter_civitai_data(data: Dict, minimal: bool = False) -> Dict: - """Filter relevant fields from CivitAI data""" - if not data: - return {} - - fields = ["id", "modelId", "name", "trainedWords"] if minimal else [ - "id", "modelId", "name", "createdAt", "updatedAt", - "publishedAt", "trainedWords", "baseModel", "description", - "model", "images", "customImages", "creator" - ] - return {k: data[k] for k in fields if k in data} - - @staticmethod - async def handle_fetch_civitai(request: web.Request, scanner) -> web.Response: - """Handle CivitAI metadata fetch request - - Args: - request: The aiohttp request - scanner: The model scanner instance with cache management methods - - Returns: - web.Response: The HTTP response with metadata on success - """ - try: - data = await request.json() - metadata_path = os.path.splitext(data['file_path'])[0] + '.metadata.json' - - # Check if model metadata exists - local_metadata = await ModelRouteUtils.load_local_metadata(metadata_path) - if not local_metadata or not local_metadata.get('sha256'): - return web.json_response({"success": False, "error": "No SHA256 hash found"}, status=400) - - # Get metadata provider and fetch from unified provider - metadata_provider = await get_default_metadata_provider() - - # Fetch and update metadata - civitai_metadata, error = await metadata_provider.get_model_by_hash(local_metadata["sha256"]) - if not civitai_metadata: - await ModelRouteUtils.handle_not_found_on_civitai(metadata_path, local_metadata) - return web.json_response({"success": False, "error": error}, status=404) - - await ModelRouteUtils.update_model_metadata(metadata_path, local_metadata, civitai_metadata, metadata_provider) - - # Update the cache - await scanner.update_single_model_cache(data['file_path'], data['file_path'], local_metadata) - - # Return the updated metadata along with success status - return web.json_response({"success": True, "metadata": local_metadata}) - - except Exception as e: - logger.error(f"Error fetching from CivitAI: {e}", exc_info=True) - return web.json_response({"success": False, "error": str(e)}, status=500) - - @staticmethod - async def handle_replace_preview(request: web.Request, scanner) -> web.Response: - """Handle preview image replacement request""" - try: - reader = await request.multipart() - - # Read preview file data - field = await reader.next() - if field.name != 'preview_file': - raise ValueError("Expected 'preview_file' field") - content_type = field.headers.get('Content-Type', 'image/png') - - # Try to get original filename if available - content_disposition = field.headers.get('Content-Disposition', '') - original_filename = None - import re - filename_match = re.search(r'filename="(.*?)"', content_disposition) - if filename_match: - original_filename = filename_match.group(1) - - preview_data = await field.read() - - # Read model path - field = await reader.next() - if field.name != 'model_path': - raise ValueError("Expected 'model_path' field") - model_path = (await field.read()).decode() - - # Read NSFW level - nsfw_level = 0 # Default to 0 (unknown) - field = await reader.next() - if field and field.name == 'nsfw_level': - try: - nsfw_level = int((await field.read()).decode()) - except (ValueError, TypeError): - logger.warning("Invalid NSFW level format, using default 0") - - # Save preview file - base_name = os.path.splitext(os.path.basename(model_path))[0] - folder = os.path.dirname(model_path) - - # Determine format based on content type and original filename - is_gif = False - if original_filename and original_filename.lower().endswith('.gif'): - is_gif = True - elif content_type.lower() == 'image/gif': - is_gif = True - - # Determine if content is video or image and handle specific formats - if content_type.startswith('video/'): - # For videos, preserve original format if possible - if original_filename: - extension = os.path.splitext(original_filename)[1].lower() - # Default to .mp4 if no extension or unrecognized - if not extension or extension not in ['.mp4', '.webm', '.mov', '.avi']: - extension = '.mp4' - else: - # Try to determine extension from content type - if 'webm' in content_type: - extension = '.webm' - else: - extension = '.mp4' # Default - optimized_data = preview_data # No optimization for videos - elif is_gif: - # Preserve GIF format without optimization - extension = '.gif' - optimized_data = preview_data - else: - # For other images, optimize and convert to WebP - optimized_data, _ = ExifUtils.optimize_image( - image_data=preview_data, - target_width=CARD_PREVIEW_WIDTH, - format='webp', - quality=85, - preserve_metadata=False - ) - extension = '.webp' - - # Delete any existing preview files for this model - for ext in PREVIEW_EXTENSIONS: - existing_preview = os.path.join(folder, base_name + ext) - if os.path.exists(existing_preview): - try: - os.remove(existing_preview) - logger.debug(f"Deleted existing preview: {existing_preview}") - except Exception as e: - logger.warning(f"Failed to delete existing preview {existing_preview}: {e}") - - preview_path = os.path.join(folder, base_name + extension).replace(os.sep, '/') - - with open(preview_path, 'wb') as f: - f.write(optimized_data) - - # Update preview path and NSFW level in metadata - metadata_path = os.path.splitext(model_path)[0] + '.metadata.json' - if os.path.exists(metadata_path): - try: - with open(metadata_path, 'r', encoding='utf-8') as f: - metadata = json.load(f) - - # Update preview_url and preview_nsfw_level in the metadata dict - metadata['preview_url'] = preview_path - metadata['preview_nsfw_level'] = nsfw_level - - await MetadataManager.save_metadata(model_path, metadata) - except Exception as e: - logger.error(f"Error updating metadata: {e}") - - # Update preview URL in scanner cache - await scanner.update_preview_in_cache(model_path, preview_path, nsfw_level) - - return web.json_response({ - "success": True, - "preview_url": config.get_preview_static_url(preview_path), - "preview_nsfw_level": nsfw_level - }) - - except Exception as e: - logger.error(f"Error replacing preview: {e}", exc_info=True) - return web.Response(text=str(e), status=500) - - @staticmethod - async def handle_download_model(request: web.Request) -> web.Response: - """Handle model download request""" - try: - download_manager = await ServiceRegistry.get_download_manager() - data = await request.json() - - # Get or generate a download ID - download_id = data.get('download_id', ws_manager.generate_download_id()) - - # Create progress callback with download ID - async def progress_callback(progress): - await ws_manager.broadcast_download_progress(download_id, { - 'status': 'progress', - 'progress': progress, - 'download_id': download_id - }) - - # Check which identifier is provided and convert to int - model_id = None - model_version_id = None - - if data.get('model_id'): - try: - model_id = int(data.get('model_id')) - except (TypeError, ValueError): - return web.json_response({ - 'success': False, - 'error': "Invalid model_id: Must be an integer" - }, status=400) - - # Convert model_version_id to int if provided - if data.get('model_version_id'): - try: - model_version_id = int(data.get('model_version_id')) - except (TypeError, ValueError): - return web.json_response({ - 'success': False, - 'error': "Invalid model_version_id: Must be an integer" - }, status=400) - - # At least one identifier is required - if not model_id and not model_version_id: - return web.json_response({ - 'success': False, - 'error': "Missing required parameter: Please provide either 'model_id' or 'model_version_id'" - }, status=400) - - use_default_paths = data.get('use_default_paths', False) - source = data.get('source') # Optional source parameter - - # Pass the download_id to download_from_civitai - result = await download_manager.download_from_civitai( - model_id=model_id, - model_version_id=model_version_id, - save_dir=data.get('model_root'), - relative_path=data.get('relative_path', ''), - use_default_paths=use_default_paths, - progress_callback=progress_callback, - download_id=download_id, # Pass download_id explicitly - source=source # Pass source parameter - ) - - # Include download_id in the response - result['download_id'] = download_id - - if not result.get('success', False): - error_message = result.get('error', 'Unknown error') - - return web.json_response({ - 'success': False, - 'error': error_message, - 'download_id': download_id - }, status=500) - - return web.json_response(result) - - except Exception as e: - error_message = str(e) - - # Check if this might be an early access error - if '401' in error_message: - logger.warning(f"Early access error (401): {error_message}") - return web.json_response({ - 'success': False, - 'error': "Early Access Restriction: This model requires purchase. Please buy early access on Civitai.com." - }, status=401) - - logger.error(f"Error downloading model: {error_message}") - return web.json_response({ - 'success': False, - 'error': error_message - }, status=500) - - @staticmethod - async def handle_cancel_download(request: web.Request) -> web.Response: - """Handle cancellation of a download task - - Args: - request: The aiohttp request - - Returns: - web.Response: The HTTP response - """ - try: - download_manager = await ServiceRegistry.get_download_manager() - download_id = request.match_info.get('download_id') - if not download_id: - return web.json_response({ - 'success': False, - 'error': 'Download ID is required' - }, status=400) - - result = await download_manager.cancel_download(download_id) - - # Notify clients about cancellation via WebSocket - await ws_manager.broadcast_download_progress(download_id, { - 'status': 'cancelled', - 'progress': 0, - 'download_id': download_id, - 'message': 'Download cancelled by user' - }) - - return web.json_response(result) - - except Exception as e: - logger.error(f"Error cancelling download: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - @staticmethod - async def handle_list_downloads(request: web.Request) -> web.Response: - """Get list of active downloads - - Args: - request: The aiohttp request - - Returns: - web.Response: The HTTP response with list of downloads - """ - try: - download_manager = await ServiceRegistry.get_download_manager() - result = await download_manager.get_active_downloads() - return web.json_response(result) - except Exception as e: - logger.error(f"Error listing downloads: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - @staticmethod - async def handle_relink_civitai(request: web.Request, scanner) -> web.Response: - """Handle CivitAI metadata re-linking request by model ID and/or version ID - - Args: - request: The aiohttp request - scanner: The model scanner instance with cache management methods - - Returns: - web.Response: The HTTP response - """ - try: - data = await request.json() - file_path = data.get('file_path') - model_id = int(data.get('model_id')) - model_version_id = None - if data.get('model_version_id'): - model_version_id = int(data.get('model_version_id')) - - if not file_path or not model_id: - return web.json_response({"success": False, "error": "Both file_path and model_id are required"}, status=400) - - metadata_path = os.path.splitext(file_path)[0] + '.metadata.json' - - # Check if model metadata exists - local_metadata = await ModelRouteUtils.load_local_metadata(metadata_path) - - # Get metadata provider and fetch metadata using get_model_version which includes more comprehensive data - metadata_provider = await get_default_metadata_provider() - civitai_metadata = await metadata_provider.get_model_version(model_id, model_version_id) - if not civitai_metadata: - error_msg = f"Model version not found on CivitAI for ID: {model_id}" - if model_version_id: - error_msg += f" with version: {model_version_id}" - return web.json_response({"success": False, "error": error_msg}, status=404) - - # Try to find the primary model file to get the SHA256 hash - primary_model_file = None - for file in civitai_metadata.get('files', []): - if file.get('primary', False) and file.get('type') == 'Model': - primary_model_file = file - break - - # Update the SHA256 hash in local metadata if available - if primary_model_file and primary_model_file.get('hashes', {}).get('SHA256'): - local_metadata['sha256'] = primary_model_file['hashes']['SHA256'].lower() - - # Update metadata with CivitAI information - await ModelRouteUtils.update_model_metadata(metadata_path, local_metadata, civitai_metadata, metadata_provider) - - # Update the cache - await scanner.update_single_model_cache(file_path, file_path, local_metadata) - - return web.json_response({ - "success": True, - "message": f"Model successfully re-linked to Civitai model {model_id}" + - (f" version {model_version_id}" if model_version_id else ""), - "hash": local_metadata.get('sha256', '') - }) - - except Exception as e: - logger.error(f"Error re-linking to CivitAI: {e}", exc_info=True) - return web.json_response({"success": False, "error": str(e)}, status=500) - - @staticmethod - async def handle_verify_duplicates(request: web.Request, scanner) -> web.Response: - """Handle verification of duplicate model hashes - - Args: - request: The aiohttp request - scanner: The model scanner instance with cache management methods - - Returns: - web.Response: The HTTP response with verification results - """ - try: - data = await request.json() - file_paths = data.get('file_paths', []) - - if not file_paths: - return web.json_response({ - 'success': False, - 'error': 'No file paths provided for verification' - }, status=400) - - # Results tracking - results = { - 'verified_as_duplicates': True, # Start true, set to false if any mismatch - 'mismatched_files': [], - 'new_hash_map': {} - } - - # Get expected hash from the first file's metadata - expected_hash = None - first_metadata_path = os.path.splitext(file_paths[0])[0] + '.metadata.json' - first_metadata = await ModelRouteUtils.load_local_metadata(first_metadata_path) - if first_metadata and 'sha256' in first_metadata: - expected_hash = first_metadata['sha256'].lower() - - # Process each file - for file_path in file_paths: - # Skip files that don't exist - if not os.path.exists(file_path): - continue - - # Calculate actual hash - try: - from .file_utils import calculate_sha256 - actual_hash = await calculate_sha256(file_path) - - # Get metadata - metadata_path = os.path.splitext(file_path)[0] + '.metadata.json' - metadata = await ModelRouteUtils.load_local_metadata(metadata_path) - - # Compare hashes - stored_hash = metadata.get('sha256', '').lower(); - - # Set expected hash from first file if not yet set - if not expected_hash: - expected_hash = stored_hash; - - # Check if hash matches expected hash - if actual_hash != expected_hash: - results['verified_as_duplicates'] = False - results['mismatched_files'].append(file_path) - results['new_hash_map'][file_path] = actual_hash - - # Check if stored hash needs updating - if actual_hash != stored_hash: - # Update metadata with actual hash - metadata['sha256'] = actual_hash - - # Save updated metadata - await MetadataManager.save_metadata(file_path, metadata) - - # Update cache - await scanner.update_single_model_cache(file_path, file_path, metadata) - except Exception as e: - logger.error(f"Error verifying hash for {file_path}: {e}") - results['mismatched_files'].append(file_path) - results['new_hash_map'][file_path] = "error_calculating_hash" - results['verified_as_duplicates'] = False - - return web.json_response({ - 'success': True, - **results - }) - - except Exception as e: - logger.error(f"Error verifying duplicate models: {e}", exc_info=True) - return web.json_response({ - 'success': False, - 'error': str(e) - }, status=500) - - @staticmethod - async def handle_save_metadata(request: web.Request, scanner) -> web.Response: - """Handle saving metadata updates - - Args: - request: The aiohttp request - scanner: The model scanner instance - - Returns: - web.Response: The HTTP response - """ - try: - data = await request.json() - file_path = data.get('file_path') - if not file_path: - return web.Response(text='File path is required', status=400) - - # Remove file path from data to avoid saving it - metadata_updates = {k: v for k, v in data.items() if k != 'file_path'} - - # Get metadata file path - metadata_path = os.path.splitext(file_path)[0] + '.metadata.json' - - # Load existing metadata - metadata = await ModelRouteUtils.load_local_metadata(metadata_path) - - # Handle nested updates (for civitai.trainedWords) - for key, value in metadata_updates.items(): - if isinstance(value, dict) and key in metadata and isinstance(metadata[key], dict): - # Deep update for nested dictionaries - for nested_key, nested_value in value.items(): - metadata[key][nested_key] = nested_value - else: - # Regular update for top-level keys - metadata[key] = value - - # Save updated metadata - await MetadataManager.save_metadata(file_path, metadata) - - # Update cache - await scanner.update_single_model_cache(file_path, file_path, metadata) - - # If model_name was updated, resort the cache - if 'model_name' in metadata_updates: - cache = await scanner.get_cached_data() - await cache.resort() - - return web.json_response({'success': True}) - - except Exception as e: - logger.error(f"Error saving metadata: {e}", exc_info=True) - return web.Response(text=str(e), status=500) - - @staticmethod - async def handle_add_tags(request: web.Request, scanner) -> web.Response: - """Handle adding tags to model metadata - - Args: - request: The aiohttp request - scanner: The model scanner instance - - Returns: - web.Response: The HTTP response - """ - try: - data = await request.json() - file_path = data.get('file_path') - new_tags = data.get('tags', []) - - if not file_path: - return web.Response(text='File path is required', status=400) - - if not isinstance(new_tags, list): - return web.Response(text='Tags must be a list', status=400) - - # Get metadata file path - metadata_path = os.path.splitext(file_path)[0] + '.metadata.json' - - # Load existing metadata - metadata = await ModelRouteUtils.load_local_metadata(metadata_path) - - # Get existing tags (case insensitive) - existing_tags = metadata.get('tags', []) - existing_tags_lower = [tag.lower() for tag in existing_tags] - - # Add new tags that don't already exist (case insensitive check) - tags_added = [] - for tag in new_tags: - if isinstance(tag, str) and tag.strip(): - tag_stripped = tag.strip() - if tag_stripped.lower() not in existing_tags_lower: - existing_tags.append(tag_stripped) - existing_tags_lower.append(tag_stripped.lower()) - tags_added.append(tag_stripped) - - # Update metadata with combined tags - metadata['tags'] = existing_tags - - # Save updated metadata - await MetadataManager.save_metadata(file_path, metadata) - - # Update cache - await scanner.update_single_model_cache(file_path, file_path, metadata) - - return web.json_response({ - 'success': True, - 'tags': existing_tags - }) - - except Exception as e: - logger.error(f"Error adding tags: {e}", exc_info=True) - return web.Response(text=str(e), status=500) From 6f4453aaf36e4252be8fba304f08d08b93c02308 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Wed, 24 Sep 2025 06:04:08 +0800 Subject: [PATCH 089/110] refactor: remove storage migration logic and associated tests --- static/js/core.js | 6 - static/js/core.test.js | 277 ------------------------- static/js/utils/storageHelpers.js | 58 ------ static/js/utils/storageHelpers.test.js | 31 --- 4 files changed, 372 deletions(-) delete mode 100644 static/js/core.test.js diff --git a/static/js/core.js b/static/js/core.js index 9c0bd377..80e0ec69 100644 --- a/static/js/core.js +++ b/static/js/core.js @@ -12,7 +12,6 @@ import { helpManager } from './managers/HelpManager.js'; import { bannerService } from './managers/BannerService.js'; import { initTheme, initBackToTop } from './utils/uiHelpers.js'; import { initializeInfiniteScroll } from './utils/infiniteScroll.js'; -import { migrateStorageItems } from './utils/storageHelpers.js'; import { i18n } from './i18n/index.js'; import { onboardingManager } from './managers/OnboardingManager.js'; import { BulkContextMenu } from './components/ContextMenu/BulkContextMenu.js'; @@ -123,10 +122,5 @@ export class AppCore { } } -document.addEventListener('DOMContentLoaded', () => { - // Migrate localStorage items to use the namespace prefix - migrateStorageItems(); -}); - // Create and export a singleton instance export const appCore = new AppCore(); \ No newline at end of file diff --git a/static/js/core.test.js b/static/js/core.test.js deleted file mode 100644 index e39d5af0..00000000 --- a/static/js/core.test.js +++ /dev/null @@ -1,277 +0,0 @@ -import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; - -const migrateStorageItemsMock = vi.fn(); -const initializeInfiniteScrollMock = vi.fn(); -const initThemeMock = vi.fn(); -const initBackToTopMock = vi.fn(); -const initializeEventManagementMock = vi.fn(); -const createPageContextMenuMock = vi.fn().mockReturnValue('page-menu'); -const createGlobalContextMenuMock = vi.fn().mockReturnValue('global-menu'); -const bulkManagerInitializeMock = vi.fn(); -const setBulkContextMenuMock = vi.fn(); -const helpManagerInitializeMock = vi.fn(); -const updateServiceInitializeMock = vi.fn(); -const bannerServiceInitializeMock = vi.fn(); -const isBannerVisibleMock = vi.fn().mockReturnValue(false); -const onboardingStartMock = vi.fn(); -const settingsWaitMock = vi.fn().mockResolvedValue(); -const i18nWaitMock = vi.fn().mockResolvedValue(); -const i18nLocaleMock = vi.fn().mockReturnValue('en'); - -const mockState = { - currentPageType: 'loras', - global: { - settings: { - card_info_display: 'hover' - } - } -}; - -const mockModalManager = { initialize: vi.fn() }; -const mockBulkManager = { - initialize: bulkManagerInitializeMock, - setBulkContextMenu: setBulkContextMenuMock -}; -const mockHelpManager = { initialize: helpManagerInitializeMock }; -const mockUpdateService = { initialize: updateServiceInitializeMock }; -const mockBannerService = { - initialize: bannerServiceInitializeMock, - isBannerVisible: isBannerVisibleMock -}; -const mockOnboardingManager = { start: onboardingStartMock }; -const mockSettingsManager = { waitForInitialization: settingsWaitMock }; -const mockMoveManager = {}; -const mockI18n = { - waitForReady: i18nWaitMock, - getCurrentLocale: i18nLocaleMock -}; - -const loadingManagerInstances = []; -const HeaderManagerInstances = []; -const bulkContextMenuInstances = []; -const exampleImagesManagerInitializeMock = vi.fn(); - -const LoadingManagerMock = vi.fn(() => { - const instance = { id: Symbol('LoadingManager') }; - loadingManagerInstances.push(instance); - return instance; -}); - -const HeaderManagerMock = vi.fn(() => { - const instance = { id: Symbol('HeaderManager') }; - HeaderManagerInstances.push(instance); - return instance; -}); - -const BulkContextMenuMock = vi.fn(() => { - const instance = { id: Symbol('BulkContextMenu') }; - bulkContextMenuInstances.push(instance); - return instance; -}); - -const ExampleImagesManagerMock = vi.fn(() => { - const instance = { initialize: exampleImagesManagerInitializeMock }; - globalThis.exampleImagesManager = instance; - return instance; -}); - -vi.stubGlobal('exampleImagesManager', null); - -vi.mock('./utils/storageHelpers.js', () => ({ - migrateStorageItems: migrateStorageItemsMock -})); - -vi.mock('./state/index.js', () => ({ - state: mockState -})); - -vi.mock('./managers/LoadingManager.js', () => ({ - LoadingManager: LoadingManagerMock -})); - -vi.mock('./managers/ModalManager.js', () => ({ - ModalManager: vi.fn(), - modalManager: mockModalManager -})); - -vi.mock('./managers/UpdateService.js', () => ({ - updateService: mockUpdateService -})); - -vi.mock('./components/Header.js', () => ({ - HeaderManager: HeaderManagerMock -})); - -vi.mock('./managers/SettingsManager.js', () => ({ - settingsManager: mockSettingsManager -})); - -vi.mock('./managers/MoveManager.js', () => ({ - moveManager: mockMoveManager -})); - -vi.mock('./managers/BulkManager.js', () => ({ - bulkManager: mockBulkManager -})); - -vi.mock('./managers/ExampleImagesManager.js', () => ({ - ExampleImagesManager: ExampleImagesManagerMock -})); - -vi.mock('./managers/HelpManager.js', () => ({ - helpManager: mockHelpManager -})); - -vi.mock('./managers/BannerService.js', () => ({ - bannerService: mockBannerService -})); - -vi.mock('./utils/uiHelpers.js', () => ({ - initTheme: initThemeMock, - initBackToTop: initBackToTopMock -})); - -vi.mock('./utils/infiniteScroll.js', () => ({ - initializeInfiniteScroll: initializeInfiniteScrollMock -})); - -vi.mock('./i18n/index.js', () => ({ - i18n: mockI18n -})); - -vi.mock('./managers/OnboardingManager.js', () => ({ - onboardingManager: mockOnboardingManager -})); - -vi.mock('./components/ContextMenu/BulkContextMenu.js', () => ({ - BulkContextMenu: BulkContextMenuMock -})); - -vi.mock('./components/ContextMenu/index.js', () => ({ - createPageContextMenu: createPageContextMenuMock, - createGlobalContextMenu: createGlobalContextMenuMock -})); - -vi.mock('./utils/eventManagementInit.js', () => ({ - initializeEventManagement: initializeEventManagementMock -})); - -beforeEach(() => { - vi.clearAllMocks(); - document.body.innerHTML = ''; - document.body.removeAttribute('data-page'); - mockState.currentPageType = 'loras'; - mockState.global.settings.card_info_display = 'hover'; - isBannerVisibleMock.mockReturnValue(false); - loadingManagerInstances.length = 0; - HeaderManagerInstances.length = 0; - bulkContextMenuInstances.length = 0; - delete window.pageContextMenu; - delete window.globalContextMenuInstance; -}); - -afterEach(() => { - vi.useRealTimers(); -}); - -const loadCoreModule = async () => { - vi.resetModules(); - return import('./core.js'); -}; - -describe('AppCore module bootstrapping', () => { - it('registers storage migration on DOMContentLoaded', async () => { - const addEventListenerSpy = vi.spyOn(document, 'addEventListener'); - await loadCoreModule(); - - expect(addEventListenerSpy).toHaveBeenCalledWith('DOMContentLoaded', expect.any(Function)); - const listener = addEventListenerSpy.mock.calls.find(([event]) => event === 'DOMContentLoaded')[1]; - listener(); - expect(migrateStorageItemsMock).toHaveBeenCalledTimes(1); - }); - - it('initializes managers, UI helpers, and onboarding sequence', async () => { - vi.useFakeTimers(); - const { AppCore } = await loadCoreModule(); - const appCore = new AppCore(); - - document.body.dataset.page = 'loras'; - - const result = await appCore.initialize(); - - expect(result).toBe(appCore); - expect(i18nWaitMock).toHaveBeenCalled(); - expect(i18nLocaleMock).toHaveBeenCalled(); - expect(settingsWaitMock).toHaveBeenCalled(); - - expect(LoadingManagerMock).toHaveBeenCalledTimes(1); - const loadingInstance = LoadingManagerMock.mock.results[0].value; - expect(mockState.loadingManager).toBe(loadingInstance); - - expect(mockModalManager.initialize).toHaveBeenCalled(); - expect(updateServiceInitializeMock).toHaveBeenCalled(); - expect(bannerServiceInitializeMock).toHaveBeenCalled(); - expect(window.modalManager).toBe(mockModalManager); - expect(window.settingsManager).toBe(mockSettingsManager); - expect(window.bulkManager).toBe(mockBulkManager); - expect(window.helpManager).toBe(mockHelpManager); - - expect(HeaderManagerMock).toHaveBeenCalledTimes(1); - expect(initThemeMock).toHaveBeenCalled(); - expect(initBackToTopMock).toHaveBeenCalled(); - - expect(bulkManagerInitializeMock).toHaveBeenCalled(); - expect(BulkContextMenuMock).toHaveBeenCalledTimes(1); - expect(setBulkContextMenuMock).toHaveBeenCalledWith(bulkContextMenuInstances[0]); - - expect(ExampleImagesManagerMock).toHaveBeenCalledTimes(1); - expect(exampleImagesManagerInitializeMock).toHaveBeenCalled(); - expect(helpManagerInitializeMock).toHaveBeenCalled(); - - expect(document.body.classList.contains('hover-reveal')).toBe(true); - expect(initializeEventManagementMock).toHaveBeenCalled(); - - vi.runAllTimers(); - expect(onboardingStartMock).toHaveBeenCalled(); - }); - - it('skips bulk manager when recipes page is active', async () => { - const { AppCore } = await loadCoreModule(); - const appCore = new AppCore(); - mockState.currentPageType = 'recipes'; - - await appCore.initialize(); - - expect(bulkManagerInitializeMock).not.toHaveBeenCalled(); - expect(BulkContextMenuMock).not.toHaveBeenCalled(); - expect(setBulkContextMenuMock).not.toHaveBeenCalled(); - }); - - it('initializes page features with context menus and infinite scroll', async () => { - const { AppCore } = await loadCoreModule(); - const appCore = new AppCore(); - document.body.dataset.page = 'loras'; - - appCore.initializeContextMenus = vi.fn(appCore.initializeContextMenus.bind(appCore)); - - appCore.initializePageFeatures(); - - expect(appCore.initializeContextMenus).toHaveBeenCalledWith('loras'); - expect(initializeInfiniteScrollMock).toHaveBeenCalledWith('loras'); - expect(createPageContextMenuMock).toHaveBeenCalledWith('loras'); - expect(window.pageContextMenu).toBe('page-menu'); - expect(createGlobalContextMenuMock).toHaveBeenCalled(); - expect(window.globalContextMenuInstance).toBe('global-menu'); - }); - - it('does not reinitialize once initialized', async () => { - const { AppCore } = await loadCoreModule(); - const appCore = new AppCore(); - - await appCore.initialize(); - await appCore.initialize(); - - expect(i18nWaitMock).toHaveBeenCalledTimes(1); - expect(settingsWaitMock).toHaveBeenCalledTimes(1); - }); -}); diff --git a/static/js/utils/storageHelpers.js b/static/js/utils/storageHelpers.js index 317d19d7..6b7a8f4f 100644 --- a/static/js/utils/storageHelpers.js +++ b/static/js/utils/storageHelpers.js @@ -116,64 +116,6 @@ export function removeSessionItem(key) { sessionStorage.removeItem(STORAGE_PREFIX + key); } -/** - * Migrate all existing localStorage items to use the prefix - * This should be called once during application initialization - */ -export function migrateStorageItems() { - // Check if migration has already been performed - if (localStorage.getItem(STORAGE_PREFIX + 'migration_completed')) { - console.log('Lora Manager: Storage migration already completed'); - return; - } - - // List of known keys used in the application - const knownKeys = [ - 'nsfwBlurLevel', - 'theme', - 'activeFolder', - 'folderTagsCollapsed', - 'settings', - 'loras_filters', - 'recipes_filters', - 'checkpoints_filters', - 'loras_search_prefs', - 'recipes_search_prefs', - 'checkpoints_search_prefs', - 'show_update_notifications', - 'last_update_check', - 'dismissed_banners' - ]; - - // Migrate each known key - knownKeys.forEach(key => { - const prefixedKey = STORAGE_PREFIX + key; - - // Only migrate if the prefixed key doesn't already exist - if (localStorage.getItem(prefixedKey) === null) { - const value = localStorage.getItem(key); - if (value !== null) { - try { - // Try to parse as JSON first - const parsedValue = JSON.parse(value); - setStorageItem(key, parsedValue); - } catch (e) { - // If not JSON, store as is - setStorageItem(key, value); - } - - // We can optionally remove the old key after migration - localStorage.removeItem(key); - } - } - }); - - // Mark migration as completed - localStorage.setItem(STORAGE_PREFIX + 'migration_completed', 'true'); - - console.log('Lora Manager: Storage migration completed'); -} - /** * Save a Map to localStorage * @param {string} key - The localStorage key diff --git a/static/js/utils/storageHelpers.test.js b/static/js/utils/storageHelpers.test.js index ed19b967..8603deb1 100644 --- a/static/js/utils/storageHelpers.test.js +++ b/static/js/utils/storageHelpers.test.js @@ -8,7 +8,6 @@ const { getSessionItem, setSessionItem, removeSessionItem, - migrateStorageItems } = storageHelpers; const createFakeStorage = () => { @@ -110,33 +109,3 @@ describe('storageHelpers namespace utilities', () => { expect(sessionStorage.getItem('lora_manager_flag')).toBeNull(); }); }); - -describe('migrateStorageItems', () => { - it('migrates known keys and logs completion', () => { - const setStorageSpy = vi.spyOn(storageHelpers, 'setStorageItem'); - localStorage.setItem('theme', '"light"'); - localStorage.setItem('loras_filters', JSON.stringify({ sort: 'asc' })); - localStorage.setItem('nsfwBlurLevel', '3'); - - migrateStorageItems(); - - expect(setStorageSpy).toHaveBeenCalledTimes(3); - expect(localStorage.getItem('lora_manager_theme')).toBe('light'); - expect(localStorage.getItem('lora_manager_loras_filters')).toBe(JSON.stringify({ sort: 'asc' })); - expect(localStorage.getItem('loras_filters')).toBeNull(); - expect(localStorage.getItem('lora_manager_nsfwBlurLevel')).toBe('3'); - expect(localStorage.getItem('nsfwBlurLevel')).toBeNull(); - expect(localStorage.getItem('lora_manager_migration_completed')).toBe('true'); - expect(consoleLogMock).toHaveBeenCalledWith('Lora Manager: Storage migration completed'); - }); - - it('skips migration when already completed and logs notice', () => { - const setStorageSpy = vi.spyOn(storageHelpers, 'setStorageItem'); - localStorage.setItem('lora_manager_migration_completed', 'true'); - - migrateStorageItems(); - - expect(setStorageSpy).not.toHaveBeenCalled(); - expect(consoleLogMock).toHaveBeenCalledWith('Lora Manager: Storage migration already completed'); - }); -}); From 12c88835f2285c14e3901db073a0ba9a65c0fc8d Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Wed, 24 Sep 2025 09:16:02 +0800 Subject: [PATCH 090/110] refactor: enhance model version retrieval logic in CivitaiClient, fixes #460 --- py/services/civitai_client.py | 84 ++++++++++---- refs/civitai_api_model_by_modelId.json | 110 +++++++++++++++++++ tests/routes/test_base_model_routes_smoke.py | 2 +- 3 files changed, 176 insertions(+), 20 deletions(-) create mode 100644 refs/civitai_api_model_by_modelId.json diff --git a/py/services/civitai_client.py b/py/services/civitai_client.py index ccadbcb5..bb6004ed 100644 --- a/py/services/civitai_client.py +++ b/py/services/civitai_client.py @@ -1,4 +1,5 @@ import os +import copy import logging import asyncio from typing import Optional, Dict, Tuple, List @@ -189,31 +190,76 @@ class CivitaiClient: ) if not success: return None - + model_versions = data.get('modelVersions', []) - - # Step 2: Determine the version_id to use - target_version_id = version_id - if target_version_id is None: - target_version_id = model_versions[0].get('id') - - # Step 3: Get detailed version info using the version_id - success, version = await downloader.make_request( - 'GET', - f"{self.base_url}/model-versions/{target_version_id}", - use_auth=True - ) - if not success: + if not model_versions: + logger.warning(f"No model versions found for model {model_id}") return None - + + # Step 2: Determine the target version entry to use + target_version = None + if version_id is not None: + target_version = next( + (item for item in model_versions if item.get('id') == version_id), + None + ) + if target_version is None: + logger.warning( + f"Version {version_id} not found for model {model_id}, defaulting to first version" + ) + if target_version is None: + target_version = model_versions[0] + + target_version_id = target_version.get('id') + + # Step 3: Get detailed version info using the SHA256 hash + model_hash = None + for file_info in target_version.get('files', []): + if file_info.get('type') == 'Model' and file_info.get('primary'): + model_hash = file_info.get('hashes', {}).get('SHA256') + if model_hash: + break + + version = None + if model_hash: + success, version = await downloader.make_request( + 'GET', + f"{self.base_url}/model-versions/by-hash/{model_hash}", + use_auth=True + ) + if not success: + logger.warning( + f"Failed to fetch version by hash for model {model_id} version {target_version_id}: {version}" + ) + version = None + else: + logger.warning( + f"No primary model hash found for model {model_id} version {target_version_id}" + ) + + if version is None: + version = copy.deepcopy(target_version) + version.pop('index', None) + version['modelId'] = model_id + version['model'] = { + 'name': data.get('name'), + 'type': data.get('type'), + 'nsfw': data.get('nsfw'), + 'poi': data.get('poi') + } + # Step 4: Enrich version_info with model data # Add description and tags from model data - version['model']['description'] = data.get("description") - version['model']['tags'] = data.get("tags", []) - + model_info = version.get('model') + if not isinstance(model_info, dict): + model_info = {} + version['model'] = model_info + model_info['description'] = data.get("description") + model_info['tags'] = data.get("tags", []) + # Add creator from model data version['creator'] = data.get("creator") - + return version # Case 3: Neither model_id nor version_id provided diff --git a/refs/civitai_api_model_by_modelId.json b/refs/civitai_api_model_by_modelId.json new file mode 100644 index 00000000..2cd20f20 --- /dev/null +++ b/refs/civitai_api_model_by_modelId.json @@ -0,0 +1,110 @@ +{ + "id": 1231067, + "name": "Vivid Impressions Storybook Style", + "description": "

    If you'd like to support me, feel free to visit my Ko-Fi page. ❤️

    Please share your images using the \"+add post\" button below. It supports the creators. Thanks! 💕

    If you like my LoRA, please like, comment, or donate some Buzz. Much appreciated! ❤️

    Trigger word: ppstorybook

    Strength: 0.8, experiment as you like

    ", + "allowNoCredit": true, + "allowCommercialUse": [ + "Image", + "RentCivit", + "Rent", + "Sell" + ], + "allowDerivatives": true, + "allowDifferentLicense": true, + "type": "LORA", + "minor": false, + "sfwOnly": false, + "poi": false, + "nsfw": false, + "nsfwLevel": 1, + "availability": "Public", + "cosmetic": null, + "supportsGeneration": true, + "stats": { + "downloadCount": 2183, + "favoriteCount": 0, + "thumbsUpCount": 416, + "thumbsDownCount": 0, + "commentCount": 12, + "ratingCount": 0, + "rating": 0, + "tippedAmountCount": 360 + }, + "creator": { + "username": "PixelPawsAI", + "image": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/f3a1aa7c-0159-4dd8-884a-1e7ceb350f96/width=96/PixelPawsAI.jpeg" + }, + "tags": [ + "style", + "illustration", + "storybook" + ], + "modelVersions": [ + { + "id": 1387174, + "index": 0, + "name": "v1.0", + "baseModel": "Flux.1 D", + "baseModelType": "Standard", + "createdAt": "2025-02-08T11:15:47.197Z", + "publishedAt": "2025-02-08T11:29:04.487Z", + "status": "Published", + "availability": "Public", + "nsfwLevel": 1, + "trainedWords": [ + "ppstorybook" + ], + "covered": true, + "stats": { + "downloadCount": 2183, + "ratingCount": 0, + "rating": 0, + "thumbsUpCount": 416, + "thumbsDownCount": 0 + }, + "files": [ + { + "id": 1289799, + "sizeKB": 18829.1484375, + "name": "pp-storybook_rank2_bf16.safetensors", + "type": "Model", + "pickleScanResult": "Success", + "pickleScanMessage": "No Pickle imports", + "virusScanResult": "Success", + "virusScanMessage": null, + "scannedAt": "2025-02-08T11:21:04.247Z", + "metadata": { + "format": "SafeTensor" + }, + "hashes": { + "AutoV1": "F414C813", + "AutoV2": "9753338AB6", + "SHA256": "9753338AB693CA82BF89ED77A5D1912879E40051463EC6E330FB9866CE798668", + "CRC32": "A65AE7B3", + "BLAKE3": "A5F8AB95AC2486345E4ACCAE541FF19D97ED53EFB0A7CC9226636975A0437591", + "AutoV3": "34A22376739D" + }, + "downloadUrl": "https://civitai.com/api/download/models/1387174", + "primary": true + } + ], + "images": [ + { + "url": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/42b875cf-c62b-41fa-a349-383b7f074351/original=true/56547310.jpeg", + "nsfwLevel": 1, + "width": 832, + "height": 1216, + "hash": "U5IiO6s-4Vn+0~EO^5xa00VsL#IU_O?E7yWC", + "type": "image", + "minor": false, + "poi": false, + "hasMeta": true, + "hasPositivePrompt": true, + "onSite": false, + "remixOfId": null + } + ], + "downloadUrl": "https://civitai.com/api/download/models/1387174" + } + ] +} \ No newline at end of file diff --git a/tests/routes/test_base_model_routes_smoke.py b/tests/routes/test_base_model_routes_smoke.py index 136bd0a8..7f7e0c9a 100644 --- a/tests/routes/test_base_model_routes_smoke.py +++ b/tests/routes/test_base_model_routes_smoke.py @@ -31,7 +31,7 @@ from py_local.routes.base_model_routes import BaseModelRoutes from py_local.services.model_file_service import AutoOrganizeResult from py_local.services.service_registry import ServiceRegistry from py_local.services.websocket_manager import ws_manager -from py_local.utils.routes_common import ExifUtils +from py_local.utils.exif_utils import ExifUtils from py_local.config import config From dc2de50924d8c35dfe5223f9385f9cbfb04cbab8 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Wed, 24 Sep 2025 09:16:50 +0800 Subject: [PATCH 091/110] bump: update version to 0.9.5 in pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 801a705e..8ac3aebd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui-lora-manager" description = "Revolutionize your workflow with the ultimate LoRA companion for ComfyUI!" -version = "0.9.4" +version = "0.9.5" license = {file = "LICENSE"} dependencies = [ "aiohttp", From 0d0988c09069b4cb5cb0913ce970a68b1ad00c91 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Wed, 24 Sep 2025 10:55:55 +0800 Subject: [PATCH 092/110] feat: add functionality to attach model files to version data in SQLiteModelMetadataProvider --- py/services/model_metadata_provider.py | 39 ++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/py/services/model_metadata_provider.py b/py/services/model_metadata_provider.py index 1a36d353..3099b5fc 100644 --- a/py/services/model_metadata_provider.py +++ b/py/services/model_metadata_provider.py @@ -389,6 +389,45 @@ class SQLiteModelMetadataProvider(ModelMetadataProvider): # Add any additional fields from version data result.update(version_data) + # Attach files associated with this version from model_files table + files_query = """ + SELECT data + FROM model_files + WHERE version_id = ? AND type = 'Model' + ORDER BY id ASC + """ + cursor = await db.execute(files_query, (version_id,)) + file_rows = await cursor.fetchall() + + files = [] + for file_row in file_rows: + try: + file_data = json.loads(file_row['data']) + except json.JSONDecodeError: + logger.warning( + "Skipping model_files entry with invalid JSON for version_id %s", version_id + ) + continue + # Remove 'modelId' and 'modelVersionId' fields if present + file_data.pop('modelId', None) + file_data.pop('modelVersionId', None) + files.append(file_data) + + if 'files' in result: + existing_files = result['files'] + if isinstance(existing_files, list): + existing_files.extend(files) + result['files'] = existing_files + else: + merged_files = files.copy() + if existing_files: + merged_files.insert(0, existing_files) + result['files'] = merged_files + elif files: + result['files'] = files + else: + result['files'] = [] + return result except json.JSONDecodeError: return None From 59d027181dc97494afb7ae3334f671b27b4fffa2 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Wed, 24 Sep 2025 10:56:06 +0800 Subject: [PATCH 093/110] refactor: remove obsolete JSON files and add new version metadata for LORA model --- refs/flux_output.json | 15 -- refs/flux_prompt.json | 314 --------------------------------- refs/output.json | 258 --------------------------- refs/prompt.json | 401 ------------------------------------------ refs/version.json | 91 ++++++++++ 5 files changed, 91 insertions(+), 988 deletions(-) delete mode 100644 refs/flux_output.json delete mode 100644 refs/flux_prompt.json delete mode 100644 refs/output.json delete mode 100644 refs/prompt.json create mode 100644 refs/version.json diff --git a/refs/flux_output.json b/refs/flux_output.json deleted file mode 100644 index 7d19efc7..00000000 --- a/refs/flux_output.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "loras": " ", - "gen_params": { - "prompt": "in the style of ppWhimsy, ral-frctlgmtry, ppstorybook,Stylized geek cat artist with glasses and a paintbrush, smiling at the viewer while holding a sign that reads 'Stay tuned!', solid white background", - "negative_prompt": "", - "steps": "25", - "sampler": "dpmpp_2m", - "scheduler": "beta", - "cfg": "1", - "seed": "48", - "guidance": 3.5, - "size": "896x1152", - "clip_skip": "2" - } -} \ No newline at end of file diff --git a/refs/flux_prompt.json b/refs/flux_prompt.json deleted file mode 100644 index 82a51077..00000000 --- a/refs/flux_prompt.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "6": { - "inputs": { - "text": [ - "46", - 0 - ], - "clip": [ - "58", - 1 - ] - }, - "class_type": "CLIPTextEncode", - "_meta": { - "title": "CLIP Text Encode (Positive Prompt)" - } - }, - "8": { - "inputs": { - "samples": [ - "31", - 0 - ], - "vae": [ - "39", - 0 - ] - }, - "class_type": "VAEDecode", - "_meta": { - "title": "VAE Decode" - } - }, - "27": { - "inputs": { - "width": 896, - "height": 1152, - "batch_size": 1 - }, - "class_type": "EmptySD3LatentImage", - "_meta": { - "title": "EmptySD3LatentImage" - } - }, - "31": { - "inputs": { - "seed": 44, - "steps": 25, - "cfg": 1, - "sampler_name": "dpmpp_2m", - "scheduler": "beta", - "denoise": 1, - "model": [ - "58", - 0 - ], - "positive": [ - "35", - 0 - ], - "negative": [ - "33", - 0 - ], - "latent_image": [ - "27", - 0 - ] - }, - "class_type": "KSampler", - "_meta": { - "title": "KSampler" - } - }, - "33": { - "inputs": { - "text": "", - "clip": [ - "58", - 1 - ] - }, - "class_type": "CLIPTextEncode", - "_meta": { - "title": "CLIP Text Encode (Negative Prompt)" - } - }, - "35": { - "inputs": { - "guidance": 3.5, - "conditioning": [ - "6", - 0 - ] - }, - "class_type": "FluxGuidance", - "_meta": { - "title": "FluxGuidance" - } - }, - "37": { - "inputs": { - "unet_name": "flux\\flux1-dev-fp8-e4m3fn.safetensors", - "weight_dtype": "fp8_e4m3fn_fast" - }, - "class_type": "UNETLoader", - "_meta": { - "title": "Load Diffusion Model" - } - }, - "38": { - "inputs": { - "clip_name1": "t5xxl_fp8_e4m3fn.safetensors", - "clip_name2": "clip_l.safetensors", - "type": "flux", - "device": "default" - }, - "class_type": "DualCLIPLoader", - "_meta": { - "title": "DualCLIPLoader" - } - }, - "39": { - "inputs": { - "vae_name": "flux1\\ae.safetensors" - }, - "class_type": "VAELoader", - "_meta": { - "title": "Load VAE" - } - }, - "46": { - "inputs": { - "string1": [ - "59", - 0 - ], - "string2": [ - "51", - 0 - ], - "delimiter": "," - }, - "class_type": "JoinStrings", - "_meta": { - "title": "Join Strings" - } - }, - "50": { - "inputs": { - "images": [ - "8", - 0 - ] - }, - "class_type": "PreviewImage", - "_meta": { - "title": "Preview Image" - } - }, - "51": { - "inputs": { - "string": "Stylized geek cat artist with glasses and a paintbrush, smiling at the viewer while holding a sign that reads 'Stay tuned!', solid white background", - "strip_newlines": true - }, - "class_type": "StringConstantMultiline", - "_meta": { - "title": "positive" - } - }, - "58": { - "inputs": { - "text": "", - "loras": [ - { - "name": "pp-enchanted-whimsy", - "strength": "0.90", - "active": false - }, - { - "name": "ral-frctlgmtry_flux", - "strength": "0.85", - "active": false - }, - { - "name": "pp-storybook_rank2_bf16", - "strength": 0.8, - "active": true - }, - { - "name": "__dummy_item1__", - "strength": 0, - "active": false, - "_isDummy": true - }, - { - "name": "__dummy_item2__", - "strength": 0, - "active": false, - "_isDummy": true - } - ], - "model": [ - "37", - 0 - ], - "clip": [ - "38", - 0 - ] - }, - "class_type": "Lora Loader (LoraManager)", - "_meta": { - "title": "Lora Loader (LoraManager)" - } - }, - "59": { - "inputs": { - "group_mode": "", - "toggle_trigger_words": [ - { - "text": "ppstorybook", - "active": false - }, - { - "text": "__dummy_item__", - "active": false, - "_isDummy": true - }, - { - "text": "__dummy_item__", - "active": false, - "_isDummy": true - } - ], - "orinalMessage": "ppstorybook", - "trigger_words": [ - "58", - 2 - ] - }, - "class_type": "TriggerWord Toggle (LoraManager)", - "_meta": { - "title": "TriggerWord Toggle (LoraManager)" - } - }, - "61": { - "inputs": { - "add_noise": "enable", - "noise_seed": 1111423448930884, - "steps": 20, - "cfg": 8, - "sampler_name": "euler", - "scheduler": "normal", - "start_at_step": 0, - "end_at_step": 10000, - "return_with_leftover_noise": "disable" - }, - "class_type": "KSamplerAdvanced", - "_meta": { - "title": "KSampler (Advanced)" - } - }, - "62": { - "inputs": { - "sigmas": [ - "63", - 0 - ] - }, - "class_type": "SamplerCustomAdvanced", - "_meta": { - "title": "SamplerCustomAdvanced" - } - }, - "63": { - "inputs": { - "scheduler": "normal", - "steps": 20, - "denoise": 1 - }, - "class_type": "BasicScheduler", - "_meta": { - "title": "BasicScheduler" - } - }, - "64": { - "inputs": { - "seed": 1089899258710474, - "steps": 20, - "cfg": 8, - "sampler_name": "euler", - "scheduler": "normal", - "denoise": 1 - }, - "class_type": "KSampler", - "_meta": { - "title": "KSampler" - } - }, - "65": { - "inputs": { - "text": ",Stylized geek cat artist with glasses and a paintbrush, smiling at the viewer while holding a sign that reads 'Stay tuned!', solid white background", - "anything": [ - "46", - 0 - ] - }, - "class_type": "easy showAnything", - "_meta": { - "title": "Show Any" - } - } -} \ No newline at end of file diff --git a/refs/output.json b/refs/output.json deleted file mode 100644 index aa5a9702..00000000 --- a/refs/output.json +++ /dev/null @@ -1,258 +0,0 @@ -{ - "id": 649516, - "name": "Cynthia -シロナ - Pokemon Diamond and Pearl - PDXL LORA", - "description": "

    Warning: Without Adetailer eyes are fucked (rainbow color and artefact)

    Trained on Pony Diffusion V6 XL with 63 pictures.
    Best result with weight between : 0.8-1.

    Basic prompts : 1girl, cynthia \\(pokemon\\), blonde hair, hair over one eye, very long hair, grey eyes, eyelashes, hair ornament 
    Outfit prompts : fur collar, black coat, fur-trimmed coat, long sleeves, black pants, black shirt, high heels

    Reviews are really appreciated, i love to see the community use my work, that's why I share it.
    If you like my work, you can tip me here.

    Got a specific request ? I'm open for commission on my kofi or fiverr gig *! If you provide enough data, OCs are accepted

    ", - "allowNoCredit": true, - "allowCommercialUse": [ - "Image", - "RentCivit" - ], - "allowDerivatives": true, - "allowDifferentLicense": true, - "type": "LORA", - "minor": false, - "sfwOnly": false, - "poi": false, - "nsfw": false, - "nsfwLevel": 29, - "availability": "Public", - "cosmetic": null, - "supportsGeneration": true, - "stats": { - "downloadCount": 811, - "favoriteCount": 0, - "thumbsUpCount": 175, - "thumbsDownCount": 0, - "commentCount": 4, - "ratingCount": 0, - "rating": 0, - "tippedAmountCount": 10 - }, - "creator": { - "username": "Konan", - "image": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/7cd552a1-60fe-4baf-a0e4-f7d5d5381711/width=96/Konan.jpeg" - }, - "tags": [ - "anime", - "character", - "cynthia", - "woman", - "pokemon", - "pokegirl" - ], - "modelVersions": [ - { - "id": 726676, - "index": 0, - "name": "v1.0", - "baseModel": "Pony", - "createdAt": "2024-08-16T01:13:16.099Z", - "publishedAt": "2024-08-16T01:14:44.984Z", - "status": "Published", - "availability": "Public", - "nsfwLevel": 29, - "trainedWords": [ - "1girl, cynthia \\(pokemon\\), blonde hair, hair over one eye, very long hair, grey eyes, eyelashes, hair ornament", - "fur collar, black coat, fur-trimmed coat, long sleeves, black pants, black shirt, high heels" - ], - "covered": true, - "stats": { - "downloadCount": 811, - "ratingCount": 0, - "rating": 0, - "thumbsUpCount": 175, - "thumbsDownCount": 0 - }, - "files": [ - { - "id": 641092, - "sizeKB": 56079.65234375, - "name": "CynthiaXL.safetensors", - "type": "Model", - "pickleScanResult": "Success", - "pickleScanMessage": "No Pickle imports", - "virusScanResult": "Success", - "virusScanMessage": null, - "scannedAt": "2024-08-16T01:17:19.087Z", - "metadata": { - "format": "SafeTensor" - }, - "hashes": {}, - "downloadUrl": "https://civitai.com/api/download/models/726676", - "primary": true - } - ], - "images": [ - { - "url": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/b346d757-2b59-4aeb-9f09-3bee2724519d/width=1248/24511993.jpeg", - "nsfwLevel": 1, - "width": 1248, - "height": 1824, - "hash": "UqNc==RP.9s+~pxvIst7kWWBWBjY%MWBt7WB", - "type": "image", - "minor": false, - "poi": false, - "hasMeta": true, - "hasPositivePrompt": true, - "onSite": false, - "remixOfId": null - }, - { - "url": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/fc132ac0-cc1c-4b68-a1d7-5b97b0996ac2/width=1248/24511997.jpeg", - "nsfwLevel": 1, - "width": 1248, - "height": 1824, - "hash": "UMGSS+?tTw.60MIX9cbb~WxHRRR-NEtLRiR%", - "type": "image", - "minor": false, - "poi": false, - "hasMeta": true, - "hasPositivePrompt": true, - "onSite": false, - "remixOfId": null - }, - { - "url": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/7b3237d1-e672-466a-85d0-cc5dd42ab130/width=1160/24512001.jpeg", - "nsfwLevel": 4, - "width": 1160, - "height": 1696, - "hash": "U9NA6f~o00%h00wvIYt74:ER-=D%5600DiE1", - "type": "image", - "minor": false, - "poi": false, - "hasMeta": true, - "hasPositivePrompt": true, - "onSite": false, - "remixOfId": null - }, - { - "url": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/ccd7d11d-4fa9-4434-85a1-fb999312e60d/width=1248/24511991.jpeg", - "nsfwLevel": 1, - "width": 1248, - "height": 1824, - "hash": "UyNTg.j?~qxu?aoLRkj]%MfkM{jZaya}a#ax", - "type": "image", - "minor": false, - "poi": false, - "hasMeta": true, - "hasPositivePrompt": true, - "onSite": false, - "remixOfId": null - }, - { - "url": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/1743be6d-7fe5-4b55-9f19-c931618fa259/width=1248/24511996.jpeg", - "nsfwLevel": 4, - "width": 1248, - "height": 1824, - "hash": "UGOC~n^+?w~6Tx_4oM^$yYEkMds74:9F#*xY", - "type": "image", - "minor": false, - "poi": false, - "hasMeta": true, - "hasPositivePrompt": true, - "onSite": false, - "remixOfId": null - }, - { - "url": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/91693c98-d037-4489-882c-100eb26019a0/width=1160/24512010.jpeg", - "nsfwLevel": 4, - "width": 1160, - "height": 1696, - "hash": "UJI}kp^-Kl%hXAIX4;Nf^+M|9GRP0Mt8%L%2", - "type": "image", - "minor": false, - "poi": false, - "hasMeta": true, - "hasPositivePrompt": true, - "onSite": false, - "remixOfId": null - }, - { - "url": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/49c7a294-ac5b-4832-98e5-2acd0f1a8782/width=1248/24512017.jpeg", - "nsfwLevel": 4, - "width": 1248, - "height": 1824, - "hash": "UML;8Qn|9G%3mnWA4nWFMf%N?Hae~qog-oNF", - "type": "image", - "minor": false, - "poi": false, - "hasMeta": true, - "hasPositivePrompt": true, - "onSite": false, - "remixOfId": null - }, - { - "url": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/d7b442f2-6ead-4a7a-9578-54d9ec2ff148/width=1248/24512015.jpeg", - "nsfwLevel": 1, - "width": 1248, - "height": 1824, - "hash": "UPGR#kt8xw%M0LWC9bWC?wxtR*NLM^jrxWM|", - "type": "image", - "minor": false, - "poi": false, - "hasMeta": true, - "hasPositivePrompt": true, - "onSite": false, - "remixOfId": null - }, - { - "url": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/d840f1e9-3dd3-4531-b83a-1ba2c6b7feaa/width=1160/24512004.jpeg", - "nsfwLevel": 8, - "width": 1160, - "height": 1696, - "hash": "ULNm1i_39wi^*I%hDiM_tlo#xuV?^kNIxCs,", - "type": "image", - "minor": false, - "poi": false, - "hasMeta": true, - "hasPositivePrompt": true, - "onSite": false, - "remixOfId": null - }, - { - "url": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/520387ae-c176-43e3-92bd-5cd2a672475e/width=1248/24512012.jpeg", - "nsfwLevel": 4, - "width": 1248, - "height": 1824, - "hash": "URM%l.%M.9Ip~poIkExu_3V@M|xuD%oJM{D*", - "type": "image", - "minor": false, - "poi": false, - "hasMeta": true, - "hasPositivePrompt": true, - "onSite": false, - "remixOfId": null - }, - { - "url": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/9ea28b94-f326-4776-83ff-851cc203c627/width=1248/24511988.jpeg", - "nsfwLevel": 1, - "width": 1248, - "height": 1824, - "hash": "U-PZloog_Nxut6j]WXWB-;j?IVa#ofaxj]j]", - "type": "image", - "minor": false, - "poi": false, - "hasMeta": true, - "hasPositivePrompt": true, - "onSite": false, - "remixOfId": null - }, - { - "url": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/2e749dbb-7d5a-48f1-8e29-fea5022a5fe9/width=1248/24522268.jpeg", - "nsfwLevel": 16, - "width": 1248, - "height": 1824, - "hash": "UPLgtm9Z0z=|0yRRE2-A9rWAoNE1~DwOr=t7", - "type": "image", - "minor": false, - "poi": false, - "hasMeta": true, - "hasPositivePrompt": true, - "onSite": false, - "remixOfId": null - } - ], - "downloadUrl": "https://civitai.com/api/download/models/726676" - } - ] -} \ No newline at end of file diff --git a/refs/prompt.json b/refs/prompt.json deleted file mode 100644 index 96f62b0a..00000000 --- a/refs/prompt.json +++ /dev/null @@ -1,401 +0,0 @@ -{ - "6": { - "inputs": { - "text": [ - "301", - 0 - ], - "clip": [ - "299", - 1 - ] - }, - "class_type": "CLIPTextEncode", - "_meta": { - "title": "CLIP Text Encode (Prompt)" - } - }, - "8": { - "inputs": { - "samples": [ - "13", - 1 - ], - "vae": [ - "10", - 0 - ] - }, - "class_type": "VAEDecode", - "_meta": { - "title": "VAE Decode" - } - }, - "10": { - "inputs": { - "vae_name": "flux1\\ae.safetensors" - }, - "class_type": "VAELoader", - "_meta": { - "title": "Load VAE" - } - }, - "11": { - "inputs": { - "clip_name1": "t5xxl_fp8_e4m3fn.safetensors", - "clip_name2": "ViT-L-14-TEXT-detail-improved-hiT-GmP-TE-only-HF.safetensors", - "type": "flux", - "device": "default" - }, - "class_type": "DualCLIPLoader", - "_meta": { - "title": "DualCLIPLoader" - } - }, - "13": { - "inputs": { - "noise": [ - "147", - 0 - ], - "guider": [ - "22", - 0 - ], - "sampler": [ - "16", - 0 - ], - "sigmas": [ - "17", - 0 - ], - "latent_image": [ - "48", - 0 - ] - }, - "class_type": "SamplerCustomAdvanced", - "_meta": { - "title": "SamplerCustomAdvanced" - } - }, - "16": { - "inputs": { - "sampler_name": "dpmpp_2m" - }, - "class_type": "KSamplerSelect", - "_meta": { - "title": "KSamplerSelect" - } - }, - "17": { - "inputs": { - "scheduler": "beta", - "steps": [ - "246", - 0 - ], - "denoise": 1, - "model": [ - "28", - 0 - ] - }, - "class_type": "BasicScheduler", - "_meta": { - "title": "BasicScheduler" - } - }, - "22": { - "inputs": { - "model": [ - "28", - 0 - ], - "conditioning": [ - "29", - 0 - ] - }, - "class_type": "BasicGuider", - "_meta": { - "title": "BasicGuider" - } - }, - "28": { - "inputs": { - "max_shift": 1.1500000000000001, - "base_shift": 0.5, - "width": [ - "48", - 1 - ], - "height": [ - "48", - 2 - ], - "model": [ - "299", - 0 - ] - }, - "class_type": "ModelSamplingFlux", - "_meta": { - "title": "ModelSamplingFlux" - } - }, - "29": { - "inputs": { - "guidance": 3.5, - "conditioning": [ - "6", - 0 - ] - }, - "class_type": "FluxGuidance", - "_meta": { - "title": "FluxGuidance" - } - }, - "48": { - "inputs": { - "resolution": "832x1216 (0.68)", - "batch_size": 1, - "width_override": 0, - "height_override": 0 - }, - "class_type": "SDXLEmptyLatentSizePicker+", - "_meta": { - "title": "🔧 SDXL Empty Latent Size Picker" - } - }, - "65": { - "inputs": { - "unet_name": "flux\\flux1-dev-fp8-e4m3fn.safetensors", - "weight_dtype": "fp8_e4m3fn_fast" - }, - "class_type": "UNETLoader", - "_meta": { - "title": "Load Diffusion Model" - } - }, - "147": { - "inputs": { - "noise_seed": 651532572596956 - }, - "class_type": "RandomNoise", - "_meta": { - "title": "RandomNoise" - } - }, - "148": { - "inputs": { - "wildcard_text": "__some-prompts__", - "populated_text": "A surreal digital artwork showcases a forward-thinking inventor captivated by his intricate mechanical creation through a large magnifying glass. Viewed from an unconventional perspective, the scene reveals an eccentric assembly of gears, springs, and brass instruments within his workshop. Soft, ethereal light radiates from the invention, casting enigmatic shadows on the walls as time appears to bend around its metallic form, invoking a sense of curiosity, wonder, and exhilaration in discovery.", - "mode": "fixed", - "seed": 553084268162351, - "Select to add Wildcard": "Select the Wildcard to add to the text" - }, - "class_type": "ImpactWildcardProcessor", - "_meta": { - "title": "ImpactWildcardProcessor" - } - }, - "151": { - "inputs": { - "text": "A hyper-realistic close-up portrait of a young woman with shoulder-length black hair styled in edgy, futuristic layers, adorned with glowing tips. She wears mecha eyewear with a neon green visor that transitions into iridescent shades of teal and gold. The frame is sleek, with angular edges and fine mechanical detailing. Her expression is fierce and confident, with flawless skin highlighted by the neon reflections. She wears a high-tech bodysuit with integrated LED lines and metallic panels. The background depicts a hazy rendition of The Great Wave off Kanagawa by Hokusai, its powerful waves blending seamlessly with the neon tones, amplifying her intense, defiant aura." - }, - "class_type": "Text Multiline", - "_meta": { - "title": "Text Multiline" - } - }, - "191": { - "inputs": { - "text": "A cinematic, oil painting masterpiece captures the essence of impressionistic surrealism, inspired by Claude Monet. A mysterious woman in a flowing crimson dress stands at the edge of a tranquil lake, where lily pads shimmer under an ethereal, golden twilight. The water’s surface reflects a dreamlike sky, its swirling hues of violet and sapphire melting together like liquid light. The thick, expressive brushstrokes lend depth to the scene, evoking a sense of nostalgia and quiet longing, as if the world itself is caught between reality and a fleeting dream. \nA mesmerizing oil painting masterpiece inspired by Salvador Dalí, blending surrealism with post-impressionist texture. A lone violinist plays atop a melting clock tower, his form distorted by the passage of time. The sky is a cascade of swirling, liquid oranges and deep blues, where floating staircases spiral endlessly into the horizon. The impasto technique gives depth and movement to the surreal elements, making time itself feel fluid, as if the world is dissolving into a dream. \nA stunning impressionistic oil painting evokes the spirit of Edvard Munch, capturing a solitary figure standing on a rain-soaked street, illuminated by the glow of flickering gas lamps. The swirling, chaotic strokes of deep blues and fiery reds reflect the turbulence of emotion, while the blurred reflections in the wet cobblestone suggest a merging of past and present. The faceless figure, draped in a dark overcoat, seems lost in thought, embodying the ephemeral nature of memory and time. \nA breathtaking oil painting masterpiece, inspired by Gustav Klimt, presents a celestial ballroom where faceless dancers swirl in an eternal waltz beneath a gilded, star-speckled sky. Their golden garments shimmer with intricate patterns, blending into the opulent mosaic floor that seems to stretch into infinity. The dreamlike composition, rich in warm amber and deep sapphire hues, captures an otherworldly elegance, as if the dancers are suspended in a moment that transcends time. \nA visionary oil painting inspired by Marc Chagall depicts a dreamlike cityscape where gravity ceases to exist. A couple floats above a crimson-tinted town, their forms dissolving into the swirling strokes of a vast, cerulean sky. The buildings below twist and bend in rhythmic motion, their windows glowing like tiny stars. The thick, textured brushwork conveys a sense of weightlessness and wonder, as if love itself has defied the laws of the universe. \nAn impressionistic oil painting in the style of J.M.W. Turner, depicting a ghostly ship sailing through a sea of swirling golden mist. The waves crash and dissolve into abstract, fiery strokes of orange and deep indigo, blurring the line between ocean and sky. The ship appears almost ethereal, as if drifting between worlds, lost in the ever-changing tides of memory and myth. The dynamic brushstrokes capture the relentless power of nature and the fleeting essence of time. \nA captivating oil painting masterpiece, infused with surrealist impressionism, portrays a grand library where books float midair, their pages unraveling into ribbons of light. The towering shelves twist into the heavens, vanishing into an infinite, starry void. A lone scholar, illuminated by the glow of a suspended lantern, reaches for a book that seems to pulse with life. The scene pulses with mystery, where the impasto textures bring depth to the interplay between knowledge and dreams. \nA luminous impressionistic oil painting captures the melancholic beauty of an abandoned carnival, its faded carousel horses frozen mid-gallop beneath a sky of swirling lavender and gold. The wind carries fragments of forgotten laughter through the empty fairground, where scattered ticket stubs and crumbling banners whisper tales of joy long past. The thick, textured brushstrokes blend nostalgia with an eerie dreamlike quality, as if the carnival exists only in the echoes of memory. \nA surreal oil painting in the spirit of René Magritte, featuring a towering lighthouse that emits not light, but cascading waterfalls from its peak. The swirling sky, painted in deep midnight blues, is punctuated by glowing, crescent moons that defy gravity. A lone figure stands at the water’s edge, gazing up in quiet contemplation, as if caught between wonder and the unknown. The painting’s rich textures and luminous colors create an enigmatic, dreamlike landscape. \nA striking impressionistic oil painting, reminiscent of Van Gogh, portrays a lone traveler on a winding cobblestone path, their silhouette bathed in the golden glow of lantern-lit cherry blossoms. The petals swirl through the night air like glowing embers, blending with the deep, rhythmic strokes of a star-filled indigo sky. The scene captures a feeling of wistful solitude, as if the traveler is walking not only through the city, but through the fleeting nature of time itself." - }, - "class_type": "Text Multiline", - "_meta": { - "title": "Text Multiline" - } - }, - "203": { - "inputs": { - "string1": [ - "289", - 0 - ], - "string2": [ - "293", - 0 - ], - "delimiter": ", " - }, - "class_type": "JoinStrings", - "_meta": { - "title": "Join Strings" - } - }, - "208": { - "inputs": { - "file_path": "", - "dictionary_name": "[filename]", - "label": "TextBatch", - "mode": "automatic", - "index": 0, - "multiline_text": [ - "191", - 0 - ] - }, - "class_type": "Text Load Line From File", - "_meta": { - "title": "Text Load Line From File" - } - }, - "226": { - "inputs": { - "images": [ - "8", - 0 - ] - }, - "class_type": "PreviewImage", - "_meta": { - "title": "Preview Image" - } - }, - "246": { - "inputs": { - "value": 25 - }, - "class_type": "INTConstant", - "_meta": { - "title": "Steps" - } - }, - "289": { - "inputs": { - "group_mode": true, - "toggle_trigger_words": [ - { - "text": "bo-exposure", - "active": true - }, - { - "text": "__dummy_item__", - "active": false, - "_isDummy": true - }, - { - "text": "__dummy_item__", - "active": false, - "_isDummy": true - } - ], - "orinalMessage": "bo-exposure", - "trigger_words": [ - "299", - 2 - ] - }, - "class_type": "TriggerWord Toggle (LoraManager)", - "_meta": { - "title": "TriggerWord Toggle (LoraManager)" - } - }, - "293": { - "inputs": { - "input": 1, - "text1": [ - "208", - 0 - ], - "text2": [ - "151", - 0 - ] - }, - "class_type": "easy textSwitch", - "_meta": { - "title": "Text Switch" - } - }, - "297": { - "inputs": { - "text": "" - }, - "class_type": "Lora Stacker (LoraManager)", - "_meta": { - "title": "Lora Stacker (LoraManager)" - } - }, - "298": { - "inputs": { - "anything": [ - "297", - 0 - ] - }, - "class_type": "easy showAnything", - "_meta": { - "title": "Show Any" - } - }, - "299": { - "inputs": { - "text": " ", - "loras": [ - { - "name": "boFLUX Double Exposure Magic v2", - "strength": 0.8, - "active": true - }, - { - "name": "FluxDFaeTasticDetails", - "strength": 0.65, - "active": true - }, - { - "name": "__dummy_item1__", - "strength": 0, - "active": false, - "_isDummy": true - }, - { - "name": "__dummy_item2__", - "strength": 0, - "active": false, - "_isDummy": true - } - ], - "model": [ - "65", - 0 - ], - "clip": [ - "11", - 0 - ], - "lora_stack": [ - "297", - 0 - ] - }, - "class_type": "Lora Loader (LoraManager)", - "_meta": { - "title": "Lora Loader (LoraManager)" - } - }, - "301": { - "inputs": { - "string": "A hyper-realistic close-up portrait of a young woman with shoulder-length black hair styled in edgy, futuristic layers, adorned with glowing tips. She wears mecha eyewear with a neon green visor that transitions into iridescent shades of teal and gold. The frame is sleek, with angular edges and fine mechanical detailing. Her expression is fierce and confident, with flawless skin highlighted by the neon reflections. She wears a high-tech bodysuit with integrated LED lines and metallic panels. The background depicts a hazy rendition of The Great Wave off Kanagawa by Hokusai, its powerful waves blending seamlessly with the neon tones, amplifying her intense, defiant aura.", - "strip_newlines": true - }, - "class_type": "StringConstantMultiline", - "_meta": { - "title": "String Constant Multiline" - } - } -} \ No newline at end of file diff --git a/refs/version.json b/refs/version.json new file mode 100644 index 00000000..03fd8fd3 --- /dev/null +++ b/refs/version.json @@ -0,0 +1,91 @@ +{ + "id": 1255556, + "modelId": 1117241, + "name": "v1.0", + "createdAt": "2025-01-08T06:13:08.839Z", + "updatedAt": "2025-01-08T06:28:54.156Z", + "status": "Published", + "publishedAt": "2025-01-08T06:28:54.155Z", + "trainedWords": ["in the style of ppWhimsy"], + "trainingStatus": null, + "trainingDetails": null, + "baseModel": "Flux.1 D", + "baseModelType": "Standard", + "earlyAccessEndsAt": null, + "earlyAccessConfig": null, + "description": null, + "uploadType": "Created", + "usageControl": "Download", + "air": "urn:air:flux1:lora:civitai:1117241@1255556", + "stats": { + "downloadCount": 210, + "ratingCount": 0, + "rating": 0, + "thumbsUpCount": 26 + }, + "model": { + "name": "Enchanted Whimsy style (Flux)", + "type": "LORA", + "nsfw": false, + "poi": false + }, + "files": [ + { + "id": 1160774, + "sizeKB": 38828.8125, + "name": "pp-enchanted-whimsy.safetensors", + "type": "Model", + "pickleScanResult": "Success", + "pickleScanMessage": "No Pickle imports", + "virusScanResult": "Success", + "virusScanMessage": null, + "scannedAt": "2025-01-08T06:16:27.731Z", + "metadata": { + "format": "SafeTensor", + "size": null, + "fp": null + }, + "hashes": { + "AutoV1": "40CAF049", + "AutoV2": "3202778C3E", + "SHA256": "3202778C3EBE5CF7EBE5FC51561DEAE8611F4362036EB7C02EFA033C705E6240", + "CRC32": "69DCD953", + "BLAKE3": "ED04580DDB1AD36D8B87F4B0800F5930C7E5D4A7269BDC2BE26ED77EA1A34697", + "AutoV3": "BF82986F8597" + }, + "primary": true, + "downloadUrl": "https://civitai.com/api/download/models/1255556" + } + ], + "images": [ + { + "url": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/707aef9b-36fb-46c2-ac41-adcab539d3a6/width=832/50270101.jpeg", + "nsfwLevel": 1, + "width": 832, + "height": 1216, + "hash": "U7Am@@$^J3%100R;pLR.M]tQ-ps+?wRiVrof", + "type": "image", + "metadata": { + "hash": "U7Am@@$^J3%100R;pLR.M]tQ-ps+?wRiVrof", + "size": 702313, + "width": 832, + "height": 1216 + }, + "minor": false, + "poi": false, + "meta": { + "prompt": "in the style of ppWhimsy, a close-up of a boy with a crown of ferns and tiny horns, his eyes wide with wonder as a family of glowing hedgehogs nestle in his hands, their spines shimmering with soft pastel colors" + }, + "availability": "Public", + "hasMeta": true, + "hasPositivePrompt": true, + "onSite": false, + "remixOfId": null + } + ], + "downloadUrl": "https://civitai.com/api/download/models/1255556", + "creator": { + "username": "PixelPawsAI", + "image": "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/f3a1aa7c-0159-4dd8-884a-1e7ceb350f96/width=96/PixelPawsAI.jpeg" + } +} From f51f354e48cd3c08b8d106b4872681ba18d87094 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Wed, 24 Sep 2025 15:39:52 +0800 Subject: [PATCH 094/110] test(frontend): add dom fixture helpers --- docs/frontend-dom-fixtures.md | 51 ++++++++++++++ docs/frontend-testing-roadmap.md | 5 +- tests/frontend/setup.js | 6 +- .../js => tests/frontend}/state/index.test.js | 6 +- tests/frontend/utils/domFixtures.js | 68 +++++++++++++++++++ .../frontend}/utils/storageHelpers.test.js | 2 +- vitest.config.js | 1 - 7 files changed, 129 insertions(+), 10 deletions(-) create mode 100644 docs/frontend-dom-fixtures.md rename {static/js => tests/frontend}/state/index.test.js (88%) create mode 100644 tests/frontend/utils/domFixtures.js rename {static/js => tests/frontend}/utils/storageHelpers.test.js (97%) diff --git a/docs/frontend-dom-fixtures.md b/docs/frontend-dom-fixtures.md new file mode 100644 index 00000000..ee7b785c --- /dev/null +++ b/docs/frontend-dom-fixtures.md @@ -0,0 +1,51 @@ +# Frontend DOM Fixture Strategy + +This guide outlines how to reproduce the markup emitted by the Django templates while running Vitest in jsdom. The aim is to make it straightforward to write integration-style unit tests for managers and UI helpers without having to duplicate template fragments inline. + +## Loading Template Markup + +Vitest executes inside Node, so we can read the same HTML templates that ship with the extension: + +1. Use the helper utilities from `tests/frontend/utils/domFixtures.js` to read files under the `templates/` directory. +2. Mount the returned markup into `document.body` (or any custom container) before importing the module under test so its query selectors resolve correctly. + +```js +import { renderTemplate } from '../utils/domFixtures.js'; // adjust the relative path to your spec + +beforeEach(() => { + renderTemplate('loras.html', { + dataset: { page: 'loras' } + }); +}); +``` + +The helper ensures the dataset is applied to the container, which mirrors how Django sets `data-page` in production. + +## Working with Partial Components + +Many features are implemented as template partials located under `templates/components/`. When a test only needs a fragment (for example, the progress panel or context menu markup), load the component file directly: + +```js +const container = renderTemplate('components/progress_panel.html'); + +const progressPanel = container.querySelector('#progress-panel'); +``` + +This pattern avoids hand-written fixture strings and keeps the tests aligned with the actual markup. + +## Resetting Between Tests + +The shared Vitest setup clears `document.body` and storage APIs before each test. If a suite adds additional DOM nodes outside of the body or needs to reset custom attributes mid-test, use `resetDom()` exported from `domFixtures.js`. + +```js +import { resetDom } from '../utils/domFixtures.js'; + +afterEach(() => { + resetDom(); +}); +``` + +## Future Enhancements + +- Provide typed helpers for injecting mock script tags (e.g., replicating ComfyUI globals). +- Compose higher-level fixtures that mimic specific pages (loras, checkpoints, recipes) once those managers receive dedicated suites. diff --git a/docs/frontend-testing-roadmap.md b/docs/frontend-testing-roadmap.md index e39e7c03..515e1baf 100644 --- a/docs/frontend-testing-roadmap.md +++ b/docs/frontend-testing-roadmap.md @@ -8,7 +8,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR | --- | --- | --- | --- | --- | | Phase 0 | Establish baseline tooling | Add Node test runner, jsdom environment, and seed smoke tests | ✅ Complete | Vitest + jsdom configured, example state tests committed | | Phase 1 | Cover state management logic | Unit test selectors, derived data helpers, and storage utilities under `static/js/state` and `static/js/utils` | ✅ Complete | Storage helpers and state selectors now exercised via deterministic suites | -| Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | 🟡 In Progress | AppCore initialization specs landed; expand to additional page wiring and scroll hooks | +| Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | 🟡 In Progress | AppCore initialization specs landed; documented DOM fixture workflow and plan to expand to additional page wiring and scroll hooks | | Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | ⚪ Not Started | Consider shared helpers for mocking API modules and storage | | Phase 4 | Interaction-level regression tests | Exercise template fragments, modals, and menus to ensure UI wiring remains intact | ⚪ Not Started | Evaluate Playwright component testing or happy-path DOM snapshots | | Phase 5 | Continuous integration & coverage | Integrate frontend tests into CI workflow and track coverage metrics | ⚪ Not Started | Align reporting directories with backend coverage for unified reporting | @@ -16,8 +16,9 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR ## Next Steps Checklist - [x] Expand unit tests for `storageHelpers` covering migrations and namespace behavior. -- [ ] Document DOM fixture strategy for reproducing template structures in tests. +- [x] Document DOM fixture strategy for reproducing template structures in tests. - [x] Prototype AppCore initialization test that verifies manager bootstrapping with stubbed dependencies. - [ ] Evaluate integrating coverage reporting once test surface grows (> 20 specs). +- [ ] Create shared fixtures for the loras and checkpoints pages once dedicated manager suites are added. Maintaining this roadmap alongside code changes will make it easier to append new automated test tasks and update their progress. diff --git a/tests/frontend/setup.js b/tests/frontend/setup.js index d575c568..b6862e67 100644 --- a/tests/frontend/setup.js +++ b/tests/frontend/setup.js @@ -1,4 +1,5 @@ import { afterEach, beforeEach } from 'vitest'; +import { resetDom } from './utils/domFixtures.js'; beforeEach(() => { // Ensure storage is clean before each test to avoid cross-test pollution @@ -6,11 +7,10 @@ beforeEach(() => { sessionStorage.clear(); // Reset DOM state for modules that rely on body attributes - document.body.innerHTML = ''; - document.body.dataset.page = ''; + resetDom(); }); afterEach(() => { // Clean any dynamically attached globals by tests - delete document.body.dataset.page; + resetDom(); }); diff --git a/static/js/state/index.test.js b/tests/frontend/state/index.test.js similarity index 88% rename from static/js/state/index.test.js rename to tests/frontend/state/index.test.js index da9221ea..50e5e6e8 100644 --- a/static/js/state/index.test.js +++ b/tests/frontend/state/index.test.js @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach } from 'vitest'; -import { createDefaultSettings, getCurrentPageState, initPageState, setCurrentPageType, state } from './index.js'; -import { MODEL_TYPES } from '../api/apiConfig.js'; -import { DEFAULT_PATH_TEMPLATES } from '../utils/constants.js'; +import { createDefaultSettings, getCurrentPageState, initPageState, setCurrentPageType, state } from '../../../static/js/state/index.js'; +import { MODEL_TYPES } from '../../../static/js/api/apiConfig.js'; +import { DEFAULT_PATH_TEMPLATES } from '../../../static/js/utils/constants.js'; describe('state module', () => { beforeEach(() => { diff --git a/tests/frontend/utils/domFixtures.js b/tests/frontend/utils/domFixtures.js new file mode 100644 index 00000000..ea903473 --- /dev/null +++ b/tests/frontend/utils/domFixtures.js @@ -0,0 +1,68 @@ +import fs from 'node:fs'; +import path from 'node:path'; + +const TEMPLATE_ROOT = path.resolve(process.cwd(), 'templates'); + +/** + * Reads an HTML template from the templates directory and returns its markup. + * @param {string} relativePath - Path relative to the templates directory. + * @returns {string} + */ +export function readTemplate(relativePath) { + const filePath = path.join(TEMPLATE_ROOT, relativePath); + return fs.readFileSync(filePath, 'utf-8'); +} + +/** + * Injects the provided HTML markup into the supplied container (defaults to document.body). + * @param {string} html + * @param {Element} [container=document.body] + * @returns {Element} + */ +export function mountMarkup(html, container = document.body) { + container.innerHTML = html; + return container; +} + +/** + * Loads a template file and mounts it into the DOM, returning the container used. + * @param {string} relativePath - Template path relative to templates directory. + * @param {{ + * container?: Element, + * dataset?: Record, + * beforeMount?: (options: { container: Element }) => void, + * afterMount?: (options: { container: Element }) => void + * }} [options] + * @returns {Element} + */ +export function renderTemplate(relativePath, options = {}) { + const { container = document.body, dataset = {}, beforeMount, afterMount } = options; + if (beforeMount) { + beforeMount({ container }); + } + + const html = readTemplate(relativePath); + const target = mountMarkup(html, container); + + Object.entries(dataset).forEach(([key, value]) => { + target.dataset[key] = value; + }); + + if (afterMount) { + afterMount({ container: target }); + } + + return target; +} + +/** + * Utility to reset the DOM to a clean state. Useful when tests modify the structure + * beyond what the shared Vitest setup clears. + * @param {Element} [container=document.body] + */ +export function resetDom(container = document.body) { + container.innerHTML = ''; + if (container === document.body) { + document.body.removeAttribute('data-page'); + } +} diff --git a/static/js/utils/storageHelpers.test.js b/tests/frontend/utils/storageHelpers.test.js similarity index 97% rename from static/js/utils/storageHelpers.test.js rename to tests/frontend/utils/storageHelpers.test.js index 8603deb1..87acbcc7 100644 --- a/static/js/utils/storageHelpers.test.js +++ b/tests/frontend/utils/storageHelpers.test.js @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; -import * as storageHelpers from './storageHelpers.js'; +import * as storageHelpers from '../../../static/js/utils/storageHelpers.js'; const { getStorageItem, diff --git a/vitest.config.js b/vitest.config.js index f0dd3877..7f804af9 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -6,7 +6,6 @@ export default defineConfig({ globals: true, setupFiles: ['tests/frontend/setup.js'], include: [ - 'static/js/**/*.test.js', 'tests/frontend/**/*.test.js' ], coverage: { From d58b61eed503b5fea5cada01f1ee6363a97e9698 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Wed, 24 Sep 2025 15:55:50 +0800 Subject: [PATCH 095/110] test(frontend): cover appcore page features --- docs/frontend-testing-roadmap.md | 3 +- tests/frontend/core/appCore.test.js | 153 ++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 tests/frontend/core/appCore.test.js diff --git a/docs/frontend-testing-roadmap.md b/docs/frontend-testing-roadmap.md index 515e1baf..4c64398e 100644 --- a/docs/frontend-testing-roadmap.md +++ b/docs/frontend-testing-roadmap.md @@ -8,7 +8,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR | --- | --- | --- | --- | --- | | Phase 0 | Establish baseline tooling | Add Node test runner, jsdom environment, and seed smoke tests | ✅ Complete | Vitest + jsdom configured, example state tests committed | | Phase 1 | Cover state management logic | Unit test selectors, derived data helpers, and storage utilities under `static/js/state` and `static/js/utils` | ✅ Complete | Storage helpers and state selectors now exercised via deterministic suites | -| Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | 🟡 In Progress | AppCore initialization specs landed; documented DOM fixture workflow and plan to expand to additional page wiring and scroll hooks | +| Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | 🟡 In Progress | AppCore initialization specs landed; DOM fixtures now cover page feature wiring (context menus + infinite scroll); next focus is scroll hooks and manager wiring | | Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | ⚪ Not Started | Consider shared helpers for mocking API modules and storage | | Phase 4 | Interaction-level regression tests | Exercise template fragments, modals, and menus to ensure UI wiring remains intact | ⚪ Not Started | Evaluate Playwright component testing or happy-path DOM snapshots | | Phase 5 | Continuous integration & coverage | Integrate frontend tests into CI workflow and track coverage metrics | ⚪ Not Started | Align reporting directories with backend coverage for unified reporting | @@ -18,6 +18,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR - [x] Expand unit tests for `storageHelpers` covering migrations and namespace behavior. - [x] Document DOM fixture strategy for reproducing template structures in tests. - [x] Prototype AppCore initialization test that verifies manager bootstrapping with stubbed dependencies. +- [x] Add AppCore page feature suite exercising context menu creation and infinite scroll registration via DOM fixtures. - [ ] Evaluate integrating coverage reporting once test surface grows (> 20 specs). - [ ] Create shared fixtures for the loras and checkpoints pages once dedicated manager suites are added. diff --git a/tests/frontend/core/appCore.test.js b/tests/frontend/core/appCore.test.js new file mode 100644 index 00000000..864cbd29 --- /dev/null +++ b/tests/frontend/core/appCore.test.js @@ -0,0 +1,153 @@ +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; +import { renderTemplate, resetDom } from '../utils/domFixtures.js'; + +vi.mock('../../../static/js/managers/LoadingManager.js', () => ({ + LoadingManager: vi.fn(() => ({})), +})); + +vi.mock('../../../static/js/managers/ModalManager.js', () => ({ + modalManager: { initialize: vi.fn() }, +})); + +vi.mock('../../../static/js/managers/UpdateService.js', () => ({ + updateService: { initialize: vi.fn() }, +})); + +vi.mock('../../../static/js/components/Header.js', () => ({ + HeaderManager: vi.fn(() => ({})), +})); + +vi.mock('../../../static/js/managers/SettingsManager.js', () => ({ + settingsManager: { + waitForInitialization: vi.fn().mockResolvedValue(undefined), + }, +})); + +vi.mock('../../../static/js/managers/MoveManager.js', () => ({ + moveManager: { initialize: vi.fn() }, +})); + +vi.mock('../../../static/js/managers/BulkManager.js', () => ({ + bulkManager: { + initialize: vi.fn(), + setBulkContextMenu: vi.fn(), + }, +})); + +vi.mock('../../../static/js/managers/ExampleImagesManager.js', () => ({ + ExampleImagesManager: vi.fn(() => ({ + initialize: vi.fn(), + })), +})); + +vi.mock('../../../static/js/managers/HelpManager.js', () => ({ + helpManager: { + initialize: vi.fn(), + }, +})); + +vi.mock('../../../static/js/managers/BannerService.js', () => ({ + bannerService: { + initialize: vi.fn(), + isBannerVisible: vi.fn().mockReturnValue(false), + }, +})); + +vi.mock('../../../static/js/utils/uiHelpers.js', () => ({ + initTheme: vi.fn(), + initBackToTop: vi.fn(), + showToast: vi.fn(), +})); + +vi.mock('../../../static/js/i18n/index.js', () => ({ + i18n: { + waitForReady: vi.fn().mockResolvedValue(undefined), + getCurrentLocale: vi.fn().mockReturnValue('en'), + }, +})); + +vi.mock('../../../static/js/managers/OnboardingManager.js', () => ({ + onboardingManager: { + start: vi.fn(), + }, +})); + +vi.mock('../../../static/js/components/ContextMenu/BulkContextMenu.js', () => ({ + BulkContextMenu: vi.fn(), +})); + +vi.mock('../../../static/js/utils/eventManagementInit.js', () => ({ + initializeEventManagement: vi.fn(), +})); + +vi.mock('../../../static/js/utils/infiniteScroll.js', () => ({ + initializeInfiniteScroll: vi.fn(), +})); + +vi.mock('../../../static/js/components/ContextMenu/index.js', () => ({ + createPageContextMenu: vi.fn((pageType) => ({ pageType })), + createGlobalContextMenu: vi.fn(() => ({ type: 'global' })), +})); + +import { appCore } from '../../../static/js/core.js'; +import { initializeInfiniteScroll } from '../../../static/js/utils/infiniteScroll.js'; +import { createPageContextMenu, createGlobalContextMenu } from '../../../static/js/components/ContextMenu/index.js'; + +const SUPPORTED_PAGES = ['loras', 'recipes', 'checkpoints', 'embeddings']; + +describe('AppCore page orchestration', () => { + beforeEach(() => { + resetDom(); + delete window.pageContextMenu; + delete window.globalContextMenuInstance; + vi.clearAllMocks(); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + it.each(SUPPORTED_PAGES)('initializes page features for %s pages', (pageType) => { + renderTemplate('loras.html', { dataset: { page: pageType } }); + const contextSpy = vi.spyOn(appCore, 'initializeContextMenus'); + + appCore.initializePageFeatures(); + + expect(contextSpy).toHaveBeenCalledWith(pageType); + expect(initializeInfiniteScroll).toHaveBeenCalledWith(pageType); + }); + + it('skips initialization when page type is unsupported', () => { + renderTemplate('statistics.html', { dataset: { page: 'statistics' } }); + const contextSpy = vi.spyOn(appCore, 'initializeContextMenus'); + + appCore.initializePageFeatures(); + + expect(contextSpy).not.toHaveBeenCalled(); + expect(initializeInfiniteScroll).not.toHaveBeenCalled(); + }); + + it('creates page and global context menus on first initialization', () => { + const pageMenu = { menu: 'page' }; + const globalMenu = { menu: 'global' }; + createPageContextMenu.mockReturnValueOnce(pageMenu); + createGlobalContextMenu.mockReturnValueOnce(globalMenu); + + appCore.initializeContextMenus('loras'); + + expect(createPageContextMenu).toHaveBeenCalledWith('loras'); + expect(window.pageContextMenu).toBe(pageMenu); + expect(createGlobalContextMenu).toHaveBeenCalledTimes(1); + expect(window.globalContextMenuInstance).toBe(globalMenu); + }); + + it('reuses the existing global context menu instance on subsequent calls', () => { + const existingGlobalMenu = { menu: 'existing' }; + window.globalContextMenuInstance = existingGlobalMenu; + + appCore.initializeContextMenus('loras'); + + expect(createGlobalContextMenu).not.toHaveBeenCalled(); + expect(window.globalContextMenuInstance).toBe(existingGlobalMenu); + }); +}); From 9d5ec43c4ef448d5629bc22f7981d8cd802c02a2 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Wed, 24 Sep 2025 16:10:27 +0800 Subject: [PATCH 096/110] fix(frontend): correct AppCore example images initialization --- docs/frontend-testing-roadmap.md | 4 +- static/js/core.js | 3 +- tests/frontend/core/appCore.test.js | 133 ++++++++++++++++++++++++++-- 3 files changed, 132 insertions(+), 8 deletions(-) diff --git a/docs/frontend-testing-roadmap.md b/docs/frontend-testing-roadmap.md index 4c64398e..03bbf026 100644 --- a/docs/frontend-testing-roadmap.md +++ b/docs/frontend-testing-roadmap.md @@ -8,7 +8,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR | --- | --- | --- | --- | --- | | Phase 0 | Establish baseline tooling | Add Node test runner, jsdom environment, and seed smoke tests | ✅ Complete | Vitest + jsdom configured, example state tests committed | | Phase 1 | Cover state management logic | Unit test selectors, derived data helpers, and storage utilities under `static/js/state` and `static/js/utils` | ✅ Complete | Storage helpers and state selectors now exercised via deterministic suites | -| Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | 🟡 In Progress | AppCore initialization specs landed; DOM fixtures now cover page feature wiring (context menus + infinite scroll); next focus is scroll hooks and manager wiring | +| Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | ✅ Complete | AppCore initialization + page feature suites now validate manager wiring, infinite scroll hooks, and onboarding gating | | Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | ⚪ Not Started | Consider shared helpers for mocking API modules and storage | | Phase 4 | Interaction-level regression tests | Exercise template fragments, modals, and menus to ensure UI wiring remains intact | ⚪ Not Started | Evaluate Playwright component testing or happy-path DOM snapshots | | Phase 5 | Continuous integration & coverage | Integrate frontend tests into CI workflow and track coverage metrics | ⚪ Not Started | Align reporting directories with backend coverage for unified reporting | @@ -19,7 +19,9 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR - [x] Document DOM fixture strategy for reproducing template structures in tests. - [x] Prototype AppCore initialization test that verifies manager bootstrapping with stubbed dependencies. - [x] Add AppCore page feature suite exercising context menu creation and infinite scroll registration via DOM fixtures. +- [x] Extend AppCore orchestration tests to cover manager wiring, bulk menu setup, and onboarding gating scenarios. - [ ] Evaluate integrating coverage reporting once test surface grows (> 20 specs). - [ ] Create shared fixtures for the loras and checkpoints pages once dedicated manager suites are added. +- [ ] Draft focused test matrix for loras/checkpoints manager filtering and sorting paths ahead of Phase 3. Maintaining this roadmap alongside code changes will make it easier to append new automated test tasks and update their progress. diff --git a/static/js/core.js b/static/js/core.js index 80e0ec69..9701a32f 100644 --- a/static/js/core.js +++ b/static/js/core.js @@ -49,7 +49,8 @@ export class AppCore { bannerService.initialize(); window.modalManager = modalManager; window.settingsManager = settingsManager; - window.exampleImagesManager = new ExampleImagesManager(); + const exampleImagesManager = new ExampleImagesManager(); + window.exampleImagesManager = exampleImagesManager; window.helpManager = helpManager; window.moveManager = moveManager; window.bulkManager = bulkManager; diff --git a/tests/frontend/core/appCore.test.js b/tests/frontend/core/appCore.test.js index 864cbd29..094200f1 100644 --- a/tests/frontend/core/appCore.test.js +++ b/tests/frontend/core/appCore.test.js @@ -1,8 +1,14 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { renderTemplate, resetDom } from '../utils/domFixtures.js'; +const loadingManagerInstance = { showSimpleLoading: vi.fn(), hide: vi.fn() }; +const exampleImagesManagerInitialize = vi.fn(); +const exampleImagesManagerInstance = { initialize: exampleImagesManagerInitialize }; +const bulkContextMenuInstance = { menu: 'bulk-context' }; +const headerManagerInstance = { type: 'header-manager' }; + vi.mock('../../../static/js/managers/LoadingManager.js', () => ({ - LoadingManager: vi.fn(() => ({})), + LoadingManager: vi.fn(() => loadingManagerInstance), })); vi.mock('../../../static/js/managers/ModalManager.js', () => ({ @@ -14,7 +20,7 @@ vi.mock('../../../static/js/managers/UpdateService.js', () => ({ })); vi.mock('../../../static/js/components/Header.js', () => ({ - HeaderManager: vi.fn(() => ({})), + HeaderManager: vi.fn(() => headerManagerInstance), })); vi.mock('../../../static/js/managers/SettingsManager.js', () => ({ @@ -35,9 +41,7 @@ vi.mock('../../../static/js/managers/BulkManager.js', () => ({ })); vi.mock('../../../static/js/managers/ExampleImagesManager.js', () => ({ - ExampleImagesManager: vi.fn(() => ({ - initialize: vi.fn(), - })), + ExampleImagesManager: vi.fn(() => exampleImagesManagerInstance), })); vi.mock('../../../static/js/managers/HelpManager.js', () => ({ @@ -73,7 +77,7 @@ vi.mock('../../../static/js/managers/OnboardingManager.js', () => ({ })); vi.mock('../../../static/js/components/ContextMenu/BulkContextMenu.js', () => ({ - BulkContextMenu: vi.fn(), + BulkContextMenu: vi.fn(() => bulkContextMenuInstance), })); vi.mock('../../../static/js/utils/eventManagementInit.js', () => ({ @@ -90,6 +94,21 @@ vi.mock('../../../static/js/components/ContextMenu/index.js', () => ({ })); import { appCore } from '../../../static/js/core.js'; +import { state } from '../../../static/js/state/index.js'; +import { LoadingManager } from '../../../static/js/managers/LoadingManager.js'; +import { modalManager } from '../../../static/js/managers/ModalManager.js'; +import { updateService } from '../../../static/js/managers/UpdateService.js'; +import { settingsManager } from '../../../static/js/managers/SettingsManager.js'; +import { moveManager } from '../../../static/js/managers/MoveManager.js'; +import { bulkManager } from '../../../static/js/managers/BulkManager.js'; +import { ExampleImagesManager } from '../../../static/js/managers/ExampleImagesManager.js'; +import { helpManager } from '../../../static/js/managers/HelpManager.js'; +import { bannerService } from '../../../static/js/managers/BannerService.js'; +import { initTheme, initBackToTop } from '../../../static/js/utils/uiHelpers.js'; +import { onboardingManager } from '../../../static/js/managers/OnboardingManager.js'; +import { BulkContextMenu } from '../../../static/js/components/ContextMenu/BulkContextMenu.js'; +import { HeaderManager } from '../../../static/js/components/Header.js'; +import { initializeEventManagement } from '../../../static/js/utils/eventManagementInit.js'; import { initializeInfiniteScroll } from '../../../static/js/utils/infiniteScroll.js'; import { createPageContextMenu, createGlobalContextMenu } from '../../../static/js/components/ContextMenu/index.js'; @@ -151,3 +170,105 @@ describe('AppCore page orchestration', () => { expect(window.globalContextMenuInstance).toBe(existingGlobalMenu); }); }); + +describe('AppCore initialization flow', () => { + beforeEach(() => { + vi.useFakeTimers(); + vi.clearAllMocks(); + resetDom(); + document.body.className = ''; + appCore.initialized = false; + state.loadingManager = undefined; + state.currentPageType = 'loras'; + state.global.settings.card_info_display = 'always'; + delete window.modalManager; + delete window.settingsManager; + delete window.exampleImagesManager; + delete window.helpManager; + delete window.moveManager; + delete window.bulkManager; + delete window.headerManager; + delete window.i18n; + delete window.pageContextMenu; + delete window.globalContextMenuInstance; + }); + + afterEach(async () => { + await vi.runAllTimersAsync(); + vi.clearAllTimers(); + vi.useRealTimers(); + }); + + it('initializes core managers and global references', async () => { + state.global.settings.card_info_display = 'hover'; + + const result = await appCore.initialize(); + + expect(result).toBe(appCore); + expect(window.i18n).toBeDefined(); + expect(settingsManager.waitForInitialization).toHaveBeenCalledTimes(1); + expect(LoadingManager).toHaveBeenCalledTimes(1); + expect(state.loadingManager).toBe(loadingManagerInstance); + expect(modalManager.initialize).toHaveBeenCalledTimes(1); + expect(updateService.initialize).toHaveBeenCalledTimes(1); + expect(bannerService.initialize).toHaveBeenCalledTimes(1); + expect(window.modalManager).toBe(modalManager); + expect(window.settingsManager).toBe(settingsManager); + expect(window.moveManager).toBe(moveManager); + expect(window.bulkManager).toBe(bulkManager); + expect(HeaderManager).toHaveBeenCalledTimes(1); + expect(window.headerManager).toBe(headerManagerInstance); + expect(initTheme).toHaveBeenCalledTimes(1); + expect(initBackToTop).toHaveBeenCalledTimes(1); + expect(bulkManager.initialize).toHaveBeenCalledTimes(1); + expect(BulkContextMenu).toHaveBeenCalledTimes(1); + expect(bulkManager.setBulkContextMenu).toHaveBeenCalledWith(bulkContextMenuInstance); + expect(ExampleImagesManager).toHaveBeenCalledTimes(1); + expect(window.exampleImagesManager).toBe(exampleImagesManagerInstance); + expect(exampleImagesManagerInitialize).toHaveBeenCalledTimes(1); + expect(helpManager.initialize).toHaveBeenCalledTimes(1); + expect(document.body.classList.contains('hover-reveal')).toBe(true); + expect(initializeEventManagement).toHaveBeenCalledTimes(1); + expect(onboardingManager.start).not.toHaveBeenCalled(); + + await vi.runAllTimersAsync(); + + expect(onboardingManager.start).toHaveBeenCalledTimes(1); + expect(bannerService.isBannerVisible).toHaveBeenCalledWith('version-mismatch'); + }); + + it('does not reinitialize once initialized', async () => { + await appCore.initialize(); + await vi.runAllTimersAsync(); + + vi.clearAllMocks(); + + const result = await appCore.initialize(); + + expect(result).toBeUndefined(); + expect(LoadingManager).not.toHaveBeenCalled(); + expect(modalManager.initialize).not.toHaveBeenCalled(); + expect(updateService.initialize).not.toHaveBeenCalled(); + expect(ExampleImagesManager).not.toHaveBeenCalled(); + expect(onboardingManager.start).not.toHaveBeenCalled(); + }); + + it('skips bulk setup when viewing recipes', async () => { + state.currentPageType = 'recipes'; + + await appCore.initialize(); + + expect(bulkManager.initialize).not.toHaveBeenCalled(); + expect(BulkContextMenu).not.toHaveBeenCalled(); + expect(bulkManager.setBulkContextMenu).not.toHaveBeenCalled(); + }); + + it('suppresses onboarding when version mismatch banner is visible', async () => { + bannerService.isBannerVisible.mockReturnValueOnce(true); + + await appCore.initialize(); + await vi.runAllTimersAsync(); + + expect(onboardingManager.start).not.toHaveBeenCalled(); + }); +}); From f0672beb467e6df69e5bd78337153bebc40c6f51 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Wed, 24 Sep 2025 16:22:17 +0800 Subject: [PATCH 097/110] test(frontend): add loras page manager suite --- docs/frontend-testing-roadmap.md | 5 +- static/js/checkpoints.js | 16 ++-- static/js/loras.js | 16 ++-- tests/frontend/pages/lorasPage.test.js | 109 +++++++++++++++++++++++++ tests/frontend/utils/pageFixtures.js | 25 ++++++ 5 files changed, 157 insertions(+), 14 deletions(-) create mode 100644 tests/frontend/pages/lorasPage.test.js create mode 100644 tests/frontend/utils/pageFixtures.js diff --git a/docs/frontend-testing-roadmap.md b/docs/frontend-testing-roadmap.md index 03bbf026..2953c3c0 100644 --- a/docs/frontend-testing-roadmap.md +++ b/docs/frontend-testing-roadmap.md @@ -9,7 +9,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR | Phase 0 | Establish baseline tooling | Add Node test runner, jsdom environment, and seed smoke tests | ✅ Complete | Vitest + jsdom configured, example state tests committed | | Phase 1 | Cover state management logic | Unit test selectors, derived data helpers, and storage utilities under `static/js/state` and `static/js/utils` | ✅ Complete | Storage helpers and state selectors now exercised via deterministic suites | | Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | ✅ Complete | AppCore initialization + page feature suites now validate manager wiring, infinite scroll hooks, and onboarding gating | -| Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | ⚪ Not Started | Consider shared helpers for mocking API modules and storage | +| Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | 🚧 In Progress | LoRA manager initialization suite landed; shared page fixtures ready for checkpoints | | Phase 4 | Interaction-level regression tests | Exercise template fragments, modals, and menus to ensure UI wiring remains intact | ⚪ Not Started | Evaluate Playwright component testing or happy-path DOM snapshots | | Phase 5 | Continuous integration & coverage | Integrate frontend tests into CI workflow and track coverage metrics | ⚪ Not Started | Align reporting directories with backend coverage for unified reporting | @@ -21,7 +21,8 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR - [x] Add AppCore page feature suite exercising context menu creation and infinite scroll registration via DOM fixtures. - [x] Extend AppCore orchestration tests to cover manager wiring, bulk menu setup, and onboarding gating scenarios. - [ ] Evaluate integrating coverage reporting once test surface grows (> 20 specs). -- [ ] Create shared fixtures for the loras and checkpoints pages once dedicated manager suites are added. +- [x] Create shared fixtures for the loras and checkpoints pages once dedicated manager suites are added. - [ ] Draft focused test matrix for loras/checkpoints manager filtering and sorting paths ahead of Phase 3. +- [ ] Implement checkpoints page manager smoke tests covering initialization and duplicate badge wiring. Maintaining this roadmap alongside code changes will make it easier to append new automated test tasks and update their progress. diff --git a/static/js/checkpoints.js b/static/js/checkpoints.js index a26099d3..de341008 100644 --- a/static/js/checkpoints.js +++ b/static/js/checkpoints.js @@ -5,7 +5,7 @@ import { ModelDuplicatesManager } from './components/ModelDuplicatesManager.js'; import { MODEL_TYPES } from './api/apiConfig.js'; // Initialize the Checkpoints page -class CheckpointsPageManager { +export class CheckpointsPageManager { constructor() { // Initialize page controls this.pageControls = createPageControls(MODEL_TYPES.CHECKPOINT); @@ -31,17 +31,21 @@ class CheckpointsPageManager { async initialize() { // Initialize common page features (including context menus) appCore.initializePageFeatures(); - + console.log('Checkpoints Manager initialized'); } } -// Initialize everything when DOM is ready -document.addEventListener('DOMContentLoaded', async () => { +export async function initializeCheckpointsPage() { // Initialize core application await appCore.initialize(); - + // Initialize checkpoints page const checkpointsPage = new CheckpointsPageManager(); await checkpointsPage.initialize(); -}); \ No newline at end of file + + return checkpointsPage; +} + +// Initialize everything when DOM is ready +document.addEventListener('DOMContentLoaded', initializeCheckpointsPage); \ No newline at end of file diff --git a/static/js/loras.js b/static/js/loras.js index 6566235f..3e2ccec8 100644 --- a/static/js/loras.js +++ b/static/js/loras.js @@ -6,7 +6,7 @@ import { confirmDelete, closeDeleteModal, confirmExclude, closeExcludeModal } fr import { ModelDuplicatesManager } from './components/ModelDuplicatesManager.js'; // Initialize the LoRA page -class LoraPageManager { +export class LoraPageManager { constructor() { // Add bulk mode to state state.bulkMode = false; @@ -38,18 +38,22 @@ class LoraPageManager { async initialize() { // Initialize cards for current bulk mode state (should be false initially) updateCardsForBulkMode(state.bulkMode); - + // Initialize common page features (including context menus and virtual scroll) appCore.initializePageFeatures(); } } -// Initialize everything when DOM is ready -document.addEventListener('DOMContentLoaded', async () => { +export async function initializeLoraPage() { // Initialize core application await appCore.initialize(); - + // Initialize page-specific functionality const loraPage = new LoraPageManager(); await loraPage.initialize(); -}); \ No newline at end of file + + return loraPage; +} + +// Initialize everything when DOM is ready +document.addEventListener('DOMContentLoaded', initializeLoraPage); \ No newline at end of file diff --git a/tests/frontend/pages/lorasPage.test.js b/tests/frontend/pages/lorasPage.test.js new file mode 100644 index 00000000..1768fa35 --- /dev/null +++ b/tests/frontend/pages/lorasPage.test.js @@ -0,0 +1,109 @@ +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; +import { renderLorasPage } from '../utils/pageFixtures.js'; + +const initializeAppMock = vi.fn(); +const initializePageFeaturesMock = vi.fn(); +const updateCardsForBulkModeMock = vi.fn(); +const createPageControlsMock = vi.fn(); +const confirmDeleteMock = vi.fn(); +const closeDeleteModalMock = vi.fn(); +const confirmExcludeMock = vi.fn(); +const closeExcludeModalMock = vi.fn(); +const state = {}; +const duplicatesManagerMock = vi.fn(); + +vi.mock('../../../static/js/core.js', () => ({ + appCore: { + initialize: initializeAppMock, + initializePageFeatures: initializePageFeaturesMock, + }, +})); + +vi.mock('../../../static/js/state/index.js', () => ({ + state, +})); + +vi.mock('../../../static/js/components/shared/ModelCard.js', () => ({ + updateCardsForBulkMode: updateCardsForBulkModeMock, +})); + +vi.mock('../../../static/js/components/controls/index.js', () => ({ + createPageControls: createPageControlsMock, +})); + +vi.mock('../../../static/js/utils/modalUtils.js', () => ({ + confirmDelete: confirmDeleteMock, + closeDeleteModal: closeDeleteModalMock, + confirmExclude: confirmExcludeMock, + closeExcludeModal: closeExcludeModalMock, +})); + +vi.mock('../../../static/js/components/ModelDuplicatesManager.js', () => ({ + ModelDuplicatesManager: duplicatesManagerMock, +})); + +describe('LoraPageManager', () => { + let LoraPageManager; + let initializeLoraPage; + let duplicatesManagerInstance; + + beforeEach(async () => { + vi.clearAllMocks(); + + state.bulkMode = undefined; + state.selectedLoras = undefined; + + duplicatesManagerInstance = { + checkDuplicatesCount: vi.fn(), + }; + + duplicatesManagerMock.mockReturnValue(duplicatesManagerInstance); + createPageControlsMock.mockReturnValue({ destroy: vi.fn() }); + initializeAppMock.mockResolvedValue(undefined); + + renderLorasPage(); + + ({ LoraPageManager, initializeLoraPage } = await import('../../../static/js/loras.js')); + }); + + afterEach(() => { + delete window.confirmDelete; + delete window.closeDeleteModal; + delete window.confirmExclude; + delete window.closeExcludeModal; + delete window.modelDuplicatesManager; + }); + + it('configures state and exposes globals during construction', () => { + const manager = new LoraPageManager(); + + expect(state.bulkMode).toBe(false); + expect(state.selectedLoras).toBeInstanceOf(Set); + expect(createPageControlsMock).toHaveBeenCalledWith('loras'); + expect(duplicatesManagerMock).toHaveBeenCalledWith(manager); + + expect(window.confirmDelete).toBe(confirmDeleteMock); + expect(window.closeDeleteModal).toBe(closeDeleteModalMock); + expect(window.confirmExclude).toBe(confirmExcludeMock); + expect(window.closeExcludeModal).toBe(closeExcludeModalMock); + expect(window.modelDuplicatesManager).toBe(duplicatesManagerInstance); + }); + + it('initializes cards and page features', async () => { + const manager = new LoraPageManager(); + + await manager.initialize(); + + expect(updateCardsForBulkModeMock).toHaveBeenCalledWith(false); + expect(initializePageFeaturesMock).toHaveBeenCalledTimes(1); + }); + + it('boots the page when DOMContentLoaded handler runs', async () => { + const manager = await initializeLoraPage(); + + expect(initializeAppMock).toHaveBeenCalledTimes(1); + expect(manager).toBeInstanceOf(LoraPageManager); + expect(updateCardsForBulkModeMock).toHaveBeenCalledWith(false); + expect(window.modelDuplicatesManager).toBe(duplicatesManagerInstance); + }); +}); diff --git a/tests/frontend/utils/pageFixtures.js b/tests/frontend/utils/pageFixtures.js new file mode 100644 index 00000000..7b4ed1b4 --- /dev/null +++ b/tests/frontend/utils/pageFixtures.js @@ -0,0 +1,25 @@ +import { renderTemplate } from './domFixtures.js'; + +/** + * Renders the LoRAs page template with expected dataset attributes. + * @returns {Element} + */ +export function renderLorasPage() { + return renderTemplate('loras.html', { + dataset: { + page: 'loras', + }, + }); +} + +/** + * Renders the Checkpoints page template with expected dataset attributes. + * @returns {Element} + */ +export function renderCheckpointsPage() { + return renderTemplate('checkpoints.html', { + dataset: { + page: 'checkpoints', + }, + }); +} From 0890c6ad24aa1e4d3e793a9959f303864c03482a Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Wed, 24 Sep 2025 17:18:20 +0800 Subject: [PATCH 098/110] test(frontend): add checkpoints manager smoke tests --- docs/frontend-testing-roadmap.md | 5 +- tests/frontend/pages/checkpointsPage.test.js | 100 +++++++++++++++++++ 2 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 tests/frontend/pages/checkpointsPage.test.js diff --git a/docs/frontend-testing-roadmap.md b/docs/frontend-testing-roadmap.md index 2953c3c0..e4b4de39 100644 --- a/docs/frontend-testing-roadmap.md +++ b/docs/frontend-testing-roadmap.md @@ -9,7 +9,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR | Phase 0 | Establish baseline tooling | Add Node test runner, jsdom environment, and seed smoke tests | ✅ Complete | Vitest + jsdom configured, example state tests committed | | Phase 1 | Cover state management logic | Unit test selectors, derived data helpers, and storage utilities under `static/js/state` and `static/js/utils` | ✅ Complete | Storage helpers and state selectors now exercised via deterministic suites | | Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | ✅ Complete | AppCore initialization + page feature suites now validate manager wiring, infinite scroll hooks, and onboarding gating | -| Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | 🚧 In Progress | LoRA manager initialization suite landed; shared page fixtures ready for checkpoints | +| Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | 🚧 In Progress | LoRA + checkpoints smoke suites landed; outlining filter/sort coverage before extending to embeddings | | Phase 4 | Interaction-level regression tests | Exercise template fragments, modals, and menus to ensure UI wiring remains intact | ⚪ Not Started | Evaluate Playwright component testing or happy-path DOM snapshots | | Phase 5 | Continuous integration & coverage | Integrate frontend tests into CI workflow and track coverage metrics | ⚪ Not Started | Align reporting directories with backend coverage for unified reporting | @@ -23,6 +23,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR - [ ] Evaluate integrating coverage reporting once test surface grows (> 20 specs). - [x] Create shared fixtures for the loras and checkpoints pages once dedicated manager suites are added. - [ ] Draft focused test matrix for loras/checkpoints manager filtering and sorting paths ahead of Phase 3. -- [ ] Implement checkpoints page manager smoke tests covering initialization and duplicate badge wiring. +- [x] Implement checkpoints page manager smoke tests covering initialization and duplicate badge wiring. +- [ ] Outline focused checkpoints scenarios (filtering, sorting, duplicate badge toggles) to feed into the shared test matrix. Maintaining this roadmap alongside code changes will make it easier to append new automated test tasks and update their progress. diff --git a/tests/frontend/pages/checkpointsPage.test.js b/tests/frontend/pages/checkpointsPage.test.js new file mode 100644 index 00000000..ea982e57 --- /dev/null +++ b/tests/frontend/pages/checkpointsPage.test.js @@ -0,0 +1,100 @@ +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; +import { renderCheckpointsPage } from '../utils/pageFixtures.js'; + +const CHECKPOINT_TYPE = 'checkpoints'; + +vi.mock('../../../static/js/api/apiConfig.js', () => ({ + MODEL_TYPES: { + CHECKPOINT: CHECKPOINT_TYPE, + }, +})); + +const initializeAppMock = vi.fn(); +const initializePageFeaturesMock = vi.fn(); +const createPageControlsMock = vi.fn(); +const confirmDeleteMock = vi.fn(); +const closeDeleteModalMock = vi.fn(); +const confirmExcludeMock = vi.fn(); +const closeExcludeModalMock = vi.fn(); +const duplicatesManagerMock = vi.fn(); + +vi.mock('../../../static/js/core.js', () => ({ + appCore: { + initialize: initializeAppMock, + initializePageFeatures: initializePageFeaturesMock, + }, +})); + +vi.mock('../../../static/js/components/controls/index.js', () => ({ + createPageControls: createPageControlsMock, +})); + +vi.mock('../../../static/js/utils/modalUtils.js', () => ({ + confirmDelete: confirmDeleteMock, + closeDeleteModal: closeDeleteModalMock, + confirmExclude: confirmExcludeMock, + closeExcludeModal: closeExcludeModalMock, +})); + +vi.mock('../../../static/js/components/ModelDuplicatesManager.js', () => ({ + ModelDuplicatesManager: duplicatesManagerMock, +})); + +describe('CheckpointsPageManager', () => { + let CheckpointsPageManager; + let initializeCheckpointsPage; + let duplicatesManagerInstance; + + beforeEach(async () => { + vi.clearAllMocks(); + + duplicatesManagerInstance = { + checkDuplicatesCount: vi.fn(), + }; + + duplicatesManagerMock.mockReturnValue(duplicatesManagerInstance); + createPageControlsMock.mockReturnValue({ destroy: vi.fn() }); + initializeAppMock.mockResolvedValue(undefined); + + renderCheckpointsPage(); + + ({ CheckpointsPageManager, initializeCheckpointsPage } = await import('../../../static/js/checkpoints.js')); + }); + + afterEach(() => { + delete window.confirmDelete; + delete window.closeDeleteModal; + delete window.confirmExclude; + delete window.closeExcludeModal; + delete window.modelDuplicatesManager; + }); + + it('wires duplicates manager and exposes globals during construction', () => { + const manager = new CheckpointsPageManager(); + + expect(createPageControlsMock).toHaveBeenCalledWith(CHECKPOINT_TYPE); + expect(duplicatesManagerMock).toHaveBeenCalledWith(manager, CHECKPOINT_TYPE); + + expect(window.confirmDelete).toBe(confirmDeleteMock); + expect(window.closeDeleteModal).toBe(closeDeleteModalMock); + expect(window.confirmExclude).toBe(confirmExcludeMock); + expect(window.closeExcludeModal).toBe(closeExcludeModalMock); + expect(window.modelDuplicatesManager).toBe(duplicatesManagerInstance); + }); + + it('initializes shared page features', async () => { + const manager = new CheckpointsPageManager(); + + await manager.initialize(); + + expect(initializePageFeaturesMock).toHaveBeenCalledTimes(1); + }); + + it('boots the page when DOMContentLoaded handler runs', async () => { + const manager = await initializeCheckpointsPage(); + + expect(initializeAppMock).toHaveBeenCalledTimes(1); + expect(manager).toBeInstanceOf(CheckpointsPageManager); + expect(window.modelDuplicatesManager).toBe(duplicatesManagerInstance); + }); +}); From 39225dc2044656ea2ed9477ff441d95b254f5499 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Wed, 24 Sep 2025 17:50:04 +0800 Subject: [PATCH 099/110] test(frontend): add filtering coverage for model pages --- docs/frontend-filtering-test-matrix.md | 44 +++ docs/frontend-testing-roadmap.md | 9 +- .../components/pageControls.filtering.test.js | 367 ++++++++++++++++++ 3 files changed, 417 insertions(+), 3 deletions(-) create mode 100644 docs/frontend-filtering-test-matrix.md create mode 100644 tests/frontend/components/pageControls.filtering.test.js diff --git a/docs/frontend-filtering-test-matrix.md b/docs/frontend-filtering-test-matrix.md new file mode 100644 index 00000000..cd8f48d2 --- /dev/null +++ b/docs/frontend-filtering-test-matrix.md @@ -0,0 +1,44 @@ +# LoRA & Checkpoints Filtering/Sorting Test Matrix + +This matrix captures the scenarios that Phase 3 frontend tests should cover for the LoRA and Checkpoint managers. It focuses on how search, filter, sort, and duplicate badge toggles interact so future specs can share fixtures and expectations. + +## Scope + +- **Components**: `PageControls`, `FilterManager`, `SearchManager`, and `ModelDuplicatesManager` wiring invoked through `CheckpointsPageManager` and `LorasPageManager`. +- **Templates**: `templates/loras.html` and `templates/checkpoints.html` along with shared filter panel and toolbar partials. +- **APIs**: Requests issued through `baseModelApi.fetchModels` (via `resetAndReload`/`refreshModels`) and duplicates badge updates. + +## Shared Setup Considerations + +1. Render full page templates using `renderLorasPage` / `renderCheckpointsPage` helpers before importing modules so DOM queries resolve. +2. Stub storage helpers (`getStorageItem`, `setStorageItem`, `getSessionItem`, `setSessionItem`) to observe persistence behavior without mutating real storage. +3. Mock `sidebarManager` to capture refresh calls triggered after sort/filter actions. +4. Provide fake API implementations exposing `resetAndReload`, `refreshModels`, `fetchFromCivitai`, `toggleBulkMode`, and `clearCustomFilter` so control events remain asynchronous but deterministic. +5. Supply a minimal `ModelDuplicatesManager` mock exposing `toggleDuplicateMode`, `checkDuplicatesCount`, and `updateDuplicatesBadgeAfterRefresh` to validate duplicate badge wiring. + +## Scenario Matrix + +| ID | Feature | Scenario | LoRAs Expectations | Checkpoints Expectations | Notes | +| --- | --- | --- | --- | --- | --- | +| F-01 | Search filter | Typing a query updates `pageState.filters.search`, persists to session, and triggers `resetAndReload` on submit | Validate `SearchManager` writes query and reloads via API stub; confirm LoRA cards pass query downstream | Same as LoRAs | Cover `enter` press and clicking search icon | +| F-02 | Tag filter | Selecting a tag chip adds it to filters, applies active styling, and reloads results | Tag stored under `filters.tags`; `FilterManager.applyFilters` persists and triggers `resetAndReload(true)` | Same; ensure base model tag set is scoped to checkpoints dataset | Include removal path | +| F-03 | Base model filter | Toggling base model checkboxes updates `filters.baseModel`, persists, and reloads | Ensure only LoRA-supported models show; toggle multi-select | Ensure SDXL/Flux base models appear as expected | Capture UI state restored from storage on next init | +| F-04 | Favorites-only | Clicking favorites toggle updates session flag and calls `resetAndReload(true)` | Button gains `.active` class and API called | Same | Verify duplicates badge refresh when active | +| F-05 | Sort selection | Changing sort select saves preference (legacy + new format) and reloads | Confirm `PageControls.saveSortPreference` invoked with option and API called | Same with checkpoints-specific defaults | Cover `convertLegacySortFormat` branch | +| F-06 | Filter persistence | Re-initializing manager loads stored filters/sort and updates DOM | Filters pre-populate chips/checkboxes; favorites state restored | Same | Requires simulating repeated construction | +| F-07 | Combined filters | Applying search + tag + base model yields aggregated query params for fetch | Assert API receives merged filter payload | Same | Validate toast messaging for active filters | +| F-08 | Clearing filters | Using "Clear filters" resets state, storage, and reloads list | `FilterManager.clearFilters` empties `filters`, removes active class, shows toast | Same | Ensure favorites-only toggle unaffected | +| F-09 | Duplicate badge toggle | Pressing "Find duplicates" toggles duplicate mode and updates badge counts post-refresh | `ModelDuplicatesManager.toggleDuplicateMode` invoked and badge refresh called after API rebuild | Same plus checkpoint-specific duplicate badge dataset | Connects to future duplicate-specific specs | +| F-10 | Bulk actions menu | Opening bulk dropdown keeps filters intact and closes on outside click | Validate dropdown class toggling and no unintended reload | Same | Guard against regression when dropdown interacts with filters | + +## Automation Coverage Status + +- ✅ F-01 Search filter, F-02 Tag filter, F-03 Base model filter, F-04 Favorites-only toggle, F-05 Sort selection, and F-09 Duplicate badge toggle are covered by `tests/frontend/components/pageControls.filtering.test.js` for both LoRA and checkpoint pages. +- ⏳ F-06 Filter persistence, F-07 Combined filters, F-08 Clearing filters, and F-10 Bulk actions remain to be automated alongside upcoming bulk mode refinements. + +## Coverage Gaps & Follow-Ups + +- Write Vitest suites that exercise the matrix for both managers, sharing fixtures through page helpers to avoid duplication. +- Capture API parameter assertions by inspecting `baseModelApi.fetchModels` mocks rather than relying solely on state mutations. +- Add regression cases for legacy storage migrations (old filter keys) once fixtures exist for older payloads. +- Extend duplicate badge coverage with scenarios where `checkDuplicatesCount` signals zero duplicates versus pending calculations. diff --git a/docs/frontend-testing-roadmap.md b/docs/frontend-testing-roadmap.md index e4b4de39..50025cb7 100644 --- a/docs/frontend-testing-roadmap.md +++ b/docs/frontend-testing-roadmap.md @@ -9,7 +9,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR | Phase 0 | Establish baseline tooling | Add Node test runner, jsdom environment, and seed smoke tests | ✅ Complete | Vitest + jsdom configured, example state tests committed | | Phase 1 | Cover state management logic | Unit test selectors, derived data helpers, and storage utilities under `static/js/state` and `static/js/utils` | ✅ Complete | Storage helpers and state selectors now exercised via deterministic suites | | Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | ✅ Complete | AppCore initialization + page feature suites now validate manager wiring, infinite scroll hooks, and onboarding gating | -| Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | 🚧 In Progress | LoRA + checkpoints smoke suites landed; outlining filter/sort coverage before extending to embeddings | +| Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | 🚧 In Progress | LoRA + checkpoints smoke suites landed; filter/sort scenario matrix drafted to guide upcoming specs | | Phase 4 | Interaction-level regression tests | Exercise template fragments, modals, and menus to ensure UI wiring remains intact | ⚪ Not Started | Evaluate Playwright component testing or happy-path DOM snapshots | | Phase 5 | Continuous integration & coverage | Integrate frontend tests into CI workflow and track coverage metrics | ⚪ Not Started | Align reporting directories with backend coverage for unified reporting | @@ -22,8 +22,11 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR - [x] Extend AppCore orchestration tests to cover manager wiring, bulk menu setup, and onboarding gating scenarios. - [ ] Evaluate integrating coverage reporting once test surface grows (> 20 specs). - [x] Create shared fixtures for the loras and checkpoints pages once dedicated manager suites are added. -- [ ] Draft focused test matrix for loras/checkpoints manager filtering and sorting paths ahead of Phase 3. +- [x] Draft focused test matrix for loras/checkpoints manager filtering and sorting paths ahead of Phase 3. +- [x] Implement LoRAs manager filtering/sorting specs for scenarios F-01–F-05 & F-09; queue remaining edge cases after duplicate/bulk flows stabilize. +- [x] Implement checkpoints manager filtering/sorting specs for scenarios F-01–F-05 & F-09; cover remaining paths alongside bulk action work. - [x] Implement checkpoints page manager smoke tests covering initialization and duplicate badge wiring. -- [ ] Outline focused checkpoints scenarios (filtering, sorting, duplicate badge toggles) to feed into the shared test matrix. +- [x] Outline focused checkpoints scenarios (filtering, sorting, duplicate badge toggles) to feed into the shared test matrix. +- [ ] Add duplicate badge regression coverage for zero/pending states after API refreshes. Maintaining this roadmap alongside code changes will make it easier to append new automated test tasks and update their progress. diff --git a/tests/frontend/components/pageControls.filtering.test.js b/tests/frontend/components/pageControls.filtering.test.js new file mode 100644 index 00000000..bdbe4121 --- /dev/null +++ b/tests/frontend/components/pageControls.filtering.test.js @@ -0,0 +1,367 @@ +import { describe, it, beforeEach, afterEach, expect, vi } from 'vitest'; + +const loadMoreWithVirtualScrollMock = vi.fn(); +const refreshModelsMock = vi.fn(); +const fetchCivitaiMetadataMock = vi.fn(); +const resetAndReloadMock = vi.fn(); +const getModelApiClientMock = vi.fn(); +const apiClientMock = { + loadMoreWithVirtualScroll: loadMoreWithVirtualScrollMock, + refreshModels: refreshModelsMock, + fetchCivitaiMetadata: fetchCivitaiMetadataMock, +}; + +const showToastMock = vi.fn(); +const updatePanelPositionsMock = vi.fn(); +const downloadManagerMock = { + showDownloadModal: vi.fn(), +}; + +const sidebarManagerMock = { + initialize: vi.fn(async () => { + sidebarManagerMock.isInitialized = true; + }), + refresh: vi.fn(async () => {}), + cleanup: vi.fn(), + isInitialized: false, +}; + +const createAlphabetBarMock = vi.fn(() => ({ destroy: vi.fn() })); + +getModelApiClientMock.mockReturnValue(apiClientMock); + +vi.mock('../../../static/js/api/modelApiFactory.js', () => ({ + getModelApiClient: getModelApiClientMock, + resetAndReload: resetAndReloadMock, +})); + +vi.mock('../../../static/js/utils/uiHelpers.js', () => ({ + showToast: showToastMock, + updatePanelPositions: updatePanelPositionsMock, +})); + +vi.mock('../../../static/js/managers/DownloadManager.js', () => ({ + downloadManager: downloadManagerMock, +})); + +vi.mock('../../../static/js/components/SidebarManager.js', () => ({ + sidebarManager: sidebarManagerMock, +})); + +vi.mock('../../../static/js/components/alphabet/index.js', () => ({ + createAlphabetBar: createAlphabetBarMock, +})); + +beforeEach(() => { + vi.resetModules(); + vi.clearAllMocks(); + + loadMoreWithVirtualScrollMock.mockResolvedValue(undefined); + refreshModelsMock.mockResolvedValue(undefined); + fetchCivitaiMetadataMock.mockResolvedValue(undefined); + resetAndReloadMock.mockResolvedValue(undefined); + getModelApiClientMock.mockReturnValue(apiClientMock); + + sidebarManagerMock.isInitialized = false; + sidebarManagerMock.initialize.mockImplementation(async () => { + sidebarManagerMock.isInitialized = true; + }); + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: async () => ({ success: true, base_models: [] }), + }); +}); + +afterEach(() => { + delete window.modelDuplicatesManager; + delete global.fetch; + vi.useRealTimers(); +}); + +function renderControlsDom(pageKey) { + document.body.dataset.page = pageKey; + document.body.innerHTML = ` + + + +
    +
    +
    +
    + +
    + +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    + + `; +} + +describe('SearchManager filtering scenarios', () => { + it.each([ + ['loras'], + ['checkpoints'], + ])('updates filters and reloads results for %s page', async (pageKey) => { + vi.useFakeTimers(); + + renderControlsDom(pageKey); + const stateModule = await import('../../../static/js/state/index.js'); + stateModule.initPageState(pageKey); + const { getCurrentPageState } = stateModule; + const { SearchManager } = await import('../../../static/js/managers/SearchManager.js'); + + new SearchManager({ page: pageKey, searchDelay: 0 }); + + const input = document.getElementById('searchInput'); + input.value = 'flux'; + input.dispatchEvent(new Event('input', { bubbles: true })); + + await vi.runAllTimersAsync(); + + expect(getCurrentPageState().filters.search).toBe('flux'); + expect(loadMoreWithVirtualScrollMock).toHaveBeenCalledWith(true, false); + expect(loadMoreWithVirtualScrollMock).toHaveBeenCalledTimes(1); + }); +}); + +describe('FilterManager tag and base model filters', () => { + it.each([ + ['loras'], + ['checkpoints'], + ])('toggles tag chips and persists filters for %s page', async (pageKey) => { + renderControlsDom(pageKey); + const stateModule = await import('../../../static/js/state/index.js'); + stateModule.initPageState(pageKey); + const { getCurrentPageState } = stateModule; + const { FilterManager } = await import('../../../static/js/managers/FilterManager.js'); + + const manager = new FilterManager({ page: pageKey }); + manager.createTagFilterElements([{ tag: 'style', count: 5 }]); + + const tagChip = document.querySelector('.filter-tag.tag-filter'); + expect(tagChip).not.toBeNull(); + + tagChip.dispatchEvent(new Event('click', { bubbles: true })); + await vi.waitFor(() => expect(loadMoreWithVirtualScrollMock).toHaveBeenCalledTimes(1)); + + expect(getCurrentPageState().filters.tags).toEqual(['style']); + expect(tagChip.classList.contains('active')).toBe(true); + expect(document.getElementById('activeFiltersCount').textContent).toBe('1'); + expect(document.getElementById('activeFiltersCount').style.display).toBe('inline-flex'); + + const storageKey = `lora_manager_${pageKey}_filters`; + const storedFilters = JSON.parse(localStorage.getItem(storageKey)); + expect(storedFilters.tags).toEqual(['style']); + + loadMoreWithVirtualScrollMock.mockClear(); + + tagChip.dispatchEvent(new Event('click', { bubbles: true })); + await vi.waitFor(() => expect(loadMoreWithVirtualScrollMock).toHaveBeenCalledTimes(1)); + + expect(getCurrentPageState().filters.tags).toEqual([]); + expect(document.getElementById('activeFiltersCount').style.display).toBe('none'); + }); + + it.each([ + ['loras'], + ['checkpoints'], + ])('toggles base model chips and reloads %s results', async (pageKey) => { + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: async () => ({ + success: true, + base_models: [{ name: 'SDXL', count: 2 }], + }), + }); + + renderControlsDom(pageKey); + const stateModule = await import('../../../static/js/state/index.js'); + stateModule.initPageState(pageKey); + const { getCurrentPageState } = stateModule; + const { FilterManager } = await import('../../../static/js/managers/FilterManager.js'); + + const manager = new FilterManager({ page: pageKey }); + + await vi.waitFor(() => { + const chip = document.querySelector('[data-base-model="SDXL"]'); + expect(chip).not.toBeNull(); + }); + + const baseModelChip = document.querySelector('[data-base-model="SDXL"]'); + + baseModelChip.dispatchEvent(new Event('click', { bubbles: true })); + await vi.waitFor(() => expect(loadMoreWithVirtualScrollMock).toHaveBeenCalledTimes(1)); + + expect(getCurrentPageState().filters.baseModel).toEqual(['SDXL']); + expect(baseModelChip.classList.contains('active')).toBe(true); + + const storageKey = `lora_manager_${pageKey}_filters`; + const storedFilters = JSON.parse(localStorage.getItem(storageKey)); + expect(storedFilters.baseModel).toEqual(['SDXL']); + + loadMoreWithVirtualScrollMock.mockClear(); + + baseModelChip.dispatchEvent(new Event('click', { bubbles: true })); + await vi.waitFor(() => expect(loadMoreWithVirtualScrollMock).toHaveBeenCalledTimes(1)); + + expect(getCurrentPageState().filters.baseModel).toEqual([]); + expect(baseModelChip.classList.contains('active')).toBe(false); + }); +}); + +describe('PageControls favorites, sorting, and duplicates scenarios', () => { + it('persists favorites toggle for LoRAs and triggers reload', async () => { + renderControlsDom('loras'); + const stateModule = await import('../../../static/js/state/index.js'); + stateModule.initPageState('loras'); + const { LorasControls } = await import('../../../static/js/components/controls/LorasControls.js'); + + const controls = new LorasControls(); + + await controls.toggleFavoritesOnly(); + + expect(sessionStorage.getItem('lora_manager_show_favorites_only_loras')).toBe('true'); + expect(stateModule.getCurrentPageState().showFavoritesOnly).toBe(true); + expect(document.getElementById('favoriteFilterBtn').classList.contains('active')).toBe(true); + expect(resetAndReloadMock).toHaveBeenCalledWith(true); + + resetAndReloadMock.mockClear(); + + await controls.toggleFavoritesOnly(); + + expect(sessionStorage.getItem('lora_manager_show_favorites_only_loras')).toBe('false'); + expect(stateModule.getCurrentPageState().showFavoritesOnly).toBe(false); + expect(document.getElementById('favoriteFilterBtn').classList.contains('active')).toBe(false); + expect(resetAndReloadMock).toHaveBeenCalledWith(true); + }); + + it('persists favorites toggle for checkpoints and triggers reload', async () => { + renderControlsDom('checkpoints'); + const stateModule = await import('../../../static/js/state/index.js'); + stateModule.initPageState('checkpoints'); + const { CheckpointsControls } = await import('../../../static/js/components/controls/CheckpointsControls.js'); + + const controls = new CheckpointsControls(); + + await controls.toggleFavoritesOnly(); + + expect(sessionStorage.getItem('lora_manager_show_favorites_only_checkpoints')).toBe('true'); + expect(stateModule.getCurrentPageState().showFavoritesOnly).toBe(true); + expect(document.getElementById('favoriteFilterBtn').classList.contains('active')).toBe(true); + expect(resetAndReloadMock).toHaveBeenCalledWith(true); + + resetAndReloadMock.mockClear(); + + await controls.toggleFavoritesOnly(); + + expect(sessionStorage.getItem('lora_manager_show_favorites_only_checkpoints')).toBe('false'); + expect(stateModule.getCurrentPageState().showFavoritesOnly).toBe(false); + expect(document.getElementById('favoriteFilterBtn').classList.contains('active')).toBe(false); + expect(resetAndReloadMock).toHaveBeenCalledWith(true); + }); + + it('saves sort selection and reloads models', async () => { + renderControlsDom('loras'); + const stateModule = await import('../../../static/js/state/index.js'); + stateModule.initPageState('loras'); + const { LorasControls } = await import('../../../static/js/components/controls/LorasControls.js'); + + new LorasControls(); + + const sortSelect = document.getElementById('sortSelect'); + sortSelect.value = 'date:asc'; + sortSelect.dispatchEvent(new Event('change', { bubbles: true })); + + await vi.waitFor(() => expect(resetAndReloadMock).toHaveBeenCalledTimes(1)); + expect(localStorage.getItem('lora_manager_loras_sort')).toBe('date:asc'); + expect(stateModule.getCurrentPageState().sortBy).toBe('date:asc'); + }); + + it('converts legacy sort preference on initialization', async () => { + localStorage.setItem('loras_sort', 'date'); + + renderControlsDom('loras'); + const stateModule = await import('../../../static/js/state/index.js'); + stateModule.initPageState('loras'); + const { LorasControls } = await import('../../../static/js/components/controls/LorasControls.js'); + + new LorasControls(); + + const sortSelect = document.getElementById('sortSelect'); + expect(sortSelect.value).toBe('date:desc'); + expect(stateModule.getCurrentPageState().sortBy).toBe('date:desc'); + }); + + it('updates duplicate badge after refresh and toggles duplicate mode from controls', async () => { + renderControlsDom('checkpoints'); + const stateModule = await import('../../../static/js/state/index.js'); + stateModule.initPageState('checkpoints'); + const { CheckpointsControls } = await import('../../../static/js/components/controls/CheckpointsControls.js'); + + const controls = new CheckpointsControls(); + + const toggleDuplicateMode = vi.fn(); + const updateDuplicatesBadgeAfterRefresh = vi.fn(); + window.modelDuplicatesManager = { + toggleDuplicateMode, + updateDuplicatesBadgeAfterRefresh, + }; + + await controls.refreshModels(true); + expect(refreshModelsMock).toHaveBeenCalledWith(true); + expect(updateDuplicatesBadgeAfterRefresh).toHaveBeenCalledTimes(1); + + const duplicateButton = document.querySelector('[data-action="find-duplicates"]'); + duplicateButton.click(); + expect(toggleDuplicateMode).toHaveBeenCalledTimes(1); + }); +}); From d7a75ea4e5c41baf803a4825ca84dedf18b3d1a7 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Wed, 24 Sep 2025 20:15:38 +0800 Subject: [PATCH 100/110] test(frontend): cover embeddings and recipes managers --- docs/frontend-testing-roadmap.md | 2 +- static/js/embeddings.js | 14 +- tests/frontend/pages/embeddingsPage.test.js | 99 ++++++++++ tests/frontend/pages/recipesPage.test.js | 209 ++++++++++++++++++++ tests/frontend/utils/pageFixtures.js | 24 +++ 5 files changed, 343 insertions(+), 5 deletions(-) create mode 100644 tests/frontend/pages/embeddingsPage.test.js create mode 100644 tests/frontend/pages/recipesPage.test.js diff --git a/docs/frontend-testing-roadmap.md b/docs/frontend-testing-roadmap.md index 50025cb7..2793b64c 100644 --- a/docs/frontend-testing-roadmap.md +++ b/docs/frontend-testing-roadmap.md @@ -9,7 +9,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR | Phase 0 | Establish baseline tooling | Add Node test runner, jsdom environment, and seed smoke tests | ✅ Complete | Vitest + jsdom configured, example state tests committed | | Phase 1 | Cover state management logic | Unit test selectors, derived data helpers, and storage utilities under `static/js/state` and `static/js/utils` | ✅ Complete | Storage helpers and state selectors now exercised via deterministic suites | | Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | ✅ Complete | AppCore initialization + page feature suites now validate manager wiring, infinite scroll hooks, and onboarding gating | -| Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | 🚧 In Progress | LoRA + checkpoints smoke suites landed; filter/sort scenario matrix drafted to guide upcoming specs | +| Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | ✅ Complete | LoRA/checkpoint suites expanded; embeddings + recipes managers now covered with initialization, filtering, and duplicate workflows | | Phase 4 | Interaction-level regression tests | Exercise template fragments, modals, and menus to ensure UI wiring remains intact | ⚪ Not Started | Evaluate Playwright component testing or happy-path DOM snapshots | | Phase 5 | Continuous integration & coverage | Integrate frontend tests into CI workflow and track coverage metrics | ⚪ Not Started | Align reporting directories with backend coverage for unified reporting | diff --git a/static/js/embeddings.js b/static/js/embeddings.js index 1352471c..654d250c 100644 --- a/static/js/embeddings.js +++ b/static/js/embeddings.js @@ -36,12 +36,18 @@ class EmbeddingsPageManager { } } -// Initialize everything when DOM is ready -document.addEventListener('DOMContentLoaded', async () => { +async function initializeEmbeddingsPage() { // Initialize core application await appCore.initialize(); - + // Initialize embeddings page const embeddingsPage = new EmbeddingsPageManager(); await embeddingsPage.initialize(); -}); + + return embeddingsPage; +} + +// Initialize everything when DOM is ready +document.addEventListener('DOMContentLoaded', initializeEmbeddingsPage); + +export { EmbeddingsPageManager, initializeEmbeddingsPage }; diff --git a/tests/frontend/pages/embeddingsPage.test.js b/tests/frontend/pages/embeddingsPage.test.js new file mode 100644 index 00000000..4d0f754f --- /dev/null +++ b/tests/frontend/pages/embeddingsPage.test.js @@ -0,0 +1,99 @@ +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; +import { renderEmbeddingsPage } from '../utils/pageFixtures.js'; + +const initializeAppMock = vi.fn(); +const initializePageFeaturesMock = vi.fn(); +const createPageControlsMock = vi.fn(); +const confirmDeleteMock = vi.fn(); +const closeDeleteModalMock = vi.fn(); +const confirmExcludeMock = vi.fn(); +const closeExcludeModalMock = vi.fn(); +const duplicatesManagerMock = vi.fn(); + +vi.mock('../../../static/js/core.js', () => ({ + appCore: { + initialize: initializeAppMock, + initializePageFeatures: initializePageFeaturesMock, + }, +})); + +vi.mock('../../../static/js/components/controls/index.js', () => ({ + createPageControls: createPageControlsMock, +})); + +vi.mock('../../../static/js/utils/modalUtils.js', () => ({ + confirmDelete: confirmDeleteMock, + closeDeleteModal: closeDeleteModalMock, + confirmExclude: confirmExcludeMock, + closeExcludeModal: closeExcludeModalMock, +})); + +vi.mock('../../../static/js/api/apiConfig.js', () => ({ + MODEL_TYPES: { + EMBEDDING: 'embeddings', + }, +})); + +vi.mock('../../../static/js/components/ModelDuplicatesManager.js', () => ({ + ModelDuplicatesManager: duplicatesManagerMock, +})); + +describe('EmbeddingsPageManager', () => { + let EmbeddingsPageManager; + let initializeEmbeddingsPage; + let duplicatesManagerInstance; + + beforeEach(async () => { + vi.resetModules(); + vi.clearAllMocks(); + + duplicatesManagerInstance = { + checkDuplicatesCount: vi.fn(), + }; + + duplicatesManagerMock.mockReturnValue(duplicatesManagerInstance); + createPageControlsMock.mockReturnValue({ destroy: vi.fn() }); + initializeAppMock.mockResolvedValue(undefined); + + renderEmbeddingsPage(); + + ({ EmbeddingsPageManager, initializeEmbeddingsPage } = await import('../../../static/js/embeddings.js')); + }); + + afterEach(() => { + delete window.confirmDelete; + delete window.closeDeleteModal; + delete window.confirmExclude; + delete window.closeExcludeModal; + delete window.modelDuplicatesManager; + }); + + it('wires page controls and exposes modal helpers during construction', () => { + const manager = new EmbeddingsPageManager(); + + expect(createPageControlsMock).toHaveBeenCalledWith('embeddings'); + expect(duplicatesManagerMock).toHaveBeenCalledWith(manager, 'embeddings'); + + expect(window.confirmDelete).toBe(confirmDeleteMock); + expect(window.closeDeleteModal).toBe(closeDeleteModalMock); + expect(window.confirmExclude).toBe(confirmExcludeMock); + expect(window.closeExcludeModal).toBe(closeExcludeModalMock); + expect(window.modelDuplicatesManager).toBe(duplicatesManagerInstance); + }); + + it('initializes shared page features', async () => { + const manager = new EmbeddingsPageManager(); + + await manager.initialize(); + + expect(initializePageFeaturesMock).toHaveBeenCalledTimes(1); + }); + + it('boots the embeddings page through the initializer', async () => { + const manager = await initializeEmbeddingsPage(); + + expect(initializeAppMock).toHaveBeenCalledTimes(1); + expect(manager).toBeInstanceOf(EmbeddingsPageManager); + expect(window.modelDuplicatesManager).toBe(duplicatesManagerInstance); + }); +}); diff --git a/tests/frontend/pages/recipesPage.test.js b/tests/frontend/pages/recipesPage.test.js new file mode 100644 index 00000000..74add4e0 --- /dev/null +++ b/tests/frontend/pages/recipesPage.test.js @@ -0,0 +1,209 @@ +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; +import { renderRecipesPage } from '../utils/pageFixtures.js'; + +const initializeAppMock = vi.fn(); +const initializePageFeaturesMock = vi.fn(); +const getCurrentPageStateMock = vi.fn(); +const getSessionItemMock = vi.fn(); +const removeSessionItemMock = vi.fn(); +const RecipeContextMenuMock = vi.fn(); +const refreshVirtualScrollMock = vi.fn(); +const refreshRecipesMock = vi.fn(); + +let importManagerInstance; +let recipeModalInstance; +let duplicatesManagerInstance; + +const ImportManagerMock = vi.fn(() => importManagerInstance); +const RecipeModalMock = vi.fn(() => recipeModalInstance); +const DuplicatesManagerMock = vi.fn(() => duplicatesManagerInstance); + +vi.mock('../../../static/js/core.js', () => ({ + appCore: { + initialize: initializeAppMock, + initializePageFeatures: initializePageFeaturesMock, + }, +})); + +vi.mock('../../../static/js/managers/ImportManager.js', () => ({ + ImportManager: ImportManagerMock, +})); + +vi.mock('../../../static/js/components/RecipeModal.js', () => ({ + RecipeModal: RecipeModalMock, +})); + +vi.mock('../../../static/js/state/index.js', () => ({ + getCurrentPageState: getCurrentPageStateMock, +})); + +vi.mock('../../../static/js/utils/storageHelpers.js', () => ({ + getSessionItem: getSessionItemMock, + removeSessionItem: removeSessionItemMock, +})); + +vi.mock('../../../static/js/components/ContextMenu/index.js', () => ({ + RecipeContextMenu: RecipeContextMenuMock, +})); + +vi.mock('../../../static/js/components/DuplicatesManager.js', () => ({ + DuplicatesManager: DuplicatesManagerMock, +})); + +vi.mock('../../../static/js/utils/infiniteScroll.js', () => ({ + refreshVirtualScroll: refreshVirtualScrollMock, +})); + +vi.mock('../../../static/js/api/recipeApi.js', () => ({ + refreshRecipes: refreshRecipesMock, +})); + +describe('RecipeManager', () => { + let RecipeManager; + let pageState; + + beforeEach(async () => { + vi.resetModules(); + vi.clearAllMocks(); + + importManagerInstance = { + showImportModal: vi.fn(), + }; + recipeModalInstance = { + showRecipeDetails: vi.fn(), + }; + duplicatesManagerInstance = { + findDuplicates: vi.fn(), + selectLatestDuplicates: vi.fn(), + deleteSelectedDuplicates: vi.fn(), + confirmDeleteDuplicates: vi.fn(), + exitDuplicateMode: vi.fn(), + }; + + pageState = { + sortBy: 'date', + searchOptions: undefined, + customFilter: undefined, + duplicatesMode: false, + }; + + getCurrentPageStateMock.mockImplementation(() => pageState); + initializeAppMock.mockResolvedValue(undefined); + initializePageFeaturesMock.mockResolvedValue(undefined); + refreshVirtualScrollMock.mockReset(); + refreshVirtualScrollMock.mockImplementation(() => {}); + refreshRecipesMock.mockResolvedValue('refreshed'); + + getSessionItemMock.mockImplementation((key) => { + const map = { + lora_to_recipe_filterLoraName: 'Flux Dream', + lora_to_recipe_filterLoraHash: 'abc123', + viewRecipeId: '42', + }; + return map[key] ?? null; + }); + removeSessionItemMock.mockImplementation(() => {}); + + renderRecipesPage(); + + ({ RecipeManager } = await import('../../../static/js/recipes.js')); + }); + + afterEach(() => { + delete window.recipeManager; + delete window.importManager; + }); + + it('initializes page controls, restores filters, and wires sort interactions', async () => { + const sortSelectElement = document.createElement('select'); + sortSelectElement.id = 'sortSelect'; + sortSelectElement.innerHTML = ` + + + `; + document.body.appendChild(sortSelectElement); + + const manager = new RecipeManager(); + await manager.initialize(); + + expect(ImportManagerMock).toHaveBeenCalledTimes(1); + expect(RecipeModalMock).toHaveBeenCalledTimes(1); + expect(DuplicatesManagerMock).toHaveBeenCalledWith(manager); + expect(RecipeContextMenuMock).toHaveBeenCalledTimes(1); + + expect(window.recipeManager).toBe(manager); + expect(window.importManager).toBe(importManagerInstance); + + expect(pageState.searchOptions).toEqual({ + title: true, + tags: true, + loraName: true, + loraModel: true, + }); + + expect(pageState.customFilter).toEqual({ + active: true, + loraName: 'Flux Dream', + loraHash: 'abc123', + recipeId: '42', + }); + + const indicator = document.getElementById('customFilterIndicator'); + expect(indicator.classList.contains('hidden')).toBe(false); + + const clearButton = indicator.querySelector('.clear-filter'); + clearButton.dispatchEvent(new Event('click', { bubbles: true })); + + expect(removeSessionItemMock).toHaveBeenCalledWith('lora_to_recipe_filterLoraName'); + expect(removeSessionItemMock).toHaveBeenCalledWith('lora_to_recipe_filterLoraHash'); + expect(removeSessionItemMock).toHaveBeenCalledWith('viewRecipeId'); + expect(pageState.customFilter.active).toBe(false); + expect(indicator.classList.contains('hidden')).toBe(true); + expect(refreshVirtualScrollMock).toHaveBeenCalledTimes(1); + + const sortSelect = document.getElementById('sortSelect'); + sortSelect.value = 'name'; + sortSelect.dispatchEvent(new Event('change', { bubbles: true })); + + expect(pageState.sortBy).toBe('name'); + expect(refreshVirtualScrollMock).toHaveBeenCalledTimes(2); + expect(initializePageFeaturesMock).toHaveBeenCalledTimes(1); + }); + + it('skips loading when duplicates mode is active and refreshes otherwise', async () => { + const manager = new RecipeManager(); + + pageState.duplicatesMode = true; + await manager.loadRecipes(); + expect(refreshVirtualScrollMock).not.toHaveBeenCalled(); + + pageState.duplicatesMode = false; + await manager.loadRecipes(); + expect(refreshVirtualScrollMock).toHaveBeenCalledTimes(1); + }); + + it('proxies duplicate management and refresh helpers', async () => { + const manager = new RecipeManager(); + + await manager.findDuplicateRecipes(); + expect(duplicatesManagerInstance.findDuplicates).toHaveBeenCalledTimes(1); + + manager.selectLatestDuplicates(); + expect(duplicatesManagerInstance.selectLatestDuplicates).toHaveBeenCalledTimes(1); + + manager.deleteSelectedDuplicates(); + expect(duplicatesManagerInstance.deleteSelectedDuplicates).toHaveBeenCalledTimes(1); + + manager.confirmDeleteDuplicates(); + expect(duplicatesManagerInstance.confirmDeleteDuplicates).toHaveBeenCalledTimes(1); + + const grid = document.getElementById('recipeGrid'); + grid.innerHTML = '
    content
    '; + manager.exitDuplicateMode(); + expect(grid.innerHTML).toBe(''); + expect(duplicatesManagerInstance.exitDuplicateMode).toHaveBeenCalledTimes(1); + + await manager.refreshRecipes(); + expect(refreshRecipesMock).toHaveBeenCalledTimes(1); + }); +}); diff --git a/tests/frontend/utils/pageFixtures.js b/tests/frontend/utils/pageFixtures.js index 7b4ed1b4..465ea8b3 100644 --- a/tests/frontend/utils/pageFixtures.js +++ b/tests/frontend/utils/pageFixtures.js @@ -23,3 +23,27 @@ export function renderCheckpointsPage() { }, }); } + +/** + * Renders the Embeddings page template with expected dataset attributes. + * @returns {Element} + */ +export function renderEmbeddingsPage() { + return renderTemplate('embeddings.html', { + dataset: { + page: 'embeddings', + }, + }); +} + +/** + * Renders the Recipes page template with expected dataset attributes. + * @returns {Element} + */ +export function renderRecipesPage() { + return renderTemplate('recipes.html', { + dataset: { + page: 'recipes', + }, + }); +} From ae8914f5c83bb46c605e422f185a4e6f41028540 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Wed, 24 Sep 2025 20:33:41 +0800 Subject: [PATCH 101/110] test(frontend): add interaction regression suites --- docs/frontend-testing-roadmap.md | 3 +- .../contextMenu.interactions.test.js | 319 ++++++++++++++++++ 2 files changed, 321 insertions(+), 1 deletion(-) create mode 100644 tests/frontend/components/contextMenu.interactions.test.js diff --git a/docs/frontend-testing-roadmap.md b/docs/frontend-testing-roadmap.md index 2793b64c..952b5af8 100644 --- a/docs/frontend-testing-roadmap.md +++ b/docs/frontend-testing-roadmap.md @@ -10,7 +10,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR | Phase 1 | Cover state management logic | Unit test selectors, derived data helpers, and storage utilities under `static/js/state` and `static/js/utils` | ✅ Complete | Storage helpers and state selectors now exercised via deterministic suites | | Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | ✅ Complete | AppCore initialization + page feature suites now validate manager wiring, infinite scroll hooks, and onboarding gating | | Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | ✅ Complete | LoRA/checkpoint suites expanded; embeddings + recipes managers now covered with initialization, filtering, and duplicate workflows | -| Phase 4 | Interaction-level regression tests | Exercise template fragments, modals, and menus to ensure UI wiring remains intact | ⚪ Not Started | Evaluate Playwright component testing or happy-path DOM snapshots | +| Phase 4 | Interaction-level regression tests | Exercise template fragments, modals, and menus to ensure UI wiring remains intact | ✅ Complete | Vitest DOM suites cover NSFW selector, recipe modal editing, and global context menus | | Phase 5 | Continuous integration & coverage | Integrate frontend tests into CI workflow and track coverage metrics | ⚪ Not Started | Align reporting directories with backend coverage for unified reporting | ## Next Steps Checklist @@ -20,6 +20,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR - [x] Prototype AppCore initialization test that verifies manager bootstrapping with stubbed dependencies. - [x] Add AppCore page feature suite exercising context menu creation and infinite scroll registration via DOM fixtures. - [x] Extend AppCore orchestration tests to cover manager wiring, bulk menu setup, and onboarding gating scenarios. +- [x] Add interaction regression suites for context menus and recipe modals to complete Phase 4. - [ ] Evaluate integrating coverage reporting once test surface grows (> 20 specs). - [x] Create shared fixtures for the loras and checkpoints pages once dedicated manager suites are added. - [x] Draft focused test matrix for loras/checkpoints manager filtering and sorting paths ahead of Phase 3. diff --git a/tests/frontend/components/contextMenu.interactions.test.js b/tests/frontend/components/contextMenu.interactions.test.js new file mode 100644 index 00000000..7dd18ad5 --- /dev/null +++ b/tests/frontend/components/contextMenu.interactions.test.js @@ -0,0 +1,319 @@ +import { describe, it, beforeEach, afterEach, expect, vi } from 'vitest'; + +const showToastMock = vi.fn(); +const copyToClipboardMock = vi.fn(); +const getNSFWLevelNameMock = vi.fn((level) => { + if (level >= 16) return 'XXX'; + if (level >= 8) return 'X'; + if (level >= 4) return 'R'; + if (level >= 2) return 'PG13'; + if (level >= 1) return 'PG'; + return 'Unknown'; +}); +const copyLoraSyntaxMock = vi.fn(); +const sendLoraToWorkflowMock = vi.fn(); +const buildLoraSyntaxMock = vi.fn((fileName) => `lora:${fileName}`); +const openExampleImagesFolderMock = vi.fn(); + +const modalManagerMock = { + showModal: vi.fn(), + closeModal: vi.fn(), + registerModal: vi.fn(), + getModal: vi.fn(() => ({ element: { style: { display: 'none' } }, isOpen: false })), + isAnyModalOpen: vi.fn(), +}; + +const loadingManagerStub = { + showSimpleLoading: vi.fn(), + hide: vi.fn(), + show: vi.fn(), +}; + +const stateStub = { + global: { settings: {}, loadingManager: loadingManagerStub }, + loadingManager: loadingManagerStub, + virtualScroller: { updateSingleItem: vi.fn() }, +}; + +const saveModelMetadataMock = vi.fn(); +const downloadExampleImagesApiMock = vi.fn(); +const replaceModelPreviewMock = vi.fn(); +const refreshSingleModelMetadataMock = vi.fn(); +const resetAndReloadMock = vi.fn(); + +const getModelApiClientMock = vi.fn(() => ({ + saveModelMetadata: saveModelMetadataMock, + downloadExampleImages: downloadExampleImagesApiMock, + replaceModelPreview: replaceModelPreviewMock, + refreshSingleModelMetadata: refreshSingleModelMetadataMock, +})); + +const updateRecipeMetadataMock = vi.fn(() => Promise.resolve({ success: true })); + +vi.mock('../../../static/js/utils/uiHelpers.js', () => ({ + showToast: showToastMock, + copyToClipboard: copyToClipboardMock, + getNSFWLevelName: getNSFWLevelNameMock, + copyLoraSyntax: copyLoraSyntaxMock, + sendLoraToWorkflow: sendLoraToWorkflowMock, + buildLoraSyntax: buildLoraSyntaxMock, + openExampleImagesFolder: openExampleImagesFolderMock, +})); + +vi.mock('../../../static/js/managers/ModalManager.js', () => ({ + modalManager: modalManagerMock, +})); + +vi.mock('../../../static/js/utils/storageHelpers.js', () => ({ + setSessionItem: vi.fn(), + removeSessionItem: vi.fn(), + getSessionItem: vi.fn(), +})); + +vi.mock('../../../static/js/api/modelApiFactory.js', () => ({ + getModelApiClient: getModelApiClientMock, + resetAndReload: resetAndReloadMock, +})); + +vi.mock('../../../static/js/state/index.js', () => ({ + state: stateStub, +})); + +vi.mock('../../../static/js/utils/modalUtils.js', () => ({ + showExcludeModal: vi.fn(), + showDeleteModal: vi.fn(), +})); + +vi.mock('../../../static/js/managers/MoveManager.js', () => ({ + moveManager: { showMoveModal: vi.fn() }, +})); + +vi.mock('../../../static/js/api/recipeApi.js', () => ({ + updateRecipeMetadata: updateRecipeMetadataMock, +})); + +async function flushAsyncTasks() { + await Promise.resolve(); + await new Promise((resolve) => setTimeout(resolve, 0)); +} + +describe('Interaction-level regression coverage', () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.useRealTimers(); + document.body.innerHTML = ''; + stateStub.global.settings = {}; + saveModelMetadataMock.mockResolvedValue(undefined); + downloadExampleImagesApiMock.mockResolvedValue(undefined); + updateRecipeMetadataMock.mockResolvedValue({ success: true }); + global.modalManager = modalManagerMock; + }); + + afterEach(() => { + vi.useRealTimers(); + document.body.innerHTML = ''; + delete window.exampleImagesManager; + delete global.fetch; + delete global.modalManager; + }); + + it('opens the NSFW selector from the LoRA context menu and persists the new rating', async () => { + document.body.innerHTML = ` +
    +
    +
    + + `; + + const card = document.createElement('div'); + card.className = 'model-card'; + card.dataset.filepath = '/models/test.safetensors'; + card.dataset.meta = JSON.stringify({ preview_nsfw_level: 1 }); + document.body.appendChild(card); + + const { LoraContextMenu } = await import('../../../static/js/components/ContextMenu/LoraContextMenu.js'); + const helpers = await import('../../../static/js/utils/uiHelpers.js'); + expect(helpers.showToast).toBe(showToastMock); + const contextMenu = new LoraContextMenu(); + + contextMenu.showMenu(120, 140, card); + + const nsfwMenuItem = document.querySelector('#loraContextMenu .context-menu-item[data-action="set-nsfw"]'); + nsfwMenuItem.dispatchEvent(new Event('click', { bubbles: true })); + + const selector = document.getElementById('nsfwLevelSelector'); + expect(selector.style.display).toBe('block'); + expect(selector.dataset.cardPath).toBe('/models/test.safetensors'); + expect(document.getElementById('currentNSFWLevel').textContent).toBe('PG'); + + const levelButton = selector.querySelector('.nsfw-level-btn[data-level="4"]'); + levelButton.dispatchEvent(new Event('click', { bubbles: true })); + + expect(saveModelMetadataMock).toHaveBeenCalledWith('/models/test.safetensors', { preview_nsfw_level: 4 }); + expect(saveModelMetadataMock).toHaveBeenCalledTimes(1); + await saveModelMetadataMock.mock.results[0].value; + await flushAsyncTasks(); + expect(selector.style.display).toBe('none'); + expect(document.getElementById('loraContextMenu').style.display).toBe('none'); + }); + + it('wires recipe modal title editing to update metadata and UI state', async () => { + document.body.innerHTML = ` + + `; + + const { RecipeModal } = await import('../../../static/js/components/RecipeModal.js'); + const recipeModal = new RecipeModal(); + + const recipe = { + id: 'recipe-1', + file_path: '/recipes/test.json', + title: 'Original Title', + tags: ['tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6'], + file_url: '', + preview_url: '', + source_path: '', + gen_params: { + prompt: 'Prompt text', + negative_prompt: 'Negative prompt', + steps: '30', + }, + loras: [], + }; + + recipeModal.showRecipeDetails(recipe); + await new Promise((resolve) => setTimeout(resolve, 60)); + await flushAsyncTasks(); + + expect(modalManagerMock.showModal).toHaveBeenCalledWith('recipeModal'); + + const editIcon = document.querySelector('#recipeModalTitle .edit-icon'); + editIcon.dispatchEvent(new Event('click', { bubbles: true })); + + const titleInput = document.querySelector('#recipeTitleEditor .title-input'); + titleInput.value = 'Updated Title'; + + recipeModal.saveTitleEdit(); + + expect(updateRecipeMetadataMock).toHaveBeenCalledWith('/recipes/test.json', { title: 'Updated Title' }); + expect(updateRecipeMetadataMock).toHaveBeenCalledTimes(1); + await updateRecipeMetadataMock.mock.results[0].value; + await flushAsyncTasks(); + + const titleContainer = document.getElementById('recipeModalTitle'); + expect(titleContainer.querySelector('.content-text').textContent).toBe('Updated Title'); + expect(titleContainer.querySelector('#recipeTitleEditor').classList.contains('active')).toBe(false); + expect(recipeModal.currentRecipe.title).toBe('Updated Title'); + }); + + it('processes global context menu actions for downloads and cleanup', async () => { + document.body.innerHTML = ` +
    +
    +
    +
    + `; + + const { GlobalContextMenu } = await import('../../../static/js/components/ContextMenu/GlobalContextMenu.js'); + const menu = new GlobalContextMenu(); + + stateStub.global.settings.example_images_path = '/tmp/examples'; + window.exampleImagesManager = { + handleDownloadButton: vi.fn().mockResolvedValue(undefined), + }; + + menu.showMenu(100, 200); + const downloadItem = document.querySelector('[data-action="download-example-images"]'); + downloadItem.dispatchEvent(new Event('click', { bubbles: true })); + expect(downloadItem.classList.contains('disabled')).toBe(true); + + expect(window.exampleImagesManager.handleDownloadButton).toHaveBeenCalledTimes(1); + await window.exampleImagesManager.handleDownloadButton.mock.results[0].value; + await flushAsyncTasks(); + expect(downloadItem.classList.contains('disabled')).toBe(false); + expect(document.getElementById('globalContextMenu').style.display).toBe('none'); + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: async () => ({ success: true, moved_total: 2 }), + }); + + menu.showMenu(240, 320); + const cleanupItem = document.querySelector('[data-action="cleanup-example-images-folders"]'); + cleanupItem.dispatchEvent(new Event('click', { bubbles: true })); + expect(cleanupItem.classList.contains('disabled')).toBe(true); + + expect(global.fetch).toHaveBeenCalledWith('/api/lm/cleanup-example-image-folders', { method: 'POST' }); + expect(global.fetch).toHaveBeenCalledTimes(1); + const responsePromise = global.fetch.mock.results[0].value; + const response = await responsePromise; + await response.json(); + await flushAsyncTasks(); + expect(cleanupItem.classList.contains('disabled')).toBe(false); + expect(menu._cleanupInProgress).toBe(false); + }); +}); From 14c468f2a2e63a80e1b7788bdf54f21d12da5be4 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Wed, 24 Sep 2025 21:11:36 +0800 Subject: [PATCH 102/110] feat(video): enhance video handling in model cards with lazy loading and autoplay settings, see #446 --- static/js/components/shared/ModelCard.js | 175 +++++++++++++++++++++-- static/js/managers/SettingsManager.js | 25 +--- 2 files changed, 162 insertions(+), 38 deletions(-) diff --git a/static/js/components/shared/ModelCard.js b/static/js/components/shared/ModelCard.js index 2a3c0d2f..17226bc0 100644 --- a/static/js/components/shared/ModelCard.js +++ b/static/js/components/shared/ModelCard.js @@ -435,7 +435,18 @@ export function createModelCard(model, modelType) { // Check if autoplayOnHover is enabled for video previews const autoplayOnHover = state.global?.settings?.autoplay_on_hover || false; const isVideo = previewUrl.endsWith('.mp4'); - const videoAttrs = autoplayOnHover ? 'controls muted loop' : 'controls autoplay muted loop'; + const videoAttrs = [ + 'controls', + 'muted', + 'loop', + 'playsinline', + 'preload="none"', + `data-src="${versionedPreviewUrl}"` + ]; + + if (!autoplayOnHover) { + videoAttrs.push('data-autoplay="true"'); + } // Get favorite status from model data const isFavorite = model.favorite === true; @@ -473,9 +484,7 @@ export function createModelCard(model, modelType) { card.innerHTML = `
    ${isVideo ? - `` : + `` : `${model.model_name}` }
    @@ -514,21 +523,155 @@ export function createModelCard(model, modelType) { // Add video auto-play on hover functionality if needed const videoElement = card.querySelector('video'); - if (videoElement && autoplayOnHover) { - const cardPreview = card.querySelector('.card-preview'); - - // Remove autoplay attribute and pause initially - videoElement.removeAttribute('autoplay'); - videoElement.pause(); - - // Add mouse events to trigger play/pause using event attributes - cardPreview.setAttribute('onmouseenter', 'this.querySelector("video")?.play()'); - cardPreview.setAttribute('onmouseleave', 'const v=this.querySelector("video"); if(v){v.pause();v.currentTime=0;}'); + if (videoElement) { + configureModelCardVideo(videoElement, autoplayOnHover); } return card; } +const VIDEO_LAZY_ROOT_MARGIN = '200px 0px'; +let videoLazyObserver = null; + +function ensureVideoLazyObserver() { + if (videoLazyObserver) { + return videoLazyObserver; + } + + videoLazyObserver = new IntersectionObserver((entries, observer) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const target = entry.target; + observer.unobserve(target); + loadVideoSource(target); + } + }); + }, { + root: null, + rootMargin: VIDEO_LAZY_ROOT_MARGIN, + threshold: 0.01 + }); + + return videoLazyObserver; +} + +function cleanupHoverHandlers(videoElement) { + const handlers = videoElement._hoverHandlers; + if (!handlers) return; + + const { cardPreview, mouseEnter, mouseLeave } = handlers; + if (cardPreview) { + cardPreview.removeEventListener('mouseenter', mouseEnter); + cardPreview.removeEventListener('mouseleave', mouseLeave); + } + + delete videoElement._hoverHandlers; +} + +function requestSafePlay(videoElement) { + const playPromise = videoElement.play(); + if (playPromise && typeof playPromise.catch === 'function') { + playPromise.catch(() => {}); + } +} + +function loadVideoSource(videoElement) { + if (!videoElement || videoElement.dataset.loaded === 'true') { + return; + } + + const sourceElement = videoElement.querySelector('source'); + const dataSrc = videoElement.dataset.src || sourceElement?.dataset?.src; + + if (!dataSrc) { + return; + } + + // Ensure src attributes are reset before applying + videoElement.removeAttribute('src'); + if (sourceElement) { + sourceElement.src = dataSrc; + } else { + videoElement.src = dataSrc; + } + + videoElement.load(); + videoElement.dataset.loaded = 'true'; + + if (videoElement.dataset.autoplay === 'true') { + videoElement.setAttribute('autoplay', ''); + requestSafePlay(videoElement); + } +} + +export function configureModelCardVideo(videoElement, autoplayOnHover) { + if (!videoElement) return; + + cleanupHoverHandlers(videoElement); + + const sourceElement = videoElement.querySelector('source'); + const existingSrc = videoElement.dataset.src || sourceElement?.dataset?.src || videoElement.currentSrc; + + if (existingSrc && !videoElement.dataset.src) { + videoElement.dataset.src = existingSrc; + } + + if (sourceElement && !sourceElement.dataset.src) { + sourceElement.dataset.src = videoElement.dataset.src || sourceElement.src; + } + + videoElement.removeAttribute('autoplay'); + videoElement.removeAttribute('src'); + videoElement.setAttribute('preload', 'none'); + videoElement.setAttribute('muted', ''); + videoElement.setAttribute('loop', ''); + videoElement.setAttribute('playsinline', ''); + videoElement.setAttribute('controls', ''); + videoElement.dataset.loaded = 'false'; + + if (sourceElement) { + sourceElement.removeAttribute('src'); + if (videoElement.dataset.src) { + sourceElement.dataset.src = videoElement.dataset.src; + } + } + + if (!autoplayOnHover) { + videoElement.dataset.autoplay = 'true'; + } else { + delete videoElement.dataset.autoplay; + } + + const observer = ensureVideoLazyObserver(); + observer.observe(videoElement); + + // Pause the video until it is either hovered or autoplay kicks in + try { + videoElement.pause(); + } catch (err) { + // Ignore pause errors (e.g., if not loaded yet) + } + + if (autoplayOnHover) { + const cardPreview = videoElement.closest('.card-preview'); + if (cardPreview) { + const mouseEnter = () => { + loadVideoSource(videoElement); + requestSafePlay(videoElement); + }; + const mouseLeave = () => { + videoElement.pause(); + videoElement.currentTime = 0; + }; + + cardPreview.addEventListener('mouseenter', mouseEnter); + cardPreview.addEventListener('mouseleave', mouseLeave); + + videoElement._hoverHandlers = { cardPreview, mouseEnter, mouseLeave }; + } + } +} + // Add a method to update card appearance based on bulk mode (LoRA only) export function updateCardsForBulkMode(isBulkMode) { // Update the state @@ -567,4 +710,6 @@ export function updateCardsForBulkMode(isBulkMode) { if (isBulkMode) { bulkManager.applySelectionState(); } -} \ No newline at end of file +} + + diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index b6ffe6c2..d7a03fc5 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -5,6 +5,7 @@ import { resetAndReload } from '../api/modelApiFactory.js'; import { DOWNLOAD_PATH_TEMPLATES, MAPPABLE_BASE_MODELS, PATH_TEMPLATE_PLACEHOLDERS, DEFAULT_PATH_TEMPLATES } from '../utils/constants.js'; import { translate } from '../utils/i18nHelpers.js'; import { i18n } from '../i18n/index.js'; +import { configureModelCardVideo } from '../components/shared/ModelCard.js'; export class SettingsManager { constructor() { @@ -1222,29 +1223,7 @@ export class SettingsManager { // Apply autoplay setting to existing videos in card previews const autoplayOnHover = state.global.settings.autoplay_on_hover; document.querySelectorAll('.card-preview video').forEach(video => { - // Remove previous event listeners by cloning and replacing the element - const videoParent = video.parentElement; - const videoClone = video.cloneNode(true); - - if (autoplayOnHover) { - // Pause video initially and set up mouse events for hover playback - videoClone.removeAttribute('autoplay'); - videoClone.pause(); - - // Add mouse events to the parent element - videoParent.onmouseenter = () => videoClone.play(); - videoParent.onmouseleave = () => { - videoClone.pause(); - videoClone.currentTime = 0; - }; - } else { - // Use default autoplay behavior - videoClone.setAttribute('autoplay', ''); - videoParent.onmouseenter = null; - videoParent.onmouseleave = null; - } - - videoParent.replaceChild(videoClone, video); + configureModelCardVideo(video, autoplayOnHover); }); // Apply display density class to grid From eda6df4a5dc6be8fe032a4ab0001545fc79ab6f4 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Wed, 24 Sep 2025 23:22:32 +0800 Subject: [PATCH 103/110] chore(ci): add frontend coverage workflow --- .github/workflows/frontend-tests.yml | 50 +++++++ docs/frontend-testing-roadmap.md | 4 +- package.json | 3 +- scripts/run_frontend_coverage.js | 198 +++++++++++++++++++++++++++ vitest.config.js | 4 +- 5 files changed, 255 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/frontend-tests.yml create mode 100755 scripts/run_frontend_coverage.js diff --git a/.github/workflows/frontend-tests.yml b/.github/workflows/frontend-tests.yml new file mode 100644 index 00000000..362a8b67 --- /dev/null +++ b/.github/workflows/frontend-tests.yml @@ -0,0 +1,50 @@ +name: Frontend Tests + +on: + push: + branches: + - main + - master + paths: + - 'package.json' + - 'package-lock.json' + - 'vitest.config.js' + - 'tests/frontend/**' + - 'static/js/**' + - '.github/workflows/frontend-tests.yml' + pull_request: + paths: + - 'package.json' + - 'package-lock.json' + - 'vitest.config.js' + - 'tests/frontend/**' + - 'static/js/**' + - '.github/workflows/frontend-tests.yml' + +jobs: + vitest: + name: Run Vitest with coverage + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Use Node.js 20 + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run frontend tests with coverage + run: npm run test:coverage + + - name: Upload coverage artifact + if: always() + uses: actions/upload-artifact@v4 + with: + name: frontend-coverage + path: coverage/frontend + if-no-files-found: warn diff --git a/docs/frontend-testing-roadmap.md b/docs/frontend-testing-roadmap.md index 952b5af8..6ef5b514 100644 --- a/docs/frontend-testing-roadmap.md +++ b/docs/frontend-testing-roadmap.md @@ -11,7 +11,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR | Phase 2 | Test AppCore orchestration | Simulate page bootstrapping, infinite scroll hooks, and manager registration using JSDOM DOM fixtures | ✅ Complete | AppCore initialization + page feature suites now validate manager wiring, infinite scroll hooks, and onboarding gating | | Phase 3 | Validate page-specific managers | Add focused suites for `loras`, `checkpoints`, `embeddings`, and `recipes` managers covering filtering, sorting, and bulk actions | ✅ Complete | LoRA/checkpoint suites expanded; embeddings + recipes managers now covered with initialization, filtering, and duplicate workflows | | Phase 4 | Interaction-level regression tests | Exercise template fragments, modals, and menus to ensure UI wiring remains intact | ✅ Complete | Vitest DOM suites cover NSFW selector, recipe modal editing, and global context menus | -| Phase 5 | Continuous integration & coverage | Integrate frontend tests into CI workflow and track coverage metrics | ⚪ Not Started | Align reporting directories with backend coverage for unified reporting | +| Phase 5 | Continuous integration & coverage | Integrate frontend tests into CI workflow and track coverage metrics | ✅ Complete | CI workflow runs Vitest and aggregates V8 coverage into `coverage/frontend` via a dedicated script | ## Next Steps Checklist @@ -21,7 +21,7 @@ This roadmap tracks the planned rollout of automated testing for the ComfyUI LoR - [x] Add AppCore page feature suite exercising context menu creation and infinite scroll registration via DOM fixtures. - [x] Extend AppCore orchestration tests to cover manager wiring, bulk menu setup, and onboarding gating scenarios. - [x] Add interaction regression suites for context menus and recipe modals to complete Phase 4. -- [ ] Evaluate integrating coverage reporting once test surface grows (> 20 specs). +- [x] Evaluate integrating coverage reporting once test surface grows (> 20 specs). - [x] Create shared fixtures for the loras and checkpoints pages once dedicated manager suites are added. - [x] Draft focused test matrix for loras/checkpoints manager filtering and sorting paths ahead of Phase 3. - [x] Implement LoRAs manager filtering/sorting specs for scenarios F-01–F-05 & F-09; queue remaining edge cases after duplicate/bulk flows stabilize. diff --git a/package.json b/package.json index 6f4a7229..1a5d64e8 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "type": "module", "scripts": { "test": "vitest run", - "test:watch": "vitest" + "test:watch": "vitest", + "test:coverage": "node scripts/run_frontend_coverage.js" }, "devDependencies": { "jsdom": "^24.0.0", diff --git a/scripts/run_frontend_coverage.js b/scripts/run_frontend_coverage.js new file mode 100755 index 00000000..efc69475 --- /dev/null +++ b/scripts/run_frontend_coverage.js @@ -0,0 +1,198 @@ +#!/usr/bin/env node +import { spawnSync } from 'node:child_process'; +import { mkdirSync, rmSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const repoRoot = path.resolve(__dirname, '..'); +const coverageRoot = path.join(repoRoot, 'coverage'); +const v8OutputDir = path.join(coverageRoot, '.v8'); +const frontendCoverageDir = path.join(coverageRoot, 'frontend'); + +rmSync(v8OutputDir, { recursive: true, force: true }); +rmSync(frontendCoverageDir, { recursive: true, force: true }); +mkdirSync(v8OutputDir, { recursive: true }); +mkdirSync(frontendCoverageDir, { recursive: true }); + +const vitestBinName = process.platform === 'win32' ? 'vitest.cmd' : 'vitest'; +const vitestBin = path.join(repoRoot, 'node_modules', '.bin', vitestBinName); + +const env = { ...process.env, NODE_V8_COVERAGE: v8OutputDir }; +const result = spawnSync(vitestBin, ['run'], { stdio: 'inherit', env }); + +if (result.error) { + console.error('Failed to execute Vitest:', result.error.message); + process.exit(result.status ?? 1); +} + +if (result.status !== 0) { + process.exit(result.status ?? 1); +} + +const fileCoverage = collectCoverageFromV8(v8OutputDir, repoRoot); +writeCoverageOutputs(fileCoverage, frontendCoverageDir, repoRoot); +printSummary(fileCoverage); +rmSync(v8OutputDir, { recursive: true, force: true }); + +function collectCoverageFromV8(v8Dir, rootDir) { + const coverageMap = new Map(); + const files = readdirSync(v8Dir).filter((file) => file.endsWith('.json')); + + for (const file of files) { + const reportPath = path.join(v8Dir, file); + const report = JSON.parse(readFileSync(reportPath, 'utf8')); + if (!Array.isArray(report.result)) { + continue; + } + + for (const script of report.result) { + const filePath = normalizeFilePath(script.url, rootDir); + if (!filePath) { + continue; + } + + if (!filePath.startsWith('static/')) { + continue; + } + + if (!filePath.endsWith('.js')) { + continue; + } + + const absolutePath = path.join(rootDir, filePath); + let lineMap = coverageMap.get(filePath); + if (!lineMap) { + lineMap = new Map(); + coverageMap.set(filePath, lineMap); + } + + const source = readFileSync(absolutePath, 'utf8'); + const lineOffsets = calculateLineOffsets(source); + + for (const fn of script.functions ?? []) { + for (const range of fn.ranges ?? []) { + if (range.startOffset === range.endOffset) { + continue; + } + const count = typeof range.count === 'number' ? range.count : 0; + const startLine = findLineNumber(range.startOffset, lineOffsets); + const endLine = findLineNumber(Math.max(range.endOffset - 1, range.startOffset), lineOffsets); + for (let line = startLine; line <= endLine; line += 1) { + const current = lineMap.get(line); + if (current === undefined || count > current) { + lineMap.set(line, count); + } + } + } + } + } + } + + return coverageMap; +} + +function normalizeFilePath(url, rootDir) { + if (!url) { + return null; + } + try { + const parsed = new URL(url); + if (parsed.protocol !== 'file:') { + return null; + } + const absolute = fileURLToPath(parsed); + const relative = path.relative(rootDir, absolute); + if (relative.startsWith('..') || path.isAbsolute(relative)) { + return null; + } + return relative.replace(/\\/g, '/'); + } catch { + if (url.startsWith(rootDir)) { + return url.slice(rootDir.length + 1).replace(/\\/g, '/'); + } + return null; + } +} + +function calculateLineOffsets(content) { + const offsets = [0]; + for (let index = 0; index < content.length; index += 1) { + if (content.charCodeAt(index) === 10) { + offsets.push(index + 1); + } + } + offsets.push(content.length); + return offsets; +} + +function findLineNumber(offset, lineOffsets) { + let low = 0; + let high = lineOffsets.length - 1; + while (low < high) { + const mid = Math.floor((low + high + 1) / 2); + if (lineOffsets[mid] <= offset) { + low = mid; + } else { + high = mid - 1; + } + } + return low + 1; +} + +function writeCoverageOutputs(coverageMap, outputDir, rootDir) { + const summary = { + total: { lines: { total: 0, covered: 0, pct: 100 } }, + files: {}, + }; + + let lcovContent = ''; + + for (const [relativePath, lineMap] of [...coverageMap.entries()].sort()) { + const lines = [...lineMap.entries()].sort((a, b) => a[0] - b[0]); + const total = lines.length; + const covered = lines.filter(([, count]) => count > 0).length; + const pct = total === 0 ? 100 : (covered / total) * 100; + + summary.files[relativePath] = { + lines: { + total, + covered, + pct, + }, + }; + + summary.total.lines.total += total; + summary.total.lines.covered += covered; + + const absolute = path.join(rootDir, relativePath); + lcovContent += 'TN:\n'; + lcovContent += `SF:${absolute.replace(/\\/g, '/')}\n`; + for (const [line, count] of lines) { + lcovContent += `DA:${line},${count}\n`; + } + lcovContent += `LF:${total}\n`; + lcovContent += `LH:${covered}\n`; + lcovContent += 'end_of_record\n'; + } + + summary.total.lines.pct = summary.total.lines.total === 0 + ? 100 + : (summary.total.lines.covered / summary.total.lines.total) * 100; + + writeFileSync(path.join(outputDir, 'coverage-summary.json'), JSON.stringify(summary, null, 2)); + writeFileSync(path.join(outputDir, 'lcov.info'), lcovContent, 'utf8'); +} + +function printSummary(coverageMap) { + let totalLines = 0; + let totalCovered = 0; + for (const lineMap of coverageMap.values()) { + const lines = lineMap.size; + const covered = [...lineMap.values()].filter((count) => count > 0).length; + totalLines += lines; + totalCovered += covered; + } + const pct = totalLines === 0 ? 100 : (totalCovered / totalLines) * 100; + console.log(`\nFrontend coverage: ${totalCovered}/${totalLines} lines (${pct.toFixed(2)}%)`); +} diff --git a/vitest.config.js b/vitest.config.js index 7f804af9..3d88d268 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -9,7 +9,9 @@ export default defineConfig({ 'tests/frontend/**/*.test.js' ], coverage: { - enabled: false, + enabled: process.env.VITEST_COVERAGE === 'true', + provider: 'v8', + reporter: ['text', 'lcov', 'json-summary'], reportsDirectory: 'coverage/frontend' } } From ec05282db64f95568fd2d599b477a322920eba01 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Thu, 25 Sep 2025 08:11:48 +0800 Subject: [PATCH 104/110] fix(coverage): improve Vitest CLI path handling and error checking --- scripts/run_frontend_coverage.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/scripts/run_frontend_coverage.js b/scripts/run_frontend_coverage.js index efc69475..922e4035 100755 --- a/scripts/run_frontend_coverage.js +++ b/scripts/run_frontend_coverage.js @@ -1,6 +1,6 @@ #!/usr/bin/env node import { spawnSync } from 'node:child_process'; -import { mkdirSync, rmSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'; +import { mkdirSync, rmSync, readdirSync, readFileSync, writeFileSync, existsSync } from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -15,11 +15,18 @@ rmSync(frontendCoverageDir, { recursive: true, force: true }); mkdirSync(v8OutputDir, { recursive: true }); mkdirSync(frontendCoverageDir, { recursive: true }); -const vitestBinName = process.platform === 'win32' ? 'vitest.cmd' : 'vitest'; -const vitestBin = path.join(repoRoot, 'node_modules', '.bin', vitestBinName); +const vitestCli = path.join(repoRoot, 'node_modules', 'vitest', 'vitest.mjs'); + +if (!existsSync(vitestCli)) { + console.error('Failed to locate Vitest CLI at', vitestCli); + console.error('Try reinstalling frontend dependencies with `npm install`.'); + process.exit(1); +} const env = { ...process.env, NODE_V8_COVERAGE: v8OutputDir }; -const result = spawnSync(vitestBin, ['run'], { stdio: 'inherit', env }); + +const spawnOptions = { stdio: 'inherit', env }; +const result = spawnSync(process.execPath, [vitestCli, 'run'], spawnOptions); if (result.error) { console.error('Failed to execute Vitest:', result.error.message); From c85e694c1d6e5e68425670294a37c9e5ad8cad05 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Thu, 25 Sep 2025 08:36:15 +0800 Subject: [PATCH 105/110] docs: update repository guidelines for clarity and consistency --- AGENTS.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 740491c5..31a731cc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,19 +1,22 @@ -# Repository Guidelines +# Repository Guidelines ## Project Structure & Module Organization -ComfyUI LoRA Manager pairs a Python backend with lightweight browser scripts. Backend modules live in `py/`, organized by responsibility: HTTP entry points under `routes/`, feature logic in `services/`, reusable helpers within `utils/`, and custom nodes in `nodes/`. Front-end widgets that extend the ComfyUI interface sit in `web/comfyui/`, while static images and templates are in `static/` and `templates/`. Shared localization files are stored in `locales/`, with workflow examples under `example_workflows/`. Tests currently reside alongside the source (`test_i18n.py`) until a dedicated `tests/` folder is introduced. +ComfyUI LoRA Manager pairs a Python backend with browser-side widgets. Backend modules live in py/ with HTTP entry points in py/routes/, feature logic in py/services/, shared helpers in py/utils/, and custom nodes in py/nodes/. UI scripts extend ComfyUI from web/comfyui/, while deploy-ready assets remain in static/ and templates/. Localization files live in locales/, example workflows in example_workflows/, and interim tests such as test_i18n.py sit beside their source until a dedicated tests/ tree lands. ## Build, Test, and Development Commands -Install dependencies with `pip install -r requirements.txt` from the repo root. Launch the standalone server for iterative work via `python standalone.py --port 8188`; ComfyUI users can also load the extension directly through ComfyUI's custom node manager. Run backend checks with `python -m pytest test_i18n.py`, and target new test files explicitly (e.g. `python -m pytest tests/test_recipes.py` once added). Use `python scripts/sync_translation_keys.py` to reconcile locale keys after updating UI strings. +- pip install -r requirements.txt installs backend dependencies. +- python standalone.py --port 8188 launches the standalone server for iterative development. +- python -m pytest test_i18n.py runs the current regression suite; target new files explicitly, e.g. python -m pytest tests/test_recipes.py. +- python scripts/sync_translation_keys.py synchronizes locale keys after UI string updates. ## Coding Style & Naming Conventions -Follow PEP 8 with four-space indentation and descriptive snake_case module/function names, mirroring files such as `py/services/settings_manager.py`. Classes remain PascalCase, constants UPPER_SNAKE_CASE, and loggers retrieved via `logging.getLogger(__name__)`. Prefer explicit type hints for new public APIs and docstrings that clarify side effects. JavaScript in `web/comfyui/` is modern ES modules; keep imports relative, favor camelCase functions, and mirror existing file suffixes like `_widget.js` for UI components. +Follow PEP 8 with four-space indentation and descriptive snake_case file and function names such as settings_manager.py. Classes stay PascalCase, constants in UPPER_SNAKE_CASE, and loggers retrieved via logging.getLogger(__name__). Prefer explicit type hints and docstrings on public APIs. JavaScript under web/comfyui/ uses ES modules with camelCase helpers and the _widget.js suffix for UI components. ## Testing Guidelines -Extend pytest coverage by co-locating tests near the code under test or in `tests/` with names like `test_.py`. When introducing new routes or services, add regression cases that mock ComfyUI dependencies (see the standalone mocking helpers in `standalone.py`). Prioritize deterministic fixtures for filesystem interactions and ensure translations include coverage when adding new locale keys. Always run `python -m pytest` before submitting work. +Pytest powers backend tests. Name modules test_.py and keep them near the code or in a future tests/ package. Mock ComfyUI dependencies through helpers in standalone.py, keep filesystem fixtures deterministic, and ensure translations are covered. Run python -m pytest before submitting changes. ## Commit & Pull Request Guidelines -Commits follow the conventional pattern seen in `git log` (`feat(scope):`, `fix(scope):`, `chore(scope):`). Keep messages imperative and scoped to a single change. Pull requests should summarize the problem, detail the solution, list manual test evidence, and link any GitHub issues. Include UI screenshots or GIFs when front-end behavior changes, and call out migration steps (e.g., settings updates) in the PR description. +Commits follow the conventional format, e.g. feat(settings): add default model path, and should stay focused on a single concern. Pull requests must outline the problem, summarize the solution, list manual verification steps (server run, targeted pytest), and link related issues. Include screenshots or GIFs for UI or locale updates and call out migration steps such as settings.json adjustments. ## Configuration & Localization Tips -Sample configuration defaults live in `settings.json.example`; copy it to `settings.json` and adjust model directories before running the standalone server. Whenever you add UI text, update `locales/.json` and run the translation sync script. Store reference assets in `civitai/` or `docs/` rather than mixing them with production templates, keeping the runtime folders (`static/`, `templates/`) deploy-ready. +Copy settings.json.example to settings.json and adapt model directories before running the standalone server. Store reference assets in civitai/ or docs/ to keep runtime directories deploy-ready. Whenever UI text changes, update every locales/<lang>.json file and rerun the translation sync script so ComfyUI surfaces localized strings. From 26b36c123de55e321d1531351485ffe2527efe3e Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Thu, 25 Sep 2025 09:21:08 +0800 Subject: [PATCH 106/110] test(i18n): modularize translation validation --- tests/i18n/test_i18n.py | 1192 +++++++-------------------------------- 1 file changed, 202 insertions(+), 990 deletions(-) diff --git a/tests/i18n/test_i18n.py b/tests/i18n/test_i18n.py index 1adf0dc9..41631287 100644 --- a/tests/i18n/test_i18n.py +++ b/tests/i18n/test_i18n.py @@ -1,1035 +1,247 @@ -#!/usr/bin/env python3 -""" -Test script to verify the updated i18n system works correctly. -This tests both JavaScript loading and Python server-side functionality. +"""Regression tests for localization data and usage. + +These tests validate three key aspects of the localisation setup: + +* Every locale file is valid JSON and contains the expected sections. +* All locales expose the same translation keys as the English reference. +* Static JavaScript/HTML sources only reference available translation keys. """ -import glob +from __future__ import annotations + import json -import os import re -import sys from pathlib import Path -from typing import Any, Dict, List, Set +from typing import Dict, Iterable, Set + +import pytest ROOT_DIR = Path(__file__).resolve().parents[2] -if str(ROOT_DIR) not in sys.path: - sys.path.insert(0, str(ROOT_DIR)) +LOCALES_DIR = ROOT_DIR / "locales" +STATIC_JS_DIR = ROOT_DIR / "static" / "js" +TEMPLATES_DIR = ROOT_DIR / "templates" + +EXPECTED_LOCALES = ( + "en", + "zh-CN", + "zh-TW", + "ja", + "ru", + "de", + "fr", + "es", + "ko", +) + +REQUIRED_SECTIONS = {"common", "header", "loras", "recipes", "modals"} + +SINGLE_WORD_TRANSLATION_KEYS = { + "loading", + "error", + "success", + "warning", + "info", + "cancel", + "save", + "delete", +} + +FALSE_POSITIVES = { + "checkpoint", + "civitai_api_key", + "div", + "embedding", + "lora", + "show_only_sfw", + "model", + "type", + "name", + "value", + "id", + "class", + "style", + "src", + "href", + "data", + "width", + "height", + "size", + "format", + "version", + "url", + "path", + "file", + "folder", + "image", + "text", + "number", + "boolean", + "array", + "object", + "non.existent.key", +} + +SPECIAL_UI_HELPER_KEYS = { + "uiHelpers.workflow.loraAdded", + "uiHelpers.workflow.loraReplaced", + "uiHelpers.workflow.loraFailedToSend", + "uiHelpers.workflow.recipeAdded", + "uiHelpers.workflow.recipeReplaced", + "uiHelpers.workflow.recipeFailedToSend", +} + +JS_TRANSLATION_PATTERNS = ( + r"\btranslate\s*\(\s*['\"]([a-zA-Z0-9._-]+)['\"]", + r"\bshowToast\s*\(\s*['\"]([a-zA-Z0-9._-]+)['\"]", + r"\bt\s*\(\s*['\"]([a-zA-Z0-9._-]+)['\"]", +) + +HTML_TRANSLATION_PATTERN = ( + r"(?:\{\{|\{%)[^}]*\bt\s*\(\s*['\"]([a-zA-Z0-9._-]+)['\"][^}]*(?:\}\}|%\})" +) -def check_json_files_exist() -> bool: - """Test that all JSON locale files exist and are valid JSON.""" - print("Testing JSON locale files...") - return check_json_structure_validation() +@pytest.fixture(scope="module") +def loaded_locales() -> Dict[str, dict]: + """Load locale JSON once per test module.""" + locales: Dict[str, dict] = {} + for locale in EXPECTED_LOCALES: + path = LOCALES_DIR / f"{locale}.json" + if not path.exists(): + pytest.fail(f"Locale file {path.name} is missing", pytrace=False) -def check_locale_files_structural_consistency() -> bool: - """Test that all locale files have identical structure, line counts, and formatting.""" - print("\nTesting locale files structural consistency...") - - locales_dir = ROOT_DIR / 'locales' - if not locales_dir.exists(): - print("❌ Locales directory does not exist!") - return False - - # Get all locale files - locale_files = [] - for file in os.listdir(locales_dir): - if file.endswith('.json'): - locale_files.append(file) - - if not locale_files: - print("❌ No locale files found!") - return False - - # Use en.json as the reference - reference_file = 'en.json' - if reference_file not in locale_files: - print(f"❌ Reference file {reference_file} not found!") - return False - - locale_files.remove(reference_file) - locale_files.insert(0, reference_file) # Put reference first - - success = True - - # Load and parse the reference file - reference_path = locales_dir / reference_file - try: - with open(reference_path, 'r', encoding='utf-8') as f: - reference_lines = f.readlines() - reference_content = ''.join(reference_lines) - - reference_data = json.loads(reference_content) - reference_structure = get_json_structure(reference_data) - - print(f"📋 Reference file {reference_file}:") - print(f" Lines: {len(reference_lines)}") - print(f" Keys: {len(get_all_translation_keys(reference_data))}") - - except Exception as e: - print(f"❌ Error reading reference file {reference_file}: {e}") - return False - - # Compare each locale file with the reference - for locale_file in locale_files[1:]: # Skip reference file - locale_path = locales_dir / locale_file - locale_name = locale_file.replace('.json', '') - try: - with open(locale_path, 'r', encoding='utf-8') as f: - locale_lines = f.readlines() - locale_content = ''.join(locale_lines) - - locale_data = json.loads(locale_content) - locale_structure = get_json_structure(locale_data) - - # Test 1: Line count consistency - if len(locale_lines) != len(reference_lines): - print(f"❌ {locale_name}: Line count mismatch!") - print(f" Reference: {len(reference_lines)} lines") - print(f" {locale_name}: {len(locale_lines)} lines") - success = False - continue - - # Test 2: Structural consistency (key order and nesting) - structure_issues = compare_json_structures(reference_structure, locale_structure) - if structure_issues: - print(f"❌ {locale_name}: Structure mismatch!") - for issue in structure_issues[:5]: # Show first 5 issues - print(f" - {issue}") - if len(structure_issues) > 5: - print(f" ... and {len(structure_issues) - 5} more issues") - success = False - continue - - # Test 3: Line-by-line format consistency (excluding translation values) - format_issues = compare_line_formats(reference_lines, locale_lines, locale_name) - if format_issues: - print(f"❌ {locale_name}: Format mismatch!") - for issue in format_issues[:5]: # Show first 5 issues - print(f" - {issue}") - if len(format_issues) > 5: - print(f" ... and {len(format_issues) - 5} more issues") - success = False - continue - - # Test 4: Key completeness - reference_keys = get_all_translation_keys(reference_data) - locale_keys = get_all_translation_keys(locale_data) - - missing_keys = reference_keys - locale_keys - extra_keys = locale_keys - reference_keys - - if missing_keys or extra_keys: - print(f"❌ {locale_name}: Key mismatch!") - if missing_keys: - print(f" Missing {len(missing_keys)} keys") - if extra_keys: - print(f" Extra {len(extra_keys)} keys") - success = False - continue - - print(f"✅ {locale_name}: Structure and format consistent") - - except json.JSONDecodeError as e: - print(f"❌ {locale_name}: Invalid JSON syntax: {e}") - success = False - except Exception as e: - print(f"❌ {locale_name}: Error during validation: {e}") - success = False - - if success: - print(f"\n✅ All {len(locale_files)} locale files have consistent structure and formatting") - - return success + data = json.loads(path.read_text(encoding="utf-8")) + except json.JSONDecodeError as exc: # pragma: no cover - explicit failure message + pytest.fail(f"Locale file {path.name} contains invalid JSON: {exc}", pytrace=False) -def get_json_structure(data: Any, path: str = '') -> Dict[str, Any]: - """ - Extract the structural information from JSON data. - Returns a dictionary describing the structure without the actual values. - """ - if isinstance(data, dict): - structure = {} - for key, value in data.items(): - current_path = f"{path}.{key}" if path else key - if isinstance(value, dict): - structure[key] = get_json_structure(value, current_path) - elif isinstance(value, list): - structure[key] = {'_type': 'array', '_length': len(value)} - if value: # If array is not empty, analyze first element - structure[key]['_element_type'] = get_json_structure(value[0], f"{current_path}[0]") - else: - structure[key] = {'_type': type(value).__name__} - return structure - elif isinstance(data, list): - return {'_type': 'array', '_length': len(data)} - else: - return {'_type': type(data).__name__} + if not isinstance(data, dict): + pytest.fail( + f"Locale file {path.name} must contain a JSON object at the top level", + pytrace=False, + ) -def compare_json_structures(ref_structure: Dict[str, Any], locale_structure: Dict[str, Any], path: str = '') -> List[str]: - """ - Compare two JSON structures and return a list of differences. - """ - issues = [] - - # Check for missing keys in locale - for key in ref_structure: - current_path = f"{path}.{key}" if path else key - if key not in locale_structure: - issues.append(f"Missing key: {current_path}") - elif isinstance(ref_structure[key], dict) and '_type' not in ref_structure[key]: - # It's a nested object, recurse - if isinstance(locale_structure[key], dict) and '_type' not in locale_structure[key]: - issues.extend(compare_json_structures(ref_structure[key], locale_structure[key], current_path)) - else: - issues.append(f"Structure mismatch at {current_path}: expected object, got {type(locale_structure[key])}") - elif ref_structure[key] != locale_structure[key]: - issues.append(f"Type mismatch at {current_path}: expected {ref_structure[key]}, got {locale_structure[key]}") - - # Check for extra keys in locale - for key in locale_structure: - current_path = f"{path}.{key}" if path else key - if key not in ref_structure: - issues.append(f"Extra key: {current_path}") - - return issues + locales[locale] = data -def extract_line_structure(line: str) -> Dict[str, str]: - """ - Extract structural elements from a JSON line. - Returns indentation, key (if present), and structural characters. - """ - # Get indentation (leading whitespace) - indentation = len(line) - len(line.lstrip()) - - # Remove leading/trailing whitespace for analysis - stripped_line = line.strip() - - # Extract key if this is a key-value line - key_match = re.match(r'^"([^"]+)"\s*:\s*', stripped_line) - key = key_match.group(1) if key_match else '' - - # Extract structural characters (everything except the actual translation value) - if key: - # For key-value lines, extract everything except the value - # Handle string values in quotes with better escaping support - value_pattern = r'^"[^"]+"\s*:\s*("(?:[^"\\]|\\.)*")(.*?)$' - value_match = re.match(value_pattern, stripped_line) - if value_match: - # Preserve the structure but replace the actual string content - structural_chars = f'"{key}": "VALUE"{value_match.group(2)}' - else: - # Handle non-string values (objects, arrays, booleans, numbers) - colon_pos = stripped_line.find(':') - if colon_pos != -1: - after_colon = stripped_line[colon_pos + 1:].strip() - if after_colon.startswith('"'): - # String value - find the end quote with proper escaping - end_quote = find_closing_quote(after_colon, 1) - if end_quote != -1: - structural_chars = f'"{key}": "VALUE"{after_colon[end_quote + 1:]}' - else: - structural_chars = f'"{key}": "VALUE"' - elif after_colon.startswith('{'): - # Object value - structural_chars = f'"{key}": {{' - elif after_colon.startswith('['): - # Array value - structural_chars = f'"{key}": [' - else: - # Other values (numbers, booleans, null) - # Replace the actual value with a placeholder - value_end = find_value_end(after_colon) - structural_chars = f'"{key}": VALUE{after_colon[value_end:]}' - else: - structural_chars = stripped_line - else: - # For non key-value lines (brackets, etc.), keep as-is - structural_chars = stripped_line - - return { - 'indentation': str(indentation), - 'key': key, - 'structural_chars': structural_chars - } - -def find_value_end(text: str) -> int: - """ - Find the end of a non-string JSON value (number, boolean, null). - """ - for i, char in enumerate(text): - if char in ',}]': - return i - return len(text) - -def find_closing_quote(text: str, start: int) -> int: - """ - Find the position of the closing quote, handling escaped quotes properly. - """ - i = start - while i < len(text): - if text[i] == '"': - # Count preceding backslashes - backslash_count = 0 - j = i - 1 - while j >= 0 and text[j] == '\\': - backslash_count += 1 - j -= 1 - - # If even number of backslashes (including 0), the quote is not escaped - if backslash_count % 2 == 0: - return i - i += 1 - return -1 - -def compare_line_formats(ref_lines: List[str], locale_lines: List[str], locale_name: str) -> List[str]: - """ - Compare line-by-line formatting between reference and locale files. - Only checks structural elements (indentation, brackets, commas) and ignores translation values. - """ - issues = [] - - for i, (ref_line, locale_line) in enumerate(zip(ref_lines, locale_lines)): - line_num = i + 1 - - # Skip empty lines and lines with only whitespace - if not ref_line.strip() and not locale_line.strip(): - continue - - # Extract structural elements from each line - ref_structure = extract_line_structure(ref_line) - locale_structure = extract_line_structure(locale_line) - - # Compare structural elements with more tolerance - structure_issues = [] - - # Check indentation (must be exact) - if ref_structure['indentation'] != locale_structure['indentation']: - structure_issues.append(f"indentation ({ref_structure['indentation']} vs {locale_structure['indentation']})") - - # Check keys (must be exact for structural consistency) - if ref_structure['key'] != locale_structure['key']: - structure_issues.append(f"key ('{ref_structure['key']}' vs '{locale_structure['key']}')") - - # Check structural characters with improved normalization - ref_normalized = normalize_structural_chars(ref_structure['structural_chars']) - locale_normalized = normalize_structural_chars(locale_structure['structural_chars']) - - if ref_normalized != locale_normalized: - # Additional check: if both lines have the same key and similar structure, - # this might be a false positive due to translation content differences - if (ref_structure['key'] and locale_structure['key'] and - ref_structure['key'] == locale_structure['key']): - - # Check if the difference is only in the translation value - ref_has_string_value = '"VALUE"' in ref_normalized - locale_has_string_value = '"VALUE"' in locale_normalized - - if ref_has_string_value and locale_has_string_value: - # Both have string values, check if structure around value is same - ref_structure_only = re.sub(r'"VALUE"', '"X"', ref_normalized) - locale_structure_only = re.sub(r'"VALUE"', '"X"', locale_normalized) - - if ref_structure_only == locale_structure_only: - # Structure is actually the same, skip this as false positive - continue - - structure_issues.append(f"structure ('{ref_normalized}' vs '{locale_normalized}')") - - if structure_issues: - issues.append(f"Line {line_num}: {', '.join(structure_issues)}") - - return issues - -def normalize_structural_chars(structural_chars: str) -> str: - """ - Normalize structural characters for comparison by replacing variable content - with placeholders while preserving the actual structure. - """ - # Normalize the structural characters more carefully - normalized = structural_chars - - # Replace quoted strings with a consistent placeholder, handling escapes - # This regex matches strings while properly handling escaped quotes - string_pattern = r'"(?:[^"\\]|\\.)*"(?=\s*[,}\]:}]|$)' - - # Find all string matches and replace with placeholder - strings = re.findall(string_pattern, normalized) - for string_match in strings: - # Only replace if this looks like a translation value, not a key - if ':' in normalized: - # Check if this string comes after a colon (likely a value) - parts = normalized.split(':', 1) - if len(parts) == 2 and string_match in parts[1]: - normalized = normalized.replace(string_match, '"VALUE"', 1) - - # Normalize whitespace around structural characters - normalized = re.sub(r'\s*:\s*', ': ', normalized) - normalized = re.sub(r'\s*,\s*', ', ', normalized) - normalized = re.sub(r'\s*{\s*', '{ ', normalized) - normalized = re.sub(r'\s*}\s*', ' }', normalized) - - return normalized.strip() - -def check_locale_files_formatting_consistency() -> bool: - """Test that all locale files have identical formatting (whitespace, indentation, etc.).""" - print("\nTesting locale files formatting consistency...") - - locales_dir = ROOT_DIR / 'locales' - expected_locales = ['en', 'zh-CN', 'zh-TW', 'ja', 'ru', 'de', 'fr', 'es', 'ko'] - - # Read reference file (en.json) - reference_path = locales_dir / 'en.json' - try: - with open(reference_path, 'r', encoding='utf-8') as f: - reference_lines = f.readlines() - except Exception as e: - print(f"❌ Error reading reference file: {e}") - return False - - success = True - - # Compare each locale file - for locale in expected_locales[1:]: # Skip 'en' as it's the reference - locale_path = locales_dir / f'{locale}.json' - - if not os.path.exists(locale_path): - print(f"❌ {locale}.json does not exist!") - success = False - continue - - try: - with open(locale_path, 'r', encoding='utf-8') as f: - locale_lines = f.readlines() - - # Compare line count - if len(locale_lines) != len(reference_lines): - print(f"❌ {locale}.json: Line count differs from reference") - print(f" Reference: {len(reference_lines)} lines") - print(f" {locale}: {len(locale_lines)} lines") - success = False - continue - - # Compare formatting with improved algorithm - formatting_issues = compare_line_formats(reference_lines, locale_lines, locale) - - if formatting_issues: - print(f"❌ {locale}.json: Formatting issues found") - # Show only the first few issues to avoid spam - shown_issues = 0 - for issue in formatting_issues: - if shown_issues < 3: # Reduced from 5 to 3 - print(f" - {issue}") - shown_issues += 1 - else: - break - - if len(formatting_issues) > 3: - print(f" ... and {len(formatting_issues) - 3} more issues") - - # Provide debug info for first issue to help identify false positives - if formatting_issues: - first_issue = formatting_issues[0] - line_match = re.match(r'Line (\d+):', first_issue) - if line_match: - line_num = int(line_match.group(1)) - 1 # Convert to 0-based - if 0 <= line_num < len(reference_lines): - print(f" Debug - Reference line {line_num + 1}: {repr(reference_lines[line_num].rstrip())}") - print(f" Debug - {locale} line {line_num + 1}: {repr(locale_lines[line_num].rstrip())}") - - success = False - else: - print(f"✅ {locale}.json: Formatting consistent with reference") - - except Exception as e: - print(f"❌ Error validating {locale}.json: {e}") - success = False - - if success: - print("✅ All locale files have consistent formatting") - else: - print("💡 Note: Some formatting differences may be false positives due to translation content.") - print(" If translations are correct but structure appears different, the test may need refinement.") - - return success - -def check_locale_key_ordering() -> bool: - """Test that all locale files maintain the same key ordering as the reference.""" - print("\nTesting locale files key ordering...") - - locales_dir = ROOT_DIR / 'locales' - expected_locales = ['en', 'zh-CN', 'zh-TW', 'ja', 'ru', 'de', 'fr', 'es', 'ko'] - - # Load reference file - reference_path = locales_dir / 'en.json' - try: - with open(reference_path, 'r', encoding='utf-8') as f: - reference_data = json.load(f, object_pairs_hook=lambda x: x) # Preserve order - - reference_key_order = get_key_order(reference_data) - except Exception as e: - print(f"❌ Error reading reference file: {e}") - return False - - success = True - - for locale in expected_locales[1:]: # Skip 'en' as it's the reference - locale_path = locales_dir / f'{locale}.json' - - if not os.path.exists(locale_path): - continue - - try: - with open(locale_path, 'r', encoding='utf-8') as f: - locale_data = json.load(f, object_pairs_hook=lambda x: x) # Preserve order - - locale_key_order = get_key_order(locale_data) - - if reference_key_order != locale_key_order: - print(f"❌ {locale}.json: Key ordering differs from reference") - - # Find the first difference - for i, (ref_key, locale_key) in enumerate(zip(reference_key_order, locale_key_order)): - if ref_key != locale_key: - print(f" First difference at position {i}: '{ref_key}' vs '{locale_key}'") - break - - success = False - else: - print(f"✅ {locale}.json: Key ordering matches reference") - - except Exception as e: - print(f"❌ Error validating {locale}.json key ordering: {e}") - success = False - - return success - -def get_key_order(data: Any, path: str = '') -> List[str]: - """ - Extract the order of keys from nested JSON data. - Returns a list of all keys in their order of appearance. - """ - keys = [] - - if isinstance(data, list): - # Handle list of key-value pairs (from object_pairs_hook) - for key, value in data: - current_path = f"{path}.{key}" if path else key - keys.append(current_path) - if isinstance(value, list): # Nested object as list of pairs - keys.extend(get_key_order(value, current_path)) - elif isinstance(data, dict): - for key, value in data.items(): - current_path = f"{path}.{key}" if path else key - keys.append(current_path) - if isinstance(value, (dict, list)): - keys.extend(get_key_order(value, current_path)) - - return keys - -def check_server_i18n() -> bool: - """Test the Python server-side i18n system.""" - print("\nTesting Python server-side i18n...") - - try: - from py.services.server_i18n import ServerI18nManager - - # Create a new instance to test - i18n = ServerI18nManager() - - # Test that translations loaded - available_locales = i18n.get_available_locales() - if not available_locales: - print("❌ No locales loaded in server i18n!") - return False - - print(f"✅ Loaded {len(available_locales)} locales: {', '.join(available_locales)}") - - # Test English translations - i18n.set_locale('en') - test_key = 'common.status.loading' - translation = i18n.get_translation(test_key) - if translation == test_key: - print(f"❌ Translation not found for key '{test_key}'") - return False - - print(f"✅ English translation for '{test_key}': '{translation}'") - - # Test Chinese translations - i18n.set_locale('zh-CN') - translation_cn = i18n.get_translation(test_key) - if translation_cn == test_key: - print(f"❌ Chinese translation not found for key '{test_key}'") - return False - - print(f"✅ Chinese translation for '{test_key}': '{translation_cn}'") - - # Test parameter interpolation - param_key = 'common.itemCount' - translation_with_params = i18n.get_translation(param_key, count=42) - if '{count}' in translation_with_params: - print(f"❌ Parameter interpolation failed for key '{param_key}'") - return False - - print(f"✅ Parameter interpolation for '{param_key}': '{translation_with_params}'") - - print("✅ Server-side i18n system working correctly") - return True - - except Exception as e: - print(f"❌ Error testing server i18n: {e}") - import traceback - traceback.print_exc() - return False - -def check_translation_completeness() -> bool: - """Test that all languages have the same translation keys.""" - print("\nTesting translation completeness...") - - locales_dir = ROOT_DIR / 'locales' - - # Load English as reference - with open(locales_dir / 'en.json', 'r', encoding='utf-8') as f: - en_data = json.load(f) - - en_keys = get_all_translation_keys(en_data) - print(f"English has {len(en_keys)} translation keys") - - # Check other languages - locales = ['zh-CN', 'zh-TW', 'ja', 'ru', 'de', 'fr', 'es', 'ko'] - - for locale in locales: - with open(locales_dir / f'{locale}.json', 'r', encoding='utf-8') as f: - locale_data = json.load(f) - - locale_keys = get_all_translation_keys(locale_data) - - missing_keys = en_keys - locale_keys - extra_keys = locale_keys - en_keys - - if missing_keys: - print(f"❌ {locale} missing keys: {len(missing_keys)}") - # Print first few missing keys - for key in sorted(missing_keys)[:5]: - print(f" - {key}") - if len(missing_keys) > 5: - print(f" ... and {len(missing_keys) - 5} more") - - if extra_keys: - print(f"⚠️ {locale} has extra keys: {len(extra_keys)}") - - if not missing_keys and not extra_keys: - print(f"✅ {locale} has complete translations ({len(locale_keys)} keys)") - - return True + return locales -def extract_i18n_keys_from_js(file_path: str) -> Set[str]: - """Extract translation keys from JavaScript files.""" - keys = set() - - try: - with open(file_path, 'r', encoding='utf-8') as f: - content = f.read() - - # Remove comments to avoid false positives - # Remove single-line comments - content = re.sub(r'//.*$', '', content, flags=re.MULTILINE) - # Remove multi-line comments - content = re.sub(r'/\*.*?\*/', '', content, flags=re.DOTALL) - - # Pattern for translate() function calls - more specific - # Matches: translate('key.name', ...) or translate("key.name", ...) - # Must have opening parenthesis immediately after translate - translate_pattern = r"\btranslate\s*\(\s*['\"]([a-zA-Z0-9._-]+)['\"]" - translate_matches = re.findall(translate_pattern, content) - - # Filter out single words that are likely not translation keys - # Translation keys should typically have dots or be in specific namespaces - filtered_translate = [key for key in translate_matches if '.' in key or key in [ - 'loading', 'error', 'success', 'warning', 'info', 'cancel', 'save', 'delete' - ]] - keys.update(filtered_translate) - - # Pattern for showToast() function calls - more specific - # Matches: showToast('key.name', ...) or showToast("key.name", ...) - showtoast_pattern = r"\bshowToast\s*\(\s*['\"]([a-zA-Z0-9._-]+)['\"]" - showtoast_matches = re.findall(showtoast_pattern, content) - - # Filter showToast matches as well - filtered_showtoast = [key for key in showtoast_matches if '.' in key or key in [ - 'loading', 'error', 'success', 'warning', 'info', 'cancel', 'save', 'delete' - ]] - keys.update(filtered_showtoast) - - # Additional patterns for other i18n function calls you might have - # Pattern for t() function calls (if used in JavaScript) - t_pattern = r"\bt\s*\(\s*['\"]([a-zA-Z0-9._-]+)['\"]" - t_matches = re.findall(t_pattern, content) - filtered_t = [key for key in t_matches if '.' in key or key in [ - 'loading', 'error', 'success', 'warning', 'info', 'cancel', 'save', 'delete' - ]] - keys.update(filtered_t) - - except Exception as e: - print(f"⚠️ Error reading {file_path}: {e}") - - return keys +@pytest.fixture(scope="module") +def english_translation_keys(loaded_locales: Dict[str, dict]) -> Set[str]: + return collect_translation_keys(loaded_locales["en"]) -def extract_i18n_keys_from_html(file_path: str) -> Set[str]: - """Extract translation keys from HTML template files.""" - keys = set() - - try: - with open(file_path, 'r', encoding='utf-8') as f: - content = f.read() - - # Remove HTML comments to avoid false positives - content = re.sub(r'', '', content, flags=re.DOTALL) - - # Pattern for t() function calls in Jinja2 templates - # Matches: {{ t('key.name') }} or {% ... t('key.name') ... %} - # More specific pattern that ensures we're in template context - t_pattern = r"(?:\{\{|\{%)[^}]*\bt\s*\(\s*['\"]([a-zA-Z0-9._-]+)['\"][^}]*(?:\}\}|%\})" - t_matches = re.findall(t_pattern, content) - - # Filter HTML matches - filtered_t = [key for key in t_matches if '.' in key or key in [ - 'loading', 'error', 'success', 'warning', 'info', 'cancel', 'save', 'delete' - ]] - keys.update(filtered_t) - - # Also check for translate() calls in script tags within HTML - script_pattern = r']*>(.*?)' - script_matches = re.findall(script_pattern, content, flags=re.DOTALL) - for script_content in script_matches: - # Apply JavaScript extraction to script content - translate_pattern = r"\btranslate\s*\(\s*['\"]([a-zA-Z0-9._-]+)['\"]" - script_translate_matches = re.findall(translate_pattern, script_content) - filtered_script = [key for key in script_translate_matches if '.' in key] - keys.update(filtered_script) - - except Exception as e: - print(f"⚠️ Error reading {file_path}: {e}") - - return keys +@pytest.fixture(scope="module") +def static_code_translation_keys() -> Set[str]: + return gather_static_translation_keys() -def get_all_translation_keys(data: dict, prefix: str = '', include_containers: bool = False) -> Set[str]: - """ - Recursively collect translation keys. - By default only leaf keys (where the value is NOT a dict) are returned so that - structural/container nodes (e.g. 'common', 'common.actions') are not treated - as real translation entries and won't appear in the 'unused' list. - - Set include_containers=True to also include container/object nodes. - """ +def collect_translation_keys(data: dict, prefix: str = "") -> Set[str]: + """Recursively collect translation keys from a locale dictionary.""" keys: Set[str] = set() - if not isinstance(data, dict): - return keys + for key, value in data.items(): full_key = f"{prefix}.{key}" if prefix else key if isinstance(value, dict): - # Recurse first - keys.update(get_all_translation_keys(value, full_key, include_containers)) - # Optionally include container nodes - if include_containers: - keys.add(full_key) + keys.update(collect_translation_keys(value, full_key)) else: - # Leaf node: actual translatable value keys.add(full_key) + return keys -def check_static_code_analysis() -> bool: - """Test static code analysis to detect missing translation keys.""" - # print("\nTesting static code analysis for translation keys...") - - # Load English translations as reference - locales_dir = ROOT_DIR / 'locales' - with open(locales_dir / 'en.json', 'r', encoding='utf-8') as f: - en_data = json.load(f) - - available_keys = get_all_translation_keys(en_data) - # print(f"Available translation keys in en.json: {len(available_keys)}") - - # Known false positives to exclude from analysis - # These are typically HTML attributes, CSS classes, or other non-translation strings - false_positives = { - 'checkpoint', 'civitai_api_key', 'div', 'embedding', 'lora', 'show_only_sfw', - 'model', 'type', 'name', 'value', 'id', 'class', 'style', 'src', 'href', - 'data', 'width', 'height', 'size', 'format', 'version', 'url', 'path', - 'file', 'folder', 'image', 'text', 'number', 'boolean', 'array', 'object', 'non.existent.key' - } +def gather_static_translation_keys() -> Set[str]: + """Collect translation keys referenced in static JavaScript and HTML templates.""" + keys: Set[str] = set() - # Special translation keys used in uiHelpers.js but not detected by regex - uihelpers_special_keys = { - 'uiHelpers.workflow.loraAdded', - 'uiHelpers.workflow.loraReplaced', - 'uiHelpers.workflow.loraFailedToSend', - 'uiHelpers.workflow.recipeAdded', - 'uiHelpers.workflow.recipeReplaced', - 'uiHelpers.workflow.recipeFailedToSend', - } - - # Extract keys from JavaScript files - js_dir = ROOT_DIR / 'static' / 'js' - js_files = [] - if os.path.exists(js_dir): - # Recursively find all JS files - for root, dirs, files in os.walk(js_dir): - for file in files: - if file.endswith('.js'): - js_files.append(os.path.join(root, file)) - - js_keys = set() - js_files_with_keys = [] - for js_file in js_files: - file_keys = extract_i18n_keys_from_js(js_file) - # Filter out false positives - file_keys = file_keys - false_positives - js_keys.update(file_keys) - if file_keys: - rel_path = os.path.relpath(js_file, ROOT_DIR) - js_files_with_keys.append((rel_path, len(file_keys))) - # print(f" Found {len(file_keys)} keys in {rel_path}") - - # print(f"Total unique keys found in JavaScript files: {len(js_keys)}") - - # Extract keys from HTML template files - templates_dir = ROOT_DIR / 'templates' - html_files = [] - if os.path.exists(templates_dir): - html_files = glob.glob(os.path.join(templates_dir, '*.html')) - # Also check for HTML files in subdirectories - html_files.extend(glob.glob(os.path.join(templates_dir, '**', '*.html'), recursive=True)) - - html_keys = set() - html_files_with_keys = [] - for html_file in html_files: - file_keys = extract_i18n_keys_from_html(html_file) - # Filter out false positives - file_keys = file_keys - false_positives - html_keys.update(file_keys) - if file_keys: - rel_path = os.path.relpath(html_file, ROOT_DIR) - html_files_with_keys.append((rel_path, len(file_keys))) - # print(f" Found {len(file_keys)} keys in {rel_path}") - - # print(f"Total unique keys found in HTML templates: {len(html_keys)}") - - # Combine all used keys - all_used_keys = js_keys.union(html_keys) - # Add special keys from uiHelpers.js - all_used_keys.update(uihelpers_special_keys) - # print(f"Total unique keys used in code: {len(all_used_keys)}") - - # Check for missing keys - missing_keys = all_used_keys - available_keys - unused_keys = available_keys - all_used_keys - - success = True - - if missing_keys: - print(f"\n❌ Found {len(missing_keys)} missing translation keys:") - for key in sorted(missing_keys): - print(f" - {key}") - success = False - - # Group missing keys by category for better analysis - key_categories = {} - for key in missing_keys: - category = key.split('.')[0] if '.' in key else 'root' - if category not in key_categories: - key_categories[category] = [] - key_categories[category].append(key) - - print(f"\n Missing keys by category:") - for category, keys in sorted(key_categories.items()): - print(f" {category}: {len(keys)} keys") - - # Provide helpful suggestion - print(f"\n💡 If these are false positives, add them to the false_positives set in test_static_code_analysis()") - else: - print("\n✅ All translation keys used in code are available in en.json") - - if unused_keys: - print(f"\n⚠️ Found {len(unused_keys)} unused translation keys in en.json:") - # Only show first 20 to avoid cluttering output - for key in sorted(unused_keys)[:20]: - print(f" - {key}") - if len(unused_keys) > 20: - print(f" ... and {len(unused_keys) - 20} more") + if STATIC_JS_DIR.exists(): + for file_path in STATIC_JS_DIR.rglob("*.js"): + keys.update(filter_translation_keys(extract_i18n_keys_from_js(file_path))) - # Group unused keys by category for better analysis - unused_categories = {} - for key in unused_keys: - category = key.split('.')[0] if '.' in key else 'root' - if category not in unused_categories: - unused_categories[category] = [] - unused_categories[category].append(key) - - print(f"\n Unused keys by category:") - for category, keys in sorted(unused_categories.items()): - print(f" {category}: {len(keys)} keys") - - # Summary statistics - # print(f"\n📊 Static Code Analysis Summary:") - # print(f" JavaScript files analyzed: {len(js_files)}") - # print(f" JavaScript files with translations: {len(js_files_with_keys)}") - # print(f" HTML template files analyzed: {len(html_files)}") - # print(f" HTML template files with translations: {len(html_files_with_keys)}") - # print(f" Translation keys in en.json: {len(available_keys)}") - # print(f" Translation keys used in code: {len(all_used_keys)}") - # print(f" Usage coverage: {len(all_used_keys)/len(available_keys)*100:.1f}%") - - return success + if TEMPLATES_DIR.exists(): + for file_path in TEMPLATES_DIR.rglob("*.html"): + keys.update(filter_translation_keys(extract_i18n_keys_from_html(file_path))) + + keys.update(SPECIAL_UI_HELPER_KEYS) + + return keys -def check_json_structure_validation() -> bool: - """Test JSON file structure and syntax validation.""" - print("\nTesting JSON file structure and syntax validation...") - - locales_dir = ROOT_DIR / 'locales' - if not locales_dir.exists(): - print("❌ Locales directory does not exist!") - return False - - expected_locales = ['en', 'zh-CN', 'zh-TW', 'ja', 'ru', 'de', 'fr', 'es', 'ko'] - success = True - - for locale in expected_locales: - file_path = locales_dir / f'{locale}.json' - if not file_path.exists(): - print(f"❌ {locale}.json does not exist!") - success = False +def filter_translation_keys(raw_keys: Iterable[str]) -> Set[str]: + """Filter out obvious false positives and non-translation identifiers.""" + filtered: Set[str] = set() + for key in raw_keys: + if key in FALSE_POSITIVES: continue - - try: - with open(file_path, 'r', encoding='utf-8') as f: - data = json.load(f) - - # Check for valid JSON structure - if not isinstance(data, dict): - print(f"❌ {locale}.json root must be an object/dictionary") - success = False - continue - - # Check that required sections exist - required_sections = ['common', 'header', 'loras', 'recipes', 'modals'] - missing_sections = [] - for section in required_sections: - if section not in data: - missing_sections.append(section) - - if missing_sections: - print(f"❌ {locale}.json missing required sections: {', '.join(missing_sections)}") - success = False - - # Check for empty values - empty_values = [] - def check_empty_values(obj, path=''): - if isinstance(obj, dict): - for key, value in obj.items(): - current_path = f"{path}.{key}" if path else key - if isinstance(value, dict): - check_empty_values(value, current_path) - elif isinstance(value, str) and not value.strip(): - empty_values.append(current_path) - elif value is None: - empty_values.append(current_path) - - check_empty_values(data) - - if empty_values: - print(f"⚠️ {locale}.json has {len(empty_values)} empty translation values:") - for path in empty_values[:5]: # Show first 5 - print(f" - {path}") - if len(empty_values) > 5: - print(f" ... and {len(empty_values) - 5} more") - - print(f"✅ {locale}.json structure is valid") - - except json.JSONDecodeError as e: - print(f"❌ {locale}.json has invalid JSON syntax: {e}") - success = False - except Exception as e: - print(f"❌ Error validating {locale}.json: {e}") - success = False - - return success + if "." not in key and key not in SINGLE_WORD_TRANSLATION_KEYS: + continue + filtered.add(key) + return filtered -def test_json_files_are_valid(): - assert check_json_files_exist() +def extract_i18n_keys_from_js(file_path: Path) -> Set[str]: + """Extract translation keys from JavaScript sources.""" + content = file_path.read_text(encoding="utf-8") + # Remove single-line and multi-line comments to avoid false positives. + content = re.sub(r"//.*$", "", content, flags=re.MULTILINE) + content = re.sub(r"/\*.*?\*/", "", content, flags=re.DOTALL) + + matches: Set[str] = set() + for pattern in JS_TRANSLATION_PATTERNS: + matches.update(re.findall(pattern, content)) + return matches -def test_locale_structures_match_reference(): - assert check_locale_files_structural_consistency() +def extract_i18n_keys_from_html(file_path: Path) -> Set[str]: + """Extract translation keys from HTML templates.""" + content = file_path.read_text(encoding="utf-8") + content = re.sub(r"", "", content, flags=re.DOTALL) + + matches: Set[str] = set(re.findall(HTML_TRANSLATION_PATTERN, content)) + + # Inspect inline script tags as JavaScript. + for script_body in re.findall(r"]*>(.*?)", content, flags=re.DOTALL): + for pattern in JS_TRANSLATION_PATTERNS: + matches.update(re.findall(pattern, script_body)) + + return matches -def test_locale_formatting_matches_reference(): - assert check_locale_files_formatting_consistency() +@pytest.mark.parametrize("locale", EXPECTED_LOCALES) +def test_locale_files_have_expected_structure(locale: str, loaded_locales: Dict[str, dict]) -> None: + """Every locale must contain the required sections.""" + data = loaded_locales[locale] + missing_sections = sorted(REQUIRED_SECTIONS - data.keys()) + assert not missing_sections, f"{locale} locale is missing sections: {missing_sections}" -def test_locale_key_order_matches_reference(): - assert check_locale_key_ordering() +@pytest.mark.parametrize("locale", EXPECTED_LOCALES[1:]) +def test_locale_keys_match_english( + locale: str, loaded_locales: Dict[str, dict], english_translation_keys: Set[str] +) -> None: + """Locales must expose the same translation keys as English.""" + locale_keys = collect_translation_keys(loaded_locales[locale]) + + missing_keys = sorted(english_translation_keys - locale_keys) + extra_keys = sorted(locale_keys - english_translation_keys) + + assert not missing_keys, ( + f"{locale} is missing translation keys: {missing_keys[:10]}" + + ("..." if len(missing_keys) > 10 else "") + ) + assert not extra_keys, ( + f"{locale} defines unexpected translation keys: {extra_keys[:10]}" + + ("..." if len(extra_keys) > 10 else "") + ) -def test_server_side_i18n_behaves_as_expected(): - assert check_server_i18n() - - -def test_translations_are_complete(): - assert check_translation_completeness() - - -def test_static_code_analysis_is_clean(): - assert check_static_code_analysis() - - -def test_json_structure_validation(): - assert check_json_structure_validation() - - -def main(): - """Run all tests.""" - print("🚀 Testing updated i18n system...\n") - - success = True - - # Test JSON files structure and syntax - if not check_json_files_exist(): - success = False - - # Test comprehensive structural consistency - if not check_locale_files_structural_consistency(): - success = False - - # Test formatting consistency - if not check_locale_files_formatting_consistency(): - success = False - - # Test key ordering - if not check_locale_key_ordering(): - success = False - - # Test server i18n - if not check_server_i18n(): - success = False - - # Test translation completeness - if not check_translation_completeness(): - success = False - - # Test static code analysis - if not check_static_code_analysis(): - success = False - - print(f"\n{'🎉 All tests passed!' if success else '❌ Some tests failed!'}") - return success - -if __name__ == '__main__': - main() +def test_static_sources_only_use_existing_translations( + english_translation_keys: Set[str], static_code_translation_keys: Set[str] +) -> None: + """Static code must not reference unknown translation keys.""" + missing_keys = sorted(static_code_translation_keys - english_translation_keys) + assert not missing_keys, ( + "Static sources reference missing translation keys: " + f"{missing_keys[:20]}" + ("..." if len(missing_keys) > 20 else "") + ) From 095320ef72b2d92d6d3262d9dc1fc994272af7e1 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Thu, 25 Sep 2025 09:40:25 +0800 Subject: [PATCH 107/110] test(routes): tidy lora route test imports --- tests/routes/test_embedding_routes.py | 50 +++++ tests/routes/test_lora_routes.py | 213 +++++++++++++++++++ tests/services/test_civitai_client.py | 222 ++++++++++++++++++++ tests/services/test_download_manager.py | 247 +++++++++++++++++++++++ tests/services/test_settings_manager.py | 61 ++++++ tests/services/test_websocket_manager.py | 84 ++++++++ 6 files changed, 877 insertions(+) create mode 100644 tests/routes/test_embedding_routes.py create mode 100644 tests/routes/test_lora_routes.py create mode 100644 tests/services/test_civitai_client.py create mode 100644 tests/services/test_download_manager.py create mode 100644 tests/services/test_settings_manager.py create mode 100644 tests/services/test_websocket_manager.py diff --git a/tests/routes/test_embedding_routes.py b/tests/routes/test_embedding_routes.py new file mode 100644 index 00000000..fc1782a0 --- /dev/null +++ b/tests/routes/test_embedding_routes.py @@ -0,0 +1,50 @@ +import json + +import pytest + +from py.routes.embedding_routes import EmbeddingRoutes + + +class DummyRequest: + def __init__(self, *, match_info=None): + self.match_info = match_info or {} + + +class StubEmbeddingService: + def __init__(self): + self.info = {} + + async def get_model_info_by_name(self, name): + value = self.info.get(name) + if isinstance(value, Exception): + raise value + return value + + +@pytest.fixture +def routes(): + handler = EmbeddingRoutes() + handler.service = StubEmbeddingService() + return handler + + +async def test_get_embedding_info_success(routes): + routes.service.info["demo"] = {"name": "demo"} + response = await routes.get_embedding_info(DummyRequest(match_info={"name": "demo"})) + payload = json.loads(response.text) + assert payload == {"name": "demo"} + + +async def test_get_embedding_info_missing(routes): + response = await routes.get_embedding_info(DummyRequest(match_info={"name": "missing"})) + payload = json.loads(response.text) + assert response.status == 404 + assert payload == {"error": "Embedding not found"} + + +async def test_get_embedding_info_error(routes): + routes.service.info["demo"] = RuntimeError("boom") + response = await routes.get_embedding_info(DummyRequest(match_info={"name": "demo"})) + payload = json.loads(response.text) + assert response.status == 500 + assert payload == {"error": "boom"} diff --git a/tests/routes/test_lora_routes.py b/tests/routes/test_lora_routes.py new file mode 100644 index 00000000..2b447987 --- /dev/null +++ b/tests/routes/test_lora_routes.py @@ -0,0 +1,213 @@ +import json +from types import SimpleNamespace +from unittest.mock import MagicMock + +import pytest + +from py.routes.lora_routes import LoraRoutes +from server import PromptServer + + +class DummyRequest: + def __init__(self, *, query=None, match_info=None, json_data=None): + self.query = query or {} + self.match_info = match_info or {} + self._json_data = json_data or {} + + async def json(self): + return self._json_data + + +class StubLoraService: + def __init__(self): + self.notes = {} + self.trigger_words = {} + self.usage_tips = {} + self.previews = {} + self.civitai = {} + + async def get_lora_notes(self, name): + return self.notes.get(name) + + async def get_lora_trigger_words(self, name): + return self.trigger_words.get(name, []) + + async def get_lora_usage_tips_by_relative_path(self, path): + return self.usage_tips.get(path) + + async def get_lora_preview_url(self, name): + return self.previews.get(name) + + async def get_lora_civitai_url(self, name): + return self.civitai.get(name, {"civitai_url": ""}) + + +@pytest.fixture +def routes(): + handler = LoraRoutes() + handler.service = StubLoraService() + return handler + + +async def test_get_lora_notes_success(routes): + routes.service.notes["demo"] = "Great notes" + request = DummyRequest(query={"name": "demo"}) + + response = await routes.get_lora_notes(request) + payload = json.loads(response.text) + + assert payload == {"success": True, "notes": "Great notes"} + + +async def test_get_lora_notes_missing_name(routes): + response = await routes.get_lora_notes(DummyRequest()) + assert response.status == 400 + assert response.text == "Lora file name is required" + + +async def test_get_lora_notes_not_found(routes): + response = await routes.get_lora_notes(DummyRequest(query={"name": "missing"})) + payload = json.loads(response.text) + assert response.status == 404 + assert payload == {"success": False, "error": "LoRA not found in cache"} + + +async def test_get_lora_notes_error(routes, monkeypatch): + async def failing(*_args, **_kwargs): + raise RuntimeError("boom") + + routes.service.get_lora_notes = failing + + response = await routes.get_lora_notes(DummyRequest(query={"name": "demo"})) + payload = json.loads(response.text) + + assert response.status == 500 + assert payload["success"] is False + assert payload["error"] == "boom" + + +async def test_get_lora_trigger_words_success(routes): + routes.service.trigger_words["demo"] = ["trigger"] + response = await routes.get_lora_trigger_words(DummyRequest(query={"name": "demo"})) + payload = json.loads(response.text) + assert payload == {"success": True, "trigger_words": ["trigger"]} + + +async def test_get_lora_trigger_words_missing_name(routes): + response = await routes.get_lora_trigger_words(DummyRequest()) + assert response.status == 400 + + +async def test_get_lora_trigger_words_error(routes): + async def failing(*_args, **_kwargs): + raise RuntimeError("fail") + + routes.service.get_lora_trigger_words = failing + + response = await routes.get_lora_trigger_words(DummyRequest(query={"name": "demo"})) + payload = json.loads(response.text) + assert response.status == 500 + assert payload["success"] is False + + +async def test_get_usage_tips_success(routes): + routes.service.usage_tips["path"] = "tips" + response = await routes.get_lora_usage_tips_by_path(DummyRequest(query={"relative_path": "path"})) + payload = json.loads(response.text) + assert payload == {"success": True, "usage_tips": "tips"} + + +async def test_get_usage_tips_missing_param(routes): + response = await routes.get_lora_usage_tips_by_path(DummyRequest()) + assert response.status == 400 + + +async def test_get_usage_tips_error(routes): + async def failing(*_args, **_kwargs): + raise RuntimeError("bad") + + routes.service.get_lora_usage_tips_by_relative_path = failing + response = await routes.get_lora_usage_tips_by_path(DummyRequest(query={"relative_path": "path"})) + payload = json.loads(response.text) + assert response.status == 500 + assert payload["success"] is False + + +async def test_get_preview_url_success(routes): + routes.service.previews["demo"] = "http://preview" + response = await routes.get_lora_preview_url(DummyRequest(query={"name": "demo"})) + payload = json.loads(response.text) + assert payload == {"success": True, "preview_url": "http://preview"} + + +async def test_get_preview_url_missing(routes): + response = await routes.get_lora_preview_url(DummyRequest()) + assert response.status == 400 + + +async def test_get_preview_url_not_found(routes): + response = await routes.get_lora_preview_url(DummyRequest(query={"name": "missing"})) + payload = json.loads(response.text) + assert response.status == 404 + assert payload["success"] is False + + +async def test_get_civitai_url_success(routes): + routes.service.civitai["demo"] = {"civitai_url": "https://civitai.com"} + response = await routes.get_lora_civitai_url(DummyRequest(query={"name": "demo"})) + payload = json.loads(response.text) + assert payload == {"success": True, "civitai_url": "https://civitai.com"} + + +async def test_get_civitai_url_missing(routes): + response = await routes.get_lora_civitai_url(DummyRequest()) + assert response.status == 400 + + +async def test_get_civitai_url_not_found(routes): + response = await routes.get_lora_civitai_url(DummyRequest(query={"name": "missing"})) + payload = json.loads(response.text) + assert response.status == 404 + assert payload["success"] is False + + +async def test_get_civitai_url_error(routes): + async def failing(*_args, **_kwargs): + raise RuntimeError("oops") + + routes.service.get_lora_civitai_url = failing + response = await routes.get_lora_civitai_url(DummyRequest(query={"name": "demo"})) + payload = json.loads(response.text) + assert response.status == 500 + assert payload["success"] is False + + +async def test_get_trigger_words_broadcasts(monkeypatch, routes): + send_mock = MagicMock() + PromptServer.instance = SimpleNamespace(send_sync=send_mock) + + monkeypatch.setattr("py.routes.lora_routes.get_lora_info", lambda name: (f"path/{name}", [f"trigger-{name}"])) + + request = DummyRequest(json_data={"lora_names": ["one"], "node_ids": ["node"]}) + + response = await routes.get_trigger_words(request) + payload = json.loads(response.text) + + assert payload == {"success": True} + send_mock.assert_called_once_with( + "trigger_word_update", + {"id": "node", "message": "trigger-one"}, + ) + + +async def test_get_trigger_words_error(monkeypatch, routes): + async def failing_json(): + raise RuntimeError("bad json") + + request = DummyRequest(json_data=None) + request.json = failing_json + + response = await routes.get_trigger_words(request) + payload = json.loads(response.text) + assert response.status == 500 + assert payload["success"] is False diff --git a/tests/services/test_civitai_client.py b/tests/services/test_civitai_client.py new file mode 100644 index 00000000..f5283443 --- /dev/null +++ b/tests/services/test_civitai_client.py @@ -0,0 +1,222 @@ +from unittest.mock import AsyncMock + +import pytest + +from py.services import civitai_client as civitai_client_module +from py.services.civitai_client import CivitaiClient +from py.services.model_metadata_provider import ModelMetadataProviderManager + + +class DummyDownloader: + def __init__(self): + self.download_calls = [] + self.memory_calls = [] + self.request_calls = [] + + async def download_file(self, **kwargs): + self.download_calls.append(kwargs) + return True, kwargs["save_path"] + + async def download_to_memory(self, url, use_auth=False): + self.memory_calls.append({"url": url, "use_auth": use_auth}) + return True, b"bytes", {"content-type": "image/jpeg"} + + async def make_request(self, method, url, use_auth=True): + self.request_calls.append({"method": method, "url": url, "use_auth": use_auth}) + return True, {} + + +@pytest.fixture(autouse=True) +def reset_singletons(): + CivitaiClient._instance = None + ModelMetadataProviderManager._instance = None + yield + CivitaiClient._instance = None + ModelMetadataProviderManager._instance = None + + +@pytest.fixture +def downloader(monkeypatch): + instance = DummyDownloader() + monkeypatch.setattr(civitai_client_module, "get_downloader", AsyncMock(return_value=instance)) + return instance + + +async def test_download_file_uses_downloader(tmp_path, downloader): + client = await CivitaiClient.get_instance() + save_dir = tmp_path / "files" + save_dir.mkdir() + + success, path = await client.download_file( + url="https://example.invalid/model", + save_dir=str(save_dir), + default_filename="model.safetensors", + ) + + assert success is True + assert path == str(save_dir / "model.safetensors") + assert downloader.download_calls[0]["use_auth"] is True + + +async def test_get_model_by_hash_enriches_metadata(monkeypatch, downloader): + version_payload = { + "modelId": 123, + "model": {"description": "", "tags": []}, + "creator": {}, + } + model_payload = {"description": "desc", "tags": ["tag"], "creator": {"username": "user"}} + + async def fake_make_request(method, url, use_auth=True): + if url.endswith("by-hash/hash"): + return True, version_payload.copy() + if url.endswith("/models/123"): + return True, model_payload + return False, "unexpected" + + downloader.make_request = fake_make_request + + client = await CivitaiClient.get_instance() + + result, error = await client.get_model_by_hash("hash") + + assert error is None + assert result["model"]["description"] == "desc" + assert result["model"]["tags"] == ["tag"] + assert result["creator"] == {"username": "user"} + + +async def test_get_model_by_hash_handles_not_found(monkeypatch, downloader): + async def fake_make_request(method, url, use_auth=True): + return False, "not found" + + downloader.make_request = fake_make_request + + client = await CivitaiClient.get_instance() + + result, error = await client.get_model_by_hash("missing") + + assert result is None + assert error == "Model not found" + + +async def test_download_preview_image_writes_file(tmp_path, downloader): + client = await CivitaiClient.get_instance() + target = tmp_path / "preview" / "image.jpg" + + success = await client.download_preview_image("https://example.invalid/preview", str(target)) + + assert success is True + assert target.exists() + assert target.read_bytes() == b"bytes" + + +async def test_download_preview_image_failure(monkeypatch, downloader): + async def failing_download(url, use_auth=False): + return False, b"", {} + + downloader.download_to_memory = failing_download + + client = await CivitaiClient.get_instance() + target = "/tmp/ignored.jpg" + + success = await client.download_preview_image("https://example.invalid/preview", target) + + assert success is False + + +async def test_get_model_versions_success(monkeypatch, downloader): + async def fake_make_request(method, url, use_auth=True): + return True, {"modelVersions": [{"id": 1}], "type": "LORA", "name": "Model"} + + downloader.make_request = fake_make_request + + client = await CivitaiClient.get_instance() + + result = await client.get_model_versions("123") + + assert result == {"modelVersions": [{"id": 1}], "type": "LORA", "name": "Model"} + + +async def test_get_model_version_by_version_id(monkeypatch, downloader): + async def fake_make_request(method, url, use_auth=True): + if url.endswith("/model-versions/7"): + return True, { + "modelId": 321, + "model": {"description": ""}, + "files": [], + } + if url.endswith("/models/321"): + return True, {"description": "desc", "tags": ["tag"], "creator": {"username": "user"}} + return False, "unexpected" + + downloader.make_request = fake_make_request + + client = await CivitaiClient.get_instance() + + result = await client.get_model_version(version_id=7) + + assert result["model"]["description"] == "desc" + assert result["model"]["tags"] == ["tag"] + assert result["creator"] == {"username": "user"} + + +async def test_get_model_version_requires_identifier(monkeypatch, downloader): + client = await CivitaiClient.get_instance() + result = await client.get_model_version() + assert result is None + + +async def test_get_model_version_info_handles_not_found(monkeypatch, downloader): + async def fake_make_request(method, url, use_auth=True): + return False, "not found" + + downloader.make_request = fake_make_request + + client = await CivitaiClient.get_instance() + + result, error = await client.get_model_version_info("55") + + assert result is None + assert error == "Model not found" + + +async def test_get_model_version_info_success(monkeypatch, downloader): + expected = {"id": 55} + + async def fake_make_request(method, url, use_auth=True): + return True, expected + + downloader.make_request = fake_make_request + + client = await CivitaiClient.get_instance() + + result, error = await client.get_model_version_info("55") + + assert result == expected + assert error is None + + +async def test_get_image_info_returns_first_item(monkeypatch, downloader): + async def fake_make_request(method, url, use_auth=True): + return True, {"items": [{"id": 1}, {"id": 2}]} + + downloader.make_request = fake_make_request + + client = await CivitaiClient.get_instance() + + result = await client.get_image_info("42") + + assert result == {"id": 1} + + +async def test_get_image_info_handles_missing(monkeypatch, downloader): + async def fake_make_request(method, url, use_auth=True): + return True, {"items": []} + + downloader.make_request = fake_make_request + + client = await CivitaiClient.get_instance() + + result = await client.get_image_info("42") + + assert result is None diff --git a/tests/services/test_download_manager.py b/tests/services/test_download_manager.py new file mode 100644 index 00000000..80701e7d --- /dev/null +++ b/tests/services/test_download_manager.py @@ -0,0 +1,247 @@ +from pathlib import Path +from types import SimpleNamespace +from unittest.mock import AsyncMock + +import pytest + +from py.services.download_manager import DownloadManager +from py.services import download_manager +from py.services.service_registry import ServiceRegistry +from py.services.settings_manager import settings + + +@pytest.fixture(autouse=True) +def reset_download_manager(): + """Ensure each test operates on a fresh singleton.""" + DownloadManager._instance = None + yield + DownloadManager._instance = None + + +@pytest.fixture(autouse=True) +def isolate_settings(monkeypatch, tmp_path): + """Point settings writes at a temporary directory to avoid touching real files.""" + default_settings = settings._get_default_settings() + default_settings.update( + { + "default_lora_root": str(tmp_path), + "default_checkpoint_root": str(tmp_path / "checkpoints"), + "default_embedding_root": str(tmp_path / "embeddings"), + "download_path_templates": { + "lora": "{base_model}/{first_tag}", + "checkpoint": "{base_model}/{first_tag}", + "embedding": "{base_model}/{first_tag}", + }, + "base_model_path_mappings": {"BaseModel": "MappedModel"}, + } + ) + monkeypatch.setattr(settings, "settings", default_settings) + monkeypatch.setattr(type(settings), "_save_settings", lambda self: None) + + +@pytest.fixture(autouse=True) +def stub_metadata(monkeypatch): + class _StubMetadata: + def __init__(self, save_path: str): + self.file_path = save_path + self.sha256 = "sha256" + self.file_name = Path(save_path).stem + + def _factory(save_path: str): + return _StubMetadata(save_path) + + def _make_class(): + @staticmethod + def from_civitai_info(_version_info, _file_info, save_path): + return _factory(save_path) + + return type("StubMetadata", (), {"from_civitai_info": from_civitai_info}) + + stub_class = _make_class() + monkeypatch.setattr(download_manager, "LoraMetadata", stub_class) + monkeypatch.setattr(download_manager, "CheckpointMetadata", stub_class) + monkeypatch.setattr(download_manager, "EmbeddingMetadata", stub_class) + + +class DummyScanner: + def __init__(self, exists: bool = False): + self.exists = exists + self.calls = [] + + async def check_model_version_exists(self, version_id): + self.calls.append(version_id) + return self.exists + + +@pytest.fixture +def scanners(monkeypatch): + lora_scanner = DummyScanner() + checkpoint_scanner = DummyScanner() + embedding_scanner = DummyScanner() + + monkeypatch.setattr(ServiceRegistry, "get_lora_scanner", AsyncMock(return_value=lora_scanner)) + monkeypatch.setattr(ServiceRegistry, "get_checkpoint_scanner", AsyncMock(return_value=checkpoint_scanner)) + monkeypatch.setattr(ServiceRegistry, "get_embedding_scanner", AsyncMock(return_value=embedding_scanner)) + + return SimpleNamespace( + lora=lora_scanner, + checkpoint=checkpoint_scanner, + embedding=embedding_scanner, + ) + + +@pytest.fixture +def metadata_provider(monkeypatch): + class DummyProvider: + def __init__(self): + self.calls = [] + + async def get_model_version(self, model_id, model_version_id): + self.calls.append((model_id, model_version_id)) + return { + "id": 42, + "model": {"type": "LoRA", "tags": ["fantasy"]}, + "baseModel": "BaseModel", + "creator": {"username": "Author"}, + "files": [ + { + "primary": True, + "downloadUrl": "https://example.invalid/file.safetensors", + "name": "file.safetensors", + } + ], + } + + provider = DummyProvider() + monkeypatch.setattr( + download_manager, + "get_default_metadata_provider", + AsyncMock(return_value=provider), + ) + return provider + + +@pytest.fixture(autouse=True) +def noop_cleanup(monkeypatch): + async def _cleanup(self, task_id): + if task_id in self._active_downloads: + self._active_downloads[task_id]["cleaned"] = True + + monkeypatch.setattr(DownloadManager, "_cleanup_download_record", _cleanup) + + +async def test_download_requires_identifier(): + manager = DownloadManager() + result = await manager.download_from_civitai() + assert result == { + "success": False, + "error": "Either model_id or model_version_id must be provided", + } + + +async def test_successful_download_uses_defaults(monkeypatch, scanners, metadata_provider, tmp_path): + manager = DownloadManager() + + captured = {} + + async def fake_execute_download( + self, + *, + download_url, + save_dir, + metadata, + version_info, + relative_path, + progress_callback, + model_type, + download_id, + ): + captured.update( + { + "download_url": download_url, + "save_dir": Path(save_dir), + "relative_path": relative_path, + "progress_callback": progress_callback, + "model_type": model_type, + "download_id": download_id, + "metadata_path": metadata.file_path, + } + ) + return {"success": True} + + monkeypatch.setattr(DownloadManager, "_execute_download", fake_execute_download, raising=False) + + result = await manager.download_from_civitai( + model_version_id=99, + save_dir=str(tmp_path), + use_default_paths=True, + progress_callback=None, + source=None, + ) + + assert result["success"] is True + assert "download_id" in result + assert manager._download_tasks == {} + assert manager._active_downloads[result["download_id"]]["status"] == "completed" + + assert captured["relative_path"] == "MappedModel/fantasy" + expected_dir = Path(settings.get("default_lora_root")) / "MappedModel" / "fantasy" + assert captured["save_dir"] == expected_dir + assert captured["model_type"] == "lora" + + +async def test_download_aborts_when_version_exists(monkeypatch, scanners, metadata_provider): + scanners.lora.exists = True + + manager = DownloadManager() + + execute_mock = AsyncMock(return_value={"success": True}) + monkeypatch.setattr(DownloadManager, "_execute_download", execute_mock) + + result = await manager.download_from_civitai(model_version_id=101, save_dir="/tmp") + + assert result["success"] is False + assert result["error"] == "Model version already exists in lora library" + assert "download_id" in result + assert execute_mock.await_count == 0 + + +async def test_download_handles_metadata_errors(monkeypatch, scanners): + async def failing_provider(*_args, **_kwargs): + return None + + monkeypatch.setattr( + download_manager, + "get_default_metadata_provider", + AsyncMock(return_value=SimpleNamespace(get_model_version=AsyncMock(return_value=None))), + ) + + manager = DownloadManager() + + result = await manager.download_from_civitai(model_version_id=5, save_dir="/tmp") + + assert result["success"] is False + assert result["error"] == "Failed to fetch model metadata" + assert "download_id" in result + + +async def test_download_rejects_unsupported_model_type(monkeypatch, scanners): + class Provider: + async def get_model_version(self, *_args, **_kwargs): + return { + "model": {"type": "Unsupported", "tags": []}, + "files": [], + } + + monkeypatch.setattr( + download_manager, + "get_default_metadata_provider", + AsyncMock(return_value=Provider()), + ) + + manager = DownloadManager() + + result = await manager.download_from_civitai(model_version_id=5, save_dir="/tmp") + + assert result["success"] is False + assert result["error"].startswith("Model type") diff --git a/tests/services/test_settings_manager.py b/tests/services/test_settings_manager.py new file mode 100644 index 00000000..7e547680 --- /dev/null +++ b/tests/services/test_settings_manager.py @@ -0,0 +1,61 @@ +import json + +import pytest + +from py.services.settings_manager import SettingsManager + + +@pytest.fixture +def manager(tmp_path, monkeypatch): + monkeypatch.setattr(SettingsManager, "_save_settings", lambda self: None) + mgr = SettingsManager() + mgr.settings_file = str(tmp_path / "settings.json") + return mgr + + +def test_environment_variable_overrides_settings(tmp_path, monkeypatch): + monkeypatch.setattr(SettingsManager, "_save_settings", lambda self: None) + monkeypatch.setenv("CIVITAI_API_KEY", "secret") + mgr = SettingsManager() + mgr.settings_file = str(tmp_path / "settings.json") + + assert mgr.get("civitai_api_key") == "secret" + + +def test_download_path_template_parses_json_string(manager): + templates = {"lora": "{author}", "checkpoint": "{author}", "embedding": "{author}"} + manager.settings["download_path_templates"] = json.dumps(templates) + + template = manager.get_download_path_template("lora") + + assert template == "{author}" + assert isinstance(manager.settings["download_path_templates"], dict) + + +def test_download_path_template_invalid_json(manager): + manager.settings["download_path_templates"] = "not json" + + template = manager.get_download_path_template("checkpoint") + + assert template == "{base_model}/{first_tag}" + assert manager.settings["download_path_templates"]["lora"] == "{base_model}/{first_tag}" + + +def test_auto_set_default_roots(manager): + manager.settings["folder_paths"] = { + "loras": ["/loras"], + "checkpoints": ["/checkpoints"], + "embeddings": ["/embeddings"], + } + + manager._auto_set_default_roots() + + assert manager.get("default_lora_root") == "/loras" + assert manager.get("default_checkpoint_root") == "/checkpoints" + assert manager.get("default_embedding_root") == "/embeddings" + + +def test_delete_setting(manager): + manager.set("example", 1) + manager.delete("example") + assert manager.get("example") is None diff --git a/tests/services/test_websocket_manager.py b/tests/services/test_websocket_manager.py new file mode 100644 index 00000000..b85c2197 --- /dev/null +++ b/tests/services/test_websocket_manager.py @@ -0,0 +1,84 @@ +from datetime import datetime, timedelta + +import pytest + +from py.services.websocket_manager import WebSocketManager + + +class DummyWebSocket: + def __init__(self): + self.messages = [] + self.closed = False + + async def send_json(self, data): + if self.closed: + raise RuntimeError("WebSocket closed") + self.messages.append(data) + + +@pytest.fixture +def manager(): + return WebSocketManager() + + +async def test_broadcast_init_progress_adds_defaults(manager): + ws = DummyWebSocket() + manager._init_websockets.add(ws) + + await manager.broadcast_init_progress({}) + + assert ws.messages == [ + { + "stage": "processing", + "progress": 0, + "details": "Processing...", + } + ] + + +async def test_broadcast_download_progress_tracks_state(manager): + ws = DummyWebSocket() + download_id = "abc" + manager._download_websockets[download_id] = ws + + await manager.broadcast_download_progress(download_id, {"progress": 55}) + + assert ws.messages == [{"progress": 55}] + assert manager.get_download_progress(download_id)["progress"] == 55 + + +async def test_broadcast_download_progress_missing_socket(manager): + await manager.broadcast_download_progress("missing", {"progress": 30}) + # Progress should be stored even without a live websocket + assert manager.get_download_progress("missing")["progress"] == 30 + + +async def test_auto_organize_progress_helpers(manager): + payload = {"status": "processing", "progress": 10} + await manager.broadcast_auto_organize_progress(payload) + + assert manager.get_auto_organize_progress() == payload + assert manager.is_auto_organize_running() is True + + manager.cleanup_auto_organize_progress() + assert manager.get_auto_organize_progress() is None + assert manager.is_auto_organize_running() is False + + +def test_cleanup_old_downloads(manager): + now = datetime.now() + manager._download_progress = { + "recent": {"progress": 10, "timestamp": now}, + "stale": {"progress": 100, "timestamp": now - timedelta(hours=48)}, + } + + manager.cleanup_old_downloads(max_age_hours=24) + + assert "stale" not in manager._download_progress + assert "recent" in manager._download_progress + + +def test_generate_download_id(manager): + download_id = manager.generate_download_id() + assert isinstance(download_id, str) + assert download_id From 6c3424029c17fd5f252f00aa0a03aa294206fd9a Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Thu, 25 Sep 2025 10:43:10 +0800 Subject: [PATCH 108/110] fix(recipe image): optimize image saving and update PNG metadata handling, fixes #481 --- py/services/recipes/persistence_service.py | 11 +++++++++-- py/utils/exif_utils.py | 9 +++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/py/services/recipes/persistence_service.py b/py/services/recipes/persistence_service.py index 078ac906..175f046c 100644 --- a/py/services/recipes/persistence_service.py +++ b/py/services/recipes/persistence_service.py @@ -279,10 +279,17 @@ class RecipePersistenceService: os.makedirs(recipes_dir, exist_ok=True) recipe_id = str(uuid.uuid4()) - image_filename = f"{recipe_id}.png" + optimized_image, extension = self._exif_utils.optimize_image( + image_data=image_bytes, + target_width=self._card_preview_width, + format="webp", + quality=85, + preserve_metadata=True, + ) + image_filename = f"{recipe_id}{extension}" image_path = os.path.join(recipes_dir, image_filename) with open(image_path, "wb") as file_obj: - file_obj.write(image_bytes) + file_obj.write(optimized_image) lora_stack = metadata.get("loras", "") lora_matches = re.findall(r"]+)>", lora_stack) diff --git a/py/utils/exif_utils.py b/py/utils/exif_utils.py index 1c5a9f80..ff96703c 100644 --- a/py/utils/exif_utils.py +++ b/py/utils/exif_utils.py @@ -4,7 +4,7 @@ import logging from typing import Optional from io import BytesIO import os -from PIL import Image +from PIL import Image, PngImagePlugin logger = logging.getLogger(__name__) @@ -86,9 +86,10 @@ class ExifUtils: # For PNG, try to update parameters directly if img_format == 'PNG': - # We'll save with parameters in the PNG info - info_dict = {'parameters': metadata} - img.save(image_path, format='PNG', pnginfo=info_dict) + # Use PngInfo instead of plain dictionary + png_info = PngImagePlugin.PngInfo() + png_info.add_text("parameters", metadata) + img.save(image_path, format='PNG', pnginfo=png_info) return image_path # For WebP format, use PIL's exif parameter directly From da52e5b9dd0ff16228f266397f6643858a059de4 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Thu, 25 Sep 2025 10:56:09 +0800 Subject: [PATCH 109/110] fix(settings): improve logic for auto-setting default root paths based on folder presence --- py/services/settings_manager.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/py/services/settings_manager.py b/py/services/settings_manager.py index 1db42eb7..795c6da0 100644 --- a/py/services/settings_manager.py +++ b/py/services/settings_manager.py @@ -111,24 +111,30 @@ class SettingsManager: logger.info("Migration completed") def _auto_set_default_roots(self): - """Auto set default root paths if only one folder is present and default is empty.""" + """Auto set default root paths when only one folder is present and the current default is unset or not among the options.""" folder_paths = self.settings.get('folder_paths', {}) updated = False # loras loras = folder_paths.get('loras', []) - if isinstance(loras, list) and len(loras) == 1 and not self.settings.get('default_lora_root'): - self.settings['default_lora_root'] = loras[0] - updated = True + if isinstance(loras, list) and len(loras) == 1: + current_lora_root = self.settings.get('default_lora_root') + if current_lora_root not in loras: + self.settings['default_lora_root'] = loras[0] + updated = True # checkpoints checkpoints = folder_paths.get('checkpoints', []) - if isinstance(checkpoints, list) and len(checkpoints) == 1 and not self.settings.get('default_checkpoint_root'): - self.settings['default_checkpoint_root'] = checkpoints[0] - updated = True + if isinstance(checkpoints, list) and len(checkpoints) == 1: + current_checkpoint_root = self.settings.get('default_checkpoint_root') + if current_checkpoint_root not in checkpoints: + self.settings['default_checkpoint_root'] = checkpoints[0] + updated = True # embeddings embeddings = folder_paths.get('embeddings', []) - if isinstance(embeddings, list) and len(embeddings) == 1 and not self.settings.get('default_embedding_root'): - self.settings['default_embedding_root'] = embeddings[0] - updated = True + if isinstance(embeddings, list) and len(embeddings) == 1: + current_embedding_root = self.settings.get('default_embedding_root') + if current_embedding_root not in embeddings: + self.settings['default_embedding_root'] = embeddings[0] + updated = True if updated: self._save_settings() From 23679ec3f5933fefada76e444abb2258a620783b Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Thu, 25 Sep 2025 14:17:45 +0800 Subject: [PATCH 110/110] chore(tests): clean integration route header --- tests/routes/test_route_integration.py | 160 +++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 tests/routes/test_route_integration.py diff --git a/tests/routes/test_route_integration.py b/tests/routes/test_route_integration.py new file mode 100644 index 00000000..dc0a1261 --- /dev/null +++ b/tests/routes/test_route_integration.py @@ -0,0 +1,160 @@ +"""End-to-end integration tests for aiohttp route registrars.""" + +from __future__ import annotations + +import asyncio +from contextlib import asynccontextmanager +from types import SimpleNamespace +from typing import AsyncIterator, Dict, Iterable, List, Sequence + +from aiohttp import web +from aiohttp.test_utils import TestClient, TestServer + +from py.routes.lora_routes import LoraRoutes +from py.services.service_registry import ServiceRegistry +from py.services.websocket_manager import ws_manager as global_ws_manager + + +class IntegrationCache: + """Minimal cache implementation satisfying the service contract.""" + + def __init__(self, items: Sequence[Dict[str, object]]) -> None: + self.raw_data: List[Dict[str, object]] = [dict(item) for item in items] + self.folders: List[str] = ["/"] + + async def get_sorted_data(self, *_: object, **__: object) -> List[Dict[str, object]]: + """Return cached data without additional sorting.""" + return [dict(item) for item in self.raw_data] + + async def resort(self) -> None: + """Resort is a no-op for the static fixture data.""" + return None + + +class IntegrationScanner: + """Scanner double that registers with ServiceRegistry expectations.""" + + def __init__(self, items: Iterable[Dict[str, object]]) -> None: + self.model_type = "lora" + self._cache = IntegrationCache(list(items)) + self._hash_index = SimpleNamespace( + removed_paths=[], + remove_by_path=lambda path: self._hash_index.removed_paths.append(path), + get_duplicate_hashes=lambda: {}, + get_duplicate_filenames=lambda: {}, + ) + self._tags_count: Dict[str, int] = {} + self._excluded_models: List[str] = [] + + async def get_cached_data(self, *_: object, **__: object) -> IntegrationCache: + return self._cache + + def get_model_roots(self) -> List[str]: # pragma: no cover - documented surface + return ["/"] + + async def bulk_delete_models(self, file_paths: Iterable[str]) -> Dict[str, object]: + existing_paths = {item["file_path"] for item in self._cache.raw_data} + deleted = [path for path in file_paths if path in existing_paths] + self._cache.raw_data = [ + item for item in self._cache.raw_data if item["file_path"] not in deleted + ] + await self._cache.resort() + for path in deleted: + self._hash_index.remove_by_path(path) + return {"success": True, "deleted": deleted} + + async def check_model_version_exists(self, *_: object, **__: object) -> bool: + return False + + +@asynccontextmanager +async def aiohttp_client(app: web.Application) -> AsyncIterator[TestClient]: + """Spin up a TestClient with lifecycle management.""" + + server = TestServer(app) + client = TestClient(server) + await client.start_server() + try: + yield client + finally: + await client.close() + + +def test_lora_route_stack_returns_real_data(): + """Spin up LoRA routes and ensure ServiceRegistry-powered wiring succeeds.""" + + async def scenario() -> None: + ServiceRegistry.clear_services() + + fixture_item = { + "model_name": "Alpha", + "file_name": "alpha.safetensors", + "folder": "root", + "file_path": "/tmp/alpha.safetensors", + "size": 128, + "modified": "2024-01-01T00:00:00Z", + "tags": ["integration"], + "civitai": {"trainedWords": ["alpha"]}, + "preview_url": "", + "preview_nsfw_level": 0, + "base_model": "SD1", + "usage_tips": "Use gently", + "notes": "Integration sample", + "from_civitai": True, + } + scanner = IntegrationScanner([fixture_item]) + await ServiceRegistry.register_service("lora_scanner", scanner) + + app = web.Application() + routes = LoraRoutes() + routes.setup_routes(app) + + async with aiohttp_client(app) as client: + response = await client.get("/api/lm/loras/list") + payload = await response.json() + + assert response.status == 200 + assert payload["total"] == 1 + returned = payload["items"][0] + assert returned["model_name"] == "Alpha" + assert returned["file_name"] == "alpha.safetensors" + assert returned["usage_tips"] == "Use gently" + + asyncio.run(scenario()) + ServiceRegistry.clear_services() + + +def test_websocket_routes_broadcast_through_registry(): + """Ensure websocket endpoints accept connections and relay broadcasts.""" + + async def scenario() -> None: + ServiceRegistry.clear_services() + ws_manager = await ServiceRegistry.get_websocket_manager() + + app = web.Application() + app.router.add_get("/ws/fetch-progress", ws_manager.handle_connection) + app.router.add_get("/ws/download-progress", ws_manager.handle_download_connection) + + async with aiohttp_client(app) as client: + fetch_ws = await client.ws_connect("/ws/fetch-progress") + await ws_manager.broadcast({"kind": "ping"}) + message = await asyncio.wait_for(fetch_ws.receive_json(), timeout=1) + assert message == {"kind": "ping"} + + download_ws = await client.ws_connect("/ws/download-progress?id=session-1") + greeting = await asyncio.wait_for(download_ws.receive_json(), timeout=1) + assert greeting["type"] == "download_id" + assert greeting["download_id"] == "session-1" + + await ws_manager.broadcast_download_progress("session-1", {"progress": 55}) + progress = await asyncio.wait_for(download_ws.receive_json(), timeout=1) + assert progress["progress"] == 55 + + await fetch_ws.close() + await download_ws.close() + + # Ensure the registry cached instance matches the module-level singleton. + assert ws_manager is global_ws_manager + + asyncio.run(scenario()) + ServiceRegistry.clear_services()