feat(telegram): add new slash commands and update regex for command handling

This commit is contained in:
Xubin Ren 2026-05-15 17:55:52 +00:00
parent 0f96ab7e70
commit 9ccef018c2
2 changed files with 27 additions and 1 deletions

View File

@ -261,12 +261,21 @@ class TelegramChannel(BaseChannel):
BotCommand("restart", "Restart the bot"),
BotCommand("status", "Show bot status"),
BotCommand("history", "Show recent conversation messages"),
BotCommand("goal", "Start a sustained objective (long-running task)"),
BotCommand("pairing", "Manage DM pairing (approve/deny/list)"),
BotCommand("model", "Switch runtime model preset"),
BotCommand("dream", "Run Dream memory consolidation now"),
BotCommand("dream_log", "Show the latest Dream memory change"),
BotCommand("dream_restore", "Restore Dream memory to an earlier version"),
BotCommand("help", "Show available commands"),
]
# Regex for slash commands routed to AgentLoop via ``_forward_command``.
# Hyphenated ``dream-*`` commands stay on a separate handler (below).
TELEGRAM_BUS_SLASH_COMMAND_RE = re.compile(
r"^/(?:new|stop|restart|status|dream|history|goal|pairing|model)(?:@\w+)?(?:\s+.*)?$"
)
@classmethod
def default_config(cls) -> dict[str, Any]:
return TelegramConfig().model_dump(by_alias=True)
@ -354,7 +363,7 @@ class TelegramChannel(BaseChannel):
self._app.add_handler(MessageHandler(filters.Regex(r"^/start(?:@\w+)?$"), self._on_start))
self._app.add_handler(
MessageHandler(
filters.Regex(r"^/(new|stop|restart|status|dream)(?:@\w+)?(?:\s+.*)?$"),
filters.Regex(TelegramChannel.TELEGRAM_BUS_SLASH_COMMAND_RE),
self._forward_command,
)
)

View File

@ -1294,6 +1294,20 @@ async def test_forward_command_normalizes_telegram_safe_dream_aliases() -> None:
assert handled[0]["content"] == "/dream-restore deadbeef"
def test_telegram_bus_slash_command_regex_matches_agent_loop_commands() -> None:
"""Bus-routed slash commands must match the Telegram handler regex (see builtin router)."""
pat = TelegramChannel.TELEGRAM_BUS_SLASH_COMMAND_RE
assert pat.fullmatch("/history")
assert pat.fullmatch("/history 5")
assert pat.fullmatch("/goal ship the feature")
assert pat.fullmatch("/pairing list")
assert pat.fullmatch("/model fast")
assert pat.fullmatch("/new@nanobot_bot")
assert pat.fullmatch("/goal@nanobot_bot refine objective")
assert pat.fullmatch("/dream-log deadbeef") is None
assert pat.fullmatch("/dream-restore deadbeef") is None
@pytest.mark.asyncio
async def test_on_help_includes_restart_command() -> None:
channel = TelegramChannel(
@ -1311,6 +1325,9 @@ async def test_on_help_includes_restart_command() -> None:
assert "/status" in help_text
assert "/dream" in help_text
assert "/dream-log" in help_text
assert "/goal" in help_text
assert "/pairing" in help_text
assert "/model" in help_text
assert "/dream-restore" in help_text