fix(llm): honor openrouter_app_title only alongside a custom referer (#453)

OpenRouter keys app pages by HTTP-Referer; X-Title only renames that
page. A custom openrouter_app_title on the default referer therefore
renamed the shared EvoScientist app page for everyone. Force the default
title whenever the resolved referer is the default, silently, so usage
keeps being attributed to EvoScientist; a private fork still overrides
both together.
This commit is contained in:
Xi Zhang
2026-09-07 17:22:18 +08:00
committed by GitHub
parent dae67e9299
commit b36c19a22a
3 changed files with 37 additions and 1 deletions
+3 -1
View File
@@ -334,7 +334,9 @@ class EvoScientistConfig:
openrouter_anthropic_prompt_cache: bool = True
# OpenRouter app attribution (issue #339). Sent only for the openrouter
# provider; identifies EvoScientist in OpenRouter's app rankings/analytics.
# Override (e.g. a private fork) via these fields or their env vars.
# Override (e.g. a private fork) via these fields or their env vars. A custom
# title only takes effect together with a custom referer: OpenRouter keys app
# pages by referer, so a lone title would rename the shared EvoScientist page.
# Defaults live in the module constants above (also imported by llm/models.py).
openrouter_http_referer: str = OPENROUTER_DEFAULT_HTTP_REFERER
openrouter_app_title: str = OPENROUTER_DEFAULT_APP_TITLE
+5
View File
@@ -501,6 +501,11 @@ def get_chat_model(
os.environ.get("EVOSCIENTIST_OPENROUTER_APP_TITLE", "").strip()
or OPENROUTER_DEFAULT_APP_TITLE,
)
# OpenRouter keys app pages by HTTP-Referer and X-Title only renames that
# page, so a custom title on the default referer would rename the shared
# EvoScientist page for everyone. Honor it only with a custom referer.
if kwargs["app_url"] == OPENROUTER_DEFAULT_HTTP_REFERER:
kwargs["app_title"] = OPENROUTER_DEFAULT_APP_TITLE
# app_categories must be a list[str] (langchain-openrouter joins it into
# the X-OpenRouter-Categories header); split the comma-separated config
# value and drop blanks so a stray comma/space can't emit an empty one.
+29
View File
@@ -1,5 +1,6 @@
"""Tests for EvoScientist LLM module."""
import warnings
from unittest.mock import patch
import pytest
@@ -864,6 +865,34 @@ class TestThirdPartyRouting:
# An explicit list is preserved verbatim, not re-split.
assert call_kwargs["app_categories"] == ["only-this"]
@pytest.mark.parametrize("source", ["env", "kwarg"])
@patch("EvoScientist.llm.models.init_chat_model")
def test_openrouter_title_override_without_referer_falls_back_silently(
self, mock_init, monkeypatch, source
):
"""OpenRouter keys app pages by HTTP-Referer, so a custom title on the
default referer would rename the shared EvoScientist page. It is
replaced by the default title, without any user-facing warning,
whether the title came from the env (config) or an explicit kwarg."""
mock_init.return_value = "mock_model"
monkeypatch.setenv("OPENROUTER_API_KEY", "or-key")
for _env in self._APP_ATTR_ENV:
monkeypatch.delenv(_env, raising=False)
extra = {}
if source == "env":
monkeypatch.setenv("EVOSCIENTIST_OPENROUTER_APP_TITLE", "Acme")
else:
extra["app_title"] = "Acme"
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
get_chat_model("x-ai/grok-4.3", provider="openrouter", **extra)
assert not [w for w in caught if "openrouter" in str(w.message).lower()]
call_kwargs = mock_init.call_args[1]
assert call_kwargs["app_url"] == "https://github.com/EvoScientist/EvoScientist"
assert call_kwargs["app_title"] == "EvoScientist"
@patch("EvoScientist.llm.models.init_chat_model")
def test_non_openrouter_providers_get_no_app_attribution(
self, mock_init, monkeypatch