"""Data models for session archival system."""
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Any
@dataclass
class SessionMessage:
"""A single message in the session buffer."""
id: str
role: str
content: str
created_at: str = field(default_factory=lambda: datetime.now(timezone.utc).isoformat())
@property
def estimated_tokens(self) -> int:
return max(1, len(self.content) // 4)
@dataclass
class SessionMeta:
"""Session metadata persisted alongside the buffer."""
session_id: str = ""
created_at: str = field(default_factory=lambda: datetime.now(timezone.utc).isoformat())
updated_at: str = ""
message_count: int = 0
commit_count: int = 0
last_commit_at: str = ""
account_id: str = ""
user_id: str = ""
agent_id: str = ""
@dataclass
class ArchiveEntry:
"""A single archived session.
Represents a compressed snapshot of a session's conversation history.
"""
archive_id: str
session_id: str
overview: str
abstract: str
messages: list[dict]
created_at: str = field(default_factory=lambda: datetime.now(timezone.utc).isoformat())
metadata: dict[str, Any] = field(default_factory=dict)
@dataclass
class ArchiveWriteResult:
"""Result of writing an archive to storage."""
archive_id: str
session_id: str
uri: str
success: bool
error: str | None = None
created_at: str = field(default_factory=lambda: datetime.now(timezone.utc).isoformat())
@dataclass
class SessionWindowState:
"""Rolling compressed window for session state layer (Layer 2).
Structured state object for cognitive state assembly, not just
chat history compression. Updated every N turns (not every turn like
Layer 3, not never like Layer 1). Provides the LLM awareness of recent
conversation flow without re-sending all messages. Goes into
systemPromptSuffix for KV cache friendliness.
"""
compressed_text: str = ""
turn_count_at_last_compress: int = 0
token_count_at_last_compress: int = 0
skills_text: str = ""
active_task: str = ""
confirmed_constraints: list[str] = field(default_factory=list)
recent_decisions: list[str] = field(default_factory=list)
open_loops: list[str] = field(default_factory=list)
uncertainties: list[str] = field(default_factory=list)
last_accessed_at: str = ""
session_state_version: int = 0
session_state_synced_at: str = ""
session_state_sync_turn_count: int = 0