chore: Add Annotation to Path, Query, and Body params

This commit is contained in:
Vineeth Voruganti 2025-04-07 18:36:45 -04:00
parent 8d2f3db6ba
commit 62f04a14d5
8 changed files with 174 additions and 206 deletions

View File

@ -1,7 +1,7 @@
import logging
from typing import Optional
from fastapi import APIRouter, Depends, Query
from fastapi import APIRouter, Body, Depends, Path, Query
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlalchemy import paginate
@ -48,39 +48,18 @@ async def get_app(
return await crud.get_app(db, app_id=target_app_id)
# @router.get(
# "",
# response_model=schemas.App,
# )
# async def get_app_from_token(jwt_params=jwt_params, db=db):
# """
# Get an App by ID from the app_id provided in the JWT.
# If no app_id is provided, return a 401 Unauthorized error.
# """
# if jwt_params.ap is None:
# raise AuthenticationException("App not found in JWT")
# return await crud.get_app(db, app_id=jwt_params.ap)
#
#
# @router.get(
# "/{app_id}",
# response_model=schemas.App,
# dependencies=[Depends(require_auth(app_id="app_id"))],
# )
# async def get_app(app_id: str, db=db):
# """Get an App by ID"""
# app = await crud.get_app(db, app_id=app_id)
# return app
@router.post(
"/list",
response_model=Page[schemas.App],
dependencies=[Depends(require_auth(admin=True))],
)
async def get_all_apps(
options: schemas.AppGet,
reverse: Optional[bool] = False,
options: schemas.AppGet = Body(
..., description="Filtering and pagination options for the apps list"
),
reverse: Optional[bool] = Query(
False, description="Whether to reverse the order of results"
),
db=db,
):
"""Get all Apps"""
@ -99,7 +78,10 @@ async def get_all_apps(
response_model=schemas.App,
dependencies=[Depends(require_auth(admin=True))],
)
async def get_app_by_name(name: str, db=db):
async def get_app_by_name(
name: str = Path(..., description="Name of the app to retrieve"),
db=db,
):
"""Get an App by Name"""
# ResourceNotFoundException will be caught by global handler if app not found
app = await crud.get_app_by_name(db, name=name)
@ -109,7 +91,10 @@ async def get_app_by_name(name: str, db=db):
@router.post(
"", response_model=schemas.App, dependencies=[Depends(require_auth(admin=True))]
)
async def create_app(app: schemas.AppCreate, db=db):
async def create_app(
app: schemas.AppCreate = Body(..., description="App creation parameters"),
db=db,
):
"""Create a new App"""
honcho_app = await crud.create_app(db, app=app)
return honcho_app
@ -120,7 +105,10 @@ async def create_app(app: schemas.AppCreate, db=db):
response_model=schemas.App,
dependencies=[Depends(require_auth(admin=True))],
)
async def get_or_create_app(name: str, db=db):
async def get_or_create_app(
name: str = Path(..., description="Name of the app to get or create"),
db=db,
):
"""Get or Create an App"""
try:
app = await crud.get_app_by_name(db=db, name=name)
@ -137,8 +125,8 @@ async def get_or_create_app(name: str, db=db):
dependencies=[Depends(require_auth(app_id="app_id"))],
)
async def update_app(
app_id: str,
app: schemas.AppUpdate,
app_id: str = Path(..., description="ID of the app to update"),
app: schemas.AppUpdate = Body(..., description="Updated app parameters"),
db=db,
):
"""Update an App"""

View File

