refactor: replace <SILENT_OK> with structured post-run evaluation

- Add nanobot/utils/evaluator.py: lightweight LLM tool-call to decide notify/silent after background task execution
- Remove magic token injection from heartbeat and cron prompts
- Clean session history (no more <SILENT_OK> pollution)
- Add tests for evaluator and updated heartbeat three-phase flow
This commit is contained in:
Xubin Ren
2026-03-14 17:41:08 +08:00
committed by Xubin Ren
parent e6c1f520ac
commit 411b059dd2
5 changed files with 272 additions and 18 deletions
+12 -9
View File
@@ -139,6 +139,8 @@ class HeartbeatService:
async def _tick(self) -> None:
"""Execute a single heartbeat tick."""
from nanobot.utils.evaluator import evaluate_response
content = self._read_heartbeat_file()
if not content:
logger.debug("Heartbeat: HEARTBEAT.md missing or empty")
@@ -153,18 +155,19 @@ class HeartbeatService:
logger.info("Heartbeat: OK (nothing to report)")
return
taskmessage = tasks + "\n\n**IMPORTANT NOTICE:** If there is nothing material to report, reply only with <SILENT_OK>."
logger.info("Heartbeat: tasks found, executing...")
if self.on_execute:
response = await self.on_execute(taskmessage)
response = await self.on_execute(tasks)
if response and "<SILENT_OK>" in response:
logger.info("Heartbeat: OK (silenced by agent)")
return
if response and self.on_notify:
logger.info("Heartbeat: completed, delivering response")
await self.on_notify(response)
if response:
should_notify = await evaluate_response(
response, tasks, self.provider, self.model,
)
if should_notify and self.on_notify:
logger.info("Heartbeat: completed, delivering response")
await self.on_notify(response)
else:
logger.info("Heartbeat: silenced by post-run evaluation")
except Exception:
logger.exception("Heartbeat execution failed")