File size: 2,384 Bytes
37ffa75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import logging
import traceback
import sys
from enum import Enum

# ── Logging setup ─────────────────────────────────────────────────────────────

LOG_FORMAT = "[%(asctime)s] %(levelname)-8s %(name)s β€” %(message)s"
DATE_FORMAT = "%H:%M:%S"

logging.basicConfig(
    level=logging.DEBUG,
    format=LOG_FORMAT,
    datefmt=DATE_FORMAT,
    handlers=[
        logging.StreamHandler(sys.stdout),
        logging.FileHandler("generai.log", encoding="utf-8"),
    ],
)


def get_logger(name: str) -> logging.Logger:
    return logging.getLogger(name)


# ── Error categories ───────────────────────────────────────────────────────────

class ErrorCode(Enum):
    # DB / Knowledge Base
    KB_INIT_FAILED      = "KB-001"
    KB_SEARCH_FAILED    = "KB-002"
    KB_WRITE_FAILED     = "KB-003"
    KB_REINFORCE_FAILED = "KB-004"
    KB_SEED_FAILED      = "KB-005"
    # Scraper / Web
    WEB_SEARCH_FAILED   = "WEB-001"
    WEB_FETCH_FAILED    = "WEB-002"
    WEB_EXTRACT_FAILED  = "WEB-003"
    WEB_NO_RESULTS      = "WEB-004"
    # Brain
    BRAIN_ASK_FAILED    = "BRN-001"
    BRAIN_ASYNC_FAILED  = "BRN-002"
    # UI
    UI_INPUT_EMPTY      = "UI-001"
    UI_HANDLER_FAILED   = "UI-002"


class GenerAIError(Exception):
    """Base exception with error code and user-friendly message."""

    def __init__(self, code: ErrorCode, detail: str, cause: Exception | None = None):
        self.code = code
        self.detail = detail
        self.cause = cause
        super().__init__(f"[{code.value}] {detail}")

    def user_message(self) -> str:
        cause_str = f"\n> Causa: `{type(self.cause).__name__}: {self.cause}`" if self.cause else ""
        return f"⚠️ **Errore {self.code.value}** β€” {self.detail}{cause_str}"

    def log(self, logger: logging.Logger):
        logger.error("[%s] %s", self.code.value, self.detail)
        if self.cause:
            logger.debug("Traceback originale:\n%s", "".join(traceback.format_exception(type(self.cause), self.cause, self.cause.__traceback__)))


def fmt_exc(e: Exception) -> str:
    """One-line summary of an exception for log messages."""
    return f"{type(e).__name__}: {e}"