From 9025c7088fe834a75addc72efc00630174da911f Mon Sep 17 00:00:00 2001 From: Kim <150593189+KimGLee@users.noreply.github.com> Date: Mon, 23 Feb 2026 12:28:21 +0800 Subject: [PATCH] fix(heartbeat): route heartbeat runs to enabled chat context --- nanobot/cli/commands.py | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/nanobot/cli/commands.py b/nanobot/cli/commands.py index f1f9b30..b2f6bd3 100644 --- a/nanobot/cli/commands.py +++ b/nanobot/cli/commands.py @@ -389,11 +389,36 @@ def gateway( return response cron.on_job = on_cron_job + # Create channel manager + channels = ChannelManager(config, bus) + + def _pick_heartbeat_target() -> tuple[str, str]: + """Pick a routable channel/chat target for heartbeat-triggered messages.""" + enabled = set(channels.enabled_channels) + # Prefer the most recently updated non-internal session on an enabled channel. + for item in session_manager.list_sessions(): + key = item.get("key") or "" + if ":" not in key: + continue + channel, chat_id = key.split(":", 1) + if channel in {"cli", "system"}: + continue + if channel in enabled and chat_id: + return channel, chat_id + # Fallback keeps prior behavior but remains explicit. + return "cli", "direct" + # Create heartbeat service async def on_heartbeat(prompt: str) -> str: """Execute heartbeat through the agent.""" - return await agent.process_direct(prompt, session_key="heartbeat") - + channel, chat_id = _pick_heartbeat_target() + return await agent.process_direct( + prompt, + session_key="heartbeat", + channel=channel, + chat_id=chat_id, + ) + heartbeat = HeartbeatService( workspace=config.workspace_path, on_heartbeat=on_heartbeat, @@ -401,9 +426,6 @@ def gateway( enabled=True ) - # Create channel manager - channels = ChannelManager(config, bus) - if channels.enabled_channels: console.print(f"[green]✓[/green] Channels enabled: {', '.join(channels.enabled_channels)}") else: