diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f7778ae..a6979ebb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,7 @@ jobs: timeout-minutes: 10 name: lint runs-on: ${{ github.repository == 'stainless-sdks/codex-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@v4 @@ -34,10 +35,10 @@ jobs: - name: Run lints run: ./scripts/lint - upload: - if: github.repository == 'stainless-sdks/codex-python' + build: + if: github.repository == 'stainless-sdks/codex-python' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork) timeout-minutes: 10 - name: upload + name: build permissions: contents: read id-token: write @@ -45,6 +46,20 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install Rye + run: | + curl -sSf https://rye.astral.sh/get | bash + echo "$HOME/.rye/shims" >> $GITHUB_PATH + env: + RYE_VERSION: '0.44.0' + RYE_INSTALL_OPTION: '--yes' + + - name: Install dependencies + run: rye sync --all-features + + - name: Run build + run: rye build + - name: Get GitHub OIDC Token id: github-oidc uses: actions/github-script@v6 diff --git a/.release-please-manifest.json b/.release-please-manifest.json index aa848759..1c0bb885 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.22" + ".": "0.1.0-alpha.23" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 04c13865..889336e3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,3 +1,3 @@ -configured_endpoints: 65 -openapi_spec_hash: 80696dc202de8bacc0e43506d7c210b0 -config_hash: 14b2643a0ec60cf326dfed00939644ff +configured_endpoints: 55 +openapi_spec_hash: 922886934580d0b2addcb6e26ada0e09 +config_hash: 8f6e5c3b064cbb77569a6bf654954a56 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b2988f8..131d3281 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,35 @@ # Changelog +## 0.1.0-alpha.23 (2025-07-07) + +Full Changelog: [v0.1.0-alpha.22...v0.1.0-alpha.23](https://github.com/cleanlab/codex-python/compare/v0.1.0-alpha.22...v0.1.0-alpha.23) + +### Features + +* **api:** api update ([29f65d7](https://github.com/cleanlab/codex-python/commit/29f65d74a04a8424cc666669167c8ba56a56485b)) +* **api:** api update ([bc15e90](https://github.com/cleanlab/codex-python/commit/bc15e9004a8f3a2b311ceeb851b5f6a666a2698b)) +* **api:** api update ([75b1e81](https://github.com/cleanlab/codex-python/commit/75b1e81e199ff4721ff21b3920bc82a48006df21)) +* **api:** api update ([ab93d9d](https://github.com/cleanlab/codex-python/commit/ab93d9d3990f52924b92518d6249f30783591a42)) +* **api:** api update ([0207b98](https://github.com/cleanlab/codex-python/commit/0207b98b34d0a484c6701d04e32ef56190936201)) +* **api:** api update ([31096f4](https://github.com/cleanlab/codex-python/commit/31096f4820a7bfdd204b0a2d1d84ab1e36e32d0c)) +* **api:** api update ([be06884](https://github.com/cleanlab/codex-python/commit/be06884d321ca5009c9d82346c1b74c7429f82fa)) +* **api:** api update ([41b210d](https://github.com/cleanlab/codex-python/commit/41b210dc69c2b9c45eeab01a0afac6a4563d41f2)) +* **api:** define pagination schemes ([d36c2c7](https://github.com/cleanlab/codex-python/commit/d36c2c7ca7a9155dab71b1c82f2e163488d32086)) +* **api:** more pagination schemes ([d4d82fe](https://github.com/cleanlab/codex-python/commit/d4d82fe33422f460c83778dc0ca767361dce86a5)) +* **api:** remove entries routes ([e80bee9](https://github.com/cleanlab/codex-python/commit/e80bee98b4f91ca7c0c19509d1f6a4f9f6bfd2c7)) + + +### Bug Fixes + +* **ci:** correct conditional ([45d3bc0](https://github.com/cleanlab/codex-python/commit/45d3bc05ab56d3e67d036ce84b2c9a1f2d8cfd69)) +* **ci:** release-doctor — report correct token name ([1a5e444](https://github.com/cleanlab/codex-python/commit/1a5e444226c829392181d98bc06f8cfb8bf13bd9)) + + +### Chores + +* **ci:** change upload type ([023823b](https://github.com/cleanlab/codex-python/commit/023823bace71bdc65ce1ff432373a26731ec43d4)) +* **ci:** only run for pushes and fork pull requests ([6b590bd](https://github.com/cleanlab/codex-python/commit/6b590bd454e939b8453d95c239ee85be1a326909)) + ## 0.1.0-alpha.22 (2025-06-24) Full Changelog: [v0.1.0-alpha.21...v0.1.0-alpha.22](https://github.com/cleanlab/codex-python/compare/v0.1.0-alpha.21...v0.1.0-alpha.22) diff --git a/api.md b/api.md index 13e82147..0c027913 100644 --- a/api.md +++ b/api.md @@ -180,38 +180,6 @@ Methods: - client.projects.access_keys.retrieve_project_id() -> AccessKeyRetrieveProjectIDResponse - client.projects.access_keys.revoke(access_key_id, \*, project_id) -> None -## Entries - -Types: - -```python -from codex.types.projects import Entry, EntryNotifySmeResponse, EntryQueryResponse -``` - -Methods: - -- client.projects.entries.create(project_id, \*\*params) -> Entry -- client.projects.entries.retrieve(entry_id, \*, project_id) -> Entry -- client.projects.entries.update(entry_id, \*, project_id, \*\*params) -> Entry -- client.projects.entries.delete(entry_id, \*, project_id) -> None -- client.projects.entries.notify_sme(entry_id, \*, project_id, \*\*params) -> EntryNotifySmeResponse -- client.projects.entries.publish_draft_answer(entry_id, \*, project_id) -> Entry -- client.projects.entries.query(project_id, \*\*params) -> EntryQueryResponse -- client.projects.entries.unpublish_answer(entry_id, \*, project_id) -> Entry - -## Clusters - -Types: - -```python -from codex.types.projects import ClusterListResponse, ClusterListVariantsResponse -``` - -Methods: - -- client.projects.clusters.list(project_id, \*\*params) -> SyncOffsetPageClusters[ClusterListResponse] -- client.projects.clusters.list_variants(representative_entry_id, \*, project_id) -> ClusterListVariantsResponse - ## Evals Types: @@ -244,9 +212,9 @@ from codex.types.projects import ( Methods: - client.projects.query_logs.retrieve(query_log_id, \*, project_id) -> QueryLogRetrieveResponse -- client.projects.query_logs.list(project_id, \*\*params) -> QueryLogListResponse +- client.projects.query_logs.list(project_id, \*\*params) -> SyncOffsetPageQueryLogs[QueryLogListResponse] - client.projects.query_logs.list_by_group(project_id, \*\*params) -> QueryLogListByGroupResponse -- client.projects.query_logs.list_groups(project_id, \*\*params) -> QueryLogListGroupsResponse +- client.projects.query_logs.list_groups(project_id, \*\*params) -> SyncOffsetPageQueryLogGroups[QueryLogListGroupsResponse] - client.projects.query_logs.start_remediation(query_log_id, \*, project_id) -> QueryLogStartRemediationResponse ## Remediations @@ -272,7 +240,7 @@ Methods: - client.projects.remediations.create(project_id, \*\*params) -> RemediationCreateResponse - client.projects.remediations.retrieve(remediation_id, \*, project_id) -> RemediationRetrieveResponse -- client.projects.remediations.list(project_id, \*\*params) -> RemediationListResponse +- client.projects.remediations.list(project_id, \*\*params) -> SyncOffsetPageRemediations[RemediationListResponse] - client.projects.remediations.delete(remediation_id, \*, project_id) -> None - client.projects.remediations.edit_answer(remediation_id, \*, project_id, \*\*params) -> RemediationEditAnswerResponse - client.projects.remediations.edit_draft_answer(remediation_id, \*, project_id, \*\*params) -> RemediationEditDraftAnswerResponse diff --git a/bin/check-release-environment b/bin/check-release-environment index a1446a75..b845b0f4 100644 --- a/bin/check-release-environment +++ b/bin/check-release-environment @@ -3,7 +3,7 @@ errors=() if [ -z "${PYPI_TOKEN}" ]; then - errors+=("The CODEX_PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.") + errors+=("The PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.") fi lenErrors=${#errors[@]} diff --git a/pyproject.toml b/pyproject.toml index b71f9f0f..16e362c4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "codex-sdk" -version = "0.1.0-alpha.22" +version = "0.1.0-alpha.23" description = "Internal SDK used within cleanlab-codex package. Refer to https://pypi.org/project/cleanlab-codex/ instead." dynamic = ["readme"] license = "MIT" diff --git a/requirements-dev.lock b/requirements-dev.lock index 11a27038..a84b5f44 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -56,7 +56,7 @@ httpx==0.28.1 # via codex-sdk # via httpx-aiohttp # via respx -httpx-aiohttp==0.1.6 +httpx-aiohttp==0.1.8 # via codex-sdk idna==3.4 # via anyio diff --git a/requirements.lock b/requirements.lock index 5eda9d9c..a0807d8f 100644 --- a/requirements.lock +++ b/requirements.lock @@ -43,7 +43,7 @@ httpcore==1.0.2 httpx==0.28.1 # via codex-sdk # via httpx-aiohttp -httpx-aiohttp==0.1.6 +httpx-aiohttp==0.1.8 # via codex-sdk idna==3.4 # via anyio diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh index 62d150a4..aac03848 100755 --- a/scripts/utils/upload-artifact.sh +++ b/scripts/utils/upload-artifact.sh @@ -1,7 +1,9 @@ #!/usr/bin/env bash set -exuo pipefail -RESPONSE=$(curl -X POST "$URL" \ +FILENAME=$(basename dist/*.whl) + +RESPONSE=$(curl -X POST "$URL?filename=$FILENAME" \ -H "Authorization: Bearer $AUTH" \ -H "Content-Type: application/json") @@ -12,13 +14,13 @@ if [[ "$SIGNED_URL" == "null" ]]; then exit 1 fi -UPLOAD_RESPONSE=$(tar -cz . | curl -v -X PUT \ - -H "Content-Type: application/gzip" \ - --data-binary @- "$SIGNED_URL" 2>&1) +UPLOAD_RESPONSE=$(curl -v -X PUT \ + -H "Content-Type: binary/octet-stream" \ + --data-binary "@dist/$FILENAME" "$SIGNED_URL" 2>&1) if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then echo -e "\033[32mUploaded build to Stainless storage.\033[0m" - echo -e "\033[32mInstallation: pip install --pre 'https://pkg.stainless.com/s/codex-python/$SHA'\033[0m" + echo -e "\033[32mInstallation: pip install 'https://pkg.stainless.com/s/codex-python/$SHA/$FILENAME'\033[0m" else echo -e "\033[31mFailed to upload artifact.\033[0m" exit 1 diff --git a/src/codex/_version.py b/src/codex/_version.py index a88a1c39..18f2dcb7 100644 --- a/src/codex/_version.py +++ b/src/codex/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "codex" -__version__ = "0.1.0-alpha.22" # x-release-please-version +__version__ = "0.1.0-alpha.23" # x-release-please-version diff --git a/src/codex/pagination.py b/src/codex/pagination.py index 1f590df5..36af0f63 100644 --- a/src/codex/pagination.py +++ b/src/codex/pagination.py @@ -14,8 +14,14 @@ "AsyncMyOffsetPageTopLevelArray", "SyncOffsetPageClusters", "AsyncOffsetPageClusters", - "SyncOffsetPageEntries", - "AsyncOffsetPageEntries", + "SyncOffsetPageQueryLogs", + "AsyncOffsetPageQueryLogs", + "SyncOffsetPageRemediations", + "AsyncOffsetPageRemediations", + "SyncOffsetPageQueryLogGroups", + "AsyncOffsetPageQueryLogGroups", + "SyncOffsetPageQueryLogsByGroup", + "AsyncOffsetPageQueryLogsByGroup", ] _BaseModelT = TypeVar("_BaseModelT", bound=BaseModel) @@ -145,16 +151,16 @@ def next_page_info(self) -> Optional[PageInfo]: return None -class SyncOffsetPageEntries(BaseSyncPage[_T], BasePage[_T], Generic[_T]): - entries: List[_T] +class SyncOffsetPageQueryLogs(BaseSyncPage[_T], BasePage[_T], Generic[_T]): + query_logs: List[_T] total_count: Optional[int] = None @override def _get_page_items(self) -> List[_T]: - entries = self.entries - if not entries: + query_logs = self.query_logs + if not query_logs: return [] - return entries + return query_logs @override def next_page_info(self) -> Optional[PageInfo]: @@ -175,16 +181,196 @@ def next_page_info(self) -> Optional[PageInfo]: return None -class AsyncOffsetPageEntries(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): - entries: List[_T] +class AsyncOffsetPageQueryLogs(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): + query_logs: List[_T] total_count: Optional[int] = None @override def _get_page_items(self) -> List[_T]: - entries = self.entries - if not entries: + query_logs = self.query_logs + if not query_logs: return [] - return entries + return query_logs + + @override + def next_page_info(self) -> Optional[PageInfo]: + offset = self._options.params.get("offset") or 0 + if not isinstance(offset, int): + raise ValueError(f'Expected "offset" param to be an integer but got {offset}') + + length = len(self._get_page_items()) + current_count = offset + length + + total_count = self.total_count + if total_count is None: + return None + + if current_count < total_count: + return PageInfo(params={"offset": current_count}) + + return None + + +class SyncOffsetPageRemediations(BaseSyncPage[_T], BasePage[_T], Generic[_T]): + remediations: List[_T] + total_count: Optional[int] = None + + @override + def _get_page_items(self) -> List[_T]: + remediations = self.remediations + if not remediations: + return [] + return remediations + + @override + def next_page_info(self) -> Optional[PageInfo]: + offset = self._options.params.get("offset") or 0 + if not isinstance(offset, int): + raise ValueError(f'Expected "offset" param to be an integer but got {offset}') + + length = len(self._get_page_items()) + current_count = offset + length + + total_count = self.total_count + if total_count is None: + return None + + if current_count < total_count: + return PageInfo(params={"offset": current_count}) + + return None + + +class AsyncOffsetPageRemediations(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): + remediations: List[_T] + total_count: Optional[int] = None + + @override + def _get_page_items(self) -> List[_T]: + remediations = self.remediations + if not remediations: + return [] + return remediations + + @override + def next_page_info(self) -> Optional[PageInfo]: + offset = self._options.params.get("offset") or 0 + if not isinstance(offset, int): + raise ValueError(f'Expected "offset" param to be an integer but got {offset}') + + length = len(self._get_page_items()) + current_count = offset + length + + total_count = self.total_count + if total_count is None: + return None + + if current_count < total_count: + return PageInfo(params={"offset": current_count}) + + return None + + +class SyncOffsetPageQueryLogGroups(BaseSyncPage[_T], BasePage[_T], Generic[_T]): + query_log_groups: List[_T] + total_count: Optional[int] = None + + @override + def _get_page_items(self) -> List[_T]: + query_log_groups = self.query_log_groups + if not query_log_groups: + return [] + return query_log_groups + + @override + def next_page_info(self) -> Optional[PageInfo]: + offset = self._options.params.get("offset") or 0 + if not isinstance(offset, int): + raise ValueError(f'Expected "offset" param to be an integer but got {offset}') + + length = len(self._get_page_items()) + current_count = offset + length + + total_count = self.total_count + if total_count is None: + return None + + if current_count < total_count: + return PageInfo(params={"offset": current_count}) + + return None + + +class AsyncOffsetPageQueryLogGroups(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): + query_log_groups: List[_T] + total_count: Optional[int] = None + + @override + def _get_page_items(self) -> List[_T]: + query_log_groups = self.query_log_groups + if not query_log_groups: + return [] + return query_log_groups + + @override + def next_page_info(self) -> Optional[PageInfo]: + offset = self._options.params.get("offset") or 0 + if not isinstance(offset, int): + raise ValueError(f'Expected "offset" param to be an integer but got {offset}') + + length = len(self._get_page_items()) + current_count = offset + length + + total_count = self.total_count + if total_count is None: + return None + + if current_count < total_count: + return PageInfo(params={"offset": current_count}) + + return None + + +class SyncOffsetPageQueryLogsByGroup(BaseSyncPage[_T], BasePage[_T], Generic[_T]): + query_logs_by_group: List[_T] + total_count: Optional[int] = None + + @override + def _get_page_items(self) -> List[_T]: + query_logs_by_group = self.query_logs_by_group + if not query_logs_by_group: + return [] + return query_logs_by_group + + @override + def next_page_info(self) -> Optional[PageInfo]: + offset = self._options.params.get("offset") or 0 + if not isinstance(offset, int): + raise ValueError(f'Expected "offset" param to be an integer but got {offset}') + + length = len(self._get_page_items()) + current_count = offset + length + + total_count = self.total_count + if total_count is None: + return None + + if current_count < total_count: + return PageInfo(params={"offset": current_count}) + + return None + + +class AsyncOffsetPageQueryLogsByGroup(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): + query_logs_by_group: List[_T] + total_count: Optional[int] = None + + @override + def _get_page_items(self) -> List[_T]: + query_logs_by_group = self.query_logs_by_group + if not query_logs_by_group: + return [] + return query_logs_by_group @override def next_page_info(self) -> Optional[PageInfo]: diff --git a/src/codex/resources/projects/__init__.py b/src/codex/resources/projects/__init__.py index 178855ac..c1627d29 100644 --- a/src/codex/resources/projects/__init__.py +++ b/src/codex/resources/projects/__init__.py @@ -8,22 +8,6 @@ EvalsResourceWithStreamingResponse, AsyncEvalsResourceWithStreamingResponse, ) -from .entries import ( - EntriesResource, - AsyncEntriesResource, - EntriesResourceWithRawResponse, - AsyncEntriesResourceWithRawResponse, - EntriesResourceWithStreamingResponse, - AsyncEntriesResourceWithStreamingResponse, -) -from .clusters import ( - ClustersResource, - AsyncClustersResource, - ClustersResourceWithRawResponse, - AsyncClustersResourceWithRawResponse, - ClustersResourceWithStreamingResponse, - AsyncClustersResourceWithStreamingResponse, -) from .projects import ( ProjectsResource, AsyncProjectsResource, @@ -64,18 +48,6 @@ "AsyncAccessKeysResourceWithRawResponse", "AccessKeysResourceWithStreamingResponse", "AsyncAccessKeysResourceWithStreamingResponse", - "EntriesResource", - "AsyncEntriesResource", - "EntriesResourceWithRawResponse", - "AsyncEntriesResourceWithRawResponse", - "EntriesResourceWithStreamingResponse", - "AsyncEntriesResourceWithStreamingResponse", - "ClustersResource", - "AsyncClustersResource", - "ClustersResourceWithRawResponse", - "AsyncClustersResourceWithRawResponse", - "ClustersResourceWithStreamingResponse", - "AsyncClustersResourceWithStreamingResponse", "EvalsResource", "AsyncEvalsResource", "EvalsResourceWithRawResponse", diff --git a/src/codex/resources/projects/clusters.py b/src/codex/resources/projects/clusters.py deleted file mode 100644 index 97124642..00000000 --- a/src/codex/resources/projects/clusters.py +++ /dev/null @@ -1,332 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import List, Optional -from typing_extensions import Literal - -import httpx - -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from ..._utils import maybe_transform -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...pagination import SyncOffsetPageClusters, AsyncOffsetPageClusters -from ..._base_client import AsyncPaginator, make_request_options -from ...types.projects import cluster_list_params -from ...types.projects.cluster_list_response import ClusterListResponse -from ...types.projects.cluster_list_variants_response import ClusterListVariantsResponse - -__all__ = ["ClustersResource", "AsyncClustersResource"] - - -class ClustersResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> ClustersResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/cleanlab/codex-python#accessing-raw-response-data-eg-headers - """ - return ClustersResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> ClustersResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/cleanlab/codex-python#with_streaming_response - """ - return ClustersResourceWithStreamingResponse(self) - - def list( - self, - project_id: str, - *, - eval_issue_types: List[ - Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "unsupported"] - ] - | NotGiven = NOT_GIVEN, - instruction_adherence_failure: Optional[Literal["html_format", "content_structure"]] | NotGiven = NOT_GIVEN, - limit: int | NotGiven = NOT_GIVEN, - offset: int | NotGiven = NOT_GIVEN, - order: Literal["asc", "desc"] | NotGiven = NOT_GIVEN, - sort: Optional[ - Literal[ - "created_at", - "answered_at", - "cluster_frequency_count", - "custom_rank", - "eval_score", - "html_format_score", - "content_structure_score", - ] - ] - | NotGiven = NOT_GIVEN, - states: List[Literal["unanswered", "draft", "published", "published_with_draft"]] | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> SyncOffsetPageClusters[ClusterListResponse]: - """ - List knowledge entries for a project. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - return self._get_api_list( - f"/api/projects/{project_id}/entries/clusters", - page=SyncOffsetPageClusters[ClusterListResponse], - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "eval_issue_types": eval_issue_types, - "instruction_adherence_failure": instruction_adherence_failure, - "limit": limit, - "offset": offset, - "order": order, - "sort": sort, - "states": states, - }, - cluster_list_params.ClusterListParams, - ), - ), - model=ClusterListResponse, - ) - - def list_variants( - self, - representative_entry_id: str, - *, - project_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> ClusterListVariantsResponse: - """ - Get Cluster Variants Route - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - if not representative_entry_id: - raise ValueError( - f"Expected a non-empty value for `representative_entry_id` but received {representative_entry_id!r}" - ) - return self._get( - f"/api/projects/{project_id}/entries/clusters/{representative_entry_id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ClusterListVariantsResponse, - ) - - -class AsyncClustersResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncClustersResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/cleanlab/codex-python#accessing-raw-response-data-eg-headers - """ - return AsyncClustersResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncClustersResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/cleanlab/codex-python#with_streaming_response - """ - return AsyncClustersResourceWithStreamingResponse(self) - - def list( - self, - project_id: str, - *, - eval_issue_types: List[ - Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "unsupported"] - ] - | NotGiven = NOT_GIVEN, - instruction_adherence_failure: Optional[Literal["html_format", "content_structure"]] | NotGiven = NOT_GIVEN, - limit: int | NotGiven = NOT_GIVEN, - offset: int | NotGiven = NOT_GIVEN, - order: Literal["asc", "desc"] | NotGiven = NOT_GIVEN, - sort: Optional[ - Literal[ - "created_at", - "answered_at", - "cluster_frequency_count", - "custom_rank", - "eval_score", - "html_format_score", - "content_structure_score", - ] - ] - | NotGiven = NOT_GIVEN, - states: List[Literal["unanswered", "draft", "published", "published_with_draft"]] | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> AsyncPaginator[ClusterListResponse, AsyncOffsetPageClusters[ClusterListResponse]]: - """ - List knowledge entries for a project. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - return self._get_api_list( - f"/api/projects/{project_id}/entries/clusters", - page=AsyncOffsetPageClusters[ClusterListResponse], - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "eval_issue_types": eval_issue_types, - "instruction_adherence_failure": instruction_adherence_failure, - "limit": limit, - "offset": offset, - "order": order, - "sort": sort, - "states": states, - }, - cluster_list_params.ClusterListParams, - ), - ), - model=ClusterListResponse, - ) - - async def list_variants( - self, - representative_entry_id: str, - *, - project_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> ClusterListVariantsResponse: - """ - Get Cluster Variants Route - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - if not representative_entry_id: - raise ValueError( - f"Expected a non-empty value for `representative_entry_id` but received {representative_entry_id!r}" - ) - return await self._get( - f"/api/projects/{project_id}/entries/clusters/{representative_entry_id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=ClusterListVariantsResponse, - ) - - -class ClustersResourceWithRawResponse: - def __init__(self, clusters: ClustersResource) -> None: - self._clusters = clusters - - self.list = to_raw_response_wrapper( - clusters.list, - ) - self.list_variants = to_raw_response_wrapper( - clusters.list_variants, - ) - - -class AsyncClustersResourceWithRawResponse: - def __init__(self, clusters: AsyncClustersResource) -> None: - self._clusters = clusters - - self.list = async_to_raw_response_wrapper( - clusters.list, - ) - self.list_variants = async_to_raw_response_wrapper( - clusters.list_variants, - ) - - -class ClustersResourceWithStreamingResponse: - def __init__(self, clusters: ClustersResource) -> None: - self._clusters = clusters - - self.list = to_streamed_response_wrapper( - clusters.list, - ) - self.list_variants = to_streamed_response_wrapper( - clusters.list_variants, - ) - - -class AsyncClustersResourceWithStreamingResponse: - def __init__(self, clusters: AsyncClustersResource) -> None: - self._clusters = clusters - - self.list = async_to_streamed_response_wrapper( - clusters.list, - ) - self.list_variants = async_to_streamed_response_wrapper( - clusters.list_variants, - ) diff --git a/src/codex/resources/projects/entries.py b/src/codex/resources/projects/entries.py deleted file mode 100644 index c6b43a4a..00000000 --- a/src/codex/resources/projects/entries.py +++ /dev/null @@ -1,948 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import typing_extensions -from typing import Iterable, Optional - -import httpx - -from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven -from ..._utils import maybe_transform, strip_not_given, async_maybe_transform -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ..._base_client import make_request_options -from ...types.projects import entry_query_params, entry_create_params, entry_update_params, entry_notify_sme_params -from ...types.projects.entry import Entry -from ...types.projects.entry_query_response import EntryQueryResponse -from ...types.projects.entry_notify_sme_response import EntryNotifySmeResponse - -__all__ = ["EntriesResource", "AsyncEntriesResource"] - - -class EntriesResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> EntriesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/cleanlab/codex-python#accessing-raw-response-data-eg-headers - """ - return EntriesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> EntriesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/cleanlab/codex-python#with_streaming_response - """ - return EntriesResourceWithStreamingResponse(self) - - def create( - self, - project_id: str, - *, - question: str, - answer: Optional[str] | NotGiven = NOT_GIVEN, - client_query_metadata: Iterable[object] | NotGiven = NOT_GIVEN, - draft_answer: Optional[str] | NotGiven = NOT_GIVEN, - x_client_library_version: str | NotGiven = NOT_GIVEN, - x_integration_type: str | NotGiven = NOT_GIVEN, - x_source: str | NotGiven = NOT_GIVEN, - x_stainless_package_version: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Entry: - """ - Create a new knowledge entry for a project. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - extra_headers = { - **strip_not_given( - { - "x-client-library-version": x_client_library_version, - "x-integration-type": x_integration_type, - "x-source": x_source, - "x-stainless-package-version": x_stainless_package_version, - } - ), - **(extra_headers or {}), - } - return self._post( - f"/api/projects/{project_id}/entries/", - body=maybe_transform( - { - "question": question, - "answer": answer, - "client_query_metadata": client_query_metadata, - "draft_answer": draft_answer, - }, - entry_create_params.EntryCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Entry, - ) - - def retrieve( - self, - entry_id: str, - *, - project_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Entry: - """ - Get a knowledge entry for a project. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - if not entry_id: - raise ValueError(f"Expected a non-empty value for `entry_id` but received {entry_id!r}") - return self._get( - f"/api/projects/{project_id}/entries/{entry_id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Entry, - ) - - def update( - self, - entry_id: str, - *, - project_id: str, - answer: Optional[str] | NotGiven = NOT_GIVEN, - draft_answer: Optional[str] | NotGiven = NOT_GIVEN, - question: Optional[str] | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Entry: - """ - Update a knowledge entry for a project. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - if not entry_id: - raise ValueError(f"Expected a non-empty value for `entry_id` but received {entry_id!r}") - return self._put( - f"/api/projects/{project_id}/entries/{entry_id}", - body=maybe_transform( - { - "answer": answer, - "draft_answer": draft_answer, - "question": question, - }, - entry_update_params.EntryUpdateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Entry, - ) - - def delete( - self, - entry_id: str, - *, - project_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> None: - """ - Delete a knowledge entry for a project. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - if not entry_id: - raise ValueError(f"Expected a non-empty value for `entry_id` but received {entry_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._delete( - f"/api/projects/{project_id}/entries/{entry_id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def notify_sme( - self, - entry_id: str, - *, - project_id: str, - email: str, - view_context: entry_notify_sme_params.ViewContext, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> EntryNotifySmeResponse: - """ - Notify a subject matter expert to review and answer a specific entry. - - Returns: SMENotificationResponse with status and notification details - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - if not entry_id: - raise ValueError(f"Expected a non-empty value for `entry_id` but received {entry_id!r}") - return self._post( - f"/api/projects/{project_id}/entries/{entry_id}/notifications", - body=maybe_transform( - { - "email": email, - "view_context": view_context, - }, - entry_notify_sme_params.EntryNotifySmeParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EntryNotifySmeResponse, - ) - - def publish_draft_answer( - self, - entry_id: str, - *, - project_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Entry: - """Promote a draft answer to a published answer for a knowledge entry. - - This always - results in the entry's draft answer being removed. If the entry already has a - published answer, it will be overwritten and permanently lost. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - if not entry_id: - raise ValueError(f"Expected a non-empty value for `entry_id` but received {entry_id!r}") - return self._put( - f"/api/projects/{project_id}/entries/{entry_id}/publish_draft_answer", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Entry, - ) - - @typing_extensions.deprecated("deprecated") - def query( - self, - project_id: str, - *, - question: str, - use_llm_matching: bool | NotGiven = NOT_GIVEN, - client_metadata: Optional[object] | NotGiven = NOT_GIVEN, - query_metadata: Optional[entry_query_params.QueryMetadata] | NotGiven = NOT_GIVEN, - x_client_library_version: str | NotGiven = NOT_GIVEN, - x_integration_type: str | NotGiven = NOT_GIVEN, - x_source: str | NotGiven = NOT_GIVEN, - x_stainless_package_version: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> EntryQueryResponse: - """ - Query Entries Route - - Args: - client_metadata: Deprecated: Use query_metadata instead - - query_metadata: Optional logging data that can be provided by the client. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - extra_headers = { - **strip_not_given( - { - "x-client-library-version": x_client_library_version, - "x-integration-type": x_integration_type, - "x-source": x_source, - "x-stainless-package-version": x_stainless_package_version, - } - ), - **(extra_headers or {}), - } - return self._post( - f"/api/projects/{project_id}/entries/query", - body=maybe_transform( - { - "question": question, - "client_metadata": client_metadata, - "query_metadata": query_metadata, - }, - entry_query_params.EntryQueryParams, - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"use_llm_matching": use_llm_matching}, entry_query_params.EntryQueryParams), - ), - cast_to=EntryQueryResponse, - ) - - def unpublish_answer( - self, - entry_id: str, - *, - project_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Entry: - """Unpublish an answer for a knowledge entry. - - This always results in the entry's - answer being removed. If the entry does not already have a draft answer, the - current answer will be retained as the draft answer. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - if not entry_id: - raise ValueError(f"Expected a non-empty value for `entry_id` but received {entry_id!r}") - return self._put( - f"/api/projects/{project_id}/entries/{entry_id}/unpublish_answer", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Entry, - ) - - -class AsyncEntriesResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncEntriesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/cleanlab/codex-python#accessing-raw-response-data-eg-headers - """ - return AsyncEntriesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncEntriesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/cleanlab/codex-python#with_streaming_response - """ - return AsyncEntriesResourceWithStreamingResponse(self) - - async def create( - self, - project_id: str, - *, - question: str, - answer: Optional[str] | NotGiven = NOT_GIVEN, - client_query_metadata: Iterable[object] | NotGiven = NOT_GIVEN, - draft_answer: Optional[str] | NotGiven = NOT_GIVEN, - x_client_library_version: str | NotGiven = NOT_GIVEN, - x_integration_type: str | NotGiven = NOT_GIVEN, - x_source: str | NotGiven = NOT_GIVEN, - x_stainless_package_version: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Entry: - """ - Create a new knowledge entry for a project. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - extra_headers = { - **strip_not_given( - { - "x-client-library-version": x_client_library_version, - "x-integration-type": x_integration_type, - "x-source": x_source, - "x-stainless-package-version": x_stainless_package_version, - } - ), - **(extra_headers or {}), - } - return await self._post( - f"/api/projects/{project_id}/entries/", - body=await async_maybe_transform( - { - "question": question, - "answer": answer, - "client_query_metadata": client_query_metadata, - "draft_answer": draft_answer, - }, - entry_create_params.EntryCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Entry, - ) - - async def retrieve( - self, - entry_id: str, - *, - project_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Entry: - """ - Get a knowledge entry for a project. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - if not entry_id: - raise ValueError(f"Expected a non-empty value for `entry_id` but received {entry_id!r}") - return await self._get( - f"/api/projects/{project_id}/entries/{entry_id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Entry, - ) - - async def update( - self, - entry_id: str, - *, - project_id: str, - answer: Optional[str] | NotGiven = NOT_GIVEN, - draft_answer: Optional[str] | NotGiven = NOT_GIVEN, - question: Optional[str] | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Entry: - """ - Update a knowledge entry for a project. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - if not entry_id: - raise ValueError(f"Expected a non-empty value for `entry_id` but received {entry_id!r}") - return await self._put( - f"/api/projects/{project_id}/entries/{entry_id}", - body=await async_maybe_transform( - { - "answer": answer, - "draft_answer": draft_answer, - "question": question, - }, - entry_update_params.EntryUpdateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Entry, - ) - - async def delete( - self, - entry_id: str, - *, - project_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> None: - """ - Delete a knowledge entry for a project. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - if not entry_id: - raise ValueError(f"Expected a non-empty value for `entry_id` but received {entry_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._delete( - f"/api/projects/{project_id}/entries/{entry_id}", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - async def notify_sme( - self, - entry_id: str, - *, - project_id: str, - email: str, - view_context: entry_notify_sme_params.ViewContext, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> EntryNotifySmeResponse: - """ - Notify a subject matter expert to review and answer a specific entry. - - Returns: SMENotificationResponse with status and notification details - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - if not entry_id: - raise ValueError(f"Expected a non-empty value for `entry_id` but received {entry_id!r}") - return await self._post( - f"/api/projects/{project_id}/entries/{entry_id}/notifications", - body=await async_maybe_transform( - { - "email": email, - "view_context": view_context, - }, - entry_notify_sme_params.EntryNotifySmeParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EntryNotifySmeResponse, - ) - - async def publish_draft_answer( - self, - entry_id: str, - *, - project_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Entry: - """Promote a draft answer to a published answer for a knowledge entry. - - This always - results in the entry's draft answer being removed. If the entry already has a - published answer, it will be overwritten and permanently lost. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - if not entry_id: - raise ValueError(f"Expected a non-empty value for `entry_id` but received {entry_id!r}") - return await self._put( - f"/api/projects/{project_id}/entries/{entry_id}/publish_draft_answer", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Entry, - ) - - @typing_extensions.deprecated("deprecated") - async def query( - self, - project_id: str, - *, - question: str, - use_llm_matching: bool | NotGiven = NOT_GIVEN, - client_metadata: Optional[object] | NotGiven = NOT_GIVEN, - query_metadata: Optional[entry_query_params.QueryMetadata] | NotGiven = NOT_GIVEN, - x_client_library_version: str | NotGiven = NOT_GIVEN, - x_integration_type: str | NotGiven = NOT_GIVEN, - x_source: str | NotGiven = NOT_GIVEN, - x_stainless_package_version: str | NotGiven = NOT_GIVEN, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> EntryQueryResponse: - """ - Query Entries Route - - Args: - client_metadata: Deprecated: Use query_metadata instead - - query_metadata: Optional logging data that can be provided by the client. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - extra_headers = { - **strip_not_given( - { - "x-client-library-version": x_client_library_version, - "x-integration-type": x_integration_type, - "x-source": x_source, - "x-stainless-package-version": x_stainless_package_version, - } - ), - **(extra_headers or {}), - } - return await self._post( - f"/api/projects/{project_id}/entries/query", - body=await async_maybe_transform( - { - "question": question, - "client_metadata": client_metadata, - "query_metadata": query_metadata, - }, - entry_query_params.EntryQueryParams, - ), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - {"use_llm_matching": use_llm_matching}, entry_query_params.EntryQueryParams - ), - ), - cast_to=EntryQueryResponse, - ) - - async def unpublish_answer( - self, - entry_id: str, - *, - project_id: str, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Entry: - """Unpublish an answer for a knowledge entry. - - This always results in the entry's - answer being removed. If the entry does not already have a draft answer, the - current answer will be retained as the draft answer. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not project_id: - raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - if not entry_id: - raise ValueError(f"Expected a non-empty value for `entry_id` but received {entry_id!r}") - return await self._put( - f"/api/projects/{project_id}/entries/{entry_id}/unpublish_answer", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=Entry, - ) - - -class EntriesResourceWithRawResponse: - def __init__(self, entries: EntriesResource) -> None: - self._entries = entries - - self.create = to_raw_response_wrapper( - entries.create, - ) - self.retrieve = to_raw_response_wrapper( - entries.retrieve, - ) - self.update = to_raw_response_wrapper( - entries.update, - ) - self.delete = to_raw_response_wrapper( - entries.delete, - ) - self.notify_sme = to_raw_response_wrapper( - entries.notify_sme, - ) - self.publish_draft_answer = to_raw_response_wrapper( - entries.publish_draft_answer, - ) - self.query = ( # pyright: ignore[reportDeprecated] - to_raw_response_wrapper( - entries.query # pyright: ignore[reportDeprecated], - ) - ) - self.unpublish_answer = to_raw_response_wrapper( - entries.unpublish_answer, - ) - - -class AsyncEntriesResourceWithRawResponse: - def __init__(self, entries: AsyncEntriesResource) -> None: - self._entries = entries - - self.create = async_to_raw_response_wrapper( - entries.create, - ) - self.retrieve = async_to_raw_response_wrapper( - entries.retrieve, - ) - self.update = async_to_raw_response_wrapper( - entries.update, - ) - self.delete = async_to_raw_response_wrapper( - entries.delete, - ) - self.notify_sme = async_to_raw_response_wrapper( - entries.notify_sme, - ) - self.publish_draft_answer = async_to_raw_response_wrapper( - entries.publish_draft_answer, - ) - self.query = ( # pyright: ignore[reportDeprecated] - async_to_raw_response_wrapper( - entries.query # pyright: ignore[reportDeprecated], - ) - ) - self.unpublish_answer = async_to_raw_response_wrapper( - entries.unpublish_answer, - ) - - -class EntriesResourceWithStreamingResponse: - def __init__(self, entries: EntriesResource) -> None: - self._entries = entries - - self.create = to_streamed_response_wrapper( - entries.create, - ) - self.retrieve = to_streamed_response_wrapper( - entries.retrieve, - ) - self.update = to_streamed_response_wrapper( - entries.update, - ) - self.delete = to_streamed_response_wrapper( - entries.delete, - ) - self.notify_sme = to_streamed_response_wrapper( - entries.notify_sme, - ) - self.publish_draft_answer = to_streamed_response_wrapper( - entries.publish_draft_answer, - ) - self.query = ( # pyright: ignore[reportDeprecated] - to_streamed_response_wrapper( - entries.query # pyright: ignore[reportDeprecated], - ) - ) - self.unpublish_answer = to_streamed_response_wrapper( - entries.unpublish_answer, - ) - - -class AsyncEntriesResourceWithStreamingResponse: - def __init__(self, entries: AsyncEntriesResource) -> None: - self._entries = entries - - self.create = async_to_streamed_response_wrapper( - entries.create, - ) - self.retrieve = async_to_streamed_response_wrapper( - entries.retrieve, - ) - self.update = async_to_streamed_response_wrapper( - entries.update, - ) - self.delete = async_to_streamed_response_wrapper( - entries.delete, - ) - self.notify_sme = async_to_streamed_response_wrapper( - entries.notify_sme, - ) - self.publish_draft_answer = async_to_streamed_response_wrapper( - entries.publish_draft_answer, - ) - self.query = ( # pyright: ignore[reportDeprecated] - async_to_streamed_response_wrapper( - entries.query # pyright: ignore[reportDeprecated], - ) - ) - self.unpublish_answer = async_to_streamed_response_wrapper( - entries.unpublish_answer, - ) diff --git a/src/codex/resources/projects/projects.py b/src/codex/resources/projects/projects.py index 22b5caff..dc01b112 100644 --- a/src/codex/resources/projects/projects.py +++ b/src/codex/resources/projects/projects.py @@ -25,24 +25,8 @@ project_increment_queries_params, project_retrieve_analytics_params, ) -from .entries import ( - EntriesResource, - AsyncEntriesResource, - EntriesResourceWithRawResponse, - AsyncEntriesResourceWithRawResponse, - EntriesResourceWithStreamingResponse, - AsyncEntriesResourceWithStreamingResponse, -) from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven from ..._utils import maybe_transform, strip_not_given, async_maybe_transform -from .clusters import ( - ClustersResource, - AsyncClustersResource, - ClustersResourceWithRawResponse, - AsyncClustersResourceWithRawResponse, - ClustersResourceWithStreamingResponse, - AsyncClustersResourceWithStreamingResponse, -) from ..._compat import cached_property from .query_logs import ( QueryLogsResource, @@ -91,14 +75,6 @@ class ProjectsResource(SyncAPIResource): def access_keys(self) -> AccessKeysResource: return AccessKeysResource(self._client) - @cached_property - def entries(self) -> EntriesResource: - return EntriesResource(self._client) - - @cached_property - def clusters(self) -> ClustersResource: - return ClustersResource(self._client) - @cached_property def evals(self) -> EvalsResource: return EvalsResource(self._client) @@ -212,10 +188,10 @@ def update( self, project_id: str, *, - config: project_update_params.Config, - name: str, - auto_clustering_enabled: bool | NotGiven = NOT_GIVEN, + auto_clustering_enabled: Optional[bool] | NotGiven = NOT_GIVEN, + config: Optional[project_update_params.Config] | NotGiven = NOT_GIVEN, description: Optional[str] | NotGiven = NOT_GIVEN, + name: Optional[str] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -241,10 +217,10 @@ def update( f"/api/projects/{project_id}", body=maybe_transform( { - "config": config, - "name": name, "auto_clustering_enabled": auto_clustering_enabled, + "config": config, "description": description, + "name": name, }, project_update_params.ProjectUpdateParams, ), @@ -512,17 +488,18 @@ def validate( project_id: str, *, context: str, - prompt: str, query: str, - response: str, + response: project_validate_params.Response, use_llm_matching: bool | NotGiven = NOT_GIVEN, constrain_outputs: Optional[List[str]] | NotGiven = NOT_GIVEN, custom_eval_thresholds: Optional[Dict[str, float]] | NotGiven = NOT_GIVEN, custom_metadata: Optional[object] | NotGiven = NOT_GIVEN, eval_scores: Optional[Dict[str, float]] | NotGiven = NOT_GIVEN, - messages: Optional[Iterable[project_validate_params.Message]] | NotGiven = NOT_GIVEN, + messages: Iterable[project_validate_params.Message] | NotGiven = NOT_GIVEN, options: Optional[project_validate_params.Options] | NotGiven = NOT_GIVEN, + prompt: Optional[str] | NotGiven = NOT_GIVEN, quality_preset: Literal["best", "high", "medium", "low", "base"] | NotGiven = NOT_GIVEN, + rewritten_question: Optional[str] | NotGiven = NOT_GIVEN, task: Optional[str] | NotGiven = NOT_GIVEN, x_client_library_version: str | NotGiven = NOT_GIVEN, x_integration_type: str | NotGiven = NOT_GIVEN, @@ -550,9 +527,8 @@ def validate( eval_scores: Scores assessing different aspects of the RAG system. If not provided, TLM will be used to generate scores. - messages: Optional message history to provide conversation context for the query. Used to - rewrite query into a self-contained version of itself. If not provided, the - query will be treated as self-contained. + messages: Message history to provide conversation context for the query. Messages contain + up to and including the latest user prompt to the LLM. options: Typed dict of advanced configuration options for the Trustworthy Language Model. Many of these configurations are determined by the quality preset selected @@ -639,8 +615,14 @@ def validate( - name: Name of the evaluation criteria. - criteria: Instructions specifying the evaluation criteria. + prompt: The prompt to use for the TLM call. If not provided, the prompt will be + generated from the messages. + quality_preset: The quality preset to use for the TLM or Trustworthy RAG API. + rewritten_question: The re-written query if it was provided by the client to Codex from a user to be + used instead of the original query. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -667,7 +649,6 @@ def validate( body=maybe_transform( { "context": context, - "prompt": prompt, "query": query, "response": response, "constrain_outputs": constrain_outputs, @@ -676,7 +657,9 @@ def validate( "eval_scores": eval_scores, "messages": messages, "options": options, + "prompt": prompt, "quality_preset": quality_preset, + "rewritten_question": rewritten_question, "task": task, }, project_validate_params.ProjectValidateParams, @@ -699,14 +682,6 @@ class AsyncProjectsResource(AsyncAPIResource): def access_keys(self) -> AsyncAccessKeysResource: return AsyncAccessKeysResource(self._client) - @cached_property - def entries(self) -> AsyncEntriesResource: - return AsyncEntriesResource(self._client) - - @cached_property - def clusters(self) -> AsyncClustersResource: - return AsyncClustersResource(self._client) - @cached_property def evals(self) -> AsyncEvalsResource: return AsyncEvalsResource(self._client) @@ -820,10 +795,10 @@ async def update( self, project_id: str, *, - config: project_update_params.Config, - name: str, - auto_clustering_enabled: bool | NotGiven = NOT_GIVEN, + auto_clustering_enabled: Optional[bool] | NotGiven = NOT_GIVEN, + config: Optional[project_update_params.Config] | NotGiven = NOT_GIVEN, description: Optional[str] | NotGiven = NOT_GIVEN, + name: Optional[str] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -849,10 +824,10 @@ async def update( f"/api/projects/{project_id}", body=await async_maybe_transform( { - "config": config, - "name": name, "auto_clustering_enabled": auto_clustering_enabled, + "config": config, "description": description, + "name": name, }, project_update_params.ProjectUpdateParams, ), @@ -1122,17 +1097,18 @@ async def validate( project_id: str, *, context: str, - prompt: str, query: str, - response: str, + response: project_validate_params.Response, use_llm_matching: bool | NotGiven = NOT_GIVEN, constrain_outputs: Optional[List[str]] | NotGiven = NOT_GIVEN, custom_eval_thresholds: Optional[Dict[str, float]] | NotGiven = NOT_GIVEN, custom_metadata: Optional[object] | NotGiven = NOT_GIVEN, eval_scores: Optional[Dict[str, float]] | NotGiven = NOT_GIVEN, - messages: Optional[Iterable[project_validate_params.Message]] | NotGiven = NOT_GIVEN, + messages: Iterable[project_validate_params.Message] | NotGiven = NOT_GIVEN, options: Optional[project_validate_params.Options] | NotGiven = NOT_GIVEN, + prompt: Optional[str] | NotGiven = NOT_GIVEN, quality_preset: Literal["best", "high", "medium", "low", "base"] | NotGiven = NOT_GIVEN, + rewritten_question: Optional[str] | NotGiven = NOT_GIVEN, task: Optional[str] | NotGiven = NOT_GIVEN, x_client_library_version: str | NotGiven = NOT_GIVEN, x_integration_type: str | NotGiven = NOT_GIVEN, @@ -1160,9 +1136,8 @@ async def validate( eval_scores: Scores assessing different aspects of the RAG system. If not provided, TLM will be used to generate scores. - messages: Optional message history to provide conversation context for the query. Used to - rewrite query into a self-contained version of itself. If not provided, the - query will be treated as self-contained. + messages: Message history to provide conversation context for the query. Messages contain + up to and including the latest user prompt to the LLM. options: Typed dict of advanced configuration options for the Trustworthy Language Model. Many of these configurations are determined by the quality preset selected @@ -1249,8 +1224,14 @@ async def validate( - name: Name of the evaluation criteria. - criteria: Instructions specifying the evaluation criteria. + prompt: The prompt to use for the TLM call. If not provided, the prompt will be + generated from the messages. + quality_preset: The quality preset to use for the TLM or Trustworthy RAG API. + rewritten_question: The re-written query if it was provided by the client to Codex from a user to be + used instead of the original query. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1277,7 +1258,6 @@ async def validate( body=await async_maybe_transform( { "context": context, - "prompt": prompt, "query": query, "response": response, "constrain_outputs": constrain_outputs, @@ -1286,7 +1266,9 @@ async def validate( "eval_scores": eval_scores, "messages": messages, "options": options, + "prompt": prompt, "quality_preset": quality_preset, + "rewritten_question": rewritten_question, "task": task, }, project_validate_params.ProjectValidateParams, @@ -1345,14 +1327,6 @@ def __init__(self, projects: ProjectsResource) -> None: def access_keys(self) -> AccessKeysResourceWithRawResponse: return AccessKeysResourceWithRawResponse(self._projects.access_keys) - @cached_property - def entries(self) -> EntriesResourceWithRawResponse: - return EntriesResourceWithRawResponse(self._projects.entries) - - @cached_property - def clusters(self) -> ClustersResourceWithRawResponse: - return ClustersResourceWithRawResponse(self._projects.clusters) - @cached_property def evals(self) -> EvalsResourceWithRawResponse: return EvalsResourceWithRawResponse(self._projects.evals) @@ -1407,14 +1381,6 @@ def __init__(self, projects: AsyncProjectsResource) -> None: def access_keys(self) -> AsyncAccessKeysResourceWithRawResponse: return AsyncAccessKeysResourceWithRawResponse(self._projects.access_keys) - @cached_property - def entries(self) -> AsyncEntriesResourceWithRawResponse: - return AsyncEntriesResourceWithRawResponse(self._projects.entries) - - @cached_property - def clusters(self) -> AsyncClustersResourceWithRawResponse: - return AsyncClustersResourceWithRawResponse(self._projects.clusters) - @cached_property def evals(self) -> AsyncEvalsResourceWithRawResponse: return AsyncEvalsResourceWithRawResponse(self._projects.evals) @@ -1469,14 +1435,6 @@ def __init__(self, projects: ProjectsResource) -> None: def access_keys(self) -> AccessKeysResourceWithStreamingResponse: return AccessKeysResourceWithStreamingResponse(self._projects.access_keys) - @cached_property - def entries(self) -> EntriesResourceWithStreamingResponse: - return EntriesResourceWithStreamingResponse(self._projects.entries) - - @cached_property - def clusters(self) -> ClustersResourceWithStreamingResponse: - return ClustersResourceWithStreamingResponse(self._projects.clusters) - @cached_property def evals(self) -> EvalsResourceWithStreamingResponse: return EvalsResourceWithStreamingResponse(self._projects.evals) @@ -1531,14 +1489,6 @@ def __init__(self, projects: AsyncProjectsResource) -> None: def access_keys(self) -> AsyncAccessKeysResourceWithStreamingResponse: return AsyncAccessKeysResourceWithStreamingResponse(self._projects.access_keys) - @cached_property - def entries(self) -> AsyncEntriesResourceWithStreamingResponse: - return AsyncEntriesResourceWithStreamingResponse(self._projects.entries) - - @cached_property - def clusters(self) -> AsyncClustersResourceWithStreamingResponse: - return AsyncClustersResourceWithStreamingResponse(self._projects.clusters) - @cached_property def evals(self) -> AsyncEvalsResourceWithStreamingResponse: return AsyncEvalsResourceWithStreamingResponse(self._projects.evals) diff --git a/src/codex/resources/projects/query_logs.py b/src/codex/resources/projects/query_logs.py index 32ec7390..9ccecbed 100644 --- a/src/codex/resources/projects/query_logs.py +++ b/src/codex/resources/projects/query_logs.py @@ -18,7 +18,13 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ..._base_client import make_request_options +from ...pagination import ( + SyncOffsetPageQueryLogs, + AsyncOffsetPageQueryLogs, + SyncOffsetPageQueryLogGroups, + AsyncOffsetPageQueryLogGroups, +) +from ..._base_client import AsyncPaginator, make_request_options from ...types.projects import query_log_list_params, query_log_list_groups_params, query_log_list_by_group_params from ...types.projects.query_log_list_response import QueryLogListResponse from ...types.projects.query_log_retrieve_response import QueryLogRetrieveResponse @@ -92,11 +98,14 @@ def list( created_at_end: Union[str, datetime, None] | NotGiven = NOT_GIVEN, created_at_start: Union[str, datetime, None] | NotGiven = NOT_GIVEN, custom_metadata: Optional[str] | NotGiven = NOT_GIVEN, + failed_evals: Optional[List[str]] | NotGiven = NOT_GIVEN, + guardrailed: Optional[bool] | NotGiven = NOT_GIVEN, limit: int | NotGiven = NOT_GIVEN, offset: int | NotGiven = NOT_GIVEN, order: Literal["asc", "desc"] | NotGiven = NOT_GIVEN, + passed_evals: Optional[List[str]] | NotGiven = NOT_GIVEN, primary_eval_issue: Optional[ - List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "unsupported"]] + List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "ungrounded"]] ] | NotGiven = NOT_GIVEN, sort: Optional[Literal["created_at", "primary_eval_issue_score"]] | NotGiven = NOT_GIVEN, @@ -107,7 +116,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> QueryLogListResponse: + ) -> SyncOffsetPageQueryLogs[QueryLogListResponse]: """ List query logs by project ID. @@ -118,6 +127,12 @@ def list( custom_metadata: Filter by custom metadata as JSON string: {"key1": "value1", "key2": "value2"} + failed_evals: Filter by evals that failed + + guardrailed: Filter by guardrailed status + + passed_evals: Filter by evals that passed + primary_eval_issue: Filter logs that have ANY of these primary evaluation issues (OR operation) was_cache_hit: Filter by cache hit status @@ -132,8 +147,9 @@ def list( """ if not project_id: raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - return self._get( + return self._get_api_list( f"/api/projects/{project_id}/query_logs/", + page=SyncOffsetPageQueryLogs[QueryLogListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -144,9 +160,12 @@ def list( "created_at_end": created_at_end, "created_at_start": created_at_start, "custom_metadata": custom_metadata, + "failed_evals": failed_evals, + "guardrailed": guardrailed, "limit": limit, "offset": offset, "order": order, + "passed_evals": passed_evals, "primary_eval_issue": primary_eval_issue, "sort": sort, "was_cache_hit": was_cache_hit, @@ -154,7 +173,7 @@ def list( query_log_list_params.QueryLogListParams, ), ), - cast_to=QueryLogListResponse, + model=QueryLogListResponse, ) def list_by_group( @@ -164,11 +183,15 @@ def list_by_group( created_at_end: Union[str, datetime, None] | NotGiven = NOT_GIVEN, created_at_start: Union[str, datetime, None] | NotGiven = NOT_GIVEN, custom_metadata: Optional[str] | NotGiven = NOT_GIVEN, + failed_evals: Optional[List[str]] | NotGiven = NOT_GIVEN, + guardrailed: Optional[bool] | NotGiven = NOT_GIVEN, limit: int | NotGiven = NOT_GIVEN, + needs_review: Optional[bool] | NotGiven = NOT_GIVEN, offset: int | NotGiven = NOT_GIVEN, order: Literal["asc", "desc"] | NotGiven = NOT_GIVEN, + passed_evals: Optional[List[str]] | NotGiven = NOT_GIVEN, primary_eval_issue: Optional[ - List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "unsupported"]] + List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "ungrounded"]] ] | NotGiven = NOT_GIVEN, remediation_ids: List[str] | NotGiven = NOT_GIVEN, @@ -191,6 +214,14 @@ def list_by_group( custom_metadata: Filter by custom metadata as JSON string: {"key1": "value1", "key2": "value2"} + failed_evals: Filter by evals that failed + + guardrailed: Filter by guardrailed status + + needs_review: Filter logs that need review + + passed_evals: Filter by evals that passed + primary_eval_issue: Filter logs that have ANY of these primary evaluation issues (OR operation) remediation_ids: List of groups to list child logs for @@ -219,9 +250,13 @@ def list_by_group( "created_at_end": created_at_end, "created_at_start": created_at_start, "custom_metadata": custom_metadata, + "failed_evals": failed_evals, + "guardrailed": guardrailed, "limit": limit, + "needs_review": needs_review, "offset": offset, "order": order, + "passed_evals": passed_evals, "primary_eval_issue": primary_eval_issue, "remediation_ids": remediation_ids, "sort": sort, @@ -240,11 +275,15 @@ def list_groups( created_at_end: Union[str, datetime, None] | NotGiven = NOT_GIVEN, created_at_start: Union[str, datetime, None] | NotGiven = NOT_GIVEN, custom_metadata: Optional[str] | NotGiven = NOT_GIVEN, + failed_evals: Optional[List[str]] | NotGiven = NOT_GIVEN, + guardrailed: Optional[bool] | NotGiven = NOT_GIVEN, limit: int | NotGiven = NOT_GIVEN, + needs_review: Optional[bool] | NotGiven = NOT_GIVEN, offset: int | NotGiven = NOT_GIVEN, order: Literal["asc", "desc"] | NotGiven = NOT_GIVEN, + passed_evals: Optional[List[str]] | NotGiven = NOT_GIVEN, primary_eval_issue: Optional[ - List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "unsupported"]] + List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "ungrounded"]] ] | NotGiven = NOT_GIVEN, sort: Optional[Literal["created_at", "primary_eval_issue_score", "total_count", "custom_rank"]] @@ -256,7 +295,7 @@ def list_groups( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> QueryLogListGroupsResponse: + ) -> SyncOffsetPageQueryLogGroups[QueryLogListGroupsResponse]: """ List query log groups by project ID. @@ -267,6 +306,14 @@ def list_groups( custom_metadata: Filter by custom metadata as JSON string: {"key1": "value1", "key2": "value2"} + failed_evals: Filter by evals that failed + + guardrailed: Filter by guardrailed status + + needs_review: Filter log groups that need review + + passed_evals: Filter by evals that passed + primary_eval_issue: Filter logs that have ANY of these primary evaluation issues (OR operation) was_cache_hit: Filter by cache hit status @@ -281,8 +328,9 @@ def list_groups( """ if not project_id: raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - return self._get( + return self._get_api_list( f"/api/projects/{project_id}/query_logs/groups", + page=SyncOffsetPageQueryLogGroups[QueryLogListGroupsResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -293,9 +341,13 @@ def list_groups( "created_at_end": created_at_end, "created_at_start": created_at_start, "custom_metadata": custom_metadata, + "failed_evals": failed_evals, + "guardrailed": guardrailed, "limit": limit, + "needs_review": needs_review, "offset": offset, "order": order, + "passed_evals": passed_evals, "primary_eval_issue": primary_eval_issue, "sort": sort, "was_cache_hit": was_cache_hit, @@ -303,7 +355,7 @@ def list_groups( query_log_list_groups_params.QueryLogListGroupsParams, ), ), - cast_to=QueryLogListGroupsResponse, + model=QueryLogListGroupsResponse, ) def start_remediation( @@ -399,18 +451,21 @@ async def retrieve( cast_to=QueryLogRetrieveResponse, ) - async def list( + def list( self, project_id: str, *, created_at_end: Union[str, datetime, None] | NotGiven = NOT_GIVEN, created_at_start: Union[str, datetime, None] | NotGiven = NOT_GIVEN, custom_metadata: Optional[str] | NotGiven = NOT_GIVEN, + failed_evals: Optional[List[str]] | NotGiven = NOT_GIVEN, + guardrailed: Optional[bool] | NotGiven = NOT_GIVEN, limit: int | NotGiven = NOT_GIVEN, offset: int | NotGiven = NOT_GIVEN, order: Literal["asc", "desc"] | NotGiven = NOT_GIVEN, + passed_evals: Optional[List[str]] | NotGiven = NOT_GIVEN, primary_eval_issue: Optional[ - List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "unsupported"]] + List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "ungrounded"]] ] | NotGiven = NOT_GIVEN, sort: Optional[Literal["created_at", "primary_eval_issue_score"]] | NotGiven = NOT_GIVEN, @@ -421,7 +476,7 @@ async def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> QueryLogListResponse: + ) -> AsyncPaginator[QueryLogListResponse, AsyncOffsetPageQueryLogs[QueryLogListResponse]]: """ List query logs by project ID. @@ -432,6 +487,12 @@ async def list( custom_metadata: Filter by custom metadata as JSON string: {"key1": "value1", "key2": "value2"} + failed_evals: Filter by evals that failed + + guardrailed: Filter by guardrailed status + + passed_evals: Filter by evals that passed + primary_eval_issue: Filter logs that have ANY of these primary evaluation issues (OR operation) was_cache_hit: Filter by cache hit status @@ -446,21 +507,25 @@ async def list( """ if not project_id: raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - return await self._get( + return self._get_api_list( f"/api/projects/{project_id}/query_logs/", + page=AsyncOffsetPageQueryLogs[QueryLogListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, - query=await async_maybe_transform( + query=maybe_transform( { "created_at_end": created_at_end, "created_at_start": created_at_start, "custom_metadata": custom_metadata, + "failed_evals": failed_evals, + "guardrailed": guardrailed, "limit": limit, "offset": offset, "order": order, + "passed_evals": passed_evals, "primary_eval_issue": primary_eval_issue, "sort": sort, "was_cache_hit": was_cache_hit, @@ -468,7 +533,7 @@ async def list( query_log_list_params.QueryLogListParams, ), ), - cast_to=QueryLogListResponse, + model=QueryLogListResponse, ) async def list_by_group( @@ -478,11 +543,15 @@ async def list_by_group( created_at_end: Union[str, datetime, None] | NotGiven = NOT_GIVEN, created_at_start: Union[str, datetime, None] | NotGiven = NOT_GIVEN, custom_metadata: Optional[str] | NotGiven = NOT_GIVEN, + failed_evals: Optional[List[str]] | NotGiven = NOT_GIVEN, + guardrailed: Optional[bool] | NotGiven = NOT_GIVEN, limit: int | NotGiven = NOT_GIVEN, + needs_review: Optional[bool] | NotGiven = NOT_GIVEN, offset: int | NotGiven = NOT_GIVEN, order: Literal["asc", "desc"] | NotGiven = NOT_GIVEN, + passed_evals: Optional[List[str]] | NotGiven = NOT_GIVEN, primary_eval_issue: Optional[ - List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "unsupported"]] + List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "ungrounded"]] ] | NotGiven = NOT_GIVEN, remediation_ids: List[str] | NotGiven = NOT_GIVEN, @@ -505,6 +574,14 @@ async def list_by_group( custom_metadata: Filter by custom metadata as JSON string: {"key1": "value1", "key2": "value2"} + failed_evals: Filter by evals that failed + + guardrailed: Filter by guardrailed status + + needs_review: Filter logs that need review + + passed_evals: Filter by evals that passed + primary_eval_issue: Filter logs that have ANY of these primary evaluation issues (OR operation) remediation_ids: List of groups to list child logs for @@ -533,9 +610,13 @@ async def list_by_group( "created_at_end": created_at_end, "created_at_start": created_at_start, "custom_metadata": custom_metadata, + "failed_evals": failed_evals, + "guardrailed": guardrailed, "limit": limit, + "needs_review": needs_review, "offset": offset, "order": order, + "passed_evals": passed_evals, "primary_eval_issue": primary_eval_issue, "remediation_ids": remediation_ids, "sort": sort, @@ -547,18 +628,22 @@ async def list_by_group( cast_to=QueryLogListByGroupResponse, ) - async def list_groups( + def list_groups( self, project_id: str, *, created_at_end: Union[str, datetime, None] | NotGiven = NOT_GIVEN, created_at_start: Union[str, datetime, None] | NotGiven = NOT_GIVEN, custom_metadata: Optional[str] | NotGiven = NOT_GIVEN, + failed_evals: Optional[List[str]] | NotGiven = NOT_GIVEN, + guardrailed: Optional[bool] | NotGiven = NOT_GIVEN, limit: int | NotGiven = NOT_GIVEN, + needs_review: Optional[bool] | NotGiven = NOT_GIVEN, offset: int | NotGiven = NOT_GIVEN, order: Literal["asc", "desc"] | NotGiven = NOT_GIVEN, + passed_evals: Optional[List[str]] | NotGiven = NOT_GIVEN, primary_eval_issue: Optional[ - List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "unsupported"]] + List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "ungrounded"]] ] | NotGiven = NOT_GIVEN, sort: Optional[Literal["created_at", "primary_eval_issue_score", "total_count", "custom_rank"]] @@ -570,7 +655,7 @@ async def list_groups( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> QueryLogListGroupsResponse: + ) -> AsyncPaginator[QueryLogListGroupsResponse, AsyncOffsetPageQueryLogGroups[QueryLogListGroupsResponse]]: """ List query log groups by project ID. @@ -581,6 +666,14 @@ async def list_groups( custom_metadata: Filter by custom metadata as JSON string: {"key1": "value1", "key2": "value2"} + failed_evals: Filter by evals that failed + + guardrailed: Filter by guardrailed status + + needs_review: Filter log groups that need review + + passed_evals: Filter by evals that passed + primary_eval_issue: Filter logs that have ANY of these primary evaluation issues (OR operation) was_cache_hit: Filter by cache hit status @@ -595,21 +688,26 @@ async def list_groups( """ if not project_id: raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - return await self._get( + return self._get_api_list( f"/api/projects/{project_id}/query_logs/groups", + page=AsyncOffsetPageQueryLogGroups[QueryLogListGroupsResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, - query=await async_maybe_transform( + query=maybe_transform( { "created_at_end": created_at_end, "created_at_start": created_at_start, "custom_metadata": custom_metadata, + "failed_evals": failed_evals, + "guardrailed": guardrailed, "limit": limit, + "needs_review": needs_review, "offset": offset, "order": order, + "passed_evals": passed_evals, "primary_eval_issue": primary_eval_issue, "sort": sort, "was_cache_hit": was_cache_hit, @@ -617,7 +715,7 @@ async def list_groups( query_log_list_groups_params.QueryLogListGroupsParams, ), ), - cast_to=QueryLogListGroupsResponse, + model=QueryLogListGroupsResponse, ) async def start_remediation( diff --git a/src/codex/resources/projects/remediations.py b/src/codex/resources/projects/remediations.py index 65015a14..ea0168c7 100644 --- a/src/codex/resources/projects/remediations.py +++ b/src/codex/resources/projects/remediations.py @@ -18,7 +18,8 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ..._base_client import make_request_options +from ...pagination import SyncOffsetPageRemediations, AsyncOffsetPageRemediations +from ..._base_client import AsyncPaginator, make_request_options from ...types.projects import ( remediation_list_params, remediation_create_params, @@ -159,7 +160,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> RemediationListResponse: + ) -> SyncOffsetPageRemediations[RemediationListResponse]: """ List remediations by project ID. @@ -186,8 +187,9 @@ def list( """ if not project_id: raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - return self._get( + return self._get_api_list( f"/api/projects/{project_id}/remediations/", + page=SyncOffsetPageRemediations[RemediationListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -209,7 +211,7 @@ def list( remediation_list_params.RemediationListParams, ), ), - cast_to=RemediationListResponse, + model=RemediationListResponse, ) def delete( @@ -608,7 +610,7 @@ async def retrieve( cast_to=RemediationRetrieveResponse, ) - async def list( + def list( self, project_id: str, *, @@ -628,7 +630,7 @@ async def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> RemediationListResponse: + ) -> AsyncPaginator[RemediationListResponse, AsyncOffsetPageRemediations[RemediationListResponse]]: """ List remediations by project ID. @@ -655,14 +657,15 @@ async def list( """ if not project_id: raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}") - return await self._get( + return self._get_api_list( f"/api/projects/{project_id}/remediations/", + page=AsyncOffsetPageRemediations[RemediationListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout, - query=await async_maybe_transform( + query=maybe_transform( { "created_at_end": created_at_end, "created_at_start": created_at_start, @@ -678,7 +681,7 @@ async def list( remediation_list_params.RemediationListParams, ), ), - cast_to=RemediationListResponse, + model=RemediationListResponse, ) async def delete( diff --git a/src/codex/types/project_update_params.py b/src/codex/types/project_update_params.py index 73dad672..3e244411 100644 --- a/src/codex/types/project_update_params.py +++ b/src/codex/types/project_update_params.py @@ -21,14 +21,14 @@ class ProjectUpdateParams(TypedDict, total=False): - config: Required[Config] + auto_clustering_enabled: Optional[bool] - name: Required[str] - - auto_clustering_enabled: bool + config: Optional[Config] description: Optional[str] + name: Optional[str] + class ConfigEvalConfigCustomEvalsEvals(TypedDict, total=False): criteria: Required[str] diff --git a/src/codex/types/project_validate_params.py b/src/codex/types/project_validate_params.py index 8b38ebfa..0862cbc1 100644 --- a/src/codex/types/project_validate_params.py +++ b/src/codex/types/project_validate_params.py @@ -2,6 +2,7 @@ from __future__ import annotations +import builtins from typing import Dict, List, Union, Iterable, Optional from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict @@ -9,6 +10,24 @@ __all__ = [ "ProjectValidateParams", + "Response", + "ResponseChatCompletion", + "ResponseChatCompletionChoice", + "ResponseChatCompletionChoiceMessage", + "ResponseChatCompletionChoiceMessageAnnotation", + "ResponseChatCompletionChoiceMessageAnnotationURLCitation", + "ResponseChatCompletionChoiceMessageAudio", + "ResponseChatCompletionChoiceMessageFunctionCall", + "ResponseChatCompletionChoiceMessageToolCall", + "ResponseChatCompletionChoiceMessageToolCallFunction", + "ResponseChatCompletionChoiceLogprobs", + "ResponseChatCompletionChoiceLogprobsContent", + "ResponseChatCompletionChoiceLogprobsContentTopLogprob", + "ResponseChatCompletionChoiceLogprobsRefusal", + "ResponseChatCompletionChoiceLogprobsRefusalTopLogprob", + "ResponseChatCompletionUsage", + "ResponseChatCompletionUsageCompletionTokensDetails", + "ResponseChatCompletionUsagePromptTokensDetails", "Message", "MessageChatCompletionDeveloperMessageParam", "MessageChatCompletionDeveloperMessageParamContentUnionMember1", @@ -41,11 +60,9 @@ class ProjectValidateParams(TypedDict, total=False): context: Required[str] - prompt: Required[str] - query: Required[str] - response: Required[str] + response: Required[Response] use_llm_matching: bool @@ -66,11 +83,10 @@ class ProjectValidateParams(TypedDict, total=False): If not provided, TLM will be used to generate scores. """ - messages: Optional[Iterable[Message]] - """Optional message history to provide conversation context for the query. + messages: Iterable[Message] + """Message history to provide conversation context for the query. - Used to rewrite query into a self-contained version of itself. If not provided, - the query will be treated as self-contained. + Messages contain up to and including the latest user prompt to the LLM. """ options: Optional[Options] @@ -161,9 +177,21 @@ class ProjectValidateParams(TypedDict, total=False): - criteria: Instructions specifying the evaluation criteria. """ + prompt: Optional[str] + """The prompt to use for the TLM call. + + If not provided, the prompt will be generated from the messages. + """ + quality_preset: Literal["best", "high", "medium", "low", "base"] """The quality preset to use for the TLM or Trustworthy RAG API.""" + rewritten_question: Optional[str] + """ + The re-written query if it was provided by the client to Codex from a user to be + used instead of the original query. + """ + task: Optional[str] x_client_library_version: Annotated[str, PropertyInfo(alias="x-client-library-version")] @@ -175,6 +203,243 @@ class ProjectValidateParams(TypedDict, total=False): x_stainless_package_version: Annotated[str, PropertyInfo(alias="x-stainless-package-version")] +class ResponseChatCompletionChoiceMessageAnnotationURLCitationTyped(TypedDict, total=False): + end_index: Required[int] + + start_index: Required[int] + + title: Required[str] + + url: Required[str] + + +ResponseChatCompletionChoiceMessageAnnotationURLCitation: TypeAlias = Union[ + ResponseChatCompletionChoiceMessageAnnotationURLCitationTyped, Dict[str, object] +] + + +class ResponseChatCompletionChoiceMessageAnnotationTyped(TypedDict, total=False): + type: Required[Literal["url_citation"]] + + url_citation: Required[ResponseChatCompletionChoiceMessageAnnotationURLCitation] + + +ResponseChatCompletionChoiceMessageAnnotation: TypeAlias = Union[ + ResponseChatCompletionChoiceMessageAnnotationTyped, Dict[str, object] +] + + +class ResponseChatCompletionChoiceMessageAudioTyped(TypedDict, total=False): + id: Required[str] + + data: Required[str] + + expires_at: Required[int] + + transcript: Required[str] + + +ResponseChatCompletionChoiceMessageAudio: TypeAlias = Union[ + ResponseChatCompletionChoiceMessageAudioTyped, Dict[str, object] +] + + +class ResponseChatCompletionChoiceMessageFunctionCallTyped(TypedDict, total=False): + arguments: Required[str] + + name: Required[str] + + +ResponseChatCompletionChoiceMessageFunctionCall: TypeAlias = Union[ + ResponseChatCompletionChoiceMessageFunctionCallTyped, Dict[str, object] +] + + +class ResponseChatCompletionChoiceMessageToolCallFunctionTyped(TypedDict, total=False): + arguments: Required[str] + + name: Required[str] + + +ResponseChatCompletionChoiceMessageToolCallFunction: TypeAlias = Union[ + ResponseChatCompletionChoiceMessageToolCallFunctionTyped, Dict[str, object] +] + + +class ResponseChatCompletionChoiceMessageToolCallTyped(TypedDict, total=False): + id: Required[str] + + function: Required[ResponseChatCompletionChoiceMessageToolCallFunction] + + type: Required[Literal["function"]] + + +ResponseChatCompletionChoiceMessageToolCall: TypeAlias = Union[ + ResponseChatCompletionChoiceMessageToolCallTyped, Dict[str, object] +] + + +class ResponseChatCompletionChoiceMessageTyped(TypedDict, total=False): + role: Required[Literal["assistant"]] + + annotations: Optional[Iterable[ResponseChatCompletionChoiceMessageAnnotation]] + + audio: Optional[ResponseChatCompletionChoiceMessageAudio] + + content: Optional[str] + + function_call: Optional[ResponseChatCompletionChoiceMessageFunctionCall] + + refusal: Optional[str] + + tool_calls: Optional[Iterable[ResponseChatCompletionChoiceMessageToolCall]] + + +ResponseChatCompletionChoiceMessage: TypeAlias = Union[ResponseChatCompletionChoiceMessageTyped, Dict[str, object]] + + +class ResponseChatCompletionChoiceLogprobsContentTopLogprobTyped(TypedDict, total=False): + token: Required[str] + + logprob: Required[float] + + bytes: Optional[Iterable[int]] + + +ResponseChatCompletionChoiceLogprobsContentTopLogprob: TypeAlias = Union[ + ResponseChatCompletionChoiceLogprobsContentTopLogprobTyped, Dict[str, object] +] + + +class ResponseChatCompletionChoiceLogprobsContentTyped(TypedDict, total=False): + token: Required[str] + + logprob: Required[float] + + top_logprobs: Required[Iterable[ResponseChatCompletionChoiceLogprobsContentTopLogprob]] + + bytes: Optional[Iterable[int]] + + +ResponseChatCompletionChoiceLogprobsContent: TypeAlias = Union[ + ResponseChatCompletionChoiceLogprobsContentTyped, Dict[str, object] +] + + +class ResponseChatCompletionChoiceLogprobsRefusalTopLogprobTyped(TypedDict, total=False): + token: Required[str] + + logprob: Required[float] + + bytes: Optional[Iterable[int]] + + +ResponseChatCompletionChoiceLogprobsRefusalTopLogprob: TypeAlias = Union[ + ResponseChatCompletionChoiceLogprobsRefusalTopLogprobTyped, Dict[str, object] +] + + +class ResponseChatCompletionChoiceLogprobsRefusalTyped(TypedDict, total=False): + token: Required[str] + + logprob: Required[float] + + top_logprobs: Required[Iterable[ResponseChatCompletionChoiceLogprobsRefusalTopLogprob]] + + bytes: Optional[Iterable[int]] + + +ResponseChatCompletionChoiceLogprobsRefusal: TypeAlias = Union[ + ResponseChatCompletionChoiceLogprobsRefusalTyped, Dict[str, object] +] + + +class ResponseChatCompletionChoiceLogprobsTyped(TypedDict, total=False): + content: Optional[Iterable[ResponseChatCompletionChoiceLogprobsContent]] + + refusal: Optional[Iterable[ResponseChatCompletionChoiceLogprobsRefusal]] + + +ResponseChatCompletionChoiceLogprobs: TypeAlias = Union[ResponseChatCompletionChoiceLogprobsTyped, Dict[str, object]] + + +class ResponseChatCompletionChoiceTyped(TypedDict, total=False): + finish_reason: Required[Literal["stop", "length", "tool_calls", "content_filter", "function_call"]] + + index: Required[int] + + message: Required[ResponseChatCompletionChoiceMessage] + + logprobs: Optional[ResponseChatCompletionChoiceLogprobs] + + +ResponseChatCompletionChoice: TypeAlias = Union[ResponseChatCompletionChoiceTyped, Dict[str, object]] + + +class ResponseChatCompletionUsageCompletionTokensDetailsTyped(TypedDict, total=False): + accepted_prediction_tokens: Optional[int] + + audio_tokens: Optional[int] + + reasoning_tokens: Optional[int] + + rejected_prediction_tokens: Optional[int] + + +ResponseChatCompletionUsageCompletionTokensDetails: TypeAlias = Union[ + ResponseChatCompletionUsageCompletionTokensDetailsTyped, Dict[str, object] +] + + +class ResponseChatCompletionUsagePromptTokensDetailsTyped(TypedDict, total=False): + audio_tokens: Optional[int] + + cached_tokens: Optional[int] + + +ResponseChatCompletionUsagePromptTokensDetails: TypeAlias = Union[ + ResponseChatCompletionUsagePromptTokensDetailsTyped, Dict[str, object] +] + + +class ResponseChatCompletionUsageTyped(TypedDict, total=False): + completion_tokens: Required[int] + + prompt_tokens: Required[int] + + total_tokens: Required[int] + + completion_tokens_details: Optional[ResponseChatCompletionUsageCompletionTokensDetails] + + prompt_tokens_details: Optional[ResponseChatCompletionUsagePromptTokensDetails] + + +ResponseChatCompletionUsage: TypeAlias = Union[ResponseChatCompletionUsageTyped, Dict[str, object]] + + +class ResponseChatCompletionTyped(TypedDict, total=False): + id: Required[str] + + choices: Required[Iterable[ResponseChatCompletionChoice]] + + created: Required[int] + + model: Required[str] + + object: Required[Literal["chat.completion"]] + + service_tier: Optional[Literal["scale", "default"]] + + system_fingerprint: Optional[str] + + usage: Optional[ResponseChatCompletionUsage] + + +ResponseChatCompletion: TypeAlias = Union[ResponseChatCompletionTyped, Dict[str, builtins.object]] + +Response: TypeAlias = Union[str, ResponseChatCompletion] + + class MessageChatCompletionDeveloperMessageParamContentUnionMember1(TypedDict, total=False): text: Required[str] diff --git a/src/codex/types/project_validate_response.py b/src/codex/types/project_validate_response.py index db65f676..3b06db2d 100644 --- a/src/codex/types/project_validate_response.py +++ b/src/codex/types/project_validate_response.py @@ -1,10 +1,18 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, Optional +from typing import Dict, List, Optional from .._models import BaseModel -__all__ = ["ProjectValidateResponse", "EvalScores"] +__all__ = ["ProjectValidateResponse", "DeterministicGuardrailsResults", "EvalScores"] + + +class DeterministicGuardrailsResults(BaseModel): + guardrail_name: str + + should_guardrail: bool + + matches: Optional[List[str]] = None class EvalScores(BaseModel): @@ -22,6 +30,9 @@ class EvalScores(BaseModel): class ProjectValidateResponse(BaseModel): + deterministic_guardrails_results: Optional[Dict[str, DeterministicGuardrailsResults]] = None + """Results from deterministic guardrails applied to the response.""" + escalated_to_sme: bool """ True if the question should be escalated to Codex for an SME to review, False diff --git a/src/codex/types/projects/__init__.py b/src/codex/types/projects/__init__.py index 8a26aa00..4f754703 100644 --- a/src/codex/types/projects/__init__.py +++ b/src/codex/types/projects/__init__.py @@ -2,25 +2,16 @@ from __future__ import annotations -from .entry import Entry as Entry from .access_key_schema import AccessKeySchema as AccessKeySchema -from .entry_query_params import EntryQueryParams as EntryQueryParams from .eval_create_params import EvalCreateParams as EvalCreateParams from .eval_list_response import EvalListResponse as EvalListResponse from .eval_update_params import EvalUpdateParams as EvalUpdateParams -from .cluster_list_params import ClusterListParams as ClusterListParams -from .entry_create_params import EntryCreateParams as EntryCreateParams -from .entry_update_params import EntryUpdateParams as EntryUpdateParams -from .entry_query_response import EntryQueryResponse as EntryQueryResponse -from .cluster_list_response import ClusterListResponse as ClusterListResponse from .query_log_list_params import QueryLogListParams as QueryLogListParams -from .entry_notify_sme_params import EntryNotifySmeParams as EntryNotifySmeParams from .query_log_list_response import QueryLogListResponse as QueryLogListResponse from .remediation_list_params import RemediationListParams as RemediationListParams from .access_key_create_params import AccessKeyCreateParams as AccessKeyCreateParams from .access_key_list_response import AccessKeyListResponse as AccessKeyListResponse from .access_key_update_params import AccessKeyUpdateParams as AccessKeyUpdateParams -from .entry_notify_sme_response import EntryNotifySmeResponse as EntryNotifySmeResponse from .remediation_create_params import RemediationCreateParams as RemediationCreateParams from .remediation_list_response import RemediationListResponse as RemediationListResponse from .remediation_pause_response import RemediationPauseResponse as RemediationPauseResponse @@ -30,7 +21,6 @@ from .remediation_publish_response import RemediationPublishResponse as RemediationPublishResponse from .remediation_unpause_response import RemediationUnpauseResponse as RemediationUnpauseResponse from .remediation_retrieve_response import RemediationRetrieveResponse as RemediationRetrieveResponse -from .cluster_list_variants_response import ClusterListVariantsResponse as ClusterListVariantsResponse from .query_log_list_by_group_params import QueryLogListByGroupParams as QueryLogListByGroupParams from .query_log_list_groups_response import QueryLogListGroupsResponse as QueryLogListGroupsResponse from .remediation_edit_answer_params import RemediationEditAnswerParams as RemediationEditAnswerParams diff --git a/src/codex/types/projects/cluster_list_params.py b/src/codex/types/projects/cluster_list_params.py deleted file mode 100644 index 20284d84..00000000 --- a/src/codex/types/projects/cluster_list_params.py +++ /dev/null @@ -1,34 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import List, Optional -from typing_extensions import Literal, TypedDict - -__all__ = ["ClusterListParams"] - - -class ClusterListParams(TypedDict, total=False): - eval_issue_types: List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "unsupported"]] - - instruction_adherence_failure: Optional[Literal["html_format", "content_structure"]] - - limit: int - - offset: int - - order: Literal["asc", "desc"] - - sort: Optional[ - Literal[ - "created_at", - "answered_at", - "cluster_frequency_count", - "custom_rank", - "eval_score", - "html_format_score", - "content_structure_score", - ] - ] - - states: List[Literal["unanswered", "draft", "published", "published_with_draft"]] diff --git a/src/codex/types/projects/cluster_list_response.py b/src/codex/types/projects/cluster_list_response.py deleted file mode 100644 index 1fc8bd5e..00000000 --- a/src/codex/types/projects/cluster_list_response.py +++ /dev/null @@ -1,214 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = [ - "ClusterListResponse", - "ManagedMetadata", - "ManagedMetadataContentStructureScores", - "ManagedMetadataContextSufficiency", - "ManagedMetadataHTMLFormatScores", - "ManagedMetadataQueryEaseCustomized", - "ManagedMetadataResponseGroundedness", - "ManagedMetadataResponseHelpfulness", - "ManagedMetadataTrustworthiness", -] - - -class ManagedMetadataContentStructureScores(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class ManagedMetadataContextSufficiency(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class ManagedMetadataHTMLFormatScores(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class ManagedMetadataQueryEaseCustomized(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class ManagedMetadataResponseGroundedness(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class ManagedMetadataResponseHelpfulness(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class ManagedMetadataTrustworthiness(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class ManagedMetadata(BaseModel): - latest_context: Optional[str] = None - """The most recent context string.""" - - latest_entry_point: Optional[str] = None - """The most recent entry point string.""" - - latest_llm_response: Optional[str] = None - """The most recent LLM response string.""" - - latest_location: Optional[str] = None - """The most recent location string.""" - - content_structure_scores: Optional[ManagedMetadataContentStructureScores] = None - """Holds a list of scores and computes aggregate statistics.""" - - context_sufficiency: Optional[ManagedMetadataContextSufficiency] = None - """Holds a list of scores and computes aggregate statistics.""" - - contexts: Optional[List[str]] = None - - entry_points: Optional[List[str]] = None - - html_format_scores: Optional[ManagedMetadataHTMLFormatScores] = None - """Holds a list of scores and computes aggregate statistics.""" - - llm_responses: Optional[List[str]] = None - - locations: Optional[List[str]] = None - - query_ease_customized: Optional[ManagedMetadataQueryEaseCustomized] = None - """Holds a list of scores and computes aggregate statistics.""" - - response_groundedness: Optional[ManagedMetadataResponseGroundedness] = None - """Holds a list of scores and computes aggregate statistics.""" - - response_helpfulness: Optional[ManagedMetadataResponseHelpfulness] = None - """Holds a list of scores and computes aggregate statistics.""" - - trustworthiness: Optional[ManagedMetadataTrustworthiness] = None - """Holds a list of scores and computes aggregate statistics.""" - - -class ClusterListResponse(BaseModel): - id: str - - cluster_frequency_count: int - - created_at: datetime - - managed_metadata: ManagedMetadata - """Extract system-defined, managed metadata from client_query_metadata.""" - - project_id: str - - question: str - - state: Literal["unanswered", "draft", "published", "published_with_draft"] - - answer: Optional[str] = None - - answered_at: Optional[datetime] = None - - client_query_metadata: Optional[List[object]] = None - - content_structure_score: Optional[float] = None - - draft_answer: Optional[str] = None - - draft_answer_last_edited: Optional[datetime] = None - - eval_issue_type: Optional[str] = None - - eval_score: Optional[float] = None - - frequency_count: Optional[int] = None - """number of times the entry matched for a /query request""" - - html_format_score: Optional[float] = None - - representative_entry_id: Optional[str] = None diff --git a/src/codex/types/projects/cluster_list_variants_response.py b/src/codex/types/projects/cluster_list_variants_response.py deleted file mode 100644 index aa359058..00000000 --- a/src/codex/types/projects/cluster_list_variants_response.py +++ /dev/null @@ -1,14 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List - -from .entry import Entry -from ..._models import BaseModel - -__all__ = ["ClusterListVariantsResponse"] - - -class ClusterListVariantsResponse(BaseModel): - entries: List[Entry] - - total_count: int diff --git a/src/codex/types/projects/entry.py b/src/codex/types/projects/entry.py deleted file mode 100644 index 3f7a86da..00000000 --- a/src/codex/types/projects/entry.py +++ /dev/null @@ -1,210 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = [ - "Entry", - "ManagedMetadata", - "ManagedMetadataContentStructureScores", - "ManagedMetadataContextSufficiency", - "ManagedMetadataHTMLFormatScores", - "ManagedMetadataQueryEaseCustomized", - "ManagedMetadataResponseGroundedness", - "ManagedMetadataResponseHelpfulness", - "ManagedMetadataTrustworthiness", -] - - -class ManagedMetadataContentStructureScores(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class ManagedMetadataContextSufficiency(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class ManagedMetadataHTMLFormatScores(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class ManagedMetadataQueryEaseCustomized(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class ManagedMetadataResponseGroundedness(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class ManagedMetadataResponseHelpfulness(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class ManagedMetadataTrustworthiness(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class ManagedMetadata(BaseModel): - latest_context: Optional[str] = None - """The most recent context string.""" - - latest_entry_point: Optional[str] = None - """The most recent entry point string.""" - - latest_llm_response: Optional[str] = None - """The most recent LLM response string.""" - - latest_location: Optional[str] = None - """The most recent location string.""" - - content_structure_scores: Optional[ManagedMetadataContentStructureScores] = None - """Holds a list of scores and computes aggregate statistics.""" - - context_sufficiency: Optional[ManagedMetadataContextSufficiency] = None - """Holds a list of scores and computes aggregate statistics.""" - - contexts: Optional[List[str]] = None - - entry_points: Optional[List[str]] = None - - html_format_scores: Optional[ManagedMetadataHTMLFormatScores] = None - """Holds a list of scores and computes aggregate statistics.""" - - llm_responses: Optional[List[str]] = None - - locations: Optional[List[str]] = None - - query_ease_customized: Optional[ManagedMetadataQueryEaseCustomized] = None - """Holds a list of scores and computes aggregate statistics.""" - - response_groundedness: Optional[ManagedMetadataResponseGroundedness] = None - """Holds a list of scores and computes aggregate statistics.""" - - response_helpfulness: Optional[ManagedMetadataResponseHelpfulness] = None - """Holds a list of scores and computes aggregate statistics.""" - - trustworthiness: Optional[ManagedMetadataTrustworthiness] = None - """Holds a list of scores and computes aggregate statistics.""" - - -class Entry(BaseModel): - id: str - - created_at: datetime - - managed_metadata: ManagedMetadata - """Extract system-defined, managed metadata from client_query_metadata.""" - - project_id: str - - question: str - - state: Literal["unanswered", "draft", "published", "published_with_draft"] - - answer: Optional[str] = None - - answered_at: Optional[datetime] = None - - client_query_metadata: Optional[List[object]] = None - - content_structure_score: Optional[float] = None - - draft_answer: Optional[str] = None - - draft_answer_last_edited: Optional[datetime] = None - - eval_issue_type: Optional[str] = None - - eval_score: Optional[float] = None - - frequency_count: Optional[int] = None - """number of times the entry matched for a /query request""" - - html_format_score: Optional[float] = None diff --git a/src/codex/types/projects/entry_create_params.py b/src/codex/types/projects/entry_create_params.py deleted file mode 100644 index f06846bb..00000000 --- a/src/codex/types/projects/entry_create_params.py +++ /dev/null @@ -1,28 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Iterable, Optional -from typing_extensions import Required, Annotated, TypedDict - -from ..._utils import PropertyInfo - -__all__ = ["EntryCreateParams"] - - -class EntryCreateParams(TypedDict, total=False): - question: Required[str] - - answer: Optional[str] - - client_query_metadata: Iterable[object] - - draft_answer: Optional[str] - - x_client_library_version: Annotated[str, PropertyInfo(alias="x-client-library-version")] - - x_integration_type: Annotated[str, PropertyInfo(alias="x-integration-type")] - - x_source: Annotated[str, PropertyInfo(alias="x-source")] - - x_stainless_package_version: Annotated[str, PropertyInfo(alias="x-stainless-package-version")] diff --git a/src/codex/types/projects/entry_notify_sme_params.py b/src/codex/types/projects/entry_notify_sme_params.py deleted file mode 100644 index 3d06d1a6..00000000 --- a/src/codex/types/projects/entry_notify_sme_params.py +++ /dev/null @@ -1,30 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, TypedDict - -__all__ = ["EntryNotifySmeParams", "ViewContext"] - - -class EntryNotifySmeParams(TypedDict, total=False): - project_id: Required[str] - - email: Required[str] - - view_context: Required[ViewContext] - - -class ViewContext(TypedDict, total=False): - page: Required[int] - - filter: Literal[ - "unanswered", - "answered", - "all", - "hallucination", - "search_failure", - "unhelpful", - "difficult_query", - "unsupported", - ] diff --git a/src/codex/types/projects/entry_notify_sme_response.py b/src/codex/types/projects/entry_notify_sme_response.py deleted file mode 100644 index b3c5b373..00000000 --- a/src/codex/types/projects/entry_notify_sme_response.py +++ /dev/null @@ -1,13 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from ..._models import BaseModel - -__all__ = ["EntryNotifySmeResponse"] - - -class EntryNotifySmeResponse(BaseModel): - entry_id: str - - recipient_email: str - - status: str diff --git a/src/codex/types/projects/entry_query_params.py b/src/codex/types/projects/entry_query_params.py deleted file mode 100644 index 2ba33b82..00000000 --- a/src/codex/types/projects/entry_query_params.py +++ /dev/null @@ -1,300 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Dict, List, Union, Iterable, Optional -from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict - -from ..._utils import PropertyInfo - -__all__ = [ - "EntryQueryParams", - "QueryMetadata", - "QueryMetadataContextUnionMember3", - "QueryMetadataMessage", - "QueryMetadataMessageChatCompletionDeveloperMessageParam", - "QueryMetadataMessageChatCompletionDeveloperMessageParamContentUnionMember1", - "QueryMetadataMessageChatCompletionSystemMessageParam", - "QueryMetadataMessageChatCompletionSystemMessageParamContentUnionMember1", - "QueryMetadataMessageChatCompletionUserMessageParam", - "QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1", - "QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartTextParam", - "QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartImageParam", - "QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartImageParamImageURL", - "QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartInputAudioParam", - "QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartInputAudioParamInputAudio", - "QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1File", - "QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1FileFile", - "QueryMetadataMessageChatCompletionAssistantMessageParam", - "QueryMetadataMessageChatCompletionAssistantMessageParamAudio", - "QueryMetadataMessageChatCompletionAssistantMessageParamContentUnionMember1", - "QueryMetadataMessageChatCompletionAssistantMessageParamContentUnionMember1ChatCompletionContentPartTextParam", - "QueryMetadataMessageChatCompletionAssistantMessageParamContentUnionMember1ChatCompletionContentPartRefusalParam", - "QueryMetadataMessageChatCompletionAssistantMessageParamFunctionCall", - "QueryMetadataMessageChatCompletionAssistantMessageParamToolCall", - "QueryMetadataMessageChatCompletionAssistantMessageParamToolCallFunction", - "QueryMetadataMessageChatCompletionToolMessageParam", - "QueryMetadataMessageChatCompletionToolMessageParamContentUnionMember1", - "QueryMetadataMessageChatCompletionFunctionMessageParam", -] - - -class EntryQueryParams(TypedDict, total=False): - question: Required[str] - - use_llm_matching: bool - - client_metadata: Optional[object] - """Deprecated: Use query_metadata instead""" - - query_metadata: Optional[QueryMetadata] - """Optional logging data that can be provided by the client.""" - - x_client_library_version: Annotated[str, PropertyInfo(alias="x-client-library-version")] - - x_integration_type: Annotated[str, PropertyInfo(alias="x-integration-type")] - - x_source: Annotated[str, PropertyInfo(alias="x-source")] - - x_stainless_package_version: Annotated[str, PropertyInfo(alias="x-stainless-package-version")] - - -class QueryMetadataContextUnionMember3(TypedDict, total=False): - content: Required[str] - """The actual content/text of the document.""" - - id: Optional[str] - """Unique identifier for the document. Useful for tracking documents""" - - source: Optional[str] - """Source or origin of the document. Useful for citations.""" - - tags: Optional[List[str]] - """Tags or categories for the document. Useful for filtering""" - - title: Optional[str] - """Title or heading of the document. Useful for display and context.""" - - -class QueryMetadataMessageChatCompletionDeveloperMessageParamContentUnionMember1(TypedDict, total=False): - text: Required[str] - - type: Required[Literal["text"]] - - -class QueryMetadataMessageChatCompletionDeveloperMessageParam(TypedDict, total=False): - content: Required[Union[str, Iterable[QueryMetadataMessageChatCompletionDeveloperMessageParamContentUnionMember1]]] - - role: Required[Literal["developer"]] - - name: str - - -class QueryMetadataMessageChatCompletionSystemMessageParamContentUnionMember1(TypedDict, total=False): - text: Required[str] - - type: Required[Literal["text"]] - - -class QueryMetadataMessageChatCompletionSystemMessageParam(TypedDict, total=False): - content: Required[Union[str, Iterable[QueryMetadataMessageChatCompletionSystemMessageParamContentUnionMember1]]] - - role: Required[Literal["system"]] - - name: str - - -class QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartTextParam( - TypedDict, total=False -): - text: Required[str] - - type: Required[Literal["text"]] - - -class QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartImageParamImageURL( - TypedDict, total=False -): - url: Required[str] - - detail: Literal["auto", "low", "high"] - - -class QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartImageParam( - TypedDict, total=False -): - image_url: Required[ - QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartImageParamImageURL - ] - - type: Required[Literal["image_url"]] - - -class QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartInputAudioParamInputAudio( - TypedDict, total=False -): - data: Required[str] - - format: Required[Literal["wav", "mp3"]] - - -class QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartInputAudioParam( - TypedDict, total=False -): - input_audio: Required[ - QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartInputAudioParamInputAudio - ] - - type: Required[Literal["input_audio"]] - - -class QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1FileFile(TypedDict, total=False): - file_data: str - - file_id: str - - filename: str - - -class QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1File(TypedDict, total=False): - file: Required[QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1FileFile] - - type: Required[Literal["file"]] - - -QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1: TypeAlias = Union[ - QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartTextParam, - QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartImageParam, - QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1ChatCompletionContentPartInputAudioParam, - QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1File, -] - - -class QueryMetadataMessageChatCompletionUserMessageParam(TypedDict, total=False): - content: Required[Union[str, Iterable[QueryMetadataMessageChatCompletionUserMessageParamContentUnionMember1]]] - - role: Required[Literal["user"]] - - name: str - - -class QueryMetadataMessageChatCompletionAssistantMessageParamAudio(TypedDict, total=False): - id: Required[str] - - -class QueryMetadataMessageChatCompletionAssistantMessageParamContentUnionMember1ChatCompletionContentPartTextParam( - TypedDict, total=False -): - text: Required[str] - - type: Required[Literal["text"]] - - -class QueryMetadataMessageChatCompletionAssistantMessageParamContentUnionMember1ChatCompletionContentPartRefusalParam( - TypedDict, total=False -): - refusal: Required[str] - - type: Required[Literal["refusal"]] - - -QueryMetadataMessageChatCompletionAssistantMessageParamContentUnionMember1: TypeAlias = Union[ - QueryMetadataMessageChatCompletionAssistantMessageParamContentUnionMember1ChatCompletionContentPartTextParam, - QueryMetadataMessageChatCompletionAssistantMessageParamContentUnionMember1ChatCompletionContentPartRefusalParam, -] - - -class QueryMetadataMessageChatCompletionAssistantMessageParamFunctionCall(TypedDict, total=False): - arguments: Required[str] - - name: Required[str] - - -class QueryMetadataMessageChatCompletionAssistantMessageParamToolCallFunction(TypedDict, total=False): - arguments: Required[str] - - name: Required[str] - - -class QueryMetadataMessageChatCompletionAssistantMessageParamToolCall(TypedDict, total=False): - id: Required[str] - - function: Required[QueryMetadataMessageChatCompletionAssistantMessageParamToolCallFunction] - - type: Required[Literal["function"]] - - -class QueryMetadataMessageChatCompletionAssistantMessageParam(TypedDict, total=False): - role: Required[Literal["assistant"]] - - audio: Optional[QueryMetadataMessageChatCompletionAssistantMessageParamAudio] - - content: Union[str, Iterable[QueryMetadataMessageChatCompletionAssistantMessageParamContentUnionMember1], None] - - function_call: Optional[QueryMetadataMessageChatCompletionAssistantMessageParamFunctionCall] - - name: str - - refusal: Optional[str] - - tool_calls: Iterable[QueryMetadataMessageChatCompletionAssistantMessageParamToolCall] - - -class QueryMetadataMessageChatCompletionToolMessageParamContentUnionMember1(TypedDict, total=False): - text: Required[str] - - type: Required[Literal["text"]] - - -class QueryMetadataMessageChatCompletionToolMessageParam(TypedDict, total=False): - content: Required[Union[str, Iterable[QueryMetadataMessageChatCompletionToolMessageParamContentUnionMember1]]] - - role: Required[Literal["tool"]] - - tool_call_id: Required[str] - - -class QueryMetadataMessageChatCompletionFunctionMessageParam(TypedDict, total=False): - content: Required[Optional[str]] - - name: Required[str] - - role: Required[Literal["function"]] - - -QueryMetadataMessage: TypeAlias = Union[ - QueryMetadataMessageChatCompletionDeveloperMessageParam, - QueryMetadataMessageChatCompletionSystemMessageParam, - QueryMetadataMessageChatCompletionUserMessageParam, - QueryMetadataMessageChatCompletionAssistantMessageParam, - QueryMetadataMessageChatCompletionToolMessageParam, - QueryMetadataMessageChatCompletionFunctionMessageParam, -] - - -class QueryMetadata(TypedDict, total=False): - context: Union[str, List[str], Iterable[object], Iterable[QueryMetadataContextUnionMember3], None] - """RAG context used for the query""" - - custom_metadata: Optional[object] - """Arbitrary metadata supplied by the user/system""" - - eval_scores: Optional[Dict[str, float]] - """Evaluation scores for the original response""" - - evaluated_response: Optional[str] - """The response being evaluated from the RAG system(before any remediation)""" - - messages: Optional[Iterable[QueryMetadataMessage]] - """Optional message history to provide conversation context for the query. - - Used to rewrite query into a self-contained version of itself. If not provided, - the query will be treated as self-contained. - """ - - original_question: Optional[str] - """The original question that was asked before any rewriting or processing. - - For all non-conversational RAG, original_question should be the same as the - final question seen in Codex. - """ diff --git a/src/codex/types/projects/entry_query_response.py b/src/codex/types/projects/entry_query_response.py deleted file mode 100644 index cd5a4c97..00000000 --- a/src/codex/types/projects/entry_query_response.py +++ /dev/null @@ -1,194 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional - -from ..._models import BaseModel - -__all__ = [ - "EntryQueryResponse", - "Entry", - "EntryManagedMetadata", - "EntryManagedMetadataContentStructureScores", - "EntryManagedMetadataContextSufficiency", - "EntryManagedMetadataHTMLFormatScores", - "EntryManagedMetadataQueryEaseCustomized", - "EntryManagedMetadataResponseGroundedness", - "EntryManagedMetadataResponseHelpfulness", - "EntryManagedMetadataTrustworthiness", -] - - -class EntryManagedMetadataContentStructureScores(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class EntryManagedMetadataContextSufficiency(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class EntryManagedMetadataHTMLFormatScores(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class EntryManagedMetadataQueryEaseCustomized(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class EntryManagedMetadataResponseGroundedness(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class EntryManagedMetadataResponseHelpfulness(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class EntryManagedMetadataTrustworthiness(BaseModel): - average: Optional[float] = None - """The average of all scores.""" - - latest: Optional[float] = None - """The most recent score.""" - - max: Optional[float] = None - """The maximum score.""" - - min: Optional[float] = None - """The minimum score.""" - - scores: Optional[List[float]] = None - - -class EntryManagedMetadata(BaseModel): - latest_context: Optional[str] = None - """The most recent context string.""" - - latest_entry_point: Optional[str] = None - """The most recent entry point string.""" - - latest_llm_response: Optional[str] = None - """The most recent LLM response string.""" - - latest_location: Optional[str] = None - """The most recent location string.""" - - content_structure_scores: Optional[EntryManagedMetadataContentStructureScores] = None - """Holds a list of scores and computes aggregate statistics.""" - - context_sufficiency: Optional[EntryManagedMetadataContextSufficiency] = None - """Holds a list of scores and computes aggregate statistics.""" - - contexts: Optional[List[str]] = None - - entry_points: Optional[List[str]] = None - - html_format_scores: Optional[EntryManagedMetadataHTMLFormatScores] = None - """Holds a list of scores and computes aggregate statistics.""" - - llm_responses: Optional[List[str]] = None - - locations: Optional[List[str]] = None - - query_ease_customized: Optional[EntryManagedMetadataQueryEaseCustomized] = None - """Holds a list of scores and computes aggregate statistics.""" - - response_groundedness: Optional[EntryManagedMetadataResponseGroundedness] = None - """Holds a list of scores and computes aggregate statistics.""" - - response_helpfulness: Optional[EntryManagedMetadataResponseHelpfulness] = None - """Holds a list of scores and computes aggregate statistics.""" - - trustworthiness: Optional[EntryManagedMetadataTrustworthiness] = None - """Holds a list of scores and computes aggregate statistics.""" - - -class Entry(BaseModel): - id: str - - managed_metadata: EntryManagedMetadata - """Extract system-defined, managed metadata from client_query_metadata.""" - - question: str - - answer: Optional[str] = None - - client_query_metadata: Optional[List[object]] = None - - draft_answer: Optional[str] = None - - -class EntryQueryResponse(BaseModel): - entry: Entry - - answer: Optional[str] = None diff --git a/src/codex/types/projects/entry_update_params.py b/src/codex/types/projects/entry_update_params.py deleted file mode 100644 index aac256f9..00000000 --- a/src/codex/types/projects/entry_update_params.py +++ /dev/null @@ -1,18 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import Required, TypedDict - -__all__ = ["EntryUpdateParams"] - - -class EntryUpdateParams(TypedDict, total=False): - project_id: Required[str] - - answer: Optional[str] - - draft_answer: Optional[str] - - question: Optional[str] diff --git a/src/codex/types/projects/query_log_list_by_group_params.py b/src/codex/types/projects/query_log_list_by_group_params.py index 66166a19..90bd3867 100644 --- a/src/codex/types/projects/query_log_list_by_group_params.py +++ b/src/codex/types/projects/query_log_list_by_group_params.py @@ -21,14 +21,26 @@ class QueryLogListByGroupParams(TypedDict, total=False): custom_metadata: Optional[str] """Filter by custom metadata as JSON string: {"key1": "value1", "key2": "value2"}""" + failed_evals: Optional[List[str]] + """Filter by evals that failed""" + + guardrailed: Optional[bool] + """Filter by guardrailed status""" + limit: int + needs_review: Optional[bool] + """Filter logs that need review""" + offset: int order: Literal["asc", "desc"] + passed_evals: Optional[List[str]] + """Filter by evals that passed""" + primary_eval_issue: Optional[ - List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "unsupported"]] + List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "ungrounded"]] ] """Filter logs that have ANY of these primary evaluation issues (OR operation)""" diff --git a/src/codex/types/projects/query_log_list_by_group_response.py b/src/codex/types/projects/query_log_list_by_group_response.py index d11d8276..16850735 100644 --- a/src/codex/types/projects/query_log_list_by_group_response.py +++ b/src/codex/types/projects/query_log_list_by_group_response.py @@ -10,10 +10,39 @@ "QueryLogListByGroupResponse", "QueryLogsByGroup", "QueryLogsByGroupQueryLog", + "QueryLogsByGroupQueryLogFormattedEscalationEvalScores", + "QueryLogsByGroupQueryLogFormattedEvalScores", + "QueryLogsByGroupQueryLogFormattedGuardrailEvalScores", + "QueryLogsByGroupQueryLogFormattedNonGuardrailEvalScores", "QueryLogsByGroupQueryLogContext", + "QueryLogsByGroupQueryLogDeterministicGuardrailsResults", ] +class QueryLogsByGroupQueryLogFormattedEscalationEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class QueryLogsByGroupQueryLogFormattedEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class QueryLogsByGroupQueryLogFormattedGuardrailEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class QueryLogsByGroupQueryLogFormattedNonGuardrailEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + class QueryLogsByGroupQueryLogContext(BaseModel): content: str """The actual content/text of the document.""" @@ -31,12 +60,22 @@ class QueryLogsByGroupQueryLogContext(BaseModel): """Title or heading of the document. Useful for display and context.""" +class QueryLogsByGroupQueryLogDeterministicGuardrailsResults(BaseModel): + guardrail_name: str + + should_guardrail: bool + + matches: Optional[List[str]] = None + + class QueryLogsByGroupQueryLog(BaseModel): id: str created_at: datetime - formatted_eval_scores: Optional[Dict[str, Dict[str, Union[float, Literal["pass", "fail"]]]]] = None + formatted_escalation_eval_scores: Optional[Dict[str, QueryLogsByGroupQueryLogFormattedEscalationEvalScores]] = None + + formatted_eval_scores: Optional[Dict[str, QueryLogsByGroupQueryLogFormattedEvalScores]] = None """Format evaluation scores for frontend display with pass/fail status. Returns: Dictionary mapping eval keys to their formatted representation: { @@ -44,14 +83,24 @@ class QueryLogsByGroupQueryLog(BaseModel): eval_scores is None. """ + formatted_guardrail_eval_scores: Optional[Dict[str, QueryLogsByGroupQueryLogFormattedGuardrailEvalScores]] = None + + formatted_non_guardrail_eval_scores: Optional[ + Dict[str, QueryLogsByGroupQueryLogFormattedNonGuardrailEvalScores] + ] = None + is_bad_response: bool + needs_review: bool + project_id: str question: str remediation_id: str + remediation_status: Literal["ACTIVE", "DRAFT", "ACTIVE_WITH_DRAFT", "NOT_STARTED", "PAUSED", "NO_ACTION_NEEDED"] + was_cache_hit: Optional[bool] = None """If similar query already answered, or None if cache was not checked""" @@ -64,9 +113,15 @@ class QueryLogsByGroupQueryLog(BaseModel): custom_metadata_keys: Optional[List[str]] = None """Keys of the custom metadata""" + deterministic_guardrails_results: Optional[Dict[str, QueryLogsByGroupQueryLogDeterministicGuardrailsResults]] = None + """Results of deterministic guardrails applied to the query""" + escalated: Optional[bool] = None """If true, the question was escalated to Codex for an SME to review""" + escalation_evals: Optional[List[str]] = None + """Evals that should trigger escalation to SME""" + eval_issue_labels: Optional[List[str]] = None """Labels derived from evaluation scores""" @@ -79,6 +134,9 @@ class QueryLogsByGroupQueryLog(BaseModel): evaluated_response: Optional[str] = None """The response being evaluated from the RAG system (before any remediation)""" + guardrail_evals: Optional[List[str]] = None + """Evals that should trigger guardrail""" + guardrailed: Optional[bool] = None """If true, the response was guardrailed""" diff --git a/src/codex/types/projects/query_log_list_groups_params.py b/src/codex/types/projects/query_log_list_groups_params.py index 558ac0b2..cd82d9a7 100644 --- a/src/codex/types/projects/query_log_list_groups_params.py +++ b/src/codex/types/projects/query_log_list_groups_params.py @@ -21,14 +21,26 @@ class QueryLogListGroupsParams(TypedDict, total=False): custom_metadata: Optional[str] """Filter by custom metadata as JSON string: {"key1": "value1", "key2": "value2"}""" + failed_evals: Optional[List[str]] + """Filter by evals that failed""" + + guardrailed: Optional[bool] + """Filter by guardrailed status""" + limit: int + needs_review: Optional[bool] + """Filter log groups that need review""" + offset: int order: Literal["asc", "desc"] + passed_evals: Optional[List[str]] + """Filter by evals that passed""" + primary_eval_issue: Optional[ - List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "unsupported"]] + List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "ungrounded"]] ] """Filter logs that have ANY of these primary evaluation issues (OR operation)""" diff --git a/src/codex/types/projects/query_log_list_groups_response.py b/src/codex/types/projects/query_log_list_groups_response.py index fd87c309..5d9222b1 100644 --- a/src/codex/types/projects/query_log_list_groups_response.py +++ b/src/codex/types/projects/query_log_list_groups_response.py @@ -6,10 +6,42 @@ from ..._models import BaseModel -__all__ = ["QueryLogListGroupsResponse", "QueryLogGroup", "QueryLogGroupContext"] +__all__ = [ + "QueryLogListGroupsResponse", + "FormattedEscalationEvalScores", + "FormattedEvalScores", + "FormattedGuardrailEvalScores", + "FormattedNonGuardrailEvalScores", + "Context", + "DeterministicGuardrailsResults", +] -class QueryLogGroupContext(BaseModel): +class FormattedEscalationEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class FormattedEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class FormattedGuardrailEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class FormattedNonGuardrailEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class Context(BaseModel): content: str """The actual content/text of the document.""" @@ -26,12 +58,22 @@ class QueryLogGroupContext(BaseModel): """Title or heading of the document. Useful for display and context.""" -class QueryLogGroup(BaseModel): +class DeterministicGuardrailsResults(BaseModel): + guardrail_name: str + + should_guardrail: bool + + matches: Optional[List[str]] = None + + +class QueryLogListGroupsResponse(BaseModel): id: str created_at: datetime - formatted_eval_scores: Optional[Dict[str, Dict[str, Union[float, Literal["pass", "fail"]]]]] = None + formatted_escalation_eval_scores: Optional[Dict[str, FormattedEscalationEvalScores]] = None + + formatted_eval_scores: Optional[Dict[str, FormattedEvalScores]] = None """Format evaluation scores for frontend display with pass/fail status. Returns: Dictionary mapping eval keys to their formatted representation: { @@ -39,6 +81,10 @@ class QueryLogGroup(BaseModel): eval_scores is None. """ + formatted_guardrail_eval_scores: Optional[Dict[str, FormattedGuardrailEvalScores]] = None + + formatted_non_guardrail_eval_scores: Optional[Dict[str, FormattedNonGuardrailEvalScores]] = None + is_bad_response: bool needs_review: bool @@ -49,14 +95,14 @@ class QueryLogGroup(BaseModel): remediation_id: str - status: Literal["ACTIVE", "DRAFT", "ACTIVE_WITH_DRAFT", "NOT_STARTED", "PAUSED", "NO_ACTION_NEEDED"] + remediation_status: Literal["ACTIVE", "DRAFT", "ACTIVE_WITH_DRAFT", "NOT_STARTED", "PAUSED", "NO_ACTION_NEEDED"] total_count: int was_cache_hit: Optional[bool] = None """If similar query already answered, or None if cache was not checked""" - context: Optional[List[QueryLogGroupContext]] = None + context: Optional[List[Context]] = None """RAG context used for the query""" custom_metadata: Optional[object] = None @@ -65,9 +111,15 @@ class QueryLogGroup(BaseModel): custom_metadata_keys: Optional[List[str]] = None """Keys of the custom metadata""" + deterministic_guardrails_results: Optional[Dict[str, DeterministicGuardrailsResults]] = None + """Results of deterministic guardrails applied to the query""" + escalated: Optional[bool] = None """If true, the question was escalated to Codex for an SME to review""" + escalation_evals: Optional[List[str]] = None + """Evals that should trigger escalation to SME""" + eval_issue_labels: Optional[List[str]] = None """Labels derived from evaluation scores""" @@ -80,6 +132,9 @@ class QueryLogGroup(BaseModel): evaluated_response: Optional[str] = None """The response being evaluated from the RAG system (before any remediation)""" + guardrail_evals: Optional[List[str]] = None + """Evals that should trigger guardrail""" + guardrailed: Optional[bool] = None """If true, the response was guardrailed""" @@ -88,11 +143,3 @@ class QueryLogGroup(BaseModel): primary_eval_issue_score: Optional[float] = None """Score of the primary eval issue""" - - -class QueryLogListGroupsResponse(BaseModel): - custom_metadata_columns: List[str] - - query_log_groups: List[QueryLogGroup] - - total_count: int diff --git a/src/codex/types/projects/query_log_list_params.py b/src/codex/types/projects/query_log_list_params.py index 9cf3211f..5892d3c9 100644 --- a/src/codex/types/projects/query_log_list_params.py +++ b/src/codex/types/projects/query_log_list_params.py @@ -21,14 +21,23 @@ class QueryLogListParams(TypedDict, total=False): custom_metadata: Optional[str] """Filter by custom metadata as JSON string: {"key1": "value1", "key2": "value2"}""" + failed_evals: Optional[List[str]] + """Filter by evals that failed""" + + guardrailed: Optional[bool] + """Filter by guardrailed status""" + limit: int offset: int order: Literal["asc", "desc"] + passed_evals: Optional[List[str]] + """Filter by evals that passed""" + primary_eval_issue: Optional[ - List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "unsupported"]] + List[Literal["hallucination", "search_failure", "unhelpful", "difficult_query", "ungrounded"]] ] """Filter logs that have ANY of these primary evaluation issues (OR operation)""" diff --git a/src/codex/types/projects/query_log_list_response.py b/src/codex/types/projects/query_log_list_response.py index bfd37cdd..ccdeb038 100644 --- a/src/codex/types/projects/query_log_list_response.py +++ b/src/codex/types/projects/query_log_list_response.py @@ -6,10 +6,42 @@ from ..._models import BaseModel -__all__ = ["QueryLogListResponse", "QueryLog", "QueryLogContext"] +__all__ = [ + "QueryLogListResponse", + "FormattedEscalationEvalScores", + "FormattedEvalScores", + "FormattedGuardrailEvalScores", + "FormattedNonGuardrailEvalScores", + "Context", + "DeterministicGuardrailsResults", +] -class QueryLogContext(BaseModel): +class FormattedEscalationEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class FormattedEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class FormattedGuardrailEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class FormattedNonGuardrailEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class Context(BaseModel): content: str """The actual content/text of the document.""" @@ -26,12 +58,22 @@ class QueryLogContext(BaseModel): """Title or heading of the document. Useful for display and context.""" -class QueryLog(BaseModel): +class DeterministicGuardrailsResults(BaseModel): + guardrail_name: str + + should_guardrail: bool + + matches: Optional[List[str]] = None + + +class QueryLogListResponse(BaseModel): id: str created_at: datetime - formatted_eval_scores: Optional[Dict[str, Dict[str, Union[float, Literal["pass", "fail"]]]]] = None + formatted_escalation_eval_scores: Optional[Dict[str, FormattedEscalationEvalScores]] = None + + formatted_eval_scores: Optional[Dict[str, FormattedEvalScores]] = None """Format evaluation scores for frontend display with pass/fail status. Returns: Dictionary mapping eval keys to their formatted representation: { @@ -39,6 +81,10 @@ class QueryLog(BaseModel): eval_scores is None. """ + formatted_guardrail_eval_scores: Optional[Dict[str, FormattedGuardrailEvalScores]] = None + + formatted_non_guardrail_eval_scores: Optional[Dict[str, FormattedNonGuardrailEvalScores]] = None + is_bad_response: bool project_id: str @@ -50,7 +96,7 @@ class QueryLog(BaseModel): was_cache_hit: Optional[bool] = None """If similar query already answered, or None if cache was not checked""" - context: Optional[List[QueryLogContext]] = None + context: Optional[List[Context]] = None """RAG context used for the query""" custom_metadata: Optional[object] = None @@ -59,9 +105,15 @@ class QueryLog(BaseModel): custom_metadata_keys: Optional[List[str]] = None """Keys of the custom metadata""" + deterministic_guardrails_results: Optional[Dict[str, DeterministicGuardrailsResults]] = None + """Results of deterministic guardrails applied to the query""" + escalated: Optional[bool] = None """If true, the question was escalated to Codex for an SME to review""" + escalation_evals: Optional[List[str]] = None + """Evals that should trigger escalation to SME""" + eval_issue_labels: Optional[List[str]] = None """Labels derived from evaluation scores""" @@ -74,6 +126,9 @@ class QueryLog(BaseModel): evaluated_response: Optional[str] = None """The response being evaluated from the RAG system (before any remediation)""" + guardrail_evals: Optional[List[str]] = None + """Evals that should trigger guardrail""" + guardrailed: Optional[bool] = None """If true, the response was guardrailed""" @@ -82,11 +137,3 @@ class QueryLog(BaseModel): primary_eval_issue_score: Optional[float] = None """Score of the primary eval issue""" - - -class QueryLogListResponse(BaseModel): - custom_metadata_columns: List[str] - - query_logs: List[QueryLog] - - total_count: int diff --git a/src/codex/types/projects/query_log_retrieve_response.py b/src/codex/types/projects/query_log_retrieve_response.py index 3b813eea..380bacba 100644 --- a/src/codex/types/projects/query_log_retrieve_response.py +++ b/src/codex/types/projects/query_log_retrieve_response.py @@ -6,7 +6,39 @@ from ..._models import BaseModel -__all__ = ["QueryLogRetrieveResponse", "Context"] +__all__ = [ + "QueryLogRetrieveResponse", + "FormattedEscalationEvalScores", + "FormattedEvalScores", + "FormattedGuardrailEvalScores", + "FormattedNonGuardrailEvalScores", + "Context", + "DeterministicGuardrailsResults", +] + + +class FormattedEscalationEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class FormattedEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class FormattedGuardrailEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class FormattedNonGuardrailEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] class Context(BaseModel): @@ -26,12 +58,22 @@ class Context(BaseModel): """Title or heading of the document. Useful for display and context.""" +class DeterministicGuardrailsResults(BaseModel): + guardrail_name: str + + should_guardrail: bool + + matches: Optional[List[str]] = None + + class QueryLogRetrieveResponse(BaseModel): id: str created_at: datetime - formatted_eval_scores: Optional[Dict[str, Dict[str, Union[float, Literal["pass", "fail"]]]]] = None + formatted_escalation_eval_scores: Optional[Dict[str, FormattedEscalationEvalScores]] = None + + formatted_eval_scores: Optional[Dict[str, FormattedEvalScores]] = None """Format evaluation scores for frontend display with pass/fail status. Returns: Dictionary mapping eval keys to their formatted representation: { @@ -39,14 +81,22 @@ class QueryLogRetrieveResponse(BaseModel): eval_scores is None. """ + formatted_guardrail_eval_scores: Optional[Dict[str, FormattedGuardrailEvalScores]] = None + + formatted_non_guardrail_eval_scores: Optional[Dict[str, FormattedNonGuardrailEvalScores]] = None + is_bad_response: bool + needs_review: bool + project_id: str question: str remediation_id: str + remediation_status: Literal["ACTIVE", "DRAFT", "ACTIVE_WITH_DRAFT", "NOT_STARTED", "PAUSED", "NO_ACTION_NEEDED"] + was_cache_hit: Optional[bool] = None """If similar query already answered, or None if cache was not checked""" @@ -59,9 +109,15 @@ class QueryLogRetrieveResponse(BaseModel): custom_metadata_keys: Optional[List[str]] = None """Keys of the custom metadata""" + deterministic_guardrails_results: Optional[Dict[str, DeterministicGuardrailsResults]] = None + """Results of deterministic guardrails applied to the query""" + escalated: Optional[bool] = None """If true, the question was escalated to Codex for an SME to review""" + escalation_evals: Optional[List[str]] = None + """Evals that should trigger escalation to SME""" + eval_issue_labels: Optional[List[str]] = None """Labels derived from evaluation scores""" @@ -74,6 +130,9 @@ class QueryLogRetrieveResponse(BaseModel): evaluated_response: Optional[str] = None """The response being evaluated from the RAG system (before any remediation)""" + guardrail_evals: Optional[List[str]] = None + """Evals that should trigger guardrail""" + guardrailed: Optional[bool] = None """If true, the response was guardrailed""" diff --git a/src/codex/types/projects/remediation_list_resolved_logs_response.py b/src/codex/types/projects/remediation_list_resolved_logs_response.py index 4f9682b6..876e7cec 100644 --- a/src/codex/types/projects/remediation_list_resolved_logs_response.py +++ b/src/codex/types/projects/remediation_list_resolved_logs_response.py @@ -6,7 +6,40 @@ from ..._models import BaseModel -__all__ = ["RemediationListResolvedLogsResponse", "QueryLog", "QueryLogContext"] +__all__ = [ + "RemediationListResolvedLogsResponse", + "QueryLog", + "QueryLogFormattedEscalationEvalScores", + "QueryLogFormattedEvalScores", + "QueryLogFormattedGuardrailEvalScores", + "QueryLogFormattedNonGuardrailEvalScores", + "QueryLogContext", + "QueryLogDeterministicGuardrailsResults", +] + + +class QueryLogFormattedEscalationEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class QueryLogFormattedEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class QueryLogFormattedGuardrailEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class QueryLogFormattedNonGuardrailEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] class QueryLogContext(BaseModel): @@ -26,12 +59,22 @@ class QueryLogContext(BaseModel): """Title or heading of the document. Useful for display and context.""" +class QueryLogDeterministicGuardrailsResults(BaseModel): + guardrail_name: str + + should_guardrail: bool + + matches: Optional[List[str]] = None + + class QueryLog(BaseModel): id: str created_at: datetime - formatted_eval_scores: Optional[Dict[str, Dict[str, Union[float, Literal["pass", "fail"]]]]] = None + formatted_escalation_eval_scores: Optional[Dict[str, QueryLogFormattedEscalationEvalScores]] = None + + formatted_eval_scores: Optional[Dict[str, QueryLogFormattedEvalScores]] = None """Format evaluation scores for frontend display with pass/fail status. Returns: Dictionary mapping eval keys to their formatted representation: { @@ -39,6 +82,10 @@ class QueryLog(BaseModel): eval_scores is None. """ + formatted_guardrail_eval_scores: Optional[Dict[str, QueryLogFormattedGuardrailEvalScores]] = None + + formatted_non_guardrail_eval_scores: Optional[Dict[str, QueryLogFormattedNonGuardrailEvalScores]] = None + is_bad_response: bool project_id: str @@ -59,9 +106,15 @@ class QueryLog(BaseModel): custom_metadata_keys: Optional[List[str]] = None """Keys of the custom metadata""" + deterministic_guardrails_results: Optional[Dict[str, QueryLogDeterministicGuardrailsResults]] = None + """Results of deterministic guardrails applied to the query""" + escalated: Optional[bool] = None """If true, the question was escalated to Codex for an SME to review""" + escalation_evals: Optional[List[str]] = None + """Evals that should trigger escalation to SME""" + eval_issue_labels: Optional[List[str]] = None """Labels derived from evaluation scores""" @@ -74,6 +127,9 @@ class QueryLog(BaseModel): evaluated_response: Optional[str] = None """The response being evaluated from the RAG system (before any remediation)""" + guardrail_evals: Optional[List[str]] = None + """Evals that should trigger guardrail""" + guardrailed: Optional[bool] = None """If true, the response was guardrailed""" diff --git a/src/codex/types/projects/remediation_list_response.py b/src/codex/types/projects/remediation_list_response.py index 9d5cda86..83410539 100644 --- a/src/codex/types/projects/remediation_list_response.py +++ b/src/codex/types/projects/remediation_list_response.py @@ -1,15 +1,15 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Optional from datetime import datetime from typing_extensions import Literal from ..._models import BaseModel -__all__ = ["RemediationListResponse", "Remediation"] +__all__ = ["RemediationListResponse"] -class Remediation(BaseModel): +class RemediationListResponse(BaseModel): id: str answered_at: Optional[datetime] = None @@ -35,9 +35,3 @@ class Remediation(BaseModel): answer: Optional[str] = None draft_answer: Optional[str] = None - - -class RemediationListResponse(BaseModel): - remediations: List[Remediation] - - total_count: int diff --git a/tests/api_resources/projects/test_clusters.py b/tests/api_resources/projects/test_clusters.py deleted file mode 100644 index 87734277..00000000 --- a/tests/api_resources/projects/test_clusters.py +++ /dev/null @@ -1,247 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from codex import Codex, AsyncCodex -from tests.utils import assert_matches_type -from codex.pagination import SyncOffsetPageClusters, AsyncOffsetPageClusters -from codex.types.projects import ClusterListResponse, ClusterListVariantsResponse - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestClusters: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @pytest.mark.skip() - @parametrize - def test_method_list(self, client: Codex) -> None: - cluster = client.projects.clusters.list( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(SyncOffsetPageClusters[ClusterListResponse], cluster, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_method_list_with_all_params(self, client: Codex) -> None: - cluster = client.projects.clusters.list( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - eval_issue_types=["hallucination"], - instruction_adherence_failure="html_format", - limit=1, - offset=0, - order="asc", - sort="created_at", - states=["unanswered"], - ) - assert_matches_type(SyncOffsetPageClusters[ClusterListResponse], cluster, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_raw_response_list(self, client: Codex) -> None: - response = client.projects.clusters.with_raw_response.list( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - cluster = response.parse() - assert_matches_type(SyncOffsetPageClusters[ClusterListResponse], cluster, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_streaming_response_list(self, client: Codex) -> None: - with client.projects.clusters.with_streaming_response.list( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - cluster = response.parse() - assert_matches_type(SyncOffsetPageClusters[ClusterListResponse], cluster, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - def test_path_params_list(self, client: Codex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - client.projects.clusters.with_raw_response.list( - project_id="", - ) - - @pytest.mark.skip() - @parametrize - def test_method_list_variants(self, client: Codex) -> None: - cluster = client.projects.clusters.list_variants( - representative_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(ClusterListVariantsResponse, cluster, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_raw_response_list_variants(self, client: Codex) -> None: - response = client.projects.clusters.with_raw_response.list_variants( - representative_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - cluster = response.parse() - assert_matches_type(ClusterListVariantsResponse, cluster, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_streaming_response_list_variants(self, client: Codex) -> None: - with client.projects.clusters.with_streaming_response.list_variants( - representative_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - cluster = response.parse() - assert_matches_type(ClusterListVariantsResponse, cluster, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - def test_path_params_list_variants(self, client: Codex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - client.projects.clusters.with_raw_response.list_variants( - representative_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="", - ) - - with pytest.raises( - ValueError, match=r"Expected a non-empty value for `representative_entry_id` but received ''" - ): - client.projects.clusters.with_raw_response.list_variants( - representative_entry_id="", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - -class TestAsyncClusters: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @pytest.mark.skip() - @parametrize - async def test_method_list(self, async_client: AsyncCodex) -> None: - cluster = await async_client.projects.clusters.list( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(AsyncOffsetPageClusters[ClusterListResponse], cluster, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncCodex) -> None: - cluster = await async_client.projects.clusters.list( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - eval_issue_types=["hallucination"], - instruction_adherence_failure="html_format", - limit=1, - offset=0, - order="asc", - sort="created_at", - states=["unanswered"], - ) - assert_matches_type(AsyncOffsetPageClusters[ClusterListResponse], cluster, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_raw_response_list(self, async_client: AsyncCodex) -> None: - response = await async_client.projects.clusters.with_raw_response.list( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - cluster = await response.parse() - assert_matches_type(AsyncOffsetPageClusters[ClusterListResponse], cluster, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_streaming_response_list(self, async_client: AsyncCodex) -> None: - async with async_client.projects.clusters.with_streaming_response.list( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - cluster = await response.parse() - assert_matches_type(AsyncOffsetPageClusters[ClusterListResponse], cluster, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - async def test_path_params_list(self, async_client: AsyncCodex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - await async_client.projects.clusters.with_raw_response.list( - project_id="", - ) - - @pytest.mark.skip() - @parametrize - async def test_method_list_variants(self, async_client: AsyncCodex) -> None: - cluster = await async_client.projects.clusters.list_variants( - representative_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(ClusterListVariantsResponse, cluster, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_raw_response_list_variants(self, async_client: AsyncCodex) -> None: - response = await async_client.projects.clusters.with_raw_response.list_variants( - representative_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - cluster = await response.parse() - assert_matches_type(ClusterListVariantsResponse, cluster, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_streaming_response_list_variants(self, async_client: AsyncCodex) -> None: - async with async_client.projects.clusters.with_streaming_response.list_variants( - representative_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - cluster = await response.parse() - assert_matches_type(ClusterListVariantsResponse, cluster, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - async def test_path_params_list_variants(self, async_client: AsyncCodex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - await async_client.projects.clusters.with_raw_response.list_variants( - representative_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="", - ) - - with pytest.raises( - ValueError, match=r"Expected a non-empty value for `representative_entry_id` but received ''" - ): - await async_client.projects.clusters.with_raw_response.list_variants( - representative_entry_id="", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) diff --git a/tests/api_resources/projects/test_entries.py b/tests/api_resources/projects/test_entries.py deleted file mode 100644 index 1b077d10..00000000 --- a/tests/api_resources/projects/test_entries.py +++ /dev/null @@ -1,1014 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from codex import Codex, AsyncCodex -from tests.utils import assert_matches_type -from codex.types.projects import ( - Entry, - EntryQueryResponse, - EntryNotifySmeResponse, -) - -# pyright: reportDeprecated=false - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestEntries: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @pytest.mark.skip() - @parametrize - def test_method_create(self, client: Codex) -> None: - entry = client.projects.entries.create( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - ) - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_method_create_with_all_params(self, client: Codex) -> None: - entry = client.projects.entries.create( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - answer="answer", - client_query_metadata=[{}], - draft_answer="draft_answer", - x_client_library_version="x-client-library-version", - x_integration_type="x-integration-type", - x_source="x-source", - x_stainless_package_version="x-stainless-package-version", - ) - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_raw_response_create(self, client: Codex) -> None: - response = client.projects.entries.with_raw_response.create( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_streaming_response_create(self, client: Codex) -> None: - with client.projects.entries.with_streaming_response.create( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - def test_path_params_create(self, client: Codex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - client.projects.entries.with_raw_response.create( - project_id="", - question="question", - ) - - @pytest.mark.skip() - @parametrize - def test_method_retrieve(self, client: Codex) -> None: - entry = client.projects.entries.retrieve( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_raw_response_retrieve(self, client: Codex) -> None: - response = client.projects.entries.with_raw_response.retrieve( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_streaming_response_retrieve(self, client: Codex) -> None: - with client.projects.entries.with_streaming_response.retrieve( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - def test_path_params_retrieve(self, client: Codex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - client.projects.entries.with_raw_response.retrieve( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entry_id` but received ''"): - client.projects.entries.with_raw_response.retrieve( - entry_id="", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - @pytest.mark.skip() - @parametrize - def test_method_update(self, client: Codex) -> None: - entry = client.projects.entries.update( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_method_update_with_all_params(self, client: Codex) -> None: - entry = client.projects.entries.update( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - answer="answer", - draft_answer="draft_answer", - question="question", - ) - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_raw_response_update(self, client: Codex) -> None: - response = client.projects.entries.with_raw_response.update( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_streaming_response_update(self, client: Codex) -> None: - with client.projects.entries.with_streaming_response.update( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - def test_path_params_update(self, client: Codex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - client.projects.entries.with_raw_response.update( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entry_id` but received ''"): - client.projects.entries.with_raw_response.update( - entry_id="", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - @pytest.mark.skip() - @parametrize - def test_method_delete(self, client: Codex) -> None: - entry = client.projects.entries.delete( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert entry is None - - @pytest.mark.skip() - @parametrize - def test_raw_response_delete(self, client: Codex) -> None: - response = client.projects.entries.with_raw_response.delete( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = response.parse() - assert entry is None - - @pytest.mark.skip() - @parametrize - def test_streaming_response_delete(self, client: Codex) -> None: - with client.projects.entries.with_streaming_response.delete( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = response.parse() - assert entry is None - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - def test_path_params_delete(self, client: Codex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - client.projects.entries.with_raw_response.delete( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entry_id` but received ''"): - client.projects.entries.with_raw_response.delete( - entry_id="", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - @pytest.mark.skip() - @parametrize - def test_method_notify_sme(self, client: Codex) -> None: - entry = client.projects.entries.notify_sme( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - email="email", - view_context={"page": 0}, - ) - assert_matches_type(EntryNotifySmeResponse, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_method_notify_sme_with_all_params(self, client: Codex) -> None: - entry = client.projects.entries.notify_sme( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - email="email", - view_context={ - "page": 0, - "filter": "unanswered", - }, - ) - assert_matches_type(EntryNotifySmeResponse, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_raw_response_notify_sme(self, client: Codex) -> None: - response = client.projects.entries.with_raw_response.notify_sme( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - email="email", - view_context={"page": 0}, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = response.parse() - assert_matches_type(EntryNotifySmeResponse, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_streaming_response_notify_sme(self, client: Codex) -> None: - with client.projects.entries.with_streaming_response.notify_sme( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - email="email", - view_context={"page": 0}, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = response.parse() - assert_matches_type(EntryNotifySmeResponse, entry, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - def test_path_params_notify_sme(self, client: Codex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - client.projects.entries.with_raw_response.notify_sme( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="", - email="email", - view_context={"page": 0}, - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entry_id` but received ''"): - client.projects.entries.with_raw_response.notify_sme( - entry_id="", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - email="email", - view_context={"page": 0}, - ) - - @pytest.mark.skip() - @parametrize - def test_method_publish_draft_answer(self, client: Codex) -> None: - entry = client.projects.entries.publish_draft_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_raw_response_publish_draft_answer(self, client: Codex) -> None: - response = client.projects.entries.with_raw_response.publish_draft_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_streaming_response_publish_draft_answer(self, client: Codex) -> None: - with client.projects.entries.with_streaming_response.publish_draft_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - def test_path_params_publish_draft_answer(self, client: Codex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - client.projects.entries.with_raw_response.publish_draft_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entry_id` but received ''"): - client.projects.entries.with_raw_response.publish_draft_answer( - entry_id="", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - @pytest.mark.skip() - @parametrize - def test_method_query(self, client: Codex) -> None: - with pytest.warns(DeprecationWarning): - entry = client.projects.entries.query( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - ) - - assert_matches_type(EntryQueryResponse, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_method_query_with_all_params(self, client: Codex) -> None: - with pytest.warns(DeprecationWarning): - entry = client.projects.entries.query( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - use_llm_matching=True, - client_metadata={}, - query_metadata={ - "context": "string", - "custom_metadata": {}, - "eval_scores": {"foo": 0}, - "evaluated_response": "evaluated_response", - "messages": [ - { - "content": "string", - "role": "developer", - "name": "name", - } - ], - "original_question": "original_question", - }, - x_client_library_version="x-client-library-version", - x_integration_type="x-integration-type", - x_source="x-source", - x_stainless_package_version="x-stainless-package-version", - ) - - assert_matches_type(EntryQueryResponse, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_raw_response_query(self, client: Codex) -> None: - with pytest.warns(DeprecationWarning): - response = client.projects.entries.with_raw_response.query( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = response.parse() - assert_matches_type(EntryQueryResponse, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_streaming_response_query(self, client: Codex) -> None: - with pytest.warns(DeprecationWarning): - with client.projects.entries.with_streaming_response.query( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = response.parse() - assert_matches_type(EntryQueryResponse, entry, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - def test_path_params_query(self, client: Codex) -> None: - with pytest.warns(DeprecationWarning): - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - client.projects.entries.with_raw_response.query( - project_id="", - question="question", - ) - - @pytest.mark.skip() - @parametrize - def test_method_unpublish_answer(self, client: Codex) -> None: - entry = client.projects.entries.unpublish_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_raw_response_unpublish_answer(self, client: Codex) -> None: - response = client.projects.entries.with_raw_response.unpublish_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_streaming_response_unpublish_answer(self, client: Codex) -> None: - with client.projects.entries.with_streaming_response.unpublish_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - def test_path_params_unpublish_answer(self, client: Codex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - client.projects.entries.with_raw_response.unpublish_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entry_id` but received ''"): - client.projects.entries.with_raw_response.unpublish_answer( - entry_id="", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - -class TestAsyncEntries: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @pytest.mark.skip() - @parametrize - async def test_method_create(self, async_client: AsyncCodex) -> None: - entry = await async_client.projects.entries.create( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - ) - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncCodex) -> None: - entry = await async_client.projects.entries.create( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - answer="answer", - client_query_metadata=[{}], - draft_answer="draft_answer", - x_client_library_version="x-client-library-version", - x_integration_type="x-integration-type", - x_source="x-source", - x_stainless_package_version="x-stainless-package-version", - ) - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_raw_response_create(self, async_client: AsyncCodex) -> None: - response = await async_client.projects.entries.with_raw_response.create( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = await response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_streaming_response_create(self, async_client: AsyncCodex) -> None: - async with async_client.projects.entries.with_streaming_response.create( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = await response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - async def test_path_params_create(self, async_client: AsyncCodex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - await async_client.projects.entries.with_raw_response.create( - project_id="", - question="question", - ) - - @pytest.mark.skip() - @parametrize - async def test_method_retrieve(self, async_client: AsyncCodex) -> None: - entry = await async_client.projects.entries.retrieve( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_raw_response_retrieve(self, async_client: AsyncCodex) -> None: - response = await async_client.projects.entries.with_raw_response.retrieve( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = await response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncCodex) -> None: - async with async_client.projects.entries.with_streaming_response.retrieve( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = await response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - async def test_path_params_retrieve(self, async_client: AsyncCodex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - await async_client.projects.entries.with_raw_response.retrieve( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entry_id` but received ''"): - await async_client.projects.entries.with_raw_response.retrieve( - entry_id="", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - @pytest.mark.skip() - @parametrize - async def test_method_update(self, async_client: AsyncCodex) -> None: - entry = await async_client.projects.entries.update( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_method_update_with_all_params(self, async_client: AsyncCodex) -> None: - entry = await async_client.projects.entries.update( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - answer="answer", - draft_answer="draft_answer", - question="question", - ) - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_raw_response_update(self, async_client: AsyncCodex) -> None: - response = await async_client.projects.entries.with_raw_response.update( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = await response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_streaming_response_update(self, async_client: AsyncCodex) -> None: - async with async_client.projects.entries.with_streaming_response.update( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = await response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - async def test_path_params_update(self, async_client: AsyncCodex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - await async_client.projects.entries.with_raw_response.update( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entry_id` but received ''"): - await async_client.projects.entries.with_raw_response.update( - entry_id="", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - @pytest.mark.skip() - @parametrize - async def test_method_delete(self, async_client: AsyncCodex) -> None: - entry = await async_client.projects.entries.delete( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert entry is None - - @pytest.mark.skip() - @parametrize - async def test_raw_response_delete(self, async_client: AsyncCodex) -> None: - response = await async_client.projects.entries.with_raw_response.delete( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = await response.parse() - assert entry is None - - @pytest.mark.skip() - @parametrize - async def test_streaming_response_delete(self, async_client: AsyncCodex) -> None: - async with async_client.projects.entries.with_streaming_response.delete( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = await response.parse() - assert entry is None - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - async def test_path_params_delete(self, async_client: AsyncCodex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - await async_client.projects.entries.with_raw_response.delete( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entry_id` but received ''"): - await async_client.projects.entries.with_raw_response.delete( - entry_id="", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - @pytest.mark.skip() - @parametrize - async def test_method_notify_sme(self, async_client: AsyncCodex) -> None: - entry = await async_client.projects.entries.notify_sme( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - email="email", - view_context={"page": 0}, - ) - assert_matches_type(EntryNotifySmeResponse, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_method_notify_sme_with_all_params(self, async_client: AsyncCodex) -> None: - entry = await async_client.projects.entries.notify_sme( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - email="email", - view_context={ - "page": 0, - "filter": "unanswered", - }, - ) - assert_matches_type(EntryNotifySmeResponse, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_raw_response_notify_sme(self, async_client: AsyncCodex) -> None: - response = await async_client.projects.entries.with_raw_response.notify_sme( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - email="email", - view_context={"page": 0}, - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = await response.parse() - assert_matches_type(EntryNotifySmeResponse, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_streaming_response_notify_sme(self, async_client: AsyncCodex) -> None: - async with async_client.projects.entries.with_streaming_response.notify_sme( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - email="email", - view_context={"page": 0}, - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = await response.parse() - assert_matches_type(EntryNotifySmeResponse, entry, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - async def test_path_params_notify_sme(self, async_client: AsyncCodex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - await async_client.projects.entries.with_raw_response.notify_sme( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="", - email="email", - view_context={"page": 0}, - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entry_id` but received ''"): - await async_client.projects.entries.with_raw_response.notify_sme( - entry_id="", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - email="email", - view_context={"page": 0}, - ) - - @pytest.mark.skip() - @parametrize - async def test_method_publish_draft_answer(self, async_client: AsyncCodex) -> None: - entry = await async_client.projects.entries.publish_draft_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_raw_response_publish_draft_answer(self, async_client: AsyncCodex) -> None: - response = await async_client.projects.entries.with_raw_response.publish_draft_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = await response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_streaming_response_publish_draft_answer(self, async_client: AsyncCodex) -> None: - async with async_client.projects.entries.with_streaming_response.publish_draft_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = await response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - async def test_path_params_publish_draft_answer(self, async_client: AsyncCodex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - await async_client.projects.entries.with_raw_response.publish_draft_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entry_id` but received ''"): - await async_client.projects.entries.with_raw_response.publish_draft_answer( - entry_id="", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - @pytest.mark.skip() - @parametrize - async def test_method_query(self, async_client: AsyncCodex) -> None: - with pytest.warns(DeprecationWarning): - entry = await async_client.projects.entries.query( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - ) - - assert_matches_type(EntryQueryResponse, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_method_query_with_all_params(self, async_client: AsyncCodex) -> None: - with pytest.warns(DeprecationWarning): - entry = await async_client.projects.entries.query( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - use_llm_matching=True, - client_metadata={}, - query_metadata={ - "context": "string", - "custom_metadata": {}, - "eval_scores": {"foo": 0}, - "evaluated_response": "evaluated_response", - "messages": [ - { - "content": "string", - "role": "developer", - "name": "name", - } - ], - "original_question": "original_question", - }, - x_client_library_version="x-client-library-version", - x_integration_type="x-integration-type", - x_source="x-source", - x_stainless_package_version="x-stainless-package-version", - ) - - assert_matches_type(EntryQueryResponse, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_raw_response_query(self, async_client: AsyncCodex) -> None: - with pytest.warns(DeprecationWarning): - response = await async_client.projects.entries.with_raw_response.query( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = await response.parse() - assert_matches_type(EntryQueryResponse, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_streaming_response_query(self, async_client: AsyncCodex) -> None: - with pytest.warns(DeprecationWarning): - async with async_client.projects.entries.with_streaming_response.query( - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - question="question", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = await response.parse() - assert_matches_type(EntryQueryResponse, entry, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - async def test_path_params_query(self, async_client: AsyncCodex) -> None: - with pytest.warns(DeprecationWarning): - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - await async_client.projects.entries.with_raw_response.query( - project_id="", - question="question", - ) - - @pytest.mark.skip() - @parametrize - async def test_method_unpublish_answer(self, async_client: AsyncCodex) -> None: - entry = await async_client.projects.entries.unpublish_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_raw_response_unpublish_answer(self, async_client: AsyncCodex) -> None: - response = await async_client.projects.entries.with_raw_response.unpublish_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - entry = await response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_streaming_response_unpublish_answer(self, async_client: AsyncCodex) -> None: - async with async_client.projects.entries.with_streaming_response.unpublish_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - entry = await response.parse() - assert_matches_type(Entry, entry, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip() - @parametrize - async def test_path_params_unpublish_answer(self, async_client: AsyncCodex) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): - await async_client.projects.entries.with_raw_response.unpublish_answer( - entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - project_id="", - ) - - with pytest.raises(ValueError, match=r"Expected a non-empty value for `entry_id` but received ''"): - await async_client.projects.entries.with_raw_response.unpublish_answer( - entry_id="", - project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) diff --git a/tests/api_resources/projects/test_query_logs.py b/tests/api_resources/projects/test_query_logs.py index d75dcabe..cd4cd7d2 100644 --- a/tests/api_resources/projects/test_query_logs.py +++ b/tests/api_resources/projects/test_query_logs.py @@ -10,6 +10,12 @@ from codex import Codex, AsyncCodex from tests.utils import assert_matches_type from codex._utils import parse_datetime +from codex.pagination import ( + SyncOffsetPageQueryLogs, + AsyncOffsetPageQueryLogs, + SyncOffsetPageQueryLogGroups, + AsyncOffsetPageQueryLogGroups, +) from codex.types.projects import ( QueryLogListResponse, QueryLogRetrieveResponse, @@ -82,7 +88,7 @@ def test_method_list(self, client: Codex) -> None: query_log = client.projects.query_logs.list( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(QueryLogListResponse, query_log, path=["response"]) + assert_matches_type(SyncOffsetPageQueryLogs[QueryLogListResponse], query_log, path=["response"]) @pytest.mark.skip() @parametrize @@ -92,14 +98,17 @@ def test_method_list_with_all_params(self, client: Codex) -> None: created_at_end=parse_datetime("2019-12-27T18:11:19.117Z"), created_at_start=parse_datetime("2019-12-27T18:11:19.117Z"), custom_metadata="custom_metadata", + failed_evals=["string"], + guardrailed=True, limit=1, offset=0, order="asc", + passed_evals=["string"], primary_eval_issue=["hallucination"], sort="created_at", was_cache_hit=True, ) - assert_matches_type(QueryLogListResponse, query_log, path=["response"]) + assert_matches_type(SyncOffsetPageQueryLogs[QueryLogListResponse], query_log, path=["response"]) @pytest.mark.skip() @parametrize @@ -111,7 +120,7 @@ def test_raw_response_list(self, client: Codex) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" query_log = response.parse() - assert_matches_type(QueryLogListResponse, query_log, path=["response"]) + assert_matches_type(SyncOffsetPageQueryLogs[QueryLogListResponse], query_log, path=["response"]) @pytest.mark.skip() @parametrize @@ -123,7 +132,7 @@ def test_streaming_response_list(self, client: Codex) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" query_log = response.parse() - assert_matches_type(QueryLogListResponse, query_log, path=["response"]) + assert_matches_type(SyncOffsetPageQueryLogs[QueryLogListResponse], query_log, path=["response"]) assert cast(Any, response.is_closed) is True @@ -151,9 +160,13 @@ def test_method_list_by_group_with_all_params(self, client: Codex) -> None: created_at_end=parse_datetime("2019-12-27T18:11:19.117Z"), created_at_start=parse_datetime("2019-12-27T18:11:19.117Z"), custom_metadata="custom_metadata", + failed_evals=["string"], + guardrailed=True, limit=1, + needs_review=True, offset=0, order="asc", + passed_evals=["string"], primary_eval_issue=["hallucination"], remediation_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], sort="created_at", @@ -201,7 +214,7 @@ def test_method_list_groups(self, client: Codex) -> None: query_log = client.projects.query_logs.list_groups( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(QueryLogListGroupsResponse, query_log, path=["response"]) + assert_matches_type(SyncOffsetPageQueryLogGroups[QueryLogListGroupsResponse], query_log, path=["response"]) @pytest.mark.skip() @parametrize @@ -211,14 +224,18 @@ def test_method_list_groups_with_all_params(self, client: Codex) -> None: created_at_end=parse_datetime("2019-12-27T18:11:19.117Z"), created_at_start=parse_datetime("2019-12-27T18:11:19.117Z"), custom_metadata="custom_metadata", + failed_evals=["string"], + guardrailed=True, limit=1, + needs_review=True, offset=0, order="asc", + passed_evals=["string"], primary_eval_issue=["hallucination"], sort="created_at", was_cache_hit=True, ) - assert_matches_type(QueryLogListGroupsResponse, query_log, path=["response"]) + assert_matches_type(SyncOffsetPageQueryLogGroups[QueryLogListGroupsResponse], query_log, path=["response"]) @pytest.mark.skip() @parametrize @@ -230,7 +247,7 @@ def test_raw_response_list_groups(self, client: Codex) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" query_log = response.parse() - assert_matches_type(QueryLogListGroupsResponse, query_log, path=["response"]) + assert_matches_type(SyncOffsetPageQueryLogGroups[QueryLogListGroupsResponse], query_log, path=["response"]) @pytest.mark.skip() @parametrize @@ -242,7 +259,7 @@ def test_streaming_response_list_groups(self, client: Codex) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" query_log = response.parse() - assert_matches_type(QueryLogListGroupsResponse, query_log, path=["response"]) + assert_matches_type(SyncOffsetPageQueryLogGroups[QueryLogListGroupsResponse], query_log, path=["response"]) assert cast(Any, response.is_closed) is True @@ -370,7 +387,7 @@ async def test_method_list(self, async_client: AsyncCodex) -> None: query_log = await async_client.projects.query_logs.list( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(QueryLogListResponse, query_log, path=["response"]) + assert_matches_type(AsyncOffsetPageQueryLogs[QueryLogListResponse], query_log, path=["response"]) @pytest.mark.skip() @parametrize @@ -380,14 +397,17 @@ async def test_method_list_with_all_params(self, async_client: AsyncCodex) -> No created_at_end=parse_datetime("2019-12-27T18:11:19.117Z"), created_at_start=parse_datetime("2019-12-27T18:11:19.117Z"), custom_metadata="custom_metadata", + failed_evals=["string"], + guardrailed=True, limit=1, offset=0, order="asc", + passed_evals=["string"], primary_eval_issue=["hallucination"], sort="created_at", was_cache_hit=True, ) - assert_matches_type(QueryLogListResponse, query_log, path=["response"]) + assert_matches_type(AsyncOffsetPageQueryLogs[QueryLogListResponse], query_log, path=["response"]) @pytest.mark.skip() @parametrize @@ -399,7 +419,7 @@ async def test_raw_response_list(self, async_client: AsyncCodex) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" query_log = await response.parse() - assert_matches_type(QueryLogListResponse, query_log, path=["response"]) + assert_matches_type(AsyncOffsetPageQueryLogs[QueryLogListResponse], query_log, path=["response"]) @pytest.mark.skip() @parametrize @@ -411,7 +431,7 @@ async def test_streaming_response_list(self, async_client: AsyncCodex) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" query_log = await response.parse() - assert_matches_type(QueryLogListResponse, query_log, path=["response"]) + assert_matches_type(AsyncOffsetPageQueryLogs[QueryLogListResponse], query_log, path=["response"]) assert cast(Any, response.is_closed) is True @@ -439,9 +459,13 @@ async def test_method_list_by_group_with_all_params(self, async_client: AsyncCod created_at_end=parse_datetime("2019-12-27T18:11:19.117Z"), created_at_start=parse_datetime("2019-12-27T18:11:19.117Z"), custom_metadata="custom_metadata", + failed_evals=["string"], + guardrailed=True, limit=1, + needs_review=True, offset=0, order="asc", + passed_evals=["string"], primary_eval_issue=["hallucination"], remediation_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], sort="created_at", @@ -489,7 +513,7 @@ async def test_method_list_groups(self, async_client: AsyncCodex) -> None: query_log = await async_client.projects.query_logs.list_groups( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(QueryLogListGroupsResponse, query_log, path=["response"]) + assert_matches_type(AsyncOffsetPageQueryLogGroups[QueryLogListGroupsResponse], query_log, path=["response"]) @pytest.mark.skip() @parametrize @@ -499,14 +523,18 @@ async def test_method_list_groups_with_all_params(self, async_client: AsyncCodex created_at_end=parse_datetime("2019-12-27T18:11:19.117Z"), created_at_start=parse_datetime("2019-12-27T18:11:19.117Z"), custom_metadata="custom_metadata", + failed_evals=["string"], + guardrailed=True, limit=1, + needs_review=True, offset=0, order="asc", + passed_evals=["string"], primary_eval_issue=["hallucination"], sort="created_at", was_cache_hit=True, ) - assert_matches_type(QueryLogListGroupsResponse, query_log, path=["response"]) + assert_matches_type(AsyncOffsetPageQueryLogGroups[QueryLogListGroupsResponse], query_log, path=["response"]) @pytest.mark.skip() @parametrize @@ -518,7 +546,7 @@ async def test_raw_response_list_groups(self, async_client: AsyncCodex) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" query_log = await response.parse() - assert_matches_type(QueryLogListGroupsResponse, query_log, path=["response"]) + assert_matches_type(AsyncOffsetPageQueryLogGroups[QueryLogListGroupsResponse], query_log, path=["response"]) @pytest.mark.skip() @parametrize @@ -530,7 +558,7 @@ async def test_streaming_response_list_groups(self, async_client: AsyncCodex) -> assert response.http_request.headers.get("X-Stainless-Lang") == "python" query_log = await response.parse() - assert_matches_type(QueryLogListGroupsResponse, query_log, path=["response"]) + assert_matches_type(AsyncOffsetPageQueryLogGroups[QueryLogListGroupsResponse], query_log, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/projects/test_remediations.py b/tests/api_resources/projects/test_remediations.py index c75a255c..947850f7 100644 --- a/tests/api_resources/projects/test_remediations.py +++ b/tests/api_resources/projects/test_remediations.py @@ -10,6 +10,7 @@ from codex import Codex, AsyncCodex from tests.utils import assert_matches_type from codex._utils import parse_datetime +from codex.pagination import SyncOffsetPageRemediations, AsyncOffsetPageRemediations from codex.types.projects import ( RemediationListResponse, RemediationPauseResponse, @@ -144,7 +145,7 @@ def test_method_list(self, client: Codex) -> None: remediation = client.projects.remediations.list( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(RemediationListResponse, remediation, path=["response"]) + assert_matches_type(SyncOffsetPageRemediations[RemediationListResponse], remediation, path=["response"]) @pytest.mark.skip() @parametrize @@ -162,7 +163,7 @@ def test_method_list_with_all_params(self, client: Codex) -> None: sort="created_at", status=["ACTIVE"], ) - assert_matches_type(RemediationListResponse, remediation, path=["response"]) + assert_matches_type(SyncOffsetPageRemediations[RemediationListResponse], remediation, path=["response"]) @pytest.mark.skip() @parametrize @@ -174,7 +175,7 @@ def test_raw_response_list(self, client: Codex) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" remediation = response.parse() - assert_matches_type(RemediationListResponse, remediation, path=["response"]) + assert_matches_type(SyncOffsetPageRemediations[RemediationListResponse], remediation, path=["response"]) @pytest.mark.skip() @parametrize @@ -186,7 +187,7 @@ def test_streaming_response_list(self, client: Codex) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" remediation = response.parse() - assert_matches_type(RemediationListResponse, remediation, path=["response"]) + assert_matches_type(SyncOffsetPageRemediations[RemediationListResponse], remediation, path=["response"]) assert cast(Any, response.is_closed) is True @@ -745,7 +746,7 @@ async def test_method_list(self, async_client: AsyncCodex) -> None: remediation = await async_client.projects.remediations.list( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(RemediationListResponse, remediation, path=["response"]) + assert_matches_type(AsyncOffsetPageRemediations[RemediationListResponse], remediation, path=["response"]) @pytest.mark.skip() @parametrize @@ -763,7 +764,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncCodex) -> No sort="created_at", status=["ACTIVE"], ) - assert_matches_type(RemediationListResponse, remediation, path=["response"]) + assert_matches_type(AsyncOffsetPageRemediations[RemediationListResponse], remediation, path=["response"]) @pytest.mark.skip() @parametrize @@ -775,7 +776,7 @@ async def test_raw_response_list(self, async_client: AsyncCodex) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" remediation = await response.parse() - assert_matches_type(RemediationListResponse, remediation, path=["response"]) + assert_matches_type(AsyncOffsetPageRemediations[RemediationListResponse], remediation, path=["response"]) @pytest.mark.skip() @parametrize @@ -787,7 +788,7 @@ async def test_streaming_response_list(self, async_client: AsyncCodex) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" remediation = await response.parse() - assert_matches_type(RemediationListResponse, remediation, path=["response"]) + assert_matches_type(AsyncOffsetPageRemediations[RemediationListResponse], remediation, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_projects.py b/tests/api_resources/test_projects.py index e7d7eb1f..9ecffa09 100644 --- a/tests/api_resources/test_projects.py +++ b/tests/api_resources/test_projects.py @@ -206,8 +206,6 @@ def test_path_params_retrieve(self, client: Codex) -> None: def test_method_update(self, client: Codex) -> None: project = client.projects.update( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - config={}, - name="name", ) assert_matches_type(ProjectReturnSchema, project, path=["response"]) @@ -216,6 +214,7 @@ def test_method_update(self, client: Codex) -> None: def test_method_update_with_all_params(self, client: Codex) -> None: project = client.projects.update( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + auto_clustering_enabled=True, config={ "clustering_use_llm_matching": True, "eval_config": { @@ -298,9 +297,8 @@ def test_method_update_with_all_params(self, client: Codex) -> None: "query_use_llm_matching": True, "upper_llm_match_distance_threshold": 0, }, - name="name", - auto_clustering_enabled=True, description="description", + name="name", ) assert_matches_type(ProjectReturnSchema, project, path=["response"]) @@ -309,8 +307,6 @@ def test_method_update_with_all_params(self, client: Codex) -> None: def test_raw_response_update(self, client: Codex) -> None: response = client.projects.with_raw_response.update( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - config={}, - name="name", ) assert response.is_closed is True @@ -323,8 +319,6 @@ def test_raw_response_update(self, client: Codex) -> None: def test_streaming_response_update(self, client: Codex) -> None: with client.projects.with_streaming_response.update( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - config={}, - name="name", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -340,8 +334,6 @@ def test_path_params_update(self, client: Codex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): client.projects.with_raw_response.update( project_id="", - config={}, - name="name", ) @pytest.mark.skip() @@ -640,9 +632,8 @@ def test_method_validate(self, client: Codex) -> None: project = client.projects.validate( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", context="context", - prompt="prompt", query="query", - response="response", + response="string", ) assert_matches_type(ProjectValidateResponse, project, path=["response"]) @@ -652,9 +643,8 @@ def test_method_validate_with_all_params(self, client: Codex) -> None: project = client.projects.validate( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", context="context", - prompt="prompt", query="query", - response="response", + response="string", use_llm_matching=True, constrain_outputs=["string"], custom_eval_thresholds={"foo": 0}, @@ -678,7 +668,9 @@ def test_method_validate_with_all_params(self, client: Codex) -> None: "similarity_measure": "similarity_measure", "use_self_reflection": True, }, + prompt="prompt", quality_preset="best", + rewritten_question="rewritten_question", task="task", x_client_library_version="x-client-library-version", x_integration_type="x-integration-type", @@ -693,9 +685,8 @@ def test_raw_response_validate(self, client: Codex) -> None: response = client.projects.with_raw_response.validate( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", context="context", - prompt="prompt", query="query", - response="response", + response="string", ) assert response.is_closed is True @@ -709,9 +700,8 @@ def test_streaming_response_validate(self, client: Codex) -> None: with client.projects.with_streaming_response.validate( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", context="context", - prompt="prompt", query="query", - response="response", + response="string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -728,9 +718,8 @@ def test_path_params_validate(self, client: Codex) -> None: client.projects.with_raw_response.validate( project_id="", context="context", - prompt="prompt", query="query", - response="response", + response="string", ) @@ -919,8 +908,6 @@ async def test_path_params_retrieve(self, async_client: AsyncCodex) -> None: async def test_method_update(self, async_client: AsyncCodex) -> None: project = await async_client.projects.update( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - config={}, - name="name", ) assert_matches_type(ProjectReturnSchema, project, path=["response"]) @@ -929,6 +916,7 @@ async def test_method_update(self, async_client: AsyncCodex) -> None: async def test_method_update_with_all_params(self, async_client: AsyncCodex) -> None: project = await async_client.projects.update( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + auto_clustering_enabled=True, config={ "clustering_use_llm_matching": True, "eval_config": { @@ -1011,9 +999,8 @@ async def test_method_update_with_all_params(self, async_client: AsyncCodex) -> "query_use_llm_matching": True, "upper_llm_match_distance_threshold": 0, }, - name="name", - auto_clustering_enabled=True, description="description", + name="name", ) assert_matches_type(ProjectReturnSchema, project, path=["response"]) @@ -1022,8 +1009,6 @@ async def test_method_update_with_all_params(self, async_client: AsyncCodex) -> async def test_raw_response_update(self, async_client: AsyncCodex) -> None: response = await async_client.projects.with_raw_response.update( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - config={}, - name="name", ) assert response.is_closed is True @@ -1036,8 +1021,6 @@ async def test_raw_response_update(self, async_client: AsyncCodex) -> None: async def test_streaming_response_update(self, async_client: AsyncCodex) -> None: async with async_client.projects.with_streaming_response.update( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - config={}, - name="name", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1053,8 +1036,6 @@ async def test_path_params_update(self, async_client: AsyncCodex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `project_id` but received ''"): await async_client.projects.with_raw_response.update( project_id="", - config={}, - name="name", ) @pytest.mark.skip() @@ -1353,9 +1334,8 @@ async def test_method_validate(self, async_client: AsyncCodex) -> None: project = await async_client.projects.validate( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", context="context", - prompt="prompt", query="query", - response="response", + response="string", ) assert_matches_type(ProjectValidateResponse, project, path=["response"]) @@ -1365,9 +1345,8 @@ async def test_method_validate_with_all_params(self, async_client: AsyncCodex) - project = await async_client.projects.validate( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", context="context", - prompt="prompt", query="query", - response="response", + response="string", use_llm_matching=True, constrain_outputs=["string"], custom_eval_thresholds={"foo": 0}, @@ -1391,7 +1370,9 @@ async def test_method_validate_with_all_params(self, async_client: AsyncCodex) - "similarity_measure": "similarity_measure", "use_self_reflection": True, }, + prompt="prompt", quality_preset="best", + rewritten_question="rewritten_question", task="task", x_client_library_version="x-client-library-version", x_integration_type="x-integration-type", @@ -1406,9 +1387,8 @@ async def test_raw_response_validate(self, async_client: AsyncCodex) -> None: response = await async_client.projects.with_raw_response.validate( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", context="context", - prompt="prompt", query="query", - response="response", + response="string", ) assert response.is_closed is True @@ -1422,9 +1402,8 @@ async def test_streaming_response_validate(self, async_client: AsyncCodex) -> No async with async_client.projects.with_streaming_response.validate( project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", context="context", - prompt="prompt", query="query", - response="response", + response="string", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1441,7 +1420,6 @@ async def test_path_params_validate(self, async_client: AsyncCodex) -> None: await async_client.projects.with_raw_response.validate( project_id="", context="context", - prompt="prompt", query="query", - response="response", + response="string", )