From 0656577b9b2145a53bc4e3116aba6ffb1e1d11b0 Mon Sep 17 00:00:00 2001 From: "onepin-pipeline-bot[bot]" <290953255+onepin-pipeline-bot[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 04:00:36 +0000 Subject: [PATCH] feat: sync SDK to OnePin API v0.41.82 --- .spec-sha | 2 +- src/onepin/.fern/metadata.json | 2 +- src/onepin/__init__.py | 9 + src/onepin/core/client_wrapper.py | 2 +- src/onepin/dictionary/client.py | 12 +- src/onepin/dictionary/raw_client.py | 12 +- src/onepin/dictionary/types/__init__.py | 24 +-- ...api_v1_dictionary_get_request_language.py} | 0 ...es_api_v1_dictionary_get_request_order.py} | 0 ...ies_api_v1_dictionary_get_request_sort.py} | 0 ...onary_search_get_request_language_item.py} | 0 ...v1_dictionary_search_get_request_order.py} | 0 ..._v1_dictionary_search_get_request_sort.py} | 0 src/onepin/reference.md | 111 ++++++++++- src/onepin/types/__init__.py | 9 + .../api_response_workflow_run_outputs_out.py | 22 +++ src/onepin/types/workflow_run_outputs_out.py | 22 +++ .../types/workflow_run_sink_output_out.py | 25 +++ src/onepin/usage/client.py | 10 +- src/onepin/usage/raw_client.py | 10 +- src/onepin/usage/types/__init__.py | 20 +- ...pi_v1_usage_activity_get_request_range.py} | 0 ..._by_language_get_request_activity_view.py} | 0 ...v1_usage_by_language_get_request_range.py} | 0 ...sage_summary_get_request_activity_view.py} | 0 ...api_v1_usage_summary_get_request_range.py} | 0 src/onepin/users/client.py | 2 +- src/onepin/users/raw_client.py | 2 +- src/onepin/users/types/__init__.py | 4 +- ...v1_users_me_templates_get_request_sort.py} | 0 src/onepin/voices/client.py | 2 +- src/onepin/voices/raw_client.py | 2 +- src/onepin/voices/types/__init__.py | 4 +- ..._voices_facets_get_request_source_item.py} | 0 src/onepin/workflows/client.py | 139 ++++++++++++-- src/onepin/workflows/raw_client.py | 173 ++++++++++++++++-- 36 files changed, 525 insertions(+), 95 deletions(-) rename src/onepin/dictionary/types/{list_dictionary_entries_api_v1dictionary_get_request_language.py => list_dictionary_entries_api_v1_dictionary_get_request_language.py} (100%) rename src/onepin/dictionary/types/{list_dictionary_entries_api_v1dictionary_get_request_order.py => list_dictionary_entries_api_v1_dictionary_get_request_order.py} (100%) rename src/onepin/dictionary/types/{list_dictionary_entries_api_v1dictionary_get_request_sort.py => list_dictionary_entries_api_v1_dictionary_get_request_sort.py} (100%) rename src/onepin/dictionary/types/{search_dictionary_entries_api_v1dictionary_search_get_request_language_item.py => search_dictionary_entries_api_v1_dictionary_search_get_request_language_item.py} (100%) rename src/onepin/dictionary/types/{search_dictionary_entries_api_v1dictionary_search_get_request_order.py => search_dictionary_entries_api_v1_dictionary_search_get_request_order.py} (100%) rename src/onepin/dictionary/types/{search_dictionary_entries_api_v1dictionary_search_get_request_sort.py => search_dictionary_entries_api_v1_dictionary_search_get_request_sort.py} (100%) create mode 100644 src/onepin/types/api_response_workflow_run_outputs_out.py create mode 100644 src/onepin/types/workflow_run_outputs_out.py create mode 100644 src/onepin/types/workflow_run_sink_output_out.py rename src/onepin/usage/types/{usage_activity_api_v1usage_activity_get_request_range.py => usage_activity_api_v1_usage_activity_get_request_range.py} (100%) rename src/onepin/usage/types/{usage_by_language_api_v1usage_by_language_get_request_activity_view.py => usage_by_language_api_v1_usage_by_language_get_request_activity_view.py} (100%) rename src/onepin/usage/types/{usage_by_language_api_v1usage_by_language_get_request_range.py => usage_by_language_api_v1_usage_by_language_get_request_range.py} (100%) rename src/onepin/usage/types/{usage_summary_api_v1usage_summary_get_request_activity_view.py => usage_summary_api_v1_usage_summary_get_request_activity_view.py} (100%) rename src/onepin/usage/types/{usage_summary_api_v1usage_summary_get_request_range.py => usage_summary_api_v1_usage_summary_get_request_range.py} (100%) rename src/onepin/users/types/{list_my_templates_api_v1users_me_templates_get_request_sort.py => list_my_templates_api_v1_users_me_templates_get_request_sort.py} (100%) rename src/onepin/voices/types/{get_voice_facets_api_v1voices_facets_get_request_source_item.py => get_voice_facets_api_v1_voices_facets_get_request_source_item.py} (100%) diff --git a/.spec-sha b/.spec-sha index 46df6d3..eccd7b1 100644 --- a/.spec-sha +++ b/.spec-sha @@ -1 +1 @@ -0b38b5c071f4b97f634faed780611d52969ea716 +cddf1ca71c61a62e9e429206b74a6d064222b4ed diff --git a/src/onepin/.fern/metadata.json b/src/onepin/.fern/metadata.json index 9d73ce4..6e675c6 100644 --- a/src/onepin/.fern/metadata.json +++ b/src/onepin/.fern/metadata.json @@ -30,7 +30,7 @@ } ] }, - "originGitCommit": "41215c0e6ac788a5ef9da91a94fdcaa669837c82", + "originGitCommit": "a3ee57d10e66cc74651c81add046845159caf420", "originGitCommitIsDirty": false, "invokedBy": "ci", "ciProvider": "github" diff --git a/src/onepin/__init__.py b/src/onepin/__init__.py index 34f18e6..939df16 100644 --- a/src/onepin/__init__.py +++ b/src/onepin/__init__.py @@ -53,6 +53,7 @@ ApiResponseWorkflowOut, ApiResponseWorkflowRunDetailOut, ApiResponseWorkflowRunOut, + ApiResponseWorkflowRunOutputsOut, ApiResponseWorkflowRunOverviewOut, ApiResponseWorkflowRunStatusOut, ApiResponseWorkspaceInviteOut, @@ -170,6 +171,7 @@ WorkflowRunDetailOut, WorkflowRunListItem, WorkflowRunOut, + WorkflowRunOutputsOut, WorkflowRunOverviewAudioLanguageOut, WorkflowRunOverviewCapabilitiesOut, WorkflowRunOverviewFutureLinksOut, @@ -185,6 +187,7 @@ WorkflowRunOverviewValidatorOut, WorkflowRunOverviewValidatorOutStatus, WorkflowRunOverviewWorkflowOut, + WorkflowRunSinkOutputOut, WorkflowRunStartIn, WorkflowRunStatusOut, WorkflowRunStepOut, @@ -290,6 +293,7 @@ "ApiResponseWorkflowOut": ".types", "ApiResponseWorkflowRunDetailOut": ".types", "ApiResponseWorkflowRunOut": ".types", + "ApiResponseWorkflowRunOutputsOut": ".types", "ApiResponseWorkflowRunOverviewOut": ".types", "ApiResponseWorkflowRunStatusOut": ".types", "ApiResponseWorkspaceInviteOut": ".types", @@ -443,6 +447,7 @@ "WorkflowRunDetailOut": ".types", "WorkflowRunListItem": ".types", "WorkflowRunOut": ".types", + "WorkflowRunOutputsOut": ".types", "WorkflowRunOverviewAudioLanguageOut": ".types", "WorkflowRunOverviewCapabilitiesOut": ".types", "WorkflowRunOverviewFutureLinksOut": ".types", @@ -458,6 +463,7 @@ "WorkflowRunOverviewValidatorOut": ".types", "WorkflowRunOverviewValidatorOutStatus": ".types", "WorkflowRunOverviewWorkflowOut": ".types", + "WorkflowRunSinkOutputOut": ".types", "WorkflowRunStartIn": ".types", "WorkflowRunStatusOut": ".types", "WorkflowRunStepOut": ".types", @@ -553,6 +559,7 @@ def __dir__(): "ApiResponseWorkflowOut", "ApiResponseWorkflowRunDetailOut", "ApiResponseWorkflowRunOut", + "ApiResponseWorkflowRunOutputsOut", "ApiResponseWorkflowRunOverviewOut", "ApiResponseWorkflowRunStatusOut", "ApiResponseWorkspaceInviteOut", @@ -706,6 +713,7 @@ def __dir__(): "WorkflowRunDetailOut", "WorkflowRunListItem", "WorkflowRunOut", + "WorkflowRunOutputsOut", "WorkflowRunOverviewAudioLanguageOut", "WorkflowRunOverviewCapabilitiesOut", "WorkflowRunOverviewFutureLinksOut", @@ -721,6 +729,7 @@ def __dir__(): "WorkflowRunOverviewValidatorOut", "WorkflowRunOverviewValidatorOutStatus", "WorkflowRunOverviewWorkflowOut", + "WorkflowRunSinkOutputOut", "WorkflowRunStartIn", "WorkflowRunStatusOut", "WorkflowRunStepOut", diff --git a/src/onepin/core/client_wrapper.py b/src/onepin/core/client_wrapper.py index d2a0f90..9ade057 100644 --- a/src/onepin/core/client_wrapper.py +++ b/src/onepin/core/client_wrapper.py @@ -33,7 +33,7 @@ def get_headers(self) -> typing.Dict[str, str]: import platform headers: typing.Dict[str, str] = { - "User-Agent": "onepin/0.9.1", + "User-Agent": "onepin/0.11.1", "X-Fern-Language": "Python", "X-Fern-Runtime": f"python/{platform.python_version()}", "X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}", diff --git a/src/onepin/dictionary/client.py b/src/onepin/dictionary/client.py index 564dafe..fd2a1cf 100644 --- a/src/onepin/dictionary/client.py +++ b/src/onepin/dictionary/client.py @@ -11,22 +11,22 @@ from ..types.api_response_pronunciation_suggestion import ApiResponsePronunciationSuggestion from ..types.dictionary_method import DictionaryMethod from .raw_client import AsyncRawDictionaryClient, RawDictionaryClient -from .types.list_dictionary_entries_api_v1dictionary_get_request_language import ( +from .types.list_dictionary_entries_api_v1_dictionary_get_request_language import ( ListDictionaryEntriesApiV1DictionaryGetRequestLanguage, ) -from .types.list_dictionary_entries_api_v1dictionary_get_request_order import ( +from .types.list_dictionary_entries_api_v1_dictionary_get_request_order import ( ListDictionaryEntriesApiV1DictionaryGetRequestOrder, ) -from .types.list_dictionary_entries_api_v1dictionary_get_request_sort import ( +from .types.list_dictionary_entries_api_v1_dictionary_get_request_sort import ( ListDictionaryEntriesApiV1DictionaryGetRequestSort, ) -from .types.search_dictionary_entries_api_v1dictionary_search_get_request_language_item import ( +from .types.search_dictionary_entries_api_v1_dictionary_search_get_request_language_item import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestLanguageItem, ) -from .types.search_dictionary_entries_api_v1dictionary_search_get_request_order import ( +from .types.search_dictionary_entries_api_v1_dictionary_search_get_request_order import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestOrder, ) -from .types.search_dictionary_entries_api_v1dictionary_search_get_request_sort import ( +from .types.search_dictionary_entries_api_v1_dictionary_search_get_request_sort import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestSort, ) diff --git a/src/onepin/dictionary/raw_client.py b/src/onepin/dictionary/raw_client.py index be72790..d7704de 100644 --- a/src/onepin/dictionary/raw_client.py +++ b/src/onepin/dictionary/raw_client.py @@ -17,22 +17,22 @@ from ..types.api_response_list_dictionary_language_out import ApiResponseListDictionaryLanguageOut from ..types.api_response_pronunciation_suggestion import ApiResponsePronunciationSuggestion from ..types.dictionary_method import DictionaryMethod -from .types.list_dictionary_entries_api_v1dictionary_get_request_language import ( +from .types.list_dictionary_entries_api_v1_dictionary_get_request_language import ( ListDictionaryEntriesApiV1DictionaryGetRequestLanguage, ) -from .types.list_dictionary_entries_api_v1dictionary_get_request_order import ( +from .types.list_dictionary_entries_api_v1_dictionary_get_request_order import ( ListDictionaryEntriesApiV1DictionaryGetRequestOrder, ) -from .types.list_dictionary_entries_api_v1dictionary_get_request_sort import ( +from .types.list_dictionary_entries_api_v1_dictionary_get_request_sort import ( ListDictionaryEntriesApiV1DictionaryGetRequestSort, ) -from .types.search_dictionary_entries_api_v1dictionary_search_get_request_language_item import ( +from .types.search_dictionary_entries_api_v1_dictionary_search_get_request_language_item import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestLanguageItem, ) -from .types.search_dictionary_entries_api_v1dictionary_search_get_request_order import ( +from .types.search_dictionary_entries_api_v1_dictionary_search_get_request_order import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestOrder, ) -from .types.search_dictionary_entries_api_v1dictionary_search_get_request_sort import ( +from .types.search_dictionary_entries_api_v1_dictionary_search_get_request_sort import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestSort, ) from pydantic import ValidationError diff --git a/src/onepin/dictionary/types/__init__.py b/src/onepin/dictionary/types/__init__.py index c0f2929..27054ce 100644 --- a/src/onepin/dictionary/types/__init__.py +++ b/src/onepin/dictionary/types/__init__.py @@ -6,31 +6,31 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .list_dictionary_entries_api_v1dictionary_get_request_language import ( + from .list_dictionary_entries_api_v1_dictionary_get_request_language import ( ListDictionaryEntriesApiV1DictionaryGetRequestLanguage, ) - from .list_dictionary_entries_api_v1dictionary_get_request_order import ( + from .list_dictionary_entries_api_v1_dictionary_get_request_order import ( ListDictionaryEntriesApiV1DictionaryGetRequestOrder, ) - from .list_dictionary_entries_api_v1dictionary_get_request_sort import ( + from .list_dictionary_entries_api_v1_dictionary_get_request_sort import ( ListDictionaryEntriesApiV1DictionaryGetRequestSort, ) - from .search_dictionary_entries_api_v1dictionary_search_get_request_language_item import ( + from .search_dictionary_entries_api_v1_dictionary_search_get_request_language_item import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestLanguageItem, ) - from .search_dictionary_entries_api_v1dictionary_search_get_request_order import ( + from .search_dictionary_entries_api_v1_dictionary_search_get_request_order import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestOrder, ) - from .search_dictionary_entries_api_v1dictionary_search_get_request_sort import ( + from .search_dictionary_entries_api_v1_dictionary_search_get_request_sort import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestSort, ) _dynamic_imports: typing.Dict[str, str] = { - "ListDictionaryEntriesApiV1DictionaryGetRequestLanguage": ".list_dictionary_entries_api_v1dictionary_get_request_language", - "ListDictionaryEntriesApiV1DictionaryGetRequestOrder": ".list_dictionary_entries_api_v1dictionary_get_request_order", - "ListDictionaryEntriesApiV1DictionaryGetRequestSort": ".list_dictionary_entries_api_v1dictionary_get_request_sort", - "SearchDictionaryEntriesApiV1DictionarySearchGetRequestLanguageItem": ".search_dictionary_entries_api_v1dictionary_search_get_request_language_item", - "SearchDictionaryEntriesApiV1DictionarySearchGetRequestOrder": ".search_dictionary_entries_api_v1dictionary_search_get_request_order", - "SearchDictionaryEntriesApiV1DictionarySearchGetRequestSort": ".search_dictionary_entries_api_v1dictionary_search_get_request_sort", + "ListDictionaryEntriesApiV1DictionaryGetRequestLanguage": ".list_dictionary_entries_api_v1_dictionary_get_request_language", + "ListDictionaryEntriesApiV1DictionaryGetRequestOrder": ".list_dictionary_entries_api_v1_dictionary_get_request_order", + "ListDictionaryEntriesApiV1DictionaryGetRequestSort": ".list_dictionary_entries_api_v1_dictionary_get_request_sort", + "SearchDictionaryEntriesApiV1DictionarySearchGetRequestLanguageItem": ".search_dictionary_entries_api_v1_dictionary_search_get_request_language_item", + "SearchDictionaryEntriesApiV1DictionarySearchGetRequestOrder": ".search_dictionary_entries_api_v1_dictionary_search_get_request_order", + "SearchDictionaryEntriesApiV1DictionarySearchGetRequestSort": ".search_dictionary_entries_api_v1_dictionary_search_get_request_sort", } diff --git a/src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_language.py b/src/onepin/dictionary/types/list_dictionary_entries_api_v1_dictionary_get_request_language.py similarity index 100% rename from src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_language.py rename to src/onepin/dictionary/types/list_dictionary_entries_api_v1_dictionary_get_request_language.py diff --git a/src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_order.py b/src/onepin/dictionary/types/list_dictionary_entries_api_v1_dictionary_get_request_order.py similarity index 100% rename from src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_order.py rename to src/onepin/dictionary/types/list_dictionary_entries_api_v1_dictionary_get_request_order.py diff --git a/src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_sort.py b/src/onepin/dictionary/types/list_dictionary_entries_api_v1_dictionary_get_request_sort.py similarity index 100% rename from src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_sort.py rename to src/onepin/dictionary/types/list_dictionary_entries_api_v1_dictionary_get_request_sort.py diff --git a/src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_language_item.py b/src/onepin/dictionary/types/search_dictionary_entries_api_v1_dictionary_search_get_request_language_item.py similarity index 100% rename from src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_language_item.py rename to src/onepin/dictionary/types/search_dictionary_entries_api_v1_dictionary_search_get_request_language_item.py diff --git a/src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_order.py b/src/onepin/dictionary/types/search_dictionary_entries_api_v1_dictionary_search_get_request_order.py similarity index 100% rename from src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_order.py rename to src/onepin/dictionary/types/search_dictionary_entries_api_v1_dictionary_search_get_request_order.py diff --git a/src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_sort.py b/src/onepin/dictionary/types/search_dictionary_entries_api_v1_dictionary_search_get_request_sort.py similarity index 100% rename from src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_sort.py rename to src/onepin/dictionary/types/search_dictionary_entries_api_v1_dictionary_search_get_request_sort.py diff --git a/src/onepin/reference.md b/src/onepin/reference.md index 7b2f385..d023b31 100644 --- a/src/onepin/reference.md +++ b/src/onepin/reference.md @@ -6894,10 +6894,8 @@ values (valid for 15 minutes) so callers can stream audio directly without a separate download step. `node_display_name` is resolved from the run's definition snapshot, so it -reflects the name the node had when the run executed. When multiple language -branches reach one output node, repeated sink steps receive locale suffixes -based on the language introduced by each iteration. Other retried nodes keep -their snapshot display name and incrementing `iteration` value. +reflects the name the node had when the run executed. Repeated executions of +the same node share that name and are distinguished by `iteration`. For a higher-level view with aggregated metrics (pass rates, audio duration by language), use `GET /runs/{run_id}/overview`. For paginated, grouped @@ -6975,6 +6973,106 @@ client.workflows.get_run_steps( + + + + +
client.workflows.get_run_outputs(...) -> ApiResponseWorkflowRunOutputsOut +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Fetch one logical output per sink node in a workflow run. + +Every sink from the run's definition snapshot is returned in graph order, +including incomplete sinks with empty lines. Completed iterations are +unioned per sink with the latest completed value winning for duplicate +`line_id` values. Status reflects the latest attempt, so earlier completed +lines remain visible when a later attempt fails. Audio playback URLs are +short-lived and hydrated only on copied result lines. + +Each sink's union is capped server-side; `truncated: true` on an output +signals that its `lines` are an incomplete prefix of the logical result. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from onepin import OnePinClient +from onepin.environment import OnePinClientEnvironment + +client = OnePinClient( + token="", + environment=OnePinClientEnvironment.PROD, +) + +client.workflows.get_run_outputs( + workflow_id="workflow_id", + run_id="run_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**workflow_id:** `str` + +
+
+ +
+
+ +**run_id:** `str` + +
+
+ +
+
+ +**workspace_id:** `typing.Optional[str]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ +
@@ -6998,16 +7096,13 @@ pass rates) grouped by display section, along with per-language audio breakdowns and per-validator scoring summaries. Also includes a `workflow_snapshot` with the graph definition and per-node completion states. -Repeated states for one shared output node use the same locale suffixes as -`GET /runs/{run_id}/steps`, based on the language introduced by each sink -iteration. - This endpoint is best suited for a summary/results view after a run completes. It differs from the other run sub-resources as follows: - `GET /runs/{run_id}` — full run record including the raw definition snapshot. - `GET /runs/{run_id}/status` — volatile status fields only; for polling. - `GET /runs/{run_id}/steps` — flat per-node step log with audio playback URLs. +- `GET /runs/{run_id}/outputs` — one logical result per snapshot sink node. - `GET /runs/{run_id}/data` — paginated script+audio rows for a data table. - `GET /runs/{run_id}/overview` (this endpoint) — pre-aggregated metrics and node state map for a dashboard/overview panel. diff --git a/src/onepin/types/__init__.py b/src/onepin/types/__init__.py index 50f0fd6..4884842 100644 --- a/src/onepin/types/__init__.py +++ b/src/onepin/types/__init__.py @@ -52,6 +52,7 @@ from .api_response_workflow_out import ApiResponseWorkflowOut from .api_response_workflow_run_detail_out import ApiResponseWorkflowRunDetailOut from .api_response_workflow_run_out import ApiResponseWorkflowRunOut + from .api_response_workflow_run_outputs_out import ApiResponseWorkflowRunOutputsOut from .api_response_workflow_run_overview_out import ApiResponseWorkflowRunOverviewOut from .api_response_workflow_run_status_out import ApiResponseWorkflowRunStatusOut from .api_response_workspace_invite_out import ApiResponseWorkspaceInviteOut @@ -171,6 +172,7 @@ from .workflow_run_detail_out import WorkflowRunDetailOut from .workflow_run_list_item import WorkflowRunListItem from .workflow_run_out import WorkflowRunOut + from .workflow_run_outputs_out import WorkflowRunOutputsOut from .workflow_run_overview_audio_language_out import WorkflowRunOverviewAudioLanguageOut from .workflow_run_overview_capabilities_out import WorkflowRunOverviewCapabilitiesOut from .workflow_run_overview_future_links_out import WorkflowRunOverviewFutureLinksOut @@ -186,6 +188,7 @@ from .workflow_run_overview_validator_out import WorkflowRunOverviewValidatorOut from .workflow_run_overview_validator_out_status import WorkflowRunOverviewValidatorOutStatus from .workflow_run_overview_workflow_out import WorkflowRunOverviewWorkflowOut + from .workflow_run_sink_output_out import WorkflowRunSinkOutputOut from .workflow_run_start_in import WorkflowRunStartIn from .workflow_run_status_out import WorkflowRunStatusOut from .workflow_run_step_out import WorkflowRunStepOut @@ -242,6 +245,7 @@ "ApiResponseWorkflowOut": ".api_response_workflow_out", "ApiResponseWorkflowRunDetailOut": ".api_response_workflow_run_detail_out", "ApiResponseWorkflowRunOut": ".api_response_workflow_run_out", + "ApiResponseWorkflowRunOutputsOut": ".api_response_workflow_run_outputs_out", "ApiResponseWorkflowRunOverviewOut": ".api_response_workflow_run_overview_out", "ApiResponseWorkflowRunStatusOut": ".api_response_workflow_run_status_out", "ApiResponseWorkspaceInviteOut": ".api_response_workspace_invite_out", @@ -359,6 +363,7 @@ "WorkflowRunDetailOut": ".workflow_run_detail_out", "WorkflowRunListItem": ".workflow_run_list_item", "WorkflowRunOut": ".workflow_run_out", + "WorkflowRunOutputsOut": ".workflow_run_outputs_out", "WorkflowRunOverviewAudioLanguageOut": ".workflow_run_overview_audio_language_out", "WorkflowRunOverviewCapabilitiesOut": ".workflow_run_overview_capabilities_out", "WorkflowRunOverviewFutureLinksOut": ".workflow_run_overview_future_links_out", @@ -374,6 +379,7 @@ "WorkflowRunOverviewValidatorOut": ".workflow_run_overview_validator_out", "WorkflowRunOverviewValidatorOutStatus": ".workflow_run_overview_validator_out_status", "WorkflowRunOverviewWorkflowOut": ".workflow_run_overview_workflow_out", + "WorkflowRunSinkOutputOut": ".workflow_run_sink_output_out", "WorkflowRunStartIn": ".workflow_run_start_in", "WorkflowRunStatusOut": ".workflow_run_status_out", "WorkflowRunStepOut": ".workflow_run_step_out", @@ -454,6 +460,7 @@ def __dir__(): "ApiResponseWorkflowOut", "ApiResponseWorkflowRunDetailOut", "ApiResponseWorkflowRunOut", + "ApiResponseWorkflowRunOutputsOut", "ApiResponseWorkflowRunOverviewOut", "ApiResponseWorkflowRunStatusOut", "ApiResponseWorkspaceInviteOut", @@ -571,6 +578,7 @@ def __dir__(): "WorkflowRunDetailOut", "WorkflowRunListItem", "WorkflowRunOut", + "WorkflowRunOutputsOut", "WorkflowRunOverviewAudioLanguageOut", "WorkflowRunOverviewCapabilitiesOut", "WorkflowRunOverviewFutureLinksOut", @@ -586,6 +594,7 @@ def __dir__(): "WorkflowRunOverviewValidatorOut", "WorkflowRunOverviewValidatorOutStatus", "WorkflowRunOverviewWorkflowOut", + "WorkflowRunSinkOutputOut", "WorkflowRunStartIn", "WorkflowRunStatusOut", "WorkflowRunStepOut", diff --git a/src/onepin/types/api_response_workflow_run_outputs_out.py b/src/onepin/types/api_response_workflow_run_outputs_out.py new file mode 100644 index 0000000..01caf30 --- /dev/null +++ b/src/onepin/types/api_response_workflow_run_outputs_out.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .meta import Meta +from .workflow_run_outputs_out import WorkflowRunOutputsOut + + +class ApiResponseWorkflowRunOutputsOut(UniversalBaseModel): + data: WorkflowRunOutputsOut + meta: Meta + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/onepin/types/workflow_run_outputs_out.py b/src/onepin/types/workflow_run_outputs_out.py new file mode 100644 index 0000000..38ac3f1 --- /dev/null +++ b/src/onepin/types/workflow_run_outputs_out.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .workflow_run_sink_output_out import WorkflowRunSinkOutputOut + + +class WorkflowRunOutputsOut(UniversalBaseModel): + run_id: str + run_status: str + outputs: typing.List[WorkflowRunSinkOutputOut] + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/onepin/types/workflow_run_sink_output_out.py b/src/onepin/types/workflow_run_sink_output_out.py new file mode 100644 index 0000000..af315b0 --- /dev/null +++ b/src/onepin/types/workflow_run_sink_output_out.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class WorkflowRunSinkOutputOut(UniversalBaseModel): + node_id: str + node_type: str + display_name: str + status: str + lines: typing.List[typing.Dict[str, typing.Any]] + line_count: int + truncated: bool + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/onepin/usage/client.py b/src/onepin/usage/client.py index 7d217fd..ee636b5 100644 --- a/src/onepin/usage/client.py +++ b/src/onepin/usage/client.py @@ -9,17 +9,17 @@ from ..types.api_response_usage_summary_out import ApiResponseUsageSummaryOut from ..types.usage_activity_action import UsageActivityAction from .raw_client import AsyncRawUsageClient, RawUsageClient -from .types.usage_activity_api_v1usage_activity_get_request_range import UsageActivityApiV1UsageActivityGetRequestRange -from .types.usage_by_language_api_v1usage_by_language_get_request_activity_view import ( +from .types.usage_activity_api_v1_usage_activity_get_request_range import UsageActivityApiV1UsageActivityGetRequestRange +from .types.usage_by_language_api_v1_usage_by_language_get_request_activity_view import ( UsageByLanguageApiV1UsageByLanguageGetRequestActivityView, ) -from .types.usage_by_language_api_v1usage_by_language_get_request_range import ( +from .types.usage_by_language_api_v1_usage_by_language_get_request_range import ( UsageByLanguageApiV1UsageByLanguageGetRequestRange, ) -from .types.usage_summary_api_v1usage_summary_get_request_activity_view import ( +from .types.usage_summary_api_v1_usage_summary_get_request_activity_view import ( UsageSummaryApiV1UsageSummaryGetRequestActivityView, ) -from .types.usage_summary_api_v1usage_summary_get_request_range import UsageSummaryApiV1UsageSummaryGetRequestRange +from .types.usage_summary_api_v1_usage_summary_get_request_range import UsageSummaryApiV1UsageSummaryGetRequestRange class UsageClient: diff --git a/src/onepin/usage/raw_client.py b/src/onepin/usage/raw_client.py index 009698b..fe0832e 100644 --- a/src/onepin/usage/raw_client.py +++ b/src/onepin/usage/raw_client.py @@ -14,17 +14,17 @@ from ..types.api_response_usage_by_language_out import ApiResponseUsageByLanguageOut from ..types.api_response_usage_summary_out import ApiResponseUsageSummaryOut from ..types.usage_activity_action import UsageActivityAction -from .types.usage_activity_api_v1usage_activity_get_request_range import UsageActivityApiV1UsageActivityGetRequestRange -from .types.usage_by_language_api_v1usage_by_language_get_request_activity_view import ( +from .types.usage_activity_api_v1_usage_activity_get_request_range import UsageActivityApiV1UsageActivityGetRequestRange +from .types.usage_by_language_api_v1_usage_by_language_get_request_activity_view import ( UsageByLanguageApiV1UsageByLanguageGetRequestActivityView, ) -from .types.usage_by_language_api_v1usage_by_language_get_request_range import ( +from .types.usage_by_language_api_v1_usage_by_language_get_request_range import ( UsageByLanguageApiV1UsageByLanguageGetRequestRange, ) -from .types.usage_summary_api_v1usage_summary_get_request_activity_view import ( +from .types.usage_summary_api_v1_usage_summary_get_request_activity_view import ( UsageSummaryApiV1UsageSummaryGetRequestActivityView, ) -from .types.usage_summary_api_v1usage_summary_get_request_range import UsageSummaryApiV1UsageSummaryGetRequestRange +from .types.usage_summary_api_v1_usage_summary_get_request_range import UsageSummaryApiV1UsageSummaryGetRequestRange from pydantic import ValidationError diff --git a/src/onepin/usage/types/__init__.py b/src/onepin/usage/types/__init__.py index 53281f8..000f50b 100644 --- a/src/onepin/usage/types/__init__.py +++ b/src/onepin/usage/types/__init__.py @@ -6,23 +6,23 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .usage_activity_api_v1usage_activity_get_request_range import UsageActivityApiV1UsageActivityGetRequestRange - from .usage_by_language_api_v1usage_by_language_get_request_activity_view import ( + from .usage_activity_api_v1_usage_activity_get_request_range import UsageActivityApiV1UsageActivityGetRequestRange + from .usage_by_language_api_v1_usage_by_language_get_request_activity_view import ( UsageByLanguageApiV1UsageByLanguageGetRequestActivityView, ) - from .usage_by_language_api_v1usage_by_language_get_request_range import ( + from .usage_by_language_api_v1_usage_by_language_get_request_range import ( UsageByLanguageApiV1UsageByLanguageGetRequestRange, ) - from .usage_summary_api_v1usage_summary_get_request_activity_view import ( + from .usage_summary_api_v1_usage_summary_get_request_activity_view import ( UsageSummaryApiV1UsageSummaryGetRequestActivityView, ) - from .usage_summary_api_v1usage_summary_get_request_range import UsageSummaryApiV1UsageSummaryGetRequestRange + from .usage_summary_api_v1_usage_summary_get_request_range import UsageSummaryApiV1UsageSummaryGetRequestRange _dynamic_imports: typing.Dict[str, str] = { - "UsageActivityApiV1UsageActivityGetRequestRange": ".usage_activity_api_v1usage_activity_get_request_range", - "UsageByLanguageApiV1UsageByLanguageGetRequestActivityView": ".usage_by_language_api_v1usage_by_language_get_request_activity_view", - "UsageByLanguageApiV1UsageByLanguageGetRequestRange": ".usage_by_language_api_v1usage_by_language_get_request_range", - "UsageSummaryApiV1UsageSummaryGetRequestActivityView": ".usage_summary_api_v1usage_summary_get_request_activity_view", - "UsageSummaryApiV1UsageSummaryGetRequestRange": ".usage_summary_api_v1usage_summary_get_request_range", + "UsageActivityApiV1UsageActivityGetRequestRange": ".usage_activity_api_v1_usage_activity_get_request_range", + "UsageByLanguageApiV1UsageByLanguageGetRequestActivityView": ".usage_by_language_api_v1_usage_by_language_get_request_activity_view", + "UsageByLanguageApiV1UsageByLanguageGetRequestRange": ".usage_by_language_api_v1_usage_by_language_get_request_range", + "UsageSummaryApiV1UsageSummaryGetRequestActivityView": ".usage_summary_api_v1_usage_summary_get_request_activity_view", + "UsageSummaryApiV1UsageSummaryGetRequestRange": ".usage_summary_api_v1_usage_summary_get_request_range", } diff --git a/src/onepin/usage/types/usage_activity_api_v1usage_activity_get_request_range.py b/src/onepin/usage/types/usage_activity_api_v1_usage_activity_get_request_range.py similarity index 100% rename from src/onepin/usage/types/usage_activity_api_v1usage_activity_get_request_range.py rename to src/onepin/usage/types/usage_activity_api_v1_usage_activity_get_request_range.py diff --git a/src/onepin/usage/types/usage_by_language_api_v1usage_by_language_get_request_activity_view.py b/src/onepin/usage/types/usage_by_language_api_v1_usage_by_language_get_request_activity_view.py similarity index 100% rename from src/onepin/usage/types/usage_by_language_api_v1usage_by_language_get_request_activity_view.py rename to src/onepin/usage/types/usage_by_language_api_v1_usage_by_language_get_request_activity_view.py diff --git a/src/onepin/usage/types/usage_by_language_api_v1usage_by_language_get_request_range.py b/src/onepin/usage/types/usage_by_language_api_v1_usage_by_language_get_request_range.py similarity index 100% rename from src/onepin/usage/types/usage_by_language_api_v1usage_by_language_get_request_range.py rename to src/onepin/usage/types/usage_by_language_api_v1_usage_by_language_get_request_range.py diff --git a/src/onepin/usage/types/usage_summary_api_v1usage_summary_get_request_activity_view.py b/src/onepin/usage/types/usage_summary_api_v1_usage_summary_get_request_activity_view.py similarity index 100% rename from src/onepin/usage/types/usage_summary_api_v1usage_summary_get_request_activity_view.py rename to src/onepin/usage/types/usage_summary_api_v1_usage_summary_get_request_activity_view.py diff --git a/src/onepin/usage/types/usage_summary_api_v1usage_summary_get_request_range.py b/src/onepin/usage/types/usage_summary_api_v1_usage_summary_get_request_range.py similarity index 100% rename from src/onepin/usage/types/usage_summary_api_v1usage_summary_get_request_range.py rename to src/onepin/usage/types/usage_summary_api_v1_usage_summary_get_request_range.py diff --git a/src/onepin/users/client.py b/src/onepin/users/client.py index 4de6674..488560b 100644 --- a/src/onepin/users/client.py +++ b/src/onepin/users/client.py @@ -10,7 +10,7 @@ from ..types.api_response_plan_limits import ApiResponsePlanLimits from ..types.template_category import TemplateCategory from .raw_client import AsyncRawUsersClient, RawUsersClient -from .types.list_my_templates_api_v1users_me_templates_get_request_sort import ( +from .types.list_my_templates_api_v1_users_me_templates_get_request_sort import ( ListMyTemplatesApiV1UsersMeTemplatesGetRequestSort, ) diff --git a/src/onepin/users/raw_client.py b/src/onepin/users/raw_client.py index 6da6376..723eb45 100644 --- a/src/onepin/users/raw_client.py +++ b/src/onepin/users/raw_client.py @@ -15,7 +15,7 @@ from ..types.api_response_email_notification_preferences_out import ApiResponseEmailNotificationPreferencesOut from ..types.api_response_plan_limits import ApiResponsePlanLimits from ..types.template_category import TemplateCategory -from .types.list_my_templates_api_v1users_me_templates_get_request_sort import ( +from .types.list_my_templates_api_v1_users_me_templates_get_request_sort import ( ListMyTemplatesApiV1UsersMeTemplatesGetRequestSort, ) from pydantic import ValidationError diff --git a/src/onepin/users/types/__init__.py b/src/onepin/users/types/__init__.py index f7f5157..a08a5f6 100644 --- a/src/onepin/users/types/__init__.py +++ b/src/onepin/users/types/__init__.py @@ -6,11 +6,11 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .list_my_templates_api_v1users_me_templates_get_request_sort import ( + from .list_my_templates_api_v1_users_me_templates_get_request_sort import ( ListMyTemplatesApiV1UsersMeTemplatesGetRequestSort, ) _dynamic_imports: typing.Dict[str, str] = { - "ListMyTemplatesApiV1UsersMeTemplatesGetRequestSort": ".list_my_templates_api_v1users_me_templates_get_request_sort" + "ListMyTemplatesApiV1UsersMeTemplatesGetRequestSort": ".list_my_templates_api_v1_users_me_templates_get_request_sort" } diff --git a/src/onepin/users/types/list_my_templates_api_v1users_me_templates_get_request_sort.py b/src/onepin/users/types/list_my_templates_api_v1_users_me_templates_get_request_sort.py similarity index 100% rename from src/onepin/users/types/list_my_templates_api_v1users_me_templates_get_request_sort.py rename to src/onepin/users/types/list_my_templates_api_v1_users_me_templates_get_request_sort.py diff --git a/src/onepin/voices/client.py b/src/onepin/voices/client.py index 36cfe30..ed265d3 100644 --- a/src/onepin/voices/client.py +++ b/src/onepin/voices/client.py @@ -14,7 +14,7 @@ from ..types.voice_category import VoiceCategory from ..types.voice_gender import VoiceGender from .raw_client import AsyncRawVoicesClient, RawVoicesClient -from .types.get_voice_facets_api_v1voices_facets_get_request_source_item import ( +from .types.get_voice_facets_api_v1_voices_facets_get_request_source_item import ( GetVoiceFacetsApiV1VoicesFacetsGetRequestSourceItem, ) from .types.list_voices_request_language_item import ListVoicesRequestLanguageItem diff --git a/src/onepin/voices/raw_client.py b/src/onepin/voices/raw_client.py index ce39276..7cab1e1 100644 --- a/src/onepin/voices/raw_client.py +++ b/src/onepin/voices/raw_client.py @@ -20,7 +20,7 @@ from ..types.voice_age import VoiceAge from ..types.voice_category import VoiceCategory from ..types.voice_gender import VoiceGender -from .types.get_voice_facets_api_v1voices_facets_get_request_source_item import ( +from .types.get_voice_facets_api_v1_voices_facets_get_request_source_item import ( GetVoiceFacetsApiV1VoicesFacetsGetRequestSourceItem, ) from .types.list_voices_request_language_item import ListVoicesRequestLanguageItem diff --git a/src/onepin/voices/types/__init__.py b/src/onepin/voices/types/__init__.py index 3c4972a..b1c9803 100644 --- a/src/onepin/voices/types/__init__.py +++ b/src/onepin/voices/types/__init__.py @@ -6,7 +6,7 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .get_voice_facets_api_v1voices_facets_get_request_source_item import ( + from .get_voice_facets_api_v1_voices_facets_get_request_source_item import ( GetVoiceFacetsApiV1VoicesFacetsGetRequestSourceItem, ) from .list_voices_request_language_item import ListVoicesRequestLanguageItem @@ -14,7 +14,7 @@ from .list_voices_request_sort_item import ListVoicesRequestSortItem from .list_voices_request_source_item import ListVoicesRequestSourceItem _dynamic_imports: typing.Dict[str, str] = { - "GetVoiceFacetsApiV1VoicesFacetsGetRequestSourceItem": ".get_voice_facets_api_v1voices_facets_get_request_source_item", + "GetVoiceFacetsApiV1VoicesFacetsGetRequestSourceItem": ".get_voice_facets_api_v1_voices_facets_get_request_source_item", "ListVoicesRequestLanguageItem": ".list_voices_request_language_item", "ListVoicesRequestOrderItem": ".list_voices_request_order_item", "ListVoicesRequestSortItem": ".list_voices_request_sort_item", diff --git a/src/onepin/voices/types/get_voice_facets_api_v1voices_facets_get_request_source_item.py b/src/onepin/voices/types/get_voice_facets_api_v1_voices_facets_get_request_source_item.py similarity index 100% rename from src/onepin/voices/types/get_voice_facets_api_v1voices_facets_get_request_source_item.py rename to src/onepin/voices/types/get_voice_facets_api_v1_voices_facets_get_request_source_item.py diff --git a/src/onepin/workflows/client.py b/src/onepin/workflows/client.py index 7eb61fa..876fdb8 100644 --- a/src/onepin/workflows/client.py +++ b/src/onepin/workflows/client.py @@ -17,6 +17,7 @@ from ..types.api_response_workflow_name_availability_out import ApiResponseWorkflowNameAvailabilityOut from ..types.api_response_workflow_out import ApiResponseWorkflowOut from ..types.api_response_workflow_run_out import ApiResponseWorkflowRunOut +from ..types.api_response_workflow_run_outputs_out import ApiResponseWorkflowRunOutputsOut from ..types.api_response_workflow_run_overview_out import ApiResponseWorkflowRunOverviewOut from ..types.workflow_definition_input import WorkflowDefinitionInput from ..types.workflow_list_status import WorkflowListStatus @@ -724,10 +725,8 @@ def get_run_steps( a separate download step. `node_display_name` is resolved from the run's definition snapshot, so it - reflects the name the node had when the run executed. When multiple language - branches reach one output node, repeated sink steps receive locale suffixes - based on the language introduced by each iteration. Other retried nodes keep - their snapshot display name and incrementing `iteration` value. + reflects the name the node had when the run executed. Repeated executions of + the same node share that name and are distinguished by `iteration`. For a higher-level view with aggregated metrics (pass rates, audio duration by language), use `GET /runs/{run_id}/overview`. For paginated, grouped @@ -766,6 +765,60 @@ def get_run_steps( ) return _response.data + def get_run_outputs( + self, + workflow_id: str, + run_id: str, + *, + workspace_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ApiResponseWorkflowRunOutputsOut: + """ + Fetch one logical output per sink node in a workflow run. + + Every sink from the run's definition snapshot is returned in graph order, + including incomplete sinks with empty lines. Completed iterations are + unioned per sink with the latest completed value winning for duplicate + `line_id` values. Status reflects the latest attempt, so earlier completed + lines remain visible when a later attempt fails. Audio playback URLs are + short-lived and hydrated only on copied result lines. + + Each sink's union is capped server-side; `truncated: true` on an output + signals that its `lines` are an incomplete prefix of the logical result. + + Parameters + ---------- + workflow_id : str + + run_id : str + + workspace_id : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ApiResponseWorkflowRunOutputsOut + Successful Response + + Examples + -------- + from onepin import OnePinClient + + client = OnePinClient( + token="YOUR_TOKEN", + ) + client.workflows.get_run_outputs( + workflow_id="workflow_id", + run_id="run_id", + ) + """ + _response = self._raw_client.get_run_outputs( + workflow_id, run_id, workspace_id=workspace_id, request_options=request_options + ) + return _response.data + def get_run_overview( self, workflow_id: str, @@ -782,16 +835,13 @@ def get_run_overview( breakdowns and per-validator scoring summaries. Also includes a `workflow_snapshot` with the graph definition and per-node completion states. - Repeated states for one shared output node use the same locale suffixes as - `GET /runs/{run_id}/steps`, based on the language introduced by each sink - iteration. - This endpoint is best suited for a summary/results view after a run completes. It differs from the other run sub-resources as follows: - `GET /runs/{run_id}` — full run record including the raw definition snapshot. - `GET /runs/{run_id}/status` — volatile status fields only; for polling. - `GET /runs/{run_id}/steps` — flat per-node step log with audio playback URLs. + - `GET /runs/{run_id}/outputs` — one logical result per snapshot sink node. - `GET /runs/{run_id}/data` — paginated script+audio rows for a data table. - `GET /runs/{run_id}/overview` (this endpoint) — pre-aggregated metrics and node state map for a dashboard/overview panel. @@ -1976,10 +2026,8 @@ async def get_run_steps( a separate download step. `node_display_name` is resolved from the run's definition snapshot, so it - reflects the name the node had when the run executed. When multiple language - branches reach one output node, repeated sink steps receive locale suffixes - based on the language introduced by each iteration. Other retried nodes keep - their snapshot display name and incrementing `iteration` value. + reflects the name the node had when the run executed. Repeated executions of + the same node share that name and are distinguished by `iteration`. For a higher-level view with aggregated metrics (pass rates, audio duration by language), use `GET /runs/{run_id}/overview`. For paginated, grouped @@ -2026,6 +2074,68 @@ async def main() -> None: ) return _response.data + async def get_run_outputs( + self, + workflow_id: str, + run_id: str, + *, + workspace_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ApiResponseWorkflowRunOutputsOut: + """ + Fetch one logical output per sink node in a workflow run. + + Every sink from the run's definition snapshot is returned in graph order, + including incomplete sinks with empty lines. Completed iterations are + unioned per sink with the latest completed value winning for duplicate + `line_id` values. Status reflects the latest attempt, so earlier completed + lines remain visible when a later attempt fails. Audio playback URLs are + short-lived and hydrated only on copied result lines. + + Each sink's union is capped server-side; `truncated: true` on an output + signals that its `lines` are an incomplete prefix of the logical result. + + Parameters + ---------- + workflow_id : str + + run_id : str + + workspace_id : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ApiResponseWorkflowRunOutputsOut + Successful Response + + Examples + -------- + import asyncio + + from onepin import AsyncOnePinClient + + client = AsyncOnePinClient( + token="YOUR_TOKEN", + ) + + + async def main() -> None: + await client.workflows.get_run_outputs( + workflow_id="workflow_id", + run_id="run_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_run_outputs( + workflow_id, run_id, workspace_id=workspace_id, request_options=request_options + ) + return _response.data + async def get_run_overview( self, workflow_id: str, @@ -2042,16 +2152,13 @@ async def get_run_overview( breakdowns and per-validator scoring summaries. Also includes a `workflow_snapshot` with the graph definition and per-node completion states. - Repeated states for one shared output node use the same locale suffixes as - `GET /runs/{run_id}/steps`, based on the language introduced by each sink - iteration. - This endpoint is best suited for a summary/results view after a run completes. It differs from the other run sub-resources as follows: - `GET /runs/{run_id}` — full run record including the raw definition snapshot. - `GET /runs/{run_id}/status` — volatile status fields only; for polling. - `GET /runs/{run_id}/steps` — flat per-node step log with audio playback URLs. + - `GET /runs/{run_id}/outputs` — one logical result per snapshot sink node. - `GET /runs/{run_id}/data` — paginated script+audio rows for a data table. - `GET /runs/{run_id}/overview` (this endpoint) — pre-aggregated metrics and node state map for a dashboard/overview panel. diff --git a/src/onepin/workflows/raw_client.py b/src/onepin/workflows/raw_client.py index e8ce115..22b75ba 100644 --- a/src/onepin/workflows/raw_client.py +++ b/src/onepin/workflows/raw_client.py @@ -26,6 +26,7 @@ from ..types.api_response_workflow_name_availability_out import ApiResponseWorkflowNameAvailabilityOut from ..types.api_response_workflow_out import ApiResponseWorkflowOut from ..types.api_response_workflow_run_out import ApiResponseWorkflowRunOut +from ..types.api_response_workflow_run_outputs_out import ApiResponseWorkflowRunOutputsOut from ..types.api_response_workflow_run_overview_out import ApiResponseWorkflowRunOverviewOut from ..types.workflow_definition_input import WorkflowDefinitionInput from ..types.workflow_list_status import WorkflowListStatus @@ -988,10 +989,8 @@ def get_run_steps( a separate download step. `node_display_name` is resolved from the run's definition snapshot, so it - reflects the name the node had when the run executed. When multiple language - branches reach one output node, repeated sink steps receive locale suffixes - based on the language introduced by each iteration. Other retried nodes keep - their snapshot display name and incrementing `iteration` value. + reflects the name the node had when the run executed. Repeated executions of + the same node share that name and are distinguished by `iteration`. For a higher-level view with aggregated metrics (pass rates, audio duration by language), use `GET /runs/{run_id}/overview`. For paginated, grouped @@ -1051,6 +1050,81 @@ def get_run_steps( ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + def get_run_outputs( + self, + workflow_id: str, + run_id: str, + *, + workspace_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ApiResponseWorkflowRunOutputsOut]: + """ + Fetch one logical output per sink node in a workflow run. + + Every sink from the run's definition snapshot is returned in graph order, + including incomplete sinks with empty lines. Completed iterations are + unioned per sink with the latest completed value winning for duplicate + `line_id` values. Status reflects the latest attempt, so earlier completed + lines remain visible when a later attempt fails. Audio playback URLs are + short-lived and hydrated only on copied result lines. + + Each sink's union is capped server-side; `truncated: true` on an output + signals that its `lines` are an incomplete prefix of the logical result. + + Parameters + ---------- + workflow_id : str + + run_id : str + + workspace_id : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ApiResponseWorkflowRunOutputsOut] + Successful Response + """ + _response = self._client_wrapper.httpx_client.request( + f"api/v1/workflows/{encode_path_param(workflow_id)}/runs/{encode_path_param(run_id)}/outputs", + method="GET", + headers={ + "X-Workspace-Id": str(workspace_id) if workspace_id is not None else None, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ApiResponseWorkflowRunOutputsOut, + parse_obj_as( + type_=ApiResponseWorkflowRunOutputsOut, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + def get_run_overview( self, workflow_id: str, @@ -1067,16 +1141,13 @@ def get_run_overview( breakdowns and per-validator scoring summaries. Also includes a `workflow_snapshot` with the graph definition and per-node completion states. - Repeated states for one shared output node use the same locale suffixes as - `GET /runs/{run_id}/steps`, based on the language introduced by each sink - iteration. - This endpoint is best suited for a summary/results view after a run completes. It differs from the other run sub-resources as follows: - `GET /runs/{run_id}` — full run record including the raw definition snapshot. - `GET /runs/{run_id}/status` — volatile status fields only; for polling. - `GET /runs/{run_id}/steps` — flat per-node step log with audio playback URLs. + - `GET /runs/{run_id}/outputs` — one logical result per snapshot sink node. - `GET /runs/{run_id}/data` — paginated script+audio rows for a data table. - `GET /runs/{run_id}/overview` (this endpoint) — pre-aggregated metrics and node state map for a dashboard/overview panel. @@ -2612,10 +2683,8 @@ async def get_run_steps( a separate download step. `node_display_name` is resolved from the run's definition snapshot, so it - reflects the name the node had when the run executed. When multiple language - branches reach one output node, repeated sink steps receive locale suffixes - based on the language introduced by each iteration. Other retried nodes keep - their snapshot display name and incrementing `iteration` value. + reflects the name the node had when the run executed. Repeated executions of + the same node share that name and are distinguished by `iteration`. For a higher-level view with aggregated metrics (pass rates, audio duration by language), use `GET /runs/{run_id}/overview`. For paginated, grouped @@ -2675,6 +2744,81 @@ async def get_run_steps( ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + async def get_run_outputs( + self, + workflow_id: str, + run_id: str, + *, + workspace_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ApiResponseWorkflowRunOutputsOut]: + """ + Fetch one logical output per sink node in a workflow run. + + Every sink from the run's definition snapshot is returned in graph order, + including incomplete sinks with empty lines. Completed iterations are + unioned per sink with the latest completed value winning for duplicate + `line_id` values. Status reflects the latest attempt, so earlier completed + lines remain visible when a later attempt fails. Audio playback URLs are + short-lived and hydrated only on copied result lines. + + Each sink's union is capped server-side; `truncated: true` on an output + signals that its `lines` are an incomplete prefix of the logical result. + + Parameters + ---------- + workflow_id : str + + run_id : str + + workspace_id : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ApiResponseWorkflowRunOutputsOut] + Successful Response + """ + _response = await self._client_wrapper.httpx_client.request( + f"api/v1/workflows/{encode_path_param(workflow_id)}/runs/{encode_path_param(run_id)}/outputs", + method="GET", + headers={ + "X-Workspace-Id": str(workspace_id) if workspace_id is not None else None, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ApiResponseWorkflowRunOutputsOut, + parse_obj_as( + type_=ApiResponseWorkflowRunOutputsOut, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + async def get_run_overview( self, workflow_id: str, @@ -2691,16 +2835,13 @@ async def get_run_overview( breakdowns and per-validator scoring summaries. Also includes a `workflow_snapshot` with the graph definition and per-node completion states. - Repeated states for one shared output node use the same locale suffixes as - `GET /runs/{run_id}/steps`, based on the language introduced by each sink - iteration. - This endpoint is best suited for a summary/results view after a run completes. It differs from the other run sub-resources as follows: - `GET /runs/{run_id}` — full run record including the raw definition snapshot. - `GET /runs/{run_id}/status` — volatile status fields only; for polling. - `GET /runs/{run_id}/steps` — flat per-node step log with audio playback URLs. + - `GET /runs/{run_id}/outputs` — one logical result per snapshot sink node. - `GET /runs/{run_id}/data` — paginated script+audio rows for a data table. - `GET /runs/{run_id}/overview` (this endpoint) — pre-aggregated metrics and node state map for a dashboard/overview panel.