diff --git a/nanobot/channels/telegram.py b/nanobot/channels/telegram.py index 916b9ba64..439d1c4d9 100644 --- a/nanobot/channels/telegram.py +++ b/nanobot/channels/telegram.py @@ -275,13 +275,10 @@ class TelegramChannel(BaseChannel): self._app = builder.build() self._app.add_error_handler(self._on_error) - # Add command handlers - self._app.add_handler(CommandHandler("start", self._on_start)) - self._app.add_handler(CommandHandler("new", self._forward_command)) - self._app.add_handler(CommandHandler("stop", self._forward_command)) - self._app.add_handler(CommandHandler("restart", self._forward_command)) - self._app.add_handler(CommandHandler("status", self._forward_command)) - self._app.add_handler(CommandHandler("help", self._on_help)) + # Add command handlers (using Regex to support @username suffixes before bot initialization) + 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)(?:@\w+)?$"), self._forward_command)) + self._app.add_handler(MessageHandler(filters.Regex(r"^/help(?:@\w+)?$"), self._on_help)) # Add message handler for text, photos, voice, documents self._app.add_handler( @@ -765,10 +762,18 @@ class TelegramChannel(BaseChannel): message = update.message user = update.effective_user self._remember_thread_context(message) + + # Strip @bot_username suffix if present + content = message.text or "" + if content.startswith("/") and "@" in content: + cmd_part, *rest = content.split(" ", 1) + cmd_part = cmd_part.split("@")[0] + content = f"{cmd_part} {rest[0]}" if rest else cmd_part + await self._handle_message( sender_id=self._sender_id(user), chat_id=str(message.chat_id), - content=message.text or "", + content=content, metadata=self._build_message_metadata(message, user), session_key=self._derive_topic_session_key(message), ) diff --git a/nanobot/command/builtin.py b/nanobot/command/builtin.py index 97fefe6cf..265f4c0ed 100644 --- a/nanobot/command/builtin.py +++ b/nanobot/command/builtin.py @@ -26,7 +26,10 @@ async def cmd_stop(ctx: CommandContext) -> OutboundMessage: sub_cancelled = await loop.subagents.cancel_by_session(msg.session_key) total = cancelled + sub_cancelled content = f"Stopped {total} task(s)." if total else "No active task to stop." - return OutboundMessage(channel=msg.channel, chat_id=msg.chat_id, content=content) + return OutboundMessage( + channel=msg.channel, chat_id=msg.chat_id, content=content, + metadata=dict(msg.metadata or {}) + ) async def cmd_restart(ctx: CommandContext) -> OutboundMessage: @@ -38,7 +41,10 @@ async def cmd_restart(ctx: CommandContext) -> OutboundMessage: os.execv(sys.executable, [sys.executable, "-m", "nanobot"] + sys.argv[1:]) asyncio.create_task(_do_restart()) - return OutboundMessage(channel=msg.channel, chat_id=msg.chat_id, content="Restarting...") + return OutboundMessage( + channel=msg.channel, chat_id=msg.chat_id, content="Restarting...", + metadata=dict(msg.metadata or {}) + ) async def cmd_status(ctx: CommandContext) -> OutboundMessage: @@ -62,7 +68,7 @@ async def cmd_status(ctx: CommandContext) -> OutboundMessage: session_msg_count=len(session.get_history(max_messages=0)), context_tokens_estimate=ctx_est, ), - metadata={"render_as": "text"}, + metadata={**dict(ctx.msg.metadata or {}), "render_as": "text"}, ) @@ -79,6 +85,7 @@ async def cmd_new(ctx: CommandContext) -> OutboundMessage: return OutboundMessage( channel=ctx.msg.channel, chat_id=ctx.msg.chat_id, content="New session started.", + metadata=dict(ctx.msg.metadata or {}) ) @@ -122,7 +129,7 @@ async def cmd_help(ctx: CommandContext) -> OutboundMessage: channel=ctx.msg.channel, chat_id=ctx.msg.chat_id, content=build_help_text(), - metadata={"render_as": "text"}, + metadata={**dict(ctx.msg.metadata or {}), "render_as": "text"}, )