File size: 4,669 Bytes
e382248 b7e4cb3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | """Pattern library service - wraps ArchitectureMemory with consistent error handling."""
import logging
from typing import Any
from fastapi import HTTPException
from app.core.architecture_memory import get_architecture_memory, ArchitectureMemory
logger = logging.getLogger("specs-before-code-api.services.architecture_patterns")
class PatternService:
"""Facade over ArchitectureMemory (Redis-backed pattern library)."""
def __init__(self) -> None:
self._memory: ArchitectureMemory = get_architecture_memory()
@property
def is_configured(self) -> bool:
return self._memory.is_configured
async def list_patterns(
self,
tag: str | None = None,
search: str | None = None,
) -> dict[str, Any]:
if not self._memory.is_configured:
return {"patterns": [], "message": "Redis not configured"}
try:
if tag:
patterns = await self._memory.get_patterns_by_tag(tag)
elif search:
patterns = await self._memory.search_patterns(search)
else:
patterns = await self._memory.get_all_patterns()
return {
"patterns": [
{
"id": p.id,
"name": p.name,
"description": p.description,
"use_cases": p.use_cases,
"tags": p.tags,
"components": p.components,
"pros": p.pros,
"cons": p.cons,
"tech_stack": p.tech_stack,
"estimated_cost": p.estimated_cost,
"estimated_setup_time": p.estimated_setup_time,
}
for p in patterns
]
}
except Exception as e:
logger.error("Failed to list patterns: %s", e)
return {"error": str(e)}
async def get_pattern(self, pattern_id: str) -> dict[str, Any]:
if not self._memory.is_configured:
return {"error": "Redis not configured"}
try:
pattern = await self._memory.get_pattern(pattern_id)
if not pattern:
return {"error": "Pattern not found"}
return {
"id": pattern.id,
"name": pattern.name,
"description": pattern.description,
"use_cases": pattern.use_cases,
"tags": pattern.tags,
"components": pattern.components,
"pros": pattern.pros,
"cons": pattern.cons,
"tech_stack": pattern.tech_stack,
"estimated_cost": pattern.estimated_cost,
"estimated_setup_time": pattern.estimated_setup_time,
}
except Exception as e:
logger.error("Failed to get pattern %s: %s", pattern_id, e)
return {"error": str(e)}
async def seed_patterns(self) -> dict[str, Any]:
if not self._memory.is_configured:
return {"error": "Redis not configured"}
try:
seeded = await self._memory.seed_default_patterns()
return {"message": f"Seeded {seeded} default patterns", "seeded_count": seeded}
except Exception as e:
logger.error("Failed to seed patterns: %s", e)
return {"error": str(e)}
async def import_to_session(self, pattern_id: str) -> dict[str, Any] | None:
"""Fetch a pattern; returns the raw pattern dict or raises HTTPException."""
if not self._memory.is_configured:
raise HTTPException(status_code=503, detail="Pattern library not available")
pattern = await self._memory.get_pattern(pattern_id)
if not pattern:
raise HTTPException(status_code=404, detail="Pattern not found")
return {
"id": pattern.id,
"name": pattern.name,
"description": pattern.description,
"use_cases": pattern.use_cases,
"tags": pattern.tags,
"components": pattern.components,
"pros": pattern.pros,
"cons": pattern.cons,
"tech_stack": pattern.tech_stack,
"estimated_cost": pattern.estimated_cost,
"estimated_setup_time": pattern.estimated_setup_time,
}
async def get_pattern_raw(self, pattern_id: str) -> Any | None:
if not self._memory.is_configured:
raise HTTPException(status_code=503, detail="Pattern library not available")
return await self._memory.get_pattern(pattern_id)
|