Merge pull request #48 from deankerr/fix/config-path-resolution

fix: resolve .env and config paths from ~/.hermes/, not project root
This commit is contained in:
Teknium 2026-02-25 23:11:30 -08:00 committed by GitHub
commit 53b3177ca5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 46 additions and 33 deletions

View file

@ -23,9 +23,13 @@ if _env_path.exists():
load_dotenv(_env_path, encoding="utf-8") load_dotenv(_env_path, encoding="utf-8")
except UnicodeDecodeError: except UnicodeDecodeError:
load_dotenv(_env_path, encoding="latin-1") load_dotenv(_env_path, encoding="latin-1")
# Also try project .env as fallback # Also try project .env as dev fallback
load_dotenv(PROJECT_ROOT / ".env", override=False, encoding="utf-8") load_dotenv(PROJECT_ROOT / ".env", override=False, encoding="utf-8")
# Point mini-swe-agent at ~/.hermes/ so it shares our config
os.environ.setdefault("MSWEA_GLOBAL_CONFIG_DIR", str(HERMES_HOME))
os.environ.setdefault("MSWEA_SILENT_STARTUP", "1")
from hermes_cli.colors import Colors, color from hermes_cli.colors import Colors, color
from hermes_constants import OPENROUTER_MODELS_URL from hermes_constants import OPENROUTER_MODELS_URL
@ -225,17 +229,6 @@ def run_doctor(args):
check_ok("Created ~/.hermes/SOUL.md with basic template") check_ok("Created ~/.hermes/SOUL.md with basic template")
fixed_count += 1 fixed_count += 1
logs_dir = PROJECT_ROOT / "logs"
if logs_dir.exists():
check_ok("logs/ directory exists (project root)")
else:
if should_fix:
logs_dir.mkdir(parents=True, exist_ok=True)
check_ok("Created logs/ directory")
fixed_count += 1
else:
check_warn("logs/ not found", "(will be created on first use)")
# Check memory directory # Check memory directory
memories_dir = hermes_home / "memories" memories_dir = hermes_home / "memories"
if memories_dir.exists(): if memories_dir.exists():
@ -447,14 +440,15 @@ def run_doctor(args):
check_ok(info.get("name", tid)) check_ok(info.get("name", tid))
for item in unavailable: for item in unavailable:
if item["missing_vars"]: env_vars = item.get("missing_vars") or item.get("env_vars") or []
vars_str = ", ".join(item["missing_vars"]) if env_vars:
vars_str = ", ".join(env_vars)
check_warn(item["name"], f"(missing {vars_str})") check_warn(item["name"], f"(missing {vars_str})")
else: else:
check_warn(item["name"], "(system dependency not met)") check_warn(item["name"], "(system dependency not met)")
# Count disabled tools with API key requirements # Count disabled tools with API key requirements
api_disabled = [u for u in unavailable if u["missing_vars"]] api_disabled = [u for u in unavailable if (u.get("missing_vars") or u.get("env_vars"))]
if api_disabled: if api_disabled:
issues.append("Run 'hermes setup' to configure missing API keys for full tool access") issues.append("Run 'hermes setup' to configure missing API keys for full tool access")
except Exception as e: except Exception as e:
@ -466,7 +460,7 @@ def run_doctor(args):
print() print()
print(color("◆ Skills Hub", Colors.CYAN, Colors.BOLD)) print(color("◆ Skills Hub", Colors.CYAN, Colors.BOLD))
hub_dir = PROJECT_ROOT / "skills" / ".hub" hub_dir = HERMES_HOME / "skills" / ".hub"
if hub_dir.exists(): if hub_dir.exists():
check_ok("Skills Hub directory exists") check_ok("Skills Hub directory exists")
lock_file = hub_dir / "lock.json" lock_file = hub_dir / "lock.json"
@ -485,7 +479,8 @@ def run_doctor(args):
else: else:
check_warn("Skills Hub directory not initialized", "(run: hermes skills list)") check_warn("Skills Hub directory not initialized", "(run: hermes skills list)")
github_token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN") from hermes_cli.config import get_env_value
github_token = get_env_value("GITHUB_TOKEN") or get_env_value("GH_TOKEN")
if github_token: if github_token:
check_ok("GitHub token configured (authenticated API access)") check_ok("GitHub token configured (authenticated API access)")
else: else:

View file

