feat(telegram): add disable_topic_auto_rename gateway flag

When Hermes auto-titles a session in a Telegram DM topic it currently
renames the topic itself to the generated title. That works for
operator-managed lanes (extra.dm_topics) but is disruptive for
ad-hoc Threaded-Mode topics that users name by hand — every first
exchange overwrites their chosen title.

Add gateway.platforms.telegram.extra.disable_topic_auto_rename (default
False, preserving prior behaviour). When set, both
_schedule_telegram_topic_title_rename and the underlying
_rename_telegram_topic_for_session_title short-circuit before touching
the Telegram API. Internal session titles (sessions list, TUI) keep
working unchanged.

Also bridge the legacy top-level telegram.disable_topic_auto_rename key
through to gateway.platforms.telegram.extra so users on the older
config layout don't have to migrate to enable it.

- Tests cover the runtime flag, the scheduling entry-point, and string
  truthiness coercion for YAML-loaded values.
- Docs updated in messaging/telegram.md with an example block.
This commit is contained in:
B0Tch1
2026-05-18 06:08:54 +08:00
committed by Teknium
parent 3ec28f34ca
commit 9d789f3a5b
4 changed files with 134 additions and 0 deletions

View File

@@ -1002,6 +1002,16 @@ def load_gateway_config() -> GatewayConfig:
# Telegram settings → env vars (env vars take precedence)
telegram_cfg = yaml_cfg.get("telegram", {})
if isinstance(telegram_cfg, dict):
# Bridge top-level legacy `telegram.disable_topic_auto_rename` into
# gateway.platforms.telegram.extra so the runtime config sees it.
# Read as a runtime-config flag, not env-var (no need for env override).
if "disable_topic_auto_rename" in telegram_cfg:
_tg_plat = platforms_data.setdefault(Platform.TELEGRAM.value, {})
_tg_extra = _tg_plat.setdefault("extra", {})
_tg_extra.setdefault(
"disable_topic_auto_rename",
telegram_cfg["disable_topic_auto_rename"],
)
# Prefer telegram.require_mention; fall back to the top-level shorthand.
_effective_rm = telegram_cfg.get("require_mention", yaml_cfg.get("require_mention"))
if _effective_rm is not None and not os.getenv("TELEGRAM_REQUIRE_MENTION"):

View File

@@ -11808,6 +11808,13 @@ class GatewayRunner:
if not self._is_telegram_topic_lane(source) or not source.chat_id or not source.thread_id:
return
# Operator can fully disable per-topic auto-rename via
# extra.disable_topic_auto_rename. Useful when topics are managed
# by the user (ad-hoc Threaded Mode) and auto-rename would
# overwrite their chosen names every time the auto-title fires.
if self._telegram_topic_auto_rename_disabled(source):
return
# Skip rename when the topic is operator-declared via
# extra.dm_topics. Those topics have fixed names chosen by the
# operator (plus optional skill binding); auto-renaming would
@@ -11876,6 +11883,29 @@ class GatewayRunner:
except Exception:
logger.debug("Failed to rename Telegram topic for auto-generated title", exc_info=True)
def _telegram_topic_auto_rename_disabled(self, source: SessionSource) -> bool:
"""Return True when operator disabled per-topic auto-rename for this Telegram chat.
Controlled via ``gateway.platforms.telegram.extra.disable_topic_auto_rename``.
Default is False (auto-rename enabled, preserves prior behaviour).
"""
platform_cfg = (
self.config.platforms.get(source.platform)
if getattr(self, "config", None) and getattr(self.config, "platforms", None)
else None
)
if platform_cfg is None:
return False
extra = getattr(platform_cfg, "extra", None) or {}
value = extra.get("disable_topic_auto_rename")
if value is None:
return False
if isinstance(value, bool):
return value
if isinstance(value, str):
return value.strip().lower() in {"1", "true", "yes", "on"}
return bool(value)
def _schedule_telegram_topic_title_rename(
self,
source: SessionSource,
@@ -11885,6 +11915,8 @@ class GatewayRunner:
"""Schedule a topic rename from the auto-title background thread."""
if not title or not self._is_telegram_topic_lane(source):
return
if self._telegram_topic_auto_rename_disabled(source):
return
try:
loop = asyncio.get_running_loop()
except RuntimeError: