From 1f20f80851c3b7f6a1aa53c3dbdabbf3911c4673 Mon Sep 17 00:00:00 2001 From: mzkarami <1917371+mzkarami@users.noreply.github.com> Date: Mon, 1 Jun 2026 07:33:40 +0200 Subject: [PATCH] fix(cron): honor profile wrap_response during delivery --- cron/scheduler.py | 7 ++++-- tests/cron/test_cron_profile.py | 42 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/cron/scheduler.py b/cron/scheduler.py index a51ade8efe65..c3e3ca9ea675 100644 --- a/cron/scheduler.py +++ b/cron/scheduler.py @@ -639,10 +639,13 @@ def _deliver_result(job: dict, content: str, adapters=None, loop=None) -> Option # Optionally wrap the content with a header/footer so the user knows this # is a cron delivery. Wrapping is on by default; set cron.wrap_response: false - # in config.yaml for clean output. + # in config.yaml for clean output. Profile-scoped jobs should read this + # from their runtime profile config, even though delivery happens after + # run_job() has restored the scheduler profile. wrap_response = True try: - user_cfg = load_config() + with _job_profile_context(job.get("id", "?"), job.get("profile")): + user_cfg = load_config() wrap_response = user_cfg.get("cron", {}).get("wrap_response", True) except Exception: pass diff --git a/tests/cron/test_cron_profile.py b/tests/cron/test_cron_profile.py index 7ed28ba381e4..6124df58bef5 100644 --- a/tests/cron/test_cron_profile.py +++ b/tests/cron/test_cron_profile.py @@ -8,6 +8,7 @@ import json import os +from unittest.mock import AsyncMock, MagicMock, patch import pytest @@ -379,6 +380,47 @@ def test_run_job_falls_back_on_missing_runtime_profile( class TestTickProfilePartition: + def test_deliver_result_uses_profile_wrap_response_config( + self, isolated_cron_profile_home, monkeypatch + ): + """Profile jobs should read cron.wrap_response from their runtime profile.""" + import cron.scheduler as sched + from gateway.config import Platform + + root, profile_home = isolated_cron_profile_home + (root / "config.yaml").write_text("cron:\n wrap_response: true\n", encoding="utf-8") + (profile_home / "config.yaml").write_text( + "cron:\n wrap_response: false\n", encoding="utf-8" + ) + monkeypatch.setattr(sched, "_hermes_home", None) + + pconfig = MagicMock() + pconfig.enabled = True + mock_cfg = MagicMock() + mock_cfg.platforms = {Platform.TELEGRAM: pconfig} + + job = { + "id": "profile-delivery", + "name": "profile delivery", + "profile": "support", + "deliver": "origin", + "origin": {"platform": "telegram", "chat_id": "123"}, + } + + with patch("gateway.config.load_gateway_config", return_value=mock_cfg), \ + patch( + "tools.send_message_tool._send_to_platform", + new=AsyncMock(return_value={"success": True}), + ) as send_mock: + sched._deliver_result(job, "Clean profile output.") + + send_mock.assert_called_once() + sent_content = send_mock.call_args.kwargs.get("content") or send_mock.call_args[0][-1] + assert sent_content == "Clean profile output." + assert "Cronjob Response" not in sent_content + assert os.environ["HERMES_HOME"] == str(root) + assert sched._get_hermes_home() == root + def test_profile_and_workdir_combined(self, isolated_cron_profile_home, monkeypatch): """Both profile and workdir set — verify both are applied and restored.""" import cron.scheduler as sched