✨ Features: - 🧠 Shadow learner that builds intelligence from command patterns - 🛡️ Smart command validation with safety checks - 💾 Automatic context monitoring and backup system - 🔄 Session continuity across Claude restarts 📚 Documentation: - Complete Diátaxis-organized documentation - Learning-oriented tutorial for getting started - Task-oriented how-to guides for specific problems - Information-oriented reference for quick lookup - Understanding-oriented explanations of architecture 🚀 Installation: - One-command installation script - Bootstrap prompt for installation via Claude - Cross-platform compatibility - Comprehensive testing suite 🎯 Ready for real-world use and community feedback! 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
198 lines
6.1 KiB
Python
198 lines
6.1 KiB
Python
#!/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 |