mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-17 18:25:42 +02:00
[eric] agents: rename cryptic names — LivePartial->PartialReply, session/lifecycle.py->resume_and_duplicate.py (it held resume/duplicate, and collided with SessionLifecycle)
This commit is contained in:
@@ -18,7 +18,7 @@ from backend.apps.agents.manager.session.session_store import (
|
||||
load_session_data as load_session_data,
|
||||
)
|
||||
from backend.apps.agents.manager.streaming.state import ThinkingState, TurnState
|
||||
from backend.apps.agents.manager.streaming.LivePartial import LivePartial
|
||||
from backend.apps.agents.manager.streaming.PartialReply import PartialReply
|
||||
from backend.apps.agents.manager.session.SessionLifecycle import SessionLifecycle
|
||||
from backend.apps.agents.manager.session.SessionPersistence import SessionPersistence
|
||||
from backend.apps.agents.manager.Messaging import Messaging
|
||||
@@ -43,7 +43,7 @@ class AgentManager(SessionLifecycle, SessionPersistence, Messaging, SessionContr
|
||||
# Live mirror of the in-flight streamed assistant text per session, so a
|
||||
# stop can persist the partial reply instantly instead of waiting out the
|
||||
# multi-second SDK teardown the cancel handler sits behind.
|
||||
self.live_partial: Dict[str, LivePartial] = {}
|
||||
self.live_partial: Dict[str, PartialReply] = {}
|
||||
# Per-session cancel signal: the loop stashes its asyncio.Event here so a
|
||||
# stop/close can set it. Lives on the manager, not the AgentSession model,
|
||||
# so it stays out of serialization (an Event can't be model_dump'd).
|
||||
|
||||
@@ -17,14 +17,14 @@ from typing import TYPE_CHECKING, Any, Dict
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from backend.apps.agents.core.models import AgentSession
|
||||
from backend.apps.agents.manager.streaming.LivePartial import LivePartial
|
||||
from backend.apps.agents.manager.streaming.PartialReply import PartialReply
|
||||
|
||||
|
||||
class AgentManagerProtocol:
|
||||
# State set in AgentManager.__init__.
|
||||
sessions: Dict[str, AgentSession]
|
||||
tasks: Dict[str, asyncio.Task]
|
||||
live_partial: Dict[str, LivePartial]
|
||||
live_partial: Dict[str, PartialReply]
|
||||
cancel_events: Dict[str, asyncio.Event]
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@@ -19,7 +19,7 @@ from backend.apps.agents.manager.session.session_store import (
|
||||
)
|
||||
from backend.apps.agents.manager.session.sync_session_close import sync_session_close
|
||||
from backend.apps.agents.manager.session.apply_context_window import apply_context_window
|
||||
from backend.apps.agents.manager.session import lifecycle
|
||||
from backend.apps.agents.manager.session import resume_and_duplicate
|
||||
from backend.apps.agents.manager.view_builder_state import (
|
||||
view_builder_render_retry_counts,
|
||||
view_builder_dirty_sessions,
|
||||
@@ -139,7 +139,7 @@ class SessionLifecycle(AgentManagerProtocol):
|
||||
async def resume_session(self, session_id: str) -> AgentSession:
|
||||
if session_id in self.sessions:
|
||||
return self.sessions[session_id]
|
||||
session = lifecycle.load_session_for_resume(session_id)
|
||||
session = resume_and_duplicate.load_session_for_resume(session_id)
|
||||
self.sessions[session_id] = session
|
||||
await ws_manager.send_to_session(session_id, "agent:status", {
|
||||
"session_id": session_id,
|
||||
@@ -193,7 +193,7 @@ class SessionLifecycle(AgentManagerProtocol):
|
||||
|
||||
@typechecked
|
||||
async def duplicate_session(self, session_id: str, dashboard_id: Optional[str] = None, up_to_message_id: Optional[str] = None) -> AgentSession:
|
||||
new_session = lifecycle.build_duplicate_session(self.sessions.get(session_id), session_id, dashboard_id, up_to_message_id)
|
||||
new_session = resume_and_duplicate.build_duplicate_session(self.sessions.get(session_id), session_id, dashboard_id, up_to_message_id)
|
||||
self.sessions[new_session.id] = new_session
|
||||
await ws_manager.send_to_session(new_session.id, "agent:status", {
|
||||
"session_id": new_session.id,
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ from typing import Optional
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
|
||||
class LivePartial(BaseModel):
|
||||
class PartialReply(BaseModel):
|
||||
model_config = ConfigDict(validate_assignment=True)
|
||||
|
||||
msg_id: Optional[str] = None
|
||||
@@ -14,7 +14,7 @@ from backend.apps.agents.core.models import AgentSession, Message
|
||||
from backend.apps.agents.core.ws_manager import ws_manager
|
||||
from backend.apps.agents.manager.streaming.state import ThinkingState, TurnState
|
||||
from backend.apps.agents.manager.streaming.upsert_message import upsert_message
|
||||
from backend.apps.agents.manager.streaming.LivePartial import LivePartial
|
||||
from backend.apps.agents.manager.streaming.PartialReply import PartialReply
|
||||
from backend.apps.agents.manager.streaming import thinking as thinking_mod
|
||||
|
||||
try:
|
||||
@@ -31,7 +31,7 @@ async def handle_assistant_message(
|
||||
session_id: str,
|
||||
turn: TurnState,
|
||||
thinking: ThinkingState,
|
||||
live_partial: Dict[str, LivePartial],
|
||||
live_partial: Dict[str, PartialReply],
|
||||
sessions: Dict[str, AgentSession],
|
||||
) -> None:
|
||||
content_parts = []
|
||||
|
||||
@@ -13,7 +13,7 @@ from typeguard import typechecked
|
||||
from backend.apps.agents.core.models import AgentSession
|
||||
from backend.apps.agents.core.ws_manager import ws_manager
|
||||
from backend.apps.agents.manager.streaming.state import ThinkingState, TurnState
|
||||
from backend.apps.agents.manager.streaming.LivePartial import LivePartial
|
||||
from backend.apps.agents.manager.streaming.PartialReply import PartialReply
|
||||
|
||||
try:
|
||||
from claude_agent_sdk.types import StreamEvent
|
||||
@@ -28,7 +28,7 @@ async def handle_stream_event(
|
||||
session_id: str,
|
||||
turn: TurnState,
|
||||
thinking: ThinkingState,
|
||||
live_partial: Dict[str, LivePartial],
|
||||
live_partial: Dict[str, PartialReply],
|
||||
) -> None:
|
||||
event = message.event
|
||||
event_type = event.get("type")
|
||||
@@ -113,7 +113,7 @@ async def handle_stream_event(
|
||||
text_chunk = delta.get("text", "")
|
||||
turn.assistant_text_chars += len(text_chunk)
|
||||
turn.stream_text_accum += text_chunk
|
||||
live_partial[session_id] = LivePartial(
|
||||
live_partial[session_id] = PartialReply(
|
||||
msg_id=turn.stream_text_msg_id,
|
||||
text=turn.stream_text_accum,
|
||||
branch_id=session.active_branch_id,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"""Pins the session build-functions lifted into manager/session/lifecycle.py:
|
||||
"""Pins the session build-functions lifted into manager/session/resume_and_duplicate.py:
|
||||
the duplicate must be an INDEPENDENT copy (fresh ids, source untouched), and both
|
||||
builders raise when there's no on-disk snapshot to restore from."""
|
||||
|
||||
import backend.apps.agents.manager.session.lifecycle as lifecycle
|
||||
import backend.apps.agents.manager.session.resume_and_duplicate as resume_and_duplicate
|
||||
from backend.apps.agents.core.models import AgentSession, Message
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ def test_build_duplicate_session_is_an_independent_copy():
|
||||
src = AgentSession(name="Orig", model="sonnet", dashboard_id="d1")
|
||||
src.messages = [Message(role="user", content="hello"), Message(role="assistant", content="hi")]
|
||||
|
||||
new = lifecycle.build_duplicate_session(src, src.id, None, None)
|
||||
new = resume_and_duplicate.build_duplicate_session(src, src.id, None, None)
|
||||
|
||||
assert new.id != src.id
|
||||
assert new.name == "Orig (copy)"
|
||||
@@ -32,23 +32,23 @@ def test_build_duplicate_session_respects_up_to_message_id():
|
||||
)
|
||||
src.messages = [m1, m2, m3]
|
||||
|
||||
new = lifecycle.build_duplicate_session(src, src.id, None, m2.id)
|
||||
new = resume_and_duplicate.build_duplicate_session(src, src.id, None, m2.id)
|
||||
assert [m.content for m in new.messages] == ["one", "two"] # truncated at the cut message
|
||||
|
||||
|
||||
def test_build_duplicate_session_raises_when_source_missing(monkeypatch):
|
||||
monkeypatch.setattr(lifecycle, "load_session_data", lambda sid: None, raising=True)
|
||||
monkeypatch.setattr(resume_and_duplicate, "load_session_data", lambda sid: None, raising=True)
|
||||
try:
|
||||
lifecycle.build_duplicate_session(None, "ghost", None, None)
|
||||
resume_and_duplicate.build_duplicate_session(None, "ghost", None, None)
|
||||
assert False, "expected ValueError when neither cache nor disk has the session"
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
def test_load_session_for_resume_raises_when_absent(monkeypatch):
|
||||
monkeypatch.setattr(lifecycle, "load_session_data", lambda sid: None, raising=True)
|
||||
monkeypatch.setattr(resume_and_duplicate, "load_session_data", lambda sid: None, raising=True)
|
||||
try:
|
||||
lifecycle.load_session_for_resume("ghost")
|
||||
resume_and_duplicate.load_session_for_resume("ghost")
|
||||
assert False, "expected ValueError when there's no snapshot on disk"
|
||||
except ValueError:
|
||||
pass
|
||||
Reference in New Issue
Block a user