mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-05 17:27:42 +02:00
61 lines
2.5 KiB
Python
61 lines
2.5 KiB
Python
"""Stopping is for LIVE turns. A settled chat must come back settled.
|
|
|
|
Found live: quit the app and relaunch, and every finished conversation came back labelled
|
|
"stopped" with a Resume button hanging off an answer that was already delivered. The chain is
|
|
short. `self.tasks[session_id]` is written when a turn starts and only removed by stop/close, so a
|
|
completed session leaves its done task in the registry forever; the agents sub-app's shutdown hook
|
|
loops over every task it finds and calls `stop_agent` on each; `stop_agent` then wrote
|
|
`status = "stopped"` unconditionally. One ordinary session was enough to reproduce it.
|
|
|
|
The guard belongs in `stop_agent`, not in the shutdown loop, so no future caller can express the
|
|
bad state either. `close_session` already had exactly this guard, which is what made the
|
|
inconsistency easy to miss.
|
|
|
|
Run:
|
|
cd backend && .venv/bin/python -m pytest tests/test_stop_agent_preserves_terminal_status.py -v
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from backend.apps.agents.agent_manager import agent_manager
|
|
from backend.apps.agents.core.models import AgentSession, Message
|
|
|
|
|
|
def p_seed(status: str) -> AgentSession:
|
|
s = AgentSession(name="t", model="sonnet")
|
|
s.status = status
|
|
s.messages = [Message(role="user", content="hi"), Message(role="assistant", content="hello")]
|
|
agent_manager.sessions[s.id] = s
|
|
return s
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("terminal", ["completed", "error", "stopped"])
|
|
async def test_stopping_a_settled_chat_leaves_its_status_alone(terminal: str) -> None:
|
|
s = p_seed(terminal)
|
|
try:
|
|
await agent_manager.stop_agent(s.id)
|
|
assert s.status == terminal, "a restart must not relabel a finished conversation"
|
|
assert s.needs_fresh_session is False, "nothing was interrupted, so nothing needs rebuilding"
|
|
assert s.closed_at is None
|
|
finally:
|
|
agent_manager.sessions.pop(s.id, None)
|
|
agent_manager.tasks.pop(s.id, None)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("live", ["running", "waiting_approval"])
|
|
async def test_stopping_a_live_turn_still_stops_it(live: str) -> None:
|
|
"""The discriminating half: the Stop button must keep working."""
|
|
s = p_seed(live)
|
|
try:
|
|
await agent_manager.stop_agent(s.id)
|
|
assert s.status == "stopped"
|
|
assert s.needs_fresh_session is True
|
|
assert s.closed_at is not None
|
|
finally:
|
|
agent_manager.sessions.pop(s.id, None)
|
|
agent_manager.tasks.pop(s.id, None)
|