File size: 9,259 Bytes
c922f8b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
#!/usr/bin/env python3
"""
GAIA Environment Validation Script
This script checks all environment variables used by the GAIA system
and generates a comprehensive validation report.
Usage:
python validate_gaia_environment.py [--generate-env] [--verbose]
Options:
--generate-env Generate a .env file from .env.example if not exists
--verbose Enable verbose output
Example:
python validate_gaia_environment.py --generate-env --verbose
"""
import os
import sys
import argparse
import json
import logging
from pathlib import Path
from datetime import datetime
from typing import Dict, List, Any, Optional
# Add the project root to the path
sys.path.append('.')
# Import the config validator
from src.gaia.utils.config_validator import (
validate_config,
generate_env_example,
initialize_env_from_example,
get_documentation,
REQUIRED_ENV_VARS,
OPTIONAL_ENV_VARS
)
# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger("gaia.env_validator")
def parse_args():
"""Parse command line arguments."""
parser = argparse.ArgumentParser(description="Validate GAIA environment configuration")
parser.add_argument("--generate-env", action="store_true", help="Generate a .env file from .env.example if not exists")
parser.add_argument("--verbose", action="store_true", help="Enable verbose output")
return parser.parse_args()
def generate_markdown_report(validation_result: Dict[str, Any]) -> str:
"""
Generate a comprehensive Markdown report of the validation results.
Args:
validation_result: Result from validate_config()
Returns:
Markdown report as string
"""
config = validation_result["config"]
errors = validation_result["errors"]
warnings = validation_result["warnings"]
# Start with report header
report = f"# GAIA Environment Configuration Report\n\n"
report += f"**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
# Overall status
if validation_result["valid"]:
report += "## ✅ Configuration Status: VALID\n\n"
else:
report += "## ❌ Configuration Status: INVALID\n\n"
report += f"Found {len(errors)} error(s) in configuration.\n\n"
# Add errors section if there are any
if errors:
report += "## Errors\n\n"
report += "The following errors must be fixed for the GAIA system to function properly:\n\n"
for error in errors:
report += f"- {error}\n"
report += "\n"
# Add warnings section if there are any
if warnings:
report += "## Warnings\n\n"
report += "The following warnings should be reviewed but don't prevent the system from functioning:\n\n"
for warning in warnings:
report += f"- {warning}\n"
report += "\n"
# Required environment variables
report += "## Required Environment Variables\n\n"
report += "| Variable | Status | Description |\n"
report += "|----------|--------|-------------|\n"
for var in REQUIRED_ENV_VARS:
var_name = var["name"]
is_set = var_name in os.environ and os.environ[var_name] != ""
var_error = None
for error in errors:
if var_name in error:
var_error = error.split(": ", 1)[1] if ": " in error else error
break
status = "✅ Set" if is_set and not var_error else "❌ Missing or Invalid"
if var_error:
status += f" - {var_error}"
# Mask sensitive values for security
value = os.environ.get(var_name, "")
if value and ("KEY" in var_name or "TOKEN" in var_name):
value = value[:4] + "****" + value[-4:] if len(value) > 8 else "****"
report += f"| {var_name} | {status} | {var['description']} |\n"
# Optional environment variables
report += "\n## Optional Environment Variables\n\n"
report += "| Variable | Status | Description | Default |\n"
report += "|----------|--------|-------------|--------|\n"
for var in OPTIONAL_ENV_VARS:
var_name = var["name"]
is_set = var_name in os.environ and os.environ[var_name] != ""
default = var["default"]
var_error = None
for error in errors:
if var_name in error:
var_error = error.split(": ", 1)[1] if ": " in error else error
break
if is_set:
status = "✅ Custom" if not var_error else f"❌ Invalid - {var_error}"
else:
status = "⚠️ Using Default"
# Mask sensitive values for security
value = os.environ.get(var_name, default)
if value and ("KEY" in var_name or "TOKEN" in var_name):
value = value[:4] + "****" + value[-4:] if len(value) > 8 else "****"
report += f"| {var_name} | {status} | {var['description']} | {default} |\n"
# Configuration sections
report += "\n## Configuration Sections\n\n"
# Model settings
report += "### Model Settings\n\n"
report += f"- **Default Model:** {config.get('DEFAULT_MODEL', 'Not set')}\n"
report += f"- **Fallback Model:** {config.get('FALLBACK_MODEL', 'Not set')}\n"
report += f"- **Embedding Model:** {config.get('EMBEDDING_MODEL', 'Not set')}\n"
report += f"- **Model Temperature:** {config.get('MODEL_TEMPERATURE', 'Not set')}\n"
report += f"- **Model Max Tokens:** {config.get('MODEL_MAX_TOKENS', 'Not set')}\n"
# Memory settings
report += "\n### Memory Settings\n\n"
report += f"- **Memory Enabled:** {config.get('MEMORY_ENABLED', 'Not set')}\n"
report += f"- **Memory Table Name:** {config.get('MEMORY_TABLE_NAME', 'Not set')}\n"
report += f"- **Memory TTL:** {config.get('MEMORY_TTL', 'Not set')} seconds\n"
report += f"- **Memory Cache Size:** {config.get('MEMORY_CACHE_SIZE', 'Not set')}\n"
# Web search settings
report += "\n### Web Search Settings\n\n"
report += f"- **Web Search Result Count:** {config.get('WEB_SEARCH_RESULT_COUNT', 'Not set')}\n"
report += f"- **DuckDuckGo Timeout:** {config.get('DUCKDUCKGO_TIMEOUT', 'Not set')} seconds\n"
report += f"- **DuckDuckGo Max Results:** {config.get('DUCKDUCKGO_MAX_RESULTS', 'Not set')}\n"
# System settings
report += "\n### System Settings\n\n"
report += f"- **Max Iterations:** {config.get('MAX_ITERATIONS', 'Not set')}\n"
report += f"- **Verbose:** {config.get('VERBOSE', 'Not set')}\n"
report += f"- **Log Level:** {config.get('LOG_LEVEL', 'Not set')}\n"
# Next steps
report += "\n## Next Steps\n\n"
if validation_result["valid"]:
report += "Your GAIA environment configuration is valid. You can proceed with running the system.\n\n"
else:
report += "Please fix the errors listed above, then run this validation script again.\n\n"
report += "To fix these issues:\n\n"
report += "1. Edit your `.env` file and add/update the required variables\n"
report += "2. Run this script again to verify your changes\n\n"
report += "You can also regenerate a template `.env.example` file by running:\n\n"
report += "```bash\n"
report += "python -c \"from src.gaia.utils.config_validator import generate_env_example; generate_env_example()\"\n"
report += "```\n"
return report
def save_report(report: str, output_path: str = "environment_report.md") -> str:
"""
Save the validation report to a file.
Args:
report: Markdown report to save
output_path: Path to the output file
Returns:
Path to the saved report
"""
with open(output_path, "w") as f:
f.write(report)
logger.info(f"Saved environment validation report to {output_path}")
return output_path
def main():
"""Main function."""
args = parse_args()
if args.verbose:
logger.setLevel(logging.DEBUG)
logger.debug("Verbose logging enabled")
logger.info("Starting GAIA environment validation")
# Generate .env file if requested
if args.generate_env:
initialize_env_from_example()
# Validate the configuration
validation_result = validate_config()
# Generate and save the report
report = generate_markdown_report(validation_result)
report_path = save_report(report)
# Print summary to console
if validation_result["valid"]:
logger.info("✅ Environment configuration is valid!")
else:
logger.error(f"❌ Environment configuration has {len(validation_result['errors'])} errors!")
for error in validation_result["errors"]:
logger.error(f" - {error}")
if validation_result["warnings"]:
logger.warning(f"⚠️ Environment configuration has {len(validation_result['warnings'])} warnings:")
for warning in validation_result["warnings"]:
logger.warning(f" - {warning}")
logger.info(f"See the full report at: {report_path}")
if __name__ == "__main__":
main() |