State Management
The Penguin State System manages conversation state across sessions and provides structured message handling.
Core Components
MessageCategory Enum
class MessageCategory(Enum):
SYSTEM = 1 # System instructions, never truncated
CONTEXT = 2 # Important reference information
DIALOG = 3 # Main conversation between user and assistant
SYSTEM_OUTPUT = 4 # Results from tool executions
Message categories determine importance for context window management and provide a structured way to handle different types of content.
Message Class
@dataclass
class Message:
role: str
content: Any
category: MessageCategory
id: str = field(default_factory=lambda: f"msg_{uuid.uuid4().hex[:8]}")
timestamp: str = field(default_factory=lambda: datetime.now().isoformat())
metadata: Dict[str, Any] = field(default_factory=dict)
tokens: int = 0
Represents a single message in a conversation. The content
field can be:
- Plain text (str)
- Structured content for multimodal messages (list/dict)
- Images via OpenAI format
{"type": "image_url", "image_url": {...}}
- Other adapter-specific formats like audio or file attachments
Session Class
@dataclass
class Session:
id: str = field(default_factory=lambda: f"session_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{uuid.uuid4().hex[:8]}")
messages: List[Message] = field(default_factory=list)
created_at: str = field(default_factory=lambda: datetime.now().isoformat())
last_active: str = field(default_factory=lambda: datetime.now().isoformat())
metadata: Dict[str, Any] = field(default_factory=dict)
Represents a conversation session containing multiple messages. Sessions have their own identity and metadata, managing a collection of messages.
Session Boundaries and Transition
Session Manager
The SessionManager handles session lifecycle operations including:
class SessionManager:
def __init__(
self,
base_path: str = CONVERSATIONS_PATH,
max_messages_per_session: int = 5000,
max_sessions_in_memory: int = 20,
format: str = "json",
auto_save_interval: int = 60
)
Session Persistence
Key Features
-
Session Creation and Loading
def create_session(self) -> Session
def load_session(self, session_id: str) -> Optional[Session] -
Session Boundary Management
def check_session_boundary(self, session: Optional[Session] = None) -> bool
def create_continuation_session(self, source_session: Optional[Session] = None) -> Session -
Persistence with Safety
def save_session(self, session: Optional[Session] = None) -> bool
-
Session Listing and Management
def list_sessions(self, limit: int = 100, offset: int = 0) -> List[Dict]
def delete_session(self, session_id: str) -> bool
Usage Example
# Initialize session manager
session_manager = SessionManager(
base_path="/path/to/conversations",
max_messages_per_session=5000,
max_sessions_in_memory=20,
auto_save_interval=60
)
# Create a new session
session = session_manager.create_session()
# Add a message
message = Message(
role="user",
content="Hello, how are you?",
category=MessageCategory.DIALOG
)
session.add_message(message)
# Save the session
session_manager.save_session(session)
# Load a session
session = session_manager.load_session("session_20230401_123456")
# Check if session boundary reached
if session_manager.check_session_boundary(session):
# Create continuation session
new_session = session_manager.create_continuation_session(session)
Automatic Session Continuation
When a session reaches the max_messages_per_session
boundary, the system automatically:
- Saves the current session
- Creates a new continuation session
- Transfers all SYSTEM and CONTEXT messages to maintain continuity
- Updates metadata to track the relationship between sessions
This ensures seamless conversation continuity for users while managing system resources efficiently.
Transaction Safety
Sessions are saved with transaction safety mechanisms:
- Write to temporary file first
- Create backup of current file if it exists
- Atomic rename of temp to target
- Recovery from backup if primary is corrupted
Error Recovery
If a session fails to load due to corruption:
- The system attempts to load from a backup
- If backup fails, it creates a recovery session
- The recovery session includes a notice about the original session ID
Relationship Tracking
Sessions maintain relationships with continuation sessions through metadata:
continued_from
: ID of the previous sessioncontinued_to
: ID of the next sessioncontinuation_index
: Number of continuations from the original session
This allows accurate token tracking and navigation across session boundaries.
Immutability Pattern
Session and Message objects follow an immutability pattern:
- Operations create new instances rather than modifying existing ones
- This provides safer code and predictable state transitions
- When trimming, a new Session is returned instead of modifying the original