""" Simple debug logger for AI prompts and responses. Writes files chronologically to gateway/test-chat/ai/ with sequential numbering. """ import os import json from datetime import datetime, UTC from typing import Any, Optional def _getDebugDir() -> str: """Get the debug directory path.""" gatewayDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) return os.path.join(gatewayDir, 'test-chat', 'ai') def _getNextSequenceNumber() -> int: """Get the next sequence number by counting existing files.""" debugDir = _getDebugDir() if not os.path.exists(debugDir): return 1 # Count existing numbered files files = [f for f in os.listdir(debugDir) if f.startswith(('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'))] return len(files) + 1 def _formatJsonReadable(data: Any) -> str: """ Format JSON data in a readable line-by-line structure. Handles both structured objects and text representations of dicts/lists. Args: data: The data to format Returns: Formatted string representation """ try: # First try to parse if it's a string representation if isinstance(data, str): try: # Try to parse as JSON first parsed = json.loads(data) data = parsed except json.JSONDecodeError: # Try to evaluate as Python literal (for dict/list strings) try: import ast parsed = ast.literal_eval(data) if isinstance(parsed, (dict, list)): data = parsed except (ValueError, SyntaxError): # If all parsing fails, treat as plain text pass # Convert to JSON string with proper indentation if isinstance(data, (dict, list)): jsonStr = json.dumps(data, ensure_ascii=False, default=str, indent=2) else: jsonStr = str(data) # Split into lines and add line numbers for better readability lines = jsonStr.split('\n') formattedLines = [] for i, line in enumerate(lines, 1): # Add line number and proper spacing lineNum = f"{i:3d}: " formattedLines.append(f"{lineNum}{line}") return '\n'.join(formattedLines) except Exception: # Fallback to string representation if JSON formatting fails return str(data) def writeDebugFile(content: str, fileType: str, data: Optional[Any] = None) -> None: """ Write debug content to a file with sequential numbering. Args: content: The main content to write fileType: Type of file (e.g., 'prompt', 'response', 'placeholders') data: Optional additional data to include as JSON """ try: debugDir = _getDebugDir() os.makedirs(debugDir, exist_ok=True) seqNum = _getNextSequenceNumber() ts = datetime.now(UTC).strftime('%Y%m%d-%H%M%S') # Add 3-digit sequence number for uniqueness tsWithSeq = f"{ts}-{seqNum:03d}" filename = f"{tsWithSeq}-{fileType}.txt" filepath = os.path.join(debugDir, filename) with open(filepath, 'w', encoding='utf-8') as f: f.write(content) # If structured data provided, also append a human-readable section to the main .txt try: if data is not None: formatted = _formatJsonReadable(data) with open(filepath, 'a', encoding='utf-8') as f: f.write("\n\n=== FORMATTED DATA (human-readable) ===\n") f.write(formatted) f.write("\n") except Exception: pass # If additional data provided, write it as a separate JSON file with readable formatting if data is not None: jsonFilename = f"{tsWithSeq}-{fileType}_data.json" jsonFilepath = os.path.join(debugDir, jsonFilename) with open(jsonFilepath, 'w', encoding='utf-8') as f: formattedData = _formatJsonReadable(data) f.write(formattedData) except Exception as e: # Silent fail - don't break the main flow pass