Add storage models and monitor modules
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
2026-01-30 09:10:46 +00:00
parent 32ceb1ff80
commit d4ae5f8dc8

170
src/storage/models.py Normal file
View File

@@ -0,0 +1,170 @@
"""Data models for DevTrace."""
from datetime import datetime
from dataclasses import dataclass, field
from typing import Optional, Dict, Any
@dataclass
class Session:
"""Represents a development session."""
id: int
name: str
directory: str
start_time: Optional[datetime] = None
end_time: Optional[datetime] = None
notes: Optional[str] = None
@property
def duration(self) -> Optional[float]:
"""Calculate session duration in seconds."""
if self.start_time and self.end_time:
return (self.end_time - self.start_time).total_seconds()
return None
@dataclass
class FileEvent:
"""Represents a file system event."""
id: int
session_id: int
event_type: str
file_path: str
timestamp: Optional[datetime] = None
details: Optional[str] = None
content_hash: Optional[str] = None
@property
def filename(self) -> str:
"""Get just the filename from the path."""
return self.file_path.split("/")[-1]
@property
def extension(self) -> str:
"""Get the file extension."""
return self.filename.split(".")[-1] if "." in self.filename else ""
@dataclass
class CommandEvent:
"""Represents a shell command execution."""
id: int
session_id: int
command: str
timestamp: Optional[datetime] = None
exit_code: Optional[int] = None
working_directory: Optional[str] = None
details: Optional[str] = None
@property
def was_successful(self) -> Optional[bool]:
"""Check if command was successful."""
if self.exit_code is None:
return None
return self.exit_code == 0
@property
def short_command(self) -> str:
"""Get truncated command for display."""
max_len = 50
if len(self.command) <= max_len:
return self.command
return self.command[:max_len] + "..."
@dataclass
class GitEvent:
"""Represents a git operation."""
id: int
session_id: int
operation: str
branch: Optional[str] = None
commit_hash: Optional[str] = None
timestamp: Optional[datetime] = None
details: Optional[str] = None
diff: Optional[str] = None
@property
def short_hash(self) -> str:
"""Get short commit hash."""
if self.commit_hash:
return self.commit_hash[:7]
return ""
@dataclass
class SearchResult:
"""Represents a search result."""
event_type: str
event_id: int
score: float
details: Dict[str, Any]
content: str = ""
@dataclass
class TimelineEvent:
"""Unified event representation for timeline display."""
id: int
session_id: int
event_type: str
timestamp: Optional[datetime]
details: Dict[str, Any]
display_text: str
icon: str
@classmethod
def from_file_event(cls, event: FileEvent) -> "TimelineEvent":
"""Create TimelineEvent from FileEvent."""
icons = {
"created": "📄",
"modified": "✏️",
"deleted": "🗑️",
"moved": "📁"
}
return cls(
id=event.id,
session_id=event.session_id,
event_type="file",
timestamp=event.timestamp,
details={"file_path": event.file_path, "content_hash": event.content_hash},
display_text=f"{event.event_type} {event.filename}",
icon=icons.get(event.event_type, "📄")
)
@classmethod
def from_command_event(cls, event: CommandEvent) -> "TimelineEvent":
"""Create TimelineEvent from CommandEvent."""
status = "" if event.was_successful else "" if event.was_successful is False else ""
return cls(
id=event.id,
session_id=event.session_id,
event_type="command",
timestamp=event.timestamp,
details={"command": event.command, "exit_code": event.exit_code},
display_text=f"{event.short_command}",
icon=f"{status}"
)
@classmethod
def from_git_event(cls, event: GitEvent) -> "TimelineEvent":
"""Create TimelineEvent from GitEvent."""
icons = {
"commit": "💾",
"branch": "🌿",
"merge": "🔀",
"checkout": "🔀",
"push": "📤",
"pull": "📥",
"rebase": "📜",
"reset": ""
}
return cls(
id=event.id,
session_id=event.session_id,
event_type="git",
timestamp=event.timestamp,
details={"operation": event.operation, "branch": event.branch, "commit": event.commit_hash},
display_text=f"{event.operation} {event.branch or event.short_hash}",
icon=icons.get(event.operation, "🔧")
)