Extracted 52 files from Timmy_Foundation/hermes-agent (gitea/main) into hermes-sovereign/ directory to restore clean upstream tracking. Layout: docs/ 19 files — deploy guides, performance reports, security docs, research security/ 5 files — audit workflows, PR checklists, validation scripts wizard-bootstrap/ 7 files — wizard environment, dependency checking, auditing notebooks/ 2 files — Jupyter health monitoring notebooks scripts/ 5 files — forge health, smoke tests, syntax guard, deploy validation ci/ 2 files — Gitea CI workflow definitions githooks/ 3 files — pre-commit hooks and config devkit/ 8 files — developer toolkit (Gitea client, health, notebook runner) README.md 1 file — directory overview Addresses: #337, #338
113 lines
3.3 KiB
Python
113 lines
3.3 KiB
Python
#!/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())
|