From 3b56c53b6c2ad3bbc7ddc85652ec792f89647e52 Mon Sep 17 00:00:00 2001 From: Kian Jones <11655409+kianjones9@users.noreply.github.com> Date: Fri, 17 Oct 2025 16:39:08 -0700 Subject: [PATCH] feat: add path parameter validation for group_id (#5521) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude --- fern/openapi.json | 64 +++++++++++++++++++--- letta/server/rest_api/routers/v1/groups.py | 16 +++--- 2 files changed, 64 insertions(+), 16 deletions(-) diff --git a/fern/openapi.json b/fern/openapi.json index 87e54792..bc67175e 100644 --- a/fern/openapi.json +++ b/fern/openapi.json @@ -7314,8 +7314,14 @@ "required": true, "schema": { "type": "string", + "minLength": 42, + "maxLength": 42, + "pattern": "^group-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "description": "The ID of the group in the format 'group-'", + "examples": ["group-123e4567-e89b-42d3-8456-426614174000"], "title": "Group Id" - } + }, + "description": "The ID of the group in the format 'group-'" } ], "responses": { @@ -7353,8 +7359,14 @@ "required": true, "schema": { "type": "string", + "minLength": 42, + "maxLength": 42, + "pattern": "^group-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "description": "The ID of the group in the format 'group-'", + "examples": ["group-123e4567-e89b-42d3-8456-426614174000"], "title": "Group Id" - } + }, + "description": "The ID of the group in the format 'group-'" }, { "name": "X-Project", @@ -7420,8 +7432,14 @@ "required": true, "schema": { "type": "string", + "minLength": 42, + "maxLength": 42, + "pattern": "^group-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "description": "The ID of the group in the format 'group-'", + "examples": ["group-123e4567-e89b-42d3-8456-426614174000"], "title": "Group Id" - } + }, + "description": "The ID of the group in the format 'group-'" } ], "responses": { @@ -7459,8 +7477,14 @@ "required": true, "schema": { "type": "string", + "minLength": 42, + "maxLength": 42, + "pattern": "^group-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "description": "The ID of the group in the format 'group-'", + "examples": ["group-123e4567-e89b-42d3-8456-426614174000"], "title": "Group Id" - } + }, + "description": "The ID of the group in the format 'group-'" } ], "requestBody": { @@ -7508,8 +7532,14 @@ "required": true, "schema": { "type": "string", + "minLength": 42, + "maxLength": 42, + "pattern": "^group-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "description": "The ID of the group in the format 'group-'", + "examples": ["group-123e4567-e89b-42d3-8456-426614174000"], "title": "Group Id" - } + }, + "description": "The ID of the group in the format 'group-'" }, { "name": "before", @@ -7670,8 +7700,14 @@ "required": true, "schema": { "type": "string", + "minLength": 42, + "maxLength": 42, + "pattern": "^group-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "description": "The ID of the group in the format 'group-'", + "examples": ["group-123e4567-e89b-42d3-8456-426614174000"], "title": "Group Id" - } + }, + "description": "The ID of the group in the format 'group-'" } ], "requestBody": { @@ -7722,8 +7758,14 @@ "required": true, "schema": { "type": "string", + "minLength": 42, + "maxLength": 42, + "pattern": "^group-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "description": "The ID of the group in the format 'group-'", + "examples": ["group-123e4567-e89b-42d3-8456-426614174000"], "title": "Group Id" - } + }, + "description": "The ID of the group in the format 'group-'" }, { "name": "message_id", @@ -7845,8 +7887,14 @@ "required": true, "schema": { "type": "string", + "minLength": 42, + "maxLength": 42, + "pattern": "^group-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "description": "The ID of the group in the format 'group-'", + "examples": ["group-123e4567-e89b-42d3-8456-426614174000"], "title": "Group Id" - } + }, + "description": "The ID of the group in the format 'group-'" } ], "responses": { diff --git a/letta/server/rest_api/routers/v1/groups.py b/letta/server/rest_api/routers/v1/groups.py index 57ee3547..f59e36b5 100644 --- a/letta/server/rest_api/routers/v1/groups.py +++ b/letta/server/rest_api/routers/v1/groups.py @@ -69,7 +69,7 @@ async def count_groups( @router.get("/{group_id}", response_model=Group, operation_id="retrieve_group") async def retrieve_group( - group_id: str, + group_id: str = PATH_VALIDATORS["group"], server: "SyncServer" = Depends(get_letta_server), headers: HeaderParams = Depends(get_headers), ): @@ -98,7 +98,7 @@ async def create_group( @router.patch("/{group_id}", response_model=Group, operation_id="modify_group") async def modify_group( - group_id: str, + group_id: str = PATH_VALIDATORS["group"], group: GroupUpdate = Body(...), server: "SyncServer" = Depends(get_letta_server), headers: HeaderParams = Depends(get_headers), @@ -115,7 +115,7 @@ async def modify_group( @router.delete("/{group_id}", response_model=None, operation_id="delete_group") async def delete_group( - group_id: str, + group_id: str = PATH_VALIDATORS["group"], server: "SyncServer" = Depends(get_letta_server), headers: HeaderParams = Depends(get_headers), ): @@ -133,7 +133,7 @@ async def delete_group( operation_id="send_group_message", ) async def send_group_message( - group_id: str, + group_id: str = PATH_VALIDATORS["group"], server: SyncServer = Depends(get_letta_server), request: LettaRequest = Body(...), headers: HeaderParams = Depends(get_headers), @@ -171,7 +171,7 @@ async def send_group_message( }, ) async def send_group_message_streaming( - group_id: str, + group_id: str = PATH_VALIDATORS["group"], server: SyncServer = Depends(get_letta_server), request: LettaStreamingRequest = Body(...), headers: HeaderParams = Depends(get_headers), @@ -203,7 +203,7 @@ GroupMessagesResponse = Annotated[ @router.patch("/{group_id}/messages/{message_id}", response_model=LettaMessageUnion, operation_id="modify_group_message") async def modify_group_message( - group_id: str, + group_id: str = PATH_VALIDATORS["group"], message_id: str = PATH_VALIDATORS["message"], request: LettaMessageUpdateUnion = Body(...), server: "SyncServer" = Depends(get_letta_server), @@ -219,7 +219,7 @@ async def modify_group_message( @router.get("/{group_id}/messages", response_model=GroupMessagesResponse, operation_id="list_group_messages") async def list_group_messages( - group_id: str, + group_id: str = PATH_VALIDATORS["group"], before: Optional[str] = Query( None, description="Message ID cursor for pagination. Returns messages that come before this message ID in the specified sort order", @@ -274,7 +274,7 @@ async def list_group_messages( @router.patch("/{group_id}/reset-messages", response_model=None, operation_id="reset_group_messages") async def reset_group_messages( - group_id: str, + group_id: str = PATH_VALIDATORS["group"], server: "SyncServer" = Depends(get_letta_server), headers: HeaderParams = Depends(get_headers), ):