# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations from typing import Mapping, Optional, cast from typing_extensions import Literal import httpx from ..._files import deepcopy_with_paths from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, FileTypes, omit, not_given from ..._utils import extract_files, path_template, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( to_raw_response_wrapper, to_streamed_response_wrapper, async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) from ...pagination import SyncArrayPage, AsyncArrayPage from ..._base_client import AsyncPaginator, make_request_options from ...types.folders import file_list_params, file_upload_params, file_retrieve_params from ...types.folders.file_list_response import FileListResponse from ...types.folders.file_upload_response import FileUploadResponse from ...types.folders.file_retrieve_response import FileRetrieveResponse __all__ = ["FilesResource", "AsyncFilesResource"] class FilesResource(SyncAPIResource): @cached_property def with_raw_response(self) -> FilesResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/letta-ai/letta-python#accessing-raw-response-data-eg-headers """ return FilesResourceWithRawResponse(self) @cached_property def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/letta-ai/letta-python#with_streaming_response """ return FilesResourceWithStreamingResponse(self) def retrieve( self, file_id: str, *, folder_id: str, include_content: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileRetrieveResponse: """ Retrieve a file from a folder by ID. Args: folder_id: The ID of the source in the format 'source-' file_id: The ID of the file in the format 'file-' include_content: Whether to include full file content extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not folder_id: raise ValueError(f"Expected a non-empty value for `folder_id` but received {folder_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return self._get( path_template("/v1/folders/{folder_id}/files/{file_id}", folder_id=folder_id, file_id=file_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform({"include_content": include_content}, file_retrieve_params.FileRetrieveParams), ), cast_to=FileRetrieveResponse, ) def list( self, folder_id: str, *, after: Optional[str] | Omit = omit, before: Optional[str] | Omit = omit, include_content: bool | Omit = omit, limit: Optional[int] | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, order_by: Literal["created_at"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncArrayPage[FileListResponse]: """ List paginated files associated with a data folder. Args: folder_id: The ID of the source in the format 'source-' after: Cursor for pagination (file ID). Returns results relative to this ID in the specified sort order. Expected format: 'file-' before: Cursor for pagination (file ID). Returns results relative to this ID in the specified sort order. Expected format: 'file-' include_content: Whether to include full file content limit: Maximum number of files to return order: Sort order for files by creation time. 'asc' for oldest first, 'desc' for newest first order_by: Field to sort by extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not folder_id: raise ValueError(f"Expected a non-empty value for `folder_id` but received {folder_id!r}") return self._get_api_list( path_template("/v1/folders/{folder_id}/files", folder_id=folder_id), page=SyncArrayPage[FileListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "include_content": include_content, "limit": limit, "order": order, "order_by": order_by, }, file_list_params.FileListParams, ), ), model=FileListResponse, ) def delete( self, file_id: str, *, folder_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete a file from a folder. Args: folder_id: The ID of the source in the format 'source-' file_id: The ID of the file in the format 'file-' extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not folder_id: raise ValueError(f"Expected a non-empty value for `folder_id` but received {folder_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._delete( path_template("/v1/folders/{folder_id}/{file_id}", folder_id=folder_id, file_id=file_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) def upload( self, folder_id: str, *, file: FileTypes, duplicate_handling: Literal["skip", "error", "suffix", "replace"] | Omit = omit, name: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileUploadResponse: """ Upload a file to a data folder. Args: folder_id: The ID of the source in the format 'source-' duplicate_handling: How to handle duplicate filenames name: Optional custom name to override the uploaded file's name extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not folder_id: raise ValueError(f"Expected a non-empty value for `folder_id` but received {folder_id!r}") body = deepcopy_with_paths({"file": file}, [["file"]]) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( path_template("/v1/folders/{folder_id}/upload", folder_id=folder_id), body=maybe_transform(body, file_upload_params.FileUploadParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "duplicate_handling": duplicate_handling, "name": name, }, file_upload_params.FileUploadParams, ), ), cast_to=FileUploadResponse, ) class AsyncFilesResource(AsyncAPIResource): @cached_property def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: """ This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. For more information, see https://www.github.com/letta-ai/letta-python#accessing-raw-response-data-eg-headers """ return AsyncFilesResourceWithRawResponse(self) @cached_property def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/letta-ai/letta-python#with_streaming_response """ return AsyncFilesResourceWithStreamingResponse(self) async def retrieve( self, file_id: str, *, folder_id: str, include_content: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileRetrieveResponse: """ Retrieve a file from a folder by ID. Args: folder_id: The ID of the source in the format 'source-' file_id: The ID of the file in the format 'file-' include_content: Whether to include full file content extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not folder_id: raise ValueError(f"Expected a non-empty value for `folder_id` but received {folder_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return await self._get( path_template("/v1/folders/{folder_id}/files/{file_id}", folder_id=folder_id, file_id=file_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform( {"include_content": include_content}, file_retrieve_params.FileRetrieveParams ), ), cast_to=FileRetrieveResponse, ) def list( self, folder_id: str, *, after: Optional[str] | Omit = omit, before: Optional[str] | Omit = omit, include_content: bool | Omit = omit, limit: Optional[int] | Omit = omit, order: Literal["asc", "desc"] | Omit = omit, order_by: Literal["created_at"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[FileListResponse, AsyncArrayPage[FileListResponse]]: """ List paginated files associated with a data folder. Args: folder_id: The ID of the source in the format 'source-' after: Cursor for pagination (file ID). Returns results relative to this ID in the specified sort order. Expected format: 'file-' before: Cursor for pagination (file ID). Returns results relative to this ID in the specified sort order. Expected format: 'file-' include_content: Whether to include full file content limit: Maximum number of files to return order: Sort order for files by creation time. 'asc' for oldest first, 'desc' for newest first order_by: Field to sort by extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not folder_id: raise ValueError(f"Expected a non-empty value for `folder_id` but received {folder_id!r}") return self._get_api_list( path_template("/v1/folders/{folder_id}/files", folder_id=folder_id), page=AsyncArrayPage[FileListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=maybe_transform( { "after": after, "before": before, "include_content": include_content, "limit": limit, "order": order, "order_by": order_by, }, file_list_params.FileListParams, ), ), model=FileListResponse, ) async def delete( self, file_id: str, *, folder_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ Delete a file from a folder. Args: folder_id: The ID of the source in the format 'source-' file_id: The ID of the file in the format 'file-' extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not folder_id: raise ValueError(f"Expected a non-empty value for `folder_id` but received {folder_id!r}") if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._delete( path_template("/v1/folders/{folder_id}/{file_id}", folder_id=folder_id, file_id=file_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=NoneType, ) async def upload( self, folder_id: str, *, file: FileTypes, duplicate_handling: Literal["skip", "error", "suffix", "replace"] | Omit = omit, name: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FileUploadResponse: """ Upload a file to a data folder. Args: folder_id: The ID of the source in the format 'source-' duplicate_handling: How to handle duplicate filenames name: Optional custom name to override the uploaded file's name extra_headers: Send extra headers extra_query: Add additional query parameters to the request extra_body: Add additional JSON properties to the request timeout: Override the client-level default timeout for this request, in seconds """ if not folder_id: raise ValueError(f"Expected a non-empty value for `folder_id` but received {folder_id!r}") body = deepcopy_with_paths({"file": file}, [["file"]]) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) # It should be noted that the actual Content-Type header that will be # sent to the server will contain a `boundary` parameter, e.g. # multipart/form-data; boundary=---abc-- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( path_template("/v1/folders/{folder_id}/upload", folder_id=folder_id), body=await async_maybe_transform(body, file_upload_params.FileUploadParams), files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, query=await async_maybe_transform( { "duplicate_handling": duplicate_handling, "name": name, }, file_upload_params.FileUploadParams, ), ), cast_to=FileUploadResponse, ) class FilesResourceWithRawResponse: def __init__(self, files: FilesResource) -> None: self._files = files self.retrieve = to_raw_response_wrapper( files.retrieve, ) self.list = to_raw_response_wrapper( files.list, ) self.delete = to_raw_response_wrapper( files.delete, ) self.upload = to_raw_response_wrapper( files.upload, ) class AsyncFilesResourceWithRawResponse: def __init__(self, files: AsyncFilesResource) -> None: self._files = files self.retrieve = async_to_raw_response_wrapper( files.retrieve, ) self.list = async_to_raw_response_wrapper( files.list, ) self.delete = async_to_raw_response_wrapper( files.delete, ) self.upload = async_to_raw_response_wrapper( files.upload, ) class FilesResourceWithStreamingResponse: def __init__(self, files: FilesResource) -> None: self._files = files self.retrieve = to_streamed_response_wrapper( files.retrieve, ) self.list = to_streamed_response_wrapper( files.list, ) self.delete = to_streamed_response_wrapper( files.delete, ) self.upload = to_streamed_response_wrapper( files.upload, ) class AsyncFilesResourceWithStreamingResponse: def __init__(self, files: AsyncFilesResource) -> None: self._files = files self.retrieve = async_to_streamed_response_wrapper( files.retrieve, ) self.list = async_to_streamed_response_wrapper( files.list, ) self.delete = async_to_streamed_response_wrapper( files.delete, ) self.upload = async_to_streamed_response_wrapper( files.upload, )