"""Resolve Space-specific runtime defaults for Hermes containers.""" from __future__ import annotations import os import shlex import sys from collections.abc import Mapping, Sequence from pathlib import Path SPACE_WEB_ARGS = ["dashboard", "--host", "0.0.0.0", "--port", "7860", "--no-open"] DEFAULT_HERMES_HOME = "/opt/data" SPACE_HERMES_HOME = "/data/hermes" DEFAULT_API_SERVER_PORT = "8642" DEFAULT_API_SERVER_UPSTREAM_HOST = "127.0.0.1" API_SERVER_PORT_PATHS = ( ("platforms", "api_server", "extra", "port"), ("platforms", "api_server", "port"), ("api_server", "extra", "port"), ("api_server", "port"), ) def is_hf_space(env: Mapping[str, str]) -> bool: return bool(env.get("SPACE_ID") or env.get("SPACE_HOST")) def resolve_hermes_home(env: Mapping[str, str]) -> str: current = env.get("HERMES_HOME") or DEFAULT_HERMES_HOME if is_hf_space(env) and current == DEFAULT_HERMES_HOME: return SPACE_HERMES_HOME return current def resolve_default_command(env: Mapping[str, str], argv: Sequence[str]) -> list[str]: if argv: return list(argv) if is_hf_space(env): return SPACE_WEB_ARGS.copy() return [] def resolve_hermes_command( env: Mapping[str, str], argv: Sequence[str], executable: str = "hermes", ) -> list[str]: return [executable, *resolve_default_command(env, argv)] def _resolve_config_path(env: Mapping[str, str]) -> Path: return Path(resolve_hermes_home(env)) / "config.yaml" def _strip_inline_comment(text: str) -> str: quote: str | None = None result: list[str] = [] for char in text: if char in {"'", '"'}: if quote == char: quote = None elif quote is None: quote = char if char == "#" and quote is None: break result.append(char) return "".join(result).rstrip() def _parse_scalar(text: str) -> str | None: value = _strip_inline_comment(text).strip() if not value: return None if len(value) >= 2 and value[0] == value[-1] and value[0] in {"'", '"'}: return value[1:-1] return value def _read_yaml_path_value(text: str, target_paths: Sequence[tuple[str, ...]]) -> str | None: stack: list[tuple[int, str]] = [] for raw_line in text.splitlines(): line = raw_line.rstrip() stripped = line.lstrip(" ") if not stripped or stripped.startswith("#") or stripped.startswith("-"): continue indent = len(line) - len(stripped) key, separator, remainder = stripped.partition(":") if not separator: continue while stack and indent <= stack[-1][0]: stack.pop() path = tuple(part for _, part in stack) + (key.strip(),) value = _parse_scalar(remainder) if path in target_paths and value is not None: return value if value is None: stack.append((indent, key.strip())) return None def _config_api_server_port(env: Mapping[str, str]) -> str | None: config_path = _resolve_config_path(env) try: config_text = config_path.read_text(encoding="utf-8") except OSError: return None value = _read_yaml_path_value(config_text, API_SERVER_PORT_PATHS) if value is None: return None try: port = int(value, 10) except ValueError: return None if 0 < port <= 65535: return str(port) return None def resolve_api_server_port(env: Mapping[str, str]) -> str: explicit = (env.get("API_SERVER_PORT") or "").strip() if explicit: return explicit return _config_api_server_port(env) or DEFAULT_API_SERVER_PORT def resolve_api_server_upstream(env: Mapping[str, str]) -> str: explicit = (env.get("UPSTREAM") or "").strip() if explicit: return explicit return f"http://{DEFAULT_API_SERVER_UPSTREAM_HOST}:{resolve_api_server_port(env)}" def _command_string(env: Mapping[str, str], argv: Sequence[str]) -> str: executable = env.get("HERMES_EXECUTABLE", "hermes") return shlex.join(resolve_hermes_command(env, argv, executable=executable)) def main(argv: Sequence[str] | None = None) -> int: argv = list(sys.argv[1:] if argv is None else argv) env = os.environ if not argv or argv[0] == "home": print(resolve_hermes_home(env)) return 0 if argv[0] == "command": print(_command_string(env, argv[1:])) return 0 if argv[0] == "api-server-port": print(resolve_api_server_port(env)) return 0 if argv[0] == "api-server-upstream": print(resolve_api_server_upstream(env)) return 0 if argv[0] == "exec": print_only = False args = argv[1:] if args and args[0] == "--print-only": print_only = True args = args[1:] command = resolve_hermes_command( env, args, executable=env.get("HERMES_EXECUTABLE", "hermes"), ) if print_only: print(shlex.join(command)) return 0 os.execvpe(command[0], command, dict(env)) prog = os.path.basename(sys.argv[0] or "space_runtime.py") raise SystemExit( f"Usage: {prog} [home|command|api-server-port|api-server-upstream|exec [--print-only] [args...]]" ) if __name__ == "__main__": raise SystemExit(main())