diff --git a/gateway/platforms/base.py b/gateway/platforms/base.py index a37240b4cc..5bb855b722 100644 --- a/gateway/platforms/base.py +++ b/gateway/platforms/base.py @@ -285,19 +285,24 @@ def should_bypass_proxy(target_hosts: str | list[str] | tuple[str, ...] | set[st def resolve_proxy_url( platform_env_var: str | None = None, *, - target_hosts: str | list[str] | tuple[str, ...] | set[str] | None = None) -> str | None: - """Proxy URL: *platform_env_var* (e.g. ``DISCORD_PROXY``) first, then HTTPS_PROXY / - HTTP_PROXY / ALL_PROXY (any case), then the macOS system proxy — the latter two only when - ``gateway.trust_env`` is true. None when nothing is found or NO_PROXY matches a target. + target_hosts: str | list[str] | tuple[str, ...] | set[str] | None = None, + configured: str | None = None) -> str | None: + """Proxy URL: *platform_env_var* (e.g. ``DISCORD_PROXY``) first, then the adapter's own YAML + value *configured* (``telegram.proxy_url``), then HTTPS_PROXY / HTTP_PROXY / ALL_PROXY (any + case), then the macOS system proxy — the latter two only when ``gateway.trust_env`` is true. + None when nothing is found or NO_PROXY matches a target. *platform_env_var* is a per-adapter, per-profile-configurable setting (each proxy URL can embed credentials, e.g. ``http://user:pass@host``) so it is read scope-aware: under a secondary multiplex profile it comes from that profile's own ``.env``, not the shared - process env another profile's ``TELEGRAM_PROXY``/``DISCORD_PROXY``/etc. may hold. The - generic ``HTTPS_PROXY``/``HTTP_PROXY``/``ALL_PROXY`` fallback stays a raw process-env read — - those are OS/system-level network settings, not a per-profile Hermes concept.""" + process env another profile's ``TELEGRAM_PROXY``/``DISCORD_PROXY``/etc. may hold; the YAML + value is the same profile's, so a secondary keeps its configured route without any env + bridge (#108440). The generic ``HTTPS_PROXY``/``HTTP_PROXY``/``ALL_PROXY`` fallback stays a raw + process-env read — those are OS/system-level network settings, not a per-profile Hermes concept.""" from gateway.platforms._shared import get_scoped_secret as _get_scoped_proxy_var value = (_get_scoped_proxy_var(platform_env_var, "") or "").strip() if platform_env_var else "" + if not value: + value = str(configured or "").strip() if not value: if not gateway_trust_env(): # only the explicit per-platform var is honored return None diff --git a/plugins/platforms/telegram/adapter.py b/plugins/platforms/telegram/adapter.py index b1adc6f248..a10ef88b06 100644 --- a/plugins/platforms/telegram/adapter.py +++ b/plugins/platforms/telegram/adapter.py @@ -2797,7 +2797,9 @@ class TelegramAdapter(BasePlatformAdapter): fallback_ips = list(SEED_FALLBACK_IPS) else: logger.info("[%s] Auto-discovered Telegram fallback IPs: %s", self.name, ", ".join(fallback_ips)) - proxy_url = resolve_proxy_url("TELEGRAM_PROXY", target_hosts=["api.telegram.org", *fallback_ips]) + proxy_url = resolve_proxy_url( + "TELEGRAM_PROXY", target_hosts=["api.telegram.org", *fallback_ips], + configured=self.config.extra.get("proxy_url")) def _pair(general_httpx: dict, updates_httpx: dict, **extra) -> tuple: return (HTTPXRequest(**request_kwargs, **extra, httpx_kwargs=general_httpx), @@ -6563,6 +6565,8 @@ def _apply_yaml_config(yaml_cfg: dict, telegram_cfg: dict) -> dict | None: _bridge_gate(key, env, telegram_cfg.get(key), seed_extra=seed) _bridge_lower("reactions", "TELEGRAM_REACTIONS") if "proxy_url" in telegram_cfg: + # Seeded into extra so ``_build_ptb_requests`` keeps a secondary's route without the env bridge. + extras.setdefault("proxy_url", str(telegram_cfg["proxy_url"]).strip()) _set_env("TELEGRAM_PROXY", str(telegram_cfg["proxy_url"]).strip()) _telegram_extra = telegram_cfg.get("extra") if isinstance(telegram_cfg.get("extra"), dict) else {} _telegram_rtm = telegram_cfg["reply_to_mode"] if "reply_to_mode" in telegram_cfg else _telegram_extra.get("reply_to_mode") diff --git a/tests/gateway/test_telegram_polling_progress.py b/tests/gateway/test_telegram_polling_progress.py index a2176d108d..681c9bdd22 100644 --- a/tests/gateway/test_telegram_polling_progress.py +++ b/tests/gateway/test_telegram_polling_progress.py @@ -326,7 +326,7 @@ async def test_fallback_disabled_excludes_configured_ips_from_proxy_targets(monk proxy_targets = [] - def resolve_proxy(_env_name, *, target_hosts): + def resolve_proxy(_env_name, *, target_hosts, configured=None): proxy_targets.append(list(target_hosts)) return "http://127.0.0.1:8080"