refactor(profiles): drop dead helpers from hermes_constants

STANDARD_PROFILES, normalize_profile, validate_profile_name, and
is_standard_profile in hermes_constants were superseded by
hermes_cli.profiles.{normalize_profile_name, validate_profile_name}
but never removed. profile_routing.py is updated to import from the
canonical location; the old helpers are deleted.

Lazy import inside parse_profile_routes avoids the circular dependency
at module load time (hermes_constants -> hermes_cli -> hermes_constants).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Burgunthy 2026-06-28 05:51:04 +09:00 committed by Teknium
parent 9166d727b8
commit a55523fd6d
2 changed files with 8 additions and 47 deletions

View file

@ -130,10 +130,15 @@ def parse_profile_routes(raw: Optional[List[Dict[str, Any]]]) -> List[ProfileRou
name,
)
continue
# Validate profile name to prevent path traversal
# Validate profile name to prevent path traversal. Lazy import avoids a
# circular dependency at module load time.
try:
from hermes_constants import validate_profile_name as _validate
profile = _validate(profile)
from hermes_cli.profiles import (
normalize_profile_name,
validate_profile_name,
)
profile = normalize_profile_name(profile)
validate_profile_name(profile)
except (ValueError, ImportError):
logger.warning("Skipping profile route %s: invalid profile name %r", name, profile)
continue

View file

@ -10,7 +10,6 @@ import stat
import sys
import sysconfig
from contextvars import ContextVar, Token
import re
from pathlib import Path
@ -1218,46 +1217,3 @@ FINISH_REASON_LENGTH = "length"
OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1"
OPENROUTER_MODELS_URL = f"{OPENROUTER_BASE_URL}/models"
# ─── Profile Normalization ────────────────────────────────────────────────
# Standard (non-isolated) profile names. All three are treated identically
# for gating and filtering purposes. Named profiles (e.g. "ai-expert")
# are anything *not* in this tuple.
STANDARD_PROFILES: tuple[str, ...] = ("main", "default")
_VALID_PROFILE_RE = re.compile(r"^[a-z0-9][a-z0-9_-]*$")
def normalize_profile(name: str | None) -> str:
"""Canonicalize a profile name. Never raises.
Returns ``"main"`` for all standard/empty profiles so that downstream
code only needs to compare against a single value. Named profiles
are returned as-is (lowercased, stripped).
"""
if not name or name.strip().lower() in STANDARD_PROFILES:
return "main"
return name.strip().lower()
def validate_profile_name(name: str | None) -> str:
"""Validate and canonicalize. Raises ValueError for invalid names.
Use at config parse boundaries. normalize_profile() is the safe
runtime version that never raises.
"""
result = normalize_profile(name)
if result == "main":
return result
if not _VALID_PROFILE_RE.match(result):
raise ValueError(
f"Invalid profile name: {name!r} (must match [a-z0-9][a-z0-9_-]*)"
)
return result
def is_standard_profile(name: str | None) -> bool:
"""Return True for default/main/None/empty — the unscoped profile."""
return not name or name.strip().lower() in STANDARD_PROFILES