Architecture 5 Session - djvolz/coda-code-assistant GitHub Wiki
This document describes the architectural design of the Session module, including:
- High-level architecture and structure for conversation persistence
- Design decisions for message storage and retrieval
- Patterns for database management and context optimization
- Component relationships between storage, management, and context handling
- Primary implementation:
coda/session/manager.py - Database layer:
coda/session/database.py - Data models:
coda/session/models.py - Context management:
coda/session/context.py - Session commands:
coda/session/commands.py - Tests:
tests/test_session.py,tests/session/
The Session module provides conversation persistence and management for Coda Code Assistant. It uses SQLAlchemy with SQLite to store sessions, messages, and metadata, while providing intelligent context management for optimal LLM interactions. The architecture centers around the SessionManager class in coda/session/manager.py.
coda/session/
├── __init__.py # Module exports
├── manager.py # Core session management
├── database.py # SQLite connection handling
├── models.py # SQLAlchemy data models
├── context.py # Context window optimization
└── commands.py # CLI command implementations
Location: coda/session/manager.py
Purpose: Central orchestrator for all session operations
Key Methods:
-
create_session(): Creates new conversation sessions -
add_message(): Adds messages with metadata tracking -
get_session_context(): Retrieves optimized conversation context -
search_sessions(): Full-text search across sessions -
export_session(): Exports in multiple formats
Location: coda/session/database.py
Purpose: Manages SQLite connections and database operations
Key Features:
- Connection pooling with SQLAlchemy
- WAL mode for concurrent access
- Full-text search (FTS5) initialization
- Database maintenance operations
Location: coda/session/models.py
Purpose: SQLAlchemy ORM models for data persistence
Key Models:
-
Session: Conversation session with metadata -
Message: Individual messages with token tracking -
Tag: Organizational tags for sessions -
Attachment: File attachments for messages
Location: coda/session/context.py
Purpose: Intelligent context window optimization for LLMs
Key Features:
- Model-specific context limits
- Token counting and estimation
- Message prioritization strategies
- Context summarization
Implementation: coda/session/manager.py
Why this pattern: Abstracts database operations from business logic, making the system more testable and maintainable.
class SessionManager:
"""Manages session persistence and operations."""
def __init__(self, database: SessionDatabase | None = None):
self.db = database or SessionDatabase()
self.context_manager = ContextManager()Implementation: coda/session/database.py
Why this pattern: Ensures database operations are atomic and consistent.
@contextmanager
def get_session(self) -> DBSession:
"""Get a database session context manager."""
session = self.SessionLocal()
try:
yield session
session.commit()
except Exception:
session.rollback()
raise
finally:
session.close()sequenceDiagram
participant CLI
participant SessionManager
participant Database
participant SQLite
participant FTS
CLI->>SessionManager: create_session()
SessionManager->>Database: get_session()
Database->>SQLite: BEGIN TRANSACTION
SessionManager->>SQLite: INSERT INTO sessions
SessionManager->>SQLite: COMMIT
CLI->>SessionManager: add_message()
SessionManager->>Database: get_session()
SessionManager->>SQLite: INSERT INTO messages
SessionManager->>FTS: INSERT INTO messages_fts
SessionManager->>SQLite: UPDATE sessions (stats)
Database->>SQLite: COMMIT
CLI->>SessionManager: search_sessions(query)
SessionManager->>FTS: MATCH query
FTS->>SessionManager: Return matches
SessionManager->>SQLite: Fetch full data
SessionManager->>CLI: Return results
erDiagram
Session ||--o{ Message : contains
Session ||--o{ Tag : has
Session ||--o| Session : branches_from
Message ||--o{ Attachment : has
Message ||--|| Session : belongs_to
Session {
string id PK
string name
string provider
string model
datetime created_at
datetime updated_at
int message_count
int total_tokens
float total_cost
}
Message {
string id PK
string session_id FK
int sequence
string role
text content
int prompt_tokens
int completion_tokens
datetime created_at
}
Tag {
string id PK
string name
string color
}
Location: coda/session/manager.py
Purpose: Main interface for session operations
Key Methods:
-
create_session(name, provider, model, **kwargs): Create new session -
add_message(session_id, role, content, **kwargs): Add message -
get_session(session_id): Retrieve session by ID -
get_active_sessions(limit, offset): List active sessions -
search_sessions(query, limit): Search with FTS -
export_session(session_id, format): Export session data
Location: coda/session/database.py
Purpose: Database connection and initialization
Key Methods:
-
__init__(db_path): Initialize with custom path -
get_session(): Get database session context -
vacuum(): Optimize database storage -
backup(backup_path): Create database backup
Context: Need for local, file-based storage without external dependencies Decision: Use SQLite with SQLAlchemy ORM for data persistence Rationale:
- Zero configuration database
- Excellent performance for single-user scenarios
- Rich querying capabilities with SQLAlchemy
- Easy backup and portability Trade-offs:
- Pros: Simple deployment, no server required, ACID compliant
- Cons: Limited concurrent write performance
Implementation: See
database.py
Context: Need for fast full-text search across message history Decision: Use SQLite's FTS5 virtual table Rationale: Native SQLite feature with excellent performance Trade-offs:
- Pros: Fast search, minimal overhead, ranking support
- Cons: Requires separate index maintenance
Implementation: FTS table creation in
database.pyand search inmanager.py
Context: LLMs have token limits requiring intelligent message selection Decision: Separate ContextManager for optimization strategies Rationale: Decouple context logic from persistence layer Trade-offs:
- Pros: Flexible strategies, model-specific handling
- Cons: Additional complexity
Implementation: See
context.py
- Separation of Concerns: Database, business logic, and context optimization are separate
- Fail-Safe Defaults: Transactions rollback on error, sensible defaults throughout
- Performance First: Indexes on commonly queried fields, efficient FTS
- Extensibility: Easy to add new export formats, storage backends
Config File: ~/.config/coda/config.toml
Database Location: ~/.config/coda/sessions.db
| Option | Type | Default | Description |
|---|---|---|---|
| session.autosave | bool | true | Auto-save messages |
| session.max_export_size | int | 10MB | Max export file size |
| session.fts_enabled | bool | true | Enable full-text search |
-
coda.configuration: Configuration management -
coda.constants: Database path constants
-
sqlalchemy>=2.0.0: ORM and database toolkit -
sqlite3: Built-in Python SQLite support
- Unit tests:
tests/test_session.py - Integration tests:
tests/session/test_session_integration.py - Database tests:
tests/session/test_database.py
- Session Creation: Tests session initialization with various parameters
- Message Addition: Tests message persistence and statistics updates
- FTS Search: Tests full-text search functionality
- Export Formats: Tests JSON, Markdown, HTML exports
-
SessionNotFoundError: When session ID doesn't exist -
DatabaseError: For database operation failures -
ExportError: For export format issues
try:
session = self.get_session(session_id)
if not session:
raise SessionNotFoundError(f"Session {session_id} not found")
except SQLAlchemyError as e:
logger.error(f"Database error: {e}")
raise DatabaseError(str(e))- Connection Pooling: Static pool prevents connection overhead
- WAL Mode: Better concurrency for reads during writes
- Lazy Loading: Messages loaded on demand, not with session
- Indexed Fields: All commonly queried fields have indexes
- SQL Injection Prevention: All queries use parameterized statements
- File Path Validation: Database path sanitized on initialization
- No Credential Storage: No sensitive data in session database
from coda.session import SessionManager
# Create manager
manager = SessionManager()
# Create session
session = manager.create_session(
name="Python Help",
provider="openai",
model="gpt-4"
)
# Add messages
manager.add_message(
session_id=session.id,
role="user",
content="How do I read a file in Python?"
)
# Search sessions
results = manager.search_sessions("python file")# Export to various formats
json_export = manager.export_session(session.id, format="json")
markdown_export = manager.export_session(session.id, format="markdown")
html_export = manager.export_session(session.id, format="html")-
CLI Module: Session commands in
interactive_cli.py - Provider Module: Stores provider responses and metadata
- Agent Module: Tool invocation results stored in messages
-
Custom Export Formats: Add methods like
_export_csv() - Alternative Storage: Implement new database backend
- Search Strategies: Extend search with semantic capabilities
- Single User: Designed for local, single-user scenarios
- SQLite Limits: Large databases may need optimization
- No Remote Sync: Local storage only, no cloud backup
All files referenced in this document:
- coda/session/manager.py
- coda/session/database.py
- coda/session/models.py
- coda/session/context.py
- coda/session/commands.py
- tests/test_session.py
- tests/session/