feat(memory): protect Dream cron and polish migration UX

This commit is contained in:
Xubin Ren
2026-04-04 09:01:42 +00:00
parent 6e896249c8
commit 408a61b0e1
4 changed files with 86 additions and 8 deletions
+24 -2
View File
@@ -6,7 +6,7 @@ from typing import Any
from nanobot.agent.tools.base import Tool
from nanobot.cron.service import CronService
from nanobot.cron.types import CronJobState, CronSchedule
from nanobot.cron.types import CronJob, CronJobState, CronSchedule
class CronTool(Tool):
@@ -219,6 +219,12 @@ class CronTool(Tool):
lines.append(f" Next run: {self._format_timestamp(state.next_run_at_ms, display_tz)}")
return lines
@staticmethod
def _system_job_purpose(job: CronJob) -> str:
if job.name == "dream":
return "Dream memory consolidation for long-term memory."
return "System-managed internal job."
def _list_jobs(self) -> str:
jobs = self._cron.list_jobs()
if not jobs:
@@ -227,6 +233,9 @@ class CronTool(Tool):
for j in jobs:
timing = self._format_timing(j.schedule)
parts = [f"- {j.name} (id: {j.id}, {timing})"]
if j.payload.kind == "system_event":
parts.append(f" Purpose: {self._system_job_purpose(j)}")
parts.append(" Protected: visible for inspection, but cannot be removed.")
parts.extend(self._format_state(j.state, j.schedule))
lines.append("\n".join(parts))
return "Scheduled jobs:\n" + "\n".join(lines)
@@ -234,6 +243,19 @@ class CronTool(Tool):
def _remove_job(self, job_id: str | None) -> str:
if not job_id:
return "Error: job_id is required for remove"
if self._cron.remove_job(job_id):
result = self._cron.remove_job(job_id)
if result == "removed":
return f"Removed job {job_id}"
if result == "protected":
job = self._cron.get_job(job_id)
if job and job.name == "dream":
return (
"Cannot remove job `dream`.\n"
"This is a system-managed Dream memory consolidation job for long-term memory.\n"
"It remains visible so you can inspect it, but it cannot be removed."
)
return (
f"Cannot remove job `{job_id}`.\n"
"This is a protected system-managed cron job."
)
return f"Job {job_id} not found"