feat: add path parameter validation for file_id (#5522)
🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2317,8 +2317,14 @@
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"minLength": 43,
|
||||
"maxLength": 43,
|
||||
"pattern": "^source-[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 source in the format 'source-<uuid4>'",
|
||||
"examples": ["source-123e4567-e89b-42d3-8456-426614174000"],
|
||||
"title": "Source Id"
|
||||
}
|
||||
},
|
||||
"description": "The ID of the source in the format 'source-<uuid4>'"
|
||||
},
|
||||
{
|
||||
"name": "file_id",
|
||||
@@ -2326,8 +2332,14 @@
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"minLength": 41,
|
||||
"maxLength": 41,
|
||||
"pattern": "^file-[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 file in the format 'file-<uuid4>'",
|
||||
"examples": ["file-123e4567-e89b-42d3-8456-426614174000"],
|
||||
"title": "File Id"
|
||||
}
|
||||
},
|
||||
"description": "The ID of the file in the format 'file-<uuid4>'"
|
||||
},
|
||||
{
|
||||
"name": "include_content",
|
||||
@@ -2380,8 +2392,14 @@
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"minLength": 43,
|
||||
"maxLength": 43,
|
||||
"pattern": "^source-[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 source in the format 'source-<uuid4>'",
|
||||
"examples": ["source-123e4567-e89b-42d3-8456-426614174000"],
|
||||
"title": "Source Id"
|
||||
}
|
||||
},
|
||||
"description": "The ID of the source in the format 'source-<uuid4>'"
|
||||
},
|
||||
{
|
||||
"name": "file_id",
|
||||
@@ -2389,8 +2407,14 @@
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"minLength": 41,
|
||||
"maxLength": 41,
|
||||
"pattern": "^file-[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 file in the format 'file-<uuid4>'",
|
||||
"examples": ["file-123e4567-e89b-42d3-8456-426614174000"],
|
||||
"title": "File Id"
|
||||
}
|
||||
},
|
||||
"description": "The ID of the file in the format 'file-<uuid4>'"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -3311,8 +3335,14 @@
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"minLength": 43,
|
||||
"maxLength": 43,
|
||||
"pattern": "^folder-[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 folder in the format 'folder-<uuid4>'",
|
||||
"examples": ["folder-123e4567-e89b-42d3-8456-426614174000"],
|
||||
"title": "Folder Id"
|
||||
}
|
||||
},
|
||||
"description": "The ID of the folder in the format 'folder-<uuid4>'"
|
||||
},
|
||||
{
|
||||
"name": "file_id",
|
||||
@@ -3320,8 +3350,14 @@
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"minLength": 41,
|
||||
"maxLength": 41,
|
||||
"pattern": "^file-[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 file in the format 'file-<uuid4>'",
|
||||
"examples": ["file-123e4567-e89b-42d3-8456-426614174000"],
|
||||
"title": "File Id"
|
||||
}
|
||||
},
|
||||
"description": "The ID of the file in the format 'file-<uuid4>'"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -4724,8 +4760,14 @@
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"minLength": 41,
|
||||
"maxLength": 41,
|
||||
"pattern": "^file-[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 file in the format 'file-<uuid4>'",
|
||||
"examples": ["file-123e4567-e89b-42d3-8456-426614174000"],
|
||||
"title": "File Id"
|
||||
}
|
||||
},
|
||||
"description": "The ID of the file in the format 'file-<uuid4>'"
|
||||
},
|
||||
{
|
||||
"name": "agent_id",
|
||||
@@ -4784,8 +4826,14 @@
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"minLength": 41,
|
||||
"maxLength": 41,
|
||||
"pattern": "^file-[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 file in the format 'file-<uuid4>'",
|
||||
"examples": ["file-123e4567-e89b-42d3-8456-426614174000"],
|
||||
"title": "File Id"
|
||||
}
|
||||
},
|
||||
"description": "The ID of the file in the format 'file-<uuid4>'"
|
||||
},
|
||||
{
|
||||
"name": "agent_id",
|
||||
|
||||
@@ -616,7 +616,7 @@ async def close_all_open_files(
|
||||
|
||||
@router.patch("/{agent_id}/files/{file_id}/open", response_model=List[str], operation_id="open_file")
|
||||
async def open_file(
|
||||
file_id: str,
|
||||
file_id: str = PATH_VALIDATORS["file"],
|
||||
agent_id: str = PATH_VALIDATORS["agent"],
|
||||
server: "SyncServer" = Depends(get_letta_server),
|
||||
headers: HeaderParams = Depends(get_headers),
|
||||
@@ -665,7 +665,7 @@ async def open_file(
|
||||
|
||||
@router.patch("/{agent_id}/files/{file_id}/close", response_model=None, operation_id="close_file")
|
||||
async def close_file(
|
||||
file_id: str,
|
||||
file_id: str = PATH_VALIDATORS["file"],
|
||||
agent_id: str = PATH_VALIDATORS["agent"],
|
||||
server: "SyncServer" = Depends(get_letta_server),
|
||||
headers: HeaderParams = Depends(get_headers),
|
||||
|
||||
@@ -37,6 +37,7 @@ from letta.services.file_processor.parser.markitdown_parser import MarkitdownFil
|
||||
from letta.services.file_processor.parser.mistral_parser import MistralFileParser
|
||||
from letta.settings import settings
|
||||
from letta.utils import safe_create_file_processing_task, safe_create_task, sanitize_filename
|
||||
from letta.validators import PATH_VALIDATORS
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -496,8 +497,8 @@ async def list_folder_files(
|
||||
# it's still good practice to return a status indicating the success or failure of the deletion
|
||||
@router.delete("/{folder_id}/{file_id}", status_code=204, operation_id="delete_file_from_folder")
|
||||
async def delete_file_from_folder(
|
||||
folder_id: str,
|
||||
file_id: str,
|
||||
folder_id: str = PATH_VALIDATORS["folder"],
|
||||
file_id: str = PATH_VALIDATORS["file"],
|
||||
server: "SyncServer" = Depends(get_letta_server),
|
||||
headers: HeaderParams = Depends(get_headers),
|
||||
):
|
||||
|
||||
@@ -36,6 +36,7 @@ from letta.services.file_processor.parser.markitdown_parser import MarkitdownFil
|
||||
from letta.services.file_processor.parser.mistral_parser import MistralFileParser
|
||||
from letta.settings import settings
|
||||
from letta.utils import safe_create_file_processing_task, safe_create_task, sanitize_filename
|
||||
from letta.validators import PATH_VALIDATORS
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -386,8 +387,8 @@ async def list_source_files(
|
||||
|
||||
@router.get("/{source_id}/files/{file_id}", response_model=FileMetadata, operation_id="get_file_metadata", deprecated=True)
|
||||
async def get_file_metadata(
|
||||
source_id: str,
|
||||
file_id: str,
|
||||
source_id: str = PATH_VALIDATORS["source"],
|
||||
file_id: str = PATH_VALIDATORS["file"],
|
||||
include_content: bool = Query(False, description="Whether to include full file content"),
|
||||
server: "SyncServer" = Depends(get_letta_server),
|
||||
headers: HeaderParams = Depends(get_headers),
|
||||
@@ -412,8 +413,8 @@ async def get_file_metadata(
|
||||
# it's still good practice to return a status indicating the success or failure of the deletion
|
||||
@router.delete("/{source_id}/{file_id}", status_code=204, operation_id="delete_file_from_source", deprecated=True)
|
||||
async def delete_file_from_source(
|
||||
source_id: str,
|
||||
file_id: str,
|
||||
source_id: str = PATH_VALIDATORS["source"],
|
||||
file_id: str = PATH_VALIDATORS["file"],
|
||||
server: "SyncServer" = Depends(get_letta_server),
|
||||
headers: HeaderParams = Depends(get_headers),
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user