From 41b210dc69c2b9c45eeab01a0afac6a4563d41f2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 24 Jun 2025 23:17:37 +0000 Subject: [PATCH 01/18] feat(api): api update --- .stats.yml | 2 +- .../query_log_list_by_group_response.py | 33 +++++++++++++++- .../query_log_list_groups_response.py | 39 ++++++++++++++++++- .../types/projects/query_log_list_response.py | 39 ++++++++++++++++++- .../projects/query_log_retrieve_response.py | 38 +++++++++++++++++- ...remediation_list_resolved_logs_response.py | 39 ++++++++++++++++++- 6 files changed, 180 insertions(+), 10 deletions(-) diff --git a/.stats.yml b/.stats.yml index 04c1386..9e05e79 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,3 +1,3 @@ configured_endpoints: 65 -openapi_spec_hash: 80696dc202de8bacc0e43506d7c210b0 +openapi_spec_hash: 8bc7a64933cd540d1d2499d055430832 config_hash: 14b2643a0ec60cf326dfed00939644ff 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 d11d827..9d1e0e6 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,31 @@ "QueryLogListByGroupResponse", "QueryLogsByGroup", "QueryLogsByGroupQueryLog", + "QueryLogsByGroupQueryLogFormattedEscalationEvalScores", + "QueryLogsByGroupQueryLogFormattedEvalScores", + "QueryLogsByGroupQueryLogFormattedGuardrailEvalScores", "QueryLogsByGroupQueryLogContext", ] +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 QueryLogsByGroupQueryLogContext(BaseModel): content: str """The actual content/text of the document.""" @@ -36,7 +57,9 @@ class QueryLogsByGroupQueryLog(BaseModel): 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,6 +67,8 @@ class QueryLogsByGroupQueryLog(BaseModel): eval_scores is None. """ + formatted_guardrail_eval_scores: Optional[Dict[str, QueryLogsByGroupQueryLogFormattedGuardrailEvalScores]] = None + is_bad_response: bool project_id: str @@ -67,6 +92,9 @@ class QueryLogsByGroupQueryLog(BaseModel): 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 +107,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_response.py b/src/codex/types/projects/query_log_list_groups_response.py index fd87c30..7b77cc0 100644 --- a/src/codex/types/projects/query_log_list_groups_response.py +++ b/src/codex/types/projects/query_log_list_groups_response.py @@ -6,7 +6,32 @@ from ..._models import BaseModel -__all__ = ["QueryLogListGroupsResponse", "QueryLogGroup", "QueryLogGroupContext"] +__all__ = [ + "QueryLogListGroupsResponse", + "QueryLogGroup", + "QueryLogGroupFormattedEscalationEvalScores", + "QueryLogGroupFormattedEvalScores", + "QueryLogGroupFormattedGuardrailEvalScores", + "QueryLogGroupContext", +] + + +class QueryLogGroupFormattedEscalationEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class QueryLogGroupFormattedEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + +class QueryLogGroupFormattedGuardrailEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] class QueryLogGroupContext(BaseModel): @@ -31,7 +56,9 @@ class QueryLogGroup(BaseModel): created_at: datetime - formatted_eval_scores: Optional[Dict[str, Dict[str, Union[float, Literal["pass", "fail"]]]]] = None + formatted_escalation_eval_scores: Optional[Dict[str, QueryLogGroupFormattedEscalationEvalScores]] = None + + formatted_eval_scores: Optional[Dict[str, QueryLogGroupFormattedEvalScores]] = None """Format evaluation scores for frontend display with pass/fail status. Returns: Dictionary mapping eval keys to their formatted representation: { @@ -39,6 +66,8 @@ class QueryLogGroup(BaseModel): eval_scores is None. """ + formatted_guardrail_eval_scores: Optional[Dict[str, QueryLogGroupFormattedGuardrailEvalScores]] = None + is_bad_response: bool needs_review: bool @@ -68,6 +97,9 @@ class QueryLogGroup(BaseModel): 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 +112,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""" diff --git a/src/codex/types/projects/query_log_list_response.py b/src/codex/types/projects/query_log_list_response.py index bfd37cd..fa04904 100644 --- a/src/codex/types/projects/query_log_list_response.py +++ b/src/codex/types/projects/query_log_list_response.py @@ -6,7 +6,32 @@ from ..._models import BaseModel -__all__ = ["QueryLogListResponse", "QueryLog", "QueryLogContext"] +__all__ = [ + "QueryLogListResponse", + "QueryLog", + "QueryLogFormattedEscalationEvalScores", + "QueryLogFormattedEvalScores", + "QueryLogFormattedGuardrailEvalScores", + "QueryLogContext", +] + + +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 QueryLogContext(BaseModel): @@ -31,7 +56,9 @@ class QueryLog(BaseModel): 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 +66,8 @@ class QueryLog(BaseModel): eval_scores is None. """ + formatted_guardrail_eval_scores: Optional[Dict[str, QueryLogFormattedGuardrailEvalScores]] = None + is_bad_response: bool project_id: str @@ -62,6 +91,9 @@ class QueryLog(BaseModel): 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 +106,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/query_log_retrieve_response.py b/src/codex/types/projects/query_log_retrieve_response.py index 3b813ee..8bb6128 100644 --- a/src/codex/types/projects/query_log_retrieve_response.py +++ b/src/codex/types/projects/query_log_retrieve_response.py @@ -6,7 +6,31 @@ from ..._models import BaseModel -__all__ = ["QueryLogRetrieveResponse", "Context"] +__all__ = [ + "QueryLogRetrieveResponse", + "FormattedEscalationEvalScores", + "FormattedEvalScores", + "FormattedGuardrailEvalScores", + "Context", +] + + +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 Context(BaseModel): @@ -31,7 +55,9 @@ class QueryLogRetrieveResponse(BaseModel): 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 +65,8 @@ class QueryLogRetrieveResponse(BaseModel): eval_scores is None. """ + formatted_guardrail_eval_scores: Optional[Dict[str, FormattedGuardrailEvalScores]] = None + is_bad_response: bool project_id: str @@ -62,6 +90,9 @@ class QueryLogRetrieveResponse(BaseModel): 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 +105,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 4f9682b..b2315aa 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,32 @@ from ..._models import BaseModel -__all__ = ["RemediationListResolvedLogsResponse", "QueryLog", "QueryLogContext"] +__all__ = [ + "RemediationListResolvedLogsResponse", + "QueryLog", + "QueryLogFormattedEscalationEvalScores", + "QueryLogFormattedEvalScores", + "QueryLogFormattedGuardrailEvalScores", + "QueryLogContext", +] + + +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 QueryLogContext(BaseModel): @@ -31,7 +56,9 @@ class QueryLog(BaseModel): 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 +66,8 @@ class QueryLog(BaseModel): eval_scores is None. """ + formatted_guardrail_eval_scores: Optional[Dict[str, QueryLogFormattedGuardrailEvalScores]] = None + is_bad_response: bool project_id: str @@ -62,6 +91,9 @@ class QueryLog(BaseModel): 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 +106,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""" From be06884d321ca5009c9d82346c1b74c7429f82fa Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 26 Jun 2025 00:17:35 +0000 Subject: [PATCH 02/18] feat(api): api update --- .stats.yml | 2 +- src/codex/resources/projects/projects.py | 20 ++++++++++---------- src/codex/types/project_update_params.py | 8 ++++---- tests/api_resources/test_projects.py | 24 ++++-------------------- 4 files changed, 19 insertions(+), 35 deletions(-) diff --git a/.stats.yml b/.stats.yml index 9e05e79..31393e0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,3 +1,3 @@ configured_endpoints: 65 -openapi_spec_hash: 8bc7a64933cd540d1d2499d055430832 +openapi_spec_hash: 5d686da2afda75185dc9e4190a42b75c config_hash: 14b2643a0ec60cf326dfed00939644ff diff --git a/src/codex/resources/projects/projects.py b/src/codex/resources/projects/projects.py index 22b5caf..fc5a43a 100644 --- a/src/codex/resources/projects/projects.py +++ b/src/codex/resources/projects/projects.py @@ -212,10 +212,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 +241,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, ), @@ -820,10 +820,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 +849,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, ), diff --git a/src/codex/types/project_update_params.py b/src/codex/types/project_update_params.py index 73dad67..3e24441 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/tests/api_resources/test_projects.py b/tests/api_resources/test_projects.py index e7d7eb1..0764d9a 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() @@ -919,8 +911,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 +919,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 +1002,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 +1012,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 +1024,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 +1039,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() From c5bb94059d507d64fbdba2d863d9682696100cdf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 26 Jun 2025 21:17:43 +0000 Subject: [PATCH 03/18] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 31393e0..3ff2f63 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,3 +1,3 @@ configured_endpoints: 65 -openapi_spec_hash: 5d686da2afda75185dc9e4190a42b75c +openapi_spec_hash: 94969e7925542f0cc845f6e3d299ed3c config_hash: 14b2643a0ec60cf326dfed00939644ff From 1a5e444226c829392181d98bc06f8cfb8bf13bd9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 02:29:21 +0000 Subject: [PATCH 04/18] =?UTF-8?q?fix(ci):=20release-doctor=20=E2=80=94=20r?= =?UTF-8?q?eport=20correct=20token=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/check-release-environment | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/check-release-environment b/bin/check-release-environment index a1446a7..b845b0f 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[@]} From 6b590bd454e939b8453d95c239ee85be1a326909 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 28 Jun 2025 08:28:28 +0000 Subject: [PATCH 05/18] chore(ci): only run for pushes and fork pull requests --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f7778a..12f686e 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 @@ -42,6 +43,7 @@ jobs: contents: read id-token: write runs-on: depot-ubuntu-24.04 + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@v4 From 45d3bc05ab56d3e67d036ce84b2c9a1f2d8cfd69 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 30 Jun 2025 02:25:48 +0000 Subject: [PATCH 06/18] fix(ci): correct conditional --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12f686e..bbb722b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,14 +36,13 @@ jobs: run: ./scripts/lint upload: - if: github.repository == 'stainless-sdks/codex-python' + if: github.repository == 'stainless-sdks/codex-python' && (github.event_name == 'push' || github.event.pull_request.head.repo.fork) timeout-minutes: 10 name: upload permissions: contents: read id-token: write runs-on: depot-ubuntu-24.04 - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@v4 From 31096f4820a7bfdd204b0a2d1d84ab1e36e32d0c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 30 Jun 2025 19:17:38 +0000 Subject: [PATCH 07/18] feat(api): api update --- .stats.yml | 2 +- src/codex/resources/projects/query_logs.py | 88 +++++++++++++++++++ .../query_log_list_by_group_params.py | 12 +++ .../projects/query_log_list_groups_params.py | 12 +++ .../types/projects/query_log_list_params.py | 9 ++ .../api_resources/projects/test_query_logs.py | 22 +++++ 6 files changed, 144 insertions(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 3ff2f63..c509062 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,3 +1,3 @@ configured_endpoints: 65 -openapi_spec_hash: 94969e7925542f0cc845f6e3d299ed3c +openapi_spec_hash: f63d4542b4bd1530ced013eb686cab99 config_hash: 14b2643a0ec60cf326dfed00939644ff diff --git a/src/codex/resources/projects/query_logs.py b/src/codex/resources/projects/query_logs.py index 32ec739..e97243e 100644 --- a/src/codex/resources/projects/query_logs.py +++ b/src/codex/resources/projects/query_logs.py @@ -92,9 +92,12 @@ 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"]] ] @@ -118,6 +121,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 @@ -144,9 +153,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, @@ -164,9 +176,13 @@ 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"]] ] @@ -191,6 +207,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 +243,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,9 +268,13 @@ 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"]] ] @@ -267,6 +299,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 @@ -293,9 +333,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, @@ -406,9 +450,12 @@ async 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"]] ] @@ -432,6 +479,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 @@ -458,9 +511,12 @@ async 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, @@ -478,9 +534,13 @@ 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"]] ] @@ -505,6 +565,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 +601,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, @@ -554,9 +626,13 @@ async 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"]] ] @@ -581,6 +657,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 @@ -607,9 +691,13 @@ async 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, 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 66166a1..b44970a 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,12 +21,24 @@ 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"]] ] 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 558ac0b..94d549f 100644 --- a/src/codex/types/projects/query_log_list_groups_params.py +++ b/src/codex/types/projects/query_log_list_groups_params.py @@ -21,12 +21,24 @@ 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"]] ] diff --git a/src/codex/types/projects/query_log_list_params.py b/src/codex/types/projects/query_log_list_params.py index 9cf3211..0f72b24 100644 --- a/src/codex/types/projects/query_log_list_params.py +++ b/src/codex/types/projects/query_log_list_params.py @@ -21,12 +21,21 @@ 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"]] ] diff --git a/tests/api_resources/projects/test_query_logs.py b/tests/api_resources/projects/test_query_logs.py index d75dcab..68d78ce 100644 --- a/tests/api_resources/projects/test_query_logs.py +++ b/tests/api_resources/projects/test_query_logs.py @@ -92,9 +92,12 @@ 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, @@ -151,9 +154,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", @@ -211,9 +218,13 @@ 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, @@ -380,9 +391,12 @@ 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, @@ -439,9 +453,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", @@ -499,9 +517,13 @@ 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, From 0207b98b34d0a484c6701d04e32ef56190936201 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 23:35:58 +0000 Subject: [PATCH 08/18] feat(api): api update --- .stats.yml | 4 +- api.md | 32 - src/codex/resources/projects/__init__.py | 28 - src/codex/resources/projects/clusters.py | 332 ------ src/codex/resources/projects/entries.py | 948 --------------- src/codex/resources/projects/projects.py | 64 -- src/codex/types/projects/__init__.py | 10 - .../types/projects/cluster_list_params.py | 34 - .../types/projects/cluster_list_response.py | 214 ---- .../cluster_list_variants_response.py | 14 - src/codex/types/projects/entry.py | 210 ---- .../types/projects/entry_create_params.py | 28 - .../types/projects/entry_notify_sme_params.py | 30 - .../projects/entry_notify_sme_response.py | 13 - .../types/projects/entry_query_params.py | 300 ----- .../types/projects/entry_query_response.py | 194 ---- .../types/projects/entry_update_params.py | 18 - .../query_log_list_by_group_response.py | 4 + .../query_log_list_groups_response.py | 2 +- .../projects/query_log_retrieve_response.py | 4 + tests/api_resources/projects/test_clusters.py | 247 ---- tests/api_resources/projects/test_entries.py | 1014 ----------------- 22 files changed, 11 insertions(+), 3733 deletions(-) delete mode 100644 src/codex/resources/projects/clusters.py delete mode 100644 src/codex/resources/projects/entries.py delete mode 100644 src/codex/types/projects/cluster_list_params.py delete mode 100644 src/codex/types/projects/cluster_list_response.py delete mode 100644 src/codex/types/projects/cluster_list_variants_response.py delete mode 100644 src/codex/types/projects/entry.py delete mode 100644 src/codex/types/projects/entry_create_params.py delete mode 100644 src/codex/types/projects/entry_notify_sme_params.py delete mode 100644 src/codex/types/projects/entry_notify_sme_response.py delete mode 100644 src/codex/types/projects/entry_query_params.py delete mode 100644 src/codex/types/projects/entry_query_response.py delete mode 100644 src/codex/types/projects/entry_update_params.py delete mode 100644 tests/api_resources/projects/test_clusters.py delete mode 100644 tests/api_resources/projects/test_entries.py diff --git a/.stats.yml b/.stats.yml index c509062..cc72a8a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,3 +1,3 @@ -configured_endpoints: 65 -openapi_spec_hash: f63d4542b4bd1530ced013eb686cab99 +configured_endpoints: 55 +openapi_spec_hash: b2b026661b19d060e5eac490807fe445 config_hash: 14b2643a0ec60cf326dfed00939644ff diff --git a/api.md b/api.md index 13e8214..ba4dfd6 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: diff --git a/src/codex/resources/projects/__init__.py b/src/codex/resources/projects/__init__.py index 178855a..c1627d2 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 9712464..0000000 --- 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 c6b43a4..0000000 --- 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 fc5a43a..1314b7b 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) @@ -699,14 +675,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) @@ -1345,14 +1313,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 +1367,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 +1421,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 +1475,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/types/projects/__init__.py b/src/codex/types/projects/__init__.py index 8a26aa0..4f75470 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 20284d8..0000000 --- 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 1fc8bd5..0000000 --- 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 aa35905..0000000 --- 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 3f7a86d..0000000 --- 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 f06846b..0000000 --- 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 3d06d1a..0000000 --- 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 b3c5b37..0000000 --- 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 2ba33b8..0000000 --- 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 cd5a4c9..0000000 --- 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 aac256f..0000000 --- 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_response.py b/src/codex/types/projects/query_log_list_by_group_response.py index 9d1e0e6..c294d93 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 @@ -71,12 +71,16 @@ class QueryLogsByGroupQueryLog(BaseModel): 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""" 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 7b77cc0..ce5806b 100644 --- a/src/codex/types/projects/query_log_list_groups_response.py +++ b/src/codex/types/projects/query_log_list_groups_response.py @@ -78,7 +78,7 @@ 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 diff --git a/src/codex/types/projects/query_log_retrieve_response.py b/src/codex/types/projects/query_log_retrieve_response.py index 8bb6128..5214cff 100644 --- a/src/codex/types/projects/query_log_retrieve_response.py +++ b/src/codex/types/projects/query_log_retrieve_response.py @@ -69,12 +69,16 @@ class QueryLogRetrieveResponse(BaseModel): 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""" diff --git a/tests/api_resources/projects/test_clusters.py b/tests/api_resources/projects/test_clusters.py deleted file mode 100644 index 8773427..0000000 --- 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 1b077d1..0000000 --- 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", - ) From 023823bace71bdc65ce1ff432373a26731ec43d4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 2 Jul 2025 05:00:55 +0000 Subject: [PATCH 09/18] chore(ci): change upload type --- .github/workflows/ci.yml | 18 ++++++++++++++++-- scripts/utils/upload-artifact.sh | 12 +++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bbb722b..a6979eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,10 +35,10 @@ jobs: - name: Run lints run: ./scripts/lint - upload: + 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 @@ -46,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/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh index 62d150a..aac0384 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 From ab93d9d3990f52924b92518d6249f30783591a42 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 2 Jul 2025 19:17:27 +0000 Subject: [PATCH 10/18] feat(api): api update --- .stats.yml | 2 +- .../projects/query_log_list_by_group_response.py | 11 +++++++++++ .../types/projects/query_log_list_groups_response.py | 9 +++++++++ src/codex/types/projects/query_log_list_response.py | 9 +++++++++ .../types/projects/query_log_retrieve_response.py | 9 +++++++++ .../remediation_list_resolved_logs_response.py | 9 +++++++++ 6 files changed, 48 insertions(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index cc72a8a..08bc5f7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,3 +1,3 @@ configured_endpoints: 55 -openapi_spec_hash: b2b026661b19d060e5eac490807fe445 +openapi_spec_hash: 06bae836118b9c7ac2cf1b5e1a576296 config_hash: 14b2643a0ec60cf326dfed00939644ff 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 c294d93..eeb4b63 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 @@ -13,6 +13,7 @@ "QueryLogsByGroupQueryLogFormattedEscalationEvalScores", "QueryLogsByGroupQueryLogFormattedEvalScores", "QueryLogsByGroupQueryLogFormattedGuardrailEvalScores", + "QueryLogsByGroupQueryLogFormattedNonGuardrailEvalScores", "QueryLogsByGroupQueryLogContext", ] @@ -35,6 +36,12 @@ class QueryLogsByGroupQueryLogFormattedGuardrailEvalScores(BaseModel): 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.""" @@ -69,6 +76,10 @@ class QueryLogsByGroupQueryLog(BaseModel): 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 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 ce5806b..074dfac 100644 --- a/src/codex/types/projects/query_log_list_groups_response.py +++ b/src/codex/types/projects/query_log_list_groups_response.py @@ -12,6 +12,7 @@ "QueryLogGroupFormattedEscalationEvalScores", "QueryLogGroupFormattedEvalScores", "QueryLogGroupFormattedGuardrailEvalScores", + "QueryLogGroupFormattedNonGuardrailEvalScores", "QueryLogGroupContext", ] @@ -34,6 +35,12 @@ class QueryLogGroupFormattedGuardrailEvalScores(BaseModel): status: Literal["pass", "fail"] +class QueryLogGroupFormattedNonGuardrailEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + class QueryLogGroupContext(BaseModel): content: str """The actual content/text of the document.""" @@ -68,6 +75,8 @@ class QueryLogGroup(BaseModel): formatted_guardrail_eval_scores: Optional[Dict[str, QueryLogGroupFormattedGuardrailEvalScores]] = None + formatted_non_guardrail_eval_scores: Optional[Dict[str, QueryLogGroupFormattedNonGuardrailEvalScores]] = None + is_bad_response: bool needs_review: bool diff --git a/src/codex/types/projects/query_log_list_response.py b/src/codex/types/projects/query_log_list_response.py index fa04904..09a9067 100644 --- a/src/codex/types/projects/query_log_list_response.py +++ b/src/codex/types/projects/query_log_list_response.py @@ -12,6 +12,7 @@ "QueryLogFormattedEscalationEvalScores", "QueryLogFormattedEvalScores", "QueryLogFormattedGuardrailEvalScores", + "QueryLogFormattedNonGuardrailEvalScores", "QueryLogContext", ] @@ -34,6 +35,12 @@ class QueryLogFormattedGuardrailEvalScores(BaseModel): status: Literal["pass", "fail"] +class QueryLogFormattedNonGuardrailEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + class QueryLogContext(BaseModel): content: str """The actual content/text of the document.""" @@ -68,6 +75,8 @@ class QueryLog(BaseModel): 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 diff --git a/src/codex/types/projects/query_log_retrieve_response.py b/src/codex/types/projects/query_log_retrieve_response.py index 5214cff..3b2277d 100644 --- a/src/codex/types/projects/query_log_retrieve_response.py +++ b/src/codex/types/projects/query_log_retrieve_response.py @@ -11,6 +11,7 @@ "FormattedEscalationEvalScores", "FormattedEvalScores", "FormattedGuardrailEvalScores", + "FormattedNonGuardrailEvalScores", "Context", ] @@ -33,6 +34,12 @@ class FormattedGuardrailEvalScores(BaseModel): 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.""" @@ -67,6 +74,8 @@ class QueryLogRetrieveResponse(BaseModel): 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 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 b2315aa..7e40fb4 100644 --- a/src/codex/types/projects/remediation_list_resolved_logs_response.py +++ b/src/codex/types/projects/remediation_list_resolved_logs_response.py @@ -12,6 +12,7 @@ "QueryLogFormattedEscalationEvalScores", "QueryLogFormattedEvalScores", "QueryLogFormattedGuardrailEvalScores", + "QueryLogFormattedNonGuardrailEvalScores", "QueryLogContext", ] @@ -34,6 +35,12 @@ class QueryLogFormattedGuardrailEvalScores(BaseModel): status: Literal["pass", "fail"] +class QueryLogFormattedNonGuardrailEvalScores(BaseModel): + score: float + + status: Literal["pass", "fail"] + + class QueryLogContext(BaseModel): content: str """The actual content/text of the document.""" @@ -68,6 +75,8 @@ class QueryLog(BaseModel): 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 From 75b1e81e199ff4721ff21b3920bc82a48006df21 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 17:17:40 +0000 Subject: [PATCH 11/18] feat(api): api update --- .stats.yml | 2 +- requirements-dev.lock | 2 +- requirements.lock | 2 +- src/codex/resources/projects/query_logs.py | 12 ++++++------ src/codex/types/project_validate_response.py | 15 +++++++++++++-- .../projects/query_log_list_by_group_params.py | 2 +- .../projects/query_log_list_by_group_response.py | 12 ++++++++++++ .../projects/query_log_list_groups_params.py | 2 +- .../projects/query_log_list_groups_response.py | 12 ++++++++++++ src/codex/types/projects/query_log_list_params.py | 2 +- .../types/projects/query_log_list_response.py | 12 ++++++++++++ .../types/projects/query_log_retrieve_response.py | 12 ++++++++++++ .../remediation_list_resolved_logs_response.py | 12 ++++++++++++ 13 files changed, 85 insertions(+), 14 deletions(-) diff --git a/.stats.yml b/.stats.yml index 08bc5f7..371ed3d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,3 +1,3 @@ configured_endpoints: 55 -openapi_spec_hash: 06bae836118b9c7ac2cf1b5e1a576296 +openapi_spec_hash: f17890d85522687a4c68702da9ad2efb config_hash: 14b2643a0ec60cf326dfed00939644ff diff --git a/requirements-dev.lock b/requirements-dev.lock index 11a2703..a84b5f4 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 5eda9d9..a0807d8 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/src/codex/resources/projects/query_logs.py b/src/codex/resources/projects/query_logs.py index e97243e..148df9f 100644 --- a/src/codex/resources/projects/query_logs.py +++ b/src/codex/resources/projects/query_logs.py @@ -99,7 +99,7 @@ def list( 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, @@ -184,7 +184,7 @@ def list_by_group( 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, @@ -276,7 +276,7 @@ def list_groups( 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"]] @@ -457,7 +457,7 @@ async def list( 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, @@ -542,7 +542,7 @@ async def list_by_group( 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, @@ -634,7 +634,7 @@ async def list_groups( 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"]] diff --git a/src/codex/types/project_validate_response.py b/src/codex/types/project_validate_response.py index db65f67..3b06db2 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/query_log_list_by_group_params.py b/src/codex/types/projects/query_log_list_by_group_params.py index b44970a..90bd386 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 @@ -40,7 +40,7 @@ class QueryLogListByGroupParams(TypedDict, total=False): """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 eeb4b63..1685073 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 @@ -15,6 +15,7 @@ "QueryLogsByGroupQueryLogFormattedGuardrailEvalScores", "QueryLogsByGroupQueryLogFormattedNonGuardrailEvalScores", "QueryLogsByGroupQueryLogContext", + "QueryLogsByGroupQueryLogDeterministicGuardrailsResults", ] @@ -59,6 +60,14 @@ 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 @@ -104,6 +113,9 @@ 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""" 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 94d549f..cd82d9a 100644 --- a/src/codex/types/projects/query_log_list_groups_params.py +++ b/src/codex/types/projects/query_log_list_groups_params.py @@ -40,7 +40,7 @@ class QueryLogListGroupsParams(TypedDict, total=False): """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 074dfac..e77dd87 100644 --- a/src/codex/types/projects/query_log_list_groups_response.py +++ b/src/codex/types/projects/query_log_list_groups_response.py @@ -14,6 +14,7 @@ "QueryLogGroupFormattedGuardrailEvalScores", "QueryLogGroupFormattedNonGuardrailEvalScores", "QueryLogGroupContext", + "QueryLogGroupDeterministicGuardrailsResults", ] @@ -58,6 +59,14 @@ class QueryLogGroupContext(BaseModel): """Title or heading of the document. Useful for display and context.""" +class QueryLogGroupDeterministicGuardrailsResults(BaseModel): + guardrail_name: str + + should_guardrail: bool + + matches: Optional[List[str]] = None + + class QueryLogGroup(BaseModel): id: str @@ -103,6 +112,9 @@ class QueryLogGroup(BaseModel): custom_metadata_keys: Optional[List[str]] = None """Keys of the custom metadata""" + deterministic_guardrails_results: Optional[Dict[str, QueryLogGroupDeterministicGuardrailsResults]] = 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""" diff --git a/src/codex/types/projects/query_log_list_params.py b/src/codex/types/projects/query_log_list_params.py index 0f72b24..5892d3c 100644 --- a/src/codex/types/projects/query_log_list_params.py +++ b/src/codex/types/projects/query_log_list_params.py @@ -37,7 +37,7 @@ class QueryLogListParams(TypedDict, total=False): """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 09a9067..147478c 100644 --- a/src/codex/types/projects/query_log_list_response.py +++ b/src/codex/types/projects/query_log_list_response.py @@ -14,6 +14,7 @@ "QueryLogFormattedGuardrailEvalScores", "QueryLogFormattedNonGuardrailEvalScores", "QueryLogContext", + "QueryLogDeterministicGuardrailsResults", ] @@ -58,6 +59,14 @@ 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 @@ -97,6 +106,9 @@ 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""" diff --git a/src/codex/types/projects/query_log_retrieve_response.py b/src/codex/types/projects/query_log_retrieve_response.py index 3b2277d..380bacb 100644 --- a/src/codex/types/projects/query_log_retrieve_response.py +++ b/src/codex/types/projects/query_log_retrieve_response.py @@ -13,6 +13,7 @@ "FormattedGuardrailEvalScores", "FormattedNonGuardrailEvalScores", "Context", + "DeterministicGuardrailsResults", ] @@ -57,6 +58,14 @@ 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 @@ -100,6 +109,9 @@ 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""" 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 7e40fb4..876e7ce 100644 --- a/src/codex/types/projects/remediation_list_resolved_logs_response.py +++ b/src/codex/types/projects/remediation_list_resolved_logs_response.py @@ -14,6 +14,7 @@ "QueryLogFormattedGuardrailEvalScores", "QueryLogFormattedNonGuardrailEvalScores", "QueryLogContext", + "QueryLogDeterministicGuardrailsResults", ] @@ -58,6 +59,14 @@ 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 @@ -97,6 +106,9 @@ 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""" From bc15e9004a8f3a2b311ceeb851b5f6a666a2698b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 23:36:29 +0000 Subject: [PATCH 12/18] feat(api): api update --- .stats.yml | 2 +- src/codex/resources/projects/projects.py | 42 ++-- src/codex/types/project_validate_params.py | 279 ++++++++++++++++++++- tests/api_resources/test_projects.py | 34 ++- 4 files changed, 315 insertions(+), 42 deletions(-) diff --git a/.stats.yml b/.stats.yml index 371ed3d..c8908e8 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,3 +1,3 @@ configured_endpoints: 55 -openapi_spec_hash: f17890d85522687a4c68702da9ad2efb +openapi_spec_hash: 922886934580d0b2addcb6e26ada0e09 config_hash: 14b2643a0ec60cf326dfed00939644ff diff --git a/src/codex/resources/projects/projects.py b/src/codex/resources/projects/projects.py index 1314b7b..dc01b11 100644 --- a/src/codex/resources/projects/projects.py +++ b/src/codex/resources/projects/projects.py @@ -488,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, @@ -526,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 @@ -615,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 @@ -643,7 +649,6 @@ def validate( body=maybe_transform( { "context": context, - "prompt": prompt, "query": query, "response": response, "constrain_outputs": constrain_outputs, @@ -652,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, @@ -1090,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, @@ -1128,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 @@ -1217,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 @@ -1245,7 +1258,6 @@ async def validate( body=await async_maybe_transform( { "context": context, - "prompt": prompt, "query": query, "response": response, "constrain_outputs": constrain_outputs, @@ -1254,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, diff --git a/src/codex/types/project_validate_params.py b/src/codex/types/project_validate_params.py index 8b38ebf..0862cbc 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/tests/api_resources/test_projects.py b/tests/api_resources/test_projects.py index 0764d9a..9ecffa0 100644 --- a/tests/api_resources/test_projects.py +++ b/tests/api_resources/test_projects.py @@ -632,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"]) @@ -644,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}, @@ -670,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", @@ -685,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 @@ -701,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" @@ -720,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", ) @@ -1337,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"]) @@ -1349,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}, @@ -1375,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", @@ -1390,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 @@ -1406,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" @@ -1425,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", ) From e80bee98b4f91ca7c0c19509d1f6a4f9f6bfd2c7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 23:38:16 +0000 Subject: [PATCH 13/18] feat(api): remove entries routes --- .stats.yml | 4 +- src/codex/pagination.py | 62 ----- src/codex/resources/projects/projects.py | 42 ++-- src/codex/types/project_validate_params.py | 279 +-------------------- tests/api_resources/test_projects.py | 34 +-- 5 files changed, 43 insertions(+), 378 deletions(-) diff --git a/.stats.yml b/.stats.yml index c8908e8..d7fdc0e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,3 +1,3 @@ configured_endpoints: 55 -openapi_spec_hash: 922886934580d0b2addcb6e26ada0e09 -config_hash: 14b2643a0ec60cf326dfed00939644ff +openapi_spec_hash: f17890d85522687a4c68702da9ad2efb +config_hash: e62d723b4a5c564dc05390753a876f31 diff --git a/src/codex/pagination.py b/src/codex/pagination.py index 1f590df..8057f2e 100644 --- a/src/codex/pagination.py +++ b/src/codex/pagination.py @@ -14,8 +14,6 @@ "AsyncMyOffsetPageTopLevelArray", "SyncOffsetPageClusters", "AsyncOffsetPageClusters", - "SyncOffsetPageEntries", - "AsyncOffsetPageEntries", ] _BaseModelT = TypeVar("_BaseModelT", bound=BaseModel) @@ -143,63 +141,3 @@ def next_page_info(self) -> Optional[PageInfo]: return PageInfo(params={"offset": current_count}) return None - - -class SyncOffsetPageEntries(BaseSyncPage[_T], BasePage[_T], Generic[_T]): - entries: List[_T] - total_count: Optional[int] = None - - @override - def _get_page_items(self) -> List[_T]: - entries = self.entries - if not entries: - return [] - return entries - - @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 AsyncOffsetPageEntries(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): - entries: List[_T] - total_count: Optional[int] = None - - @override - def _get_page_items(self) -> List[_T]: - entries = self.entries - if not entries: - return [] - return entries - - @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 diff --git a/src/codex/resources/projects/projects.py b/src/codex/resources/projects/projects.py index dc01b11..1314b7b 100644 --- a/src/codex/resources/projects/projects.py +++ b/src/codex/resources/projects/projects.py @@ -488,18 +488,17 @@ def validate( project_id: str, *, context: str, + prompt: str, query: str, - response: project_validate_params.Response, + response: str, 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: Iterable[project_validate_params.Message] | NotGiven = NOT_GIVEN, + messages: Optional[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, @@ -527,8 +526,9 @@ def validate( eval_scores: Scores assessing different aspects of the RAG system. If not provided, TLM will be used to generate scores. - messages: Message history to provide conversation context for the query. Messages contain - up to and including the latest user prompt to the LLM. + 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. options: Typed dict of advanced configuration options for the Trustworthy Language Model. Many of these configurations are determined by the quality preset selected @@ -615,14 +615,8 @@ 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 @@ -649,6 +643,7 @@ def validate( body=maybe_transform( { "context": context, + "prompt": prompt, "query": query, "response": response, "constrain_outputs": constrain_outputs, @@ -657,9 +652,7 @@ 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, @@ -1097,18 +1090,17 @@ async def validate( project_id: str, *, context: str, + prompt: str, query: str, - response: project_validate_params.Response, + response: str, 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: Iterable[project_validate_params.Message] | NotGiven = NOT_GIVEN, + messages: Optional[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, @@ -1136,8 +1128,9 @@ async def validate( eval_scores: Scores assessing different aspects of the RAG system. If not provided, TLM will be used to generate scores. - messages: Message history to provide conversation context for the query. Messages contain - up to and including the latest user prompt to the LLM. + 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. options: Typed dict of advanced configuration options for the Trustworthy Language Model. Many of these configurations are determined by the quality preset selected @@ -1224,14 +1217,8 @@ 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 @@ -1258,6 +1245,7 @@ async def validate( body=await async_maybe_transform( { "context": context, + "prompt": prompt, "query": query, "response": response, "constrain_outputs": constrain_outputs, @@ -1266,9 +1254,7 @@ 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, diff --git a/src/codex/types/project_validate_params.py b/src/codex/types/project_validate_params.py index 0862cbc..8b38ebf 100644 --- a/src/codex/types/project_validate_params.py +++ b/src/codex/types/project_validate_params.py @@ -2,7 +2,6 @@ from __future__ import annotations -import builtins from typing import Dict, List, Union, Iterable, Optional from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict @@ -10,24 +9,6 @@ __all__ = [ "ProjectValidateParams", - "Response", - "ResponseChatCompletion", - "ResponseChatCompletionChoice", - "ResponseChatCompletionChoiceMessage", - "ResponseChatCompletionChoiceMessageAnnotation", - "ResponseChatCompletionChoiceMessageAnnotationURLCitation", - "ResponseChatCompletionChoiceMessageAudio", - "ResponseChatCompletionChoiceMessageFunctionCall", - "ResponseChatCompletionChoiceMessageToolCall", - "ResponseChatCompletionChoiceMessageToolCallFunction", - "ResponseChatCompletionChoiceLogprobs", - "ResponseChatCompletionChoiceLogprobsContent", - "ResponseChatCompletionChoiceLogprobsContentTopLogprob", - "ResponseChatCompletionChoiceLogprobsRefusal", - "ResponseChatCompletionChoiceLogprobsRefusalTopLogprob", - "ResponseChatCompletionUsage", - "ResponseChatCompletionUsageCompletionTokensDetails", - "ResponseChatCompletionUsagePromptTokensDetails", "Message", "MessageChatCompletionDeveloperMessageParam", "MessageChatCompletionDeveloperMessageParamContentUnionMember1", @@ -60,9 +41,11 @@ class ProjectValidateParams(TypedDict, total=False): context: Required[str] + prompt: Required[str] + query: Required[str] - response: Required[Response] + response: Required[str] use_llm_matching: bool @@ -83,10 +66,11 @@ class ProjectValidateParams(TypedDict, total=False): If not provided, TLM will be used to generate scores. """ - messages: Iterable[Message] - """Message history to provide conversation context for the query. + messages: Optional[Iterable[Message]] + """Optional message history to provide conversation context for the query. - Messages contain up to and including the latest user prompt to the LLM. + Used to rewrite query into a self-contained version of itself. If not provided, + the query will be treated as self-contained. """ options: Optional[Options] @@ -177,21 +161,9 @@ 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")] @@ -203,243 +175,6 @@ 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/tests/api_resources/test_projects.py b/tests/api_resources/test_projects.py index 9ecffa0..0764d9a 100644 --- a/tests/api_resources/test_projects.py +++ b/tests/api_resources/test_projects.py @@ -632,8 +632,9 @@ 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="string", + response="response", ) assert_matches_type(ProjectValidateResponse, project, path=["response"]) @@ -643,8 +644,9 @@ 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="string", + response="response", use_llm_matching=True, constrain_outputs=["string"], custom_eval_thresholds={"foo": 0}, @@ -668,9 +670,7 @@ 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", @@ -685,8 +685,9 @@ 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="string", + response="response", ) assert response.is_closed is True @@ -700,8 +701,9 @@ 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="string", + response="response", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -718,8 +720,9 @@ def test_path_params_validate(self, client: Codex) -> None: client.projects.with_raw_response.validate( project_id="", context="context", + prompt="prompt", query="query", - response="string", + response="response", ) @@ -1334,8 +1337,9 @@ 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="string", + response="response", ) assert_matches_type(ProjectValidateResponse, project, path=["response"]) @@ -1345,8 +1349,9 @@ 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="string", + response="response", use_llm_matching=True, constrain_outputs=["string"], custom_eval_thresholds={"foo": 0}, @@ -1370,9 +1375,7 @@ 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", @@ -1387,8 +1390,9 @@ 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="string", + response="response", ) assert response.is_closed is True @@ -1402,8 +1406,9 @@ 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="string", + response="response", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -1420,6 +1425,7 @@ 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="string", + response="response", ) From c24afc38a28c6bce4d28e7313922d750e7854770 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 23:39:41 +0000 Subject: [PATCH 14/18] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index d7fdc0e..429b3f8 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,3 +1,3 @@ configured_endpoints: 55 openapi_spec_hash: f17890d85522687a4c68702da9ad2efb -config_hash: e62d723b4a5c564dc05390753a876f31 +config_hash: f44faee9ff5bdf66e9e38fc69f6e4daa From d36c2c7ca7a9155dab71b1c82f2e163488d32086 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 23:45:06 +0000 Subject: [PATCH 15/18] feat(api): define pagination schemes --- .stats.yml | 2 +- api.md | 4 +- src/codex/pagination.py | 124 ++++++++++++++++++ src/codex/resources/projects/query_logs.py | 21 +-- src/codex/resources/projects/remediations.py | 21 +-- .../types/projects/query_log_list_response.py | 47 +++---- .../projects/remediation_list_response.py | 12 +- .../api_resources/projects/test_query_logs.py | 17 +-- .../projects/test_remediations.py | 17 +-- 9 files changed, 191 insertions(+), 74 deletions(-) diff --git a/.stats.yml b/.stats.yml index 429b3f8..ac24d56 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,3 +1,3 @@ configured_endpoints: 55 openapi_spec_hash: f17890d85522687a4c68702da9ad2efb -config_hash: f44faee9ff5bdf66e9e38fc69f6e4daa +config_hash: 86582a50eb22b2866777cbd4d94f4e8d diff --git a/api.md b/api.md index ba4dfd6..edc03cd 100644 --- a/api.md +++ b/api.md @@ -212,7 +212,7 @@ 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.start_remediation(query_log_id, \*, project_id) -> QueryLogStartRemediationResponse @@ -240,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/src/codex/pagination.py b/src/codex/pagination.py index 8057f2e..89ed0cf 100644 --- a/src/codex/pagination.py +++ b/src/codex/pagination.py @@ -14,6 +14,10 @@ "AsyncMyOffsetPageTopLevelArray", "SyncOffsetPageClusters", "AsyncOffsetPageClusters", + "SyncOffsetPageQueryLogs", + "AsyncOffsetPageQueryLogs", + "SyncOffsetPageRemediations", + "AsyncOffsetPageRemediations", ] _BaseModelT = TypeVar("_BaseModelT", bound=BaseModel) @@ -141,3 +145,123 @@ def next_page_info(self) -> Optional[PageInfo]: return PageInfo(params={"offset": current_count}) return None + + +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]: + query_logs = self.query_logs + if not query_logs: + return [] + 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 AsyncOffsetPageQueryLogs(BaseAsyncPage[_T], BasePage[_T], Generic[_T]): + query_logs: List[_T] + total_count: Optional[int] = None + + @override + def _get_page_items(self) -> List[_T]: + query_logs = self.query_logs + if not query_logs: + return [] + 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 diff --git a/src/codex/resources/projects/query_logs.py b/src/codex/resources/projects/query_logs.py index 148df9f..24535d4 100644 --- a/src/codex/resources/projects/query_logs.py +++ b/src/codex/resources/projects/query_logs.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 SyncOffsetPageQueryLogs, AsyncOffsetPageQueryLogs +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 @@ -110,7 +111,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. @@ -141,8 +142,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, @@ -166,7 +168,7 @@ def list( query_log_list_params.QueryLogListParams, ), ), - cast_to=QueryLogListResponse, + model=QueryLogListResponse, ) def list_by_group( @@ -443,7 +445,7 @@ async def retrieve( cast_to=QueryLogRetrieveResponse, ) - async def list( + def list( self, project_id: str, *, @@ -468,7 +470,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. @@ -499,14 +501,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}/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, @@ -524,7 +527,7 @@ async def list( query_log_list_params.QueryLogListParams, ), ), - cast_to=QueryLogListResponse, + model=QueryLogListResponse, ) async def list_by_group( diff --git a/src/codex/resources/projects/remediations.py b/src/codex/resources/projects/remediations.py index 65015a1..ea0168c 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/projects/query_log_list_response.py b/src/codex/types/projects/query_log_list_response.py index 147478c..ccdeb03 100644 --- a/src/codex/types/projects/query_log_list_response.py +++ b/src/codex/types/projects/query_log_list_response.py @@ -8,41 +8,40 @@ __all__ = [ "QueryLogListResponse", - "QueryLog", - "QueryLogFormattedEscalationEvalScores", - "QueryLogFormattedEvalScores", - "QueryLogFormattedGuardrailEvalScores", - "QueryLogFormattedNonGuardrailEvalScores", - "QueryLogContext", - "QueryLogDeterministicGuardrailsResults", + "FormattedEscalationEvalScores", + "FormattedEvalScores", + "FormattedGuardrailEvalScores", + "FormattedNonGuardrailEvalScores", + "Context", + "DeterministicGuardrailsResults", ] -class QueryLogFormattedEscalationEvalScores(BaseModel): +class FormattedEscalationEvalScores(BaseModel): score: float status: Literal["pass", "fail"] -class QueryLogFormattedEvalScores(BaseModel): +class FormattedEvalScores(BaseModel): score: float status: Literal["pass", "fail"] -class QueryLogFormattedGuardrailEvalScores(BaseModel): +class FormattedGuardrailEvalScores(BaseModel): score: float status: Literal["pass", "fail"] -class QueryLogFormattedNonGuardrailEvalScores(BaseModel): +class FormattedNonGuardrailEvalScores(BaseModel): score: float status: Literal["pass", "fail"] -class QueryLogContext(BaseModel): +class Context(BaseModel): content: str """The actual content/text of the document.""" @@ -59,7 +58,7 @@ class QueryLogContext(BaseModel): """Title or heading of the document. Useful for display and context.""" -class QueryLogDeterministicGuardrailsResults(BaseModel): +class DeterministicGuardrailsResults(BaseModel): guardrail_name: str should_guardrail: bool @@ -67,14 +66,14 @@ class QueryLogDeterministicGuardrailsResults(BaseModel): matches: Optional[List[str]] = None -class QueryLog(BaseModel): +class QueryLogListResponse(BaseModel): id: str created_at: datetime - formatted_escalation_eval_scores: Optional[Dict[str, QueryLogFormattedEscalationEvalScores]] = None + formatted_escalation_eval_scores: Optional[Dict[str, FormattedEscalationEvalScores]] = None - formatted_eval_scores: Optional[Dict[str, QueryLogFormattedEvalScores]] = 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: { @@ -82,9 +81,9 @@ class QueryLog(BaseModel): eval_scores is None. """ - formatted_guardrail_eval_scores: Optional[Dict[str, QueryLogFormattedGuardrailEvalScores]] = None + formatted_guardrail_eval_scores: Optional[Dict[str, FormattedGuardrailEvalScores]] = None - formatted_non_guardrail_eval_scores: Optional[Dict[str, QueryLogFormattedNonGuardrailEvalScores]] = None + formatted_non_guardrail_eval_scores: Optional[Dict[str, FormattedNonGuardrailEvalScores]] = None is_bad_response: bool @@ -97,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 @@ -106,7 +105,7 @@ class QueryLog(BaseModel): custom_metadata_keys: Optional[List[str]] = None """Keys of the custom metadata""" - deterministic_guardrails_results: Optional[Dict[str, QueryLogDeterministicGuardrailsResults]] = None + deterministic_guardrails_results: Optional[Dict[str, DeterministicGuardrailsResults]] = None """Results of deterministic guardrails applied to the query""" escalated: Optional[bool] = None @@ -138,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/remediation_list_response.py b/src/codex/types/projects/remediation_list_response.py index 9d5cda8..8341053 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_query_logs.py b/tests/api_resources/projects/test_query_logs.py index 68d78ce..be867e2 100644 --- a/tests/api_resources/projects/test_query_logs.py +++ b/tests/api_resources/projects/test_query_logs.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 SyncOffsetPageQueryLogs, AsyncOffsetPageQueryLogs from codex.types.projects import ( QueryLogListResponse, QueryLogRetrieveResponse, @@ -82,7 +83,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 @@ -102,7 +103,7 @@ def test_method_list_with_all_params(self, client: Codex) -> None: 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 @@ -114,7 +115,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 @@ -126,7 +127,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 @@ -381,7 +382,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 @@ -401,7 +402,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncCodex) -> No 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 @@ -413,7 +414,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 @@ -425,7 +426,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 diff --git a/tests/api_resources/projects/test_remediations.py b/tests/api_resources/projects/test_remediations.py index c75a255..947850f 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 From d4d82fe33422f460c83778dc0ca767361dce86a5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 23:43:46 +0000 Subject: [PATCH 16/18] feat(api): more pagination schemes --- .stats.yml | 2 +- api.md | 2 +- src/codex/pagination.py | 124 ++++++++++++++++++ src/codex/resources/projects/query_logs.py | 25 ++-- .../query_log_list_groups_response.py | 47 +++---- .../api_resources/projects/test_query_logs.py | 23 ++-- 6 files changed, 175 insertions(+), 48 deletions(-) diff --git a/.stats.yml b/.stats.yml index ac24d56..01dc7b2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,3 +1,3 @@ configured_endpoints: 55 openapi_spec_hash: f17890d85522687a4c68702da9ad2efb -config_hash: 86582a50eb22b2866777cbd4d94f4e8d +config_hash: 8f6e5c3b064cbb77569a6bf654954a56 diff --git a/api.md b/api.md index edc03cd..0c02791 100644 --- a/api.md +++ b/api.md @@ -214,7 +214,7 @@ Methods: - client.projects.query_logs.retrieve(query_log_id, \*, project_id) -> QueryLogRetrieveResponse - 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 diff --git a/src/codex/pagination.py b/src/codex/pagination.py index 89ed0cf..36af0f6 100644 --- a/src/codex/pagination.py +++ b/src/codex/pagination.py @@ -18,6 +18,10 @@ "AsyncOffsetPageQueryLogs", "SyncOffsetPageRemediations", "AsyncOffsetPageRemediations", + "SyncOffsetPageQueryLogGroups", + "AsyncOffsetPageQueryLogGroups", + "SyncOffsetPageQueryLogsByGroup", + "AsyncOffsetPageQueryLogsByGroup", ] _BaseModelT = TypeVar("_BaseModelT", bound=BaseModel) @@ -265,3 +269,123 @@ def next_page_info(self) -> Optional[PageInfo]: 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]: + 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 diff --git a/src/codex/resources/projects/query_logs.py b/src/codex/resources/projects/query_logs.py index 24535d4..9ccecbe 100644 --- a/src/codex/resources/projects/query_logs.py +++ b/src/codex/resources/projects/query_logs.py @@ -18,7 +18,12 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from ...pagination import SyncOffsetPageQueryLogs, AsyncOffsetPageQueryLogs +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 @@ -290,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. @@ -323,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, @@ -349,7 +355,7 @@ def list_groups( query_log_list_groups_params.QueryLogListGroupsParams, ), ), - cast_to=QueryLogListGroupsResponse, + model=QueryLogListGroupsResponse, ) def start_remediation( @@ -622,7 +628,7 @@ async def list_by_group( cast_to=QueryLogListByGroupResponse, ) - async def list_groups( + def list_groups( self, project_id: str, *, @@ -649,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. @@ -682,14 +688,15 @@ 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, @@ -708,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/types/projects/query_log_list_groups_response.py b/src/codex/types/projects/query_log_list_groups_response.py index e77dd87..5d9222b 100644 --- a/src/codex/types/projects/query_log_list_groups_response.py +++ b/src/codex/types/projects/query_log_list_groups_response.py @@ -8,41 +8,40 @@ __all__ = [ "QueryLogListGroupsResponse", - "QueryLogGroup", - "QueryLogGroupFormattedEscalationEvalScores", - "QueryLogGroupFormattedEvalScores", - "QueryLogGroupFormattedGuardrailEvalScores", - "QueryLogGroupFormattedNonGuardrailEvalScores", - "QueryLogGroupContext", - "QueryLogGroupDeterministicGuardrailsResults", + "FormattedEscalationEvalScores", + "FormattedEvalScores", + "FormattedGuardrailEvalScores", + "FormattedNonGuardrailEvalScores", + "Context", + "DeterministicGuardrailsResults", ] -class QueryLogGroupFormattedEscalationEvalScores(BaseModel): +class FormattedEscalationEvalScores(BaseModel): score: float status: Literal["pass", "fail"] -class QueryLogGroupFormattedEvalScores(BaseModel): +class FormattedEvalScores(BaseModel): score: float status: Literal["pass", "fail"] -class QueryLogGroupFormattedGuardrailEvalScores(BaseModel): +class FormattedGuardrailEvalScores(BaseModel): score: float status: Literal["pass", "fail"] -class QueryLogGroupFormattedNonGuardrailEvalScores(BaseModel): +class FormattedNonGuardrailEvalScores(BaseModel): score: float status: Literal["pass", "fail"] -class QueryLogGroupContext(BaseModel): +class Context(BaseModel): content: str """The actual content/text of the document.""" @@ -59,7 +58,7 @@ class QueryLogGroupContext(BaseModel): """Title or heading of the document. Useful for display and context.""" -class QueryLogGroupDeterministicGuardrailsResults(BaseModel): +class DeterministicGuardrailsResults(BaseModel): guardrail_name: str should_guardrail: bool @@ -67,14 +66,14 @@ class QueryLogGroupDeterministicGuardrailsResults(BaseModel): matches: Optional[List[str]] = None -class QueryLogGroup(BaseModel): +class QueryLogListGroupsResponse(BaseModel): id: str created_at: datetime - formatted_escalation_eval_scores: Optional[Dict[str, QueryLogGroupFormattedEscalationEvalScores]] = None + formatted_escalation_eval_scores: Optional[Dict[str, FormattedEscalationEvalScores]] = None - formatted_eval_scores: Optional[Dict[str, QueryLogGroupFormattedEvalScores]] = 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: { @@ -82,9 +81,9 @@ class QueryLogGroup(BaseModel): eval_scores is None. """ - formatted_guardrail_eval_scores: Optional[Dict[str, QueryLogGroupFormattedGuardrailEvalScores]] = None + formatted_guardrail_eval_scores: Optional[Dict[str, FormattedGuardrailEvalScores]] = None - formatted_non_guardrail_eval_scores: Optional[Dict[str, QueryLogGroupFormattedNonGuardrailEvalScores]] = None + formatted_non_guardrail_eval_scores: Optional[Dict[str, FormattedNonGuardrailEvalScores]] = None is_bad_response: bool @@ -103,7 +102,7 @@ class QueryLogGroup(BaseModel): 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 @@ -112,7 +111,7 @@ class QueryLogGroup(BaseModel): custom_metadata_keys: Optional[List[str]] = None """Keys of the custom metadata""" - deterministic_guardrails_results: Optional[Dict[str, QueryLogGroupDeterministicGuardrailsResults]] = None + deterministic_guardrails_results: Optional[Dict[str, DeterministicGuardrailsResults]] = None """Results of deterministic guardrails applied to the query""" escalated: Optional[bool] = None @@ -144,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/tests/api_resources/projects/test_query_logs.py b/tests/api_resources/projects/test_query_logs.py index be867e2..cd4cd7d 100644 --- a/tests/api_resources/projects/test_query_logs.py +++ b/tests/api_resources/projects/test_query_logs.py @@ -10,7 +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 +from codex.pagination import ( + SyncOffsetPageQueryLogs, + AsyncOffsetPageQueryLogs, + SyncOffsetPageQueryLogGroups, + AsyncOffsetPageQueryLogGroups, +) from codex.types.projects import ( QueryLogListResponse, QueryLogRetrieveResponse, @@ -209,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 @@ -230,7 +235,7 @@ def test_method_list_groups_with_all_params(self, client: Codex) -> None: 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 @@ -242,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 @@ -254,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 @@ -508,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 @@ -529,7 +534,7 @@ async def test_method_list_groups_with_all_params(self, async_client: AsyncCodex 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 @@ -541,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 @@ -553,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 From 29f65d74a04a8424cc666669167c8ba56a56485b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 23:47:39 +0000 Subject: [PATCH 17/18] feat(api): api update --- .stats.yml | 2 +- src/codex/resources/projects/projects.py | 42 ++-- src/codex/types/project_validate_params.py | 279 ++++++++++++++++++++- tests/api_resources/test_projects.py | 34 ++- 4 files changed, 315 insertions(+), 42 deletions(-) diff --git a/.stats.yml b/.stats.yml index 01dc7b2..889336e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,3 +1,3 @@ configured_endpoints: 55 -openapi_spec_hash: f17890d85522687a4c68702da9ad2efb +openapi_spec_hash: 922886934580d0b2addcb6e26ada0e09 config_hash: 8f6e5c3b064cbb77569a6bf654954a56 diff --git a/src/codex/resources/projects/projects.py b/src/codex/resources/projects/projects.py index 1314b7b..dc01b11 100644 --- a/src/codex/resources/projects/projects.py +++ b/src/codex/resources/projects/projects.py @@ -488,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, @@ -526,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 @@ -615,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 @@ -643,7 +649,6 @@ def validate( body=maybe_transform( { "context": context, - "prompt": prompt, "query": query, "response": response, "constrain_outputs": constrain_outputs, @@ -652,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, @@ -1090,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, @@ -1128,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 @@ -1217,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 @@ -1245,7 +1258,6 @@ async def validate( body=await async_maybe_transform( { "context": context, - "prompt": prompt, "query": query, "response": response, "constrain_outputs": constrain_outputs, @@ -1254,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, diff --git a/src/codex/types/project_validate_params.py b/src/codex/types/project_validate_params.py index 8b38ebf..0862cbc 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/tests/api_resources/test_projects.py b/tests/api_resources/test_projects.py index 0764d9a..9ecffa0 100644 --- a/tests/api_resources/test_projects.py +++ b/tests/api_resources/test_projects.py @@ -632,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"]) @@ -644,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}, @@ -670,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", @@ -685,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 @@ -701,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" @@ -720,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", ) @@ -1337,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"]) @@ -1349,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}, @@ -1375,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", @@ -1390,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 @@ -1406,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" @@ -1425,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", ) From 257a8f68216001ac2b1d16165dfda532ac54e57e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 23:47:55 +0000 Subject: [PATCH 18/18] release: 0.1.0-alpha.23 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ pyproject.toml | 2 +- src/codex/_version.py | 2 +- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index aa84875..1c0bb88 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/CHANGELOG.md b/CHANGELOG.md index 2b2988f..131d328 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/pyproject.toml b/pyproject.toml index b71f9f0..16e362c 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/src/codex/_version.py b/src/codex/_version.py index a88a1c3..18f2dcb 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