@ -1,6 +1,6 @@
from typing import Optional
from fastapi import APIRouter, Depends, Query
from fastapi import APIRouter, Depends, Query, Path, Body
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlalchemy import paginate
@ -20,8 +20,8 @@ router = APIRouter(
response_model=schemas.Collection,
)
async def get_collection(
app_id: str,
user_id: str,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
collection_id: Optional[str] = Query(
None, description="Collection ID to retrieve. If not provided, uses JWT token"
),
@ -69,10 +69,10 @@ async def get_collection(
dependencies=[Depends(require_auth(app_id="app_id", user_id="user_id"))],
)
async def get_collections(
app_id: str,
user_id: str,
options: schemas.CollectionGet,
reverse: Optional[bool] = False,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
options: schemas.CollectionGet = Body(..., description="Filtering options for the collections list"),
reverse: Optional[bool] = Query(False, description="Whether to reverse the order of results"),
db=db,
):
"""Get All Collections for a User"""
@ -90,9 +90,9 @@ async def get_collections(
dependencies=[Depends(require_auth(app_id="app_id", user_id="user_id"))],
)
async def get_collection_by_name(
app_id: str,
user_id: str,
name: str,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
name: str = Path(..., description="Name of the collection to retrieve"),
db=db,
) -> schemas.Collection:
"""Get a Collection by Name"""
@ -108,9 +108,9 @@ async def get_collection_by_name(
dependencies=[Depends(require_auth(app_id="app_id", user_id="user_id"))],
)
async def create_collection(
app_id: str,
user_id: str,
collection: schemas.CollectionCreate,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
collection: schemas.CollectionCreate = Body(..., description="Collection creation parameters"),
db=db,
):
"""Create a new Collection"""
@ -133,10 +133,10 @@ async def create_collection(
],
)
async def update_collection(
app_id: str,
user_id: str,
collection_id: str,
collection: schemas.CollectionUpdate,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
collection_id: str = Path(..., description="ID of the collection to update"),
collection: schemas.CollectionUpdate = Body(..., description="Updated collection parameters"),
db=db,
):
"Update a Collection's name or metadata"
@ -163,9 +163,9 @@ async def update_collection(
],
)
async def delete_collection(
app_id: str,
user_id: str,
collection_id: str,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
collection_id: str = Path(..., description="ID of the collection to delete"),
db=db,
):
"""Delete a Collection and its documents"""

View File

