From a3e3b23a5e9c95daaf19d1beb84a07a9a61bf2f3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 11 Aug 2025 07:35:05 +0000 Subject: [PATCH 1/2] feat(api): update via SDK Studio --- .stats.yml | 2 +- api.md | 3 +- .../resources/vector_stores/files.py | 90 +++++++++---------- .../types/vector_stores/__init__.py | 1 + .../types/vector_stores/file_list_params.py | 17 +++- .../types/vector_stores/file_list_response.py | 69 ++++++++++++++ .../api_resources/vector_stores/test_files.py | 32 ++++--- 7 files changed, 153 insertions(+), 61 deletions(-) create mode 100644 src/mixedbread/types/vector_stores/file_list_response.py diff --git a/.stats.yml b/.stats.yml index c7586392..33d7691d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 49 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mixedbread%2Fmixedbread-4983c57f5143aaeadfbb4af35595570e613035ae500ff1597fdf600cc2a48959.yml openapi_spec_hash: ecc0a6cfe61c3c959d034d094f36befe -config_hash: 810d9712d3d0d6a1f50d71a25511d8a7 +config_hash: ac27678c24558b71ee39b3db54fa12da diff --git a/api.md b/api.md index 257f5d28..f251791d 100644 --- a/api.md +++ b/api.md @@ -63,6 +63,7 @@ from mixedbread.types.vector_stores import ( ScoredVectorStoreFile, VectorStoreFileStatus, VectorStoreFile, + FileListResponse, FileDeleteResponse, FileSearchResponse, ) @@ -72,7 +73,7 @@ Methods: - client.vector_stores.files.create(vector_store_identifier, \*\*params) -> VectorStoreFile - client.vector_stores.files.retrieve(file_id, \*, vector_store_identifier, \*\*params) -> VectorStoreFile -- client.vector_stores.files.list(vector_store_identifier, \*\*params) -> SyncCursor[VectorStoreFile] +- client.vector_stores.files.list(vector_store_identifier, \*\*params) -> FileListResponse - client.vector_stores.files.delete(file_id, \*, vector_store_identifier) -> FileDeleteResponse - client.vector_stores.files.search(\*\*params) -> FileSearchResponse diff --git a/src/mixedbread/resources/vector_stores/files.py b/src/mixedbread/resources/vector_stores/files.py index 44d28868..7f1ef7c7 100644 --- a/src/mixedbread/resources/vector_stores/files.py +++ b/src/mixedbread/resources/vector_stores/files.py @@ -18,10 +18,10 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ...pagination import SyncCursor, AsyncCursor -from ..._base_client import AsyncPaginator, make_request_options +from ..._base_client import make_request_options from ...types.vector_stores import file_list_params, file_create_params, file_search_params, file_retrieve_params from ...types.vector_stores.vector_store_file import VectorStoreFile +from ...types.vector_stores.file_list_response import FileListResponse from ...types.vector_stores.file_delete_response import FileDeleteResponse from ...types.vector_stores.file_search_response import FileSearchResponse from ...types.vector_stores.vector_store_file_status import VectorStoreFileStatus @@ -171,18 +171,19 @@ def list( before: Optional[str] | NotGiven = NOT_GIVEN, include_total: bool | NotGiven = NOT_GIVEN, statuses: Optional[List[VectorStoreFileStatus]] | NotGiven = NOT_GIVEN, + metadata_filter: Optional[file_list_params.MetadataFilter] | NotGiven = NOT_GIVEN, # 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, - ) -> SyncCursor[VectorStoreFile]: + ) -> FileListResponse: """ - List files indexed in a vector store with pagination. + List files indexed in a vector store with pagination and metadata filter. Args: vector_store_identifier: The ID or name of the vector store pagination: - Pagination parameters + Pagination parameters and metadata filter Returns: VectorStoreFileListResponse: Paginated list of vector store files @@ -201,6 +202,8 @@ def list( statuses: Status to filter by + metadata_filter: Metadata filter to apply to the query + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -213,26 +216,23 @@ def list( raise ValueError( f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" ) - return self._get_api_list( - f"/v1/vector_stores/{vector_store_identifier}/files", - page=SyncCursor[VectorStoreFile], + return self._post( + f"/v1/vector_stores/{vector_store_identifier}/files/list", + body=maybe_transform( + { + "limit": limit, + "after": after, + "before": before, + "include_total": include_total, + "statuses": statuses, + "metadata_filter": metadata_filter, + }, + file_list_params.FileListParams, + ), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "limit": limit, - "after": after, - "before": before, - "include_total": include_total, - "statuses": statuses, - }, - file_list_params.FileListParams, - ), + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - model=VectorStoreFile, + cast_to=FileListResponse, ) def delete( @@ -600,7 +600,7 @@ async def retrieve( cast_to=VectorStoreFile, ) - def list( + async def list( self, vector_store_identifier: str, *, @@ -609,18 +609,19 @@ def list( before: Optional[str] | NotGiven = NOT_GIVEN, include_total: bool | NotGiven = NOT_GIVEN, statuses: Optional[List[VectorStoreFileStatus]] | NotGiven = NOT_GIVEN, + metadata_filter: Optional[file_list_params.MetadataFilter] | NotGiven = NOT_GIVEN, # 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[VectorStoreFile, AsyncCursor[VectorStoreFile]]: + ) -> FileListResponse: """ - List files indexed in a vector store with pagination. + List files indexed in a vector store with pagination and metadata filter. Args: vector_store_identifier: The ID or name of the vector store pagination: - Pagination parameters + Pagination parameters and metadata filter Returns: VectorStoreFileListResponse: Paginated list of vector store files @@ -639,6 +640,8 @@ def list( statuses: Status to filter by + metadata_filter: Metadata filter to apply to the query + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -651,26 +654,23 @@ def list( raise ValueError( f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" ) - return self._get_api_list( - f"/v1/vector_stores/{vector_store_identifier}/files", - page=AsyncCursor[VectorStoreFile], + return await self._post( + f"/v1/vector_stores/{vector_store_identifier}/files/list", + body=await async_maybe_transform( + { + "limit": limit, + "after": after, + "before": before, + "include_total": include_total, + "statuses": statuses, + "metadata_filter": metadata_filter, + }, + file_list_params.FileListParams, + ), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "limit": limit, - "after": after, - "before": before, - "include_total": include_total, - "statuses": statuses, - }, - file_list_params.FileListParams, - ), + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - model=VectorStoreFile, + cast_to=FileListResponse, ) async def delete( diff --git a/src/mixedbread/types/vector_stores/__init__.py b/src/mixedbread/types/vector_stores/__init__.py index 6919f613..dcfaa05b 100644 --- a/src/mixedbread/types/vector_stores/__init__.py +++ b/src/mixedbread/types/vector_stores/__init__.py @@ -5,6 +5,7 @@ from .file_list_params import FileListParams as FileListParams from .vector_store_file import VectorStoreFile as VectorStoreFile from .file_create_params import FileCreateParams as FileCreateParams +from .file_list_response import FileListResponse as FileListResponse from .file_search_params import FileSearchParams as FileSearchParams from .rerank_config_param import RerankConfigParam as RerankConfigParam from .file_delete_response import FileDeleteResponse as FileDeleteResponse diff --git a/src/mixedbread/types/vector_stores/file_list_params.py b/src/mixedbread/types/vector_stores/file_list_params.py index 49fe0c08..a4ac03c8 100644 --- a/src/mixedbread/types/vector_stores/file_list_params.py +++ b/src/mixedbread/types/vector_stores/file_list_params.py @@ -2,12 +2,13 @@ from __future__ import annotations -from typing import List, Optional -from typing_extensions import TypedDict +from typing import List, Union, Iterable, Optional +from typing_extensions import TypeAlias, TypedDict from .vector_store_file_status import VectorStoreFileStatus +from ..shared_params.search_filter_condition import SearchFilterCondition -__all__ = ["FileListParams"] +__all__ = ["FileListParams", "MetadataFilter", "MetadataFilterUnionMember2"] class FileListParams(TypedDict, total=False): @@ -31,3 +32,13 @@ class FileListParams(TypedDict, total=False): statuses: Optional[List[VectorStoreFileStatus]] """Status to filter by""" + + metadata_filter: Optional[MetadataFilter] + """Metadata filter to apply to the query""" + + +MetadataFilterUnionMember2: TypeAlias = Union["SearchFilter", SearchFilterCondition] + +MetadataFilter: TypeAlias = Union["SearchFilter", SearchFilterCondition, Iterable[MetadataFilterUnionMember2]] + +from ..shared_params.search_filter import SearchFilter diff --git a/src/mixedbread/types/vector_stores/file_list_response.py b/src/mixedbread/types/vector_stores/file_list_response.py new file mode 100644 index 00000000..252d1c93 --- /dev/null +++ b/src/mixedbread/types/vector_stores/file_list_response.py @@ -0,0 +1,69 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from typing_extensions import Literal + +from ..._models import BaseModel +from .vector_store_file import VectorStoreFile + +__all__ = ["FileListResponse", "Pagination"] + + +class Pagination(BaseModel): + has_more: bool + """ + Contextual direction-aware flag: True if more items exist in the requested + pagination direction. For 'after': more items after this page. For 'before': + more items before this page. + """ + + first_cursor: Optional[str] = None + """Cursor of the first item in this page. + + Use for backward pagination. None if page is empty. + """ + + last_cursor: Optional[str] = None + """Cursor of the last item in this page. + + Use for forward pagination. None if page is empty. + """ + + total: Optional[int] = None + """Total number of items available across all pages. + + Only included when include_total=true was requested. Expensive operation - use + sparingly. + """ + + +class FileListResponse(BaseModel): + pagination: Pagination + """Response model for cursor-based pagination. + + Examples: Forward pagination response: { "has_more": true, "first_cursor": + "eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0zMSIsImlkIjoiYWJjMTIzIn0=", "last_cursor": + "eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0zMCIsImlkIjoieHl6Nzg5In0=", "total": null } + + Final page response: + { + "has_more": false, + "first_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0yOSIsImlkIjoibGFzdDEyMyJ9", + "last_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0yOCIsImlkIjoiZmluYWw0NTYifQ==", + "total": 42 + } + + Empty results: + { + "has_more": false, + "first_cursor": null, + "last_cursor": null, + "total": 0 + } + """ + + object: Optional[Literal["list"]] = None + """The object type of the response""" + + data: List[VectorStoreFile] + """The list of vector store files""" diff --git a/tests/api_resources/vector_stores/test_files.py b/tests/api_resources/vector_stores/test_files.py index 13922a78..15a1c34b 100644 --- a/tests/api_resources/vector_stores/test_files.py +++ b/tests/api_resources/vector_stores/test_files.py @@ -9,9 +9,9 @@ from mixedbread import Mixedbread, AsyncMixedbread from tests.utils import assert_matches_type -from mixedbread.pagination import SyncCursor, AsyncCursor from mixedbread.types.vector_stores import ( VectorStoreFile, + FileListResponse, FileDeleteResponse, FileSearchResponse, ) @@ -143,7 +143,7 @@ def test_method_list(self, client: Mixedbread) -> None: file = client.vector_stores.files.list( vector_store_identifier="vector_store_identifier", ) - assert_matches_type(SyncCursor[VectorStoreFile], file, path=["response"]) + assert_matches_type(FileListResponse, file, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: Mixedbread) -> None: @@ -153,9 +153,14 @@ def test_method_list_with_all_params(self, client: Mixedbread) -> None: after="eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0zMVQyMzo1OTo1OS4wMDBaIiwiaWQiOiJhYmMxMjMifQ==", before="eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0zMVQyMzo1OTo1OS4wMDBaIiwiaWQiOiJhYmMxMjMifQ==", include_total=False, - statuses=["pending", "in_progress"], + statuses=["pending"], + metadata_filter={ + "all": [], + "any": [], + "none": [], + }, ) - assert_matches_type(SyncCursor[VectorStoreFile], file, path=["response"]) + assert_matches_type(FileListResponse, file, path=["response"]) @parametrize def test_raw_response_list(self, client: Mixedbread) -> None: @@ -166,7 +171,7 @@ def test_raw_response_list(self, client: Mixedbread) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(SyncCursor[VectorStoreFile], file, path=["response"]) + assert_matches_type(FileListResponse, file, path=["response"]) @parametrize def test_streaming_response_list(self, client: Mixedbread) -> None: @@ -177,7 +182,7 @@ def test_streaming_response_list(self, client: Mixedbread) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = response.parse() - assert_matches_type(SyncCursor[VectorStoreFile], file, path=["response"]) + assert_matches_type(FileListResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True @@ -423,7 +428,7 @@ async def test_method_list(self, async_client: AsyncMixedbread) -> None: file = await async_client.vector_stores.files.list( vector_store_identifier="vector_store_identifier", ) - assert_matches_type(AsyncCursor[VectorStoreFile], file, path=["response"]) + assert_matches_type(FileListResponse, file, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncMixedbread) -> None: @@ -433,9 +438,14 @@ async def test_method_list_with_all_params(self, async_client: AsyncMixedbread) after="eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0zMVQyMzo1OTo1OS4wMDBaIiwiaWQiOiJhYmMxMjMifQ==", before="eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0zMVQyMzo1OTo1OS4wMDBaIiwiaWQiOiJhYmMxMjMifQ==", include_total=False, - statuses=["pending", "in_progress"], + statuses=["pending"], + metadata_filter={ + "all": [], + "any": [], + "none": [], + }, ) - assert_matches_type(AsyncCursor[VectorStoreFile], file, path=["response"]) + assert_matches_type(FileListResponse, file, path=["response"]) @parametrize async def test_raw_response_list(self, async_client: AsyncMixedbread) -> None: @@ -446,7 +456,7 @@ async def test_raw_response_list(self, async_client: AsyncMixedbread) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(AsyncCursor[VectorStoreFile], file, path=["response"]) + assert_matches_type(FileListResponse, file, path=["response"]) @parametrize async def test_streaming_response_list(self, async_client: AsyncMixedbread) -> None: @@ -457,7 +467,7 @@ async def test_streaming_response_list(self, async_client: AsyncMixedbread) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" file = await response.parse() - assert_matches_type(AsyncCursor[VectorStoreFile], file, path=["response"]) + assert_matches_type(FileListResponse, file, path=["response"]) assert cast(Any, response.is_closed) is True From e7a9076d884c88bc18d0325566f5f4fa008827c7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 11 Aug 2025 07:35:24 +0000 Subject: [PATCH 2/2] release: 0.23.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 8 ++++++++ pyproject.toml | 2 +- src/mixedbread/_version.py | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3f63a672..7f3f5c84 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.22.1" + ".": "0.23.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8314ff8b..186715c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.23.0 (2025-08-11) + +Full Changelog: [v0.22.1...v0.23.0](https://github.com/mixedbread-ai/mixedbread-python/compare/v0.22.1...v0.23.0) + +### Features + +* **api:** update via SDK Studio ([a3e3b23](https://github.com/mixedbread-ai/mixedbread-python/commit/a3e3b23a5e9c95daaf19d1beb84a07a9a61bf2f3)) + ## 0.22.1 (2025-08-09) Full Changelog: [v0.22.0...v0.22.1](https://github.com/mixedbread-ai/mixedbread-python/compare/v0.22.0...v0.22.1) diff --git a/pyproject.toml b/pyproject.toml index 14fac4d6..a3533921 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "mixedbread" -version = "0.22.1" +version = "0.23.0" description = "The official Python library for the Mixedbread API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/mixedbread/_version.py b/src/mixedbread/_version.py index fc0f2056..4927e510 100644 --- a/src/mixedbread/_version.py +++ b/src/mixedbread/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "mixedbread" -__version__ = "0.22.1" # x-release-please-version +__version__ = "0.23.0" # x-release-please-version