#135348 ran ruff's UP037 autofix with ruff.strict.toml's target-version = "py314". On 3.14
annotations are lazy (PEP 649), so stripping quotes is safe there; on 3.11-3.13 a function or
variable annotation is evaluated when the def or statement runs. Every unquoted annotation that
names the enclosing class (`def clone_for_agent(self) -> ContextEngine`), a class bound later in
the module, or a TYPE_CHECKING-only import now raises NameError on import: 300 modules on main
(gateway.config, run_agent, hermes_state, cron.jobs, the Telegram adapter, ...) fail to import
under 3.11, the update path crashes mid-`hermes update` on any install whose interpreter is
older than 3.14, and the e2e-upgrade suite's retry leg fails with
`NameError: name 'ContextEngine' is not defined`.
- Re-quote exactly the 79 annotations (36 files) that name something unbound when they are
evaluated (including tui_gateway/server.py's `_TurnScopes`, which only reaches that module's
globals through register() after import); no other text changes.
- agent/turn_scripted_prelude.py: `Generator[...]` gets its third argument back. d76cce4f11
applied UP043 (default type args, valid only from 3.13) to a module-level alias, so
`Generator[Y, S]` raises TypeError on 3.11/3.12 and takes gateway.run, agent.conversation_loop
and tui_gateway.{server,ws,entry} down with it.
- ruff.strict.toml target-version = "py311", the requires-python floor. With it UP037 leaves
these quotes alone and only strips the two that are genuinely redundant, which this commit
strips; any future version-gated fix stays valid on every supported Python.
- tests/ci/test_strict_ruff_target.py pins the target to the requires-python floor (red on main).
54 lines
2.4 KiB
Python
54 lines
2.4 KiB
Python
"""Telegram group addressing helpers, kept out of the adapter facade.
|
|
|
|
The identity line lives in ``channel_prompt`` and therefore in the cached-agent signature: it
|
|
must be stable for the life of a session (username only — never a per-message fact).
|
|
"""
|
|
|
|
from typing import TYPE_CHECKING, Optional
|
|
|
|
if TYPE_CHECKING:
|
|
from telegram import Message
|
|
from plugins.platforms.telegram.adapter import TelegramAdapter
|
|
|
|
|
|
def mentions_other_participants(adapter: "TelegramAdapter", message: "Message") -> bool:
|
|
"""True when a ``mention``/``text_mention`` entity names someone other than this bot."""
|
|
own = adapter._current_bot_username()
|
|
bot_id = getattr(adapter._bot, "id", None) if adapter._bot else None
|
|
for source_text, entities in adapter._entity_sources(message):
|
|
for entity in entities:
|
|
entity_type = adapter._entity_type(entity)
|
|
if entity_type == "mention":
|
|
handle = (adapter._entity_span(source_text, entity) or "").strip().lstrip("@").lower()
|
|
if handle and handle != own:
|
|
return True
|
|
elif entity_type == "text_mention":
|
|
user = getattr(entity, "user", None)
|
|
if user is not None and getattr(user, "id", None) != bot_id:
|
|
return True
|
|
return False
|
|
|
|
|
|
def group_trigger_text(adapter: "TelegramAdapter", message: "Message", text: Optional[str]) -> Optional[str]:
|
|
"""Strip our own handle only when we are the sole addressee. With other participants named,
|
|
``@research_bot , @ops_bot are you both listening?`` must not reach us as ``, @ops_bot …``."""
|
|
if adapter._is_group_chat(message) and mentions_other_participants(adapter, message):
|
|
return text
|
|
return adapter._clean_bot_trigger_text(text)
|
|
|
|
|
|
def group_identity_prompt(
|
|
adapter: "TelegramAdapter", message: "Message", channel_prompt: Optional[str],
|
|
) -> Optional[str]:
|
|
"""Session-stable identity line so the model can read retained @mentions as itself or not."""
|
|
if not adapter._is_group_chat(message) or not getattr(adapter, "_bot", None):
|
|
return channel_prompt
|
|
username = adapter._current_bot_username()
|
|
if not username:
|
|
return channel_prompt
|
|
identity = (
|
|
f"Your Telegram bot username in this group: @{username}. "
|
|
"Mentions of other bots are not requests for you to relay the message."
|
|
)
|
|
return f"{channel_prompt}\n\n{identity}" if channel_prompt else identity
|