diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index f81bf992..f04d0896 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.31.0"
+ ".": "0.32.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 193855ae..1b0430f8 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 49
+configured_endpoints: 61
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mixedbread%2Fmixedbread-34b8fc657696023cc3a74eee6febe0d2fc0decda668f874bfa42abe6222d8566.yml
openapi_spec_hash: dcd015b362c3fcb4ef449606a8027873
-config_hash: a2549e1f1923904c8cee4ea4f5ff58e1
+config_hash: 2de40c343cf7b242d5925e3405ee8908
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d0f35722..1a2bac45 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.32.0 (2025-10-01)
+
+Full Changelog: [v0.31.0...v0.32.0](https://github.com/mixedbread-ai/mixedbread-python/compare/v0.31.0...v0.32.0)
+
+### Features
+
+* **api:** update via SDK Studio ([cdca00d](https://github.com/mixedbread-ai/mixedbread-python/commit/cdca00d9f31579e66e3992cd08e43aa70a9079d1))
+
## 0.31.0 (2025-10-01)
Full Changelog: [v0.30.0...v0.31.0](https://github.com/mixedbread-ai/mixedbread-python/compare/v0.30.0...v0.31.0)
diff --git a/README.md b/README.md
index b9c96e63..ade28bb0 100644
--- a/README.md
+++ b/README.md
@@ -34,8 +34,8 @@ client = Mixedbread(
environment="development",
)
-vector_store = client.vector_stores.create()
-print(vector_store.id)
+store = client.stores.create()
+print(store.id)
```
While you can provide an `api_key` keyword argument,
@@ -60,8 +60,8 @@ client = AsyncMixedbread(
async def main() -> None:
- vector_store = await client.vector_stores.create()
- print(vector_store.id)
+ store = await client.stores.create()
+ print(store.id)
asyncio.run(main())
@@ -93,8 +93,8 @@ async def main() -> None:
api_key="My API Key",
http_client=DefaultAioHttpClient(),
) as client:
- vector_store = await client.vector_stores.create()
- print(vector_store.id)
+ store = await client.stores.create()
+ print(store.id)
asyncio.run(main())
@@ -120,12 +120,12 @@ from mixedbread import Mixedbread
client = Mixedbread()
-all_vector_stores = []
+all_stores = []
# Automatically fetches more pages as needed.
-for vector_store in client.vector_stores.list():
- # Do something with vector_store here
- all_vector_stores.append(vector_store)
-print(all_vector_stores)
+for store in client.stores.list():
+ # Do something with store here
+ all_stores.append(store)
+print(all_stores)
```
Or, asynchronously:
@@ -138,11 +138,11 @@ client = AsyncMixedbread()
async def main() -> None:
- all_vector_stores = []
+ all_stores = []
# Iterate through items across all pages, issuing requests as needed.
- async for vector_store in client.vector_stores.list():
- all_vector_stores.append(vector_store)
- print(all_vector_stores)
+ async for store in client.stores.list():
+ all_stores.append(store)
+ print(all_stores)
asyncio.run(main())
@@ -151,7 +151,7 @@ asyncio.run(main())
Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
```python
-first_page = await client.vector_stores.list()
+first_page = await client.stores.list()
if first_page.has_next_page():
print(f"will fetch next page using these details: {first_page.next_page_info()}")
next_page = await first_page.get_next_page()
@@ -163,11 +163,11 @@ if first_page.has_next_page():
Or just work directly with the returned data:
```python
-first_page = await client.vector_stores.list()
+first_page = await client.stores.list()
print(f"next page cursor: {first_page.pagination.last_cursor}") # => "next page cursor: ..."
-for vector_store in first_page.data:
- print(vector_store.id)
+for store in first_page.data:
+ print(store.id)
# Remove `await` for non-async usage.
```
@@ -181,10 +181,10 @@ from mixedbread import Mixedbread
client = Mixedbread()
-vector_store = client.vector_stores.create(
+store = client.stores.create(
expires_after={},
)
-print(vector_store.expires_after)
+print(store.expires_after)
```
## File uploads
@@ -220,7 +220,7 @@ from mixedbread import Mixedbread
client = Mixedbread()
try:
- client.vector_stores.create()
+ client.stores.create()
except mixedbread.APIConnectionError as e:
print("The server could not be reached")
print(e.__cause__) # an underlying Exception, likely raised within httpx.
@@ -263,7 +263,7 @@ client = Mixedbread(
)
# Or, configure per-request:
-client.with_options(max_retries=5).vector_stores.create()
+client.with_options(max_retries=5).stores.create()
```
### Timeouts
@@ -286,7 +286,7 @@ client = Mixedbread(
)
# Override per-request:
-client.with_options(timeout=5.0).vector_stores.create()
+client.with_options(timeout=5.0).stores.create()
```
On timeout, an `APITimeoutError` is thrown.
@@ -327,11 +327,11 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to
from mixedbread import Mixedbread
client = Mixedbread()
-response = client.vector_stores.with_raw_response.create()
+response = client.stores.with_raw_response.create()
print(response.headers.get('X-My-Header'))
-vector_store = response.parse() # get the object that `vector_stores.create()` would have returned
-print(vector_store.id)
+store = response.parse() # get the object that `stores.create()` would have returned
+print(store.id)
```
These methods return an [`APIResponse`](https://github.com/mixedbread-ai/mixedbread-python/tree/main/src/mixedbread/_response.py) object.
@@ -345,7 +345,7 @@ The above interface eagerly reads the full response body when you make the reque
To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.
```python
-with client.vector_stores.with_streaming_response.create() as response:
+with client.stores.with_streaming_response.create() as response:
print(response.headers.get("X-My-Header"))
for line in response.iter_lines():
diff --git a/api.md b/api.md
index 2a054ea2..ba725e0b 100644
--- a/api.md
+++ b/api.md
@@ -77,6 +77,53 @@ Methods:
- client.vector_stores.files.delete(file_id, \*, vector_store_identifier) -> FileDeleteResponse
- client.vector_stores.files.search(\*\*params) -> FileSearchResponse
+# Stores
+
+Types:
+
+```python
+from mixedbread.types import (
+ Store,
+ StoreChunkSearchOptions,
+ StoreDeleteResponse,
+ StoreQuestionAnsweringResponse,
+ StoreSearchResponse,
+)
+```
+
+Methods:
+
+- client.stores.create(\*\*params) -> Store
+- client.stores.retrieve(store_identifier) -> Store
+- client.stores.update(store_identifier, \*\*params) -> Store
+- client.stores.list(\*\*params) -> SyncCursor[Store]
+- client.stores.delete(store_identifier) -> StoreDeleteResponse
+- client.stores.question_answering(\*\*params) -> StoreQuestionAnsweringResponse
+- client.stores.search(\*\*params) -> StoreSearchResponse
+
+## Files
+
+Types:
+
+```python
+from mixedbread.types.stores import (
+ ScoredStoreFile,
+ StoreFileStatus,
+ StoreFile,
+ FileListResponse,
+ FileDeleteResponse,
+ FileSearchResponse,
+)
+```
+
+Methods:
+
+- client.stores.files.create(store_identifier, \*\*params) -> StoreFile
+- client.stores.files.retrieve(file_id, \*, store_identifier, \*\*params) -> StoreFile
+- client.stores.files.list(store_identifier, \*\*params) -> FileListResponse
+- client.stores.files.delete(file_id, \*, store_identifier) -> FileDeleteResponse
+- client.stores.files.search(\*\*params) -> FileSearchResponse
+
# Parsing
## Jobs
diff --git a/pyproject.toml b/pyproject.toml
index e3bc88a2..f9ec7480 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "mixedbread"
-version = "0.31.0"
+version = "0.32.0"
description = "The official Python library for the Mixedbread API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/mixedbread/_client.py b/src/mixedbread/_client.py
index 31462225..0a01cdd2 100644
--- a/src/mixedbread/_client.py
+++ b/src/mixedbread/_client.py
@@ -47,6 +47,7 @@
AsyncAPIClient,
make_request_options,
)
+from .resources.stores import stores
from .resources.parsing import parsing
from .types.info_response import InfoResponse
from .resources.extractions import extractions
@@ -77,6 +78,7 @@
class Mixedbread(SyncAPIClient):
vector_stores: vector_stores.VectorStoresResource
+ stores: stores.StoresResource
parsing: parsing.ParsingResource
files: files.FilesResource
extractions: extractions.ExtractionsResource
@@ -166,6 +168,7 @@ def __init__(
)
self.vector_stores = vector_stores.VectorStoresResource(self)
+ self.stores = stores.StoresResource(self)
self.parsing = parsing.ParsingResource(self)
self.files = files.FilesResource(self)
self.extractions = extractions.ExtractionsResource(self)
@@ -440,6 +443,7 @@ def _make_status_error(
class AsyncMixedbread(AsyncAPIClient):
vector_stores: vector_stores.AsyncVectorStoresResource
+ stores: stores.AsyncStoresResource
parsing: parsing.AsyncParsingResource
files: files.AsyncFilesResource
extractions: extractions.AsyncExtractionsResource
@@ -529,6 +533,7 @@ def __init__(
)
self.vector_stores = vector_stores.AsyncVectorStoresResource(self)
+ self.stores = stores.AsyncStoresResource(self)
self.parsing = parsing.AsyncParsingResource(self)
self.files = files.AsyncFilesResource(self)
self.extractions = extractions.AsyncExtractionsResource(self)
@@ -804,6 +809,7 @@ def _make_status_error(
class MixedbreadWithRawResponse:
def __init__(self, client: Mixedbread) -> None:
self.vector_stores = vector_stores.VectorStoresResourceWithRawResponse(client.vector_stores)
+ self.stores = stores.StoresResourceWithRawResponse(client.stores)
self.parsing = parsing.ParsingResourceWithRawResponse(client.parsing)
self.files = files.FilesResourceWithRawResponse(client.files)
self.extractions = extractions.ExtractionsResourceWithRawResponse(client.extractions)
@@ -826,6 +832,7 @@ def __init__(self, client: Mixedbread) -> None:
class AsyncMixedbreadWithRawResponse:
def __init__(self, client: AsyncMixedbread) -> None:
self.vector_stores = vector_stores.AsyncVectorStoresResourceWithRawResponse(client.vector_stores)
+ self.stores = stores.AsyncStoresResourceWithRawResponse(client.stores)
self.parsing = parsing.AsyncParsingResourceWithRawResponse(client.parsing)
self.files = files.AsyncFilesResourceWithRawResponse(client.files)
self.extractions = extractions.AsyncExtractionsResourceWithRawResponse(client.extractions)
@@ -848,6 +855,7 @@ def __init__(self, client: AsyncMixedbread) -> None:
class MixedbreadWithStreamedResponse:
def __init__(self, client: Mixedbread) -> None:
self.vector_stores = vector_stores.VectorStoresResourceWithStreamingResponse(client.vector_stores)
+ self.stores = stores.StoresResourceWithStreamingResponse(client.stores)
self.parsing = parsing.ParsingResourceWithStreamingResponse(client.parsing)
self.files = files.FilesResourceWithStreamingResponse(client.files)
self.extractions = extractions.ExtractionsResourceWithStreamingResponse(client.extractions)
@@ -870,6 +878,7 @@ def __init__(self, client: Mixedbread) -> None:
class AsyncMixedbreadWithStreamedResponse:
def __init__(self, client: AsyncMixedbread) -> None:
self.vector_stores = vector_stores.AsyncVectorStoresResourceWithStreamingResponse(client.vector_stores)
+ self.stores = stores.AsyncStoresResourceWithStreamingResponse(client.stores)
self.parsing = parsing.AsyncParsingResourceWithStreamingResponse(client.parsing)
self.files = files.AsyncFilesResourceWithStreamingResponse(client.files)
self.extractions = extractions.AsyncExtractionsResourceWithStreamingResponse(client.extractions)
diff --git a/src/mixedbread/_version.py b/src/mixedbread/_version.py
index fae94c2c..6c91f797 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.31.0" # x-release-please-version
+__version__ = "0.32.0" # x-release-please-version
diff --git a/src/mixedbread/resources/__init__.py b/src/mixedbread/resources/__init__.py
index 0b3e0954..368addbe 100644
--- a/src/mixedbread/resources/__init__.py
+++ b/src/mixedbread/resources/__init__.py
@@ -16,6 +16,14 @@
FilesResourceWithStreamingResponse,
AsyncFilesResourceWithStreamingResponse,
)
+from .stores import (
+ StoresResource,
+ AsyncStoresResource,
+ StoresResourceWithRawResponse,
+ AsyncStoresResourceWithRawResponse,
+ StoresResourceWithStreamingResponse,
+ AsyncStoresResourceWithStreamingResponse,
+)
from .parsing import (
ParsingResource,
AsyncParsingResource,
@@ -72,6 +80,12 @@
"AsyncVectorStoresResourceWithRawResponse",
"VectorStoresResourceWithStreamingResponse",
"AsyncVectorStoresResourceWithStreamingResponse",
+ "StoresResource",
+ "AsyncStoresResource",
+ "StoresResourceWithRawResponse",
+ "AsyncStoresResourceWithRawResponse",
+ "StoresResourceWithStreamingResponse",
+ "AsyncStoresResourceWithStreamingResponse",
"ParsingResource",
"AsyncParsingResource",
"ParsingResourceWithRawResponse",
diff --git a/src/mixedbread/resources/stores/__init__.py b/src/mixedbread/resources/stores/__init__.py
new file mode 100644
index 00000000..8ec1ec90
--- /dev/null
+++ b/src/mixedbread/resources/stores/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .files import (
+ FilesResource,
+ AsyncFilesResource,
+ FilesResourceWithRawResponse,
+ AsyncFilesResourceWithRawResponse,
+ FilesResourceWithStreamingResponse,
+ AsyncFilesResourceWithStreamingResponse,
+)
+from .stores import (
+ StoresResource,
+ AsyncStoresResource,
+ StoresResourceWithRawResponse,
+ AsyncStoresResourceWithRawResponse,
+ StoresResourceWithStreamingResponse,
+ AsyncStoresResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "FilesResource",
+ "AsyncFilesResource",
+ "FilesResourceWithRawResponse",
+ "AsyncFilesResourceWithRawResponse",
+ "FilesResourceWithStreamingResponse",
+ "AsyncFilesResourceWithStreamingResponse",
+ "StoresResource",
+ "AsyncStoresResource",
+ "StoresResourceWithRawResponse",
+ "AsyncStoresResourceWithRawResponse",
+ "StoresResourceWithStreamingResponse",
+ "AsyncStoresResourceWithStreamingResponse",
+]
diff --git a/src/mixedbread/resources/stores/files.py b/src/mixedbread/resources/stores/files.py
new file mode 100644
index 00000000..9fc14bb6
--- /dev/null
+++ b/src/mixedbread/resources/stores/files.py
@@ -0,0 +1,741 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import List, Union, Iterable, Optional
+
+import httpx
+
+from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
+from ..._utils import 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 ..._base_client import make_request_options
+from ...types.stores import file_list_params, file_create_params, file_search_params, file_retrieve_params
+from ...types.stores.store_file import StoreFile
+from ...types.stores.store_file_status import StoreFileStatus
+from ...types.stores.file_list_response import FileListResponse
+from ...types.stores.file_delete_response import FileDeleteResponse
+from ...types.stores.file_search_response import FileSearchResponse
+
+__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/mixedbread-ai/mixedbread-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/mixedbread-ai/mixedbread-python#with_streaming_response
+ """
+ return FilesResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ store_identifier: str,
+ *,
+ metadata: object | Omit = omit,
+ experimental: file_create_params.Experimental | Omit = omit,
+ file_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,
+ ) -> StoreFile:
+ """Upload a file to a store.
+
+ Args: store_identifier: The ID or name of the store.
+
+ file_add_params: The file
+ to add to the store.
+
+ Returns: VectorStoreFile: The uploaded file details.
+
+ Args:
+ store_identifier: The ID or name of the store
+
+ metadata: Optional metadata for the file
+
+ experimental: Strategy for adding the file
+
+ file_id: ID of the file to add
+
+ 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}/files",
+ body=maybe_transform(
+ {
+ "metadata": metadata,
+ "experimental": experimental,
+ "file_id": file_id,
+ },
+ file_create_params.FileCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=StoreFile,
+ )
+
+ def retrieve(
+ self,
+ file_id: str,
+ *,
+ store_identifier: str,
+ return_chunks: 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,
+ ) -> StoreFile:
+ """Get a file from a store.
+
+ Args: store_identifier: The ID or name of the store.
+
+ file_id: The ID or name of
+ the file. options: Get file options.
+
+ Returns: VectorStoreFile: The file details.
+
+ Args:
+ store_identifier: The ID or name of the store
+
+ file_id: The ID or name of the file
+
+ return_chunks: Whether to return the chunks for the 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 store_identifier:
+ raise ValueError(f"Expected a non-empty value for `store_identifier` but received {store_identifier!r}")
+ if not file_id:
+ raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
+ return self._get(
+ f"/v1/stores/{store_identifier}/files/{file_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform({"return_chunks": return_chunks}, file_retrieve_params.FileRetrieveParams),
+ ),
+ cast_to=StoreFile,
+ )
+
+ def list(
+ self,
+ store_identifier: str,
+ *,
+ limit: int | Omit = omit,
+ after: Optional[str] | Omit = omit,
+ before: Optional[str] | Omit = omit,
+ include_total: bool | Omit = omit,
+ statuses: Optional[List[StoreFileStatus]] | Omit = omit,
+ metadata_filter: Optional[file_list_params.MetadataFilter] | 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,
+ ) -> FileListResponse:
+ """
+ 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 and metadata filter
+
+ Returns: VectorStoreFileListResponse: Paginated list of vector store files
+
+ Args:
+ store_identifier: The ID or name of the store
+
+ limit: Maximum number of items to return per page (1-100)
+
+ after: Cursor for forward pagination - get items after this position. Use last_cursor
+ from previous response.
+
+ before: Cursor for backward pagination - get items before this position. Use
+ first_cursor from previous response.
+
+ include_total: Whether to include total count in response (expensive operation)
+
+ 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
+
+ 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}/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
+ ),
+ cast_to=FileListResponse,
+ )
+
+ def delete(
+ self,
+ file_id: str,
+ *,
+ store_identifier: 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,
+ ) -> FileDeleteResponse:
+ """Delete a file from a store.
+
+ Args: store_identifier: The ID or name of the store.
+
+ file_id: The ID or name of
+ the file to delete.
+
+ Returns: VectorStoreFileDeleted: The deleted file details.
+
+ Args:
+ store_identifier: The ID or name of the store
+
+ file_id: The ID or name of the file to delete
+
+ 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}")
+ if not file_id:
+ raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
+ return self._delete(
+ f"/v1/stores/{store_identifier}/files/{file_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FileDeleteResponse,
+ )
+
+ def search(
+ self,
+ *,
+ query: str,
+ store_identifiers: SequenceNotStr[str],
+ top_k: int | Omit = omit,
+ filters: Optional[file_search_params.Filters] | Omit = omit,
+ file_ids: Union[Iterable[object], SequenceNotStr[str], None] | Omit = omit,
+ search_options: file_search_params.SearchOptions | 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,
+ ) -> FileSearchResponse:
+ """
+ Search for files within a store based on semantic similarity.
+
+ Args: store_identifier: The ID or name of the store to search within
+ search_params: Search configuration including query text, pagination, and
+ filters
+
+ Returns: StoreFileSearchResponse: List of matching files with relevance scores
+
+ Args:
+ query: Search query text
+
+ store_identifiers: IDs or names of stores to search
+
+ top_k: Number of results to return
+
+ filters: Optional filter conditions
+
+ file_ids: Optional list of file IDs to filter chunks by (inclusion filter)
+
+ search_options: Search configuration options
+
+ 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
+ """
+ return self._post(
+ "/v1/stores/files/search",
+ body=maybe_transform(
+ {
+ "query": query,
+ "store_identifiers": store_identifiers,
+ "top_k": top_k,
+ "filters": filters,
+ "file_ids": file_ids,
+ "search_options": search_options,
+ },
+ file_search_params.FileSearchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FileSearchResponse,
+ )
+
+
+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/mixedbread-ai/mixedbread-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/mixedbread-ai/mixedbread-python#with_streaming_response
+ """
+ return AsyncFilesResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ store_identifier: str,
+ *,
+ metadata: object | Omit = omit,
+ experimental: file_create_params.Experimental | Omit = omit,
+ file_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,
+ ) -> StoreFile:
+ """Upload a file to a store.
+
+ Args: store_identifier: The ID or name of the store.
+
+ file_add_params: The file
+ to add to the store.
+
+ Returns: VectorStoreFile: The uploaded file details.
+
+ Args:
+ store_identifier: The ID or name of the store
+
+ metadata: Optional metadata for the file
+
+ experimental: Strategy for adding the file
+
+ file_id: ID of the file to add
+
+ 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}/files",
+ body=await async_maybe_transform(
+ {
+ "metadata": metadata,
+ "experimental": experimental,
+ "file_id": file_id,
+ },
+ file_create_params.FileCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=StoreFile,
+ )
+
+ async def retrieve(
+ self,
+ file_id: str,
+ *,
+ store_identifier: str,
+ return_chunks: 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,
+ ) -> StoreFile:
+ """Get a file from a store.
+
+ Args: store_identifier: The ID or name of the store.
+
+ file_id: The ID or name of
+ the file. options: Get file options.
+
+ Returns: VectorStoreFile: The file details.
+
+ Args:
+ store_identifier: The ID or name of the store
+
+ file_id: The ID or name of the file
+
+ return_chunks: Whether to return the chunks for the 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 store_identifier:
+ raise ValueError(f"Expected a non-empty value for `store_identifier` but received {store_identifier!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(
+ f"/v1/stores/{store_identifier}/files/{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(
+ {"return_chunks": return_chunks}, file_retrieve_params.FileRetrieveParams
+ ),
+ ),
+ cast_to=StoreFile,
+ )
+
+ async def list(
+ self,
+ store_identifier: str,
+ *,
+ limit: int | Omit = omit,
+ after: Optional[str] | Omit = omit,
+ before: Optional[str] | Omit = omit,
+ include_total: bool | Omit = omit,
+ statuses: Optional[List[StoreFileStatus]] | Omit = omit,
+ metadata_filter: Optional[file_list_params.MetadataFilter] | 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,
+ ) -> FileListResponse:
+ """
+ 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 and metadata filter
+
+ Returns: VectorStoreFileListResponse: Paginated list of vector store files
+
+ Args:
+ store_identifier: The ID or name of the store
+
+ limit: Maximum number of items to return per page (1-100)
+
+ after: Cursor for forward pagination - get items after this position. Use last_cursor
+ from previous response.
+
+ before: Cursor for backward pagination - get items before this position. Use
+ first_cursor from previous response.
+
+ include_total: Whether to include total count in response (expensive operation)
+
+ 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
+
+ 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}/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
+ ),
+ cast_to=FileListResponse,
+ )
+
+ async def delete(
+ self,
+ file_id: str,
+ *,
+ store_identifier: 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,
+ ) -> FileDeleteResponse:
+ """Delete a file from a store.
+
+ Args: store_identifier: The ID or name of the store.
+
+ file_id: The ID or name of
+ the file to delete.
+
+ Returns: VectorStoreFileDeleted: The deleted file details.
+
+ Args:
+ store_identifier: The ID or name of the store
+
+ file_id: The ID or name of the file to delete
+
+ 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}")
+ if not file_id:
+ raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}")
+ return await self._delete(
+ f"/v1/stores/{store_identifier}/files/{file_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FileDeleteResponse,
+ )
+
+ async def search(
+ self,
+ *,
+ query: str,
+ store_identifiers: SequenceNotStr[str],
+ top_k: int | Omit = omit,
+ filters: Optional[file_search_params.Filters] | Omit = omit,
+ file_ids: Union[Iterable[object], SequenceNotStr[str], None] | Omit = omit,
+ search_options: file_search_params.SearchOptions | 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,
+ ) -> FileSearchResponse:
+ """
+ Search for files within a store based on semantic similarity.
+
+ Args: store_identifier: The ID or name of the store to search within
+ search_params: Search configuration including query text, pagination, and
+ filters
+
+ Returns: StoreFileSearchResponse: List of matching files with relevance scores
+
+ Args:
+ query: Search query text
+
+ store_identifiers: IDs or names of stores to search
+
+ top_k: Number of results to return
+
+ filters: Optional filter conditions
+
+ file_ids: Optional list of file IDs to filter chunks by (inclusion filter)
+
+ search_options: Search configuration options
+
+ 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
+ """
+ return await self._post(
+ "/v1/stores/files/search",
+ body=await async_maybe_transform(
+ {
+ "query": query,
+ "store_identifiers": store_identifiers,
+ "top_k": top_k,
+ "filters": filters,
+ "file_ids": file_ids,
+ "search_options": search_options,
+ },
+ file_search_params.FileSearchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FileSearchResponse,
+ )
+
+
+class FilesResourceWithRawResponse:
+ def __init__(self, files: FilesResource) -> None:
+ self._files = files
+
+ self.create = to_raw_response_wrapper(
+ files.create,
+ )
+ 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.search = to_raw_response_wrapper(
+ files.search,
+ )
+
+
+class AsyncFilesResourceWithRawResponse:
+ def __init__(self, files: AsyncFilesResource) -> None:
+ self._files = files
+
+ self.create = async_to_raw_response_wrapper(
+ files.create,
+ )
+ 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.search = async_to_raw_response_wrapper(
+ files.search,
+ )
+
+
+class FilesResourceWithStreamingResponse:
+ def __init__(self, files: FilesResource) -> None:
+ self._files = files
+
+ self.create = to_streamed_response_wrapper(
+ files.create,
+ )
+ 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.search = to_streamed_response_wrapper(
+ files.search,
+ )
+
+
+class AsyncFilesResourceWithStreamingResponse:
+ def __init__(self, files: AsyncFilesResource) -> None:
+ self._files = files
+
+ self.create = async_to_streamed_response_wrapper(
+ files.create,
+ )
+ 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.search = async_to_streamed_response_wrapper(
+ files.search,
+ )
diff --git a/src/mixedbread/resources/stores/stores.py b/src/mixedbread/resources/stores/stores.py
new file mode 100644
index 00000000..a2128963
--- /dev/null
+++ b/src/mixedbread/resources/stores/stores.py
@@ -0,0 +1,1053 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union, Iterable, Optional
+
+import httpx
+
+from .files import (
+ FilesResource,
+ AsyncFilesResource,
+ FilesResourceWithRawResponse,
+ AsyncFilesResourceWithRawResponse,
+ FilesResourceWithStreamingResponse,
+ AsyncFilesResourceWithStreamingResponse,
+)
+from ...types import (
+ store_list_params,
+ store_create_params,
+ store_search_params,
+ store_update_params,
+ store_question_answering_params,
+)
+from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
+from ..._utils import 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 SyncCursor, AsyncCursor
+from ...types.store import Store
+from ..._base_client import AsyncPaginator, make_request_options
+from ...types.expires_after_param import ExpiresAfterParam
+from ...types.store_delete_response import StoreDeleteResponse
+from ...types.store_search_response import StoreSearchResponse
+from ...types.store_chunk_search_options_param import StoreChunkSearchOptionsParam
+from ...types.store_question_answering_response import StoreQuestionAnsweringResponse
+
+__all__ = ["StoresResource", "AsyncStoresResource"]
+
+
+class StoresResource(SyncAPIResource):
+ @cached_property
+ def files(self) -> FilesResource:
+ return FilesResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> StoresResourceWithRawResponse:
+ """
+ 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/mixedbread-ai/mixedbread-python#accessing-raw-response-data-eg-headers
+ """
+ return StoresResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> StoresResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/mixedbread-ai/mixedbread-python#with_streaming_response
+ """
+ return StoresResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ name: Optional[str] | Omit = omit,
+ description: Optional[str] | Omit = omit,
+ is_public: bool | Omit = omit,
+ expires_after: Optional[ExpiresAfterParam] | Omit = omit,
+ metadata: object | Omit = omit,
+ file_ids: 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,
+ ) -> Store:
+ """
+ Create a new vector store.
+
+ Args: vector_store_create: VectorStoreCreate object containing the name,
+ description, and metadata.
+
+ Returns: VectorStore: The response containing the created vector store details.
+
+ Args:
+ name: Name for the new store
+
+ description: Description of the store
+
+ is_public: Whether the store can be accessed by anyone with valid login credentials
+
+ expires_after: Represents an expiration policy for a store.
+
+ metadata: Optional metadata key-value pairs
+
+ file_ids: Optional list of file IDs
+
+ 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
+ """
+ return self._post(
+ "/v1/stores",
+ body=maybe_transform(
+ {
+ "name": name,
+ "description": description,
+ "is_public": is_public,
+ "expires_after": expires_after,
+ "metadata": metadata,
+ "file_ids": file_ids,
+ },
+ store_create_params.StoreCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Store,
+ )
+
+ def retrieve(
+ self,
+ store_identifier: 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,
+ ) -> Store:
+ """
+ Get a store by ID or name.
+
+ Args: store_identifier: The ID or name of the store to retrieve.
+
+ Returns: Store: The response containing the store details.
+
+ Args:
+ store_identifier: The ID or name of the store
+
+ 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._get(
+ f"/v1/stores/{store_identifier}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Store,
+ )
+
+ def update(
+ self,
+ store_identifier: str,
+ *,
+ name: Optional[str] | Omit = omit,
+ description: Optional[str] | Omit = omit,
+ is_public: Optional[bool] | Omit = omit,
+ expires_after: Optional[ExpiresAfterParam] | Omit = omit,
+ metadata: object | 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,
+ ) -> Store:
+ """
+ Update a store by ID or name.
+
+ Args: store_identifier: The ID or name of the store to update. store_update:
+ StoreCreate object containing the name, description, and metadata.
+
+ Returns: Store: The response containing the updated store details.
+
+ Args:
+ store_identifier: The ID or name of the store
+
+ name: New name for the store
+
+ description: New description
+
+ is_public: Whether the store can be accessed by anyone with valid login credentials
+
+ expires_after: Represents an expiration policy for a store.
+
+ metadata: Optional metadata key-value pairs
+
+ 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._put(
+ f"/v1/stores/{store_identifier}",
+ body=maybe_transform(
+ {
+ "name": name,
+ "description": description,
+ "is_public": is_public,
+ "expires_after": expires_after,
+ "metadata": metadata,
+ },
+ store_update_params.StoreUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Store,
+ )
+
+ def list(
+ self,
+ *,
+ limit: int | Omit = omit,
+ after: Optional[str] | Omit = omit,
+ before: Optional[str] | Omit = omit,
+ include_total: bool | Omit = omit,
+ q: 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,
+ ) -> SyncCursor[Store]:
+ """List all stores with optional search.
+
+ Args: pagination: The pagination options.
+
+ q: Optional search query to filter
+ vector stores.
+
+ Returns: StoreListResponse: The list of stores.
+
+ Args:
+ limit: Maximum number of items to return per page (1-100)
+
+ after: Cursor for forward pagination - get items after this position. Use last_cursor
+ from previous response.
+
+ before: Cursor for backward pagination - get items before this position. Use
+ first_cursor from previous response.
+
+ include_total: Whether to include total count in response (expensive operation)
+
+ q: Search query for fuzzy matching over name and description 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
+ """
+ return self._get_api_list(
+ "/v1/stores",
+ page=SyncCursor[Store],
+ 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,
+ "q": q,
+ },
+ store_list_params.StoreListParams,
+ ),
+ ),
+ model=Store,
+ )
+
+ def delete(
+ self,
+ store_identifier: 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,
+ ) -> StoreDeleteResponse:
+ """
+ Delete a store by ID or name.
+
+ Args: store_identifier: The ID or name of the store to delete.
+
+ Returns: Store: The response containing the deleted store details.
+
+ Args:
+ store_identifier: The ID or name of the store to delete
+
+ 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._delete(
+ f"/v1/stores/{store_identifier}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=StoreDeleteResponse,
+ )
+
+ def question_answering(
+ self,
+ *,
+ query: str | Omit = omit,
+ store_identifiers: SequenceNotStr[str],
+ top_k: int | Omit = omit,
+ filters: Optional[store_question_answering_params.Filters] | Omit = omit,
+ file_ids: Union[Iterable[object], SequenceNotStr[str], None] | Omit = omit,
+ search_options: StoreChunkSearchOptionsParam | Omit = omit,
+ stream: bool | Omit = omit,
+ qa_options: store_question_answering_params.QaOptions | 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,
+ ) -> StoreQuestionAnsweringResponse:
+ """Question answering
+
+ Args:
+ query: Question to answer.
+
+ If not provided, the question will be extracted from the
+ passed messages.
+
+ store_identifiers: IDs or names of stores to search
+
+ top_k: Number of results to return
+
+ filters: Optional filter conditions
+
+ file_ids: Optional list of file IDs to filter chunks by (inclusion filter)
+
+ search_options: Search configuration options
+
+ stream: Whether to stream the answer
+
+ qa_options: Question answering configuration options
+
+ 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
+ """
+ return self._post(
+ "/v1/stores/question-answering",
+ body=maybe_transform(
+ {
+ "query": query,
+ "store_identifiers": store_identifiers,
+ "top_k": top_k,
+ "filters": filters,
+ "file_ids": file_ids,
+ "search_options": search_options,
+ "stream": stream,
+ "qa_options": qa_options,
+ },
+ store_question_answering_params.StoreQuestionAnsweringParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=StoreQuestionAnsweringResponse,
+ )
+
+ def search(
+ self,
+ *,
+ query: str,
+ store_identifiers: SequenceNotStr[str],
+ top_k: int | Omit = omit,
+ filters: Optional[store_search_params.Filters] | Omit = omit,
+ file_ids: Union[Iterable[object], SequenceNotStr[str], None] | Omit = omit,
+ search_options: StoreChunkSearchOptionsParam | 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,
+ ) -> StoreSearchResponse:
+ """
+ Perform semantic search across store chunks.
+
+ This endpoint searches through store chunks using semantic similarity matching.
+ It supports complex search queries with filters and returns relevance-scored
+ results.
+
+ Args: search_params: Search configuration including: - query text or
+ embeddings - store_identifiers: List of store identifiers to search - file_ids:
+ Optional list of file IDs to filter chunks by (or tuple of list and condition
+ operator) - metadata filters - pagination parameters - sorting preferences
+ \\__state: API state dependency \\__ctx: Service context dependency
+
+ Returns: StoreSearchResponse containing: - List of matched chunks with relevance
+ scores - Pagination details including total result count
+
+ Raises: HTTPException (400): If search parameters are invalid HTTPException
+ (404): If no vector stores are found to search
+
+ Args:
+ query: Search query text
+
+ store_identifiers: IDs or names of stores to search
+
+ top_k: Number of results to return
+
+ filters: Optional filter conditions
+
+ file_ids: Optional list of file IDs to filter chunks by (inclusion filter)
+
+ search_options: Search configuration options
+
+ 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
+ """
+ return self._post(
+ "/v1/stores/search",
+ body=maybe_transform(
+ {
+ "query": query,
+ "store_identifiers": store_identifiers,
+ "top_k": top_k,
+ "filters": filters,
+ "file_ids": file_ids,
+ "search_options": search_options,
+ },
+ store_search_params.StoreSearchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=StoreSearchResponse,
+ )
+
+
+class AsyncStoresResource(AsyncAPIResource):
+ @cached_property
+ def files(self) -> AsyncFilesResource:
+ return AsyncFilesResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncStoresResourceWithRawResponse:
+ """
+ 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/mixedbread-ai/mixedbread-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncStoresResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncStoresResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/mixedbread-ai/mixedbread-python#with_streaming_response
+ """
+ return AsyncStoresResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ name: Optional[str] | Omit = omit,
+ description: Optional[str] | Omit = omit,
+ is_public: bool | Omit = omit,
+ expires_after: Optional[ExpiresAfterParam] | Omit = omit,
+ metadata: object | Omit = omit,
+ file_ids: 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,
+ ) -> Store:
+ """
+ Create a new vector store.
+
+ Args: vector_store_create: VectorStoreCreate object containing the name,
+ description, and metadata.
+
+ Returns: VectorStore: The response containing the created vector store details.
+
+ Args:
+ name: Name for the new store
+
+ description: Description of the store
+
+ is_public: Whether the store can be accessed by anyone with valid login credentials
+
+ expires_after: Represents an expiration policy for a store.
+
+ metadata: Optional metadata key-value pairs
+
+ file_ids: Optional list of file IDs
+
+ 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
+ """
+ return await self._post(
+ "/v1/stores",
+ body=await async_maybe_transform(
+ {
+ "name": name,
+ "description": description,
+ "is_public": is_public,
+ "expires_after": expires_after,
+ "metadata": metadata,
+ "file_ids": file_ids,
+ },
+ store_create_params.StoreCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Store,
+ )
+
+ async def retrieve(
+ self,
+ store_identifier: 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,
+ ) -> Store:
+ """
+ Get a store by ID or name.
+
+ Args: store_identifier: The ID or name of the store to retrieve.
+
+ Returns: Store: The response containing the store details.
+
+ Args:
+ store_identifier: The ID or name of the store
+
+ 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._get(
+ f"/v1/stores/{store_identifier}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Store,
+ )
+
+ async def update(
+ self,
+ store_identifier: str,
+ *,
+ name: Optional[str] | Omit = omit,
+ description: Optional[str] | Omit = omit,
+ is_public: Optional[bool] | Omit = omit,
+ expires_after: Optional[ExpiresAfterParam] | Omit = omit,
+ metadata: object | 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,
+ ) -> Store:
+ """
+ Update a store by ID or name.
+
+ Args: store_identifier: The ID or name of the store to update. store_update:
+ StoreCreate object containing the name, description, and metadata.
+
+ Returns: Store: The response containing the updated store details.
+
+ Args:
+ store_identifier: The ID or name of the store
+
+ name: New name for the store
+
+ description: New description
+
+ is_public: Whether the store can be accessed by anyone with valid login credentials
+
+ expires_after: Represents an expiration policy for a store.
+
+ metadata: Optional metadata key-value pairs
+
+ 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._put(
+ f"/v1/stores/{store_identifier}",
+ body=await async_maybe_transform(
+ {
+ "name": name,
+ "description": description,
+ "is_public": is_public,
+ "expires_after": expires_after,
+ "metadata": metadata,
+ },
+ store_update_params.StoreUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Store,
+ )
+
+ def list(
+ self,
+ *,
+ limit: int | Omit = omit,
+ after: Optional[str] | Omit = omit,
+ before: Optional[str] | Omit = omit,
+ include_total: bool | Omit = omit,
+ q: 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,
+ ) -> AsyncPaginator[Store, AsyncCursor[Store]]:
+ """List all stores with optional search.
+
+ Args: pagination: The pagination options.
+
+ q: Optional search query to filter
+ vector stores.
+
+ Returns: StoreListResponse: The list of stores.
+
+ Args:
+ limit: Maximum number of items to return per page (1-100)
+
+ after: Cursor for forward pagination - get items after this position. Use last_cursor
+ from previous response.
+
+ before: Cursor for backward pagination - get items before this position. Use
+ first_cursor from previous response.
+
+ include_total: Whether to include total count in response (expensive operation)
+
+ q: Search query for fuzzy matching over name and description 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
+ """
+ return self._get_api_list(
+ "/v1/stores",
+ page=AsyncCursor[Store],
+ 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,
+ "q": q,
+ },
+ store_list_params.StoreListParams,
+ ),
+ ),
+ model=Store,
+ )
+
+ async def delete(
+ self,
+ store_identifier: 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,
+ ) -> StoreDeleteResponse:
+ """
+ Delete a store by ID or name.
+
+ Args: store_identifier: The ID or name of the store to delete.
+
+ Returns: Store: The response containing the deleted store details.
+
+ Args:
+ store_identifier: The ID or name of the store to delete
+
+ 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._delete(
+ f"/v1/stores/{store_identifier}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=StoreDeleteResponse,
+ )
+
+ async def question_answering(
+ self,
+ *,
+ query: str | Omit = omit,
+ store_identifiers: SequenceNotStr[str],
+ top_k: int | Omit = omit,
+ filters: Optional[store_question_answering_params.Filters] | Omit = omit,
+ file_ids: Union[Iterable[object], SequenceNotStr[str], None] | Omit = omit,
+ search_options: StoreChunkSearchOptionsParam | Omit = omit,
+ stream: bool | Omit = omit,
+ qa_options: store_question_answering_params.QaOptions | 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,
+ ) -> StoreQuestionAnsweringResponse:
+ """Question answering
+
+ Args:
+ query: Question to answer.
+
+ If not provided, the question will be extracted from the
+ passed messages.
+
+ store_identifiers: IDs or names of stores to search
+
+ top_k: Number of results to return
+
+ filters: Optional filter conditions
+
+ file_ids: Optional list of file IDs to filter chunks by (inclusion filter)
+
+ search_options: Search configuration options
+
+ stream: Whether to stream the answer
+
+ qa_options: Question answering configuration options
+
+ 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
+ """
+ return await self._post(
+ "/v1/stores/question-answering",
+ body=await async_maybe_transform(
+ {
+ "query": query,
+ "store_identifiers": store_identifiers,
+ "top_k": top_k,
+ "filters": filters,
+ "file_ids": file_ids,
+ "search_options": search_options,
+ "stream": stream,
+ "qa_options": qa_options,
+ },
+ store_question_answering_params.StoreQuestionAnsweringParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=StoreQuestionAnsweringResponse,
+ )
+
+ async def search(
+ self,
+ *,
+ query: str,
+ store_identifiers: SequenceNotStr[str],
+ top_k: int | Omit = omit,
+ filters: Optional[store_search_params.Filters] | Omit = omit,
+ file_ids: Union[Iterable[object], SequenceNotStr[str], None] | Omit = omit,
+ search_options: StoreChunkSearchOptionsParam | 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,
+ ) -> StoreSearchResponse:
+ """
+ Perform semantic search across store chunks.
+
+ This endpoint searches through store chunks using semantic similarity matching.
+ It supports complex search queries with filters and returns relevance-scored
+ results.
+
+ Args: search_params: Search configuration including: - query text or
+ embeddings - store_identifiers: List of store identifiers to search - file_ids:
+ Optional list of file IDs to filter chunks by (or tuple of list and condition
+ operator) - metadata filters - pagination parameters - sorting preferences
+ \\__state: API state dependency \\__ctx: Service context dependency
+
+ Returns: StoreSearchResponse containing: - List of matched chunks with relevance
+ scores - Pagination details including total result count
+
+ Raises: HTTPException (400): If search parameters are invalid HTTPException
+ (404): If no vector stores are found to search
+
+ Args:
+ query: Search query text
+
+ store_identifiers: IDs or names of stores to search
+
+ top_k: Number of results to return
+
+ filters: Optional filter conditions
+
+ file_ids: Optional list of file IDs to filter chunks by (inclusion filter)
+
+ search_options: Search configuration options
+
+ 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
+ """
+ return await self._post(
+ "/v1/stores/search",
+ body=await async_maybe_transform(
+ {
+ "query": query,
+ "store_identifiers": store_identifiers,
+ "top_k": top_k,
+ "filters": filters,
+ "file_ids": file_ids,
+ "search_options": search_options,
+ },
+ store_search_params.StoreSearchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=StoreSearchResponse,
+ )
+
+
+class StoresResourceWithRawResponse:
+ def __init__(self, stores: StoresResource) -> None:
+ self._stores = stores
+
+ self.create = to_raw_response_wrapper(
+ stores.create,
+ )
+ self.retrieve = to_raw_response_wrapper(
+ stores.retrieve,
+ )
+ self.update = to_raw_response_wrapper(
+ stores.update,
+ )
+ self.list = to_raw_response_wrapper(
+ stores.list,
+ )
+ self.delete = to_raw_response_wrapper(
+ stores.delete,
+ )
+ self.question_answering = to_raw_response_wrapper(
+ stores.question_answering,
+ )
+ self.search = to_raw_response_wrapper(
+ stores.search,
+ )
+
+ @cached_property
+ def files(self) -> FilesResourceWithRawResponse:
+ return FilesResourceWithRawResponse(self._stores.files)
+
+
+class AsyncStoresResourceWithRawResponse:
+ def __init__(self, stores: AsyncStoresResource) -> None:
+ self._stores = stores
+
+ self.create = async_to_raw_response_wrapper(
+ stores.create,
+ )
+ self.retrieve = async_to_raw_response_wrapper(
+ stores.retrieve,
+ )
+ self.update = async_to_raw_response_wrapper(
+ stores.update,
+ )
+ self.list = async_to_raw_response_wrapper(
+ stores.list,
+ )
+ self.delete = async_to_raw_response_wrapper(
+ stores.delete,
+ )
+ self.question_answering = async_to_raw_response_wrapper(
+ stores.question_answering,
+ )
+ self.search = async_to_raw_response_wrapper(
+ stores.search,
+ )
+
+ @cached_property
+ def files(self) -> AsyncFilesResourceWithRawResponse:
+ return AsyncFilesResourceWithRawResponse(self._stores.files)
+
+
+class StoresResourceWithStreamingResponse:
+ def __init__(self, stores: StoresResource) -> None:
+ self._stores = stores
+
+ self.create = to_streamed_response_wrapper(
+ stores.create,
+ )
+ self.retrieve = to_streamed_response_wrapper(
+ stores.retrieve,
+ )
+ self.update = to_streamed_response_wrapper(
+ stores.update,
+ )
+ self.list = to_streamed_response_wrapper(
+ stores.list,
+ )
+ self.delete = to_streamed_response_wrapper(
+ stores.delete,
+ )
+ self.question_answering = to_streamed_response_wrapper(
+ stores.question_answering,
+ )
+ self.search = to_streamed_response_wrapper(
+ stores.search,
+ )
+
+ @cached_property
+ def files(self) -> FilesResourceWithStreamingResponse:
+ return FilesResourceWithStreamingResponse(self._stores.files)
+
+
+class AsyncStoresResourceWithStreamingResponse:
+ def __init__(self, stores: AsyncStoresResource) -> None:
+ self._stores = stores
+
+ self.create = async_to_streamed_response_wrapper(
+ stores.create,
+ )
+ self.retrieve = async_to_streamed_response_wrapper(
+ stores.retrieve,
+ )
+ self.update = async_to_streamed_response_wrapper(
+ stores.update,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ stores.list,
+ )
+ self.delete = async_to_streamed_response_wrapper(
+ stores.delete,
+ )
+ self.question_answering = async_to_streamed_response_wrapper(
+ stores.question_answering,
+ )
+ self.search = async_to_streamed_response_wrapper(
+ stores.search,
+ )
+
+ @cached_property
+ def files(self) -> AsyncFilesResourceWithStreamingResponse:
+ return AsyncFilesResourceWithStreamingResponse(self._stores.files)
diff --git a/src/mixedbread/resources/vector_stores/files.py b/src/mixedbread/resources/vector_stores/files.py
index e3d1776e..215f0a23 100644
--- a/src/mixedbread/resources/vector_stores/files.py
+++ b/src/mixedbread/resources/vector_stores/files.py
@@ -5,7 +5,6 @@
import functools
import typing_extensions
from typing import Any, List, Union, Iterable, Optional
-from typing_extensions import Literal
import httpx
@@ -22,6 +21,7 @@
)
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.stores.store_file_status import StoreFileStatus
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
@@ -50,7 +50,7 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse:
"""
return FilesResourceWithStreamingResponse(self)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use post stores.files instead")
def create(
self,
vector_store_identifier: str,
@@ -105,7 +105,7 @@ def create(
cast_to=VectorStoreFile,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores.files instead")
def retrieve(
self,
file_id: str,
@@ -155,7 +155,7 @@ def retrieve(
cast_to=VectorStoreFile,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use post stores.files.list instead")
def list(
self,
vector_store_identifier: str,
@@ -164,7 +164,7 @@ def list(
after: Optional[str] | Omit = omit,
before: Optional[str] | Omit = omit,
include_total: bool | Omit = omit,
- statuses: Optional[List[Literal["pending", "in_progress", "cancelled", "completed", "failed"]]] | Omit = omit,
+ statuses: Optional[List[StoreFileStatus]] | Omit = omit,
metadata_filter: Optional[file_list_params.MetadataFilter] | 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.
@@ -224,7 +224,7 @@ def list(
cast_to=FileListResponse,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores.files instead")
def delete(
self,
file_id: str,
@@ -267,7 +267,7 @@ def delete(
cast_to=FileDeleteResponse,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores.files.search instead")
def search(
self,
*,
@@ -454,7 +454,7 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse:
"""
return AsyncFilesResourceWithStreamingResponse(self)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use post stores.files instead")
async def create(
self,
vector_store_identifier: str,
@@ -509,7 +509,7 @@ async def create(
cast_to=VectorStoreFile,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores.files instead")
async def retrieve(
self,
file_id: str,
@@ -561,7 +561,7 @@ async def retrieve(
cast_to=VectorStoreFile,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use post stores.files.list instead")
async def list(
self,
vector_store_identifier: str,
@@ -570,7 +570,7 @@ async def list(
after: Optional[str] | Omit = omit,
before: Optional[str] | Omit = omit,
include_total: bool | Omit = omit,
- statuses: Optional[List[Literal["pending", "in_progress", "cancelled", "completed", "failed"]]] | Omit = omit,
+ statuses: Optional[List[StoreFileStatus]] | Omit = omit,
metadata_filter: Optional[file_list_params.MetadataFilter] | 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.
@@ -630,7 +630,7 @@ async def list(
cast_to=FileListResponse,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores.files instead")
async def delete(
self,
file_id: str,
@@ -673,7 +673,7 @@ async def delete(
cast_to=FileDeleteResponse,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores.files.search instead")
async def search(
self,
*,
diff --git a/src/mixedbread/resources/vector_stores/vector_stores.py b/src/mixedbread/resources/vector_stores/vector_stores.py
index 548ffe13..b8e3dd13 100644
--- a/src/mixedbread/resources/vector_stores/vector_stores.py
+++ b/src/mixedbread/resources/vector_stores/vector_stores.py
@@ -68,7 +68,7 @@ def with_streaming_response(self) -> VectorStoresResourceWithStreamingResponse:
"""
return VectorStoresResourceWithStreamingResponse(self)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores instead")
def create(
self,
*,
@@ -128,7 +128,7 @@ def create(
cast_to=VectorStore,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores instead")
def retrieve(
self,
vector_store_identifier: str,
@@ -166,7 +166,7 @@ def retrieve(
cast_to=VectorStore,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores instead")
def update(
self,
vector_store_identifier: str,
@@ -229,7 +229,7 @@ def update(
cast_to=VectorStore,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores instead")
def list(
self,
*,
@@ -291,7 +291,7 @@ def list(
model=VectorStore,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores instead")
def delete(
self,
vector_store_identifier: str,
@@ -329,7 +329,7 @@ def delete(
cast_to=VectorStoreDeleteResponse,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores.question_answering instead")
def question_answering(
self,
*,
@@ -398,7 +398,7 @@ def question_answering(
cast_to=VectorStoreQuestionAnsweringResponse,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores.search instead")
def search(
self,
*,
@@ -483,7 +483,7 @@ def with_streaming_response(self) -> AsyncVectorStoresResourceWithStreamingRespo
"""
return AsyncVectorStoresResourceWithStreamingResponse(self)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores instead")
async def create(
self,
*,
@@ -543,7 +543,7 @@ async def create(
cast_to=VectorStore,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores instead")
async def retrieve(
self,
vector_store_identifier: str,
@@ -581,7 +581,7 @@ async def retrieve(
cast_to=VectorStore,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores instead")
async def update(
self,
vector_store_identifier: str,
@@ -644,7 +644,7 @@ async def update(
cast_to=VectorStore,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores instead")
def list(
self,
*,
@@ -706,7 +706,7 @@ def list(
model=VectorStore,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores instead")
async def delete(
self,
vector_store_identifier: str,
@@ -744,7 +744,7 @@ async def delete(
cast_to=VectorStoreDeleteResponse,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores.question_answering instead")
async def question_answering(
self,
*,
@@ -813,7 +813,7 @@ async def question_answering(
cast_to=VectorStoreQuestionAnsweringResponse,
)
- @typing_extensions.deprecated("deprecated")
+ @typing_extensions.deprecated("Use stores.search instead")
async def search(
self,
*,
diff --git a/src/mixedbread/types/__init__.py b/src/mixedbread/types/__init__.py
index 87fe66f4..3ec3253b 100644
--- a/src/mixedbread/types/__init__.py
+++ b/src/mixedbread/types/__init__.py
@@ -4,6 +4,7 @@
from . import shared
from .. import _compat
+from .store import Store as Store
from .shared import Usage as Usage, SearchFilter as SearchFilter, SearchFilterCondition as SearchFilterCondition
from .api_key import APIKey as APIKey
from .embedding import Embedding as Embedding
@@ -18,18 +19,25 @@
from .rerank_response import RerankResponse as RerankResponse
from .data_source_type import DataSourceType as DataSourceType
from .file_list_params import FileListParams as FileListParams
+from .store_list_params import StoreListParams as StoreListParams
from .file_create_params import FileCreateParams as FileCreateParams
from .file_update_params import FileUpdateParams as FileUpdateParams
from .api_key_list_params import APIKeyListParams as APIKeyListParams
from .client_embed_params import ClientEmbedParams as ClientEmbedParams
from .expires_after_param import ExpiresAfterParam as ExpiresAfterParam
+from .store_create_params import StoreCreateParams as StoreCreateParams
+from .store_search_params import StoreSearchParams as StoreSearchParams
+from .store_update_params import StoreUpdateParams as StoreUpdateParams
from .client_rerank_params import ClientRerankParams as ClientRerankParams
from .file_delete_response import FileDeleteResponse as FileDeleteResponse
from .api_key_create_params import APIKeyCreateParams as APIKeyCreateParams
from .pagination_with_total import PaginationWithTotal as PaginationWithTotal
+from .store_delete_response import StoreDeleteResponse as StoreDeleteResponse
+from .store_search_response import StoreSearchResponse as StoreSearchResponse
from .api_key_delete_response import APIKeyDeleteResponse as APIKeyDeleteResponse
from .data_source_list_params import DataSourceListParams as DataSourceListParams
from .embedding_create_params import EmbeddingCreateParams as EmbeddingCreateParams
+from .scored_text_input_chunk import ScoredTextInputChunk as ScoredTextInputChunk
from .linear_data_source_param import LinearDataSourceParam as LinearDataSourceParam
from .multi_encoding_embedding import MultiEncodingEmbedding as MultiEncodingEmbedding
from .notion_data_source_param import NotionDataSourceParam as NotionDataSourceParam
@@ -42,8 +50,14 @@
from .vector_store_search_params import VectorStoreSearchParams as VectorStoreSearchParams
from .vector_store_update_params import VectorStoreUpdateParams as VectorStoreUpdateParams
from .data_source_delete_response import DataSourceDeleteResponse as DataSourceDeleteResponse
+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 .vector_store_delete_response import VectorStoreDeleteResponse as VectorStoreDeleteResponse
from .vector_store_search_response import VectorStoreSearchResponse as VectorStoreSearchResponse
+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
from .vector_store_question_answering_params import (
VectorStoreQuestionAnsweringParams as VectorStoreQuestionAnsweringParams,
)
diff --git a/src/mixedbread/types/scored_audio_url_input_chunk.py b/src/mixedbread/types/scored_audio_url_input_chunk.py
new file mode 100644
index 00000000..0e749c30
--- /dev/null
+++ b/src/mixedbread/types/scored_audio_url_input_chunk.py
@@ -0,0 +1,57 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["ScoredAudioURLInputChunk", "AudioURL"]
+
+
+class AudioURL(BaseModel):
+ url: str
+ """The audio URL. Can be either a URL or a Data URI."""
+
+
+class ScoredAudioURLInputChunk(BaseModel):
+ chunk_index: int
+ """position of the chunk in a file"""
+
+ mime_type: Optional[str] = None
+ """mime type of the chunk"""
+
+ generated_metadata: Optional[Dict[str, object]] = None
+ """metadata of the chunk"""
+
+ model: Optional[str] = None
+ """model used for this chunk"""
+
+ score: float
+ """score of the chunk"""
+
+ file_id: str
+ """file id"""
+
+ filename: str
+ """filename"""
+
+ store_id: str
+ """store id"""
+
+ metadata: Optional[object] = None
+ """file metadata"""
+
+ type: Optional[Literal["audio_url"]] = None
+ """Input type identifier"""
+
+ transcription: Optional[str] = None
+ """speech recognition (sr) text of the audio"""
+
+ summary: Optional[str] = None
+ """summary of the audio"""
+
+ audio_url: AudioURL
+ """The audio input specification."""
+
+ sampling_rate: int
+ """The sampling rate of the audio."""
diff --git a/src/mixedbread/types/scored_image_url_input_chunk.py b/src/mixedbread/types/scored_image_url_input_chunk.py
new file mode 100644
index 00000000..b7a925fd
--- /dev/null
+++ b/src/mixedbread/types/scored_image_url_input_chunk.py
@@ -0,0 +1,57 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["ScoredImageURLInputChunk", "ImageURL"]
+
+
+class ImageURL(BaseModel):
+ url: str
+ """The image URL. Can be either a URL or a Data URI."""
+
+ format: Optional[str] = None
+ """The image format/mimetype"""
+
+
+class ScoredImageURLInputChunk(BaseModel):
+ chunk_index: int
+ """position of the chunk in a file"""
+
+ mime_type: Optional[str] = None
+ """mime type of the chunk"""
+
+ generated_metadata: Optional[Dict[str, object]] = None
+ """metadata of the chunk"""
+
+ model: Optional[str] = None
+ """model used for this chunk"""
+
+ score: float
+ """score of the chunk"""
+
+ file_id: str
+ """file id"""
+
+ filename: str
+ """filename"""
+
+ store_id: str
+ """store id"""
+
+ metadata: Optional[object] = None
+ """file metadata"""
+
+ type: Optional[Literal["image_url"]] = None
+ """Input type identifier"""
+
+ ocr_text: Optional[str] = None
+ """ocr text of the image"""
+
+ summary: Optional[str] = None
+ """summary of the image"""
+
+ image_url: ImageURL
+ """The image input specification."""
diff --git a/src/mixedbread/types/scored_text_input_chunk.py b/src/mixedbread/types/scored_text_input_chunk.py
new file mode 100644
index 00000000..6a120e42
--- /dev/null
+++ b/src/mixedbread/types/scored_text_input_chunk.py
@@ -0,0 +1,46 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["ScoredTextInputChunk"]
+
+
+class ScoredTextInputChunk(BaseModel):
+ chunk_index: int
+ """position of the chunk in a file"""
+
+ mime_type: Optional[str] = None
+ """mime type of the chunk"""
+
+ generated_metadata: Optional[Dict[str, object]] = None
+ """metadata of the chunk"""
+
+ model: Optional[str] = None
+ """model used for this chunk"""
+
+ score: float
+ """score of the chunk"""
+
+ file_id: str
+ """file id"""
+
+ filename: str
+ """filename"""
+
+ store_id: str
+ """store id"""
+
+ metadata: Optional[object] = None
+ """file metadata"""
+
+ type: Optional[Literal["text"]] = None
+ """Input type identifier"""
+
+ offset: Optional[int] = None
+ """The offset of the text in the file relative to the start of the file."""
+
+ text: str
+ """Text content to process"""
diff --git a/src/mixedbread/types/scored_video_url_input_chunk.py b/src/mixedbread/types/scored_video_url_input_chunk.py
new file mode 100644
index 00000000..c31cb23c
--- /dev/null
+++ b/src/mixedbread/types/scored_video_url_input_chunk.py
@@ -0,0 +1,54 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["ScoredVideoURLInputChunk", "VideoURL"]
+
+
+class VideoURL(BaseModel):
+ url: str
+ """The video URL. Can be either a URL or a Data URI."""
+
+
+class ScoredVideoURLInputChunk(BaseModel):
+ chunk_index: int
+ """position of the chunk in a file"""
+
+ mime_type: Optional[str] = None
+ """mime type of the chunk"""
+
+ generated_metadata: Optional[Dict[str, object]] = None
+ """metadata of the chunk"""
+
+ model: Optional[str] = None
+ """model used for this chunk"""
+
+ score: float
+ """score of the chunk"""
+
+ file_id: str
+ """file id"""
+
+ filename: str
+ """filename"""
+
+ store_id: str
+ """store id"""
+
+ metadata: Optional[object] = None
+ """file metadata"""
+
+ type: Optional[Literal["video_url"]] = None
+ """Input type identifier"""
+
+ transcription: Optional[str] = None
+ """speech recognition (sr) text of the video"""
+
+ summary: Optional[str] = None
+ """summary of the video"""
+
+ video_url: VideoURL
+ """The video input specification."""
diff --git a/src/mixedbread/types/store.py b/src/mixedbread/types/store.py
new file mode 100644
index 00000000..5c7db5d1
--- /dev/null
+++ b/src/mixedbread/types/store.py
@@ -0,0 +1,74 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+from .expires_after import ExpiresAfter
+
+__all__ = ["Store", "FileCounts"]
+
+
+class FileCounts(BaseModel):
+ pending: Optional[int] = None
+ """Number of files waiting to be processed"""
+
+ in_progress: Optional[int] = None
+ """Number of files currently being processed"""
+
+ cancelled: Optional[int] = None
+ """Number of files whose processing was cancelled"""
+
+ completed: Optional[int] = None
+ """Number of successfully processed files"""
+
+ failed: Optional[int] = None
+ """Number of files that failed processing"""
+
+ total: Optional[int] = None
+ """Total number of files"""
+
+
+class Store(BaseModel):
+ id: str
+ """Unique identifier for the store"""
+
+ name: str
+ """Name of the store"""
+
+ description: Optional[str] = None
+ """Detailed description of the store's purpose and contents"""
+
+ is_public: Optional[bool] = None
+ """Whether the store can be accessed by anyone with valid login credentials"""
+
+ metadata: Optional[object] = None
+ """Additional metadata associated with the store"""
+
+ file_counts: Optional[FileCounts] = None
+ """Counts of files in different states"""
+
+ expires_after: Optional[ExpiresAfter] = None
+ """Represents an expiration policy for a store."""
+
+ status: Optional[Literal["expired", "in_progress", "completed"]] = None
+ """Processing status of the store"""
+
+ created_at: datetime
+ """Timestamp when the store was created"""
+
+ updated_at: datetime
+ """Timestamp when the store was last updated"""
+
+ last_active_at: Optional[datetime] = None
+ """Timestamp when the store was last used"""
+
+ usage_bytes: Optional[int] = None
+ """Total storage usage in bytes"""
+
+ expires_at: Optional[datetime] = None
+ """Optional expiration timestamp for the store"""
+
+ object: Optional[Literal["store"]] = None
+ """Type of the object"""
diff --git a/src/mixedbread/types/store_chunk_search_options_param.py b/src/mixedbread/types/store_chunk_search_options_param.py
new file mode 100644
index 00000000..89c64712
--- /dev/null
+++ b/src/mixedbread/types/store_chunk_search_options_param.py
@@ -0,0 +1,29 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union, Optional
+from typing_extensions import TypeAlias, TypedDict
+
+from .vector_stores.rerank_config_param import RerankConfigParam
+
+__all__ = ["StoreChunkSearchOptionsParam", "Rerank"]
+
+Rerank: TypeAlias = Union[bool, RerankConfigParam]
+
+
+class StoreChunkSearchOptionsParam(TypedDict, total=False):
+ score_threshold: float
+ """Minimum similarity score threshold"""
+
+ rewrite_query: bool
+ """Whether to rewrite the query"""
+
+ rerank: Optional[Rerank]
+ """Whether to rerank results and optional reranking configuration"""
+
+ return_metadata: bool
+ """Whether to return file metadata"""
+
+ apply_search_rules: bool
+ """Whether to apply search rules"""
diff --git a/src/mixedbread/types/store_create_params.py b/src/mixedbread/types/store_create_params.py
new file mode 100644
index 00000000..1c307c18
--- /dev/null
+++ b/src/mixedbread/types/store_create_params.py
@@ -0,0 +1,31 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import TypedDict
+
+from .._types import SequenceNotStr
+from .expires_after_param import ExpiresAfterParam
+
+__all__ = ["StoreCreateParams"]
+
+
+class StoreCreateParams(TypedDict, total=False):
+ name: Optional[str]
+ """Name for the new store"""
+
+ description: Optional[str]
+ """Description of the store"""
+
+ is_public: bool
+ """Whether the store can be accessed by anyone with valid login credentials"""
+
+ expires_after: Optional[ExpiresAfterParam]
+ """Represents an expiration policy for a store."""
+
+ metadata: object
+ """Optional metadata key-value pairs"""
+
+ file_ids: Optional[SequenceNotStr[str]]
+ """Optional list of file IDs"""
diff --git a/src/mixedbread/types/store_delete_response.py b/src/mixedbread/types/store_delete_response.py
new file mode 100644
index 00000000..c35970ab
--- /dev/null
+++ b/src/mixedbread/types/store_delete_response.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["StoreDeleteResponse"]
+
+
+class StoreDeleteResponse(BaseModel):
+ id: str
+ """ID of the deleted store"""
+
+ deleted: bool
+ """Whether the deletion was successful"""
+
+ object: Optional[Literal["store"]] = None
+ """Type of the deleted object"""
diff --git a/src/mixedbread/types/store_list_params.py b/src/mixedbread/types/store_list_params.py
new file mode 100644
index 00000000..addec411
--- /dev/null
+++ b/src/mixedbread/types/store_list_params.py
@@ -0,0 +1,31 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import TypedDict
+
+__all__ = ["StoreListParams"]
+
+
+class StoreListParams(TypedDict, total=False):
+ limit: int
+ """Maximum number of items to return per page (1-100)"""
+
+ after: Optional[str]
+ """Cursor for forward pagination - get items after this position.
+
+ Use last_cursor from previous response.
+ """
+
+ before: Optional[str]
+ """Cursor for backward pagination - get items before this position.
+
+ Use first_cursor from previous response.
+ """
+
+ include_total: bool
+ """Whether to include total count in response (expensive operation)"""
+
+ q: Optional[str]
+ """Search query for fuzzy matching over name and description fields"""
diff --git a/src/mixedbread/types/store_question_answering_params.py b/src/mixedbread/types/store_question_answering_params.py
new file mode 100644
index 00000000..37366a6f
--- /dev/null
+++ b/src/mixedbread/types/store_question_answering_params.py
@@ -0,0 +1,57 @@
+# 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 Required, TypeAlias, TypedDict
+
+from .._types import SequenceNotStr
+from .store_chunk_search_options_param import StoreChunkSearchOptionsParam
+from .shared_params.search_filter_condition import SearchFilterCondition
+
+__all__ = ["StoreQuestionAnsweringParams", "Filters", "FiltersUnionMember2", "QaOptions"]
+
+
+class StoreQuestionAnsweringParams(TypedDict, total=False):
+ query: str
+ """Question to answer.
+
+ If not provided, the question will be extracted from the passed messages.
+ """
+
+ store_identifiers: Required[SequenceNotStr[str]]
+ """IDs or names of stores to search"""
+
+ top_k: int
+ """Number of results to return"""
+
+ filters: Optional[Filters]
+ """Optional filter conditions"""
+
+ file_ids: Union[Iterable[object], SequenceNotStr[str], None]
+ """Optional list of file IDs to filter chunks by (inclusion filter)"""
+
+ search_options: StoreChunkSearchOptionsParam
+ """Search configuration options"""
+
+ stream: bool
+ """Whether to stream the answer"""
+
+ qa_options: QaOptions
+ """Question answering configuration options"""
+
+
+FiltersUnionMember2: TypeAlias = Union["SearchFilter", SearchFilterCondition]
+
+Filters: TypeAlias = Union["SearchFilter", SearchFilterCondition, Iterable[FiltersUnionMember2]]
+
+
+class QaOptions(TypedDict, total=False):
+ cite: bool
+ """Whether to use citations"""
+
+ multimodal: bool
+ """Whether to use multimodal context"""
+
+
+from .shared_params.search_filter import SearchFilter
diff --git a/src/mixedbread/types/store_question_answering_response.py b/src/mixedbread/types/store_question_answering_response.py
new file mode 100644
index 00000000..f47f71b3
--- /dev/null
+++ b/src/mixedbread/types/store_question_answering_response.py
@@ -0,0 +1,26 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Union, Optional
+from typing_extensions import Annotated, TypeAlias
+
+from .._utils import PropertyInfo
+from .._models import BaseModel
+from .scored_text_input_chunk import ScoredTextInputChunk
+from .scored_audio_url_input_chunk import ScoredAudioURLInputChunk
+from .scored_image_url_input_chunk import ScoredImageURLInputChunk
+from .scored_video_url_input_chunk import ScoredVideoURLInputChunk
+
+__all__ = ["StoreQuestionAnsweringResponse", "Source"]
+
+Source: TypeAlias = Annotated[
+ Union[ScoredTextInputChunk, ScoredImageURLInputChunk, ScoredAudioURLInputChunk, ScoredVideoURLInputChunk],
+ PropertyInfo(discriminator="type"),
+]
+
+
+class StoreQuestionAnsweringResponse(BaseModel):
+ answer: str
+ """The answer generated by the LLM"""
+
+ sources: Optional[List[Source]] = None
+ """Source documents used to generate the answer"""
diff --git a/src/mixedbread/types/store_search_params.py b/src/mixedbread/types/store_search_params.py
new file mode 100644
index 00000000..1bff13de
--- /dev/null
+++ b/src/mixedbread/types/store_search_params.py
@@ -0,0 +1,39 @@
+# 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 Required, TypeAlias, TypedDict
+
+from .._types import SequenceNotStr
+from .store_chunk_search_options_param import StoreChunkSearchOptionsParam
+from .shared_params.search_filter_condition import SearchFilterCondition
+
+__all__ = ["StoreSearchParams", "Filters", "FiltersUnionMember2"]
+
+
+class StoreSearchParams(TypedDict, total=False):
+ query: Required[str]
+ """Search query text"""
+
+ store_identifiers: Required[SequenceNotStr[str]]
+ """IDs or names of stores to search"""
+
+ top_k: int
+ """Number of results to return"""
+
+ filters: Optional[Filters]
+ """Optional filter conditions"""
+
+ file_ids: Union[Iterable[object], SequenceNotStr[str], None]
+ """Optional list of file IDs to filter chunks by (inclusion filter)"""
+
+ search_options: StoreChunkSearchOptionsParam
+ """Search configuration options"""
+
+
+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_search_response.py b/src/mixedbread/types/store_search_response.py
new file mode 100644
index 00000000..6ab757c5
--- /dev/null
+++ b/src/mixedbread/types/store_search_response.py
@@ -0,0 +1,26 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Union, Optional
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from .._utils import PropertyInfo
+from .._models import BaseModel
+from .scored_text_input_chunk import ScoredTextInputChunk
+from .scored_audio_url_input_chunk import ScoredAudioURLInputChunk
+from .scored_image_url_input_chunk import ScoredImageURLInputChunk
+from .scored_video_url_input_chunk import ScoredVideoURLInputChunk
+
+__all__ = ["StoreSearchResponse", "Data"]
+
+Data: TypeAlias = Annotated[
+ Union[ScoredTextInputChunk, ScoredImageURLInputChunk, ScoredAudioURLInputChunk, ScoredVideoURLInputChunk],
+ PropertyInfo(discriminator="type"),
+]
+
+
+class StoreSearchResponse(BaseModel):
+ object: Optional[Literal["list"]] = None
+ """The object type of the response"""
+
+ data: List[Data]
+ """The list of scored store file chunks"""
diff --git a/src/mixedbread/types/store_update_params.py b/src/mixedbread/types/store_update_params.py
new file mode 100644
index 00000000..6133eb5c
--- /dev/null
+++ b/src/mixedbread/types/store_update_params.py
@@ -0,0 +1,27 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import TypedDict
+
+from .expires_after_param import ExpiresAfterParam
+
+__all__ = ["StoreUpdateParams"]
+
+
+class StoreUpdateParams(TypedDict, total=False):
+ name: Optional[str]
+ """New name for the store"""
+
+ description: Optional[str]
+ """New description"""
+
+ is_public: Optional[bool]
+ """Whether the store can be accessed by anyone with valid login credentials"""
+
+ expires_after: Optional[ExpiresAfterParam]
+ """Represents an expiration policy for a store."""
+
+ metadata: object
+ """Optional metadata key-value pairs"""
diff --git a/src/mixedbread/types/stores/__init__.py b/src/mixedbread/types/stores/__init__.py
new file mode 100644
index 00000000..3dee7dac
--- /dev/null
+++ b/src/mixedbread/types/stores/__init__.py
@@ -0,0 +1,14 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .store_file import StoreFile as StoreFile
+from .file_list_params import FileListParams as FileListParams
+from .scored_store_file import ScoredStoreFile as ScoredStoreFile
+from .store_file_status import StoreFileStatus as StoreFileStatus
+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 .file_delete_response import FileDeleteResponse as FileDeleteResponse
+from .file_retrieve_params import FileRetrieveParams as FileRetrieveParams
+from .file_search_response import FileSearchResponse as FileSearchResponse
diff --git a/src/mixedbread/types/stores/file_create_params.py b/src/mixedbread/types/stores/file_create_params.py
new file mode 100644
index 00000000..ce39cfd1
--- /dev/null
+++ b/src/mixedbread/types/stores/file_create_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_extensions import Literal, Required, TypedDict
+
+__all__ = ["FileCreateParams", "Experimental"]
+
+
+class FileCreateParams(TypedDict, total=False):
+ metadata: object
+ """Optional metadata for the file"""
+
+ experimental: Experimental
+ """Strategy for adding the file"""
+
+ file_id: Required[str]
+ """ID of the file to add"""
+
+
+class Experimental(TypedDict, total=False):
+ parsing_strategy: Literal["fast", "high_quality"]
+ """Strategy for adding the file"""
+
+ contextualization: bool
+ """Whether to contextualize the file"""
diff --git a/src/mixedbread/types/stores/file_delete_response.py b/src/mixedbread/types/stores/file_delete_response.py
new file mode 100644
index 00000000..ada45e9c
--- /dev/null
+++ b/src/mixedbread/types/stores/file_delete_response.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = ["FileDeleteResponse"]
+
+
+class FileDeleteResponse(BaseModel):
+ id: str
+ """ID of the deleted file"""
+
+ deleted: Optional[bool] = None
+ """Whether the deletion was successful"""
+
+ object: Optional[Literal["store.file"]] = None
+ """Type of the deleted object"""
diff --git a/src/mixedbread/types/stores/file_list_params.py b/src/mixedbread/types/stores/file_list_params.py
new file mode 100644
index 00000000..27edd05e
--- /dev/null
+++ b/src/mixedbread/types/stores/file_list_params.py
@@ -0,0 +1,44 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import List, Union, Iterable, Optional
+from typing_extensions import TypeAlias, TypedDict
+
+from .store_file_status import StoreFileStatus
+from ..shared_params.search_filter_condition import SearchFilterCondition
+
+__all__ = ["FileListParams", "MetadataFilter", "MetadataFilterUnionMember2"]
+
+
+class FileListParams(TypedDict, total=False):
+ limit: int
+ """Maximum number of items to return per page (1-100)"""
+
+ after: Optional[str]
+ """Cursor for forward pagination - get items after this position.
+
+ Use last_cursor from previous response.
+ """
+
+ before: Optional[str]
+ """Cursor for backward pagination - get items before this position.
+
+ Use first_cursor from previous response.
+ """
+
+ include_total: bool
+ """Whether to include total count in response (expensive operation)"""
+
+ statuses: Optional[List[StoreFileStatus]]
+ """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/stores/file_list_response.py b/src/mixedbread/types/stores/file_list_response.py
new file mode 100644
index 00000000..2d47abcc
--- /dev/null
+++ b/src/mixedbread/types/stores/file_list_response.py
@@ -0,0 +1,48 @@
+# 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 .store_file import StoreFile
+
+__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."""
+
+ object: Optional[Literal["list"]] = None
+ """The object type of the response"""
+
+ data: List[StoreFile]
+ """The list of store files"""
diff --git a/src/mixedbread/types/stores/file_retrieve_params.py b/src/mixedbread/types/stores/file_retrieve_params.py
new file mode 100644
index 00000000..ae924454
--- /dev/null
+++ b/src/mixedbread/types/stores/file_retrieve_params.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["FileRetrieveParams"]
+
+
+class FileRetrieveParams(TypedDict, total=False):
+ store_identifier: Required[str]
+ """The ID or name of the store"""
+
+ return_chunks: bool
+ """Whether to return the chunks for the file"""
diff --git a/src/mixedbread/types/stores/file_search_params.py b/src/mixedbread/types/stores/file_search_params.py
new file mode 100644
index 00000000..8558e0c8
--- /dev/null
+++ b/src/mixedbread/types/stores/file_search_params.py
@@ -0,0 +1,65 @@
+# 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 Required, TypeAlias, TypedDict
+
+from ..._types import SequenceNotStr
+from ..vector_stores.rerank_config_param import RerankConfigParam
+from ..shared_params.search_filter_condition import SearchFilterCondition
+
+__all__ = ["FileSearchParams", "Filters", "FiltersUnionMember2", "SearchOptions", "SearchOptionsRerank"]
+
+
+class FileSearchParams(TypedDict, total=False):
+ query: Required[str]
+ """Search query text"""
+
+ store_identifiers: Required[SequenceNotStr[str]]
+ """IDs or names of stores to search"""
+
+ top_k: int
+ """Number of results to return"""
+
+ filters: Optional[Filters]
+ """Optional filter conditions"""
+
+ file_ids: Union[Iterable[object], SequenceNotStr[str], None]
+ """Optional list of file IDs to filter chunks by (inclusion filter)"""
+
+ search_options: SearchOptions
+ """Search configuration options"""
+
+
+FiltersUnionMember2: TypeAlias = Union["SearchFilter", SearchFilterCondition]
+
+Filters: TypeAlias = Union["SearchFilter", SearchFilterCondition, Iterable[FiltersUnionMember2]]
+
+SearchOptionsRerank: TypeAlias = Union[bool, RerankConfigParam]
+
+
+class SearchOptions(TypedDict, total=False):
+ score_threshold: float
+ """Minimum similarity score threshold"""
+
+ rewrite_query: bool
+ """Whether to rewrite the query"""
+
+ rerank: Optional[SearchOptionsRerank]
+ """Whether to rerank results and optional reranking configuration"""
+
+ return_metadata: bool
+ """Whether to return file metadata"""
+
+ return_chunks: bool
+ """Whether to return matching text chunks"""
+
+ chunks_per_file: int
+ """Number of chunks to return for each file"""
+
+ apply_search_rules: bool
+ """Whether to apply search rules"""
+
+
+from ..shared_params.search_filter import SearchFilter
diff --git a/src/mixedbread/types/stores/file_search_response.py b/src/mixedbread/types/stores/file_search_response.py
new file mode 100644
index 00000000..304512e4
--- /dev/null
+++ b/src/mixedbread/types/stores/file_search_response.py
@@ -0,0 +1,17 @@
+# 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 .scored_store_file import ScoredStoreFile
+
+__all__ = ["FileSearchResponse"]
+
+
+class FileSearchResponse(BaseModel):
+ object: Optional[Literal["list"]] = None
+ """The object type of the response"""
+
+ data: List[ScoredStoreFile]
+ """The list of scored store files"""
diff --git a/src/mixedbread/types/stores/scored_store_file.py b/src/mixedbread/types/stores/scored_store_file.py
new file mode 100644
index 00000000..24aafbbe
--- /dev/null
+++ b/src/mixedbread/types/stores/scored_store_file.py
@@ -0,0 +1,58 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from ..._utils import PropertyInfo
+from ..._models import BaseModel
+from .store_file_status import StoreFileStatus
+from ..scored_text_input_chunk import ScoredTextInputChunk
+from ..scored_audio_url_input_chunk import ScoredAudioURLInputChunk
+from ..scored_image_url_input_chunk import ScoredImageURLInputChunk
+from ..scored_video_url_input_chunk import ScoredVideoURLInputChunk
+
+__all__ = ["ScoredStoreFile", "Chunk"]
+
+Chunk: TypeAlias = Annotated[
+ Union[ScoredTextInputChunk, ScoredImageURLInputChunk, ScoredAudioURLInputChunk, ScoredVideoURLInputChunk],
+ PropertyInfo(discriminator="type"),
+]
+
+
+class ScoredStoreFile(BaseModel):
+ id: str
+ """Unique identifier for the file"""
+
+ filename: Optional[str] = None
+ """Name of the file"""
+
+ metadata: Optional[object] = None
+ """Optional file metadata"""
+
+ status: Optional[StoreFileStatus] = None
+ """Processing status of the file"""
+
+ last_error: Optional[object] = None
+ """Last error message if processing failed"""
+
+ store_id: str
+ """ID of the containing store"""
+
+ created_at: datetime
+ """Timestamp of store file creation"""
+
+ version: Optional[int] = None
+ """Version number of the file"""
+
+ usage_bytes: Optional[int] = None
+ """Storage usage in bytes"""
+
+ object: Optional[Literal["store.file"]] = None
+ """Type of the object"""
+
+ chunks: Optional[List[Chunk]] = None
+ """Array of scored file chunks"""
+
+ score: float
+ """score of the file"""
diff --git a/src/mixedbread/types/stores/store_file.py b/src/mixedbread/types/stores/store_file.py
new file mode 100644
index 00000000..75d385cb
--- /dev/null
+++ b/src/mixedbread/types/stores/store_file.py
@@ -0,0 +1,184 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, List, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from ..._utils import PropertyInfo
+from ..._models import BaseModel
+from .store_file_status import StoreFileStatus
+
+__all__ = [
+ "StoreFile",
+ "Chunk",
+ "ChunkTextInputChunk",
+ "ChunkImageURLInputChunk",
+ "ChunkImageURLInputChunkImageURL",
+ "ChunkAudioURLInputChunk",
+ "ChunkAudioURLInputChunkAudioURL",
+ "ChunkVideoURLInputChunk",
+ "ChunkVideoURLInputChunkVideoURL",
+]
+
+
+class ChunkTextInputChunk(BaseModel):
+ chunk_index: int
+ """position of the chunk in a file"""
+
+ mime_type: Optional[str] = None
+ """mime type of the chunk"""
+
+ generated_metadata: Optional[Dict[str, object]] = None
+ """metadata of the chunk"""
+
+ model: Optional[str] = None
+ """model used for this chunk"""
+
+ type: Optional[Literal["text"]] = None
+ """Input type identifier"""
+
+ offset: Optional[int] = None
+ """The offset of the text in the file relative to the start of the file."""
+
+ text: str
+ """Text content to process"""
+
+
+class ChunkImageURLInputChunkImageURL(BaseModel):
+ url: str
+ """The image URL. Can be either a URL or a Data URI."""
+
+ format: Optional[str] = None
+ """The image format/mimetype"""
+
+
+class ChunkImageURLInputChunk(BaseModel):
+ chunk_index: int
+ """position of the chunk in a file"""
+
+ mime_type: Optional[str] = None
+ """mime type of the chunk"""
+
+ generated_metadata: Optional[Dict[str, object]] = None
+ """metadata of the chunk"""
+
+ model: Optional[str] = None
+ """model used for this chunk"""
+
+ type: Optional[Literal["image_url"]] = None
+ """Input type identifier"""
+
+ ocr_text: Optional[str] = None
+ """ocr text of the image"""
+
+ summary: Optional[str] = None
+ """summary of the image"""
+
+ image_url: ChunkImageURLInputChunkImageURL
+ """The image input specification."""
+
+
+class ChunkAudioURLInputChunkAudioURL(BaseModel):
+ url: str
+ """The audio URL. Can be either a URL or a Data URI."""
+
+
+class ChunkAudioURLInputChunk(BaseModel):
+ chunk_index: int
+ """position of the chunk in a file"""
+
+ mime_type: Optional[str] = None
+ """mime type of the chunk"""
+
+ generated_metadata: Optional[Dict[str, object]] = None
+ """metadata of the chunk"""
+
+ model: Optional[str] = None
+ """model used for this chunk"""
+
+ type: Optional[Literal["audio_url"]] = None
+ """Input type identifier"""
+
+ transcription: Optional[str] = None
+ """speech recognition (sr) text of the audio"""
+
+ summary: Optional[str] = None
+ """summary of the audio"""
+
+ audio_url: ChunkAudioURLInputChunkAudioURL
+ """The audio input specification."""
+
+ sampling_rate: int
+ """The sampling rate of the audio."""
+
+
+class ChunkVideoURLInputChunkVideoURL(BaseModel):
+ url: str
+ """The video URL. Can be either a URL or a Data URI."""
+
+
+class ChunkVideoURLInputChunk(BaseModel):
+ chunk_index: int
+ """position of the chunk in a file"""
+
+ mime_type: Optional[str] = None
+ """mime type of the chunk"""
+
+ generated_metadata: Optional[Dict[str, object]] = None
+ """metadata of the chunk"""
+
+ model: Optional[str] = None
+ """model used for this chunk"""
+
+ type: Optional[Literal["video_url"]] = None
+ """Input type identifier"""
+
+ transcription: Optional[str] = None
+ """speech recognition (sr) text of the video"""
+
+ summary: Optional[str] = None
+ """summary of the video"""
+
+ video_url: ChunkVideoURLInputChunkVideoURL
+ """The video input specification."""
+
+
+Chunk: TypeAlias = Annotated[
+ Union[ChunkTextInputChunk, ChunkImageURLInputChunk, ChunkAudioURLInputChunk, ChunkVideoURLInputChunk],
+ PropertyInfo(discriminator="type"),
+]
+
+
+class StoreFile(BaseModel):
+ id: str
+ """Unique identifier for the file"""
+
+ filename: Optional[str] = None
+ """Name of the file"""
+
+ metadata: Optional[object] = None
+ """Optional file metadata"""
+
+ status: Optional[StoreFileStatus] = None
+ """Processing status of the file"""
+
+ last_error: Optional[object] = None
+ """Last error message if processing failed"""
+
+ store_id: str
+ """ID of the containing store"""
+
+ created_at: datetime
+ """Timestamp of store file creation"""
+
+ version: Optional[int] = None
+ """Version number of the file"""
+
+ usage_bytes: Optional[int] = None
+ """Storage usage in bytes"""
+
+ object: Optional[Literal["store.file"]] = None
+ """Type of the object"""
+
+ chunks: Optional[List[Chunk]] = None
+ """chunks"""
diff --git a/src/mixedbread/types/stores/store_file_status.py b/src/mixedbread/types/stores/store_file_status.py
new file mode 100644
index 00000000..a0061477
--- /dev/null
+++ b/src/mixedbread/types/stores/store_file_status.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["StoreFileStatus"]
+
+StoreFileStatus: TypeAlias = Literal["pending", "in_progress", "cancelled", "completed", "failed"]
diff --git a/src/mixedbread/types/vector_stores/file_list_params.py b/src/mixedbread/types/vector_stores/file_list_params.py
index 9f89685c..ef2c2848 100644
--- a/src/mixedbread/types/vector_stores/file_list_params.py
+++ b/src/mixedbread/types/vector_stores/file_list_params.py
@@ -3,8 +3,9 @@
from __future__ import annotations
from typing import List, Union, Iterable, Optional
-from typing_extensions import Literal, TypeAlias, TypedDict
+from typing_extensions import TypeAlias, TypedDict
+from ..stores.store_file_status import StoreFileStatus
from ..shared_params.search_filter_condition import SearchFilterCondition
__all__ = ["FileListParams", "MetadataFilter", "MetadataFilterUnionMember2"]
@@ -29,7 +30,7 @@ class FileListParams(TypedDict, total=False):
include_total: bool
"""Whether to include total count in response (expensive operation)"""
- statuses: Optional[List[Literal["pending", "in_progress", "cancelled", "completed", "failed"]]]
+ statuses: Optional[List[StoreFileStatus]]
"""Status to filter by"""
metadata_filter: Optional[MetadataFilter]
diff --git a/src/mixedbread/types/vector_stores/scored_vector_store_file.py b/src/mixedbread/types/vector_stores/scored_vector_store_file.py
index 247d7d39..7300999c 100644
--- a/src/mixedbread/types/vector_stores/scored_vector_store_file.py
+++ b/src/mixedbread/types/vector_stores/scored_vector_store_file.py
@@ -6,6 +6,7 @@
from ..._utils import PropertyInfo
from ..._models import BaseModel
+from ..stores.store_file_status import StoreFileStatus
__all__ = [
"ScoredVectorStoreFile",
@@ -223,7 +224,7 @@ class ScoredVectorStoreFile(BaseModel):
metadata: Optional[object] = None
"""Optional file metadata"""
- status: Optional[Literal["pending", "in_progress", "cancelled", "completed", "failed"]] = None
+ status: Optional[StoreFileStatus] = None
"""Processing status of the file"""
last_error: Optional[object] = None
diff --git a/src/mixedbread/types/vector_stores/vector_store_file.py b/src/mixedbread/types/vector_stores/vector_store_file.py
index 89f64d8a..9b0713fc 100644
--- a/src/mixedbread/types/vector_stores/vector_store_file.py
+++ b/src/mixedbread/types/vector_stores/vector_store_file.py
@@ -6,6 +6,7 @@
from ..._utils import PropertyInfo
from ..._models import BaseModel
+from ..stores.store_file_status import StoreFileStatus
__all__ = [
"VectorStoreFile",
@@ -158,7 +159,7 @@ class VectorStoreFile(BaseModel):
metadata: Optional[object] = None
"""Optional file metadata"""
- status: Optional[Literal["pending", "in_progress", "cancelled", "completed", "failed"]] = None
+ status: Optional[StoreFileStatus] = None
"""Processing status of the file"""
last_error: Optional[object] = None
diff --git a/tests/api_resources/stores/__init__.py b/tests/api_resources/stores/__init__.py
new file mode 100644
index 00000000..fd8019a9
--- /dev/null
+++ b/tests/api_resources/stores/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/stores/test_files.py b/tests/api_resources/stores/test_files.py
new file mode 100644
index 00000000..66797c82
--- /dev/null
+++ b/tests/api_resources/stores/test_files.py
@@ -0,0 +1,707 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from mixedbread import Mixedbread, AsyncMixedbread
+from tests.utils import assert_matches_type
+from mixedbread.types.stores import (
+ StoreFile,
+ FileListResponse,
+ FileDeleteResponse,
+ FileSearchResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestFiles:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_create(self, client: Mixedbread) -> None:
+ file = client.stores.files.create(
+ store_identifier="store_identifier",
+ file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ @parametrize
+ def test_method_create_with_all_params(self, client: Mixedbread) -> None:
+ file = client.stores.files.create(
+ store_identifier="store_identifier",
+ metadata={},
+ experimental={
+ "parsing_strategy": "fast",
+ "contextualization": True,
+ },
+ file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ @parametrize
+ def test_raw_response_create(self, client: Mixedbread) -> None:
+ response = client.stores.files.with_raw_response.create(
+ store_identifier="store_identifier",
+ file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file = response.parse()
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ @parametrize
+ def test_streaming_response_create(self, client: Mixedbread) -> None:
+ with client.stores.files.with_streaming_response.create(
+ store_identifier="store_identifier",
+ file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file = response.parse()
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_create(self, client: Mixedbread) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `store_identifier` but received ''"):
+ client.stores.files.with_raw_response.create(
+ store_identifier="",
+ file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ @parametrize
+ def test_method_retrieve(self, client: Mixedbread) -> None:
+ file = client.stores.files.retrieve(
+ file_id="file_id",
+ store_identifier="store_identifier",
+ )
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ @parametrize
+ def test_method_retrieve_with_all_params(self, client: Mixedbread) -> None:
+ file = client.stores.files.retrieve(
+ file_id="file_id",
+ store_identifier="store_identifier",
+ return_chunks=True,
+ )
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ @parametrize
+ def test_raw_response_retrieve(self, client: Mixedbread) -> None:
+ response = client.stores.files.with_raw_response.retrieve(
+ file_id="file_id",
+ store_identifier="store_identifier",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file = response.parse()
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Mixedbread) -> None:
+ with client.stores.files.with_streaming_response.retrieve(
+ file_id="file_id",
+ store_identifier="store_identifier",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file = response.parse()
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_retrieve(self, client: Mixedbread) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `store_identifier` but received ''"):
+ client.stores.files.with_raw_response.retrieve(
+ file_id="file_id",
+ store_identifier="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"):
+ client.stores.files.with_raw_response.retrieve(
+ file_id="",
+ store_identifier="store_identifier",
+ )
+
+ @parametrize
+ def test_method_list(self, client: Mixedbread) -> None:
+ file = client.stores.files.list(
+ store_identifier="store_identifier",
+ )
+ assert_matches_type(FileListResponse, file, path=["response"])
+
+ @parametrize
+ def test_method_list_with_all_params(self, client: Mixedbread) -> None:
+ file = client.stores.files.list(
+ store_identifier="store_identifier",
+ limit=10,
+ after="eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0zMVQyMzo1OTo1OS4wMDBaIiwiaWQiOiJhYmMxMjMifQ==",
+ before="eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0zMVQyMzo1OTo1OS4wMDBaIiwiaWQiOiJhYmMxMjMifQ==",
+ include_total=False,
+ statuses=["pending"],
+ metadata_filter={
+ "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",
+ },
+ ],
+ },
+ )
+ assert_matches_type(FileListResponse, file, path=["response"])
+
+ @parametrize
+ def test_raw_response_list(self, client: Mixedbread) -> None:
+ response = client.stores.files.with_raw_response.list(
+ store_identifier="store_identifier",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file = response.parse()
+ assert_matches_type(FileListResponse, file, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list(self, client: Mixedbread) -> None:
+ with client.stores.files.with_streaming_response.list(
+ store_identifier="store_identifier",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file = response.parse()
+ assert_matches_type(FileListResponse, file, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_list(self, client: Mixedbread) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `store_identifier` but received ''"):
+ client.stores.files.with_raw_response.list(
+ store_identifier="",
+ )
+
+ @parametrize
+ def test_method_delete(self, client: Mixedbread) -> None:
+ file = client.stores.files.delete(
+ file_id="file_id",
+ store_identifier="store_identifier",
+ )
+ assert_matches_type(FileDeleteResponse, file, path=["response"])
+
+ @parametrize
+ def test_raw_response_delete(self, client: Mixedbread) -> None:
+ response = client.stores.files.with_raw_response.delete(
+ file_id="file_id",
+ store_identifier="store_identifier",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file = response.parse()
+ assert_matches_type(FileDeleteResponse, file, path=["response"])
+
+ @parametrize
+ def test_streaming_response_delete(self, client: Mixedbread) -> None:
+ with client.stores.files.with_streaming_response.delete(
+ file_id="file_id",
+ store_identifier="store_identifier",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file = response.parse()
+ assert_matches_type(FileDeleteResponse, file, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_delete(self, client: Mixedbread) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `store_identifier` but received ''"):
+ client.stores.files.with_raw_response.delete(
+ file_id="file_id",
+ store_identifier="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"):
+ client.stores.files.with_raw_response.delete(
+ file_id="",
+ store_identifier="store_identifier",
+ )
+
+ @parametrize
+ def test_method_search(self, client: Mixedbread) -> None:
+ file = client.stores.files.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ )
+ assert_matches_type(FileSearchResponse, file, path=["response"])
+
+ @parametrize
+ def test_method_search_with_all_params(self, client: Mixedbread) -> None:
+ file = client.stores.files.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ top_k=1,
+ 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",
+ },
+ ],
+ },
+ file_ids=["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001"],
+ search_options={
+ "score_threshold": 0,
+ "rewrite_query": True,
+ "rerank": True,
+ "return_metadata": True,
+ "return_chunks": True,
+ "chunks_per_file": 0,
+ "apply_search_rules": True,
+ },
+ )
+ assert_matches_type(FileSearchResponse, file, path=["response"])
+
+ @parametrize
+ def test_raw_response_search(self, client: Mixedbread) -> None:
+ response = client.stores.files.with_raw_response.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file = response.parse()
+ assert_matches_type(FileSearchResponse, file, path=["response"])
+
+ @parametrize
+ def test_streaming_response_search(self, client: Mixedbread) -> None:
+ with client.stores.files.with_streaming_response.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file = response.parse()
+ assert_matches_type(FileSearchResponse, file, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncFiles:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @parametrize
+ async def test_method_create(self, async_client: AsyncMixedbread) -> None:
+ file = await async_client.stores.files.create(
+ store_identifier="store_identifier",
+ file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ @parametrize
+ async def test_method_create_with_all_params(self, async_client: AsyncMixedbread) -> None:
+ file = await async_client.stores.files.create(
+ store_identifier="store_identifier",
+ metadata={},
+ experimental={
+ "parsing_strategy": "fast",
+ "contextualization": True,
+ },
+ file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ @parametrize
+ async def test_raw_response_create(self, async_client: AsyncMixedbread) -> None:
+ response = await async_client.stores.files.with_raw_response.create(
+ store_identifier="store_identifier",
+ file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file = await response.parse()
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_create(self, async_client: AsyncMixedbread) -> None:
+ async with async_client.stores.files.with_streaming_response.create(
+ store_identifier="store_identifier",
+ file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file = await response.parse()
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_create(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.files.with_raw_response.create(
+ store_identifier="",
+ file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncMixedbread) -> None:
+ file = await async_client.stores.files.retrieve(
+ file_id="file_id",
+ store_identifier="store_identifier",
+ )
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ @parametrize
+ async def test_method_retrieve_with_all_params(self, async_client: AsyncMixedbread) -> None:
+ file = await async_client.stores.files.retrieve(
+ file_id="file_id",
+ store_identifier="store_identifier",
+ return_chunks=True,
+ )
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncMixedbread) -> None:
+ response = await async_client.stores.files.with_raw_response.retrieve(
+ file_id="file_id",
+ store_identifier="store_identifier",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file = await response.parse()
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncMixedbread) -> None:
+ async with async_client.stores.files.with_streaming_response.retrieve(
+ file_id="file_id",
+ store_identifier="store_identifier",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file = await response.parse()
+ assert_matches_type(StoreFile, file, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_retrieve(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.files.with_raw_response.retrieve(
+ file_id="file_id",
+ store_identifier="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"):
+ await async_client.stores.files.with_raw_response.retrieve(
+ file_id="",
+ store_identifier="store_identifier",
+ )
+
+ @parametrize
+ async def test_method_list(self, async_client: AsyncMixedbread) -> None:
+ file = await async_client.stores.files.list(
+ store_identifier="store_identifier",
+ )
+ assert_matches_type(FileListResponse, file, path=["response"])
+
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncMixedbread) -> None:
+ file = await async_client.stores.files.list(
+ store_identifier="store_identifier",
+ limit=10,
+ after="eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0zMVQyMzo1OTo1OS4wMDBaIiwiaWQiOiJhYmMxMjMifQ==",
+ before="eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0zMVQyMzo1OTo1OS4wMDBaIiwiaWQiOiJhYmMxMjMifQ==",
+ include_total=False,
+ statuses=["pending"],
+ metadata_filter={
+ "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",
+ },
+ ],
+ },
+ )
+ assert_matches_type(FileListResponse, file, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncMixedbread) -> None:
+ response = await async_client.stores.files.with_raw_response.list(
+ store_identifier="store_identifier",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file = await response.parse()
+ assert_matches_type(FileListResponse, file, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncMixedbread) -> None:
+ async with async_client.stores.files.with_streaming_response.list(
+ store_identifier="store_identifier",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file = await response.parse()
+ assert_matches_type(FileListResponse, file, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_list(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.files.with_raw_response.list(
+ store_identifier="",
+ )
+
+ @parametrize
+ async def test_method_delete(self, async_client: AsyncMixedbread) -> None:
+ file = await async_client.stores.files.delete(
+ file_id="file_id",
+ store_identifier="store_identifier",
+ )
+ assert_matches_type(FileDeleteResponse, file, path=["response"])
+
+ @parametrize
+ async def test_raw_response_delete(self, async_client: AsyncMixedbread) -> None:
+ response = await async_client.stores.files.with_raw_response.delete(
+ file_id="file_id",
+ store_identifier="store_identifier",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file = await response.parse()
+ assert_matches_type(FileDeleteResponse, file, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_delete(self, async_client: AsyncMixedbread) -> None:
+ async with async_client.stores.files.with_streaming_response.delete(
+ file_id="file_id",
+ store_identifier="store_identifier",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file = await response.parse()
+ assert_matches_type(FileDeleteResponse, file, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_delete(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.files.with_raw_response.delete(
+ file_id="file_id",
+ store_identifier="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"):
+ await async_client.stores.files.with_raw_response.delete(
+ file_id="",
+ store_identifier="store_identifier",
+ )
+
+ @parametrize
+ async def test_method_search(self, async_client: AsyncMixedbread) -> None:
+ file = await async_client.stores.files.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ )
+ assert_matches_type(FileSearchResponse, file, path=["response"])
+
+ @parametrize
+ async def test_method_search_with_all_params(self, async_client: AsyncMixedbread) -> None:
+ file = await async_client.stores.files.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ top_k=1,
+ 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",
+ },
+ ],
+ },
+ file_ids=["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001"],
+ search_options={
+ "score_threshold": 0,
+ "rewrite_query": True,
+ "rerank": True,
+ "return_metadata": True,
+ "return_chunks": True,
+ "chunks_per_file": 0,
+ "apply_search_rules": True,
+ },
+ )
+ assert_matches_type(FileSearchResponse, file, path=["response"])
+
+ @parametrize
+ async def test_raw_response_search(self, async_client: AsyncMixedbread) -> None:
+ response = await async_client.stores.files.with_raw_response.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file = await response.parse()
+ assert_matches_type(FileSearchResponse, file, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_search(self, async_client: AsyncMixedbread) -> None:
+ async with async_client.stores.files.with_streaming_response.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file = await response.parse()
+ assert_matches_type(FileSearchResponse, file, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_stores.py b/tests/api_resources/test_stores.py
new file mode 100644
index 00000000..180773e7
--- /dev/null
+++ b/tests/api_resources/test_stores.py
@@ -0,0 +1,800 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from mixedbread import Mixedbread, AsyncMixedbread
+from tests.utils import assert_matches_type
+from mixedbread.types import (
+ Store,
+ StoreDeleteResponse,
+ StoreSearchResponse,
+ StoreQuestionAnsweringResponse,
+)
+from mixedbread.pagination import SyncCursor, AsyncCursor
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestStores:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_create(self, client: Mixedbread) -> None:
+ store = client.stores.create()
+ assert_matches_type(Store, store, path=["response"])
+
+ @parametrize
+ def test_method_create_with_all_params(self, client: Mixedbread) -> None:
+ store = client.stores.create(
+ name="Technical Documentation",
+ description="Contains technical specifications and guides",
+ is_public=False,
+ expires_after={
+ "anchor": "last_active_at",
+ "days": 0,
+ },
+ metadata={},
+ file_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
+ )
+ assert_matches_type(Store, store, path=["response"])
+
+ @parametrize
+ def test_raw_response_create(self, client: Mixedbread) -> None:
+ response = client.stores.with_raw_response.create()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ store = response.parse()
+ assert_matches_type(Store, store, path=["response"])
+
+ @parametrize
+ def test_streaming_response_create(self, client: Mixedbread) -> None:
+ with client.stores.with_streaming_response.create() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ store = response.parse()
+ assert_matches_type(Store, store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_method_retrieve(self, client: Mixedbread) -> None:
+ store = client.stores.retrieve(
+ "store_identifier",
+ )
+ assert_matches_type(Store, store, path=["response"])
+
+ @parametrize
+ def test_raw_response_retrieve(self, client: Mixedbread) -> None:
+ response = client.stores.with_raw_response.retrieve(
+ "store_identifier",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ store = response.parse()
+ assert_matches_type(Store, store, path=["response"])
+
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Mixedbread) -> None:
+ with client.stores.with_streaming_response.retrieve(
+ "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(Store, store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_retrieve(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.retrieve(
+ "",
+ )
+
+ @parametrize
+ def test_method_update(self, client: Mixedbread) -> None:
+ store = client.stores.update(
+ store_identifier="store_identifier",
+ )
+ assert_matches_type(Store, store, path=["response"])
+
+ @parametrize
+ def test_method_update_with_all_params(self, client: Mixedbread) -> None:
+ store = client.stores.update(
+ store_identifier="store_identifier",
+ name="x",
+ description="description",
+ is_public=True,
+ expires_after={
+ "anchor": "last_active_at",
+ "days": 0,
+ },
+ metadata={},
+ )
+ assert_matches_type(Store, store, path=["response"])
+
+ @parametrize
+ def test_raw_response_update(self, client: Mixedbread) -> None:
+ response = client.stores.with_raw_response.update(
+ 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(Store, store, path=["response"])
+
+ @parametrize
+ def test_streaming_response_update(self, client: Mixedbread) -> None:
+ with client.stores.with_streaming_response.update(
+ 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(Store, store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_update(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.update(
+ store_identifier="",
+ )
+
+ @parametrize
+ def test_method_list(self, client: Mixedbread) -> None:
+ store = client.stores.list()
+ assert_matches_type(SyncCursor[Store], store, path=["response"])
+
+ @parametrize
+ def test_method_list_with_all_params(self, client: Mixedbread) -> None:
+ store = client.stores.list(
+ limit=10,
+ after="eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0zMVQyMzo1OTo1OS4wMDBaIiwiaWQiOiJhYmMxMjMifQ==",
+ before="eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0zMVQyMzo1OTo1OS4wMDBaIiwiaWQiOiJhYmMxMjMifQ==",
+ include_total=False,
+ q="x",
+ )
+ assert_matches_type(SyncCursor[Store], store, path=["response"])
+
+ @parametrize
+ def test_raw_response_list(self, client: Mixedbread) -> None:
+ response = client.stores.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ store = response.parse()
+ assert_matches_type(SyncCursor[Store], store, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list(self, client: Mixedbread) -> None:
+ with client.stores.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ store = response.parse()
+ assert_matches_type(SyncCursor[Store], store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_method_delete(self, client: Mixedbread) -> None:
+ store = client.stores.delete(
+ "store_identifier",
+ )
+ assert_matches_type(StoreDeleteResponse, store, path=["response"])
+
+ @parametrize
+ def test_raw_response_delete(self, client: Mixedbread) -> None:
+ response = client.stores.with_raw_response.delete(
+ "store_identifier",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ store = response.parse()
+ assert_matches_type(StoreDeleteResponse, store, path=["response"])
+
+ @parametrize
+ def test_streaming_response_delete(self, client: Mixedbread) -> None:
+ with client.stores.with_streaming_response.delete(
+ "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(StoreDeleteResponse, store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_delete(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.delete(
+ "",
+ )
+
+ @parametrize
+ def test_method_question_answering(self, client: Mixedbread) -> None:
+ store = client.stores.question_answering(
+ store_identifiers=["string"],
+ )
+ assert_matches_type(StoreQuestionAnsweringResponse, store, path=["response"])
+
+ @parametrize
+ def test_method_question_answering_with_all_params(self, client: Mixedbread) -> None:
+ store = client.stores.question_answering(
+ query="x",
+ store_identifiers=["string"],
+ top_k=1,
+ 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",
+ },
+ ],
+ },
+ file_ids=["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001"],
+ search_options={
+ "score_threshold": 0,
+ "rewrite_query": True,
+ "rerank": True,
+ "return_metadata": True,
+ "apply_search_rules": True,
+ },
+ stream=True,
+ qa_options={
+ "cite": True,
+ "multimodal": True,
+ },
+ )
+ assert_matches_type(StoreQuestionAnsweringResponse, store, path=["response"])
+
+ @parametrize
+ def test_raw_response_question_answering(self, client: Mixedbread) -> None:
+ response = client.stores.with_raw_response.question_answering(
+ store_identifiers=["string"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ store = response.parse()
+ assert_matches_type(StoreQuestionAnsweringResponse, store, path=["response"])
+
+ @parametrize
+ def test_streaming_response_question_answering(self, client: Mixedbread) -> None:
+ with client.stores.with_streaming_response.question_answering(
+ store_identifiers=["string"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ store = response.parse()
+ assert_matches_type(StoreQuestionAnsweringResponse, store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_method_search(self, client: Mixedbread) -> None:
+ store = client.stores.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ )
+ assert_matches_type(StoreSearchResponse, store, path=["response"])
+
+ @parametrize
+ def test_method_search_with_all_params(self, client: Mixedbread) -> None:
+ store = client.stores.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ top_k=1,
+ 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",
+ },
+ ],
+ },
+ file_ids=["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001"],
+ search_options={
+ "score_threshold": 0,
+ "rewrite_query": True,
+ "rerank": True,
+ "return_metadata": True,
+ "apply_search_rules": True,
+ },
+ )
+ assert_matches_type(StoreSearchResponse, store, path=["response"])
+
+ @parametrize
+ def test_raw_response_search(self, client: Mixedbread) -> None:
+ response = client.stores.with_raw_response.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ store = response.parse()
+ assert_matches_type(StoreSearchResponse, store, path=["response"])
+
+ @parametrize
+ def test_streaming_response_search(self, client: Mixedbread) -> None:
+ with client.stores.with_streaming_response.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ store = response.parse()
+ assert_matches_type(StoreSearchResponse, store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncStores:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @parametrize
+ async def test_method_create(self, async_client: AsyncMixedbread) -> None:
+ store = await async_client.stores.create()
+ assert_matches_type(Store, store, path=["response"])
+
+ @parametrize
+ async def test_method_create_with_all_params(self, async_client: AsyncMixedbread) -> None:
+ store = await async_client.stores.create(
+ name="Technical Documentation",
+ description="Contains technical specifications and guides",
+ is_public=False,
+ expires_after={
+ "anchor": "last_active_at",
+ "days": 0,
+ },
+ metadata={},
+ file_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
+ )
+ assert_matches_type(Store, store, path=["response"])
+
+ @parametrize
+ async def test_raw_response_create(self, async_client: AsyncMixedbread) -> None:
+ response = await async_client.stores.with_raw_response.create()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ store = await response.parse()
+ assert_matches_type(Store, store, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_create(self, async_client: AsyncMixedbread) -> None:
+ async with async_client.stores.with_streaming_response.create() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ store = await response.parse()
+ assert_matches_type(Store, store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncMixedbread) -> None:
+ store = await async_client.stores.retrieve(
+ "store_identifier",
+ )
+ assert_matches_type(Store, store, path=["response"])
+
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncMixedbread) -> None:
+ response = await async_client.stores.with_raw_response.retrieve(
+ "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(Store, store, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncMixedbread) -> None:
+ async with async_client.stores.with_streaming_response.retrieve(
+ "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(Store, store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_retrieve(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.retrieve(
+ "",
+ )
+
+ @parametrize
+ async def test_method_update(self, async_client: AsyncMixedbread) -> None:
+ store = await async_client.stores.update(
+ store_identifier="store_identifier",
+ )
+ assert_matches_type(Store, store, path=["response"])
+
+ @parametrize
+ async def test_method_update_with_all_params(self, async_client: AsyncMixedbread) -> None:
+ store = await async_client.stores.update(
+ store_identifier="store_identifier",
+ name="x",
+ description="description",
+ is_public=True,
+ expires_after={
+ "anchor": "last_active_at",
+ "days": 0,
+ },
+ metadata={},
+ )
+ assert_matches_type(Store, store, path=["response"])
+
+ @parametrize
+ async def test_raw_response_update(self, async_client: AsyncMixedbread) -> None:
+ response = await async_client.stores.with_raw_response.update(
+ 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(Store, store, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_update(self, async_client: AsyncMixedbread) -> None:
+ async with async_client.stores.with_streaming_response.update(
+ 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(Store, store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_update(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.update(
+ store_identifier="",
+ )
+
+ @parametrize
+ async def test_method_list(self, async_client: AsyncMixedbread) -> None:
+ store = await async_client.stores.list()
+ assert_matches_type(AsyncCursor[Store], store, path=["response"])
+
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncMixedbread) -> None:
+ store = await async_client.stores.list(
+ limit=10,
+ after="eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0zMVQyMzo1OTo1OS4wMDBaIiwiaWQiOiJhYmMxMjMifQ==",
+ before="eyJjcmVhdGVkX2F0IjoiMjAyNC0xMi0zMVQyMzo1OTo1OS4wMDBaIiwiaWQiOiJhYmMxMjMifQ==",
+ include_total=False,
+ q="x",
+ )
+ assert_matches_type(AsyncCursor[Store], store, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncMixedbread) -> None:
+ response = await async_client.stores.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ store = await response.parse()
+ assert_matches_type(AsyncCursor[Store], store, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncMixedbread) -> None:
+ async with async_client.stores.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ store = await response.parse()
+ assert_matches_type(AsyncCursor[Store], store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_method_delete(self, async_client: AsyncMixedbread) -> None:
+ store = await async_client.stores.delete(
+ "store_identifier",
+ )
+ assert_matches_type(StoreDeleteResponse, store, path=["response"])
+
+ @parametrize
+ async def test_raw_response_delete(self, async_client: AsyncMixedbread) -> None:
+ response = await async_client.stores.with_raw_response.delete(
+ "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(StoreDeleteResponse, store, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_delete(self, async_client: AsyncMixedbread) -> None:
+ async with async_client.stores.with_streaming_response.delete(
+ "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(StoreDeleteResponse, store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_delete(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.delete(
+ "",
+ )
+
+ @parametrize
+ async def test_method_question_answering(self, async_client: AsyncMixedbread) -> None:
+ store = await async_client.stores.question_answering(
+ store_identifiers=["string"],
+ )
+ assert_matches_type(StoreQuestionAnsweringResponse, store, path=["response"])
+
+ @parametrize
+ async def test_method_question_answering_with_all_params(self, async_client: AsyncMixedbread) -> None:
+ store = await async_client.stores.question_answering(
+ query="x",
+ store_identifiers=["string"],
+ top_k=1,
+ 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",
+ },
+ ],
+ },
+ file_ids=["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001"],
+ search_options={
+ "score_threshold": 0,
+ "rewrite_query": True,
+ "rerank": True,
+ "return_metadata": True,
+ "apply_search_rules": True,
+ },
+ stream=True,
+ qa_options={
+ "cite": True,
+ "multimodal": True,
+ },
+ )
+ assert_matches_type(StoreQuestionAnsweringResponse, store, path=["response"])
+
+ @parametrize
+ async def test_raw_response_question_answering(self, async_client: AsyncMixedbread) -> None:
+ response = await async_client.stores.with_raw_response.question_answering(
+ store_identifiers=["string"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ store = await response.parse()
+ assert_matches_type(StoreQuestionAnsweringResponse, store, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_question_answering(self, async_client: AsyncMixedbread) -> None:
+ async with async_client.stores.with_streaming_response.question_answering(
+ store_identifiers=["string"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ store = await response.parse()
+ assert_matches_type(StoreQuestionAnsweringResponse, store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_method_search(self, async_client: AsyncMixedbread) -> None:
+ store = await async_client.stores.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ )
+ assert_matches_type(StoreSearchResponse, store, path=["response"])
+
+ @parametrize
+ async def test_method_search_with_all_params(self, async_client: AsyncMixedbread) -> None:
+ store = await async_client.stores.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ top_k=1,
+ 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",
+ },
+ ],
+ },
+ file_ids=["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001"],
+ search_options={
+ "score_threshold": 0,
+ "rewrite_query": True,
+ "rerank": True,
+ "return_metadata": True,
+ "apply_search_rules": True,
+ },
+ )
+ assert_matches_type(StoreSearchResponse, store, path=["response"])
+
+ @parametrize
+ async def test_raw_response_search(self, async_client: AsyncMixedbread) -> None:
+ response = await async_client.stores.with_raw_response.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ store = await response.parse()
+ assert_matches_type(StoreSearchResponse, store, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_search(self, async_client: AsyncMixedbread) -> None:
+ async with async_client.stores.with_streaming_response.search(
+ query="how to configure SSL",
+ store_identifiers=["string"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ store = await response.parse()
+ assert_matches_type(StoreSearchResponse, store, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/test_client.py b/tests/test_client.py
index 177f226f..ef2e38b3 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -732,20 +732,20 @@ def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str
@mock.patch("mixedbread._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
@pytest.mark.respx(base_url=base_url)
def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, client: Mixedbread) -> None:
- respx_mock.post("/v1/vector_stores").mock(side_effect=httpx.TimeoutException("Test timeout error"))
+ respx_mock.post("/v1/stores").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- client.vector_stores.with_streaming_response.create().__enter__()
+ client.stores.with_streaming_response.create().__enter__()
assert _get_open_connections(self.client) == 0
@mock.patch("mixedbread._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
@pytest.mark.respx(base_url=base_url)
def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client: Mixedbread) -> None:
- respx_mock.post("/v1/vector_stores").mock(return_value=httpx.Response(500))
+ respx_mock.post("/v1/stores").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- client.vector_stores.with_streaming_response.create().__enter__()
+ client.stores.with_streaming_response.create().__enter__()
assert _get_open_connections(self.client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -772,9 +772,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
return httpx.Response(500)
return httpx.Response(200)
- respx_mock.post("/v1/vector_stores").mock(side_effect=retry_handler)
+ respx_mock.post("/v1/stores").mock(side_effect=retry_handler)
- response = client.vector_stores.with_raw_response.create()
+ response = client.stores.with_raw_response.create()
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -796,9 +796,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
return httpx.Response(500)
return httpx.Response(200)
- respx_mock.post("/v1/vector_stores").mock(side_effect=retry_handler)
+ respx_mock.post("/v1/stores").mock(side_effect=retry_handler)
- response = client.vector_stores.with_raw_response.create(extra_headers={"x-stainless-retry-count": Omit()})
+ response = client.stores.with_raw_response.create(extra_headers={"x-stainless-retry-count": Omit()})
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -819,9 +819,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
return httpx.Response(500)
return httpx.Response(200)
- respx_mock.post("/v1/vector_stores").mock(side_effect=retry_handler)
+ respx_mock.post("/v1/stores").mock(side_effect=retry_handler)
- response = client.vector_stores.with_raw_response.create(extra_headers={"x-stainless-retry-count": "42"})
+ response = client.stores.with_raw_response.create(extra_headers={"x-stainless-retry-count": "42"})
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
@@ -1559,10 +1559,10 @@ async def test_parse_retry_after_header(self, remaining_retries: int, retry_afte
async def test_retrying_timeout_errors_doesnt_leak(
self, respx_mock: MockRouter, async_client: AsyncMixedbread
) -> None:
- respx_mock.post("/v1/vector_stores").mock(side_effect=httpx.TimeoutException("Test timeout error"))
+ respx_mock.post("/v1/stores").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- await async_client.vector_stores.with_streaming_response.create().__aenter__()
+ await async_client.stores.with_streaming_response.create().__aenter__()
assert _get_open_connections(self.client) == 0
@@ -1571,10 +1571,10 @@ async def test_retrying_timeout_errors_doesnt_leak(
async def test_retrying_status_errors_doesnt_leak(
self, respx_mock: MockRouter, async_client: AsyncMixedbread
) -> None:
- respx_mock.post("/v1/vector_stores").mock(return_value=httpx.Response(500))
+ respx_mock.post("/v1/stores").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- await async_client.vector_stores.with_streaming_response.create().__aenter__()
+ await async_client.stores.with_streaming_response.create().__aenter__()
assert _get_open_connections(self.client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -1602,9 +1602,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
return httpx.Response(500)
return httpx.Response(200)
- respx_mock.post("/v1/vector_stores").mock(side_effect=retry_handler)
+ respx_mock.post("/v1/stores").mock(side_effect=retry_handler)
- response = await client.vector_stores.with_raw_response.create()
+ response = await client.stores.with_raw_response.create()
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -1627,11 +1627,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
return httpx.Response(500)
return httpx.Response(200)
- respx_mock.post("/v1/vector_stores").mock(side_effect=retry_handler)
+ respx_mock.post("/v1/stores").mock(side_effect=retry_handler)
- response = await client.vector_stores.with_raw_response.create(
- extra_headers={"x-stainless-retry-count": Omit()}
- )
+ response = await client.stores.with_raw_response.create(extra_headers={"x-stainless-retry-count": Omit()})
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -1653,9 +1651,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
return httpx.Response(500)
return httpx.Response(200)
- respx_mock.post("/v1/vector_stores").mock(side_effect=retry_handler)
+ respx_mock.post("/v1/stores").mock(side_effect=retry_handler)
- response = await client.vector_stores.with_raw_response.create(extra_headers={"x-stainless-retry-count": "42"})
+ response = await client.stores.with_raw_response.create(extra_headers={"x-stainless-retry-count": "42"})
assert response.http_request.headers.get("x-stainless-retry-count") == "42"