diff --git a/.spec-sha b/.spec-sha index eccd7b1..52ea54b 100644 --- a/.spec-sha +++ b/.spec-sha @@ -1 +1 @@ -cddf1ca71c61a62e9e429206b74a6d064222b4ed +28bf2af12a8765adb95381c7160cfc5b5e4ddd12 diff --git a/src/onepin/.fern/metadata.json b/src/onepin/.fern/metadata.json index 6e675c6..4ded201 100644 --- a/src/onepin/.fern/metadata.json +++ b/src/onepin/.fern/metadata.json @@ -30,7 +30,7 @@ } ] }, - "originGitCommit": "a3ee57d10e66cc74651c81add046845159caf420", + "originGitCommit": "968747c21f0b427963288a82817fbe21a736230b", "originGitCommitIsDirty": false, "invokedBy": "ci", "ciProvider": "github" diff --git a/src/onepin/__init__.py b/src/onepin/__init__.py index 939df16..3fa3327 100644 --- a/src/onepin/__init__.py +++ b/src/onepin/__init__.py @@ -156,10 +156,14 @@ WorkflowRunDataAudioOut, WorkflowRunDataAudioOutStatus, WorkflowRunDataCardOut, + WorkflowRunDataCardOutStatus, WorkflowRunDataCardOutWaveformStatus, + WorkflowRunDataDroppedOut, + WorkflowRunDataDroppedVerdictOut, WorkflowRunDataOut, WorkflowRunDataPartialOut, WorkflowRunDataPartialOutStatus, + WorkflowRunDataRejectedOut, WorkflowRunDataResponse, WorkflowRunDataRowOut, WorkflowRunDataRowOutAutoCorrectedStatus, @@ -175,6 +179,7 @@ WorkflowRunOverviewAudioLanguageOut, WorkflowRunOverviewCapabilitiesOut, WorkflowRunOverviewFutureLinksOut, + WorkflowRunOverviewMetricAnnotation, WorkflowRunOverviewMetricDisplay, WorkflowRunOverviewMetricOut, WorkflowRunOverviewMetricOutStatus, @@ -432,10 +437,14 @@ "WorkflowRunDataAudioOut": ".types", "WorkflowRunDataAudioOutStatus": ".types", "WorkflowRunDataCardOut": ".types", + "WorkflowRunDataCardOutStatus": ".types", "WorkflowRunDataCardOutWaveformStatus": ".types", + "WorkflowRunDataDroppedOut": ".types", + "WorkflowRunDataDroppedVerdictOut": ".types", "WorkflowRunDataOut": ".types", "WorkflowRunDataPartialOut": ".types", "WorkflowRunDataPartialOutStatus": ".types", + "WorkflowRunDataRejectedOut": ".types", "WorkflowRunDataResponse": ".types", "WorkflowRunDataRowOut": ".types", "WorkflowRunDataRowOutAutoCorrectedStatus": ".types", @@ -451,6 +460,7 @@ "WorkflowRunOverviewAudioLanguageOut": ".types", "WorkflowRunOverviewCapabilitiesOut": ".types", "WorkflowRunOverviewFutureLinksOut": ".types", + "WorkflowRunOverviewMetricAnnotation": ".types", "WorkflowRunOverviewMetricDisplay": ".types", "WorkflowRunOverviewMetricOut": ".types", "WorkflowRunOverviewMetricOutStatus": ".types", @@ -698,10 +708,14 @@ def __dir__(): "WorkflowRunDataAudioOut", "WorkflowRunDataAudioOutStatus", "WorkflowRunDataCardOut", + "WorkflowRunDataCardOutStatus", "WorkflowRunDataCardOutWaveformStatus", + "WorkflowRunDataDroppedOut", + "WorkflowRunDataDroppedVerdictOut", "WorkflowRunDataOut", "WorkflowRunDataPartialOut", "WorkflowRunDataPartialOutStatus", + "WorkflowRunDataRejectedOut", "WorkflowRunDataResponse", "WorkflowRunDataRowOut", "WorkflowRunDataRowOutAutoCorrectedStatus", @@ -717,6 +731,7 @@ def __dir__(): "WorkflowRunOverviewAudioLanguageOut", "WorkflowRunOverviewCapabilitiesOut", "WorkflowRunOverviewFutureLinksOut", + "WorkflowRunOverviewMetricAnnotation", "WorkflowRunOverviewMetricDisplay", "WorkflowRunOverviewMetricOut", "WorkflowRunOverviewMetricOutStatus", diff --git a/src/onepin/dictionary/client.py b/src/onepin/dictionary/client.py index fd2a1cf..564dafe 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_v1_dictionary_get_request_language import ( +from .types.list_dictionary_entries_api_v1dictionary_get_request_language import ( ListDictionaryEntriesApiV1DictionaryGetRequestLanguage, ) -from .types.list_dictionary_entries_api_v1_dictionary_get_request_order import ( +from .types.list_dictionary_entries_api_v1dictionary_get_request_order import ( ListDictionaryEntriesApiV1DictionaryGetRequestOrder, ) -from .types.list_dictionary_entries_api_v1_dictionary_get_request_sort import ( +from .types.list_dictionary_entries_api_v1dictionary_get_request_sort import ( ListDictionaryEntriesApiV1DictionaryGetRequestSort, ) -from .types.search_dictionary_entries_api_v1_dictionary_search_get_request_language_item import ( +from .types.search_dictionary_entries_api_v1dictionary_search_get_request_language_item import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestLanguageItem, ) -from .types.search_dictionary_entries_api_v1_dictionary_search_get_request_order import ( +from .types.search_dictionary_entries_api_v1dictionary_search_get_request_order import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestOrder, ) -from .types.search_dictionary_entries_api_v1_dictionary_search_get_request_sort import ( +from .types.search_dictionary_entries_api_v1dictionary_search_get_request_sort import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestSort, ) diff --git a/src/onepin/dictionary/raw_client.py b/src/onepin/dictionary/raw_client.py index d7704de..be72790 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_v1_dictionary_get_request_language import ( +from .types.list_dictionary_entries_api_v1dictionary_get_request_language import ( ListDictionaryEntriesApiV1DictionaryGetRequestLanguage, ) -from .types.list_dictionary_entries_api_v1_dictionary_get_request_order import ( +from .types.list_dictionary_entries_api_v1dictionary_get_request_order import ( ListDictionaryEntriesApiV1DictionaryGetRequestOrder, ) -from .types.list_dictionary_entries_api_v1_dictionary_get_request_sort import ( +from .types.list_dictionary_entries_api_v1dictionary_get_request_sort import ( ListDictionaryEntriesApiV1DictionaryGetRequestSort, ) -from .types.search_dictionary_entries_api_v1_dictionary_search_get_request_language_item import ( +from .types.search_dictionary_entries_api_v1dictionary_search_get_request_language_item import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestLanguageItem, ) -from .types.search_dictionary_entries_api_v1_dictionary_search_get_request_order import ( +from .types.search_dictionary_entries_api_v1dictionary_search_get_request_order import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestOrder, ) -from .types.search_dictionary_entries_api_v1_dictionary_search_get_request_sort import ( +from .types.search_dictionary_entries_api_v1dictionary_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 27054ce..c0f2929 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_v1_dictionary_get_request_language import ( + from .list_dictionary_entries_api_v1dictionary_get_request_language import ( ListDictionaryEntriesApiV1DictionaryGetRequestLanguage, ) - from .list_dictionary_entries_api_v1_dictionary_get_request_order import ( + from .list_dictionary_entries_api_v1dictionary_get_request_order import ( ListDictionaryEntriesApiV1DictionaryGetRequestOrder, ) - from .list_dictionary_entries_api_v1_dictionary_get_request_sort import ( + from .list_dictionary_entries_api_v1dictionary_get_request_sort import ( ListDictionaryEntriesApiV1DictionaryGetRequestSort, ) - from .search_dictionary_entries_api_v1_dictionary_search_get_request_language_item import ( + from .search_dictionary_entries_api_v1dictionary_search_get_request_language_item import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestLanguageItem, ) - from .search_dictionary_entries_api_v1_dictionary_search_get_request_order import ( + from .search_dictionary_entries_api_v1dictionary_search_get_request_order import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestOrder, ) - from .search_dictionary_entries_api_v1_dictionary_search_get_request_sort import ( + from .search_dictionary_entries_api_v1dictionary_search_get_request_sort import ( SearchDictionaryEntriesApiV1DictionarySearchGetRequestSort, ) _dynamic_imports: typing.Dict[str, str] = { - "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", + "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", } diff --git a/src/onepin/dictionary/types/list_dictionary_entries_api_v1_dictionary_get_request_language.py b/src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_language.py similarity index 100% rename from src/onepin/dictionary/types/list_dictionary_entries_api_v1_dictionary_get_request_language.py rename to src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_language.py diff --git a/src/onepin/dictionary/types/list_dictionary_entries_api_v1_dictionary_get_request_order.py b/src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_order.py similarity index 100% rename from src/onepin/dictionary/types/list_dictionary_entries_api_v1_dictionary_get_request_order.py rename to src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_order.py diff --git a/src/onepin/dictionary/types/list_dictionary_entries_api_v1_dictionary_get_request_sort.py b/src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_sort.py similarity index 100% rename from src/onepin/dictionary/types/list_dictionary_entries_api_v1_dictionary_get_request_sort.py rename to src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_sort.py diff --git a/src/onepin/dictionary/types/search_dictionary_entries_api_v1_dictionary_search_get_request_language_item.py b/src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_language_item.py similarity index 100% rename from src/onepin/dictionary/types/search_dictionary_entries_api_v1_dictionary_search_get_request_language_item.py rename to src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_language_item.py diff --git a/src/onepin/dictionary/types/search_dictionary_entries_api_v1_dictionary_search_get_request_order.py b/src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_order.py similarity index 100% rename from src/onepin/dictionary/types/search_dictionary_entries_api_v1_dictionary_search_get_request_order.py rename to src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_order.py diff --git a/src/onepin/dictionary/types/search_dictionary_entries_api_v1_dictionary_search_get_request_sort.py b/src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_sort.py similarity index 100% rename from src/onepin/dictionary/types/search_dictionary_entries_api_v1_dictionary_search_get_request_sort.py rename to src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_sort.py diff --git a/src/onepin/reference.md b/src/onepin/reference.md index d023b31..b2c9a79 100644 --- a/src/onepin/reference.md +++ b/src/onepin/reference.md @@ -4797,7 +4797,7 @@ client.uploads.confirm(
-**context_type:** `UploadConfirmRequestContextType` — Type of resource this upload is being attached to: `workflow` or `playground`. +**context_type:** `UploadConfirmRequestContextType` — Type of resource this upload is being attached to: `workflow`, `playground`, or `assistant_session`.
@@ -6867,112 +6867,6 @@ client.workflows.runs_summary( - - - - -
client.workflows.get_run_steps(...) -> ApiResponseListWorkflowRunStepOut -
-
- -#### 📝 Description - -
-
- -
-
- -List per-node execution steps for a workflow run. - -Returns one entry per node execution attempt, ordered by execution sequence. -Each step includes the node type, status, iteration number (for nodes that -are retried), start/completion timestamps, and the node's `result` output. - -For audio output nodes, `result` is hydrated with short-lived `playback_url` -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. 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 -script+audio rows suitable for a data table, use `GET /runs/{run_id}/data`. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from onepin import OnePinClient -from onepin.environment import OnePinClientEnvironment - -client = OnePinClient( - token="", - environment=OnePinClientEnvironment.PROD, -) - -client.workflows.get_run_steps( - 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. - -
-
-
-
- -
@@ -7101,7 +6995,8 @@ 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}/steps` — lightweight per-node step log by default; + `include_result=true` includes results and 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 @@ -7208,6 +7103,8 @@ validation scores (word accuracy, naturalness), and short-lived audio locale. Rows with no matching cards are still returned (with empty `cards`), and `pagination.total` always reflects the search-filtered row count regardless of `language`. +- `include_dropped=true` adds rejected attempts to `cards` with + `status="dropped"`; the default response remains delivered/generated data only. **Pagination:** `pagination.total` is scoped to the `search` filter only. @@ -7288,6 +7185,14 @@ client.workflows.get_run_data(
+**include_dropped:** `typing.Optional[bool]` — Include validator-rejected audio cards reconstructed from unwired fail ports. Defaults to false so existing clients continue receiving delivered output only. + +
+
+ +
+
+ **offset:** `typing.Optional[int]` — Zero-based pagination offset.
@@ -7423,6 +7328,112 @@ client.workflows.download_run(
+ + + + +
client.workflows.get_run_audio_url(...) -> ApiResponseDownloadUrlOut +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Mint a fresh playback URL for one audio output of a run. + +`audio_id` is the stable 16-hex output identifier embedded in run-data +card ids and carried by assistant chat `audio` parts. Presigned playback +URLs expire after 15 minutes; call this endpoint at play time to refresh +the URL by id instead of caching it or re-fetching a whole run-data page. + +Returns 404 when the run has no s3-backed audio output with this id. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from onepin import OnePinClient +from onepin.environment import OnePinClientEnvironment + +client = OnePinClient( + token="", + environment=OnePinClientEnvironment.PROD, +) + +client.workflows.get_run_audio_url( + workflow_id="workflow_id", + run_id="run_id", + audio_id="audio_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**workflow_id:** `str` + +
+
+ +
+
+ +**run_id:** `str` + +
+
+ +
+
+ +**audio_id:** `str` + +
+
+ +
+
+ +**workspace_id:** `typing.Optional[str]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ +
@@ -8101,7 +8112,8 @@ workflow definition has since been edited. This is the heaviest run endpoint. For progress polling, use the lighter `GET /runs/{run_id}/status` which omits the snapshot. For aggregated visual metrics, use `GET /runs/{run_id}/overview`. For the per-node step -log with audio playback URLs, use `GET /runs/{run_id}/steps`. +log, use `GET /runs/{run_id}/steps`; opt into full results and audio +playback URLs with `include_result=true`. @@ -8281,6 +8293,137 @@ client.workflows.runs.status( + + + + +
client.workflows.runs.steps(...) -> ApiResponseListWorkflowRunStepOut +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List per-node execution steps for a workflow run. + +Returns one entry per node execution attempt, ordered by execution sequence. +By default, the response is lightweight: `result` is null, `has_result` +reports whether a stored result exists, and `active_ports` is projected from +the result without loading the full JSON payload. + +Set `include_result=true` to restore the full result payload. Audio results +are then hydrated with short-lived `playback_url` values (valid for 15 +minutes). `node_type` and `node_id` filters combine with AND semantics. + +`node_display_name` is resolved from the run's definition snapshot, so it +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 +script+audio rows suitable for a data table, use `GET /runs/{run_id}/data`. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from onepin import OnePinClient +from onepin.environment import OnePinClientEnvironment + +client = OnePinClient( + token="", + environment=OnePinClientEnvironment.PROD, +) + +client.workflows.runs.steps( + workflow_id="workflow_id", + run_id="run_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**workflow_id:** `str` + +
+
+ +
+
+ +**run_id:** `str` + +
+
+ +
+
+ +**include_result:** `typing.Optional[bool]` — Include the full step result payload and hydrate audio playback URLs. + +
+
+ +
+
+ +**node_type:** `typing.Optional[NodeType]` — Filter steps by node type. + +
+
+ +
+
+ +**node_id:** `typing.Optional[str]` — Filter steps by node ID. + +
+
+ +
+
+ +**workspace_id:** `typing.Optional[str]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ +
@@ -8304,9 +8447,9 @@ In-flight work at the current node may be abandoned mid-execution. The operation is idempotent: cancelling an already-cancelled run returns the run unchanged without error. -Only runs in `pending`, `running`, or `paused` status can be cancelled. -Runs that have already reached a terminal state (`completed`, `failed`, -`cancelled`) return 409. +Runs already in a terminal state (`completed`, `failed`, or `cancelled`) +are returned unchanged. Concurrent terminalization is also treated as an +idempotent success; a still-active compare-and-swap loser returns 409. Unlike `pause`, cancel is permanent — a cancelled run cannot be resumed. Use `pause` if you intend to continue the run later. diff --git a/src/onepin/types/__init__.py b/src/onepin/types/__init__.py index 4884842..c2f5808 100644 --- a/src/onepin/types/__init__.py +++ b/src/onepin/types/__init__.py @@ -157,10 +157,14 @@ from .workflow_run_data_audio_out import WorkflowRunDataAudioOut from .workflow_run_data_audio_out_status import WorkflowRunDataAudioOutStatus from .workflow_run_data_card_out import WorkflowRunDataCardOut + from .workflow_run_data_card_out_status import WorkflowRunDataCardOutStatus from .workflow_run_data_card_out_waveform_status import WorkflowRunDataCardOutWaveformStatus + from .workflow_run_data_dropped_out import WorkflowRunDataDroppedOut + from .workflow_run_data_dropped_verdict_out import WorkflowRunDataDroppedVerdictOut from .workflow_run_data_out import WorkflowRunDataOut from .workflow_run_data_partial_out import WorkflowRunDataPartialOut from .workflow_run_data_partial_out_status import WorkflowRunDataPartialOutStatus + from .workflow_run_data_rejected_out import WorkflowRunDataRejectedOut from .workflow_run_data_response import WorkflowRunDataResponse from .workflow_run_data_row_out import WorkflowRunDataRowOut from .workflow_run_data_row_out_auto_corrected_status import WorkflowRunDataRowOutAutoCorrectedStatus @@ -176,6 +180,7 @@ 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 + from .workflow_run_overview_metric_annotation import WorkflowRunOverviewMetricAnnotation from .workflow_run_overview_metric_display import WorkflowRunOverviewMetricDisplay from .workflow_run_overview_metric_out import WorkflowRunOverviewMetricOut from .workflow_run_overview_metric_out_status import WorkflowRunOverviewMetricOutStatus @@ -348,10 +353,14 @@ "WorkflowRunDataAudioOut": ".workflow_run_data_audio_out", "WorkflowRunDataAudioOutStatus": ".workflow_run_data_audio_out_status", "WorkflowRunDataCardOut": ".workflow_run_data_card_out", + "WorkflowRunDataCardOutStatus": ".workflow_run_data_card_out_status", "WorkflowRunDataCardOutWaveformStatus": ".workflow_run_data_card_out_waveform_status", + "WorkflowRunDataDroppedOut": ".workflow_run_data_dropped_out", + "WorkflowRunDataDroppedVerdictOut": ".workflow_run_data_dropped_verdict_out", "WorkflowRunDataOut": ".workflow_run_data_out", "WorkflowRunDataPartialOut": ".workflow_run_data_partial_out", "WorkflowRunDataPartialOutStatus": ".workflow_run_data_partial_out_status", + "WorkflowRunDataRejectedOut": ".workflow_run_data_rejected_out", "WorkflowRunDataResponse": ".workflow_run_data_response", "WorkflowRunDataRowOut": ".workflow_run_data_row_out", "WorkflowRunDataRowOutAutoCorrectedStatus": ".workflow_run_data_row_out_auto_corrected_status", @@ -367,6 +376,7 @@ "WorkflowRunOverviewAudioLanguageOut": ".workflow_run_overview_audio_language_out", "WorkflowRunOverviewCapabilitiesOut": ".workflow_run_overview_capabilities_out", "WorkflowRunOverviewFutureLinksOut": ".workflow_run_overview_future_links_out", + "WorkflowRunOverviewMetricAnnotation": ".workflow_run_overview_metric_annotation", "WorkflowRunOverviewMetricDisplay": ".workflow_run_overview_metric_display", "WorkflowRunOverviewMetricOut": ".workflow_run_overview_metric_out", "WorkflowRunOverviewMetricOutStatus": ".workflow_run_overview_metric_out_status", @@ -563,10 +573,14 @@ def __dir__(): "WorkflowRunDataAudioOut", "WorkflowRunDataAudioOutStatus", "WorkflowRunDataCardOut", + "WorkflowRunDataCardOutStatus", "WorkflowRunDataCardOutWaveformStatus", + "WorkflowRunDataDroppedOut", + "WorkflowRunDataDroppedVerdictOut", "WorkflowRunDataOut", "WorkflowRunDataPartialOut", "WorkflowRunDataPartialOutStatus", + "WorkflowRunDataRejectedOut", "WorkflowRunDataResponse", "WorkflowRunDataRowOut", "WorkflowRunDataRowOutAutoCorrectedStatus", @@ -582,6 +596,7 @@ def __dir__(): "WorkflowRunOverviewAudioLanguageOut", "WorkflowRunOverviewCapabilitiesOut", "WorkflowRunOverviewFutureLinksOut", + "WorkflowRunOverviewMetricAnnotation", "WorkflowRunOverviewMetricDisplay", "WorkflowRunOverviewMetricOut", "WorkflowRunOverviewMetricOutStatus", diff --git a/src/onepin/types/workflow_run_data_card_out.py b/src/onepin/types/workflow_run_data_card_out.py index b4b9e16..57bed63 100644 --- a/src/onepin/types/workflow_run_data_card_out.py +++ b/src/onepin/types/workflow_run_data_card_out.py @@ -5,7 +5,10 @@ import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .workflow_run_data_audio_out import WorkflowRunDataAudioOut +from .workflow_run_data_card_out_status import WorkflowRunDataCardOutStatus from .workflow_run_data_card_out_waveform_status import WorkflowRunDataCardOutWaveformStatus +from .workflow_run_data_dropped_out import WorkflowRunDataDroppedOut +from .workflow_run_data_rejected_out import WorkflowRunDataRejectedOut from .workflow_run_data_validation_out import WorkflowRunDataValidationOut from .workflow_run_data_voice_out import WorkflowRunDataVoiceOut @@ -24,6 +27,9 @@ class WorkflowRunDataCardOut(UniversalBaseModel): waveform_status: typing.Optional[WorkflowRunDataCardOutWaveformStatus] = None waveform_reason: typing.Optional[str] = None retry_count: typing.Optional[int] = None + status: typing.Optional[WorkflowRunDataCardOutStatus] = None + dropped: typing.Optional[WorkflowRunDataDroppedOut] = None + rejected: typing.Optional[WorkflowRunDataRejectedOut] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/onepin/types/workflow_run_data_card_out_status.py b/src/onepin/types/workflow_run_data_card_out_status.py new file mode 100644 index 0000000..9ed2c35 --- /dev/null +++ b/src/onepin/types/workflow_run_data_card_out_status.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkflowRunDataCardOutStatus = typing.Union[ + typing.Literal["delivered", "generated", "not_delivered", "dropped"], typing.Any +] diff --git a/src/onepin/types/workflow_run_data_dropped_out.py b/src/onepin/types/workflow_run_data_dropped_out.py new file mode 100644 index 0000000..2617b5d --- /dev/null +++ b/src/onepin/types/workflow_run_data_dropped_out.py @@ -0,0 +1,20 @@ +# 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_data_dropped_verdict_out import WorkflowRunDataDroppedVerdictOut + + +class WorkflowRunDataDroppedOut(UniversalBaseModel): + verdicts: typing.Optional[typing.List[WorkflowRunDataDroppedVerdictOut]] = None + + 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_data_dropped_verdict_out.py b/src/onepin/types/workflow_run_data_dropped_verdict_out.py new file mode 100644 index 0000000..b418359 --- /dev/null +++ b/src/onepin/types/workflow_run_data_dropped_verdict_out.py @@ -0,0 +1,32 @@ +# 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 WorkflowRunDataDroppedVerdictOut(UniversalBaseModel): + """ + One failing validator's verdict on a dropped take. + + A take can fail several parallel validators at once; ``validator_node_id`` + disambiguates two validators of the same kind (e.g. two WER nodes with + different thresholds). ``threshold`` is the pass bar that actually gated + the line (schema defaults resolved); null only for invalid snapshots. + """ + + validator_node_id: str + validator_kind: str + validator_label: str + score: typing.Optional[float] = None + threshold: typing.Optional[float] = None + + 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_data_out.py b/src/onepin/types/workflow_run_data_out.py index 0af36ff..7b22f18 100644 --- a/src/onepin/types/workflow_run_data_out.py +++ b/src/onepin/types/workflow_run_data_out.py @@ -14,6 +14,7 @@ class WorkflowRunDataOut(UniversalBaseModel): run_status: str rows: typing.Optional[typing.List[WorkflowRunDataRowOut]] = None partial: WorkflowRunDataPartialOut + dropped_truncated: typing.Optional[bool] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/onepin/types/workflow_run_data_rejected_out.py b/src/onepin/types/workflow_run_data_rejected_out.py new file mode 100644 index 0000000..c9ef385 --- /dev/null +++ b/src/onepin/types/workflow_run_data_rejected_out.py @@ -0,0 +1,24 @@ +# 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_data_dropped_verdict_out import WorkflowRunDataDroppedVerdictOut + + +class WorkflowRunDataRejectedOut(UniversalBaseModel): + """ + Per-take validator failures, independent of delivery disposition. + """ + + verdicts: typing.Optional[typing.List[WorkflowRunDataDroppedVerdictOut]] = None + + 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_overview_metric_annotation.py b/src/onepin/types/workflow_run_overview_metric_annotation.py new file mode 100644 index 0000000..79f2601 --- /dev/null +++ b/src/onepin/types/workflow_run_overview_metric_annotation.py @@ -0,0 +1,24 @@ +# 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 WorkflowRunOverviewMetricAnnotation(UniversalBaseModel): + """ + Small subtext under a metric value (e.g. `output_lines` → "2 dropped"). + """ + + text: str + emphasis: typing.Optional[str] = None + + 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_overview_metric_out.py b/src/onepin/types/workflow_run_overview_metric_out.py index 737df05..a2e7b73 100644 --- a/src/onepin/types/workflow_run_overview_metric_out.py +++ b/src/onepin/types/workflow_run_overview_metric_out.py @@ -4,6 +4,7 @@ import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .workflow_run_overview_metric_annotation import WorkflowRunOverviewMetricAnnotation from .workflow_run_overview_metric_display import WorkflowRunOverviewMetricDisplay from .workflow_run_overview_metric_out_status import WorkflowRunOverviewMetricOutStatus from .workflow_run_overview_metric_out_value import WorkflowRunOverviewMetricOutValue @@ -18,6 +19,7 @@ class WorkflowRunOverviewMetricOut(UniversalBaseModel): status: WorkflowRunOverviewMetricOutStatus reason: typing.Optional[str] = None display: WorkflowRunOverviewMetricDisplay + annotation: typing.Optional[WorkflowRunOverviewMetricAnnotation] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/onepin/types/workflow_run_step_out.py b/src/onepin/types/workflow_run_step_out.py index 14da64c..19593a3 100644 --- a/src/onepin/types/workflow_run_step_out.py +++ b/src/onepin/types/workflow_run_step_out.py @@ -17,6 +17,8 @@ class WorkflowRunStepOut(UniversalBaseModel): started_at: typing.Optional[dt.datetime] = None completed_at: typing.Optional[dt.datetime] = None result: typing.Optional[typing.Dict[str, typing.Any]] = None + has_result: typing.Optional[bool] = None + active_ports: typing.Optional[typing.List[str]] = None error: typing.Optional[str] = None if IS_PYDANTIC_V2: diff --git a/src/onepin/uploads/client.py b/src/onepin/uploads/client.py index ca8c311..d0a06a0 100644 --- a/src/onepin/uploads/client.py +++ b/src/onepin/uploads/client.py @@ -133,7 +133,7 @@ def confirm( upload_id : str context_type : UploadConfirmRequestContextType - Type of resource this upload is being attached to: `workflow` or `playground`. + Type of resource this upload is being attached to: `workflow`, `playground`, or `assistant_session`. context_id : str ID of the resource to attach this upload to. Must be an existing resource of the given `context_type` that the caller has access to. @@ -349,7 +349,7 @@ async def confirm( upload_id : str context_type : UploadConfirmRequestContextType - Type of resource this upload is being attached to: `workflow` or `playground`. + Type of resource this upload is being attached to: `workflow`, `playground`, or `assistant_session`. context_id : str ID of the resource to attach this upload to. Must be an existing resource of the given `context_type` that the caller has access to. diff --git a/src/onepin/uploads/raw_client.py b/src/onepin/uploads/raw_client.py index 01b6a6a..0bc4135 100644 --- a/src/onepin/uploads/raw_client.py +++ b/src/onepin/uploads/raw_client.py @@ -156,7 +156,7 @@ def confirm( upload_id : str context_type : UploadConfirmRequestContextType - Type of resource this upload is being attached to: `workflow` or `playground`. + Type of resource this upload is being attached to: `workflow`, `playground`, or `assistant_session`. context_id : str ID of the resource to attach this upload to. Must be an existing resource of the given `context_type` that the caller has access to. @@ -426,7 +426,7 @@ async def confirm( upload_id : str context_type : UploadConfirmRequestContextType - Type of resource this upload is being attached to: `workflow` or `playground`. + Type of resource this upload is being attached to: `workflow`, `playground`, or `assistant_session`. context_id : str ID of the resource to attach this upload to. Must be an existing resource of the given `context_type` that the caller has access to. diff --git a/src/onepin/uploads/types/upload_confirm_request_context_type.py b/src/onepin/uploads/types/upload_confirm_request_context_type.py index 182e6ce..c0fb534 100644 --- a/src/onepin/uploads/types/upload_confirm_request_context_type.py +++ b/src/onepin/uploads/types/upload_confirm_request_context_type.py @@ -2,4 +2,6 @@ import typing -UploadConfirmRequestContextType = typing.Union[typing.Literal["workflow", "playground"], typing.Any] +UploadConfirmRequestContextType = typing.Union[ + typing.Literal["workflow", "playground", "assistant_session"], typing.Any +] diff --git a/src/onepin/usage/client.py b/src/onepin/usage/client.py index ee636b5..7d217fd 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_v1_usage_activity_get_request_range import UsageActivityApiV1UsageActivityGetRequestRange -from .types.usage_by_language_api_v1_usage_by_language_get_request_activity_view import ( +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 ( UsageByLanguageApiV1UsageByLanguageGetRequestActivityView, ) -from .types.usage_by_language_api_v1_usage_by_language_get_request_range import ( +from .types.usage_by_language_api_v1usage_by_language_get_request_range import ( UsageByLanguageApiV1UsageByLanguageGetRequestRange, ) -from .types.usage_summary_api_v1_usage_summary_get_request_activity_view import ( +from .types.usage_summary_api_v1usage_summary_get_request_activity_view import ( UsageSummaryApiV1UsageSummaryGetRequestActivityView, ) -from .types.usage_summary_api_v1_usage_summary_get_request_range import UsageSummaryApiV1UsageSummaryGetRequestRange +from .types.usage_summary_api_v1usage_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 fe0832e..009698b 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_v1_usage_activity_get_request_range import UsageActivityApiV1UsageActivityGetRequestRange -from .types.usage_by_language_api_v1_usage_by_language_get_request_activity_view import ( +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 ( UsageByLanguageApiV1UsageByLanguageGetRequestActivityView, ) -from .types.usage_by_language_api_v1_usage_by_language_get_request_range import ( +from .types.usage_by_language_api_v1usage_by_language_get_request_range import ( UsageByLanguageApiV1UsageByLanguageGetRequestRange, ) -from .types.usage_summary_api_v1_usage_summary_get_request_activity_view import ( +from .types.usage_summary_api_v1usage_summary_get_request_activity_view import ( UsageSummaryApiV1UsageSummaryGetRequestActivityView, ) -from .types.usage_summary_api_v1_usage_summary_get_request_range import UsageSummaryApiV1UsageSummaryGetRequestRange +from .types.usage_summary_api_v1usage_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 000f50b..53281f8 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_v1_usage_activity_get_request_range import UsageActivityApiV1UsageActivityGetRequestRange - from .usage_by_language_api_v1_usage_by_language_get_request_activity_view import ( + from .usage_activity_api_v1usage_activity_get_request_range import UsageActivityApiV1UsageActivityGetRequestRange + from .usage_by_language_api_v1usage_by_language_get_request_activity_view import ( UsageByLanguageApiV1UsageByLanguageGetRequestActivityView, ) - from .usage_by_language_api_v1_usage_by_language_get_request_range import ( + from .usage_by_language_api_v1usage_by_language_get_request_range import ( UsageByLanguageApiV1UsageByLanguageGetRequestRange, ) - from .usage_summary_api_v1_usage_summary_get_request_activity_view import ( + from .usage_summary_api_v1usage_summary_get_request_activity_view import ( UsageSummaryApiV1UsageSummaryGetRequestActivityView, ) - from .usage_summary_api_v1_usage_summary_get_request_range import UsageSummaryApiV1UsageSummaryGetRequestRange + from .usage_summary_api_v1usage_summary_get_request_range import UsageSummaryApiV1UsageSummaryGetRequestRange _dynamic_imports: typing.Dict[str, str] = { - "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", + "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", } diff --git a/src/onepin/usage/types/usage_activity_api_v1_usage_activity_get_request_range.py b/src/onepin/usage/types/usage_activity_api_v1usage_activity_get_request_range.py similarity index 100% rename from src/onepin/usage/types/usage_activity_api_v1_usage_activity_get_request_range.py rename to src/onepin/usage/types/usage_activity_api_v1usage_activity_get_request_range.py diff --git a/src/onepin/usage/types/usage_by_language_api_v1_usage_by_language_get_request_activity_view.py b/src/onepin/usage/types/usage_by_language_api_v1usage_by_language_get_request_activity_view.py similarity index 100% rename from src/onepin/usage/types/usage_by_language_api_v1_usage_by_language_get_request_activity_view.py rename to src/onepin/usage/types/usage_by_language_api_v1usage_by_language_get_request_activity_view.py diff --git a/src/onepin/usage/types/usage_by_language_api_v1_usage_by_language_get_request_range.py b/src/onepin/usage/types/usage_by_language_api_v1usage_by_language_get_request_range.py similarity index 100% rename from src/onepin/usage/types/usage_by_language_api_v1_usage_by_language_get_request_range.py rename to src/onepin/usage/types/usage_by_language_api_v1usage_by_language_get_request_range.py diff --git a/src/onepin/usage/types/usage_summary_api_v1_usage_summary_get_request_activity_view.py b/src/onepin/usage/types/usage_summary_api_v1usage_summary_get_request_activity_view.py similarity index 100% rename from src/onepin/usage/types/usage_summary_api_v1_usage_summary_get_request_activity_view.py rename to src/onepin/usage/types/usage_summary_api_v1usage_summary_get_request_activity_view.py diff --git a/src/onepin/usage/types/usage_summary_api_v1_usage_summary_get_request_range.py b/src/onepin/usage/types/usage_summary_api_v1usage_summary_get_request_range.py similarity index 100% rename from src/onepin/usage/types/usage_summary_api_v1_usage_summary_get_request_range.py rename to src/onepin/usage/types/usage_summary_api_v1usage_summary_get_request_range.py diff --git a/src/onepin/users/client.py b/src/onepin/users/client.py index 488560b..4de6674 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_v1_users_me_templates_get_request_sort import ( +from .types.list_my_templates_api_v1users_me_templates_get_request_sort import ( ListMyTemplatesApiV1UsersMeTemplatesGetRequestSort, ) diff --git a/src/onepin/users/raw_client.py b/src/onepin/users/raw_client.py index 723eb45..6da6376 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_v1_users_me_templates_get_request_sort import ( +from .types.list_my_templates_api_v1users_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 a08a5f6..f7f5157 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_v1_users_me_templates_get_request_sort import ( + from .list_my_templates_api_v1users_me_templates_get_request_sort import ( ListMyTemplatesApiV1UsersMeTemplatesGetRequestSort, ) _dynamic_imports: typing.Dict[str, str] = { - "ListMyTemplatesApiV1UsersMeTemplatesGetRequestSort": ".list_my_templates_api_v1_users_me_templates_get_request_sort" + "ListMyTemplatesApiV1UsersMeTemplatesGetRequestSort": ".list_my_templates_api_v1users_me_templates_get_request_sort" } diff --git a/src/onepin/users/types/list_my_templates_api_v1_users_me_templates_get_request_sort.py b/src/onepin/users/types/list_my_templates_api_v1users_me_templates_get_request_sort.py similarity index 100% rename from src/onepin/users/types/list_my_templates_api_v1_users_me_templates_get_request_sort.py rename to src/onepin/users/types/list_my_templates_api_v1users_me_templates_get_request_sort.py diff --git a/src/onepin/voices/client.py b/src/onepin/voices/client.py index ed265d3..36cfe30 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_v1_voices_facets_get_request_source_item import ( +from .types.get_voice_facets_api_v1voices_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 7cab1e1..ce39276 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_v1_voices_facets_get_request_source_item import ( +from .types.get_voice_facets_api_v1voices_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 b1c9803..3c4972a 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_v1_voices_facets_get_request_source_item import ( + from .get_voice_facets_api_v1voices_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_v1_voices_facets_get_request_source_item", + "GetVoiceFacetsApiV1VoicesFacetsGetRequestSourceItem": ".get_voice_facets_api_v1voices_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_v1_voices_facets_get_request_source_item.py b/src/onepin/voices/types/get_voice_facets_api_v1voices_facets_get_request_source_item.py similarity index 100% rename from src/onepin/voices/types/get_voice_facets_api_v1_voices_facets_get_request_source_item.py rename to src/onepin/voices/types/get_voice_facets_api_v1voices_facets_get_request_source_item.py diff --git a/src/onepin/workflows/client.py b/src/onepin/workflows/client.py index 876fdb8..6343c95 100644 --- a/src/onepin/workflows/client.py +++ b/src/onepin/workflows/client.py @@ -12,7 +12,6 @@ from ..types.api_response_dict import ApiResponseDict from ..types.api_response_download_url_out import ApiResponseDownloadUrlOut from ..types.api_response_estimate_response import ApiResponseEstimateResponse -from ..types.api_response_list_workflow_run_step_out import ApiResponseListWorkflowRunStepOut from ..types.api_response_runs_summary_out import ApiResponseRunsSummaryOut from ..types.api_response_workflow_name_availability_out import ApiResponseWorkflowNameAvailabilityOut from ..types.api_response_workflow_out import ApiResponseWorkflowOut @@ -705,66 +704,6 @@ def runs_summary( ) return _response.data - def get_run_steps( - self, - workflow_id: str, - run_id: str, - *, - workspace_id: typing.Optional[str] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> ApiResponseListWorkflowRunStepOut: - """ - List per-node execution steps for a workflow run. - - Returns one entry per node execution attempt, ordered by execution sequence. - Each step includes the node type, status, iteration number (for nodes that - are retried), start/completion timestamps, and the node's `result` output. - - For audio output nodes, `result` is hydrated with short-lived `playback_url` - 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. 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 - script+audio rows suitable for a data table, use `GET /runs/{run_id}/data`. - - Parameters - ---------- - workflow_id : str - - run_id : str - - workspace_id : typing.Optional[str] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ApiResponseListWorkflowRunStepOut - Successful Response - - Examples - -------- - from onepin import OnePinClient - - client = OnePinClient( - token="YOUR_TOKEN", - ) - client.workflows.get_run_steps( - workflow_id="workflow_id", - run_id="run_id", - ) - """ - _response = self._raw_client.get_run_steps( - workflow_id, run_id, workspace_id=workspace_id, request_options=request_options - ) - return _response.data - def get_run_outputs( self, workflow_id: str, @@ -840,7 +779,8 @@ def get_run_overview( - `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}/steps` — lightweight per-node step log by default; + `include_result=true` includes results and 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 @@ -886,6 +826,7 @@ def get_run_data( *, search: typing.Optional[str] = None, language: typing.Optional[str] = None, + include_dropped: typing.Optional[bool] = None, offset: typing.Optional[int] = None, limit: typing.Optional[int] = None, workspace_id: typing.Optional[str] = None, @@ -905,6 +846,8 @@ def get_run_data( locale. Rows with no matching cards are still returned (with empty `cards`), and `pagination.total` always reflects the search-filtered row count regardless of `language`. + - `include_dropped=true` adds rejected attempts to `cards` with + `status="dropped"`; the default response remains delivered/generated data only. **Pagination:** `pagination.total` is scoped to the `search` filter only. @@ -925,6 +868,9 @@ def get_run_data( language : typing.Optional[str] Exact full-locale code to filter cards within each row (e.g. `en-US`). `_` is normalized to `-`. Filtering is card-level only — rows remain visible even when all their cards are filtered out, and `pagination.total` is unaffected. + include_dropped : typing.Optional[bool] + Include validator-rejected audio cards reconstructed from unwired fail ports. Defaults to false so existing clients continue receiving delivered output only. + offset : typing.Optional[int] Zero-based pagination offset. @@ -958,6 +904,7 @@ def get_run_data( run_id, search=search, language=language, + include_dropped=include_dropped, offset=offset, limit=limit, workspace_id=workspace_id, @@ -1022,6 +969,61 @@ def download_run( ) return _response.data + def get_run_audio_url( + self, + workflow_id: str, + run_id: str, + audio_id: str, + *, + workspace_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ApiResponseDownloadUrlOut: + """ + Mint a fresh playback URL for one audio output of a run. + + `audio_id` is the stable 16-hex output identifier embedded in run-data + card ids and carried by assistant chat `audio` parts. Presigned playback + URLs expire after 15 minutes; call this endpoint at play time to refresh + the URL by id instead of caching it or re-fetching a whole run-data page. + + Returns 404 when the run has no s3-backed audio output with this id. + + Parameters + ---------- + workflow_id : str + + run_id : str + + audio_id : str + + workspace_id : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ApiResponseDownloadUrlOut + Successful Response + + Examples + -------- + from onepin import OnePinClient + + client = OnePinClient( + token="YOUR_TOKEN", + ) + client.workflows.get_run_audio_url( + workflow_id="workflow_id", + run_id="run_id", + audio_id="audio_id", + ) + """ + _response = self._raw_client.get_run_audio_url( + workflow_id, run_id, audio_id, workspace_id=workspace_id, request_options=request_options + ) + return _response.data + def download_run_node( self, workflow_id: str, @@ -2006,74 +2008,6 @@ async def main() -> None: ) return _response.data - async def get_run_steps( - self, - workflow_id: str, - run_id: str, - *, - workspace_id: typing.Optional[str] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> ApiResponseListWorkflowRunStepOut: - """ - List per-node execution steps for a workflow run. - - Returns one entry per node execution attempt, ordered by execution sequence. - Each step includes the node type, status, iteration number (for nodes that - are retried), start/completion timestamps, and the node's `result` output. - - For audio output nodes, `result` is hydrated with short-lived `playback_url` - 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. 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 - script+audio rows suitable for a data table, use `GET /runs/{run_id}/data`. - - Parameters - ---------- - workflow_id : str - - run_id : str - - workspace_id : typing.Optional[str] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - ApiResponseListWorkflowRunStepOut - Successful Response - - Examples - -------- - import asyncio - - from onepin import AsyncOnePinClient - - client = AsyncOnePinClient( - token="YOUR_TOKEN", - ) - - - async def main() -> None: - await client.workflows.get_run_steps( - workflow_id="workflow_id", - run_id="run_id", - ) - - - asyncio.run(main()) - """ - _response = await self._raw_client.get_run_steps( - workflow_id, run_id, workspace_id=workspace_id, request_options=request_options - ) - return _response.data - async def get_run_outputs( self, workflow_id: str, @@ -2157,7 +2091,8 @@ async def get_run_overview( - `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}/steps` — lightweight per-node step log by default; + `include_result=true` includes results and 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 @@ -2211,6 +2146,7 @@ async def get_run_data( *, search: typing.Optional[str] = None, language: typing.Optional[str] = None, + include_dropped: typing.Optional[bool] = None, offset: typing.Optional[int] = None, limit: typing.Optional[int] = None, workspace_id: typing.Optional[str] = None, @@ -2230,6 +2166,8 @@ async def get_run_data( locale. Rows with no matching cards are still returned (with empty `cards`), and `pagination.total` always reflects the search-filtered row count regardless of `language`. + - `include_dropped=true` adds rejected attempts to `cards` with + `status="dropped"`; the default response remains delivered/generated data only. **Pagination:** `pagination.total` is scoped to the `search` filter only. @@ -2250,6 +2188,9 @@ async def get_run_data( language : typing.Optional[str] Exact full-locale code to filter cards within each row (e.g. `en-US`). `_` is normalized to `-`. Filtering is card-level only — rows remain visible even when all their cards are filtered out, and `pagination.total` is unaffected. + include_dropped : typing.Optional[bool] + Include validator-rejected audio cards reconstructed from unwired fail ports. Defaults to false so existing clients continue receiving delivered output only. + offset : typing.Optional[int] Zero-based pagination offset. @@ -2291,6 +2232,7 @@ async def main() -> None: run_id, search=search, language=language, + include_dropped=include_dropped, offset=offset, limit=limit, workspace_id=workspace_id, @@ -2363,6 +2305,69 @@ async def main() -> None: ) return _response.data + async def get_run_audio_url( + self, + workflow_id: str, + run_id: str, + audio_id: str, + *, + workspace_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ApiResponseDownloadUrlOut: + """ + Mint a fresh playback URL for one audio output of a run. + + `audio_id` is the stable 16-hex output identifier embedded in run-data + card ids and carried by assistant chat `audio` parts. Presigned playback + URLs expire after 15 minutes; call this endpoint at play time to refresh + the URL by id instead of caching it or re-fetching a whole run-data page. + + Returns 404 when the run has no s3-backed audio output with this id. + + Parameters + ---------- + workflow_id : str + + run_id : str + + audio_id : str + + workspace_id : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ApiResponseDownloadUrlOut + Successful Response + + Examples + -------- + import asyncio + + from onepin import AsyncOnePinClient + + client = AsyncOnePinClient( + token="YOUR_TOKEN", + ) + + + async def main() -> None: + await client.workflows.get_run_audio_url( + workflow_id="workflow_id", + run_id="run_id", + audio_id="audio_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_run_audio_url( + workflow_id, run_id, audio_id, workspace_id=workspace_id, request_options=request_options + ) + return _response.data + async def download_run_node( self, workflow_id: str, diff --git a/src/onepin/workflows/raw_client.py b/src/onepin/workflows/raw_client.py index 22b75ba..376fade 100644 --- a/src/onepin/workflows/raw_client.py +++ b/src/onepin/workflows/raw_client.py @@ -21,7 +21,6 @@ from ..types.api_response_dict import ApiResponseDict from ..types.api_response_download_url_out import ApiResponseDownloadUrlOut from ..types.api_response_estimate_response import ApiResponseEstimateResponse -from ..types.api_response_list_workflow_run_step_out import ApiResponseListWorkflowRunStepOut from ..types.api_response_runs_summary_out import ApiResponseRunsSummaryOut from ..types.api_response_workflow_name_availability_out import ApiResponseWorkflowNameAvailabilityOut from ..types.api_response_workflow_out import ApiResponseWorkflowOut @@ -969,87 +968,6 @@ def runs_summary( ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - def get_run_steps( - self, - workflow_id: str, - run_id: str, - *, - workspace_id: typing.Optional[str] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ApiResponseListWorkflowRunStepOut]: - """ - List per-node execution steps for a workflow run. - - Returns one entry per node execution attempt, ordered by execution sequence. - Each step includes the node type, status, iteration number (for nodes that - are retried), start/completion timestamps, and the node's `result` output. - - For audio output nodes, `result` is hydrated with short-lived `playback_url` - 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. 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 - script+audio rows suitable for a data table, use `GET /runs/{run_id}/data`. - - Parameters - ---------- - workflow_id : str - - run_id : str - - workspace_id : typing.Optional[str] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - HttpResponse[ApiResponseListWorkflowRunStepOut] - Successful Response - """ - _response = self._client_wrapper.httpx_client.request( - f"api/v1/workflows/{encode_path_param(workflow_id)}/runs/{encode_path_param(run_id)}/steps", - 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( - ApiResponseListWorkflowRunStepOut, - parse_obj_as( - type_=ApiResponseListWorkflowRunStepOut, # 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_outputs( self, workflow_id: str, @@ -1146,7 +1064,8 @@ def get_run_overview( - `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}/steps` — lightweight per-node step log by default; + `include_result=true` includes results and 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 @@ -1213,6 +1132,7 @@ def get_run_data( *, search: typing.Optional[str] = None, language: typing.Optional[str] = None, + include_dropped: typing.Optional[bool] = None, offset: typing.Optional[int] = None, limit: typing.Optional[int] = None, workspace_id: typing.Optional[str] = None, @@ -1232,6 +1152,8 @@ def get_run_data( locale. Rows with no matching cards are still returned (with empty `cards`), and `pagination.total` always reflects the search-filtered row count regardless of `language`. + - `include_dropped=true` adds rejected attempts to `cards` with + `status="dropped"`; the default response remains delivered/generated data only. **Pagination:** `pagination.total` is scoped to the `search` filter only. @@ -1252,6 +1174,9 @@ def get_run_data( language : typing.Optional[str] Exact full-locale code to filter cards within each row (e.g. `en-US`). `_` is normalized to `-`. Filtering is card-level only — rows remain visible even when all their cards are filtered out, and `pagination.total` is unaffected. + include_dropped : typing.Optional[bool] + Include validator-rejected audio cards reconstructed from unwired fail ports. Defaults to false so existing clients continue receiving delivered output only. + offset : typing.Optional[int] Zero-based pagination offset. @@ -1274,6 +1199,7 @@ def get_run_data( params={ "search": search, "language": language, + "include_dropped": include_dropped, "offset": offset, "limit": limit, }, @@ -1412,6 +1338,92 @@ def download_run( ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + def get_run_audio_url( + self, + workflow_id: str, + run_id: str, + audio_id: str, + *, + workspace_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ApiResponseDownloadUrlOut]: + """ + Mint a fresh playback URL for one audio output of a run. + + `audio_id` is the stable 16-hex output identifier embedded in run-data + card ids and carried by assistant chat `audio` parts. Presigned playback + URLs expire after 15 minutes; call this endpoint at play time to refresh + the URL by id instead of caching it or re-fetching a whole run-data page. + + Returns 404 when the run has no s3-backed audio output with this id. + + Parameters + ---------- + workflow_id : str + + run_id : str + + audio_id : str + + workspace_id : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ApiResponseDownloadUrlOut] + Successful Response + """ + _response = self._client_wrapper.httpx_client.request( + f"api/v1/workflows/{encode_path_param(workflow_id)}/runs/{encode_path_param(run_id)}/audio/{encode_path_param(audio_id)}/url", + 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( + ApiResponseDownloadUrlOut, + parse_obj_as( + type_=ApiResponseDownloadUrlOut, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + 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 download_run_node( self, workflow_id: str, @@ -2663,87 +2675,6 @@ async def runs_summary( ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - async def get_run_steps( - self, - workflow_id: str, - run_id: str, - *, - workspace_id: typing.Optional[str] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ApiResponseListWorkflowRunStepOut]: - """ - List per-node execution steps for a workflow run. - - Returns one entry per node execution attempt, ordered by execution sequence. - Each step includes the node type, status, iteration number (for nodes that - are retried), start/completion timestamps, and the node's `result` output. - - For audio output nodes, `result` is hydrated with short-lived `playback_url` - 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. 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 - script+audio rows suitable for a data table, use `GET /runs/{run_id}/data`. - - Parameters - ---------- - workflow_id : str - - run_id : str - - workspace_id : typing.Optional[str] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AsyncHttpResponse[ApiResponseListWorkflowRunStepOut] - 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)}/steps", - 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( - ApiResponseListWorkflowRunStepOut, - parse_obj_as( - type_=ApiResponseListWorkflowRunStepOut, # 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_outputs( self, workflow_id: str, @@ -2840,7 +2771,8 @@ async def get_run_overview( - `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}/steps` — lightweight per-node step log by default; + `include_result=true` includes results and 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 @@ -2907,6 +2839,7 @@ async def get_run_data( *, search: typing.Optional[str] = None, language: typing.Optional[str] = None, + include_dropped: typing.Optional[bool] = None, offset: typing.Optional[int] = None, limit: typing.Optional[int] = None, workspace_id: typing.Optional[str] = None, @@ -2926,6 +2859,8 @@ async def get_run_data( locale. Rows with no matching cards are still returned (with empty `cards`), and `pagination.total` always reflects the search-filtered row count regardless of `language`. + - `include_dropped=true` adds rejected attempts to `cards` with + `status="dropped"`; the default response remains delivered/generated data only. **Pagination:** `pagination.total` is scoped to the `search` filter only. @@ -2946,6 +2881,9 @@ async def get_run_data( language : typing.Optional[str] Exact full-locale code to filter cards within each row (e.g. `en-US`). `_` is normalized to `-`. Filtering is card-level only — rows remain visible even when all their cards are filtered out, and `pagination.total` is unaffected. + include_dropped : typing.Optional[bool] + Include validator-rejected audio cards reconstructed from unwired fail ports. Defaults to false so existing clients continue receiving delivered output only. + offset : typing.Optional[int] Zero-based pagination offset. @@ -2968,6 +2906,7 @@ async def get_run_data( params={ "search": search, "language": language, + "include_dropped": include_dropped, "offset": offset, "limit": limit, }, @@ -3106,6 +3045,92 @@ async def download_run( ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + async def get_run_audio_url( + self, + workflow_id: str, + run_id: str, + audio_id: str, + *, + workspace_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ApiResponseDownloadUrlOut]: + """ + Mint a fresh playback URL for one audio output of a run. + + `audio_id` is the stable 16-hex output identifier embedded in run-data + card ids and carried by assistant chat `audio` parts. Presigned playback + URLs expire after 15 minutes; call this endpoint at play time to refresh + the URL by id instead of caching it or re-fetching a whole run-data page. + + Returns 404 when the run has no s3-backed audio output with this id. + + Parameters + ---------- + workflow_id : str + + run_id : str + + audio_id : str + + workspace_id : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ApiResponseDownloadUrlOut] + 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)}/audio/{encode_path_param(audio_id)}/url", + 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( + ApiResponseDownloadUrlOut, + parse_obj_as( + type_=ApiResponseDownloadUrlOut, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + 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 download_run_node( self, workflow_id: str, diff --git a/src/onepin/workflows/runs/client.py b/src/onepin/workflows/runs/client.py index 4e36b4f..fe403b1 100644 --- a/src/onepin/workflows/runs/client.py +++ b/src/onepin/workflows/runs/client.py @@ -5,9 +5,11 @@ from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions from ...types.api_counted_list_response_workflow_run_list_item import ApiCountedListResponseWorkflowRunListItem +from ...types.api_response_list_workflow_run_step_out import ApiResponseListWorkflowRunStepOut from ...types.api_response_workflow_run_detail_out import ApiResponseWorkflowRunDetailOut from ...types.api_response_workflow_run_out import ApiResponseWorkflowRunOut from ...types.api_response_workflow_run_status_out import ApiResponseWorkflowRunStatusOut +from ...types.node_type import NodeType from ...types.workflow_run_start_in import WorkflowRunStartIn from .raw_client import AsyncRawRunsClient, RawRunsClient from .types.list_runs_request_order import ListRunsRequestOrder @@ -201,7 +203,8 @@ def get( This is the heaviest run endpoint. For progress polling, use the lighter `GET /runs/{run_id}/status` which omits the snapshot. For aggregated visual metrics, use `GET /runs/{run_id}/overview`. For the per-node step - log with audio playback URLs, use `GET /runs/{run_id}/steps`. + log, use `GET /runs/{run_id}/steps`; opt into full results and audio + playback URLs with `include_result=true`. Parameters ---------- @@ -296,6 +299,85 @@ def status( ) return _response.data + def steps( + self, + workflow_id: str, + run_id: str, + *, + include_result: typing.Optional[bool] = None, + node_type: typing.Optional[NodeType] = None, + node_id: typing.Optional[str] = None, + workspace_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ApiResponseListWorkflowRunStepOut: + """ + List per-node execution steps for a workflow run. + + Returns one entry per node execution attempt, ordered by execution sequence. + By default, the response is lightweight: `result` is null, `has_result` + reports whether a stored result exists, and `active_ports` is projected from + the result without loading the full JSON payload. + + Set `include_result=true` to restore the full result payload. Audio results + are then hydrated with short-lived `playback_url` values (valid for 15 + minutes). `node_type` and `node_id` filters combine with AND semantics. + + `node_display_name` is resolved from the run's definition snapshot, so it + 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 + script+audio rows suitable for a data table, use `GET /runs/{run_id}/data`. + + Parameters + ---------- + workflow_id : str + + run_id : str + + include_result : typing.Optional[bool] + Include the full step result payload and hydrate audio playback URLs. + + node_type : typing.Optional[NodeType] + Filter steps by node type. + + node_id : typing.Optional[str] + Filter steps by node ID. + + workspace_id : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ApiResponseListWorkflowRunStepOut + Successful Response + + Examples + -------- + from onepin import OnePinClient + + client = OnePinClient( + token="YOUR_TOKEN", + ) + client.workflows.runs.steps( + workflow_id="workflow_id", + run_id="run_id", + ) + """ + _response = self._raw_client.steps( + workflow_id, + run_id, + include_result=include_result, + node_type=node_type, + node_id=node_id, + workspace_id=workspace_id, + request_options=request_options, + ) + return _response.data + def cancel( self, workflow_id: str, @@ -312,9 +394,9 @@ def cancel( operation is idempotent: cancelling an already-cancelled run returns the run unchanged without error. - Only runs in `pending`, `running`, or `paused` status can be cancelled. - Runs that have already reached a terminal state (`completed`, `failed`, - `cancelled`) return 409. + Runs already in a terminal state (`completed`, `failed`, or `cancelled`) + are returned unchanged. Concurrent terminalization is also treated as an + idempotent success; a still-active compare-and-swap loser returns 409. Unlike `pause`, cancel is permanent — a cancelled run cannot be resumed. Use `pause` if you intend to continue the run later. @@ -553,7 +635,8 @@ async def get( This is the heaviest run endpoint. For progress polling, use the lighter `GET /runs/{run_id}/status` which omits the snapshot. For aggregated visual metrics, use `GET /runs/{run_id}/overview`. For the per-node step - log with audio playback URLs, use `GET /runs/{run_id}/steps`. + log, use `GET /runs/{run_id}/steps`; opt into full results and audio + playback URLs with `include_result=true`. Parameters ---------- @@ -664,6 +747,93 @@ async def main() -> None: ) return _response.data + async def steps( + self, + workflow_id: str, + run_id: str, + *, + include_result: typing.Optional[bool] = None, + node_type: typing.Optional[NodeType] = None, + node_id: typing.Optional[str] = None, + workspace_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ApiResponseListWorkflowRunStepOut: + """ + List per-node execution steps for a workflow run. + + Returns one entry per node execution attempt, ordered by execution sequence. + By default, the response is lightweight: `result` is null, `has_result` + reports whether a stored result exists, and `active_ports` is projected from + the result without loading the full JSON payload. + + Set `include_result=true` to restore the full result payload. Audio results + are then hydrated with short-lived `playback_url` values (valid for 15 + minutes). `node_type` and `node_id` filters combine with AND semantics. + + `node_display_name` is resolved from the run's definition snapshot, so it + 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 + script+audio rows suitable for a data table, use `GET /runs/{run_id}/data`. + + Parameters + ---------- + workflow_id : str + + run_id : str + + include_result : typing.Optional[bool] + Include the full step result payload and hydrate audio playback URLs. + + node_type : typing.Optional[NodeType] + Filter steps by node type. + + node_id : typing.Optional[str] + Filter steps by node ID. + + workspace_id : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ApiResponseListWorkflowRunStepOut + Successful Response + + Examples + -------- + import asyncio + + from onepin import AsyncOnePinClient + + client = AsyncOnePinClient( + token="YOUR_TOKEN", + ) + + + async def main() -> None: + await client.workflows.runs.steps( + workflow_id="workflow_id", + run_id="run_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.steps( + workflow_id, + run_id, + include_result=include_result, + node_type=node_type, + node_id=node_id, + workspace_id=workspace_id, + request_options=request_options, + ) + return _response.data + async def cancel( self, workflow_id: str, @@ -680,9 +850,9 @@ async def cancel( operation is idempotent: cancelling an already-cancelled run returns the run unchanged without error. - Only runs in `pending`, `running`, or `paused` status can be cancelled. - Runs that have already reached a terminal state (`completed`, `failed`, - `cancelled`) return 409. + Runs already in a terminal state (`completed`, `failed`, or `cancelled`) + are returned unchanged. Concurrent terminalization is also treated as an + idempotent success; a still-active compare-and-swap loser returns 409. Unlike `pause`, cancel is permanent — a cancelled run cannot be resumed. Use `pause` if you intend to continue the run later. diff --git a/src/onepin/workflows/runs/raw_client.py b/src/onepin/workflows/runs/raw_client.py index b848485..aed4559 100644 --- a/src/onepin/workflows/runs/raw_client.py +++ b/src/onepin/workflows/runs/raw_client.py @@ -13,9 +13,11 @@ from ...core.serialization import convert_and_respect_annotation_metadata from ...errors.unprocessable_entity_error import UnprocessableEntityError from ...types.api_counted_list_response_workflow_run_list_item import ApiCountedListResponseWorkflowRunListItem +from ...types.api_response_list_workflow_run_step_out import ApiResponseListWorkflowRunStepOut from ...types.api_response_workflow_run_detail_out import ApiResponseWorkflowRunDetailOut from ...types.api_response_workflow_run_out import ApiResponseWorkflowRunOut from ...types.api_response_workflow_run_status_out import ApiResponseWorkflowRunStatusOut +from ...types.node_type import NodeType from ...types.workflow_run_start_in import WorkflowRunStartIn from .types.list_runs_request_order import ListRunsRequestOrder from .types.list_runs_request_sort import ListRunsRequestSort @@ -246,7 +248,8 @@ def get( This is the heaviest run endpoint. For progress polling, use the lighter `GET /runs/{run_id}/status` which omits the snapshot. For aggregated visual metrics, use `GET /runs/{run_id}/overview`. For the per-node step - log with audio playback URLs, use `GET /runs/{run_id}/steps`. + log, use `GET /runs/{run_id}/steps`; opt into full results and audio + playback URLs with `include_result=true`. Parameters ---------- @@ -383,6 +386,105 @@ def status( ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + def steps( + self, + workflow_id: str, + run_id: str, + *, + include_result: typing.Optional[bool] = None, + node_type: typing.Optional[NodeType] = None, + node_id: typing.Optional[str] = None, + workspace_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ApiResponseListWorkflowRunStepOut]: + """ + List per-node execution steps for a workflow run. + + Returns one entry per node execution attempt, ordered by execution sequence. + By default, the response is lightweight: `result` is null, `has_result` + reports whether a stored result exists, and `active_ports` is projected from + the result without loading the full JSON payload. + + Set `include_result=true` to restore the full result payload. Audio results + are then hydrated with short-lived `playback_url` values (valid for 15 + minutes). `node_type` and `node_id` filters combine with AND semantics. + + `node_display_name` is resolved from the run's definition snapshot, so it + 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 + script+audio rows suitable for a data table, use `GET /runs/{run_id}/data`. + + Parameters + ---------- + workflow_id : str + + run_id : str + + include_result : typing.Optional[bool] + Include the full step result payload and hydrate audio playback URLs. + + node_type : typing.Optional[NodeType] + Filter steps by node type. + + node_id : typing.Optional[str] + Filter steps by node ID. + + workspace_id : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ApiResponseListWorkflowRunStepOut] + Successful Response + """ + _response = self._client_wrapper.httpx_client.request( + f"api/v1/workflows/{encode_path_param(workflow_id)}/runs/{encode_path_param(run_id)}/steps", + method="GET", + params={ + "include_result": include_result, + "node_type": node_type, + "node_id": node_id, + }, + 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( + ApiResponseListWorkflowRunStepOut, + parse_obj_as( + type_=ApiResponseListWorkflowRunStepOut, # 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 cancel( self, workflow_id: str, @@ -399,9 +501,9 @@ def cancel( operation is idempotent: cancelling an already-cancelled run returns the run unchanged without error. - Only runs in `pending`, `running`, or `paused` status can be cancelled. - Runs that have already reached a terminal state (`completed`, `failed`, - `cancelled`) return 409. + Runs already in a terminal state (`completed`, `failed`, or `cancelled`) + are returned unchanged. Concurrent terminalization is also treated as an + idempotent success; a still-active compare-and-swap loser returns 409. Unlike `pause`, cancel is permanent — a cancelled run cannot be resumed. Use `pause` if you intend to continue the run later. @@ -682,7 +784,8 @@ async def get( This is the heaviest run endpoint. For progress polling, use the lighter `GET /runs/{run_id}/status` which omits the snapshot. For aggregated visual metrics, use `GET /runs/{run_id}/overview`. For the per-node step - log with audio playback URLs, use `GET /runs/{run_id}/steps`. + log, use `GET /runs/{run_id}/steps`; opt into full results and audio + playback URLs with `include_result=true`. Parameters ---------- @@ -819,6 +922,105 @@ async def status( ) raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + async def steps( + self, + workflow_id: str, + run_id: str, + *, + include_result: typing.Optional[bool] = None, + node_type: typing.Optional[NodeType] = None, + node_id: typing.Optional[str] = None, + workspace_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ApiResponseListWorkflowRunStepOut]: + """ + List per-node execution steps for a workflow run. + + Returns one entry per node execution attempt, ordered by execution sequence. + By default, the response is lightweight: `result` is null, `has_result` + reports whether a stored result exists, and `active_ports` is projected from + the result without loading the full JSON payload. + + Set `include_result=true` to restore the full result payload. Audio results + are then hydrated with short-lived `playback_url` values (valid for 15 + minutes). `node_type` and `node_id` filters combine with AND semantics. + + `node_display_name` is resolved from the run's definition snapshot, so it + 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 + script+audio rows suitable for a data table, use `GET /runs/{run_id}/data`. + + Parameters + ---------- + workflow_id : str + + run_id : str + + include_result : typing.Optional[bool] + Include the full step result payload and hydrate audio playback URLs. + + node_type : typing.Optional[NodeType] + Filter steps by node type. + + node_id : typing.Optional[str] + Filter steps by node ID. + + workspace_id : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ApiResponseListWorkflowRunStepOut] + 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)}/steps", + method="GET", + params={ + "include_result": include_result, + "node_type": node_type, + "node_id": node_id, + }, + 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( + ApiResponseListWorkflowRunStepOut, + parse_obj_as( + type_=ApiResponseListWorkflowRunStepOut, # 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 cancel( self, workflow_id: str, @@ -835,9 +1037,9 @@ async def cancel( operation is idempotent: cancelling an already-cancelled run returns the run unchanged without error. - Only runs in `pending`, `running`, or `paused` status can be cancelled. - Runs that have already reached a terminal state (`completed`, `failed`, - `cancelled`) return 409. + Runs already in a terminal state (`completed`, `failed`, or `cancelled`) + are returned unchanged. Concurrent terminalization is also treated as an + idempotent success; a still-active compare-and-swap loser returns 409. Unlike `pause`, cancel is permanent — a cancelled run cannot be resumed. Use `pause` if you intend to continue the run later.