#!/usr/bin/env python3 """Data models for Claude Code Hooks system""" from dataclasses import dataclass, field from datetime import datetime from typing import Dict, List, Optional, Any import json @dataclass class ToolExecution: """Single tool execution record""" timestamp: datetime tool: str parameters: Dict[str, Any] success: bool error_message: Optional[str] = None execution_time: float = 0.0 context: Dict[str, Any] = field(default_factory=dict) def to_dict(self) -> Dict[str, Any]: return { "timestamp": self.timestamp.isoformat(), "tool": self.tool, "parameters": self.parameters, "success": self.success, "error_message": self.error_message, "execution_time": self.execution_time, "context": self.context } @classmethod def from_dict(cls, data: Dict[str, Any]) -> 'ToolExecution': return cls( timestamp=datetime.fromisoformat(data["timestamp"]), tool=data["tool"], parameters=data["parameters"], success=data["success"], error_message=data.get("error_message"), execution_time=data.get("execution_time", 0.0), context=data.get("context", {}) ) @dataclass class Pattern: """Learned pattern with confidence scoring""" pattern_id: str pattern_type: str # "command_failure", "tool_sequence", "context_error" trigger: Dict[str, Any] # What triggers this pattern prediction: Dict[str, Any] # What we predict will happen confidence: float # 0.0 to 1.0 evidence_count: int # How many times we've seen this last_seen: datetime success_rate: float = 0.0 def to_dict(self) -> Dict[str, Any]: return { "pattern_id": self.pattern_id, "pattern_type": self.pattern_type, "trigger": self.trigger, "prediction": self.prediction, "confidence": self.confidence, "evidence_count": self.evidence_count, "last_seen": self.last_seen.isoformat(), "success_rate": self.success_rate } @classmethod def from_dict(cls, data: Dict[str, Any]) -> 'Pattern': return cls( pattern_id=data["pattern_id"], pattern_type=data["pattern_type"], trigger=data["trigger"], prediction=data["prediction"], confidence=data["confidence"], evidence_count=data["evidence_count"], last_seen=datetime.fromisoformat(data["last_seen"]), success_rate=data.get("success_rate", 0.0) ) @dataclass class HookResult: """Result of hook execution""" allow: bool message: str = "" warning: bool = False metadata: Dict[str, Any] = field(default_factory=dict) @classmethod def success(cls, message: str = "Operation allowed") -> 'HookResult': return cls(allow=True, message=message) @classmethod def blocked(cls, reason: str) -> 'HookResult': return cls(allow=False, message=reason) @classmethod def allow_with_warning(cls, warning: str) -> 'HookResult': return cls(allow=True, message=warning, warning=True) def to_claude_response(self) -> Dict[str, Any]: """Convert to Claude Code hook response format""" response = { "allow": self.allow, "message": self.message } if self.metadata: response.update(self.metadata) return response @dataclass class ValidationResult: """Result of validation operations""" allowed: bool reason: str = "" severity: str = "info" # info, warning, medium, high, critical suggestions: List[str] = field(default_factory=list) @property def is_critical(self) -> bool: return self.severity == "critical" @property def is_blocking(self) -> bool: return not self.allowed @dataclass class BackupDecision: """Decision about whether to trigger backup""" should_backup: bool reason: str urgency: str = "medium" # low, medium, high metadata: Dict[str, Any] = field(default_factory=dict) @dataclass class BackupResult: """Result of backup operation""" success: bool backup_id: str = "" backup_path: str = "" error: str = "" git_success: bool = False fallback_performed: bool = False components: Dict[str, Any] = field(default_factory=dict) @dataclass class GitBackupResult: """Result of git backup operation""" success: bool commit_id: str = "" message: str = "" error: str = "" class PatternDatabase: """Fast lookup database for learned patterns""" def __init__(self): self.command_patterns: Dict[str, Pattern] = {} self.sequence_patterns: List[Pattern] = [] self.context_patterns: Dict[str, Pattern] = {} self.execution_history: List[ToolExecution] = [] def to_dict(self) -> Dict[str, Any]: return { "command_patterns": {k: v.to_dict() for k, v in self.command_patterns.items()}, "sequence_patterns": [p.to_dict() for p in self.sequence_patterns], "context_patterns": {k: v.to_dict() for k, v in self.context_patterns.items()}, "execution_history": [e.to_dict() for e in self.execution_history[-100:]] # Keep last 100 } @classmethod def from_dict(cls, data: Dict[str, Any]) -> 'PatternDatabase': db = cls() # Load command patterns for k, v in data.get("command_patterns", {}).items(): db.command_patterns[k] = Pattern.from_dict(v) # Load sequence patterns for p in data.get("sequence_patterns", []): db.sequence_patterns.append(Pattern.from_dict(p)) # Load context patterns for k, v in data.get("context_patterns", {}).items(): db.context_patterns[k] = Pattern.from_dict(v) # Load execution history for e in data.get("execution_history", []): db.execution_history.append(ToolExecution.from_dict(e)) return db