@ -2,7 +2,7 @@ import logging
from collections.abc import Sequence
from typing import Optional
from fastapi import APIRouter, Depends
from fastapi import APIRouter, Depends, Query, Path, Body
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlalchemy import paginate
@ -28,11 +28,11 @@ router = APIRouter(
@router.post("/list", response_model=Page[schemas.Document])
async def get_documents(
app_id: str,
user_id: str,
collection_id: str,
options: schemas.DocumentGet,
reverse: Optional[bool] = False,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
collection_id: str = Path(..., description="ID of the collection"),
options: schemas.DocumentGet = Body(..., description="Filtering options for the documents list"),
reverse: Optional[bool] = Query(False, description="Whether to reverse the order of results"),
db=db,
):
"""Get all of the Documents in a Collection"""
@ -58,10 +58,10 @@ async def get_documents(
@router.get("/{document_id}", response_model=schemas.Document)
async def get_document(
app_id: str,
user_id: str,
collection_id: str,
document_id: str,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
collection_id: str = Path(..., description="ID of the collection"),
document_id: str = Path(..., description="ID of the document to retrieve"),
db=db,
):
"""Get a document by ID"""
@ -77,10 +77,10 @@ async def get_document(
@router.post("/query", response_model=Sequence[schemas.Document])
async def query_documents(
app_id: str,
user_id: str,
collection_id: str,
options: schemas.DocumentQuery,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
collection_id: str = Path(..., description="ID of the collection"),
options: schemas.DocumentQuery = Body(..., description="Query parameters for document search"),
db=db,
):
"""Cosine Similarity Search for Documents"""
@ -112,10 +112,10 @@ async def query_documents(
@router.post("", response_model=schemas.Document)
async def create_document(
app_id: str,
user_id: str,
collection_id: str,
document: schemas.DocumentCreate,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
collection_id: str = Path(..., description="ID of the collection"),
document: schemas.DocumentCreate = Body(..., description="Document creation parameters"),
db=db,
):
"""Embed text as a vector and create a Document"""
@ -143,11 +143,11 @@ async def create_document(
response_model=schemas.Document,
)
async def update_document(
app_id: str,
user_id: str,
collection_id: str,
document_id: str,
document: schemas.DocumentUpdate,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
collection_id: str = Path(..., description="ID of the collection"),
document_id: str = Path(..., description="ID of the document to update"),
document: schemas.DocumentUpdate = Body(..., description="Updated document parameters"),
db=db,
):
"""Update the content and/or the metadata of a Document"""
@ -175,10 +175,10 @@ async def update_document(
@router.delete("/{document_id}")
async def delete_document(
app_id: str,
user_id: str,
collection_id: str,
document_id: str,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
collection_id: str = Path(..., description="ID of the collection"),
document_id: str = Path(..., description="ID of the document to delete"),
db=db,
):
"""Delete a Document by ID"""

View File

@ -1,7 +1,7 @@
import logging
import os
from fastapi import APIRouter, Depends
from fastapi import APIRouter, Depends, Query
from src.exceptions import DisabledException, ValidationException
from src.security import (
@ -23,10 +23,10 @@ router = APIRouter(
@router.post("")
async def create_key(
app_id: str | None = None,
user_id: str | None = None,
session_id: str | None = None,
collection_id: str | None = None,
app_id: str | None = Query(None, description="ID of the app to scope the key to"),
user_id: str | None = Query(None, description="ID of the user to scope the key to"),
session_id: str | None = Query(None, description="ID of the session to scope the key to"),
collection_id: str | None = Query(None, description="ID of the collection to scope the key to"),
):
"""Create a new Key"""
if not USE_AUTH:

View File

@ -2,7 +2,7 @@ import logging
import os
from typing import List, Optional
from fastapi import APIRouter, BackgroundTasks, Depends
from fastapi import APIRouter, BackgroundTasks, Depends, Query, Path, Body
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlalchemy import paginate
from sqlalchemy.sql import insert
@ -151,11 +151,11 @@ async def enqueue(payload: dict | list[dict]):
@router.post("", response_model=schemas.Message)
async def create_message_for_session(
app_id: str,
user_id: str,
session_id: str,
message: schemas.MessageCreate,
background_tasks: BackgroundTasks,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
session_id: str = Path(..., description="ID of the session"),
message: schemas.MessageCreate = Body(..., description="Message creation parameters"),
db=db,
):
"""Adds a message to a session"""
@ -189,11 +189,11 @@ async def create_message_for_session(
@router.post("/batch", response_model=List[schemas.Message])
async def create_batch_messages_for_session(
app_id: str,
user_id: str,
session_id: str,
batch: schemas.MessageBatchCreate,
background_tasks: BackgroundTasks,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
session_id: str = Path(..., description="ID of the session"),
batch: schemas.MessageBatchCreate = Body(..., description="Batch of messages to create"),
db=db,
):
"""Bulk create messages for a session while maintaining order. Maximum 100 messages per batch."""
@ -236,11 +236,11 @@ async def create_batch_messages_for_session(
@router.post("/list", response_model=Page[schemas.Message])
async def get_messages(
app_id: str,
user_id: str,
session_id: str,
options: schemas.MessageGet,
reverse: Optional[bool] = False,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
session_id: str = Path(..., description="ID of the session"),
options: schemas.MessageGet = Body(..., description="Filtering options for the messages list"),
reverse: Optional[bool] = Query(False, description="Whether to reverse the order of results"),
db=db,
):
"""Get all messages for a session"""
@ -266,10 +266,10 @@ async def get_messages(
@router.get("/{message_id}", response_model=schemas.Message)
async def get_message(
app_id: str,
user_id: str,
session_id: str,
message_id: str,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
session_id: str = Path(..., description="ID of the session"),
message_id: str = Path(..., description="ID of the message to retrieve"),
db=db,
):
"""Get a Message by ID"""
@ -284,11 +284,11 @@ async def get_message(
@router.put("/{message_id}", response_model=schemas.Message)
async def update_message(
app_id: str,
user_id: str,
session_id: str,
message_id: str,
message: schemas.MessageUpdate,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
session_id: str = Path(..., description="ID of the session"),
message_id: str = Path(..., description="ID of the message to update"),
message: schemas.MessageUpdate = Body(..., description="Updated message parameters"),
db=db,
):
"""Update the metadata of a Message"""
@ -305,4 +305,4 @@ async def update_message(
return updated_message
except ValueError as e:
logger.warning(f"Failed to update message {message_id}: {str(e)}")
raise ResourceNotFoundException("Message or session not found") from e
raise ResourceNotFoundException("Message not found") from e

View File

@ -1,7 +1,7 @@
import logging
from typing import Optional
from fastapi import APIRouter, Depends
from fastapi import APIRouter, Depends, Query, Path, Body
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlalchemy import paginate
@ -24,9 +24,9 @@ router = APIRouter(
@router.post("", response_model=schemas.Metamessage)
async def create_metamessage(
app_id: str,
user_id: str,
metamessage: schemas.MetamessageCreate,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
metamessage: schemas.MetamessageCreate = Body(..., description="Metamessage creation parameters"),
db=db,
):
"""
@ -51,10 +51,10 @@ async def create_metamessage(
@router.post("/list", response_model=Page[schemas.Metamessage])
async def get_metamessages(
app_id: str,
user_id: str,
options: schemas.MetamessageGet,
reverse: Optional[bool] = False,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
options: schemas.MetamessageGet = Body(..., description="Filtering options for the metamessages list"),
reverse: Optional[bool] = Query(False, description="Whether to reverse the order of results"),
db=db,
):
"""
@ -89,9 +89,9 @@ async def get_metamessages(
response_model=schemas.Metamessage,
)
async def get_metamessage(
app_id: str,
user_id: str,
metamessage_id: str,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
metamessage_id: str = Path(..., description="ID of the metamessage to retrieve"),
db=db,
):
"""Get a specific Metamessage by ID"""
@ -114,10 +114,10 @@ async def get_metamessage(
response_model=schemas.Metamessage,
)
async def update_metamessage(
app_id: str,
user_id: str,
metamessage_id: str,
metamessage: schemas.MetamessageUpdate,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
metamessage_id: str = Path(..., description="ID of the metamessage to update"),
metamessage: schemas.MetamessageUpdate = Body(..., description="Updated metamessage parameters"),
db=db,
):
"""Update a metamessage's metadata, type, or relationships"""

View File

@ -2,7 +2,7 @@ import logging
from typing import Optional
from anthropic import MessageStreamManager
from fastapi import APIRouter, Depends, Query
from fastapi import APIRouter, Depends, Query, Path, Body
from fastapi.responses import StreamingResponse
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlalchemy import paginate
@ -29,8 +29,8 @@ router = APIRouter(
response_model=schemas.Session,
)
async def get_session(
app_id: str,
user_id: str,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
session_id: Optional[str] = Query(
None, description="Session ID to retrieve. If not provided, uses JWT token"
),
@ -78,10 +78,10 @@ async def get_session(
dependencies=[Depends(require_auth(app_id="app_id", user_id="user_id"))],
)
async def get_sessions(
app_id: str,
user_id: str,
options: schemas.SessionGet,
reverse: Optional[bool] = False,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
options: schemas.SessionGet = Body(..., description="Filtering and pagination options for the sessions list"),
reverse: Optional[bool] = Query(False, description="Whether to reverse the order of results"),
db=db,
):
"""Get All Sessions for a User"""
@ -104,9 +104,9 @@ async def get_sessions(
dependencies=[Depends(require_auth(app_id="app_id", user_id="user_id"))],
)
async def create_session(
app_id: str,
user_id: str,
session: schemas.SessionCreate,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
session: schemas.SessionCreate = Body(..., description="Session creation parameters"),
db=db,
):
"""Create a Session for a User"""
@ -131,10 +131,10 @@ async def create_session(
],
)
async def update_session(
app_id: str,
user_id: str,
session_id: str,
session: schemas.SessionUpdate,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
session_id: str = Path(..., description="ID of the session to update"),
session: schemas.SessionUpdate = Body(..., description="Updated session parameters"),
db=db,
):
"""Update the metadata of a Session"""
@ -158,9 +158,9 @@ async def update_session(
],
)
async def delete_session(
app_id: str,
user_id: str,
session_id: str,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
session_id: str = Path(..., description="ID of the session to delete"),
db=db,
):
"""Delete a session by marking it as inactive"""
@ -185,10 +185,10 @@ async def delete_session(
],
)
async def chat(
app_id: str,
user_id: str,
session_id: str,
query: schemas.AgentQuery,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
session_id: str = Path(..., description="ID of the session"),
query: schemas.AgentQuery = Body(..., description="Chat query parameters"),
):
"""Chat with the Dialectic API"""
return await agent.chat(
@ -213,10 +213,10 @@ async def chat(
],
)
async def get_chat_stream(
app_id: str,
user_id: str,
session_id: str,
query: schemas.AgentQuery,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
session_id: str = Path(..., description="ID of the session"),
query: schemas.AgentQuery = Body(..., description="Chat query parameters"),
):
"""Stream Results from the Dialectic API"""
@ -248,19 +248,25 @@ async def get_chat_stream(
],
)
async def clone_session(
app_id: str,
user_id: str,
session_id: str,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user"),
session_id: str = Path(..., description="ID of the session to clone"),
db=db,
message_id: Optional[str] = None,
deep_copy: bool = False,
message_id: Optional[str] = Query(None, description="Message ID to cut off the clone at"),
deep_copy: bool = Query(False, description="Whether to deep copy metamessages"),
):
"""Clone a session for a user, optionally will deep clone metamessages as well"""
return await crud.clone_session(
db,
app_id=app_id,
user_id=user_id,
original_session_id=session_id,
cutoff_message_id=message_id,
deep_copy=deep_copy,
)
"""Clone a session, optionally up to a specific message"""
try:
cloned_session = await crud.clone_session(
db,
app_id=app_id,
user_id=user_id,
original_session_id=session_id,
cutoff_message_id=message_id,
deep_copy=deep_copy,
)
logger.info(f"Session {session_id} cloned successfully")
return cloned_session
except ValueError as e:
logger.warning(f"Failed to clone session {session_id}: {str(e)}")
raise ResourceNotFoundException("Session not found") from e

View File

@ -1,7 +1,7 @@
import logging
from typing import Optional
from fastapi import APIRouter, Depends, Query
from fastapi import APIRouter, Depends, Query, Path, Body
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlalchemy import paginate
@ -27,8 +27,8 @@ router = APIRouter(
dependencies=[Depends(require_auth(app_id="app_id", user_id="user_id"))],
)
async def create_user(
app_id: str,
user: schemas.UserCreate,
app_id: str = Path(..., description="ID of the app"),
user: schemas.UserCreate = Body(..., description="User creation parameters"),
db=db,
):
"""Create a new User"""
@ -42,9 +42,9 @@ async def create_user(
dependencies=[Depends(require_auth(app_id="app_id", user_id="user_id"))],
)
async def get_users(
app_id: str,
options: schemas.UserGet,
reverse: bool = False,
app_id: str = Path(..., description="ID of the app"),
options: schemas.UserGet = Body(..., description="Filtering options for the users list"),
reverse: bool = Query(False, description="Whether to reverse the order of results"),
db=db,
):
"""Get All Users for an App"""
@ -59,7 +59,7 @@ async def get_users(
response_model=schemas.User,
)
async def get_user(
app_id: str,
app_id: str = Path(..., description="ID of the app"),
user_id: Optional[str] = Query(
None, description="User ID to retrieve. If not provided, users JWT token"
),
@ -89,36 +89,6 @@ async def get_user(
return user
# @router.get(
# "",
# response_model=schemas.User,
# )
# async def get_user_from_token(app_id: str, jwt_params=jwt_params, db=db):
# """
# Get a User by ID from the user_id provided in the JWT.
# If no user_id is provided, return a 401 Unauthorized error.
# """
# if jwt_params.us is None:
# raise AuthenticationException("User not found in JWT")
# return await crud.get_user(db, app_id=app_id, user_id=jwt_params.us)
#
#
# @router.get(
# "/{user_id}",
# response_model=schemas.User,
# dependencies=[Depends(require_auth(app_id="app_id", user_id="user_id"))],
# )
# async def get_user(
# app_id: str,
# user_id: str,
# db=db,
# ):
# """Get a User by ID"""
# user = await crud.get_user(db, app_id=app_id, user_id=user_id)
# return user
#
@router.get(
"/name/{name}",
response_model=schemas.User,
@ -131,8 +101,8 @@ async def get_user(
],
)
async def get_user_by_name(
app_id: str,
name: str,
app_id: str = Path(..., description="ID of the app"),
name: str = Path(..., description="Name of the user to retrieve"),
db=db,
):
"""Get a User by name"""
@ -151,7 +121,11 @@ async def get_user_by_name(
)
],
)
async def get_or_create_user(app_id: str, name: str, db=db):
async def get_or_create_user(
app_id: str = Path(..., description="ID of the app"),
name: str = Path(..., description="Name of the user to get or create"),
db=db,
):
"""Get a User or create a new one by the input name"""
try:
user = await crud.get_user_by_name(db, app_id=app_id, name=name)
@ -170,9 +144,9 @@ async def get_or_create_user(app_id: str, name: str, db=db):
dependencies=[Depends(require_auth(app_id="app_id", user_id="user_id"))],
)
async def update_user(
app_id: str,
user_id: str,
user: schemas.UserUpdate,
app_id: str = Path(..., description="ID of the app"),
user_id: str = Path(..., description="ID of the user to update"),
user: schemas.UserUpdate = Body(..., description="Updated user parameters"),
db=db,
):
"""Update a User's name and/or metadata"""