# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

from __future__ import annotations

from typing import Dict, Iterable
from typing_extensions import Literal

import httpx

from ...types import (
    vector_store_list_params,
    vector_store_count_params,
    vector_store_query_params,
    vector_store_create_params,
    vector_store_delete_params,
    vector_store_upsert_params,
    vector_store_configure_params,
)
from .vectors import (
    VectorsResource,
    AsyncVectorsResource,
    VectorsResourceWithRawResponse,
    AsyncVectorsResourceWithRawResponse,
    VectorsResourceWithStreamingResponse,
    AsyncVectorsResourceWithStreamingResponse,
)
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 SyncCursorPage, AsyncCursorPage
from ..._base_client import AsyncPaginator, make_request_options
from ...types.vector_store import VectorStore
from ...types.text_content_param import TextContentParam
from ...types.vector_store_drop_response import VectorStoreDropResponse
from ...types.vector_store_count_response import VectorStoreCountResponse
from ...types.vector_store_query_response import VectorStoreQueryResponse
from ...types.vector_store_delete_response import VectorStoreDeleteResponse
from ...types.vector_store_upsert_response import VectorStoreUpsertResponse

__all__ = ["VectorStoresResource", "AsyncVectorStoresResource"]


class VectorStoresResource(SyncAPIResource):
    @cached_property
    def vectors(self) -> VectorsResource:
        return VectorsResource(self._client)

    @cached_property
    def with_raw_response(self) -> VectorStoresResourceWithRawResponse:
        """
        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/scaleapi/sgp-python-beta#accessing-raw-response-data-eg-headers
        """
        return VectorStoresResourceWithRawResponse(self)

    @cached_property
    def with_streaming_response(self) -> VectorStoresResourceWithStreamingResponse:
        """
        An alternative to `.with_raw_response` that doesn't eagerly read the response body.

        For more information, see https://www.github.com/scaleapi/sgp-python-beta#with_streaming_response
        """
        return VectorStoresResourceWithStreamingResponse(self)

    def create(
        self,
        *,
        embedding_model: Literal[
            "sentence-transformers/all-MiniLM-L12-v2",
            "sentence-transformers/all-mpnet-base-v2",
            "sentence-transformers/multi-qa-distilbert-cos-v1",
            "sentence-transformers/paraphrase-multilingual-mpnet-base-v2",
            "openai/text-embedding-ada-002",
            "openai/text-embedding-3-small",
            "openai/text-embedding-3-large",
            "embed-english-v3.0",
            "embed-english-light-v3.0",
            "embed-multilingual-v3.0",
            "gemini/text-embedding-005",
            "gemini/text-multilingual-embedding-002",
            "gemini/gemini-embedding-001",
        ],
        name: str,
        indexed_metadata_fields: Dict[str, Literal["string", "number", "boolean", "object", "list"]] | 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,
    ) -> VectorStore:
        """
        Create a new vector store for storing and querying document embeddings.

        The vector store name must be unique within your account and follow naming
        conventions (3-63 characters, alphanumeric with hyphens/underscores). Once
        created, the `name`, `embedding_model`, and `embedding_dimensions` are
        permanently locked and cannot be changed. To use a different model, create a new
        vector store.

        **Indexed Fields:** Optionally specify metadata fields to index at creation time
        for faster filtering. You can add more indexed fields later using the configure
        endpoint, but cannot remove them once added.

        **Note:** The `embedding_dimensions` is automatically determined by your chosen
        `embedding_model` and cannot be manually specified (e.g., text-embedding-3-small
        = 1536 dimensions).

        Args:
          embedding_model: The embedding model to use

          name: A unique name for the vector store within the account

          indexed_metadata_fields: Dictionary mapping metadata field names to their types for efficient filtering.
              Only STRING, NUMBER, and BOOLEAN types can be indexed.

          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(
            "/v5/vector-stores/create",
            body=maybe_transform(
                {
                    "embedding_model": embedding_model,
                    "name": name,
                    "indexed_metadata_fields": indexed_metadata_fields,
                },
                vector_store_create_params.VectorStoreCreateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStore,
        )

    def retrieve(
        self,
        vector_store_name: 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,
    ) -> VectorStore:
        """
        Retrieve detailed configuration and metadata for a specific vector store.

        Returns the store's embedding model, dimensions, indexed metadata field
        definitions, creation timestamp, and last update timestamp. Use this to verify
        store settings before performing operations or to display store information in
        your application.

        Args:
          vector_store_name: The name of the vector 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 vector_store_name:
            raise ValueError(f"Expected a non-empty value for `vector_store_name` but received {vector_store_name!r}")
        return self._get(
            f"/v5/vector-stores/{vector_store_name}",
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStore,
        )

    def list(
        self,
        *,
        ending_before: str | Omit = omit,
        limit: int | Omit = omit,
        sort_by: str | Omit = omit,
        sort_order: Literal["asc", "desc"] | Omit = omit,
        starting_after: 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,
    ) -> SyncCursorPage[VectorStore]:
        """
        List all vector stores in your account with pagination.

        Returns vector stores sorted by creation date (newest first). Each store
        includes its configuration, embedding model, dimensions, indexed fields, and
        timestamps.

        Args:
          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(
            "/v5/vector-stores",
            page=SyncCursorPage[VectorStore],
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                query=maybe_transform(
                    {
                        "ending_before": ending_before,
                        "limit": limit,
                        "sort_by": sort_by,
                        "sort_order": sort_order,
                        "starting_after": starting_after,
                    },
                    vector_store_list_params.VectorStoreListParams,
                ),
            ),
            model=VectorStore,
        )

    def delete(
        self,
        vector_store_name: str,
        *,
        filter: Dict[str, object] | Omit = omit,
        ids: 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,
    ) -> VectorStoreDeleteResponse:
        """
        Delete documents from a vector store by specific IDs or metadata filter
        criteria.

        **Delete by IDs:** Provide an array of document IDs to delete specific
        documents. Documents that don't exist are silently skipped.

        **Delete by Filter:** Use metadata filters to delete all documents matching
        criteria (e.g., delete all documents with `status: "archived"`). The filter
        cannot be empty - you must specify at least one condition. To delete all
        documents, use the drop endpoint to delete the entire vector store instead.

        **Filter Operators:** Supports MongoDB-style operators including equality
        (`{"field": "value"}`), comparison (`$gt`, `$gte`, `$lt`, `$lte`, `$eq`, `$ne`),
        logical (`$and`, `$or`, `$not`), and membership (`$in`, `$nin`). Filters work on
        indexed metadata fields for best performance.

        **Safety Tip:** Use the count endpoint with the same filter first to preview how
        many documents will be deleted before executing the deletion.

        Args:
          vector_store_name: The name of the vector store

          filter: Metadata filter expression for deletion

          ids: Array of document IDs 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 vector_store_name:
            raise ValueError(f"Expected a non-empty value for `vector_store_name` but received {vector_store_name!r}")
        return self._post(
            f"/v5/vector-stores/{vector_store_name}/delete",
            body=maybe_transform(
                {
                    "filter": filter,
                    "ids": ids,
                },
                vector_store_delete_params.VectorStoreDeleteParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStoreDeleteResponse,
        )

    def configure(
        self,
        vector_store_name: str,
        *,
        indexed_metadata_fields: Dict[str, Literal["string", "number", "boolean", "object", "list"]],
        # 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,
    ) -> VectorStore:
        """
        Update the indexed metadata fields configuration for a vector store.

        Indexing metadata fields dramatically improves filtering performance during
        queries, list, and count operations by creating database indexes on those
        fields. Without indexing, filters perform full collection scans.

        **Field Types:** Only STRING, NUMBER, and BOOLEAN fields can be indexed (max 20
        fields total). OBJECT and LIST types are stored but cannot be indexed for
        filtering.

        **Adding Fields:** You can add new indexed fields at any time. Existing
        documents will have their metadata automatically indexed if they contain those
        fields.

        **Removing Fields:** Currently, indexed fields cannot be removed once added.
        Plan your indexed fields carefully based on your filtering needs.

        **Note:** The `name`, `embedding_model`, and `embedding_dimensions` cannot be
        changed after creation.

        Args:
          vector_store_name: The name of the vector store

          indexed_metadata_fields: Dictionary mapping metadata field names to their types. Only STRING, NUMBER, and
              BOOLEAN types can be indexed.

          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 vector_store_name:
            raise ValueError(f"Expected a non-empty value for `vector_store_name` but received {vector_store_name!r}")
        return self._post(
            f"/v5/vector-stores/{vector_store_name}/configure",
            body=maybe_transform(
                {"indexed_metadata_fields": indexed_metadata_fields},
                vector_store_configure_params.VectorStoreConfigureParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStore,
        )

    def count(
        self,
        vector_store_name: str,
        *,
        filter: Dict[str, 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,
    ) -> VectorStoreCountResponse:
        """
        Count documents in a vector store, optionally filtered by metadata.

        **Use Cases:**

        - Monitor vector store size and growth over time
        - Preview how many documents match a filter before deleting (safety check)
        - Validate data ingestion by counting expected vs actual documents
        - Check distribution of documents across metadata categories

        **Filtering:** Apply the same metadata filter syntax as delete/list operations.
        An empty filter or no filter counts all documents in the store.

        Args:
          vector_store_name: The name of the vector store

          filter: Metadata filter expression

          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 vector_store_name:
            raise ValueError(f"Expected a non-empty value for `vector_store_name` but received {vector_store_name!r}")
        return self._post(
            f"/v5/vector-stores/{vector_store_name}/count",
            body=maybe_transform({"filter": filter}, vector_store_count_params.VectorStoreCountParams),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStoreCountResponse,
        )

    def drop(
        self,
        vector_store_name: 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,
    ) -> VectorStoreDropResponse:
        """
        Permanently delete a vector store and all its contents.

        **⚠️ WARNING:** This is a destructive operation that cannot be undone. All
        documents, embeddings, metadata, and index configurations will be permanently
        deleted. There is no way to recover the data after deletion.

        Use the count endpoint first to verify the number of documents before deleting
        the entire store.

        Args:
          vector_store_name: The name of the vector 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 vector_store_name:
            raise ValueError(f"Expected a non-empty value for `vector_store_name` but received {vector_store_name!r}")
        return self._post(
            f"/v5/vector-stores/{vector_store_name}/drop",
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStoreDropResponse,
        )

    def query(
        self,
        vector_store_name: str,
        *,
        content: TextContentParam,
        filter: Dict[str, object] | Omit = omit,
        include_vectors: bool | Omit = omit,
        query_type: Literal["semantic", "lexical", "hybrid"] | Omit = omit,
        rerank: bool | Omit = omit,
        rerank_model: str | Omit = omit,
        rerank_top_n: int | Omit = omit,
        top_k: int | 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,
    ) -> VectorStoreQueryResponse:
        """
        Query documents using similarity search with optional reranking.

        The primary endpoint for semantic search, question-answering, and RAG
        (Retrieval-Augmented Generation) applications. Returns documents ranked by
        relevance to your query text, with similarity scores.

        **Query Types:**

        - `semantic` (default): Meaning-based search using embedding similarity. Best
          for Q&A, conceptual search, and finding semantically related content even
          without exact keyword matches.
        - `lexical`: Traditional keyword-based text search (BM25). Best for exact phrase
          matching, proper nouns, and cases where keyword presence is more important
          than semantic meaning.
        - `hybrid`: Combines semantic and lexical with weighted scoring. Best for
          maximum recall by finding documents that match either semantically or
          lexically.

        **Metadata Filtering:** Narrow search scope by applying metadata filters (e.g.,
        only search documents where `category: "technical"`). Filters are applied before
        similarity search for efficiency.

        **Reranking (Advanced):** Optionally improve result quality using a
        cross-encoder reranking model. The reranker re-scores the top results using a
        more sophisticated model that considers the full query-document pair (not just
        embeddings). This adds 100-500ms latency but significantly improves precision
        for critical applications.

        **Reranking Strategy:** Set `top_k` higher than your desired final count
        (e.g., 50) to retrieve more candidates from the initial search. Then set
        `rerank_top_n` to your desired final count (e.g., 10) to return only the most
        relevant documents after reranking. This two-stage approach maximizes both
        recall and precision.

        **Performance Metrics:** The response includes detailed timing breakdowns
        (embedding generation time, index query time, reranking time) to help you
        optimize your search pipeline and understand where latency is coming from.

        **Similarity Scores:** Each result includes a `score` field indicating
        relevance. Higher scores mean more relevant. Score ranges and semantics vary by
        query type (semantic scores are cosine similarity, lexical scores are BM25,
        hybrid scores are combined).

        Args:
          vector_store_name: The name of the vector store

          content: Text content for documents.

          filter: Metadata filter expression

          include_vectors: Include embedding vectors in response

          query_type: Query type: semantic, lexical, or hybrid

          rerank: Enable reranking of search results

          rerank_model: Reranking model to use (uses system default if not specified)

          rerank_top_n: Number of results after reranking (defaults to top_k)

          top_k: Number of search results to return

          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 vector_store_name:
            raise ValueError(f"Expected a non-empty value for `vector_store_name` but received {vector_store_name!r}")
        return self._post(
            f"/v5/vector-stores/{vector_store_name}/query",
            body=maybe_transform(
                {
                    "content": content,
                    "filter": filter,
                    "include_vectors": include_vectors,
                    "query_type": query_type,
                    "rerank": rerank,
                    "rerank_model": rerank_model,
                    "rerank_top_n": rerank_top_n,
                    "top_k": top_k,
                },
                vector_store_query_params.VectorStoreQueryParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStoreQueryResponse,
        )

    def upsert(
        self,
        vector_store_name: str,
        *,
        vectors: Iterable[vector_store_upsert_params.Vector],
        # 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,
    ) -> VectorStoreUpsertResponse:
        """
        Insert new documents or update existing ones in a vector store.

        **Upsert Behavior:** If a document ID already exists, it will be completely
        replaced with the new content and metadata. The previous document's text,
        embedding, and all metadata fields are discarded. If the ID doesn't exist, a new
        document is created.

        **Automatic Embedding:** Text content is automatically embedded using the vector
        store's configured embedding model. You don't need to generate embeddings
        yourself - just provide the text.

        **Batch Operations:** This endpoint supports batch operations with partial
        success handling. If some documents fail (e.g., due to validation errors),
        others will still be processed. Check the response for detailed success/failure
        counts and error messages.

        **Metadata:** Supports nested metadata with string, number, boolean, dict
        (object), and list types. None values are not allowed - omit the field or use an
        empty string instead.

        Args:
          vector_store_name: The name of the vector store

          vectors: Array of documents to upsert

          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 vector_store_name:
            raise ValueError(f"Expected a non-empty value for `vector_store_name` but received {vector_store_name!r}")
        return self._post(
            f"/v5/vector-stores/{vector_store_name}/upsert",
            body=maybe_transform({"vectors": vectors}, vector_store_upsert_params.VectorStoreUpsertParams),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStoreUpsertResponse,
        )


class AsyncVectorStoresResource(AsyncAPIResource):
    @cached_property
    def vectors(self) -> AsyncVectorsResource:
        return AsyncVectorsResource(self._client)

    @cached_property
    def with_raw_response(self) -> AsyncVectorStoresResourceWithRawResponse:
        """
        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/scaleapi/sgp-python-beta#accessing-raw-response-data-eg-headers
        """
        return AsyncVectorStoresResourceWithRawResponse(self)

    @cached_property
    def with_streaming_response(self) -> AsyncVectorStoresResourceWithStreamingResponse:
        """
        An alternative to `.with_raw_response` that doesn't eagerly read the response body.

        For more information, see https://www.github.com/scaleapi/sgp-python-beta#with_streaming_response
        """
        return AsyncVectorStoresResourceWithStreamingResponse(self)

    async def create(
        self,
        *,
        embedding_model: Literal[
            "sentence-transformers/all-MiniLM-L12-v2",
            "sentence-transformers/all-mpnet-base-v2",
            "sentence-transformers/multi-qa-distilbert-cos-v1",
            "sentence-transformers/paraphrase-multilingual-mpnet-base-v2",
            "openai/text-embedding-ada-002",
            "openai/text-embedding-3-small",
            "openai/text-embedding-3-large",
            "embed-english-v3.0",
            "embed-english-light-v3.0",
            "embed-multilingual-v3.0",
            "gemini/text-embedding-005",
            "gemini/text-multilingual-embedding-002",
            "gemini/gemini-embedding-001",
        ],
        name: str,
        indexed_metadata_fields: Dict[str, Literal["string", "number", "boolean", "object", "list"]] | 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,
    ) -> VectorStore:
        """
        Create a new vector store for storing and querying document embeddings.

        The vector store name must be unique within your account and follow naming
        conventions (3-63 characters, alphanumeric with hyphens/underscores). Once
        created, the `name`, `embedding_model`, and `embedding_dimensions` are
        permanently locked and cannot be changed. To use a different model, create a new
        vector store.

        **Indexed Fields:** Optionally specify metadata fields to index at creation time
        for faster filtering. You can add more indexed fields later using the configure
        endpoint, but cannot remove them once added.

        **Note:** The `embedding_dimensions` is automatically determined by your chosen
        `embedding_model` and cannot be manually specified (e.g., text-embedding-3-small
        = 1536 dimensions).

        Args:
          embedding_model: The embedding model to use

          name: A unique name for the vector store within the account

          indexed_metadata_fields: Dictionary mapping metadata field names to their types for efficient filtering.
              Only STRING, NUMBER, and BOOLEAN types can be indexed.

          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(
            "/v5/vector-stores/create",
            body=await async_maybe_transform(
                {
                    "embedding_model": embedding_model,
                    "name": name,
                    "indexed_metadata_fields": indexed_metadata_fields,
                },
                vector_store_create_params.VectorStoreCreateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStore,
        )

    async def retrieve(
        self,
        vector_store_name: 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,
    ) -> VectorStore:
        """
        Retrieve detailed configuration and metadata for a specific vector store.

        Returns the store's embedding model, dimensions, indexed metadata field
        definitions, creation timestamp, and last update timestamp. Use this to verify
        store settings before performing operations or to display store information in
        your application.

        Args:
          vector_store_name: The name of the vector 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 vector_store_name:
            raise ValueError(f"Expected a non-empty value for `vector_store_name` but received {vector_store_name!r}")
        return await self._get(
            f"/v5/vector-stores/{vector_store_name}",
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStore,
        )

    def list(
        self,
        *,
        ending_before: str | Omit = omit,
        limit: int | Omit = omit,
        sort_by: str | Omit = omit,
        sort_order: Literal["asc", "desc"] | Omit = omit,
        starting_after: 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[VectorStore, AsyncCursorPage[VectorStore]]:
        """
        List all vector stores in your account with pagination.

        Returns vector stores sorted by creation date (newest first). Each store
        includes its configuration, embedding model, dimensions, indexed fields, and
        timestamps.

        Args:
          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(
            "/v5/vector-stores",
            page=AsyncCursorPage[VectorStore],
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                query=maybe_transform(
                    {
                        "ending_before": ending_before,
                        "limit": limit,
                        "sort_by": sort_by,
                        "sort_order": sort_order,
                        "starting_after": starting_after,
                    },
                    vector_store_list_params.VectorStoreListParams,
                ),
            ),
            model=VectorStore,
        )

    async def delete(
        self,
        vector_store_name: str,
        *,
        filter: Dict[str, object] | Omit = omit,
        ids: 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,
    ) -> VectorStoreDeleteResponse:
        """
        Delete documents from a vector store by specific IDs or metadata filter
        criteria.

        **Delete by IDs:** Provide an array of document IDs to delete specific
        documents. Documents that don't exist are silently skipped.

        **Delete by Filter:** Use metadata filters to delete all documents matching
        criteria (e.g., delete all documents with `status: "archived"`). The filter
        cannot be empty - you must specify at least one condition. To delete all
        documents, use the drop endpoint to delete the entire vector store instead.

        **Filter Operators:** Supports MongoDB-style operators including equality
        (`{"field": "value"}`), comparison (`$gt`, `$gte`, `$lt`, `$lte`, `$eq`, `$ne`),
        logical (`$and`, `$or`, `$not`), and membership (`$in`, `$nin`). Filters work on
        indexed metadata fields for best performance.

        **Safety Tip:** Use the count endpoint with the same filter first to preview how
        many documents will be deleted before executing the deletion.

        Args:
          vector_store_name: The name of the vector store

          filter: Metadata filter expression for deletion

          ids: Array of document IDs 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 vector_store_name:
            raise ValueError(f"Expected a non-empty value for `vector_store_name` but received {vector_store_name!r}")
        return await self._post(
            f"/v5/vector-stores/{vector_store_name}/delete",
            body=await async_maybe_transform(
                {
                    "filter": filter,
                    "ids": ids,
                },
                vector_store_delete_params.VectorStoreDeleteParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStoreDeleteResponse,
        )

    async def configure(
        self,
        vector_store_name: str,
        *,
        indexed_metadata_fields: Dict[str, Literal["string", "number", "boolean", "object", "list"]],
        # 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,
    ) -> VectorStore:
        """
        Update the indexed metadata fields configuration for a vector store.

        Indexing metadata fields dramatically improves filtering performance during
        queries, list, and count operations by creating database indexes on those
        fields. Without indexing, filters perform full collection scans.

        **Field Types:** Only STRING, NUMBER, and BOOLEAN fields can be indexed (max 20
        fields total). OBJECT and LIST types are stored but cannot be indexed for
        filtering.

        **Adding Fields:** You can add new indexed fields at any time. Existing
        documents will have their metadata automatically indexed if they contain those
        fields.

        **Removing Fields:** Currently, indexed fields cannot be removed once added.
        Plan your indexed fields carefully based on your filtering needs.

        **Note:** The `name`, `embedding_model`, and `embedding_dimensions` cannot be
        changed after creation.

        Args:
          vector_store_name: The name of the vector store

          indexed_metadata_fields: Dictionary mapping metadata field names to their types. Only STRING, NUMBER, and
              BOOLEAN types can be indexed.

          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 vector_store_name:
            raise ValueError(f"Expected a non-empty value for `vector_store_name` but received {vector_store_name!r}")
        return await self._post(
            f"/v5/vector-stores/{vector_store_name}/configure",
            body=await async_maybe_transform(
                {"indexed_metadata_fields": indexed_metadata_fields},
                vector_store_configure_params.VectorStoreConfigureParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStore,
        )

    async def count(
        self,
        vector_store_name: str,
        *,
        filter: Dict[str, 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,
    ) -> VectorStoreCountResponse:
        """
        Count documents in a vector store, optionally filtered by metadata.

        **Use Cases:**

        - Monitor vector store size and growth over time
        - Preview how many documents match a filter before deleting (safety check)
        - Validate data ingestion by counting expected vs actual documents
        - Check distribution of documents across metadata categories

        **Filtering:** Apply the same metadata filter syntax as delete/list operations.
        An empty filter or no filter counts all documents in the store.

        Args:
          vector_store_name: The name of the vector store

          filter: Metadata filter expression

          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 vector_store_name:
            raise ValueError(f"Expected a non-empty value for `vector_store_name` but received {vector_store_name!r}")
        return await self._post(
            f"/v5/vector-stores/{vector_store_name}/count",
            body=await async_maybe_transform({"filter": filter}, vector_store_count_params.VectorStoreCountParams),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStoreCountResponse,
        )

    async def drop(
        self,
        vector_store_name: 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,
    ) -> VectorStoreDropResponse:
        """
        Permanently delete a vector store and all its contents.

        **⚠️ WARNING:** This is a destructive operation that cannot be undone. All
        documents, embeddings, metadata, and index configurations will be permanently
        deleted. There is no way to recover the data after deletion.

        Use the count endpoint first to verify the number of documents before deleting
        the entire store.

        Args:
          vector_store_name: The name of the vector 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 vector_store_name:
            raise ValueError(f"Expected a non-empty value for `vector_store_name` but received {vector_store_name!r}")
        return await self._post(
            f"/v5/vector-stores/{vector_store_name}/drop",
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStoreDropResponse,
        )

    async def query(
        self,
        vector_store_name: str,
        *,
        content: TextContentParam,
        filter: Dict[str, object] | Omit = omit,
        include_vectors: bool | Omit = omit,
        query_type: Literal["semantic", "lexical", "hybrid"] | Omit = omit,
        rerank: bool | Omit = omit,
        rerank_model: str | Omit = omit,
        rerank_top_n: int | Omit = omit,
        top_k: int | 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,
    ) -> VectorStoreQueryResponse:
        """
        Query documents using similarity search with optional reranking.

        The primary endpoint for semantic search, question-answering, and RAG
        (Retrieval-Augmented Generation) applications. Returns documents ranked by
        relevance to your query text, with similarity scores.

        **Query Types:**

        - `semantic` (default): Meaning-based search using embedding similarity. Best
          for Q&A, conceptual search, and finding semantically related content even
          without exact keyword matches.
        - `lexical`: Traditional keyword-based text search (BM25). Best for exact phrase
          matching, proper nouns, and cases where keyword presence is more important
          than semantic meaning.
        - `hybrid`: Combines semantic and lexical with weighted scoring. Best for
          maximum recall by finding documents that match either semantically or
          lexically.

        **Metadata Filtering:** Narrow search scope by applying metadata filters (e.g.,
        only search documents where `category: "technical"`). Filters are applied before
        similarity search for efficiency.

        **Reranking (Advanced):** Optionally improve result quality using a
        cross-encoder reranking model. The reranker re-scores the top results using a
        more sophisticated model that considers the full query-document pair (not just
        embeddings). This adds 100-500ms latency but significantly improves precision
        for critical applications.

        **Reranking Strategy:** Set `top_k` higher than your desired final count
        (e.g., 50) to retrieve more candidates from the initial search. Then set
        `rerank_top_n` to your desired final count (e.g., 10) to return only the most
        relevant documents after reranking. This two-stage approach maximizes both
        recall and precision.

        **Performance Metrics:** The response includes detailed timing breakdowns
        (embedding generation time, index query time, reranking time) to help you
        optimize your search pipeline and understand where latency is coming from.

        **Similarity Scores:** Each result includes a `score` field indicating
        relevance. Higher scores mean more relevant. Score ranges and semantics vary by
        query type (semantic scores are cosine similarity, lexical scores are BM25,
        hybrid scores are combined).

        Args:
          vector_store_name: The name of the vector store

          content: Text content for documents.

          filter: Metadata filter expression

          include_vectors: Include embedding vectors in response

          query_type: Query type: semantic, lexical, or hybrid

          rerank: Enable reranking of search results

          rerank_model: Reranking model to use (uses system default if not specified)

          rerank_top_n: Number of results after reranking (defaults to top_k)

          top_k: Number of search results to return

          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 vector_store_name:
            raise ValueError(f"Expected a non-empty value for `vector_store_name` but received {vector_store_name!r}")
        return await self._post(
            f"/v5/vector-stores/{vector_store_name}/query",
            body=await async_maybe_transform(
                {
                    "content": content,
                    "filter": filter,
                    "include_vectors": include_vectors,
                    "query_type": query_type,
                    "rerank": rerank,
                    "rerank_model": rerank_model,
                    "rerank_top_n": rerank_top_n,
                    "top_k": top_k,
                },
                vector_store_query_params.VectorStoreQueryParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStoreQueryResponse,
        )

    async def upsert(
        self,
        vector_store_name: str,
        *,
        vectors: Iterable[vector_store_upsert_params.Vector],
        # 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,
    ) -> VectorStoreUpsertResponse:
        """
        Insert new documents or update existing ones in a vector store.

        **Upsert Behavior:** If a document ID already exists, it will be completely
        replaced with the new content and metadata. The previous document's text,
        embedding, and all metadata fields are discarded. If the ID doesn't exist, a new
        document is created.

        **Automatic Embedding:** Text content is automatically embedded using the vector
        store's configured embedding model. You don't need to generate embeddings
        yourself - just provide the text.

        **Batch Operations:** This endpoint supports batch operations with partial
        success handling. If some documents fail (e.g., due to validation errors),
        others will still be processed. Check the response for detailed success/failure
        counts and error messages.

        **Metadata:** Supports nested metadata with string, number, boolean, dict
        (object), and list types. None values are not allowed - omit the field or use an
        empty string instead.

        Args:
          vector_store_name: The name of the vector store

          vectors: Array of documents to upsert

          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 vector_store_name:
            raise ValueError(f"Expected a non-empty value for `vector_store_name` but received {vector_store_name!r}")
        return await self._post(
            f"/v5/vector-stores/{vector_store_name}/upsert",
            body=await async_maybe_transform({"vectors": vectors}, vector_store_upsert_params.VectorStoreUpsertParams),
            options=make_request_options(
                extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
            ),
            cast_to=VectorStoreUpsertResponse,
        )


class VectorStoresResourceWithRawResponse:
    def __init__(self, vector_stores: VectorStoresResource) -> None:
        self._vector_stores = vector_stores

        self.create = to_raw_response_wrapper(
            vector_stores.create,
        )
        self.retrieve = to_raw_response_wrapper(
            vector_stores.retrieve,
        )
        self.list = to_raw_response_wrapper(
            vector_stores.list,
        )
        self.delete = to_raw_response_wrapper(
            vector_stores.delete,
        )
        self.configure = to_raw_response_wrapper(
            vector_stores.configure,
        )
        self.count = to_raw_response_wrapper(
            vector_stores.count,
        )
        self.drop = to_raw_response_wrapper(
            vector_stores.drop,
        )
        self.query = to_raw_response_wrapper(
            vector_stores.query,
        )
        self.upsert = to_raw_response_wrapper(
            vector_stores.upsert,
        )

    @cached_property
    def vectors(self) -> VectorsResourceWithRawResponse:
        return VectorsResourceWithRawResponse(self._vector_stores.vectors)


class AsyncVectorStoresResourceWithRawResponse:
    def __init__(self, vector_stores: AsyncVectorStoresResource) -> None:
        self._vector_stores = vector_stores

        self.create = async_to_raw_response_wrapper(
            vector_stores.create,
        )
        self.retrieve = async_to_raw_response_wrapper(
            vector_stores.retrieve,
        )
        self.list = async_to_raw_response_wrapper(
            vector_stores.list,
        )
        self.delete = async_to_raw_response_wrapper(
            vector_stores.delete,
        )
        self.configure = async_to_raw_response_wrapper(
            vector_stores.configure,
        )
        self.count = async_to_raw_response_wrapper(
            vector_stores.count,
        )
        self.drop = async_to_raw_response_wrapper(
            vector_stores.drop,
        )
        self.query = async_to_raw_response_wrapper(
            vector_stores.query,
        )
        self.upsert = async_to_raw_response_wrapper(
            vector_stores.upsert,
        )

    @cached_property
    def vectors(self) -> AsyncVectorsResourceWithRawResponse:
        return AsyncVectorsResourceWithRawResponse(self._vector_stores.vectors)


class VectorStoresResourceWithStreamingResponse:
    def __init__(self, vector_stores: VectorStoresResource) -> None:
        self._vector_stores = vector_stores

        self.create = to_streamed_response_wrapper(
            vector_stores.create,
        )
        self.retrieve = to_streamed_response_wrapper(
            vector_stores.retrieve,
        )
        self.list = to_streamed_response_wrapper(
            vector_stores.list,
        )
        self.delete = to_streamed_response_wrapper(
            vector_stores.delete,
        )
        self.configure = to_streamed_response_wrapper(
            vector_stores.configure,
        )
        self.count = to_streamed_response_wrapper(
            vector_stores.count,
        )
        self.drop = to_streamed_response_wrapper(
            vector_stores.drop,
        )
        self.query = to_streamed_response_wrapper(
            vector_stores.query,
        )
        self.upsert = to_streamed_response_wrapper(
            vector_stores.upsert,
        )

    @cached_property
    def vectors(self) -> VectorsResourceWithStreamingResponse:
        return VectorsResourceWithStreamingResponse(self._vector_stores.vectors)


class AsyncVectorStoresResourceWithStreamingResponse:
    def __init__(self, vector_stores: AsyncVectorStoresResource) -> None:
        self._vector_stores = vector_stores

        self.create = async_to_streamed_response_wrapper(
            vector_stores.create,
        )
        self.retrieve = async_to_streamed_response_wrapper(
            vector_stores.retrieve,
        )
        self.list = async_to_streamed_response_wrapper(
            vector_stores.list,
        )
        self.delete = async_to_streamed_response_wrapper(
            vector_stores.delete,
        )
        self.configure = async_to_streamed_response_wrapper(
            vector_stores.configure,
        )
        self.count = async_to_streamed_response_wrapper(
            vector_stores.count,
        )
        self.drop = async_to_streamed_response_wrapper(
            vector_stores.drop,
        )
        self.query = async_to_streamed_response_wrapper(
            vector_stores.query,
        )
        self.upsert = async_to_streamed_response_wrapper(
            vector_stores.upsert,
        )

    @cached_property
    def vectors(self) -> AsyncVectorsResourceWithStreamingResponse:
        return AsyncVectorsResourceWithStreamingResponse(self._vector_stores.vectors)
