Second-Me/lpm_kernel/api/domains/space/context/context_manager.py
2025-03-20 00:37:54 +08:00

200 lines
6 KiB
Python

"""
Space context manager, responsible for managing context information during Space discussions
"""
from typing import List, Dict, Optional
from datetime import datetime
import uuid
from ..space_dto import SpaceDTO, SpaceMessageDTO
from ..space_repository import space_repository
class SpaceContextManager:
"""Space Context Manager"""
def __init__(self, space: SpaceDTO):
"""
Initialize context manager
Args:
space: Space DTO object
"""
self.space_dto = space
# Record current message position for each participant
self.participant_positions: Dict[str, int] = {
participant: 0 for participant in space.get_all_participants()
}
# Current discussion round
self.current_round: int = 0
# Currently active participant
self.current_participant: Optional[str] = None
def save_message(self, message_dto: SpaceMessageDTO) -> None:
"""
Save new message
Args:
message_dto: SpaceMessage DTO instance
"""
self.space_dto.add_message(message_dto)
space_repository.add_message(self.space_dto.id, message_dto)
def get_context_for_participant(self, participants: str) -> List[SpaceMessageDTO]:
"""
Get context message list for participant
Args:
participants: Participant's endpoint
Returns:
List of messages visible to this participant
"""
if participants not in self.participant_positions:
raise ValueError(f"Participant not in discussion: {participants}")
# Get participant's last read position
last_position = self.participant_positions[participants]
# Update read position to latest
self.participant_positions[participants] = len(self.space_dto.messages)
# Return unread messages
return self.space_dto.messages[last_position:]
def create_message(
self,
sender_endpoint: str,
content: str,
message_type: str,
round: Optional[int] = None
) -> SpaceMessageDTO:
"""
Create new message
Args:
sender_endpoint: Sender endpoint
content: Message content
message_type: Message type
round: Optional round number, uses current round if not specified
Returns:
Created SpaceMessage DTO instance
"""
if round is None:
round = self.current_round
# Check if content is empty (None, empty string, whitespace) or starts with "error"
if not content or (isinstance(content, str) and (content.strip() == "" or content.lower().strip().startswith("error"))):
content = "I am currently not accessible."
# Determine message sender's role
role = "host" if sender_endpoint == self.space_dto.host else "participant"
message_dto = SpaceMessageDTO(
id=str(uuid.uuid4()), # Generate unique ID
space_id=self.space_dto.id,
sender_endpoint=sender_endpoint,
content=content,
message_type=message_type,
round=round,
create_time=datetime.now(),
role=role
)
self.save_message(message_dto)
return message_dto
def advance_round(self) -> None:
"""Advance to next discussion round"""
self.current_round += 1
def get_current_round(self) -> int:
"""Get current round"""
return self.current_round
def get_messages_in_round(self, round: int) -> List[SpaceMessageDTO]:
"""
Get all messages for specified round
Args:
round: Round number
Returns:
All messages in this round
"""
return self.space_dto.get_messages_by_round(round)
def get_all_messages(self) -> List[SpaceMessageDTO]:
"""
Get all messages
Returns:
List of all messages
"""
return self.space_dto.messages
def get_participant_last_message(self, participants: str) -> Optional[SpaceMessageDTO]:
"""
Get participant's last message
Args:
participants: Participant endpoint
Returns:
Last message, or None if no messages exist
"""
for message in reversed(self.space_dto.messages):
if message.sender_endpoint == participants:
return message
return None
def get_opening_message(self) -> str:
"""Get opening message"""
return f"""Welcome to the discussion on "{self.space_dto.title}"!
Discussion objective: {self.space_dto.objective}
Let's begin!"""
def get_round_prompt(self, round: int) -> str:
"""
Get prompt for specified round
Args:
round: Round number
Returns:
str: Prompt content
"""
# Get messages from previous rounds
previous_messages = [msg for msg in self.space_dto.messages if msg.round < round]
# Build prompt
prompt = f"""This is round {round} of the discussion on "{self.space_dto.title}".
Discussion objective: {self.space_dto.objective}
"""
if previous_messages:
prompt += "\nPrevious discussion content:\n"
for msg in previous_messages:
prompt += f"{msg.sender_endpoint}: {msg.content}\n"
prompt += "\nPlease share your thoughts:"
return prompt
def get_summary_prompt(self) -> str:
"""Get summary prompt"""
# Get all discussion messages
discussion_messages = [msg for msg in self.space_dto.messages if msg.message_type == "discussion"]
prompt = f"""Please summarize the discussion on "{self.space_dto.title}".
Discussion objective: {self.space_dto.objective}
Discussion content:
"""
for msg in discussion_messages:
prompt += f"{msg.sender_endpoint} (Round {msg.round}): {msg.content}\n"
prompt += "\nPlease summarize the main points and conclusions:"
return prompt