Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm
Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)
Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability
Migration completed: $(date)
🤖 Clean migration with full functionality preserved
69 lines
2.2 KiB
Python
69 lines
2.2 KiB
Python
import os
|
|
import logging
|
|
from logging.handlers import RotatingFileHandler
|
|
from fastapi import APIRouter, HTTPException
|
|
from pydantic import BaseModel
|
|
from typing import List, Any, Optional
|
|
|
|
# --- Configuration ---
|
|
# Use project-local logs directory to avoid permission issues
|
|
_current_file = os.path.dirname(os.path.abspath(__file__))
|
|
_project_root = os.path.dirname(os.path.dirname(_current_file))
|
|
LOG_DIR = os.path.join(_project_root, ".dss", "logs", "browser-logs")
|
|
LOG_FILE = os.path.join(LOG_DIR, "browser.log")
|
|
|
|
# Ensure log directory exists
|
|
os.makedirs(LOG_DIR, exist_ok=True)
|
|
|
|
# --- Logging Setup ---
|
|
# We use a specific logger for browser logs to separate them from app logs
|
|
browser_logger = logging.getLogger("browser_logger")
|
|
browser_logger.setLevel(logging.INFO)
|
|
|
|
# Rotating file handler: 10MB max size, keep last 5 backups
|
|
handler = RotatingFileHandler(LOG_FILE, maxBytes=10*1024*1024, backupCount=5)
|
|
formatter = logging.Formatter(
|
|
'%(asctime)s [%(levelname)s] [BROWSER] %(message)s'
|
|
)
|
|
handler.setFormatter(formatter)
|
|
browser_logger.addHandler(handler)
|
|
|
|
# --- API Router ---
|
|
router = APIRouter()
|
|
|
|
class LogEntry(BaseModel):
|
|
level: str
|
|
timestamp: str
|
|
message: str
|
|
data: Optional[List[Any]] = None
|
|
|
|
class LogBatch(BaseModel):
|
|
logs: List[LogEntry]
|
|
|
|
@router.post("/api/logs/browser")
|
|
async def receive_browser_logs(batch: LogBatch):
|
|
"""
|
|
Receives a batch of logs from the browser and writes them to the log file.
|
|
"""
|
|
try:
|
|
for log in batch.logs:
|
|
# Map browser levels to python logging levels
|
|
level = log.level.lower()
|
|
|
|
log_message = f"[{log.timestamp}] {log.message}"
|
|
|
|
if level == 'error':
|
|
browser_logger.error(log_message)
|
|
elif level == 'warn':
|
|
browser_logger.warning(log_message)
|
|
elif level == 'debug':
|
|
browser_logger.debug(log_message)
|
|
else:
|
|
browser_logger.info(log_message)
|
|
|
|
return {"status": "ok", "count": len(batch.logs)}
|
|
except Exception as e:
|
|
# Fallback to standard logger if something breaks deeply
|
|
logging.error(f"Failed to process browser logs: {str(e)}")
|
|
raise HTTPException(status_code=500, detail="Internal processing error")
|