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

import contextlib
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.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.not_found_error import NotFoundError
from ..types.dataset_expansion_response import DatasetExpansionResponse
from ..types.dataset_export_job_public import DatasetExportJobPublic
from ..types.dataset_item_changes_public import DatasetItemChangesPublic
from ..types.dataset_item_filter import DatasetItemFilter
from ..types.dataset_item_page_compare import DatasetItemPageCompare
from ..types.dataset_item_page_public import DatasetItemPagePublic
from ..types.dataset_item_public import DatasetItemPublic
from ..types.dataset_item_update import DatasetItemUpdate
from ..types.dataset_item_write import DatasetItemWrite
from ..types.dataset_item_write_source import DatasetItemWriteSource
from ..types.dataset_page_public import DatasetPagePublic
from ..types.dataset_public import DatasetPublic
from ..types.dataset_version_diff import DatasetVersionDiff
from ..types.dataset_version_page_public import DatasetVersionPagePublic
from ..types.dataset_version_public import DatasetVersionPublic
from ..types.evaluator_item_write import EvaluatorItemWrite
from ..types.execution_policy_write import ExecutionPolicyWrite
from ..types.json_node import JsonNode
from ..types.page_columns import PageColumns
from ..types.project_stats_public import ProjectStatsPublic
from ..types.span_enrichment_options import SpanEnrichmentOptions
from ..types.trace_enrichment_options import TraceEnrichmentOptions
from .types.dataset_update_visibility import DatasetUpdateVisibility
from .types.dataset_write_type import DatasetWriteType
from .types.dataset_write_visibility import DatasetWriteVisibility

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


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

    def apply_dataset_item_changes(
        self,
        id: str,
        *,
        request: DatasetItemChangesPublic,
        override: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[DatasetVersionPublic]:
        """
        Apply delta changes (add, edit, delete) to a dataset version with conflict detection.

        This endpoint:
        - Creates a new version with the applied changes
        - Validates that baseVersion matches the latest version (unless override=true)
        - Returns 409 Conflict if baseVersion is stale and override is not set

        Use `override=true` query parameter to force version creation even with stale baseVersion.

        Parameters
        ----------
        id : str

        request : DatasetItemChangesPublic

        override : typing.Optional[bool]

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

        Returns
        -------
        HttpResponse[DatasetVersionPublic]
            Version created successfully
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/items/changes",
            method="POST",
            params={
                "override": override,
            },
            json=request,
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetVersionPublic,
                    parse_obj_as(
                        type_=DatasetVersionPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 409:
                raise ConflictError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def batch_update_dataset_items(
        self,
        *,
        update: DatasetItemUpdate,
        ids: typing.Optional[typing.Sequence[str]] = OMIT,
        filters: typing.Optional[typing.Sequence[DatasetItemFilter]] = OMIT,
        dataset_id: typing.Optional[str] = OMIT,
        merge_tags: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[None]:
        """
        Update multiple dataset items

        Parameters
        ----------
        update : DatasetItemUpdate

        ids : typing.Optional[typing.Sequence[str]]
            List of dataset item IDs to update (max 1000). Mutually exclusive with 'filters'.

        filters : typing.Optional[typing.Sequence[DatasetItemFilter]]

        dataset_id : typing.Optional[str]
            Dataset ID. Required when using 'filters', optional when using 'ids'.

        merge_tags : typing.Optional[bool]
            If true, merge tags with existing tags instead of replacing them. Default: false. When using 'filters', this is automatically set to true.

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/private/datasets/items/batch",
            method="PATCH",
            json={
                "ids": ids,
                "filters": convert_and_respect_annotation_metadata(
                    object_=filters, annotation=typing.Sequence[DatasetItemFilter], direction="write"
                ),
                "dataset_id": dataset_id,
                "update": convert_and_respect_annotation_metadata(
                    object_=update, annotation=DatasetItemUpdate, direction="write"
                ),
                "merge_tags": merge_tags,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def find_datasets(
        self,
        *,
        page: typing.Optional[int] = None,
        size: typing.Optional[int] = None,
        with_experiments_only: typing.Optional[bool] = None,
        with_optimizations_only: typing.Optional[bool] = None,
        prompt_id: typing.Optional[str] = None,
        project_id: typing.Optional[str] = None,
        name: typing.Optional[str] = None,
        sorting: typing.Optional[str] = None,
        filters: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[DatasetPagePublic]:
        """
        Find datasets

        Parameters
        ----------
        page : typing.Optional[int]

        size : typing.Optional[int]

        with_experiments_only : typing.Optional[bool]

        with_optimizations_only : typing.Optional[bool]

        prompt_id : typing.Optional[str]

        project_id : typing.Optional[str]

        name : typing.Optional[str]

        sorting : typing.Optional[str]

        filters : typing.Optional[str]

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

        Returns
        -------
        HttpResponse[DatasetPagePublic]
            Dataset resource
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/private/datasets",
            method="GET",
            params={
                "page": page,
                "size": size,
                "with_experiments_only": with_experiments_only,
                "with_optimizations_only": with_optimizations_only,
                "prompt_id": prompt_id,
                "project_id": project_id,
                "name": name,
                "sorting": sorting,
                "filters": filters,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetPagePublic,
                    parse_obj_as(
                        type_=DatasetPagePublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def create_dataset(
        self,
        *,
        name: str,
        id: typing.Optional[str] = OMIT,
        project_id: typing.Optional[str] = OMIT,
        project_name: typing.Optional[str] = OMIT,
        type: typing.Optional[DatasetWriteType] = OMIT,
        visibility: typing.Optional[DatasetWriteVisibility] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        description: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[None]:
        """
        Create dataset

        Parameters
        ----------
        name : str

        id : typing.Optional[str]

        project_id : typing.Optional[str]
            Project ID. Takes precedence over project_name when both are provided.

        project_name : typing.Optional[str]
            For project scope, specify either project_id or project_name. If project_name is provided and the project does not exist, it will be created. Ignored when project_id is provided. If neither is provided, the dataset is created at workspace level.

        type : typing.Optional[DatasetWriteType]

        visibility : typing.Optional[DatasetWriteVisibility]

        tags : typing.Optional[typing.Sequence[str]]

        description : typing.Optional[str]

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/private/datasets",
            method="POST",
            json={
                "id": id,
                "name": name,
                "project_id": project_id,
                "project_name": project_name,
                "type": type,
                "visibility": visibility,
                "tags": tags,
                "description": description,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def create_or_update_dataset_items(
        self,
        *,
        items: typing.Sequence[DatasetItemWrite],
        dataset_name: typing.Optional[str] = OMIT,
        dataset_id: typing.Optional[str] = OMIT,
        batch_group_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[None]:
        """
        Create/update dataset items based on dataset item id

        Parameters
        ----------
        items : typing.Sequence[DatasetItemWrite]

        dataset_name : typing.Optional[str]
            If null, dataset_id must be provided

        dataset_id : typing.Optional[str]
            If null, dataset_name must be provided

        batch_group_id : typing.Optional[str]
            Optional batch group ID to group multiple batches into a single dataset version. If null, mutates the latest version instead of creating a new one.

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/private/datasets/items",
            method="PUT",
            json={
                "dataset_name": dataset_name,
                "dataset_id": dataset_id,
                "items": convert_and_respect_annotation_metadata(
                    object_=items, annotation=typing.Sequence[DatasetItemWrite], direction="write"
                ),
                "batch_group_id": batch_group_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def create_dataset_items_from_csv(
        self,
        *,
        file: typing.Dict[str, typing.Optional[typing.Any]],
        dataset_id: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[None]:
        """
        Create dataset items from uploaded CSV file. CSV should have headers in the first row. Processing happens asynchronously in batches.

        Parameters
        ----------
        file : typing.Dict[str, typing.Optional[typing.Any]]

        dataset_id : str

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/private/datasets/items/from-csv",
            method="POST",
            data={
                "file": file,
                "dataset_id": dataset_id,
            },
            files={},
            headers={
                "content-type": "multipart/form-data",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def create_dataset_items_from_spans(
        self,
        dataset_id: str,
        *,
        span_ids: typing.Sequence[str],
        enrichment_options: SpanEnrichmentOptions,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[None]:
        """
        Create dataset items from spans with enriched metadata

        Parameters
        ----------
        dataset_id : str

        span_ids : typing.Sequence[str]
            Set of span IDs to add to the dataset

        enrichment_options : SpanEnrichmentOptions

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(dataset_id)}/items/from-spans",
            method="POST",
            json={
                "span_ids": span_ids,
                "enrichment_options": convert_and_respect_annotation_metadata(
                    object_=enrichment_options, annotation=SpanEnrichmentOptions, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def create_dataset_items_from_traces(
        self,
        dataset_id: str,
        *,
        trace_ids: typing.Sequence[str],
        enrichment_options: TraceEnrichmentOptions,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[None]:
        """
        Create dataset items from traces with enriched metadata

        Parameters
        ----------
        dataset_id : str

        trace_ids : typing.Sequence[str]
            Set of trace IDs to add to the dataset

        enrichment_options : TraceEnrichmentOptions

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(dataset_id)}/items/from-traces",
            method="POST",
            json={
                "trace_ids": trace_ids,
                "enrichment_options": convert_and_respect_annotation_metadata(
                    object_=enrichment_options, annotation=TraceEnrichmentOptions, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_dataset_by_id(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[DatasetPublic]:
        """
        Get dataset by id

        Parameters
        ----------
        id : str

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

        Returns
        -------
        HttpResponse[DatasetPublic]
            Dataset resource
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetPublic,
                    parse_obj_as(
                        type_=DatasetPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def update_dataset(
        self,
        id: str,
        *,
        name: str,
        description: typing.Optional[str] = OMIT,
        visibility: typing.Optional[DatasetUpdateVisibility] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[None]:
        """
        Update dataset by id

        Parameters
        ----------
        id : str

        name : str

        description : typing.Optional[str]

        visibility : typing.Optional[DatasetUpdateVisibility]

        tags : typing.Optional[typing.Sequence[str]]

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}",
            method="PUT",
            json={
                "name": name,
                "description": description,
                "visibility": visibility,
                "tags": tags,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def delete_dataset(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[None]:
        """
        Delete dataset by id

        Parameters
        ----------
        id : str

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def delete_dataset_by_name(
        self,
        *,
        dataset_name: str,
        project_name: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[None]:
        """
        Delete dataset by name

        Parameters
        ----------
        dataset_name : str

        project_name : typing.Optional[str]

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/private/datasets/delete",
            method="POST",
            json={
                "dataset_name": dataset_name,
                "project_name": project_name,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def delete_dataset_items(
        self,
        *,
        item_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        dataset_id: typing.Optional[str] = OMIT,
        filters: typing.Optional[typing.Sequence[DatasetItemFilter]] = OMIT,
        batch_group_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[None]:
        """
        Delete dataset items using one of two modes:
        1. **Delete by IDs**: Provide 'item_ids' to delete specific items by their IDs
        2. **Delete by filters**: Provide 'dataset_id' with optional 'filters' to delete items matching criteria

        When using filters, an empty 'filters' array will delete all items in the specified dataset.

        Parameters
        ----------
        item_ids : typing.Optional[typing.Sequence[str]]
            List of dataset item IDs to delete (max 1000). Use this to delete specific items by their IDs. Mutually exclusive with 'dataset_id' and 'filters'.

        dataset_id : typing.Optional[str]
            Dataset ID to scope the deletion. Required when using 'filters'. Mutually exclusive with 'item_ids'.

        filters : typing.Optional[typing.Sequence[DatasetItemFilter]]
            Filters to select dataset items to delete within the specified dataset. Must be used with 'dataset_id'. Mutually exclusive with 'item_ids'. Empty array means 'delete all items in the dataset'.

        batch_group_id : typing.Optional[str]
            Optional batch group ID to group multiple delete operations into a single dataset version. If null, mutates the latest version instead of creating a new one.

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/private/datasets/items/delete",
            method="POST",
            json={
                "item_ids": item_ids,
                "dataset_id": dataset_id,
                "filters": convert_and_respect_annotation_metadata(
                    object_=filters, annotation=typing.Sequence[DatasetItemFilter], direction="write"
                ),
                "batch_group_id": batch_group_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def delete_datasets_batch(
        self, *, ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[None]:
        """
        Delete datasets batch

        Parameters
        ----------
        ids : typing.Sequence[str]

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/private/datasets/delete-batch",
            method="POST",
            json={
                "ids": ids,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    @contextlib.contextmanager
    def download_dataset_export(
        self, job_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]:
        """
        Downloads the exported CSV file for a completed export job. This endpoint proxies the file download to avoid exposing internal storage URLs.

        Parameters
        ----------
        job_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response.

        Returns
        -------
        typing.Iterator[HttpResponse[typing.Iterator[bytes]]]
            CSV file content
        """
        with self._client_wrapper.httpx_client.stream(
            f"v1/private/datasets/export-jobs/{jsonable_encoder(job_id)}/download",
            method="GET",
            request_options=request_options,
        ) as _response:

            def stream() -> HttpResponse[typing.Iterator[bytes]]:
                try:
                    if 200 <= _response.status_code < 300:
                        _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None
                        return HttpResponse(
                            response=_response, data=(_chunk for _chunk in _response.iter_bytes(chunk_size=_chunk_size))
                        )
                    _response.read()
                    if _response.status_code == 400:
                        raise BadRequestError(
                            headers=dict(_response.headers),
                            body=typing.cast(
                                typing.Optional[typing.Any],
                                parse_obj_as(
                                    type_=typing.Optional[typing.Any],  # type: ignore
                                    object_=_response.json(),
                                ),
                            ),
                        )
                    if _response.status_code == 404:
                        raise NotFoundError(
                            headers=dict(_response.headers),
                            body=typing.cast(
                                typing.Optional[typing.Any],
                                parse_obj_as(
                                    type_=typing.Optional[typing.Any],  # type: ignore
                                    object_=_response.json(),
                                ),
                            ),
                        )
                    _response_json = _response.json()
                except JSONDecodeError:
                    raise ApiError(
                        status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
                    )
                raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

            yield stream()

    def expand_dataset(
        self,
        id: str,
        *,
        model: str,
        sample_count: typing.Optional[int] = OMIT,
        preserve_fields: typing.Optional[typing.Sequence[str]] = OMIT,
        variation_instructions: typing.Optional[str] = OMIT,
        custom_prompt: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[DatasetExpansionResponse]:
        """
        Generate synthetic dataset samples using LLM based on existing data patterns

        Parameters
        ----------
        id : str

        model : str
            The model to use for synthetic data generation

        sample_count : typing.Optional[int]
            Number of synthetic samples to generate

        preserve_fields : typing.Optional[typing.Sequence[str]]
            Fields to preserve patterns from original data

        variation_instructions : typing.Optional[str]
            Additional instructions for data variation

        custom_prompt : typing.Optional[str]
            Custom prompt to use for generation instead of auto-generated one

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

        Returns
        -------
        HttpResponse[DatasetExpansionResponse]
            Generated synthetic samples
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/expansions",
            method="POST",
            json={
                "model": model,
                "sample_count": sample_count,
                "preserve_fields": preserve_fields,
                "variation_instructions": variation_instructions,
                "custom_prompt": custom_prompt,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetExpansionResponse,
                    parse_obj_as(
                        type_=DatasetExpansionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def find_dataset_items_with_experiment_items(
        self,
        id: str,
        *,
        experiment_ids: str,
        page: typing.Optional[int] = None,
        size: typing.Optional[int] = None,
        filters: typing.Optional[str] = None,
        sorting: typing.Optional[str] = None,
        search: typing.Optional[str] = None,
        truncate: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[DatasetItemPageCompare]:
        """
        Find dataset items with experiment items

        Parameters
        ----------
        id : str

        experiment_ids : str

        page : typing.Optional[int]

        size : typing.Optional[int]

        filters : typing.Optional[str]

        sorting : typing.Optional[str]

        search : typing.Optional[str]

        truncate : typing.Optional[bool]

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

        Returns
        -------
        HttpResponse[DatasetItemPageCompare]
            Dataset item resource
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/items/experiments/items",
            method="GET",
            params={
                "page": page,
                "size": size,
                "experiment_ids": experiment_ids,
                "filters": filters,
                "sorting": sorting,
                "search": search,
                "truncate": truncate,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetItemPageCompare,
                    parse_obj_as(
                        type_=DatasetItemPageCompare,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_dataset_by_identifier(
        self,
        *,
        dataset_name: str,
        project_name: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[DatasetPublic]:
        """
        Get dataset by name

        Parameters
        ----------
        dataset_name : str

        project_name : typing.Optional[str]

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

        Returns
        -------
        HttpResponse[DatasetPublic]
            Dataset resource
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/private/datasets/retrieve",
            method="POST",
            json={
                "dataset_name": dataset_name,
                "project_name": project_name,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetPublic,
                    parse_obj_as(
                        type_=DatasetPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_dataset_experiment_items_stats(
        self,
        id: str,
        *,
        experiment_ids: str,
        filters: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[ProjectStatsPublic]:
        """
        Get experiment items stats for dataset

        Parameters
        ----------
        id : str

        experiment_ids : str

        filters : typing.Optional[str]

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

        Returns
        -------
        HttpResponse[ProjectStatsPublic]
            Experiment items stats resource
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/items/experiments/items/stats",
            method="GET",
            params={
                "experiment_ids": experiment_ids,
                "filters": filters,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ProjectStatsPublic,
                    parse_obj_as(
                        type_=ProjectStatsPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_dataset_export_job(
        self, job_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[DatasetExportJobPublic]:
        """
        Retrieves the current status of a dataset export job

        Parameters
        ----------
        job_id : str

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

        Returns
        -------
        HttpResponse[DatasetExportJobPublic]
            Export job details
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/export-jobs/{jsonable_encoder(job_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetExportJobPublic,
                    parse_obj_as(
                        type_=DatasetExportJobPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_dataset_export_jobs(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[typing.List[DatasetExportJobPublic]]:
        """
        Retrieves all export jobs for the workspace. This is used to restore the export panel state after page refresh.

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

        Returns
        -------
        HttpResponse[typing.List[DatasetExportJobPublic]]
            List of export jobs
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/private/datasets/export-jobs",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.List[DatasetExportJobPublic],
                    parse_obj_as(
                        type_=typing.List[DatasetExportJobPublic],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_dataset_item_by_id(
        self, item_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[DatasetItemPublic]:
        """
        Get dataset item by id

        Parameters
        ----------
        item_id : str

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

        Returns
        -------
        HttpResponse[DatasetItemPublic]
            Dataset item resource
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/items/{jsonable_encoder(item_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetItemPublic,
                    parse_obj_as(
                        type_=DatasetItemPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def patch_dataset_item(
        self,
        item_id: str,
        *,
        source: DatasetItemWriteSource,
        data: JsonNode,
        id: typing.Optional[str] = OMIT,
        trace_id: typing.Optional[str] = OMIT,
        span_id: typing.Optional[str] = OMIT,
        description: typing.Optional[str] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        evaluators: typing.Optional[typing.Sequence[EvaluatorItemWrite]] = OMIT,
        execution_policy: typing.Optional[ExecutionPolicyWrite] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[None]:
        """
        Partially update dataset item by id. Only provided fields will be updated.

        Parameters
        ----------
        item_id : str

        source : DatasetItemWriteSource

        data : JsonNode

        id : typing.Optional[str]

        trace_id : typing.Optional[str]

        span_id : typing.Optional[str]

        description : typing.Optional[str]

        tags : typing.Optional[typing.Sequence[str]]

        evaluators : typing.Optional[typing.Sequence[EvaluatorItemWrite]]

        execution_policy : typing.Optional[ExecutionPolicyWrite]

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/items/{jsonable_encoder(item_id)}",
            method="PATCH",
            json={
                "id": id,
                "trace_id": trace_id,
                "span_id": span_id,
                "source": source,
                "data": data,
                "description": description,
                "tags": tags,
                "evaluators": convert_and_respect_annotation_metadata(
                    object_=evaluators, annotation=typing.Sequence[EvaluatorItemWrite], direction="write"
                ),
                "execution_policy": convert_and_respect_annotation_metadata(
                    object_=execution_policy, annotation=ExecutionPolicyWrite, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_dataset_items(
        self,
        id: str,
        *,
        page: typing.Optional[int] = None,
        size: typing.Optional[int] = None,
        version: typing.Optional[str] = None,
        filters: typing.Optional[str] = None,
        truncate: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[DatasetItemPagePublic]:
        """
        Get dataset items

        Parameters
        ----------
        id : str

        page : typing.Optional[int]

        size : typing.Optional[int]

        version : typing.Optional[str]

        filters : typing.Optional[str]

        truncate : typing.Optional[bool]

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

        Returns
        -------
        HttpResponse[DatasetItemPagePublic]
            Dataset items resource
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/items",
            method="GET",
            params={
                "page": page,
                "size": size,
                "version": version,
                "filters": filters,
                "truncate": truncate,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetItemPagePublic,
                    parse_obj_as(
                        type_=DatasetItemPagePublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_dataset_items_output_columns(
        self,
        id: str,
        *,
        experiment_ids: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[PageColumns]:
        """
        Get dataset items output columns

        Parameters
        ----------
        id : str

        experiment_ids : typing.Optional[str]

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

        Returns
        -------
        HttpResponse[PageColumns]
            Dataset item output columns
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/items/experiments/items/output/columns",
            method="GET",
            params={
                "experiment_ids": experiment_ids,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PageColumns,
                    parse_obj_as(
                        type_=PageColumns,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def mark_dataset_export_job_viewed(
        self, job_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[None]:
        """
        Marks a dataset export job as viewed by setting the viewed_at timestamp. This is used to track that a user has seen a failed job's error message. This operation is idempotent.

        Parameters
        ----------
        job_id : str

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/export-jobs/{jsonable_encoder(job_id)}/mark-viewed",
            method="PUT",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def start_dataset_export(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[DatasetExportJobPublic]:
        """
        Initiates an asynchronous CSV export job for the dataset. Returns immediately with job details for polling.

        Parameters
        ----------
        id : str

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

        Returns
        -------
        HttpResponse[DatasetExportJobPublic]
            Existing export job in progress
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/export",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetExportJobPublic,
                    parse_obj_as(
                        type_=DatasetExportJobPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    @contextlib.contextmanager
    def stream_dataset_items(
        self,
        *,
        dataset_name: str,
        last_retrieved_id: typing.Optional[str] = OMIT,
        steam_limit: typing.Optional[int] = OMIT,
        dataset_version: typing.Optional[str] = OMIT,
        project_name: typing.Optional[str] = OMIT,
        filters: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]:
        """
        Stream dataset items

        Parameters
        ----------
        dataset_name : str

        last_retrieved_id : typing.Optional[str]

        steam_limit : typing.Optional[int]

        dataset_version : typing.Optional[str]

        project_name : typing.Optional[str]

        filters : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response.

        Returns
        -------
        typing.Iterator[HttpResponse[typing.Iterator[bytes]]]
            Dataset items stream or error during process
        """
        with self._client_wrapper.httpx_client.stream(
            "v1/private/datasets/items/stream",
            method="POST",
            json={
                "dataset_name": dataset_name,
                "last_retrieved_id": last_retrieved_id,
                "steam_limit": steam_limit,
                "dataset_version": dataset_version,
                "project_name": project_name,
                "filters": filters,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        ) as _response:

            def stream() -> HttpResponse[typing.Iterator[bytes]]:
                try:
                    if 200 <= _response.status_code < 300:
                        _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None
                        return HttpResponse(
                            response=_response, data=(_chunk for _chunk in _response.iter_bytes(chunk_size=_chunk_size))
                        )
                    _response.read()
                    _response_json = _response.json()
                except JSONDecodeError:
                    raise ApiError(
                        status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
                    )
                raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

            yield stream()

    def compare_dataset_versions(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[DatasetVersionDiff]:
        """
        Compare the latest committed dataset version with the current draft state. This endpoint provides insights into changes made since the last version was committed. The comparison calculates additions, modifications, deletions, and unchanged items between the latest version snapshot and current draft.

        Parameters
        ----------
        id : str

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

        Returns
        -------
        HttpResponse[DatasetVersionDiff]
            Diff computed successfully
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/versions/diff",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetVersionDiff,
                    parse_obj_as(
                        type_=DatasetVersionDiff,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def create_version_tag(
        self, id: str, version_hash: str, *, tag: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[None]:
        """
        Add a tag to a specific dataset version for easy reference (e.g., 'baseline', 'v1.0', 'production')

        Parameters
        ----------
        id : str

        version_hash : str

        tag : str

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/versions/hash/{jsonable_encoder(version_hash)}/tags",
            method="POST",
            json={
                "tag": tag,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 409:
                raise ConflictError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def delete_version_tag(
        self, id: str, version_hash: str, tag: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[None]:
        """
        Remove a tag from a dataset version. The version itself is not deleted, only the tag reference.

        Parameters
        ----------
        id : str

        version_hash : str

        tag : str

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/versions/{jsonable_encoder(version_hash)}/tags/{jsonable_encoder(tag)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def list_dataset_versions(
        self,
        id: str,
        *,
        page: typing.Optional[int] = None,
        size: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[DatasetVersionPagePublic]:
        """
        Get paginated list of versions for a dataset, ordered by creation time (newest first)

        Parameters
        ----------
        id : str

        page : typing.Optional[int]

        size : typing.Optional[int]

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

        Returns
        -------
        HttpResponse[DatasetVersionPagePublic]
            Dataset versions
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/versions",
            method="GET",
            params={
                "page": page,
                "size": size,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetVersionPagePublic,
                    parse_obj_as(
                        type_=DatasetVersionPagePublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def restore_dataset_version(
        self, id: str, *, version_ref: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[DatasetVersionPublic]:
        """
        Restores the dataset to a previous version state by creating a new version with items copied from the specified version. If the version is already the latest, returns it as-is (no-op).

        Parameters
        ----------
        id : str

        version_ref : str
            Version hash or tag to restore from

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

        Returns
        -------
        HttpResponse[DatasetVersionPublic]
            Version restored successfully
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/versions/restore",
            method="POST",
            json={
                "version_ref": version_ref,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetVersionPublic,
                    parse_obj_as(
                        type_=DatasetVersionPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def retrieve_dataset_version(
        self, id: str, *, version_name: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[DatasetVersionPublic]:
        """
        Get a specific version by its version name (e.g., 'v1', 'v373'). This is more efficient than paginating through all versions for large datasets.

        Parameters
        ----------
        id : str

        version_name : str
            Version name in format 'vN' (e.g., 'v1', 'v373')

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

        Returns
        -------
        HttpResponse[DatasetVersionPublic]
            Dataset version
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/versions/retrieve",
            method="POST",
            json={
                "version_name": version_name,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetVersionPublic,
                    parse_obj_as(
                        type_=DatasetVersionPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def update_dataset_version(
        self,
        id: str,
        version_hash: str,
        *,
        change_description: typing.Optional[str] = OMIT,
        tags_to_add: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[DatasetVersionPublic]:
        """
        Update a dataset version's change_description and/or add new tags

        Parameters
        ----------
        id : str

        version_hash : str

        change_description : typing.Optional[str]
            Optional description of changes in this version

        tags_to_add : typing.Optional[typing.Sequence[str]]
            Optional list of tags to add to this version

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

        Returns
        -------
        HttpResponse[DatasetVersionPublic]
            Version updated successfully
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/versions/hash/{jsonable_encoder(version_hash)}",
            method="PATCH",
            json={
                "change_description": change_description,
                "tags_to_add": tags_to_add,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetVersionPublic,
                    parse_obj_as(
                        type_=DatasetVersionPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 409:
                raise ConflictError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


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

    async def apply_dataset_item_changes(
        self,
        id: str,
        *,
        request: DatasetItemChangesPublic,
        override: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[DatasetVersionPublic]:
        """
        Apply delta changes (add, edit, delete) to a dataset version with conflict detection.

        This endpoint:
        - Creates a new version with the applied changes
        - Validates that baseVersion matches the latest version (unless override=true)
        - Returns 409 Conflict if baseVersion is stale and override is not set

        Use `override=true` query parameter to force version creation even with stale baseVersion.

        Parameters
        ----------
        id : str

        request : DatasetItemChangesPublic

        override : typing.Optional[bool]

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

        Returns
        -------
        AsyncHttpResponse[DatasetVersionPublic]
            Version created successfully
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/items/changes",
            method="POST",
            params={
                "override": override,
            },
            json=request,
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetVersionPublic,
                    parse_obj_as(
                        type_=DatasetVersionPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 409:
                raise ConflictError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def batch_update_dataset_items(
        self,
        *,
        update: DatasetItemUpdate,
        ids: typing.Optional[typing.Sequence[str]] = OMIT,
        filters: typing.Optional[typing.Sequence[DatasetItemFilter]] = OMIT,
        dataset_id: typing.Optional[str] = OMIT,
        merge_tags: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[None]:
        """
        Update multiple dataset items

        Parameters
        ----------
        update : DatasetItemUpdate

        ids : typing.Optional[typing.Sequence[str]]
            List of dataset item IDs to update (max 1000). Mutually exclusive with 'filters'.

        filters : typing.Optional[typing.Sequence[DatasetItemFilter]]

        dataset_id : typing.Optional[str]
            Dataset ID. Required when using 'filters', optional when using 'ids'.

        merge_tags : typing.Optional[bool]
            If true, merge tags with existing tags instead of replacing them. Default: false. When using 'filters', this is automatically set to true.

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/private/datasets/items/batch",
            method="PATCH",
            json={
                "ids": ids,
                "filters": convert_and_respect_annotation_metadata(
                    object_=filters, annotation=typing.Sequence[DatasetItemFilter], direction="write"
                ),
                "dataset_id": dataset_id,
                "update": convert_and_respect_annotation_metadata(
                    object_=update, annotation=DatasetItemUpdate, direction="write"
                ),
                "merge_tags": merge_tags,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def find_datasets(
        self,
        *,
        page: typing.Optional[int] = None,
        size: typing.Optional[int] = None,
        with_experiments_only: typing.Optional[bool] = None,
        with_optimizations_only: typing.Optional[bool] = None,
        prompt_id: typing.Optional[str] = None,
        project_id: typing.Optional[str] = None,
        name: typing.Optional[str] = None,
        sorting: typing.Optional[str] = None,
        filters: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[DatasetPagePublic]:
        """
        Find datasets

        Parameters
        ----------
        page : typing.Optional[int]

        size : typing.Optional[int]

        with_experiments_only : typing.Optional[bool]

        with_optimizations_only : typing.Optional[bool]

        prompt_id : typing.Optional[str]

        project_id : typing.Optional[str]

        name : typing.Optional[str]

        sorting : typing.Optional[str]

        filters : typing.Optional[str]

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

        Returns
        -------
        AsyncHttpResponse[DatasetPagePublic]
            Dataset resource
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/private/datasets",
            method="GET",
            params={
                "page": page,
                "size": size,
                "with_experiments_only": with_experiments_only,
                "with_optimizations_only": with_optimizations_only,
                "prompt_id": prompt_id,
                "project_id": project_id,
                "name": name,
                "sorting": sorting,
                "filters": filters,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetPagePublic,
                    parse_obj_as(
                        type_=DatasetPagePublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def create_dataset(
        self,
        *,
        name: str,
        id: typing.Optional[str] = OMIT,
        project_id: typing.Optional[str] = OMIT,
        project_name: typing.Optional[str] = OMIT,
        type: typing.Optional[DatasetWriteType] = OMIT,
        visibility: typing.Optional[DatasetWriteVisibility] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        description: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[None]:
        """
        Create dataset

        Parameters
        ----------
        name : str

        id : typing.Optional[str]

        project_id : typing.Optional[str]
            Project ID. Takes precedence over project_name when both are provided.

        project_name : typing.Optional[str]
            For project scope, specify either project_id or project_name. If project_name is provided and the project does not exist, it will be created. Ignored when project_id is provided. If neither is provided, the dataset is created at workspace level.

        type : typing.Optional[DatasetWriteType]

        visibility : typing.Optional[DatasetWriteVisibility]

        tags : typing.Optional[typing.Sequence[str]]

        description : typing.Optional[str]

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/private/datasets",
            method="POST",
            json={
                "id": id,
                "name": name,
                "project_id": project_id,
                "project_name": project_name,
                "type": type,
                "visibility": visibility,
                "tags": tags,
                "description": description,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def create_or_update_dataset_items(
        self,
        *,
        items: typing.Sequence[DatasetItemWrite],
        dataset_name: typing.Optional[str] = OMIT,
        dataset_id: typing.Optional[str] = OMIT,
        batch_group_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[None]:
        """
        Create/update dataset items based on dataset item id

        Parameters
        ----------
        items : typing.Sequence[DatasetItemWrite]

        dataset_name : typing.Optional[str]
            If null, dataset_id must be provided

        dataset_id : typing.Optional[str]
            If null, dataset_name must be provided

        batch_group_id : typing.Optional[str]
            Optional batch group ID to group multiple batches into a single dataset version. If null, mutates the latest version instead of creating a new one.

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/private/datasets/items",
            method="PUT",
            json={
                "dataset_name": dataset_name,
                "dataset_id": dataset_id,
                "items": convert_and_respect_annotation_metadata(
                    object_=items, annotation=typing.Sequence[DatasetItemWrite], direction="write"
                ),
                "batch_group_id": batch_group_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def create_dataset_items_from_csv(
        self,
        *,
        file: typing.Dict[str, typing.Optional[typing.Any]],
        dataset_id: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[None]:
        """
        Create dataset items from uploaded CSV file. CSV should have headers in the first row. Processing happens asynchronously in batches.

        Parameters
        ----------
        file : typing.Dict[str, typing.Optional[typing.Any]]

        dataset_id : str

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/private/datasets/items/from-csv",
            method="POST",
            data={
                "file": file,
                "dataset_id": dataset_id,
            },
            files={},
            headers={
                "content-type": "multipart/form-data",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def create_dataset_items_from_spans(
        self,
        dataset_id: str,
        *,
        span_ids: typing.Sequence[str],
        enrichment_options: SpanEnrichmentOptions,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[None]:
        """
        Create dataset items from spans with enriched metadata

        Parameters
        ----------
        dataset_id : str

        span_ids : typing.Sequence[str]
            Set of span IDs to add to the dataset

        enrichment_options : SpanEnrichmentOptions

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(dataset_id)}/items/from-spans",
            method="POST",
            json={
                "span_ids": span_ids,
                "enrichment_options": convert_and_respect_annotation_metadata(
                    object_=enrichment_options, annotation=SpanEnrichmentOptions, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def create_dataset_items_from_traces(
        self,
        dataset_id: str,
        *,
        trace_ids: typing.Sequence[str],
        enrichment_options: TraceEnrichmentOptions,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[None]:
        """
        Create dataset items from traces with enriched metadata

        Parameters
        ----------
        dataset_id : str

        trace_ids : typing.Sequence[str]
            Set of trace IDs to add to the dataset

        enrichment_options : TraceEnrichmentOptions

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(dataset_id)}/items/from-traces",
            method="POST",
            json={
                "trace_ids": trace_ids,
                "enrichment_options": convert_and_respect_annotation_metadata(
                    object_=enrichment_options, annotation=TraceEnrichmentOptions, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_dataset_by_id(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[DatasetPublic]:
        """
        Get dataset by id

        Parameters
        ----------
        id : str

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

        Returns
        -------
        AsyncHttpResponse[DatasetPublic]
            Dataset resource
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetPublic,
                    parse_obj_as(
                        type_=DatasetPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def update_dataset(
        self,
        id: str,
        *,
        name: str,
        description: typing.Optional[str] = OMIT,
        visibility: typing.Optional[DatasetUpdateVisibility] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[None]:
        """
        Update dataset by id

        Parameters
        ----------
        id : str

        name : str

        description : typing.Optional[str]

        visibility : typing.Optional[DatasetUpdateVisibility]

        tags : typing.Optional[typing.Sequence[str]]

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}",
            method="PUT",
            json={
                "name": name,
                "description": description,
                "visibility": visibility,
                "tags": tags,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def delete_dataset(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[None]:
        """
        Delete dataset by id

        Parameters
        ----------
        id : str

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def delete_dataset_by_name(
        self,
        *,
        dataset_name: str,
        project_name: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[None]:
        """
        Delete dataset by name

        Parameters
        ----------
        dataset_name : str

        project_name : typing.Optional[str]

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/private/datasets/delete",
            method="POST",
            json={
                "dataset_name": dataset_name,
                "project_name": project_name,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def delete_dataset_items(
        self,
        *,
        item_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        dataset_id: typing.Optional[str] = OMIT,
        filters: typing.Optional[typing.Sequence[DatasetItemFilter]] = OMIT,
        batch_group_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[None]:
        """
        Delete dataset items using one of two modes:
        1. **Delete by IDs**: Provide 'item_ids' to delete specific items by their IDs
        2. **Delete by filters**: Provide 'dataset_id' with optional 'filters' to delete items matching criteria

        When using filters, an empty 'filters' array will delete all items in the specified dataset.

        Parameters
        ----------
        item_ids : typing.Optional[typing.Sequence[str]]
            List of dataset item IDs to delete (max 1000). Use this to delete specific items by their IDs. Mutually exclusive with 'dataset_id' and 'filters'.

        dataset_id : typing.Optional[str]
            Dataset ID to scope the deletion. Required when using 'filters'. Mutually exclusive with 'item_ids'.

        filters : typing.Optional[typing.Sequence[DatasetItemFilter]]
            Filters to select dataset items to delete within the specified dataset. Must be used with 'dataset_id'. Mutually exclusive with 'item_ids'. Empty array means 'delete all items in the dataset'.

        batch_group_id : typing.Optional[str]
            Optional batch group ID to group multiple delete operations into a single dataset version. If null, mutates the latest version instead of creating a new one.

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/private/datasets/items/delete",
            method="POST",
            json={
                "item_ids": item_ids,
                "dataset_id": dataset_id,
                "filters": convert_and_respect_annotation_metadata(
                    object_=filters, annotation=typing.Sequence[DatasetItemFilter], direction="write"
                ),
                "batch_group_id": batch_group_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def delete_datasets_batch(
        self, *, ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[None]:
        """
        Delete datasets batch

        Parameters
        ----------
        ids : typing.Sequence[str]

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/private/datasets/delete-batch",
            method="POST",
            json={
                "ids": ids,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    @contextlib.asynccontextmanager
    async def download_dataset_export(
        self, job_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]:
        """
        Downloads the exported CSV file for a completed export job. This endpoint proxies the file download to avoid exposing internal storage URLs.

        Parameters
        ----------
        job_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response.

        Returns
        -------
        typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]
            CSV file content
        """
        async with self._client_wrapper.httpx_client.stream(
            f"v1/private/datasets/export-jobs/{jsonable_encoder(job_id)}/download",
            method="GET",
            request_options=request_options,
        ) as _response:

            async def stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]:
                try:
                    if 200 <= _response.status_code < 300:
                        _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None
                        return AsyncHttpResponse(
                            response=_response,
                            data=(_chunk async for _chunk in _response.aiter_bytes(chunk_size=_chunk_size)),
                        )
                    await _response.aread()
                    if _response.status_code == 400:
                        raise BadRequestError(
                            headers=dict(_response.headers),
                            body=typing.cast(
                                typing.Optional[typing.Any],
                                parse_obj_as(
                                    type_=typing.Optional[typing.Any],  # type: ignore
                                    object_=_response.json(),
                                ),
                            ),
                        )
                    if _response.status_code == 404:
                        raise NotFoundError(
                            headers=dict(_response.headers),
                            body=typing.cast(
                                typing.Optional[typing.Any],
                                parse_obj_as(
                                    type_=typing.Optional[typing.Any],  # type: ignore
                                    object_=_response.json(),
                                ),
                            ),
                        )
                    _response_json = _response.json()
                except JSONDecodeError:
                    raise ApiError(
                        status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
                    )
                raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

            yield await stream()

    async def expand_dataset(
        self,
        id: str,
        *,
        model: str,
        sample_count: typing.Optional[int] = OMIT,
        preserve_fields: typing.Optional[typing.Sequence[str]] = OMIT,
        variation_instructions: typing.Optional[str] = OMIT,
        custom_prompt: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[DatasetExpansionResponse]:
        """
        Generate synthetic dataset samples using LLM based on existing data patterns

        Parameters
        ----------
        id : str

        model : str
            The model to use for synthetic data generation

        sample_count : typing.Optional[int]
            Number of synthetic samples to generate

        preserve_fields : typing.Optional[typing.Sequence[str]]
            Fields to preserve patterns from original data

        variation_instructions : typing.Optional[str]
            Additional instructions for data variation

        custom_prompt : typing.Optional[str]
            Custom prompt to use for generation instead of auto-generated one

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

        Returns
        -------
        AsyncHttpResponse[DatasetExpansionResponse]
            Generated synthetic samples
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/expansions",
            method="POST",
            json={
                "model": model,
                "sample_count": sample_count,
                "preserve_fields": preserve_fields,
                "variation_instructions": variation_instructions,
                "custom_prompt": custom_prompt,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetExpansionResponse,
                    parse_obj_as(
                        type_=DatasetExpansionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def find_dataset_items_with_experiment_items(
        self,
        id: str,
        *,
        experiment_ids: str,
        page: typing.Optional[int] = None,
        size: typing.Optional[int] = None,
        filters: typing.Optional[str] = None,
        sorting: typing.Optional[str] = None,
        search: typing.Optional[str] = None,
        truncate: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[DatasetItemPageCompare]:
        """
        Find dataset items with experiment items

        Parameters
        ----------
        id : str

        experiment_ids : str

        page : typing.Optional[int]

        size : typing.Optional[int]

        filters : typing.Optional[str]

        sorting : typing.Optional[str]

        search : typing.Optional[str]

        truncate : typing.Optional[bool]

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

        Returns
        -------
        AsyncHttpResponse[DatasetItemPageCompare]
            Dataset item resource
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/items/experiments/items",
            method="GET",
            params={
                "page": page,
                "size": size,
                "experiment_ids": experiment_ids,
                "filters": filters,
                "sorting": sorting,
                "search": search,
                "truncate": truncate,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetItemPageCompare,
                    parse_obj_as(
                        type_=DatasetItemPageCompare,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_dataset_by_identifier(
        self,
        *,
        dataset_name: str,
        project_name: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[DatasetPublic]:
        """
        Get dataset by name

        Parameters
        ----------
        dataset_name : str

        project_name : typing.Optional[str]

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

        Returns
        -------
        AsyncHttpResponse[DatasetPublic]
            Dataset resource
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/private/datasets/retrieve",
            method="POST",
            json={
                "dataset_name": dataset_name,
                "project_name": project_name,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetPublic,
                    parse_obj_as(
                        type_=DatasetPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_dataset_experiment_items_stats(
        self,
        id: str,
        *,
        experiment_ids: str,
        filters: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[ProjectStatsPublic]:
        """
        Get experiment items stats for dataset

        Parameters
        ----------
        id : str

        experiment_ids : str

        filters : typing.Optional[str]

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

        Returns
        -------
        AsyncHttpResponse[ProjectStatsPublic]
            Experiment items stats resource
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/items/experiments/items/stats",
            method="GET",
            params={
                "experiment_ids": experiment_ids,
                "filters": filters,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ProjectStatsPublic,
                    parse_obj_as(
                        type_=ProjectStatsPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_dataset_export_job(
        self, job_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[DatasetExportJobPublic]:
        """
        Retrieves the current status of a dataset export job

        Parameters
        ----------
        job_id : str

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

        Returns
        -------
        AsyncHttpResponse[DatasetExportJobPublic]
            Export job details
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/export-jobs/{jsonable_encoder(job_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetExportJobPublic,
                    parse_obj_as(
                        type_=DatasetExportJobPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_dataset_export_jobs(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[typing.List[DatasetExportJobPublic]]:
        """
        Retrieves all export jobs for the workspace. This is used to restore the export panel state after page refresh.

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

        Returns
        -------
        AsyncHttpResponse[typing.List[DatasetExportJobPublic]]
            List of export jobs
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/private/datasets/export-jobs",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.List[DatasetExportJobPublic],
                    parse_obj_as(
                        type_=typing.List[DatasetExportJobPublic],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_dataset_item_by_id(
        self, item_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[DatasetItemPublic]:
        """
        Get dataset item by id

        Parameters
        ----------
        item_id : str

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

        Returns
        -------
        AsyncHttpResponse[DatasetItemPublic]
            Dataset item resource
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/items/{jsonable_encoder(item_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetItemPublic,
                    parse_obj_as(
                        type_=DatasetItemPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def patch_dataset_item(
        self,
        item_id: str,
        *,
        source: DatasetItemWriteSource,
        data: JsonNode,
        id: typing.Optional[str] = OMIT,
        trace_id: typing.Optional[str] = OMIT,
        span_id: typing.Optional[str] = OMIT,
        description: typing.Optional[str] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        evaluators: typing.Optional[typing.Sequence[EvaluatorItemWrite]] = OMIT,
        execution_policy: typing.Optional[ExecutionPolicyWrite] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[None]:
        """
        Partially update dataset item by id. Only provided fields will be updated.

        Parameters
        ----------
        item_id : str

        source : DatasetItemWriteSource

        data : JsonNode

        id : typing.Optional[str]

        trace_id : typing.Optional[str]

        span_id : typing.Optional[str]

        description : typing.Optional[str]

        tags : typing.Optional[typing.Sequence[str]]

        evaluators : typing.Optional[typing.Sequence[EvaluatorItemWrite]]

        execution_policy : typing.Optional[ExecutionPolicyWrite]

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/items/{jsonable_encoder(item_id)}",
            method="PATCH",
            json={
                "id": id,
                "trace_id": trace_id,
                "span_id": span_id,
                "source": source,
                "data": data,
                "description": description,
                "tags": tags,
                "evaluators": convert_and_respect_annotation_metadata(
                    object_=evaluators, annotation=typing.Sequence[EvaluatorItemWrite], direction="write"
                ),
                "execution_policy": convert_and_respect_annotation_metadata(
                    object_=execution_policy, annotation=ExecutionPolicyWrite, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_dataset_items(
        self,
        id: str,
        *,
        page: typing.Optional[int] = None,
        size: typing.Optional[int] = None,
        version: typing.Optional[str] = None,
        filters: typing.Optional[str] = None,
        truncate: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[DatasetItemPagePublic]:
        """
        Get dataset items

        Parameters
        ----------
        id : str

        page : typing.Optional[int]

        size : typing.Optional[int]

        version : typing.Optional[str]

        filters : typing.Optional[str]

        truncate : typing.Optional[bool]

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

        Returns
        -------
        AsyncHttpResponse[DatasetItemPagePublic]
            Dataset items resource
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/items",
            method="GET",
            params={
                "page": page,
                "size": size,
                "version": version,
                "filters": filters,
                "truncate": truncate,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetItemPagePublic,
                    parse_obj_as(
                        type_=DatasetItemPagePublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_dataset_items_output_columns(
        self,
        id: str,
        *,
        experiment_ids: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[PageColumns]:
        """
        Get dataset items output columns

        Parameters
        ----------
        id : str

        experiment_ids : typing.Optional[str]

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

        Returns
        -------
        AsyncHttpResponse[PageColumns]
            Dataset item output columns
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/items/experiments/items/output/columns",
            method="GET",
            params={
                "experiment_ids": experiment_ids,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PageColumns,
                    parse_obj_as(
                        type_=PageColumns,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def mark_dataset_export_job_viewed(
        self, job_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[None]:
        """
        Marks a dataset export job as viewed by setting the viewed_at timestamp. This is used to track that a user has seen a failed job's error message. This operation is idempotent.

        Parameters
        ----------
        job_id : str

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/export-jobs/{jsonable_encoder(job_id)}/mark-viewed",
            method="PUT",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def start_dataset_export(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[DatasetExportJobPublic]:
        """
        Initiates an asynchronous CSV export job for the dataset. Returns immediately with job details for polling.

        Parameters
        ----------
        id : str

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

        Returns
        -------
        AsyncHttpResponse[DatasetExportJobPublic]
            Existing export job in progress
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/export",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetExportJobPublic,
                    parse_obj_as(
                        type_=DatasetExportJobPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    @contextlib.asynccontextmanager
    async def stream_dataset_items(
        self,
        *,
        dataset_name: str,
        last_retrieved_id: typing.Optional[str] = OMIT,
        steam_limit: typing.Optional[int] = OMIT,
        dataset_version: typing.Optional[str] = OMIT,
        project_name: typing.Optional[str] = OMIT,
        filters: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]:
        """
        Stream dataset items

        Parameters
        ----------
        dataset_name : str

        last_retrieved_id : typing.Optional[str]

        steam_limit : typing.Optional[int]

        dataset_version : typing.Optional[str]

        project_name : typing.Optional[str]

        filters : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response.

        Returns
        -------
        typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]
            Dataset items stream or error during process
        """
        async with self._client_wrapper.httpx_client.stream(
            "v1/private/datasets/items/stream",
            method="POST",
            json={
                "dataset_name": dataset_name,
                "last_retrieved_id": last_retrieved_id,
                "steam_limit": steam_limit,
                "dataset_version": dataset_version,
                "project_name": project_name,
                "filters": filters,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        ) as _response:

            async def stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]:
                try:
                    if 200 <= _response.status_code < 300:
                        _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None
                        return AsyncHttpResponse(
                            response=_response,
                            data=(_chunk async for _chunk in _response.aiter_bytes(chunk_size=_chunk_size)),
                        )
                    await _response.aread()
                    _response_json = _response.json()
                except JSONDecodeError:
                    raise ApiError(
                        status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
                    )
                raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

            yield await stream()

    async def compare_dataset_versions(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[DatasetVersionDiff]:
        """
        Compare the latest committed dataset version with the current draft state. This endpoint provides insights into changes made since the last version was committed. The comparison calculates additions, modifications, deletions, and unchanged items between the latest version snapshot and current draft.

        Parameters
        ----------
        id : str

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

        Returns
        -------
        AsyncHttpResponse[DatasetVersionDiff]
            Diff computed successfully
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/versions/diff",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetVersionDiff,
                    parse_obj_as(
                        type_=DatasetVersionDiff,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def create_version_tag(
        self, id: str, version_hash: str, *, tag: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[None]:
        """
        Add a tag to a specific dataset version for easy reference (e.g., 'baseline', 'v1.0', 'production')

        Parameters
        ----------
        id : str

        version_hash : str

        tag : str

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/versions/hash/{jsonable_encoder(version_hash)}/tags",
            method="POST",
            json={
                "tag": tag,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 409:
                raise ConflictError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def delete_version_tag(
        self, id: str, version_hash: str, tag: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[None]:
        """
        Remove a tag from a dataset version. The version itself is not deleted, only the tag reference.

        Parameters
        ----------
        id : str

        version_hash : str

        tag : str

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/versions/{jsonable_encoder(version_hash)}/tags/{jsonable_encoder(tag)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def list_dataset_versions(
        self,
        id: str,
        *,
        page: typing.Optional[int] = None,
        size: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[DatasetVersionPagePublic]:
        """
        Get paginated list of versions for a dataset, ordered by creation time (newest first)

        Parameters
        ----------
        id : str

        page : typing.Optional[int]

        size : typing.Optional[int]

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

        Returns
        -------
        AsyncHttpResponse[DatasetVersionPagePublic]
            Dataset versions
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/versions",
            method="GET",
            params={
                "page": page,
                "size": size,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetVersionPagePublic,
                    parse_obj_as(
                        type_=DatasetVersionPagePublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def restore_dataset_version(
        self, id: str, *, version_ref: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[DatasetVersionPublic]:
        """
        Restores the dataset to a previous version state by creating a new version with items copied from the specified version. If the version is already the latest, returns it as-is (no-op).

        Parameters
        ----------
        id : str

        version_ref : str
            Version hash or tag to restore from

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

        Returns
        -------
        AsyncHttpResponse[DatasetVersionPublic]
            Version restored successfully
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/versions/restore",
            method="POST",
            json={
                "version_ref": version_ref,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetVersionPublic,
                    parse_obj_as(
                        type_=DatasetVersionPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def retrieve_dataset_version(
        self, id: str, *, version_name: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[DatasetVersionPublic]:
        """
        Get a specific version by its version name (e.g., 'v1', 'v373'). This is more efficient than paginating through all versions for large datasets.

        Parameters
        ----------
        id : str

        version_name : str
            Version name in format 'vN' (e.g., 'v1', 'v373')

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

        Returns
        -------
        AsyncHttpResponse[DatasetVersionPublic]
            Dataset version
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/versions/retrieve",
            method="POST",
            json={
                "version_name": version_name,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetVersionPublic,
                    parse_obj_as(
                        type_=DatasetVersionPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def update_dataset_version(
        self,
        id: str,
        version_hash: str,
        *,
        change_description: typing.Optional[str] = OMIT,
        tags_to_add: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[DatasetVersionPublic]:
        """
        Update a dataset version's change_description and/or add new tags

        Parameters
        ----------
        id : str

        version_hash : str

        change_description : typing.Optional[str]
            Optional description of changes in this version

        tags_to_add : typing.Optional[typing.Sequence[str]]
            Optional list of tags to add to this version

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

        Returns
        -------
        AsyncHttpResponse[DatasetVersionPublic]
            Version updated successfully
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/private/datasets/{jsonable_encoder(id)}/versions/hash/{jsonable_encoder(version_hash)}",
            method="PATCH",
            json={
                "change_description": change_description,
                "tags_to_add": tags_to_add,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DatasetVersionPublic,
                    parse_obj_as(
                        type_=DatasetVersionPublic,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 409:
                raise ConflictError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
