From 468dfc406bfdd96eb6049852f679336f8d13bbf2 Mon Sep 17 00:00:00 2001 From: VITOHJL Date: Sun, 1 Mar 2026 17:05:04 +0800 Subject: [PATCH 1/2] feat(cron): improve cron job context handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improve cron job execution context to ensure proper message delivery and session history recording. Changes: - Add [绯荤粺瀹氭椂浠诲姟] prefix to cron reminder messages to clearly mark them as system-driven, not user queries - Use user role for cron reminder messages (required by some LLM APIs) - Properly handle MessageTool to avoid duplicate message delivery - Correctly save turn history with proper skip count - Ensure Runtime Context is included in the message list This ensures that: 1. Cron jobs execute with proper context 2. Messages are correctly delivered to users 3. Session history accurately records cron job interactions 4. The LLM understands these are system-driven reminders, not user queries --- nanobot/cli/commands.py | 51 ++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/nanobot/cli/commands.py b/nanobot/cli/commands.py index 4987c84..4b70f32 100644 --- a/nanobot/cli/commands.py +++ b/nanobot/cli/commands.py @@ -295,20 +295,55 @@ def gateway( # Set cron callback (needs agent) async def on_cron_job(job: CronJob) -> str | None: """Execute a cron job through the agent.""" - response = await agent.process_direct( - job.payload.message, - session_key=f"cron:{job.id}", - channel=job.payload.channel or "cli", - chat_id=job.payload.to or "direct", + from nanobot.agent.tools.message import MessageTool + + cron_session_key = f"cron:{job.id}" + cron_session = agent.sessions.get_or_create(cron_session_key) + + reminder_note = ( + f"[系统定时任务] ⏰ 计时已结束\n\n" + f"定时任务 '{job.name}' 已触发。定时内容:{job.payload.message}\n\n" ) - if job.payload.deliver and job.payload.to: + + cron_session.add_message(role="user", content=reminder_note) + agent.sessions.save(cron_session) + + agent._set_tool_context( + job.payload.channel or "cli", + job.payload.to or "direct", + None + ) + + message_tool = agent.tools.get("message") + if isinstance(message_tool, MessageTool): + message_tool.start_turn() + + history = cron_session.get_history(max_messages=agent.memory_window) + + messages = [ + {"role": "system", "content": agent.context.build_system_prompt()}, + *history, + {"role": "user", "content": agent.context._build_runtime_context( + job.payload.channel or "cli", + job.payload.to or "direct" + )}, + ] + + final_content, _, all_msgs = await agent._run_agent_loop(messages) + agent._save_turn(cron_session, all_msgs, 1 + len(history) + 1) + agent.sessions.save(cron_session) + + if isinstance(message_tool, MessageTool) and message_tool._sent_in_turn: + return final_content + + if job.payload.deliver and job.payload.to and final_content: from nanobot.bus.events import OutboundMessage await bus.publish_outbound(OutboundMessage( channel=job.payload.channel or "cli", chat_id=job.payload.to, - content=response or "" + content=final_content )) - return response + return final_content cron.on_job = on_cron_job # Create channel manager From a7d24192d94c413c035284e7f1905666c63bed80 Mon Sep 17 00:00:00 2001 From: Re-bin Date: Sun, 1 Mar 2026 12:45:53 +0000 Subject: [PATCH 2/2] fix(cron): route scheduled jobs through process_direct with english reminder prefix --- nanobot/cli/commands.py | 53 ++++++++++++----------------------------- 1 file changed, 15 insertions(+), 38 deletions(-) diff --git a/nanobot/cli/commands.py b/nanobot/cli/commands.py index 4b70f32..fbc8e20 100644 --- a/nanobot/cli/commands.py +++ b/nanobot/cli/commands.py @@ -296,54 +296,31 @@ def gateway( async def on_cron_job(job: CronJob) -> str | None: """Execute a cron job through the agent.""" from nanobot.agent.tools.message import MessageTool - - cron_session_key = f"cron:{job.id}" - cron_session = agent.sessions.get_or_create(cron_session_key) - reminder_note = ( - f"[系统定时任务] ⏰ 计时已结束\n\n" - f"定时任务 '{job.name}' 已触发。定时内容:{job.payload.message}\n\n" + "[Scheduled Task] Timer finished.\n\n" + f"Task '{job.name}' has been triggered.\n" + f"Scheduled instruction: {job.payload.message}" ) - - cron_session.add_message(role="user", content=reminder_note) - agent.sessions.save(cron_session) - - agent._set_tool_context( - job.payload.channel or "cli", - job.payload.to or "direct", - None + + response = await agent.process_direct( + reminder_note, + session_key=f"cron:{job.id}", + channel=job.payload.channel or "cli", + chat_id=job.payload.to or "direct", ) - + message_tool = agent.tools.get("message") - if isinstance(message_tool, MessageTool): - message_tool.start_turn() - - history = cron_session.get_history(max_messages=agent.memory_window) - - messages = [ - {"role": "system", "content": agent.context.build_system_prompt()}, - *history, - {"role": "user", "content": agent.context._build_runtime_context( - job.payload.channel or "cli", - job.payload.to or "direct" - )}, - ] - - final_content, _, all_msgs = await agent._run_agent_loop(messages) - agent._save_turn(cron_session, all_msgs, 1 + len(history) + 1) - agent.sessions.save(cron_session) - if isinstance(message_tool, MessageTool) and message_tool._sent_in_turn: - return final_content - - if job.payload.deliver and job.payload.to and final_content: + return response + + if job.payload.deliver and job.payload.to and response: from nanobot.bus.events import OutboundMessage await bus.publish_outbound(OutboundMessage( channel=job.payload.channel or "cli", chat_id=job.payload.to, - content=final_content + content=response )) - return final_content + return response cron.on_job = on_cron_job # Create channel manager