#!/usr/bin/env python3 """ Wizard environment validator. Checks that a new wizard environment is ready for duty. Usage as CLI: python -m devkit.wizard_env python -m devkit.wizard_env --fix Usage as module: from devkit.wizard_env import validate report = validate() """ import argparse import json import os import shutil import subprocess import sys from typing import Any, Dict, List def _has_cmd(name: str) -> bool: return shutil.which(name) is not None def _check_env_var(name: str) -> Dict[str, Any]: value = os.getenv(name) return { "name": name, "status": "ok" if value else "missing", "value": value[:10] + "..." if value and len(value) > 20 else value, } def _check_python_pkg(name: str) -> Dict[str, Any]: try: __import__(name) return {"name": name, "status": "ok"} except ImportError: return {"name": name, "status": "missing"} def validate() -> Dict[str, Any]: checks = { "binaries": [ {"name": "python3", "status": "ok" if _has_cmd("python3") else "missing"}, {"name": "git", "status": "ok" if _has_cmd("git") else "missing"}, {"name": "curl", "status": "ok" if _has_cmd("curl") else "missing"}, {"name": "jupyter-lab", "status": "ok" if _has_cmd("jupyter-lab") else "missing"}, {"name": "papermill", "status": "ok" if _has_cmd("papermill") else "missing"}, {"name": "jupytext", "status": "ok" if _has_cmd("jupytext") else "missing"}, ], "env_vars": [ _check_env_var("GITEA_URL"), _check_env_var("GITEA_TOKEN"), _check_env_var("TELEGRAM_BOT_TOKEN"), ], "python_packages": [ _check_python_pkg("requests"), _check_python_pkg("jupyter_server"), _check_python_pkg("nbformat"), ], } all_ok = all( c["status"] == "ok" for group in checks.values() for c in group ) # Hermes-specific checks hermes_home = os.path.expanduser("~/.hermes") checks["hermes"] = [ {"name": "config.yaml", "status": "ok" if os.path.exists(f"{hermes_home}/config.yaml") else "missing"}, {"name": "skills_dir", "status": "ok" if os.path.exists(f"{hermes_home}/skills") else "missing"}, ] all_ok = all_ok and all(c["status"] == "ok" for c in checks["hermes"]) return { "overall": "ok" if all_ok else "incomplete", "checks": checks, } def main(argv: List[str] = None) -> int: argv = argv or sys.argv[1:] parser = argparse.ArgumentParser(description="Wizard environment validator") parser.add_argument("--json", action="store_true") parser.add_argument("--fail-on-incomplete", action="store_true") args = parser.parse_args(argv) report = validate() if args.json: print(json.dumps(report, indent=2)) else: print(f"Wizard Environment: {report['overall']}") for group, items in report["checks"].items(): print(f"\n[{group}]") for item in items: status_icon = "✅" if item["status"] == "ok" else "❌" print(f" {status_icon} {item['name']}: {item['status']}") if args.fail_on_incomplete and report["overall"] != "ok": return 1 return 0 if __name__ == "__main__": sys.exit(main())