fix(heartbeat): skip when HEARTBEAT.md has no tasks and fail closed on delivery (#4111)
This commit is contained in:
@@ -61,3 +61,21 @@ async def test_no_tool_call_fallback() -> None:
|
||||
provider = DummyProvider([LLMResponse(content="I think you should notify", tool_calls=[])])
|
||||
result = await evaluate_response("some response", "some task", provider, "m")
|
||||
assert result is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fail_closed_on_error() -> None:
|
||||
class FailingProvider(DummyProvider):
|
||||
async def chat(self, *args, **kwargs) -> LLMResponse:
|
||||
raise RuntimeError("provider down")
|
||||
|
||||
provider = FailingProvider([])
|
||||
result = await evaluate_response("some", "task", provider, "m", default_notify=False)
|
||||
assert result is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fail_closed_on_no_tool_call() -> None:
|
||||
provider = DummyProvider([LLMResponse(content="text only", tool_calls=[])])
|
||||
result = await evaluate_response("some", "task", provider, "m", default_notify=False)
|
||||
assert result is False
|
||||
|
||||
@@ -952,6 +952,29 @@ def test_heartbeat_retains_recent_messages_by_default():
|
||||
assert config.gateway.heartbeat.keep_recent_messages == 8
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"content, expected",
|
||||
[
|
||||
("", False),
|
||||
("# Title\n\n## Active Tasks\n", False),
|
||||
("<!--\nmulti-line\ncomment\n-->\n", False), # block comment, not tasks
|
||||
("<!-- single line -->\n", False),
|
||||
("## Active Tasks\n\n- water the plants\n", True),
|
||||
],
|
||||
)
|
||||
def test_heartbeat_has_active_tasks(content, expected):
|
||||
from nanobot.cli.commands import _heartbeat_has_active_tasks
|
||||
|
||||
assert _heartbeat_has_active_tasks(content) is expected
|
||||
|
||||
|
||||
def test_heartbeat_skips_bundled_template():
|
||||
from nanobot.cli.commands import _heartbeat_has_active_tasks
|
||||
from nanobot.utils.helpers import load_bundled_template
|
||||
|
||||
assert _heartbeat_has_active_tasks(load_bundled_template("HEARTBEAT.md")) is False
|
||||
|
||||
|
||||
def _write_instance_config(tmp_path: Path) -> Path:
|
||||
config_file = tmp_path / "instance" / "config.json"
|
||||
config_file.parent.mkdir(parents=True)
|
||||
|
||||
@@ -38,6 +38,28 @@ async def test_message_tool_rejects_malformed_buttons(bad) -> None:
|
||||
assert result == "Error: buttons must be a list of list of strings"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_message_tool_suppresses_delivery_when_active() -> None:
|
||||
sent: list[OutboundMessage] = []
|
||||
|
||||
async def _send(msg: OutboundMessage) -> None:
|
||||
sent.append(msg)
|
||||
|
||||
tool = MessageTool(send_callback=_send)
|
||||
|
||||
token = tool.set_suppress_delivery(True)
|
||||
try:
|
||||
result = await tool.execute(content="all clear", channel="telegram", chat_id="1")
|
||||
finally:
|
||||
tool.reset_suppress_delivery(token)
|
||||
assert sent == []
|
||||
assert "not delivered" in result
|
||||
|
||||
await tool.execute(content="real", channel="telegram", chat_id="1")
|
||||
assert len(sent) == 1
|
||||
assert sent[0].content == "real"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_message_tool_marks_channel_delivery_only_when_enabled() -> None:
|
||||
sent: list[OutboundMessage] = []
|
||||
|
||||
Reference in New Issue
Block a user