Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions hermes_cli/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,21 @@ def _effective_provider_label() -> str:
except AuthError:
effective = requested or "auto"

if effective == "openrouter" and get_env_value("OPENAI_BASE_URL"):
effective = "custom"
if effective == "openrouter":
# A custom endpoint may be configured either in config.yaml
# (model.base_url — the canonical location; the runtime treats
# config.yaml as the single source of truth) or via the legacy
# OPENAI_BASE_URL env var. Either way, labeling it "OpenRouter"
# is misleading (#3296).
config_base_url = ""
try:
model_cfg = load_config().get("model")
if isinstance(model_cfg, dict):
config_base_url = (model_cfg.get("base_url") or "").strip()
except Exception:
pass
if config_base_url or get_env_value("OPENAI_BASE_URL"):
effective = "custom"

return provider_label(effective)

Expand Down Expand Up @@ -412,17 +425,6 @@ def _resolve_env(env_ref) -> str:
elif terminal_env == "daytona":
daytona_image = os.getenv("TERMINAL_DAYTONA_IMAGE", "nikolaik/python-nodejs:python3.11-nodejs20")
print(f" Daytona Image: {daytona_image}")
elif terminal_env == "tenki":
tenki_image = os.getenv("TERMINAL_TENKI_IMAGE", "")
tenki_endpoint = os.getenv("TERMINAL_TENKI_API_ENDPOINT", "https://api.tenki.cloud")
tenki_workspace = os.getenv("TERMINAL_TENKI_WORKSPACE_ID", "")
tenki_project = os.getenv("TERMINAL_TENKI_PROJECT_ID", "")
tenki_sync = os.getenv("TERMINAL_TENKI_SYNC_HERMES_HOME", "false").lower() in {"true", "1", "yes"}
print(f" Tenki Image: {tenki_image or '(Tenki default)'}")
print(f" Endpoint: {tenki_endpoint}")
print(f" Workspace: {tenki_workspace or '(from Tenki CLI)'}")
print(f" Project: {tenki_project or '(from Tenki CLI)'}")
print(f" Sync .hermes: {check_mark(tenki_sync)} {'enabled' if tenki_sync else 'disabled'}")

sudo_password = os.getenv("SUDO_PASSWORD", "")
print(f" Sudo: {check_mark(bool(sudo_password))} {'enabled' if sudo_password else 'disabled'}")
Expand Down
1 change: 1 addition & 0 deletions scripts/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
AUTHOR_MAP = {
"ai-lab@foxmail.com": "CrazyBoyM", # PR #55828 salvage (image_gen openai-codex: wire image-to-image / reference-image editing via Codex Responses input_image parts; magic-byte + read-guard + 25MB-cap + clamp-to-16 hardening)
"r0gersm1th@users.noreply.github.com": "r0gersm1th", # PR #3219 salvage (whatsapp bridge: resolve LID sender IDs to phone numbers in the message payload so phone-based allowlists match; commit authored by collaborator r0gersm1th, PR by @ajmeese7)
"louis@letsfive.io": "Mibayy", # PR #3296 salvage (status: provider label honors config.yaml model.base_url, not just OPENAI_BASE_URL env)
"tarunravi@gmail.com": "tarunravi", # PR #2696 salvage (api-server: inline MEDIA:<path> image tags as base64 data URLs in final responses so remote OpenAI-compatible frontends can render server-local screenshots; the PR's tool-progress-streaming and SSE-sentinel pieces were independently superseded on main)
"aqdrgg19@gmail.com": "VolodymyrBg", # PR #2861 salvage (webhook: drop the unused full request payload from retained _delivery_info entries — up to ~1MB dead weight per delivery for the 1h idempotency TTL)
"ohyes9711@gmail.com": "CharmingGroot", # PR #2794 salvage (email: guard msg_data[0][1] against malformed IMAP fetch structures so one bad response can't abort the batch and permanently lose seen-marked messages; Message-ID domain falls back to localhost when EMAIL_ADDRESS lacks '@')
Expand Down
41 changes: 41 additions & 0 deletions tests/hermes_cli/test_status_provider_label.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""`hermes status` provider label honors config.yaml model.base_url (#3296)."""

from unittest.mock import patch

from hermes_cli.status import _effective_provider_label


def _label_with(config, env_base_url=""):
with patch("hermes_cli.status.resolve_requested_provider", return_value="auto"), \
patch("hermes_cli.status.resolve_provider", return_value="openrouter"), \
patch("hermes_cli.status.load_config", return_value=config), \
patch("hermes_cli.status.get_env_value",
side_effect=lambda k: env_base_url if k == "OPENAI_BASE_URL" else ""):
return _effective_provider_label()


def test_config_base_url_labels_custom():
label = _label_with({"model": {"base_url": "http://localhost:8080/v1"}})
assert "OpenRouter" not in label


def test_env_base_url_labels_custom():
label = _label_with({"model": {}}, env_base_url="http://localhost:1234/v1")
assert "OpenRouter" not in label


def test_no_base_url_stays_openrouter():
label = _label_with({"model": {}})
assert "OpenRouter" in label


def test_blank_base_url_stays_openrouter():
label = _label_with({"model": {"base_url": " "}})
assert "OpenRouter" in label


def test_non_openrouter_provider_untouched():
with patch("hermes_cli.status.resolve_requested_provider", return_value="anthropic"), \
patch("hermes_cli.status.resolve_provider", return_value="anthropic"):
label = _effective_provider_label()
assert "OpenRouter" not in label
Loading