@ -34,14 +34,20 @@ from typing import Optional
PROJECT_ROOT = Path(__file__).parent.parent.resolve() PROJECT_ROOT = Path(__file__).parent.parent.resolve()
sys.path.insert(0, str(PROJECT_ROOT)) sys.path.insert(0, str(PROJECT_ROOT))
# Load .env file # Load .env from ~/.hermes/.env first, then project root as dev fallback
from dotenv import load_dotenv from dotenv import load_dotenv
env_path = PROJECT_ROOT / '.env' from hermes_cli.config import get_env_path, get_hermes_home
if env_path.exists(): _user_env = get_env_path()
if _user_env.exists():
try: try:
load_dotenv(dotenv_path=env_path, encoding="utf-8") load_dotenv(dotenv_path=_user_env, encoding="utf-8")
except UnicodeDecodeError: except UnicodeDecodeError:
load_dotenv(dotenv_path=env_path, encoding="latin-1") load_dotenv(dotenv_path=_user_env, encoding="latin-1")
load_dotenv(dotenv_path=PROJECT_ROOT / '.env', override=False)
# Point mini-swe-agent at ~/.hermes/ so it shares our config
os.environ.setdefault("MSWEA_GLOBAL_CONFIG_DIR", str(get_hermes_home()))
os.environ.setdefault("MSWEA_SILENT_STARTUP", "1")
import logging import logging

View file

@ -12,6 +12,7 @@ from pathlib import Path
PROJECT_ROOT = Path(__file__).parent.parent.resolve() PROJECT_ROOT = Path(__file__).parent.parent.resolve()
from hermes_cli.colors import Colors, color from hermes_cli.colors import Colors, color
from hermes_cli.config import get_env_path, get_env_value
from hermes_constants import OPENROUTER_MODELS_URL from hermes_constants import OPENROUTER_MODELS_URL
def check_mark(ok: bool) -> str: def check_mark(ok: bool) -> str:
@ -65,7 +66,7 @@ def show_status(args):
print(f" Project: {PROJECT_ROOT}") print(f" Project: {PROJECT_ROOT}")
print(f" Python: {sys.version.split()[0]}") print(f" Python: {sys.version.split()[0]}")
env_path = PROJECT_ROOT / '.env' env_path = get_env_path()
print(f" .env file: {check_mark(env_path.exists())} {'exists' if env_path.exists() else 'not found'}") print(f" .env file: {check_mark(env_path.exists())} {'exists' if env_path.exists() else 'not found'}")
# ========================================================================= # =========================================================================
@ -88,7 +89,7 @@ def show_status(args):
} }
for name, env_var in keys.items(): for name, env_var in keys.items():
value = os.getenv(env_var, "") value = get_env_value(env_var) or ""
has_key = bool(value) has_key = bool(value)
display = redact_key(value) if not show_all else value display = redact_key(value) if not show_all else value
print(f" {name:<12} {check_mark(has_key)} {display}") print(f" {name:<12} {check_mark(has_key)} {display}")

View file

@ -37,19 +37,30 @@ import fire
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
# Load environment variables from .env file # Load .env from ~/.hermes/.env first, then project root as dev fallback
from dotenv import load_dotenv from dotenv import load_dotenv
# Load .env file if it exists _hermes_home = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
env_path = Path(__file__).parent / '.env' _user_env = _hermes_home / ".env"
if env_path.exists(): _project_env = Path(__file__).parent / '.env'
if _user_env.exists():
try: try:
load_dotenv(dotenv_path=env_path, encoding="utf-8") load_dotenv(dotenv_path=_user_env, encoding="utf-8")
except UnicodeDecodeError: except UnicodeDecodeError:
load_dotenv(dotenv_path=env_path, encoding="latin-1") load_dotenv(dotenv_path=_user_env, encoding="latin-1")
logger.info("Loaded environment variables from %s", env_path) logger.info("Loaded environment variables from %s", _user_env)
elif _project_env.exists():
try:
load_dotenv(dotenv_path=_project_env, encoding="utf-8")
except UnicodeDecodeError:
load_dotenv(dotenv_path=_project_env, encoding="latin-1")
logger.info("Loaded environment variables from %s", _project_env)
else: else:
logger.info("No .env file found at %s. Using system environment variables.", env_path) logger.info("No .env file found. Using system environment variables.")
# Point mini-swe-agent at ~/.hermes/ so it shares our config
os.environ.setdefault("MSWEA_GLOBAL_CONFIG_DIR", str(_hermes_home))
os.environ.setdefault("MSWEA_SILENT_STARTUP", "1")
# Import our tool system # Import our tool system
from model_tools import get_tool_definitions, handle_function_call, check_toolset_requirements from model_tools import get_tool_definitions, handle_function_call, check_toolset_requirements