From 01122e3b62814c864b2aebb4696f6440008746ba Mon Sep 17 00:00:00 2001 From: stlc-bot Date: Fri, 11 Sep 2026 08:17:28 +0000 Subject: [PATCH] Build SDK Stainless-Generated-From: 4dfa6b84787cb1abadb852e4e69a3773e8b64d35 --- .stats.yml | 2 +- api.md | 82 +- src/mobilerun_sdk/_client.py | 38 - src/mobilerun_sdk/resources/__init__.py | 14 - src/mobilerun_sdk/resources/apps.py | 8 +- .../resources/assistant/conversations.py | 38 +- .../resources/connect/proxies.py | 6 +- .../resources/devices/__init__.py | 14 + src/mobilerun_sdk/resources/devices/apps.py | 132 +- .../resources/devices/devices.py | 46 +- .../resources/devices/keyboard.py | 30 +- .../resources/devices/recordings.py | 20 + .../resources/devices/traffic_sessions.py | 470 ++++++ src/mobilerun_sdk/resources/esims/__init__.py | 33 - src/mobilerun_sdk/resources/esims/esims.py | 1286 ----------------- src/mobilerun_sdk/resources/esims/messages.py | 352 ----- src/mobilerun_sdk/resources/files.py | 266 +--- .../resources/mailboxes/mailboxes.py | 144 +- .../resources/mailboxes/messages.py | 8 +- .../resources/messages/conversations.py | 42 +- .../resources/messages/messages.py | 18 +- .../resources/numbers/numbers.py | 211 +-- src/mobilerun_sdk/resources/tasks/tasks.py | 76 +- .../resources/workflows/flows/actions.py | 4 + .../resources/workflows/flows/flows.py | 99 +- src/mobilerun_sdk/types/__init__.py | 23 +- .../types/app_storage_usage_response.py | 9 +- .../conversation_history_response.py | 2 + .../types/connect/proxy_buy_params.py | 6 +- .../types/connect/proxy_buy_response.py | 15 +- .../types/connect/proxy_list_response.py | 17 +- .../types/connect/proxy_retrieve_response.py | 15 +- .../types/device_create_response.py | 4 + .../types/device_list_response.py | 4 + .../device_retrieve_capabilities_response.py | 4 + .../types/device_retrieve_response.py | 4 + .../types/device_set_name_response.py | 4 + .../types/device_wait_ready_response.py | 4 + src/mobilerun_sdk/types/devices/__init__.py | 6 + .../types/devices/app_install_params.py | 24 + .../devices/app_list_installs_response.py | 9 +- .../types/devices/keyboard_write_params.py | 10 +- .../types/devices/recording_start_params.py | 12 + .../devices/traffic_session_create_params.py | 17 + .../traffic_session_create_response.py | 52 + .../traffic_session_delete_response.py | 52 + .../traffic_session_list_params.py} | 6 +- .../devices/traffic_session_list_response.py | 62 + .../traffic_session_retrieve_response.py | 52 + .../types/esim_capacity_response.py | 17 - .../types/esim_confirm_payment_response.py | 69 - src/mobilerun_sdk/types/esim_create_params.py | 24 - .../types/esim_create_response.py | 69 - src/mobilerun_sdk/types/esim_import_params.py | 59 - .../types/esim_import_response.py | 204 --- .../types/esim_install_params.py | 14 - .../types/esim_install_response.py | 69 - .../types/esim_install_status_response.py | 93 -- src/mobilerun_sdk/types/esim_list_params.py | 20 - src/mobilerun_sdk/types/esim_list_response.py | 72 - .../types/esim_retrieve_response.py | 69 - .../types/esim_selector_response.py | 33 - src/mobilerun_sdk/types/esim_update_params.py | 24 - .../types/esim_update_response.py | 69 - src/mobilerun_sdk/types/esims/__init__.py | 8 - .../types/esims/message_list_params.py | 27 - .../types/esims/message_list_response.py | 44 - .../types/esims/message_send_params.py | 38 - .../types/esims/message_send_response.py | 41 - .../types/file_confirm_response.py | 35 - src/mobilerun_sdk/types/file_list_params.py | 11 - src/mobilerun_sdk/types/file_list_response.py | 43 - src/mobilerun_sdk/types/file_update_params.py | 16 - .../types/file_update_response.py | 31 - .../types/mailbox_create_params.py | 20 +- .../types/mailbox_create_response.py | 4 +- .../types/mailbox_delete_response.py | 4 +- .../types/mailbox_list_response.py | 4 +- .../types/mailbox_otp_response.py | 2 +- .../types/mailbox_restart_params.py | 10 +- .../types/mailbox_restart_response.py | 4 +- .../types/mailbox_retrieve_response.py | 4 +- .../types/mailbox_uncancel_response.py | 4 +- .../types/mailbox_update_response.py | 4 +- .../types/number_capacity_params.py | 12 + .../types/number_capacity_response.py | 27 + .../types/number_create_params.py | 10 +- .../types/task_get_status_response.py | 8 +- src/mobilerun_sdk/types/task_list_params.py | 7 +- src/mobilerun_sdk/types/task_list_response.py | 19 +- .../types/task_retrieve_response.py | 19 +- src/mobilerun_sdk/types/task_run_params.py | 14 +- src/mobilerun_sdk/types/task_run_response.py | 2 +- .../types/task_run_streamed_params.py | 14 +- .../types/webhook_event_types_response.py | 4 +- src/mobilerun_sdk/types/workflows/__init__.py | 1 + .../types/workflows/event_dry_run_response.py | 23 + .../workflows/execution_list_response.py | 38 +- .../workflows/execution_retrieve_response.py | 38 +- .../types/workflows/flow_capacity_response.py | 19 + .../types/workflows/flow_clone_response.py | 20 +- .../types/workflows/flow_create_params.py | 16 +- .../types/workflows/flow_create_response.py | 20 +- .../types/workflows/flow_dry_run_response.py | 4 + .../types/workflows/flow_list_response.py | 20 +- .../types/workflows/flow_retrieve_response.py | 20 +- .../types/workflows/flow_unblock_response.py | 20 +- .../types/workflows/flow_update_params.py | 17 +- .../types/workflows/flow_update_response.py | 20 +- .../workflows/flows/action_add_params.py | 4 + .../workflows/flows/action_add_response.py | 6 + .../workflows/flows/action_list_response.py | 6 + .../workflows/flows/action_replace_params.py | 4 + .../flows/action_replace_response.py | 6 + tests/api_resources/connect/test_proxies.py | 20 + tests/api_resources/devices/test_apps.py | 8 + tests/api_resources/devices/test_keyboard.py | 2 + .../api_resources/devices/test_recordings.py | 2 + .../devices/test_traffic_sessions.py | 455 ++++++ tests/api_resources/esims/__init__.py | 1 - tests/api_resources/esims/test_messages.py | 262 ---- tests/api_resources/test_esims.py | 953 ------------ tests/api_resources/test_files.py | 263 ---- tests/api_resources/test_mailboxes.py | 2 + tests/api_resources/test_numbers.py | 69 + tests/api_resources/test_tasks.py | 18 +- .../workflows/flows/test_actions.py | 4 + tests/api_resources/workflows/test_flows.py | 67 + 128 files changed, 2542 insertions(+), 5133 deletions(-) create mode 100644 src/mobilerun_sdk/resources/devices/traffic_sessions.py delete mode 100644 src/mobilerun_sdk/resources/esims/__init__.py delete mode 100644 src/mobilerun_sdk/resources/esims/esims.py delete mode 100644 src/mobilerun_sdk/resources/esims/messages.py create mode 100644 src/mobilerun_sdk/types/devices/traffic_session_create_params.py create mode 100644 src/mobilerun_sdk/types/devices/traffic_session_create_response.py create mode 100644 src/mobilerun_sdk/types/devices/traffic_session_delete_response.py rename src/mobilerun_sdk/types/{esim_selector_params.py => devices/traffic_session_list_params.py} (66%) create mode 100644 src/mobilerun_sdk/types/devices/traffic_session_list_response.py create mode 100644 src/mobilerun_sdk/types/devices/traffic_session_retrieve_response.py delete mode 100644 src/mobilerun_sdk/types/esim_capacity_response.py delete mode 100644 src/mobilerun_sdk/types/esim_confirm_payment_response.py delete mode 100644 src/mobilerun_sdk/types/esim_create_params.py delete mode 100644 src/mobilerun_sdk/types/esim_create_response.py delete mode 100644 src/mobilerun_sdk/types/esim_import_params.py delete mode 100644 src/mobilerun_sdk/types/esim_import_response.py delete mode 100644 src/mobilerun_sdk/types/esim_install_params.py delete mode 100644 src/mobilerun_sdk/types/esim_install_response.py delete mode 100644 src/mobilerun_sdk/types/esim_install_status_response.py delete mode 100644 src/mobilerun_sdk/types/esim_list_params.py delete mode 100644 src/mobilerun_sdk/types/esim_list_response.py delete mode 100644 src/mobilerun_sdk/types/esim_retrieve_response.py delete mode 100644 src/mobilerun_sdk/types/esim_selector_response.py delete mode 100644 src/mobilerun_sdk/types/esim_update_params.py delete mode 100644 src/mobilerun_sdk/types/esim_update_response.py delete mode 100644 src/mobilerun_sdk/types/esims/__init__.py delete mode 100644 src/mobilerun_sdk/types/esims/message_list_params.py delete mode 100644 src/mobilerun_sdk/types/esims/message_list_response.py delete mode 100644 src/mobilerun_sdk/types/esims/message_send_params.py delete mode 100644 src/mobilerun_sdk/types/esims/message_send_response.py delete mode 100644 src/mobilerun_sdk/types/file_confirm_response.py delete mode 100644 src/mobilerun_sdk/types/file_list_params.py delete mode 100644 src/mobilerun_sdk/types/file_list_response.py delete mode 100644 src/mobilerun_sdk/types/file_update_params.py delete mode 100644 src/mobilerun_sdk/types/file_update_response.py create mode 100644 src/mobilerun_sdk/types/number_capacity_params.py create mode 100644 src/mobilerun_sdk/types/number_capacity_response.py create mode 100644 src/mobilerun_sdk/types/workflows/flow_capacity_response.py create mode 100644 tests/api_resources/devices/test_traffic_sessions.py delete mode 100644 tests/api_resources/esims/__init__.py delete mode 100644 tests/api_resources/esims/test_messages.py delete mode 100644 tests/api_resources/test_esims.py diff --git a/.stats.yml b/.stats.yml index c92480be..dd9fa391 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1 +1 @@ -configured_endpoints: 247 +configured_endpoints: 237 diff --git a/api.md b/api.md index bfeceaed..37b9afc5 100644 --- a/api.md +++ b/api.md @@ -431,6 +431,26 @@ Methods: - client.devices.recordings.trajectory(recording_id, \*, device_id) -> None - client.devices.recordings.video(recording_id, \*, device_id) -> None +## TrafficSessions + +Types: + +```python +from mobilerun_sdk.types.devices import ( + TrafficSessionCreateResponse, + TrafficSessionRetrieveResponse, + TrafficSessionListResponse, + TrafficSessionDeleteResponse, +) +``` + +Methods: + +- client.devices.traffic_sessions.create(device_id, \*\*params) -> TrafficSessionCreateResponse +- client.devices.traffic_sessions.retrieve(session_id, \*, device_id) -> TrafficSessionRetrieveResponse +- client.devices.traffic_sessions.list(device_id, \*\*params) -> TrafficSessionListResponse +- client.devices.traffic_sessions.delete(session_id, \*, device_id) -> TrafficSessionDeleteResponse + # Models Types: @@ -688,6 +708,7 @@ from mobilerun_sdk.types.workflows import ( FlowUpdateResponse, FlowListResponse, FlowDeleteResponse, + FlowCapacityResponse, FlowCloneResponse, FlowDryRunResponse, FlowListRepairsResponse, @@ -702,6 +723,7 @@ Methods: - client.workflows.flows.update(flow_id, \*\*params) -> FlowUpdateResponse - client.workflows.flows.list(\*\*params) -> FlowListResponse - client.workflows.flows.delete(flow_id) -> FlowDeleteResponse +- client.workflows.flows.capacity() -> FlowCapacityResponse - client.workflows.flows.clone(flow_id, \*\*params) -> FlowCloneResponse - client.workflows.flows.dry_run(flow_id, \*\*params) -> FlowDryRunResponse - client.workflows.flows.list_repairs(flow_id) -> FlowListRepairsResponse @@ -867,23 +889,13 @@ Methods: Types: ```python -from mobilerun_sdk.types import ( - FileUpdateResponse, - FileListResponse, - FileDeleteResponse, - FileCancelPendingResponse, - FileConfirmResponse, - FileUploadURLResponse, -) +from mobilerun_sdk.types import FileDeleteResponse, FileCancelPendingResponse, FileUploadURLResponse ``` Methods: -- client.files.update(file_id, \*\*params) -> FileUpdateResponse -- client.files.list(\*\*params) -> FileListResponse - client.files.delete(file_id) -> FileDeleteResponse - client.files.cancel_pending(file_id) -> FileCancelPendingResponse -- client.files.confirm(file_id) -> FileConfirmResponse - client.files.download(file_id) -> None - client.files.upload_url(\*\*params) -> FileUploadURLResponse @@ -965,52 +977,6 @@ Methods: - client.notifications.get_preferences() -> NotificationGetPreferencesResponse - client.notifications.update_preferences(\*\*params) -> NotificationUpdatePreferencesResponse -# Esims - -Types: - -```python -from mobilerun_sdk.types import ( - EsimCreateResponse, - EsimRetrieveResponse, - EsimUpdateResponse, - EsimListResponse, - EsimCapacityResponse, - EsimConfirmPaymentResponse, - EsimImportResponse, - EsimInstallResponse, - EsimInstallStatusResponse, - EsimSelectorResponse, -) -``` - -Methods: - -- client.esims.create(\*\*params) -> EsimCreateResponse -- client.esims.retrieve(id) -> EsimRetrieveResponse -- client.esims.update(id, \*\*params) -> EsimUpdateResponse -- client.esims.list(\*\*params) -> EsimListResponse -- client.esims.delete(id) -> None -- client.esims.capacity() -> EsimCapacityResponse -- client.esims.confirm_payment(id) -> EsimConfirmPaymentResponse -- client.esims.import\_(\*\*params) -> EsimImportResponse -- client.esims.install(id, \*\*params) -> EsimInstallResponse -- client.esims.install_status(id) -> EsimInstallStatusResponse -- client.esims.selector(\*\*params) -> EsimSelectorResponse - -## Messages - -Types: - -```python -from mobilerun_sdk.types.esims import MessageListResponse, MessageSendResponse -``` - -Methods: - -- client.esims.messages.list(id, \*\*params) -> MessageListResponse -- client.esims.messages.send(id, \*\*params) -> MessageSendResponse - # Messages Types: @@ -1047,6 +1013,7 @@ from mobilerun_sdk.types import ( NumberUpdateResponse, NumberListResponse, NumberDeleteResponse, + NumberCapacityResponse, NumberCountriesResponse, NumberPurposesResponse, ) @@ -1059,6 +1026,7 @@ Methods: - client.numbers.update(id, \*\*params) -> NumberUpdateResponse - client.numbers.list(\*\*params) -> NumberListResponse - client.numbers.delete(id) -> NumberDeleteResponse +- client.numbers.capacity(\*\*params) -> NumberCapacityResponse - client.numbers.countries() -> NumberCountriesResponse - client.numbers.purposes() -> NumberPurposesResponse diff --git a/src/mobilerun_sdk/_client.py b/src/mobilerun_sdk/_client.py index 4a8abcae..cb8ba65a 100644 --- a/src/mobilerun_sdk/_client.py +++ b/src/mobilerun_sdk/_client.py @@ -38,7 +38,6 @@ if TYPE_CHECKING: from .resources import ( apps, - esims, files, store, tasks, @@ -64,7 +63,6 @@ from .resources.proxies import ProxiesResource, AsyncProxiesResource from .resources.carriers import CarriersResource, AsyncCarriersResource from .resources.profiles import ProfilesResource, AsyncProfilesResource - from .resources.esims.esims import EsimsResource, AsyncEsimsResource from .resources.store.store import StoreResource, AsyncStoreResource from .resources.tasks.tasks import TasksResource, AsyncTasksResource from .resources.notifications import NotificationsResource, AsyncNotificationsResource @@ -249,12 +247,6 @@ def notifications(self) -> NotificationsResource: return NotificationsResource(self) - @cached_property - def esims(self) -> EsimsResource: - from .resources.esims import EsimsResource - - return EsimsResource(self) - @cached_property def messages(self) -> MessagesResource: from .resources.messages import MessagesResource @@ -555,12 +547,6 @@ def notifications(self) -> AsyncNotificationsResource: return AsyncNotificationsResource(self) - @cached_property - def esims(self) -> AsyncEsimsResource: - from .resources.esims import AsyncEsimsResource - - return AsyncEsimsResource(self) - @cached_property def messages(self) -> AsyncMessagesResource: from .resources.messages import AsyncMessagesResource @@ -807,12 +793,6 @@ def notifications(self) -> notifications.NotificationsResourceWithRawResponse: return NotificationsResourceWithRawResponse(self._client.notifications) - @cached_property - def esims(self) -> esims.EsimsResourceWithRawResponse: - from .resources.esims import EsimsResourceWithRawResponse - - return EsimsResourceWithRawResponse(self._client.esims) - @cached_property def messages(self) -> messages.MessagesResourceWithRawResponse: from .resources.messages import MessagesResourceWithRawResponse @@ -936,12 +916,6 @@ def notifications(self) -> notifications.AsyncNotificationsResourceWithRawRespon return AsyncNotificationsResourceWithRawResponse(self._client.notifications) - @cached_property - def esims(self) -> esims.AsyncEsimsResourceWithRawResponse: - from .resources.esims import AsyncEsimsResourceWithRawResponse - - return AsyncEsimsResourceWithRawResponse(self._client.esims) - @cached_property def messages(self) -> messages.AsyncMessagesResourceWithRawResponse: from .resources.messages import AsyncMessagesResourceWithRawResponse @@ -1065,12 +1039,6 @@ def notifications(self) -> notifications.NotificationsResourceWithStreamingRespo return NotificationsResourceWithStreamingResponse(self._client.notifications) - @cached_property - def esims(self) -> esims.EsimsResourceWithStreamingResponse: - from .resources.esims import EsimsResourceWithStreamingResponse - - return EsimsResourceWithStreamingResponse(self._client.esims) - @cached_property def messages(self) -> messages.MessagesResourceWithStreamingResponse: from .resources.messages import MessagesResourceWithStreamingResponse @@ -1194,12 +1162,6 @@ def notifications(self) -> notifications.AsyncNotificationsResourceWithStreaming return AsyncNotificationsResourceWithStreamingResponse(self._client.notifications) - @cached_property - def esims(self) -> esims.AsyncEsimsResourceWithStreamingResponse: - from .resources.esims import AsyncEsimsResourceWithStreamingResponse - - return AsyncEsimsResourceWithStreamingResponse(self._client.esims) - @cached_property def messages(self) -> messages.AsyncMessagesResourceWithStreamingResponse: from .resources.messages import AsyncMessagesResourceWithStreamingResponse diff --git a/src/mobilerun_sdk/resources/__init__.py b/src/mobilerun_sdk/resources/__init__.py index c86ce259..30c0dbfc 100644 --- a/src/mobilerun_sdk/resources/__init__.py +++ b/src/mobilerun_sdk/resources/__init__.py @@ -8,14 +8,6 @@ AppsResourceWithStreamingResponse, AsyncAppsResourceWithStreamingResponse, ) -from .esims import ( - EsimsResource, - AsyncEsimsResource, - EsimsResourceWithRawResponse, - AsyncEsimsResourceWithRawResponse, - EsimsResourceWithStreamingResponse, - AsyncEsimsResourceWithStreamingResponse, -) from .files import ( FilesResource, AsyncFilesResource, @@ -258,12 +250,6 @@ "AsyncNotificationsResourceWithRawResponse", "NotificationsResourceWithStreamingResponse", "AsyncNotificationsResourceWithStreamingResponse", - "EsimsResource", - "AsyncEsimsResource", - "EsimsResourceWithRawResponse", - "AsyncEsimsResourceWithRawResponse", - "EsimsResourceWithStreamingResponse", - "AsyncEsimsResourceWithStreamingResponse", "MessagesResource", "AsyncMessagesResource", "MessagesResourceWithRawResponse", diff --git a/src/mobilerun_sdk/resources/apps.py b/src/mobilerun_sdk/resources/apps.py index e46dbbf0..3f0f323f 100644 --- a/src/mobilerun_sdk/resources/apps.py +++ b/src/mobilerun_sdk/resources/apps.py @@ -183,7 +183,9 @@ def confirm_upload( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AppConfirmUploadResponse: """ - Verifies the APK file exists in R2 and sets the app status to available. + Verifies the uploaded files in R2 and sets the app version status to available. + Idempotent: replaying confirmation for an already-available version returns the + same successful response without re-verifying the files. Args: extra_headers: Send extra headers @@ -506,7 +508,9 @@ async def confirm_upload( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AppConfirmUploadResponse: """ - Verifies the APK file exists in R2 and sets the app status to available. + Verifies the uploaded files in R2 and sets the app version status to available. + Idempotent: replaying confirmation for an already-available version returns the + same successful response without re-verifying the files. Args: extra_headers: Send extra headers diff --git a/src/mobilerun_sdk/resources/assistant/conversations.py b/src/mobilerun_sdk/resources/assistant/conversations.py index 04b2a56c..a077836d 100644 --- a/src/mobilerun_sdk/resources/assistant/conversations.py +++ b/src/mobilerun_sdk/resources/assistant/conversations.py @@ -263,8 +263,14 @@ def answer_permission( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ConversationAnswerPermissionResponse: - """ - Deliver a HITL approval/rejection for an in-flight turn. + """Deliver a HITL approval/rejection for an in-flight turn. + + Interactive HITL + clients must start the turn with `Accept: text/event-stream`, wait for a + `tool-hitl-approval` event, and send its `permissionId` here at + `/assistant/chat/permission`. Do not submit approval as free-form user text or + as `confirmed: true`. For `devices.reset`, only `once` and `reject` are allowed; + the generic `always` response is rejected with HTTP 400. Args: extra_headers: Send extra headers @@ -428,9 +434,12 @@ def send( The response format follows the Accept header: `text/event-stream` for SSE, `application/json` for a buffered assistant reply. - `sessionId` targets a concrete active chat. The resolved chat session ID is - returned as `chatSessionId` in the JSON body and as the `X-Chat-Session-Id` - response header on the SSE response. + Interactive HITL requires `Accept: text/event-stream`: the stream can emit a + `tool-hitl-approval` event, whose decision must be delivered to + `/assistant/chat/permission`. Buffered JSON responses do not provide an + interactive HITL continuation contract. `sessionId` targets a concrete active + chat. The resolved chat session ID is returned as `chatSessionId` in the JSON + body and as the `X-Chat-Session-Id` response header on the SSE response. Args: extra_headers: Send extra headers @@ -721,8 +730,14 @@ async def answer_permission( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ConversationAnswerPermissionResponse: - """ - Deliver a HITL approval/rejection for an in-flight turn. + """Deliver a HITL approval/rejection for an in-flight turn. + + Interactive HITL + clients must start the turn with `Accept: text/event-stream`, wait for a + `tool-hitl-approval` event, and send its `permissionId` here at + `/assistant/chat/permission`. Do not submit approval as free-form user text or + as `confirmed: true`. For `devices.reset`, only `once` and `reject` are allowed; + the generic `always` response is rejected with HTTP 400. Args: extra_headers: Send extra headers @@ -886,9 +901,12 @@ async def send( The response format follows the Accept header: `text/event-stream` for SSE, `application/json` for a buffered assistant reply. - `sessionId` targets a concrete active chat. The resolved chat session ID is - returned as `chatSessionId` in the JSON body and as the `X-Chat-Session-Id` - response header on the SSE response. + Interactive HITL requires `Accept: text/event-stream`: the stream can emit a + `tool-hitl-approval` event, whose decision must be delivered to + `/assistant/chat/permission`. Buffered JSON responses do not provide an + interactive HITL continuation contract. `sessionId` targets a concrete active + chat. The resolved chat session ID is returned as `chatSessionId` in the JSON + body and as the `X-Chat-Session-Id` response header on the SSE response. Args: extra_headers: Send extra headers diff --git a/src/mobilerun_sdk/resources/connect/proxies.py b/src/mobilerun_sdk/resources/connect/proxies.py index c89fce4c..718dc6d6 100644 --- a/src/mobilerun_sdk/resources/connect/proxies.py +++ b/src/mobilerun_sdk/resources/connect/proxies.py @@ -9,7 +9,7 @@ import httpx from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform +from ..._utils import path_template, maybe_transform, strip_not_given, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -140,6 +140,7 @@ def buy( *, country: str, type: Literal["dedicated_residential", "residential", "mobile"], + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -161,6 +162,7 @@ def buy( timeout: Override the client-level default timeout for this request, in seconds """ + extra_headers = {**strip_not_given({"Idempotency-Key": idempotency_key}), **(extra_headers or {})} return self._post( "/connect/proxies", body=maybe_transform( @@ -505,6 +507,7 @@ async def buy( *, country: str, type: Literal["dedicated_residential", "residential", "mobile"], + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -526,6 +529,7 @@ async def buy( timeout: Override the client-level default timeout for this request, in seconds """ + extra_headers = {**strip_not_given({"Idempotency-Key": idempotency_key}), **(extra_headers or {})} return await self._post( "/connect/proxies", body=await async_maybe_transform( diff --git a/src/mobilerun_sdk/resources/devices/__init__.py b/src/mobilerun_sdk/resources/devices/__init__.py index 7a429240..17516758 100644 --- a/src/mobilerun_sdk/resources/devices/__init__.py +++ b/src/mobilerun_sdk/resources/devices/__init__.py @@ -160,6 +160,14 @@ MediaSessionsResourceWithStreamingResponse, AsyncMediaSessionsResourceWithStreamingResponse, ) +from .traffic_sessions import ( + TrafficSessionsResource, + AsyncTrafficSessionsResource, + TrafficSessionsResourceWithRawResponse, + AsyncTrafficSessionsResourceWithRawResponse, + TrafficSessionsResourceWithStreamingResponse, + AsyncTrafficSessionsResourceWithStreamingResponse, +) __all__ = [ "ActionsResource", @@ -276,6 +284,12 @@ "AsyncRecordingsResourceWithRawResponse", "RecordingsResourceWithStreamingResponse", "AsyncRecordingsResourceWithStreamingResponse", + "TrafficSessionsResource", + "AsyncTrafficSessionsResource", + "TrafficSessionsResourceWithRawResponse", + "AsyncTrafficSessionsResourceWithRawResponse", + "TrafficSessionsResourceWithStreamingResponse", + "AsyncTrafficSessionsResourceWithStreamingResponse", "DevicesResource", "AsyncDevicesResource", "DevicesResourceWithRawResponse", diff --git a/src/mobilerun_sdk/resources/devices/apps.py b/src/mobilerun_sdk/resources/devices/apps.py index f89729c8..e672a017 100644 --- a/src/mobilerun_sdk/resources/devices/apps.py +++ b/src/mobilerun_sdk/resources/devices/apps.py @@ -207,7 +207,9 @@ def install( *, bundle_id: str, background: bool | Omit = omit, + country: str | Omit = omit, package_name: str | Omit = omit, + version_code: int | Omit = omit, x_device_display_id: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -219,15 +221,16 @@ def install( """Requests an app install on the device. The request body must supply exactly one - of an Android packageName or an iOS bundleId; protected packages are rejected. - background (default false) selects the response contract: false installs inline - and returns the outcome directly (200 on success, an error status on failure); - true accepts the request and runs the download + install in the background, - returning 202 immediately — poll list-app-installs for the backend's view of - that attempt's status. Refuses with 409 once 2 other installs are already - running on the device, in either mode; a repeat request for an app that already - has an install running is also refused with 409 rather than superseding it — - retry once that attempt reaches a terminal state. + of an Android packageName or an iOS bundleId; optional country and versionCode + select an exact regional uploaded Android version, and protected packages are + rejected. background (default false) selects the response contract: false + installs inline and returns the outcome directly (200 on success, an error + status on failure); true accepts the request and runs the download + install in + the background, returning 202 immediately — poll list-app-installs for the + backend's view of that attempt's status. Refuses with 409 once 2 other installs + are already running on the device, in either mode; a repeat request for an app + that already has an install running is also refused with 409 rather than + superseding it — retry once that attempt reaches a terminal state. Args: bundle_id: iOS bundle identifier (e.g. com.example.app) @@ -236,8 +239,13 @@ def install( list-app-installs). false/omitted: install inline and return the outcome directly (200 on success, an error status on failure). + country: Optional ISO 3166-1 alpha-2 country of the uploaded app version (e.g. MY or SG). + package_name: Android package name (e.g. com.example.app) + version_code: Optional exact app-library version code. Use with country when multiple regional + versions share an identifier. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -256,6 +264,8 @@ def install( package_name: str, background: bool | Omit = omit, bundle_id: str | Omit = omit, + country: str | Omit = omit, + version_code: int | Omit = omit, x_device_display_id: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -267,15 +277,16 @@ def install( """Requests an app install on the device. The request body must supply exactly one - of an Android packageName or an iOS bundleId; protected packages are rejected. - background (default false) selects the response contract: false installs inline - and returns the outcome directly (200 on success, an error status on failure); - true accepts the request and runs the download + install in the background, - returning 202 immediately — poll list-app-installs for the backend's view of - that attempt's status. Refuses with 409 once 2 other installs are already - running on the device, in either mode; a repeat request for an app that already - has an install running is also refused with 409 rather than superseding it — - retry once that attempt reaches a terminal state. + of an Android packageName or an iOS bundleId; optional country and versionCode + select an exact regional uploaded Android version, and protected packages are + rejected. background (default false) selects the response contract: false + installs inline and returns the outcome directly (200 on success, an error + status on failure); true accepts the request and runs the download + install in + the background, returning 202 immediately — poll list-app-installs for the + backend's view of that attempt's status. Refuses with 409 once 2 other installs + are already running on the device, in either mode; a repeat request for an app + that already has an install running is also refused with 409 rather than + superseding it — retry once that attempt reaches a terminal state. Args: package_name: Android package name (e.g. com.example.app) @@ -286,6 +297,11 @@ def install( bundle_id: iOS bundle identifier (e.g. com.example.app) + country: Optional ISO 3166-1 alpha-2 country of the uploaded app version (e.g. MY or SG). + + version_code: Optional exact app-library version code. Use with country when multiple regional + versions share an identifier. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -303,7 +319,9 @@ def install( *, bundle_id: str | Omit = omit, background: bool | Omit = omit, + country: str | Omit = omit, package_name: str | Omit = omit, + version_code: int | Omit = omit, x_device_display_id: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -327,7 +345,9 @@ def install( { "bundle_id": bundle_id, "background": background, + "country": country, "package_name": package_name, + "version_code": version_code, }, app_install_params.AppInstallParams, ), @@ -350,11 +370,11 @@ def list_installs( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AppListInstallsResponse: """ - Reports the backend's view of background app-install attempts on this device — - status reflects the install ATTEMPT, not device ground truth; list-apps remains - authoritative for what is actually installed. Records are in-memory and lost on - service restart; terminal records are kept ~15 minutes. Not gated on device - readiness, so it also answers while the device is offline or crashed. + Reports the backend's durable view of background app-install attempts on this + device — status reflects the install ATTEMPT, not device ground truth; list-apps + remains authoritative for what is actually installed. Terminal and projected + timeout records are kept ~15 minutes. Not gated on device readiness, so it also + answers while the device is offline or crashed. Args: extra_headers: Send extra headers @@ -719,7 +739,9 @@ async def install( *, bundle_id: str, background: bool | Omit = omit, + country: str | Omit = omit, package_name: str | Omit = omit, + version_code: int | Omit = omit, x_device_display_id: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -731,15 +753,16 @@ async def install( """Requests an app install on the device. The request body must supply exactly one - of an Android packageName or an iOS bundleId; protected packages are rejected. - background (default false) selects the response contract: false installs inline - and returns the outcome directly (200 on success, an error status on failure); - true accepts the request and runs the download + install in the background, - returning 202 immediately — poll list-app-installs for the backend's view of - that attempt's status. Refuses with 409 once 2 other installs are already - running on the device, in either mode; a repeat request for an app that already - has an install running is also refused with 409 rather than superseding it — - retry once that attempt reaches a terminal state. + of an Android packageName or an iOS bundleId; optional country and versionCode + select an exact regional uploaded Android version, and protected packages are + rejected. background (default false) selects the response contract: false + installs inline and returns the outcome directly (200 on success, an error + status on failure); true accepts the request and runs the download + install in + the background, returning 202 immediately — poll list-app-installs for the + backend's view of that attempt's status. Refuses with 409 once 2 other installs + are already running on the device, in either mode; a repeat request for an app + that already has an install running is also refused with 409 rather than + superseding it — retry once that attempt reaches a terminal state. Args: bundle_id: iOS bundle identifier (e.g. com.example.app) @@ -748,8 +771,13 @@ async def install( list-app-installs). false/omitted: install inline and return the outcome directly (200 on success, an error status on failure). + country: Optional ISO 3166-1 alpha-2 country of the uploaded app version (e.g. MY or SG). + package_name: Android package name (e.g. com.example.app) + version_code: Optional exact app-library version code. Use with country when multiple regional + versions share an identifier. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -768,6 +796,8 @@ async def install( package_name: str, background: bool | Omit = omit, bundle_id: str | Omit = omit, + country: str | Omit = omit, + version_code: int | Omit = omit, x_device_display_id: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -779,15 +809,16 @@ async def install( """Requests an app install on the device. The request body must supply exactly one - of an Android packageName or an iOS bundleId; protected packages are rejected. - background (default false) selects the response contract: false installs inline - and returns the outcome directly (200 on success, an error status on failure); - true accepts the request and runs the download + install in the background, - returning 202 immediately — poll list-app-installs for the backend's view of - that attempt's status. Refuses with 409 once 2 other installs are already - running on the device, in either mode; a repeat request for an app that already - has an install running is also refused with 409 rather than superseding it — - retry once that attempt reaches a terminal state. + of an Android packageName or an iOS bundleId; optional country and versionCode + select an exact regional uploaded Android version, and protected packages are + rejected. background (default false) selects the response contract: false + installs inline and returns the outcome directly (200 on success, an error + status on failure); true accepts the request and runs the download + install in + the background, returning 202 immediately — poll list-app-installs for the + backend's view of that attempt's status. Refuses with 409 once 2 other installs + are already running on the device, in either mode; a repeat request for an app + that already has an install running is also refused with 409 rather than + superseding it — retry once that attempt reaches a terminal state. Args: package_name: Android package name (e.g. com.example.app) @@ -798,6 +829,11 @@ async def install( bundle_id: iOS bundle identifier (e.g. com.example.app) + country: Optional ISO 3166-1 alpha-2 country of the uploaded app version (e.g. MY or SG). + + version_code: Optional exact app-library version code. Use with country when multiple regional + versions share an identifier. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -815,7 +851,9 @@ async def install( *, bundle_id: str | Omit = omit, background: bool | Omit = omit, + country: str | Omit = omit, package_name: str | Omit = omit, + version_code: int | Omit = omit, x_device_display_id: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -839,7 +877,9 @@ async def install( { "bundle_id": bundle_id, "background": background, + "country": country, "package_name": package_name, + "version_code": version_code, }, app_install_params.AppInstallParams, ), @@ -862,11 +902,11 @@ async def list_installs( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AppListInstallsResponse: """ - Reports the backend's view of background app-install attempts on this device — - status reflects the install ATTEMPT, not device ground truth; list-apps remains - authoritative for what is actually installed. Records are in-memory and lost on - service restart; terminal records are kept ~15 minutes. Not gated on device - readiness, so it also answers while the device is offline or crashed. + Reports the backend's durable view of background app-install attempts on this + device — status reflects the install ATTEMPT, not device ground truth; list-apps + remains authoritative for what is actually installed. Terminal and projected + timeout records are kept ~15 minutes. Not gated on device readiness, so it also + answers while the device is offline or crashed. Args: extra_headers: Send extra headers diff --git a/src/mobilerun_sdk/resources/devices/devices.py b/src/mobilerun_sdk/resources/devices/devices.py index ad34958e..beb5138b 100644 --- a/src/mobilerun_sdk/resources/devices/devices.py +++ b/src/mobilerun_sdk/resources/devices/devices.py @@ -172,6 +172,14 @@ MediaSessionsResourceWithStreamingResponse, AsyncMediaSessionsResourceWithStreamingResponse, ) +from .traffic_sessions import ( + TrafficSessionsResource, + AsyncTrafficSessionsResource, + TrafficSessionsResourceWithRawResponse, + AsyncTrafficSessionsResourceWithRawResponse, + TrafficSessionsResourceWithStreamingResponse, + AsyncTrafficSessionsResourceWithStreamingResponse, +) from ...types.device_list_response import DeviceListResponse from ...types.device_count_response import DeviceCountResponse from ...types.device_create_response import DeviceCreateResponse @@ -264,6 +272,10 @@ def media_sessions(self) -> MediaSessionsResource: def recordings(self) -> RecordingsResource: return RecordingsResource(self._client) + @cached_property + def traffic_sessions(self) -> TrafficSessionsResource: + return TrafficSessionsResource(self._client) + @cached_property def with_raw_response(self) -> DevicesResourceWithRawResponse: """ @@ -657,10 +669,9 @@ def resume( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ - Wakes a parked device: capacity is preflighted (the device's data may be - replicated to another node if its home is full), the device starts running - again, and per-minute billing resumes. On a device that is not parked this is a - no-op ready transition. + Wakes a parked device: backend readiness and any required capacity are + preflighted, the same device starts running again, and per-minute billing + resumes. On a device that is not parked this is a no-op ready transition. Args: extra_headers: Send extra headers @@ -951,6 +962,10 @@ def media_sessions(self) -> AsyncMediaSessionsResource: def recordings(self) -> AsyncRecordingsResource: return AsyncRecordingsResource(self._client) + @cached_property + def traffic_sessions(self) -> AsyncTrafficSessionsResource: + return AsyncTrafficSessionsResource(self._client) + @cached_property def with_raw_response(self) -> AsyncDevicesResourceWithRawResponse: """ @@ -1344,10 +1359,9 @@ async def resume( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ - Wakes a parked device: capacity is preflighted (the device's data may be - replicated to another node if its home is full), the device starts running - again, and per-minute billing resumes. On a device that is not parked this is a - no-op ready transition. + Wakes a parked device: backend readiness and any required capacity are + preflighted, the same device starts running again, and per-minute billing + resumes. On a device that is not parked this is a no-op ready transition. Args: extra_headers: Send extra headers @@ -1681,6 +1695,10 @@ def media_sessions(self) -> MediaSessionsResourceWithRawResponse: def recordings(self) -> RecordingsResourceWithRawResponse: return RecordingsResourceWithRawResponse(self._devices.recordings) + @cached_property + def traffic_sessions(self) -> TrafficSessionsResourceWithRawResponse: + return TrafficSessionsResourceWithRawResponse(self._devices.traffic_sessions) + class AsyncDevicesResourceWithRawResponse: def __init__(self, devices: AsyncDevicesResource) -> None: @@ -1802,6 +1820,10 @@ def media_sessions(self) -> AsyncMediaSessionsResourceWithRawResponse: def recordings(self) -> AsyncRecordingsResourceWithRawResponse: return AsyncRecordingsResourceWithRawResponse(self._devices.recordings) + @cached_property + def traffic_sessions(self) -> AsyncTrafficSessionsResourceWithRawResponse: + return AsyncTrafficSessionsResourceWithRawResponse(self._devices.traffic_sessions) + class DevicesResourceWithStreamingResponse: def __init__(self, devices: DevicesResource) -> None: @@ -1923,6 +1945,10 @@ def media_sessions(self) -> MediaSessionsResourceWithStreamingResponse: def recordings(self) -> RecordingsResourceWithStreamingResponse: return RecordingsResourceWithStreamingResponse(self._devices.recordings) + @cached_property + def traffic_sessions(self) -> TrafficSessionsResourceWithStreamingResponse: + return TrafficSessionsResourceWithStreamingResponse(self._devices.traffic_sessions) + class AsyncDevicesResourceWithStreamingResponse: def __init__(self, devices: AsyncDevicesResource) -> None: @@ -2043,3 +2069,7 @@ def media_sessions(self) -> AsyncMediaSessionsResourceWithStreamingResponse: @cached_property def recordings(self) -> AsyncRecordingsResourceWithStreamingResponse: return AsyncRecordingsResourceWithStreamingResponse(self._devices.recordings) + + @cached_property + def traffic_sessions(self) -> AsyncTrafficSessionsResourceWithStreamingResponse: + return AsyncTrafficSessionsResourceWithStreamingResponse(self._devices.traffic_sessions) diff --git a/src/mobilerun_sdk/resources/devices/keyboard.py b/src/mobilerun_sdk/resources/devices/keyboard.py index a1bd8bbc..dd5439ce 100644 --- a/src/mobilerun_sdk/resources/devices/keyboard.py +++ b/src/mobilerun_sdk/resources/devices/keyboard.py @@ -2,6 +2,8 @@ from __future__ import annotations +from typing_extensions import Literal + import httpx from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given @@ -130,6 +132,7 @@ def write( *, text: str, clear: bool | Omit = omit, + completion_mode: Literal["accepted", "committed"] | Omit = omit, error_rate: float | Omit = omit, stealth: bool | Omit = omit, wpm: int | Omit = omit, @@ -141,13 +144,17 @@ def write( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """Types the given text into the focused input field. + """Types text into the focused input field. - Supports optionally clearing - the field first and a stealth mode that emulates human typing speed and error - rate on supported devices. + The optional completionMode defaults to + accepted for backwards-compatible low latency; committed additionally waits for + the complete text or a quiescent UI state. Args: + completion_mode: Completion guarantee. accepted returns after the input provider accepts the + operation; committed additionally waits for the focused UI state to contain the + complete text or become quiescent. + error_rate: Per-character mistake rate for humantouch typing. -1 uses server default. wpm: Words per minute for stealth typing. 0 uses portal default. @@ -175,6 +182,7 @@ def write( { "text": text, "clear": clear, + "completion_mode": completion_mode, "error_rate": error_rate, "stealth": stealth, "wpm": wpm, @@ -298,6 +306,7 @@ async def write( *, text: str, clear: bool | Omit = omit, + completion_mode: Literal["accepted", "committed"] | Omit = omit, error_rate: float | Omit = omit, stealth: bool | Omit = omit, wpm: int | Omit = omit, @@ -309,13 +318,17 @@ async def write( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """Types the given text into the focused input field. + """Types text into the focused input field. - Supports optionally clearing - the field first and a stealth mode that emulates human typing speed and error - rate on supported devices. + The optional completionMode defaults to + accepted for backwards-compatible low latency; committed additionally waits for + the complete text or a quiescent UI state. Args: + completion_mode: Completion guarantee. accepted returns after the input provider accepts the + operation; committed additionally waits for the focused UI state to contain the + complete text or become quiescent. + error_rate: Per-character mistake rate for humantouch typing. -1 uses server default. wpm: Words per minute for stealth typing. 0 uses portal default. @@ -343,6 +356,7 @@ async def write( { "text": text, "clear": clear, + "completion_mode": completion_mode, "error_rate": error_rate, "stealth": stealth, "wpm": wpm, diff --git a/src/mobilerun_sdk/resources/devices/recordings.py b/src/mobilerun_sdk/resources/devices/recordings.py index 11ed0b6a..1591a3b8 100644 --- a/src/mobilerun_sdk/resources/devices/recordings.py +++ b/src/mobilerun_sdk/resources/devices/recordings.py @@ -135,6 +135,7 @@ def start( device_id: str, *, name: str | Omit = omit, + quality: int | Omit = omit, retention_days: int | Omit = omit, types: Optional[SequenceNotStr[str]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -148,6 +149,14 @@ def start( Start a device recording Args: + quality: Capture quality from 1 (lowest) to 10 (full stream quality). Defaults to the + device's full quality. Honored by devices recording through the portal stream + bridge. + + types: Artifacts to capture: trajectory (input actions), video, and audio (captured + into the video artifact, so it requires video; honored by portal stream-bridge + recorders). Defaults to trajectory and video. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -163,6 +172,7 @@ def start( body=maybe_transform( { "name": name, + "quality": quality, "retention_days": retention_days, "types": types, }, @@ -440,6 +450,7 @@ async def start( device_id: str, *, name: str | Omit = omit, + quality: int | Omit = omit, retention_days: int | Omit = omit, types: Optional[SequenceNotStr[str]] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -453,6 +464,14 @@ async def start( Start a device recording Args: + quality: Capture quality from 1 (lowest) to 10 (full stream quality). Defaults to the + device's full quality. Honored by devices recording through the portal stream + bridge. + + types: Artifacts to capture: trajectory (input actions), video, and audio (captured + into the video artifact, so it requires video; honored by portal stream-bridge + recorders). Defaults to trajectory and video. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -468,6 +487,7 @@ async def start( body=await async_maybe_transform( { "name": name, + "quality": quality, "retention_days": retention_days, "types": types, }, diff --git a/src/mobilerun_sdk/resources/devices/traffic_sessions.py b/src/mobilerun_sdk/resources/devices/traffic_sessions.py new file mode 100644 index 00000000..3a23caaf --- /dev/null +++ b/src/mobilerun_sdk/resources/devices/traffic_sessions.py @@ -0,0 +1,470 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import path_template, maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.devices import traffic_session_list_params, traffic_session_create_params +from ...types.devices.traffic_session_list_response import TrafficSessionListResponse +from ...types.devices.traffic_session_create_response import TrafficSessionCreateResponse +from ...types.devices.traffic_session_delete_response import TrafficSessionDeleteResponse +from ...types.devices.traffic_session_retrieve_response import TrafficSessionRetrieveResponse + +__all__ = ["TrafficSessionsResource", "AsyncTrafficSessionsResource"] + + +class TrafficSessionsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> TrafficSessionsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#accessing-raw-response-data-eg-headers + """ + return TrafficSessionsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> TrafficSessionsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#with_streaming_response + """ + return TrafficSessionsResourceWithStreamingResponse(self) + + def create( + self, + device_id: str, + *, + idempotency_key: str, + expires_in_seconds: int | Omit = omit, + max_body_bytes: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> TrafficSessionCreateResponse: + """ + Starts one live-only decoded HTTP/1.1, HTTP/2, HTTP/3 and WebSocket traffic + session. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not device_id: + raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}") + extra_headers = {"Idempotency-Key": idempotency_key, **(extra_headers or {})} + return self._post( + path_template("/devices/{device_id}/traffic/sessions", device_id=device_id), + body=maybe_transform( + { + "expires_in_seconds": expires_in_seconds, + "max_body_bytes": max_body_bytes, + }, + traffic_session_create_params.TrafficSessionCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TrafficSessionCreateResponse, + ) + + def retrieve( + self, + session_id: str, + *, + device_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> TrafficSessionRetrieveResponse: + """ + Returns status and the device stream credential for a live session. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not device_id: + raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}") + if not session_id: + raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") + return self._get( + path_template( + "/devices/{device_id}/traffic/sessions/{session_id}", device_id=device_id, session_id=session_id + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TrafficSessionRetrieveResponse, + ) + + def list( + self, + device_id: str, + *, + page: int | Omit = omit, + page_size: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> TrafficSessionListResponse: + """ + List device traffic sessions + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not device_id: + raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}") + return self._get( + path_template("/devices/{device_id}/traffic/sessions", device_id=device_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "page": page, + "page_size": page_size, + }, + traffic_session_list_params.TrafficSessionListParams, + ), + ), + cast_to=TrafficSessionListResponse, + ) + + def delete( + self, + session_id: str, + *, + device_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> TrafficSessionDeleteResponse: + """ + Stop device traffic inspection + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not device_id: + raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}") + if not session_id: + raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") + return self._delete( + path_template( + "/devices/{device_id}/traffic/sessions/{session_id}", device_id=device_id, session_id=session_id + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TrafficSessionDeleteResponse, + ) + + +class AsyncTrafficSessionsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncTrafficSessionsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncTrafficSessionsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncTrafficSessionsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#with_streaming_response + """ + return AsyncTrafficSessionsResourceWithStreamingResponse(self) + + async def create( + self, + device_id: str, + *, + idempotency_key: str, + expires_in_seconds: int | Omit = omit, + max_body_bytes: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> TrafficSessionCreateResponse: + """ + Starts one live-only decoded HTTP/1.1, HTTP/2, HTTP/3 and WebSocket traffic + session. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not device_id: + raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}") + extra_headers = {"Idempotency-Key": idempotency_key, **(extra_headers or {})} + return await self._post( + path_template("/devices/{device_id}/traffic/sessions", device_id=device_id), + body=await async_maybe_transform( + { + "expires_in_seconds": expires_in_seconds, + "max_body_bytes": max_body_bytes, + }, + traffic_session_create_params.TrafficSessionCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TrafficSessionCreateResponse, + ) + + async def retrieve( + self, + session_id: str, + *, + device_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> TrafficSessionRetrieveResponse: + """ + Returns status and the device stream credential for a live session. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not device_id: + raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}") + if not session_id: + raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") + return await self._get( + path_template( + "/devices/{device_id}/traffic/sessions/{session_id}", device_id=device_id, session_id=session_id + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TrafficSessionRetrieveResponse, + ) + + async def list( + self, + device_id: str, + *, + page: int | Omit = omit, + page_size: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> TrafficSessionListResponse: + """ + List device traffic sessions + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not device_id: + raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}") + return await self._get( + path_template("/devices/{device_id}/traffic/sessions", device_id=device_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "page": page, + "page_size": page_size, + }, + traffic_session_list_params.TrafficSessionListParams, + ), + ), + cast_to=TrafficSessionListResponse, + ) + + async def delete( + self, + session_id: str, + *, + device_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> TrafficSessionDeleteResponse: + """ + Stop device traffic inspection + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not device_id: + raise ValueError(f"Expected a non-empty value for `device_id` but received {device_id!r}") + if not session_id: + raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") + return await self._delete( + path_template( + "/devices/{device_id}/traffic/sessions/{session_id}", device_id=device_id, session_id=session_id + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TrafficSessionDeleteResponse, + ) + + +class TrafficSessionsResourceWithRawResponse: + def __init__(self, traffic_sessions: TrafficSessionsResource) -> None: + self._traffic_sessions = traffic_sessions + + self.create = to_raw_response_wrapper( + traffic_sessions.create, + ) + self.retrieve = to_raw_response_wrapper( + traffic_sessions.retrieve, + ) + self.list = to_raw_response_wrapper( + traffic_sessions.list, + ) + self.delete = to_raw_response_wrapper( + traffic_sessions.delete, + ) + + +class AsyncTrafficSessionsResourceWithRawResponse: + def __init__(self, traffic_sessions: AsyncTrafficSessionsResource) -> None: + self._traffic_sessions = traffic_sessions + + self.create = async_to_raw_response_wrapper( + traffic_sessions.create, + ) + self.retrieve = async_to_raw_response_wrapper( + traffic_sessions.retrieve, + ) + self.list = async_to_raw_response_wrapper( + traffic_sessions.list, + ) + self.delete = async_to_raw_response_wrapper( + traffic_sessions.delete, + ) + + +class TrafficSessionsResourceWithStreamingResponse: + def __init__(self, traffic_sessions: TrafficSessionsResource) -> None: + self._traffic_sessions = traffic_sessions + + self.create = to_streamed_response_wrapper( + traffic_sessions.create, + ) + self.retrieve = to_streamed_response_wrapper( + traffic_sessions.retrieve, + ) + self.list = to_streamed_response_wrapper( + traffic_sessions.list, + ) + self.delete = to_streamed_response_wrapper( + traffic_sessions.delete, + ) + + +class AsyncTrafficSessionsResourceWithStreamingResponse: + def __init__(self, traffic_sessions: AsyncTrafficSessionsResource) -> None: + self._traffic_sessions = traffic_sessions + + self.create = async_to_streamed_response_wrapper( + traffic_sessions.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + traffic_sessions.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + traffic_sessions.list, + ) + self.delete = async_to_streamed_response_wrapper( + traffic_sessions.delete, + ) diff --git a/src/mobilerun_sdk/resources/esims/__init__.py b/src/mobilerun_sdk/resources/esims/__init__.py deleted file mode 100644 index 394c2d72..00000000 --- a/src/mobilerun_sdk/resources/esims/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .esims import ( - EsimsResource, - AsyncEsimsResource, - EsimsResourceWithRawResponse, - AsyncEsimsResourceWithRawResponse, - EsimsResourceWithStreamingResponse, - AsyncEsimsResourceWithStreamingResponse, -) -from .messages import ( - MessagesResource, - AsyncMessagesResource, - MessagesResourceWithRawResponse, - AsyncMessagesResourceWithRawResponse, - MessagesResourceWithStreamingResponse, - AsyncMessagesResourceWithStreamingResponse, -) - -__all__ = [ - "MessagesResource", - "AsyncMessagesResource", - "MessagesResourceWithRawResponse", - "AsyncMessagesResourceWithRawResponse", - "MessagesResourceWithStreamingResponse", - "AsyncMessagesResourceWithStreamingResponse", - "EsimsResource", - "AsyncEsimsResource", - "EsimsResourceWithRawResponse", - "AsyncEsimsResourceWithRawResponse", - "EsimsResourceWithStreamingResponse", - "AsyncEsimsResourceWithStreamingResponse", -] diff --git a/src/mobilerun_sdk/resources/esims/esims.py b/src/mobilerun_sdk/resources/esims/esims.py deleted file mode 100644 index 49347cbe..00000000 --- a/src/mobilerun_sdk/resources/esims/esims.py +++ /dev/null @@ -1,1286 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import Literal - -import httpx - -from ...types import ( - esim_list_params, - esim_create_params, - esim_import_params, - esim_update_params, - esim_install_params, - esim_selector_params, -) -from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform -from .messages import ( - MessagesResource, - AsyncMessagesResource, - MessagesResourceWithRawResponse, - AsyncMessagesResourceWithRawResponse, - MessagesResourceWithStreamingResponse, - AsyncMessagesResourceWithStreamingResponse, -) -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ..._base_client import make_request_options -from ...types.esim_list_response import EsimListResponse -from ...types.esim_create_response import EsimCreateResponse -from ...types.esim_import_response import EsimImportResponse -from ...types.esim_update_response import EsimUpdateResponse -from ...types.esim_install_response import EsimInstallResponse -from ...types.esim_capacity_response import EsimCapacityResponse -from ...types.esim_retrieve_response import EsimRetrieveResponse -from ...types.esim_selector_response import EsimSelectorResponse -from ...types.esim_install_status_response import EsimInstallStatusResponse -from ...types.esim_confirm_payment_response import EsimConfirmPaymentResponse - -__all__ = ["EsimsResource", "AsyncEsimsResource"] - - -class EsimsResource(SyncAPIResource): - @cached_property - def messages(self) -> MessagesResource: - return MessagesResource(self._client) - - @cached_property - def with_raw_response(self) -> EsimsResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#accessing-raw-response-data-eg-headers - """ - return EsimsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> EsimsResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#with_streaming_response - """ - return EsimsResourceWithStreamingResponse(self) - - def create( - self, - *, - idempotency_key: str | Omit = omit, - name: Optional[str] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimCreateResponse: - """ - Purchases a physical eSIM from available inventory for the authenticated owner. - Returns 409 when no stock is available, or 402 with a billing checkout URL when - billing capacity is exhausted. - - Args: - idempotency_key: Client-supplied key; replaying the same key returns the original purchase - instead of buying again - - name: Optional user-defined display label — NFC-normalized, up to 15 GRAPHEMES. Omit - or null for no label. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._post( - "/numbers/esims", - body=maybe_transform( - { - "idempotency_key": idempotency_key, - "name": name, - }, - esim_create_params.EsimCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimCreateResponse, - ) - - def retrieve( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimRetrieveResponse: - """ - Retrieves a single physical eSIM. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._get( - path_template("/numbers/esims/{id}", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimRetrieveResponse, - ) - - def update( - self, - id: str, - *, - msisdn: Optional[str] | Omit = omit, - name: Optional[str] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimUpdateResponse: - """Updates the eSIM's self-reported msisdn and/or display name. - - Both fields are - optional, but the request body itself is required. Omitting a field leaves it - unchanged; setting it to null or an empty string clears it. `name` is capped at - 15 characters. Available regardless of the eSIM's current status. - - Args: - msisdn: Self-reported E.164 MSISDN for this eSIM's line. Omit to leave unchanged; - null/empty clears it. An unverified label — never used for routing. - - name: User-defined display label — NFC-normalized, up to 15 GRAPHEMES (not UTF-16 code - units; an emoji/flag may span several). Omit to leave unchanged; - null/empty/whitespace-only clears it. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._patch( - path_template("/numbers/esims/{id}", id=id), - body=maybe_transform( - { - "msisdn": msisdn, - "name": name, - }, - esim_update_params.EsimUpdateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimUpdateResponse, - ) - - def list( - self, - *, - mine: Literal["true", "false"] | Omit = omit, - page: int | Omit = omit, - page_size: int | Omit = omit, - status: Literal["all", "in_stock", "owned", "installing", "installed", "install_failed", "retired"] - | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimListResponse: - """ - Lists physical eSIMs owned by the authenticated owner. - - Args: - mine: Only include eSIMs created by the calling actor. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._get( - "/numbers/esims", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "mine": mine, - "page": page, - "page_size": page_size, - "status": status, - }, - esim_list_params.EsimListParams, - ), - ), - cast_to=EsimListResponse, - ) - - def delete( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """Removes a physical eSIM. - - Idempotent — returns 204 for a fresh removal or a - replay of an already-removed eSIM. An eSIM currently installed on a device is - uninstalled first, then removed. An eSIM in an intermediate install state - returns 409 `operator_resolution_required` and requires manual resolution. - Returns 404 if the eSIM doesn't exist or isn't owned by the caller. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._delete( - path_template("/numbers/esims/{id}", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def capacity( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimCapacityResponse: - """ - Reports whether a free device is currently available, for pre-checking the - import flow before upload. This is a hint only, not a reservation — - `POST /esims/import` re-checks availability at submit time. - """ - return self._get( - "/numbers/esims/capacity", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimCapacityResponse, - ) - - def confirm_payment( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimConfirmPaymentResponse: - """ - Checks for proof of payment for this eSIM's current rent and confirms it if - found. If no proof is available yet, returns 200 with the eSIM unchanged rather - than an error. Always returns the current eSIM state. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._post( - path_template("/numbers/esims/{id}/confirm-payment", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimConfirmPaymentResponse, - ) - - def import_( - self, - *, - auto_install: bool | Omit = omit, - carrier_name: str | Omit = omit, - confirmation_code: str | Omit = omit, - country_code: str | Omit = omit, - device_id: str | Omit = omit, - idempotency_key: str | Omit = omit, - lpa_code: str | Omit = omit, - matching_id: str | Omit = omit, - msisdn: str | Omit = omit, - name: Optional[str] | Omit = omit, - notes: str | Omit = omit, - smdp_address: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimImportResponse: - """ - Registers a bring-your-own (BYO) eSIM activation code as owned inventory. - Provide either `{ smdpAddress, matchingId?, confirmationCode? }` or - `{ lpaCode }` — supplying both, or neither, returns 400. An optional `name` sets - a display label on the created eSIM (up to 15 characters). - - Subject to per-owner and daily import limits, and disabled entirely unless BYO - imports are enabled for this deployment (409 `byo_disabled`). Idempotent via - `idempotencyKey`: replaying the same key with an identical request returns the - original response; the same key with a different request returns 409 - `idempotency_conflict`. - - When rent-first billing is off (default), the import is free — 201 with the - eSIM. Setting `autoInstall: true` additionally dispatches an install immediately - after import (`deviceId` may only be set together with `autoInstall`): this - returns 202 with `{esim, operationId, statusUrl}` when the install claim - succeeds (poll `GET /esims/{id}/install-status`), or 201 with the eSIM plus - `installDispatch: {ok: false, reason}` when the install could not be dispatched - — the import itself still succeeds either way. - - When rent-first billing is on, import additionally requires available device - capacity (409 `device_pool_empty`) and is subject to a per-owner - awaiting-payment cap (409 `byo_awaiting_payment_cap`). On success the eSIM is - created `awaiting_payment` and a checkout is started: 201 with - `{esim, rentStatus, checkoutUrl}` when the checkout URL is ready immediately, or - 202 with `checkoutUrl: null` otherwise — poll `GET /esims/{id}` until it's - populated. Once payment is confirmed, install is triggered automatically. - - Args: - auto_install: Rent OFF only: dispatch install-on-device immediately after a successful import. - No-op when ESIM_BYO_RENT_ENABLED=true. - - device_id: physedge device id to auto-install onto; requires autoInstall:true and rent OFF. - Omit for a random pool device. - - idempotency_key: Client-supplied key; replaying the same key+request returns the original import - instead of importing again - - lpa_code: Full LPA activation code - - msisdn: Self-reported E.164 MSISDN for this eSIM's line — an unverified label, never - used for routing - - name: User-defined display label — NFC-normalized, up to 15 GRAPHEMES (not UTF-16 code - units; an emoji/flag may span several). Omit/null/empty/whitespace-only leaves - it unset. - - smdp_address: SM-DP+ activation host — bare hostname ONLY, no port/scheme/path. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._post( - "/numbers/esims/import", - body=maybe_transform( - { - "auto_install": auto_install, - "carrier_name": carrier_name, - "confirmation_code": confirmation_code, - "country_code": country_code, - "device_id": device_id, - "idempotency_key": idempotency_key, - "lpa_code": lpa_code, - "matching_id": matching_id, - "msisdn": msisdn, - "name": name, - "notes": notes, - "smdp_address": smdp_address, - }, - esim_import_params.EsimImportParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimImportResponse, - ) - - def install( - self, - id: str, - *, - device_id: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimInstallResponse: - """Installs the eSIM's activation code onto a device. - - `deviceId` is optional — omit - it to use an available device from the pool. This call is asynchronous: it - returns 202 with `{esim, operationId, statusUrl}` immediately, and the result is - available by polling `GET /esims/{id}/install-status`. Retrying with the same - request is safe if a response is lost. - - Returns 409 when the eSIM is not in the `owned` state, or when no device is - currently available (see `reason`). When rent-first billing is enabled, a BYO - eSIM whose rent isn't active returns 402 with `{esim, rentStatus, checkoutUrl}` - instead. - - Args: - device_id: physedge device id to install the eSIM onto; omit for a random pool device - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._post( - path_template("/numbers/esims/{id}/install", id=id), - body=maybe_transform({"device_id": device_id}, esim_install_params.EsimInstallParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimInstallResponse, - ) - - def install_status( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimInstallStatusResponse: - """ - Returns the eSIM's current install status, checking for a terminal outcome if an - install is still in progress. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._get( - path_template("/numbers/esims/{id}/install-status", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimInstallStatusResponse, - ) - - def selector( - self, - *, - page: int | Omit = omit, - page_size: int | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimSelectorResponse: - """ - Returns a lightweight list (id, msisdn, carrierName, status, masked iccid) for - use in a message filter dropdown. Unlike `GET /esims`, this includes all - statuses, including retired eSIMs. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._get( - "/numbers/esims/selector", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "page": page, - "page_size": page_size, - }, - esim_selector_params.EsimSelectorParams, - ), - ), - cast_to=EsimSelectorResponse, - ) - - -class AsyncEsimsResource(AsyncAPIResource): - @cached_property - def messages(self) -> AsyncMessagesResource: - return AsyncMessagesResource(self._client) - - @cached_property - def with_raw_response(self) -> AsyncEsimsResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#accessing-raw-response-data-eg-headers - """ - return AsyncEsimsResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncEsimsResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#with_streaming_response - """ - return AsyncEsimsResourceWithStreamingResponse(self) - - async def create( - self, - *, - idempotency_key: str | Omit = omit, - name: Optional[str] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimCreateResponse: - """ - Purchases a physical eSIM from available inventory for the authenticated owner. - Returns 409 when no stock is available, or 402 with a billing checkout URL when - billing capacity is exhausted. - - Args: - idempotency_key: Client-supplied key; replaying the same key returns the original purchase - instead of buying again - - name: Optional user-defined display label — NFC-normalized, up to 15 GRAPHEMES. Omit - or null for no label. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._post( - "/numbers/esims", - body=await async_maybe_transform( - { - "idempotency_key": idempotency_key, - "name": name, - }, - esim_create_params.EsimCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimCreateResponse, - ) - - async def retrieve( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimRetrieveResponse: - """ - Retrieves a single physical eSIM. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._get( - path_template("/numbers/esims/{id}", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimRetrieveResponse, - ) - - async def update( - self, - id: str, - *, - msisdn: Optional[str] | Omit = omit, - name: Optional[str] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimUpdateResponse: - """Updates the eSIM's self-reported msisdn and/or display name. - - Both fields are - optional, but the request body itself is required. Omitting a field leaves it - unchanged; setting it to null or an empty string clears it. `name` is capped at - 15 characters. Available regardless of the eSIM's current status. - - Args: - msisdn: Self-reported E.164 MSISDN for this eSIM's line. Omit to leave unchanged; - null/empty clears it. An unverified label — never used for routing. - - name: User-defined display label — NFC-normalized, up to 15 GRAPHEMES (not UTF-16 code - units; an emoji/flag may span several). Omit to leave unchanged; - null/empty/whitespace-only clears it. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._patch( - path_template("/numbers/esims/{id}", id=id), - body=await async_maybe_transform( - { - "msisdn": msisdn, - "name": name, - }, - esim_update_params.EsimUpdateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimUpdateResponse, - ) - - async def list( - self, - *, - mine: Literal["true", "false"] | Omit = omit, - page: int | Omit = omit, - page_size: int | Omit = omit, - status: Literal["all", "in_stock", "owned", "installing", "installed", "install_failed", "retired"] - | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimListResponse: - """ - Lists physical eSIMs owned by the authenticated owner. - - Args: - mine: Only include eSIMs created by the calling actor. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._get( - "/numbers/esims", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "mine": mine, - "page": page, - "page_size": page_size, - "status": status, - }, - esim_list_params.EsimListParams, - ), - ), - cast_to=EsimListResponse, - ) - - async def delete( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """Removes a physical eSIM. - - Idempotent — returns 204 for a fresh removal or a - replay of an already-removed eSIM. An eSIM currently installed on a device is - uninstalled first, then removed. An eSIM in an intermediate install state - returns 409 `operator_resolution_required` and requires manual resolution. - Returns 404 if the eSIM doesn't exist or isn't owned by the caller. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._delete( - path_template("/numbers/esims/{id}", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - async def capacity( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimCapacityResponse: - """ - Reports whether a free device is currently available, for pre-checking the - import flow before upload. This is a hint only, not a reservation — - `POST /esims/import` re-checks availability at submit time. - """ - return await self._get( - "/numbers/esims/capacity", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimCapacityResponse, - ) - - async def confirm_payment( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimConfirmPaymentResponse: - """ - Checks for proof of payment for this eSIM's current rent and confirms it if - found. If no proof is available yet, returns 200 with the eSIM unchanged rather - than an error. Always returns the current eSIM state. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._post( - path_template("/numbers/esims/{id}/confirm-payment", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimConfirmPaymentResponse, - ) - - async def import_( - self, - *, - auto_install: bool | Omit = omit, - carrier_name: str | Omit = omit, - confirmation_code: str | Omit = omit, - country_code: str | Omit = omit, - device_id: str | Omit = omit, - idempotency_key: str | Omit = omit, - lpa_code: str | Omit = omit, - matching_id: str | Omit = omit, - msisdn: str | Omit = omit, - name: Optional[str] | Omit = omit, - notes: str | Omit = omit, - smdp_address: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimImportResponse: - """ - Registers a bring-your-own (BYO) eSIM activation code as owned inventory. - Provide either `{ smdpAddress, matchingId?, confirmationCode? }` or - `{ lpaCode }` — supplying both, or neither, returns 400. An optional `name` sets - a display label on the created eSIM (up to 15 characters). - - Subject to per-owner and daily import limits, and disabled entirely unless BYO - imports are enabled for this deployment (409 `byo_disabled`). Idempotent via - `idempotencyKey`: replaying the same key with an identical request returns the - original response; the same key with a different request returns 409 - `idempotency_conflict`. - - When rent-first billing is off (default), the import is free — 201 with the - eSIM. Setting `autoInstall: true` additionally dispatches an install immediately - after import (`deviceId` may only be set together with `autoInstall`): this - returns 202 with `{esim, operationId, statusUrl}` when the install claim - succeeds (poll `GET /esims/{id}/install-status`), or 201 with the eSIM plus - `installDispatch: {ok: false, reason}` when the install could not be dispatched - — the import itself still succeeds either way. - - When rent-first billing is on, import additionally requires available device - capacity (409 `device_pool_empty`) and is subject to a per-owner - awaiting-payment cap (409 `byo_awaiting_payment_cap`). On success the eSIM is - created `awaiting_payment` and a checkout is started: 201 with - `{esim, rentStatus, checkoutUrl}` when the checkout URL is ready immediately, or - 202 with `checkoutUrl: null` otherwise — poll `GET /esims/{id}` until it's - populated. Once payment is confirmed, install is triggered automatically. - - Args: - auto_install: Rent OFF only: dispatch install-on-device immediately after a successful import. - No-op when ESIM_BYO_RENT_ENABLED=true. - - device_id: physedge device id to auto-install onto; requires autoInstall:true and rent OFF. - Omit for a random pool device. - - idempotency_key: Client-supplied key; replaying the same key+request returns the original import - instead of importing again - - lpa_code: Full LPA activation code - - msisdn: Self-reported E.164 MSISDN for this eSIM's line — an unverified label, never - used for routing - - name: User-defined display label — NFC-normalized, up to 15 GRAPHEMES (not UTF-16 code - units; an emoji/flag may span several). Omit/null/empty/whitespace-only leaves - it unset. - - smdp_address: SM-DP+ activation host — bare hostname ONLY, no port/scheme/path. - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._post( - "/numbers/esims/import", - body=await async_maybe_transform( - { - "auto_install": auto_install, - "carrier_name": carrier_name, - "confirmation_code": confirmation_code, - "country_code": country_code, - "device_id": device_id, - "idempotency_key": idempotency_key, - "lpa_code": lpa_code, - "matching_id": matching_id, - "msisdn": msisdn, - "name": name, - "notes": notes, - "smdp_address": smdp_address, - }, - esim_import_params.EsimImportParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimImportResponse, - ) - - async def install( - self, - id: str, - *, - device_id: str | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimInstallResponse: - """Installs the eSIM's activation code onto a device. - - `deviceId` is optional — omit - it to use an available device from the pool. This call is asynchronous: it - returns 202 with `{esim, operationId, statusUrl}` immediately, and the result is - available by polling `GET /esims/{id}/install-status`. Retrying with the same - request is safe if a response is lost. - - Returns 409 when the eSIM is not in the `owned` state, or when no device is - currently available (see `reason`). When rent-first billing is enabled, a BYO - eSIM whose rent isn't active returns 402 with `{esim, rentStatus, checkoutUrl}` - instead. - - Args: - device_id: physedge device id to install the eSIM onto; omit for a random pool device - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._post( - path_template("/numbers/esims/{id}/install", id=id), - body=await async_maybe_transform({"device_id": device_id}, esim_install_params.EsimInstallParams), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimInstallResponse, - ) - - async def install_status( - self, - id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimInstallStatusResponse: - """ - Returns the eSIM's current install status, checking for a terminal outcome if an - install is still in progress. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._get( - path_template("/numbers/esims/{id}/install-status", id=id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=EsimInstallStatusResponse, - ) - - async def selector( - self, - *, - page: int | Omit = omit, - page_size: int | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> EsimSelectorResponse: - """ - Returns a lightweight list (id, msisdn, carrierName, status, masked iccid) for - use in a message filter dropdown. Unlike `GET /esims`, this includes all - statuses, including retired eSIMs. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._get( - "/numbers/esims/selector", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "page": page, - "page_size": page_size, - }, - esim_selector_params.EsimSelectorParams, - ), - ), - cast_to=EsimSelectorResponse, - ) - - -class EsimsResourceWithRawResponse: - def __init__(self, esims: EsimsResource) -> None: - self._esims = esims - - self.create = to_raw_response_wrapper( - esims.create, - ) - self.retrieve = to_raw_response_wrapper( - esims.retrieve, - ) - self.update = to_raw_response_wrapper( - esims.update, - ) - self.list = to_raw_response_wrapper( - esims.list, - ) - self.delete = to_raw_response_wrapper( - esims.delete, - ) - self.capacity = to_raw_response_wrapper( - esims.capacity, - ) - self.confirm_payment = to_raw_response_wrapper( - esims.confirm_payment, - ) - self.import_ = to_raw_response_wrapper( - esims.import_, - ) - self.install = to_raw_response_wrapper( - esims.install, - ) - self.install_status = to_raw_response_wrapper( - esims.install_status, - ) - self.selector = to_raw_response_wrapper( - esims.selector, - ) - - @cached_property - def messages(self) -> MessagesResourceWithRawResponse: - return MessagesResourceWithRawResponse(self._esims.messages) - - -class AsyncEsimsResourceWithRawResponse: - def __init__(self, esims: AsyncEsimsResource) -> None: - self._esims = esims - - self.create = async_to_raw_response_wrapper( - esims.create, - ) - self.retrieve = async_to_raw_response_wrapper( - esims.retrieve, - ) - self.update = async_to_raw_response_wrapper( - esims.update, - ) - self.list = async_to_raw_response_wrapper( - esims.list, - ) - self.delete = async_to_raw_response_wrapper( - esims.delete, - ) - self.capacity = async_to_raw_response_wrapper( - esims.capacity, - ) - self.confirm_payment = async_to_raw_response_wrapper( - esims.confirm_payment, - ) - self.import_ = async_to_raw_response_wrapper( - esims.import_, - ) - self.install = async_to_raw_response_wrapper( - esims.install, - ) - self.install_status = async_to_raw_response_wrapper( - esims.install_status, - ) - self.selector = async_to_raw_response_wrapper( - esims.selector, - ) - - @cached_property - def messages(self) -> AsyncMessagesResourceWithRawResponse: - return AsyncMessagesResourceWithRawResponse(self._esims.messages) - - -class EsimsResourceWithStreamingResponse: - def __init__(self, esims: EsimsResource) -> None: - self._esims = esims - - self.create = to_streamed_response_wrapper( - esims.create, - ) - self.retrieve = to_streamed_response_wrapper( - esims.retrieve, - ) - self.update = to_streamed_response_wrapper( - esims.update, - ) - self.list = to_streamed_response_wrapper( - esims.list, - ) - self.delete = to_streamed_response_wrapper( - esims.delete, - ) - self.capacity = to_streamed_response_wrapper( - esims.capacity, - ) - self.confirm_payment = to_streamed_response_wrapper( - esims.confirm_payment, - ) - self.import_ = to_streamed_response_wrapper( - esims.import_, - ) - self.install = to_streamed_response_wrapper( - esims.install, - ) - self.install_status = to_streamed_response_wrapper( - esims.install_status, - ) - self.selector = to_streamed_response_wrapper( - esims.selector, - ) - - @cached_property - def messages(self) -> MessagesResourceWithStreamingResponse: - return MessagesResourceWithStreamingResponse(self._esims.messages) - - -class AsyncEsimsResourceWithStreamingResponse: - def __init__(self, esims: AsyncEsimsResource) -> None: - self._esims = esims - - self.create = async_to_streamed_response_wrapper( - esims.create, - ) - self.retrieve = async_to_streamed_response_wrapper( - esims.retrieve, - ) - self.update = async_to_streamed_response_wrapper( - esims.update, - ) - self.list = async_to_streamed_response_wrapper( - esims.list, - ) - self.delete = async_to_streamed_response_wrapper( - esims.delete, - ) - self.capacity = async_to_streamed_response_wrapper( - esims.capacity, - ) - self.confirm_payment = async_to_streamed_response_wrapper( - esims.confirm_payment, - ) - self.import_ = async_to_streamed_response_wrapper( - esims.import_, - ) - self.install = async_to_streamed_response_wrapper( - esims.install, - ) - self.install_status = async_to_streamed_response_wrapper( - esims.install_status, - ) - self.selector = async_to_streamed_response_wrapper( - esims.selector, - ) - - @cached_property - def messages(self) -> AsyncMessagesResourceWithStreamingResponse: - return AsyncMessagesResourceWithStreamingResponse(self._esims.messages) diff --git a/src/mobilerun_sdk/resources/esims/messages.py b/src/mobilerun_sdk/resources/esims/messages.py deleted file mode 100644 index f6d7efad..00000000 --- a/src/mobilerun_sdk/resources/esims/messages.py +++ /dev/null @@ -1,352 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal - -import httpx - -from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ...types.esims import message_list_params, message_send_params -from ..._base_client import make_request_options -from ...types.esims.message_list_response import MessageListResponse -from ...types.esims.message_send_response import MessageSendResponse - -__all__ = ["MessagesResource", "AsyncMessagesResource"] - - -class MessagesResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> MessagesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#accessing-raw-response-data-eg-headers - """ - return MessagesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> MessagesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#with_streaming_response - """ - return MessagesResourceWithStreamingResponse(self) - - def list( - self, - id: str, - *, - direction: Literal["all", "inbound", "outbound"] | Omit = omit, - number_id: str | Omit = omit, - page: int | Omit = omit, - page_size: int | Omit = omit, - peer_key: str | Omit = omit, - peer_number: str | Omit = omit, - status: Literal[ - "all", "received", "queued", "claimed", "sending", "sent", "sent_unconfirmed", "delivered", "failed" - ] - | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> MessageListResponse: - """ - List messages for one eSIM - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._get( - path_template("/numbers/esims/{id}/messages", id=id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "direction": direction, - "number_id": number_id, - "page": page, - "page_size": page_size, - "peer_key": peer_key, - "peer_number": peer_number, - "status": status, - }, - message_list_params.MessageListParams, - ), - ), - cast_to=MessageListResponse, - ) - - def send( - self, - id: str, - *, - body: str, - to: str, - client_request_id: str | Omit = omit, - delivery_report: bool | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> MessageSendResponse: - """ - Send an SMS through one eSIM - - Args: - body: SMS body text (max 320 chars — smaller than the admin tier's cap; see the - schema's own doc comment for why) - - to: Recipient phone number — normalized to E.164 (spaces/dashes/dots stripped); - rejected with 400 if it doesn't validate as E.164 afterward. - - client_request_id: Client-supplied idempotency key, scoped to (owner, esimId, key). Replaying the - same key + identical payload returns the original send; the same key with a - DIFFERENT payload is a 409 conflict. - - delivery_report: Wait for physedge to confirm carrier delivery before completing the send (adds - executor-side latency, never on this request — sends are always async/202). - Defaults to false for the public tier (opt-in, unlike the admin tier's - default-true). - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return self._post( - path_template("/numbers/esims/{id}/messages", id=id), - body=maybe_transform( - { - "body": body, - "to": to, - "client_request_id": client_request_id, - "delivery_report": delivery_report, - }, - message_send_params.MessageSendParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=MessageSendResponse, - ) - - -class AsyncMessagesResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncMessagesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#accessing-raw-response-data-eg-headers - """ - return AsyncMessagesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncMessagesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/droidrun/mobilerun-sdk-python#with_streaming_response - """ - return AsyncMessagesResourceWithStreamingResponse(self) - - async def list( - self, - id: str, - *, - direction: Literal["all", "inbound", "outbound"] | Omit = omit, - number_id: str | Omit = omit, - page: int | Omit = omit, - page_size: int | Omit = omit, - peer_key: str | Omit = omit, - peer_number: str | Omit = omit, - status: Literal[ - "all", "received", "queued", "claimed", "sending", "sent", "sent_unconfirmed", "delivered", "failed" - ] - | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> MessageListResponse: - """ - List messages for one eSIM - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._get( - path_template("/numbers/esims/{id}/messages", id=id), - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "direction": direction, - "number_id": number_id, - "page": page, - "page_size": page_size, - "peer_key": peer_key, - "peer_number": peer_number, - "status": status, - }, - message_list_params.MessageListParams, - ), - ), - cast_to=MessageListResponse, - ) - - async def send( - self, - id: str, - *, - body: str, - to: str, - client_request_id: str | Omit = omit, - delivery_report: bool | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> MessageSendResponse: - """ - Send an SMS through one eSIM - - Args: - body: SMS body text (max 320 chars — smaller than the admin tier's cap; see the - schema's own doc comment for why) - - to: Recipient phone number — normalized to E.164 (spaces/dashes/dots stripped); - rejected with 400 if it doesn't validate as E.164 afterward. - - client_request_id: Client-supplied idempotency key, scoped to (owner, esimId, key). Replaying the - same key + identical payload returns the original send; the same key with a - DIFFERENT payload is a 409 conflict. - - delivery_report: Wait for physedge to confirm carrier delivery before completing the send (adds - executor-side latency, never on this request — sends are always async/202). - Defaults to false for the public tier (opt-in, unlike the admin tier's - default-true). - - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not id: - raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") - return await self._post( - path_template("/numbers/esims/{id}/messages", id=id), - body=await async_maybe_transform( - { - "body": body, - "to": to, - "client_request_id": client_request_id, - "delivery_report": delivery_report, - }, - message_send_params.MessageSendParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=MessageSendResponse, - ) - - -class MessagesResourceWithRawResponse: - def __init__(self, messages: MessagesResource) -> None: - self._messages = messages - - self.list = to_raw_response_wrapper( - messages.list, - ) - self.send = to_raw_response_wrapper( - messages.send, - ) - - -class AsyncMessagesResourceWithRawResponse: - def __init__(self, messages: AsyncMessagesResource) -> None: - self._messages = messages - - self.list = async_to_raw_response_wrapper( - messages.list, - ) - self.send = async_to_raw_response_wrapper( - messages.send, - ) - - -class MessagesResourceWithStreamingResponse: - def __init__(self, messages: MessagesResource) -> None: - self._messages = messages - - self.list = to_streamed_response_wrapper( - messages.list, - ) - self.send = to_streamed_response_wrapper( - messages.send, - ) - - -class AsyncMessagesResourceWithStreamingResponse: - def __init__(self, messages: AsyncMessagesResource) -> None: - self._messages = messages - - self.list = async_to_streamed_response_wrapper( - messages.list, - ) - self.send = async_to_streamed_response_wrapper( - messages.send, - ) diff --git a/src/mobilerun_sdk/resources/files.py b/src/mobilerun_sdk/resources/files.py index 739ba6f8..ee56372d 100644 --- a/src/mobilerun_sdk/resources/files.py +++ b/src/mobilerun_sdk/resources/files.py @@ -2,12 +2,11 @@ from __future__ import annotations -from typing import Optional from typing_extensions import Literal import httpx -from ..types import file_list_params, file_update_params, file_upload_url_params +from ..types import file_upload_url_params from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given from .._utils import path_template, maybe_transform, strip_not_given, async_maybe_transform from .._compat import cached_property @@ -19,10 +18,7 @@ async_to_streamed_response_wrapper, ) from .._base_client import make_request_options -from ..types.file_list_response import FileListResponse from ..types.file_delete_response import FileDeleteResponse -from ..types.file_update_response import FileUpdateResponse -from ..types.file_confirm_response import FileConfirmResponse from ..types.file_upload_url_response import FileUploadURLResponse from ..types.file_cancel_pending_response import FileCancelPendingResponse @@ -49,85 +45,6 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: """ return FilesResourceWithStreamingResponse(self) - def update( - self, - file_id: str, - *, - display_name: Optional[str] | Omit = omit, - enabled: bool | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> FileUpdateResponse: - """Partial update of `displayName` and/or `enabled`. - - Only files with `zone=skills` - are mutable; other zones return 422 `unsupported_zone`. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not file_id: - raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - return self._patch( - path_template("/agents/files/{file_id}", file_id=file_id), - body=maybe_transform( - { - "display_name": display_name, - "enabled": enabled, - }, - file_update_params.FileUpdateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=FileUpdateResponse, - ) - - def list( - self, - *, - zone: Literal["user", "agent", "workflow", "skills"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> FileListResponse: - """ - List the user's ready files, optionally filtered by zone - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return self._get( - "/agents/files", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"zone": zone}, file_list_params.FileListParams), - ), - cast_to=FileListResponse, - ) - def delete( self, file_id: str, @@ -197,39 +114,6 @@ def cancel_pending( cast_to=FileCancelPendingResponse, ) - def confirm( - self, - file_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> FileConfirmResponse: - """ - Confirm a file upload by server-side HEAD validation - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not file_id: - raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - return self._post( - path_template("/agents/files/{file_id}/confirm", file_id=file_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=FileConfirmResponse, - ) - def download( self, file_id: str, @@ -332,85 +216,6 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: """ return AsyncFilesResourceWithStreamingResponse(self) - async def update( - self, - file_id: str, - *, - display_name: Optional[str] | Omit = omit, - enabled: bool | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> FileUpdateResponse: - """Partial update of `displayName` and/or `enabled`. - - Only files with `zone=skills` - are mutable; other zones return 422 `unsupported_zone`. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not file_id: - raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - return await self._patch( - path_template("/agents/files/{file_id}", file_id=file_id), - body=await async_maybe_transform( - { - "display_name": display_name, - "enabled": enabled, - }, - file_update_params.FileUpdateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=FileUpdateResponse, - ) - - async def list( - self, - *, - zone: Literal["user", "agent", "workflow", "skills"] | Omit = omit, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> FileListResponse: - """ - List the user's ready files, optionally filtered by zone - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - return await self._get( - "/agents/files", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform({"zone": zone}, file_list_params.FileListParams), - ), - cast_to=FileListResponse, - ) - async def delete( self, file_id: str, @@ -480,39 +285,6 @@ async def cancel_pending( cast_to=FileCancelPendingResponse, ) - async def confirm( - self, - file_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> FileConfirmResponse: - """ - Confirm a file upload by server-side HEAD validation - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not file_id: - raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") - return await self._post( - path_template("/agents/files/{file_id}/confirm", file_id=file_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=FileConfirmResponse, - ) - async def download( self, file_id: str, @@ -599,21 +371,12 @@ class FilesResourceWithRawResponse: def __init__(self, files: FilesResource) -> None: self._files = files - self.update = to_raw_response_wrapper( - files.update, - ) - self.list = to_raw_response_wrapper( - files.list, - ) self.delete = to_raw_response_wrapper( files.delete, ) self.cancel_pending = to_raw_response_wrapper( files.cancel_pending, ) - self.confirm = to_raw_response_wrapper( - files.confirm, - ) self.download = to_raw_response_wrapper( files.download, ) @@ -626,21 +389,12 @@ class AsyncFilesResourceWithRawResponse: def __init__(self, files: AsyncFilesResource) -> None: self._files = files - self.update = async_to_raw_response_wrapper( - files.update, - ) - self.list = async_to_raw_response_wrapper( - files.list, - ) self.delete = async_to_raw_response_wrapper( files.delete, ) self.cancel_pending = async_to_raw_response_wrapper( files.cancel_pending, ) - self.confirm = async_to_raw_response_wrapper( - files.confirm, - ) self.download = async_to_raw_response_wrapper( files.download, ) @@ -653,21 +407,12 @@ class FilesResourceWithStreamingResponse: def __init__(self, files: FilesResource) -> None: self._files = files - self.update = to_streamed_response_wrapper( - files.update, - ) - self.list = to_streamed_response_wrapper( - files.list, - ) self.delete = to_streamed_response_wrapper( files.delete, ) self.cancel_pending = to_streamed_response_wrapper( files.cancel_pending, ) - self.confirm = to_streamed_response_wrapper( - files.confirm, - ) self.download = to_streamed_response_wrapper( files.download, ) @@ -680,21 +425,12 @@ class AsyncFilesResourceWithStreamingResponse: def __init__(self, files: AsyncFilesResource) -> None: self._files = files - self.update = async_to_streamed_response_wrapper( - files.update, - ) - self.list = async_to_streamed_response_wrapper( - files.list, - ) self.delete = async_to_streamed_response_wrapper( files.delete, ) self.cancel_pending = async_to_streamed_response_wrapper( files.cancel_pending, ) - self.confirm = async_to_streamed_response_wrapper( - files.confirm, - ) self.download = async_to_streamed_response_wrapper( files.download, ) diff --git a/src/mobilerun_sdk/resources/mailboxes/mailboxes.py b/src/mobilerun_sdk/resources/mailboxes/mailboxes.py index 0a62f3c9..50e03570 100644 --- a/src/mobilerun_sdk/resources/mailboxes/mailboxes.py +++ b/src/mobilerun_sdk/resources/mailboxes/mailboxes.py @@ -75,7 +75,8 @@ def create( self, *, client_request_id: str, - billing_preference: Literal["included", "rent"] | Omit = omit, + billing_preference: Literal["included", "included_only", "rent"] | Omit = omit, + domain_id: str | Omit = omit, label: str | Omit = omit, local_part: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -85,22 +86,22 @@ def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MailboxCreateResponse: - """ - Reserves a permanently-allocated, individually-rented mailbox and starts an - Autumn rental checkout. An optional localPart selects the full address local - part; omitting it keeps the default random, non-guessable mx\\__-prefixed address. - The address is withheld until the first payment is confirmed. Idempotent on - (owner, clientRequestId): same key + payload replays (200); a conflicting or - already-held local part returns 409. 201 when the checkout URL is already - persisted, otherwise 202 (poll GET for the URL). + """Creates a mailbox on the default domain or a connected custom domain. + + An + optional `localPart` selects the address. Replaying the same `clientRequestId` + and payload returns the original mailbox. Poll the mailbox when a 202 response + does not yet include a checkout URL. Args: - billing_preference: Funding preference. Omit or use included for included-first activation; rent - always preserves package capacity and starts paid checkout. + billing_preference: included uses package capacity when available and otherwise starts paid + checkout; included_only fails without creating a paid reservation when no + included slot remains; rent always starts paid checkout. + + domain_id: Optional active custom mailbox domain owned by the caller. Omit to use the + system domain. - local_part: Optional full mailbox local part (the address before "@"). Trimmed and - lowercased before validation. Omit for a random, non-guessable mx\\__-prefixed - address. + local_part: Optional mailbox name before the "@". Omit to generate a random address. extra_headers: Send extra headers @@ -116,6 +117,7 @@ def create( { "client_request_id": client_request_id, "billing_preference": billing_preference, + "domain_id": domain_id, "label": label, "local_part": local_part, }, @@ -248,12 +250,9 @@ def delete( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MailboxDeleteResponse: - """For paid rent, schedules end-of-cycle cancellation. - - For an included generation, - archives immediately and releases its package seat. This never deletes the - mailbox, its address, or its messages — the address is permanently reserved. - Idempotent. + """ + Cancels a pending mailbox or schedules an active paid mailbox for cancellation. + Existing addresses and messages are retained. Repeating the request is safe. Args: extra_headers: Send extra headers @@ -284,10 +283,7 @@ def capacity( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MailboxCapacityResponse: - """ - Returns the authoritative number of package-funded mailbox claims currently - available after local reservations. - """ + """Returns the number of mailboxes currently available through included capacity.""" return self._get( "/mailboxes/capacity", options=make_request_options( @@ -311,10 +307,10 @@ def otp( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MailboxOtpResponse: - """ - Returns the highest-confidence, most recent OTP for the mailbox, restricted to - messages of completed/active paid intervals. Does not wait server-side (SDKs - poll). 200 with the best code, 204 when none matches. + """Returns the most likely recent OTP for the mailbox. + + Returns 204 when no matching + code is available. Args: extra_headers: Send extra headers @@ -351,7 +347,7 @@ def restart( self, mailbox_id: str, *, - billing_preference: Literal["included", "rent"] | Omit = omit, + billing_preference: Literal["included", "included_only", "rent"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -359,13 +355,15 @@ def restart( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MailboxRestartResponse: - """ - Starts a new generation on an archived mailbox, reusing the same permanent - address. Uses included capacity first unless paid rent is requested. + """Restarts an archived mailbox with the same address. + + Uses included capacity when + available unless paid service is requested. Args: - billing_preference: Funding preference. Omit or use included for included-first activation; rent - always preserves package capacity and starts paid checkout. + billing_preference: included uses package capacity when available and otherwise starts paid + checkout; included_only fails without creating a paid reservation when no + included slot remains; rent always starts paid checkout. extra_headers: Send extra headers @@ -399,10 +397,10 @@ def uncancel( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MailboxUncancelResponse: - """Retracts a scheduled end-of-cycle cancellation for the current generation. + """Withdraws a scheduled cancellation. - Only - valid while cancellation is pending. + Only available while cancellation is + pending. Args: extra_headers: Send extra headers @@ -452,7 +450,8 @@ async def create( self, *, client_request_id: str, - billing_preference: Literal["included", "rent"] | Omit = omit, + billing_preference: Literal["included", "included_only", "rent"] | Omit = omit, + domain_id: str | Omit = omit, label: str | Omit = omit, local_part: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -462,22 +461,22 @@ async def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MailboxCreateResponse: - """ - Reserves a permanently-allocated, individually-rented mailbox and starts an - Autumn rental checkout. An optional localPart selects the full address local - part; omitting it keeps the default random, non-guessable mx\\__-prefixed address. - The address is withheld until the first payment is confirmed. Idempotent on - (owner, clientRequestId): same key + payload replays (200); a conflicting or - already-held local part returns 409. 201 when the checkout URL is already - persisted, otherwise 202 (poll GET for the URL). + """Creates a mailbox on the default domain or a connected custom domain. + + An + optional `localPart` selects the address. Replaying the same `clientRequestId` + and payload returns the original mailbox. Poll the mailbox when a 202 response + does not yet include a checkout URL. Args: - billing_preference: Funding preference. Omit or use included for included-first activation; rent - always preserves package capacity and starts paid checkout. + billing_preference: included uses package capacity when available and otherwise starts paid + checkout; included_only fails without creating a paid reservation when no + included slot remains; rent always starts paid checkout. + + domain_id: Optional active custom mailbox domain owned by the caller. Omit to use the + system domain. - local_part: Optional full mailbox local part (the address before "@"). Trimmed and - lowercased before validation. Omit for a random, non-guessable mx\\__-prefixed - address. + local_part: Optional mailbox name before the "@". Omit to generate a random address. extra_headers: Send extra headers @@ -493,6 +492,7 @@ async def create( { "client_request_id": client_request_id, "billing_preference": billing_preference, + "domain_id": domain_id, "label": label, "local_part": local_part, }, @@ -625,12 +625,9 @@ async def delete( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MailboxDeleteResponse: - """For paid rent, schedules end-of-cycle cancellation. - - For an included generation, - archives immediately and releases its package seat. This never deletes the - mailbox, its address, or its messages — the address is permanently reserved. - Idempotent. + """ + Cancels a pending mailbox or schedules an active paid mailbox for cancellation. + Existing addresses and messages are retained. Repeating the request is safe. Args: extra_headers: Send extra headers @@ -661,10 +658,7 @@ async def capacity( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MailboxCapacityResponse: - """ - Returns the authoritative number of package-funded mailbox claims currently - available after local reservations. - """ + """Returns the number of mailboxes currently available through included capacity.""" return await self._get( "/mailboxes/capacity", options=make_request_options( @@ -688,10 +682,10 @@ async def otp( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MailboxOtpResponse: - """ - Returns the highest-confidence, most recent OTP for the mailbox, restricted to - messages of completed/active paid intervals. Does not wait server-side (SDKs - poll). 200 with the best code, 204 when none matches. + """Returns the most likely recent OTP for the mailbox. + + Returns 204 when no matching + code is available. Args: extra_headers: Send extra headers @@ -728,7 +722,7 @@ async def restart( self, mailbox_id: str, *, - billing_preference: Literal["included", "rent"] | Omit = omit, + billing_preference: Literal["included", "included_only", "rent"] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -736,13 +730,15 @@ async def restart( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MailboxRestartResponse: - """ - Starts a new generation on an archived mailbox, reusing the same permanent - address. Uses included capacity first unless paid rent is requested. + """Restarts an archived mailbox with the same address. + + Uses included capacity when + available unless paid service is requested. Args: - billing_preference: Funding preference. Omit or use included for included-first activation; rent - always preserves package capacity and starts paid checkout. + billing_preference: included uses package capacity when available and otherwise starts paid + checkout; included_only fails without creating a paid reservation when no + included slot remains; rent always starts paid checkout. extra_headers: Send extra headers @@ -776,10 +772,10 @@ async def uncancel( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MailboxUncancelResponse: - """Retracts a scheduled end-of-cycle cancellation for the current generation. + """Withdraws a scheduled cancellation. - Only - valid while cancellation is pending. + Only available while cancellation is + pending. Args: extra_headers: Send extra headers diff --git a/src/mobilerun_sdk/resources/mailboxes/messages.py b/src/mobilerun_sdk/resources/mailboxes/messages.py index d1baa1f8..2e7c54cd 100644 --- a/src/mobilerun_sdk/resources/mailboxes/messages.py +++ b/src/mobilerun_sdk/resources/mailboxes/messages.py @@ -101,8 +101,8 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MessageListResponse: """ - Lists messages for a mailbox with keyset pagination and time/sender/hasOtp - filters for polling. + Lists mailbox messages with cursor pagination and optional time, sender, and OTP + filters. Args: extra_headers: Send extra headers @@ -212,8 +212,8 @@ async def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MessageListResponse: """ - Lists messages for a mailbox with keyset pagination and time/sender/hasOtp - filters for polling. + Lists mailbox messages with cursor pagination and optional time, sender, and OTP + filters. Args: extra_headers: Send extra headers diff --git a/src/mobilerun_sdk/resources/messages/conversations.py b/src/mobilerun_sdk/resources/messages/conversations.py index 9ef14bfa..397a5a3e 100644 --- a/src/mobilerun_sdk/resources/messages/conversations.py +++ b/src/mobilerun_sdk/resources/messages/conversations.py @@ -60,19 +60,10 @@ def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ConversationListResponse: - """Lists the caller's own SMS conversations, one row per thread. + """Lists SMS conversations by recent activity. - Each row includes - the most recent message in the thread, its unread inbound count, and the eSIMs - it was seen through. Optional `esimId` or `numberId` narrows to threads on one - eSIM or number. - - Cursor-paginated via `limit` (default 20, max 100) and - `cursorLastOccurredAt`/`cursorLastMessageId` (both required together, taken from - a previous page's `nextCursor`). Pagination follows each thread's most recent - activity rather than a fixed snapshot, so a thread with new activity can move - ahead of an in-progress page fetch. Clients that need a stable ordering should - snapshot their own view. + Use both cursor fields from + `nextCursor` to fetch the next page. Args: extra_headers: Send extra headers @@ -118,10 +109,8 @@ def mark_read( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ConversationMarkReadResponse: """ - Marks the caller's own inbound messages in a conversation thread as read, up to - and including the given `(upToOccurredAt, upToMessageId)` cursor — typically a - conversation row's `lastMessage`. Idempotent: repeating the call with the same - cursor updates 0 rows. Returns the number of rows updated. + Marks inbound messages in a conversation as read through the supplied cursor. + Repeating the request is safe. Args: peer_key: The thread's canonical peer key (see GET .../conversations) @@ -189,19 +178,10 @@ async def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ConversationListResponse: - """Lists the caller's own SMS conversations, one row per thread. - - Each row includes - the most recent message in the thread, its unread inbound count, and the eSIMs - it was seen through. Optional `esimId` or `numberId` narrows to threads on one - eSIM or number. + """Lists SMS conversations by recent activity. - Cursor-paginated via `limit` (default 20, max 100) and - `cursorLastOccurredAt`/`cursorLastMessageId` (both required together, taken from - a previous page's `nextCursor`). Pagination follows each thread's most recent - activity rather than a fixed snapshot, so a thread with new activity can move - ahead of an in-progress page fetch. Clients that need a stable ordering should - snapshot their own view. + Use both cursor fields from + `nextCursor` to fetch the next page. Args: extra_headers: Send extra headers @@ -247,10 +227,8 @@ async def mark_read( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ConversationMarkReadResponse: """ - Marks the caller's own inbound messages in a conversation thread as read, up to - and including the given `(upToOccurredAt, upToMessageId)` cursor — typically a - conversation row's `lastMessage`. Idempotent: repeating the call with the same - cursor updates 0 rows. Returns the number of rows updated. + Marks inbound messages in a conversation as read through the supplied cursor. + Repeating the request is safe. Args: peer_key: The thread's canonical peer key (see GET .../conversations) diff --git a/src/mobilerun_sdk/resources/messages/messages.py b/src/mobilerun_sdk/resources/messages/messages.py index 2e5f30b6..49cc99a2 100644 --- a/src/mobilerun_sdk/resources/messages/messages.py +++ b/src/mobilerun_sdk/resources/messages/messages.py @@ -76,12 +76,9 @@ def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MessageListResponse: - """Lists the caller's own SMS messages, newest first. - - Supports filtering by - direction, esimId, numberId, status, peerNumber (substring search, min 3 - characters), and peerKey (exact thread match). Each row includes its canonical - thread key (`peerKey`). + """ + Lists SMS messages newest first, with filters for direction, eSIM, phone number, + status, and conversation. Args: extra_headers: Send extra headers @@ -162,12 +159,9 @@ async def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MessageListResponse: - """Lists the caller's own SMS messages, newest first. - - Supports filtering by - direction, esimId, numberId, status, peerNumber (substring search, min 3 - characters), and peerKey (exact thread match). Each row includes its canonical - thread key (`peerKey`). + """ + Lists SMS messages newest first, with filters for direction, eSIM, phone number, + status, and conversation. Args: extra_headers: Send extra headers diff --git a/src/mobilerun_sdk/resources/numbers/numbers.py b/src/mobilerun_sdk/resources/numbers/numbers.py index 7b39353f..76972e69 100644 --- a/src/mobilerun_sdk/resources/numbers/numbers.py +++ b/src/mobilerun_sdk/resources/numbers/numbers.py @@ -7,7 +7,7 @@ import httpx -from ...types import number_list_params, number_create_params, number_update_params +from ...types import number_list_params, number_create_params, number_update_params, number_capacity_params from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given from ..._utils import path_template, maybe_transform, strip_not_given, async_maybe_transform from .messages import ( @@ -31,6 +31,7 @@ from ...types.number_create_response import NumberCreateResponse from ...types.number_delete_response import NumberDeleteResponse from ...types.number_update_response import NumberUpdateResponse +from ...types.number_capacity_response import NumberCapacityResponse from ...types.number_purposes_response import NumberPurposesResponse from ...types.number_retrieve_response import NumberRetrieveResponse from ...types.number_countries_response import NumberCountriesResponse @@ -65,7 +66,7 @@ def with_streaming_response(self) -> NumbersResourceWithStreamingResponse: def create( self, *, - billing_preference: Literal["included", "rent"] | Omit = omit, + billing_preference: Literal["included", "included_only", "rent"] | Omit = omit, country: str | Omit = omit, label: Optional[str] | Omit = omit, purpose: str | Omit = omit, @@ -77,24 +78,23 @@ def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberCreateResponse: - """Starts a Mobilerun Phone purchase for the authenticated owner. + """Starts a phone-number purchase. - Accepted requests - always return the same asynchronous envelope; poll GET /numbers/phones/{id} for - its business state. `purpose` and `country` are mutually exclusive. + Poll the returned phone number for status + updates. `purpose` and `country` cannot be combined. Args: - billing_preference: Prefer a free package seat ('included', default) or force the paid checkout - ('rent') + billing_preference: Use included capacity when available, require included capacity without paid + fallback (included_only), or start a paid checkout (rent). - country: Optional ISO 3166-1 alpha-2 country code from GET /numbers/countries. Cannot be - combined with `purpose`. + country: Optional ISO 3166-1 alpha-2 country code from GET /numbers/phones/countries. + Cannot be combined with `purpose`. label: User-defined display label — NFC-normalized, up to 100 GRAPHEMES (not UTF-16 code units; an emoji/flag may span several). Display-only, never used for routing. Also seeds the billing entity name at purchase. - purpose: Optional Mobilerun Phone purpose slug from GET /numbers/purposes. + purpose: Optional purpose from GET /numbers/phones/purposes. idempotency_key: Optional request idempotency key. @@ -169,13 +169,10 @@ def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberUpdateResponse: - """Updates the phone number's user-defined display label. + """Updates the display label. - Omitting `label` leaves - it unchanged; setting it to null or an empty string clears it. The label is - capped at 100 characters, is display-only, and never affects routing. It also - seeds the billing entity name when set at purchase time; a later change here - does not rename the already-created billing entity. + Omitting `label` leaves it unchanged; null or an + empty string clears it. Args: label: User-defined display label — NFC-normalized, up to 100 GRAPHEMES (not UTF-16 @@ -214,8 +211,7 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberListResponse: """ - Lists phone numbers owned by the authenticated user — both BYO (`user`) and - provisioned (`mobilerun`) numbers. + Lists the caller's phone numbers. Args: extra_headers: Send extra headers @@ -255,25 +251,10 @@ def delete( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberDeleteResponse: - """Cancels a Mobilerun Phone. - - The outcome depends on the number's current state: - - - If the number is still awaiting payment and no payment for it is currently - being processed, the checkout is closed immediately and the number is retired. - - If the number is on the standard paid plan and already paid and in service, - cancellation is scheduled for the end of the current billing period rather - than taking effect immediately. The number stays usable through the period - already paid for, with no partial refund. Calling this again while a - cancellation is already scheduled is a no-op that returns the same result. The - response's `state` reflects this as `cancel_scheduled` with - `cancelAtPeriodEnd: true`; `currentPeriodEnd` is populated once billing - confirms the cancellation. - - Any other state (already refunding, a permanent billing failure, a payment - currently being processed, an included-plan number, or a non-hosted/BYO number) - returns 409 `not_cancellable`. Returns 404 if the number doesn't exist or isn't - owned by the caller. + """ + Cancels a pending purchase or schedules cancellation of an active paid phone + number. Repeating a scheduled cancellation is safe. Returns 409 when + cancellation is not available. Args: extra_headers: Send extra headers @@ -294,6 +275,45 @@ def delete( cast_to=NumberDeleteResponse, ) + def capacity( + self, + *, + country: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> NumberCapacityResponse: + """Returns included phone capacity for a country. + + Creating a phone is + authoritative. + + Args: + country: ISO 3166-1 alpha-2 country code from GET /numbers/phones/countries. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/numbers/phones/capacity", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"country": country}, number_capacity_params.NumberCapacityParams), + ), + cast_to=NumberCapacityResponse, + ) + def countries( self, *, @@ -304,10 +324,7 @@ def countries( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberCountriesResponse: - """ - Lists the countries currently offered for a dedicated Mobilerun Phone, with live - stock status. Pass `country` as the `country` field on POST /numbers/phones. - """ + """Lists available countries and current phone-number availability.""" return self._get( "/numbers/phones/countries", options=make_request_options( @@ -363,7 +380,7 @@ def with_streaming_response(self) -> AsyncNumbersResourceWithStreamingResponse: async def create( self, *, - billing_preference: Literal["included", "rent"] | Omit = omit, + billing_preference: Literal["included", "included_only", "rent"] | Omit = omit, country: str | Omit = omit, label: Optional[str] | Omit = omit, purpose: str | Omit = omit, @@ -375,24 +392,23 @@ async def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberCreateResponse: - """Starts a Mobilerun Phone purchase for the authenticated owner. + """Starts a phone-number purchase. - Accepted requests - always return the same asynchronous envelope; poll GET /numbers/phones/{id} for - its business state. `purpose` and `country` are mutually exclusive. + Poll the returned phone number for status + updates. `purpose` and `country` cannot be combined. Args: - billing_preference: Prefer a free package seat ('included', default) or force the paid checkout - ('rent') + billing_preference: Use included capacity when available, require included capacity without paid + fallback (included_only), or start a paid checkout (rent). - country: Optional ISO 3166-1 alpha-2 country code from GET /numbers/countries. Cannot be - combined with `purpose`. + country: Optional ISO 3166-1 alpha-2 country code from GET /numbers/phones/countries. + Cannot be combined with `purpose`. label: User-defined display label — NFC-normalized, up to 100 GRAPHEMES (not UTF-16 code units; an emoji/flag may span several). Display-only, never used for routing. Also seeds the billing entity name at purchase. - purpose: Optional Mobilerun Phone purpose slug from GET /numbers/purposes. + purpose: Optional purpose from GET /numbers/phones/purposes. idempotency_key: Optional request idempotency key. @@ -467,13 +483,10 @@ async def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberUpdateResponse: - """Updates the phone number's user-defined display label. + """Updates the display label. - Omitting `label` leaves - it unchanged; setting it to null or an empty string clears it. The label is - capped at 100 characters, is display-only, and never affects routing. It also - seeds the billing entity name when set at purchase time; a later change here - does not rename the already-created billing entity. + Omitting `label` leaves it unchanged; null or an + empty string clears it. Args: label: User-defined display label — NFC-normalized, up to 100 GRAPHEMES (not UTF-16 @@ -512,8 +525,7 @@ async def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberListResponse: """ - Lists phone numbers owned by the authenticated user — both BYO (`user`) and - provisioned (`mobilerun`) numbers. + Lists the caller's phone numbers. Args: extra_headers: Send extra headers @@ -553,25 +565,10 @@ async def delete( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberDeleteResponse: - """Cancels a Mobilerun Phone. - - The outcome depends on the number's current state: - - - If the number is still awaiting payment and no payment for it is currently - being processed, the checkout is closed immediately and the number is retired. - - If the number is on the standard paid plan and already paid and in service, - cancellation is scheduled for the end of the current billing period rather - than taking effect immediately. The number stays usable through the period - already paid for, with no partial refund. Calling this again while a - cancellation is already scheduled is a no-op that returns the same result. The - response's `state` reflects this as `cancel_scheduled` with - `cancelAtPeriodEnd: true`; `currentPeriodEnd` is populated once billing - confirms the cancellation. - - Any other state (already refunding, a permanent billing failure, a payment - currently being processed, an included-plan number, or a non-hosted/BYO number) - returns 409 `not_cancellable`. Returns 404 if the number doesn't exist or isn't - owned by the caller. + """ + Cancels a pending purchase or schedules cancellation of an active paid phone + number. Repeating a scheduled cancellation is safe. Returns 409 when + cancellation is not available. Args: extra_headers: Send extra headers @@ -592,6 +589,45 @@ async def delete( cast_to=NumberDeleteResponse, ) + async def capacity( + self, + *, + country: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> NumberCapacityResponse: + """Returns included phone capacity for a country. + + Creating a phone is + authoritative. + + Args: + country: ISO 3166-1 alpha-2 country code from GET /numbers/phones/countries. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/numbers/phones/capacity", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"country": country}, number_capacity_params.NumberCapacityParams), + ), + cast_to=NumberCapacityResponse, + ) + async def countries( self, *, @@ -602,10 +638,7 @@ async def countries( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberCountriesResponse: - """ - Lists the countries currently offered for a dedicated Mobilerun Phone, with live - stock status. Pass `country` as the `country` field on POST /numbers/phones. - """ + """Lists available countries and current phone-number availability.""" return await self._get( "/numbers/phones/countries", options=make_request_options( @@ -653,6 +686,9 @@ def __init__(self, numbers: NumbersResource) -> None: self.delete = to_raw_response_wrapper( numbers.delete, ) + self.capacity = to_raw_response_wrapper( + numbers.capacity, + ) self.countries = to_raw_response_wrapper( numbers.countries, ) @@ -684,6 +720,9 @@ def __init__(self, numbers: AsyncNumbersResource) -> None: self.delete = async_to_raw_response_wrapper( numbers.delete, ) + self.capacity = async_to_raw_response_wrapper( + numbers.capacity, + ) self.countries = async_to_raw_response_wrapper( numbers.countries, ) @@ -715,6 +754,9 @@ def __init__(self, numbers: NumbersResource) -> None: self.delete = to_streamed_response_wrapper( numbers.delete, ) + self.capacity = to_streamed_response_wrapper( + numbers.capacity, + ) self.countries = to_streamed_response_wrapper( numbers.countries, ) @@ -746,6 +788,9 @@ def __init__(self, numbers: AsyncNumbersResource) -> None: self.delete = async_to_streamed_response_wrapper( numbers.delete, ) + self.capacity = async_to_streamed_response_wrapper( + numbers.capacity, + ) self.countries = async_to_streamed_response_wrapper( numbers.countries, ) diff --git a/src/mobilerun_sdk/resources/tasks/tasks.py b/src/mobilerun_sdk/resources/tasks/tasks.py index e73ca6bb..c7687a78 100644 --- a/src/mobilerun_sdk/resources/tasks/tasks.py +++ b/src/mobilerun_sdk/resources/tasks/tasks.py @@ -121,7 +121,10 @@ def list( page: int | Omit = omit, page_size: int | Omit = omit, query: Optional[str] | Omit = omit, - status: Optional[Literal["queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]] + source: Optional[Literal["api", "agent"]] | Omit = omit, + status: Optional[ + Literal["prepared", "queued", "created", "running", "cancelling", "completed", "failed", "cancelled"] + ] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -140,6 +143,8 @@ def list( query: Search in task description. + source: Only tasks created via the API ('api') or spawned by an agent step ('agent'). + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -164,6 +169,7 @@ def list( "page": page, "page_size": page_size, "query": query, + "source": source, "status": status, }, task_list_params.TaskListParams, @@ -278,7 +284,6 @@ def run( device_id: str, task: str, accessibility: bool | Omit = omit, - agent_id: int | Omit = omit, apps: SequenceNotStr[str] | Omit = omit, continue_on_failure: bool | Omit = omit, credentials: Iterable[task_run_params.Credential] | Omit = omit, @@ -290,8 +295,10 @@ def run( memory_namespace: str | Omit = omit, output_schema: Optional[Dict[str, object]] | Omit = omit, reasoning: bool | Omit = omit, + recording_enabled: bool | Omit = omit, stealth: bool | Omit = omit, subagent_model: str | Omit = omit, + system_prompt: Optional[str] | Omit = omit, temperature: float | Omit = omit, vision: bool | Omit = omit, vpn_country: Optional[Literal["US", "BR", "FR", "DE", "IN", "JP", "KR", "ZA"]] | Omit = omit, @@ -313,12 +320,19 @@ def run( display_id: The display ID of the device to run the task on. - llm_model: The LLM model identifier to use for the task (e.g. 'google/gemini-3.5-flash') + llm_model: The LLM model identifier to use for the task (e.g. 'openai/gpt-5.6-luna') memory_namespace: Memory namespace for cross-task personalization + recording_enabled: Record device video for the whole task and persist a retrievable reference + subagent_model: LLM model used by sub-agent roles: executor, app_opener, structured_output + system_prompt: Optional custom behavioral overlay applied on top of the agent's default system + prompts. Never echoed back in responses or errors. + + temperature: Deprecated and ignored. Sampling behavior is controlled by the model provider. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -335,7 +349,6 @@ def run( "device_id": device_id, "task": task, "accessibility": accessibility, - "agent_id": agent_id, "apps": apps, "continue_on_failure": continue_on_failure, "credentials": credentials, @@ -347,8 +360,10 @@ def run( "memory_namespace": memory_namespace, "output_schema": output_schema, "reasoning": reasoning, + "recording_enabled": recording_enabled, "stealth": stealth, "subagent_model": subagent_model, + "system_prompt": system_prompt, "temperature": temperature, "vision": vision, "vpn_country": vpn_country, @@ -367,7 +382,6 @@ def run_streamed( device_id: str, task: str, accessibility: bool | Omit = omit, - agent_id: int | Omit = omit, apps: SequenceNotStr[str] | Omit = omit, continue_on_failure: bool | Omit = omit, credentials: Iterable[task_run_streamed_params.Credential] | Omit = omit, @@ -379,8 +393,10 @@ def run_streamed( memory_namespace: str | Omit = omit, output_schema: Optional[Dict[str, object]] | Omit = omit, reasoning: bool | Omit = omit, + recording_enabled: bool | Omit = omit, stealth: bool | Omit = omit, subagent_model: str | Omit = omit, + system_prompt: Optional[str] | Omit = omit, temperature: float | Omit = omit, vision: bool | Omit = omit, vpn_country: Optional[Literal["US", "BR", "FR", "DE", "IN", "JP", "KR", "ZA"]] | Omit = omit, @@ -400,12 +416,19 @@ def run_streamed( display_id: The display ID of the device to run the task on. - llm_model: The LLM model identifier to use for the task (e.g. 'google/gemini-3.5-flash') + llm_model: The LLM model identifier to use for the task (e.g. 'openai/gpt-5.6-luna') memory_namespace: Memory namespace for cross-task personalization + recording_enabled: Record device video for the whole task and persist a retrievable reference + subagent_model: LLM model used by sub-agent roles: executor, app_opener, structured_output + system_prompt: Optional custom behavioral overlay applied on top of the agent's default system + prompts. Never echoed back in responses or errors. + + temperature: Deprecated and ignored. Sampling behavior is controlled by the model provider. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -421,7 +444,6 @@ def run_streamed( "device_id": device_id, "task": task, "accessibility": accessibility, - "agent_id": agent_id, "apps": apps, "continue_on_failure": continue_on_failure, "credentials": credentials, @@ -433,8 +455,10 @@ def run_streamed( "memory_namespace": memory_namespace, "output_schema": output_schema, "reasoning": reasoning, + "recording_enabled": recording_enabled, "stealth": stealth, "subagent_model": subagent_model, + "system_prompt": system_prompt, "temperature": temperature, "vision": vision, "vpn_country": vpn_country, @@ -597,7 +621,10 @@ async def list( page: int | Omit = omit, page_size: int | Omit = omit, query: Optional[str] | Omit = omit, - status: Optional[Literal["queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]] + source: Optional[Literal["api", "agent"]] | Omit = omit, + status: Optional[ + Literal["prepared", "queued", "created", "running", "cancelling", "completed", "failed", "cancelled"] + ] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -616,6 +643,8 @@ async def list( query: Search in task description. + source: Only tasks created via the API ('api') or spawned by an agent step ('agent'). + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -640,6 +669,7 @@ async def list( "page": page, "page_size": page_size, "query": query, + "source": source, "status": status, }, task_list_params.TaskListParams, @@ -754,7 +784,6 @@ async def run( device_id: str, task: str, accessibility: bool | Omit = omit, - agent_id: int | Omit = omit, apps: SequenceNotStr[str] | Omit = omit, continue_on_failure: bool | Omit = omit, credentials: Iterable[task_run_params.Credential] | Omit = omit, @@ -766,8 +795,10 @@ async def run( memory_namespace: str | Omit = omit, output_schema: Optional[Dict[str, object]] | Omit = omit, reasoning: bool | Omit = omit, + recording_enabled: bool | Omit = omit, stealth: bool | Omit = omit, subagent_model: str | Omit = omit, + system_prompt: Optional[str] | Omit = omit, temperature: float | Omit = omit, vision: bool | Omit = omit, vpn_country: Optional[Literal["US", "BR", "FR", "DE", "IN", "JP", "KR", "ZA"]] | Omit = omit, @@ -789,12 +820,19 @@ async def run( display_id: The display ID of the device to run the task on. - llm_model: The LLM model identifier to use for the task (e.g. 'google/gemini-3.5-flash') + llm_model: The LLM model identifier to use for the task (e.g. 'openai/gpt-5.6-luna') memory_namespace: Memory namespace for cross-task personalization + recording_enabled: Record device video for the whole task and persist a retrievable reference + subagent_model: LLM model used by sub-agent roles: executor, app_opener, structured_output + system_prompt: Optional custom behavioral overlay applied on top of the agent's default system + prompts. Never echoed back in responses or errors. + + temperature: Deprecated and ignored. Sampling behavior is controlled by the model provider. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -811,7 +849,6 @@ async def run( "device_id": device_id, "task": task, "accessibility": accessibility, - "agent_id": agent_id, "apps": apps, "continue_on_failure": continue_on_failure, "credentials": credentials, @@ -823,8 +860,10 @@ async def run( "memory_namespace": memory_namespace, "output_schema": output_schema, "reasoning": reasoning, + "recording_enabled": recording_enabled, "stealth": stealth, "subagent_model": subagent_model, + "system_prompt": system_prompt, "temperature": temperature, "vision": vision, "vpn_country": vpn_country, @@ -843,7 +882,6 @@ async def run_streamed( device_id: str, task: str, accessibility: bool | Omit = omit, - agent_id: int | Omit = omit, apps: SequenceNotStr[str] | Omit = omit, continue_on_failure: bool | Omit = omit, credentials: Iterable[task_run_streamed_params.Credential] | Omit = omit, @@ -855,8 +893,10 @@ async def run_streamed( memory_namespace: str | Omit = omit, output_schema: Optional[Dict[str, object]] | Omit = omit, reasoning: bool | Omit = omit, + recording_enabled: bool | Omit = omit, stealth: bool | Omit = omit, subagent_model: str | Omit = omit, + system_prompt: Optional[str] | Omit = omit, temperature: float | Omit = omit, vision: bool | Omit = omit, vpn_country: Optional[Literal["US", "BR", "FR", "DE", "IN", "JP", "KR", "ZA"]] | Omit = omit, @@ -876,12 +916,19 @@ async def run_streamed( display_id: The display ID of the device to run the task on. - llm_model: The LLM model identifier to use for the task (e.g. 'google/gemini-3.5-flash') + llm_model: The LLM model identifier to use for the task (e.g. 'openai/gpt-5.6-luna') memory_namespace: Memory namespace for cross-task personalization + recording_enabled: Record device video for the whole task and persist a retrievable reference + subagent_model: LLM model used by sub-agent roles: executor, app_opener, structured_output + system_prompt: Optional custom behavioral overlay applied on top of the agent's default system + prompts. Never echoed back in responses or errors. + + temperature: Deprecated and ignored. Sampling behavior is controlled by the model provider. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -897,7 +944,6 @@ async def run_streamed( "device_id": device_id, "task": task, "accessibility": accessibility, - "agent_id": agent_id, "apps": apps, "continue_on_failure": continue_on_failure, "credentials": credentials, @@ -909,8 +955,10 @@ async def run_streamed( "memory_namespace": memory_namespace, "output_schema": output_schema, "reasoning": reasoning, + "recording_enabled": recording_enabled, "stealth": stealth, "subagent_model": subagent_model, + "system_prompt": system_prompt, "temperature": temperature, "vision": vision, "vpn_country": vpn_country, diff --git a/src/mobilerun_sdk/resources/workflows/flows/actions.py b/src/mobilerun_sdk/resources/workflows/flows/actions.py index 0fd2150d..26ca8773 100644 --- a/src/mobilerun_sdk/resources/workflows/flows/actions.py +++ b/src/mobilerun_sdk/resources/workflows/flows/actions.py @@ -91,6 +91,7 @@ def add( name_override: str | Omit = omit, overrides: Optional[action_add_params.Overrides] | Omit = omit, parent_flow_action_id: Optional[str] | Omit = omit, + recording_enabled: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -126,6 +127,7 @@ def add( "name_override": name_override, "overrides": overrides, "parent_flow_action_id": parent_flow_action_id, + "recording_enabled": recording_enabled, }, action_add_params.ActionAddParams, ), @@ -277,6 +279,7 @@ async def add( name_override: str | Omit = omit, overrides: Optional[action_add_params.Overrides] | Omit = omit, parent_flow_action_id: Optional[str] | Omit = omit, + recording_enabled: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -312,6 +315,7 @@ async def add( "name_override": name_override, "overrides": overrides, "parent_flow_action_id": parent_flow_action_id, + "recording_enabled": recording_enabled, }, action_add_params.ActionAddParams, ), diff --git a/src/mobilerun_sdk/resources/workflows/flows/flows.py b/src/mobilerun_sdk/resources/workflows/flows/flows.py index db390fcc..1faf5913 100644 --- a/src/mobilerun_sdk/resources/workflows/flows/flows.py +++ b/src/mobilerun_sdk/resources/workflows/flows/flows.py @@ -40,6 +40,7 @@ from ....types.workflows.flow_update_response import FlowUpdateResponse from ....types.workflows.flow_dry_run_response import FlowDryRunResponse from ....types.workflows.flow_unblock_response import FlowUnblockResponse +from ....types.workflows.flow_capacity_response import FlowCapacityResponse from ....types.workflows.flow_retrieve_response import FlowRetrieveResponse from ....types.workflows.flow_list_repairs_response import FlowListRepairsResponse @@ -86,6 +87,7 @@ def create( notify_on_success: bool | Omit = omit, notify_webhook_id: Optional[str] | Omit = omit, recording_enabled: bool | Omit = omit, + recording_policy: flow_create_params.RecordingPolicy | Omit = omit, self_healing_enabled: bool | Omit = omit, self_healing_max_attempts: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -102,6 +104,9 @@ def create( success or failure. Args: + recording_enabled: Deprecated compatibility field. true maps to recordingPolicy.mode="flow"; false + maps to "off". + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -127,6 +132,7 @@ def create( "notify_on_success": notify_on_success, "notify_webhook_id": notify_webhook_id, "recording_enabled": recording_enabled, + "recording_policy": recording_policy, "self_healing_enabled": self_healing_enabled, "self_healing_max_attempts": self_healing_max_attempts, }, @@ -182,11 +188,13 @@ def update( device_ids: SequenceNotStr[str] | Omit = omit, enabled: bool | Omit = omit, health_monitoring_enabled: bool | Omit = omit, + lifecycle_status: Literal["enabled", "disabled"] | Omit = omit, name: str | Omit = omit, notify_on_failure: bool | Omit = omit, notify_on_success: bool | Omit = omit, notify_webhook_id: Optional[str] | Omit = omit, recording_enabled: bool | Omit = omit, + recording_policy: flow_update_params.RecordingPolicy | Omit = omit, self_healing_enabled: bool | Omit = omit, self_healing_max_attempts: int | Omit = omit, trigger_id: str | Omit = omit, @@ -204,6 +212,11 @@ def update( does not exist. Args: + lifecycle_status: Set the visible agent lifecycle. Archive remains available only through DELETE. + + recording_enabled: Deprecated compatibility field. true maps to recordingPolicy.mode="flow"; false + maps to "off". + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -224,11 +237,13 @@ def update( "device_ids": device_ids, "enabled": enabled, "health_monitoring_enabled": health_monitoring_enabled, + "lifecycle_status": lifecycle_status, "name": name, "notify_on_failure": notify_on_failure, "notify_on_success": notify_on_success, "notify_webhook_id": notify_webhook_id, "recording_enabled": recording_enabled, + "recording_policy": recording_policy, "self_healing_enabled": self_healing_enabled, "self_healing_max_attempts": self_healing_max_attempts, "trigger_id": trigger_id, @@ -318,9 +333,10 @@ def delete( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FlowDeleteResponse: - """Delete a flow by its ID. + """Terminally archive a flow by its ID. - Returns 404 if no flow matches. + Archived flows cannot be restored and are + hidden from customer reads. Repeating the request is idempotent for the owner. Args: extra_headers: Send extra headers @@ -341,6 +357,30 @@ def delete( cast_to=FlowDeleteResponse, ) + def capacity( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> FlowCapacityResponse: + """ + Returns an owner-scoped snapshot of finite included workflow-agent capacity + after locally stored enabled and disabled agents. Available only while slot + enforcement is enabled; otherwise returns 503. This is advisory; create and + clone perform authoritative admission under an owner lock. + """ + return self._get( + "/flows/capacity", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FlowCapacityResponse, + ) + def clone( self, flow_id: str, @@ -543,6 +583,7 @@ async def create( notify_on_success: bool | Omit = omit, notify_webhook_id: Optional[str] | Omit = omit, recording_enabled: bool | Omit = omit, + recording_policy: flow_create_params.RecordingPolicy | Omit = omit, self_healing_enabled: bool | Omit = omit, self_healing_max_attempts: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -559,6 +600,9 @@ async def create( success or failure. Args: + recording_enabled: Deprecated compatibility field. true maps to recordingPolicy.mode="flow"; false + maps to "off". + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -584,6 +628,7 @@ async def create( "notify_on_success": notify_on_success, "notify_webhook_id": notify_webhook_id, "recording_enabled": recording_enabled, + "recording_policy": recording_policy, "self_healing_enabled": self_healing_enabled, "self_healing_max_attempts": self_healing_max_attempts, }, @@ -639,11 +684,13 @@ async def update( device_ids: SequenceNotStr[str] | Omit = omit, enabled: bool | Omit = omit, health_monitoring_enabled: bool | Omit = omit, + lifecycle_status: Literal["enabled", "disabled"] | Omit = omit, name: str | Omit = omit, notify_on_failure: bool | Omit = omit, notify_on_success: bool | Omit = omit, notify_webhook_id: Optional[str] | Omit = omit, recording_enabled: bool | Omit = omit, + recording_policy: flow_update_params.RecordingPolicy | Omit = omit, self_healing_enabled: bool | Omit = omit, self_healing_max_attempts: int | Omit = omit, trigger_id: str | Omit = omit, @@ -661,6 +708,11 @@ async def update( does not exist. Args: + lifecycle_status: Set the visible agent lifecycle. Archive remains available only through DELETE. + + recording_enabled: Deprecated compatibility field. true maps to recordingPolicy.mode="flow"; false + maps to "off". + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -681,11 +733,13 @@ async def update( "device_ids": device_ids, "enabled": enabled, "health_monitoring_enabled": health_monitoring_enabled, + "lifecycle_status": lifecycle_status, "name": name, "notify_on_failure": notify_on_failure, "notify_on_success": notify_on_success, "notify_webhook_id": notify_webhook_id, "recording_enabled": recording_enabled, + "recording_policy": recording_policy, "self_healing_enabled": self_healing_enabled, "self_healing_max_attempts": self_healing_max_attempts, "trigger_id": trigger_id, @@ -775,9 +829,10 @@ async def delete( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> FlowDeleteResponse: - """Delete a flow by its ID. + """Terminally archive a flow by its ID. - Returns 404 if no flow matches. + Archived flows cannot be restored and are + hidden from customer reads. Repeating the request is idempotent for the owner. Args: extra_headers: Send extra headers @@ -798,6 +853,30 @@ async def delete( cast_to=FlowDeleteResponse, ) + async def capacity( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> FlowCapacityResponse: + """ + Returns an owner-scoped snapshot of finite included workflow-agent capacity + after locally stored enabled and disabled agents. Available only while slot + enforcement is enabled; otherwise returns 503. This is advisory; create and + clone perform authoritative admission under an owner lock. + """ + return await self._get( + "/flows/capacity", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FlowCapacityResponse, + ) + async def clone( self, flow_id: str, @@ -979,6 +1058,9 @@ def __init__(self, flows: FlowsResource) -> None: self.delete = to_raw_response_wrapper( flows.delete, ) + self.capacity = to_raw_response_wrapper( + flows.capacity, + ) self.clone = to_raw_response_wrapper( flows.clone, ) @@ -1016,6 +1098,9 @@ def __init__(self, flows: AsyncFlowsResource) -> None: self.delete = async_to_raw_response_wrapper( flows.delete, ) + self.capacity = async_to_raw_response_wrapper( + flows.capacity, + ) self.clone = async_to_raw_response_wrapper( flows.clone, ) @@ -1053,6 +1138,9 @@ def __init__(self, flows: FlowsResource) -> None: self.delete = to_streamed_response_wrapper( flows.delete, ) + self.capacity = to_streamed_response_wrapper( + flows.capacity, + ) self.clone = to_streamed_response_wrapper( flows.clone, ) @@ -1090,6 +1178,9 @@ def __init__(self, flows: AsyncFlowsResource) -> None: self.delete = async_to_streamed_response_wrapper( flows.delete, ) + self.capacity = async_to_streamed_response_wrapper( + flows.capacity, + ) self.clone = async_to_streamed_response_wrapper( flows.clone, ) diff --git a/src/mobilerun_sdk/types/__init__.py b/src/mobilerun_sdk/types/__init__.py index 310d2f0f..7e1d124c 100644 --- a/src/mobilerun_sdk/types/__init__.py +++ b/src/mobilerun_sdk/types/__init__.py @@ -17,26 +17,17 @@ ) from .app_list_params import AppListParams as AppListParams from .task_run_params import TaskRunParams as TaskRunParams -from .esim_list_params import EsimListParams as EsimListParams -from .file_list_params import FileListParams as FileListParams from .task_list_params import TaskListParams as TaskListParams from .app_list_response import AppListResponse as AppListResponse from .proxy_list_params import ProxyListParams as ProxyListParams from .task_run_response import TaskRunResponse as TaskRunResponse from .device_list_params import DeviceListParams as DeviceListParams -from .esim_create_params import EsimCreateParams as EsimCreateParams -from .esim_import_params import EsimImportParams as EsimImportParams -from .esim_list_response import EsimListResponse as EsimListResponse -from .esim_update_params import EsimUpdateParams as EsimUpdateParams -from .file_list_response import FileListResponse as FileListResponse -from .file_update_params import FileUpdateParams as FileUpdateParams from .mailbox_otp_params import MailboxOtpParams as MailboxOtpParams from .number_list_params import NumberListParams as NumberListParams from .task_list_response import TaskListResponse as TaskListResponse from .task_stop_response import TaskStopResponse as TaskStopResponse from .app_delete_response import AppDeleteResponse as AppDeleteResponse from .carrier_list_params import CarrierListParams as CarrierListParams -from .esim_install_params import EsimInstallParams as EsimInstallParams from .mailbox_list_params import MailboxListParams as MailboxListParams from .message_list_params import MessageListParams as MessageListParams from .model_list_response import ModelListResponse as ModelListResponse @@ -48,12 +39,7 @@ from .webhook_list_params import WebhookListParams as WebhookListParams from .device_create_params import DeviceCreateParams as DeviceCreateParams from .device_list_response import DeviceListResponse as DeviceListResponse -from .esim_create_response import EsimCreateResponse as EsimCreateResponse -from .esim_import_response import EsimImportResponse as EsimImportResponse -from .esim_selector_params import EsimSelectorParams as EsimSelectorParams -from .esim_update_response import EsimUpdateResponse as EsimUpdateResponse from .file_delete_response import FileDeleteResponse as FileDeleteResponse -from .file_update_response import FileUpdateResponse as FileUpdateResponse from .mailbox_otp_response import MailboxOtpResponse as MailboxOtpResponse from .number_create_params import NumberCreateParams as NumberCreateParams from .number_list_response import NumberListResponse as NumberListResponse @@ -65,8 +51,6 @@ from .carrier_lookup_params import CarrierLookupParams as CarrierLookupParams from .carrier_update_params import CarrierUpdateParams as CarrierUpdateParams from .device_count_response import DeviceCountResponse as DeviceCountResponse -from .esim_install_response import EsimInstallResponse as EsimInstallResponse -from .file_confirm_response import FileConfirmResponse as FileConfirmResponse from .mailbox_create_params import MailboxCreateParams as MailboxCreateParams from .mailbox_list_response import MailboxListResponse as MailboxListResponse from .mailbox_update_params import MailboxUpdateParams as MailboxUpdateParams @@ -84,11 +68,9 @@ from .credential_list_params import CredentialListParams as CredentialListParams from .device_create_response import DeviceCreateResponse as DeviceCreateResponse from .device_set_name_params import DeviceSetNameParams as DeviceSetNameParams -from .esim_capacity_response import EsimCapacityResponse as EsimCapacityResponse -from .esim_retrieve_response import EsimRetrieveResponse as EsimRetrieveResponse -from .esim_selector_response import EsimSelectorResponse as EsimSelectorResponse from .file_upload_url_params import FileUploadURLParams as FileUploadURLParams from .mailbox_restart_params import MailboxRestartParams as MailboxRestartParams +from .number_capacity_params import NumberCapacityParams as NumberCapacityParams from .number_create_response import NumberCreateResponse as NumberCreateResponse from .number_delete_response import NumberDeleteResponse as NumberDeleteResponse from .number_update_response import NumberUpdateResponse as NumberUpdateResponse @@ -114,6 +96,7 @@ from .device_set_name_response import DeviceSetNameResponse as DeviceSetNameResponse from .file_upload_url_response import FileUploadURLResponse as FileUploadURLResponse from .mailbox_restart_response import MailboxRestartResponse as MailboxRestartResponse +from .number_capacity_response import NumberCapacityResponse as NumberCapacityResponse from .number_purposes_response import NumberPurposesResponse as NumberPurposesResponse from .number_retrieve_response import NumberRetrieveResponse as NumberRetrieveResponse from .task_get_status_response import TaskGetStatusResponse as TaskGetStatusResponse @@ -134,11 +117,9 @@ from .app_confirm_upload_response import AppConfirmUploadResponse as AppConfirmUploadResponse from .app_event_retrieve_response import AppEventRetrieveResponse as AppEventRetrieveResponse from .device_fingerprint_response import DeviceFingerprintResponse as DeviceFingerprintResponse -from .esim_install_status_response import EsimInstallStatusResponse as EsimInstallStatusResponse from .file_cancel_pending_response import FileCancelPendingResponse as FileCancelPendingResponse from .task_get_trajectory_response import TaskGetTrajectoryResponse as TaskGetTrajectoryResponse from .webhook_event_types_response import WebhookEventTypesResponse as WebhookEventTypesResponse -from .esim_confirm_payment_response import EsimConfirmPaymentResponse as EsimConfirmPaymentResponse from .notification_catalog_response import NotificationCatalogResponse as NotificationCatalogResponse from .webhook_rotate_secret_response import WebhookRotateSecretResponse as WebhookRotateSecretResponse from .webhook_test_delivery_response import WebhookTestDeliveryResponse as WebhookTestDeliveryResponse diff --git a/src/mobilerun_sdk/types/app_storage_usage_response.py b/src/mobilerun_sdk/types/app_storage_usage_response.py index f1c225ec..f9dd47c4 100644 --- a/src/mobilerun_sdk/types/app_storage_usage_response.py +++ b/src/mobilerun_sdk/types/app_storage_usage_response.py @@ -9,12 +9,19 @@ class Data(BaseModel): available_bytes: float = FieldInfo(alias="availableBytes") - """Remaining bytes — the reliable maximum size for the next upload. + """Remaining bytes — the reliable maximum TOTAL size for the next upload. Advisory snapshot: the quota is enforced under a lock at confirm, so concurrent uploads may reduce actual headroom. """ + max_file_bytes: float = FieldInfo(alias="maxFileBytes") + """Per-file upload cap in bytes (env.MAX_UPLOAD_FILE_BYTES). + + A single file larger than this is rejected at confirm even when it fits the + remaining quota. Source of truth for the client-side per-file limit. + """ + quota_bytes: float = FieldInfo(alias="quotaBytes") """Total storage allowance for the user, in bytes""" diff --git a/src/mobilerun_sdk/types/assistant/conversation_history_response.py b/src/mobilerun_sdk/types/assistant/conversation_history_response.py index 8288033a..b2f79efc 100644 --- a/src/mobilerun_sdk/types/assistant/conversation_history_response.py +++ b/src/mobilerun_sdk/types/assistant/conversation_history_response.py @@ -65,4 +65,6 @@ class ConversationHistoryResponse(BaseModel): turn_active: bool = FieldInfo(alias="turnActive") + last_turn_outcome: Optional[str] = FieldInfo(alias="lastTurnOutcome", default=None) + truncated: Optional[bool] = None diff --git a/src/mobilerun_sdk/types/connect/proxy_buy_params.py b/src/mobilerun_sdk/types/connect/proxy_buy_params.py index b8147750..8426ebeb 100644 --- a/src/mobilerun_sdk/types/connect/proxy_buy_params.py +++ b/src/mobilerun_sdk/types/connect/proxy_buy_params.py @@ -2,7 +2,9 @@ from __future__ import annotations -from typing_extensions import Literal, Required, TypedDict +from typing_extensions import Literal, Required, Annotated, TypedDict + +from ..._utils import PropertyInfo __all__ = ["ProxyBuyParams"] @@ -12,3 +14,5 @@ class ProxyBuyParams(TypedDict, total=False): """ISO 3166-1 alpha-2 country code to provision the proxy in.""" type: Required[Literal["dedicated_residential", "residential", "mobile"]] + + idempotency_key: Annotated[str, PropertyInfo(alias="Idempotency-Key")] diff --git a/src/mobilerun_sdk/types/connect/proxy_buy_response.py b/src/mobilerun_sdk/types/connect/proxy_buy_response.py index 403a8d80..d512bbef 100644 --- a/src/mobilerun_sdk/types/connect/proxy_buy_response.py +++ b/src/mobilerun_sdk/types/connect/proxy_buy_response.py @@ -27,20 +27,23 @@ class ProxyBuyResponse(BaseModel): port: int - status: Literal["pending_payment", "provisioning", "active", "cancelling", "ended", "error"] + status: Literal["checking", "pending_payment", "provisioning", "active", "cancelling", "ended", "error"] """Lifecycle of a proxy. - A freshly created proxy is `provisioning` — or `pending_payment` until the - customer completes checkout — and becomes `active` once its upstream is - assigned. `cancelling` retains full access through the paid period; when the - subscription expires the proxy is `ended`. `error` marks a failed provisioning - attempt. + A freshly created proxy is `checking` while its billing identity is being + resolved — clients should poll until a `paymentUrl` or a later status appears — + then `provisioning` — or `pending_payment` until the customer completes checkout + — and becomes `active` once its upstream is assigned. `cancelling` retains full + access through the paid period; when the subscription expires the proxy is + `ended`. `error` marks a failed provisioning attempt. """ type: Literal["dedicated_residential", "residential", "mobile"] username: str + billing_mode: Optional[Literal["included", "standalone_paid"]] = FieldInfo(alias="billingMode", default=None) + payment_url: Optional[str] = FieldInfo(alias="paymentUrl", default=None) """Checkout URL to complete payment while status is `pending_payment`. diff --git a/src/mobilerun_sdk/types/connect/proxy_list_response.py b/src/mobilerun_sdk/types/connect/proxy_list_response.py index 26135dca..e68fd457 100644 --- a/src/mobilerun_sdk/types/connect/proxy_list_response.py +++ b/src/mobilerun_sdk/types/connect/proxy_list_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List +from typing import List, Optional from datetime import datetime from typing_extensions import Literal @@ -25,20 +25,23 @@ class Item(BaseModel): port: int - status: Literal["pending_payment", "provisioning", "active", "cancelling", "ended", "error"] + status: Literal["checking", "pending_payment", "provisioning", "active", "cancelling", "ended", "error"] """Lifecycle of a proxy. - A freshly created proxy is `provisioning` — or `pending_payment` until the - customer completes checkout — and becomes `active` once its upstream is - assigned. `cancelling` retains full access through the paid period; when the - subscription expires the proxy is `ended`. `error` marks a failed provisioning - attempt. + A freshly created proxy is `checking` while its billing identity is being + resolved — clients should poll until a `paymentUrl` or a later status appears — + then `provisioning` — or `pending_payment` until the customer completes checkout + — and becomes `active` once its upstream is assigned. `cancelling` retains full + access through the paid period; when the subscription expires the proxy is + `ended`. `error` marks a failed provisioning attempt. """ type: Literal["dedicated_residential", "residential", "mobile"] username: str + billing_mode: Optional[Literal["included", "standalone_paid"]] = FieldInfo(alias="billingMode", default=None) + class Pagination(BaseModel): """Pagination metadata for a list response.""" diff --git a/src/mobilerun_sdk/types/connect/proxy_retrieve_response.py b/src/mobilerun_sdk/types/connect/proxy_retrieve_response.py index be8cd872..41014606 100644 --- a/src/mobilerun_sdk/types/connect/proxy_retrieve_response.py +++ b/src/mobilerun_sdk/types/connect/proxy_retrieve_response.py @@ -27,20 +27,23 @@ class ProxyRetrieveResponse(BaseModel): port: int - status: Literal["pending_payment", "provisioning", "active", "cancelling", "ended", "error"] + status: Literal["checking", "pending_payment", "provisioning", "active", "cancelling", "ended", "error"] """Lifecycle of a proxy. - A freshly created proxy is `provisioning` — or `pending_payment` until the - customer completes checkout — and becomes `active` once its upstream is - assigned. `cancelling` retains full access through the paid period; when the - subscription expires the proxy is `ended`. `error` marks a failed provisioning - attempt. + A freshly created proxy is `checking` while its billing identity is being + resolved — clients should poll until a `paymentUrl` or a later status appears — + then `provisioning` — or `pending_payment` until the customer completes checkout + — and becomes `active` once its upstream is assigned. `cancelling` retains full + access through the paid period; when the subscription expires the proxy is + `ended`. `error` marks a failed provisioning attempt. """ type: Literal["dedicated_residential", "residential", "mobile"] username: str + billing_mode: Optional[Literal["included", "standalone_paid"]] = FieldInfo(alias="billingMode", default=None) + payment_url: Optional[str] = FieldInfo(alias="paymentUrl", default=None) """Checkout URL to complete payment while status is `pending_payment`. diff --git a/src/mobilerun_sdk/types/device_create_response.py b/src/mobilerun_sdk/types/device_create_response.py index c792c9f7..307565c2 100644 --- a/src/mobilerun_sdk/types/device_create_response.py +++ b/src/mobilerun_sdk/types/device_create_response.py @@ -2,6 +2,7 @@ from typing import Optional from datetime import datetime +from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -21,6 +22,9 @@ class DeviceCreateResponse(BaseModel): name: str + platform: Literal["android", "ios"] + """Operating system the device runs.""" + state: str state_message: str = FieldInfo(alias="stateMessage") diff --git a/src/mobilerun_sdk/types/device_list_response.py b/src/mobilerun_sdk/types/device_list_response.py index f8c1a26a..e4c0e942 100644 --- a/src/mobilerun_sdk/types/device_list_response.py +++ b/src/mobilerun_sdk/types/device_list_response.py @@ -2,6 +2,7 @@ from typing import List, Optional from datetime import datetime +from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -22,6 +23,9 @@ class Item(BaseModel): name: str + platform: Literal["android", "ios"] + """Operating system the device runs.""" + state: str state_message: str = FieldInfo(alias="stateMessage") diff --git a/src/mobilerun_sdk/types/device_retrieve_capabilities_response.py b/src/mobilerun_sdk/types/device_retrieve_capabilities_response.py index 2e02c5ea..f5a6020c 100644 --- a/src/mobilerun_sdk/types/device_retrieve_capabilities_response.py +++ b/src/mobilerun_sdk/types/device_retrieve_capabilities_response.py @@ -42,6 +42,8 @@ class Capabilities(BaseModel): proxy: bool + recording: bool + reset: bool shell: bool @@ -54,6 +56,8 @@ class Capabilities(BaseModel): time: bool + traffic_inspection: bool = FieldInfo(alias="trafficInspection") + class DeviceRetrieveCapabilitiesResponse(BaseModel): capabilities: Capabilities diff --git a/src/mobilerun_sdk/types/device_retrieve_response.py b/src/mobilerun_sdk/types/device_retrieve_response.py index 6735522c..be523d09 100644 --- a/src/mobilerun_sdk/types/device_retrieve_response.py +++ b/src/mobilerun_sdk/types/device_retrieve_response.py @@ -2,6 +2,7 @@ from typing import Optional from datetime import datetime +from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -21,6 +22,9 @@ class DeviceRetrieveResponse(BaseModel): name: str + platform: Literal["android", "ios"] + """Operating system the device runs.""" + state: str state_message: str = FieldInfo(alias="stateMessage") diff --git a/src/mobilerun_sdk/types/device_set_name_response.py b/src/mobilerun_sdk/types/device_set_name_response.py index f7976eea..026ac9b1 100644 --- a/src/mobilerun_sdk/types/device_set_name_response.py +++ b/src/mobilerun_sdk/types/device_set_name_response.py @@ -2,6 +2,7 @@ from typing import Optional from datetime import datetime +from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -21,6 +22,9 @@ class DeviceSetNameResponse(BaseModel): name: str + platform: Literal["android", "ios"] + """Operating system the device runs.""" + state: str state_message: str = FieldInfo(alias="stateMessage") diff --git a/src/mobilerun_sdk/types/device_wait_ready_response.py b/src/mobilerun_sdk/types/device_wait_ready_response.py index 73a50c61..d8de894d 100644 --- a/src/mobilerun_sdk/types/device_wait_ready_response.py +++ b/src/mobilerun_sdk/types/device_wait_ready_response.py @@ -2,6 +2,7 @@ from typing import Optional from datetime import datetime +from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -21,6 +22,9 @@ class DeviceWaitReadyResponse(BaseModel): name: str + platform: Literal["android", "ios"] + """Operating system the device runs.""" + state: str state_message: str = FieldInfo(alias="stateMessage") diff --git a/src/mobilerun_sdk/types/devices/__init__.py b/src/mobilerun_sdk/types/devices/__init__.py index 6b5d3494..2e93fc88 100644 --- a/src/mobilerun_sdk/types/devices/__init__.py +++ b/src/mobilerun_sdk/types/devices/__init__.py @@ -54,12 +54,18 @@ from .state_screenshot_response import StateScreenshotResponse as StateScreenshotResponse from .app_list_installs_response import AppListInstallsResponse as AppListInstallsResponse from .media_session_create_params import MediaSessionCreateParams as MediaSessionCreateParams +from .traffic_session_list_params import TrafficSessionListParams as TrafficSessionListParams from .browser_execute_script_params import BrowserExecuteScriptParams as BrowserExecuteScriptParams from .media_session_create_response import MediaSessionCreateResponse as MediaSessionCreateResponse +from .traffic_session_create_params import TrafficSessionCreateParams as TrafficSessionCreateParams +from .traffic_session_list_response import TrafficSessionListResponse as TrafficSessionListResponse from .action_overlay_visible_response import ActionOverlayVisibleResponse as ActionOverlayVisibleResponse from .browser_execute_script_response import BrowserExecuteScriptResponse as BrowserExecuteScriptResponse from .media_session_activate_response import MediaSessionActivateResponse as MediaSessionActivateResponse +from .traffic_session_create_response import TrafficSessionCreateResponse as TrafficSessionCreateResponse +from .traffic_session_delete_response import TrafficSessionDeleteResponse as TrafficSessionDeleteResponse from .action_set_overlay_visible_params import ActionSetOverlayVisibleParams as ActionSetOverlayVisibleParams +from .traffic_session_retrieve_response import TrafficSessionRetrieveResponse as TrafficSessionRetrieveResponse from .deep_link_execute_deep_link_params import DeepLinkExecuteDeepLinkParams as DeepLinkExecuteDeepLinkParams from .media_session_retrieve_current_response import ( MediaSessionRetrieveCurrentResponse as MediaSessionRetrieveCurrentResponse, diff --git a/src/mobilerun_sdk/types/devices/app_install_params.py b/src/mobilerun_sdk/types/devices/app_install_params.py index f419dd4e..3624dc3a 100644 --- a/src/mobilerun_sdk/types/devices/app_install_params.py +++ b/src/mobilerun_sdk/types/devices/app_install_params.py @@ -21,9 +21,21 @@ class Variant0(TypedDict, total=False): directly (200 on success, an error status on failure). """ + country: str + """Optional ISO 3166-1 alpha-2 country of the uploaded app version (e.g. + + MY or SG). + """ + package_name: Annotated[str, PropertyInfo(alias="packageName")] """Android package name (e.g. com.example.app)""" + version_code: Annotated[int, PropertyInfo(alias="versionCode")] + """Optional exact app-library version code. + + Use with country when multiple regional versions share an identifier. + """ + x_device_display_id: Annotated[int, PropertyInfo(alias="X-Device-Display-ID")] @@ -41,6 +53,18 @@ class Variant1(TypedDict, total=False): bundle_id: Annotated[str, PropertyInfo(alias="bundleId")] """iOS bundle identifier (e.g. com.example.app)""" + country: str + """Optional ISO 3166-1 alpha-2 country of the uploaded app version (e.g. + + MY or SG). + """ + + version_code: Annotated[int, PropertyInfo(alias="versionCode")] + """Optional exact app-library version code. + + Use with country when multiple regional versions share an identifier. + """ + x_device_display_id: Annotated[int, PropertyInfo(alias="X-Device-Display-ID")] diff --git a/src/mobilerun_sdk/types/devices/app_list_installs_response.py b/src/mobilerun_sdk/types/devices/app_list_installs_response.py index 796f7b2a..ae079f10 100644 --- a/src/mobilerun_sdk/types/devices/app_list_installs_response.py +++ b/src/mobilerun_sdk/types/devices/app_list_installs_response.py @@ -28,11 +28,10 @@ class Install(BaseModel): updated_at: datetime = FieldInfo(alias="updatedAt") - error_class: Optional[str] = FieldInfo(alias="errorClass", default=None) - """Closed set: download_failed, adb_install_failed, panic, timeout, failed. - - Only present when status is failed. - """ + error_class: Optional[Literal["download_failed", "adb_install_failed", "panic", "timeout", "failed"]] = FieldInfo( + alias="errorClass", default=None + ) + """Only present when status is failed.""" class AppListInstallsResponse(BaseModel): diff --git a/src/mobilerun_sdk/types/devices/keyboard_write_params.py b/src/mobilerun_sdk/types/devices/keyboard_write_params.py index c1340d7a..7bff865f 100644 --- a/src/mobilerun_sdk/types/devices/keyboard_write_params.py +++ b/src/mobilerun_sdk/types/devices/keyboard_write_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import Required, Annotated, TypedDict +from typing_extensions import Literal, Required, Annotated, TypedDict from ..._utils import PropertyInfo @@ -14,6 +14,14 @@ class KeyboardWriteParams(TypedDict, total=False): clear: bool + completion_mode: Annotated[Literal["accepted", "committed"], PropertyInfo(alias="completionMode")] + """Completion guarantee. + + accepted returns after the input provider accepts the operation; committed + additionally waits for the focused UI state to contain the complete text or + become quiescent. + """ + error_rate: Annotated[float, PropertyInfo(alias="errorRate")] """Per-character mistake rate for humantouch typing. -1 uses server default.""" diff --git a/src/mobilerun_sdk/types/devices/recording_start_params.py b/src/mobilerun_sdk/types/devices/recording_start_params.py index 621a86aa..007181d3 100644 --- a/src/mobilerun_sdk/types/devices/recording_start_params.py +++ b/src/mobilerun_sdk/types/devices/recording_start_params.py @@ -14,6 +14,18 @@ class RecordingStartParams(TypedDict, total=False): name: str + quality: int + """Capture quality from 1 (lowest) to 10 (full stream quality). + + Defaults to the device's full quality. Honored by devices recording through the + portal stream bridge. + """ + retention_days: Annotated[int, PropertyInfo(alias="retentionDays")] types: Optional[SequenceNotStr[str]] + """ + Artifacts to capture: trajectory (input actions), video, and audio (captured + into the video artifact, so it requires video; honored by portal stream-bridge + recorders). Defaults to trajectory and video. + """ diff --git a/src/mobilerun_sdk/types/devices/traffic_session_create_params.py b/src/mobilerun_sdk/types/devices/traffic_session_create_params.py new file mode 100644 index 00000000..20d0df0a --- /dev/null +++ b/src/mobilerun_sdk/types/devices/traffic_session_create_params.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["TrafficSessionCreateParams"] + + +class TrafficSessionCreateParams(TypedDict, total=False): + idempotency_key: Required[Annotated[str, PropertyInfo(alias="Idempotency-Key")]] + + expires_in_seconds: Annotated[int, PropertyInfo(alias="expiresInSeconds")] + + max_body_bytes: Annotated[int, PropertyInfo(alias="maxBodyBytes")] diff --git a/src/mobilerun_sdk/types/devices/traffic_session_create_response.py b/src/mobilerun_sdk/types/devices/traffic_session_create_response.py new file mode 100644 index 00000000..833e638b --- /dev/null +++ b/src/mobilerun_sdk/types/devices/traffic_session_create_response.py @@ -0,0 +1,52 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["TrafficSessionCreateResponse", "Error", "Stream"] + + +class Error(BaseModel): + code: str + + message: str + + +class Stream(BaseModel): + token: str + + protocol: str + + url: str + + +class TrafficSessionCreateResponse(BaseModel): + id: str + + created_at: datetime = FieldInfo(alias="createdAt") + + device_id: str = FieldInfo(alias="deviceId") + + expires_at: datetime = FieldInfo(alias="expiresAt") + + max_body_bytes: int = FieldInfo(alias="maxBodyBytes") + + retention: Literal["none"] + + state: Literal["starting", "active", "stopping", "stopped", "failed", "expired"] + + schema_: Optional[str] = FieldInfo(alias="$schema", default=None) + """A URL to the JSON Schema for this object.""" + + error: Optional[Error] = None + + started_at: Optional[datetime] = FieldInfo(alias="startedAt", default=None) + + stopped_at: Optional[datetime] = FieldInfo(alias="stoppedAt", default=None) + + stream: Optional[Stream] = None diff --git a/src/mobilerun_sdk/types/devices/traffic_session_delete_response.py b/src/mobilerun_sdk/types/devices/traffic_session_delete_response.py new file mode 100644 index 00000000..4b1ff552 --- /dev/null +++ b/src/mobilerun_sdk/types/devices/traffic_session_delete_response.py @@ -0,0 +1,52 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["TrafficSessionDeleteResponse", "Error", "Stream"] + + +class Error(BaseModel): + code: str + + message: str + + +class Stream(BaseModel): + token: str + + protocol: str + + url: str + + +class TrafficSessionDeleteResponse(BaseModel): + id: str + + created_at: datetime = FieldInfo(alias="createdAt") + + device_id: str = FieldInfo(alias="deviceId") + + expires_at: datetime = FieldInfo(alias="expiresAt") + + max_body_bytes: int = FieldInfo(alias="maxBodyBytes") + + retention: Literal["none"] + + state: Literal["starting", "active", "stopping", "stopped", "failed", "expired"] + + schema_: Optional[str] = FieldInfo(alias="$schema", default=None) + """A URL to the JSON Schema for this object.""" + + error: Optional[Error] = None + + started_at: Optional[datetime] = FieldInfo(alias="startedAt", default=None) + + stopped_at: Optional[datetime] = FieldInfo(alias="stoppedAt", default=None) + + stream: Optional[Stream] = None diff --git a/src/mobilerun_sdk/types/esim_selector_params.py b/src/mobilerun_sdk/types/devices/traffic_session_list_params.py similarity index 66% rename from src/mobilerun_sdk/types/esim_selector_params.py rename to src/mobilerun_sdk/types/devices/traffic_session_list_params.py index d5cd46c1..9685e594 100644 --- a/src/mobilerun_sdk/types/esim_selector_params.py +++ b/src/mobilerun_sdk/types/devices/traffic_session_list_params.py @@ -4,12 +4,12 @@ from typing_extensions import Annotated, TypedDict -from .._utils import PropertyInfo +from ..._utils import PropertyInfo -__all__ = ["EsimSelectorParams"] +__all__ = ["TrafficSessionListParams"] -class EsimSelectorParams(TypedDict, total=False): +class TrafficSessionListParams(TypedDict, total=False): page: int page_size: Annotated[int, PropertyInfo(alias="pageSize")] diff --git a/src/mobilerun_sdk/types/devices/traffic_session_list_response.py b/src/mobilerun_sdk/types/devices/traffic_session_list_response.py new file mode 100644 index 00000000..d4a13f54 --- /dev/null +++ b/src/mobilerun_sdk/types/devices/traffic_session_list_response.py @@ -0,0 +1,62 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel +from ..shared.meta import Meta + +__all__ = ["TrafficSessionListResponse", "Item", "ItemError", "ItemStream"] + + +class ItemError(BaseModel): + code: str + + message: str + + +class ItemStream(BaseModel): + token: str + + protocol: str + + url: str + + +class Item(BaseModel): + id: str + + created_at: datetime = FieldInfo(alias="createdAt") + + device_id: str = FieldInfo(alias="deviceId") + + expires_at: datetime = FieldInfo(alias="expiresAt") + + max_body_bytes: int = FieldInfo(alias="maxBodyBytes") + + retention: Literal["none"] + + state: Literal["starting", "active", "stopping", "stopped", "failed", "expired"] + + schema_: Optional[str] = FieldInfo(alias="$schema", default=None) + """A URL to the JSON Schema for this object.""" + + error: Optional[ItemError] = None + + started_at: Optional[datetime] = FieldInfo(alias="startedAt", default=None) + + stopped_at: Optional[datetime] = FieldInfo(alias="stoppedAt", default=None) + + stream: Optional[ItemStream] = None + + +class TrafficSessionListResponse(BaseModel): + items: Optional[List[Item]] = None + + pagination: Meta + + schema_: Optional[str] = FieldInfo(alias="$schema", default=None) + """A URL to the JSON Schema for this object.""" diff --git a/src/mobilerun_sdk/types/devices/traffic_session_retrieve_response.py b/src/mobilerun_sdk/types/devices/traffic_session_retrieve_response.py new file mode 100644 index 00000000..6534ad06 --- /dev/null +++ b/src/mobilerun_sdk/types/devices/traffic_session_retrieve_response.py @@ -0,0 +1,52 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["TrafficSessionRetrieveResponse", "Error", "Stream"] + + +class Error(BaseModel): + code: str + + message: str + + +class Stream(BaseModel): + token: str + + protocol: str + + url: str + + +class TrafficSessionRetrieveResponse(BaseModel): + id: str + + created_at: datetime = FieldInfo(alias="createdAt") + + device_id: str = FieldInfo(alias="deviceId") + + expires_at: datetime = FieldInfo(alias="expiresAt") + + max_body_bytes: int = FieldInfo(alias="maxBodyBytes") + + retention: Literal["none"] + + state: Literal["starting", "active", "stopping", "stopped", "failed", "expired"] + + schema_: Optional[str] = FieldInfo(alias="$schema", default=None) + """A URL to the JSON Schema for this object.""" + + error: Optional[Error] = None + + started_at: Optional[datetime] = FieldInfo(alias="startedAt", default=None) + + stopped_at: Optional[datetime] = FieldInfo(alias="stoppedAt", default=None) + + stream: Optional[Stream] = None diff --git a/src/mobilerun_sdk/types/esim_capacity_response.py b/src/mobilerun_sdk/types/esim_capacity_response.py deleted file mode 100644 index 69204004..00000000 --- a/src/mobilerun_sdk/types/esim_capacity_response.py +++ /dev/null @@ -1,17 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["EsimCapacityResponse", "Data"] - - -class Data(BaseModel): - available: bool - - free_devices: int = FieldInfo(alias="freeDevices") - - -class EsimCapacityResponse(BaseModel): - data: Data diff --git a/src/mobilerun_sdk/types/esim_confirm_payment_response.py b/src/mobilerun_sdk/types/esim_confirm_payment_response.py deleted file mode 100644 index d981ab88..00000000 --- a/src/mobilerun_sdk/types/esim_confirm_payment_response.py +++ /dev/null @@ -1,69 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["EsimConfirmPaymentResponse", "Data"] - - -class Data(BaseModel): - id: str - - carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None) - - country_code: Optional[str] = FieldInfo(alias="countryCode", default=None) - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - created_by: Optional[str] = FieldInfo(alias="createdBy", default=None) - - device_id: Optional[str] = FieldInfo(alias="deviceId", default=None) - - device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None) - - iccid: Optional[str] = None - - msisdn: Optional[str] = None - - name: Optional[str] = None - - network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None) - - source: Literal["stocked", "byo"] - - status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"] - - subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None) - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - - cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None) - - checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None) - - current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) - - exempt: Optional[bool] = None - - rent_status: Optional[ - Literal[ - "not_applicable", - "exempt", - "inactive", - "awaiting_payment", - "active", - "cancel_pending", - "refund_pending", - "retiring", - "billing_error", - ] - ] = FieldInfo(alias="rentStatus", default=None) - - -class EsimConfirmPaymentResponse(BaseModel): - data: Data diff --git a/src/mobilerun_sdk/types/esim_create_params.py b/src/mobilerun_sdk/types/esim_create_params.py deleted file mode 100644 index 973cbd1d..00000000 --- a/src/mobilerun_sdk/types/esim_create_params.py +++ /dev/null @@ -1,24 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import Annotated, TypedDict - -from .._utils import PropertyInfo - -__all__ = ["EsimCreateParams"] - - -class EsimCreateParams(TypedDict, total=False): - idempotency_key: Annotated[str, PropertyInfo(alias="idempotencyKey")] - """ - Client-supplied key; replaying the same key returns the original purchase - instead of buying again - """ - - name: Optional[str] - """Optional user-defined display label — NFC-normalized, up to 15 GRAPHEMES. - - Omit or null for no label. - """ diff --git a/src/mobilerun_sdk/types/esim_create_response.py b/src/mobilerun_sdk/types/esim_create_response.py deleted file mode 100644 index 11111f7a..00000000 --- a/src/mobilerun_sdk/types/esim_create_response.py +++ /dev/null @@ -1,69 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["EsimCreateResponse", "Data"] - - -class Data(BaseModel): - id: str - - carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None) - - country_code: Optional[str] = FieldInfo(alias="countryCode", default=None) - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - created_by: Optional[str] = FieldInfo(alias="createdBy", default=None) - - device_id: Optional[str] = FieldInfo(alias="deviceId", default=None) - - device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None) - - iccid: Optional[str] = None - - msisdn: Optional[str] = None - - name: Optional[str] = None - - network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None) - - source: Literal["stocked", "byo"] - - status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"] - - subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None) - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - - cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None) - - checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None) - - current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) - - exempt: Optional[bool] = None - - rent_status: Optional[ - Literal[ - "not_applicable", - "exempt", - "inactive", - "awaiting_payment", - "active", - "cancel_pending", - "refund_pending", - "retiring", - "billing_error", - ] - ] = FieldInfo(alias="rentStatus", default=None) - - -class EsimCreateResponse(BaseModel): - data: Data diff --git a/src/mobilerun_sdk/types/esim_import_params.py b/src/mobilerun_sdk/types/esim_import_params.py deleted file mode 100644 index 59433916..00000000 --- a/src/mobilerun_sdk/types/esim_import_params.py +++ /dev/null @@ -1,59 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import Annotated, TypedDict - -from .._utils import PropertyInfo - -__all__ = ["EsimImportParams"] - - -class EsimImportParams(TypedDict, total=False): - auto_install: Annotated[bool, PropertyInfo(alias="autoInstall")] - """Rent OFF only: dispatch install-on-device immediately after a successful import. - - No-op when ESIM_BYO_RENT_ENABLED=true. - """ - - carrier_name: Annotated[str, PropertyInfo(alias="carrierName")] - - confirmation_code: Annotated[str, PropertyInfo(alias="confirmationCode")] - - country_code: Annotated[str, PropertyInfo(alias="countryCode")] - - device_id: Annotated[str, PropertyInfo(alias="deviceId")] - """physedge device id to auto-install onto; requires autoInstall:true and rent OFF. - - Omit for a random pool device. - """ - - idempotency_key: Annotated[str, PropertyInfo(alias="idempotencyKey")] - """ - Client-supplied key; replaying the same key+request returns the original import - instead of importing again - """ - - lpa_code: Annotated[str, PropertyInfo(alias="lpaCode")] - """Full LPA activation code""" - - matching_id: Annotated[str, PropertyInfo(alias="matchingId")] - - msisdn: str - """ - Self-reported E.164 MSISDN for this eSIM's line — an unverified label, never - used for routing - """ - - name: Optional[str] - """ - User-defined display label — NFC-normalized, up to 15 GRAPHEMES (not UTF-16 code - units; an emoji/flag may span several). Omit/null/empty/whitespace-only leaves - it unset. - """ - - notes: str - - smdp_address: Annotated[str, PropertyInfo(alias="smdpAddress")] - """SM-DP+ activation host — bare hostname ONLY, no port/scheme/path.""" diff --git a/src/mobilerun_sdk/types/esim_import_response.py b/src/mobilerun_sdk/types/esim_import_response.py deleted file mode 100644 index 5ab93dba..00000000 --- a/src/mobilerun_sdk/types/esim_import_response.py +++ /dev/null @@ -1,204 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Union, Optional -from datetime import datetime -from typing_extensions import Literal, TypeAlias - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = [ - "EsimImportResponse", - "Data", - "DataPublicEsim", - "DataEsimAwaitingPaymentResponse", - "DataEsimAwaitingPaymentResponseEsim", - "DataEsimImportInstallDispatchFailedResponse", - "DataEsimImportInstallDispatchFailedResponseInstallDispatch", -] - - -class DataPublicEsim(BaseModel): - id: str - - carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None) - - country_code: Optional[str] = FieldInfo(alias="countryCode", default=None) - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - created_by: Optional[str] = FieldInfo(alias="createdBy", default=None) - - device_id: Optional[str] = FieldInfo(alias="deviceId", default=None) - - device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None) - - iccid: Optional[str] = None - - msisdn: Optional[str] = None - - name: Optional[str] = None - - network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None) - - source: Literal["stocked", "byo"] - - status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"] - - subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None) - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - - cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None) - - checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None) - - current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) - - exempt: Optional[bool] = None - - rent_status: Optional[ - Literal[ - "not_applicable", - "exempt", - "inactive", - "awaiting_payment", - "active", - "cancel_pending", - "refund_pending", - "retiring", - "billing_error", - ] - ] = FieldInfo(alias="rentStatus", default=None) - - -class DataEsimAwaitingPaymentResponseEsim(BaseModel): - id: str - - carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None) - - country_code: Optional[str] = FieldInfo(alias="countryCode", default=None) - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - created_by: Optional[str] = FieldInfo(alias="createdBy", default=None) - - device_id: Optional[str] = FieldInfo(alias="deviceId", default=None) - - device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None) - - iccid: Optional[str] = None - - msisdn: Optional[str] = None - - name: Optional[str] = None - - network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None) - - source: Literal["stocked", "byo"] - - status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"] - - subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None) - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - - cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None) - - checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None) - - current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) - - exempt: Optional[bool] = None - - rent_status: Optional[ - Literal[ - "not_applicable", - "exempt", - "inactive", - "awaiting_payment", - "active", - "cancel_pending", - "refund_pending", - "retiring", - "billing_error", - ] - ] = FieldInfo(alias="rentStatus", default=None) - - -class DataEsimAwaitingPaymentResponse(BaseModel): - checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None) - - esim: DataEsimAwaitingPaymentResponseEsim - - rent_status: Literal["awaiting_payment"] = FieldInfo(alias="rentStatus") - - -class DataEsimImportInstallDispatchFailedResponseInstallDispatch(BaseModel): - ok: Literal[False] - - reason: str - - -class DataEsimImportInstallDispatchFailedResponse(BaseModel): - id: str - - carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None) - - country_code: Optional[str] = FieldInfo(alias="countryCode", default=None) - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - created_by: Optional[str] = FieldInfo(alias="createdBy", default=None) - - device_id: Optional[str] = FieldInfo(alias="deviceId", default=None) - - device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None) - - iccid: Optional[str] = None - - install_dispatch: DataEsimImportInstallDispatchFailedResponseInstallDispatch = FieldInfo(alias="installDispatch") - - msisdn: Optional[str] = None - - name: Optional[str] = None - - network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None) - - source: Literal["stocked", "byo"] - - status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"] - - subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None) - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - - cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None) - - checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None) - - current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) - - exempt: Optional[bool] = None - - rent_status: Optional[ - Literal[ - "not_applicable", - "exempt", - "inactive", - "awaiting_payment", - "active", - "cancel_pending", - "refund_pending", - "retiring", - "billing_error", - ] - ] = FieldInfo(alias="rentStatus", default=None) - - -Data: TypeAlias = Union[DataPublicEsim, DataEsimAwaitingPaymentResponse, DataEsimImportInstallDispatchFailedResponse] - - -class EsimImportResponse(BaseModel): - data: Data diff --git a/src/mobilerun_sdk/types/esim_install_params.py b/src/mobilerun_sdk/types/esim_install_params.py deleted file mode 100644 index ca23a433..00000000 --- a/src/mobilerun_sdk/types/esim_install_params.py +++ /dev/null @@ -1,14 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Annotated, TypedDict - -from .._utils import PropertyInfo - -__all__ = ["EsimInstallParams"] - - -class EsimInstallParams(TypedDict, total=False): - device_id: Annotated[str, PropertyInfo(alias="deviceId")] - """physedge device id to install the eSIM onto; omit for a random pool device""" diff --git a/src/mobilerun_sdk/types/esim_install_response.py b/src/mobilerun_sdk/types/esim_install_response.py deleted file mode 100644 index 24ea2f92..00000000 --- a/src/mobilerun_sdk/types/esim_install_response.py +++ /dev/null @@ -1,69 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["EsimInstallResponse", "Data"] - - -class Data(BaseModel): - id: str - - carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None) - - country_code: Optional[str] = FieldInfo(alias="countryCode", default=None) - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - created_by: Optional[str] = FieldInfo(alias="createdBy", default=None) - - device_id: Optional[str] = FieldInfo(alias="deviceId", default=None) - - device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None) - - iccid: Optional[str] = None - - msisdn: Optional[str] = None - - name: Optional[str] = None - - network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None) - - source: Literal["stocked", "byo"] - - status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"] - - subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None) - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - - cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None) - - checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None) - - current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) - - exempt: Optional[bool] = None - - rent_status: Optional[ - Literal[ - "not_applicable", - "exempt", - "inactive", - "awaiting_payment", - "active", - "cancel_pending", - "refund_pending", - "retiring", - "billing_error", - ] - ] = FieldInfo(alias="rentStatus", default=None) - - -class EsimInstallResponse(BaseModel): - data: Data diff --git a/src/mobilerun_sdk/types/esim_install_status_response.py b/src/mobilerun_sdk/types/esim_install_status_response.py deleted file mode 100644 index 87f8c3e5..00000000 --- a/src/mobilerun_sdk/types/esim_install_status_response.py +++ /dev/null @@ -1,93 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["EsimInstallStatusResponse", "Data", "DataEsim"] - - -class DataEsim(BaseModel): - id: str - - carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None) - - country_code: Optional[str] = FieldInfo(alias="countryCode", default=None) - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - created_by: Optional[str] = FieldInfo(alias="createdBy", default=None) - - device_id: Optional[str] = FieldInfo(alias="deviceId", default=None) - - device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None) - - iccid: Optional[str] = None - - msisdn: Optional[str] = None - - name: Optional[str] = None - - network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None) - - source: Literal["stocked", "byo"] - - status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"] - - subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None) - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - - cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None) - - checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None) - - current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) - - exempt: Optional[bool] = None - - rent_status: Optional[ - Literal[ - "not_applicable", - "exempt", - "inactive", - "awaiting_payment", - "active", - "cancel_pending", - "refund_pending", - "retiring", - "billing_error", - ] - ] = FieldInfo(alias="rentStatus", default=None) - - -class Data(BaseModel): - esim: DataEsim - - operation_id: Optional[str] = FieldInfo(alias="operationId", default=None) - - status: Optional[ - Literal[ - "installing", - "pending_download", - "downloading", - "downloaded", - "enabling", - "configuring_apn", - "active", - "download_failed", - "enable_failed", - "download_outcome_unknown", - "install_failed", - "physical_removal_unconfirmed", - "deleted", - ] - ] = None - - -class EsimInstallStatusResponse(BaseModel): - data: Data diff --git a/src/mobilerun_sdk/types/esim_list_params.py b/src/mobilerun_sdk/types/esim_list_params.py deleted file mode 100644 index a653308b..00000000 --- a/src/mobilerun_sdk/types/esim_list_params.py +++ /dev/null @@ -1,20 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Annotated, TypedDict - -from .._utils import PropertyInfo - -__all__ = ["EsimListParams"] - - -class EsimListParams(TypedDict, total=False): - mine: Literal["true", "false"] - """Only include eSIMs created by the calling actor.""" - - page: int - - page_size: Annotated[int, PropertyInfo(alias="pageSize")] - - status: Literal["all", "in_stock", "owned", "installing", "installed", "install_failed", "retired"] diff --git a/src/mobilerun_sdk/types/esim_list_response.py b/src/mobilerun_sdk/types/esim_list_response.py deleted file mode 100644 index 5c236e21..00000000 --- a/src/mobilerun_sdk/types/esim_list_response.py +++ /dev/null @@ -1,72 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel -from .shared.pagination import Pagination - -__all__ = ["EsimListResponse", "Item"] - - -class Item(BaseModel): - id: str - - carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None) - - country_code: Optional[str] = FieldInfo(alias="countryCode", default=None) - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - created_by: Optional[str] = FieldInfo(alias="createdBy", default=None) - - device_id: Optional[str] = FieldInfo(alias="deviceId", default=None) - - device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None) - - iccid: Optional[str] = None - - msisdn: Optional[str] = None - - name: Optional[str] = None - - network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None) - - source: Literal["stocked", "byo"] - - status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"] - - subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None) - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - - cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None) - - checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None) - - current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) - - exempt: Optional[bool] = None - - rent_status: Optional[ - Literal[ - "not_applicable", - "exempt", - "inactive", - "awaiting_payment", - "active", - "cancel_pending", - "refund_pending", - "retiring", - "billing_error", - ] - ] = FieldInfo(alias="rentStatus", default=None) - - -class EsimListResponse(BaseModel): - items: List[Item] - - pagination: Pagination diff --git a/src/mobilerun_sdk/types/esim_retrieve_response.py b/src/mobilerun_sdk/types/esim_retrieve_response.py deleted file mode 100644 index 41cf5a88..00000000 --- a/src/mobilerun_sdk/types/esim_retrieve_response.py +++ /dev/null @@ -1,69 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["EsimRetrieveResponse", "Data"] - - -class Data(BaseModel): - id: str - - carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None) - - country_code: Optional[str] = FieldInfo(alias="countryCode", default=None) - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - created_by: Optional[str] = FieldInfo(alias="createdBy", default=None) - - device_id: Optional[str] = FieldInfo(alias="deviceId", default=None) - - device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None) - - iccid: Optional[str] = None - - msisdn: Optional[str] = None - - name: Optional[str] = None - - network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None) - - source: Literal["stocked", "byo"] - - status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"] - - subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None) - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - - cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None) - - checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None) - - current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) - - exempt: Optional[bool] = None - - rent_status: Optional[ - Literal[ - "not_applicable", - "exempt", - "inactive", - "awaiting_payment", - "active", - "cancel_pending", - "refund_pending", - "retiring", - "billing_error", - ] - ] = FieldInfo(alias="rentStatus", default=None) - - -class EsimRetrieveResponse(BaseModel): - data: Data diff --git a/src/mobilerun_sdk/types/esim_selector_response.py b/src/mobilerun_sdk/types/esim_selector_response.py deleted file mode 100644 index 4288bcf9..00000000 --- a/src/mobilerun_sdk/types/esim_selector_response.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel -from .shared.pagination import Pagination - -__all__ = ["EsimSelectorResponse", "Item"] - - -class Item(BaseModel): - id: str - - carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None) - - iccid: Optional[str] = None - - msisdn: Optional[str] = None - - name: Optional[str] = None - - source: Literal["stocked", "byo"] - - status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"] - - -class EsimSelectorResponse(BaseModel): - items: List[Item] - - pagination: Pagination diff --git a/src/mobilerun_sdk/types/esim_update_params.py b/src/mobilerun_sdk/types/esim_update_params.py deleted file mode 100644 index a0fdc6de..00000000 --- a/src/mobilerun_sdk/types/esim_update_params.py +++ /dev/null @@ -1,24 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import TypedDict - -__all__ = ["EsimUpdateParams"] - - -class EsimUpdateParams(TypedDict, total=False): - msisdn: Optional[str] - """Self-reported E.164 MSISDN for this eSIM's line. - - Omit to leave unchanged; null/empty clears it. An unverified label — never used - for routing. - """ - - name: Optional[str] - """ - User-defined display label — NFC-normalized, up to 15 GRAPHEMES (not UTF-16 code - units; an emoji/flag may span several). Omit to leave unchanged; - null/empty/whitespace-only clears it. - """ diff --git a/src/mobilerun_sdk/types/esim_update_response.py b/src/mobilerun_sdk/types/esim_update_response.py deleted file mode 100644 index 407eb7d9..00000000 --- a/src/mobilerun_sdk/types/esim_update_response.py +++ /dev/null @@ -1,69 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["EsimUpdateResponse", "Data"] - - -class Data(BaseModel): - id: str - - carrier_name: Optional[str] = FieldInfo(alias="carrierName", default=None) - - country_code: Optional[str] = FieldInfo(alias="countryCode", default=None) - - created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None) - - created_by: Optional[str] = FieldInfo(alias="createdBy", default=None) - - device_id: Optional[str] = FieldInfo(alias="deviceId", default=None) - - device_uuid: Optional[str] = FieldInfo(alias="deviceUuid", default=None) - - iccid: Optional[str] = None - - msisdn: Optional[str] = None - - name: Optional[str] = None - - network_status: Optional[Literal["degraded"]] = FieldInfo(alias="networkStatus", default=None) - - source: Literal["stocked", "byo"] - - status: Literal["in_stock", "owned", "installing", "installed", "install_failed", "retired"] - - subscription_id: Optional[int] = FieldInfo(alias="subscriptionId", default=None) - - updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) - - cancellation_scheduled: Optional[bool] = FieldInfo(alias="cancellationScheduled", default=None) - - checkout_url: Optional[str] = FieldInfo(alias="checkoutUrl", default=None) - - current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) - - exempt: Optional[bool] = None - - rent_status: Optional[ - Literal[ - "not_applicable", - "exempt", - "inactive", - "awaiting_payment", - "active", - "cancel_pending", - "refund_pending", - "retiring", - "billing_error", - ] - ] = FieldInfo(alias="rentStatus", default=None) - - -class EsimUpdateResponse(BaseModel): - data: Data diff --git a/src/mobilerun_sdk/types/esims/__init__.py b/src/mobilerun_sdk/types/esims/__init__.py deleted file mode 100644 index d059c99c..00000000 --- a/src/mobilerun_sdk/types/esims/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .message_list_params import MessageListParams as MessageListParams -from .message_send_params import MessageSendParams as MessageSendParams -from .message_list_response import MessageListResponse as MessageListResponse -from .message_send_response import MessageSendResponse as MessageSendResponse diff --git a/src/mobilerun_sdk/types/esims/message_list_params.py b/src/mobilerun_sdk/types/esims/message_list_params.py deleted file mode 100644 index c55e68af..00000000 --- a/src/mobilerun_sdk/types/esims/message_list_params.py +++ /dev/null @@ -1,27 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Annotated, TypedDict - -from ..._utils import PropertyInfo - -__all__ = ["MessageListParams"] - - -class MessageListParams(TypedDict, total=False): - direction: Literal["all", "inbound", "outbound"] - - number_id: Annotated[str, PropertyInfo(alias="numberId")] - - page: int - - page_size: Annotated[int, PropertyInfo(alias="pageSize")] - - peer_key: Annotated[str, PropertyInfo(alias="peerKey")] - - peer_number: Annotated[str, PropertyInfo(alias="peerNumber")] - - status: Literal[ - "all", "received", "queued", "claimed", "sending", "sent", "sent_unconfirmed", "delivered", "failed" - ] diff --git a/src/mobilerun_sdk/types/esims/message_list_response.py b/src/mobilerun_sdk/types/esims/message_list_response.py deleted file mode 100644 index c04b3d46..00000000 --- a/src/mobilerun_sdk/types/esims/message_list_response.py +++ /dev/null @@ -1,44 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel -from ..shared.pagination import Pagination - -__all__ = ["MessageListResponse", "Item"] - - -class Item(BaseModel): - id: str - - body: Optional[str] = None - - created_at: datetime = FieldInfo(alias="createdAt") - - delivery_status: Optional[str] = FieldInfo(alias="deliveryStatus", default=None) - - detected_sender: Optional[str] = FieldInfo(alias="detectedSender", default=None) - - direction: Literal["inbound", "outbound"] - - esim_id: Optional[str] = FieldInfo(alias="esimId", default=None) - - occurred_at: datetime = FieldInfo(alias="occurredAt") - - peer_key: Optional[str] = FieldInfo(alias="peerKey", default=None) - - peer_number: Optional[str] = FieldInfo(alias="peerNumber", default=None) - - provider_code: Optional[str] = FieldInfo(alias="providerCode", default=None) - - status: Literal["received", "queued", "claimed", "sending", "sent", "sent_unconfirmed", "delivered", "failed"] - - -class MessageListResponse(BaseModel): - items: List[Item] - - pagination: Pagination diff --git a/src/mobilerun_sdk/types/esims/message_send_params.py b/src/mobilerun_sdk/types/esims/message_send_params.py deleted file mode 100644 index 48c2c65a..00000000 --- a/src/mobilerun_sdk/types/esims/message_send_params.py +++ /dev/null @@ -1,38 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Required, Annotated, TypedDict - -from ..._utils import PropertyInfo - -__all__ = ["MessageSendParams"] - - -class MessageSendParams(TypedDict, total=False): - body: Required[str] - """ - SMS body text (max 320 chars — smaller than the admin tier's cap; see the - schema's own doc comment for why) - """ - - to: Required[str] - """ - Recipient phone number — normalized to E.164 (spaces/dashes/dots stripped); - rejected with 400 if it doesn't validate as E.164 afterward. - """ - - client_request_id: Annotated[str, PropertyInfo(alias="clientRequestId")] - """Client-supplied idempotency key, scoped to (owner, esimId, key). - - Replaying the same key + identical payload returns the original send; the same - key with a DIFFERENT payload is a 409 conflict. - """ - - delivery_report: Annotated[bool, PropertyInfo(alias="deliveryReport")] - """ - Wait for physedge to confirm carrier delivery before completing the send (adds - executor-side latency, never on this request — sends are always async/202). - Defaults to false for the public tier (opt-in, unlike the admin tier's - default-true). - """ diff --git a/src/mobilerun_sdk/types/esims/message_send_response.py b/src/mobilerun_sdk/types/esims/message_send_response.py deleted file mode 100644 index 86e545d6..00000000 --- a/src/mobilerun_sdk/types/esims/message_send_response.py +++ /dev/null @@ -1,41 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel - -__all__ = ["MessageSendResponse", "Data"] - - -class Data(BaseModel): - id: str - - body: Optional[str] = None - - created_at: datetime = FieldInfo(alias="createdAt") - - delivery_status: Optional[str] = FieldInfo(alias="deliveryStatus", default=None) - - detected_sender: Optional[str] = FieldInfo(alias="detectedSender", default=None) - - direction: Literal["inbound", "outbound"] - - esim_id: Optional[str] = FieldInfo(alias="esimId", default=None) - - occurred_at: datetime = FieldInfo(alias="occurredAt") - - peer_key: Optional[str] = FieldInfo(alias="peerKey", default=None) - - peer_number: Optional[str] = FieldInfo(alias="peerNumber", default=None) - - provider_code: Optional[str] = FieldInfo(alias="providerCode", default=None) - - status: Literal["received", "queued", "claimed", "sending", "sent", "sent_unconfirmed", "delivered", "failed"] - - -class MessageSendResponse(BaseModel): - data: Data diff --git a/src/mobilerun_sdk/types/file_confirm_response.py b/src/mobilerun_sdk/types/file_confirm_response.py deleted file mode 100644 index 7ee2a30c..00000000 --- a/src/mobilerun_sdk/types/file_confirm_response.py +++ /dev/null @@ -1,35 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["FileConfirmResponse"] - - -class FileConfirmResponse(BaseModel): - actual_size_bytes: float = FieldInfo(alias="actualSizeBytes") - - created_at: datetime = FieldInfo(alias="createdAt") - - created_by: Literal["user", "agent", "workflow"] = FieldInfo(alias="createdBy") - - display_name: Optional[str] = FieldInfo(alias="displayName", default=None) - - enabled: bool - - file_id: str = FieldInfo(alias="fileId") - - filename: str - - mime_type: str = FieldInfo(alias="mimeType") - - size_bytes: float = FieldInfo(alias="sizeBytes") - - state: Literal["ready"] - - zone: Literal["user", "agent", "workflow", "skills"] diff --git a/src/mobilerun_sdk/types/file_list_params.py b/src/mobilerun_sdk/types/file_list_params.py deleted file mode 100644 index fe1d5561..00000000 --- a/src/mobilerun_sdk/types/file_list_params.py +++ /dev/null @@ -1,11 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, TypedDict - -__all__ = ["FileListParams"] - - -class FileListParams(TypedDict, total=False): - zone: Literal["user", "agent", "workflow", "skills"] diff --git a/src/mobilerun_sdk/types/file_list_response.py b/src/mobilerun_sdk/types/file_list_response.py deleted file mode 100644 index 014c11fb..00000000 --- a/src/mobilerun_sdk/types/file_list_response.py +++ /dev/null @@ -1,43 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["FileListResponse", "File", "Quota"] - - -class File(BaseModel): - created_at: datetime = FieldInfo(alias="createdAt") - - created_by: Literal["user", "agent", "workflow"] = FieldInfo(alias="createdBy") - - display_name: Optional[str] = FieldInfo(alias="displayName", default=None) - - enabled: bool - - file_id: str = FieldInfo(alias="fileId") - - filename: str - - mime_type: str = FieldInfo(alias="mimeType") - - size_bytes: float = FieldInfo(alias="sizeBytes") - - zone: Literal["user", "agent", "workflow", "skills"] - - -class Quota(BaseModel): - current_bytes: int = FieldInfo(alias="currentBytes") - - quota_bytes: int = FieldInfo(alias="quotaBytes") - - -class FileListResponse(BaseModel): - files: List[File] - - quota: Quota diff --git a/src/mobilerun_sdk/types/file_update_params.py b/src/mobilerun_sdk/types/file_update_params.py deleted file mode 100644 index e6da4e5a..00000000 --- a/src/mobilerun_sdk/types/file_update_params.py +++ /dev/null @@ -1,16 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Optional -from typing_extensions import Annotated, TypedDict - -from .._utils import PropertyInfo - -__all__ = ["FileUpdateParams"] - - -class FileUpdateParams(TypedDict, total=False): - display_name: Annotated[Optional[str], PropertyInfo(alias="displayName")] - - enabled: bool diff --git a/src/mobilerun_sdk/types/file_update_response.py b/src/mobilerun_sdk/types/file_update_response.py deleted file mode 100644 index a3903256..00000000 --- a/src/mobilerun_sdk/types/file_update_response.py +++ /dev/null @@ -1,31 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .._models import BaseModel - -__all__ = ["FileUpdateResponse"] - - -class FileUpdateResponse(BaseModel): - created_at: datetime = FieldInfo(alias="createdAt") - - created_by: Literal["user", "agent", "workflow"] = FieldInfo(alias="createdBy") - - display_name: Optional[str] = FieldInfo(alias="displayName", default=None) - - enabled: bool - - file_id: str = FieldInfo(alias="fileId") - - filename: str - - mime_type: str = FieldInfo(alias="mimeType") - - size_bytes: float = FieldInfo(alias="sizeBytes") - - zone: Literal["user", "agent", "workflow", "skills"] diff --git a/src/mobilerun_sdk/types/mailbox_create_params.py b/src/mobilerun_sdk/types/mailbox_create_params.py index bd5b7ce5..68cf68f8 100644 --- a/src/mobilerun_sdk/types/mailbox_create_params.py +++ b/src/mobilerun_sdk/types/mailbox_create_params.py @@ -12,18 +12,20 @@ class MailboxCreateParams(TypedDict, total=False): client_request_id: Required[Annotated[str, PropertyInfo(alias="clientRequestId")]] - billing_preference: Annotated[Literal["included", "rent"], PropertyInfo(alias="billingPreference")] - """Funding preference. + billing_preference: Annotated[Literal["included", "included_only", "rent"], PropertyInfo(alias="billingPreference")] + """ + included uses package capacity when available and otherwise starts paid + checkout; included_only fails without creating a paid reservation when no + included slot remains; rent always starts paid checkout. + """ + + domain_id: Annotated[str, PropertyInfo(alias="domainId")] + """Optional active custom mailbox domain owned by the caller. - Omit or use included for included-first activation; rent always preserves - package capacity and starts paid checkout. + Omit to use the system domain. """ label: str local_part: Annotated[str, PropertyInfo(alias="localPart")] - """Optional full mailbox local part (the address before "@"). - - Trimmed and lowercased before validation. Omit for a random, non-guessable - mx\\__-prefixed address. - """ + """Optional mailbox name before the "@". Omit to generate a random address.""" diff --git a/src/mobilerun_sdk/types/mailbox_create_response.py b/src/mobilerun_sdk/types/mailbox_create_response.py index 0ed4e6c4..2bb8b3c9 100644 --- a/src/mobilerun_sdk/types/mailbox_create_response.py +++ b/src/mobilerun_sdk/types/mailbox_create_response.py @@ -26,7 +26,7 @@ class Data(BaseModel): address: Optional[str] = None - billing_mode: Literal["rent", "included"] = FieldInfo(alias="billingMode") + billing_mode: Literal["rent", "included", "domain"] = FieldInfo(alias="billingMode") cancel_at_period_end: bool = FieldInfo(alias="cancelAtPeriodEnd") @@ -38,6 +38,8 @@ class Data(BaseModel): current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) + domain_id: Optional[str] = FieldInfo(alias="domainId", default=None) + inbound_messages: DataInboundMessages = FieldInfo(alias="inboundMessages") label: Optional[str] = None diff --git a/src/mobilerun_sdk/types/mailbox_delete_response.py b/src/mobilerun_sdk/types/mailbox_delete_response.py index 7b6675cd..ac6cd9b8 100644 --- a/src/mobilerun_sdk/types/mailbox_delete_response.py +++ b/src/mobilerun_sdk/types/mailbox_delete_response.py @@ -26,7 +26,7 @@ class Data(BaseModel): address: Optional[str] = None - billing_mode: Literal["rent", "included"] = FieldInfo(alias="billingMode") + billing_mode: Literal["rent", "included", "domain"] = FieldInfo(alias="billingMode") cancel_at_period_end: bool = FieldInfo(alias="cancelAtPeriodEnd") @@ -38,6 +38,8 @@ class Data(BaseModel): current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) + domain_id: Optional[str] = FieldInfo(alias="domainId", default=None) + inbound_messages: DataInboundMessages = FieldInfo(alias="inboundMessages") label: Optional[str] = None diff --git a/src/mobilerun_sdk/types/mailbox_list_response.py b/src/mobilerun_sdk/types/mailbox_list_response.py index df935fc8..70ace920 100644 --- a/src/mobilerun_sdk/types/mailbox_list_response.py +++ b/src/mobilerun_sdk/types/mailbox_list_response.py @@ -27,7 +27,7 @@ class Item(BaseModel): address: Optional[str] = None - billing_mode: Literal["rent", "included"] = FieldInfo(alias="billingMode") + billing_mode: Literal["rent", "included", "domain"] = FieldInfo(alias="billingMode") cancel_at_period_end: bool = FieldInfo(alias="cancelAtPeriodEnd") @@ -39,6 +39,8 @@ class Item(BaseModel): current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) + domain_id: Optional[str] = FieldInfo(alias="domainId", default=None) + inbound_messages: ItemInboundMessages = FieldInfo(alias="inboundMessages") label: Optional[str] = None diff --git a/src/mobilerun_sdk/types/mailbox_otp_response.py b/src/mobilerun_sdk/types/mailbox_otp_response.py index 28ce8f48..540069ac 100644 --- a/src/mobilerun_sdk/types/mailbox_otp_response.py +++ b/src/mobilerun_sdk/types/mailbox_otp_response.py @@ -13,7 +13,7 @@ class Data(BaseModel): code: str - """String to preserve leading zeros""" + """OTP code as text to preserve leading zeros.""" confidence: Literal["high", "medium", "low"] diff --git a/src/mobilerun_sdk/types/mailbox_restart_params.py b/src/mobilerun_sdk/types/mailbox_restart_params.py index 497bb7e0..ca174720 100644 --- a/src/mobilerun_sdk/types/mailbox_restart_params.py +++ b/src/mobilerun_sdk/types/mailbox_restart_params.py @@ -10,9 +10,9 @@ class MailboxRestartParams(TypedDict, total=False): - billing_preference: Annotated[Literal["included", "rent"], PropertyInfo(alias="billingPreference")] - """Funding preference. - - Omit or use included for included-first activation; rent always preserves - package capacity and starts paid checkout. + billing_preference: Annotated[Literal["included", "included_only", "rent"], PropertyInfo(alias="billingPreference")] + """ + included uses package capacity when available and otherwise starts paid + checkout; included_only fails without creating a paid reservation when no + included slot remains; rent always starts paid checkout. """ diff --git a/src/mobilerun_sdk/types/mailbox_restart_response.py b/src/mobilerun_sdk/types/mailbox_restart_response.py index 4bef7939..ab9e1d79 100644 --- a/src/mobilerun_sdk/types/mailbox_restart_response.py +++ b/src/mobilerun_sdk/types/mailbox_restart_response.py @@ -26,7 +26,7 @@ class Data(BaseModel): address: Optional[str] = None - billing_mode: Literal["rent", "included"] = FieldInfo(alias="billingMode") + billing_mode: Literal["rent", "included", "domain"] = FieldInfo(alias="billingMode") cancel_at_period_end: bool = FieldInfo(alias="cancelAtPeriodEnd") @@ -38,6 +38,8 @@ class Data(BaseModel): current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) + domain_id: Optional[str] = FieldInfo(alias="domainId", default=None) + inbound_messages: DataInboundMessages = FieldInfo(alias="inboundMessages") label: Optional[str] = None diff --git a/src/mobilerun_sdk/types/mailbox_retrieve_response.py b/src/mobilerun_sdk/types/mailbox_retrieve_response.py index efb60e24..ed490495 100644 --- a/src/mobilerun_sdk/types/mailbox_retrieve_response.py +++ b/src/mobilerun_sdk/types/mailbox_retrieve_response.py @@ -26,7 +26,7 @@ class Data(BaseModel): address: Optional[str] = None - billing_mode: Literal["rent", "included"] = FieldInfo(alias="billingMode") + billing_mode: Literal["rent", "included", "domain"] = FieldInfo(alias="billingMode") cancel_at_period_end: bool = FieldInfo(alias="cancelAtPeriodEnd") @@ -38,6 +38,8 @@ class Data(BaseModel): current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) + domain_id: Optional[str] = FieldInfo(alias="domainId", default=None) + inbound_messages: DataInboundMessages = FieldInfo(alias="inboundMessages") label: Optional[str] = None diff --git a/src/mobilerun_sdk/types/mailbox_uncancel_response.py b/src/mobilerun_sdk/types/mailbox_uncancel_response.py index 04688b3b..fc6b588e 100644 --- a/src/mobilerun_sdk/types/mailbox_uncancel_response.py +++ b/src/mobilerun_sdk/types/mailbox_uncancel_response.py @@ -26,7 +26,7 @@ class Data(BaseModel): address: Optional[str] = None - billing_mode: Literal["rent", "included"] = FieldInfo(alias="billingMode") + billing_mode: Literal["rent", "included", "domain"] = FieldInfo(alias="billingMode") cancel_at_period_end: bool = FieldInfo(alias="cancelAtPeriodEnd") @@ -38,6 +38,8 @@ class Data(BaseModel): current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) + domain_id: Optional[str] = FieldInfo(alias="domainId", default=None) + inbound_messages: DataInboundMessages = FieldInfo(alias="inboundMessages") label: Optional[str] = None diff --git a/src/mobilerun_sdk/types/mailbox_update_response.py b/src/mobilerun_sdk/types/mailbox_update_response.py index 893d9928..99de186b 100644 --- a/src/mobilerun_sdk/types/mailbox_update_response.py +++ b/src/mobilerun_sdk/types/mailbox_update_response.py @@ -26,7 +26,7 @@ class Data(BaseModel): address: Optional[str] = None - billing_mode: Literal["rent", "included"] = FieldInfo(alias="billingMode") + billing_mode: Literal["rent", "included", "domain"] = FieldInfo(alias="billingMode") cancel_at_period_end: bool = FieldInfo(alias="cancelAtPeriodEnd") @@ -38,6 +38,8 @@ class Data(BaseModel): current_period_end: Optional[datetime] = FieldInfo(alias="currentPeriodEnd", default=None) + domain_id: Optional[str] = FieldInfo(alias="domainId", default=None) + inbound_messages: DataInboundMessages = FieldInfo(alias="inboundMessages") label: Optional[str] = None diff --git a/src/mobilerun_sdk/types/number_capacity_params.py b/src/mobilerun_sdk/types/number_capacity_params.py new file mode 100644 index 00000000..a574c248 --- /dev/null +++ b/src/mobilerun_sdk/types/number_capacity_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["NumberCapacityParams"] + + +class NumberCapacityParams(TypedDict, total=False): + country: Required[str] + """ISO 3166-1 alpha-2 country code from GET /numbers/phones/countries.""" diff --git a/src/mobilerun_sdk/types/number_capacity_response.py b/src/mobilerun_sdk/types/number_capacity_response.py new file mode 100644 index 00000000..49d9e6ba --- /dev/null +++ b/src/mobilerun_sdk/types/number_capacity_response.py @@ -0,0 +1,27 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["NumberCapacityResponse", "Data"] + + +class Data(BaseModel): + included: int + + included_remaining: int = FieldInfo(alias="includedRemaining") + """Deprecated — always equal to `remaining`. + + Migrate to `remaining`; this field will be removed in a future revision. + """ + + remaining: int + + status: Literal["available", "exhausted", "not_included"] + + +class NumberCapacityResponse(BaseModel): + data: Data diff --git a/src/mobilerun_sdk/types/number_create_params.py b/src/mobilerun_sdk/types/number_create_params.py index 6098fc62..353cd5fb 100644 --- a/src/mobilerun_sdk/types/number_create_params.py +++ b/src/mobilerun_sdk/types/number_create_params.py @@ -11,14 +11,14 @@ class NumberCreateParams(TypedDict, total=False): - billing_preference: Annotated[Literal["included", "rent"], PropertyInfo(alias="billingPreference")] + billing_preference: Annotated[Literal["included", "included_only", "rent"], PropertyInfo(alias="billingPreference")] """ - Prefer a free package seat ('included', default) or force the paid checkout - ('rent') + Use included capacity when available, require included capacity without paid + fallback (included_only), or start a paid checkout (rent). """ country: str - """Optional ISO 3166-1 alpha-2 country code from GET /numbers/countries. + """Optional ISO 3166-1 alpha-2 country code from GET /numbers/phones/countries. Cannot be combined with `purpose`. """ @@ -31,7 +31,7 @@ class NumberCreateParams(TypedDict, total=False): """ purpose: str - """Optional Mobilerun Phone purpose slug from GET /numbers/purposes.""" + """Optional purpose from GET /numbers/phones/purposes.""" idempotency_key: Annotated[str, PropertyInfo(alias="Idempotency-Key")] """Optional request idempotency key.""" diff --git a/src/mobilerun_sdk/types/task_get_status_response.py b/src/mobilerun_sdk/types/task_get_status_response.py index 4446b3bb..0e0f823c 100644 --- a/src/mobilerun_sdk/types/task_get_status_response.py +++ b/src/mobilerun_sdk/types/task_get_status_response.py @@ -33,7 +33,7 @@ class Execution(BaseModel): class TaskGetStatusResponse(BaseModel): - status: Literal["queued", "created", "running", "cancelling", "completed", "failed", "cancelled"] + status: Literal["prepared", "queued", "created", "running", "cancelling", "completed", "failed", "cancelled"] """The status of the task""" execution: Optional[Execution] = None @@ -48,6 +48,12 @@ class TaskGetStatusResponse(BaseModel): output: Optional[Dict[str, object]] = None """Structured output if outputSchema was set""" + recording_device_id: Optional[str] = FieldInfo(alias="recordingDeviceId", default=None) + """Device ID associated with recordingId""" + + recording_id: Optional[str] = FieldInfo(alias="recordingId", default=None) + """ID of the task's whole-task video recording, if recordingEnabled was set""" + steps: Optional[int] = None """Number of steps taken""" diff --git a/src/mobilerun_sdk/types/task_list_params.py b/src/mobilerun_sdk/types/task_list_params.py index 044f84ad..1b08553e 100644 --- a/src/mobilerun_sdk/types/task_list_params.py +++ b/src/mobilerun_sdk/types/task_list_params.py @@ -28,4 +28,9 @@ class TaskListParams(TypedDict, total=False): query: Optional[str] """Search in task description.""" - status: Optional[Literal["queued", "created", "running", "cancelling", "completed", "failed", "cancelled"]] + source: Optional[Literal["api", "agent"]] + """Only tasks created via the API ('api') or spawned by an agent step ('agent').""" + + status: Optional[ + Literal["prepared", "queued", "created", "running", "cancelling", "completed", "failed", "cancelled"] + ] diff --git a/src/mobilerun_sdk/types/task_list_response.py b/src/mobilerun_sdk/types/task_list_response.py index 20a9744c..06fa4a46 100644 --- a/src/mobilerun_sdk/types/task_list_response.py +++ b/src/mobilerun_sdk/types/task_list_response.py @@ -32,7 +32,7 @@ class Item(BaseModel): owner_id: str = FieldInfo(alias="ownerId") - status: Literal["queued", "created", "running", "cancelling", "completed", "failed", "cancelled"] + status: Literal["prepared", "queued", "created", "running", "cancelling", "completed", "failed", "cancelled"] task: str @@ -43,8 +43,6 @@ class Item(BaseModel): accessibility: Optional[bool] = None - agent_id: Optional[int] = FieldInfo(alias="agentId", default=None) - apps: Optional[List[str]] = None cancel_requested_at: Optional[datetime] = FieldInfo(alias="cancelRequestedAt", default=None) @@ -82,6 +80,20 @@ class Item(BaseModel): reasoning: Optional[bool] = None + recording_device_id: Optional[str] = FieldInfo(alias="recordingDeviceId", default=None) + + recording_enabled: Optional[bool] = FieldInfo(alias="recordingEnabled", default=None) + """Record device video for the whole task and persist a retrievable reference""" + + recording_id: Optional[str] = FieldInfo(alias="recordingId", default=None) + + source: Optional[Literal["api", "agent"]] = None + """ + Where the task came from: 'api' for tasks created via POST /tasks, 'agent' for + tasks spawned by an agent step. Agent tasks are readable (status, trajectory, + media) but not controllable via this API. + """ + stealth: Optional[bool] = None steps: Optional[int] = None @@ -94,6 +106,7 @@ class Item(BaseModel): succeeded: Optional[bool] = None temperature: Optional[float] = None + """Deprecated and ignored. Sampling behavior is controlled by the model provider.""" updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) diff --git a/src/mobilerun_sdk/types/task_retrieve_response.py b/src/mobilerun_sdk/types/task_retrieve_response.py index 85887f56..95306e62 100644 --- a/src/mobilerun_sdk/types/task_retrieve_response.py +++ b/src/mobilerun_sdk/types/task_retrieve_response.py @@ -31,7 +31,7 @@ class Task(BaseModel): owner_id: str = FieldInfo(alias="ownerId") - status: Literal["queued", "created", "running", "cancelling", "completed", "failed", "cancelled"] + status: Literal["prepared", "queued", "created", "running", "cancelling", "completed", "failed", "cancelled"] task: str @@ -42,8 +42,6 @@ class Task(BaseModel): accessibility: Optional[bool] = None - agent_id: Optional[int] = FieldInfo(alias="agentId", default=None) - apps: Optional[List[str]] = None cancel_requested_at: Optional[datetime] = FieldInfo(alias="cancelRequestedAt", default=None) @@ -81,6 +79,20 @@ class Task(BaseModel): reasoning: Optional[bool] = None + recording_device_id: Optional[str] = FieldInfo(alias="recordingDeviceId", default=None) + + recording_enabled: Optional[bool] = FieldInfo(alias="recordingEnabled", default=None) + """Record device video for the whole task and persist a retrievable reference""" + + recording_id: Optional[str] = FieldInfo(alias="recordingId", default=None) + + source: Optional[Literal["api", "agent"]] = None + """ + Where the task came from: 'api' for tasks created via POST /tasks, 'agent' for + tasks spawned by an agent step. Agent tasks are readable (status, trajectory, + media) but not controllable via this API. + """ + stealth: Optional[bool] = None steps: Optional[int] = None @@ -93,6 +105,7 @@ class Task(BaseModel): succeeded: Optional[bool] = None temperature: Optional[float] = None + """Deprecated and ignored. Sampling behavior is controlled by the model provider.""" updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None) diff --git a/src/mobilerun_sdk/types/task_run_params.py b/src/mobilerun_sdk/types/task_run_params.py index b66cf98f..ab090746 100644 --- a/src/mobilerun_sdk/types/task_run_params.py +++ b/src/mobilerun_sdk/types/task_run_params.py @@ -19,8 +19,6 @@ class TaskRunParams(TypedDict, total=False): accessibility: bool - agent_id: Annotated[int, PropertyInfo(alias="agentId")] - apps: SequenceNotStr[str] continue_on_failure: Annotated[bool, PropertyInfo(alias="continueOnFailure")] @@ -35,7 +33,7 @@ class TaskRunParams(TypedDict, total=False): files: SequenceNotStr[str] llm_model: Annotated[str, PropertyInfo(alias="llmModel")] - """The LLM model identifier to use for the task (e.g. 'google/gemini-3.5-flash')""" + """The LLM model identifier to use for the task (e.g. 'openai/gpt-5.6-luna')""" max_steps: Annotated[int, PropertyInfo(alias="maxSteps")] @@ -46,12 +44,22 @@ class TaskRunParams(TypedDict, total=False): reasoning: bool + recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")] + """Record device video for the whole task and persist a retrievable reference""" + stealth: bool subagent_model: Annotated[str, PropertyInfo(alias="subagentModel")] """LLM model used by sub-agent roles: executor, app_opener, structured_output""" + system_prompt: Annotated[Optional[str], PropertyInfo(alias="systemPrompt")] + """ + Optional custom behavioral overlay applied on top of the agent's default system + prompts. Never echoed back in responses or errors. + """ + temperature: float + """Deprecated and ignored. Sampling behavior is controlled by the model provider.""" vision: bool diff --git a/src/mobilerun_sdk/types/task_run_response.py b/src/mobilerun_sdk/types/task_run_response.py index 5987ba3d..6b402a65 100644 --- a/src/mobilerun_sdk/types/task_run_response.py +++ b/src/mobilerun_sdk/types/task_run_response.py @@ -14,7 +14,7 @@ class TaskRunResponse(BaseModel): id: str """The ID of the task""" - status: Literal["queued", "created", "running", "cancelling", "completed", "failed", "cancelled"] + status: Literal["prepared", "queued", "created", "running", "cancelling", "completed", "failed", "cancelled"] """The status of the task (queued or created)""" stream_url: Optional[str] = FieldInfo(alias="streamUrl", default=None) diff --git a/src/mobilerun_sdk/types/task_run_streamed_params.py b/src/mobilerun_sdk/types/task_run_streamed_params.py index 2522d16b..a25065bc 100644 --- a/src/mobilerun_sdk/types/task_run_streamed_params.py +++ b/src/mobilerun_sdk/types/task_run_streamed_params.py @@ -19,8 +19,6 @@ class TaskRunStreamedParams(TypedDict, total=False): accessibility: bool - agent_id: Annotated[int, PropertyInfo(alias="agentId")] - apps: SequenceNotStr[str] continue_on_failure: Annotated[bool, PropertyInfo(alias="continueOnFailure")] @@ -35,7 +33,7 @@ class TaskRunStreamedParams(TypedDict, total=False): files: SequenceNotStr[str] llm_model: Annotated[str, PropertyInfo(alias="llmModel")] - """The LLM model identifier to use for the task (e.g. 'google/gemini-3.5-flash')""" + """The LLM model identifier to use for the task (e.g. 'openai/gpt-5.6-luna')""" max_steps: Annotated[int, PropertyInfo(alias="maxSteps")] @@ -46,12 +44,22 @@ class TaskRunStreamedParams(TypedDict, total=False): reasoning: bool + recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")] + """Record device video for the whole task and persist a retrievable reference""" + stealth: bool subagent_model: Annotated[str, PropertyInfo(alias="subagentModel")] """LLM model used by sub-agent roles: executor, app_opener, structured_output""" + system_prompt: Annotated[Optional[str], PropertyInfo(alias="systemPrompt")] + """ + Optional custom behavioral overlay applied on top of the agent's default system + prompts. Never echoed back in responses or errors. + """ + temperature: float + """Deprecated and ignored. Sampling behavior is controlled by the model provider.""" vision: bool diff --git a/src/mobilerun_sdk/types/webhook_event_types_response.py b/src/mobilerun_sdk/types/webhook_event_types_response.py index 2d1d9e2f..9c7439d7 100644 --- a/src/mobilerun_sdk/types/webhook_event_types_response.py +++ b/src/mobilerun_sdk/types/webhook_event_types_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List +from typing import List, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -17,6 +17,8 @@ class DataSourceEventSurfaces(BaseModel): webhook: bool + agent: Optional[bool] = None + class DataSourceEvent(BaseModel): description: str diff --git a/src/mobilerun_sdk/types/workflows/__init__.py b/src/mobilerun_sdk/types/workflows/__init__.py index d9ae0f73..1de48081 100644 --- a/src/mobilerun_sdk/types/workflows/__init__.py +++ b/src/mobilerun_sdk/types/workflows/__init__.py @@ -32,6 +32,7 @@ from .action_delete_response import ActionDeleteResponse as ActionDeleteResponse from .action_update_response import ActionUpdateResponse as ActionUpdateResponse from .event_dry_run_response import EventDryRunResponse as EventDryRunResponse +from .flow_capacity_response import FlowCapacityResponse as FlowCapacityResponse from .flow_retrieve_response import FlowRetrieveResponse as FlowRetrieveResponse from .timezone_list_response import TimezoneListResponse as TimezoneListResponse from .execution_list_response import ExecutionListResponse as ExecutionListResponse diff --git a/src/mobilerun_sdk/types/workflows/event_dry_run_response.py b/src/mobilerun_sdk/types/workflows/event_dry_run_response.py index b04779e3..e7bb6eee 100644 --- a/src/mobilerun_sdk/types/workflows/event_dry_run_response.py +++ b/src/mobilerun_sdk/types/workflows/event_dry_run_response.py @@ -13,6 +13,7 @@ "DataMatchedFlow", "DataMatchedFlowAction", "DataMatchedFlowFlow", + "DataMatchedFlowFlowRecordingPolicy", "DataMatchedFlowGates", "DataMatchedFlowTrigger", "DataValidation", @@ -23,10 +24,14 @@ class DataMatchedFlowAction(BaseModel): continue_on_error: bool = FieldInfo(alias="continueOnError") + flow_action_id: str = FieldInfo(alias="flowActionId") + method: str name: str + recording_enabled: bool = FieldInfo(alias="recordingEnabled") + service: Literal["tasks_api", "devices_api", "agents_api", "webhooks"] children: Optional[List[object]] = None @@ -38,9 +43,15 @@ class DataMatchedFlowAction(BaseModel): params: Optional[Dict[str, object]] = None +class DataMatchedFlowFlowRecordingPolicy(BaseModel): + mode: Literal["off", "flow", "selected_steps"] + + class DataMatchedFlowFlow(BaseModel): id: str + archived_at: Optional[str] = FieldInfo(alias="archivedAt", default=None) + blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None) consecutive_failures: int = FieldInfo(alias="consecutiveFailures") @@ -58,6 +69,10 @@ class DataMatchedFlowFlow(BaseModel): device_ids: List[str] = FieldInfo(alias="deviceIds") enabled: bool + """ + Compatibility projection of lifecycleStatus; true only when lifecycleStatus is + enabled. + """ health_monitoring_enabled: bool = FieldInfo(alias="healthMonitoringEnabled") @@ -69,6 +84,8 @@ class DataMatchedFlowFlow(BaseModel): last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None) + lifecycle_status: Literal["enabled", "disabled", "archived"] = FieldInfo(alias="lifecycleStatus") + name: str notify_on_failure: bool = FieldInfo(alias="notifyOnFailure") @@ -80,6 +97,12 @@ class DataMatchedFlowFlow(BaseModel): owner_id: str = FieldInfo(alias="ownerId") recording_enabled: bool = FieldInfo(alias="recordingEnabled") + """ + Deprecated: use recordingPolicy.mode ("flow" = recordingEnabled=true, "off" = + recordingEnabled=false). + """ + + recording_policy: DataMatchedFlowFlowRecordingPolicy = FieldInfo(alias="recordingPolicy") self_healing_enabled: bool = FieldInfo(alias="selfHealingEnabled") diff --git a/src/mobilerun_sdk/types/workflows/execution_list_response.py b/src/mobilerun_sdk/types/workflows/execution_list_response.py index b7c4993f..2a01709f 100644 --- a/src/mobilerun_sdk/types/workflows/execution_list_response.py +++ b/src/mobilerun_sdk/types/workflows/execution_list_response.py @@ -8,7 +8,37 @@ from ..._models import BaseModel from ..shared.pagination import Pagination -__all__ = ["ExecutionListResponse", "Item"] +__all__ = ["ExecutionListResponse", "Item", "ItemRecording"] + + +class ItemRecording(BaseModel): + id: str + + attempt: int + + child_index: int = FieldInfo(alias="childIndex") + + flow_action_id: Optional[str] = FieldInfo(alias="flowActionId", default=None) + + iteration_index: int = FieldInfo(alias="iterationIndex") + + last_error: Optional[str] = FieldInfo(alias="lastError", default=None) + + parent_index: int = FieldInfo(alias="parentIndex") + + recording_device_id: Optional[str] = FieldInfo(alias="recordingDeviceId", default=None) + + recording_id: Optional[str] = FieldInfo(alias="recordingId", default=None) + + scope: Literal["flow", "step"] + + started_at: Optional[str] = FieldInfo(alias="startedAt", default=None) + + status: Literal["starting", "recording", "stopping", "stopped", "failed"] + + step_index: int = FieldInfo(alias="stepIndex") + + stopped_at: Optional[str] = FieldInfo(alias="stoppedAt", default=None) class Item(BaseModel): @@ -37,6 +67,12 @@ class Item(BaseModel): the recording failed to start. """ + recordings: List[ItemRecording] + """Durable recording segments ordered by step/loop coordinate and retry attempt. + + Whole-flow recordings use -1 for every coordinate. + """ + started_at: Optional[str] = FieldInfo(alias="startedAt", default=None) status: Optional[Literal["pending", "running", "success", "failed", "cancelled", "skipped", "invalid"]] = None diff --git a/src/mobilerun_sdk/types/workflows/execution_retrieve_response.py b/src/mobilerun_sdk/types/workflows/execution_retrieve_response.py index de6c2d19..cda1e5ff 100644 --- a/src/mobilerun_sdk/types/workflows/execution_retrieve_response.py +++ b/src/mobilerun_sdk/types/workflows/execution_retrieve_response.py @@ -7,7 +7,7 @@ from ..._models import BaseModel -__all__ = ["ExecutionRetrieveResponse", "Data", "DataFile"] +__all__ = ["ExecutionRetrieveResponse", "Data", "DataFile", "DataRecording"] class DataFile(BaseModel): @@ -20,6 +20,36 @@ class DataFile(BaseModel): size_bytes: int = FieldInfo(alias="sizeBytes") +class DataRecording(BaseModel): + id: str + + attempt: int + + child_index: int = FieldInfo(alias="childIndex") + + flow_action_id: Optional[str] = FieldInfo(alias="flowActionId", default=None) + + iteration_index: int = FieldInfo(alias="iterationIndex") + + last_error: Optional[str] = FieldInfo(alias="lastError", default=None) + + parent_index: int = FieldInfo(alias="parentIndex") + + recording_device_id: Optional[str] = FieldInfo(alias="recordingDeviceId", default=None) + + recording_id: Optional[str] = FieldInfo(alias="recordingId", default=None) + + scope: Literal["flow", "step"] + + started_at: Optional[str] = FieldInfo(alias="startedAt", default=None) + + status: Literal["starting", "recording", "stopping", "stopped", "failed"] + + step_index: int = FieldInfo(alias="stepIndex") + + stopped_at: Optional[str] = FieldInfo(alias="stoppedAt", default=None) + + class Data(BaseModel): id: str @@ -53,6 +83,12 @@ class Data(BaseModel): the recording failed to start. """ + recordings: List[DataRecording] + """Durable recording segments ordered by step/loop coordinate and retry attempt. + + Whole-flow recordings use -1 for every coordinate. + """ + started_at: Optional[str] = FieldInfo(alias="startedAt", default=None) status: Optional[Literal["pending", "running", "success", "failed", "cancelled", "skipped", "invalid"]] = None diff --git a/src/mobilerun_sdk/types/workflows/flow_capacity_response.py b/src/mobilerun_sdk/types/workflows/flow_capacity_response.py new file mode 100644 index 00000000..c101de72 --- /dev/null +++ b/src/mobilerun_sdk/types/workflows/flow_capacity_response.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["FlowCapacityResponse", "Data"] + + +class Data(BaseModel): + included: int + + remaining: int + + status: Literal["available", "exhausted", "not_included"] + + +class FlowCapacityResponse(BaseModel): + data: Data diff --git a/src/mobilerun_sdk/types/workflows/flow_clone_response.py b/src/mobilerun_sdk/types/workflows/flow_clone_response.py index 14ed8d1f..e08b73dd 100644 --- a/src/mobilerun_sdk/types/workflows/flow_clone_response.py +++ b/src/mobilerun_sdk/types/workflows/flow_clone_response.py @@ -7,12 +7,18 @@ from ..._models import BaseModel -__all__ = ["FlowCloneResponse", "Data"] +__all__ = ["FlowCloneResponse", "Data", "DataRecordingPolicy"] + + +class DataRecordingPolicy(BaseModel): + mode: Literal["off", "flow", "selected_steps"] class Data(BaseModel): id: str + archived_at: Optional[str] = FieldInfo(alias="archivedAt", default=None) + blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None) consecutive_failures: int = FieldInfo(alias="consecutiveFailures") @@ -30,6 +36,10 @@ class Data(BaseModel): device_ids: List[str] = FieldInfo(alias="deviceIds") enabled: bool + """ + Compatibility projection of lifecycleStatus; true only when lifecycleStatus is + enabled. + """ health_monitoring_enabled: bool = FieldInfo(alias="healthMonitoringEnabled") @@ -41,6 +51,8 @@ class Data(BaseModel): last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None) + lifecycle_status: Literal["enabled", "disabled", "archived"] = FieldInfo(alias="lifecycleStatus") + name: str notify_on_failure: bool = FieldInfo(alias="notifyOnFailure") @@ -52,6 +64,12 @@ class Data(BaseModel): owner_id: str = FieldInfo(alias="ownerId") recording_enabled: bool = FieldInfo(alias="recordingEnabled") + """ + Deprecated: use recordingPolicy.mode ("flow" = recordingEnabled=true, "off" = + recordingEnabled=false). + """ + + recording_policy: DataRecordingPolicy = FieldInfo(alias="recordingPolicy") self_healing_enabled: bool = FieldInfo(alias="selfHealingEnabled") diff --git a/src/mobilerun_sdk/types/workflows/flow_create_params.py b/src/mobilerun_sdk/types/workflows/flow_create_params.py index cde7b202..1a292cf5 100644 --- a/src/mobilerun_sdk/types/workflows/flow_create_params.py +++ b/src/mobilerun_sdk/types/workflows/flow_create_params.py @@ -8,7 +8,7 @@ from ..._types import SequenceNotStr from ..._utils import PropertyInfo -__all__ = ["FlowCreateParams", "Action", "ActionChild", "ActionChildOverrides", "ActionOverrides"] +__all__ = ["FlowCreateParams", "Action", "ActionChild", "ActionChildOverrides", "ActionOverrides", "RecordingPolicy"] class FlowCreateParams(TypedDict, total=False): @@ -37,6 +37,12 @@ class FlowCreateParams(TypedDict, total=False): notify_webhook_id: Annotated[Optional[str], PropertyInfo(alias="notifyWebhookId")] recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")] + """Deprecated compatibility field. + + true maps to recordingPolicy.mode="flow"; false maps to "off". + """ + + recording_policy: Annotated[RecordingPolicy, PropertyInfo(alias="recordingPolicy")] self_healing_enabled: Annotated[bool, PropertyInfo(alias="selfHealingEnabled")] @@ -58,6 +64,8 @@ class ActionChild(TypedDict, total=False): overrides: Optional[ActionChildOverrides] + recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")] + class ActionOverrides(TypedDict, total=False): params: Dict[str, object] @@ -75,3 +83,9 @@ class Action(TypedDict, total=False): name_override: Annotated[str, PropertyInfo(alias="nameOverride")] overrides: Optional[ActionOverrides] + + recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")] + + +class RecordingPolicy(TypedDict, total=False): + mode: Required[Literal["off", "flow", "selected_steps"]] diff --git a/src/mobilerun_sdk/types/workflows/flow_create_response.py b/src/mobilerun_sdk/types/workflows/flow_create_response.py index a840cf45..d4129117 100644 --- a/src/mobilerun_sdk/types/workflows/flow_create_response.py +++ b/src/mobilerun_sdk/types/workflows/flow_create_response.py @@ -7,12 +7,18 @@ from ..._models import BaseModel -__all__ = ["FlowCreateResponse", "Data"] +__all__ = ["FlowCreateResponse", "Data", "DataRecordingPolicy"] + + +class DataRecordingPolicy(BaseModel): + mode: Literal["off", "flow", "selected_steps"] class Data(BaseModel): id: str + archived_at: Optional[str] = FieldInfo(alias="archivedAt", default=None) + blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None) consecutive_failures: int = FieldInfo(alias="consecutiveFailures") @@ -30,6 +36,10 @@ class Data(BaseModel): device_ids: List[str] = FieldInfo(alias="deviceIds") enabled: bool + """ + Compatibility projection of lifecycleStatus; true only when lifecycleStatus is + enabled. + """ health_monitoring_enabled: bool = FieldInfo(alias="healthMonitoringEnabled") @@ -41,6 +51,8 @@ class Data(BaseModel): last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None) + lifecycle_status: Literal["enabled", "disabled", "archived"] = FieldInfo(alias="lifecycleStatus") + name: str notify_on_failure: bool = FieldInfo(alias="notifyOnFailure") @@ -52,6 +64,12 @@ class Data(BaseModel): owner_id: str = FieldInfo(alias="ownerId") recording_enabled: bool = FieldInfo(alias="recordingEnabled") + """ + Deprecated: use recordingPolicy.mode ("flow" = recordingEnabled=true, "off" = + recordingEnabled=false). + """ + + recording_policy: DataRecordingPolicy = FieldInfo(alias="recordingPolicy") self_healing_enabled: bool = FieldInfo(alias="selfHealingEnabled") diff --git a/src/mobilerun_sdk/types/workflows/flow_dry_run_response.py b/src/mobilerun_sdk/types/workflows/flow_dry_run_response.py index d9a5bf30..5592add2 100644 --- a/src/mobilerun_sdk/types/workflows/flow_dry_run_response.py +++ b/src/mobilerun_sdk/types/workflows/flow_dry_run_response.py @@ -13,10 +13,14 @@ class DataAction(BaseModel): continue_on_error: bool = FieldInfo(alias="continueOnError") + flow_action_id: str = FieldInfo(alias="flowActionId") + method: str name: str + recording_enabled: bool = FieldInfo(alias="recordingEnabled") + service: Literal["tasks_api", "devices_api", "agents_api", "webhooks"] children: Optional[List[object]] = None diff --git a/src/mobilerun_sdk/types/workflows/flow_list_response.py b/src/mobilerun_sdk/types/workflows/flow_list_response.py index 5cd546ab..01705f9f 100644 --- a/src/mobilerun_sdk/types/workflows/flow_list_response.py +++ b/src/mobilerun_sdk/types/workflows/flow_list_response.py @@ -8,12 +8,18 @@ from ..._models import BaseModel from ..shared.pagination import Pagination -__all__ = ["FlowListResponse", "Item"] +__all__ = ["FlowListResponse", "Item", "ItemRecordingPolicy"] + + +class ItemRecordingPolicy(BaseModel): + mode: Literal["off", "flow", "selected_steps"] class Item(BaseModel): id: str + archived_at: Optional[str] = FieldInfo(alias="archivedAt", default=None) + blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None) consecutive_failures: int = FieldInfo(alias="consecutiveFailures") @@ -31,6 +37,10 @@ class Item(BaseModel): device_ids: List[str] = FieldInfo(alias="deviceIds") enabled: bool + """ + Compatibility projection of lifecycleStatus; true only when lifecycleStatus is + enabled. + """ health_monitoring_enabled: bool = FieldInfo(alias="healthMonitoringEnabled") @@ -42,6 +52,8 @@ class Item(BaseModel): last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None) + lifecycle_status: Literal["enabled", "disabled", "archived"] = FieldInfo(alias="lifecycleStatus") + name: str notify_on_failure: bool = FieldInfo(alias="notifyOnFailure") @@ -53,6 +65,12 @@ class Item(BaseModel): owner_id: str = FieldInfo(alias="ownerId") recording_enabled: bool = FieldInfo(alias="recordingEnabled") + """ + Deprecated: use recordingPolicy.mode ("flow" = recordingEnabled=true, "off" = + recordingEnabled=false). + """ + + recording_policy: ItemRecordingPolicy = FieldInfo(alias="recordingPolicy") self_healing_enabled: bool = FieldInfo(alias="selfHealingEnabled") diff --git a/src/mobilerun_sdk/types/workflows/flow_retrieve_response.py b/src/mobilerun_sdk/types/workflows/flow_retrieve_response.py index dab4caa9..b4cd5806 100644 --- a/src/mobilerun_sdk/types/workflows/flow_retrieve_response.py +++ b/src/mobilerun_sdk/types/workflows/flow_retrieve_response.py @@ -7,12 +7,18 @@ from ..._models import BaseModel -__all__ = ["FlowRetrieveResponse", "Data"] +__all__ = ["FlowRetrieveResponse", "Data", "DataRecordingPolicy"] + + +class DataRecordingPolicy(BaseModel): + mode: Literal["off", "flow", "selected_steps"] class Data(BaseModel): id: str + archived_at: Optional[str] = FieldInfo(alias="archivedAt", default=None) + blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None) consecutive_failures: int = FieldInfo(alias="consecutiveFailures") @@ -30,6 +36,10 @@ class Data(BaseModel): device_ids: List[str] = FieldInfo(alias="deviceIds") enabled: bool + """ + Compatibility projection of lifecycleStatus; true only when lifecycleStatus is + enabled. + """ health_monitoring_enabled: bool = FieldInfo(alias="healthMonitoringEnabled") @@ -41,6 +51,8 @@ class Data(BaseModel): last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None) + lifecycle_status: Literal["enabled", "disabled", "archived"] = FieldInfo(alias="lifecycleStatus") + name: str notify_on_failure: bool = FieldInfo(alias="notifyOnFailure") @@ -52,6 +64,12 @@ class Data(BaseModel): owner_id: str = FieldInfo(alias="ownerId") recording_enabled: bool = FieldInfo(alias="recordingEnabled") + """ + Deprecated: use recordingPolicy.mode ("flow" = recordingEnabled=true, "off" = + recordingEnabled=false). + """ + + recording_policy: DataRecordingPolicy = FieldInfo(alias="recordingPolicy") self_healing_enabled: bool = FieldInfo(alias="selfHealingEnabled") diff --git a/src/mobilerun_sdk/types/workflows/flow_unblock_response.py b/src/mobilerun_sdk/types/workflows/flow_unblock_response.py index 0429bba4..d71392de 100644 --- a/src/mobilerun_sdk/types/workflows/flow_unblock_response.py +++ b/src/mobilerun_sdk/types/workflows/flow_unblock_response.py @@ -7,12 +7,18 @@ from ..._models import BaseModel -__all__ = ["FlowUnblockResponse", "Data"] +__all__ = ["FlowUnblockResponse", "Data", "DataRecordingPolicy"] + + +class DataRecordingPolicy(BaseModel): + mode: Literal["off", "flow", "selected_steps"] class Data(BaseModel): id: str + archived_at: Optional[str] = FieldInfo(alias="archivedAt", default=None) + blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None) consecutive_failures: int = FieldInfo(alias="consecutiveFailures") @@ -30,6 +36,10 @@ class Data(BaseModel): device_ids: List[str] = FieldInfo(alias="deviceIds") enabled: bool + """ + Compatibility projection of lifecycleStatus; true only when lifecycleStatus is + enabled. + """ health_monitoring_enabled: bool = FieldInfo(alias="healthMonitoringEnabled") @@ -41,6 +51,8 @@ class Data(BaseModel): last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None) + lifecycle_status: Literal["enabled", "disabled", "archived"] = FieldInfo(alias="lifecycleStatus") + name: str notify_on_failure: bool = FieldInfo(alias="notifyOnFailure") @@ -52,6 +64,12 @@ class Data(BaseModel): owner_id: str = FieldInfo(alias="ownerId") recording_enabled: bool = FieldInfo(alias="recordingEnabled") + """ + Deprecated: use recordingPolicy.mode ("flow" = recordingEnabled=true, "off" = + recordingEnabled=false). + """ + + recording_policy: DataRecordingPolicy = FieldInfo(alias="recordingPolicy") self_healing_enabled: bool = FieldInfo(alias="selfHealingEnabled") diff --git a/src/mobilerun_sdk/types/workflows/flow_update_params.py b/src/mobilerun_sdk/types/workflows/flow_update_params.py index 8db31b2e..9f32e4bb 100644 --- a/src/mobilerun_sdk/types/workflows/flow_update_params.py +++ b/src/mobilerun_sdk/types/workflows/flow_update_params.py @@ -3,12 +3,12 @@ from __future__ import annotations from typing import Optional -from typing_extensions import Literal, Annotated, TypedDict +from typing_extensions import Literal, Required, Annotated, TypedDict from ..._types import SequenceNotStr from ..._utils import PropertyInfo -__all__ = ["FlowUpdateParams"] +__all__ = ["FlowUpdateParams", "RecordingPolicy"] class FlowUpdateParams(TypedDict, total=False): @@ -24,6 +24,9 @@ class FlowUpdateParams(TypedDict, total=False): health_monitoring_enabled: Annotated[bool, PropertyInfo(alias="healthMonitoringEnabled")] + lifecycle_status: Annotated[Literal["enabled", "disabled"], PropertyInfo(alias="lifecycleStatus")] + """Set the visible agent lifecycle. Archive remains available only through DELETE.""" + name: str notify_on_failure: Annotated[bool, PropertyInfo(alias="notifyOnFailure")] @@ -33,9 +36,19 @@ class FlowUpdateParams(TypedDict, total=False): notify_webhook_id: Annotated[Optional[str], PropertyInfo(alias="notifyWebhookId")] recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")] + """Deprecated compatibility field. + + true maps to recordingPolicy.mode="flow"; false maps to "off". + """ + + recording_policy: Annotated[RecordingPolicy, PropertyInfo(alias="recordingPolicy")] self_healing_enabled: Annotated[bool, PropertyInfo(alias="selfHealingEnabled")] self_healing_max_attempts: Annotated[int, PropertyInfo(alias="selfHealingMaxAttempts")] trigger_id: Annotated[str, PropertyInfo(alias="triggerId")] + + +class RecordingPolicy(TypedDict, total=False): + mode: Required[Literal["off", "flow", "selected_steps"]] diff --git a/src/mobilerun_sdk/types/workflows/flow_update_response.py b/src/mobilerun_sdk/types/workflows/flow_update_response.py index ad10348f..511e934a 100644 --- a/src/mobilerun_sdk/types/workflows/flow_update_response.py +++ b/src/mobilerun_sdk/types/workflows/flow_update_response.py @@ -7,12 +7,18 @@ from ..._models import BaseModel -__all__ = ["FlowUpdateResponse", "Data"] +__all__ = ["FlowUpdateResponse", "Data", "DataRecordingPolicy"] + + +class DataRecordingPolicy(BaseModel): + mode: Literal["off", "flow", "selected_steps"] class Data(BaseModel): id: str + archived_at: Optional[str] = FieldInfo(alias="archivedAt", default=None) + blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None) consecutive_failures: int = FieldInfo(alias="consecutiveFailures") @@ -30,6 +36,10 @@ class Data(BaseModel): device_ids: List[str] = FieldInfo(alias="deviceIds") enabled: bool + """ + Compatibility projection of lifecycleStatus; true only when lifecycleStatus is + enabled. + """ health_monitoring_enabled: bool = FieldInfo(alias="healthMonitoringEnabled") @@ -41,6 +51,8 @@ class Data(BaseModel): last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None) + lifecycle_status: Literal["enabled", "disabled", "archived"] = FieldInfo(alias="lifecycleStatus") + name: str notify_on_failure: bool = FieldInfo(alias="notifyOnFailure") @@ -52,6 +64,12 @@ class Data(BaseModel): owner_id: str = FieldInfo(alias="ownerId") recording_enabled: bool = FieldInfo(alias="recordingEnabled") + """ + Deprecated: use recordingPolicy.mode ("flow" = recordingEnabled=true, "off" = + recordingEnabled=false). + """ + + recording_policy: DataRecordingPolicy = FieldInfo(alias="recordingPolicy") self_healing_enabled: bool = FieldInfo(alias="selfHealingEnabled") diff --git a/src/mobilerun_sdk/types/workflows/flows/action_add_params.py b/src/mobilerun_sdk/types/workflows/flows/action_add_params.py index 1275209c..88af2ccf 100644 --- a/src/mobilerun_sdk/types/workflows/flows/action_add_params.py +++ b/src/mobilerun_sdk/types/workflows/flows/action_add_params.py @@ -25,6 +25,8 @@ class ActionAddParams(TypedDict, total=False): parent_flow_action_id: Annotated[Optional[str], PropertyInfo(alias="parentFlowActionId")] + recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")] + class ChildOverrides(TypedDict, total=False): params: Dict[str, object] @@ -41,6 +43,8 @@ class Child(TypedDict, total=False): overrides: Optional[ChildOverrides] + recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")] + class Overrides(TypedDict, total=False): params: Dict[str, object] diff --git a/src/mobilerun_sdk/types/workflows/flows/action_add_response.py b/src/mobilerun_sdk/types/workflows/flows/action_add_response.py index 00d02c81..420a30e5 100644 --- a/src/mobilerun_sdk/types/workflows/flows/action_add_response.py +++ b/src/mobilerun_sdk/types/workflows/flows/action_add_response.py @@ -32,6 +32,12 @@ class Data(BaseModel): position: int + recording_enabled: bool = FieldInfo(alias="recordingEnabled") + """ + Selected for per-step recording under the flow's "selected_steps" recording + policy. + """ + class ActionAddResponse(BaseModel): data: Data diff --git a/src/mobilerun_sdk/types/workflows/flows/action_list_response.py b/src/mobilerun_sdk/types/workflows/flows/action_list_response.py index 88c4965b..1ff8dd43 100644 --- a/src/mobilerun_sdk/types/workflows/flows/action_list_response.py +++ b/src/mobilerun_sdk/types/workflows/flows/action_list_response.py @@ -32,6 +32,12 @@ class Data(BaseModel): position: int + recording_enabled: bool = FieldInfo(alias="recordingEnabled") + """ + Selected for per-step recording under the flow's "selected_steps" recording + policy. + """ + class ActionListResponse(BaseModel): data: List[Data] diff --git a/src/mobilerun_sdk/types/workflows/flows/action_replace_params.py b/src/mobilerun_sdk/types/workflows/flows/action_replace_params.py index ec5c42a1..fd89af25 100644 --- a/src/mobilerun_sdk/types/workflows/flows/action_replace_params.py +++ b/src/mobilerun_sdk/types/workflows/flows/action_replace_params.py @@ -29,6 +29,8 @@ class ActionChild(TypedDict, total=False): overrides: Optional[ActionChildOverrides] + recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")] + class ActionOverrides(TypedDict, total=False): params: Dict[str, object] @@ -46,3 +48,5 @@ class Action(TypedDict, total=False): name_override: Annotated[str, PropertyInfo(alias="nameOverride")] overrides: Optional[ActionOverrides] + + recording_enabled: Annotated[bool, PropertyInfo(alias="recordingEnabled")] diff --git a/src/mobilerun_sdk/types/workflows/flows/action_replace_response.py b/src/mobilerun_sdk/types/workflows/flows/action_replace_response.py index cf358f90..a9939a84 100644 --- a/src/mobilerun_sdk/types/workflows/flows/action_replace_response.py +++ b/src/mobilerun_sdk/types/workflows/flows/action_replace_response.py @@ -32,6 +32,12 @@ class Data(BaseModel): position: int + recording_enabled: bool = FieldInfo(alias="recordingEnabled") + """ + Selected for per-step recording under the flow's "selected_steps" recording + policy. + """ + class ActionReplaceResponse(BaseModel): data: List[Data] diff --git a/tests/api_resources/connect/test_proxies.py b/tests/api_resources/connect/test_proxies.py index acd84195..f2e62efb 100644 --- a/tests/api_resources/connect/test_proxies.py +++ b/tests/api_resources/connect/test_proxies.py @@ -113,6 +113,16 @@ def test_method_buy(self, client: Mobilerun) -> None: ) assert_matches_type(ProxyBuyResponse, proxy, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_buy_with_all_params(self, client: Mobilerun) -> None: + proxy = client.connect.proxies.buy( + country="country", + type="dedicated_residential", + idempotency_key="Idempotency-Key", + ) + assert_matches_type(ProxyBuyResponse, proxy, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_buy(self, client: Mobilerun) -> None: @@ -395,6 +405,16 @@ async def test_method_buy(self, async_client: AsyncMobilerun) -> None: ) assert_matches_type(ProxyBuyResponse, proxy, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_buy_with_all_params(self, async_client: AsyncMobilerun) -> None: + proxy = await async_client.connect.proxies.buy( + country="country", + type="dedicated_residential", + idempotency_key="Idempotency-Key", + ) + assert_matches_type(ProxyBuyResponse, proxy, path=["response"]) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_buy(self, async_client: AsyncMobilerun) -> None: diff --git a/tests/api_resources/devices/test_apps.py b/tests/api_resources/devices/test_apps.py index c1281d68..aa3726ed 100644 --- a/tests/api_resources/devices/test_apps.py +++ b/tests/api_resources/devices/test_apps.py @@ -219,7 +219,9 @@ def test_method_install_with_all_params_overload_1(self, client: Mobilerun) -> N device_id="deviceId", bundle_id="x", background=True, + country="se", package_name="x", + version_code=1, x_device_display_id=0, ) assert app is None @@ -278,6 +280,8 @@ def test_method_install_with_all_params_overload_2(self, client: Mobilerun) -> N package_name="x", background=True, bundle_id="x", + country="se", + version_code=1, x_device_display_id=0, ) assert app is None @@ -769,7 +773,9 @@ async def test_method_install_with_all_params_overload_1(self, async_client: Asy device_id="deviceId", bundle_id="x", background=True, + country="se", package_name="x", + version_code=1, x_device_display_id=0, ) assert app is None @@ -828,6 +834,8 @@ async def test_method_install_with_all_params_overload_2(self, async_client: Asy package_name="x", background=True, bundle_id="x", + country="se", + version_code=1, x_device_display_id=0, ) assert app is None diff --git a/tests/api_resources/devices/test_keyboard.py b/tests/api_resources/devices/test_keyboard.py index 766a63b8..29044ca3 100644 --- a/tests/api_resources/devices/test_keyboard.py +++ b/tests/api_resources/devices/test_keyboard.py @@ -138,6 +138,7 @@ def test_method_write_with_all_params(self, client: Mobilerun) -> None: device_id="deviceId", text="text", clear=True, + completion_mode="accepted", error_rate=0, stealth=True, wpm=0, @@ -311,6 +312,7 @@ async def test_method_write_with_all_params(self, async_client: AsyncMobilerun) device_id="deviceId", text="text", clear=True, + completion_mode="accepted", error_rate=0, stealth=True, wpm=0, diff --git a/tests/api_resources/devices/test_recordings.py b/tests/api_resources/devices/test_recordings.py index f3e134fb..4d72e541 100644 --- a/tests/api_resources/devices/test_recordings.py +++ b/tests/api_resources/devices/test_recordings.py @@ -140,6 +140,7 @@ def test_method_start_with_all_params(self, client: Mobilerun) -> None: recording = client.devices.recordings.start( device_id="deviceId", name="name", + quality=1, retention_days=1, types=["string"], ) @@ -511,6 +512,7 @@ async def test_method_start_with_all_params(self, async_client: AsyncMobilerun) recording = await async_client.devices.recordings.start( device_id="deviceId", name="name", + quality=1, retention_days=1, types=["string"], ) diff --git a/tests/api_resources/devices/test_traffic_sessions.py b/tests/api_resources/devices/test_traffic_sessions.py new file mode 100644 index 00000000..458eddf1 --- /dev/null +++ b/tests/api_resources/devices/test_traffic_sessions.py @@ -0,0 +1,455 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from tests.utils import assert_matches_type +from mobilerun_sdk import Mobilerun, AsyncMobilerun +from mobilerun_sdk.types.devices import ( + TrafficSessionListResponse, + TrafficSessionCreateResponse, + TrafficSessionDeleteResponse, + TrafficSessionRetrieveResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestTrafficSessions: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create(self, client: Mobilerun) -> None: + traffic_session = client.devices.traffic_sessions.create( + device_id="deviceId", + idempotency_key="x", + ) + assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: Mobilerun) -> None: + traffic_session = client.devices.traffic_sessions.create( + device_id="deviceId", + idempotency_key="x", + expires_in_seconds=60, + max_body_bytes=0, + ) + assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_create(self, client: Mobilerun) -> None: + response = client.devices.traffic_sessions.with_raw_response.create( + device_id="deviceId", + idempotency_key="x", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + traffic_session = response.parse() + assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_create(self, client: Mobilerun) -> None: + with client.devices.traffic_sessions.with_streaming_response.create( + device_id="deviceId", + idempotency_key="x", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + traffic_session = response.parse() + assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_create(self, client: Mobilerun) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): + client.devices.traffic_sessions.with_raw_response.create( + device_id="", + idempotency_key="x", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve(self, client: Mobilerun) -> None: + traffic_session = client.devices.traffic_sessions.retrieve( + session_id="sessionId", + device_id="deviceId", + ) + assert_matches_type(TrafficSessionRetrieveResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: Mobilerun) -> None: + response = client.devices.traffic_sessions.with_raw_response.retrieve( + session_id="sessionId", + device_id="deviceId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + traffic_session = response.parse() + assert_matches_type(TrafficSessionRetrieveResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: Mobilerun) -> None: + with client.devices.traffic_sessions.with_streaming_response.retrieve( + session_id="sessionId", + device_id="deviceId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + traffic_session = response.parse() + assert_matches_type(TrafficSessionRetrieveResponse, traffic_session, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: Mobilerun) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): + client.devices.traffic_sessions.with_raw_response.retrieve( + session_id="sessionId", + device_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): + client.devices.traffic_sessions.with_raw_response.retrieve( + session_id="", + device_id="deviceId", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: Mobilerun) -> None: + traffic_session = client.devices.traffic_sessions.list( + device_id="deviceId", + ) + assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Mobilerun) -> None: + traffic_session = client.devices.traffic_sessions.list( + device_id="deviceId", + page=1, + page_size=1, + ) + assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Mobilerun) -> None: + response = client.devices.traffic_sessions.with_raw_response.list( + device_id="deviceId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + traffic_session = response.parse() + assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Mobilerun) -> None: + with client.devices.traffic_sessions.with_streaming_response.list( + device_id="deviceId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + traffic_session = response.parse() + assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_list(self, client: Mobilerun) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): + client.devices.traffic_sessions.with_raw_response.list( + device_id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_delete(self, client: Mobilerun) -> None: + traffic_session = client.devices.traffic_sessions.delete( + session_id="sessionId", + device_id="deviceId", + ) + assert_matches_type(TrafficSessionDeleteResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_delete(self, client: Mobilerun) -> None: + response = client.devices.traffic_sessions.with_raw_response.delete( + session_id="sessionId", + device_id="deviceId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + traffic_session = response.parse() + assert_matches_type(TrafficSessionDeleteResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: Mobilerun) -> None: + with client.devices.traffic_sessions.with_streaming_response.delete( + session_id="sessionId", + device_id="deviceId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + traffic_session = response.parse() + assert_matches_type(TrafficSessionDeleteResponse, traffic_session, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_delete(self, client: Mobilerun) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): + client.devices.traffic_sessions.with_raw_response.delete( + session_id="sessionId", + device_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): + client.devices.traffic_sessions.with_raw_response.delete( + session_id="", + device_id="deviceId", + ) + + +class TestAsyncTrafficSessions: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncMobilerun) -> None: + traffic_session = await async_client.devices.traffic_sessions.create( + device_id="deviceId", + idempotency_key="x", + ) + assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncMobilerun) -> None: + traffic_session = await async_client.devices.traffic_sessions.create( + device_id="deviceId", + idempotency_key="x", + expires_in_seconds=60, + max_body_bytes=0, + ) + assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncMobilerun) -> None: + response = await async_client.devices.traffic_sessions.with_raw_response.create( + device_id="deviceId", + idempotency_key="x", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + traffic_session = await response.parse() + assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncMobilerun) -> None: + async with async_client.devices.traffic_sessions.with_streaming_response.create( + device_id="deviceId", + idempotency_key="x", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + traffic_session = await response.parse() + assert_matches_type(TrafficSessionCreateResponse, traffic_session, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_create(self, async_client: AsyncMobilerun) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): + await async_client.devices.traffic_sessions.with_raw_response.create( + device_id="", + idempotency_key="x", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncMobilerun) -> None: + traffic_session = await async_client.devices.traffic_sessions.retrieve( + session_id="sessionId", + device_id="deviceId", + ) + assert_matches_type(TrafficSessionRetrieveResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncMobilerun) -> None: + response = await async_client.devices.traffic_sessions.with_raw_response.retrieve( + session_id="sessionId", + device_id="deviceId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + traffic_session = await response.parse() + assert_matches_type(TrafficSessionRetrieveResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncMobilerun) -> None: + async with async_client.devices.traffic_sessions.with_streaming_response.retrieve( + session_id="sessionId", + device_id="deviceId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + traffic_session = await response.parse() + assert_matches_type(TrafficSessionRetrieveResponse, traffic_session, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncMobilerun) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): + await async_client.devices.traffic_sessions.with_raw_response.retrieve( + session_id="sessionId", + device_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): + await async_client.devices.traffic_sessions.with_raw_response.retrieve( + session_id="", + device_id="deviceId", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncMobilerun) -> None: + traffic_session = await async_client.devices.traffic_sessions.list( + device_id="deviceId", + ) + assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncMobilerun) -> None: + traffic_session = await async_client.devices.traffic_sessions.list( + device_id="deviceId", + page=1, + page_size=1, + ) + assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncMobilerun) -> None: + response = await async_client.devices.traffic_sessions.with_raw_response.list( + device_id="deviceId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + traffic_session = await response.parse() + assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncMobilerun) -> None: + async with async_client.devices.traffic_sessions.with_streaming_response.list( + device_id="deviceId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + traffic_session = await response.parse() + assert_matches_type(TrafficSessionListResponse, traffic_session, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_list(self, async_client: AsyncMobilerun) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): + await async_client.devices.traffic_sessions.with_raw_response.list( + device_id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncMobilerun) -> None: + traffic_session = await async_client.devices.traffic_sessions.delete( + session_id="sessionId", + device_id="deviceId", + ) + assert_matches_type(TrafficSessionDeleteResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncMobilerun) -> None: + response = await async_client.devices.traffic_sessions.with_raw_response.delete( + session_id="sessionId", + device_id="deviceId", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + traffic_session = await response.parse() + assert_matches_type(TrafficSessionDeleteResponse, traffic_session, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncMobilerun) -> None: + async with async_client.devices.traffic_sessions.with_streaming_response.delete( + session_id="sessionId", + device_id="deviceId", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + traffic_session = await response.parse() + assert_matches_type(TrafficSessionDeleteResponse, traffic_session, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncMobilerun) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"): + await async_client.devices.traffic_sessions.with_raw_response.delete( + session_id="sessionId", + device_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): + await async_client.devices.traffic_sessions.with_raw_response.delete( + session_id="", + device_id="deviceId", + ) diff --git a/tests/api_resources/esims/__init__.py b/tests/api_resources/esims/__init__.py deleted file mode 100644 index fd8019a9..00000000 --- a/tests/api_resources/esims/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/esims/test_messages.py b/tests/api_resources/esims/test_messages.py deleted file mode 100644 index aa71f91d..00000000 --- a/tests/api_resources/esims/test_messages.py +++ /dev/null @@ -1,262 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from tests.utils import assert_matches_type -from mobilerun_sdk import Mobilerun, AsyncMobilerun -from mobilerun_sdk.types.esims import MessageListResponse, MessageSendResponse - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestMessages: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_list(self, client: Mobilerun) -> None: - message = client.esims.messages.list( - id="550e8400-e29b-41d4-a716-446655440000", - ) - assert_matches_type(MessageListResponse, message, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_list_with_all_params(self, client: Mobilerun) -> None: - message = client.esims.messages.list( - id="550e8400-e29b-41d4-a716-446655440000", - direction="all", - number_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - page=1, - page_size=1, - peer_key="x", - peer_number="xxx", - status="all", - ) - assert_matches_type(MessageListResponse, message, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_list(self, client: Mobilerun) -> None: - response = client.esims.messages.with_raw_response.list( - id="550e8400-e29b-41d4-a716-446655440000", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - message = response.parse() - assert_matches_type(MessageListResponse, message, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_list(self, client: Mobilerun) -> None: - with client.esims.messages.with_streaming_response.list( - id="550e8400-e29b-41d4-a716-446655440000", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - message = response.parse() - assert_matches_type(MessageListResponse, message, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_list(self, client: Mobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.esims.messages.with_raw_response.list( - id="", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_send(self, client: Mobilerun) -> None: - message = client.esims.messages.send( - id="550e8400-e29b-41d4-a716-446655440000", - body="x", - to="+15551230001", - ) - assert_matches_type(MessageSendResponse, message, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_send_with_all_params(self, client: Mobilerun) -> None: - message = client.esims.messages.send( - id="550e8400-e29b-41d4-a716-446655440000", - body="x", - to="+15551230001", - client_request_id="x", - delivery_report=True, - ) - assert_matches_type(MessageSendResponse, message, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_send(self, client: Mobilerun) -> None: - response = client.esims.messages.with_raw_response.send( - id="550e8400-e29b-41d4-a716-446655440000", - body="x", - to="+15551230001", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - message = response.parse() - assert_matches_type(MessageSendResponse, message, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_send(self, client: Mobilerun) -> None: - with client.esims.messages.with_streaming_response.send( - id="550e8400-e29b-41d4-a716-446655440000", - body="x", - to="+15551230001", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - message = response.parse() - assert_matches_type(MessageSendResponse, message, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_send(self, client: Mobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.esims.messages.with_raw_response.send( - id="", - body="x", - to="+15551230001", - ) - - -class TestAsyncMessages: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list(self, async_client: AsyncMobilerun) -> None: - message = await async_client.esims.messages.list( - id="550e8400-e29b-41d4-a716-446655440000", - ) - assert_matches_type(MessageListResponse, message, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncMobilerun) -> None: - message = await async_client.esims.messages.list( - id="550e8400-e29b-41d4-a716-446655440000", - direction="all", - number_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - page=1, - page_size=1, - peer_key="x", - peer_number="xxx", - status="all", - ) - assert_matches_type(MessageListResponse, message, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_list(self, async_client: AsyncMobilerun) -> None: - response = await async_client.esims.messages.with_raw_response.list( - id="550e8400-e29b-41d4-a716-446655440000", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - message = await response.parse() - assert_matches_type(MessageListResponse, message, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_list(self, async_client: AsyncMobilerun) -> None: - async with async_client.esims.messages.with_streaming_response.list( - id="550e8400-e29b-41d4-a716-446655440000", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - message = await response.parse() - assert_matches_type(MessageListResponse, message, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_list(self, async_client: AsyncMobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.esims.messages.with_raw_response.list( - id="", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_send(self, async_client: AsyncMobilerun) -> None: - message = await async_client.esims.messages.send( - id="550e8400-e29b-41d4-a716-446655440000", - body="x", - to="+15551230001", - ) - assert_matches_type(MessageSendResponse, message, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_send_with_all_params(self, async_client: AsyncMobilerun) -> None: - message = await async_client.esims.messages.send( - id="550e8400-e29b-41d4-a716-446655440000", - body="x", - to="+15551230001", - client_request_id="x", - delivery_report=True, - ) - assert_matches_type(MessageSendResponse, message, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_send(self, async_client: AsyncMobilerun) -> None: - response = await async_client.esims.messages.with_raw_response.send( - id="550e8400-e29b-41d4-a716-446655440000", - body="x", - to="+15551230001", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - message = await response.parse() - assert_matches_type(MessageSendResponse, message, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_send(self, async_client: AsyncMobilerun) -> None: - async with async_client.esims.messages.with_streaming_response.send( - id="550e8400-e29b-41d4-a716-446655440000", - body="x", - to="+15551230001", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - message = await response.parse() - assert_matches_type(MessageSendResponse, message, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_send(self, async_client: AsyncMobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.esims.messages.with_raw_response.send( - id="", - body="x", - to="+15551230001", - ) diff --git a/tests/api_resources/test_esims.py b/tests/api_resources/test_esims.py deleted file mode 100644 index a47275d3..00000000 --- a/tests/api_resources/test_esims.py +++ /dev/null @@ -1,953 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from tests.utils import assert_matches_type -from mobilerun_sdk import Mobilerun, AsyncMobilerun -from mobilerun_sdk.types import ( - EsimListResponse, - EsimCreateResponse, - EsimImportResponse, - EsimUpdateResponse, - EsimInstallResponse, - EsimCapacityResponse, - EsimRetrieveResponse, - EsimSelectorResponse, - EsimInstallStatusResponse, - EsimConfirmPaymentResponse, -) - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestEsims: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_create(self, client: Mobilerun) -> None: - esim = client.esims.create() - assert_matches_type(EsimCreateResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_create_with_all_params(self, client: Mobilerun) -> None: - esim = client.esims.create( - idempotency_key="idempotencyKey", - name="Mom's phone", - ) - assert_matches_type(EsimCreateResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_create(self, client: Mobilerun) -> None: - response = client.esims.with_raw_response.create() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = response.parse() - assert_matches_type(EsimCreateResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_create(self, client: Mobilerun) -> None: - with client.esims.with_streaming_response.create() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = response.parse() - assert_matches_type(EsimCreateResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_retrieve(self, client: Mobilerun) -> None: - esim = client.esims.retrieve( - "550e8400-e29b-41d4-a716-446655440000", - ) - assert_matches_type(EsimRetrieveResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_retrieve(self, client: Mobilerun) -> None: - response = client.esims.with_raw_response.retrieve( - "550e8400-e29b-41d4-a716-446655440000", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = response.parse() - assert_matches_type(EsimRetrieveResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_retrieve(self, client: Mobilerun) -> None: - with client.esims.with_streaming_response.retrieve( - "550e8400-e29b-41d4-a716-446655440000", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = response.parse() - assert_matches_type(EsimRetrieveResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_retrieve(self, client: Mobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.esims.with_raw_response.retrieve( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_update(self, client: Mobilerun) -> None: - esim = client.esims.update( - id="550e8400-e29b-41d4-a716-446655440000", - ) - assert_matches_type(EsimUpdateResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_update_with_all_params(self, client: Mobilerun) -> None: - esim = client.esims.update( - id="550e8400-e29b-41d4-a716-446655440000", - msisdn="+33612345678", - name="Mom's phone", - ) - assert_matches_type(EsimUpdateResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_update(self, client: Mobilerun) -> None: - response = client.esims.with_raw_response.update( - id="550e8400-e29b-41d4-a716-446655440000", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = response.parse() - assert_matches_type(EsimUpdateResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_update(self, client: Mobilerun) -> None: - with client.esims.with_streaming_response.update( - id="550e8400-e29b-41d4-a716-446655440000", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = response.parse() - assert_matches_type(EsimUpdateResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_update(self, client: Mobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.esims.with_raw_response.update( - id="", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_list(self, client: Mobilerun) -> None: - esim = client.esims.list() - assert_matches_type(EsimListResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_list_with_all_params(self, client: Mobilerun) -> None: - esim = client.esims.list( - mine="true", - page=1, - page_size=1, - status="all", - ) - assert_matches_type(EsimListResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_list(self, client: Mobilerun) -> None: - response = client.esims.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = response.parse() - assert_matches_type(EsimListResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_list(self, client: Mobilerun) -> None: - with client.esims.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = response.parse() - assert_matches_type(EsimListResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_delete(self, client: Mobilerun) -> None: - esim = client.esims.delete( - "550e8400-e29b-41d4-a716-446655440000", - ) - assert esim is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_delete(self, client: Mobilerun) -> None: - response = client.esims.with_raw_response.delete( - "550e8400-e29b-41d4-a716-446655440000", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = response.parse() - assert esim is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_delete(self, client: Mobilerun) -> None: - with client.esims.with_streaming_response.delete( - "550e8400-e29b-41d4-a716-446655440000", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = response.parse() - assert esim is None - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_delete(self, client: Mobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.esims.with_raw_response.delete( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_capacity(self, client: Mobilerun) -> None: - esim = client.esims.capacity() - assert_matches_type(EsimCapacityResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_capacity(self, client: Mobilerun) -> None: - response = client.esims.with_raw_response.capacity() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = response.parse() - assert_matches_type(EsimCapacityResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_capacity(self, client: Mobilerun) -> None: - with client.esims.with_streaming_response.capacity() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = response.parse() - assert_matches_type(EsimCapacityResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_confirm_payment(self, client: Mobilerun) -> None: - esim = client.esims.confirm_payment( - "550e8400-e29b-41d4-a716-446655440000", - ) - assert_matches_type(EsimConfirmPaymentResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_confirm_payment(self, client: Mobilerun) -> None: - response = client.esims.with_raw_response.confirm_payment( - "550e8400-e29b-41d4-a716-446655440000", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = response.parse() - assert_matches_type(EsimConfirmPaymentResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_confirm_payment(self, client: Mobilerun) -> None: - with client.esims.with_streaming_response.confirm_payment( - "550e8400-e29b-41d4-a716-446655440000", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = response.parse() - assert_matches_type(EsimConfirmPaymentResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_confirm_payment(self, client: Mobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.esims.with_raw_response.confirm_payment( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_import(self, client: Mobilerun) -> None: - esim = client.esims.import_() - assert_matches_type(EsimImportResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_import_with_all_params(self, client: Mobilerun) -> None: - esim = client.esims.import_( - auto_install=True, - carrier_name="carrierName", - confirmation_code="confirmationCode", - country_code="countryCode", - device_id="physedge-dev-8f3a2c", - idempotency_key="x", - lpa_code="LPA:1$smdp.example.com$QR-MATCH-1", - matching_id="matchingId", - msisdn="+33612345678", - name="Mom's phone", - notes="notes", - smdp_address="smdp.example.com", - ) - assert_matches_type(EsimImportResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_import(self, client: Mobilerun) -> None: - response = client.esims.with_raw_response.import_() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = response.parse() - assert_matches_type(EsimImportResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_import(self, client: Mobilerun) -> None: - with client.esims.with_streaming_response.import_() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = response.parse() - assert_matches_type(EsimImportResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_install(self, client: Mobilerun) -> None: - esim = client.esims.install( - id="550e8400-e29b-41d4-a716-446655440000", - ) - assert_matches_type(EsimInstallResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_install_with_all_params(self, client: Mobilerun) -> None: - esim = client.esims.install( - id="550e8400-e29b-41d4-a716-446655440000", - device_id="physedge-dev-8f3a2c", - ) - assert_matches_type(EsimInstallResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_install(self, client: Mobilerun) -> None: - response = client.esims.with_raw_response.install( - id="550e8400-e29b-41d4-a716-446655440000", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = response.parse() - assert_matches_type(EsimInstallResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_install(self, client: Mobilerun) -> None: - with client.esims.with_streaming_response.install( - id="550e8400-e29b-41d4-a716-446655440000", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = response.parse() - assert_matches_type(EsimInstallResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_install(self, client: Mobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.esims.with_raw_response.install( - id="", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_install_status(self, client: Mobilerun) -> None: - esim = client.esims.install_status( - "550e8400-e29b-41d4-a716-446655440000", - ) - assert_matches_type(EsimInstallStatusResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_install_status(self, client: Mobilerun) -> None: - response = client.esims.with_raw_response.install_status( - "550e8400-e29b-41d4-a716-446655440000", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = response.parse() - assert_matches_type(EsimInstallStatusResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_install_status(self, client: Mobilerun) -> None: - with client.esims.with_streaming_response.install_status( - "550e8400-e29b-41d4-a716-446655440000", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = response.parse() - assert_matches_type(EsimInstallStatusResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_install_status(self, client: Mobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.esims.with_raw_response.install_status( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_selector(self, client: Mobilerun) -> None: - esim = client.esims.selector() - assert_matches_type(EsimSelectorResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_selector_with_all_params(self, client: Mobilerun) -> None: - esim = client.esims.selector( - page=1, - page_size=1, - ) - assert_matches_type(EsimSelectorResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_selector(self, client: Mobilerun) -> None: - response = client.esims.with_raw_response.selector() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = response.parse() - assert_matches_type(EsimSelectorResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_selector(self, client: Mobilerun) -> None: - with client.esims.with_streaming_response.selector() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = response.parse() - assert_matches_type(EsimSelectorResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - -class TestAsyncEsims: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_create(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.create() - assert_matches_type(EsimCreateResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.create( - idempotency_key="idempotencyKey", - name="Mom's phone", - ) - assert_matches_type(EsimCreateResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_create(self, async_client: AsyncMobilerun) -> None: - response = await async_client.esims.with_raw_response.create() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = await response.parse() - assert_matches_type(EsimCreateResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_create(self, async_client: AsyncMobilerun) -> None: - async with async_client.esims.with_streaming_response.create() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = await response.parse() - assert_matches_type(EsimCreateResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_retrieve(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.retrieve( - "550e8400-e29b-41d4-a716-446655440000", - ) - assert_matches_type(EsimRetrieveResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_retrieve(self, async_client: AsyncMobilerun) -> None: - response = await async_client.esims.with_raw_response.retrieve( - "550e8400-e29b-41d4-a716-446655440000", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = await response.parse() - assert_matches_type(EsimRetrieveResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncMobilerun) -> None: - async with async_client.esims.with_streaming_response.retrieve( - "550e8400-e29b-41d4-a716-446655440000", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = await response.parse() - assert_matches_type(EsimRetrieveResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_retrieve(self, async_client: AsyncMobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.esims.with_raw_response.retrieve( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_update(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.update( - id="550e8400-e29b-41d4-a716-446655440000", - ) - assert_matches_type(EsimUpdateResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_update_with_all_params(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.update( - id="550e8400-e29b-41d4-a716-446655440000", - msisdn="+33612345678", - name="Mom's phone", - ) - assert_matches_type(EsimUpdateResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_update(self, async_client: AsyncMobilerun) -> None: - response = await async_client.esims.with_raw_response.update( - id="550e8400-e29b-41d4-a716-446655440000", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = await response.parse() - assert_matches_type(EsimUpdateResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_update(self, async_client: AsyncMobilerun) -> None: - async with async_client.esims.with_streaming_response.update( - id="550e8400-e29b-41d4-a716-446655440000", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = await response.parse() - assert_matches_type(EsimUpdateResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_update(self, async_client: AsyncMobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.esims.with_raw_response.update( - id="", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.list() - assert_matches_type(EsimListResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.list( - mine="true", - page=1, - page_size=1, - status="all", - ) - assert_matches_type(EsimListResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_list(self, async_client: AsyncMobilerun) -> None: - response = await async_client.esims.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = await response.parse() - assert_matches_type(EsimListResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_list(self, async_client: AsyncMobilerun) -> None: - async with async_client.esims.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = await response.parse() - assert_matches_type(EsimListResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_delete(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.delete( - "550e8400-e29b-41d4-a716-446655440000", - ) - assert esim is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_delete(self, async_client: AsyncMobilerun) -> None: - response = await async_client.esims.with_raw_response.delete( - "550e8400-e29b-41d4-a716-446655440000", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = await response.parse() - assert esim is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_delete(self, async_client: AsyncMobilerun) -> None: - async with async_client.esims.with_streaming_response.delete( - "550e8400-e29b-41d4-a716-446655440000", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = await response.parse() - assert esim is None - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_delete(self, async_client: AsyncMobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.esims.with_raw_response.delete( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_capacity(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.capacity() - assert_matches_type(EsimCapacityResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_capacity(self, async_client: AsyncMobilerun) -> None: - response = await async_client.esims.with_raw_response.capacity() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = await response.parse() - assert_matches_type(EsimCapacityResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_capacity(self, async_client: AsyncMobilerun) -> None: - async with async_client.esims.with_streaming_response.capacity() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = await response.parse() - assert_matches_type(EsimCapacityResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_confirm_payment(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.confirm_payment( - "550e8400-e29b-41d4-a716-446655440000", - ) - assert_matches_type(EsimConfirmPaymentResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_confirm_payment(self, async_client: AsyncMobilerun) -> None: - response = await async_client.esims.with_raw_response.confirm_payment( - "550e8400-e29b-41d4-a716-446655440000", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = await response.parse() - assert_matches_type(EsimConfirmPaymentResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_confirm_payment(self, async_client: AsyncMobilerun) -> None: - async with async_client.esims.with_streaming_response.confirm_payment( - "550e8400-e29b-41d4-a716-446655440000", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = await response.parse() - assert_matches_type(EsimConfirmPaymentResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_confirm_payment(self, async_client: AsyncMobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.esims.with_raw_response.confirm_payment( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_import(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.import_() - assert_matches_type(EsimImportResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_import_with_all_params(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.import_( - auto_install=True, - carrier_name="carrierName", - confirmation_code="confirmationCode", - country_code="countryCode", - device_id="physedge-dev-8f3a2c", - idempotency_key="x", - lpa_code="LPA:1$smdp.example.com$QR-MATCH-1", - matching_id="matchingId", - msisdn="+33612345678", - name="Mom's phone", - notes="notes", - smdp_address="smdp.example.com", - ) - assert_matches_type(EsimImportResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_import(self, async_client: AsyncMobilerun) -> None: - response = await async_client.esims.with_raw_response.import_() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = await response.parse() - assert_matches_type(EsimImportResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_import(self, async_client: AsyncMobilerun) -> None: - async with async_client.esims.with_streaming_response.import_() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = await response.parse() - assert_matches_type(EsimImportResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_install(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.install( - id="550e8400-e29b-41d4-a716-446655440000", - ) - assert_matches_type(EsimInstallResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_install_with_all_params(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.install( - id="550e8400-e29b-41d4-a716-446655440000", - device_id="physedge-dev-8f3a2c", - ) - assert_matches_type(EsimInstallResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_install(self, async_client: AsyncMobilerun) -> None: - response = await async_client.esims.with_raw_response.install( - id="550e8400-e29b-41d4-a716-446655440000", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = await response.parse() - assert_matches_type(EsimInstallResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_install(self, async_client: AsyncMobilerun) -> None: - async with async_client.esims.with_streaming_response.install( - id="550e8400-e29b-41d4-a716-446655440000", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = await response.parse() - assert_matches_type(EsimInstallResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_install(self, async_client: AsyncMobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.esims.with_raw_response.install( - id="", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_install_status(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.install_status( - "550e8400-e29b-41d4-a716-446655440000", - ) - assert_matches_type(EsimInstallStatusResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_install_status(self, async_client: AsyncMobilerun) -> None: - response = await async_client.esims.with_raw_response.install_status( - "550e8400-e29b-41d4-a716-446655440000", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = await response.parse() - assert_matches_type(EsimInstallStatusResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_install_status(self, async_client: AsyncMobilerun) -> None: - async with async_client.esims.with_streaming_response.install_status( - "550e8400-e29b-41d4-a716-446655440000", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = await response.parse() - assert_matches_type(EsimInstallStatusResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_install_status(self, async_client: AsyncMobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - await async_client.esims.with_raw_response.install_status( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_selector(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.selector() - assert_matches_type(EsimSelectorResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_selector_with_all_params(self, async_client: AsyncMobilerun) -> None: - esim = await async_client.esims.selector( - page=1, - page_size=1, - ) - assert_matches_type(EsimSelectorResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_selector(self, async_client: AsyncMobilerun) -> None: - response = await async_client.esims.with_raw_response.selector() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - esim = await response.parse() - assert_matches_type(EsimSelectorResponse, esim, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_selector(self, async_client: AsyncMobilerun) -> None: - async with async_client.esims.with_streaming_response.selector() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - esim = await response.parse() - assert_matches_type(EsimSelectorResponse, esim, path=["response"]) - - assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_files.py b/tests/api_resources/test_files.py index 47decef9..47e3feb7 100644 --- a/tests/api_resources/test_files.py +++ b/tests/api_resources/test_files.py @@ -10,10 +10,7 @@ from tests.utils import assert_matches_type from mobilerun_sdk import Mobilerun, AsyncMobilerun from mobilerun_sdk.types import ( - FileListResponse, FileDeleteResponse, - FileUpdateResponse, - FileConfirmResponse, FileUploadURLResponse, FileCancelPendingResponse, ) @@ -24,94 +21,6 @@ class TestFiles: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_update(self, client: Mobilerun) -> None: - file = client.files.update( - file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_update_with_all_params(self, client: Mobilerun) -> None: - file = client.files.update( - file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - display_name="x", - enabled=True, - ) - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_update(self, client: Mobilerun) -> None: - response = client.files.with_raw_response.update( - file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = response.parse() - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_update(self, client: Mobilerun) -> None: - with client.files.with_streaming_response.update( - file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = response.parse() - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_update(self, client: Mobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - client.files.with_raw_response.update( - file_id="", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_list(self, client: Mobilerun) -> None: - file = client.files.list() - assert_matches_type(FileListResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_list_with_all_params(self, client: Mobilerun) -> None: - file = client.files.list( - zone="user", - ) - assert_matches_type(FileListResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_list(self, client: Mobilerun) -> None: - response = client.files.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = response.parse() - assert_matches_type(FileListResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_list(self, client: Mobilerun) -> None: - with client.files.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = response.parse() - assert_matches_type(FileListResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_delete(self, client: Mobilerun) -> None: @@ -196,48 +105,6 @@ def test_path_params_cancel_pending(self, client: Mobilerun) -> None: "", ) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_confirm(self, client: Mobilerun) -> None: - file = client.files.confirm( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(FileConfirmResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_confirm(self, client: Mobilerun) -> None: - response = client.files.with_raw_response.confirm( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = response.parse() - assert_matches_type(FileConfirmResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_confirm(self, client: Mobilerun) -> None: - with client.files.with_streaming_response.confirm( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = response.parse() - assert_matches_type(FileConfirmResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_confirm(self, client: Mobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - client.files.with_raw_response.confirm( - "", - ) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_download(self, client: Mobilerun) -> None: @@ -338,94 +205,6 @@ class TestAsyncFiles: "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_update(self, async_client: AsyncMobilerun) -> None: - file = await async_client.files.update( - file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_update_with_all_params(self, async_client: AsyncMobilerun) -> None: - file = await async_client.files.update( - file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - display_name="x", - enabled=True, - ) - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_update(self, async_client: AsyncMobilerun) -> None: - response = await async_client.files.with_raw_response.update( - file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = await response.parse() - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_update(self, async_client: AsyncMobilerun) -> None: - async with async_client.files.with_streaming_response.update( - file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = await response.parse() - assert_matches_type(FileUpdateResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_update(self, async_client: AsyncMobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - await async_client.files.with_raw_response.update( - file_id="", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list(self, async_client: AsyncMobilerun) -> None: - file = await async_client.files.list() - assert_matches_type(FileListResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncMobilerun) -> None: - file = await async_client.files.list( - zone="user", - ) - assert_matches_type(FileListResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_list(self, async_client: AsyncMobilerun) -> None: - response = await async_client.files.with_raw_response.list() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = await response.parse() - assert_matches_type(FileListResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_list(self, async_client: AsyncMobilerun) -> None: - async with async_client.files.with_streaming_response.list() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = await response.parse() - assert_matches_type(FileListResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_delete(self, async_client: AsyncMobilerun) -> None: @@ -510,48 +289,6 @@ async def test_path_params_cancel_pending(self, async_client: AsyncMobilerun) -> "", ) - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_confirm(self, async_client: AsyncMobilerun) -> None: - file = await async_client.files.confirm( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(FileConfirmResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_confirm(self, async_client: AsyncMobilerun) -> None: - response = await async_client.files.with_raw_response.confirm( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - file = await response.parse() - assert_matches_type(FileConfirmResponse, file, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_confirm(self, async_client: AsyncMobilerun) -> None: - async with async_client.files.with_streaming_response.confirm( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - file = await response.parse() - assert_matches_type(FileConfirmResponse, file, path=["response"]) - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_confirm(self, async_client: AsyncMobilerun) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): - await async_client.files.with_raw_response.confirm( - "", - ) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_download(self, async_client: AsyncMobilerun) -> None: diff --git a/tests/api_resources/test_mailboxes.py b/tests/api_resources/test_mailboxes.py index fee64e12..45d04734 100644 --- a/tests/api_resources/test_mailboxes.py +++ b/tests/api_resources/test_mailboxes.py @@ -42,6 +42,7 @@ def test_method_create_with_all_params(self, client: Mobilerun) -> None: mailbox = client.mailboxes.create( client_request_id="x", billing_preference="included", + domain_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", label="label", local_part="jane-doe", ) @@ -435,6 +436,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncMobilerun) mailbox = await async_client.mailboxes.create( client_request_id="x", billing_preference="included", + domain_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", label="label", local_part="jane-doe", ) diff --git a/tests/api_resources/test_numbers.py b/tests/api_resources/test_numbers.py index 44193174..957aab3c 100644 --- a/tests/api_resources/test_numbers.py +++ b/tests/api_resources/test_numbers.py @@ -14,6 +14,7 @@ NumberCreateResponse, NumberDeleteResponse, NumberUpdateResponse, + NumberCapacityResponse, NumberPurposesResponse, NumberRetrieveResponse, NumberCountriesResponse, @@ -237,6 +238,40 @@ def test_path_params_delete(self, client: Mobilerun) -> None: "", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_capacity(self, client: Mobilerun) -> None: + number = client.numbers.capacity( + country="de", + ) + assert_matches_type(NumberCapacityResponse, number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_capacity(self, client: Mobilerun) -> None: + response = client.numbers.with_raw_response.capacity( + country="de", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + number = response.parse() + assert_matches_type(NumberCapacityResponse, number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_capacity(self, client: Mobilerun) -> None: + with client.numbers.with_streaming_response.capacity( + country="de", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + number = response.parse() + assert_matches_type(NumberCapacityResponse, number, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_countries(self, client: Mobilerun) -> None: @@ -511,6 +546,40 @@ async def test_path_params_delete(self, async_client: AsyncMobilerun) -> None: "", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_capacity(self, async_client: AsyncMobilerun) -> None: + number = await async_client.numbers.capacity( + country="de", + ) + assert_matches_type(NumberCapacityResponse, number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_capacity(self, async_client: AsyncMobilerun) -> None: + response = await async_client.numbers.with_raw_response.capacity( + country="de", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + number = await response.parse() + assert_matches_type(NumberCapacityResponse, number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_capacity(self, async_client: AsyncMobilerun) -> None: + async with async_client.numbers.with_streaming_response.capacity( + country="de", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + number = await response.parse() + assert_matches_type(NumberCapacityResponse, number, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_countries(self, async_client: AsyncMobilerun) -> None: diff --git a/tests/api_resources/test_tasks.py b/tests/api_resources/test_tasks.py index cf65f53d..9a7b6bee 100644 --- a/tests/api_resources/test_tasks.py +++ b/tests/api_resources/test_tasks.py @@ -84,7 +84,8 @@ def test_method_list_with_all_params(self, client: Mobilerun) -> None: page=1, page_size=1, query="query", - status="queued", + source="api", + status="prepared", ) assert_matches_type(TaskListResponse, task, path=["response"]) @@ -252,7 +253,6 @@ def test_method_run_with_all_params(self, client: Mobilerun) -> None: device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task="x", accessibility=True, - agent_id=0, apps=["string"], continue_on_failure=True, credentials=[ @@ -269,8 +269,10 @@ def test_method_run_with_all_params(self, client: Mobilerun) -> None: memory_namespace="memoryNamespace", output_schema={"foo": "bar"}, reasoning=True, + recording_enabled=True, stealth=True, subagent_model="subagentModel", + system_prompt="systemPrompt", temperature=0, vision=True, vpn_country="US", @@ -322,7 +324,6 @@ def test_method_run_streamed_with_all_params(self, client: Mobilerun) -> None: device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task="x", accessibility=True, - agent_id=0, apps=["string"], continue_on_failure=True, credentials=[ @@ -339,8 +340,10 @@ def test_method_run_streamed_with_all_params(self, client: Mobilerun) -> None: memory_namespace="memoryNamespace", output_schema={"foo": "bar"}, reasoning=True, + recording_enabled=True, stealth=True, subagent_model="subagentModel", + system_prompt="systemPrompt", temperature=0, vision=True, vpn_country="US", @@ -528,7 +531,8 @@ async def test_method_list_with_all_params(self, async_client: AsyncMobilerun) - page=1, page_size=1, query="query", - status="queued", + source="api", + status="prepared", ) assert_matches_type(TaskListResponse, task, path=["response"]) @@ -696,7 +700,6 @@ async def test_method_run_with_all_params(self, async_client: AsyncMobilerun) -> device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task="x", accessibility=True, - agent_id=0, apps=["string"], continue_on_failure=True, credentials=[ @@ -713,8 +716,10 @@ async def test_method_run_with_all_params(self, async_client: AsyncMobilerun) -> memory_namespace="memoryNamespace", output_schema={"foo": "bar"}, reasoning=True, + recording_enabled=True, stealth=True, subagent_model="subagentModel", + system_prompt="systemPrompt", temperature=0, vision=True, vpn_country="US", @@ -766,7 +771,6 @@ async def test_method_run_streamed_with_all_params(self, async_client: AsyncMobi device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task="x", accessibility=True, - agent_id=0, apps=["string"], continue_on_failure=True, credentials=[ @@ -783,8 +787,10 @@ async def test_method_run_streamed_with_all_params(self, async_client: AsyncMobi memory_namespace="memoryNamespace", output_schema={"foo": "bar"}, reasoning=True, + recording_enabled=True, stealth=True, subagent_model="subagentModel", + system_prompt="systemPrompt", temperature=0, vision=True, vpn_country="US", diff --git a/tests/api_resources/workflows/flows/test_actions.py b/tests/api_resources/workflows/flows/test_actions.py index 797f7246..21f7ca88 100644 --- a/tests/api_resources/workflows/flows/test_actions.py +++ b/tests/api_resources/workflows/flows/test_actions.py @@ -88,12 +88,14 @@ def test_method_add_with_all_params(self, client: Mobilerun) -> None: "continue_on_error": True, "name_override": "x", "overrides": {"params": {"foo": "bar"}}, + "recording_enabled": True, } ], continue_on_error=True, name_override="x", overrides={"params": {"foo": "bar"}}, parent_flow_action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + recording_enabled=True, ) assert_matches_type(ActionAddResponse, action, path=["response"]) @@ -327,12 +329,14 @@ async def test_method_add_with_all_params(self, async_client: AsyncMobilerun) -> "continue_on_error": True, "name_override": "x", "overrides": {"params": {"foo": "bar"}}, + "recording_enabled": True, } ], continue_on_error=True, name_override="x", overrides={"params": {"foo": "bar"}}, parent_flow_action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + recording_enabled=True, ) assert_matches_type(ActionAddResponse, action, path=["response"]) diff --git a/tests/api_resources/workflows/test_flows.py b/tests/api_resources/workflows/test_flows.py index 845d0f4f..eb527497 100644 --- a/tests/api_resources/workflows/test_flows.py +++ b/tests/api_resources/workflows/test_flows.py @@ -17,6 +17,7 @@ FlowDryRunResponse, FlowUpdateResponse, FlowUnblockResponse, + FlowCapacityResponse, FlowRetrieveResponse, FlowListRepairsResponse, ) @@ -57,11 +58,13 @@ def test_method_create_with_all_params(self, client: Mobilerun) -> None: "continue_on_error": True, "name_override": "x", "overrides": {"params": {"foo": "bar"}}, + "recording_enabled": True, } ], "continue_on_error": True, "name_override": "x", "overrides": {"params": {"foo": "bar"}}, + "recording_enabled": True, } ], name="x", @@ -76,6 +79,7 @@ def test_method_create_with_all_params(self, client: Mobilerun) -> None: notify_on_success=True, notify_webhook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", recording_enabled=True, + recording_policy={"mode": "off"}, self_healing_enabled=True, self_healing_max_attempts=1, ) @@ -182,11 +186,13 @@ def test_method_update_with_all_params(self, client: Mobilerun) -> None: device_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], enabled=True, health_monitoring_enabled=True, + lifecycle_status="enabled", name="x", notify_on_failure=True, notify_on_success=True, notify_webhook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", recording_enabled=True, + recording_policy={"mode": "off"}, self_healing_enabled=True, self_healing_max_attempts=1, trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", @@ -314,6 +320,34 @@ def test_path_params_delete(self, client: Mobilerun) -> None: "", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_capacity(self, client: Mobilerun) -> None: + flow = client.workflows.flows.capacity() + assert_matches_type(FlowCapacityResponse, flow, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_capacity(self, client: Mobilerun) -> None: + response = client.workflows.flows.with_raw_response.capacity() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + flow = response.parse() + assert_matches_type(FlowCapacityResponse, flow, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_capacity(self, client: Mobilerun) -> None: + with client.workflows.flows.with_streaming_response.capacity() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + flow = response.parse() + assert_matches_type(FlowCapacityResponse, flow, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_clone(self, client: Mobilerun) -> None: @@ -537,11 +571,13 @@ async def test_method_create_with_all_params(self, async_client: AsyncMobilerun) "continue_on_error": True, "name_override": "x", "overrides": {"params": {"foo": "bar"}}, + "recording_enabled": True, } ], "continue_on_error": True, "name_override": "x", "overrides": {"params": {"foo": "bar"}}, + "recording_enabled": True, } ], name="x", @@ -556,6 +592,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncMobilerun) notify_on_success=True, notify_webhook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", recording_enabled=True, + recording_policy={"mode": "off"}, self_healing_enabled=True, self_healing_max_attempts=1, ) @@ -662,11 +699,13 @@ async def test_method_update_with_all_params(self, async_client: AsyncMobilerun) device_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], enabled=True, health_monitoring_enabled=True, + lifecycle_status="enabled", name="x", notify_on_failure=True, notify_on_success=True, notify_webhook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", recording_enabled=True, + recording_policy={"mode": "off"}, self_healing_enabled=True, self_healing_max_attempts=1, trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", @@ -794,6 +833,34 @@ async def test_path_params_delete(self, async_client: AsyncMobilerun) -> None: "", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_capacity(self, async_client: AsyncMobilerun) -> None: + flow = await async_client.workflows.flows.capacity() + assert_matches_type(FlowCapacityResponse, flow, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_capacity(self, async_client: AsyncMobilerun) -> None: + response = await async_client.workflows.flows.with_raw_response.capacity() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + flow = await response.parse() + assert_matches_type(FlowCapacityResponse, flow, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_capacity(self, async_client: AsyncMobilerun) -> None: + async with async_client.workflows.flows.with_streaming_response.capacity() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + flow = await response.parse() + assert_matches_type(FlowCapacityResponse, flow, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_clone(self, async_client: AsyncMobilerun) -> None: