diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index ce5e5c7c..157f0355 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.35.0"
+ ".": "0.36.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index d8c421cd..2373becf 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 61
+configured_endpoints: 62
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mixedbread%2Fmixedbread-d4c4a6e0d99b371dc5e84a63cf447770fc684d6a0650b2e36013404245a5876b.yml
openapi_spec_hash: 9d377ce6164438d3207d8a50c954a9cd
-config_hash: 2de40c343cf7b242d5925e3405ee8908
+config_hash: 1f4b314dbc7ae3afe6d669e36217b842
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 49bd5fbb..26f7271c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.36.0 (2025-10-30)
+
+Full Changelog: [v0.35.0...v0.36.0](https://github.com/mixedbread-ai/mixedbread-python/compare/v0.35.0...v0.36.0)
+
+### Features
+
+* **api:** update via SDK Studio ([979a334](https://github.com/mixedbread-ai/mixedbread-python/commit/979a33419c7700c2e20c6df2cd532249517a0a00))
+
## 0.35.0 (2025-10-30)
Full Changelog: [v0.34.0...v0.35.0](https://github.com/mixedbread-ai/mixedbread-python/compare/v0.34.0...v0.35.0)
diff --git a/api.md b/api.md
index ba725e0b..664fa3c1 100644
--- a/api.md
+++ b/api.md
@@ -86,6 +86,7 @@ from mixedbread.types import (
Store,
StoreChunkSearchOptions,
StoreDeleteResponse,
+ StoreMetadataFacetsResponse,
StoreQuestionAnsweringResponse,
StoreSearchResponse,
)
@@ -98,6 +99,7 @@ Methods:
- client.stores.update(store_identifier, \*\*params) -> Store
- client.stores.list(\*\*params) -> SyncCursor[Store]
- client.stores.delete(store_identifier) -> StoreDeleteResponse
+- client.stores.metadata_facets(store_identifier, \*\*params) -> StoreMetadataFacetsResponse
- client.stores.question_answering(\*\*params) -> StoreQuestionAnsweringResponse
- client.stores.search(\*\*params) -> StoreSearchResponse
diff --git a/pyproject.toml b/pyproject.toml
index cc1d73b6..aee7303a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "mixedbread"
-version = "0.35.0"
+version = "0.36.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 372ffb33..90e190d2 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.35.0" # x-release-please-version
+__version__ = "0.36.0" # x-release-please-version
diff --git a/src/mixedbread/resources/stores/stores.py b/src/mixedbread/resources/stores/stores.py
index a2128963..f5f00bc5 100644
--- a/src/mixedbread/resources/stores/stores.py
+++ b/src/mixedbread/resources/stores/stores.py
@@ -19,6 +19,7 @@
store_create_params,
store_search_params,
store_update_params,
+ store_metadata_facets_params,
store_question_answering_params,
)
from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
@@ -37,6 +38,7 @@
from ...types.expires_after_param import ExpiresAfterParam
from ...types.store_delete_response import StoreDeleteResponse
from ...types.store_search_response import StoreSearchResponse
+from ...types.store_metadata_facets_response import StoreMetadataFacetsResponse
from ...types.store_chunk_search_options_param import StoreChunkSearchOptionsParam
from ...types.store_question_answering_response import StoreQuestionAnsweringResponse
@@ -341,6 +343,54 @@ def delete(
cast_to=StoreDeleteResponse,
)
+ def metadata_facets(
+ self,
+ store_identifier: str,
+ *,
+ filters: Optional[store_metadata_facets_params.Filters] | Omit = omit,
+ facets: Optional[SequenceNotStr[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,
+ ) -> StoreMetadataFacetsResponse:
+ """
+ Get metadata facets
+
+ Args:
+ store_identifier: The ID or name of the store
+
+ filters: Optional filter conditions
+
+ facets: Optional list of facets to return. Use dot for nested fields.
+
+ 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 store_identifier:
+ raise ValueError(f"Expected a non-empty value for `store_identifier` but received {store_identifier!r}")
+ return self._post(
+ f"/v1/stores/{store_identifier}/metadata-facets",
+ body=maybe_transform(
+ {
+ "filters": filters,
+ "facets": facets,
+ },
+ store_metadata_facets_params.StoreMetadataFacetsParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=StoreMetadataFacetsResponse,
+ )
+
def question_answering(
self,
*,
@@ -784,6 +834,54 @@ async def delete(
cast_to=StoreDeleteResponse,
)
+ async def metadata_facets(
+ self,
+ store_identifier: str,
+ *,
+ filters: Optional[store_metadata_facets_params.Filters] | Omit = omit,
+ facets: Optional[SequenceNotStr[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,
+ ) -> StoreMetadataFacetsResponse:
+ """
+ Get metadata facets
+
+ Args:
+ store_identifier: The ID or name of the store
+
+ filters: Optional filter conditions
+
+ facets: Optional list of facets to return. Use dot for nested fields.
+
+ 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 store_identifier:
+ raise ValueError(f"Expected a non-empty value for `store_identifier` but received {store_identifier!r}")
+ return await self._post(
+ f"/v1/stores/{store_identifier}/metadata-facets",
+ body=await async_maybe_transform(
+ {
+ "filters": filters,
+ "facets": facets,
+ },
+ store_metadata_facets_params.StoreMetadataFacetsParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=StoreMetadataFacetsResponse,
+ )
+
async def question_answering(
self,
*,
@@ -948,6 +1046,9 @@ def __init__(self, stores: StoresResource) -> None:
self.delete = to_raw_response_wrapper(
stores.delete,
)
+ self.metadata_facets = to_raw_response_wrapper(
+ stores.metadata_facets,
+ )
self.question_answering = to_raw_response_wrapper(
stores.question_answering,
)
@@ -979,6 +1080,9 @@ def __init__(self, stores: AsyncStoresResource) -> None:
self.delete = async_to_raw_response_wrapper(
stores.delete,
)
+ self.metadata_facets = async_to_raw_response_wrapper(
+ stores.metadata_facets,
+ )
self.question_answering = async_to_raw_response_wrapper(
stores.question_answering,
)
@@ -1010,6 +1114,9 @@ def __init__(self, stores: StoresResource) -> None:
self.delete = to_streamed_response_wrapper(
stores.delete,
)
+ self.metadata_facets = to_streamed_response_wrapper(
+ stores.metadata_facets,
+ )
self.question_answering = to_streamed_response_wrapper(
stores.question_answering,
)
@@ -1041,6 +1148,9 @@ def __init__(self, stores: AsyncStoresResource) -> None:
self.delete = async_to_streamed_response_wrapper(
stores.delete,
)
+ self.metadata_facets = async_to_streamed_response_wrapper(
+ stores.metadata_facets,
+ )
self.question_answering = async_to_streamed_response_wrapper(
stores.question_answering,
)
diff --git a/src/mixedbread/types/__init__.py b/src/mixedbread/types/__init__.py
index 3ec3253b..20bcd899 100644
--- a/src/mixedbread/types/__init__.py
+++ b/src/mixedbread/types/__init__.py
@@ -53,8 +53,10 @@
from .scored_audio_url_input_chunk import ScoredAudioURLInputChunk as ScoredAudioURLInputChunk
from .scored_image_url_input_chunk import ScoredImageURLInputChunk as ScoredImageURLInputChunk
from .scored_video_url_input_chunk import ScoredVideoURLInputChunk as ScoredVideoURLInputChunk
+from .store_metadata_facets_params import StoreMetadataFacetsParams as StoreMetadataFacetsParams
from .vector_store_delete_response import VectorStoreDeleteResponse as VectorStoreDeleteResponse
from .vector_store_search_response import VectorStoreSearchResponse as VectorStoreSearchResponse
+from .store_metadata_facets_response import StoreMetadataFacetsResponse as StoreMetadataFacetsResponse
from .store_question_answering_params import StoreQuestionAnsweringParams as StoreQuestionAnsweringParams
from .store_chunk_search_options_param import StoreChunkSearchOptionsParam as StoreChunkSearchOptionsParam
from .store_question_answering_response import StoreQuestionAnsweringResponse as StoreQuestionAnsweringResponse
diff --git a/src/mixedbread/types/store_metadata_facets_params.py b/src/mixedbread/types/store_metadata_facets_params.py
new file mode 100644
index 00000000..e1b87603
--- /dev/null
+++ b/src/mixedbread/types/store_metadata_facets_params.py
@@ -0,0 +1,26 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union, Iterable, Optional
+from typing_extensions import TypeAlias, TypedDict
+
+from .._types import SequenceNotStr
+from .shared_params.search_filter_condition import SearchFilterCondition
+
+__all__ = ["StoreMetadataFacetsParams", "Filters", "FiltersUnionMember2"]
+
+
+class StoreMetadataFacetsParams(TypedDict, total=False):
+ filters: Optional[Filters]
+ """Optional filter conditions"""
+
+ facets: Optional[SequenceNotStr[str]]
+ """Optional list of facets to return. Use dot for nested fields."""
+
+
+FiltersUnionMember2: TypeAlias = Union["SearchFilter", SearchFilterCondition]
+
+Filters: TypeAlias = Union["SearchFilter", SearchFilterCondition, Iterable[FiltersUnionMember2]]
+
+from .shared_params.search_filter import SearchFilter
diff --git a/src/mixedbread/types/store_metadata_facets_response.py b/src/mixedbread/types/store_metadata_facets_response.py
new file mode 100644
index 00000000..989562c4
--- /dev/null
+++ b/src/mixedbread/types/store_metadata_facets_response.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict
+
+from .._models import BaseModel
+
+__all__ = ["StoreMetadataFacetsResponse"]
+
+
+class StoreMetadataFacetsResponse(BaseModel):
+ facets: Dict[str, Dict[str, object]]
+ """Metadata facets"""
diff --git a/tests/api_resources/test_stores.py b/tests/api_resources/test_stores.py
index 180773e7..895c5494 100644
--- a/tests/api_resources/test_stores.py
+++ b/tests/api_resources/test_stores.py
@@ -13,6 +13,7 @@
Store,
StoreDeleteResponse,
StoreSearchResponse,
+ StoreMetadataFacetsResponse,
StoreQuestionAnsweringResponse,
)
from mixedbread.pagination import SyncCursor, AsyncCursor
@@ -228,6 +229,90 @@ def test_path_params_delete(self, client: Mixedbread) -> None:
"",
)
+ @parametrize
+ def test_method_metadata_facets(self, client: Mixedbread) -> None:
+ store = client.stores.metadata_facets(
+ store_identifier="store_identifier",
+ )
+ assert_matches_type(StoreMetadataFacetsResponse, store, path=["response"])
+
+ @parametrize
+ def test_method_metadata_facets_with_all_params(self, client: Mixedbread) -> None:
+ store = client.stores.metadata_facets(
+ store_identifier="store_identifier",
+ filters={
+ "all": [
+ {
+ "key": "price",
+ "value": "100",
+ "operator": "gt",
+ },
+ {
+ "key": "color",
+ "value": "red",
+ "operator": "eq",
+ },
+ ],
+ "any": [
+ {
+ "key": "price",
+ "value": "100",
+ "operator": "gt",
+ },
+ {
+ "key": "color",
+ "value": "red",
+ "operator": "eq",
+ },
+ ],
+ "none": [
+ {
+ "key": "price",
+ "value": "100",
+ "operator": "gt",
+ },
+ {
+ "key": "color",
+ "value": "red",
+ "operator": "eq",
+ },
+ ],
+ },
+ facets=["string"],
+ )
+ assert_matches_type(StoreMetadataFacetsResponse, store, path=["response"])
+
+ @parametrize
+ def test_raw_response_metadata_facets(self, client: Mixedbread) -> None:
+ response = client.stores.with_raw_response.metadata_facets(
+ store_identifier="store_identifier",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ store = response.parse()
+ assert_matches_type(StoreMetadataFacetsResponse, store, path=["response"])
+
+ @parametrize
+ def test_streaming_response_metadata_facets(self, client: Mixedbread) -> None:
+ with client.stores.with_streaming_response.metadata_facets(
+ store_identifier="store_identifier",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ store = response.parse()
+ assert_matches_type(StoreMetadataFacetsResponse, store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_metadata_facets(self, client: Mixedbread) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `store_identifier` but received ''"):
+ client.stores.with_raw_response.metadata_facets(
+ store_identifier="",
+ )
+
@parametrize
def test_method_question_answering(self, client: Mixedbread) -> None:
store = client.stores.question_answering(
@@ -619,6 +704,90 @@ async def test_path_params_delete(self, async_client: AsyncMixedbread) -> None:
"",
)
+ @parametrize
+ async def test_method_metadata_facets(self, async_client: AsyncMixedbread) -> None:
+ store = await async_client.stores.metadata_facets(
+ store_identifier="store_identifier",
+ )
+ assert_matches_type(StoreMetadataFacetsResponse, store, path=["response"])
+
+ @parametrize
+ async def test_method_metadata_facets_with_all_params(self, async_client: AsyncMixedbread) -> None:
+ store = await async_client.stores.metadata_facets(
+ store_identifier="store_identifier",
+ filters={
+ "all": [
+ {
+ "key": "price",
+ "value": "100",
+ "operator": "gt",
+ },
+ {
+ "key": "color",
+ "value": "red",
+ "operator": "eq",
+ },
+ ],
+ "any": [
+ {
+ "key": "price",
+ "value": "100",
+ "operator": "gt",
+ },
+ {
+ "key": "color",
+ "value": "red",
+ "operator": "eq",
+ },
+ ],
+ "none": [
+ {
+ "key": "price",
+ "value": "100",
+ "operator": "gt",
+ },
+ {
+ "key": "color",
+ "value": "red",
+ "operator": "eq",
+ },
+ ],
+ },
+ facets=["string"],
+ )
+ assert_matches_type(StoreMetadataFacetsResponse, store, path=["response"])
+
+ @parametrize
+ async def test_raw_response_metadata_facets(self, async_client: AsyncMixedbread) -> None:
+ response = await async_client.stores.with_raw_response.metadata_facets(
+ store_identifier="store_identifier",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ store = await response.parse()
+ assert_matches_type(StoreMetadataFacetsResponse, store, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_metadata_facets(self, async_client: AsyncMixedbread) -> None:
+ async with async_client.stores.with_streaming_response.metadata_facets(
+ store_identifier="store_identifier",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ store = await response.parse()
+ assert_matches_type(StoreMetadataFacetsResponse, store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_metadata_facets(self, async_client: AsyncMixedbread) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `store_identifier` but received ''"):
+ await async_client.stores.with_raw_response.metadata_facets(
+ store_identifier="",
+ )
+
@parametrize
async def test_method_question_answering(self, async_client: AsyncMixedbread) -> None:
store = await async_client.stores.question_answering(