Add comprehensive Docker deployment and file upload functionality
Features Added: • Docker containerization with multi-stage Python 3.12 build • Caddy reverse proxy integration with automatic SSL • File upload interface for .claude.json imports with preview • Comprehensive hook system with 39+ hook types across 9 categories • Complete documentation system with Docker and import guides Technical Improvements: • Enhanced database models with hook tracking capabilities • Robust file validation and error handling for uploads • Production-ready Docker compose configuration • Health checks and resource limits for containers • Database initialization scripts for containerized deployments Documentation: • Docker Deployment Guide with troubleshooting • Data Import Guide with step-by-step instructions • Updated Getting Started guide with new features • Enhanced documentation index with responsive grid layout 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
bec1606c86
commit
50c80596d0
36 changed files with 4334 additions and 172 deletions
|
|
@ -10,6 +10,11 @@ from .activity import Activity
|
|||
from .waiting_period import WaitingPeriod
|
||||
from .git_operation import GitOperation
|
||||
from .tool_call import ToolCall
|
||||
from .hooks import (
|
||||
HookEvent, ToolError, WaitingPeriodNew, PerformanceMetric,
|
||||
CodeQualityEvent, WorkflowEvent, LearningEvent,
|
||||
EnvironmentEvent, CollaborationEvent, ProjectIntelligence
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"Base",
|
||||
|
|
@ -20,4 +25,14 @@ __all__ = [
|
|||
"WaitingPeriod",
|
||||
"GitOperation",
|
||||
"ToolCall",
|
||||
"HookEvent",
|
||||
"ToolError",
|
||||
"WaitingPeriodNew",
|
||||
"PerformanceMetric",
|
||||
"CodeQualityEvent",
|
||||
"WorkflowEvent",
|
||||
"LearningEvent",
|
||||
"EnvironmentEvent",
|
||||
"CollaborationEvent",
|
||||
"ProjectIntelligence",
|
||||
]
|
||||
225
app/models/hooks.py
Normal file
225
app/models/hooks.py
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
"""
|
||||
Comprehensive hook tracking models for Claude Code sessions.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Optional, Dict, Any
|
||||
from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, Boolean, Float, JSON
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from app.models.base import Base
|
||||
|
||||
|
||||
class HookEvent(Base):
|
||||
"""
|
||||
Base model for all hook events with common fields.
|
||||
"""
|
||||
__tablename__ = "hook_events"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
|
||||
hook_type = Column(String(50), nullable=False, index=True)
|
||||
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
|
||||
data = Column(JSON, nullable=True) # Flexible JSON data for hook-specific information
|
||||
|
||||
# Relationships
|
||||
session = relationship("Session", back_populates="hook_events")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<HookEvent(id={self.id}, type={self.hook_type}, session={self.session_id})>"
|
||||
|
||||
|
||||
class ToolError(Base):
|
||||
"""Track failed tool calls with error details."""
|
||||
__tablename__ = "tool_errors"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
|
||||
tool_name = Column(String(100), nullable=False, index=True)
|
||||
error_type = Column(String(100), nullable=False, index=True)
|
||||
error_message = Column(Text, nullable=False)
|
||||
stack_trace = Column(Text, nullable=True)
|
||||
parameters = Column(JSON, nullable=True)
|
||||
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
|
||||
|
||||
session = relationship("Session")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<ToolError(id={self.id}, tool={self.tool_name}, error={self.error_type})>"
|
||||
|
||||
|
||||
class WaitingPeriodNew(Base):
|
||||
"""Track periods when Claude is thinking vs actively working."""
|
||||
__tablename__ = "waiting_periods_new"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
|
||||
start_time = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
|
||||
end_time = Column(DateTime, nullable=True)
|
||||
duration_ms = Column(Integer, nullable=True)
|
||||
reason = Column(String(100), nullable=True, index=True) # thinking, processing, waiting_for_input
|
||||
context = Column(Text, nullable=True) # What was happening when waiting started
|
||||
|
||||
session = relationship("Session")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<WaitingPeriodNew(id={self.id}, reason={self.reason}, duration={self.duration_ms}ms)>"
|
||||
|
||||
|
||||
class PerformanceMetric(Base):
|
||||
"""Monitor system performance during development."""
|
||||
__tablename__ = "performance_metrics"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
|
||||
metric_type = Column(String(50), nullable=False, index=True) # memory, cpu, disk
|
||||
value = Column(Float, nullable=False)
|
||||
unit = Column(String(20), nullable=False) # MB, %, seconds
|
||||
threshold_exceeded = Column(Boolean, default=False)
|
||||
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
|
||||
|
||||
session = relationship("Session")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<PerformanceMetric(id={self.id}, type={self.metric_type}, value={self.value}{self.unit})>"
|
||||
|
||||
|
||||
class CodeQualityEvent(Base):
|
||||
"""Track code quality analysis, linting, and testing."""
|
||||
__tablename__ = "code_quality_events"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
|
||||
event_type = Column(String(50), nullable=False, index=True) # lint, format, test, build, analysis
|
||||
file_path = Column(Text, nullable=True)
|
||||
tool_name = Column(String(100), nullable=True) # eslint, prettier, pytest, etc.
|
||||
status = Column(String(20), nullable=False, index=True) # success, warning, error
|
||||
issues_count = Column(Integer, default=0)
|
||||
details = Column(JSON, nullable=True) # Specific issues, test results, etc.
|
||||
duration_ms = Column(Integer, nullable=True)
|
||||
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
|
||||
|
||||
session = relationship("Session")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<CodeQualityEvent(id={self.id}, type={self.event_type}, status={self.status})>"
|
||||
|
||||
|
||||
class WorkflowEvent(Base):
|
||||
"""Track development workflow patterns."""
|
||||
__tablename__ = "workflow_events"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
|
||||
event_type = Column(String(50), nullable=False, index=True) # context_switch, search_query, browser_tab, etc.
|
||||
description = Column(Text, nullable=True)
|
||||
event_metadata = Column(JSON, nullable=True) # Event-specific data
|
||||
source = Column(String(100), nullable=True) # Where the event came from
|
||||
duration_ms = Column(Integer, nullable=True) # For events with duration
|
||||
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
|
||||
|
||||
session = relationship("Session")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<WorkflowEvent(id={self.id}, type={self.event_type})>"
|
||||
|
||||
|
||||
class LearningEvent(Base):
|
||||
"""Track learning sessions and knowledge acquisition."""
|
||||
__tablename__ = "learning_events"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
|
||||
event_type = Column(String(50), nullable=False, index=True) # tutorial, documentation, experimentation
|
||||
topic = Column(String(200), nullable=True, index=True) # What was being learned
|
||||
resource_url = Column(Text, nullable=True) # Documentation URL, tutorial link
|
||||
confidence_before = Column(Integer, nullable=True) # 1-10 scale
|
||||
confidence_after = Column(Integer, nullable=True) # 1-10 scale
|
||||
notes = Column(Text, nullable=True)
|
||||
duration_ms = Column(Integer, nullable=True)
|
||||
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
|
||||
|
||||
session = relationship("Session")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<LearningEvent(id={self.id}, topic={self.topic})>"
|
||||
|
||||
|
||||
class EnvironmentEvent(Base):
|
||||
"""Track environment and configuration changes."""
|
||||
__tablename__ = "environment_events"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
|
||||
event_type = Column(String(50), nullable=False, index=True) # env_change, config_update, security_scan
|
||||
environment = Column(String(50), nullable=True, index=True) # dev, staging, prod
|
||||
config_file = Column(Text, nullable=True)
|
||||
changes = Column(JSON, nullable=True) # What changed
|
||||
impact_level = Column(String(20), nullable=True) # low, medium, high, critical
|
||||
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
|
||||
|
||||
session = relationship("Session")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<EnvironmentEvent(id={self.id}, type={self.event_type}, env={self.environment})>"
|
||||
|
||||
|
||||
class CollaborationEvent(Base):
|
||||
"""Track collaboration and external interactions."""
|
||||
__tablename__ = "collaboration_events"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
|
||||
event_type = Column(String(50), nullable=False, index=True) # external_resource, ai_question, review_request
|
||||
interaction_type = Column(String(50), nullable=True) # documentation, stackoverflow, api_docs
|
||||
query_or_topic = Column(Text, nullable=True)
|
||||
resource_url = Column(Text, nullable=True)
|
||||
response_quality = Column(Integer, nullable=True) # 1-5 rating
|
||||
time_to_resolution = Column(Integer, nullable=True) # minutes
|
||||
event_metadata = Column(JSON, nullable=True)
|
||||
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
|
||||
|
||||
session = relationship("Session")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<CollaborationEvent(id={self.id}, type={self.event_type})>"
|
||||
|
||||
|
||||
class ProjectIntelligence(Base):
|
||||
"""Track high-level project development patterns."""
|
||||
__tablename__ = "project_intelligence"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
session_id = Column(String, ForeignKey("sessions.id"), nullable=False, index=True)
|
||||
event_type = Column(String(50), nullable=False, index=True) # refactor, feature_flag, debugging_session
|
||||
scope = Column(String(20), nullable=True, index=True) # small, medium, large
|
||||
complexity = Column(String(20), nullable=True, index=True) # low, medium, high
|
||||
start_time = Column(DateTime, nullable=False, default=datetime.utcnow)
|
||||
end_time = Column(DateTime, nullable=True)
|
||||
duration_minutes = Column(Integer, nullable=True)
|
||||
files_affected = Column(JSON, nullable=True) # List of file paths
|
||||
outcome = Column(String(20), nullable=True) # success, partial, failed, abandoned
|
||||
notes = Column(Text, nullable=True)
|
||||
timestamp = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
|
||||
|
||||
session = relationship("Session")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<ProjectIntelligence(id={self.id}, type={self.event_type}, scope={self.scope})>"
|
||||
|
||||
|
||||
# Add hook_events relationship to Session model
|
||||
def add_hook_relationships():
|
||||
"""Add hook event relationships to the Session model."""
|
||||
from app.models.session import Session
|
||||
|
||||
Session.hook_events = relationship("HookEvent", back_populates="session", cascade="all, delete-orphan")
|
||||
Session.tool_errors = relationship("ToolError", cascade="all, delete-orphan")
|
||||
Session.waiting_periods_new = relationship("WaitingPeriodNew", cascade="all, delete-orphan")
|
||||
Session.performance_metrics = relationship("PerformanceMetric", cascade="all, delete-orphan")
|
||||
Session.code_quality_events = relationship("CodeQualityEvent", cascade="all, delete-orphan")
|
||||
Session.workflow_events = relationship("WorkflowEvent", cascade="all, delete-orphan")
|
||||
Session.learning_events = relationship("LearningEvent", cascade="all, delete-orphan")
|
||||
Session.environment_events = relationship("EnvironmentEvent", cascade="all, delete-orphan")
|
||||
Session.collaboration_events = relationship("CollaborationEvent", cascade="all, delete-orphan")
|
||||
Session.project_intelligence = relationship("ProjectIntelligence", cascade="all, delete-orphan")
|
||||
Loading…
Add table
Add a link
Reference in a new issue