Remove reset

This commit is contained in:
Tao Chen
2026-06-11 11:14:36 -07:00
Unverified
parent 6534a739d0
commit 9da83347c8
19 changed files with 15 additions and 1311 deletions
@@ -1097,139 +1097,3 @@ def test_group_chat_orchestrator_factory_invalid_return_type():
# endregion
# region Reset
async def test_base_orchestrator_reset_clears_conversation_and_round_index() -> None:
"""reset() clears the conversation history and the round counter."""
from agent_framework.orchestrations import GroupChatOrchestrator
from agent_framework_orchestrations._base_group_chat_orchestrator import ParticipantRegistry
selector = make_sequence_selector()
orchestrator = GroupChatOrchestrator(
id="orch",
participant_registry=ParticipantRegistry([]),
selection_func=selector,
max_rounds=2,
)
orchestrator._full_conversation = [Message(role="user", contents=["hi"], author_name="user")]
orchestrator._round_index = 4
await orchestrator.reset()
assert orchestrator._full_conversation == []
assert orchestrator._round_index == 0
async def test_base_orchestrator_reset_invokes_pattern_state_hook() -> None:
"""reset() calls _reset_pattern_state() so subclasses can clean up their own state."""
from agent_framework.orchestrations import GroupChatOrchestrator
from agent_framework_orchestrations._base_group_chat_orchestrator import ParticipantRegistry
selector = make_sequence_selector()
class TrackingOrchestrator(GroupChatOrchestrator):
reset_calls: int = 0
def _reset_pattern_state(self) -> None:
type(self).reset_calls += 1
orchestrator = TrackingOrchestrator(
id="orch",
participant_registry=ParticipantRegistry([]),
selection_func=selector,
max_rounds=2,
)
await orchestrator.reset()
await orchestrator.reset()
assert TrackingOrchestrator.reset_calls == 2
async def test_agent_based_orchestrator_reset_clears_cache_and_rotates_session() -> None:
"""When the session was not supplied by the caller, reset() rotates the session and clears the cache."""
from agent_framework.orchestrations import AgentBasedGroupChatOrchestrator
from agent_framework_orchestrations._base_group_chat_orchestrator import ParticipantRegistry
agent = cast(Agent, StubManagerAgent())
orchestrator = AgentBasedGroupChatOrchestrator(
agent=agent,
participant_registry=ParticipantRegistry([]),
max_rounds=2,
)
original_session = orchestrator._session
orchestrator._cache = [Message(role="assistant", contents=["x"], author_name="agent")]
orchestrator._full_conversation = [Message(role="user", contents=["x"], author_name="user")]
orchestrator._round_index = 3
await orchestrator.reset()
assert orchestrator._cache == []
assert orchestrator._full_conversation == []
assert orchestrator._round_index == 0
assert orchestrator._session is not original_session
async def test_agent_based_orchestrator_reset_warns_when_session_supplied(caplog: pytest.LogCaptureFixture) -> None:
"""When the caller supplied a session, reset() preserves it and logs a warning."""
import logging
from agent_framework.orchestrations import AgentBasedGroupChatOrchestrator
from agent_framework_orchestrations._base_group_chat_orchestrator import ParticipantRegistry
agent = cast(Agent, StubManagerAgent())
supplied_session = agent.create_session()
orchestrator = AgentBasedGroupChatOrchestrator(
agent=agent,
participant_registry=ParticipantRegistry([]),
session=supplied_session,
max_rounds=2,
)
orchestrator._cache = [Message(role="assistant", contents=["x"], author_name="agent")]
with caplog.at_level(logging.WARNING, logger="agent_framework_orchestrations._group_chat"):
await orchestrator.reset()
assert orchestrator._cache == []
# The caller-owned session must be preserved.
assert orchestrator._session is supplied_session
warnings = [
r for r in caplog.records if r.levelno == logging.WARNING and "Session was supplied by the caller" in r.message
]
assert warnings, f"expected a warning about caller-supplied session, got: {[r.message for r in caplog.records]}"
async def test_workflow_reset_resets_group_chat_orchestrator() -> None:
"""End-to-end: workflow.reset_for_new_run() resets the orchestrator's conversation state."""
selector = make_sequence_selector()
alpha = StubAgent("alpha", "ack from alpha")
beta = StubAgent("beta", "ack from beta")
workflow = GroupChatBuilder(
participants=[alpha, beta],
max_rounds=2,
selection_func=selector,
orchestrator_name="manager",
).build()
async for _ in workflow.run("first task", stream=True):
pass
orchestrator = cast(BaseGroupChatOrchestrator, workflow.executors[GroupChatBuilder.DEFAULT_ORCHESTRATOR_ID])
assert orchestrator._full_conversation, "orchestrator should have accumulated conversation after first run"
assert orchestrator._round_index > 0
await workflow.reset_for_new_run()
assert orchestrator._full_conversation == []
assert orchestrator._round_index == 0
# endregion
@@ -1243,135 +1243,3 @@ def test_standard_manager_checkpoint_restore_empty_state():
# endregion
# region Manager Reset Tests
def test_magentic_manager_base_on_reset_is_noop_by_default():
"""MagenticManagerBase.on_reset() is a no-op so subclasses can opt in."""
mgr = FakeManager()
# Seed some state on the fake to confirm the base hook does not touch it.
mgr.task_ledger = _SimpleLedger(
facts=Message("assistant", ["facts"]),
plan=Message("assistant", ["plan"]),
)
mgr.on_reset() # base implementation is a no-op
assert mgr.task_ledger is not None
def test_standard_manager_on_reset_clears_ledger_and_rotates_session():
"""StandardMagenticManager.on_reset() clears the cached ledger and creates a fresh session."""
from agent_framework_orchestrations._magentic import _MagenticTaskLedger # type: ignore[reportPrivateUsage]
agent = StubManagerAgent()
mgr = StandardMagenticManager(agent=agent)
mgr.task_ledger = _MagenticTaskLedger(
facts=Message("assistant", ["facts"]),
plan=Message("assistant", ["plan"]),
)
original_session = mgr._session
mgr.on_reset()
assert mgr.task_ledger is None
assert mgr._session is not original_session
assert mgr._session.session_id != original_session.session_id
async def test_magentic_orchestrator_reset_invokes_manager_on_reset() -> None:
"""_reset_pattern_state() clears orchestrator state and delegates to manager.on_reset()."""
from agent_framework_orchestrations._base_group_chat_orchestrator import (
ParticipantRegistry, # type: ignore[reportPrivateUsage]
)
class TrackingManager(FakeManager):
reset_calls: int = 0
@override
def on_reset(self) -> None:
type(self).reset_calls += 1
manager = TrackingManager()
orchestrator = MagenticOrchestrator(
manager=manager,
participant_registry=ParticipantRegistry([]),
)
# Seed magentic-specific state to confirm it is cleared.
orchestrator._magentic_context = MagenticContext( # type: ignore[reportPrivateUsage]
task="task",
participant_descriptions={"agentA": "desc"},
)
orchestrator._task_ledger = Message("assistant", ["ledger"]) # type: ignore[reportPrivateUsage]
orchestrator._progress_ledger = MagenticProgressLedger( # type: ignore[reportPrivateUsage]
is_request_satisfied=MagenticProgressLedgerItem(reason="r", answer=False),
is_in_loop=MagenticProgressLedgerItem(reason="r", answer=False),
is_progress_being_made=MagenticProgressLedgerItem(reason="r", answer=True),
next_speaker=MagenticProgressLedgerItem(reason="r", answer="agentA"),
instruction_or_question=MagenticProgressLedgerItem(reason="r", answer="do"),
)
orchestrator._terminated = True # type: ignore[reportPrivateUsage]
await orchestrator.reset()
assert orchestrator._magentic_context is None # type: ignore[reportPrivateUsage]
assert orchestrator._task_ledger is None # type: ignore[reportPrivateUsage]
assert orchestrator._progress_ledger is None # type: ignore[reportPrivateUsage]
assert orchestrator._terminated is False # type: ignore[reportPrivateUsage]
assert TrackingManager.reset_calls == 1
async def test_magentic_orchestrator_reset_propagates_manager_on_reset_failure() -> None:
"""Failures in manager.on_reset() must propagate so callers can react."""
from agent_framework_orchestrations._base_group_chat_orchestrator import (
ParticipantRegistry, # type: ignore[reportPrivateUsage]
)
class FailingManager(FakeManager):
@override
def on_reset(self) -> None:
raise RuntimeError("boom")
manager = FailingManager()
orchestrator = MagenticOrchestrator(
manager=manager,
participant_registry=ParticipantRegistry([]),
)
with pytest.raises(RuntimeError, match="boom"):
await orchestrator.reset()
async def test_workflow_reset_resets_magentic_orchestrator_and_manager() -> None:
"""End-to-end: workflow.reset_for_new_run() resets Magentic orchestrator and manager state."""
manager = FakeManager()
manager.task_ledger = _SimpleLedger(
facts=Message("assistant", ["seeded facts"]),
plan=Message("assistant", ["seeded plan"]),
)
workflow = MagenticBuilder(
participants=[StubAgent(manager.next_speaker_name, "first draft")],
manager=manager,
).build()
async for _ in workflow.run("first task", stream=True):
pass
orchestrator = next(e for e in workflow.executors.values() if isinstance(e, MagenticOrchestrator))
assert orchestrator._terminated is True # type: ignore[reportPrivateUsage]
assert orchestrator._task_ledger is not None # type: ignore[reportPrivateUsage]
assert manager.task_ledger is not None
await workflow.reset_for_new_run()
assert orchestrator._magentic_context is None # type: ignore[reportPrivateUsage]
assert orchestrator._task_ledger is None # type: ignore[reportPrivateUsage]
assert orchestrator._progress_ledger is None # type: ignore[reportPrivateUsage]
assert orchestrator._terminated is False # type: ignore[reportPrivateUsage]
# FakeManager.on_reset is the base no-op, but the orchestrator still tolerates that case.
# For the standard manager we exercise full clearing in the dedicated unit test above.
# endregion