|
|
|
""" |
|
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 |
|
|
|
|
|
sys.path.append('.') |
|
|
|
|
|
from src.gaia.utils.config_validator import ( |
|
validate_config, |
|
generate_env_example, |
|
initialize_env_from_example, |
|
get_documentation, |
|
REQUIRED_ENV_VARS, |
|
OPTIONAL_ENV_VARS |
|
) |
|
|
|
|
|
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"] |
|
|
|
|
|
report = f"# GAIA Environment Configuration Report\n\n" |
|
report += f"**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n" |
|
|
|
|
|
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" |
|
|
|
|
|
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" |
|
|
|
|
|
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" |
|
|
|
|
|
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}" |
|
|
|
|
|
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" |
|
|
|
|
|
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" |
|
|
|
|
|
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" |
|
|
|
|
|
report += "\n## Configuration Sections\n\n" |
|
|
|
|
|
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" |
|
|
|
|
|
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" |
|
|
|
|
|
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" |
|
|
|
|
|
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" |
|
|
|
|
|
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") |
|
|
|
|
|
if args.generate_env: |
|
initialize_env_from_example() |
|
|
|
|
|
validation_result = validate_config() |
|
|
|
|
|
report = generate_markdown_report(validation_result) |
|
report_path = save_report(report) |
|
|
|
|
|
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() |