fix(config): load discord.reply_to_mode from config.yaml into DISCORD_REPLY_TO_MODE

discord.reply_to_mode (and discord.extra.reply_to_mode) in config.yaml was
silently ignored — the gateway only honoured the DISCORD_REPLY_TO_MODE env
var, leaving the YAML setting with no effect.

Apply the same env-var bridge already used for require_mention, auto_thread,
free_response_channels, etc.  Also handles YAML 1.1 bare 'off' (parsed as
boolean False) correctly.

Top-level discord.reply_to_mode takes precedence over discord.extra.reply_to_mode;
a pre-existing DISCORD_REPLY_TO_MODE env var is never overwritten.
This commit is contained in:
Matteo De Agazio 2026-04-14 21:15:55 +02:00
parent b7e71fb727
commit 0267ae0b49
2 changed files with 76 additions and 1 deletions

View file

@ -655,6 +655,17 @@ def load_gateway_config() -> GatewayConfig:
):
if yaml_key in allow_mentions_cfg and not os.getenv(env_key):
os.environ[env_key] = str(allow_mentions_cfg[yaml_key]).lower()
# reply_to_mode: whether bot replies reference the triggering message (off/first/all)
# Supported at top-level (discord.reply_to_mode) or nested (discord.extra.reply_to_mode)
# Note: YAML 1.1 parses bare 'off' as boolean False, so we handle that explicitly.
_extra = discord_cfg.get("extra") if isinstance(discord_cfg.get("extra"), dict) else {}
_rtp_sources = (
discord_cfg["reply_to_mode"] if "reply_to_mode" in discord_cfg
else _extra.get("reply_to_mode")
)
if _rtp_sources is not None and not os.getenv("DISCORD_REPLY_TO_MODE"):
_rtp_str = "off" if _rtp_sources is False else str(_rtp_sources).lower()
os.environ["DISCORD_REPLY_TO_MODE"] = _rtp_str
# Telegram settings → env vars (env vars take precedence)
telegram_cfg = yaml_cfg.get("telegram", {})

View file

@ -15,7 +15,7 @@ from unittest.mock import MagicMock, AsyncMock, patch
import pytest
from gateway.config import PlatformConfig, GatewayConfig, Platform, _apply_env_overrides
from gateway.config import PlatformConfig, GatewayConfig, Platform, _apply_env_overrides, load_gateway_config
def _ensure_discord_mock():
@ -396,3 +396,67 @@ class TestReplyToText:
event = reply_text_adapter.handle_message.await_args.args[0]
assert event.reply_to_message_id == "555"
assert event.reply_to_text is None
class TestYamlConfigLoading:
"""Tests for reply_to_mode loaded from config.yaml discord section."""
def _write_config(self, tmp_path, content: str):
hermes_home = tmp_path / ".hermes"
hermes_home.mkdir()
(hermes_home / "config.yaml").write_text(content, encoding="utf-8")
return hermes_home
def test_top_level_reply_to_mode_off(self, tmp_path, monkeypatch):
"""discord.reply_to_mode: off sets DISCORD_REPLY_TO_MODE env var."""
hermes_home = self._write_config(tmp_path, "discord:\n reply_to_mode: off\n")
monkeypatch.setenv("HERMES_HOME", str(hermes_home))
monkeypatch.delenv("DISCORD_REPLY_TO_MODE", raising=False)
load_gateway_config()
assert os.environ.get("DISCORD_REPLY_TO_MODE") == "off"
def test_top_level_reply_to_mode_all(self, tmp_path, monkeypatch):
hermes_home = self._write_config(tmp_path, "discord:\n reply_to_mode: all\n")
monkeypatch.setenv("HERMES_HOME", str(hermes_home))
monkeypatch.delenv("DISCORD_REPLY_TO_MODE", raising=False)
load_gateway_config()
assert os.environ.get("DISCORD_REPLY_TO_MODE") == "all"
def test_extra_reply_to_mode_off(self, tmp_path, monkeypatch):
"""discord.extra.reply_to_mode: off is also honoured."""
hermes_home = self._write_config(
tmp_path, "discord:\n extra:\n reply_to_mode: \"off\"\n"
)
monkeypatch.setenv("HERMES_HOME", str(hermes_home))
monkeypatch.delenv("DISCORD_REPLY_TO_MODE", raising=False)
load_gateway_config()
assert os.environ.get("DISCORD_REPLY_TO_MODE") == "off"
def test_env_var_takes_precedence_over_yaml(self, tmp_path, monkeypatch):
"""Existing DISCORD_REPLY_TO_MODE env var is not overwritten by YAML."""
hermes_home = self._write_config(tmp_path, "discord:\n reply_to_mode: all\n")
monkeypatch.setenv("HERMES_HOME", str(hermes_home))
monkeypatch.setenv("DISCORD_REPLY_TO_MODE", "first")
load_gateway_config()
assert os.environ.get("DISCORD_REPLY_TO_MODE") == "first"
def test_top_level_takes_precedence_over_extra(self, tmp_path, monkeypatch):
"""discord.reply_to_mode wins over discord.extra.reply_to_mode."""
hermes_home = self._write_config(
tmp_path,
"discord:\n reply_to_mode: all\n extra:\n reply_to_mode: \"off\"\n",
)
monkeypatch.setenv("HERMES_HOME", str(hermes_home))
monkeypatch.delenv("DISCORD_REPLY_TO_MODE", raising=False)
load_gateway_config()
assert os.environ.get("DISCORD_REPLY_TO_MODE") == "all"