Spaces:
Configuration error
Configuration error
| """backend/api/conversations.py — Conversations + Messages CRUD (S354).""" | |
| import json, logging | |
| from .state import safe_json_dumps | |
| from typing import Optional, Any | |
| from fastapi import APIRouter, Body, HTTPException | |
| from pydantic import BaseModel | |
| from .state import sb | |
| router = APIRouter() | |
| _logger = logging.getLogger("conversations") | |
| class ConversationIn(BaseModel): | |
| id: str | |
| title: str = 'Nuova conversazione' | |
| created_at: int | |
| updated_at: int | |
| class MessageIn(BaseModel): | |
| id: str | |
| conversation_id: str | |
| role: str | |
| content: str | |
| created_at: int | |
| error: Optional[bool] = False | |
| steps: Optional[Any] = None | |
| agent_status: Optional[str] = None | |
| # ── Conversations ────────────────────────────────────────────────────────────── | |
| async def list_conversations(): | |
| try: | |
| data = sb().table('conversations').select('*').order('updated_at', desc=True).execute() | |
| return {'conversations': data.data} | |
| except Exception as exc: | |
| _logger.warning("list_conversations: %s", exc) | |
| # S750-GAP-I: Supabase non configurato o irraggiungibile → lista vuota invece di 500 | |
| return {'conversations': [], '_error': str(exc)[:120]} | |
| async def upsert_conversation(conv: ConversationIn): | |
| try: | |
| data = sb().table('conversations').upsert(conv.model_dump()).execute() | |
| return {'conversation': data.data[0] if data.data else conv.model_dump()} | |
| except Exception as exc: | |
| _logger.warning("upsert_conversation %s: %s", conv.id, exc) | |
| return {'conversation': conv.model_dump(), '_error': str(exc)[:120]} | |
| async def update_conversation(conv_id: str, body: dict = Body(...)): | |
| body['id'] = conv_id | |
| try: | |
| data = sb().table('conversations').upsert(body).execute() | |
| return {'conversation': data.data[0] if data.data else body} | |
| except Exception as exc: | |
| _logger.warning("update_conversation %s: %s", conv_id, exc) | |
| return {'conversation': body, '_error': str(exc)[:120]} | |
| async def delete_conversation(conv_id: str): | |
| try: | |
| sb().table('messages').delete().eq('conversation_id', conv_id).execute() | |
| sb().table('conversations').delete().eq('id', conv_id).execute() | |
| except Exception as exc: | |
| _logger.warning("delete_conversation %s: %s", conv_id, exc) | |
| return {'deleted': conv_id} | |
| # ── Messages ─────────────────────────────────────────────────────────────────── | |
| async def list_messages(conv_id: str): | |
| try: | |
| data = sb().table('messages').select('*').eq('conversation_id', conv_id).order('created_at').execute() | |
| return {'messages': data.data} | |
| except Exception as exc: | |
| _logger.warning("list_messages %s: %s", conv_id, exc) | |
| return {'messages': [], '_error': str(exc)[:120]} | |
| async def upsert_messages(conv_id: str, body: dict = Body(...)): | |
| msgs = body.get('messages', []) | |
| if not msgs: | |
| return {'upserted': 0} | |
| for m in msgs: | |
| m['conversation_id'] = conv_id | |
| if 'steps' in m and m['steps'] is not None: | |
| m['steps'] = safe_json_dumps(m['steps']) if not isinstance(m['steps'], str) else m['steps'] | |
| try: | |
| data = sb().table('messages').upsert(msgs).execute() | |
| return {'upserted': len(data.data)} | |
| except Exception as exc: | |
| _logger.warning("upsert_messages %s: %s", conv_id, exc) | |
| return {'upserted': 0, '_error': str(exc)[:120]} | |
| async def clear_messages(conv_id: str): | |
| try: | |
| sb().table('messages').delete().eq('conversation_id', conv_id).execute() | |
| except Exception as exc: | |
| _logger.warning("clear_messages %s: %s", conv_id, exc) | |
| return {'cleared': conv_id} | |