diff --git a/platform/hermes/start-hermes-managed.sh b/platform/hermes/start-hermes-managed.sh index c976b71..dbb242d 100755 --- a/platform/hermes/start-hermes-managed.sh +++ b/platform/hermes/start-hermes-managed.sh @@ -6,6 +6,70 @@ if [ ! -r "$config" ]; then echo "HERMES_START_REFUSED: managed config is not readable" >&2 exit 78 fi + +# Hermes Desktop can persist a model selection back into config.yaml. A bad +# selection must never be able to detach the central gateway from Athena's +# authenticated profile router. Repair only the managed model block from the +# container secret on every start; all user settings, sessions and MCP entries +# remain untouched. +python - "$config" <<'PY' +import os +import re +import sys +import tempfile + +path = sys.argv[1] +router_key = os.environ.get("ROUTER_API_KEY", "").strip() +if not router_key or router_key.startswith("${"): + raise SystemExit("HERMES_START_REFUSED: ROUTER_API_KEY is missing") + +with open(path, "r", encoding="utf-8") as handle: + lines = handle.readlines() + +try: + start = next(i for i, line in enumerate(lines) if re.match(r"^model:\s*(?:#.*)?$", line)) +except StopIteration: + raise SystemExit("HERMES_START_REFUSED: model block is missing") + +end = len(lines) +for i in range(start + 1, len(lines)): + if re.match(r"^[A-Za-z_][A-Za-z0-9_-]*:\s*", lines[i]): + end = i + break + +managed = { + "default": "qwen-medium", + "provider": "custom", + "base_url": "http://router:8081/v1", + "api_key": router_key, +} + +for field, value in managed.items(): + rendered = f' {field}: "{value}"\n' + match = next( + (i for i in range(start + 1, end) if re.match(rf"^\s+{re.escape(field)}:\s*", lines[i])), + None, + ) + if match is None: + lines.insert(end, rendered) + end += 1 + else: + lines[match] = rendered + +directory = os.path.dirname(path) +fd, temporary = tempfile.mkstemp(prefix=".config.yaml.", dir=directory, text=True) +try: + with os.fdopen(fd, "w", encoding="utf-8") as handle: + handle.writelines(lines) + handle.flush() + os.fsync(handle.fileno()) + os.chmod(temporary, os.stat(path).st_mode & 0o777) + os.replace(temporary, path) +finally: + if os.path.exists(temporary): + os.unlink(temporary) +PY + grep -Eq '^[[:space:]]+provider:[[:space:]]+["'\'']?custom["'\'']?[[:space:]]*$' "$config" || { echo "HERMES_START_REFUSED: provider is not custom" >&2 exit 78 @@ -16,4 +80,3 @@ grep -Eq '^[[:space:]]+base_url:[[:space:]]+["'\'']?http://router:8081/v1["'\''] } exec hermes gateway run -