From 9decd1fec0278c437e4f5b948a7c21459404476a Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Fri, 4 Oct 2024 17:26:32 -0400 Subject: [PATCH 1/8] fix(typespec,agents-api): Update metadata_filter to have object type Signed-off-by: Diwank Singh Tomer --- .../agents_api/dependencies/query_filter.py | 55 +++++++++++++++++++ .../agents_api/routers/agents/list_agents.py | 22 ++++---- .../agents_api/routers/docs/list_docs.py | 25 ++------- .../routers/sessions/list_sessions.py | 13 +---- typespec/common/scalars.tsp | 2 + typespec/common/types.tsp | 5 +- 6 files changed, 78 insertions(+), 44 deletions(-) create mode 100644 agents-api/agents_api/dependencies/query_filter.py diff --git a/agents-api/agents_api/dependencies/query_filter.py b/agents-api/agents_api/dependencies/query_filter.py new file mode 100644 index 000000000..2481ff474 --- /dev/null +++ b/agents-api/agents_api/dependencies/query_filter.py @@ -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 diff --git a/agents-api/agents_api/routers/agents/list_agents.py b/agents-api/agents_api/routers/agents/list_agents.py index 21cd736b5..d12e2b4e8 100644 --- a/agents-api/agents_api/routers/agents/list_agents.py +++ b/agents-api/agents_api/routers/agents/list_agents.py @@ -1,12 +1,11 @@ -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 @@ -14,19 +13,18 @@ @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, @@ -34,7 +32,7 @@ async def list_agents( 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) diff --git a/agents-api/agents_api/routers/docs/list_docs.py b/agents-api/agents_api/routers/docs/list_docs.py index 2ba99a932..a359be892 100644 --- a/agents-api/agents_api/routers/docs/list_docs.py +++ b/agents-api/agents_api/routers/docs/list_docs.py @@ -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 @@ -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", @@ -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) @@ -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", @@ -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) diff --git a/agents-api/agents_api/routers/sessions/list_sessions.py b/agents-api/agents_api/routers/sessions/list_sessions.py index 21d7b643b..0494245fd 100644 --- a/agents-api/agents_api/routers/sessions/list_sessions.py +++ b/agents-api/agents_api/routers/sessions/list_sessions.py @@ -7,6 +7,7 @@ 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 @@ -14,27 +15,19 @@ @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) diff --git a/typespec/common/scalars.tsp b/typespec/common/scalars.tsp index 8dc07cbbc..dc206fa02 100644 --- a/typespec/common/scalars.tsp +++ b/typespec/common/scalars.tsp @@ -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/ diff --git a/typespec/common/types.tsp b/typespec/common/types.tsp index 7d954a80e..dd331e98c 100644 --- a/typespec/common/types.tsp +++ b/typespec/common/types.tsp @@ -11,6 +11,7 @@ namespace Common; // alias Metadata = Record; +alias MetadataFilter = Record; model ResourceCreatedResponse { @doc("ID of created resource") @@ -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, } \ No newline at end of file From c3afa8f0959250e40c167528f46037e5289a78fd Mon Sep 17 00:00:00 2001 From: creatorrr Date: Fri, 4 Oct 2024 21:28:06 +0000 Subject: [PATCH 2/8] refactor: Lint agents-api (CI) --- agents-api/agents_api/dependencies/query_filter.py | 3 ++- agents-api/agents_api/routers/agents/list_agents.py | 4 +--- agents-api/agents_api/routers/docs/list_docs.py | 8 ++++++-- agents-api/agents_api/routers/sessions/list_sessions.py | 4 +++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/agents-api/agents_api/dependencies/query_filter.py b/agents-api/agents_api/dependencies/query_filter.py index 2481ff474..766a5b7c3 100644 --- a/agents-api/agents_api/dependencies/query_filter.py +++ b/agents-api/agents_api/dependencies/query_filter.py @@ -20,6 +20,7 @@ def convert_value(value: str) -> Any: 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. @@ -47,7 +48,7 @@ def extract_filters(request: Request) -> FilterModel: filters: dict[str, Any] = {} for key, value in request.query_params.items(): if key.startswith(prefix): - filter_key = key[len(prefix):] + filter_key = key[len(prefix) :] filters[filter_key] = convert_value(value) return FilterModel(**filters) diff --git a/agents-api/agents_api/routers/agents/list_agents.py b/agents-api/agents_api/routers/agents/list_agents.py index d12e2b4e8..aa6986d0d 100644 --- a/agents-api/agents_api/routers/agents/list_agents.py +++ b/agents-api/agents_api/routers/agents/list_agents.py @@ -17,15 +17,13 @@ async def list_agents( # Example: # > ?metadata_filter.name=John&metadata_filter.age=30 metadata_filter: Annotated[ - FilterModel | None, - Depends(create_filter_extractor("metadata_filter")) + 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", ) -> ListResponse[Agent]: - agents = list_agents_query( developer_id=x_developer_id, limit=limit, diff --git a/agents-api/agents_api/routers/docs/list_docs.py b/agents-api/agents_api/routers/docs/list_docs.py index a359be892..0cd823919 100644 --- a/agents-api/agents_api/routers/docs/list_docs.py +++ b/agents-api/agents_api/routers/docs/list_docs.py @@ -16,7 +16,9 @@ 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"))], + 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", @@ -40,7 +42,9 @@ 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"))], + 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", diff --git a/agents-api/agents_api/routers/sessions/list_sessions.py b/agents-api/agents_api/routers/sessions/list_sessions.py index 0494245fd..ae011fb18 100644 --- a/agents-api/agents_api/routers/sessions/list_sessions.py +++ b/agents-api/agents_api/routers/sessions/list_sessions.py @@ -15,7 +15,9 @@ @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"))], + 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", From 28f66b73dd1854143b0aa5716f4af3f31efbcefa Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Fri, 4 Oct 2024 18:35:48 -0400 Subject: [PATCH 3/8] fix: Minor fixes for typecheck Signed-off-by: Diwank Singh Tomer --- agents-api/agents_api/routers/agents/list_agents.py | 4 +++- agents-api/agents_api/routers/docs/list_docs.py | 8 ++++++-- agents-api/agents_api/routers/sessions/list_sessions.py | 4 +++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/agents-api/agents_api/routers/agents/list_agents.py b/agents-api/agents_api/routers/agents/list_agents.py index aa6986d0d..a24f0667c 100644 --- a/agents-api/agents_api/routers/agents/list_agents.py +++ b/agents-api/agents_api/routers/agents/list_agents.py @@ -30,7 +30,9 @@ async def list_agents( offset=offset, sort_by=sort_by, direction=direction, - metadata_filter=metadata_filter.model_dump(mode="json"), + metadata_filter=metadata_filter.model_dump(mode="json") + if metadata_filter + else {}, ) return ListResponse[Agent](items=agents) diff --git a/agents-api/agents_api/routers/docs/list_docs.py b/agents-api/agents_api/routers/docs/list_docs.py index 0cd823919..f342f4b4b 100644 --- a/agents-api/agents_api/routers/docs/list_docs.py +++ b/agents-api/agents_api/routers/docs/list_docs.py @@ -32,7 +32,9 @@ async def list_user_docs( offset=offset, sort_by=sort_by, direction=direction, - metadata_filter=metadata_filter.model_dump(mode="json"), + metadata_filter=metadata_filter.model_dump(mode="json") + if metadata_filter + else {}, ) return ListResponse[Doc](items=docs) @@ -58,7 +60,9 @@ async def list_agent_docs( offset=offset, sort_by=sort_by, direction=direction, - metadata_filter=metadata_filter.model_dump(mode="json"), + metadata_filter=metadata_filter.model_dump(mode="json") + if metadata_filter + else {}, ) return ListResponse[Doc](items=docs) diff --git a/agents-api/agents_api/routers/sessions/list_sessions.py b/agents-api/agents_api/routers/sessions/list_sessions.py index ae011fb18..157b9f681 100644 --- a/agents-api/agents_api/routers/sessions/list_sessions.py +++ b/agents-api/agents_api/routers/sessions/list_sessions.py @@ -29,7 +29,9 @@ async def list_sessions( offset=offset, sort_by=sort_by, direction=direction, - metadata_filter=metadata_filter.model_dump(mode="json"), + metadata_filter=metadata_filter.model_dump(mode="json") + if metadata_filter + else {}, ) return ListResponse[Session](items=sessions) From 1f501bd63bc974d0c261efae8bc37457d7dd6f64 Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Fri, 4 Oct 2024 20:13:51 -0400 Subject: [PATCH 4/8] fix(agents-api): Fix metadata_filter logic Signed-off-by: Diwank Singh Tomer --- agents-api/agents_api/dependencies/query_filter.py | 6 ++++-- agents-api/agents_api/models/docs/list_docs.py | 4 ++-- agents-api/agents_api/routers/agents/list_agents.py | 2 +- agents-api/agents_api/routers/docs/list_docs.py | 12 +++++------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/agents-api/agents_api/dependencies/query_filter.py b/agents-api/agents_api/dependencies/query_filter.py index 766a5b7c3..da9a76528 100644 --- a/agents-api/agents_api/dependencies/query_filter.py +++ b/agents-api/agents_api/dependencies/query_filter.py @@ -32,6 +32,9 @@ def create_filter_extractor(prefix: str = "filter") -> Callable[[Request], Filte Callable[[Request], FilterModel]: The dependency function. """ + # Add a dot to the prefix to allow for nested filters + prefix += "." + def extract_filters(request: Request) -> FilterModel: """ Extracts query parameters that start with the specified prefix and returns them as a dictionary. @@ -42,10 +45,9 @@ def extract_filters(request: Request) -> FilterModel: 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) :] diff --git a/agents-api/agents_api/models/docs/list_docs.py b/agents-api/agents_api/models/docs/list_docs.py index 3c095c2db..4dad7ec06 100644 --- a/agents-api/agents_api/models/docs/list_docs.py +++ b/agents-api/agents_api/models/docs/list_docs.py @@ -90,7 +90,8 @@ def list_docs( created_at, metadata, }}, - snippets[id, snippet_data] + snippets[id, snippet_data], + {metadata_filter_str} :limit $limit :offset $offset @@ -112,6 +113,5 @@ def list_docs( "owner_type": owner_type, "limit": limit, "offset": offset, - "metadata_filter": metadata_filter_str, }, ) diff --git a/agents-api/agents_api/routers/agents/list_agents.py b/agents-api/agents_api/routers/agents/list_agents.py index a24f0667c..0e14be261 100644 --- a/agents-api/agents_api/routers/agents/list_agents.py +++ b/agents-api/agents_api/routers/agents/list_agents.py @@ -17,7 +17,7 @@ async def list_agents( # Example: # > ?metadata_filter.name=John&metadata_filter.age=30 metadata_filter: Annotated[ - FilterModel | None, Depends(create_filter_extractor("metadata_filter")) + FilterModel, Depends(create_filter_extractor("metadata_filter")) ], limit: int = 100, offset: int = 0, diff --git a/agents-api/agents_api/routers/docs/list_docs.py b/agents-api/agents_api/routers/docs/list_docs.py index f342f4b4b..f56de7c84 100644 --- a/agents-api/agents_api/routers/docs/list_docs.py +++ b/agents-api/agents_api/routers/docs/list_docs.py @@ -1,9 +1,7 @@ -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 Doc, ListResponse from ...dependencies.developer_id import get_developer_id @@ -15,10 +13,10 @@ @router.get("/users/{user_id}/docs", tags=["docs"]) 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")) + FilterModel, Depends(create_filter_extractor("metadata_filter")) ], + user_id: UUID, limit: int = 100, offset: int = 0, sort_by: Literal["created_at", "updated_at"] = "created_at", @@ -43,10 +41,10 @@ async def list_user_docs( @router.get("/agents/{agent_id}/docs", tags=["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")) + FilterModel, Depends(create_filter_extractor("metadata_filter")) ], + agent_id: UUID, limit: int = 100, offset: int = 0, sort_by: Literal["created_at", "updated_at"] = "created_at", From 59f242364357d84c01cbda6b3cdaa217f07bb14b Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Fri, 4 Oct 2024 20:51:44 -0400 Subject: [PATCH 5/8] feat: Merge dev and regenerate openapi spec Signed-off-by: Diwank Singh Tomer --- .../tsp-output/@typespec/openapi3/openapi-0.4.0.yaml | 11 ++++++++--- .../tsp-output/@typespec/openapi3/openapi-1.0.0.yaml | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/typespec/tsp-output/@typespec/openapi3/openapi-0.4.0.yaml b/typespec/tsp-output/@typespec/openapi3/openapi-0.4.0.yaml index e578d26d9..9f0324b0c 100644 --- a/typespec/tsp-output/@typespec/openapi3/openapi-0.4.0.yaml +++ b/typespec/tsp-output/@typespec/openapi3/openapi-0.4.0.yaml @@ -1317,10 +1317,15 @@ components: name: metadata_filter in: query required: true - description: JSON string of object that should be used to filter objects by metadata + description: Object to filter results by metadata schema: - type: string - default: '{}' + type: object + additionalProperties: + anyOf: + - type: number + - type: string + - type: boolean + nullable: true explode: false Common.PaginationOptions.offset: name: offset diff --git a/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml b/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml index e5a5f99e6..a6ea6461d 100644 --- a/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml +++ b/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml @@ -1317,10 +1317,15 @@ components: name: metadata_filter in: query required: true - description: JSON string of object that should be used to filter objects by metadata + description: Object to filter results by metadata schema: - type: string - default: '{}' + type: object + additionalProperties: + anyOf: + - type: number + - type: string + - type: boolean + nullable: true explode: false Common.PaginationOptions.offset: name: offset From 71da38e82399f5e34b04872c916885429f9ed4c2 Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Fri, 4 Oct 2024 21:05:37 -0400 Subject: [PATCH 6/8] fix(agents-api): Simplify metadata_filter type to dict Signed-off-by: Diwank Singh Tomer --- .../agents_api/dependencies/query_filter.py | 16 +++++----------- .../agents_api/routers/agents/list_agents.py | 8 +++----- agents-api/agents_api/routers/docs/list_docs.py | 14 +++++--------- .../agents_api/routers/sessions/list_sessions.py | 14 +++++--------- 4 files changed, 18 insertions(+), 34 deletions(-) diff --git a/agents-api/agents_api/dependencies/query_filter.py b/agents-api/agents_api/dependencies/query_filter.py index da9a76528..116841570 100644 --- a/agents-api/agents_api/dependencies/query_filter.py +++ b/agents-api/agents_api/dependencies/query_filter.py @@ -1,12 +1,6 @@ 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: @@ -21,7 +15,7 @@ def convert_value(value: str) -> Any: return value -def create_filter_extractor(prefix: str = "filter") -> Callable[[Request], FilterModel]: +def create_filter_extractor(prefix: str = "filter") -> Callable[[Request], dict[str, Any]]: """ Creates a dependency function to extract filter parameters with a given prefix. @@ -29,13 +23,13 @@ def create_filter_extractor(prefix: str = "filter") -> Callable[[Request], Filte prefix (str): The prefix to identify filter parameters. Returns: - Callable[[Request], FilterModel]: The dependency function. + Callable[[Request], dict[str, Any]]: The dependency function. """ # Add a dot to the prefix to allow for nested filters prefix += "." - def extract_filters(request: Request) -> FilterModel: + def extract_filters(request: Request) -> dict[str, Any]: """ Extracts query parameters that start with the specified prefix and returns them as a dictionary. @@ -43,7 +37,7 @@ def extract_filters(request: Request) -> FilterModel: request (Request): The incoming HTTP request. Returns: - FilterModel: A FilterModel instance containing the filter parameters. + dict[str, Any]: A dictionary containing the filter parameters. """ filters: dict[str, Any] = {} @@ -53,6 +47,6 @@ def extract_filters(request: Request) -> FilterModel: filter_key = key[len(prefix) :] filters[filter_key] = convert_value(value) - return FilterModel(**filters) + return filters return extract_filters diff --git a/agents-api/agents_api/routers/agents/list_agents.py b/agents-api/agents_api/routers/agents/list_agents.py index 0e14be261..ef9bb09db 100644 --- a/agents-api/agents_api/routers/agents/list_agents.py +++ b/agents-api/agents_api/routers/agents/list_agents.py @@ -5,7 +5,7 @@ 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 ...dependencies.query_filter import create_filter_extractor from ...models.agent.list_agents import list_agents as list_agents_query from .router import router @@ -17,7 +17,7 @@ async def list_agents( # Example: # > ?metadata_filter.name=John&metadata_filter.age=30 metadata_filter: Annotated[ - FilterModel, Depends(create_filter_extractor("metadata_filter")) + dict, Depends(create_filter_extractor("metadata_filter")) ], limit: int = 100, offset: int = 0, @@ -30,9 +30,7 @@ async def list_agents( offset=offset, sort_by=sort_by, direction=direction, - metadata_filter=metadata_filter.model_dump(mode="json") - if metadata_filter - else {}, + metadata_filter=metadata_filter or {}, ) return ListResponse[Agent](items=agents) diff --git a/agents-api/agents_api/routers/docs/list_docs.py b/agents-api/agents_api/routers/docs/list_docs.py index f56de7c84..a4701646d 100644 --- a/agents-api/agents_api/routers/docs/list_docs.py +++ b/agents-api/agents_api/routers/docs/list_docs.py @@ -5,7 +5,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 ...dependencies.query_filter import create_filter_extractor from ...models.docs.list_docs import list_docs as list_docs_query from .router import router @@ -14,7 +14,7 @@ async def list_user_docs( x_developer_id: Annotated[UUID, Depends(get_developer_id)], metadata_filter: Annotated[ - FilterModel, Depends(create_filter_extractor("metadata_filter")) + dict, Depends(create_filter_extractor("metadata_filter")) ], user_id: UUID, limit: int = 100, @@ -30,9 +30,7 @@ async def list_user_docs( offset=offset, sort_by=sort_by, direction=direction, - metadata_filter=metadata_filter.model_dump(mode="json") - if metadata_filter - else {}, + metadata_filter=metadata_filter or {}, ) return ListResponse[Doc](items=docs) @@ -42,7 +40,7 @@ async def list_user_docs( async def list_agent_docs( x_developer_id: Annotated[UUID, Depends(get_developer_id)], metadata_filter: Annotated[ - FilterModel, Depends(create_filter_extractor("metadata_filter")) + dict, Depends(create_filter_extractor("metadata_filter")) ], agent_id: UUID, limit: int = 100, @@ -58,9 +56,7 @@ async def list_agent_docs( offset=offset, sort_by=sort_by, direction=direction, - metadata_filter=metadata_filter.model_dump(mode="json") - if metadata_filter - else {}, + metadata_filter=metadata_filter or {}, ) return ListResponse[Doc](items=docs) diff --git a/agents-api/agents_api/routers/sessions/list_sessions.py b/agents-api/agents_api/routers/sessions/list_sessions.py index 157b9f681..6a4555e6e 100644 --- a/agents-api/agents_api/routers/sessions/list_sessions.py +++ b/agents-api/agents_api/routers/sessions/list_sessions.py @@ -1,13 +1,11 @@ -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 ListResponse, Session from ...dependencies.developer_id import get_developer_id -from ...dependencies.query_filter import FilterModel, create_filter_extractor +from ...dependencies.query_filter import create_filter_extractor from ...models.session.list_sessions import list_sessions as list_sessions_query from .router import router @@ -16,8 +14,8 @@ async def list_sessions( x_developer_id: Annotated[UUID, Depends(get_developer_id)], metadata_filter: Annotated[ - FilterModel | None, Depends(create_filter_extractor("metadata_filter")) - ], + dict, Depends(create_filter_extractor("metadata_filter")) + ] = {}, limit: int = 100, offset: int = 0, sort_by: Literal["created_at", "updated_at"] = "created_at", @@ -29,9 +27,7 @@ async def list_sessions( offset=offset, sort_by=sort_by, direction=direction, - metadata_filter=metadata_filter.model_dump(mode="json") - if metadata_filter - else {}, + metadata_filter=metadata_filter or {}, ) return ListResponse[Session](items=sessions) From dd705050dd0d8704ff797122c0005459449bf5d4 Mon Sep 17 00:00:00 2001 From: creatorrr Date: Sat, 5 Oct 2024 01:06:20 +0000 Subject: [PATCH 7/8] refactor: Lint agents-api (CI) --- agents-api/agents_api/dependencies/query_filter.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/agents-api/agents_api/dependencies/query_filter.py b/agents-api/agents_api/dependencies/query_filter.py index 116841570..c100f1489 100644 --- a/agents-api/agents_api/dependencies/query_filter.py +++ b/agents-api/agents_api/dependencies/query_filter.py @@ -15,7 +15,9 @@ def convert_value(value: str) -> Any: return value -def create_filter_extractor(prefix: str = "filter") -> Callable[[Request], dict[str, Any]]: +def create_filter_extractor( + prefix: str = "filter", +) -> Callable[[Request], dict[str, Any]]: """ Creates a dependency function to extract filter parameters with a given prefix. From 63eda8b9da45b5200862c799e7d9da97299f0029 Mon Sep 17 00:00:00 2001 From: Diwank Singh Tomer Date: Fri, 4 Oct 2024 21:34:38 -0400 Subject: [PATCH 8/8] fix(typespec): Fix childlist return type to items from results Signed-off-by: Diwank Singh Tomer --- typespec/common/interfaces.tsp | 2 +- .../@typespec/openapi3/openapi-0.4.0.yaml | 24 +++++++++---------- .../@typespec/openapi3/openapi-1.0.0.yaml | 24 +++++++++---------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/typespec/common/interfaces.tsp b/typespec/common/interfaces.tsp index d44d8aab0..d9e4a9e2e 100644 --- a/typespec/common/interfaces.tsp +++ b/typespec/common/interfaces.tsp @@ -136,7 +136,7 @@ interface ChildLimitOffsetPagination< ...PaginationOptions, ): { - results: T[]; + items: T[]; }; } diff --git a/typespec/tsp-output/@typespec/openapi3/openapi-0.4.0.yaml b/typespec/tsp-output/@typespec/openapi3/openapi-0.4.0.yaml index 9f0324b0c..7a7afc3e9 100644 --- a/typespec/tsp-output/@typespec/openapi3/openapi-0.4.0.yaml +++ b/typespec/tsp-output/@typespec/openapi3/openapi-0.4.0.yaml @@ -181,12 +181,12 @@ paths: schema: type: object properties: - results: + items: type: array items: $ref: '#/components/schemas/Docs.Doc' required: - - results + - items post: operationId: AgentDocsRoute_create description: Create a Doc for this Agent @@ -290,12 +290,12 @@ paths: schema: type: object properties: - results: + items: type: array items: $ref: '#/components/schemas/Tasks.Task' required: - - results + - items post: operationId: TasksRoute_create description: Create a new task @@ -434,12 +434,12 @@ paths: schema: type: object properties: - results: + items: type: array items: $ref: '#/components/schemas/Tools.Tool' required: - - results + - items post: operationId: AgentToolsRoute_create description: Create a new tool for this agent @@ -713,7 +713,7 @@ paths: schema: type: object properties: - results: + items: type: array items: type: object @@ -725,7 +725,7 @@ paths: required: - transitions required: - - results + - items /executions/{id}/transitions.stream: get: operationId: ExecutionTransitionsStreamRoute_stream @@ -1026,12 +1026,12 @@ paths: schema: type: object properties: - results: + items: type: array items: $ref: '#/components/schemas/Executions.Execution' required: - - results + - items /users: get: operationId: UsersRoute_list @@ -1196,12 +1196,12 @@ paths: schema: type: object properties: - results: + items: type: array items: $ref: '#/components/schemas/Docs.Doc' required: - - results + - items post: operationId: UserDocsRoute_create description: Create a Doc for this User diff --git a/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml b/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml index a6ea6461d..d82540194 100644 --- a/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml +++ b/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml @@ -181,12 +181,12 @@ paths: schema: type: object properties: - results: + items: type: array items: $ref: '#/components/schemas/Docs.Doc' required: - - results + - items post: operationId: AgentDocsRoute_create description: Create a Doc for this Agent @@ -290,12 +290,12 @@ paths: schema: type: object properties: - results: + items: type: array items: $ref: '#/components/schemas/Tasks.Task' required: - - results + - items post: operationId: TasksRoute_create description: Create a new task @@ -434,12 +434,12 @@ paths: schema: type: object properties: - results: + items: type: array items: $ref: '#/components/schemas/Tools.Tool' required: - - results + - items post: operationId: AgentToolsRoute_create description: Create a new tool for this agent @@ -713,7 +713,7 @@ paths: schema: type: object properties: - results: + items: type: array items: type: object @@ -725,7 +725,7 @@ paths: required: - transitions required: - - results + - items /executions/{id}/transitions.stream: get: operationId: ExecutionTransitionsStreamRoute_stream @@ -1026,12 +1026,12 @@ paths: schema: type: object properties: - results: + items: type: array items: $ref: '#/components/schemas/Executions.Execution' required: - - results + - items /users: get: operationId: UsersRoute_list @@ -1196,12 +1196,12 @@ paths: schema: type: object properties: - results: + items: type: array items: $ref: '#/components/schemas/Docs.Doc' required: - - results + - items post: operationId: UserDocsRoute_create description: Create a Doc for this User