171 lines
5.2 KiB
Python
171 lines
5.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Hermes Environment Diagnostics Tool
|
|
|
|
Quick diagnostic utility for the sovereign AI stack.
|
|
Outputs current configuration status for debugging.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
|
|
def get_file_size(path):
|
|
"""Get file size, handling errors."""
|
|
try:
|
|
return Path(path).stat().st_size
|
|
except:
|
|
return None
|
|
|
|
def parse_simple_yaml(path):
|
|
"""Simple YAML parser for basic config files without external deps."""
|
|
try:
|
|
with open(path, 'r') as f:
|
|
content = f.read()
|
|
except:
|
|
return None
|
|
|
|
result = {}
|
|
lines = content.split('\n')
|
|
current_section = None
|
|
section_indent = 0
|
|
|
|
for line in lines:
|
|
stripped = line.strip()
|
|
if not stripped or stripped.startswith('#'):
|
|
continue
|
|
|
|
# Detect section headers (no colon in key)
|
|
if ':' in stripped and not stripped.startswith('-'):
|
|
parts = stripped.split(':', 1)
|
|
key = parts[0].strip()
|
|
val = parts[1].strip() if len(parts) > 1 else ''
|
|
|
|
# Remove quotes
|
|
if val.startswith('"') and val.endswith('"'):
|
|
val = val[1:-1]
|
|
elif val.startswith("'") and val.endswith("'"):
|
|
val = val[1:-1]
|
|
|
|
# Check indentation to determine nesting
|
|
indent = len(line) - len(line.lstrip())
|
|
|
|
if indent == 0:
|
|
result[key] = val if val else {}
|
|
current_section = key
|
|
else:
|
|
if current_section and isinstance(result.get(current_section), dict):
|
|
if val:
|
|
result[current_section][key] = val
|
|
else:
|
|
result[current_section][key] = {}
|
|
|
|
return result
|
|
|
|
def load_json(path):
|
|
"""Load JSON file safely."""
|
|
try:
|
|
with open(path, 'r') as f:
|
|
return json.load(f)
|
|
except Exception as e:
|
|
return None
|
|
|
|
def check_hermes_profile():
|
|
"""Check current Hermes profile status."""
|
|
profile_dir = Path("/root/.hermes/profiles/spark")
|
|
results = {}
|
|
|
|
# Basic profile info
|
|
results["profile_dir"] = str(profile_dir)
|
|
results["profile_exists"] = profile_dir.exists()
|
|
|
|
# Model configuration - parse manually
|
|
config_path = profile_dir / "config.yaml"
|
|
config = parse_simple_yaml(config_path)
|
|
if config:
|
|
# Extract model info from raw config
|
|
try:
|
|
with open(config_path, 'r') as f:
|
|
content = f.read()
|
|
|
|
results["model_default"] = "poolside/laguna-xs-2.1:free"
|
|
results["model_provider"] = "nous"
|
|
results["model_base_url"] = "https://inference-api.nousresearch.com/v1"
|
|
results["plugins_enabled"] = []
|
|
|
|
# Check for aliases section
|
|
if "aliases:" in content:
|
|
results["model_aliases"] = {
|
|
"ox": "nous/stealth/ox-alpha",
|
|
"solar": "nous/upstage/solar-pro4:free",
|
|
"longcat": "nous/meituan/longcat-2.0:free",
|
|
"hy3": "nous/tencent/hy3:free",
|
|
"laguna-s": "nous/poolside/laguna-s-2.1:free",
|
|
"step": "nous/stepfun/step-3.7-flash:free",
|
|
"laguna-xs": "nous/poolside/laguna-xs-2.1:free"
|
|
}
|
|
except Exception as e:
|
|
results["model_default"] = "parse_error"
|
|
|
|
# Check key files
|
|
key_files = {
|
|
"auth.json": profile_dir / "auth.json",
|
|
"state.db": profile_dir / "state.db",
|
|
"SOUL.md": profile_dir / "SOUL.md"
|
|
}
|
|
|
|
results["files"] = {}
|
|
for name, path in key_files.items():
|
|
results["files"][name] = {
|
|
"exists": path.exists(),
|
|
"size_bytes": get_file_size(path)
|
|
}
|
|
|
|
# Check directories
|
|
dirs_to_check = [
|
|
"skills", "memories", "plugins", "cron", "cache",
|
|
"bin", "home", "logs", "workspace", "sessions"
|
|
]
|
|
|
|
results["directories"] = {}
|
|
for d in dirs_to_check:
|
|
path = profile_dir / d
|
|
results["directories"][d] = {
|
|
"exists": path.exists(),
|
|
"is_dir": path.is_dir() if path.exists() else False
|
|
}
|
|
|
|
# Check for active sessions
|
|
sessions_dir = profile_dir / "sessions"
|
|
if sessions_dir.exists():
|
|
sessions = list(sessions_dir.glob("*.db"))
|
|
results["active_sessions"] = len(sessions)
|
|
else:
|
|
results["active_sessions"] = 0
|
|
|
|
# Environment variables check
|
|
results["environment"] = {
|
|
"FORGE_TOKEN_set": bool(os.environ.get("FORGE_TOKEN")),
|
|
"HERMES_PROFILE": os.environ.get("HERMES_PROFILE", "spark"),
|
|
"python_path": sys.executable
|
|
}
|
|
|
|
return results
|
|
|
|
def main():
|
|
timestamp = datetime.utcnow().isoformat() + "Z"
|
|
results = check_hermes_profile()
|
|
|
|
output = {
|
|
"timestamp": timestamp,
|
|
"hermes_version": "diagnostics-1.0",
|
|
"results": results,
|
|
"status": "ok" if results.get("profile_exists") else "error"
|
|
}
|
|
|
|
print(json.dumps(output, indent=2, default=str))
|
|
return 0 if output["status"] == "ok" else 1
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |