mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-09 08:21:50 +00:00
feat(cron): title cron sessions from the job, not the [IMPORTANT] hint
A cron session's first message is the injected "[IMPORTANT: you are running as a scheduled cron job …]" delivery hint, so with no explicit title the sidebar and history rows fell back to that hint as their label. Set the session title from the job (name → short prompt → id) with a run-time suffix for uniqueness against the sessions.title index. Done after the run so the agent's own INSERT keeps model/system_prompt — this only updates the title.
This commit is contained in:
parent
3e2d758816
commit
ad0f6db151
2 changed files with 49 additions and 0 deletions
|
|
@ -1973,6 +1973,18 @@ def _run_job_impl(job: dict) -> tuple[bool, str, str, Optional[str]]:
|
|||
for _var_name in _cron_delivery_vars:
|
||||
_VAR_MAP[_var_name].set("")
|
||||
if _session_db:
|
||||
# Title the cron session from the job (name → short prompt → id) so
|
||||
# sidebars/history show a meaningful label instead of the injected
|
||||
# "[IMPORTANT: …]" hint that is the session's first message. Set here
|
||||
# (not at create time) so the agent's own INSERT keeps model /
|
||||
# system_prompt; this only UPDATEs the title column. The run-time
|
||||
# suffix keeps it unique against the sessions.title index across runs.
|
||||
try:
|
||||
_title_base = " ".join(job_name.split())[:60].strip() or f"cron {job_id}"
|
||||
_cron_title = f"{_title_base} · {_hermes_now().strftime('%b %d %H:%M')}"
|
||||
_session_db.set_session_title(_cron_session_id, _cron_title)
|
||||
except (Exception, KeyboardInterrupt) as e:
|
||||
logger.debug("Job '%s': failed to set cron session title: %s", job_id, e)
|
||||
try:
|
||||
_session_db.end_session(_cron_session_id, "cron_complete")
|
||||
except (Exception, KeyboardInterrupt) as e:
|
||||
|
|
|
|||
|
|
@ -912,6 +912,43 @@ class TestRunJobSessionPersistence:
|
|||
fake_db.close.assert_called_once()
|
||||
mock_agent.close.assert_called_once()
|
||||
|
||||
def test_run_job_titles_cron_session_from_job_not_important_hint(self, tmp_path):
|
||||
# The cron session's first message is the injected "[IMPORTANT: …]"
|
||||
# hint, which used to surface as the sidebar/history row label. run_job
|
||||
# must title the session from the job (name → short prompt → id).
|
||||
job = {
|
||||
"id": "test-job",
|
||||
"name": "Morning digest",
|
||||
"prompt": "summarize my inbox",
|
||||
}
|
||||
fake_db = MagicMock()
|
||||
|
||||
with patch("cron.scheduler._hermes_home", tmp_path), \
|
||||
patch("cron.scheduler._resolve_origin", return_value=None), \
|
||||
patch("dotenv.load_dotenv"), \
|
||||
patch("hermes_state.SessionDB", return_value=fake_db), \
|
||||
patch(
|
||||
"hermes_cli.runtime_provider.resolve_runtime_provider",
|
||||
return_value={
|
||||
"api_key": "test-key",
|
||||
"base_url": "https://example.invalid/v1",
|
||||
"provider": "openrouter",
|
||||
"api_mode": "chat_completions",
|
||||
},
|
||||
), \
|
||||
patch("run_agent.AIAgent") as mock_agent_cls:
|
||||
mock_agent = MagicMock()
|
||||
mock_agent.run_conversation.return_value = {"final_response": "ok"}
|
||||
mock_agent_cls.return_value = mock_agent
|
||||
|
||||
run_job(job)
|
||||
|
||||
fake_db.set_session_title.assert_called_once()
|
||||
sid, title = fake_db.set_session_title.call_args[0]
|
||||
assert sid.startswith("cron_test-job_")
|
||||
assert "IMPORTANT" not in title
|
||||
assert title.startswith("Morning digest")
|
||||
|
||||
def test_run_job_closes_agent_on_failure_to_prevent_fd_leak(self, tmp_path):
|
||||
# Regression: if ``run_conversation`` raises, the ephemeral cron
|
||||
# agent was previously leaked — over days of ticks this accumulated
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue