Skip to content

Commit

Permalink
fix(typespec,agents-api): Update metadata_filter to have object type
Browse files Browse the repository at this point in the history
Signed-off-by: Diwank Singh Tomer <[email protected]>
  • Loading branch information
creatorrr committed Oct 4, 2024
1 parent cb9a1d5 commit 9decd1f
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 44 deletions.
55 changes: 55 additions & 0 deletions agents-api/agents_api/dependencies/query_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from typing import Any, Callable

from fastapi import Request
from pydantic import BaseModel


class FilterModel(BaseModel):
class Config:
extra = "allow" # Allow arbitrary fields


def convert_value(value: str) -> Any:
"""
Attempts to convert a string value to an int or float. Returns the original string if conversion fails.
"""
for convert in (int, float):
try:
return convert(value)
except ValueError:
continue
return value

def create_filter_extractor(prefix: str = "filter") -> Callable[[Request], FilterModel]:
"""
Creates a dependency function to extract filter parameters with a given prefix.
Args:
prefix (str): The prefix to identify filter parameters.
Returns:
Callable[[Request], FilterModel]: The dependency function.
"""

def extract_filters(request: Request) -> FilterModel:
"""
Extracts query parameters that start with the specified prefix and returns them as a dictionary.
Args:
request (Request): The incoming HTTP request.
Returns:
FilterModel: A FilterModel instance containing the filter parameters.
"""
nonlocal prefix
prefix += "."

filters: dict[str, Any] = {}
for key, value in request.query_params.items():
if key.startswith(prefix):
filter_key = key[len(prefix):]
filters[filter_key] = convert_value(value)

return FilterModel(**filters)

return extract_filters
22 changes: 10 additions & 12 deletions agents-api/agents_api/routers/agents/list_agents.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,38 @@
import json
from json import JSONDecodeError
from typing import Annotated, Literal
from uuid import UUID

from fastapi import Depends, HTTPException, status
from fastapi import Depends

from ...autogen.openapi_model import Agent, ListResponse
from ...dependencies.developer_id import get_developer_id
from ...dependencies.query_filter import FilterModel, create_filter_extractor
from ...models.agent.list_agents import list_agents as list_agents_query
from .router import router


@router.get("/agents", tags=["agents"])
async def list_agents(
x_developer_id: Annotated[UUID, Depends(get_developer_id)],
# Expects the dot notation of object in query params
# Example:
# > ?metadata_filter.name=John&metadata_filter.age=30
metadata_filter: Annotated[
FilterModel | None,
Depends(create_filter_extractor("metadata_filter"))
],
limit: int = 100,
offset: int = 0,
sort_by: Literal["created_at", "updated_at"] = "created_at",
direction: Literal["asc", "desc"] = "desc",
metadata_filter: str = "{}",
) -> ListResponse[Agent]:
try:
metadata_filter = json.loads(metadata_filter)
except JSONDecodeError:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="metadata_filter is not a valid JSON",
)

agents = list_agents_query(
developer_id=x_developer_id,
limit=limit,
offset=offset,
sort_by=sort_by,
direction=direction,
metadata_filter=metadata_filter,
metadata_filter=metadata_filter.model_dump(mode="json"),
)

return ListResponse[Agent](items=agents)
25 changes: 5 additions & 20 deletions agents-api/agents_api/routers/docs/list_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from ...autogen.openapi_model import Doc, ListResponse
from ...dependencies.developer_id import get_developer_id
from ...dependencies.query_filter import FilterModel, create_filter_extractor
from ...models.docs.list_docs import list_docs as list_docs_query
from .router import router

Expand All @@ -15,20 +16,12 @@
async def list_user_docs(
x_developer_id: Annotated[UUID, Depends(get_developer_id)],
user_id: UUID,
metadata_filter: Annotated[FilterModel | None, Depends(create_filter_extractor("metadata_filter"))],
limit: int = 100,
offset: int = 0,
sort_by: Literal["created_at", "updated_at"] = "created_at",
direction: Literal["asc", "desc"] = "desc",
metadata_filter: str = "{}",
) -> ListResponse[Doc]:
try:
metadata_filter = json.loads(metadata_filter)
except JSONDecodeError:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="metadata_filter is not a valid JSON",
)

