# This file was auto-generated by Fern from our API Definition.

import typing
from json.decoder import JSONDecodeError

from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..core.pagination import AsyncPager, SyncPager
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..errors.bad_request_error import BadRequestError
from ..errors.conflict_error import ConflictError
from ..errors.forbidden_error import ForbiddenError
from ..errors.not_found_error import NotFoundError
from ..errors.too_many_requests_error import TooManyRequestsError
from ..types.bad_request_error_body import BadRequestErrorBody
from ..types.corpus_key import CorpusKey
from ..types.create_document_request import CreateDocumentRequest
from ..types.document import Document
from ..types.error import Error
from ..types.list_documents_response import ListDocumentsResponse
from ..types.not_found_error_body import NotFoundErrorBody
from ..types.summarize_document_response import SummarizeDocumentResponse

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class RawDocumentsClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper

    def list(
        self,
        corpus_key: CorpusKey,
        *,
        limit: typing.Optional[int] = None,
        metadata_filter: typing.Optional[str] = None,
        page_key: typing.Optional[str] = None,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[SyncPager[Document]]:
        """
        Retrieve a list of documents stored in a specific corpus. This endpoint
        provides an overview of document metadata without returning the full content of
        each document.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the queried corpus.

        limit : typing.Optional[int]
            The maximum number of documents to return at one time.

        metadata_filter : typing.Optional[str]
            Filter documents by metadata. Uses the same expression as a query metadata filter, but only
            allows filtering on document metadata.

        page_key : typing.Optional[str]
            Used to retrieve the next page of documents after the limit has been reached.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[SyncPager[Document]]
            List of documents.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/documents",
            base_url=self._client_wrapper.get_environment().default,
            method="GET",
            params={
                "limit": limit,
                "metadata_filter": metadata_filter,
                "page_key": page_key,
            },
            headers={
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListDocumentsResponse,
                    parse_obj_as(
                        type_=ListDocumentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _has_next = False
                _get_next = None
                if _parsed_response.metadata is not None:
                    _parsed_next = _parsed_response.metadata.page_key
                    _has_next = _parsed_next is not None and _parsed_next != ""
                    _get_next = lambda: self.list(
                        corpus_key,
                        limit=limit,
                        metadata_filter=metadata_filter,
                        page_key=_parsed_next,
                        request_timeout=request_timeout,
                        request_timeout_millis=request_timeout_millis,
                        request_options=request_options,
                    )
                _items = _parsed_response.documents
                return HttpResponse(
                    response=_response, data=SyncPager(has_next=_has_next, items=_items, get_next=_get_next)
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def create(
        self,
        corpus_key: CorpusKey,
        *,
        request: CreateDocumentRequest,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[Document]:
        """
        Add a document to a corpus. This endpoint supports two document formats, structured and core.

        * **Structured** documents have a more conventional structure that provide document sections
        and parts in a format created by Vectara's proprietary strategy automatically. You provide
        a logical document structure, and Vectara handles the partitioning.
        * **Core** documents differ in that they follow an advanced, granular structure that
        explicitly defines each document part in an array. Each part becomes a distinct,
        searchable item in query results. You have precise control over the document structure
        and content.

        For more details, see [Indexing](https://docs.vectara.com/docs/learn/select-ideal-indexing-api).

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the queried corpus.

        request : CreateDocumentRequest

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[Document]
            Document added to the corpus.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/documents",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            json=convert_and_respect_annotation_metadata(
                object_=request, annotation=CreateDocumentRequest, direction="write"
            ),
            headers={
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Document,
                    parse_obj_as(
                        type_=Document,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        BadRequestErrorBody,
                        parse_obj_as(
                            type_=BadRequestErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 409:
                raise ConflictError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get(
        self,
        corpus_key: CorpusKey,
        document_id: str,
        *,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[Document]:
        """
        Retrieve the content and metadata of a specific document, identified by its
        unique `document_id` from a specific corpus.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus containing the document to retrieve.

        document_id : str
            The document ID of the document to retrieve.
            This `document_id` must be percent encoded.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[Document]
            Successfully retrieved the document.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/documents/{jsonable_encoder(document_id)}",
            base_url=self._client_wrapper.get_environment().default,
            method="GET",
            headers={
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Document,
                    parse_obj_as(
                        type_=Document,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def delete(
        self,
        corpus_key: CorpusKey,
        document_id: str,
        *,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[None]:
        """
        Permanently delete a document identified by its unique `document_id` from a specific
        corpus. This operation cannot be undone, so use it with caution.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus with the document to delete.

        document_id : str
            The document ID of the document to delete.
            This `document_id` must be percent encoded.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/documents/{jsonable_encoder(document_id)}",
            base_url=self._client_wrapper.get_environment().default,
            method="DELETE",
            headers={
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def update(
        self,
        corpus_key: CorpusKey,
        document_id: str,
        *,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[Document]:
        """
        Updates document identified by its unique `document_id` from a specific
        corpus. The request body metadata is merged with the existing metadata,
        adding or modifying only the specified fields.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus with the document to update.

        document_id : str
            The document ID of the document to update.
            This `document_id` must be percent encoded.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            The metadata for a document as an arbitrary object. Properties of this object
            can be used by document level filter attributes.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[Document]
            Successfully updated the document.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/documents/{jsonable_encoder(document_id)}",
            base_url=self._client_wrapper.get_environment().default,
            method="PATCH",
            json={
                "metadata": metadata,
            },
            headers={
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Document,
                    parse_obj_as(
                        type_=Document,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def update_metadata(
        self,
        corpus_key: CorpusKey,
        document_id: str,
        *,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[Document]:
        """
        Replaces metadata of a document identified by its unique `document_id`
        from a specific corpus.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus with the document to update.

        document_id : str
            The document ID of the document to update.
            This `document_id` must be percent encoded.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            The metadata for a document as an arbitrary object. Properties of this object
            can be used by document level filter attributes.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[Document]
            Successfully updated the document.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/documents/{jsonable_encoder(document_id)}/metadata",
            base_url=self._client_wrapper.get_environment().default,
            method="PUT",
            json={
                "metadata": metadata,
            },
            headers={
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Document,
                    parse_obj_as(
                        type_=Document,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def summarize(
        self,
        corpus_key: CorpusKey,
        document_id: str,
        *,
        llm_name: str,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        prompt_template: typing.Optional[str] = OMIT,
        model_parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        stream_response: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[SummarizeDocumentResponse]:
        """
        Summarize a document identified by its unique `document_id` from a specific corpus.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus containing the document to retrieve.

        document_id : str
            The document ID of the document to retrieve.
            This `document_id` must be percent encoded.

        llm_name : str
            The name of the LLM.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        prompt_template : typing.Optional[str]
            The prompt template to use when generating the summary.
            Vectara manages both system and user roles and prompts for the generative
            LLM out of the box by default. However, users can override the
            `prompt_template` via this variable. The `prompt_template` is in the form of an
            Apache Velocity template. For more details on how to configure the
            `prompt_template`, see the [long-form documentation](https://docs.vectara.com/docs/prompts/vectara-prompt-engine).

        model_parameters : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            Optional parameters for the specified model used when generating the summary.

        stream_response : typing.Optional[bool]
            Indicates whether the response should be streamed or not.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[SummarizeDocumentResponse]
            Document summarization response on success.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/documents/{jsonable_encoder(document_id)}/summarize",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            json={
                "llm_name": llm_name,
                "prompt_template": prompt_template,
                "model_parameters": model_parameters,
                "stream_response": stream_response,
            },
            headers={
                "content-type": "application/json",
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SummarizeDocumentResponse,
                    parse_obj_as(
                        type_=SummarizeDocumentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)


class AsyncRawDocumentsClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def list(
        self,
        corpus_key: CorpusKey,
        *,
        limit: typing.Optional[int] = None,
        metadata_filter: typing.Optional[str] = None,
        page_key: typing.Optional[str] = None,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[AsyncPager[Document]]:
        """
        Retrieve a list of documents stored in a specific corpus. This endpoint
        provides an overview of document metadata without returning the full content of
        each document.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the queried corpus.

        limit : typing.Optional[int]
            The maximum number of documents to return at one time.

        metadata_filter : typing.Optional[str]
            Filter documents by metadata. Uses the same expression as a query metadata filter, but only
            allows filtering on document metadata.

        page_key : typing.Optional[str]
            Used to retrieve the next page of documents after the limit has been reached.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[AsyncPager[Document]]
            List of documents.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/documents",
            base_url=self._client_wrapper.get_environment().default,
            method="GET",
            params={
                "limit": limit,
                "metadata_filter": metadata_filter,
                "page_key": page_key,
            },
            headers={
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListDocumentsResponse,
                    parse_obj_as(
                        type_=ListDocumentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _has_next = False
                _get_next = None
                if _parsed_response.metadata is not None:
                    _parsed_next = _parsed_response.metadata.page_key
                    _has_next = _parsed_next is not None and _parsed_next != ""
                    _get_next = lambda: self.list(
                        corpus_key,
                        limit=limit,
                        metadata_filter=metadata_filter,
                        page_key=_parsed_next,
                        request_timeout=request_timeout,
                        request_timeout_millis=request_timeout_millis,
                        request_options=request_options,
                    )
                _items = _parsed_response.documents
                return AsyncHttpResponse(
                    response=_response, data=AsyncPager(has_next=_has_next, items=_items, get_next=_get_next)
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def create(
        self,
        corpus_key: CorpusKey,
        *,
        request: CreateDocumentRequest,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[Document]:
        """
        Add a document to a corpus. This endpoint supports two document formats, structured and core.

        * **Structured** documents have a more conventional structure that provide document sections
        and parts in a format created by Vectara's proprietary strategy automatically. You provide
        a logical document structure, and Vectara handles the partitioning.
        * **Core** documents differ in that they follow an advanced, granular structure that
        explicitly defines each document part in an array. Each part becomes a distinct,
        searchable item in query results. You have precise control over the document structure
        and content.

        For more details, see [Indexing](https://docs.vectara.com/docs/learn/select-ideal-indexing-api).

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the queried corpus.

        request : CreateDocumentRequest

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[Document]
            Document added to the corpus.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/documents",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            json=convert_and_respect_annotation_metadata(
                object_=request, annotation=CreateDocumentRequest, direction="write"
            ),
            headers={
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Document,
                    parse_obj_as(
                        type_=Document,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        BadRequestErrorBody,
                        parse_obj_as(
                            type_=BadRequestErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 409:
                raise ConflictError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get(
        self,
        corpus_key: CorpusKey,
        document_id: str,
        *,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[Document]:
        """
        Retrieve the content and metadata of a specific document, identified by its
        unique `document_id` from a specific corpus.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus containing the document to retrieve.

        document_id : str
            The document ID of the document to retrieve.
            This `document_id` must be percent encoded.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[Document]
            Successfully retrieved the document.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/documents/{jsonable_encoder(document_id)}",
            base_url=self._client_wrapper.get_environment().default,
            method="GET",
            headers={
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Document,
                    parse_obj_as(
                        type_=Document,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def delete(
        self,
        corpus_key: CorpusKey,
        document_id: str,
        *,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[None]:
        """
        Permanently delete a document identified by its unique `document_id` from a specific
        corpus. This operation cannot be undone, so use it with caution.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus with the document to delete.

        document_id : str
            The document ID of the document to delete.
            This `document_id` must be percent encoded.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/documents/{jsonable_encoder(document_id)}",
            base_url=self._client_wrapper.get_environment().default,
            method="DELETE",
            headers={
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def update(
        self,
        corpus_key: CorpusKey,
        document_id: str,
        *,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[Document]:
        """
        Updates document identified by its unique `document_id` from a specific
        corpus. The request body metadata is merged with the existing metadata,
        adding or modifying only the specified fields.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus with the document to update.

        document_id : str
            The document ID of the document to update.
            This `document_id` must be percent encoded.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            The metadata for a document as an arbitrary object. Properties of this object
            can be used by document level filter attributes.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[Document]
            Successfully updated the document.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/documents/{jsonable_encoder(document_id)}",
            base_url=self._client_wrapper.get_environment().default,
            method="PATCH",
            json={
                "metadata": metadata,
            },
            headers={
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Document,
                    parse_obj_as(
                        type_=Document,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def update_metadata(
        self,
        corpus_key: CorpusKey,
        document_id: str,
        *,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[Document]:
        """
        Replaces metadata of a document identified by its unique `document_id`
        from a specific corpus.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus with the document to update.

        document_id : str
            The document ID of the document to update.
            This `document_id` must be percent encoded.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            The metadata for a document as an arbitrary object. Properties of this object
            can be used by document level filter attributes.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[Document]
            Successfully updated the document.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/documents/{jsonable_encoder(document_id)}/metadata",
            base_url=self._client_wrapper.get_environment().default,
            method="PUT",
            json={
                "metadata": metadata,
            },
            headers={
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Document,
                    parse_obj_as(
                        type_=Document,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 429:
                raise TooManyRequestsError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def summarize(
        self,
        corpus_key: CorpusKey,
        document_id: str,
        *,
        llm_name: str,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        prompt_template: typing.Optional[str] = OMIT,
        model_parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
        stream_response: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[SummarizeDocumentResponse]:
        """
        Summarize a document identified by its unique `document_id` from a specific corpus.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus containing the document to retrieve.

        document_id : str
            The document ID of the document to retrieve.
            This `document_id` must be percent encoded.

        llm_name : str
            The name of the LLM.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        prompt_template : typing.Optional[str]
            The prompt template to use when generating the summary.
            Vectara manages both system and user roles and prompts for the generative
            LLM out of the box by default. However, users can override the
            `prompt_template` via this variable. The `prompt_template` is in the form of an
            Apache Velocity template. For more details on how to configure the
            `prompt_template`, see the [long-form documentation](https://docs.vectara.com/docs/prompts/vectara-prompt-engine).

        model_parameters : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
            Optional parameters for the specified model used when generating the summary.

        stream_response : typing.Optional[bool]
            Indicates whether the response should be streamed or not.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[SummarizeDocumentResponse]
            Document summarization response on success.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/documents/{jsonable_encoder(document_id)}/summarize",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            json={
                "llm_name": llm_name,
                "prompt_template": prompt_template,
                "model_parameters": model_parameters,
                "stream_response": stream_response,
            },
            headers={
                "content-type": "application/json",
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SummarizeDocumentResponse,
                    parse_obj_as(
                        type_=SummarizeDocumentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)
