diff --git a/app/api/agent_documents.py b/app/api/agent_documents.py index edba64a5f..65f6c72f1 100644 --- a/app/api/agent_documents.py +++ b/app/api/agent_documents.py @@ -1,10 +1,13 @@ -from fastapi import APIRouter, Depends +import logging + +from fastapi import APIRouter, Depends, HTTPException, status from starlette.requests import Request from app.lib.auth.prisma import JWTBearer from app.lib.models.agent_document import AgentDocument from app.lib.prisma import prisma +logger = logging.getLogger(__name__) router = APIRouter() @@ -28,11 +31,22 @@ def parse_filter_params(request: Request): ) async def create_agent_document(body: AgentDocument, token=Depends(JWTBearer())): """Create api token endpoint""" - agent_document = prisma.agentdocument.create( - {"agentId": body.agentId, "documentId": body.documentId} - ) - - return {"success": True, "data": agent_document} + try: + agent_document = prisma.agentdocument.create( + {"agentId": body.agentId, "documentId": body.documentId} + ) + return {"success": True, "data": agent_document} + except Exception as e: + logger.error( + """ + Cannot create agent document for agent {body.agentId} + and document {body.documentId} + """, + exc_info=e, + ) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) @router.get( @@ -46,9 +60,16 @@ async def read_agent_documents( token=Depends(JWTBearer()), ): """List api tokens endpoint""" - agent_documents = prisma.agentdocument.find_many( - where=filters, include={"document": expand} - ) + + try: + agent_documents = prisma.agentdocument.find_many( + where=filters, include={"document": expand} + ) + except Exception as e: + logger.error("Cannot read agent documents", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) return {"success": True, "data": agent_documents} @@ -60,7 +81,13 @@ async def read_agent_documents( ) async def read_agent_document(agentDocumentId: str, token=Depends(JWTBearer())): """Get an agent document""" - agent_document = prisma.agentdocument.find_unique(where={"id": agentDocumentId}) + try: + agent_document = prisma.agentdocument.find_unique(where={"id": agentDocumentId}) + except Exception as e: + logger.error("Cannot read agent document {agentDocumentId}", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) return {"success": True, "data": agent_document} @@ -73,6 +100,12 @@ async def read_agent_document(agentDocumentId: str, token=Depends(JWTBearer())): async def delete_agent_document(agentDocumentId: str, token=Depends(JWTBearer())): """Delete agent document endpoint""" - prisma.agentdocument.delete(where={"id": agentDocumentId}) + try: + prisma.agentdocument.delete(where={"id": agentDocumentId}) + except Exception as e: + logger.error("Cannot delete agent document {agentDocumentId}", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) return {"success": True, "data": None} diff --git a/app/api/agent_tools.py b/app/api/agent_tools.py index d3496f2d5..8592a52d3 100644 --- a/app/api/agent_tools.py +++ b/app/api/agent_tools.py @@ -1,10 +1,14 @@ -from fastapi import APIRouter, Depends +import logging + +from fastapi import APIRouter, Depends, HTTPException, status from starlette.requests import Request from app.lib.auth.prisma import JWTBearer from app.lib.models.agent_tool import AgentTool from app.lib.prisma import prisma +logger = logging.getLogger(__name__) + router = APIRouter() @@ -28,9 +32,19 @@ def parse_filter_params(request: Request): ) async def create_agent_tool(body: AgentTool, token=Depends(JWTBearer())): """Create agent tool endpoint""" - agent_tool = prisma.agenttool.create( - {"agentId": body.agentId, "toolId": body.toolId} - ) + + try: + agent_tool = prisma.agenttool.create( + {"agentId": body.agentId, "toolId": body.toolId} + ) + except Exception as e: + logger.error( + "Cannot create agent tool for agent {body.agentId} and tool {body.toolId}", + exc_info=e, + ) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) return {"success": True, "data": agent_tool} @@ -46,7 +60,16 @@ async def read_agent_tools( token=Depends(JWTBearer()), ): """List agent tools endpoint""" - agent_tools = prisma.agenttool.find_many(where=filters, include={"tool": expand}) + + try: + agent_tools = prisma.agenttool.find_many( + where=filters, include={"tool": expand} + ) + except Exception as e: + logger.error("Cannot read agent tools", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) return {"success": True, "data": agent_tools} @@ -58,7 +81,14 @@ async def read_agent_tools( ) async def read_agent_tool(agentToolId: str, token=Depends(JWTBearer())): """Get an agent tool""" - agent_tool = prisma.agenttool.find_unique(where={"id": agentToolId}) + + try: + agent_tool = prisma.agenttool.find_unique(where={"id": agentToolId}) + except Exception as e: + logger.error("Cannot read agent tool {agentToolId}", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) return {"success": True, "data": agent_tool} @@ -71,6 +101,12 @@ async def read_agent_tool(agentToolId: str, token=Depends(JWTBearer())): async def delete_agent_tool(agentToolId: str, token=Depends(JWTBearer())): """Delete agent tool endpoint""" - prisma.agenttool.delete(where={"id": agentToolId}) + try: + prisma.agenttool.delete(where={"id": agentToolId}) + except Exception as e: + logger.error("Cannot delete agent tool {agentToolId}", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) return {"success": True, "data": None} diff --git a/app/api/agents.py b/app/api/agents.py index 2309b368c..a5f82273e 100644 --- a/app/api/agents.py +++ b/app/api/agents.py @@ -1,4 +1,5 @@ import json +import logging import threading from queue import Queue from typing import Any, Dict @@ -15,6 +16,7 @@ from app.lib.models.agent import Agent, PredictAgent from app.lib.prisma import prisma +logger = logging.getLogger(__name__) router = APIRouter() @@ -39,9 +41,9 @@ async def create_agent(body: Agent, token=Depends(JWTBearer())): return {"success": True, "data": agent} except Exception as e: + logger.error(e) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=e, ) @@ -49,16 +51,20 @@ async def create_agent(body: Agent, token=Depends(JWTBearer())): async def read_agents(token=Depends(JWTBearer())): """Agents endpoint""" decoded = decodeJWT(token) - agents = prisma.agent.find_many( - where={"userId": decoded["userId"]}, - include={ - "user": True, - }, - order={"createdAt": "desc"}, - ) - - if agents: - return {"success": True, "data": agents} + try: + agents = prisma.agent.find_many( + where={"userId": decoded["userId"]}, + include={ + "user": True, + }, + order={"createdAt": "desc"}, + ) + if agents or agents == []: + return {"success": True, "data": agents} + else: + raise Exception("Couldn't fetch agents from prisma") + except Exception as e: + logger.error(e) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, @@ -74,6 +80,7 @@ async def read_agent(agentId: str, token=Depends(JWTBearer())): if agent: return {"success": True, "data": agent} + logger.error(f"Agent with id: {agentId} not found") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Agent with id: {agentId} not found", @@ -91,9 +98,9 @@ async def delete_agent(agentId: str, token=Depends(JWTBearer())): return {"success": True, "data": None} except Exception as e: + logger.error(f"Couldn't delete agent with id {agentId}", exc_info=e) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=e, ) @@ -106,7 +113,13 @@ async def patch_agent(agentId: str, body: dict, token=Depends(JWTBearer())): if tags or tags == []: body["tags"] = json.dumps(tags) - prisma.agent.update(data=body, where={"id": agentId}) + try: + prisma.agent.update(data=body, where={"id": agentId}) + except Exception as e: + logger.error(f"Couldn't patch agent with id {agentId}", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) return {"success": True, "data": None} @@ -209,6 +222,7 @@ def conversation_run_thread(input: dict) -> None: return {"success": True, "data": output} + logger.error(f"Cannot run agent with id: {agentId} not found") raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Agent with id: {agentId} not found", diff --git a/app/api/api_tokens.py b/app/api/api_tokens.py index 0581faf5b..fc4fcf2c2 100644 --- a/app/api/api_tokens.py +++ b/app/api/api_tokens.py @@ -1,3 +1,5 @@ +import logging + from fastapi import APIRouter, Depends, HTTPException, status from app.lib.api_tokens import generate_api_token @@ -5,6 +7,8 @@ from app.lib.models.api_token import ApiToken from app.lib.prisma import prisma +logger = logging.getLogger(__name__) + router = APIRouter() @@ -29,23 +33,27 @@ async def create_api_token(body: ApiToken, token=Depends(JWTBearer())): return {"success": True, "data": agent} except Exception as e: + logger.error("Cannot create api token", exc_info=e) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=e, ) @router.get("/api-tokens", name="List API tokens", description="List all API tokens") async def read_api_tokens(token=Depends(JWTBearer())): """List api tokens endpoint""" - decoded = decodeJWT(token) - api_tokens = prisma.apitoken.find_many( - where={"userId": decoded["userId"]}, include={"user": True} - ) + try: + decoded = decodeJWT(token) + api_tokens = prisma.apitoken.find_many( + where={"userId": decoded["userId"]}, include={"user": True} + ) - if api_tokens: - return {"success": True, "data": api_tokens} + if api_tokens or api_tokens == []: + return {"success": True, "data": api_tokens} + except Exception as e: + logger.error("Error finding api tokens for user {userId}", exc_info=e) + logger.error("Couldn't find api tokens") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="No agents found", @@ -59,13 +67,17 @@ async def read_api_tokens(token=Depends(JWTBearer())): ) async def read_api_token(tokenId: str, token=Depends(JWTBearer())): """Get an api token endpoint""" - api_token = prisma.apitoken.find_unique( - where={"id": tokenId}, include={"user": True} - ) - if api_token: - return {"success": True, "data": api_token} + try: + api_token = prisma.apitoken.find_unique( + where={"id": tokenId}, include={"user": True} + ) + if api_token: + return {"success": True, "data": api_token} + except Exception as e: + logger.error("Cannot find api token {tokenId}", exc_info=e) + logger.error("Cannot find api token {tokenId}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"API token with id: {tokenId} not found", @@ -84,7 +96,7 @@ async def delete_api_token(tokenId: str, token=Depends(JWTBearer())): return {"success": True, "data": None} except Exception as e: + logger.error(f"Couldn't delete api token with id {tokenId}", exc_info=e) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=e, ) diff --git a/app/api/auth.py b/app/api/auth.py index 728573d48..4f8d2a948 100644 --- a/app/api/auth.py +++ b/app/api/auth.py @@ -1,4 +1,5 @@ import json +import logging from fastapi import APIRouter, HTTPException, status @@ -10,51 +11,66 @@ from app.lib.models.auth import SignIn, SignInOut, SignUp from app.lib.prisma import prisma +logger = logging.getLogger(__name__) + router = APIRouter() @router.post("/auth/sign-in") async def sign_in(signIn: SignIn): - user = prisma.user.find_first( - where={ - "email": signIn.email, - }, - include={"profile": True}, - ) - if user: - validated = validatePassword(signIn.password, user.password) - del user.password + try: + user = prisma.user.find_first( + where={ + "email": signIn.email, + }, + include={"profile": True}, + ) + if user: + validated = validatePassword(signIn.password, user.password) + del user.password - if validated: - token = signJWT(user.id) - return {"success": True, "data": SignInOut(token=token, user=user)} + if validated: + token = signJWT(user.id) + return {"success": True, "data": SignInOut(token=token, user=user)} - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Invalid credentials", - ) - else: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Invalid credentials", - ) + logger.warning("Invalid password") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Invalid credentials", + ) + else: + logger.warning("User not found") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Invalid credentials", + ) + except Exception as e: + logger.error("Couldn't find user by email", exc_info=e) + raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) @router.post("/auth/sign-up") async def sign_up(body: SignUp): - encryptPassword(body.password) - user = prisma.user.create( - { - "email": body.email, - "password": encryptPassword(body.password), - "name": body.name, - } - ) - prisma.profile.create({"userId": user.id, "metadata": json.dumps(body.metadata)}) + try: + encryptPassword(body.password) + user = prisma.user.create( + { + "email": body.email, + "password": encryptPassword(body.password), + "name": body.name, + } + ) + prisma.profile.create( + {"userId": user.id, "metadata": json.dumps(body.metadata)} + ) + except Exception as e: + logger.error("Couldn't create user", exc_info=e) + raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) if user: return {"success": True, "data": user} + logger.error("User not created") raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid credentials", diff --git a/app/api/documents.py b/app/api/documents.py index 608231d76..c7ae46997 100644 --- a/app/api/documents.py +++ b/app/api/documents.py @@ -1,4 +1,5 @@ import json +import logging from fastapi import APIRouter, Depends, HTTPException, status @@ -7,58 +8,71 @@ from app.lib.models.document import Document from app.lib.prisma import prisma +logger = logging.getLogger(__name__) + router = APIRouter() @router.post("/documents", name="Create document", description="Create a new document") async def create_document(body: Document, token=Depends(JWTBearer())): """Create document endpoint""" - decoded = decodeJWT(token) - document = prisma.document.create( - { - "type": body.type, - "url": body.url, - "userId": decoded["userId"], - "name": body.name, - "splitter": json.dumps(body.splitter), - "authorization": json.dumps(body.authorization), - "metadata": json.dumps(body.metadata), - } - ) - - if body.type in valid_ingestion_types: - upsert_document( - url=body.url, - type=body.type, - document_id=document.id, - authorization=body.authorization, - metadata=body.metadata, - text_splitter=body.splitter, - from_page=body.from_page, - to_page=body.to_page, - user_id=decoded["userId"], + try: + decoded = decodeJWT(token) + document = prisma.document.create( + { + "type": body.type, + "url": body.url, + "userId": decoded["userId"], + "name": body.name, + "splitter": json.dumps(body.splitter), + "authorization": json.dumps(body.authorization), + "metadata": json.dumps(body.metadata), + } ) - return {"success": True, "data": document} + if body.type in valid_ingestion_types: + upsert_document( + url=body.url, + type=body.type, + document_id=document.id, + authorization=body.authorization, + metadata=body.metadata, + text_splitter=body.splitter, + from_page=body.from_page, + to_page=body.to_page, + user_id=decoded["userId"], + ) + else: + logger.error("Invalid ingestion type") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Invalid ingestion type", + ) + return {"success": True, "data": document} + except Exception as e: + logger.error("Couldn't create document", exc_info=e) + raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) @router.get("/documents", name="List documents", description="List all documents") async def read_documents(token=Depends(JWTBearer())): """List documents endpoint""" - decoded = decodeJWT(token) - documents = prisma.document.find_many( - where={"userId": decoded["userId"]}, - include={"user": True}, - order={"createdAt": "desc"}, - ) - - if documents: - return {"success": True, "data": documents} + try: + decoded = decodeJWT(token) + documents = prisma.document.find_many( + where={"userId": decoded["userId"]}, + include={"user": True}, + order={"createdAt": "desc"}, + ) - raise HTTPException( - status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail="No agents found", - ) + if documents or documents == []: + return {"success": True, "data": documents} + except Exception as e: + logger.error("Couldn't find documents", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="No agents found", + ) @router.get( @@ -68,13 +82,19 @@ async def read_documents(token=Depends(JWTBearer())): ) async def read_document(documentId: str, token=Depends(JWTBearer())): """Get a single document""" - document = prisma.document.find_unique( - where={"id": documentId}, include={"user": True} - ) + try: + document = prisma.document.find_unique( + where={"id": documentId}, include={"user": True} + ) + except Exception as e: + logger.error("Couldn't find document with id {documentId}", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Agent with id: {documentId} not found", + ) if document: return {"success": True, "data": document} - raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Agent with id: {documentId} not found", @@ -90,12 +110,11 @@ async def delete_document(documentId: str, token=Depends(JWTBearer())): """Delete a document""" try: prisma.document.delete(where={"id": documentId}) - return {"success": True, "data": None} except Exception as e: + logger.error("Couldn't delete document with id {documentId}", exc_info=e) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=e, ) @@ -106,9 +125,15 @@ async def delete_document(documentId: str, token=Depends(JWTBearer())): ) async def patch_document(documentId: str, body: dict, token=Depends(JWTBearer())): """Patch document endpoint""" - document = prisma.document.update( - data=body, - where={"id": documentId}, - ) + try: + document = prisma.document.update( + data=body, + where={"id": documentId}, + ) + return {"success": True, "data": document} + except Exception as e: + logger.error(f"Couldn't patch document with id {documentId}", exc_info=e) - return {"success": True, "data": document} + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) diff --git a/app/api/prompts.py b/app/api/prompts.py index 83c6e722f..9181a5757 100644 --- a/app/api/prompts.py +++ b/app/api/prompts.py @@ -1,43 +1,55 @@ import json +import logging -from fastapi import APIRouter, Depends +from fastapi import APIRouter, Depends, HTTPException, status from app.lib.auth.prisma import JWTBearer, decodeJWT from app.lib.models.prompt import Prompt from app.lib.prisma import prisma +logger = logging.getLogger(__name__) + router = APIRouter() @router.post("/prompts", name="Create a prompt", description="Create a new prompt") async def create_prompt(body: Prompt, token=Depends(JWTBearer())): """Create prompt endpoint""" - decoded = decodeJWT(token) - - prompt = prisma.prompt.create( - { - "name": body.name, - "input_variables": json.dumps(body.input_variables), - "template": body.template, - "userId": decoded["userId"], - }, - include={"user": True}, + try: + decoded = decodeJWT(token) + prompt = prisma.prompt.create( + { + "name": body.name, + "input_variables": json.dumps(body.input_variables), + "template": body.template, + "userId": decoded["userId"], + }, + include={"user": True}, + ) + return {"success": True, "data": prompt} + except Exception as e: + logger.error(e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, ) - return {"success": True, "data": prompt} - @router.get("/prompts", name="List prompts", description="List all prompts") async def read_prompts(token=Depends(JWTBearer())): """List prompts endpoint""" - decoded = decodeJWT(token) - prompts = prisma.prompt.find_many( - where={"userId": decoded["userId"]}, - include={"user": True}, - order={"createdAt": "desc"}, - ) - - return {"success": True, "data": prompts} + try: + decoded = decodeJWT(token) + prompts = prisma.prompt.find_many( + where={"userId": decoded["userId"]}, + include={"user": True}, + order={"createdAt": "desc"}, + ) + return {"success": True, "data": prompts} + except Exception as e: + logger.error("Couldn't find prompts for user", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) @router.get( @@ -47,9 +59,16 @@ async def read_prompts(token=Depends(JWTBearer())): ) async def read_prompt(promptId: str, token=Depends(JWTBearer())): """Get prompt endpoint""" - prompt = prisma.prompt.find_unique(where={"id": promptId}, include={"user": True}) - - return {"success": True, "data": prompt} + try: + prompt = prisma.prompt.find_unique( + where={"id": promptId}, include={"user": True} + ) + return {"success": True, "data": prompt} + except Exception as e: + logger.error("Couldn't find prompt", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) @router.delete( @@ -59,9 +78,14 @@ async def read_prompt(promptId: str, token=Depends(JWTBearer())): ) async def delete_prompt(promptId: str, token=Depends(JWTBearer())): """Delete prompt endpoint""" - prisma.prompt.delete(where={"id": promptId}) - - return {"success": True, "data": None} + try: + prisma.prompt.delete(where={"id": promptId}) + return {"success": True, "data": None} + except Exception as e: + logger.error("Couldn't delete prompt with id {promptId}", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) @router.patch( @@ -69,13 +93,17 @@ async def delete_prompt(promptId: str, token=Depends(JWTBearer())): ) async def patch_prompt(promptId: str, body: dict, token=Depends(JWTBearer())): """Patch prompt endpoint""" - input_variables = body["input_variables"] - if input_variables or input_variables == []: - body["input_variables"] = json.dumps(input_variables) - - prompt = prisma.prompt.update( - data=body, - where={"id": promptId}, - ) - - return {"success": True, "data": prompt} + try: + input_variables = body["input_variables"] + if input_variables or input_variables == []: + body["input_variables"] = json.dumps(input_variables) + prompt = prisma.prompt.update( + data=body, + where={"id": promptId}, + ) + return {"success": True, "data": prompt} + except Exception as e: + logger.error("Couldn't patch prompt with id {promptId}", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) diff --git a/app/api/tags.py b/app/api/tags.py index d329a7e78..6916a5056 100644 --- a/app/api/tags.py +++ b/app/api/tags.py @@ -1,38 +1,51 @@ -from fastapi import APIRouter, Depends +import logging + +from fastapi import APIRouter, Depends, HTTPException, status from app.lib.auth.prisma import JWTBearer, decodeJWT from app.lib.models.tag import Tag from app.lib.prisma import prisma +logger = logging.getLogger(__name__) + router = APIRouter() @router.post("/tags", name="Create a tag", description="Create a new tag") async def create_tag(body: Tag, token=Depends(JWTBearer())): """Create tag endpoint""" - decoded = decodeJWT(token) - - tag = prisma.tag.create( - { - "name": body.name, - "color": body.color, - "userId": decoded["userId"], - }, - ) - - return {"success": True, "data": tag} + try: + decoded = decodeJWT(token) + tag = prisma.tag.create( + { + "name": body.name, + "color": body.color, + "userId": decoded["userId"], + }, + ) + return {"success": True, "data": tag} + except Exception as e: + logger.error("Couldn't create tag", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) @router.get("/tags", name="List tags", description="List all tags") async def read_tags(token=Depends(JWTBearer())): """List tags endpoint""" - decoded = decodeJWT(token) - tags = prisma.tag.find_many( - where={"userId": decoded["userId"]}, - order={"createdAt": "desc"}, - ) - - return {"success": True, "data": tags} + try: + decoded = decodeJWT(token) + tags = prisma.tag.find_many( + where={"userId": decoded["userId"]}, + order={"createdAt": "desc"}, + ) + return {"success": True, "data": tags} + except Exception as e: + logger.error("Couldn't find tags for user", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) @router.get( @@ -42,9 +55,14 @@ async def read_tags(token=Depends(JWTBearer())): ) async def read_tag(tagId: str, token=Depends(JWTBearer())): """Get tag endpoint""" - tag = prisma.tag.find_unique(where={"id": tagId}) - - return {"success": True, "data": tag} + try: + tag = prisma.tag.find_unique(where={"id": tagId}) + return {"success": True, "data": tag} + except Exception as e: + logger.error("Couldn't find tag", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) @router.delete( @@ -54,17 +72,27 @@ async def read_tag(tagId: str, token=Depends(JWTBearer())): ) async def delete_tag(tagId: str, token=Depends(JWTBearer())): """Delete tag endpoint""" - prisma.tag.delete(where={"id": tagId}) - - return {"success": True, "data": None} + try: + prisma.tag.delete(where={"id": tagId}) + return {"success": True, "data": None} + except Exception as e: + logger.error("Couldn't delete tag with id {tagId}", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) @router.patch("/tags/{tagId}", name="Patch tag", description="Patch a specific tag") async def patch_tag(tagId: str, body: dict, token=Depends(JWTBearer())): """Patch tag endpoint""" - tag = prisma.tag.update( - data=body, - where={"id": tagId}, - ) - - return {"success": True, "data": tag} + try: + tag = prisma.tag.update( + data=body, + where={"id": tagId}, + ) + return {"success": True, "data": tag} + except Exception as e: + logger.error(f"Couldn't patch tag with id {tagId}", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) diff --git a/app/api/tools.py b/app/api/tools.py index c1a74d34a..ebc650db9 100644 --- a/app/api/tools.py +++ b/app/api/tools.py @@ -1,44 +1,56 @@ import json +import logging -from fastapi import APIRouter, Depends +from fastapi import APIRouter, Depends, HTTPException, status from app.lib.auth.prisma import JWTBearer, decodeJWT from app.lib.models.tool import Tool from app.lib.prisma import prisma +logger = logging.getLogger(__name__) + router = APIRouter() @router.post("/tools", name="Create a tool", description="Create a new tool") async def create_tool(body: Tool, token=Depends(JWTBearer())): """Create tool endpoint""" - decoded = decodeJWT(token) - - tool = prisma.tool.create( - { - "name": body.name, - "type": body.type, - "metadata": json.dumps(body.metadata), - "userId": decoded["userId"], - "description": body.description, - }, - include={"user": True}, - ) - - return {"success": True, "data": tool} + try: + decoded = decodeJWT(token) + tool = prisma.tool.create( + { + "name": body.name, + "type": body.type, + "metadata": json.dumps(body.metadata), + "userId": decoded["userId"], + "description": body.description, + }, + include={"user": True}, + ) + return {"success": True, "data": tool} + except Exception as e: + logger.error("Couldn't create tool", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) @router.get("/tools", name="List tools", description="List all tools") async def read_tools(token=Depends(JWTBearer())): """List tools endpoint""" - decoded = decodeJWT(token) - tools = prisma.tool.find_many( - where={"userId": decoded["userId"]}, - include={"user": True}, - order={"createdAt": "desc"}, - ) - - return {"success": True, "data": tools} + try: + decoded = decodeJWT(token) + tools = prisma.tool.find_many( + where={"userId": decoded["userId"]}, + include={"user": True}, + order={"createdAt": "desc"}, + ) + return {"success": True, "data": tools} + except Exception as e: + logger.error("Couldn't find tools for user", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) @router.get( @@ -48,9 +60,14 @@ async def read_tools(token=Depends(JWTBearer())): ) async def read_tool(toolId: str, token=Depends(JWTBearer())): """Get tool endpoint""" - tool = prisma.tool.find_unique(where={"id": toolId}, include={"user": True}) - - return {"success": True, "data": tool} + try: + tool = prisma.tool.find_unique(where={"id": toolId}, include={"user": True}) + return {"success": True, "data": tool} + except Exception as e: + logger.error("Couldn't find tool {toolId}", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) @router.delete( @@ -60,18 +77,28 @@ async def read_tool(toolId: str, token=Depends(JWTBearer())): ) async def delete_tool(toolId: str, token=Depends(JWTBearer())): """Delete tool endpoint""" - prisma.tool.delete(where={"id": toolId}) - - return {"success": True, "data": None} + try: + prisma.tool.delete(where={"id": toolId}) + return {"success": True, "data": None} + except Exception as e: + logger.error("Couldn't delete tool {toolId}", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) @router.patch("/tools/{toolId}", name="Patch tool", description="Patch a specific tool") async def patch_tool(toolId: str, body: dict, token=Depends(JWTBearer())): """Patch tool endpoint""" - body["metadata"] = json.dumps(body["metadata"]) - tool = prisma.tool.update( - data=body, - where={"id": toolId}, - ) - - return {"success": True, "data": tool} + try: + body["metadata"] = json.dumps(body["metadata"]) + tool = prisma.tool.update( + data=body, + where={"id": toolId}, + ) + return {"success": True, "data": tool} + except Exception as e: + logger.error("Couldn't patch tool {toolId}", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) diff --git a/app/api/traces.py b/app/api/traces.py index 69c507892..7739af047 100644 --- a/app/api/traces.py +++ b/app/api/traces.py @@ -1,8 +1,12 @@ -from fastapi import APIRouter, Depends +import logging + +from fastapi import APIRouter, Depends, HTTPException, status from app.lib.auth.prisma import JWTBearer, decodeJWT from app.lib.prisma import prisma +logger = logging.getLogger(__name__) + router = APIRouter() @@ -13,13 +17,18 @@ ) async def list_agent_traces(token=Depends(JWTBearer())): """List agent traces endpoint""" - decoded = decodeJWT(token) - agent_traces = prisma.agenttrace.find_many( - where={"userId": decoded["userId"]}, - include={ - "agent": True, - }, - order={"createdAt": "desc"}, - ) - - return {"success": True, "data": agent_traces} + try: + decoded = decodeJWT(token) + agent_traces = prisma.agenttrace.find_many( + where={"userId": decoded["userId"]}, + include={ + "agent": True, + }, + order={"createdAt": "desc"}, + ) + return {"success": True, "data": agent_traces} + except Exception as e: + logger.error("Couldn't find agent traces for user", exc_info=e) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) diff --git a/app/api/users.py b/app/api/users.py index f18eedc83..2e582a686 100644 --- a/app/api/users.py +++ b/app/api/users.py @@ -1,20 +1,29 @@ +import logging + from fastapi import APIRouter, Depends, HTTPException, status from app.lib.auth.prisma import JWTBearer, decodeJWT from app.lib.prisma import prisma +logger = logging.getLogger(__name__) + router = APIRouter() @router.get("/users/me") async def read_user_me(token=Depends(JWTBearer())): - decoded = decodeJWT(token) - - if "userId" in decoded: - userId = decoded["userId"] - user = prisma.user.find_unique(where={"id": userId}, include={"profile": True}) - - return {"success": True, "data": user} + try: + decoded = decodeJWT(token) + if "userId" in decoded: + userId = decoded["userId"] + user = prisma.user.find_unique( + where={"id": userId}, include={"profile": True} + ) + return {"success": True, "data": user} + else: + logger.error("userId not in JWT") + except Exception as e: + logger.error("Couldn't find user", exc_info=e) raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, @@ -24,10 +33,14 @@ async def read_user_me(token=Depends(JWTBearer())): @router.get("/users/{userId}") async def read_user(userId: str): - user = prisma.user.find_unique(where={"id": userId}, include={"profile": True}) - - if user: - return {"success": True, "data": user} + try: + user = prisma.user.find_unique(where={"id": userId}, include={"profile": True}) + if user: + return {"success": True, "data": user} + else: + logger.error("Couldn't find user") + except Exception as e: + logger.error("Error finding user", exc_info=e) raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, diff --git a/app/main.py b/app/main.py index 6e802e6e5..261bb49d7 100644 --- a/app/main.py +++ b/app/main.py @@ -1,11 +1,36 @@ +import logging import time +import colorlog from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from app.lib.prisma import prisma from app.routers import router +# Create a color formatter +formatter = colorlog.ColoredFormatter( + "%(log_color)s%(levelname)s: %(message)s", + log_colors={ + "DEBUG": "cyan", + "INFO": "green", + "WARNING": "yellow", + "ERROR": "red", + "CRITICAL": "bold_red", + }, + secondary_log_colors={}, + style="%", +) # Create a console handler and set the formatter +console_handler = logging.StreamHandler() +console_handler.setFormatter(formatter) + +logging.basicConfig( + level=logging.INFO, + format="%(levelname)s: %(message)s", + handlers=[console_handler], + force=True, +) + app = FastAPI( title="Superagent", description="Bring your agents to production", diff --git a/poetry.lock b/poetry.lock index cc7a82377..b8dab0e53 100644 --- a/poetry.lock +++ b/poetry.lock @@ -549,6 +549,23 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "colorlog" +version = "6.7.0" +description = "Add colours to the output of Python's logging module." +optional = false +python-versions = ">=3.6" +files = [ + {file = "colorlog-6.7.0-py2.py3-none-any.whl", hash = "sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662"}, + {file = "colorlog-6.7.0.tar.gz", hash = "sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} + +[package.extras] +development = ["black", "flake8", "mypy", "pytest", "types-colorama"] + [[package]] name = "commonmark" version = "0.9.1" @@ -4014,4 +4031,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "702d2d1f0f3891f37f9512fb3209712913dc71cd5ca604c7058f50b87089722b" \ No newline at end of file +content-hash = "febc91827556c43f45a6f1fcb84aea4968eef33a8c9d9b1b3b015e30cf1b1259" diff --git a/pyproject.toml b/pyproject.toml index 5dcc5535b..b5b55d918 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,6 +44,7 @@ llama-index = "^0.6.38.post1" psychicapi = "^0.8.0" tabulate = "^0.9.0" superagent-py = "^0.0.29" +colorlog = "^6.7.0" [build-system] diff --git a/setup.sh b/setup.sh old mode 100644 new mode 100755