Spaces:
Running
Running
| #!/usr/bin/env python3 | |
| """ | |
| Environment Variable Debugging Helper | |
| This script helps you debug environment variable initialization issues. | |
| """ | |
| import os | |
| import sys | |
| import json | |
| from typing import Set | |
| def _mask_value(name: str, value: str) -> str: | |
| """Mask secrets for display while preserving basic diagnostics.""" | |
| if any(tok in name.upper() for tok in ["KEY", "TOKEN", "SECRET", "PASSWORD"]): | |
| return f"<REDACTED> ({len(str(value))} chars)" | |
| return str(value) | |
| def print_env_var_status(): | |
| """Print the current status of all critical environment variables.""" | |
| print("π Current Environment Variable Status:") | |
| print("=" * 60) | |
| # Critical environment variables that should always be set | |
| critical_env_vars = { | |
| # Glossary-related | |
| 'GLOSSARY_SYSTEM_PROMPT': 'Manual glossary extraction prompt', | |
| 'AUTO_GLOSSARY_PROMPT': 'Auto glossary generation prompt', | |
| 'GLOSSARY_CUSTOM_ENTRY_TYPES': 'Custom entry types configuration (JSON)', | |
| 'GLOSSARY_DISABLE_HONORIFICS_FILTER': 'Honorifics filter disable flag', | |
| 'GLOSSARY_STRIP_HONORIFICS': 'Strip honorifics flag', | |
| 'GLOSSARY_FUZZY_THRESHOLD': 'Fuzzy matching threshold', | |
| 'GLOSSARY_USE_LEGACY_CSV': 'Legacy CSV format flag', | |
| 'GLOSSARY_CHAPTER_SPLIT_THRESHOLD': 'Chapter split threshold for large texts', | |
| 'GLOSSARY_MAX_SENTENCES': 'Maximum sentences for glossary processing', | |
| # OpenRouter settings | |
| 'OPENROUTER_USE_HTTP_ONLY': 'OpenRouter HTTP-only transport', | |
| 'OPENROUTER_ACCEPT_IDENTITY': 'OpenRouter identity encoding', | |
| 'OPENROUTER_PREFERRED_PROVIDER': 'OpenRouter preferred provider', | |
| # General application settings | |
| 'EXTRACTION_WORKERS': 'Number of extraction worker threads', | |
| 'ENABLE_GUI_YIELD': 'GUI yield during processing', | |
| 'RETAIN_SOURCE_EXTENSION': 'Retain source file extension', | |
| } | |
| # Optional environment variables | |
| optional_env_vars = { | |
| 'GLOSSARY_CUSTOM_FIELDS': 'Custom glossary fields (JSON)', | |
| 'GLOSSARY_TRANSLATION_PROMPT': 'Glossary translation prompt', | |
| 'GLOSSARY_FORMAT_INSTRUCTIONS': 'Glossary formatting instructions', | |
| } | |
| # Manga-related environment variables (Settings Dialog + Integration) | |
| manga_env_vars = { | |
| 'MANGA_FULL_PAGE_CONTEXT': 'Enable full page context translation', | |
| 'MANGA_VISUAL_CONTEXT_ENABLED': 'Include page image in requests', | |
| 'MANGA_CREATE_SUBFOLDER': "Create 'translated' subfolder for output", | |
| 'MANGA_BG_OPACITY': 'Background opacity (0-255)', | |
| 'MANGA_BG_STYLE': 'Background style (box/circle/wrap)', | |
| 'MANGA_BG_REDUCTION': 'Background reduction factor', | |
| 'MANGA_FONT_SIZE': 'Fixed font size (0=auto)', | |
| 'MANGA_FONT_STYLE': 'Font style name', | |
| 'MANGA_FONT_PATH': 'Selected font path', | |
| 'MANGA_FONT_SIZE_MODE': 'Font size mode (fixed/multiplier)', | |
| 'MANGA_FONT_SIZE_MULTIPLIER': 'Font size multiplier (for multiplier mode)', | |
| 'MANGA_MAX_FONT_SIZE': 'Maximum font size', | |
| 'MANGA_AUTO_MIN_SIZE': 'Automatic minimum readable font size', | |
| 'MANGA_FREE_TEXT_ONLY_BG_OPACITY': 'Apply BG opacity only to free text', | |
| 'MANGA_FORCE_CAPS_LOCK': 'Force caps lock', | |
| 'MANGA_STRICT_TEXT_WRAPPING': 'Strict text wrapping (force fit)', | |
| 'MANGA_CONSTRAIN_TO_BUBBLE': 'Constrain text to bubble bounds', | |
| 'MANGA_TEXT_COLOR': 'Text color RGB (R,G,B)', | |
| 'MANGA_SHADOW_ENABLED': 'Shadow enabled', | |
| 'MANGA_SHADOW_COLOR': 'Shadow color RGB (R,G,B)', | |
| 'MANGA_SHADOW_OFFSET_X': 'Shadow offset X', | |
| 'MANGA_SHADOW_OFFSET_Y': 'Shadow offset Y', | |
| 'MANGA_SHADOW_BLUR': 'Shadow blur radius', | |
| 'MANGA_SKIP_INPAINTING': 'Skip inpainting', | |
| 'MANGA_INPAINT_QUALITY': 'Inpainting quality preset', | |
| 'MANGA_INPAINT_DILATION': 'Inpainting dilation (px)', | |
| 'MANGA_INPAINT_PASSES': 'Inpainting passes', | |
| 'MANGA_INPAINT_METHOD': 'Inpainting method (local/cloud/hybrid/skip)', | |
| 'MANGA_LOCAL_INPAINT_METHOD': 'Local inpainting model type', | |
| 'MANGA_FONT_ALGORITHM': 'Font sizing algorithm preset', | |
| 'MANGA_PREFER_LARGER': 'Prefer larger font sizing', | |
| 'MANGA_BUBBLE_SIZE_FACTOR': 'Use bubble size factor for sizing', | |
| 'MANGA_LINE_SPACING': 'Line spacing multiplier', | |
| 'MANGA_MAX_LINES': 'Maximum lines per bubble', | |
| 'MANGA_QWEN2VL_MODEL_SIZE': 'Qwen2-VL model size selection', | |
| 'MANGA_RAPIDOCR_USE_RECOGNITION': 'RapidOCR: use recognition step', | |
| 'MANGA_RAPIDOCR_LANGUAGE': 'RapidOCR detection language', | |
| 'MANGA_RAPIDOCR_DETECTION_MODE': 'RapidOCR detection mode', | |
| 'MANGA_FULL_PAGE_CONTEXT_PROMPT_LEN': 'Length of full page context prompt', | |
| 'MANGA_OCR_PROMPT_LEN': 'Length of OCR system prompt', | |
| } | |
| missing_critical = set() | |
| empty_critical = set() | |
| set_critical = set() | |
| print("\nπ CRITICAL ENVIRONMENT VARIABLES:") | |
| print("-" * 40) | |
| all_critical = set(critical_env_vars.keys()) | |
| for var_name, description in critical_env_vars.items(): | |
| value = os.environ.get(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β MISSING: {var_name}") | |
| print(f" Description: {description}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ EMPTY: {var_name}") | |
| print(f" Description: {description}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = str(value)[:80] + ('...' if len(str(value)) > 80 else '') | |
| print(f"β {var_name}: {value_preview}") | |
| print(f"\nπ OPTIONAL ENVIRONMENT VARIABLES:") | |
| print("-" * 40) | |
| for var_name, description in optional_env_vars.items(): | |
| value = os.environ.get(var_name) | |
| if value is None: | |
| print(f"π Not set: {var_name}") | |
| elif not value.strip(): | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| value_preview = str(value)[:80] + ('...' if len(str(value)) > 80 else '') | |
| print(f"π {var_name}: {value_preview}") | |
| known_vars: Set[str] = set() | |
| # Manga section | |
| print(f"\nπ MANGA ENVIRONMENT VARIABLES:") | |
| print("-" * 40) | |
| manga_set = 0 | |
| for var_name, description in manga_env_vars.items(): | |
| known_vars.add(var_name) | |
| value = os.environ.get(var_name) | |
| all_critical.add(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β Not set: {var_name}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = str(value)[:80] + ('...' if len(str(value)) > 80 else '') | |
| print(f"β {var_name}: {value_preview}") | |
| manga_set += 1 | |
| # Rolling summary variables | |
| rolling_vars = { | |
| 'USE_ROLLING_SUMMARY': 'Enable rolling summary', | |
| 'SUMMARY_ROLE': 'Summary injection (user/system/both)', | |
| 'ROLLING_SUMMARY_EXCHANGES': 'Max exchanges before roll', | |
| 'ROLLING_SUMMARY_MODE': 'Rolling mode (append/replace)', | |
| 'ROLLING_SUMMARY_SYSTEM_PROMPT': 'System prompt for rolling summary', | |
| 'ROLLING_SUMMARY_USER_PROMPT': 'User prompt template for rolling summary', | |
| 'ROLLING_SUMMARY_MAX_ENTRIES': 'Max retained summaries in append mode', | |
| } | |
| print(f"\nπ§Ύ ROLLING SUMMARY VARIABLES:") | |
| print("-" * 40) | |
| rolling_set = 0 | |
| for var_name, description in rolling_vars.items(): | |
| known_vars.add(var_name) | |
| value = os.environ.get(var_name) | |
| all_critical.add(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β Not set: {var_name}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = str(value)[:80] + ('...' if len(str(value)) > 80 else '') | |
| print(f"β {var_name}: {value_preview}") | |
| rolling_set += 1 | |
| # Retry and network variables | |
| retry_net_vars = { | |
| 'RETRY_TRUNCATED': 'Retry truncated responses', | |
| 'MAX_RETRY_TOKENS': 'Max tokens for retry budget', | |
| 'RETRY_DUPLICATE_BODIES': 'Retry duplicate outputs', | |
| 'DUPLICATE_LOOKBACK_CHAPTERS': 'Duplicate lookback chapters', | |
| 'RETRY_TIMEOUT': 'Enable retry on timeouts', | |
| 'CHUNK_TIMEOUT': 'Per-chunk timeout (sec)', | |
| 'ENABLE_HTTP_TUNING': 'Enable HTTP tuning', | |
| 'CONNECT_TIMEOUT': 'Connect timeout (sec)', | |
| 'READ_TIMEOUT': 'Read timeout (sec)', | |
| 'HTTP_POOL_CONNECTIONS': 'HTTP pool connections', | |
| 'HTTP_POOL_MAXSIZE': 'HTTP pool maxsize', | |
| 'IGNORE_RETRY_AFTER': 'Ignore Retry-After header', | |
| 'MAX_RETRIES': 'Max retries', | |
| } | |
| print(f"\nπ RETRY/NETWORK VARIABLES:") | |
| print("-" * 40) | |
| retry_set = 0 | |
| for var_name, description in retry_net_vars.items(): | |
| known_vars.add(var_name) | |
| value = os.environ.get(var_name) | |
| all_critical.add(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β Not set: {var_name}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = str(value)[:80] + ('...' if len(str(value)) > 80 else '') | |
| print(f"β {var_name}: {value_preview}") | |
| retry_set += 1 | |
| # QA/meta variables | |
| qa_meta_vars = { | |
| 'QA_AUTO_SEARCH_OUTPUT': 'QA auto-search output folder', | |
| 'INDEFINITE_RATE_LIMIT_RETRY': 'Indefinite rate limit retries', | |
| 'REINFORCEMENT_FREQUENCY': 'Prompt reinforcement frequency', | |
| 'SCAN_PHASE_ENABLED': 'Enable post-translation scanning phase', | |
| 'SCAN_PHASE_MODE': 'Scanning mode (quick-scan/aggressive/ai-hunter/custom)', | |
| } | |
| print(f"\nπ§ͺ QA/META VARIABLES:") | |
| print("-" * 40) | |
| qa_set = 0 | |
| for var_name, description in qa_meta_vars.items(): | |
| known_vars.add(var_name) | |
| value = os.environ.get(var_name) | |
| all_critical.add(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β Not set: {var_name}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = str(value)[:80] + ('...' if len(str(value)) > 80 else '') | |
| print(f"β {var_name}: {value_preview}") | |
| qa_set += 1 | |
| # Book title variables | |
| book_vars = { | |
| 'TRANSLATE_BOOK_TITLE': 'Translate book title', | |
| 'BOOK_TITLE_PROMPT': 'Book title prompt', | |
| } | |
| print(f"\nπ BOOK TITLE VARIABLES:") | |
| print("-" * 40) | |
| book_set = 0 | |
| for var_name, description in book_vars.items(): | |
| known_vars.add(var_name) | |
| value = os.environ.get(var_name) | |
| all_critical.add(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β Not set: {var_name}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = str(value)[:80] + ('...' if len(str(value)) > 80 else '') | |
| print(f"β {var_name}: {value_preview}") | |
| book_set += 1 | |
| # Image translation/EPUB variables | |
| image_vars = { | |
| 'ENABLE_IMAGE_TRANSLATION': 'Enable image translation', | |
| 'PROCESS_WEBNOVEL_IMAGES': 'Process images from HTML', | |
| 'WEBNOVEL_MIN_HEIGHT': 'Minimum image height', | |
| 'MAX_IMAGES_PER_CHAPTER': 'Max images per chapter', | |
| 'IMAGE_CHUNK_HEIGHT': 'Image chunk height', | |
| 'HIDE_IMAGE_TRANSLATION_LABEL': 'Hide image translation label', | |
| 'DISABLE_EPUB_GALLERY': 'Disable EPUB gallery', | |
| 'DISABLE_AUTOMATIC_COVER_CREATION': 'Disable automatic cover creation', | |
| 'TRANSLATE_COVER_HTML': 'Translate cover.html', | |
| 'DISABLE_ZERO_DETECTION': 'Disable zero detection', | |
| 'DUPLICATE_DETECTION_MODE': 'Duplicate detection mode', | |
| 'ENABLE_DECIMAL_CHAPTERS': 'Enable decimal chapter numbers', | |
| } | |
| print(f"\nπΌοΈ IMAGE/EPUB VARIABLES:") | |
| print("-" * 40) | |
| image_set = 0 | |
| for var_name, description in image_vars.items(): | |
| known_vars.add(var_name) | |
| value = os.environ.get(var_name) | |
| all_critical.add(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β Not set: {var_name}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = str(value)[:80] + ('...' if len(str(value)) > 80 else '') | |
| print(f"β {var_name}: {value_preview}") | |
| image_set += 1 | |
| # Watermark/image cleaning | |
| watermark_vars = { | |
| 'ENABLE_WATERMARK_REMOVAL': 'Enable watermark removal', | |
| 'SAVE_CLEANED_IMAGES': 'Save cleaned images', | |
| } | |
| print(f"\nπ§ IMAGE CLEANING VARIABLES:") | |
| print("-" * 40) | |
| watermark_set = 0 | |
| for var_name, description in watermark_vars.items(): | |
| known_vars.add(var_name) | |
| value = os.environ.get(var_name) | |
| all_critical.add(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β Not set: {var_name}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = str(value)[:80] + ('...' if len(str(value)) > 80 else '') | |
| print(f"β {var_name}: {value_preview}") | |
| watermark_set += 1 | |
| # Prompts and safety | |
| prompt_vars = { | |
| 'TRANSLATION_CHUNK_PROMPT': 'Translation chunk prompt', | |
| 'IMAGE_CHUNK_PROMPT': 'Image chunk prompt', | |
| 'DISABLE_GEMINI_SAFETY': 'Disable Gemini safety checks', | |
| } | |
| print(f"\nπ PROMPT/Safety VARIABLES:") | |
| print("-" * 40) | |
| prompt_set = 0 | |
| for var_name, description in prompt_vars.items(): | |
| known_vars.add(var_name) | |
| value = os.environ.get(var_name) | |
| all_critical.add(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β Not set: {var_name}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = (str(value)[:80] + ('...' if len(str(value)) > 80 else '')) | |
| print(f"β {var_name}: {value_preview}") | |
| prompt_set += 1 | |
| # Thinking features | |
| thinking_vars = { | |
| 'ENABLE_GEMINI_THINKING': 'Enable Gemini thinking', | |
| 'THINKING_BUDGET': 'Thinking token budget', | |
| 'ENABLE_GPT_THINKING': 'Enable GPT thinking', | |
| 'GPT_REASONING_TOKENS': 'Reasoning tokens for GPT', | |
| 'GPT_EFFORT': 'GPT effort level', | |
| } | |
| print(f"\nπ§ THINKING VARIABLES:") | |
| print("-" * 40) | |
| thinking_set = 0 | |
| for var_name, description in thinking_vars.items(): | |
| known_vars.add(var_name) | |
| value = os.environ.get(var_name) | |
| all_critical.add(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β Not set: {var_name}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = (str(value)[:80] + ('...' if len(str(value)) > 80 else '')) | |
| print(f"β {var_name}: {value_preview}") | |
| thinking_set += 1 | |
| # API endpoints | |
| api_vars = { | |
| 'OPENAI_CUSTOM_BASE_URL': 'Custom OpenAI base URL', | |
| 'GROQ_API_URL': 'Groq API base URL', | |
| 'FIREWORKS_API_URL': 'Fireworks API base URL', | |
| 'USE_CUSTOM_OPENAI_ENDPOINT': 'Use custom OpenAI-compatible endpoint', | |
| 'USE_GEMINI_OPENAI_ENDPOINT': 'Use Gemini-compatible OpenAI endpoint', | |
| 'GEMINI_OPENAI_ENDPOINT': 'Gemini OpenAI endpoint URL', | |
| } | |
| print(f"\nπ API ENDPOINT VARIABLES:") | |
| print("-" * 40) | |
| api_set = 0 | |
| for var_name, description in api_vars.items(): | |
| known_vars.add(var_name) | |
| value = os.environ.get(var_name) | |
| all_critical.add(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β Not set: {var_name}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = (str(value)[:80] + ('...' if len(str(value)) > 80 else '')) | |
| print(f"β {var_name}: {value_preview}") | |
| api_set += 1 | |
| # Image compression | |
| compression_vars = { | |
| 'ENABLE_IMAGE_COMPRESSION': 'Enable image compression', | |
| 'AUTO_COMPRESS_ENABLED': 'Auto compression enabled', | |
| 'TARGET_IMAGE_TOKENS': 'Target image tokens', | |
| 'IMAGE_COMPRESSION_FORMAT': 'Image compression format', | |
| 'WEBP_QUALITY': 'WEBP quality', | |
| 'JPEG_QUALITY': 'JPEG quality', | |
| 'PNG_COMPRESSION': 'PNG compression level', | |
| 'MAX_IMAGE_DIMENSION': 'Max image dimension', | |
| 'MAX_IMAGE_SIZE_MB': 'Max image size MB', | |
| 'PRESERVE_TRANSPARENCY': 'Preserve transparency', | |
| 'OPTIMIZE_FOR_OCR': 'Optimize for OCR', | |
| 'PROGRESSIVE_ENCODING': 'Progressive encoding', | |
| 'SAVE_COMPRESSED_IMAGES': 'Save compressed images', | |
| 'USE_FALLBACK_KEYS': 'Use fallback API keys', | |
| 'FALLBACK_KEYS': 'Fallback key list (JSON)', | |
| 'IMAGE_CHUNK_OVERLAP_PERCENT': 'Image chunk overlap percent', | |
| } | |
| print(f"\nποΈ IMAGE COMPRESSION VARIABLES:") | |
| print("-" * 40) | |
| comp_set = 0 | |
| for var_name, description in compression_vars.items(): | |
| known_vars.add(var_name) | |
| value = os.environ.get(var_name) | |
| all_critical.add(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β Not set: {var_name}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = (str(value)[:80] + ('...' if len(str(value)) > 80 else '')) | |
| print(f"β {var_name}: {value_preview}") | |
| comp_set += 1 | |
| # Metadata and headers | |
| metadata_vars = { | |
| 'TRANSLATE_METADATA_FIELDS': 'Translate metadata fields (JSON)', | |
| 'METADATA_TRANSLATION_MODE': 'Metadata translation mode', | |
| 'BATCH_TRANSLATE_HEADERS': 'Batch translate headers', | |
| 'HEADERS_PER_BATCH': 'Headers per batch', | |
| 'UPDATE_HTML_HEADERS': 'Update HTML headers', | |
| 'SAVE_HEADER_TRANSLATIONS': 'Save header translations', | |
| 'IGNORE_HEADER': 'Ignore header', | |
| 'USE_TITLE': 'Use title', | |
| } | |
| print(f"\nπ·οΈ METADATA/HEADERS VARIABLES:") | |
| print("-" * 40) | |
| meta_set = 0 | |
| for var_name, description in metadata_vars.items(): | |
| known_vars.add(var_name) | |
| value = os.environ.get(var_name) | |
| all_critical.add(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β Not set: {var_name}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = (str(value)[:80] + ('...' if len(str(value)) > 80 else '')) | |
| print(f"β {var_name}: {value_preview}") | |
| meta_set += 1 | |
| # Extraction mode and anti-duplicate | |
| extraction_vars = { | |
| 'TEXT_EXTRACTION_METHOD': 'Text extraction method', | |
| 'FILE_FILTERING_LEVEL': 'File filtering level', | |
| 'EXTRACTION_MODE': 'Extraction mode', | |
| 'ENHANCED_FILTERING': 'Enhanced filtering preset', | |
| 'ENABLE_ANTI_DUPLICATE': 'Enable anti-duplicate', | |
| 'TOP_P': 'Top-p sampling', | |
| 'TOP_K': 'Top-k sampling', | |
| 'FREQUENCY_PENALTY': 'Frequency penalty', | |
| 'PRESENCE_PENALTY': 'Presence penalty', | |
| 'REPETITION_PENALTY': 'Repetition penalty', | |
| 'CANDIDATE_COUNT': 'Candidate count', | |
| 'CUSTOM_STOP_SEQUENCES': 'Custom stop sequences', | |
| 'LOGIT_BIAS_ENABLED': 'Logit bias enabled', | |
| 'LOGIT_BIAS_STRENGTH': 'Logit bias strength', | |
| 'BIAS_COMMON_WORDS': 'Bias common words', | |
| 'BIAS_REPETITIVE_PHRASES': 'Bias repetitive phrases', | |
| } | |
| print(f"\nπ§© EXTRACTION/ANTI-DUPLICATE VARIABLES:") | |
| print("-" * 40) | |
| extract_set = 0 | |
| for var_name, description in extraction_vars.items(): | |
| known_vars.add(var_name) | |
| value = os.environ.get(var_name) | |
| all_critical.add(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β Not set: {var_name}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = (str(value)[:80] + ('...' if len(str(value)) > 80 else '')) | |
| print(f"β {var_name}: {value_preview}") | |
| extract_set += 1 | |
| # Azure API version | |
| azure_vars = { | |
| 'AZURE_API_VERSION': 'Azure API version', | |
| } | |
| print(f"\nβοΈ AZURE VARIABLES:") | |
| print("-" * 40) | |
| azure_set = 0 | |
| for var_name, description in azure_vars.items(): | |
| known_vars.add(var_name) | |
| value = os.environ.get(var_name) | |
| all_critical.add(var_name) | |
| if value is None: | |
| missing_critical.add(var_name) | |
| print(f"β Not set: {var_name}") | |
| elif not str(value).strip(): | |
| empty_critical.add(var_name) | |
| print(f"β οΈ Empty: {var_name}") | |
| else: | |
| set_critical.add(var_name) | |
| value_preview = (str(value)[:80] + ('...' if len(str(value)) > 80 else '')) | |
| print(f"β {var_name}: {value_preview}") | |
| azure_set += 1 | |
| # Summary | |
| total_critical = len(all_critical) | |
| print(f"\nπ SUMMARY:") | |
| print("-" * 20) | |
| print(f"Critical variables set: {len(set_critical)}/{total_critical}") | |
| print(f"Manga variables set: {manga_set}/{len(manga_env_vars)}") | |
| print(f"Rolling summary set: {rolling_set}/{len(rolling_vars)}") | |
| print(f"Retry/network set: {retry_set}/{len(retry_net_vars)}") | |
| print(f"QA/meta set: {qa_set}/{len(qa_meta_vars)}") | |
| print(f"Book title set: {book_set}/{len(book_vars)}") | |
| print(f"Image/EPUB set: {image_set}/{len(image_vars)}") | |
| print(f"Cleaning set: {watermark_set}/{len(watermark_vars)}") | |
| print(f"Prompts set: {prompt_set}/{len(prompt_vars)}") | |
| print(f"Thinking set: {thinking_set}/{len(thinking_vars)}") | |
| print(f"API endpoints set: {api_set}/{len(api_vars)}") | |
| print(f"Compression set: {comp_set}/{len(compression_vars)}") | |
| print(f"Metadata set: {meta_set}/{len(metadata_vars)}") | |
| print(f"Extraction/Anti-dup set: {extract_set}/{len(extraction_vars)}") | |
| print(f"Azure set: {azure_set}/{len(azure_vars)}") | |
| # Catch-all app variables by prefix (not yet listed) | |
| prefixes = [ | |
| 'GLOSSARY_', 'MANGA_', 'QA_', 'SCAN_PHASE_', 'TRANSLATE_', 'TRANSLATION_', 'BOOK_', | |
| 'OPENROUTER_', 'ENABLE_', 'DISABLE_', 'EXTRACTION_', 'METADATA_', 'BATCH_', 'HEADERS_', | |
| 'HTTP_', 'CONNECT_TIMEOUT', 'READ_TIMEOUT', 'MAX_RETRIES', 'IGNORE_RETRY_AFTER', | |
| 'TEXT_EXTRACTION_', 'FILE_FILTERING_', 'ENHANCED_FILTERING', 'AZURE_', 'OPENAI_', | |
| 'GROQ_', 'FIREWORKS_', 'USE_CUSTOM_', 'USE_GEMINI_', 'GEMINI_', 'IMAGE_', 'WEBP_', | |
| 'JPEG_', 'PNG_', 'TARGET_IMAGE_TOKENS', 'MAX_IMAGE_', 'PRESERVE_', 'OPTIMIZE_', | |
| 'PROGRESSIVE_', 'SAVE_COMPRESSED_IMAGES', 'USE_FALLBACK_KEYS', 'FALLBACK_KEYS', | |
| 'TOP_P', 'TOP_K', 'FREQUENCY_PENALTY', 'PRESENCE_PENALTY', 'REPETITION_PENALTY', | |
| 'CANDIDATE_COUNT', 'CUSTOM_STOP_SEQUENCES', 'LOGIT_BIAS_', 'BIAS_', 'THINKING_', 'GPT_', | |
| 'AI_HUNTER_', 'SYSTEM_PROMPT', 'MODEL', 'RETAIN_SOURCE_EXTENSION', 'auto_update_check', | |
| 'FORCE_NCX_ONLY', 'SINGLE_API_IMAGE_CHUNKS' | |
| ] | |
| print(f"\nπ§Ύ OTHER APP VARIABLES:") | |
| print("-" * 40) | |
| other_set = 0 | |
| for k, v in sorted(os.environ.items()): | |
| if k in known_vars: | |
| continue | |
| if any(k.startswith(pfx) for pfx in prefixes): | |
| masked = _mask_value(k, v) | |
| all_critical.add(k) | |
| if v is None or not str(v).strip(): | |
| if v is None: | |
| missing_critical.add(k) | |
| else: | |
| empty_critical.add(k) | |
| print(f"β {k}: not set/empty") | |
| else: | |
| set_critical.add(k) | |
| print(f"β {k}: {masked[:80]}{'...' if len(masked) > 80 else ''}") | |
| other_set += 1 | |
| print(f"Other app vars listed: {other_set}") | |
| if missing_critical: | |
| print(f"β Missing ({len(missing_critical)}): {', '.join(sorted(missing_critical))}") | |
| if empty_critical: | |
| print(f"β οΈ Empty ({len(empty_critical)}): {', '.join(sorted(empty_critical))}") | |
| if not missing_critical and not empty_critical: | |
| print("β All critical environment variables are properly set!") | |
| return True | |
| else: | |
| print("\nπ§ RECOMMENDATIONS:") | |
| print("1. Run the Glossary Manager and save settings") | |
| print("2. Check that all GUI variables are properly initialized") | |
| print("3. Call self.initialize_environment_variables() on app startup") | |
| print("4. Call self.debug_environment_variables() to see detailed debugging") | |
| return False | |
| def test_json_env_vars(): | |
| """Test JSON environment variables for validity.""" | |
| print("\nπ§ͺ JSON Environment Variable Validation:") | |
| print("=" * 50) | |
| json_vars = ['GLOSSARY_CUSTOM_ENTRY_TYPES', 'GLOSSARY_CUSTOM_FIELDS'] | |
| for var_name in json_vars: | |
| value = os.environ.get(var_name) | |
| if not value: | |
| print(f"π {var_name}: Not set") | |
| continue | |
| try: | |
| parsed_json = json.loads(value) | |
| print(f"β {var_name}: Valid JSON ({len(value)} chars)") | |
| print(f" Content type: {type(parsed_json).__name__}") | |
| if isinstance(parsed_json, dict): | |
| print(f" Keys: {list(parsed_json.keys())}") | |
| elif isinstance(parsed_json, list): | |
| print(f" Items: {len(parsed_json)}") | |
| except json.JSONDecodeError as e: | |
| print(f"β {var_name}: Invalid JSON") | |
| print(f" Error: {e}") | |
| print(f" Value preview: {value[:100]}...") | |
| if __name__ == "__main__": | |
| from shutdown_utils import run_cli_main | |
| def _main(): | |
| print("π Environment Variable Debugging Tool") | |
| print("This tool helps debug Glossarion environment variable issues") | |
| # Check current status | |
| success = print_env_var_status() | |
| # Test JSON variables | |
| test_json_env_vars() | |
| if not success: | |
| print(f"\nπ‘ TIP: Add these methods to your TranslatorGUI class:") | |
| print(" β’ self.initialize_environment_variables() - Call on startup") | |
| print(" β’ self.debug_environment_variables() - Call for debugging") | |
| print("\n" + "=" * 60) | |
| print("π― To use the new debugging features in your app:") | |
| print(" 1. self.initialize_environment_variables() # On startup") | |
| print(" 2. self.debug_environment_variables() # For debugging") | |
| print(" 3. Enhanced save_glossary_settings() now has full debugging") | |
| print(" 4. Enhanced save_config() now has full debugging") | |
| return 0 if success else 1 | |
| run_cli_main(_main) | |