Add AgentSessionService and refactor agent routes
Move session-related responsibilities into a new application-layer AgentSessionService (and AgentSessionFeedbackResult dataclass), provide a bootstrap factory (get_agent_session_service), and update agent API routes to call the service instead of accessing ConversationStore directly. Routes now translate ValueError into 404 responses and use service methods for get/list/history/delete/feedback. Also update package exports and docs/READMEs to declare the backend architecture authority, enforce api -> application -> domain ports -> infrastructure boundaries, and call out legacy services/workflows as migration-only. These changes centralize session logic in the application layer and tighten architecture guidance for future backend work.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""Initialize the app.application.agent package."""
|
||||
|
||||
from .services import AgentConversationService
|
||||
from .services import AgentConversationService, AgentSessionFeedbackResult, AgentSessionService
|
||||
# Keep package boundaries explicit so backend imports stay predictable.
|
||||
|
||||
|
||||
__all__ = ["AgentConversationService"]
|
||||
__all__ = ["AgentConversationService", "AgentSessionFeedbackResult", "AgentSessionService"]
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
"""Implement application-layer logic for services."""
|
||||
"""Implement application-layer logic for agent services."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Generator
|
||||
|
||||
from app.domain.conversation import AnswerGenerator, AnswerResult, ConversationStore
|
||||
@@ -141,5 +142,50 @@ class AgentConversationService:
|
||||
content=full_answer,
|
||||
sources=sources_payload,
|
||||
)
|
||||
|
||||
|
||||
return session.session_id, event_stream()
|
||||
|
||||
|
||||
@dataclass
|
||||
class AgentSessionFeedbackResult:
|
||||
"""Represent the result of storing session feedback."""
|
||||
|
||||
session_id: str
|
||||
message_index: int
|
||||
|
||||
|
||||
class AgentSessionService:
|
||||
"""Provide application-layer access to session management workflows."""
|
||||
|
||||
def __init__(self, *, conversation_store: ConversationStore) -> None:
|
||||
"""Initialize the Agent Session Service instance."""
|
||||
self.conversation_store = conversation_store
|
||||
|
||||
def get_session(self, session_id: str):
|
||||
"""Return a session by id or raise when it does not exist."""
|
||||
session = self.conversation_store.get_session(session_id)
|
||||
if not session:
|
||||
raise ValueError("会话不存在或已过期")
|
||||
return session
|
||||
|
||||
def get_history(self, *, session_id: str, max_turns: int = 5) -> list[dict[str, str]]:
|
||||
"""Return the recent conversation history for a session."""
|
||||
session = self.get_session(session_id)
|
||||
return [{"role": msg.role, "content": msg.content} for msg in session.messages[-(max_turns * 2):]]
|
||||
|
||||
def delete_session(self, session_id: str) -> None:
|
||||
"""Delete a session or raise when it does not exist."""
|
||||
if not self.conversation_store.delete_session(session_id):
|
||||
raise ValueError("会话不存在")
|
||||
|
||||
def list_sessions(self) -> list[dict]:
|
||||
"""Return the list of visible sessions."""
|
||||
return self.conversation_store.list_sessions()
|
||||
|
||||
def submit_feedback(self, *, session_id: str, message_index: int) -> AgentSessionFeedbackResult:
|
||||
"""Validate feedback targets and return a normalized feedback result."""
|
||||
session = self.get_session(session_id)
|
||||
if message_index < 0 or message_index >= len(session.messages):
|
||||
raise ValueError("消息索引不存在")
|
||||
# Preserve the existing API behavior until a persistent feedback store is introduced.
|
||||
return AgentSessionFeedbackResult(session_id=session_id, message_index=message_index)
|
||||
|
||||
Reference in New Issue
Block a user