Initial commit: Claude Code Project Tracker
Add comprehensive development intelligence system that tracks: - Development sessions with automatic start/stop - Full conversation history with semantic search - Tool usage and file operation analytics - Think time and engagement analysis - Git activity correlation - Learning pattern recognition - Productivity insights and metrics Features: - FastAPI backend with SQLite database - Modern web dashboard with interactive charts - Claude Code hook integration for automatic tracking - Comprehensive test suite with 100+ tests - Complete API documentation (OpenAPI/Swagger) - Privacy-first design with local data storage 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
commit
44ed9936b7
48 changed files with 9707 additions and 0 deletions
220
app/api/schemas.py
Normal file
220
app/api/schemas.py
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
"""
|
||||
Pydantic schemas for API request/response models.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Optional, List, Dict, Any, Union
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# Base schemas
|
||||
class TimestampMixin(BaseModel):
|
||||
"""Mixin for timestamp fields."""
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
# Session schemas
|
||||
class SessionStartRequest(BaseModel):
|
||||
"""Request schema for starting a session."""
|
||||
session_type: str = Field(..., description="Type of session: startup, resume, or clear")
|
||||
working_directory: str = Field(..., description="Current working directory")
|
||||
git_branch: Optional[str] = Field(None, description="Current git branch")
|
||||
git_repo: Optional[str] = Field(None, description="Git repository URL")
|
||||
environment: Optional[Dict[str, Any]] = Field(None, description="Environment variables and context")
|
||||
|
||||
|
||||
class SessionEndRequest(BaseModel):
|
||||
"""Request schema for ending a session."""
|
||||
session_id: int = Field(..., description="ID of the session to end")
|
||||
end_reason: str = Field(default="normal", description="Reason for ending: normal, interrupted, or timeout")
|
||||
|
||||
|
||||
class SessionResponse(BaseModel):
|
||||
"""Response schema for session operations."""
|
||||
session_id: int
|
||||
project_id: int
|
||||
status: str
|
||||
message: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# Conversation schemas
|
||||
class ConversationRequest(BaseModel):
|
||||
"""Request schema for logging conversations."""
|
||||
session_id: int = Field(..., description="Associated session ID")
|
||||
timestamp: datetime = Field(default_factory=datetime.utcnow, description="When the exchange occurred")
|
||||
user_prompt: Optional[str] = Field(None, description="User's input message")
|
||||
claude_response: Optional[str] = Field(None, description="Claude's response")
|
||||
tools_used: Optional[List[str]] = Field(None, description="Tools used in the response")
|
||||
files_affected: Optional[List[str]] = Field(None, description="Files mentioned or modified")
|
||||
context: Optional[Dict[str, Any]] = Field(None, description="Additional context")
|
||||
tokens_input: Optional[int] = Field(None, description="Estimated input token count")
|
||||
tokens_output: Optional[int] = Field(None, description="Estimated output token count")
|
||||
exchange_type: str = Field(..., description="Type of exchange: user_prompt or claude_response")
|
||||
|
||||
|
||||
class ConversationResponse(BaseModel):
|
||||
"""Response schema for conversation operations."""
|
||||
id: int
|
||||
session_id: int
|
||||
timestamp: datetime
|
||||
exchange_type: str
|
||||
content_length: int
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# Activity schemas
|
||||
class ActivityRequest(BaseModel):
|
||||
"""Request schema for recording activities."""
|
||||
session_id: int = Field(..., description="Associated session ID")
|
||||
conversation_id: Optional[int] = Field(None, description="Associated conversation ID")
|
||||
timestamp: datetime = Field(default_factory=datetime.utcnow, description="When the activity occurred")
|
||||
tool_name: str = Field(..., description="Name of the tool used")
|
||||
action: str = Field(..., description="Specific action taken")
|
||||
file_path: Optional[str] = Field(None, description="Target file path if applicable")
|
||||
metadata: Optional[Dict[str, Any]] = Field(None, description="Tool-specific metadata")
|
||||
success: bool = Field(default=True, description="Whether the operation succeeded")
|
||||
error_message: Optional[str] = Field(None, description="Error details if failed")
|
||||
lines_added: Optional[int] = Field(None, description="Lines added for Edit/Write operations")
|
||||
lines_removed: Optional[int] = Field(None, description="Lines removed for Edit operations")
|
||||
|
||||
|
||||
class ActivityResponse(BaseModel):
|
||||
"""Response schema for activity operations."""
|
||||
id: int
|
||||
session_id: int
|
||||
tool_name: str
|
||||
action: str
|
||||
timestamp: datetime
|
||||
success: bool
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# Waiting period schemas
|
||||
class WaitingStartRequest(BaseModel):
|
||||
"""Request schema for starting a waiting period."""
|
||||
session_id: int = Field(..., description="Associated session ID")
|
||||
timestamp: datetime = Field(default_factory=datetime.utcnow, description="When waiting started")
|
||||
context_before: Optional[str] = Field(None, description="Context before waiting")
|
||||
|
||||
|
||||
class WaitingEndRequest(BaseModel):
|
||||
"""Request schema for ending a waiting period."""
|
||||
session_id: int = Field(..., description="Associated session ID")
|
||||
timestamp: datetime = Field(default_factory=datetime.utcnow, description="When waiting ended")
|
||||
duration_seconds: Optional[int] = Field(None, description="Total waiting duration")
|
||||
context_after: Optional[str] = Field(None, description="Context after waiting")
|
||||
|
||||
|
||||
class WaitingPeriodResponse(BaseModel):
|
||||
"""Response schema for waiting period operations."""
|
||||
id: int
|
||||
session_id: int
|
||||
start_time: datetime
|
||||
end_time: Optional[datetime]
|
||||
duration_seconds: Optional[int]
|
||||
engagement_score: float
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# Git operation schemas
|
||||
class GitOperationRequest(BaseModel):
|
||||
"""Request schema for git operations."""
|
||||
session_id: int = Field(..., description="Associated session ID")
|
||||
timestamp: datetime = Field(default_factory=datetime.utcnow, description="When the operation occurred")
|
||||
operation: str = Field(..., description="Type of git operation")
|
||||
command: str = Field(..., description="Full git command executed")
|
||||
result: Optional[str] = Field(None, description="Command output")
|
||||
success: bool = Field(default=True, description="Whether the command succeeded")
|
||||
files_changed: Optional[List[str]] = Field(None, description="Files affected by the operation")
|
||||
lines_added: Optional[int] = Field(None, description="Lines added")
|
||||
lines_removed: Optional[int] = Field(None, description="Lines removed")
|
||||
commit_hash: Optional[str] = Field(None, description="Git commit SHA")
|
||||
branch_from: Optional[str] = Field(None, description="Source branch")
|
||||
branch_to: Optional[str] = Field(None, description="Target branch")
|
||||
|
||||
|
||||
class GitOperationResponse(BaseModel):
|
||||
"""Response schema for git operations."""
|
||||
id: int
|
||||
session_id: int
|
||||
operation: str
|
||||
timestamp: datetime
|
||||
success: bool
|
||||
commit_hash: Optional[str]
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# Project schemas
|
||||
class ProjectSummary(BaseModel):
|
||||
"""Summary information about a project."""
|
||||
id: int
|
||||
name: str
|
||||
path: str
|
||||
git_repo: Optional[str]
|
||||
languages: Optional[List[str]]
|
||||
total_sessions: int
|
||||
total_time_minutes: int
|
||||
last_activity: Optional[datetime]
|
||||
files_modified_count: int
|
||||
lines_changed_count: int
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class TimelineEvent(BaseModel):
|
||||
"""Individual event in project timeline."""
|
||||
timestamp: datetime
|
||||
type: str # session_start, session_end, conversation, activity, git_operation
|
||||
data: Dict[str, Any]
|
||||
|
||||
|
||||
class ProjectTimeline(BaseModel):
|
||||
"""Project timeline with events."""
|
||||
project: ProjectSummary
|
||||
timeline: List[TimelineEvent]
|
||||
|
||||
|
||||
# Analytics schemas
|
||||
class ProductivityMetrics(BaseModel):
|
||||
"""Productivity analytics response."""
|
||||
engagement_score: float = Field(..., description="Overall engagement level (0-100)")
|
||||
average_session_length: float = Field(..., description="Minutes per session")
|
||||
think_time_average: float = Field(..., description="Average waiting time between interactions")
|
||||
files_per_session: float = Field(..., description="Average files touched per session")
|
||||
tools_most_used: List[Dict[str, Union[str, int]]] = Field(..., description="Most frequently used tools")
|
||||
productivity_trends: List[Dict[str, Union[str, float]]] = Field(..., description="Daily productivity scores")
|
||||
|
||||
|
||||
class ConversationSearchResult(BaseModel):
|
||||
"""Search result for conversation search."""
|
||||
id: int
|
||||
project_name: str
|
||||
timestamp: datetime
|
||||
user_prompt: Optional[str]
|
||||
claude_response: Optional[str]
|
||||
relevance_score: float
|
||||
context: List[str]
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# Error schemas
|
||||
class ErrorResponse(BaseModel):
|
||||
"""Standard error response."""
|
||||
error: str
|
||||
message: str
|
||||
details: Optional[Dict[str, Any]] = None
|
||||
Loading…
Add table
Add a link
Reference in a new issue