docs = list_docs_query(
developer_id=x_developer_id,
owner_type="user",
Expand All @@ -37,7 +30,7 @@ async def list_user_docs(
offset=offset,
sort_by=sort_by,
direction=direction,
metadata_filter=metadata_filter,
metadata_filter=metadata_filter.model_dump(mode="json"),
)

return ListResponse[Doc](items=docs)
Expand All @@ -47,20 +40,12 @@ async def list_user_docs(
async def list_agent_docs(
x_developer_id: Annotated[UUID, Depends(get_developer_id)],
agent_id: UUID,
metadata_filter: Annotated[FilterModel | None, Depends(create_filter_extractor("metadata_filter"))],
limit: int = 100,
offset: int = 0,
sort_by: Literal["created_at", "updated_at"] = "created_at",
direction: Literal["asc", "desc"] = "desc",
metadata_filter: str = "{}",
) -> ListResponse[Doc]:
try:
metadata_filter = json.loads(metadata_filter)
except JSONDecodeError:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="metadata_filter is not a valid JSON",
)

docs = list_docs_query(
developer_id=x_developer_id,
owner_type="agent",
Expand All @@ -69,7 +54,7 @@ async def list_agent_docs(
offset=offset,
sort_by=sort_by,
direction=direction,
metadata_filter=metadata_filter,
metadata_filter=metadata_filter.model_dump(mode="json"),
)

return ListResponse[Doc](items=docs)
13 changes: 3 additions & 10 deletions agents-api/agents_api/routers/sessions/list_sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,27 @@

from ...autogen.openapi_model import ListResponse, Session
from ...dependencies.developer_id import get_developer_id
from ...dependencies.query_filter import FilterModel, create_filter_extractor
from ...models.session.list_sessions import list_sessions as list_sessions_query
from .router import router


@router.get("/sessions", tags=["sessions"])
async def list_sessions(
x_developer_id: Annotated[UUID, Depends(get_developer_id)],
metadata_filter: Annotated[FilterModel | None, Depends(create_filter_extractor("metadata_filter"))],
limit: int = 100,
offset: int = 0,
sort_by: Literal["created_at", "updated_at"] = "created_at",
direction: Literal["asc", "desc"] = "desc",
metadata_filter: str = "{}",
) -> ListResponse[Session]:
try:
metadata_filter = json.loads(metadata_filter)
except JSONDecodeError:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="metadata_filter is not a valid JSON",
)

sessions = list_sessions_query(
developer_id=x_developer_id,
limit=limit,
offset=offset,
sort_by=sort_by,
direction=direction,
metadata_filter=metadata_filter,
metadata_filter=metadata_filter.model_dump(mode="json"),
)

return ListResponse[Session](items=sessions)
2 changes: 2 additions & 0 deletions typespec/common/scalars.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ namespace Common;
@format("uuid")
scalar uuid extends string;

alias concreteType = numeric | string | boolean | null;

/**
* For Unicode character safety
* See: https://unicode.org/reports/tr31/
Expand Down
5 changes: 3 additions & 2 deletions typespec/common/types.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Common;
//

alias Metadata = Record<unknown>;
alias MetadataFilter = Record<concreteType>;

model ResourceCreatedResponse {
@doc("ID of created resource")
Expand Down Expand Up @@ -48,6 +49,6 @@ model PaginationOptions {
/** Sort direction */
@query direction: sortDirection = "asc",

/** JSON string of object that should be used to filter objects by metadata */
@query metadata_filter: string = "{}",
/** Object to filter results by metadata */
@query metadata_filter: MetadataFilter,
}

0 comments on commit 9decd1f

Please sign in to comment.