diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 1f73031..8e76abb 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "3.2.0"
+ ".": "5.0.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 20e38d9..693b09d 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 104
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/droidrun/droidrun-cloud-9c5542353ace880640fb7e8946c5c8d008480abb8d1952595ba2ee9323aed724.yml
-openapi_spec_hash: afa528f0921063291f66c56c6093f2ab
-config_hash: 27cfddf59d8227e89667fa012952335c
+configured_endpoints: 166
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/droidrun/droidrun-cloud-4e32174d9764ddeec31db33c46c772c4ac06eb72aa399445f79283b35c57e37d.yml
+openapi_spec_hash: b2b7096b8e12f79a52ad303aa9b21dea
+config_hash: 7eee71321886b0cd05bdbd017f9d06ec
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 91e1a63..7832318 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,25 @@
# Changelog
+## 5.0.0 (2026-06-11)
+
+Full Changelog: [v3.2.0...v5.0.0](https://github.com/droidrun/mobilerun-sdk-python/compare/v3.2.0...v5.0.0)
+
+### Features
+
+* **api:** add agents-api ([ec80ec3](https://github.com/droidrun/mobilerun-sdk-python/commit/ec80ec35e333e302f8b09cd8ddf81d69d297f027))
+* **api:** api update ([080b0a8](https://github.com/droidrun/mobilerun-sdk-python/commit/080b0a8a668e792ddfc8f2ceacb30ca59ac0f45a))
+* **api:** api update ([13645e2](https://github.com/droidrun/mobilerun-sdk-python/commit/13645e2290241b8930ad56231b0aac9ffb0d8b9d))
+* **api:** api update ([472689f](https://github.com/droidrun/mobilerun-sdk-python/commit/472689f40d0225edcedb331fabda5d9b5ddbe390))
+* **api:** api update ([b58be1c](https://github.com/droidrun/mobilerun-sdk-python/commit/b58be1c00be168f8719a56d2ce5c1806ac30ef92))
+* **api:** api update ([2add42e](https://github.com/droidrun/mobilerun-sdk-python/commit/2add42ec33a0accad90ab5afe8d27ce22629b871))
+* **api:** enable workflows ([b01d496](https://github.com/droidrun/mobilerun-sdk-python/commit/b01d4969bea4f20289720122c261a9897af656f2))
+* **api:** manual updates ([16e622e](https://github.com/droidrun/mobilerun-sdk-python/commit/16e622e471e8043c80c30f9904eb74bd168f1b00))
+* **api:** manual updates ([1b32b0d](https://github.com/droidrun/mobilerun-sdk-python/commit/1b32b0daa46383c045df0b9ec5e8903d0c6b8808))
+* **api:** manual updates ([7fa7979](https://github.com/droidrun/mobilerun-sdk-python/commit/7fa7979dda9d7827014ec82d390c622c3f096929))
+* **api:** manual updates ([1a4d40d](https://github.com/droidrun/mobilerun-sdk-python/commit/1a4d40df9fc939af3fc0c1cd7885b450821b7ce2))
+* **api:** manual updates ([88c9ae0](https://github.com/droidrun/mobilerun-sdk-python/commit/88c9ae09fe4979789e30e859bf9f7d57f39887c2))
+* **api:** mobilerun connect endpoints ([7856951](https://github.com/droidrun/mobilerun-sdk-python/commit/785695138d9ad132ef6ea86802c6b26d89ed9337))
+
## 3.2.0 (2026-05-21)
Full Changelog: [v3.1.0...v3.2.0](https://github.com/droidrun/mobilerun-sdk-python/compare/v3.1.0...v3.2.0)
diff --git a/api.md b/api.md
index ccda2c7..6511b2d 100644
--- a/api.md
+++ b/api.md
@@ -16,15 +16,85 @@ from mobilerun_sdk.types import (
# Agents
+## Chat
+
Types:
```python
-from mobilerun_sdk.types import AgentListResponse
+from mobilerun_sdk.types.agents import (
+ ChatDeliverPermissionResponse,
+ ChatGetChatStateResponse,
+ ChatListSlashCommandsResponse,
+ ChatRehydrateChatResponse,
+)
```
Methods:
-- client.agents.list() -> AgentListResponse
+- client.agents.chat.deliver_permission(\*\*params) -> ChatDeliverPermissionResponse
+- client.agents.chat.get_chat_state() -> ChatGetChatStateResponse
+- client.agents.chat.list_slash_commands() -> ChatListSlashCommandsResponse
+- client.agents.chat.rehydrate_chat() -> ChatRehydrateChatResponse
+
+### Abort
+
+Types:
+
+```python
+from mobilerun_sdk.types.agents.chat import AbortForceClearResponse, AbortPerformResponse
+```
+
+Methods:
+
+- client.agents.chat.abort.force_clear() -> AbortForceClearResponse
+- client.agents.chat.abort.perform() -> AbortPerformResponse
+
+### Question
+
+Types:
+
+```python
+from mobilerun_sdk.types.agents.chat import QuestionDeliverAnswerResponse, QuestionDismissResponse
+```
+
+Methods:
+
+- client.agents.chat.question.deliver_answer(\*\*params) -> QuestionDeliverAnswerResponse
+- client.agents.chat.question.dismiss(\*\*params) -> QuestionDismissResponse
+
+## Files
+
+Types:
+
+```python
+from mobilerun_sdk.types.agents import FileListFilesResponse, FileMintUploadURLResponse
+```
+
+Methods:
+
+- client.agents.files.list_files(\*\*params) -> FileListFilesResponse
+- client.agents.files.mint_upload_url(\*\*params) -> FileMintUploadURLResponse
+
+### FileID
+
+Types:
+
+```python
+from mobilerun_sdk.types.agents.files import (
+ FileIDCancelPendingUploadResponse,
+ FileIDConfirmUploadResponse,
+ FileIDDeleteFileResponse,
+ FileIDUpdateMetadataResponse,
+)
+```
+
+Methods:
+
+- client.agents.files.file_id.cancel_pending_upload() -> FileIDCancelPendingUploadResponse
+- client.agents.files.file_id.confirm_upload() -> FileIDConfirmUploadResponse
+- client.agents.files.file_id.delete_file() -> FileIDDeleteFileResponse
+- client.agents.files.file_id.download_file() -> None
+- client.agents.files.file_id.update_metadata(\*\*params) -> FileIDUpdateMetadataResponse
# Apps
@@ -37,6 +107,7 @@ from mobilerun_sdk.types import (
AppDeleteResponse,
AppConfirmUploadResponse,
AppCreateSignedUploadURLResponse,
+ AppListVersionsResponse,
AppMarkFailedResponse,
)
```
@@ -48,6 +119,7 @@ Methods:
- client.apps.delete(id) -> AppDeleteResponse
- client.apps.confirm_upload(id) -> AppConfirmUploadResponse
- client.apps.create_signed_upload_url(\*\*params) -> AppCreateSignedUploadURLResponse
+- client.apps.list_versions(id) -> AppListVersionsResponse
- client.apps.mark_failed(id) -> AppMarkFailedResponse
# Carriers
@@ -188,42 +260,26 @@ from mobilerun_sdk.types.devices import AppListResponse
Methods:
-- client.devices.apps.update(package_name, \*, device_id) -> None
- client.devices.apps.list(device_id, \*\*params) -> Optional[AppListResponse]
- client.devices.apps.delete(package_name, \*, device_id) -> None
- client.devices.apps.install(device_id, \*\*params) -> None
- client.devices.apps.start(package_name, \*, device_id, \*\*params) -> None
+- client.devices.apps.stop(package_name, \*, device_id) -> None
## Esim
Types:
```python
-from mobilerun_sdk.types.devices import EsimListResponse, EsimActivateResponse, EsimStatusResponse
-```
-
-Methods:
-
-- client.devices.esim.list(device_id) -> Optional[EsimListResponse]
-- client.devices.esim.activate(device_id, \*\*params) -> EsimActivateResponse
-- client.devices.esim.enable(device_id, \*\*params) -> None
-- client.devices.esim.remove(device_id, \*\*params) -> None
-- client.devices.esim.set_roaming(device_id, \*\*params) -> None
-- client.devices.esim.status(device_id) -> Optional[EsimStatusResponse]
-
-### Apn
-
-Types:
-
-```python
-from mobilerun_sdk.types.devices.esim import ApnListResponse
+from mobilerun_sdk.types.devices import EsimListResponse, EsimActivateResponse
```
Methods:
-- client.devices.esim.apn.create(device_id, \*\*params) -> None
-- client.devices.esim.apn.list(device_id) -> Optional[ApnListResponse]
-- client.devices.esim.apn.select(device_id, \*\*params) -> None
+- client.devices.esim.list(device_id) -> Optional[EsimListResponse]
+- client.devices.esim.activate(device_id, \*\*params) -> EsimActivateResponse
+- client.devices.esim.enable(device_id, \*\*params) -> None
+- client.devices.esim.remove(device_id, \*\*params) -> None
## Files
@@ -293,6 +349,7 @@ Types:
```python
from mobilerun_sdk.types.devices import (
+ A11YNode,
Rect,
StateScreenshotResponse,
StateTimeResponse,
@@ -356,6 +413,7 @@ from mobilerun_sdk.types import (
HookGetSampleDataResponse,
HookPerformResponse,
HookSubscribeResponse,
+ HookTestResponse,
HookUnsubscribeResponse,
)
```
@@ -368,6 +426,7 @@ Methods:
- client.hooks.get_sample_data() -> HookGetSampleDataResponse
- client.hooks.perform(\*\*params) -> HookPerformResponse
- client.hooks.subscribe(\*\*params) -> HookSubscribeResponse
+- client.hooks.test(hook_id, \*\*params) -> HookTestResponse
- client.hooks.unsubscribe(hook_id) -> HookUnsubscribeResponse
# Models
@@ -410,6 +469,7 @@ from mobilerun_sdk.types import (
ProxyUpdateResponse,
ProxyListResponse,
ProxyDeleteResponse,
+ ProxyLookupResponse,
)
```
@@ -420,6 +480,67 @@ Methods:
- client.proxies.update(proxy_id, \*\*params) -> ProxyUpdateResponse
- client.proxies.list(\*\*params) -> ProxyListResponse
- client.proxies.delete(proxy_id) -> ProxyDeleteResponse
+- client.proxies.lookup(\*\*params) -> ProxyLookupResponse
+
+# Connect
+
+## Countries
+
+Types:
+
+```python
+from mobilerun_sdk.types.connect import CountryListResponse
+```
+
+Methods:
+
+- client.connect.countries.list(\*\*params) -> CountryListResponse
+
+## Proxies
+
+Types:
+
+```python
+from mobilerun_sdk.types.connect import (
+ ProxyRetrieveResponse,
+ ProxyListResponse,
+ ProxyBuyResponse,
+ ProxyListConnectionsResponse,
+ ProxyPingResponse,
+)
+```
+
+Methods:
+
+- client.connect.proxies.retrieve(id) -> ProxyRetrieveResponse
+- client.connect.proxies.list(\*\*params) -> ProxyListResponse
+- client.connect.proxies.buy(\*\*params) -> ProxyBuyResponse
+- client.connect.proxies.cancel(id) -> None
+- client.connect.proxies.list_connections(id, \*\*params) -> ProxyListConnectionsResponse
+- client.connect.proxies.ping(id) -> ProxyPingResponse
+
+## Users
+
+Types:
+
+```python
+from mobilerun_sdk.types.connect import (
+ UserCreateResponse,
+ UserRetrieveResponse,
+ UserUpdateResponse,
+ UserListResponse,
+ UserListConnectionsResponse,
+)
+```
+
+Methods:
+
+- client.connect.users.create(\*\*params) -> UserCreateResponse
+- client.connect.users.retrieve(id) -> UserRetrieveResponse
+- client.connect.users.update(id, \*\*params) -> UserUpdateResponse
+- client.connect.users.list(\*\*params) -> UserListResponse
+- client.connect.users.delete(id) -> None
+- client.connect.users.list_connections(id, \*\*params) -> UserListConnectionsResponse
# Tasks
@@ -478,3 +599,213 @@ Methods:
- client.tasks.ui_states.retrieve(index, \*, task_id) -> MediaResponse
- client.tasks.ui_states.list(task_id) -> UiStateListResponse
+
+# Workflows
+
+Types:
+
+```python
+from mobilerun_sdk.types import Flow
+```
+
+## Triggers
+
+Types:
+
+```python
+from mobilerun_sdk.types.workflows import (
+ TriggerCreateResponse,
+ TriggerRetrieveResponse,
+ TriggerUpdateResponse,
+ TriggerListResponse,
+ TriggerDeleteResponse,
+ TriggerFireResponse,
+)
+```
+
+Methods:
+
+- client.workflows.triggers.create(\*\*params) -> TriggerCreateResponse
+- client.workflows.triggers.retrieve(trigger_id) -> TriggerRetrieveResponse
+- client.workflows.triggers.update(trigger_id, \*\*params) -> TriggerUpdateResponse
+- client.workflows.triggers.list(\*\*params) -> TriggerListResponse
+- client.workflows.triggers.delete(trigger_id) -> TriggerDeleteResponse
+- client.workflows.triggers.fire(trigger_id, \*\*params) -> TriggerFireResponse
+
+## ActionCatalog
+
+Types:
+
+```python
+from mobilerun_sdk.types.workflows import (
+ ActionCatalogEntry,
+ ActionCatalogRetrieveResponse,
+ ActionCatalogListResponse,
+)
+```
+
+Methods:
+
+- client.workflows.action_catalog.retrieve(catalog_entry_id) -> ActionCatalogRetrieveResponse
+- client.workflows.action_catalog.list(\*\*params) -> ActionCatalogListResponse
+
+## Actions
+
+Types:
+
+```python
+from mobilerun_sdk.types.workflows import (
+ Action,
+ ActionCreateResponse,
+ ActionRetrieveResponse,
+ ActionUpdateResponse,
+ ActionListResponse,
+ ActionDeleteResponse,
+)
+```
+
+Methods:
+
+- client.workflows.actions.create(\*\*params) -> ActionCreateResponse
+- client.workflows.actions.retrieve(action_id) -> ActionRetrieveResponse
+- client.workflows.actions.update(action_id, \*\*params) -> ActionUpdateResponse
+- client.workflows.actions.list(\*\*params) -> ActionListResponse
+- client.workflows.actions.delete(action_id) -> ActionDeleteResponse
+
+### Services
+
+Types:
+
+```python
+from mobilerun_sdk.types.workflows.actions import ServiceListResponse, ServiceListMethodsResponse
+```
+
+Methods:
+
+- client.workflows.actions.services.list() -> ServiceListResponse
+- client.workflows.actions.services.list_methods(service) -> ServiceListMethodsResponse
+
+## Flows
+
+Types:
+
+```python
+from mobilerun_sdk.types.workflows import (
+ FlowActionOverrides,
+ FlowChildActionInput,
+ FlowCreateResponse,
+ FlowRetrieveResponse,
+ FlowUpdateResponse,
+ FlowListResponse,
+ FlowDeleteResponse,
+ FlowCloneResponse,
+ FlowUnblockResponse,
+)
+```
+
+Methods:
+
+- client.workflows.flows.create(\*\*params) -> FlowCreateResponse
+- client.workflows.flows.retrieve(flow_id) -> FlowRetrieveResponse
+- client.workflows.flows.update(flow_id, \*\*params) -> FlowUpdateResponse
+- client.workflows.flows.list(\*\*params) -> FlowListResponse
+- client.workflows.flows.delete(flow_id) -> FlowDeleteResponse
+- client.workflows.flows.clone(flow_id, \*\*params) -> FlowCloneResponse
+- client.workflows.flows.unblock(flow_id) -> FlowUnblockResponse
+
+### Actions
+
+Types:
+
+```python
+from mobilerun_sdk.types.workflows.flows import (
+ FlowAction,
+ ActionListResponse,
+ ActionAddResponse,
+ ActionRemoveResponse,
+ ActionReplaceResponse,
+)
+```
+
+Methods:
+
+- client.workflows.flows.actions.list(flow_id) -> ActionListResponse
+- client.workflows.flows.actions.add(flow_id, \*\*params) -> ActionAddResponse
+- client.workflows.flows.actions.remove(flow_action_id, \*, flow_id) -> ActionRemoveResponse
+- client.workflows.flows.actions.replace(flow_id, \*\*params) -> ActionReplaceResponse
+
+## Events
+
+Types:
+
+```python
+from mobilerun_sdk.types.workflows import EventDryRunResponse, EventIngestResponse
+```
+
+Methods:
+
+- client.workflows.events.dry_run(\*\*params) -> EventDryRunResponse
+- client.workflows.events.ingest(\*\*params) -> EventIngestResponse
+
+### Catalog
+
+Types:
+
+```python
+from mobilerun_sdk.types.workflows.events import CatalogListResponse, CatalogRegisterResponse
+```
+
+Methods:
+
+- client.workflows.events.catalog.list(\*\*params) -> CatalogListResponse
+- client.workflows.events.catalog.register(\*\*params) -> CatalogRegisterResponse
+
+## Executions
+
+Types:
+
+```python
+from mobilerun_sdk.types.workflows import (
+ FlowExecution,
+ ExecutionRetrieveResponse,
+ ExecutionListResponse,
+ ExecutionGetMetricsResponse,
+)
+```
+
+Methods:
+
+- client.workflows.executions.retrieve(execution_id) -> ExecutionRetrieveResponse
+- client.workflows.executions.list(\*\*params) -> ExecutionListResponse
+- client.workflows.executions.get_metrics(\*\*params) -> ExecutionGetMetricsResponse
+
+## Timezones
+
+Types:
+
+```python
+from mobilerun_sdk.types.workflows import TimezoneListResponse
+```
+
+Methods:
+
+- client.workflows.timezones.list() -> TimezoneListResponse
+
+## Secrets
+
+Types:
+
+```python
+from mobilerun_sdk.types.workflows import (
+ UserSecret,
+ SecretCreateResponse,
+ SecretListResponse,
+ SecretDeleteResponse,
+)
+```
+
+Methods:
+
+- client.workflows.secrets.create(\*\*params) -> SecretCreateResponse
+- client.workflows.secrets.list() -> SecretListResponse
+- client.workflows.secrets.delete(secret_id) -> SecretDeleteResponse
diff --git a/pyproject.toml b/pyproject.toml
index b097c23..92a3d5d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "mobilerun-sdk"
-version = "3.2.0"
+version = "5.0.0"
description = "The official Python library for the mobilerun API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/mobilerun_sdk/_client.py b/src/mobilerun_sdk/_client.py
index 28b10f0..152574a 100644
--- a/src/mobilerun_sdk/_client.py
+++ b/src/mobilerun_sdk/_client.py
@@ -36,16 +36,31 @@
)
if TYPE_CHECKING:
- from .resources import apps, hooks, tasks, agents, models, devices, proxies, carriers, profiles, credentials
+ from .resources import (
+ apps,
+ hooks,
+ tasks,
+ agents,
+ models,
+ connect,
+ devices,
+ proxies,
+ carriers,
+ profiles,
+ workflows,
+ credentials,
+ )
from .resources.apps import AppsResource, AsyncAppsResource
from .resources.hooks import HooksResource, AsyncHooksResource
- from .resources.agents import AgentsResource, AsyncAgentsResource
from .resources.models import ModelsResource, AsyncModelsResource
from .resources.proxies import ProxiesResource, AsyncProxiesResource
from .resources.carriers import CarriersResource, AsyncCarriersResource
from .resources.profiles import ProfilesResource, AsyncProfilesResource
from .resources.tasks.tasks import TasksResource, AsyncTasksResource
+ from .resources.agents.agents import AgentsResource, AsyncAgentsResource
+ from .resources.connect.connect import ConnectResource, AsyncConnectResource
from .resources.devices.devices import DevicesResource, AsyncDevicesResource
+ from .resources.workflows.workflows import WorkflowsResource, AsyncWorkflowsResource
from .resources.credentials.credentials import CredentialsResource, AsyncCredentialsResource
__all__ = [
@@ -122,7 +137,6 @@ def __init__(
@cached_property
def agents(self) -> AgentsResource:
- """Agents API"""
from .resources.agents import AgentsResource
return AgentsResource(self)
@@ -180,6 +194,12 @@ def proxies(self) -> ProxiesResource:
return ProxiesResource(self)
+ @cached_property
+ def connect(self) -> ConnectResource:
+ from .resources.connect import ConnectResource
+
+ return ConnectResource(self)
+
@cached_property
def tasks(self) -> TasksResource:
"""Tasks API"""
@@ -187,6 +207,12 @@ def tasks(self) -> TasksResource:
return TasksResource(self)
+ @cached_property
+ def workflows(self) -> WorkflowsResource:
+ from .resources.workflows import WorkflowsResource
+
+ return WorkflowsResource(self)
+
@cached_property
def with_raw_response(self) -> MobilerunWithRawResponse:
return MobilerunWithRawResponse(self)
@@ -373,7 +399,6 @@ def __init__(
@cached_property
def agents(self) -> AsyncAgentsResource:
- """Agents API"""
from .resources.agents import AsyncAgentsResource
return AsyncAgentsResource(self)
@@ -431,6 +456,12 @@ def proxies(self) -> AsyncProxiesResource:
return AsyncProxiesResource(self)
+ @cached_property
+ def connect(self) -> AsyncConnectResource:
+ from .resources.connect import AsyncConnectResource
+
+ return AsyncConnectResource(self)
+
@cached_property
def tasks(self) -> AsyncTasksResource:
"""Tasks API"""
@@ -438,6 +469,12 @@ def tasks(self) -> AsyncTasksResource:
return AsyncTasksResource(self)
+ @cached_property
+ def workflows(self) -> AsyncWorkflowsResource:
+ from .resources.workflows import AsyncWorkflowsResource
+
+ return AsyncWorkflowsResource(self)
+
@cached_property
def with_raw_response(self) -> AsyncMobilerunWithRawResponse:
return AsyncMobilerunWithRawResponse(self)
@@ -570,7 +607,6 @@ def __init__(self, client: Mobilerun) -> None:
@cached_property
def agents(self) -> agents.AgentsResourceWithRawResponse:
- """Agents API"""
from .resources.agents import AgentsResourceWithRawResponse
return AgentsResourceWithRawResponse(self._client.agents)
@@ -628,6 +664,12 @@ def proxies(self) -> proxies.ProxiesResourceWithRawResponse:
return ProxiesResourceWithRawResponse(self._client.proxies)
+ @cached_property
+ def connect(self) -> connect.ConnectResourceWithRawResponse:
+ from .resources.connect import ConnectResourceWithRawResponse
+
+ return ConnectResourceWithRawResponse(self._client.connect)
+
@cached_property
def tasks(self) -> tasks.TasksResourceWithRawResponse:
"""Tasks API"""
@@ -635,6 +677,12 @@ def tasks(self) -> tasks.TasksResourceWithRawResponse:
return TasksResourceWithRawResponse(self._client.tasks)
+ @cached_property
+ def workflows(self) -> workflows.WorkflowsResourceWithRawResponse:
+ from .resources.workflows import WorkflowsResourceWithRawResponse
+
+ return WorkflowsResourceWithRawResponse(self._client.workflows)
+
class AsyncMobilerunWithRawResponse:
_client: AsyncMobilerun
@@ -644,7 +692,6 @@ def __init__(self, client: AsyncMobilerun) -> None:
@cached_property
def agents(self) -> agents.AsyncAgentsResourceWithRawResponse:
- """Agents API"""
from .resources.agents import AsyncAgentsResourceWithRawResponse
return AsyncAgentsResourceWithRawResponse(self._client.agents)
@@ -702,6 +749,12 @@ def proxies(self) -> proxies.AsyncProxiesResourceWithRawResponse:
return AsyncProxiesResourceWithRawResponse(self._client.proxies)
+ @cached_property
+ def connect(self) -> connect.AsyncConnectResourceWithRawResponse:
+ from .resources.connect import AsyncConnectResourceWithRawResponse
+
+ return AsyncConnectResourceWithRawResponse(self._client.connect)
+
@cached_property
def tasks(self) -> tasks.AsyncTasksResourceWithRawResponse:
"""Tasks API"""
@@ -709,6 +762,12 @@ def tasks(self) -> tasks.AsyncTasksResourceWithRawResponse:
return AsyncTasksResourceWithRawResponse(self._client.tasks)
+ @cached_property
+ def workflows(self) -> workflows.AsyncWorkflowsResourceWithRawResponse:
+ from .resources.workflows import AsyncWorkflowsResourceWithRawResponse
+
+ return AsyncWorkflowsResourceWithRawResponse(self._client.workflows)
+
class MobilerunWithStreamedResponse:
_client: Mobilerun
@@ -718,7 +777,6 @@ def __init__(self, client: Mobilerun) -> None:
@cached_property
def agents(self) -> agents.AgentsResourceWithStreamingResponse:
- """Agents API"""
from .resources.agents import AgentsResourceWithStreamingResponse
return AgentsResourceWithStreamingResponse(self._client.agents)
@@ -776,6 +834,12 @@ def proxies(self) -> proxies.ProxiesResourceWithStreamingResponse:
return ProxiesResourceWithStreamingResponse(self._client.proxies)
+ @cached_property
+ def connect(self) -> connect.ConnectResourceWithStreamingResponse:
+ from .resources.connect import ConnectResourceWithStreamingResponse
+
+ return ConnectResourceWithStreamingResponse(self._client.connect)
+
@cached_property
def tasks(self) -> tasks.TasksResourceWithStreamingResponse:
"""Tasks API"""
@@ -783,6 +847,12 @@ def tasks(self) -> tasks.TasksResourceWithStreamingResponse:
return TasksResourceWithStreamingResponse(self._client.tasks)
+ @cached_property
+ def workflows(self) -> workflows.WorkflowsResourceWithStreamingResponse:
+ from .resources.workflows import WorkflowsResourceWithStreamingResponse
+
+ return WorkflowsResourceWithStreamingResponse(self._client.workflows)
+
class AsyncMobilerunWithStreamedResponse:
_client: AsyncMobilerun
@@ -792,7 +862,6 @@ def __init__(self, client: AsyncMobilerun) -> None:
@cached_property
def agents(self) -> agents.AsyncAgentsResourceWithStreamingResponse:
- """Agents API"""
from .resources.agents import AsyncAgentsResourceWithStreamingResponse
return AsyncAgentsResourceWithStreamingResponse(self._client.agents)
@@ -850,6 +919,12 @@ def proxies(self) -> proxies.AsyncProxiesResourceWithStreamingResponse:
return AsyncProxiesResourceWithStreamingResponse(self._client.proxies)
+ @cached_property
+ def connect(self) -> connect.AsyncConnectResourceWithStreamingResponse:
+ from .resources.connect import AsyncConnectResourceWithStreamingResponse
+
+ return AsyncConnectResourceWithStreamingResponse(self._client.connect)
+
@cached_property
def tasks(self) -> tasks.AsyncTasksResourceWithStreamingResponse:
"""Tasks API"""
@@ -857,6 +932,12 @@ def tasks(self) -> tasks.AsyncTasksResourceWithStreamingResponse:
return AsyncTasksResourceWithStreamingResponse(self._client.tasks)
+ @cached_property
+ def workflows(self) -> workflows.AsyncWorkflowsResourceWithStreamingResponse:
+ from .resources.workflows import AsyncWorkflowsResourceWithStreamingResponse
+
+ return AsyncWorkflowsResourceWithStreamingResponse(self._client.workflows)
+
Client = Mobilerun
diff --git a/src/mobilerun_sdk/_version.py b/src/mobilerun_sdk/_version.py
index a3beadb..f6ed05f 100644
--- a/src/mobilerun_sdk/_version.py
+++ b/src/mobilerun_sdk/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "mobilerun_sdk"
-__version__ = "3.2.0" # x-release-please-version
+__version__ = "5.0.0" # x-release-please-version
diff --git a/src/mobilerun_sdk/resources/__init__.py b/src/mobilerun_sdk/resources/__init__.py
index 21f473c..c28ea9f 100644
--- a/src/mobilerun_sdk/resources/__init__.py
+++ b/src/mobilerun_sdk/resources/__init__.py
@@ -40,6 +40,14 @@
ModelsResourceWithStreamingResponse,
AsyncModelsResourceWithStreamingResponse,
)
+from .connect import (
+ ConnectResource,
+ AsyncConnectResource,
+ ConnectResourceWithRawResponse,
+ AsyncConnectResourceWithRawResponse,
+ ConnectResourceWithStreamingResponse,
+ AsyncConnectResourceWithStreamingResponse,
+)
from .devices import (
DevicesResource,
AsyncDevicesResource,
@@ -72,6 +80,14 @@
ProfilesResourceWithStreamingResponse,
AsyncProfilesResourceWithStreamingResponse,
)
+from .workflows import (
+ WorkflowsResource,
+ AsyncWorkflowsResource,
+ WorkflowsResourceWithRawResponse,
+ AsyncWorkflowsResourceWithRawResponse,
+ WorkflowsResourceWithStreamingResponse,
+ AsyncWorkflowsResourceWithStreamingResponse,
+)
from .credentials import (
CredentialsResource,
AsyncCredentialsResource,
@@ -136,10 +152,22 @@
"AsyncProxiesResourceWithRawResponse",
"ProxiesResourceWithStreamingResponse",
"AsyncProxiesResourceWithStreamingResponse",
+ "ConnectResource",
+ "AsyncConnectResource",
+ "ConnectResourceWithRawResponse",
+ "AsyncConnectResourceWithRawResponse",
+ "ConnectResourceWithStreamingResponse",
+ "AsyncConnectResourceWithStreamingResponse",
"TasksResource",
"AsyncTasksResource",
"TasksResourceWithRawResponse",
"AsyncTasksResourceWithRawResponse",
"TasksResourceWithStreamingResponse",
"AsyncTasksResourceWithStreamingResponse",
+ "WorkflowsResource",
+ "AsyncWorkflowsResource",
+ "WorkflowsResourceWithRawResponse",
+ "AsyncWorkflowsResourceWithRawResponse",
+ "WorkflowsResourceWithStreamingResponse",
+ "AsyncWorkflowsResourceWithStreamingResponse",
]
diff --git a/src/mobilerun_sdk/resources/agents/__init__.py b/src/mobilerun_sdk/resources/agents/__init__.py
new file mode 100644
index 0000000..8cd1035
--- /dev/null
+++ b/src/mobilerun_sdk/resources/agents/__init__.py
@@ -0,0 +1,47 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .chat import (
+ ChatResource,
+ AsyncChatResource,
+ ChatResourceWithRawResponse,
+ AsyncChatResourceWithRawResponse,
+ ChatResourceWithStreamingResponse,
+ AsyncChatResourceWithStreamingResponse,
+)
+from .files import (
+ FilesResource,
+ AsyncFilesResource,
+ FilesResourceWithRawResponse,
+ AsyncFilesResourceWithRawResponse,
+ FilesResourceWithStreamingResponse,
+ AsyncFilesResourceWithStreamingResponse,
+)
+from .agents import (
+ AgentsResource,
+ AsyncAgentsResource,
+ AgentsResourceWithRawResponse,
+ AsyncAgentsResourceWithRawResponse,
+ AgentsResourceWithStreamingResponse,
+ AsyncAgentsResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "ChatResource",
+ "AsyncChatResource",
+ "ChatResourceWithRawResponse",
+ "AsyncChatResourceWithRawResponse",
+ "ChatResourceWithStreamingResponse",
+ "AsyncChatResourceWithStreamingResponse",
+ "FilesResource",
+ "AsyncFilesResource",
+ "FilesResourceWithRawResponse",
+ "AsyncFilesResourceWithRawResponse",
+ "FilesResourceWithStreamingResponse",
+ "AsyncFilesResourceWithStreamingResponse",
+ "AgentsResource",
+ "AsyncAgentsResource",
+ "AgentsResourceWithRawResponse",
+ "AsyncAgentsResourceWithRawResponse",
+ "AgentsResourceWithStreamingResponse",
+ "AsyncAgentsResourceWithStreamingResponse",
+]
diff --git a/src/mobilerun_sdk/resources/agents/agents.py b/src/mobilerun_sdk/resources/agents/agents.py
new file mode 100644
index 0000000..1d6053a
--- /dev/null
+++ b/src/mobilerun_sdk/resources/agents/agents.py
@@ -0,0 +1,134 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from ..._compat import cached_property
+from .chat.chat import (
+ ChatResource,
+ AsyncChatResource,
+ ChatResourceWithRawResponse,
+ AsyncChatResourceWithRawResponse,
+ ChatResourceWithStreamingResponse,
+ AsyncChatResourceWithStreamingResponse,
+)
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from .files.files import (
+ FilesResource,
+ AsyncFilesResource,
+ FilesResourceWithRawResponse,
+ AsyncFilesResourceWithRawResponse,
+ FilesResourceWithStreamingResponse,
+ AsyncFilesResourceWithStreamingResponse,
+)
+
+__all__ = ["AgentsResource", "AsyncAgentsResource"]
+
+
+class AgentsResource(SyncAPIResource):
+ @cached_property
+ def chat(self) -> ChatResource:
+ return ChatResource(self._client)
+
+ @cached_property
+ def files(self) -> FilesResource:
+ return FilesResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AgentsResourceWithRawResponse:
+ """
+ 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 AgentsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AgentsResourceWithStreamingResponse:
+ """
+ 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 AgentsResourceWithStreamingResponse(self)
+
+
+class AsyncAgentsResource(AsyncAPIResource):
+ @cached_property
+ def chat(self) -> AsyncChatResource:
+ return AsyncChatResource(self._client)
+
+ @cached_property
+ def files(self) -> AsyncFilesResource:
+ return AsyncFilesResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncAgentsResourceWithRawResponse:
+ """
+ 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 AsyncAgentsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncAgentsResourceWithStreamingResponse:
+ """
+ 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 AsyncAgentsResourceWithStreamingResponse(self)
+
+
+class AgentsResourceWithRawResponse:
+ def __init__(self, agents: AgentsResource) -> None:
+ self._agents = agents
+
+ @cached_property
+ def chat(self) -> ChatResourceWithRawResponse:
+ return ChatResourceWithRawResponse(self._agents.chat)
+
+ @cached_property
+ def files(self) -> FilesResourceWithRawResponse:
+ return FilesResourceWithRawResponse(self._agents.files)
+
+
+class AsyncAgentsResourceWithRawResponse:
+ def __init__(self, agents: AsyncAgentsResource) -> None:
+ self._agents = agents
+
+ @cached_property
+ def chat(self) -> AsyncChatResourceWithRawResponse:
+ return AsyncChatResourceWithRawResponse(self._agents.chat)
+
+ @cached_property
+ def files(self) -> AsyncFilesResourceWithRawResponse:
+ return AsyncFilesResourceWithRawResponse(self._agents.files)
+
+
+class AgentsResourceWithStreamingResponse:
+ def __init__(self, agents: AgentsResource) -> None:
+ self._agents = agents
+
+ @cached_property
+ def chat(self) -> ChatResourceWithStreamingResponse:
+ return ChatResourceWithStreamingResponse(self._agents.chat)
+
+ @cached_property
+ def files(self) -> FilesResourceWithStreamingResponse:
+ return FilesResourceWithStreamingResponse(self._agents.files)
+
+
+class AsyncAgentsResourceWithStreamingResponse:
+ def __init__(self, agents: AsyncAgentsResource) -> None:
+ self._agents = agents
+
+ @cached_property
+ def chat(self) -> AsyncChatResourceWithStreamingResponse:
+ return AsyncChatResourceWithStreamingResponse(self._agents.chat)
+
+ @cached_property
+ def files(self) -> AsyncFilesResourceWithStreamingResponse:
+ return AsyncFilesResourceWithStreamingResponse(self._agents.files)
diff --git a/src/mobilerun_sdk/resources/agents/chat/__init__.py b/src/mobilerun_sdk/resources/agents/chat/__init__.py
new file mode 100644
index 0000000..3541671
--- /dev/null
+++ b/src/mobilerun_sdk/resources/agents/chat/__init__.py
@@ -0,0 +1,47 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .chat import (
+ ChatResource,
+ AsyncChatResource,
+ ChatResourceWithRawResponse,
+ AsyncChatResourceWithRawResponse,
+ ChatResourceWithStreamingResponse,
+ AsyncChatResourceWithStreamingResponse,
+)
+from .abort import (
+ AbortResource,
+ AsyncAbortResource,
+ AbortResourceWithRawResponse,
+ AsyncAbortResourceWithRawResponse,
+ AbortResourceWithStreamingResponse,
+ AsyncAbortResourceWithStreamingResponse,
+)
+from .question import (
+ QuestionResource,
+ AsyncQuestionResource,
+ QuestionResourceWithRawResponse,
+ AsyncQuestionResourceWithRawResponse,
+ QuestionResourceWithStreamingResponse,
+ AsyncQuestionResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "AbortResource",
+ "AsyncAbortResource",
+ "AbortResourceWithRawResponse",
+ "AsyncAbortResourceWithRawResponse",
+ "AbortResourceWithStreamingResponse",
+ "AsyncAbortResourceWithStreamingResponse",
+ "QuestionResource",
+ "AsyncQuestionResource",
+ "QuestionResourceWithRawResponse",
+ "AsyncQuestionResourceWithRawResponse",
+ "QuestionResourceWithStreamingResponse",
+ "AsyncQuestionResourceWithStreamingResponse",
+ "ChatResource",
+ "AsyncChatResource",
+ "ChatResourceWithRawResponse",
+ "AsyncChatResourceWithRawResponse",
+ "ChatResourceWithStreamingResponse",
+ "AsyncChatResourceWithStreamingResponse",
+]
diff --git a/src/mobilerun_sdk/resources/agents/chat/abort.py b/src/mobilerun_sdk/resources/agents/chat/abort.py
new file mode 100644
index 0000000..5d6829b
--- /dev/null
+++ b/src/mobilerun_sdk/resources/agents/chat/abort.py
@@ -0,0 +1,194 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import httpx
+
+from ...._types import Body, Query, Headers, NotGiven, not_given
+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.agents.chat.abort_perform_response import AbortPerformResponse
+from ....types.agents.chat.abort_force_clear_response import AbortForceClearResponse
+
+__all__ = ["AbortResource", "AsyncAbortResource"]
+
+
+class AbortResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AbortResourceWithRawResponse:
+ """
+ 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 AbortResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AbortResourceWithStreamingResponse:
+ """
+ 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 AbortResourceWithStreamingResponse(self)
+
+ def force_clear(
+ 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,
+ ) -> AbortForceClearResponse:
+ """Unconditionally clears the in-flight chat state for the caller.
+
+ Idempotent
+ escape hatch when /chat/abort cannot settle.
+ """
+ return self._post(
+ "/agents/chat/abort/force",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AbortForceClearResponse,
+ )
+
+ def perform(
+ 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,
+ ) -> AbortPerformResponse:
+ """Abort the in-flight chat turn. Idempotent."""
+ return self._post(
+ "/agents/chat/abort",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AbortPerformResponse,
+ )
+
+
+class AsyncAbortResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncAbortResourceWithRawResponse:
+ """
+ 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 AsyncAbortResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncAbortResourceWithStreamingResponse:
+ """
+ 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 AsyncAbortResourceWithStreamingResponse(self)
+
+ async def force_clear(
+ 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,
+ ) -> AbortForceClearResponse:
+ """Unconditionally clears the in-flight chat state for the caller.
+
+ Idempotent
+ escape hatch when /chat/abort cannot settle.
+ """
+ return await self._post(
+ "/agents/chat/abort/force",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AbortForceClearResponse,
+ )
+
+ async def perform(
+ 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,
+ ) -> AbortPerformResponse:
+ """Abort the in-flight chat turn. Idempotent."""
+ return await self._post(
+ "/agents/chat/abort",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AbortPerformResponse,
+ )
+
+
+class AbortResourceWithRawResponse:
+ def __init__(self, abort: AbortResource) -> None:
+ self._abort = abort
+
+ self.force_clear = to_raw_response_wrapper(
+ abort.force_clear,
+ )
+ self.perform = to_raw_response_wrapper(
+ abort.perform,
+ )
+
+
+class AsyncAbortResourceWithRawResponse:
+ def __init__(self, abort: AsyncAbortResource) -> None:
+ self._abort = abort
+
+ self.force_clear = async_to_raw_response_wrapper(
+ abort.force_clear,
+ )
+ self.perform = async_to_raw_response_wrapper(
+ abort.perform,
+ )
+
+
+class AbortResourceWithStreamingResponse:
+ def __init__(self, abort: AbortResource) -> None:
+ self._abort = abort
+
+ self.force_clear = to_streamed_response_wrapper(
+ abort.force_clear,
+ )
+ self.perform = to_streamed_response_wrapper(
+ abort.perform,
+ )
+
+
+class AsyncAbortResourceWithStreamingResponse:
+ def __init__(self, abort: AsyncAbortResource) -> None:
+ self._abort = abort
+
+ self.force_clear = async_to_streamed_response_wrapper(
+ abort.force_clear,
+ )
+ self.perform = async_to_streamed_response_wrapper(
+ abort.perform,
+ )
diff --git a/src/mobilerun_sdk/resources/agents/chat/chat.py b/src/mobilerun_sdk/resources/agents/chat/chat.py
new file mode 100644
index 0000000..ed91b94
--- /dev/null
+++ b/src/mobilerun_sdk/resources/agents/chat/chat.py
@@ -0,0 +1,406 @@
+# 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 .abort import (
+ AbortResource,
+ AsyncAbortResource,
+ AbortResourceWithRawResponse,
+ AsyncAbortResourceWithRawResponse,
+ AbortResourceWithStreamingResponse,
+ AsyncAbortResourceWithStreamingResponse,
+)
+from .question import (
+ QuestionResource,
+ AsyncQuestionResource,
+ QuestionResourceWithRawResponse,
+ AsyncQuestionResourceWithRawResponse,
+ QuestionResourceWithStreamingResponse,
+ AsyncQuestionResourceWithStreamingResponse,
+)
+from ...._types import Body, Query, Headers, NotGiven, not_given
+from ...._utils import 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.agents import chat_deliver_permission_params
+from ....types.agents.chat_get_chat_state_response import ChatGetChatStateResponse
+from ....types.agents.chat_rehydrate_chat_response import ChatRehydrateChatResponse
+from ....types.agents.chat_deliver_permission_response import ChatDeliverPermissionResponse
+from ....types.agents.chat_list_slash_commands_response import ChatListSlashCommandsResponse
+
+__all__ = ["ChatResource", "AsyncChatResource"]
+
+
+class ChatResource(SyncAPIResource):
+ @cached_property
+ def abort(self) -> AbortResource:
+ return AbortResource(self._client)
+
+ @cached_property
+ def question(self) -> QuestionResource:
+ return QuestionResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> ChatResourceWithRawResponse:
+ """
+ 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 ChatResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ChatResourceWithStreamingResponse:
+ """
+ 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 ChatResourceWithStreamingResponse(self)
+
+ def deliver_permission(
+ self,
+ *,
+ permission_id: str,
+ response: Literal["once", "always", "reject"],
+ # 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,
+ ) -> ChatDeliverPermissionResponse:
+ """
+ Deliver a HITL approval/rejection for an in-flight turn.
+
+ 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._post(
+ "/agents/chat/permission",
+ body=maybe_transform(
+ {
+ "permission_id": permission_id,
+ "response": response,
+ },
+ chat_deliver_permission_params.ChatDeliverPermissionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatDeliverPermissionResponse,
+ )
+
+ def get_chat_state(
+ 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,
+ ) -> ChatGetChatStateResponse:
+ """Advisory snapshot of in-flight activity for the caller.
+
+ Returns boolean flags
+ for an interactive chat turn, a background workflow run, and a pending graceful
+ abort. Intended for FE UI before deciding to invoke /chat/abort/force.
+ """
+ return self._get(
+ "/agents/chat/state",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatGetChatStateResponse,
+ )
+
+ def list_slash_commands(
+ 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,
+ ) -> ChatListSlashCommandsResponse:
+ """List the chat slash-command catalog."""
+ return self._get(
+ "/agents/chat/slash-commands",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatListSlashCommandsResponse,
+ )
+
+ def rehydrate_chat(
+ 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,
+ ) -> ChatRehydrateChatResponse:
+ """Rehydrate the user's chat history. Does not wake a hibernated machine."""
+ return self._get(
+ "/agents/chat/messages",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatRehydrateChatResponse,
+ )
+
+
+class AsyncChatResource(AsyncAPIResource):
+ @cached_property
+ def abort(self) -> AsyncAbortResource:
+ return AsyncAbortResource(self._client)
+
+ @cached_property
+ def question(self) -> AsyncQuestionResource:
+ return AsyncQuestionResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncChatResourceWithRawResponse:
+ """
+ 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 AsyncChatResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncChatResourceWithStreamingResponse:
+ """
+ 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 AsyncChatResourceWithStreamingResponse(self)
+
+ async def deliver_permission(
+ self,
+ *,
+ permission_id: str,
+ response: Literal["once", "always", "reject"],
+ # 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,
+ ) -> ChatDeliverPermissionResponse:
+ """
+ Deliver a HITL approval/rejection for an in-flight turn.
+
+ 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._post(
+ "/agents/chat/permission",
+ body=await async_maybe_transform(
+ {
+ "permission_id": permission_id,
+ "response": response,
+ },
+ chat_deliver_permission_params.ChatDeliverPermissionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatDeliverPermissionResponse,
+ )
+
+ async def get_chat_state(
+ 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,
+ ) -> ChatGetChatStateResponse:
+ """Advisory snapshot of in-flight activity for the caller.
+
+ Returns boolean flags
+ for an interactive chat turn, a background workflow run, and a pending graceful
+ abort. Intended for FE UI before deciding to invoke /chat/abort/force.
+ """
+ return await self._get(
+ "/agents/chat/state",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatGetChatStateResponse,
+ )
+
+ async def list_slash_commands(
+ 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,
+ ) -> ChatListSlashCommandsResponse:
+ """List the chat slash-command catalog."""
+ return await self._get(
+ "/agents/chat/slash-commands",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatListSlashCommandsResponse,
+ )
+
+ async def rehydrate_chat(
+ 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,
+ ) -> ChatRehydrateChatResponse:
+ """Rehydrate the user's chat history. Does not wake a hibernated machine."""
+ return await self._get(
+ "/agents/chat/messages",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatRehydrateChatResponse,
+ )
+
+
+class ChatResourceWithRawResponse:
+ def __init__(self, chat: ChatResource) -> None:
+ self._chat = chat
+
+ self.deliver_permission = to_raw_response_wrapper(
+ chat.deliver_permission,
+ )
+ self.get_chat_state = to_raw_response_wrapper(
+ chat.get_chat_state,
+ )
+ self.list_slash_commands = to_raw_response_wrapper(
+ chat.list_slash_commands,
+ )
+ self.rehydrate_chat = to_raw_response_wrapper(
+ chat.rehydrate_chat,
+ )
+
+ @cached_property
+ def abort(self) -> AbortResourceWithRawResponse:
+ return AbortResourceWithRawResponse(self._chat.abort)
+
+ @cached_property
+ def question(self) -> QuestionResourceWithRawResponse:
+ return QuestionResourceWithRawResponse(self._chat.question)
+
+
+class AsyncChatResourceWithRawResponse:
+ def __init__(self, chat: AsyncChatResource) -> None:
+ self._chat = chat
+
+ self.deliver_permission = async_to_raw_response_wrapper(
+ chat.deliver_permission,
+ )
+ self.get_chat_state = async_to_raw_response_wrapper(
+ chat.get_chat_state,
+ )
+ self.list_slash_commands = async_to_raw_response_wrapper(
+ chat.list_slash_commands,
+ )
+ self.rehydrate_chat = async_to_raw_response_wrapper(
+ chat.rehydrate_chat,
+ )
+
+ @cached_property
+ def abort(self) -> AsyncAbortResourceWithRawResponse:
+ return AsyncAbortResourceWithRawResponse(self._chat.abort)
+
+ @cached_property
+ def question(self) -> AsyncQuestionResourceWithRawResponse:
+ return AsyncQuestionResourceWithRawResponse(self._chat.question)
+
+
+class ChatResourceWithStreamingResponse:
+ def __init__(self, chat: ChatResource) -> None:
+ self._chat = chat
+
+ self.deliver_permission = to_streamed_response_wrapper(
+ chat.deliver_permission,
+ )
+ self.get_chat_state = to_streamed_response_wrapper(
+ chat.get_chat_state,
+ )
+ self.list_slash_commands = to_streamed_response_wrapper(
+ chat.list_slash_commands,
+ )
+ self.rehydrate_chat = to_streamed_response_wrapper(
+ chat.rehydrate_chat,
+ )
+
+ @cached_property
+ def abort(self) -> AbortResourceWithStreamingResponse:
+ return AbortResourceWithStreamingResponse(self._chat.abort)
+
+ @cached_property
+ def question(self) -> QuestionResourceWithStreamingResponse:
+ return QuestionResourceWithStreamingResponse(self._chat.question)
+
+
+class AsyncChatResourceWithStreamingResponse:
+ def __init__(self, chat: AsyncChatResource) -> None:
+ self._chat = chat
+
+ self.deliver_permission = async_to_streamed_response_wrapper(
+ chat.deliver_permission,
+ )
+ self.get_chat_state = async_to_streamed_response_wrapper(
+ chat.get_chat_state,
+ )
+ self.list_slash_commands = async_to_streamed_response_wrapper(
+ chat.list_slash_commands,
+ )
+ self.rehydrate_chat = async_to_streamed_response_wrapper(
+ chat.rehydrate_chat,
+ )
+
+ @cached_property
+ def abort(self) -> AsyncAbortResourceWithStreamingResponse:
+ return AsyncAbortResourceWithStreamingResponse(self._chat.abort)
+
+ @cached_property
+ def question(self) -> AsyncQuestionResourceWithStreamingResponse:
+ return AsyncQuestionResourceWithStreamingResponse(self._chat.question)
diff --git a/src/mobilerun_sdk/resources/agents/chat/question.py b/src/mobilerun_sdk/resources/agents/chat/question.py
new file mode 100644
index 0000000..31cd897
--- /dev/null
+++ b/src/mobilerun_sdk/resources/agents/chat/question.py
@@ -0,0 +1,264 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+
+import httpx
+
+from ...._types import Body, Query, Headers, NotGiven, not_given
+from ...._utils import 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.agents.chat import question_dismiss_params, question_deliver_answer_params
+from ....types.agents.chat.question_dismiss_response import QuestionDismissResponse
+from ....types.agents.chat.question_deliver_answer_response import QuestionDeliverAnswerResponse
+
+__all__ = ["QuestionResource", "AsyncQuestionResource"]
+
+
+class QuestionResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> QuestionResourceWithRawResponse:
+ """
+ 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 QuestionResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> QuestionResourceWithStreamingResponse:
+ """
+ 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 QuestionResourceWithStreamingResponse(self)
+
+ def deliver_answer(
+ self,
+ *,
+ answers: Iterable[Iterable[question_deliver_answer_params.Answer]],
+ question_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,
+ ) -> QuestionDeliverAnswerResponse:
+ """
+ Forward the user's answers to kilo's `/question/{id}/reply` for an in-flight
+ turn. Idempotent via the `idempotency-key` header.
+
+ 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._post(
+ "/agents/chat/question",
+ body=maybe_transform(
+ {
+ "answers": answers,
+ "question_id": question_id,
+ },
+ question_deliver_answer_params.QuestionDeliverAnswerParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=QuestionDeliverAnswerResponse,
+ )
+
+ def dismiss(
+ self,
+ *,
+ question_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,
+ ) -> QuestionDismissResponse:
+ """Forward a reject to kilo's `/question/{id}/reject`.
+
+ Already-resolved questions
+ return 200 (no-op) so multi-tab dismiss stays idempotent.
+
+ 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._post(
+ "/agents/chat/question/reject",
+ body=maybe_transform({"question_id": question_id}, question_dismiss_params.QuestionDismissParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=QuestionDismissResponse,
+ )
+
+
+class AsyncQuestionResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncQuestionResourceWithRawResponse:
+ """
+ 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 AsyncQuestionResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncQuestionResourceWithStreamingResponse:
+ """
+ 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 AsyncQuestionResourceWithStreamingResponse(self)
+
+ async def deliver_answer(
+ self,
+ *,
+ answers: Iterable[Iterable[question_deliver_answer_params.Answer]],
+ question_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,
+ ) -> QuestionDeliverAnswerResponse:
+ """
+ Forward the user's answers to kilo's `/question/{id}/reply` for an in-flight
+ turn. Idempotent via the `idempotency-key` header.
+
+ 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._post(
+ "/agents/chat/question",
+ body=await async_maybe_transform(
+ {
+ "answers": answers,
+ "question_id": question_id,
+ },
+ question_deliver_answer_params.QuestionDeliverAnswerParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=QuestionDeliverAnswerResponse,
+ )
+
+ async def dismiss(
+ self,
+ *,
+ question_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,
+ ) -> QuestionDismissResponse:
+ """Forward a reject to kilo's `/question/{id}/reject`.
+
+ Already-resolved questions
+ return 200 (no-op) so multi-tab dismiss stays idempotent.
+
+ 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._post(
+ "/agents/chat/question/reject",
+ body=await async_maybe_transform(
+ {"question_id": question_id}, question_dismiss_params.QuestionDismissParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=QuestionDismissResponse,
+ )
+
+
+class QuestionResourceWithRawResponse:
+ def __init__(self, question: QuestionResource) -> None:
+ self._question = question
+
+ self.deliver_answer = to_raw_response_wrapper(
+ question.deliver_answer,
+ )
+ self.dismiss = to_raw_response_wrapper(
+ question.dismiss,
+ )
+
+
+class AsyncQuestionResourceWithRawResponse:
+ def __init__(self, question: AsyncQuestionResource) -> None:
+ self._question = question
+
+ self.deliver_answer = async_to_raw_response_wrapper(
+ question.deliver_answer,
+ )
+ self.dismiss = async_to_raw_response_wrapper(
+ question.dismiss,
+ )
+
+
+class QuestionResourceWithStreamingResponse:
+ def __init__(self, question: QuestionResource) -> None:
+ self._question = question
+
+ self.deliver_answer = to_streamed_response_wrapper(
+ question.deliver_answer,
+ )
+ self.dismiss = to_streamed_response_wrapper(
+ question.dismiss,
+ )
+
+
+class AsyncQuestionResourceWithStreamingResponse:
+ def __init__(self, question: AsyncQuestionResource) -> None:
+ self._question = question
+
+ self.deliver_answer = async_to_streamed_response_wrapper(
+ question.deliver_answer,
+ )
+ self.dismiss = async_to_streamed_response_wrapper(
+ question.dismiss,
+ )
diff --git a/src/mobilerun_sdk/resources/agents/files/__init__.py b/src/mobilerun_sdk/resources/agents/files/__init__.py
new file mode 100644
index 0000000..6fbc8bc
--- /dev/null
+++ b/src/mobilerun_sdk/resources/agents/files/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .files import (
+ FilesResource,
+ AsyncFilesResource,
+ FilesResourceWithRawResponse,
+ AsyncFilesResourceWithRawResponse,
+ FilesResourceWithStreamingResponse,
+ AsyncFilesResourceWithStreamingResponse,
+)
+from .file_id import (
+ FileIDResource,
+ AsyncFileIDResource,
+ FileIDResourceWithRawResponse,
+ AsyncFileIDResourceWithRawResponse,
+ FileIDResourceWithStreamingResponse,
+ AsyncFileIDResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "FileIDResource",
+ "AsyncFileIDResource",
+ "FileIDResourceWithRawResponse",
+ "AsyncFileIDResourceWithRawResponse",
+ "FileIDResourceWithStreamingResponse",
+ "AsyncFileIDResourceWithStreamingResponse",
+ "FilesResource",
+ "AsyncFilesResource",
+ "FilesResourceWithRawResponse",
+ "AsyncFilesResourceWithRawResponse",
+ "FilesResourceWithStreamingResponse",
+ "AsyncFilesResourceWithStreamingResponse",
+]
diff --git a/src/mobilerun_sdk/resources/agents/files/file_id.py b/src/mobilerun_sdk/resources/agents/files/file_id.py
new file mode 100644
index 0000000..9728743
--- /dev/null
+++ b/src/mobilerun_sdk/resources/agents/files/file_id.py
@@ -0,0 +1,398 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+
+import httpx
+
+from ...._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
+from ...._utils import 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.agents.files import file_id_update_metadata_params
+from ....types.agents.files.file_id_delete_file_response import FileIDDeleteFileResponse
+from ....types.agents.files.file_id_confirm_upload_response import FileIDConfirmUploadResponse
+from ....types.agents.files.file_id_update_metadata_response import FileIDUpdateMetadataResponse
+from ....types.agents.files.file_id_cancel_pending_upload_response import FileIDCancelPendingUploadResponse
+
+__all__ = ["FileIDResource", "AsyncFileIDResource"]
+
+
+class FileIDResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> FileIDResourceWithRawResponse:
+ """
+ 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 FileIDResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> FileIDResourceWithStreamingResponse:
+ """
+ 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 FileIDResourceWithStreamingResponse(self)
+
+ def cancel_pending_upload(
+ 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,
+ ) -> FileIDCancelPendingUploadResponse:
+ """Soft-cancels an in-flight upload before confirm.
+
+ Only acts on `pending` rows —
+ refuses to touch `ready` to avoid wiping confirmed files. Idempotent:
+ `{ cancelled: false }` if the row exists but is no longer pending.
+ """
+ return self._delete(
+ "/agents/files/:fileId/pending",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FileIDCancelPendingUploadResponse,
+ )
+
+ def confirm_upload(
+ 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,
+ ) -> FileIDConfirmUploadResponse:
+ """Confirm a file upload by server-side HEAD validation"""
+ return self._post(
+ "/agents/files/:fileId/confirm",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FileIDConfirmUploadResponse,
+ )
+
+ def delete_file(
+ 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,
+ ) -> FileIDDeleteFileResponse:
+ """Hard-delete a file"""
+ return self._delete(
+ "/agents/files/:fileId",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FileIDDeleteFileResponse,
+ )
+
+ def download_file(
+ 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,
+ ) -> None:
+ """Redirect to a presigned GET URL for a file (FE owner only)"""
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return self._get(
+ "/agents/files/:fileId/download",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ def update_metadata(
+ self,
+ *,
+ 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,
+ ) -> FileIDUpdateMetadataResponse:
+ """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
+ """
+ return self._patch(
+ "/agents/files/:fileId",
+ body=maybe_transform(
+ {
+ "display_name": display_name,
+ "enabled": enabled,
+ },
+ file_id_update_metadata_params.FileIDUpdateMetadataParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FileIDUpdateMetadataResponse,
+ )
+
+
+class AsyncFileIDResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncFileIDResourceWithRawResponse:
+ """
+ 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 AsyncFileIDResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncFileIDResourceWithStreamingResponse:
+ """
+ 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 AsyncFileIDResourceWithStreamingResponse(self)
+
+ async def cancel_pending_upload(
+ 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,
+ ) -> FileIDCancelPendingUploadResponse:
+ """Soft-cancels an in-flight upload before confirm.
+
+ Only acts on `pending` rows —
+ refuses to touch `ready` to avoid wiping confirmed files. Idempotent:
+ `{ cancelled: false }` if the row exists but is no longer pending.
+ """
+ return await self._delete(
+ "/agents/files/:fileId/pending",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FileIDCancelPendingUploadResponse,
+ )
+
+ async def confirm_upload(
+ 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,
+ ) -> FileIDConfirmUploadResponse:
+ """Confirm a file upload by server-side HEAD validation"""
+ return await self._post(
+ "/agents/files/:fileId/confirm",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FileIDConfirmUploadResponse,
+ )
+
+ async def delete_file(
+ 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,
+ ) -> FileIDDeleteFileResponse:
+ """Hard-delete a file"""
+ return await self._delete(
+ "/agents/files/:fileId",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FileIDDeleteFileResponse,
+ )
+
+ async def download_file(
+ 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,
+ ) -> None:
+ """Redirect to a presigned GET URL for a file (FE owner only)"""
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return await self._get(
+ "/agents/files/:fileId/download",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+ async def update_metadata(
+ self,
+ *,
+ 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,
+ ) -> FileIDUpdateMetadataResponse:
+ """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
+ """
+ return await self._patch(
+ "/agents/files/:fileId",
+ body=await async_maybe_transform(
+ {
+ "display_name": display_name,
+ "enabled": enabled,
+ },
+ file_id_update_metadata_params.FileIDUpdateMetadataParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FileIDUpdateMetadataResponse,
+ )
+
+
+class FileIDResourceWithRawResponse:
+ def __init__(self, file_id: FileIDResource) -> None:
+ self._file_id = file_id
+
+ self.cancel_pending_upload = to_raw_response_wrapper(
+ file_id.cancel_pending_upload,
+ )
+ self.confirm_upload = to_raw_response_wrapper(
+ file_id.confirm_upload,
+ )
+ self.delete_file = to_raw_response_wrapper(
+ file_id.delete_file,
+ )
+ self.download_file = to_raw_response_wrapper(
+ file_id.download_file,
+ )
+ self.update_metadata = to_raw_response_wrapper(
+ file_id.update_metadata,
+ )
+
+
+class AsyncFileIDResourceWithRawResponse:
+ def __init__(self, file_id: AsyncFileIDResource) -> None:
+ self._file_id = file_id
+
+ self.cancel_pending_upload = async_to_raw_response_wrapper(
+ file_id.cancel_pending_upload,
+ )
+ self.confirm_upload = async_to_raw_response_wrapper(
+ file_id.confirm_upload,
+ )
+ self.delete_file = async_to_raw_response_wrapper(
+ file_id.delete_file,
+ )
+ self.download_file = async_to_raw_response_wrapper(
+ file_id.download_file,
+ )
+ self.update_metadata = async_to_raw_response_wrapper(
+ file_id.update_metadata,
+ )
+
+
+class FileIDResourceWithStreamingResponse:
+ def __init__(self, file_id: FileIDResource) -> None:
+ self._file_id = file_id
+
+ self.cancel_pending_upload = to_streamed_response_wrapper(
+ file_id.cancel_pending_upload,
+ )
+ self.confirm_upload = to_streamed_response_wrapper(
+ file_id.confirm_upload,
+ )
+ self.delete_file = to_streamed_response_wrapper(
+ file_id.delete_file,
+ )
+ self.download_file = to_streamed_response_wrapper(
+ file_id.download_file,
+ )
+ self.update_metadata = to_streamed_response_wrapper(
+ file_id.update_metadata,
+ )
+
+
+class AsyncFileIDResourceWithStreamingResponse:
+ def __init__(self, file_id: AsyncFileIDResource) -> None:
+ self._file_id = file_id
+
+ self.cancel_pending_upload = async_to_streamed_response_wrapper(
+ file_id.cancel_pending_upload,
+ )
+ self.confirm_upload = async_to_streamed_response_wrapper(
+ file_id.confirm_upload,
+ )
+ self.delete_file = async_to_streamed_response_wrapper(
+ file_id.delete_file,
+ )
+ self.download_file = async_to_streamed_response_wrapper(
+ file_id.download_file,
+ )
+ self.update_metadata = async_to_streamed_response_wrapper(
+ file_id.update_metadata,
+ )
diff --git a/src/mobilerun_sdk/resources/agents/files/files.py b/src/mobilerun_sdk/resources/agents/files/files.py
new file mode 100644
index 0000000..65e8ae0
--- /dev/null
+++ b/src/mobilerun_sdk/resources/agents/files/files.py
@@ -0,0 +1,306 @@
+# 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 .file_id import (
+ FileIDResource,
+ AsyncFileIDResource,
+ FileIDResourceWithRawResponse,
+ AsyncFileIDResourceWithRawResponse,
+ FileIDResourceWithStreamingResponse,
+ AsyncFileIDResourceWithStreamingResponse,
+)
+from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ...._utils import maybe_transform, strip_not_given, async_maybe_transform
+from ...._compat import cached_property
+from ...._resource import SyncAPIResource, AsyncAPIResource
+from ...._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ...._base_client import make_request_options
+from ....types.agents import file_list_files_params, file_mint_upload_url_params
+from ....types.agents.file_list_files_response import FileListFilesResponse
+from ....types.agents.file_mint_upload_url_response import FileMintUploadURLResponse
+
+__all__ = ["FilesResource", "AsyncFilesResource"]
+
+
+class FilesResource(SyncAPIResource):
+ @cached_property
+ def file_id(self) -> FileIDResource:
+ return FileIDResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> FilesResourceWithRawResponse:
+ """
+ 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 FilesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> FilesResourceWithStreamingResponse:
+ """
+ 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 FilesResourceWithStreamingResponse(self)
+
+ def list_files(
+ 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,
+ ) -> FileListFilesResponse:
+ """
+ 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_files_params.FileListFilesParams),
+ ),
+ cast_to=FileListFilesResponse,
+ )
+
+ def mint_upload_url(
+ self,
+ *,
+ filename: str,
+ mime_type: str,
+ size_bytes: int,
+ zone: Literal["user", "skills"] | Omit = omit,
+ 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,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> FileMintUploadURLResponse:
+ """
+ Mint a presigned PUT URL for a user file upload
+
+ 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
+ """
+ extra_headers = {**strip_not_given({"Idempotency-Key": idempotency_key}), **(extra_headers or {})}
+ return self._post(
+ "/agents/files/upload-url",
+ body=maybe_transform(
+ {
+ "filename": filename,
+ "mime_type": mime_type,
+ "size_bytes": size_bytes,
+ "zone": zone,
+ },
+ file_mint_upload_url_params.FileMintUploadURLParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FileMintUploadURLResponse,
+ )
+
+
+class AsyncFilesResource(AsyncAPIResource):
+ @cached_property
+ def file_id(self) -> AsyncFileIDResource:
+ return AsyncFileIDResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncFilesResourceWithRawResponse:
+ """
+ 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 AsyncFilesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse:
+ """
+ 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 AsyncFilesResourceWithStreamingResponse(self)
+
+ async def list_files(
+ 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,
+ ) -> FileListFilesResponse:
+ """
+ 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_files_params.FileListFilesParams),
+ ),
+ cast_to=FileListFilesResponse,
+ )
+
+ async def mint_upload_url(
+ self,
+ *,
+ filename: str,
+ mime_type: str,
+ size_bytes: int,
+ zone: Literal["user", "skills"] | Omit = omit,
+ 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,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> FileMintUploadURLResponse:
+ """
+ Mint a presigned PUT URL for a user file upload
+
+ 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
+ """
+ extra_headers = {**strip_not_given({"Idempotency-Key": idempotency_key}), **(extra_headers or {})}
+ return await self._post(
+ "/agents/files/upload-url",
+ body=await async_maybe_transform(
+ {
+ "filename": filename,
+ "mime_type": mime_type,
+ "size_bytes": size_bytes,
+ "zone": zone,
+ },
+ file_mint_upload_url_params.FileMintUploadURLParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FileMintUploadURLResponse,
+ )
+
+
+class FilesResourceWithRawResponse:
+ def __init__(self, files: FilesResource) -> None:
+ self._files = files
+
+ self.list_files = to_raw_response_wrapper(
+ files.list_files,
+ )
+ self.mint_upload_url = to_raw_response_wrapper(
+ files.mint_upload_url,
+ )
+
+ @cached_property
+ def file_id(self) -> FileIDResourceWithRawResponse:
+ return FileIDResourceWithRawResponse(self._files.file_id)
+
+
+class AsyncFilesResourceWithRawResponse:
+ def __init__(self, files: AsyncFilesResource) -> None:
+ self._files = files
+
+ self.list_files = async_to_raw_response_wrapper(
+ files.list_files,
+ )
+ self.mint_upload_url = async_to_raw_response_wrapper(
+ files.mint_upload_url,
+ )
+
+ @cached_property
+ def file_id(self) -> AsyncFileIDResourceWithRawResponse:
+ return AsyncFileIDResourceWithRawResponse(self._files.file_id)
+
+
+class FilesResourceWithStreamingResponse:
+ def __init__(self, files: FilesResource) -> None:
+ self._files = files
+
+ self.list_files = to_streamed_response_wrapper(
+ files.list_files,
+ )
+ self.mint_upload_url = to_streamed_response_wrapper(
+ files.mint_upload_url,
+ )
+
+ @cached_property
+ def file_id(self) -> FileIDResourceWithStreamingResponse:
+ return FileIDResourceWithStreamingResponse(self._files.file_id)
+
+
+class AsyncFilesResourceWithStreamingResponse:
+ def __init__(self, files: AsyncFilesResource) -> None:
+ self._files = files
+
+ self.list_files = async_to_streamed_response_wrapper(
+ files.list_files,
+ )
+ self.mint_upload_url = async_to_streamed_response_wrapper(
+ files.mint_upload_url,
+ )
+
+ @cached_property
+ def file_id(self) -> AsyncFileIDResourceWithStreamingResponse:
+ return AsyncFileIDResourceWithStreamingResponse(self._files.file_id)
diff --git a/src/mobilerun_sdk/resources/apps.py b/src/mobilerun_sdk/resources/apps.py
index 2587290..3e2bb8f 100644
--- a/src/mobilerun_sdk/resources/apps.py
+++ b/src/mobilerun_sdk/resources/apps.py
@@ -23,6 +23,7 @@
from ..types.app_delete_response import AppDeleteResponse
from ..types.app_retrieve_response import AppRetrieveResponse
from ..types.app_mark_failed_response import AppMarkFailedResponse
+from ..types.app_list_versions_response import AppListVersionsResponse
from ..types.app_confirm_upload_response import AppConfirmUploadResponse
from ..types.app_create_signed_upload_url_response import AppCreateSignedUploadURLResponse
@@ -266,6 +267,40 @@ def create_signed_upload_url(
cast_to=AppCreateSignedUploadURLResponse,
)
+ def list_versions(
+ 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,
+ ) -> AppListVersionsResponse:
+ """
+ Retrieves all versions of an app visible to the user (own uploads + system
+ versions)
+
+ 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("/apps/{id}/versions", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AppListVersionsResponse,
+ )
+
def mark_failed(
self,
id: str,
@@ -537,6 +572,40 @@ async def create_signed_upload_url(
cast_to=AppCreateSignedUploadURLResponse,
)
+ async def list_versions(
+ 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,
+ ) -> AppListVersionsResponse:
+ """
+ Retrieves all versions of an app visible to the user (own uploads + system
+ versions)
+
+ 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("/apps/{id}/versions", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AppListVersionsResponse,
+ )
+
async def mark_failed(
self,
id: str,
@@ -590,6 +659,9 @@ def __init__(self, apps: AppsResource) -> None:
self.create_signed_upload_url = to_raw_response_wrapper(
apps.create_signed_upload_url,
)
+ self.list_versions = to_raw_response_wrapper(
+ apps.list_versions,
+ )
self.mark_failed = to_raw_response_wrapper(
apps.mark_failed,
)
@@ -614,6 +686,9 @@ def __init__(self, apps: AsyncAppsResource) -> None:
self.create_signed_upload_url = async_to_raw_response_wrapper(
apps.create_signed_upload_url,
)
+ self.list_versions = async_to_raw_response_wrapper(
+ apps.list_versions,
+ )
self.mark_failed = async_to_raw_response_wrapper(
apps.mark_failed,
)
@@ -638,6 +713,9 @@ def __init__(self, apps: AppsResource) -> None:
self.create_signed_upload_url = to_streamed_response_wrapper(
apps.create_signed_upload_url,
)
+ self.list_versions = to_streamed_response_wrapper(
+ apps.list_versions,
+ )
self.mark_failed = to_streamed_response_wrapper(
apps.mark_failed,
)
@@ -662,6 +740,9 @@ def __init__(self, apps: AsyncAppsResource) -> None:
self.create_signed_upload_url = async_to_streamed_response_wrapper(
apps.create_signed_upload_url,
)
+ self.list_versions = async_to_streamed_response_wrapper(
+ apps.list_versions,
+ )
self.mark_failed = async_to_streamed_response_wrapper(
apps.mark_failed,
)
diff --git a/src/mobilerun_sdk/resources/connect/__init__.py b/src/mobilerun_sdk/resources/connect/__init__.py
new file mode 100644
index 0000000..65fca6b
--- /dev/null
+++ b/src/mobilerun_sdk/resources/connect/__init__.py
@@ -0,0 +1,61 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .users import (
+ UsersResource,
+ AsyncUsersResource,
+ UsersResourceWithRawResponse,
+ AsyncUsersResourceWithRawResponse,
+ UsersResourceWithStreamingResponse,
+ AsyncUsersResourceWithStreamingResponse,
+)
+from .connect import (
+ ConnectResource,
+ AsyncConnectResource,
+ ConnectResourceWithRawResponse,
+ AsyncConnectResourceWithRawResponse,
+ ConnectResourceWithStreamingResponse,
+ AsyncConnectResourceWithStreamingResponse,
+)
+from .proxies import (
+ ProxiesResource,
+ AsyncProxiesResource,
+ ProxiesResourceWithRawResponse,
+ AsyncProxiesResourceWithRawResponse,
+ ProxiesResourceWithStreamingResponse,
+ AsyncProxiesResourceWithStreamingResponse,
+)
+from .countries import (
+ CountriesResource,
+ AsyncCountriesResource,
+ CountriesResourceWithRawResponse,
+ AsyncCountriesResourceWithRawResponse,
+ CountriesResourceWithStreamingResponse,
+ AsyncCountriesResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "CountriesResource",
+ "AsyncCountriesResource",
+ "CountriesResourceWithRawResponse",
+ "AsyncCountriesResourceWithRawResponse",
+ "CountriesResourceWithStreamingResponse",
+ "AsyncCountriesResourceWithStreamingResponse",
+ "ProxiesResource",
+ "AsyncProxiesResource",
+ "ProxiesResourceWithRawResponse",
+ "AsyncProxiesResourceWithRawResponse",
+ "ProxiesResourceWithStreamingResponse",
+ "AsyncProxiesResourceWithStreamingResponse",
+ "UsersResource",
+ "AsyncUsersResource",
+ "UsersResourceWithRawResponse",
+ "AsyncUsersResourceWithRawResponse",
+ "UsersResourceWithStreamingResponse",
+ "AsyncUsersResourceWithStreamingResponse",
+ "ConnectResource",
+ "AsyncConnectResource",
+ "ConnectResourceWithRawResponse",
+ "AsyncConnectResourceWithRawResponse",
+ "ConnectResourceWithStreamingResponse",
+ "AsyncConnectResourceWithStreamingResponse",
+]
diff --git a/src/mobilerun_sdk/resources/connect/connect.py b/src/mobilerun_sdk/resources/connect/connect.py
new file mode 100644
index 0000000..67c2d65
--- /dev/null
+++ b/src/mobilerun_sdk/resources/connect/connect.py
@@ -0,0 +1,166 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .users import (
+ UsersResource,
+ AsyncUsersResource,
+ UsersResourceWithRawResponse,
+ AsyncUsersResourceWithRawResponse,
+ UsersResourceWithStreamingResponse,
+ AsyncUsersResourceWithStreamingResponse,
+)
+from .proxies import (
+ ProxiesResource,
+ AsyncProxiesResource,
+ ProxiesResourceWithRawResponse,
+ AsyncProxiesResourceWithRawResponse,
+ ProxiesResourceWithStreamingResponse,
+ AsyncProxiesResourceWithStreamingResponse,
+)
+from ..._compat import cached_property
+from .countries import (
+ CountriesResource,
+ AsyncCountriesResource,
+ CountriesResourceWithRawResponse,
+ AsyncCountriesResourceWithRawResponse,
+ CountriesResourceWithStreamingResponse,
+ AsyncCountriesResourceWithStreamingResponse,
+)
+from ..._resource import SyncAPIResource, AsyncAPIResource
+
+__all__ = ["ConnectResource", "AsyncConnectResource"]
+
+
+class ConnectResource(SyncAPIResource):
+ @cached_property
+ def countries(self) -> CountriesResource:
+ return CountriesResource(self._client)
+
+ @cached_property
+ def proxies(self) -> ProxiesResource:
+ return ProxiesResource(self._client)
+
+ @cached_property
+ def users(self) -> UsersResource:
+ return UsersResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> ConnectResourceWithRawResponse:
+ """
+ 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 ConnectResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ConnectResourceWithStreamingResponse:
+ """
+ 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 ConnectResourceWithStreamingResponse(self)
+
+
+class AsyncConnectResource(AsyncAPIResource):
+ @cached_property
+ def countries(self) -> AsyncCountriesResource:
+ return AsyncCountriesResource(self._client)
+
+ @cached_property
+ def proxies(self) -> AsyncProxiesResource:
+ return AsyncProxiesResource(self._client)
+
+ @cached_property
+ def users(self) -> AsyncUsersResource:
+ return AsyncUsersResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncConnectResourceWithRawResponse:
+ """
+ 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 AsyncConnectResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncConnectResourceWithStreamingResponse:
+ """
+ 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 AsyncConnectResourceWithStreamingResponse(self)
+
+
+class ConnectResourceWithRawResponse:
+ def __init__(self, connect: ConnectResource) -> None:
+ self._connect = connect
+
+ @cached_property
+ def countries(self) -> CountriesResourceWithRawResponse:
+ return CountriesResourceWithRawResponse(self._connect.countries)
+
+ @cached_property
+ def proxies(self) -> ProxiesResourceWithRawResponse:
+ return ProxiesResourceWithRawResponse(self._connect.proxies)
+
+ @cached_property
+ def users(self) -> UsersResourceWithRawResponse:
+ return UsersResourceWithRawResponse(self._connect.users)
+
+
+class AsyncConnectResourceWithRawResponse:
+ def __init__(self, connect: AsyncConnectResource) -> None:
+ self._connect = connect
+
+ @cached_property
+ def countries(self) -> AsyncCountriesResourceWithRawResponse:
+ return AsyncCountriesResourceWithRawResponse(self._connect.countries)
+
+ @cached_property
+ def proxies(self) -> AsyncProxiesResourceWithRawResponse:
+ return AsyncProxiesResourceWithRawResponse(self._connect.proxies)
+
+ @cached_property
+ def users(self) -> AsyncUsersResourceWithRawResponse:
+ return AsyncUsersResourceWithRawResponse(self._connect.users)
+
+
+class ConnectResourceWithStreamingResponse:
+ def __init__(self, connect: ConnectResource) -> None:
+ self._connect = connect
+
+ @cached_property
+ def countries(self) -> CountriesResourceWithStreamingResponse:
+ return CountriesResourceWithStreamingResponse(self._connect.countries)
+
+ @cached_property
+ def proxies(self) -> ProxiesResourceWithStreamingResponse:
+ return ProxiesResourceWithStreamingResponse(self._connect.proxies)
+
+ @cached_property
+ def users(self) -> UsersResourceWithStreamingResponse:
+ return UsersResourceWithStreamingResponse(self._connect.users)
+
+
+class AsyncConnectResourceWithStreamingResponse:
+ def __init__(self, connect: AsyncConnectResource) -> None:
+ self._connect = connect
+
+ @cached_property
+ def countries(self) -> AsyncCountriesResourceWithStreamingResponse:
+ return AsyncCountriesResourceWithStreamingResponse(self._connect.countries)
+
+ @cached_property
+ def proxies(self) -> AsyncProxiesResourceWithStreamingResponse:
+ return AsyncProxiesResourceWithStreamingResponse(self._connect.proxies)
+
+ @cached_property
+ def users(self) -> AsyncUsersResourceWithStreamingResponse:
+ return AsyncUsersResourceWithStreamingResponse(self._connect.users)
diff --git a/src/mobilerun_sdk/resources/connect/countries.py b/src/mobilerun_sdk/resources/connect/countries.py
new file mode 100644
index 0000000..d6d0bf0
--- /dev/null
+++ b/src/mobilerun_sdk/resources/connect/countries.py
@@ -0,0 +1,201 @@
+# 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 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.connect import country_list_params
+from ...types.connect.country_list_response import CountryListResponse
+
+__all__ = ["CountriesResource", "AsyncCountriesResource"]
+
+
+class CountriesResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> CountriesResourceWithRawResponse:
+ """
+ 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 CountriesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> CountriesResourceWithStreamingResponse:
+ """
+ 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 CountriesResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ type: Literal["residential"] | 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,
+ ) -> CountryListResponse:
+ """
+ Lookup of countries that can be selected when creating a proxy.
+
+ Args:
+ page: Page number (1-based).
+
+ page_size: Number of items per page.
+
+ type: Filter to countries offering this proxy type.
+
+ 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(
+ "/connect/countries",
+ 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,
+ "type": type,
+ },
+ country_list_params.CountryListParams,
+ ),
+ ),
+ cast_to=CountryListResponse,
+ )
+
+
+class AsyncCountriesResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncCountriesResourceWithRawResponse:
+ """
+ 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 AsyncCountriesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncCountriesResourceWithStreamingResponse:
+ """
+ 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 AsyncCountriesResourceWithStreamingResponse(self)
+
+ async def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ type: Literal["residential"] | 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,
+ ) -> CountryListResponse:
+ """
+ Lookup of countries that can be selected when creating a proxy.
+
+ Args:
+ page: Page number (1-based).
+
+ page_size: Number of items per page.
+
+ type: Filter to countries offering this proxy type.
+
+ 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(
+ "/connect/countries",
+ 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,
+ "type": type,
+ },
+ country_list_params.CountryListParams,
+ ),
+ ),
+ cast_to=CountryListResponse,
+ )
+
+
+class CountriesResourceWithRawResponse:
+ def __init__(self, countries: CountriesResource) -> None:
+ self._countries = countries
+
+ self.list = to_raw_response_wrapper(
+ countries.list,
+ )
+
+
+class AsyncCountriesResourceWithRawResponse:
+ def __init__(self, countries: AsyncCountriesResource) -> None:
+ self._countries = countries
+
+ self.list = async_to_raw_response_wrapper(
+ countries.list,
+ )
+
+
+class CountriesResourceWithStreamingResponse:
+ def __init__(self, countries: CountriesResource) -> None:
+ self._countries = countries
+
+ self.list = to_streamed_response_wrapper(
+ countries.list,
+ )
+
+
+class AsyncCountriesResourceWithStreamingResponse:
+ def __init__(self, countries: AsyncCountriesResource) -> None:
+ self._countries = countries
+
+ self.list = async_to_streamed_response_wrapper(
+ countries.list,
+ )
diff --git a/src/mobilerun_sdk/resources/connect/proxies.py b/src/mobilerun_sdk/resources/connect/proxies.py
new file mode 100644
index 0000000..48d5db0
--- /dev/null
+++ b/src/mobilerun_sdk/resources/connect/proxies.py
@@ -0,0 +1,849 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from datetime import datetime
+from typing_extensions import Literal
+
+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 ..._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.connect import proxy_buy_params, proxy_list_params, proxy_list_connections_params
+from ...types.connect.proxy_buy_response import ProxyBuyResponse
+from ...types.connect.proxy_list_response import ProxyListResponse
+from ...types.connect.proxy_ping_response import ProxyPingResponse
+from ...types.connect.proxy_retrieve_response import ProxyRetrieveResponse
+from ...types.connect.proxy_list_connections_response import ProxyListConnectionsResponse
+
+__all__ = ["ProxiesResource", "AsyncProxiesResource"]
+
+
+class ProxiesResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ProxiesResourceWithRawResponse:
+ """
+ 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 ProxiesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ProxiesResourceWithStreamingResponse:
+ """
+ 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 ProxiesResourceWithStreamingResponse(self)
+
+ 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,
+ ) -> ProxyRetrieveResponse:
+ """
+ Get a proxy by ID, including its password
+
+ 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("/connect/proxies/{id}", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ProxyRetrieveResponse,
+ )
+
+ def list(
+ self,
+ *,
+ country: str | Omit = omit,
+ 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,
+ ) -> ProxyListResponse:
+ """
+ Returns proxies owned by the user identified by the X-User-ID header.
+ Credentials are omitted from the list.
+
+ Args:
+ country: Filter to proxies in this country (ISO 3166-1 alpha-2, lowercase).
+
+ page: Page number (1-based).
+
+ page_size: Number of items per page.
+
+ 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(
+ "/connect/proxies",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "country": country,
+ "page": page,
+ "page_size": page_size,
+ },
+ proxy_list_params.ProxyListParams,
+ ),
+ ),
+ cast_to=ProxyListResponse,
+ )
+
+ def buy(
+ self,
+ *,
+ country: str,
+ type: Literal["residential"] | 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,
+ ) -> ProxyBuyResponse:
+ """
+ Provisions a proxy for the caller in the selected country.
+
+ Args:
+ country: ISO 3166-1 alpha-2 country code to provision the proxy in.
+
+ 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(
+ "/connect/proxies",
+ body=maybe_transform(
+ {
+ "country": country,
+ "type": type,
+ },
+ proxy_buy_params.ProxyBuyParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ProxyBuyResponse,
+ )
+
+ def cancel(
+ 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:
+ """
+ Delete a proxy
+
+ 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("/connect/proxies/{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 list_connections(
+ self,
+ id: str,
+ *,
+ close_reason: str | Omit = omit,
+ country: str | Omit = omit,
+ dst_host: str | Omit = omit,
+ dst_port: int | Omit = omit,
+ ended_after: Union[str, datetime] | Omit = omit,
+ ended_before: Union[str, datetime] | Omit = omit,
+ max_bytes_in: int | Omit = omit,
+ max_bytes_out: int | Omit = omit,
+ max_duration_ms: int | Omit = omit,
+ max_total_bytes: int | Omit = omit,
+ min_bytes_in: int | Omit = omit,
+ min_bytes_out: int | Omit = omit,
+ min_duration_ms: int | Omit = omit,
+ min_total_bytes: int | Omit = omit,
+ order: Literal["asc", "desc"] | Omit = omit,
+ order_by: Literal["startedAt", "endedAt", "bytesIn", "bytesOut", "totalBytes", "durationMs"] | Omit = omit,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ protocol: Literal["tcp", "udp", "unknown"] | Omit = omit,
+ provider: str | Omit = omit,
+ session_id: str | Omit = omit,
+ started_after: Union[str, datetime] | Omit = omit,
+ started_before: Union[str, datetime] | Omit = omit,
+ status: Literal["active", "closed"] | Omit = omit,
+ user_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,
+ ) -> ProxyListConnectionsResponse:
+ """
+ Returns the connection history recorded for this proxy, one item per connection
+ (aggregated across the connection's lifetime). Supports filtering on every
+ property plus ordering and pagination. Returns 503 when the connection-insights
+ backend is disabled or unreachable.
+
+ Args:
+ close_reason: Filter to connections that closed with this reason (closed connections only).
+
+ country: Filter to connections served from this upstream country (ISO 3166-1 alpha-2).
+
+ dst_host: Filter to connections to this destination host (exact match).
+
+ dst_port: Filter to connections to this destination port.
+
+ ended_after: Filter to connections whose last activity was at or after this time (inclusive).
+
+ ended_before: Filter to connections whose last activity was at or before this time
+ (inclusive).
+
+ max_bytes_in: Filter to connections with at most this many bytes received from upstream.
+
+ max_bytes_out: Filter to connections with at most this many bytes sent to upstream.
+
+ max_duration_ms: Filter to connections lasting at most this many milliseconds.
+
+ max_total_bytes: Filter to connections with at most this much total traffic (bytesIn + bytesOut).
+
+ min_bytes_in: Filter to connections with at least this many bytes received from upstream.
+
+ min_bytes_out: Filter to connections with at least this many bytes sent to upstream.
+
+ min_duration_ms: Filter to connections lasting at least this many milliseconds.
+
+ min_total_bytes: Filter to connections with at least this much total traffic (bytesIn +
+ bytesOut).
+
+ order: Sort direction.
+
+ order_by: Property to order the results by.
+
+ page: Page number (1-based).
+
+ page_size: Number of items per page.
+
+ protocol: Filter to connections of this transport protocol.
+
+ provider: Filter to connections served by this upstream provider.
+
+ session_id: Filter to a single connection by its session id.
+
+ started_after: Filter to connections that started at or after this time (inclusive).
+
+ started_before: Filter to connections that started at or before this time (inclusive).
+
+ status: Filter by connection status.
+
+ user_id: Filter to connections made by this user.
+
+ 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("/connect/proxies/{id}/connections", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "close_reason": close_reason,
+ "country": country,
+ "dst_host": dst_host,
+ "dst_port": dst_port,
+ "ended_after": ended_after,
+ "ended_before": ended_before,
+ "max_bytes_in": max_bytes_in,
+ "max_bytes_out": max_bytes_out,
+ "max_duration_ms": max_duration_ms,
+ "max_total_bytes": max_total_bytes,
+ "min_bytes_in": min_bytes_in,
+ "min_bytes_out": min_bytes_out,
+ "min_duration_ms": min_duration_ms,
+ "min_total_bytes": min_total_bytes,
+ "order": order,
+ "order_by": order_by,
+ "page": page,
+ "page_size": page_size,
+ "protocol": protocol,
+ "provider": provider,
+ "session_id": session_id,
+ "started_after": started_after,
+ "started_before": started_before,
+ "status": status,
+ "user_id": user_id,
+ },
+ proxy_list_connections_params.ProxyListConnectionsParams,
+ ),
+ ),
+ cast_to=ProxyListConnectionsResponse,
+ )
+
+ def ping(
+ 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,
+ ) -> ProxyPingResponse:
+ """
+ Returns the most recent cached network-latency measurement for the proxy,
+ sampled periodically by connecting through the proxy to a fixed target.
+ `latency` is null when no measurement is available yet (e.g. the proxy is not
+ active, or it has not been sampled since coming online).
+
+ 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("/connect/proxies/{id}/ping", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ProxyPingResponse,
+ )
+
+
+class AsyncProxiesResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncProxiesResourceWithRawResponse:
+ """
+ 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 AsyncProxiesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncProxiesResourceWithStreamingResponse:
+ """
+ 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 AsyncProxiesResourceWithStreamingResponse(self)
+
+ 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,
+ ) -> ProxyRetrieveResponse:
+ """
+ Get a proxy by ID, including its password
+
+ 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("/connect/proxies/{id}", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ProxyRetrieveResponse,
+ )
+
+ async def list(
+ self,
+ *,
+ country: str | Omit = omit,
+ 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,
+ ) -> ProxyListResponse:
+ """
+ Returns proxies owned by the user identified by the X-User-ID header.
+ Credentials are omitted from the list.
+
+ Args:
+ country: Filter to proxies in this country (ISO 3166-1 alpha-2, lowercase).
+
+ page: Page number (1-based).
+
+ page_size: Number of items per page.
+
+ 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(
+ "/connect/proxies",
+ 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,
+ "page": page,
+ "page_size": page_size,
+ },
+ proxy_list_params.ProxyListParams,
+ ),
+ ),
+ cast_to=ProxyListResponse,
+ )
+
+ async def buy(
+ self,
+ *,
+ country: str,
+ type: Literal["residential"] | 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,
+ ) -> ProxyBuyResponse:
+ """
+ Provisions a proxy for the caller in the selected country.
+
+ Args:
+ country: ISO 3166-1 alpha-2 country code to provision the proxy in.
+
+ 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(
+ "/connect/proxies",
+ body=await async_maybe_transform(
+ {
+ "country": country,
+ "type": type,
+ },
+ proxy_buy_params.ProxyBuyParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ProxyBuyResponse,
+ )
+
+ async def cancel(
+ 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:
+ """
+ Delete a proxy
+
+ 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("/connect/proxies/{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 list_connections(
+ self,
+ id: str,
+ *,
+ close_reason: str | Omit = omit,
+ country: str | Omit = omit,
+ dst_host: str | Omit = omit,
+ dst_port: int | Omit = omit,
+ ended_after: Union[str, datetime] | Omit = omit,
+ ended_before: Union[str, datetime] | Omit = omit,
+ max_bytes_in: int | Omit = omit,
+ max_bytes_out: int | Omit = omit,
+ max_duration_ms: int | Omit = omit,
+ max_total_bytes: int | Omit = omit,
+ min_bytes_in: int | Omit = omit,
+ min_bytes_out: int | Omit = omit,
+ min_duration_ms: int | Omit = omit,
+ min_total_bytes: int | Omit = omit,
+ order: Literal["asc", "desc"] | Omit = omit,
+ order_by: Literal["startedAt", "endedAt", "bytesIn", "bytesOut", "totalBytes", "durationMs"] | Omit = omit,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ protocol: Literal["tcp", "udp", "unknown"] | Omit = omit,
+ provider: str | Omit = omit,
+ session_id: str | Omit = omit,
+ started_after: Union[str, datetime] | Omit = omit,
+ started_before: Union[str, datetime] | Omit = omit,
+ status: Literal["active", "closed"] | Omit = omit,
+ user_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,
+ ) -> ProxyListConnectionsResponse:
+ """
+ Returns the connection history recorded for this proxy, one item per connection
+ (aggregated across the connection's lifetime). Supports filtering on every
+ property plus ordering and pagination. Returns 503 when the connection-insights
+ backend is disabled or unreachable.
+
+ Args:
+ close_reason: Filter to connections that closed with this reason (closed connections only).
+
+ country: Filter to connections served from this upstream country (ISO 3166-1 alpha-2).
+
+ dst_host: Filter to connections to this destination host (exact match).
+
+ dst_port: Filter to connections to this destination port.
+
+ ended_after: Filter to connections whose last activity was at or after this time (inclusive).
+
+ ended_before: Filter to connections whose last activity was at or before this time
+ (inclusive).
+
+ max_bytes_in: Filter to connections with at most this many bytes received from upstream.
+
+ max_bytes_out: Filter to connections with at most this many bytes sent to upstream.
+
+ max_duration_ms: Filter to connections lasting at most this many milliseconds.
+
+ max_total_bytes: Filter to connections with at most this much total traffic (bytesIn + bytesOut).
+
+ min_bytes_in: Filter to connections with at least this many bytes received from upstream.
+
+ min_bytes_out: Filter to connections with at least this many bytes sent to upstream.
+
+ min_duration_ms: Filter to connections lasting at least this many milliseconds.
+
+ min_total_bytes: Filter to connections with at least this much total traffic (bytesIn +
+ bytesOut).
+
+ order: Sort direction.
+
+ order_by: Property to order the results by.
+
+ page: Page number (1-based).
+
+ page_size: Number of items per page.
+
+ protocol: Filter to connections of this transport protocol.
+
+ provider: Filter to connections served by this upstream provider.
+
+ session_id: Filter to a single connection by its session id.
+
+ started_after: Filter to connections that started at or after this time (inclusive).
+
+ started_before: Filter to connections that started at or before this time (inclusive).
+
+ status: Filter by connection status.
+
+ user_id: Filter to connections made by this user.
+
+ 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("/connect/proxies/{id}/connections", 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(
+ {
+ "close_reason": close_reason,
+ "country": country,
+ "dst_host": dst_host,
+ "dst_port": dst_port,
+ "ended_after": ended_after,
+ "ended_before": ended_before,
+ "max_bytes_in": max_bytes_in,
+ "max_bytes_out": max_bytes_out,
+ "max_duration_ms": max_duration_ms,
+ "max_total_bytes": max_total_bytes,
+ "min_bytes_in": min_bytes_in,
+ "min_bytes_out": min_bytes_out,
+ "min_duration_ms": min_duration_ms,
+ "min_total_bytes": min_total_bytes,
+ "order": order,
+ "order_by": order_by,
+ "page": page,
+ "page_size": page_size,
+ "protocol": protocol,
+ "provider": provider,
+ "session_id": session_id,
+ "started_after": started_after,
+ "started_before": started_before,
+ "status": status,
+ "user_id": user_id,
+ },
+ proxy_list_connections_params.ProxyListConnectionsParams,
+ ),
+ ),
+ cast_to=ProxyListConnectionsResponse,
+ )
+
+ async def ping(
+ 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,
+ ) -> ProxyPingResponse:
+ """
+ Returns the most recent cached network-latency measurement for the proxy,
+ sampled periodically by connecting through the proxy to a fixed target.
+ `latency` is null when no measurement is available yet (e.g. the proxy is not
+ active, or it has not been sampled since coming online).
+
+ 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("/connect/proxies/{id}/ping", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ProxyPingResponse,
+ )
+
+
+class ProxiesResourceWithRawResponse:
+ def __init__(self, proxies: ProxiesResource) -> None:
+ self._proxies = proxies
+
+ self.retrieve = to_raw_response_wrapper(
+ proxies.retrieve,
+ )
+ self.list = to_raw_response_wrapper(
+ proxies.list,
+ )
+ self.buy = to_raw_response_wrapper(
+ proxies.buy,
+ )
+ self.cancel = to_raw_response_wrapper(
+ proxies.cancel,
+ )
+ self.list_connections = to_raw_response_wrapper(
+ proxies.list_connections,
+ )
+ self.ping = to_raw_response_wrapper(
+ proxies.ping,
+ )
+
+
+class AsyncProxiesResourceWithRawResponse:
+ def __init__(self, proxies: AsyncProxiesResource) -> None:
+ self._proxies = proxies
+
+ self.retrieve = async_to_raw_response_wrapper(
+ proxies.retrieve,
+ )
+ self.list = async_to_raw_response_wrapper(
+ proxies.list,
+ )
+ self.buy = async_to_raw_response_wrapper(
+ proxies.buy,
+ )
+ self.cancel = async_to_raw_response_wrapper(
+ proxies.cancel,
+ )
+ self.list_connections = async_to_raw_response_wrapper(
+ proxies.list_connections,
+ )
+ self.ping = async_to_raw_response_wrapper(
+ proxies.ping,
+ )
+
+
+class ProxiesResourceWithStreamingResponse:
+ def __init__(self, proxies: ProxiesResource) -> None:
+ self._proxies = proxies
+
+ self.retrieve = to_streamed_response_wrapper(
+ proxies.retrieve,
+ )
+ self.list = to_streamed_response_wrapper(
+ proxies.list,
+ )
+ self.buy = to_streamed_response_wrapper(
+ proxies.buy,
+ )
+ self.cancel = to_streamed_response_wrapper(
+ proxies.cancel,
+ )
+ self.list_connections = to_streamed_response_wrapper(
+ proxies.list_connections,
+ )
+ self.ping = to_streamed_response_wrapper(
+ proxies.ping,
+ )
+
+
+class AsyncProxiesResourceWithStreamingResponse:
+ def __init__(self, proxies: AsyncProxiesResource) -> None:
+ self._proxies = proxies
+
+ self.retrieve = async_to_streamed_response_wrapper(
+ proxies.retrieve,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ proxies.list,
+ )
+ self.buy = async_to_streamed_response_wrapper(
+ proxies.buy,
+ )
+ self.cancel = async_to_streamed_response_wrapper(
+ proxies.cancel,
+ )
+ self.list_connections = async_to_streamed_response_wrapper(
+ proxies.list_connections,
+ )
+ self.ping = async_to_streamed_response_wrapper(
+ proxies.ping,
+ )
diff --git a/src/mobilerun_sdk/resources/connect/users.py b/src/mobilerun_sdk/resources/connect/users.py
new file mode 100644
index 0000000..9f7fa63
--- /dev/null
+++ b/src/mobilerun_sdk/resources/connect/users.py
@@ -0,0 +1,869 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+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 ..._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.connect import user_list_params, user_create_params, user_update_params, user_list_connections_params
+from ...types.connect.user_list_response import UserListResponse
+from ...types.connect.user_create_response import UserCreateResponse
+from ...types.connect.user_update_response import UserUpdateResponse
+from ...types.connect.user_retrieve_response import UserRetrieveResponse
+from ...types.connect.user_list_connections_response import UserListConnectionsResponse
+
+__all__ = ["UsersResource", "AsyncUsersResource"]
+
+
+class UsersResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> UsersResourceWithRawResponse:
+ """
+ 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 UsersResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> UsersResourceWithStreamingResponse:
+ """
+ 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 UsersResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ password: str | Omit = omit,
+ proxy_id: str | Omit = omit,
+ username: 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,
+ ) -> UserCreateResponse:
+ """
+ Creates a SOCKS5 credential, optionally bound to a proxy for dedicated routing.
+ Username and password are generated when omitted.
+
+ Args:
+ password: Desired SOCKS5 password, 1-255 bytes (RFC 1929). Generated when omitted.
+
+ proxy_id: Proxy to bind the user to for dedicated routing.
+
+ username: Desired SOCKS5 username, 1-255 bytes (RFC 1929). Generated when omitted.
+
+ 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(
+ "/connect/users",
+ body=maybe_transform(
+ {
+ "password": password,
+ "proxy_id": proxy_id,
+ "username": username,
+ },
+ user_create_params.UserCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=UserCreateResponse,
+ )
+
+ 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,
+ ) -> UserRetrieveResponse:
+ """
+ Get a SOCKS5 user by ID, including its password
+
+ 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("/connect/users/{id}", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=UserRetrieveResponse,
+ )
+
+ def update(
+ self,
+ id: str,
+ *,
+ proxy_id: 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,
+ ) -> UserUpdateResponse:
+ """
+ Rebind the user to a different proxy (or detach it by passing null).
+
+ Args:
+ proxy_id: Proxy to rebind to, or null to detach. Omit to leave the user's current binding
+ unchanged — only an explicit null detaches.
+
+ 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("/connect/users/{id}", id=id),
+ body=maybe_transform({"proxy_id": proxy_id}, user_update_params.UserUpdateParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=UserUpdateResponse,
+ )
+
+ def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ proxy_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,
+ ) -> UserListResponse:
+ """Returns SOCKS5 users owned by the caller.
+
+ Passwords are omitted from the list.
+
+ Args:
+ page: Page number (1-based).
+
+ page_size: Number of items per page.
+
+ proxy_id: Filter to users bound to this proxy. Users not bound to it (including unbound
+ users) are excluded.
+
+ 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(
+ "/connect/users",
+ 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,
+ "proxy_id": proxy_id,
+ },
+ user_list_params.UserListParams,
+ ),
+ ),
+ cast_to=UserListResponse,
+ )
+
+ 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:
+ """
+ Delete a SOCKS5 user
+
+ 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("/connect/users/{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 list_connections(
+ self,
+ id: str,
+ *,
+ close_reason: str | Omit = omit,
+ country: str | Omit = omit,
+ dst_host: str | Omit = omit,
+ dst_port: int | Omit = omit,
+ ended_after: Union[str, datetime] | Omit = omit,
+ ended_before: Union[str, datetime] | Omit = omit,
+ max_bytes_in: int | Omit = omit,
+ max_bytes_out: int | Omit = omit,
+ max_duration_ms: int | Omit = omit,
+ max_total_bytes: int | Omit = omit,
+ min_bytes_in: int | Omit = omit,
+ min_bytes_out: int | Omit = omit,
+ min_duration_ms: int | Omit = omit,
+ min_total_bytes: int | Omit = omit,
+ order: Literal["asc", "desc"] | Omit = omit,
+ order_by: Literal["startedAt", "endedAt", "bytesIn", "bytesOut", "totalBytes", "durationMs"] | Omit = omit,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ protocol: Literal["tcp", "udp", "unknown"] | Omit = omit,
+ provider: str | Omit = omit,
+ proxy_id: str | Omit = omit,
+ session_id: str | Omit = omit,
+ started_after: Union[str, datetime] | Omit = omit,
+ started_before: Union[str, datetime] | Omit = omit,
+ status: Literal["active", "closed"] | 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,
+ ) -> UserListConnectionsResponse:
+ """
+ Returns the connection history recorded for this user, one item per connection
+ (aggregated across the connection's lifetime). Supports filtering on every
+ property plus ordering and pagination. Returns 503 when the connection-insights
+ backend is disabled or unreachable.
+
+ Args:
+ close_reason: Filter to connections that closed with this reason (closed connections only).
+
+ country: Filter to connections served from this upstream country (ISO 3166-1 alpha-2).
+
+ dst_host: Filter to connections to this destination host (exact match).
+
+ dst_port: Filter to connections to this destination port.
+
+ ended_after: Filter to connections whose last activity was at or after this time (inclusive).
+
+ ended_before: Filter to connections whose last activity was at or before this time
+ (inclusive).
+
+ max_bytes_in: Filter to connections with at most this many bytes received from upstream.
+
+ max_bytes_out: Filter to connections with at most this many bytes sent to upstream.
+
+ max_duration_ms: Filter to connections lasting at most this many milliseconds.
+
+ max_total_bytes: Filter to connections with at most this much total traffic (bytesIn + bytesOut).
+
+ min_bytes_in: Filter to connections with at least this many bytes received from upstream.
+
+ min_bytes_out: Filter to connections with at least this many bytes sent to upstream.
+
+ min_duration_ms: Filter to connections lasting at least this many milliseconds.
+
+ min_total_bytes: Filter to connections with at least this much total traffic (bytesIn +
+ bytesOut).
+
+ order: Sort direction.
+
+ order_by: Property to order the results by.
+
+ page: Page number (1-based).
+
+ page_size: Number of items per page.
+
+ protocol: Filter to connections of this transport protocol.
+
+ provider: Filter to connections served by this upstream provider.
+
+ proxy_id: Filter to connections routed through this proxy.
+
+ session_id: Filter to a single connection by its session id.
+
+ started_after: Filter to connections that started at or after this time (inclusive).
+
+ started_before: Filter to connections that started at or before this time (inclusive).
+
+ status: Filter by connection status.
+
+ 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("/connect/users/{id}/connections", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "close_reason": close_reason,
+ "country": country,
+ "dst_host": dst_host,
+ "dst_port": dst_port,
+ "ended_after": ended_after,
+ "ended_before": ended_before,
+ "max_bytes_in": max_bytes_in,
+ "max_bytes_out": max_bytes_out,
+ "max_duration_ms": max_duration_ms,
+ "max_total_bytes": max_total_bytes,
+ "min_bytes_in": min_bytes_in,
+ "min_bytes_out": min_bytes_out,
+ "min_duration_ms": min_duration_ms,
+ "min_total_bytes": min_total_bytes,
+ "order": order,
+ "order_by": order_by,
+ "page": page,
+ "page_size": page_size,
+ "protocol": protocol,
+ "provider": provider,
+ "proxy_id": proxy_id,
+ "session_id": session_id,
+ "started_after": started_after,
+ "started_before": started_before,
+ "status": status,
+ },
+ user_list_connections_params.UserListConnectionsParams,
+ ),
+ ),
+ cast_to=UserListConnectionsResponse,
+ )
+
+
+class AsyncUsersResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncUsersResourceWithRawResponse:
+ """
+ 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 AsyncUsersResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncUsersResourceWithStreamingResponse:
+ """
+ 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 AsyncUsersResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ password: str | Omit = omit,
+ proxy_id: str | Omit = omit,
+ username: 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,
+ ) -> UserCreateResponse:
+ """
+ Creates a SOCKS5 credential, optionally bound to a proxy for dedicated routing.
+ Username and password are generated when omitted.
+
+ Args:
+ password: Desired SOCKS5 password, 1-255 bytes (RFC 1929). Generated when omitted.
+
+ proxy_id: Proxy to bind the user to for dedicated routing.
+
+ username: Desired SOCKS5 username, 1-255 bytes (RFC 1929). Generated when omitted.
+
+ 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(
+ "/connect/users",
+ body=await async_maybe_transform(
+ {
+ "password": password,
+ "proxy_id": proxy_id,
+ "username": username,
+ },
+ user_create_params.UserCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=UserCreateResponse,
+ )
+
+ 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,
+ ) -> UserRetrieveResponse:
+ """
+ Get a SOCKS5 user by ID, including its password
+
+ 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("/connect/users/{id}", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=UserRetrieveResponse,
+ )
+
+ async def update(
+ self,
+ id: str,
+ *,
+ proxy_id: 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,
+ ) -> UserUpdateResponse:
+ """
+ Rebind the user to a different proxy (or detach it by passing null).
+
+ Args:
+ proxy_id: Proxy to rebind to, or null to detach. Omit to leave the user's current binding
+ unchanged — only an explicit null detaches.
+
+ 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("/connect/users/{id}", id=id),
+ body=await async_maybe_transform({"proxy_id": proxy_id}, user_update_params.UserUpdateParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=UserUpdateResponse,
+ )
+
+ async def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ proxy_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,
+ ) -> UserListResponse:
+ """Returns SOCKS5 users owned by the caller.
+
+ Passwords are omitted from the list.
+
+ Args:
+ page: Page number (1-based).
+
+ page_size: Number of items per page.
+
+ proxy_id: Filter to users bound to this proxy. Users not bound to it (including unbound
+ users) are excluded.
+
+ 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(
+ "/connect/users",
+ 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,
+ "proxy_id": proxy_id,
+ },
+ user_list_params.UserListParams,
+ ),
+ ),
+ cast_to=UserListResponse,
+ )
+
+ 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:
+ """
+ Delete a SOCKS5 user
+
+ 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("/connect/users/{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 list_connections(
+ self,
+ id: str,
+ *,
+ close_reason: str | Omit = omit,
+ country: str | Omit = omit,
+ dst_host: str | Omit = omit,
+ dst_port: int | Omit = omit,
+ ended_after: Union[str, datetime] | Omit = omit,
+ ended_before: Union[str, datetime] | Omit = omit,
+ max_bytes_in: int | Omit = omit,
+ max_bytes_out: int | Omit = omit,
+ max_duration_ms: int | Omit = omit,
+ max_total_bytes: int | Omit = omit,
+ min_bytes_in: int | Omit = omit,
+ min_bytes_out: int | Omit = omit,
+ min_duration_ms: int | Omit = omit,
+ min_total_bytes: int | Omit = omit,
+ order: Literal["asc", "desc"] | Omit = omit,
+ order_by: Literal["startedAt", "endedAt", "bytesIn", "bytesOut", "totalBytes", "durationMs"] | Omit = omit,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ protocol: Literal["tcp", "udp", "unknown"] | Omit = omit,
+ provider: str | Omit = omit,
+ proxy_id: str | Omit = omit,
+ session_id: str | Omit = omit,
+ started_after: Union[str, datetime] | Omit = omit,
+ started_before: Union[str, datetime] | Omit = omit,
+ status: Literal["active", "closed"] | 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,
+ ) -> UserListConnectionsResponse:
+ """
+ Returns the connection history recorded for this user, one item per connection
+ (aggregated across the connection's lifetime). Supports filtering on every
+ property plus ordering and pagination. Returns 503 when the connection-insights
+ backend is disabled or unreachable.
+
+ Args:
+ close_reason: Filter to connections that closed with this reason (closed connections only).
+
+ country: Filter to connections served from this upstream country (ISO 3166-1 alpha-2).
+
+ dst_host: Filter to connections to this destination host (exact match).
+
+ dst_port: Filter to connections to this destination port.
+
+ ended_after: Filter to connections whose last activity was at or after this time (inclusive).
+
+ ended_before: Filter to connections whose last activity was at or before this time
+ (inclusive).
+
+ max_bytes_in: Filter to connections with at most this many bytes received from upstream.
+
+ max_bytes_out: Filter to connections with at most this many bytes sent to upstream.
+
+ max_duration_ms: Filter to connections lasting at most this many milliseconds.
+
+ max_total_bytes: Filter to connections with at most this much total traffic (bytesIn + bytesOut).
+
+ min_bytes_in: Filter to connections with at least this many bytes received from upstream.
+
+ min_bytes_out: Filter to connections with at least this many bytes sent to upstream.
+
+ min_duration_ms: Filter to connections lasting at least this many milliseconds.
+
+ min_total_bytes: Filter to connections with at least this much total traffic (bytesIn +
+ bytesOut).
+
+ order: Sort direction.
+
+ order_by: Property to order the results by.
+
+ page: Page number (1-based).
+
+ page_size: Number of items per page.
+
+ protocol: Filter to connections of this transport protocol.
+
+ provider: Filter to connections served by this upstream provider.
+
+ proxy_id: Filter to connections routed through this proxy.
+
+ session_id: Filter to a single connection by its session id.
+
+ started_after: Filter to connections that started at or after this time (inclusive).
+
+ started_before: Filter to connections that started at or before this time (inclusive).
+
+ status: Filter by connection status.
+
+ 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("/connect/users/{id}/connections", 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(
+ {
+ "close_reason": close_reason,
+ "country": country,
+ "dst_host": dst_host,
+ "dst_port": dst_port,
+ "ended_after": ended_after,
+ "ended_before": ended_before,
+ "max_bytes_in": max_bytes_in,
+ "max_bytes_out": max_bytes_out,
+ "max_duration_ms": max_duration_ms,
+ "max_total_bytes": max_total_bytes,
+ "min_bytes_in": min_bytes_in,
+ "min_bytes_out": min_bytes_out,
+ "min_duration_ms": min_duration_ms,
+ "min_total_bytes": min_total_bytes,
+ "order": order,
+ "order_by": order_by,
+ "page": page,
+ "page_size": page_size,
+ "protocol": protocol,
+ "provider": provider,
+ "proxy_id": proxy_id,
+ "session_id": session_id,
+ "started_after": started_after,
+ "started_before": started_before,
+ "status": status,
+ },
+ user_list_connections_params.UserListConnectionsParams,
+ ),
+ ),
+ cast_to=UserListConnectionsResponse,
+ )
+
+
+class UsersResourceWithRawResponse:
+ def __init__(self, users: UsersResource) -> None:
+ self._users = users
+
+ self.create = to_raw_response_wrapper(
+ users.create,
+ )
+ self.retrieve = to_raw_response_wrapper(
+ users.retrieve,
+ )
+ self.update = to_raw_response_wrapper(
+ users.update,
+ )
+ self.list = to_raw_response_wrapper(
+ users.list,
+ )
+ self.delete = to_raw_response_wrapper(
+ users.delete,
+ )
+ self.list_connections = to_raw_response_wrapper(
+ users.list_connections,
+ )
+
+
+class AsyncUsersResourceWithRawResponse:
+ def __init__(self, users: AsyncUsersResource) -> None:
+ self._users = users
+
+ self.create = async_to_raw_response_wrapper(
+ users.create,
+ )
+ self.retrieve = async_to_raw_response_wrapper(
+ users.retrieve,
+ )
+ self.update = async_to_raw_response_wrapper(
+ users.update,
+ )
+ self.list = async_to_raw_response_wrapper(
+ users.list,
+ )
+ self.delete = async_to_raw_response_wrapper(
+ users.delete,
+ )
+ self.list_connections = async_to_raw_response_wrapper(
+ users.list_connections,
+ )
+
+
+class UsersResourceWithStreamingResponse:
+ def __init__(self, users: UsersResource) -> None:
+ self._users = users
+
+ self.create = to_streamed_response_wrapper(
+ users.create,
+ )
+ self.retrieve = to_streamed_response_wrapper(
+ users.retrieve,
+ )
+ self.update = to_streamed_response_wrapper(
+ users.update,
+ )
+ self.list = to_streamed_response_wrapper(
+ users.list,
+ )
+ self.delete = to_streamed_response_wrapper(
+ users.delete,
+ )
+ self.list_connections = to_streamed_response_wrapper(
+ users.list_connections,
+ )
+
+
+class AsyncUsersResourceWithStreamingResponse:
+ def __init__(self, users: AsyncUsersResource) -> None:
+ self._users = users
+
+ self.create = async_to_streamed_response_wrapper(
+ users.create,
+ )
+ self.retrieve = async_to_streamed_response_wrapper(
+ users.retrieve,
+ )
+ self.update = async_to_streamed_response_wrapper(
+ users.update,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ users.list,
+ )
+ self.delete = async_to_streamed_response_wrapper(
+ users.delete,
+ )
+ self.list_connections = async_to_streamed_response_wrapper(
+ users.list_connections,
+ )
diff --git a/src/mobilerun_sdk/resources/devices/apps.py b/src/mobilerun_sdk/resources/devices/apps.py
index 4541bb5..dbd6985 100644
--- a/src/mobilerun_sdk/resources/devices/apps.py
+++ b/src/mobilerun_sdk/resources/devices/apps.py
@@ -44,50 +44,6 @@ def with_streaming_response(self) -> AppsResourceWithStreamingResponse:
"""
return AppsResourceWithStreamingResponse(self)
- def update(
- self,
- package_name: str,
- *,
- device_id: str,
- 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.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> None:
- """
- Stop app
-
- 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 package_name:
- raise ValueError(f"Expected a non-empty value for `package_name` but received {package_name!r}")
- extra_headers = {"Accept": "*/*", **(extra_headers or {})}
- extra_headers = {
- **strip_not_given(
- {"X-Device-Display-ID": str(x_device_display_id) if is_given(x_device_display_id) else not_given}
- ),
- **(extra_headers or {}),
- }
- return self._patch(
- path_template("/devices/{device_id}/apps/{package_name}", device_id=device_id, package_name=package_name),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=NoneType,
- )
-
def list(
self,
device_id: str,
@@ -337,28 +293,7 @@ def start(
cast_to=NoneType,
)
-
-class AsyncAppsResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncAppsResourceWithRawResponse:
- """
- 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 AsyncAppsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncAppsResourceWithStreamingResponse:
- """
- 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 AsyncAppsResourceWithStreamingResponse(self)
-
- async def update(
+ def stop(
self,
package_name: str,
*,
@@ -394,7 +329,7 @@ async def update(
),
**(extra_headers or {}),
}
- return await self._patch(
+ return self._patch(
path_template("/devices/{device_id}/apps/{package_name}", device_id=device_id, package_name=package_name),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -402,6 +337,27 @@ async def update(
cast_to=NoneType,
)
+
+class AsyncAppsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncAppsResourceWithRawResponse:
+ """
+ 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 AsyncAppsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncAppsResourceWithStreamingResponse:
+ """
+ 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 AsyncAppsResourceWithStreamingResponse(self)
+
async def list(
self,
device_id: str,
@@ -651,14 +607,55 @@ async def start(
cast_to=NoneType,
)
+ async def stop(
+ self,
+ package_name: str,
+ *,
+ device_id: str,
+ 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.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Stop app
+
+ 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 package_name:
+ raise ValueError(f"Expected a non-empty value for `package_name` but received {package_name!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ extra_headers = {
+ **strip_not_given(
+ {"X-Device-Display-ID": str(x_device_display_id) if is_given(x_device_display_id) else not_given}
+ ),
+ **(extra_headers or {}),
+ }
+ return await self._patch(
+ path_template("/devices/{device_id}/apps/{package_name}", device_id=device_id, package_name=package_name),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
class AppsResourceWithRawResponse:
def __init__(self, apps: AppsResource) -> None:
self._apps = apps
- self.update = to_raw_response_wrapper(
- apps.update,
- )
self.list = to_raw_response_wrapper(
apps.list,
)
@@ -671,15 +668,15 @@ def __init__(self, apps: AppsResource) -> None:
self.start = to_raw_response_wrapper(
apps.start,
)
+ self.stop = to_raw_response_wrapper(
+ apps.stop,
+ )
class AsyncAppsResourceWithRawResponse:
def __init__(self, apps: AsyncAppsResource) -> None:
self._apps = apps
- self.update = async_to_raw_response_wrapper(
- apps.update,
- )
self.list = async_to_raw_response_wrapper(
apps.list,
)
@@ -692,15 +689,15 @@ def __init__(self, apps: AsyncAppsResource) -> None:
self.start = async_to_raw_response_wrapper(
apps.start,
)
+ self.stop = async_to_raw_response_wrapper(
+ apps.stop,
+ )
class AppsResourceWithStreamingResponse:
def __init__(self, apps: AppsResource) -> None:
self._apps = apps
- self.update = to_streamed_response_wrapper(
- apps.update,
- )
self.list = to_streamed_response_wrapper(
apps.list,
)
@@ -713,15 +710,15 @@ def __init__(self, apps: AppsResource) -> None:
self.start = to_streamed_response_wrapper(
apps.start,
)
+ self.stop = to_streamed_response_wrapper(
+ apps.stop,
+ )
class AsyncAppsResourceWithStreamingResponse:
def __init__(self, apps: AsyncAppsResource) -> None:
self._apps = apps
- self.update = async_to_streamed_response_wrapper(
- apps.update,
- )
self.list = async_to_streamed_response_wrapper(
apps.list,
)
@@ -734,3 +731,6 @@ def __init__(self, apps: AsyncAppsResource) -> None:
self.start = async_to_streamed_response_wrapper(
apps.start,
)
+ self.stop = async_to_streamed_response_wrapper(
+ apps.stop,
+ )
diff --git a/src/mobilerun_sdk/resources/devices/devices.py b/src/mobilerun_sdk/resources/devices/devices.py
index 31c41ed..9837a6f 100644
--- a/src/mobilerun_sdk/resources/devices/devices.py
+++ b/src/mobilerun_sdk/resources/devices/devices.py
@@ -16,6 +16,14 @@
AppsResourceWithStreamingResponse,
AsyncAppsResourceWithStreamingResponse,
)
+from .esim import (
+ EsimResource,
+ AsyncEsimResource,
+ EsimResourceWithRawResponse,
+ AsyncEsimResourceWithRawResponse,
+ EsimResourceWithStreamingResponse,
+ AsyncEsimResourceWithStreamingResponse,
+)
from .files import (
FilesResource,
AsyncFilesResource,
@@ -108,14 +116,6 @@
AsyncTimezoneResourceWithStreamingResponse,
)
from ..._compat import cached_property
-from .esim.esim import (
- EsimResource,
- AsyncEsimResource,
- EsimResourceWithRawResponse,
- AsyncEsimResourceWithRawResponse,
- EsimResourceWithStreamingResponse,
- AsyncEsimResourceWithStreamingResponse,
-)
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
to_raw_response_wrapper,
@@ -495,8 +495,7 @@ def reset(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> None:
"""
- Reset a device to a fresh state (VMOS one-click new device; non-VMOS providers
- return 404)
+ Reset a device to a fresh state
Args:
extra_headers: Send extra headers
@@ -990,8 +989,7 @@ async def reset(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> None:
"""
- Reset a device to a fresh state (VMOS one-click new device; non-VMOS providers
- return 404)
+ Reset a device to a fresh state
Args:
extra_headers: Send extra headers
diff --git a/src/mobilerun_sdk/resources/devices/esim/esim.py b/src/mobilerun_sdk/resources/devices/esim.py
similarity index 67%
rename from src/mobilerun_sdk/resources/devices/esim/esim.py
rename to src/mobilerun_sdk/resources/devices/esim.py
index 9693e2e..ba2d38e 100644
--- a/src/mobilerun_sdk/resources/devices/esim/esim.py
+++ b/src/mobilerun_sdk/resources/devices/esim.py
@@ -6,38 +6,25 @@
import httpx
-from .apn import (
- ApnResource,
- AsyncApnResource,
- ApnResourceWithRawResponse,
- AsyncApnResourceWithRawResponse,
- ApnResourceWithStreamingResponse,
- AsyncApnResourceWithStreamingResponse,
-)
-from ...._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
-from ...._utils import is_given, path_template, maybe_transform, strip_not_given, async_maybe_transform
-from ...._compat import cached_property
-from ...._resource import SyncAPIResource, AsyncAPIResource
-from ...._response import (
+from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
+from ..._utils import is_given, path_template, maybe_transform, strip_not_given, async_maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
to_raw_response_wrapper,
to_streamed_response_wrapper,
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
-from ...._base_client import make_request_options
-from ....types.devices import esim_enable_params, esim_remove_params, esim_activate_params, esim_set_roaming_params
-from ....types.devices.esim_list_response import EsimListResponse
-from ....types.devices.esim_status_response import EsimStatusResponse
-from ....types.devices.esim_activate_response import EsimActivateResponse
+from ..._base_client import make_request_options
+from ...types.devices import esim_enable_params, esim_remove_params, esim_activate_params
+from ...types.devices.esim_list_response import EsimListResponse
+from ...types.devices.esim_activate_response import EsimActivateResponse
__all__ = ["EsimResource", "AsyncEsimResource"]
class EsimResource(SyncAPIResource):
- @cached_property
- def apn(self) -> ApnResource:
- return ApnResource(self._client)
-
@cached_property
def with_raw_response(self) -> EsimResourceWithRawResponse:
"""
@@ -243,95 +230,8 @@ def remove(
cast_to=NoneType,
)
- def set_roaming(
- self,
- device_id: str,
- *,
- enabled: bool,
- 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.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> None:
- """
- Toggle eSIM data roaming
-
- 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 = {"Accept": "*/*", **(extra_headers or {})}
- extra_headers = {
- **strip_not_given(
- {"X-Device-Display-ID": str(x_device_display_id) if is_given(x_device_display_id) else not_given}
- ),
- **(extra_headers or {}),
- }
- return self._put(
- path_template("/devices/{device_id}/esim/roaming", device_id=device_id),
- body=maybe_transform({"enabled": enabled}, esim_set_roaming_params.EsimSetRoamingParams),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=NoneType,
- )
-
- def status(
- self,
- device_id: str,
- *,
- 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.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> Optional[EsimStatusResponse]:
- """
- Get eSIM connectivity status
-
- 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 = {
- **strip_not_given(
- {"X-Device-Display-ID": str(x_device_display_id) if is_given(x_device_display_id) else not_given}
- ),
- **(extra_headers or {}),
- }
- return self._get(
- path_template("/devices/{device_id}/esim/status", device_id=device_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimStatusResponse,
- )
-
class AsyncEsimResource(AsyncAPIResource):
- @cached_property
- def apn(self) -> AsyncApnResource:
- return AsyncApnResource(self._client)
-
@cached_property
def with_raw_response(self) -> AsyncEsimResourceWithRawResponse:
"""
@@ -537,89 +437,6 @@ async def remove(
cast_to=NoneType,
)
- async def set_roaming(
- self,
- device_id: str,
- *,
- enabled: bool,
- 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.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> None:
- """
- Toggle eSIM data roaming
-
- 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 = {"Accept": "*/*", **(extra_headers or {})}
- extra_headers = {
- **strip_not_given(
- {"X-Device-Display-ID": str(x_device_display_id) if is_given(x_device_display_id) else not_given}
- ),
- **(extra_headers or {}),
- }
- return await self._put(
- path_template("/devices/{device_id}/esim/roaming", device_id=device_id),
- body=await async_maybe_transform({"enabled": enabled}, esim_set_roaming_params.EsimSetRoamingParams),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=NoneType,
- )
-
- async def status(
- self,
- device_id: str,
- *,
- 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.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> Optional[EsimStatusResponse]:
- """
- Get eSIM connectivity status
-
- 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 = {
- **strip_not_given(
- {"X-Device-Display-ID": str(x_device_display_id) if is_given(x_device_display_id) else not_given}
- ),
- **(extra_headers or {}),
- }
- return await self._get(
- path_template("/devices/{device_id}/esim/status", device_id=device_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=EsimStatusResponse,
- )
-
class EsimResourceWithRawResponse:
def __init__(self, esim: EsimResource) -> None:
@@ -637,16 +454,6 @@ def __init__(self, esim: EsimResource) -> None:
self.remove = to_raw_response_wrapper(
esim.remove,
)
- self.set_roaming = to_raw_response_wrapper(
- esim.set_roaming,
- )
- self.status = to_raw_response_wrapper(
- esim.status,
- )
-
- @cached_property
- def apn(self) -> ApnResourceWithRawResponse:
- return ApnResourceWithRawResponse(self._esim.apn)
class AsyncEsimResourceWithRawResponse:
@@ -665,16 +472,6 @@ def __init__(self, esim: AsyncEsimResource) -> None:
self.remove = async_to_raw_response_wrapper(
esim.remove,
)
- self.set_roaming = async_to_raw_response_wrapper(
- esim.set_roaming,
- )
- self.status = async_to_raw_response_wrapper(
- esim.status,
- )
-
- @cached_property
- def apn(self) -> AsyncApnResourceWithRawResponse:
- return AsyncApnResourceWithRawResponse(self._esim.apn)
class EsimResourceWithStreamingResponse:
@@ -693,16 +490,6 @@ def __init__(self, esim: EsimResource) -> None:
self.remove = to_streamed_response_wrapper(
esim.remove,
)
- self.set_roaming = to_streamed_response_wrapper(
- esim.set_roaming,
- )
- self.status = to_streamed_response_wrapper(
- esim.status,
- )
-
- @cached_property
- def apn(self) -> ApnResourceWithStreamingResponse:
- return ApnResourceWithStreamingResponse(self._esim.apn)
class AsyncEsimResourceWithStreamingResponse:
@@ -721,13 +508,3 @@ def __init__(self, esim: AsyncEsimResource) -> None:
self.remove = async_to_streamed_response_wrapper(
esim.remove,
)
- self.set_roaming = async_to_streamed_response_wrapper(
- esim.set_roaming,
- )
- self.status = async_to_streamed_response_wrapper(
- esim.status,
- )
-
- @cached_property
- def apn(self) -> AsyncApnResourceWithStreamingResponse:
- return AsyncApnResourceWithStreamingResponse(self._esim.apn)
diff --git a/src/mobilerun_sdk/resources/devices/esim/__init__.py b/src/mobilerun_sdk/resources/devices/esim/__init__.py
deleted file mode 100644
index 12056c7..0000000
--- a/src/mobilerun_sdk/resources/devices/esim/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .apn import (
- ApnResource,
- AsyncApnResource,
- ApnResourceWithRawResponse,
- AsyncApnResourceWithRawResponse,
- ApnResourceWithStreamingResponse,
- AsyncApnResourceWithStreamingResponse,
-)
-from .esim import (
- EsimResource,
- AsyncEsimResource,
- EsimResourceWithRawResponse,
- AsyncEsimResourceWithRawResponse,
- EsimResourceWithStreamingResponse,
- AsyncEsimResourceWithStreamingResponse,
-)
-
-__all__ = [
- "ApnResource",
- "AsyncApnResource",
- "ApnResourceWithRawResponse",
- "AsyncApnResourceWithRawResponse",
- "ApnResourceWithStreamingResponse",
- "AsyncApnResourceWithStreamingResponse",
- "EsimResource",
- "AsyncEsimResource",
- "EsimResourceWithRawResponse",
- "AsyncEsimResourceWithRawResponse",
- "EsimResourceWithStreamingResponse",
- "AsyncEsimResourceWithStreamingResponse",
-]
diff --git a/src/mobilerun_sdk/resources/devices/esim/apn.py b/src/mobilerun_sdk/resources/devices/esim/apn.py
deleted file mode 100644
index c732e52..0000000
--- a/src/mobilerun_sdk/resources/devices/esim/apn.py
+++ /dev/null
@@ -1,429 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Optional
-
-import httpx
-
-from ...._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
-from ...._utils import is_given, path_template, maybe_transform, strip_not_given, async_maybe_transform
-from ...._compat import cached_property
-from ...._resource import SyncAPIResource, AsyncAPIResource
-from ...._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ...._base_client import make_request_options
-from ....types.devices.esim import apn_create_params, apn_select_params
-from ....types.devices.esim.apn_list_response import ApnListResponse
-
-__all__ = ["ApnResource", "AsyncApnResource"]
-
-
-class ApnResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> ApnResourceWithRawResponse:
- """
- 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 ApnResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ApnResourceWithStreamingResponse:
- """
- 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 ApnResourceWithStreamingResponse(self)
-
- def create(
- self,
- device_id: str,
- *,
- apn: str,
- mcc: str,
- mnc: str,
- name: str,
- protocol: str,
- roaming_protocol: str,
- sub_id: int,
- type: str,
- 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.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> None:
- """
- Create and set an APN for an eSIM subscription
-
- 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 = {"Accept": "*/*", **(extra_headers or {})}
- extra_headers = {
- **strip_not_given(
- {"X-Device-Display-ID": str(x_device_display_id) if is_given(x_device_display_id) else not_given}
- ),
- **(extra_headers or {}),
- }
- return self._post(
- path_template("/devices/{device_id}/esim/apn", device_id=device_id),
- body=maybe_transform(
- {
- "apn": apn,
- "mcc": mcc,
- "mnc": mnc,
- "name": name,
- "protocol": protocol,
- "roaming_protocol": roaming_protocol,
- "sub_id": sub_id,
- "type": type,
- },
- apn_create_params.ApnCreateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=NoneType,
- )
-
- def list(
- self,
- device_id: str,
- *,
- 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.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> Optional[ApnListResponse]:
- """
- List APNs for active subscriptions
-
- 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 = {
- **strip_not_given(
- {"X-Device-Display-ID": str(x_device_display_id) if is_given(x_device_display_id) else not_given}
- ),
- **(extra_headers or {}),
- }
- return self._get(
- path_template("/devices/{device_id}/esim/apn", device_id=device_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ApnListResponse,
- )
-
- def select(
- self,
- device_id: str,
- *,
- apn_id: int,
- sub_id: int,
- 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.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> None:
- """
- Select an existing APN as preferred
-
- 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 = {"Accept": "*/*", **(extra_headers or {})}
- extra_headers = {
- **strip_not_given(
- {"X-Device-Display-ID": str(x_device_display_id) if is_given(x_device_display_id) else not_given}
- ),
- **(extra_headers or {}),
- }
- return self._put(
- path_template("/devices/{device_id}/esim/apn", device_id=device_id),
- body=maybe_transform(
- {
- "apn_id": apn_id,
- "sub_id": sub_id,
- },
- apn_select_params.ApnSelectParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=NoneType,
- )
-
-
-class AsyncApnResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncApnResourceWithRawResponse:
- """
- 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 AsyncApnResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncApnResourceWithStreamingResponse:
- """
- 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 AsyncApnResourceWithStreamingResponse(self)
-
- async def create(
- self,
- device_id: str,
- *,
- apn: str,
- mcc: str,
- mnc: str,
- name: str,
- protocol: str,
- roaming_protocol: str,
- sub_id: int,
- type: str,
- 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.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> None:
- """
- Create and set an APN for an eSIM subscription
-
- 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 = {"Accept": "*/*", **(extra_headers or {})}
- extra_headers = {
- **strip_not_given(
- {"X-Device-Display-ID": str(x_device_display_id) if is_given(x_device_display_id) else not_given}
- ),
- **(extra_headers or {}),
- }
- return await self._post(
- path_template("/devices/{device_id}/esim/apn", device_id=device_id),
- body=await async_maybe_transform(
- {
- "apn": apn,
- "mcc": mcc,
- "mnc": mnc,
- "name": name,
- "protocol": protocol,
- "roaming_protocol": roaming_protocol,
- "sub_id": sub_id,
- "type": type,
- },
- apn_create_params.ApnCreateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=NoneType,
- )
-
- async def list(
- self,
- device_id: str,
- *,
- 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.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> Optional[ApnListResponse]:
- """
- List APNs for active subscriptions
-
- 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 = {
- **strip_not_given(
- {"X-Device-Display-ID": str(x_device_display_id) if is_given(x_device_display_id) else not_given}
- ),
- **(extra_headers or {}),
- }
- return await self._get(
- path_template("/devices/{device_id}/esim/apn", device_id=device_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ApnListResponse,
- )
-
- async def select(
- self,
- device_id: str,
- *,
- apn_id: int,
- sub_id: int,
- 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.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> None:
- """
- Select an existing APN as preferred
-
- 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 = {"Accept": "*/*", **(extra_headers or {})}
- extra_headers = {
- **strip_not_given(
- {"X-Device-Display-ID": str(x_device_display_id) if is_given(x_device_display_id) else not_given}
- ),
- **(extra_headers or {}),
- }
- return await self._put(
- path_template("/devices/{device_id}/esim/apn", device_id=device_id),
- body=await async_maybe_transform(
- {
- "apn_id": apn_id,
- "sub_id": sub_id,
- },
- apn_select_params.ApnSelectParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=NoneType,
- )
-
-
-class ApnResourceWithRawResponse:
- def __init__(self, apn: ApnResource) -> None:
- self._apn = apn
-
- self.create = to_raw_response_wrapper(
- apn.create,
- )
- self.list = to_raw_response_wrapper(
- apn.list,
- )
- self.select = to_raw_response_wrapper(
- apn.select,
- )
-
-
-class AsyncApnResourceWithRawResponse:
- def __init__(self, apn: AsyncApnResource) -> None:
- self._apn = apn
-
- self.create = async_to_raw_response_wrapper(
- apn.create,
- )
- self.list = async_to_raw_response_wrapper(
- apn.list,
- )
- self.select = async_to_raw_response_wrapper(
- apn.select,
- )
-
-
-class ApnResourceWithStreamingResponse:
- def __init__(self, apn: ApnResource) -> None:
- self._apn = apn
-
- self.create = to_streamed_response_wrapper(
- apn.create,
- )
- self.list = to_streamed_response_wrapper(
- apn.list,
- )
- self.select = to_streamed_response_wrapper(
- apn.select,
- )
-
-
-class AsyncApnResourceWithStreamingResponse:
- def __init__(self, apn: AsyncApnResource) -> None:
- self._apn = apn
-
- self.create = async_to_streamed_response_wrapper(
- apn.create,
- )
- self.list = async_to_streamed_response_wrapper(
- apn.list,
- )
- self.select = async_to_streamed_response_wrapper(
- apn.select,
- )
diff --git a/src/mobilerun_sdk/resources/hooks.py b/src/mobilerun_sdk/resources/hooks.py
index 185b05e..6f3c43b 100644
--- a/src/mobilerun_sdk/resources/hooks.py
+++ b/src/mobilerun_sdk/resources/hooks.py
@@ -7,7 +7,7 @@
import httpx
-from ..types import hook_list_params, hook_update_params, hook_perform_params, hook_subscribe_params
+from ..types import hook_list_params, hook_test_params, hook_update_params, hook_perform_params, hook_subscribe_params
from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
@@ -20,6 +20,7 @@
)
from .._base_client import make_request_options
from ..types.hook_list_response import HookListResponse
+from ..types.hook_test_response import HookTestResponse
from ..types.hook_update_response import HookUpdateResponse
from ..types.hook_perform_response import HookPerformResponse
from ..types.hook_retrieve_response import HookRetrieveResponse
@@ -277,6 +278,46 @@ def subscribe(
cast_to=HookSubscribeResponse,
)
+ def test(
+ self,
+ hook_id: str,
+ *,
+ event: 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,
+ ) -> HookTestResponse:
+ """
+ Send a test event to a webhook endpoint.
+
+ Delivers a sample payload to the hook's URL with a single attempt (no retries)
+ for fast feedback.
+
+ Args:
+ event: Event type to simulate (default: completed)
+
+ 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 hook_id:
+ raise ValueError(f"Expected a non-empty value for `hook_id` but received {hook_id!r}")
+ return self._post(
+ path_template("/hooks/{hook_id}/test", hook_id=hook_id),
+ body=maybe_transform({"event": event}, hook_test_params.HookTestParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=HookTestResponse,
+ )
+
def unsubscribe(
self,
hook_id: str,
@@ -560,6 +601,46 @@ async def subscribe(
cast_to=HookSubscribeResponse,
)
+ async def test(
+ self,
+ hook_id: str,
+ *,
+ event: 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,
+ ) -> HookTestResponse:
+ """
+ Send a test event to a webhook endpoint.
+
+ Delivers a sample payload to the hook's URL with a single attempt (no retries)
+ for fast feedback.
+
+ Args:
+ event: Event type to simulate (default: completed)
+
+ 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 hook_id:
+ raise ValueError(f"Expected a non-empty value for `hook_id` but received {hook_id!r}")
+ return await self._post(
+ path_template("/hooks/{hook_id}/test", hook_id=hook_id),
+ body=await async_maybe_transform({"event": event}, hook_test_params.HookTestParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=HookTestResponse,
+ )
+
async def unsubscribe(
self,
hook_id: str,
@@ -618,6 +699,9 @@ def __init__(self, hooks: HooksResource) -> None:
self.subscribe = to_raw_response_wrapper(
hooks.subscribe,
)
+ self.test = to_raw_response_wrapper(
+ hooks.test,
+ )
self.unsubscribe = to_raw_response_wrapper(
hooks.unsubscribe,
)
@@ -645,6 +729,9 @@ def __init__(self, hooks: AsyncHooksResource) -> None:
self.subscribe = async_to_raw_response_wrapper(
hooks.subscribe,
)
+ self.test = async_to_raw_response_wrapper(
+ hooks.test,
+ )
self.unsubscribe = async_to_raw_response_wrapper(
hooks.unsubscribe,
)
@@ -672,6 +759,9 @@ def __init__(self, hooks: HooksResource) -> None:
self.subscribe = to_streamed_response_wrapper(
hooks.subscribe,
)
+ self.test = to_streamed_response_wrapper(
+ hooks.test,
+ )
self.unsubscribe = to_streamed_response_wrapper(
hooks.unsubscribe,
)
@@ -699,6 +789,9 @@ def __init__(self, hooks: AsyncHooksResource) -> None:
self.subscribe = async_to_streamed_response_wrapper(
hooks.subscribe,
)
+ self.test = async_to_streamed_response_wrapper(
+ hooks.test,
+ )
self.unsubscribe = async_to_streamed_response_wrapper(
hooks.unsubscribe,
)
diff --git a/src/mobilerun_sdk/resources/proxies.py b/src/mobilerun_sdk/resources/proxies.py
index cd4235f..4abd363 100644
--- a/src/mobilerun_sdk/resources/proxies.py
+++ b/src/mobilerun_sdk/resources/proxies.py
@@ -6,7 +6,7 @@
import httpx
-from ..types import proxy_list_params, proxy_create_params, proxy_update_params
+from ..types import proxy_list_params, proxy_create_params, proxy_lookup_params, proxy_update_params
from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
from .._utils import path_template, required_args, maybe_transform, async_maybe_transform
from .._compat import cached_property
@@ -21,6 +21,7 @@
from ..types.proxy_list_response import ProxyListResponse
from ..types.proxy_create_response import ProxyCreateResponse
from ..types.proxy_delete_response import ProxyDeleteResponse
+from ..types.proxy_lookup_response import ProxyLookupResponse
from ..types.proxy_update_response import ProxyUpdateResponse
from ..types.proxy_retrieve_response import ProxyRetrieveResponse
@@ -349,6 +350,40 @@ def delete(
cast_to=ProxyDeleteResponse,
)
+ def lookup(
+ self,
+ *,
+ socks5: proxy_lookup_params.Socks5,
+ # 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,
+ ) -> ProxyLookupResponse:
+ """
+ Lookup proxy location
+
+ Args:
+ socks5: SOCKS5 proxy configuration.
+
+ 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(
+ "/proxies/lookup",
+ body=maybe_transform({"socks5": socks5}, proxy_lookup_params.ProxyLookupParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ProxyLookupResponse,
+ )
+
class AsyncProxiesResource(AsyncAPIResource):
"""Network Proxies"""
@@ -672,6 +707,40 @@ async def delete(
cast_to=ProxyDeleteResponse,
)
+ async def lookup(
+ self,
+ *,
+ socks5: proxy_lookup_params.Socks5,
+ # 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,
+ ) -> ProxyLookupResponse:
+ """
+ Lookup proxy location
+
+ Args:
+ socks5: SOCKS5 proxy configuration.
+
+ 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(
+ "/proxies/lookup",
+ body=await async_maybe_transform({"socks5": socks5}, proxy_lookup_params.ProxyLookupParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ProxyLookupResponse,
+ )
+
class ProxiesResourceWithRawResponse:
def __init__(self, proxies: ProxiesResource) -> None:
@@ -692,6 +761,9 @@ def __init__(self, proxies: ProxiesResource) -> None:
self.delete = to_raw_response_wrapper(
proxies.delete,
)
+ self.lookup = to_raw_response_wrapper(
+ proxies.lookup,
+ )
class AsyncProxiesResourceWithRawResponse:
@@ -713,6 +785,9 @@ def __init__(self, proxies: AsyncProxiesResource) -> None:
self.delete = async_to_raw_response_wrapper(
proxies.delete,
)
+ self.lookup = async_to_raw_response_wrapper(
+ proxies.lookup,
+ )
class ProxiesResourceWithStreamingResponse:
@@ -734,6 +809,9 @@ def __init__(self, proxies: ProxiesResource) -> None:
self.delete = to_streamed_response_wrapper(
proxies.delete,
)
+ self.lookup = to_streamed_response_wrapper(
+ proxies.lookup,
+ )
class AsyncProxiesResourceWithStreamingResponse:
@@ -755,3 +833,6 @@ def __init__(self, proxies: AsyncProxiesResource) -> None:
self.delete = async_to_streamed_response_wrapper(
proxies.delete,
)
+ self.lookup = async_to_streamed_response_wrapper(
+ proxies.lookup,
+ )
diff --git a/src/mobilerun_sdk/resources/tasks/tasks.py b/src/mobilerun_sdk/resources/tasks/tasks.py
index 47d4c1a..b765073 100644
--- a/src/mobilerun_sdk/resources/tasks/tasks.py
+++ b/src/mobilerun_sdk/resources/tasks/tasks.py
@@ -270,6 +270,7 @@ 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,
@@ -305,7 +306,7 @@ 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.1-flash-lite-preview')
+ 'google/gemini-3.1-flash-lite')
memory_namespace: Memory namespace for cross-task personalization
@@ -325,6 +326,7 @@ def run(
{
"device_id": device_id,
"task": task,
+ "accessibility": accessibility,
"agent_id": agent_id,
"apps": apps,
"continue_on_failure": continue_on_failure,
@@ -356,6 +358,7 @@ 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,
@@ -390,7 +393,7 @@ 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.1-flash-lite-preview')
+ 'google/gemini-3.1-flash-lite')
memory_namespace: Memory namespace for cross-task personalization
@@ -410,6 +413,7 @@ def run_streamed(
{
"device_id": device_id,
"task": task,
+ "accessibility": accessibility,
"agent_id": agent_id,
"apps": apps,
"continue_on_failure": continue_on_failure,
@@ -733,6 +737,7 @@ 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,
@@ -768,7 +773,7 @@ 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.1-flash-lite-preview')
+ 'google/gemini-3.1-flash-lite')
memory_namespace: Memory namespace for cross-task personalization
@@ -788,6 +793,7 @@ async def run(
{
"device_id": device_id,
"task": task,
+ "accessibility": accessibility,
"agent_id": agent_id,
"apps": apps,
"continue_on_failure": continue_on_failure,
@@ -819,6 +825,7 @@ 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,
@@ -853,7 +860,7 @@ 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.1-flash-lite-preview')
+ 'google/gemini-3.1-flash-lite')
memory_namespace: Memory namespace for cross-task personalization
@@ -873,6 +880,7 @@ async def run_streamed(
{
"device_id": device_id,
"task": task,
+ "accessibility": accessibility,
"agent_id": agent_id,
"apps": apps,
"continue_on_failure": continue_on_failure,
diff --git a/src/mobilerun_sdk/resources/workflows/__init__.py b/src/mobilerun_sdk/resources/workflows/__init__.py
new file mode 100644
index 0000000..9923a1b
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/__init__.py
@@ -0,0 +1,131 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .flows import (
+ FlowsResource,
+ AsyncFlowsResource,
+ FlowsResourceWithRawResponse,
+ AsyncFlowsResourceWithRawResponse,
+ FlowsResourceWithStreamingResponse,
+ AsyncFlowsResourceWithStreamingResponse,
+)
+from .events import (
+ EventsResource,
+ AsyncEventsResource,
+ EventsResourceWithRawResponse,
+ AsyncEventsResourceWithRawResponse,
+ EventsResourceWithStreamingResponse,
+ AsyncEventsResourceWithStreamingResponse,
+)
+from .actions import (
+ ActionsResource,
+ AsyncActionsResource,
+ ActionsResourceWithRawResponse,
+ AsyncActionsResourceWithRawResponse,
+ ActionsResourceWithStreamingResponse,
+ AsyncActionsResourceWithStreamingResponse,
+)
+from .secrets import (
+ SecretsResource,
+ AsyncSecretsResource,
+ SecretsResourceWithRawResponse,
+ AsyncSecretsResourceWithRawResponse,
+ SecretsResourceWithStreamingResponse,
+ AsyncSecretsResourceWithStreamingResponse,
+)
+from .triggers import (
+ TriggersResource,
+ AsyncTriggersResource,
+ TriggersResourceWithRawResponse,
+ AsyncTriggersResourceWithRawResponse,
+ TriggersResourceWithStreamingResponse,
+ AsyncTriggersResourceWithStreamingResponse,
+)
+from .timezones import (
+ TimezonesResource,
+ AsyncTimezonesResource,
+ TimezonesResourceWithRawResponse,
+ AsyncTimezonesResourceWithRawResponse,
+ TimezonesResourceWithStreamingResponse,
+ AsyncTimezonesResourceWithStreamingResponse,
+)
+from .workflows import (
+ WorkflowsResource,
+ AsyncWorkflowsResource,
+ WorkflowsResourceWithRawResponse,
+ AsyncWorkflowsResourceWithRawResponse,
+ WorkflowsResourceWithStreamingResponse,
+ AsyncWorkflowsResourceWithStreamingResponse,
+)
+from .executions import (
+ ExecutionsResource,
+ AsyncExecutionsResource,
+ ExecutionsResourceWithRawResponse,
+ AsyncExecutionsResourceWithRawResponse,
+ ExecutionsResourceWithStreamingResponse,
+ AsyncExecutionsResourceWithStreamingResponse,
+)
+from .action_catalog import (
+ ActionCatalogResource,
+ AsyncActionCatalogResource,
+ ActionCatalogResourceWithRawResponse,
+ AsyncActionCatalogResourceWithRawResponse,
+ ActionCatalogResourceWithStreamingResponse,
+ AsyncActionCatalogResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "TriggersResource",
+ "AsyncTriggersResource",
+ "TriggersResourceWithRawResponse",
+ "AsyncTriggersResourceWithRawResponse",
+ "TriggersResourceWithStreamingResponse",
+ "AsyncTriggersResourceWithStreamingResponse",
+ "ActionCatalogResource",
+ "AsyncActionCatalogResource",
+ "ActionCatalogResourceWithRawResponse",
+ "AsyncActionCatalogResourceWithRawResponse",
+ "ActionCatalogResourceWithStreamingResponse",
+ "AsyncActionCatalogResourceWithStreamingResponse",
+ "ActionsResource",
+ "AsyncActionsResource",
+ "ActionsResourceWithRawResponse",
+ "AsyncActionsResourceWithRawResponse",
+ "ActionsResourceWithStreamingResponse",
+ "AsyncActionsResourceWithStreamingResponse",
+ "FlowsResource",
+ "AsyncFlowsResource",
+ "FlowsResourceWithRawResponse",
+ "AsyncFlowsResourceWithRawResponse",
+ "FlowsResourceWithStreamingResponse",
+ "AsyncFlowsResourceWithStreamingResponse",
+ "EventsResource",
+ "AsyncEventsResource",
+ "EventsResourceWithRawResponse",
+ "AsyncEventsResourceWithRawResponse",
+ "EventsResourceWithStreamingResponse",
+ "AsyncEventsResourceWithStreamingResponse",
+ "ExecutionsResource",
+ "AsyncExecutionsResource",
+ "ExecutionsResourceWithRawResponse",
+ "AsyncExecutionsResourceWithRawResponse",
+ "ExecutionsResourceWithStreamingResponse",
+ "AsyncExecutionsResourceWithStreamingResponse",
+ "TimezonesResource",
+ "AsyncTimezonesResource",
+ "TimezonesResourceWithRawResponse",
+ "AsyncTimezonesResourceWithRawResponse",
+ "TimezonesResourceWithStreamingResponse",
+ "AsyncTimezonesResourceWithStreamingResponse",
+ "SecretsResource",
+ "AsyncSecretsResource",
+ "SecretsResourceWithRawResponse",
+ "AsyncSecretsResourceWithRawResponse",
+ "SecretsResourceWithStreamingResponse",
+ "AsyncSecretsResourceWithStreamingResponse",
+ "WorkflowsResource",
+ "AsyncWorkflowsResource",
+ "WorkflowsResourceWithRawResponse",
+ "AsyncWorkflowsResourceWithRawResponse",
+ "WorkflowsResourceWithStreamingResponse",
+ "AsyncWorkflowsResourceWithStreamingResponse",
+]
diff --git a/src/mobilerun_sdk/resources/workflows/action_catalog.py b/src/mobilerun_sdk/resources/workflows/action_catalog.py
new file mode 100644
index 0000000..b637dd4
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/action_catalog.py
@@ -0,0 +1,268 @@
+# 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 ..._base_client import make_request_options
+from ...types.workflows import action_catalog_list_params
+from ...types.workflows.action_catalog_list_response import ActionCatalogListResponse
+from ...types.workflows.action_catalog_retrieve_response import ActionCatalogRetrieveResponse
+
+__all__ = ["ActionCatalogResource", "AsyncActionCatalogResource"]
+
+
+class ActionCatalogResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ActionCatalogResourceWithRawResponse:
+ """
+ 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 ActionCatalogResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ActionCatalogResourceWithStreamingResponse:
+ """
+ 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 ActionCatalogResourceWithStreamingResponse(self)
+
+ def retrieve(
+ self,
+ catalog_entry_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,
+ ) -> ActionCatalogRetrieveResponse:
+ """
+ Get a catalog entry
+
+ 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 catalog_entry_id:
+ raise ValueError(f"Expected a non-empty value for `catalog_entry_id` but received {catalog_entry_id!r}")
+ return self._get(
+ path_template("/action-catalog/{catalog_entry_id}", catalog_entry_id=catalog_entry_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionCatalogRetrieveResponse,
+ )
+
+ def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ service: Literal["tasks_api", "devices_api", "agents_api", "webhooks"] | 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,
+ ) -> ActionCatalogListResponse:
+ """
+ List action catalog entries
+
+ 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(
+ "/action-catalog",
+ 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,
+ "service": service,
+ },
+ action_catalog_list_params.ActionCatalogListParams,
+ ),
+ ),
+ cast_to=ActionCatalogListResponse,
+ )
+
+
+class AsyncActionCatalogResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncActionCatalogResourceWithRawResponse:
+ """
+ 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 AsyncActionCatalogResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncActionCatalogResourceWithStreamingResponse:
+ """
+ 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 AsyncActionCatalogResourceWithStreamingResponse(self)
+
+ async def retrieve(
+ self,
+ catalog_entry_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,
+ ) -> ActionCatalogRetrieveResponse:
+ """
+ Get a catalog entry
+
+ 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 catalog_entry_id:
+ raise ValueError(f"Expected a non-empty value for `catalog_entry_id` but received {catalog_entry_id!r}")
+ return await self._get(
+ path_template("/action-catalog/{catalog_entry_id}", catalog_entry_id=catalog_entry_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionCatalogRetrieveResponse,
+ )
+
+ async def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ service: Literal["tasks_api", "devices_api", "agents_api", "webhooks"] | 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,
+ ) -> ActionCatalogListResponse:
+ """
+ List action catalog entries
+
+ 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(
+ "/action-catalog",
+ 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,
+ "service": service,
+ },
+ action_catalog_list_params.ActionCatalogListParams,
+ ),
+ ),
+ cast_to=ActionCatalogListResponse,
+ )
+
+
+class ActionCatalogResourceWithRawResponse:
+ def __init__(self, action_catalog: ActionCatalogResource) -> None:
+ self._action_catalog = action_catalog
+
+ self.retrieve = to_raw_response_wrapper(
+ action_catalog.retrieve,
+ )
+ self.list = to_raw_response_wrapper(
+ action_catalog.list,
+ )
+
+
+class AsyncActionCatalogResourceWithRawResponse:
+ def __init__(self, action_catalog: AsyncActionCatalogResource) -> None:
+ self._action_catalog = action_catalog
+
+ self.retrieve = async_to_raw_response_wrapper(
+ action_catalog.retrieve,
+ )
+ self.list = async_to_raw_response_wrapper(
+ action_catalog.list,
+ )
+
+
+class ActionCatalogResourceWithStreamingResponse:
+ def __init__(self, action_catalog: ActionCatalogResource) -> None:
+ self._action_catalog = action_catalog
+
+ self.retrieve = to_streamed_response_wrapper(
+ action_catalog.retrieve,
+ )
+ self.list = to_streamed_response_wrapper(
+ action_catalog.list,
+ )
+
+
+class AsyncActionCatalogResourceWithStreamingResponse:
+ def __init__(self, action_catalog: AsyncActionCatalogResource) -> None:
+ self._action_catalog = action_catalog
+
+ self.retrieve = async_to_streamed_response_wrapper(
+ action_catalog.retrieve,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ action_catalog.list,
+ )
diff --git a/src/mobilerun_sdk/resources/workflows/actions/__init__.py b/src/mobilerun_sdk/resources/workflows/actions/__init__.py
new file mode 100644
index 0000000..f4307e4
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/actions/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .actions import (
+ ActionsResource,
+ AsyncActionsResource,
+ ActionsResourceWithRawResponse,
+ AsyncActionsResourceWithRawResponse,
+ ActionsResourceWithStreamingResponse,
+ AsyncActionsResourceWithStreamingResponse,
+)
+from .services import (
+ ServicesResource,
+ AsyncServicesResource,
+ ServicesResourceWithRawResponse,
+ AsyncServicesResourceWithRawResponse,
+ ServicesResourceWithStreamingResponse,
+ AsyncServicesResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "ServicesResource",
+ "AsyncServicesResource",
+ "ServicesResourceWithRawResponse",
+ "AsyncServicesResourceWithRawResponse",
+ "ServicesResourceWithStreamingResponse",
+ "AsyncServicesResourceWithStreamingResponse",
+ "ActionsResource",
+ "AsyncActionsResource",
+ "ActionsResourceWithRawResponse",
+ "AsyncActionsResourceWithRawResponse",
+ "ActionsResourceWithStreamingResponse",
+ "AsyncActionsResourceWithStreamingResponse",
+]
diff --git a/src/mobilerun_sdk/resources/workflows/actions/actions.py b/src/mobilerun_sdk/resources/workflows/actions/actions.py
new file mode 100644
index 0000000..2b4723a
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/actions/actions.py
@@ -0,0 +1,592 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Optional
+from typing_extensions import Literal
+
+import httpx
+
+from .services import (
+ ServicesResource,
+ AsyncServicesResource,
+ ServicesResourceWithRawResponse,
+ AsyncServicesResourceWithRawResponse,
+ ServicesResourceWithStreamingResponse,
+ AsyncServicesResourceWithStreamingResponse,
+)
+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.workflows import action_list_params, action_create_params, action_update_params
+from ....types.workflows.action_list_response import ActionListResponse
+from ....types.workflows.action_create_response import ActionCreateResponse
+from ....types.workflows.action_delete_response import ActionDeleteResponse
+from ....types.workflows.action_update_response import ActionUpdateResponse
+from ....types.workflows.action_retrieve_response import ActionRetrieveResponse
+
+__all__ = ["ActionsResource", "AsyncActionsResource"]
+
+
+class ActionsResource(SyncAPIResource):
+ @cached_property
+ def services(self) -> ServicesResource:
+ return ServicesResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> ActionsResourceWithRawResponse:
+ """
+ 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 ActionsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ActionsResourceWithStreamingResponse:
+ """
+ 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 ActionsResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ catalog_entry_id: str,
+ name: str,
+ description: str | Omit = omit,
+ params: Dict[str, Optional[object]] | 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,
+ ) -> ActionCreateResponse:
+ """
+ Create an action
+
+ 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._post(
+ "/actions",
+ body=maybe_transform(
+ {
+ "catalog_entry_id": catalog_entry_id,
+ "name": name,
+ "description": description,
+ "params": params,
+ },
+ action_create_params.ActionCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionCreateResponse,
+ )
+
+ def retrieve(
+ self,
+ action_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,
+ ) -> ActionRetrieveResponse:
+ """
+ Get an action
+
+ 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 action_id:
+ raise ValueError(f"Expected a non-empty value for `action_id` but received {action_id!r}")
+ return self._get(
+ path_template("/actions/{action_id}", action_id=action_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionRetrieveResponse,
+ )
+
+ def update(
+ self,
+ action_id: str,
+ *,
+ description: str | Omit = omit,
+ name: str | Omit = omit,
+ params: Dict[str, Optional[object]] | 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,
+ ) -> ActionUpdateResponse:
+ """
+ Update an action
+
+ 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 action_id:
+ raise ValueError(f"Expected a non-empty value for `action_id` but received {action_id!r}")
+ return self._patch(
+ path_template("/actions/{action_id}", action_id=action_id),
+ body=maybe_transform(
+ {
+ "description": description,
+ "name": name,
+ "params": params,
+ },
+ action_update_params.ActionUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionUpdateResponse,
+ )
+
+ def list(
+ self,
+ *,
+ order_by: Literal["name", "createdAt", "updatedAt"] | Omit = omit,
+ order_by_direction: Literal["asc", "desc"] | Omit = omit,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ search: str | Omit = omit,
+ service: Literal["tasks_api", "devices_api", "agents_api", "webhooks"] | 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,
+ ) -> ActionListResponse:
+ """
+ List actions
+
+ 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(
+ "/actions",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "order_by": order_by,
+ "order_by_direction": order_by_direction,
+ "page": page,
+ "page_size": page_size,
+ "search": search,
+ "service": service,
+ },
+ action_list_params.ActionListParams,
+ ),
+ ),
+ cast_to=ActionListResponse,
+ )
+
+ def delete(
+ self,
+ action_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,
+ ) -> ActionDeleteResponse:
+ """
+ Delete an action
+
+ 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 action_id:
+ raise ValueError(f"Expected a non-empty value for `action_id` but received {action_id!r}")
+ return self._delete(
+ path_template("/actions/{action_id}", action_id=action_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionDeleteResponse,
+ )
+
+
+class AsyncActionsResource(AsyncAPIResource):
+ @cached_property
+ def services(self) -> AsyncServicesResource:
+ return AsyncServicesResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncActionsResourceWithRawResponse:
+ """
+ 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 AsyncActionsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncActionsResourceWithStreamingResponse:
+ """
+ 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 AsyncActionsResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ catalog_entry_id: str,
+ name: str,
+ description: str | Omit = omit,
+ params: Dict[str, Optional[object]] | 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,
+ ) -> ActionCreateResponse:
+ """
+ Create an action
+
+ 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._post(
+ "/actions",
+ body=await async_maybe_transform(
+ {
+ "catalog_entry_id": catalog_entry_id,
+ "name": name,
+ "description": description,
+ "params": params,
+ },
+ action_create_params.ActionCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionCreateResponse,
+ )
+
+ async def retrieve(
+ self,
+ action_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,
+ ) -> ActionRetrieveResponse:
+ """
+ Get an action
+
+ 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 action_id:
+ raise ValueError(f"Expected a non-empty value for `action_id` but received {action_id!r}")
+ return await self._get(
+ path_template("/actions/{action_id}", action_id=action_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionRetrieveResponse,
+ )
+
+ async def update(
+ self,
+ action_id: str,
+ *,
+ description: str | Omit = omit,
+ name: str | Omit = omit,
+ params: Dict[str, Optional[object]] | 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,
+ ) -> ActionUpdateResponse:
+ """
+ Update an action
+
+ 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 action_id:
+ raise ValueError(f"Expected a non-empty value for `action_id` but received {action_id!r}")
+ return await self._patch(
+ path_template("/actions/{action_id}", action_id=action_id),
+ body=await async_maybe_transform(
+ {
+ "description": description,
+ "name": name,
+ "params": params,
+ },
+ action_update_params.ActionUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionUpdateResponse,
+ )
+
+ async def list(
+ self,
+ *,
+ order_by: Literal["name", "createdAt", "updatedAt"] | Omit = omit,
+ order_by_direction: Literal["asc", "desc"] | Omit = omit,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ search: str | Omit = omit,
+ service: Literal["tasks_api", "devices_api", "agents_api", "webhooks"] | 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,
+ ) -> ActionListResponse:
+ """
+ List actions
+
+ 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(
+ "/actions",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "order_by": order_by,
+ "order_by_direction": order_by_direction,
+ "page": page,
+ "page_size": page_size,
+ "search": search,
+ "service": service,
+ },
+ action_list_params.ActionListParams,
+ ),
+ ),
+ cast_to=ActionListResponse,
+ )
+
+ async def delete(
+ self,
+ action_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,
+ ) -> ActionDeleteResponse:
+ """
+ Delete an action
+
+ 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 action_id:
+ raise ValueError(f"Expected a non-empty value for `action_id` but received {action_id!r}")
+ return await self._delete(
+ path_template("/actions/{action_id}", action_id=action_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionDeleteResponse,
+ )
+
+
+class ActionsResourceWithRawResponse:
+ def __init__(self, actions: ActionsResource) -> None:
+ self._actions = actions
+
+ self.create = to_raw_response_wrapper(
+ actions.create,
+ )
+ self.retrieve = to_raw_response_wrapper(
+ actions.retrieve,
+ )
+ self.update = to_raw_response_wrapper(
+ actions.update,
+ )
+ self.list = to_raw_response_wrapper(
+ actions.list,
+ )
+ self.delete = to_raw_response_wrapper(
+ actions.delete,
+ )
+
+ @cached_property
+ def services(self) -> ServicesResourceWithRawResponse:
+ return ServicesResourceWithRawResponse(self._actions.services)
+
+
+class AsyncActionsResourceWithRawResponse:
+ def __init__(self, actions: AsyncActionsResource) -> None:
+ self._actions = actions
+
+ self.create = async_to_raw_response_wrapper(
+ actions.create,
+ )
+ self.retrieve = async_to_raw_response_wrapper(
+ actions.retrieve,
+ )
+ self.update = async_to_raw_response_wrapper(
+ actions.update,
+ )
+ self.list = async_to_raw_response_wrapper(
+ actions.list,
+ )
+ self.delete = async_to_raw_response_wrapper(
+ actions.delete,
+ )
+
+ @cached_property
+ def services(self) -> AsyncServicesResourceWithRawResponse:
+ return AsyncServicesResourceWithRawResponse(self._actions.services)
+
+
+class ActionsResourceWithStreamingResponse:
+ def __init__(self, actions: ActionsResource) -> None:
+ self._actions = actions
+
+ self.create = to_streamed_response_wrapper(
+ actions.create,
+ )
+ self.retrieve = to_streamed_response_wrapper(
+ actions.retrieve,
+ )
+ self.update = to_streamed_response_wrapper(
+ actions.update,
+ )
+ self.list = to_streamed_response_wrapper(
+ actions.list,
+ )
+ self.delete = to_streamed_response_wrapper(
+ actions.delete,
+ )
+
+ @cached_property
+ def services(self) -> ServicesResourceWithStreamingResponse:
+ return ServicesResourceWithStreamingResponse(self._actions.services)
+
+
+class AsyncActionsResourceWithStreamingResponse:
+ def __init__(self, actions: AsyncActionsResource) -> None:
+ self._actions = actions
+
+ self.create = async_to_streamed_response_wrapper(
+ actions.create,
+ )
+ self.retrieve = async_to_streamed_response_wrapper(
+ actions.retrieve,
+ )
+ self.update = async_to_streamed_response_wrapper(
+ actions.update,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ actions.list,
+ )
+ self.delete = async_to_streamed_response_wrapper(
+ actions.delete,
+ )
+
+ @cached_property
+ def services(self) -> AsyncServicesResourceWithStreamingResponse:
+ return AsyncServicesResourceWithStreamingResponse(self._actions.services)
diff --git a/src/mobilerun_sdk/resources/workflows/actions/services.py b/src/mobilerun_sdk/resources/workflows/actions/services.py
new file mode 100644
index 0000000..fd46c48
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/actions/services.py
@@ -0,0 +1,215 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import httpx
+
+from ...._types import Body, Query, Headers, NotGiven, not_given
+from ...._utils import path_template
+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.workflows.actions.service_list_response import ServiceListResponse
+from ....types.workflows.actions.service_list_methods_response import ServiceListMethodsResponse
+
+__all__ = ["ServicesResource", "AsyncServicesResource"]
+
+
+class ServicesResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ServicesResourceWithRawResponse:
+ """
+ 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 ServicesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ServicesResourceWithStreamingResponse:
+ """
+ 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 ServicesResourceWithStreamingResponse(self)
+
+ def list(
+ 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,
+ ) -> ServiceListResponse:
+ """List available services"""
+ return self._get(
+ "/actions/services",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ServiceListResponse,
+ )
+
+ def list_methods(
+ self,
+ service: 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,
+ ) -> ServiceListMethodsResponse:
+ """
+ List allowed methods for a service
+
+ 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 service:
+ raise ValueError(f"Expected a non-empty value for `service` but received {service!r}")
+ return self._get(
+ path_template("/actions/services/{service}/methods", service=service),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ServiceListMethodsResponse,
+ )
+
+
+class AsyncServicesResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncServicesResourceWithRawResponse:
+ """
+ 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 AsyncServicesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncServicesResourceWithStreamingResponse:
+ """
+ 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 AsyncServicesResourceWithStreamingResponse(self)
+
+ async def list(
+ 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,
+ ) -> ServiceListResponse:
+ """List available services"""
+ return await self._get(
+ "/actions/services",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ServiceListResponse,
+ )
+
+ async def list_methods(
+ self,
+ service: 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,
+ ) -> ServiceListMethodsResponse:
+ """
+ List allowed methods for a service
+
+ 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 service:
+ raise ValueError(f"Expected a non-empty value for `service` but received {service!r}")
+ return await self._get(
+ path_template("/actions/services/{service}/methods", service=service),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ServiceListMethodsResponse,
+ )
+
+
+class ServicesResourceWithRawResponse:
+ def __init__(self, services: ServicesResource) -> None:
+ self._services = services
+
+ self.list = to_raw_response_wrapper(
+ services.list,
+ )
+ self.list_methods = to_raw_response_wrapper(
+ services.list_methods,
+ )
+
+
+class AsyncServicesResourceWithRawResponse:
+ def __init__(self, services: AsyncServicesResource) -> None:
+ self._services = services
+
+ self.list = async_to_raw_response_wrapper(
+ services.list,
+ )
+ self.list_methods = async_to_raw_response_wrapper(
+ services.list_methods,
+ )
+
+
+class ServicesResourceWithStreamingResponse:
+ def __init__(self, services: ServicesResource) -> None:
+ self._services = services
+
+ self.list = to_streamed_response_wrapper(
+ services.list,
+ )
+ self.list_methods = to_streamed_response_wrapper(
+ services.list_methods,
+ )
+
+
+class AsyncServicesResourceWithStreamingResponse:
+ def __init__(self, services: AsyncServicesResource) -> None:
+ self._services = services
+
+ self.list = async_to_streamed_response_wrapper(
+ services.list,
+ )
+ self.list_methods = async_to_streamed_response_wrapper(
+ services.list_methods,
+ )
diff --git a/src/mobilerun_sdk/resources/workflows/events/__init__.py b/src/mobilerun_sdk/resources/workflows/events/__init__.py
new file mode 100644
index 0000000..2c1e382
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/events/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .events import (
+ EventsResource,
+ AsyncEventsResource,
+ EventsResourceWithRawResponse,
+ AsyncEventsResourceWithRawResponse,
+ EventsResourceWithStreamingResponse,
+ AsyncEventsResourceWithStreamingResponse,
+)
+from .catalog import (
+ CatalogResource,
+ AsyncCatalogResource,
+ CatalogResourceWithRawResponse,
+ AsyncCatalogResourceWithRawResponse,
+ CatalogResourceWithStreamingResponse,
+ AsyncCatalogResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "CatalogResource",
+ "AsyncCatalogResource",
+ "CatalogResourceWithRawResponse",
+ "AsyncCatalogResourceWithRawResponse",
+ "CatalogResourceWithStreamingResponse",
+ "AsyncCatalogResourceWithStreamingResponse",
+ "EventsResource",
+ "AsyncEventsResource",
+ "EventsResourceWithRawResponse",
+ "AsyncEventsResourceWithRawResponse",
+ "EventsResourceWithStreamingResponse",
+ "AsyncEventsResourceWithStreamingResponse",
+]
diff --git a/src/mobilerun_sdk/resources/workflows/events/catalog.py b/src/mobilerun_sdk/resources/workflows/events/catalog.py
new file mode 100644
index 0000000..73c22cc
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/events/catalog.py
@@ -0,0 +1,267 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+from typing_extensions import Literal
+
+import httpx
+
+from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ...._utils import 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.workflows.events import catalog_list_params, catalog_register_params
+from ....types.workflows.events.catalog_list_response import CatalogListResponse
+from ....types.workflows.events.catalog_register_response import CatalogRegisterResponse
+
+__all__ = ["CatalogResource", "AsyncCatalogResource"]
+
+
+class CatalogResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> CatalogResourceWithRawResponse:
+ """
+ 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 CatalogResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> CatalogResourceWithStreamingResponse:
+ """
+ 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 CatalogResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ source: Literal["device", "system", "webhook"] | 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,
+ ) -> CatalogListResponse:
+ """
+ List event catalog
+
+ 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(
+ "/events/catalog",
+ 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,
+ "source": source,
+ },
+ catalog_list_params.CatalogListParams,
+ ),
+ ),
+ cast_to=CatalogListResponse,
+ )
+
+ def register(
+ self,
+ *,
+ events: Iterable[catalog_register_params.Event],
+ # 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,
+ ) -> CatalogRegisterResponse:
+ """
+ Register event types in the catalog
+
+ 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._post(
+ "/events/catalog/register",
+ body=maybe_transform({"events": events}, catalog_register_params.CatalogRegisterParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=CatalogRegisterResponse,
+ )
+
+
+class AsyncCatalogResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncCatalogResourceWithRawResponse:
+ """
+ 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 AsyncCatalogResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncCatalogResourceWithStreamingResponse:
+ """
+ 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 AsyncCatalogResourceWithStreamingResponse(self)
+
+ async def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ source: Literal["device", "system", "webhook"] | 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,
+ ) -> CatalogListResponse:
+ """
+ List event catalog
+
+ 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(
+ "/events/catalog",
+ 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,
+ "source": source,
+ },
+ catalog_list_params.CatalogListParams,
+ ),
+ ),
+ cast_to=CatalogListResponse,
+ )
+
+ async def register(
+ self,
+ *,
+ events: Iterable[catalog_register_params.Event],
+ # 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,
+ ) -> CatalogRegisterResponse:
+ """
+ Register event types in the catalog
+
+ 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._post(
+ "/events/catalog/register",
+ body=await async_maybe_transform({"events": events}, catalog_register_params.CatalogRegisterParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=CatalogRegisterResponse,
+ )
+
+
+class CatalogResourceWithRawResponse:
+ def __init__(self, catalog: CatalogResource) -> None:
+ self._catalog = catalog
+
+ self.list = to_raw_response_wrapper(
+ catalog.list,
+ )
+ self.register = to_raw_response_wrapper(
+ catalog.register,
+ )
+
+
+class AsyncCatalogResourceWithRawResponse:
+ def __init__(self, catalog: AsyncCatalogResource) -> None:
+ self._catalog = catalog
+
+ self.list = async_to_raw_response_wrapper(
+ catalog.list,
+ )
+ self.register = async_to_raw_response_wrapper(
+ catalog.register,
+ )
+
+
+class CatalogResourceWithStreamingResponse:
+ def __init__(self, catalog: CatalogResource) -> None:
+ self._catalog = catalog
+
+ self.list = to_streamed_response_wrapper(
+ catalog.list,
+ )
+ self.register = to_streamed_response_wrapper(
+ catalog.register,
+ )
+
+
+class AsyncCatalogResourceWithStreamingResponse:
+ def __init__(self, catalog: AsyncCatalogResource) -> None:
+ self._catalog = catalog
+
+ self.list = async_to_streamed_response_wrapper(
+ catalog.list,
+ )
+ self.register = async_to_streamed_response_wrapper(
+ catalog.register,
+ )
diff --git a/src/mobilerun_sdk/resources/workflows/events/events.py b/src/mobilerun_sdk/resources/workflows/events/events.py
new file mode 100644
index 0000000..09d9238
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/events/events.py
@@ -0,0 +1,316 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Optional
+
+import httpx
+
+from .catalog import (
+ CatalogResource,
+ AsyncCatalogResource,
+ CatalogResourceWithRawResponse,
+ AsyncCatalogResourceWithRawResponse,
+ CatalogResourceWithStreamingResponse,
+ AsyncCatalogResourceWithStreamingResponse,
+)
+from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ...._utils import 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.workflows import event_ingest_params, event_dry_run_params
+from ....types.workflows.event_ingest_response import EventIngestResponse
+from ....types.workflows.event_dry_run_response import EventDryRunResponse
+
+__all__ = ["EventsResource", "AsyncEventsResource"]
+
+
+class EventsResource(SyncAPIResource):
+ @cached_property
+ def catalog(self) -> CatalogResource:
+ return CatalogResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> EventsResourceWithRawResponse:
+ """
+ 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 EventsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> EventsResourceWithStreamingResponse:
+ """
+ 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 EventsResourceWithStreamingResponse(self)
+
+ def dry_run(
+ self,
+ *,
+ event_type: str,
+ device_id: str | Omit = omit,
+ payload: Dict[str, Optional[object]] | 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,
+ ) -> EventDryRunResponse:
+ """Simulate an event against all configured flows.
+
+ Returns which flows would match
+ and what actions would run, without storing the event or enqueuing jobs.
+
+ 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._post(
+ "/events/dry-run",
+ body=maybe_transform(
+ {
+ "event_type": event_type,
+ "device_id": device_id,
+ "payload": payload,
+ },
+ event_dry_run_params.EventDryRunParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=EventDryRunResponse,
+ )
+
+ def ingest(
+ self,
+ *,
+ event_type: str,
+ device_id: str | Omit = omit,
+ payload: Dict[str, Optional[object]] | 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,
+ ) -> EventIngestResponse:
+ """Ingest an event for trigger evaluation.
+
+ Returns immediately with 202 Accepted.
+
+ 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._post(
+ "/events/ingest",
+ body=maybe_transform(
+ {
+ "event_type": event_type,
+ "device_id": device_id,
+ "payload": payload,
+ },
+ event_ingest_params.EventIngestParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=EventIngestResponse,
+ )
+
+
+class AsyncEventsResource(AsyncAPIResource):
+ @cached_property
+ def catalog(self) -> AsyncCatalogResource:
+ return AsyncCatalogResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncEventsResourceWithRawResponse:
+ """
+ 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 AsyncEventsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncEventsResourceWithStreamingResponse:
+ """
+ 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 AsyncEventsResourceWithStreamingResponse(self)
+
+ async def dry_run(
+ self,
+ *,
+ event_type: str,
+ device_id: str | Omit = omit,
+ payload: Dict[str, Optional[object]] | 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,
+ ) -> EventDryRunResponse:
+ """Simulate an event against all configured flows.
+
+ Returns which flows would match
+ and what actions would run, without storing the event or enqueuing jobs.
+
+ 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._post(
+ "/events/dry-run",
+ body=await async_maybe_transform(
+ {
+ "event_type": event_type,
+ "device_id": device_id,
+ "payload": payload,
+ },
+ event_dry_run_params.EventDryRunParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=EventDryRunResponse,
+ )
+
+ async def ingest(
+ self,
+ *,
+ event_type: str,
+ device_id: str | Omit = omit,
+ payload: Dict[str, Optional[object]] | 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,
+ ) -> EventIngestResponse:
+ """Ingest an event for trigger evaluation.
+
+ Returns immediately with 202 Accepted.
+
+ 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._post(
+ "/events/ingest",
+ body=await async_maybe_transform(
+ {
+ "event_type": event_type,
+ "device_id": device_id,
+ "payload": payload,
+ },
+ event_ingest_params.EventIngestParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=EventIngestResponse,
+ )
+
+
+class EventsResourceWithRawResponse:
+ def __init__(self, events: EventsResource) -> None:
+ self._events = events
+
+ self.dry_run = to_raw_response_wrapper(
+ events.dry_run,
+ )
+ self.ingest = to_raw_response_wrapper(
+ events.ingest,
+ )
+
+ @cached_property
+ def catalog(self) -> CatalogResourceWithRawResponse:
+ return CatalogResourceWithRawResponse(self._events.catalog)
+
+
+class AsyncEventsResourceWithRawResponse:
+ def __init__(self, events: AsyncEventsResource) -> None:
+ self._events = events
+
+ self.dry_run = async_to_raw_response_wrapper(
+ events.dry_run,
+ )
+ self.ingest = async_to_raw_response_wrapper(
+ events.ingest,
+ )
+
+ @cached_property
+ def catalog(self) -> AsyncCatalogResourceWithRawResponse:
+ return AsyncCatalogResourceWithRawResponse(self._events.catalog)
+
+
+class EventsResourceWithStreamingResponse:
+ def __init__(self, events: EventsResource) -> None:
+ self._events = events
+
+ self.dry_run = to_streamed_response_wrapper(
+ events.dry_run,
+ )
+ self.ingest = to_streamed_response_wrapper(
+ events.ingest,
+ )
+
+ @cached_property
+ def catalog(self) -> CatalogResourceWithStreamingResponse:
+ return CatalogResourceWithStreamingResponse(self._events.catalog)
+
+
+class AsyncEventsResourceWithStreamingResponse:
+ def __init__(self, events: AsyncEventsResource) -> None:
+ self._events = events
+
+ self.dry_run = async_to_streamed_response_wrapper(
+ events.dry_run,
+ )
+ self.ingest = async_to_streamed_response_wrapper(
+ events.ingest,
+ )
+
+ @cached_property
+ def catalog(self) -> AsyncCatalogResourceWithStreamingResponse:
+ return AsyncCatalogResourceWithStreamingResponse(self._events.catalog)
diff --git a/src/mobilerun_sdk/resources/workflows/executions.py b/src/mobilerun_sdk/resources/workflows/executions.py
new file mode 100644
index 0000000..cb5a0dd
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/executions.py
@@ -0,0 +1,402 @@
+# 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 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.workflows import execution_list_params, execution_get_metrics_params
+from ...types.workflows.execution_list_response import ExecutionListResponse
+from ...types.workflows.execution_retrieve_response import ExecutionRetrieveResponse
+from ...types.workflows.execution_get_metrics_response import ExecutionGetMetricsResponse
+
+__all__ = ["ExecutionsResource", "AsyncExecutionsResource"]
+
+
+class ExecutionsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ExecutionsResourceWithRawResponse:
+ """
+ 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 ExecutionsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ExecutionsResourceWithStreamingResponse:
+ """
+ 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 ExecutionsResourceWithStreamingResponse(self)
+
+ def retrieve(
+ self,
+ execution_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,
+ ) -> ExecutionRetrieveResponse:
+ """
+ Get execution details
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not execution_id:
+ raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}")
+ return self._get(
+ path_template("/executions/{execution_id}", execution_id=execution_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExecutionRetrieveResponse,
+ )
+
+ def list(
+ self,
+ *,
+ flow_id: str | Omit = omit,
+ from_: Optional[str] | Omit = omit,
+ order_by: Literal["startedAt", "finishedAt", "status"] | Omit = omit,
+ order_by_direction: Literal["asc", "desc"] | Omit = omit,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ search: str | Omit = omit,
+ status: Literal["pending", "running", "success", "failed"] | Omit = omit,
+ to: Optional[str] | Omit = omit,
+ trigger_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,
+ ) -> ExecutionListResponse:
+ """
+ List flow executions
+
+ 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(
+ "/executions",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "flow_id": flow_id,
+ "from_": from_,
+ "order_by": order_by,
+ "order_by_direction": order_by_direction,
+ "page": page,
+ "page_size": page_size,
+ "search": search,
+ "status": status,
+ "to": to,
+ "trigger_id": trigger_id,
+ },
+ execution_list_params.ExecutionListParams,
+ ),
+ ),
+ cast_to=ExecutionListResponse,
+ )
+
+ def get_metrics(
+ self,
+ *,
+ flow_id: str | Omit = omit,
+ from_: Optional[str] | Omit = omit,
+ to: Optional[str] | Omit = omit,
+ trigger_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,
+ ) -> ExecutionGetMetricsResponse:
+ """
+ Get execution metrics
+
+ 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(
+ "/executions/metrics",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "flow_id": flow_id,
+ "from_": from_,
+ "to": to,
+ "trigger_id": trigger_id,
+ },
+ execution_get_metrics_params.ExecutionGetMetricsParams,
+ ),
+ ),
+ cast_to=ExecutionGetMetricsResponse,
+ )
+
+
+class AsyncExecutionsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncExecutionsResourceWithRawResponse:
+ """
+ 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 AsyncExecutionsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncExecutionsResourceWithStreamingResponse:
+ """
+ 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 AsyncExecutionsResourceWithStreamingResponse(self)
+
+ async def retrieve(
+ self,
+ execution_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,
+ ) -> ExecutionRetrieveResponse:
+ """
+ Get execution details
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not execution_id:
+ raise ValueError(f"Expected a non-empty value for `execution_id` but received {execution_id!r}")
+ return await self._get(
+ path_template("/executions/{execution_id}", execution_id=execution_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExecutionRetrieveResponse,
+ )
+
+ async def list(
+ self,
+ *,
+ flow_id: str | Omit = omit,
+ from_: Optional[str] | Omit = omit,
+ order_by: Literal["startedAt", "finishedAt", "status"] | Omit = omit,
+ order_by_direction: Literal["asc", "desc"] | Omit = omit,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ search: str | Omit = omit,
+ status: Literal["pending", "running", "success", "failed"] | Omit = omit,
+ to: Optional[str] | Omit = omit,
+ trigger_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,
+ ) -> ExecutionListResponse:
+ """
+ List flow executions
+
+ 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(
+ "/executions",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "flow_id": flow_id,
+ "from_": from_,
+ "order_by": order_by,
+ "order_by_direction": order_by_direction,
+ "page": page,
+ "page_size": page_size,
+ "search": search,
+ "status": status,
+ "to": to,
+ "trigger_id": trigger_id,
+ },
+ execution_list_params.ExecutionListParams,
+ ),
+ ),
+ cast_to=ExecutionListResponse,
+ )
+
+ async def get_metrics(
+ self,
+ *,
+ flow_id: str | Omit = omit,
+ from_: Optional[str] | Omit = omit,
+ to: Optional[str] | Omit = omit,
+ trigger_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,
+ ) -> ExecutionGetMetricsResponse:
+ """
+ Get execution metrics
+
+ 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(
+ "/executions/metrics",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "flow_id": flow_id,
+ "from_": from_,
+ "to": to,
+ "trigger_id": trigger_id,
+ },
+ execution_get_metrics_params.ExecutionGetMetricsParams,
+ ),
+ ),
+ cast_to=ExecutionGetMetricsResponse,
+ )
+
+
+class ExecutionsResourceWithRawResponse:
+ def __init__(self, executions: ExecutionsResource) -> None:
+ self._executions = executions
+
+ self.retrieve = to_raw_response_wrapper(
+ executions.retrieve,
+ )
+ self.list = to_raw_response_wrapper(
+ executions.list,
+ )
+ self.get_metrics = to_raw_response_wrapper(
+ executions.get_metrics,
+ )
+
+
+class AsyncExecutionsResourceWithRawResponse:
+ def __init__(self, executions: AsyncExecutionsResource) -> None:
+ self._executions = executions
+
+ self.retrieve = async_to_raw_response_wrapper(
+ executions.retrieve,
+ )
+ self.list = async_to_raw_response_wrapper(
+ executions.list,
+ )
+ self.get_metrics = async_to_raw_response_wrapper(
+ executions.get_metrics,
+ )
+
+
+class ExecutionsResourceWithStreamingResponse:
+ def __init__(self, executions: ExecutionsResource) -> None:
+ self._executions = executions
+
+ self.retrieve = to_streamed_response_wrapper(
+ executions.retrieve,
+ )
+ self.list = to_streamed_response_wrapper(
+ executions.list,
+ )
+ self.get_metrics = to_streamed_response_wrapper(
+ executions.get_metrics,
+ )
+
+
+class AsyncExecutionsResourceWithStreamingResponse:
+ def __init__(self, executions: AsyncExecutionsResource) -> None:
+ self._executions = executions
+
+ self.retrieve = async_to_streamed_response_wrapper(
+ executions.retrieve,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ executions.list,
+ )
+ self.get_metrics = async_to_streamed_response_wrapper(
+ executions.get_metrics,
+ )
diff --git a/src/mobilerun_sdk/resources/workflows/flows/__init__.py b/src/mobilerun_sdk/resources/workflows/flows/__init__.py
new file mode 100644
index 0000000..bfeb155
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/flows/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .flows import (
+ FlowsResource,
+ AsyncFlowsResource,
+ FlowsResourceWithRawResponse,
+ AsyncFlowsResourceWithRawResponse,
+ FlowsResourceWithStreamingResponse,
+ AsyncFlowsResourceWithStreamingResponse,
+)
+from .actions import (
+ ActionsResource,
+ AsyncActionsResource,
+ ActionsResourceWithRawResponse,
+ AsyncActionsResourceWithRawResponse,
+ ActionsResourceWithStreamingResponse,
+ AsyncActionsResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "ActionsResource",
+ "AsyncActionsResource",
+ "ActionsResourceWithRawResponse",
+ "AsyncActionsResourceWithRawResponse",
+ "ActionsResourceWithStreamingResponse",
+ "AsyncActionsResourceWithStreamingResponse",
+ "FlowsResource",
+ "AsyncFlowsResource",
+ "FlowsResourceWithRawResponse",
+ "AsyncFlowsResourceWithRawResponse",
+ "FlowsResourceWithStreamingResponse",
+ "AsyncFlowsResourceWithStreamingResponse",
+]
diff --git a/src/mobilerun_sdk/resources/workflows/flows/actions.py b/src/mobilerun_sdk/resources/workflows/flows/actions.py
new file mode 100644
index 0000000..caea3b8
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/flows/actions.py
@@ -0,0 +1,458 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable, Optional
+
+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.workflows.flows import action_add_params, action_replace_params
+from ....types.workflows.flows.action_add_response import ActionAddResponse
+from ....types.workflows.flows.action_list_response import ActionListResponse
+from ....types.workflows.flow_action_overrides_param import FlowActionOverridesParam
+from ....types.workflows.flows.action_remove_response import ActionRemoveResponse
+from ....types.workflows.flow_child_action_input_param import FlowChildActionInputParam
+from ....types.workflows.flows.action_replace_response import ActionReplaceResponse
+
+__all__ = ["ActionsResource", "AsyncActionsResource"]
+
+
+class ActionsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ActionsResourceWithRawResponse:
+ """
+ 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 ActionsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ActionsResourceWithStreamingResponse:
+ """
+ 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 ActionsResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ flow_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,
+ ) -> ActionListResponse:
+ """
+ List actions for a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return self._get(
+ path_template("/flows/{flow_id}/actions", flow_id=flow_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionListResponse,
+ )
+
+ def add(
+ self,
+ flow_id: str,
+ *,
+ action_id: str,
+ position: int,
+ children: Iterable[FlowChildActionInputParam] | Omit = omit,
+ continue_on_error: bool | Omit = omit,
+ device_id: str | Omit = omit,
+ name_override: str | Omit = omit,
+ overrides: Optional[FlowActionOverridesParam] | Omit = omit,
+ parent_flow_action_id: 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,
+ ) -> ActionAddResponse:
+ """
+ Add an action to a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return self._post(
+ path_template("/flows/{flow_id}/actions", flow_id=flow_id),
+ body=maybe_transform(
+ {
+ "action_id": action_id,
+ "position": position,
+ "children": children,
+ "continue_on_error": continue_on_error,
+ "device_id": device_id,
+ "name_override": name_override,
+ "overrides": overrides,
+ "parent_flow_action_id": parent_flow_action_id,
+ },
+ action_add_params.ActionAddParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionAddResponse,
+ )
+
+ def remove(
+ self,
+ flow_action_id: str,
+ *,
+ flow_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,
+ ) -> ActionRemoveResponse:
+ """
+ Remove an action from a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ if not flow_action_id:
+ raise ValueError(f"Expected a non-empty value for `flow_action_id` but received {flow_action_id!r}")
+ return self._delete(
+ path_template("/flows/{flow_id}/actions/{flow_action_id}", flow_id=flow_id, flow_action_id=flow_action_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionRemoveResponse,
+ )
+
+ def replace(
+ self,
+ flow_id: str,
+ *,
+ actions: Iterable[action_replace_params.Action],
+ # 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,
+ ) -> ActionReplaceResponse:
+ """
+ Replace all actions for a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return self._put(
+ path_template("/flows/{flow_id}/actions", flow_id=flow_id),
+ body=maybe_transform({"actions": actions}, action_replace_params.ActionReplaceParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionReplaceResponse,
+ )
+
+
+class AsyncActionsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncActionsResourceWithRawResponse:
+ """
+ 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 AsyncActionsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncActionsResourceWithStreamingResponse:
+ """
+ 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 AsyncActionsResourceWithStreamingResponse(self)
+
+ async def list(
+ self,
+ flow_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,
+ ) -> ActionListResponse:
+ """
+ List actions for a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return await self._get(
+ path_template("/flows/{flow_id}/actions", flow_id=flow_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionListResponse,
+ )
+
+ async def add(
+ self,
+ flow_id: str,
+ *,
+ action_id: str,
+ position: int,
+ children: Iterable[FlowChildActionInputParam] | Omit = omit,
+ continue_on_error: bool | Omit = omit,
+ device_id: str | Omit = omit,
+ name_override: str | Omit = omit,
+ overrides: Optional[FlowActionOverridesParam] | Omit = omit,
+ parent_flow_action_id: 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,
+ ) -> ActionAddResponse:
+ """
+ Add an action to a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return await self._post(
+ path_template("/flows/{flow_id}/actions", flow_id=flow_id),
+ body=await async_maybe_transform(
+ {
+ "action_id": action_id,
+ "position": position,
+ "children": children,
+ "continue_on_error": continue_on_error,
+ "device_id": device_id,
+ "name_override": name_override,
+ "overrides": overrides,
+ "parent_flow_action_id": parent_flow_action_id,
+ },
+ action_add_params.ActionAddParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionAddResponse,
+ )
+
+ async def remove(
+ self,
+ flow_action_id: str,
+ *,
+ flow_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,
+ ) -> ActionRemoveResponse:
+ """
+ Remove an action from a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ if not flow_action_id:
+ raise ValueError(f"Expected a non-empty value for `flow_action_id` but received {flow_action_id!r}")
+ return await self._delete(
+ path_template("/flows/{flow_id}/actions/{flow_action_id}", flow_id=flow_id, flow_action_id=flow_action_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionRemoveResponse,
+ )
+
+ async def replace(
+ self,
+ flow_id: str,
+ *,
+ actions: Iterable[action_replace_params.Action],
+ # 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,
+ ) -> ActionReplaceResponse:
+ """
+ Replace all actions for a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return await self._put(
+ path_template("/flows/{flow_id}/actions", flow_id=flow_id),
+ body=await async_maybe_transform({"actions": actions}, action_replace_params.ActionReplaceParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ActionReplaceResponse,
+ )
+
+
+class ActionsResourceWithRawResponse:
+ def __init__(self, actions: ActionsResource) -> None:
+ self._actions = actions
+
+ self.list = to_raw_response_wrapper(
+ actions.list,
+ )
+ self.add = to_raw_response_wrapper(
+ actions.add,
+ )
+ self.remove = to_raw_response_wrapper(
+ actions.remove,
+ )
+ self.replace = to_raw_response_wrapper(
+ actions.replace,
+ )
+
+
+class AsyncActionsResourceWithRawResponse:
+ def __init__(self, actions: AsyncActionsResource) -> None:
+ self._actions = actions
+
+ self.list = async_to_raw_response_wrapper(
+ actions.list,
+ )
+ self.add = async_to_raw_response_wrapper(
+ actions.add,
+ )
+ self.remove = async_to_raw_response_wrapper(
+ actions.remove,
+ )
+ self.replace = async_to_raw_response_wrapper(
+ actions.replace,
+ )
+
+
+class ActionsResourceWithStreamingResponse:
+ def __init__(self, actions: ActionsResource) -> None:
+ self._actions = actions
+
+ self.list = to_streamed_response_wrapper(
+ actions.list,
+ )
+ self.add = to_streamed_response_wrapper(
+ actions.add,
+ )
+ self.remove = to_streamed_response_wrapper(
+ actions.remove,
+ )
+ self.replace = to_streamed_response_wrapper(
+ actions.replace,
+ )
+
+
+class AsyncActionsResourceWithStreamingResponse:
+ def __init__(self, actions: AsyncActionsResource) -> None:
+ self._actions = actions
+
+ self.list = async_to_streamed_response_wrapper(
+ actions.list,
+ )
+ self.add = async_to_streamed_response_wrapper(
+ actions.add,
+ )
+ self.remove = async_to_streamed_response_wrapper(
+ actions.remove,
+ )
+ self.replace = async_to_streamed_response_wrapper(
+ actions.replace,
+ )
diff --git a/src/mobilerun_sdk/resources/workflows/flows/flows.py b/src/mobilerun_sdk/resources/workflows/flows/flows.py
new file mode 100644
index 0000000..d6881fa
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/flows/flows.py
@@ -0,0 +1,790 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import List, Iterable, Optional
+from typing_extensions import Literal
+
+import httpx
+
+from .actions import (
+ ActionsResource,
+ AsyncActionsResource,
+ ActionsResourceWithRawResponse,
+ AsyncActionsResourceWithRawResponse,
+ ActionsResourceWithStreamingResponse,
+ AsyncActionsResourceWithStreamingResponse,
+)
+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.workflows import flow_list_params, flow_clone_params, flow_create_params, flow_update_params
+from ....types.workflows.flow_list_response import FlowListResponse
+from ....types.workflows.flow_clone_response import FlowCloneResponse
+from ....types.workflows.flow_create_response import FlowCreateResponse
+from ....types.workflows.flow_delete_response import FlowDeleteResponse
+from ....types.workflows.flow_update_response import FlowUpdateResponse
+from ....types.workflows.flow_unblock_response import FlowUnblockResponse
+from ....types.workflows.flow_retrieve_response import FlowRetrieveResponse
+
+__all__ = ["FlowsResource", "AsyncFlowsResource"]
+
+
+class FlowsResource(SyncAPIResource):
+ @cached_property
+ def actions(self) -> ActionsResource:
+ return ActionsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> FlowsResourceWithRawResponse:
+ """
+ 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 FlowsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> FlowsResourceWithStreamingResponse:
+ """
+ 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 FlowsResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ actions: Iterable[flow_create_params.Action],
+ name: str,
+ trigger_id: str,
+ cooldown_scope: Literal["flow", "device"] | Omit = omit,
+ cooldown_seconds: Optional[int] | Omit = omit,
+ description: 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,
+ ) -> FlowCreateResponse:
+ """
+ Create a flow
+
+ 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._post(
+ "/flows",
+ body=maybe_transform(
+ {
+ "actions": actions,
+ "name": name,
+ "trigger_id": trigger_id,
+ "cooldown_scope": cooldown_scope,
+ "cooldown_seconds": cooldown_seconds,
+ "description": description,
+ "enabled": enabled,
+ },
+ flow_create_params.FlowCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FlowCreateResponse,
+ )
+
+ def retrieve(
+ self,
+ flow_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,
+ ) -> FlowRetrieveResponse:
+ """
+ Get a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return self._get(
+ path_template("/flows/{flow_id}", flow_id=flow_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FlowRetrieveResponse,
+ )
+
+ def update(
+ self,
+ flow_id: str,
+ *,
+ cooldown_scope: Literal["flow", "device"] | Omit = omit,
+ cooldown_seconds: Optional[int] | Omit = omit,
+ description: str | Omit = omit,
+ enabled: bool | Omit = omit,
+ name: str | Omit = omit,
+ trigger_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,
+ ) -> FlowUpdateResponse:
+ """
+ Update a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return self._patch(
+ path_template("/flows/{flow_id}", flow_id=flow_id),
+ body=maybe_transform(
+ {
+ "cooldown_scope": cooldown_scope,
+ "cooldown_seconds": cooldown_seconds,
+ "description": description,
+ "enabled": enabled,
+ "name": name,
+ "trigger_id": trigger_id,
+ },
+ flow_update_params.FlowUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FlowUpdateResponse,
+ )
+
+ def list(
+ self,
+ *,
+ enabled: Optional[bool] | Omit = omit,
+ order_by: Literal["name", "createdAt", "updatedAt"] | Omit = omit,
+ order_by_direction: Literal["asc", "desc"] | Omit = omit,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ search: str | Omit = omit,
+ status: List[Literal["healthy", "failing", "blocked"]] | Omit = omit,
+ trigger_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,
+ ) -> FlowListResponse:
+ """
+ List flows
+
+ 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(
+ "/flows",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "enabled": enabled,
+ "order_by": order_by,
+ "order_by_direction": order_by_direction,
+ "page": page,
+ "page_size": page_size,
+ "search": search,
+ "status": status,
+ "trigger_id": trigger_id,
+ },
+ flow_list_params.FlowListParams,
+ ),
+ ),
+ cast_to=FlowListResponse,
+ )
+
+ def delete(
+ self,
+ flow_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,
+ ) -> FlowDeleteResponse:
+ """
+ Delete a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return self._delete(
+ path_template("/flows/{flow_id}", flow_id=flow_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FlowDeleteResponse,
+ )
+
+ def clone(
+ self,
+ flow_id: str,
+ *,
+ name: 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,
+ ) -> FlowCloneResponse:
+ """
+ Clone a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return self._post(
+ path_template("/flows/{flow_id}/clone", flow_id=flow_id),
+ body=maybe_transform({"name": name}, flow_clone_params.FlowCloneParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FlowCloneResponse,
+ )
+
+ def unblock(
+ self,
+ flow_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,
+ ) -> FlowUnblockResponse:
+ """Clear a flow's blocked status after fixing the underlying issue.
+
+ Idempotent —
+ safe to call on already-healthy flows.
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return self._post(
+ path_template("/flows/{flow_id}/unblock", flow_id=flow_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FlowUnblockResponse,
+ )
+
+
+class AsyncFlowsResource(AsyncAPIResource):
+ @cached_property
+ def actions(self) -> AsyncActionsResource:
+ return AsyncActionsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncFlowsResourceWithRawResponse:
+ """
+ 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 AsyncFlowsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncFlowsResourceWithStreamingResponse:
+ """
+ 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 AsyncFlowsResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ actions: Iterable[flow_create_params.Action],
+ name: str,
+ trigger_id: str,
+ cooldown_scope: Literal["flow", "device"] | Omit = omit,
+ cooldown_seconds: Optional[int] | Omit = omit,
+ description: 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,
+ ) -> FlowCreateResponse:
+ """
+ Create a flow
+
+ 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._post(
+ "/flows",
+ body=await async_maybe_transform(
+ {
+ "actions": actions,
+ "name": name,
+ "trigger_id": trigger_id,
+ "cooldown_scope": cooldown_scope,
+ "cooldown_seconds": cooldown_seconds,
+ "description": description,
+ "enabled": enabled,
+ },
+ flow_create_params.FlowCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FlowCreateResponse,
+ )
+
+ async def retrieve(
+ self,
+ flow_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,
+ ) -> FlowRetrieveResponse:
+ """
+ Get a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return await self._get(
+ path_template("/flows/{flow_id}", flow_id=flow_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FlowRetrieveResponse,
+ )
+
+ async def update(
+ self,
+ flow_id: str,
+ *,
+ cooldown_scope: Literal["flow", "device"] | Omit = omit,
+ cooldown_seconds: Optional[int] | Omit = omit,
+ description: str | Omit = omit,
+ enabled: bool | Omit = omit,
+ name: str | Omit = omit,
+ trigger_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,
+ ) -> FlowUpdateResponse:
+ """
+ Update a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return await self._patch(
+ path_template("/flows/{flow_id}", flow_id=flow_id),
+ body=await async_maybe_transform(
+ {
+ "cooldown_scope": cooldown_scope,
+ "cooldown_seconds": cooldown_seconds,
+ "description": description,
+ "enabled": enabled,
+ "name": name,
+ "trigger_id": trigger_id,
+ },
+ flow_update_params.FlowUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FlowUpdateResponse,
+ )
+
+ async def list(
+ self,
+ *,
+ enabled: Optional[bool] | Omit = omit,
+ order_by: Literal["name", "createdAt", "updatedAt"] | Omit = omit,
+ order_by_direction: Literal["asc", "desc"] | Omit = omit,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ search: str | Omit = omit,
+ status: List[Literal["healthy", "failing", "blocked"]] | Omit = omit,
+ trigger_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,
+ ) -> FlowListResponse:
+ """
+ List flows
+
+ 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(
+ "/flows",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "enabled": enabled,
+ "order_by": order_by,
+ "order_by_direction": order_by_direction,
+ "page": page,
+ "page_size": page_size,
+ "search": search,
+ "status": status,
+ "trigger_id": trigger_id,
+ },
+ flow_list_params.FlowListParams,
+ ),
+ ),
+ cast_to=FlowListResponse,
+ )
+
+ async def delete(
+ self,
+ flow_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,
+ ) -> FlowDeleteResponse:
+ """
+ Delete a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return await self._delete(
+ path_template("/flows/{flow_id}", flow_id=flow_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FlowDeleteResponse,
+ )
+
+ async def clone(
+ self,
+ flow_id: str,
+ *,
+ name: 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,
+ ) -> FlowCloneResponse:
+ """
+ Clone a flow
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return await self._post(
+ path_template("/flows/{flow_id}/clone", flow_id=flow_id),
+ body=await async_maybe_transform({"name": name}, flow_clone_params.FlowCloneParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FlowCloneResponse,
+ )
+
+ async def unblock(
+ self,
+ flow_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,
+ ) -> FlowUnblockResponse:
+ """Clear a flow's blocked status after fixing the underlying issue.
+
+ Idempotent —
+ safe to call on already-healthy flows.
+
+ 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 flow_id:
+ raise ValueError(f"Expected a non-empty value for `flow_id` but received {flow_id!r}")
+ return await self._post(
+ path_template("/flows/{flow_id}/unblock", flow_id=flow_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FlowUnblockResponse,
+ )
+
+
+class FlowsResourceWithRawResponse:
+ def __init__(self, flows: FlowsResource) -> None:
+ self._flows = flows
+
+ self.create = to_raw_response_wrapper(
+ flows.create,
+ )
+ self.retrieve = to_raw_response_wrapper(
+ flows.retrieve,
+ )
+ self.update = to_raw_response_wrapper(
+ flows.update,
+ )
+ self.list = to_raw_response_wrapper(
+ flows.list,
+ )
+ self.delete = to_raw_response_wrapper(
+ flows.delete,
+ )
+ self.clone = to_raw_response_wrapper(
+ flows.clone,
+ )
+ self.unblock = to_raw_response_wrapper(
+ flows.unblock,
+ )
+
+ @cached_property
+ def actions(self) -> ActionsResourceWithRawResponse:
+ return ActionsResourceWithRawResponse(self._flows.actions)
+
+
+class AsyncFlowsResourceWithRawResponse:
+ def __init__(self, flows: AsyncFlowsResource) -> None:
+ self._flows = flows
+
+ self.create = async_to_raw_response_wrapper(
+ flows.create,
+ )
+ self.retrieve = async_to_raw_response_wrapper(
+ flows.retrieve,
+ )
+ self.update = async_to_raw_response_wrapper(
+ flows.update,
+ )
+ self.list = async_to_raw_response_wrapper(
+ flows.list,
+ )
+ self.delete = async_to_raw_response_wrapper(
+ flows.delete,
+ )
+ self.clone = async_to_raw_response_wrapper(
+ flows.clone,
+ )
+ self.unblock = async_to_raw_response_wrapper(
+ flows.unblock,
+ )
+
+ @cached_property
+ def actions(self) -> AsyncActionsResourceWithRawResponse:
+ return AsyncActionsResourceWithRawResponse(self._flows.actions)
+
+
+class FlowsResourceWithStreamingResponse:
+ def __init__(self, flows: FlowsResource) -> None:
+ self._flows = flows
+
+ self.create = to_streamed_response_wrapper(
+ flows.create,
+ )
+ self.retrieve = to_streamed_response_wrapper(
+ flows.retrieve,
+ )
+ self.update = to_streamed_response_wrapper(
+ flows.update,
+ )
+ self.list = to_streamed_response_wrapper(
+ flows.list,
+ )
+ self.delete = to_streamed_response_wrapper(
+ flows.delete,
+ )
+ self.clone = to_streamed_response_wrapper(
+ flows.clone,
+ )
+ self.unblock = to_streamed_response_wrapper(
+ flows.unblock,
+ )
+
+ @cached_property
+ def actions(self) -> ActionsResourceWithStreamingResponse:
+ return ActionsResourceWithStreamingResponse(self._flows.actions)
+
+
+class AsyncFlowsResourceWithStreamingResponse:
+ def __init__(self, flows: AsyncFlowsResource) -> None:
+ self._flows = flows
+
+ self.create = async_to_streamed_response_wrapper(
+ flows.create,
+ )
+ self.retrieve = async_to_streamed_response_wrapper(
+ flows.retrieve,
+ )
+ self.update = async_to_streamed_response_wrapper(
+ flows.update,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ flows.list,
+ )
+ self.delete = async_to_streamed_response_wrapper(
+ flows.delete,
+ )
+ self.clone = async_to_streamed_response_wrapper(
+ flows.clone,
+ )
+ self.unblock = async_to_streamed_response_wrapper(
+ flows.unblock,
+ )
+
+ @cached_property
+ def actions(self) -> AsyncActionsResourceWithStreamingResponse:
+ return AsyncActionsResourceWithStreamingResponse(self._flows.actions)
diff --git a/src/mobilerun_sdk/resources/workflows/secrets.py b/src/mobilerun_sdk/resources/workflows/secrets.py
new file mode 100644
index 0000000..04f2e00
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/secrets.py
@@ -0,0 +1,311 @@
+# 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.workflows import secret_create_params
+from ...types.workflows.secret_list_response import SecretListResponse
+from ...types.workflows.secret_create_response import SecretCreateResponse
+from ...types.workflows.secret_delete_response import SecretDeleteResponse
+
+__all__ = ["SecretsResource", "AsyncSecretsResource"]
+
+
+class SecretsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> SecretsResourceWithRawResponse:
+ """
+ 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 SecretsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> SecretsResourceWithStreamingResponse:
+ """
+ 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 SecretsResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ name: str,
+ value: str,
+ description: 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,
+ ) -> SecretCreateResponse:
+ """
+ Create a user secret (write-only; value cannot be read back)
+
+ 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._post(
+ "/secrets",
+ body=maybe_transform(
+ {
+ "name": name,
+ "value": value,
+ "description": description,
+ },
+ secret_create_params.SecretCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SecretCreateResponse,
+ )
+
+ def list(
+ 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,
+ ) -> SecretListResponse:
+ """List user secrets (metadata only — values never returned)"""
+ return self._get(
+ "/secrets",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SecretListResponse,
+ )
+
+ def delete(
+ self,
+ secret_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,
+ ) -> SecretDeleteResponse:
+ """
+ Delete a user secret
+
+ 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 secret_id:
+ raise ValueError(f"Expected a non-empty value for `secret_id` but received {secret_id!r}")
+ return self._delete(
+ path_template("/secrets/{secret_id}", secret_id=secret_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SecretDeleteResponse,
+ )
+
+
+class AsyncSecretsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncSecretsResourceWithRawResponse:
+ """
+ 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 AsyncSecretsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncSecretsResourceWithStreamingResponse:
+ """
+ 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 AsyncSecretsResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ name: str,
+ value: str,
+ description: 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,
+ ) -> SecretCreateResponse:
+ """
+ Create a user secret (write-only; value cannot be read back)
+
+ 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._post(
+ "/secrets",
+ body=await async_maybe_transform(
+ {
+ "name": name,
+ "value": value,
+ "description": description,
+ },
+ secret_create_params.SecretCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SecretCreateResponse,
+ )
+
+ async def list(
+ 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,
+ ) -> SecretListResponse:
+ """List user secrets (metadata only — values never returned)"""
+ return await self._get(
+ "/secrets",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SecretListResponse,
+ )
+
+ async def delete(
+ self,
+ secret_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,
+ ) -> SecretDeleteResponse:
+ """
+ Delete a user secret
+
+ 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 secret_id:
+ raise ValueError(f"Expected a non-empty value for `secret_id` but received {secret_id!r}")
+ return await self._delete(
+ path_template("/secrets/{secret_id}", secret_id=secret_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SecretDeleteResponse,
+ )
+
+
+class SecretsResourceWithRawResponse:
+ def __init__(self, secrets: SecretsResource) -> None:
+ self._secrets = secrets
+
+ self.create = to_raw_response_wrapper(
+ secrets.create,
+ )
+ self.list = to_raw_response_wrapper(
+ secrets.list,
+ )
+ self.delete = to_raw_response_wrapper(
+ secrets.delete,
+ )
+
+
+class AsyncSecretsResourceWithRawResponse:
+ def __init__(self, secrets: AsyncSecretsResource) -> None:
+ self._secrets = secrets
+
+ self.create = async_to_raw_response_wrapper(
+ secrets.create,
+ )
+ self.list = async_to_raw_response_wrapper(
+ secrets.list,
+ )
+ self.delete = async_to_raw_response_wrapper(
+ secrets.delete,
+ )
+
+
+class SecretsResourceWithStreamingResponse:
+ def __init__(self, secrets: SecretsResource) -> None:
+ self._secrets = secrets
+
+ self.create = to_streamed_response_wrapper(
+ secrets.create,
+ )
+ self.list = to_streamed_response_wrapper(
+ secrets.list,
+ )
+ self.delete = to_streamed_response_wrapper(
+ secrets.delete,
+ )
+
+
+class AsyncSecretsResourceWithStreamingResponse:
+ def __init__(self, secrets: AsyncSecretsResource) -> None:
+ self._secrets = secrets
+
+ self.create = async_to_streamed_response_wrapper(
+ secrets.create,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ secrets.list,
+ )
+ self.delete = async_to_streamed_response_wrapper(
+ secrets.delete,
+ )
diff --git a/src/mobilerun_sdk/resources/agents.py b/src/mobilerun_sdk/resources/workflows/timezones.py
similarity index 60%
rename from src/mobilerun_sdk/resources/agents.py
rename to src/mobilerun_sdk/resources/workflows/timezones.py
index bbe316c..5b7e797 100644
--- a/src/mobilerun_sdk/resources/agents.py
+++ b/src/mobilerun_sdk/resources/workflows/timezones.py
@@ -4,42 +4,40 @@
import httpx
-from .._types import Body, Query, Headers, NotGiven, not_given
-from .._compat import cached_property
-from .._resource import SyncAPIResource, AsyncAPIResource
-from .._response import (
+from ..._types import Body, Query, Headers, NotGiven, not_given
+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.agent_list_response import AgentListResponse
+from ..._base_client import make_request_options
+from ...types.workflows.timezone_list_response import TimezoneListResponse
-__all__ = ["AgentsResource", "AsyncAgentsResource"]
+__all__ = ["TimezonesResource", "AsyncTimezonesResource"]
-class AgentsResource(SyncAPIResource):
- """Agents API"""
-
+class TimezonesResource(SyncAPIResource):
@cached_property
- def with_raw_response(self) -> AgentsResourceWithRawResponse:
+ def with_raw_response(self) -> TimezonesResourceWithRawResponse:
"""
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 AgentsResourceWithRawResponse(self)
+ return TimezonesResourceWithRawResponse(self)
@cached_property
- def with_streaming_response(self) -> AgentsResourceWithStreamingResponse:
+ def with_streaming_response(self) -> TimezonesResourceWithStreamingResponse:
"""
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 AgentsResourceWithStreamingResponse(self)
+ return TimezonesResourceWithStreamingResponse(self)
def list(
self,
@@ -50,38 +48,36 @@ def list(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> AgentListResponse:
- """List all available agents with their default configurations."""
+ ) -> TimezoneListResponse:
+ """List supported IANA timezones"""
return self._get(
- "/agents",
+ "/timezones",
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=AgentListResponse,
+ cast_to=TimezoneListResponse,
)
-class AsyncAgentsResource(AsyncAPIResource):
- """Agents API"""
-
+class AsyncTimezonesResource(AsyncAPIResource):
@cached_property
- def with_raw_response(self) -> AsyncAgentsResourceWithRawResponse:
+ def with_raw_response(self) -> AsyncTimezonesResourceWithRawResponse:
"""
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 AsyncAgentsResourceWithRawResponse(self)
+ return AsyncTimezonesResourceWithRawResponse(self)
@cached_property
- def with_streaming_response(self) -> AsyncAgentsResourceWithStreamingResponse:
+ def with_streaming_response(self) -> AsyncTimezonesResourceWithStreamingResponse:
"""
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 AsyncAgentsResourceWithStreamingResponse(self)
+ return AsyncTimezonesResourceWithStreamingResponse(self)
async def list(
self,
@@ -92,48 +88,48 @@ async def list(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> AgentListResponse:
- """List all available agents with their default configurations."""
+ ) -> TimezoneListResponse:
+ """List supported IANA timezones"""
return await self._get(
- "/agents",
+ "/timezones",
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=AgentListResponse,
+ cast_to=TimezoneListResponse,
)
-class AgentsResourceWithRawResponse:
- def __init__(self, agents: AgentsResource) -> None:
- self._agents = agents
+class TimezonesResourceWithRawResponse:
+ def __init__(self, timezones: TimezonesResource) -> None:
+ self._timezones = timezones
self.list = to_raw_response_wrapper(
- agents.list,
+ timezones.list,
)
-class AsyncAgentsResourceWithRawResponse:
- def __init__(self, agents: AsyncAgentsResource) -> None:
- self._agents = agents
+class AsyncTimezonesResourceWithRawResponse:
+ def __init__(self, timezones: AsyncTimezonesResource) -> None:
+ self._timezones = timezones
self.list = async_to_raw_response_wrapper(
- agents.list,
+ timezones.list,
)
-class AgentsResourceWithStreamingResponse:
- def __init__(self, agents: AgentsResource) -> None:
- self._agents = agents
+class TimezonesResourceWithStreamingResponse:
+ def __init__(self, timezones: TimezonesResource) -> None:
+ self._timezones = timezones
self.list = to_streamed_response_wrapper(
- agents.list,
+ timezones.list,
)
-class AsyncAgentsResourceWithStreamingResponse:
- def __init__(self, agents: AsyncAgentsResource) -> None:
- self._agents = agents
+class AsyncTimezonesResourceWithStreamingResponse:
+ def __init__(self, timezones: AsyncTimezonesResource) -> None:
+ self._timezones = timezones
self.list = async_to_streamed_response_wrapper(
- agents.list,
+ timezones.list,
)
diff --git a/src/mobilerun_sdk/resources/workflows/triggers.py b/src/mobilerun_sdk/resources/workflows/triggers.py
new file mode 100644
index 0000000..99ed8c3
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/triggers.py
@@ -0,0 +1,753 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Optional
+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 ..._base_client import make_request_options
+from ...types.workflows import trigger_fire_params, trigger_list_params, trigger_create_params, trigger_update_params
+from ...types.workflows.trigger_fire_response import TriggerFireResponse
+from ...types.workflows.trigger_list_response import TriggerListResponse
+from ...types.workflows.trigger_create_response import TriggerCreateResponse
+from ...types.workflows.trigger_delete_response import TriggerDeleteResponse
+from ...types.workflows.trigger_update_response import TriggerUpdateResponse
+from ...types.workflows.trigger_retrieve_response import TriggerRetrieveResponse
+
+__all__ = ["TriggersResource", "AsyncTriggersResource"]
+
+
+class TriggersResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> TriggersResourceWithRawResponse:
+ """
+ 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 TriggersResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> TriggersResourceWithStreamingResponse:
+ """
+ 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 TriggersResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ activation: Literal["event", "schedule", "custom"],
+ name: str,
+ conditions: trigger_create_params.Conditions | Omit = omit,
+ custom_payload_schema: Dict[str, object] | Omit = omit,
+ description: str | Omit = omit,
+ event_type: str | Omit = omit,
+ schedule_rule: trigger_create_params.ScheduleRule | Omit = omit,
+ timezone: 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,
+ ) -> TriggerCreateResponse:
+ """
+ Create a trigger
+
+ Args:
+ custom_payload_schema: Optional JSON Schema for validating payloads sent to this custom trigger
+
+ 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(
+ "/triggers",
+ body=maybe_transform(
+ {
+ "activation": activation,
+ "name": name,
+ "conditions": conditions,
+ "custom_payload_schema": custom_payload_schema,
+ "description": description,
+ "event_type": event_type,
+ "schedule_rule": schedule_rule,
+ "timezone": timezone,
+ },
+ trigger_create_params.TriggerCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TriggerCreateResponse,
+ )
+
+ def retrieve(
+ self,
+ trigger_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,
+ ) -> TriggerRetrieveResponse:
+ """
+ Get a trigger
+
+ 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 trigger_id:
+ raise ValueError(f"Expected a non-empty value for `trigger_id` but received {trigger_id!r}")
+ return self._get(
+ path_template("/triggers/{trigger_id}", trigger_id=trigger_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TriggerRetrieveResponse,
+ )
+
+ def update(
+ self,
+ trigger_id: str,
+ *,
+ activation: Literal["event", "schedule", "custom"] | Omit = omit,
+ conditions: trigger_update_params.Conditions | Omit = omit,
+ custom_payload_schema: Optional[Dict[str, object]] | Omit = omit,
+ description: str | Omit = omit,
+ event_type: str | Omit = omit,
+ name: str | Omit = omit,
+ schedule_rule: trigger_update_params.ScheduleRule | Omit = omit,
+ timezone: 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,
+ ) -> TriggerUpdateResponse:
+ """
+ Update a trigger
+
+ Args:
+ custom_payload_schema: Optional JSON Schema for validating payloads sent to this custom trigger
+
+ 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 trigger_id:
+ raise ValueError(f"Expected a non-empty value for `trigger_id` but received {trigger_id!r}")
+ return self._patch(
+ path_template("/triggers/{trigger_id}", trigger_id=trigger_id),
+ body=maybe_transform(
+ {
+ "activation": activation,
+ "conditions": conditions,
+ "custom_payload_schema": custom_payload_schema,
+ "description": description,
+ "event_type": event_type,
+ "name": name,
+ "schedule_rule": schedule_rule,
+ "timezone": timezone,
+ },
+ trigger_update_params.TriggerUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TriggerUpdateResponse,
+ )
+
+ def list(
+ self,
+ *,
+ activation: Literal["event", "schedule", "custom"] | Omit = omit,
+ event_type: str | Omit = omit,
+ order_by: Literal["name", "createdAt", "updatedAt"] | Omit = omit,
+ order_by_direction: Literal["asc", "desc"] | Omit = omit,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ search: 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,
+ ) -> TriggerListResponse:
+ """
+ List triggers
+
+ 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(
+ "/triggers",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "activation": activation,
+ "event_type": event_type,
+ "order_by": order_by,
+ "order_by_direction": order_by_direction,
+ "page": page,
+ "page_size": page_size,
+ "search": search,
+ },
+ trigger_list_params.TriggerListParams,
+ ),
+ ),
+ cast_to=TriggerListResponse,
+ )
+
+ def delete(
+ self,
+ trigger_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,
+ ) -> TriggerDeleteResponse:
+ """
+ Delete a trigger
+
+ 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 trigger_id:
+ raise ValueError(f"Expected a non-empty value for `trigger_id` but received {trigger_id!r}")
+ return self._delete(
+ path_template("/triggers/{trigger_id}", trigger_id=trigger_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TriggerDeleteResponse,
+ )
+
+ def fire(
+ self,
+ trigger_id: str,
+ *,
+ payload: Dict[str, object],
+ 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,
+ ) -> TriggerFireResponse:
+ """
+ Invoke a custom trigger directly with an arbitrary JSON payload.
+
+ Fan-out: a trigger may be referenced by multiple flows (workflows). Firing it
+ enqueues one execution per enabled, non-deleted flow attached to this trigger,
+ each receiving the same payload. The `enqueuedCount` in the response reports how
+ many were enqueued (0 if no flows are attached, or if all matching flows are
+ gated by a cooldown).
+
+ Payload validation:
+
+ - If the trigger has a `customPayloadSchema`, the payload is validated against
+ it (JSON Schema via AJV).
+ - If no schema is configured, the payload only needs to be a JSON object — any
+ keys and values are accepted.
+
+ Only triggers with `activation = "custom"` can be fired through this endpoint;
+ event and schedule triggers return 409.
+
+ Args:
+ payload: Arbitrary JSON object forwarded to every flow attached to this trigger.
+ Validated against the trigger's customPayloadSchema when one is configured;
+ otherwise only "must be a JSON object" is enforced.
+
+ device_id: Optional device scope. When supplied, ownership is verified for the calling user
+ and the value is passed through to each enqueued execution as the default device
+ context.
+
+ 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 trigger_id:
+ raise ValueError(f"Expected a non-empty value for `trigger_id` but received {trigger_id!r}")
+ return self._post(
+ path_template("/triggers/{trigger_id}/fire", trigger_id=trigger_id),
+ body=maybe_transform(
+ {
+ "payload": payload,
+ "device_id": device_id,
+ },
+ trigger_fire_params.TriggerFireParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TriggerFireResponse,
+ )
+
+
+class AsyncTriggersResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncTriggersResourceWithRawResponse:
+ """
+ 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 AsyncTriggersResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncTriggersResourceWithStreamingResponse:
+ """
+ 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 AsyncTriggersResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ activation: Literal["event", "schedule", "custom"],
+ name: str,
+ conditions: trigger_create_params.Conditions | Omit = omit,
+ custom_payload_schema: Dict[str, object] | Omit = omit,
+ description: str | Omit = omit,
+ event_type: str | Omit = omit,
+ schedule_rule: trigger_create_params.ScheduleRule | Omit = omit,
+ timezone: 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,
+ ) -> TriggerCreateResponse:
+ """
+ Create a trigger
+
+ Args:
+ custom_payload_schema: Optional JSON Schema for validating payloads sent to this custom trigger
+
+ 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(
+ "/triggers",
+ body=await async_maybe_transform(
+ {
+ "activation": activation,
+ "name": name,
+ "conditions": conditions,
+ "custom_payload_schema": custom_payload_schema,
+ "description": description,
+ "event_type": event_type,
+ "schedule_rule": schedule_rule,
+ "timezone": timezone,
+ },
+ trigger_create_params.TriggerCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TriggerCreateResponse,
+ )
+
+ async def retrieve(
+ self,
+ trigger_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,
+ ) -> TriggerRetrieveResponse:
+ """
+ Get a trigger
+
+ 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 trigger_id:
+ raise ValueError(f"Expected a non-empty value for `trigger_id` but received {trigger_id!r}")
+ return await self._get(
+ path_template("/triggers/{trigger_id}", trigger_id=trigger_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TriggerRetrieveResponse,
+ )
+
+ async def update(
+ self,
+ trigger_id: str,
+ *,
+ activation: Literal["event", "schedule", "custom"] | Omit = omit,
+ conditions: trigger_update_params.Conditions | Omit = omit,
+ custom_payload_schema: Optional[Dict[str, object]] | Omit = omit,
+ description: str | Omit = omit,
+ event_type: str | Omit = omit,
+ name: str | Omit = omit,
+ schedule_rule: trigger_update_params.ScheduleRule | Omit = omit,
+ timezone: 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,
+ ) -> TriggerUpdateResponse:
+ """
+ Update a trigger
+
+ Args:
+ custom_payload_schema: Optional JSON Schema for validating payloads sent to this custom trigger
+
+ 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 trigger_id:
+ raise ValueError(f"Expected a non-empty value for `trigger_id` but received {trigger_id!r}")
+ return await self._patch(
+ path_template("/triggers/{trigger_id}", trigger_id=trigger_id),
+ body=await async_maybe_transform(
+ {
+ "activation": activation,
+ "conditions": conditions,
+ "custom_payload_schema": custom_payload_schema,
+ "description": description,
+ "event_type": event_type,
+ "name": name,
+ "schedule_rule": schedule_rule,
+ "timezone": timezone,
+ },
+ trigger_update_params.TriggerUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TriggerUpdateResponse,
+ )
+
+ async def list(
+ self,
+ *,
+ activation: Literal["event", "schedule", "custom"] | Omit = omit,
+ event_type: str | Omit = omit,
+ order_by: Literal["name", "createdAt", "updatedAt"] | Omit = omit,
+ order_by_direction: Literal["asc", "desc"] | Omit = omit,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ search: 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,
+ ) -> TriggerListResponse:
+ """
+ List triggers
+
+ 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(
+ "/triggers",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "activation": activation,
+ "event_type": event_type,
+ "order_by": order_by,
+ "order_by_direction": order_by_direction,
+ "page": page,
+ "page_size": page_size,
+ "search": search,
+ },
+ trigger_list_params.TriggerListParams,
+ ),
+ ),
+ cast_to=TriggerListResponse,
+ )
+
+ async def delete(
+ self,
+ trigger_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,
+ ) -> TriggerDeleteResponse:
+ """
+ Delete a trigger
+
+ 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 trigger_id:
+ raise ValueError(f"Expected a non-empty value for `trigger_id` but received {trigger_id!r}")
+ return await self._delete(
+ path_template("/triggers/{trigger_id}", trigger_id=trigger_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TriggerDeleteResponse,
+ )
+
+ async def fire(
+ self,
+ trigger_id: str,
+ *,
+ payload: Dict[str, object],
+ 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,
+ ) -> TriggerFireResponse:
+ """
+ Invoke a custom trigger directly with an arbitrary JSON payload.
+
+ Fan-out: a trigger may be referenced by multiple flows (workflows). Firing it
+ enqueues one execution per enabled, non-deleted flow attached to this trigger,
+ each receiving the same payload. The `enqueuedCount` in the response reports how
+ many were enqueued (0 if no flows are attached, or if all matching flows are
+ gated by a cooldown).
+
+ Payload validation:
+
+ - If the trigger has a `customPayloadSchema`, the payload is validated against
+ it (JSON Schema via AJV).
+ - If no schema is configured, the payload only needs to be a JSON object — any
+ keys and values are accepted.
+
+ Only triggers with `activation = "custom"` can be fired through this endpoint;
+ event and schedule triggers return 409.
+
+ Args:
+ payload: Arbitrary JSON object forwarded to every flow attached to this trigger.
+ Validated against the trigger's customPayloadSchema when one is configured;
+ otherwise only "must be a JSON object" is enforced.
+
+ device_id: Optional device scope. When supplied, ownership is verified for the calling user
+ and the value is passed through to each enqueued execution as the default device
+ context.
+
+ 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 trigger_id:
+ raise ValueError(f"Expected a non-empty value for `trigger_id` but received {trigger_id!r}")
+ return await self._post(
+ path_template("/triggers/{trigger_id}/fire", trigger_id=trigger_id),
+ body=await async_maybe_transform(
+ {
+ "payload": payload,
+ "device_id": device_id,
+ },
+ trigger_fire_params.TriggerFireParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TriggerFireResponse,
+ )
+
+
+class TriggersResourceWithRawResponse:
+ def __init__(self, triggers: TriggersResource) -> None:
+ self._triggers = triggers
+
+ self.create = to_raw_response_wrapper(
+ triggers.create,
+ )
+ self.retrieve = to_raw_response_wrapper(
+ triggers.retrieve,
+ )
+ self.update = to_raw_response_wrapper(
+ triggers.update,
+ )
+ self.list = to_raw_response_wrapper(
+ triggers.list,
+ )
+ self.delete = to_raw_response_wrapper(
+ triggers.delete,
+ )
+ self.fire = to_raw_response_wrapper(
+ triggers.fire,
+ )
+
+
+class AsyncTriggersResourceWithRawResponse:
+ def __init__(self, triggers: AsyncTriggersResource) -> None:
+ self._triggers = triggers
+
+ self.create = async_to_raw_response_wrapper(
+ triggers.create,
+ )
+ self.retrieve = async_to_raw_response_wrapper(
+ triggers.retrieve,
+ )
+ self.update = async_to_raw_response_wrapper(
+ triggers.update,
+ )
+ self.list = async_to_raw_response_wrapper(
+ triggers.list,
+ )
+ self.delete = async_to_raw_response_wrapper(
+ triggers.delete,
+ )
+ self.fire = async_to_raw_response_wrapper(
+ triggers.fire,
+ )
+
+
+class TriggersResourceWithStreamingResponse:
+ def __init__(self, triggers: TriggersResource) -> None:
+ self._triggers = triggers
+
+ self.create = to_streamed_response_wrapper(
+ triggers.create,
+ )
+ self.retrieve = to_streamed_response_wrapper(
+ triggers.retrieve,
+ )
+ self.update = to_streamed_response_wrapper(
+ triggers.update,
+ )
+ self.list = to_streamed_response_wrapper(
+ triggers.list,
+ )
+ self.delete = to_streamed_response_wrapper(
+ triggers.delete,
+ )
+ self.fire = to_streamed_response_wrapper(
+ triggers.fire,
+ )
+
+
+class AsyncTriggersResourceWithStreamingResponse:
+ def __init__(self, triggers: AsyncTriggersResource) -> None:
+ self._triggers = triggers
+
+ self.create = async_to_streamed_response_wrapper(
+ triggers.create,
+ )
+ self.retrieve = async_to_streamed_response_wrapper(
+ triggers.retrieve,
+ )
+ self.update = async_to_streamed_response_wrapper(
+ triggers.update,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ triggers.list,
+ )
+ self.delete = async_to_streamed_response_wrapper(
+ triggers.delete,
+ )
+ self.fire = async_to_streamed_response_wrapper(
+ triggers.fire,
+ )
diff --git a/src/mobilerun_sdk/resources/workflows/workflows.py b/src/mobilerun_sdk/resources/workflows/workflows.py
new file mode 100644
index 0000000..75a9afa
--- /dev/null
+++ b/src/mobilerun_sdk/resources/workflows/workflows.py
@@ -0,0 +1,326 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .secrets import (
+ SecretsResource,
+ AsyncSecretsResource,
+ SecretsResourceWithRawResponse,
+ AsyncSecretsResourceWithRawResponse,
+ SecretsResourceWithStreamingResponse,
+ AsyncSecretsResourceWithStreamingResponse,
+)
+from .triggers import (
+ TriggersResource,
+ AsyncTriggersResource,
+ TriggersResourceWithRawResponse,
+ AsyncTriggersResourceWithRawResponse,
+ TriggersResourceWithStreamingResponse,
+ AsyncTriggersResourceWithStreamingResponse,
+)
+from ..._compat import cached_property
+from .timezones import (
+ TimezonesResource,
+ AsyncTimezonesResource,
+ TimezonesResourceWithRawResponse,
+ AsyncTimezonesResourceWithRawResponse,
+ TimezonesResourceWithStreamingResponse,
+ AsyncTimezonesResourceWithStreamingResponse,
+)
+from .executions import (
+ ExecutionsResource,
+ AsyncExecutionsResource,
+ ExecutionsResourceWithRawResponse,
+ AsyncExecutionsResourceWithRawResponse,
+ ExecutionsResourceWithStreamingResponse,
+ AsyncExecutionsResourceWithStreamingResponse,
+)
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from .flows.flows import (
+ FlowsResource,
+ AsyncFlowsResource,
+ FlowsResourceWithRawResponse,
+ AsyncFlowsResourceWithRawResponse,
+ FlowsResourceWithStreamingResponse,
+ AsyncFlowsResourceWithStreamingResponse,
+)
+from .events.events import (
+ EventsResource,
+ AsyncEventsResource,
+ EventsResourceWithRawResponse,
+ AsyncEventsResourceWithRawResponse,
+ EventsResourceWithStreamingResponse,
+ AsyncEventsResourceWithStreamingResponse,
+)
+from .action_catalog import (
+ ActionCatalogResource,
+ AsyncActionCatalogResource,
+ ActionCatalogResourceWithRawResponse,
+ AsyncActionCatalogResourceWithRawResponse,
+ ActionCatalogResourceWithStreamingResponse,
+ AsyncActionCatalogResourceWithStreamingResponse,
+)
+from .actions.actions import (
+ ActionsResource,
+ AsyncActionsResource,
+ ActionsResourceWithRawResponse,
+ AsyncActionsResourceWithRawResponse,
+ ActionsResourceWithStreamingResponse,
+ AsyncActionsResourceWithStreamingResponse,
+)
+
+__all__ = ["WorkflowsResource", "AsyncWorkflowsResource"]
+
+
+class WorkflowsResource(SyncAPIResource):
+ @cached_property
+ def triggers(self) -> TriggersResource:
+ return TriggersResource(self._client)
+
+ @cached_property
+ def action_catalog(self) -> ActionCatalogResource:
+ return ActionCatalogResource(self._client)
+
+ @cached_property
+ def actions(self) -> ActionsResource:
+ return ActionsResource(self._client)
+
+ @cached_property
+ def flows(self) -> FlowsResource:
+ return FlowsResource(self._client)
+
+ @cached_property
+ def events(self) -> EventsResource:
+ return EventsResource(self._client)
+
+ @cached_property
+ def executions(self) -> ExecutionsResource:
+ return ExecutionsResource(self._client)
+
+ @cached_property
+ def timezones(self) -> TimezonesResource:
+ return TimezonesResource(self._client)
+
+ @cached_property
+ def secrets(self) -> SecretsResource:
+ return SecretsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> WorkflowsResourceWithRawResponse:
+ """
+ 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 WorkflowsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> WorkflowsResourceWithStreamingResponse:
+ """
+ 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 WorkflowsResourceWithStreamingResponse(self)
+
+
+class AsyncWorkflowsResource(AsyncAPIResource):
+ @cached_property
+ def triggers(self) -> AsyncTriggersResource:
+ return AsyncTriggersResource(self._client)
+
+ @cached_property
+ def action_catalog(self) -> AsyncActionCatalogResource:
+ return AsyncActionCatalogResource(self._client)
+
+ @cached_property
+ def actions(self) -> AsyncActionsResource:
+ return AsyncActionsResource(self._client)
+
+ @cached_property
+ def flows(self) -> AsyncFlowsResource:
+ return AsyncFlowsResource(self._client)
+
+ @cached_property
+ def events(self) -> AsyncEventsResource:
+ return AsyncEventsResource(self._client)
+
+ @cached_property
+ def executions(self) -> AsyncExecutionsResource:
+ return AsyncExecutionsResource(self._client)
+
+ @cached_property
+ def timezones(self) -> AsyncTimezonesResource:
+ return AsyncTimezonesResource(self._client)
+
+ @cached_property
+ def secrets(self) -> AsyncSecretsResource:
+ return AsyncSecretsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncWorkflowsResourceWithRawResponse:
+ """
+ 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 AsyncWorkflowsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncWorkflowsResourceWithStreamingResponse:
+ """
+ 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 AsyncWorkflowsResourceWithStreamingResponse(self)
+
+
+class WorkflowsResourceWithRawResponse:
+ def __init__(self, workflows: WorkflowsResource) -> None:
+ self._workflows = workflows
+
+ @cached_property
+ def triggers(self) -> TriggersResourceWithRawResponse:
+ return TriggersResourceWithRawResponse(self._workflows.triggers)
+
+ @cached_property
+ def action_catalog(self) -> ActionCatalogResourceWithRawResponse:
+ return ActionCatalogResourceWithRawResponse(self._workflows.action_catalog)
+
+ @cached_property
+ def actions(self) -> ActionsResourceWithRawResponse:
+ return ActionsResourceWithRawResponse(self._workflows.actions)
+
+ @cached_property
+ def flows(self) -> FlowsResourceWithRawResponse:
+ return FlowsResourceWithRawResponse(self._workflows.flows)
+
+ @cached_property
+ def events(self) -> EventsResourceWithRawResponse:
+ return EventsResourceWithRawResponse(self._workflows.events)
+
+ @cached_property
+ def executions(self) -> ExecutionsResourceWithRawResponse:
+ return ExecutionsResourceWithRawResponse(self._workflows.executions)
+
+ @cached_property
+ def timezones(self) -> TimezonesResourceWithRawResponse:
+ return TimezonesResourceWithRawResponse(self._workflows.timezones)
+
+ @cached_property
+ def secrets(self) -> SecretsResourceWithRawResponse:
+ return SecretsResourceWithRawResponse(self._workflows.secrets)
+
+
+class AsyncWorkflowsResourceWithRawResponse:
+ def __init__(self, workflows: AsyncWorkflowsResource) -> None:
+ self._workflows = workflows
+
+ @cached_property
+ def triggers(self) -> AsyncTriggersResourceWithRawResponse:
+ return AsyncTriggersResourceWithRawResponse(self._workflows.triggers)
+
+ @cached_property
+ def action_catalog(self) -> AsyncActionCatalogResourceWithRawResponse:
+ return AsyncActionCatalogResourceWithRawResponse(self._workflows.action_catalog)
+
+ @cached_property
+ def actions(self) -> AsyncActionsResourceWithRawResponse:
+ return AsyncActionsResourceWithRawResponse(self._workflows.actions)
+
+ @cached_property
+ def flows(self) -> AsyncFlowsResourceWithRawResponse:
+ return AsyncFlowsResourceWithRawResponse(self._workflows.flows)
+
+ @cached_property
+ def events(self) -> AsyncEventsResourceWithRawResponse:
+ return AsyncEventsResourceWithRawResponse(self._workflows.events)
+
+ @cached_property
+ def executions(self) -> AsyncExecutionsResourceWithRawResponse:
+ return AsyncExecutionsResourceWithRawResponse(self._workflows.executions)
+
+ @cached_property
+ def timezones(self) -> AsyncTimezonesResourceWithRawResponse:
+ return AsyncTimezonesResourceWithRawResponse(self._workflows.timezones)
+
+ @cached_property
+ def secrets(self) -> AsyncSecretsResourceWithRawResponse:
+ return AsyncSecretsResourceWithRawResponse(self._workflows.secrets)
+
+
+class WorkflowsResourceWithStreamingResponse:
+ def __init__(self, workflows: WorkflowsResource) -> None:
+ self._workflows = workflows
+
+ @cached_property
+ def triggers(self) -> TriggersResourceWithStreamingResponse:
+ return TriggersResourceWithStreamingResponse(self._workflows.triggers)
+
+ @cached_property
+ def action_catalog(self) -> ActionCatalogResourceWithStreamingResponse:
+ return ActionCatalogResourceWithStreamingResponse(self._workflows.action_catalog)
+
+ @cached_property
+ def actions(self) -> ActionsResourceWithStreamingResponse:
+ return ActionsResourceWithStreamingResponse(self._workflows.actions)
+
+ @cached_property
+ def flows(self) -> FlowsResourceWithStreamingResponse:
+ return FlowsResourceWithStreamingResponse(self._workflows.flows)
+
+ @cached_property
+ def events(self) -> EventsResourceWithStreamingResponse:
+ return EventsResourceWithStreamingResponse(self._workflows.events)
+
+ @cached_property
+ def executions(self) -> ExecutionsResourceWithStreamingResponse:
+ return ExecutionsResourceWithStreamingResponse(self._workflows.executions)
+
+ @cached_property
+ def timezones(self) -> TimezonesResourceWithStreamingResponse:
+ return TimezonesResourceWithStreamingResponse(self._workflows.timezones)
+
+ @cached_property
+ def secrets(self) -> SecretsResourceWithStreamingResponse:
+ return SecretsResourceWithStreamingResponse(self._workflows.secrets)
+
+
+class AsyncWorkflowsResourceWithStreamingResponse:
+ def __init__(self, workflows: AsyncWorkflowsResource) -> None:
+ self._workflows = workflows
+
+ @cached_property
+ def triggers(self) -> AsyncTriggersResourceWithStreamingResponse:
+ return AsyncTriggersResourceWithStreamingResponse(self._workflows.triggers)
+
+ @cached_property
+ def action_catalog(self) -> AsyncActionCatalogResourceWithStreamingResponse:
+ return AsyncActionCatalogResourceWithStreamingResponse(self._workflows.action_catalog)
+
+ @cached_property
+ def actions(self) -> AsyncActionsResourceWithStreamingResponse:
+ return AsyncActionsResourceWithStreamingResponse(self._workflows.actions)
+
+ @cached_property
+ def flows(self) -> AsyncFlowsResourceWithStreamingResponse:
+ return AsyncFlowsResourceWithStreamingResponse(self._workflows.flows)
+
+ @cached_property
+ def events(self) -> AsyncEventsResourceWithStreamingResponse:
+ return AsyncEventsResourceWithStreamingResponse(self._workflows.events)
+
+ @cached_property
+ def executions(self) -> AsyncExecutionsResourceWithStreamingResponse:
+ return AsyncExecutionsResourceWithStreamingResponse(self._workflows.executions)
+
+ @cached_property
+ def timezones(self) -> AsyncTimezonesResourceWithStreamingResponse:
+ return AsyncTimezonesResourceWithStreamingResponse(self._workflows.timezones)
+
+ @cached_property
+ def secrets(self) -> AsyncSecretsResourceWithStreamingResponse:
+ return AsyncSecretsResourceWithStreamingResponse(self._workflows.secrets)
diff --git a/src/mobilerun_sdk/types/__init__.py b/src/mobilerun_sdk/types/__init__.py
index ba767ee..2b5082d 100644
--- a/src/mobilerun_sdk/types/__init__.py
+++ b/src/mobilerun_sdk/types/__init__.py
@@ -2,6 +2,9 @@
from __future__ import annotations
+from . import devices
+from .. import _compat
+from .flow import Flow as Flow
from .task import Task as Task
from .device import Device as Device
from .shared import (
@@ -22,16 +25,17 @@
from .app_list_params import AppListParams as AppListParams
from .task_run_params import TaskRunParams as TaskRunParams
from .hook_list_params import HookListParams as HookListParams
+from .hook_test_params import HookTestParams as HookTestParams
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 .hook_list_response import HookListResponse as HookListResponse
+from .hook_test_response import HookTestResponse as HookTestResponse
from .hook_update_params import HookUpdateParams as HookUpdateParams
from .task_list_response import TaskListResponse as TaskListResponse
from .task_stop_response import TaskStopResponse as TaskStopResponse
-from .agent_list_response import AgentListResponse as AgentListResponse
from .app_delete_response import AppDeleteResponse as AppDeleteResponse
from .carrier_list_params import CarrierListParams as CarrierListParams
from .hook_perform_params import HookPerformParams as HookPerformParams
@@ -40,6 +44,7 @@
from .profile_list_params import ProfileListParams as ProfileListParams
from .proxy_create_params import ProxyCreateParams as ProxyCreateParams
from .proxy_list_response import ProxyListResponse as ProxyListResponse
+from .proxy_lookup_params import ProxyLookupParams as ProxyLookupParams
from .proxy_update_params import ProxyUpdateParams as ProxyUpdateParams
from .device_create_params import DeviceCreateParams as DeviceCreateParams
from .device_list_response import DeviceListResponse as DeviceListResponse
@@ -57,6 +62,7 @@
from .profile_update_params import ProfileUpdateParams as ProfileUpdateParams
from .proxy_create_response import ProxyCreateResponse as ProxyCreateResponse
from .proxy_delete_response import ProxyDeleteResponse as ProxyDeleteResponse
+from .proxy_lookup_response import ProxyLookupResponse as ProxyLookupResponse
from .proxy_update_response import ProxyUpdateResponse as ProxyUpdateResponse
from .credential_list_params import CredentialListParams as CredentialListParams
from .device_set_name_params import DeviceSetNameParams as DeviceSetNameParams
@@ -78,6 +84,7 @@
from .carrier_retrieve_response import CarrierRetrieveResponse as CarrierRetrieveResponse
from .hook_unsubscribe_response import HookUnsubscribeResponse as HookUnsubscribeResponse
from .package_credentials_param import PackageCredentialsParam as PackageCredentialsParam
+from .app_list_versions_response import AppListVersionsResponse as AppListVersionsResponse
from .task_send_message_response import TaskSendMessageResponse as TaskSendMessageResponse
from .app_confirm_upload_response import AppConfirmUploadResponse as AppConfirmUploadResponse
from .device_fingerprint_response import DeviceFingerprintResponse as DeviceFingerprintResponse
@@ -85,3 +92,14 @@
from .hook_get_sample_data_response import HookGetSampleDataResponse as HookGetSampleDataResponse
from .app_create_signed_upload_url_params import AppCreateSignedUploadURLParams as AppCreateSignedUploadURLParams
from .app_create_signed_upload_url_response import AppCreateSignedUploadURLResponse as AppCreateSignedUploadURLResponse
+
+# Rebuild cyclical models only after all modules are imported.
+# This ensures that, when building the deferred (due to cyclical references) model schema,
+# Pydantic can resolve the necessary references.
+# See: https://github.com/pydantic/pydantic/issues/11250 for more context.
+if _compat.PYDANTIC_V1:
+ devices.a11_y_node.A11YNode.update_forward_refs() # type: ignore
+ devices.state_ui_response.StateUiResponse.update_forward_refs() # type: ignore
+else:
+ devices.a11_y_node.A11YNode.model_rebuild(_parent_namespace_depth=0)
+ devices.state_ui_response.StateUiResponse.model_rebuild(_parent_namespace_depth=0)
diff --git a/src/mobilerun_sdk/types/agent_list_response.py b/src/mobilerun_sdk/types/agent_list_response.py
deleted file mode 100644
index fc366d6..0000000
--- a/src/mobilerun_sdk/types/agent_list_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 TypeAlias
-
-from pydantic import Field as FieldInfo
-
-from .._models import BaseModel
-
-__all__ = ["AgentListResponse", "AgentListResponseItem"]
-
-
-class AgentListResponseItem(BaseModel):
- id: int
-
- description: Optional[str] = None
-
- icon: str
-
- llm_model: str = FieldInfo(alias="llmModel")
-
- max_steps: int = FieldInfo(alias="maxSteps")
-
- name: str
-
- reasoning: bool
-
- subagent_model: Optional[str] = FieldInfo(alias="subagentModel", default=None)
-
- vision: bool
-
-
-AgentListResponse: TypeAlias = List[AgentListResponseItem]
diff --git a/src/mobilerun_sdk/types/agents/__init__.py b/src/mobilerun_sdk/types/agents/__init__.py
new file mode 100644
index 0000000..f8cfbf9
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/__init__.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .file_list_files_params import FileListFilesParams as FileListFilesParams
+from .file_list_files_response import FileListFilesResponse as FileListFilesResponse
+from .file_mint_upload_url_params import FileMintUploadURLParams as FileMintUploadURLParams
+from .chat_get_chat_state_response import ChatGetChatStateResponse as ChatGetChatStateResponse
+from .chat_rehydrate_chat_response import ChatRehydrateChatResponse as ChatRehydrateChatResponse
+from .file_mint_upload_url_response import FileMintUploadURLResponse as FileMintUploadURLResponse
+from .chat_deliver_permission_params import ChatDeliverPermissionParams as ChatDeliverPermissionParams
+from .chat_deliver_permission_response import ChatDeliverPermissionResponse as ChatDeliverPermissionResponse
+from .chat_list_slash_commands_response import ChatListSlashCommandsResponse as ChatListSlashCommandsResponse
diff --git a/src/mobilerun_sdk/types/agents/chat/__init__.py b/src/mobilerun_sdk/types/agents/chat/__init__.py
new file mode 100644
index 0000000..0d2b831
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/chat/__init__.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .abort_perform_response import AbortPerformResponse as AbortPerformResponse
+from .question_dismiss_params import QuestionDismissParams as QuestionDismissParams
+from .question_dismiss_response import QuestionDismissResponse as QuestionDismissResponse
+from .abort_force_clear_response import AbortForceClearResponse as AbortForceClearResponse
+from .question_deliver_answer_params import QuestionDeliverAnswerParams as QuestionDeliverAnswerParams
+from .question_deliver_answer_response import QuestionDeliverAnswerResponse as QuestionDeliverAnswerResponse
diff --git a/src/mobilerun_sdk/types/agents/chat/abort_force_clear_response.py b/src/mobilerun_sdk/types/agents/chat/abort_force_clear_response.py
new file mode 100644
index 0000000..d8fdfa3
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/chat/abort_force_clear_response.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from ...._models import BaseModel
+
+__all__ = ["AbortForceClearResponse"]
+
+
+class AbortForceClearResponse(BaseModel):
+ cleared: int
+
+ ok: Literal[True]
diff --git a/src/mobilerun_sdk/types/agents/chat/abort_perform_response.py b/src/mobilerun_sdk/types/agents/chat/abort_perform_response.py
new file mode 100644
index 0000000..881f737
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/chat/abort_perform_response.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from ...._models import BaseModel
+
+__all__ = ["AbortPerformResponse"]
+
+
+class AbortPerformResponse(BaseModel):
+ ok: Literal[True]
diff --git a/src/mobilerun_sdk/types/agents/chat/question_deliver_answer_params.py b/src/mobilerun_sdk/types/agents/chat/question_deliver_answer_params.py
new file mode 100644
index 0000000..2d9afa7
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/chat/question_deliver_answer_params.py
@@ -0,0 +1,27 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union, Iterable
+from typing_extensions import Required, Annotated, TypeAlias, TypedDict
+
+from ...._utils import PropertyInfo
+
+__all__ = ["QuestionDeliverAnswerParams", "Answer", "AnswerLabel", "AnswerCustom"]
+
+
+class QuestionDeliverAnswerParams(TypedDict, total=False):
+ answers: Required[Iterable[Iterable[Answer]]]
+
+ question_id: Required[Annotated[str, PropertyInfo(alias="questionId")]]
+
+
+class AnswerLabel(TypedDict, total=False):
+ label: Required[str]
+
+
+class AnswerCustom(TypedDict, total=False):
+ custom: Required[str]
+
+
+Answer: TypeAlias = Union[AnswerLabel, AnswerCustom]
diff --git a/src/mobilerun_sdk/types/agents/chat/question_deliver_answer_response.py b/src/mobilerun_sdk/types/agents/chat/question_deliver_answer_response.py
new file mode 100644
index 0000000..474adbb
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/chat/question_deliver_answer_response.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from ...._models import BaseModel
+
+__all__ = ["QuestionDeliverAnswerResponse"]
+
+
+class QuestionDeliverAnswerResponse(BaseModel):
+ ok: Literal[True]
diff --git a/src/mobilerun_sdk/types/agents/chat/question_dismiss_params.py b/src/mobilerun_sdk/types/agents/chat/question_dismiss_params.py
new file mode 100644
index 0000000..a9247df
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/chat/question_dismiss_params.py
@@ -0,0 +1,13 @@
+# 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__ = ["QuestionDismissParams"]
+
+
+class QuestionDismissParams(TypedDict, total=False):
+ question_id: Required[Annotated[str, PropertyInfo(alias="questionId")]]
diff --git a/src/mobilerun_sdk/types/agents/chat/question_dismiss_response.py b/src/mobilerun_sdk/types/agents/chat/question_dismiss_response.py
new file mode 100644
index 0000000..ce036a9
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/chat/question_dismiss_response.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from ...._models import BaseModel
+
+__all__ = ["QuestionDismissResponse"]
+
+
+class QuestionDismissResponse(BaseModel):
+ ok: Literal[True]
diff --git a/src/mobilerun_sdk/types/agents/chat_deliver_permission_params.py b/src/mobilerun_sdk/types/agents/chat_deliver_permission_params.py
new file mode 100644
index 0000000..c3e54c1
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/chat_deliver_permission_params.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["ChatDeliverPermissionParams"]
+
+
+class ChatDeliverPermissionParams(TypedDict, total=False):
+ permission_id: Required[Annotated[str, PropertyInfo(alias="permissionId")]]
+
+ response: Required[Literal["once", "always", "reject"]]
diff --git a/src/mobilerun_sdk/types/agents/chat_deliver_permission_response.py b/src/mobilerun_sdk/types/agents/chat_deliver_permission_response.py
new file mode 100644
index 0000000..342281d
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/chat_deliver_permission_response.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = ["ChatDeliverPermissionResponse"]
+
+
+class ChatDeliverPermissionResponse(BaseModel):
+ ok: Literal[True]
diff --git a/src/mobilerun_sdk/types/agents/chat_get_chat_state_response.py b/src/mobilerun_sdk/types/agents/chat_get_chat_state_response.py
new file mode 100644
index 0000000..78d661f
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/chat_get_chat_state_response.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["ChatGetChatStateResponse"]
+
+
+class ChatGetChatStateResponse(BaseModel):
+ abort_requested: bool = FieldInfo(alias="abortRequested")
+
+ chat_active: bool = FieldInfo(alias="chatActive")
+
+ workflow_active: bool = FieldInfo(alias="workflowActive")
diff --git a/src/mobilerun_sdk/types/agents/chat_list_slash_commands_response.py b/src/mobilerun_sdk/types/agents/chat_list_slash_commands_response.py
new file mode 100644
index 0000000..8e85806
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/chat_list_slash_commands_response.py
@@ -0,0 +1,25 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from ..._models import BaseModel
+
+__all__ = ["ChatListSlashCommandsResponse", "Command"]
+
+
+class Command(BaseModel):
+ name: str
+ """Including the leading slash (e.g. `/help`)."""
+
+ summary: str
+
+ args: Optional[str] = None
+ """Arg signature for the help card (e.g.
+
+ ``, ``). Always angle-bracketed; the summary spells out when an
+ arg is optional.
+ """
+
+
+class ChatListSlashCommandsResponse(BaseModel):
+ commands: List[Command]
diff --git a/src/mobilerun_sdk/types/agents/chat_rehydrate_chat_response.py b/src/mobilerun_sdk/types/agents/chat_rehydrate_chat_response.py
new file mode 100644
index 0000000..3214bd6
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/chat_rehydrate_chat_response.py
@@ -0,0 +1,44 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import TYPE_CHECKING, Dict, List, Optional
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["ChatRehydrateChatResponse", "Message", "MessagePart"]
+
+
+class MessagePart(BaseModel):
+ type: str
+
+ if TYPE_CHECKING:
+ # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a
+ # value to this field, so for compatibility we avoid doing it at runtime.
+ __pydantic_extra__: Dict[str, Optional[object]] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride]
+
+ # Stub to indicate that arbitrary properties are accepted.
+ # To access properties that are not valid identifiers you can use `getattr`, e.g.
+ # `getattr(obj, '$type')`
+ def __getattr__(self, attr: str) -> Optional[object]: ...
+ else:
+ __pydantic_extra__: Dict[str, Optional[object]]
+
+
+class Message(BaseModel):
+ id: str
+
+ parts: List[MessagePart]
+
+ role: Literal["user", "assistant", "system"]
+
+ source: Optional[Literal["cloud", "telegram", "api", "workflow"]] = None
+
+ synthetic: Optional[bool] = None
+
+
+class ChatRehydrateChatResponse(BaseModel):
+ messages: List[Message]
+
+ turn_active: bool = FieldInfo(alias="turnActive")
diff --git a/src/mobilerun_sdk/types/agents/file_list_files_params.py b/src/mobilerun_sdk/types/agents/file_list_files_params.py
new file mode 100644
index 0000000..8802615
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/file_list_files_params.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, TypedDict
+
+__all__ = ["FileListFilesParams"]
+
+
+class FileListFilesParams(TypedDict, total=False):
+ zone: Literal["user", "agent", "workflow", "skills"]
diff --git a/src/mobilerun_sdk/types/agents/file_list_files_response.py b/src/mobilerun_sdk/types/agents/file_list_files_response.py
new file mode 100644
index 0000000..83554e2
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/file_list_files_response.py
@@ -0,0 +1,43 @@
+# 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__ = ["FileListFilesResponse", "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 FileListFilesResponse(BaseModel):
+ files: List[File]
+
+ quota: Quota
diff --git a/src/mobilerun_sdk/types/agents/file_mint_upload_url_params.py b/src/mobilerun_sdk/types/agents/file_mint_upload_url_params.py
new file mode 100644
index 0000000..c68739b
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/file_mint_upload_url_params.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["FileMintUploadURLParams"]
+
+
+class FileMintUploadURLParams(TypedDict, total=False):
+ filename: Required[str]
+
+ mime_type: Required[Annotated[str, PropertyInfo(alias="mimeType")]]
+
+ size_bytes: Required[Annotated[int, PropertyInfo(alias="sizeBytes")]]
+
+ zone: Literal["user", "skills"]
+
+ idempotency_key: Annotated[str, PropertyInfo(alias="Idempotency-Key")]
diff --git a/src/mobilerun_sdk/types/agents/file_mint_upload_url_response.py b/src/mobilerun_sdk/types/agents/file_mint_upload_url_response.py
new file mode 100644
index 0000000..162c71a
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/file_mint_upload_url_response.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from datetime import datetime
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["FileMintUploadURLResponse"]
+
+
+class FileMintUploadURLResponse(BaseModel):
+ expires_at: datetime = FieldInfo(alias="expiresAt")
+
+ file_id: str = FieldInfo(alias="fileId")
+
+ put_url: str = FieldInfo(alias="putUrl")
diff --git a/src/mobilerun_sdk/types/agents/files/__init__.py b/src/mobilerun_sdk/types/agents/files/__init__.py
new file mode 100644
index 0000000..b74a1a8
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/files/__init__.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .file_id_delete_file_response import FileIDDeleteFileResponse as FileIDDeleteFileResponse
+from .file_id_update_metadata_params import FileIDUpdateMetadataParams as FileIDUpdateMetadataParams
+from .file_id_confirm_upload_response import FileIDConfirmUploadResponse as FileIDConfirmUploadResponse
+from .file_id_update_metadata_response import FileIDUpdateMetadataResponse as FileIDUpdateMetadataResponse
+from .file_id_cancel_pending_upload_response import (
+ FileIDCancelPendingUploadResponse as FileIDCancelPendingUploadResponse,
+)
diff --git a/src/mobilerun_sdk/types/agents/files/file_id_cancel_pending_upload_response.py b/src/mobilerun_sdk/types/agents/files/file_id_cancel_pending_upload_response.py
new file mode 100644
index 0000000..18e2ee4
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/files/file_id_cancel_pending_upload_response.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ...._models import BaseModel
+
+__all__ = ["FileIDCancelPendingUploadResponse"]
+
+
+class FileIDCancelPendingUploadResponse(BaseModel):
+ cancelled: bool
diff --git a/src/mobilerun_sdk/types/agents/files/file_id_confirm_upload_response.py b/src/mobilerun_sdk/types/agents/files/file_id_confirm_upload_response.py
new file mode 100644
index 0000000..fd838b8
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/files/file_id_confirm_upload_response.py
@@ -0,0 +1,35 @@
+# 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__ = ["FileIDConfirmUploadResponse"]
+
+
+class FileIDConfirmUploadResponse(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/agents/files/file_id_delete_file_response.py b/src/mobilerun_sdk/types/agents/files/file_id_delete_file_response.py
new file mode 100644
index 0000000..3014432
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/files/file_id_delete_file_response.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from ...._models import BaseModel
+
+__all__ = ["FileIDDeleteFileResponse"]
+
+
+class FileIDDeleteFileResponse(BaseModel):
+ ok: Literal[True]
diff --git a/src/mobilerun_sdk/types/agents/files/file_id_update_metadata_params.py b/src/mobilerun_sdk/types/agents/files/file_id_update_metadata_params.py
new file mode 100644
index 0000000..9a0b940
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/files/file_id_update_metadata_params.py
@@ -0,0 +1,16 @@
+# 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__ = ["FileIDUpdateMetadataParams"]
+
+
+class FileIDUpdateMetadataParams(TypedDict, total=False):
+ display_name: Annotated[Optional[str], PropertyInfo(alias="displayName")]
+
+ enabled: bool
diff --git a/src/mobilerun_sdk/types/agents/files/file_id_update_metadata_response.py b/src/mobilerun_sdk/types/agents/files/file_id_update_metadata_response.py
new file mode 100644
index 0000000..6ab101b
--- /dev/null
+++ b/src/mobilerun_sdk/types/agents/files/file_id_update_metadata_response.py
@@ -0,0 +1,31 @@
+# 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__ = ["FileIDUpdateMetadataResponse"]
+
+
+class FileIDUpdateMetadataResponse(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/app_list_versions_response.py b/src/mobilerun_sdk/types/app_list_versions_response.py
new file mode 100644
index 0000000..130eab8
--- /dev/null
+++ b/src/mobilerun_sdk/types/app_list_versions_response.py
@@ -0,0 +1,296 @@
+# 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__ = ["AppListVersionsResponse", "Data"]
+
+
+class Data(BaseModel):
+ id: str
+
+ app_id: str = FieldInfo(alias="appId")
+
+ country: Literal[
+ "AF",
+ "AL",
+ "DZ",
+ "AS",
+ "AD",
+ "AO",
+ "AI",
+ "AQ",
+ "AG",
+ "AR",
+ "AM",
+ "AW",
+ "AP",
+ "AU",
+ "AT",
+ "AZ",
+ "BS",
+ "BH",
+ "BD",
+ "BB",
+ "BY",
+ "BE",
+ "BZ",
+ "BJ",
+ "BM",
+ "BT",
+ "BO",
+ "BQ",
+ "BA",
+ "BW",
+ "BV",
+ "BR",
+ "IO",
+ "BN",
+ "BG",
+ "BF",
+ "BI",
+ "KH",
+ "CM",
+ "CA",
+ "CV",
+ "KY",
+ "CF",
+ "TD",
+ "CL",
+ "CN",
+ "CX",
+ "CC",
+ "CO",
+ "KM",
+ "CG",
+ "CD",
+ "CK",
+ "CR",
+ "HR",
+ "CU",
+ "CW",
+ "CY",
+ "CZ",
+ "CI",
+ "DK",
+ "DJ",
+ "DM",
+ "DO",
+ "EC",
+ "EG",
+ "SV",
+ "GQ",
+ "ER",
+ "EE",
+ "ET",
+ "FK",
+ "FO",
+ "FJ",
+ "FI",
+ "FR",
+ "GF",
+ "PF",
+ "TF",
+ "GA",
+ "GM",
+ "GE",
+ "DE",
+ "GH",
+ "GI",
+ "GR",
+ "GL",
+ "GD",
+ "GP",
+ "GU",
+ "GT",
+ "GG",
+ "GN",
+ "GW",
+ "GY",
+ "HT",
+ "HM",
+ "VA",
+ "HN",
+ "HK",
+ "HU",
+ "IS",
+ "IN",
+ "ID",
+ "IR",
+ "IQ",
+ "IE",
+ "IM",
+ "IL",
+ "IT",
+ "JM",
+ "JP",
+ "JE",
+ "JO",
+ "KZ",
+ "KE",
+ "KI",
+ "KR",
+ "KW",
+ "KG",
+ "LA",
+ "LV",
+ "LB",
+ "LS",
+ "LR",
+ "LY",
+ "LI",
+ "LT",
+ "LU",
+ "MO",
+ "MG",
+ "MW",
+ "MY",
+ "MV",
+ "ML",
+ "MT",
+ "MH",
+ "MQ",
+ "MR",
+ "MU",
+ "YT",
+ "MX",
+ "FM",
+ "MD",
+ "MC",
+ "MN",
+ "ME",
+ "MS",
+ "MA",
+ "MZ",
+ "MM",
+ "NA",
+ "NR",
+ "NP",
+ "NL",
+ "AN",
+ "NC",
+ "NZ",
+ "NI",
+ "NE",
+ "NG",
+ "NU",
+ "NF",
+ "KP",
+ "MK",
+ "MP",
+ "NO",
+ "OM",
+ "PK",
+ "PW",
+ "PS",
+ "PA",
+ "PG",
+ "PY",
+ "PE",
+ "PH",
+ "PN",
+ "PL",
+ "PT",
+ "PR",
+ "QA",
+ "RE",
+ "RO",
+ "RU",
+ "RW",
+ "BL",
+ "SH",
+ "KN",
+ "LC",
+ "MF",
+ "PM",
+ "VC",
+ "WS",
+ "SM",
+ "ST",
+ "SA",
+ "SN",
+ "RS",
+ "CS",
+ "SC",
+ "SL",
+ "SG",
+ "SX",
+ "SK",
+ "SI",
+ "SB",
+ "SO",
+ "ZA",
+ "GS",
+ "SS",
+ "ES",
+ "LK",
+ "SD",
+ "SR",
+ "SJ",
+ "SZ",
+ "SE",
+ "CH",
+ "SY",
+ "TW",
+ "TJ",
+ "TZ",
+ "TH",
+ "TL",
+ "TG",
+ "TK",
+ "TO",
+ "TT",
+ "TN",
+ "TR",
+ "TM",
+ "TC",
+ "TV",
+ "UG",
+ "UA",
+ "AE",
+ "GB",
+ "US",
+ "UM",
+ "UY",
+ "UZ",
+ "VU",
+ "VE",
+ "VN",
+ "VG",
+ "VI",
+ "WF",
+ "EH",
+ "YE",
+ "ZM",
+ "ZW",
+ "AX",
+ ]
+
+ created_at: Optional[datetime] = FieldInfo(alias="createdAt", default=None)
+
+ queued_at: Optional[datetime] = FieldInfo(alias="queuedAt", default=None)
+
+ size_bytes: Optional[int] = FieldInfo(alias="sizeBytes", default=None)
+
+ source: Literal["user", "system", "portal"]
+
+ status: Literal["queued", "available", "failed"]
+
+ target_sdk: Optional[int] = FieldInfo(alias="targetSdk", default=None)
+
+ updated_at: Optional[datetime] = FieldInfo(alias="updatedAt", default=None)
+
+ user_id: Optional[str] = FieldInfo(alias="userId", default=None)
+
+ version_code: int = FieldInfo(alias="versionCode")
+
+ version_name: str = FieldInfo(alias="versionName")
+
+
+class AppListVersionsResponse(BaseModel):
+ data: List[Data]
diff --git a/src/mobilerun_sdk/types/connect/__init__.py b/src/mobilerun_sdk/types/connect/__init__.py
new file mode 100644
index 0000000..bc194ec
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/__init__.py
@@ -0,0 +1,23 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .proxy_buy_params import ProxyBuyParams as ProxyBuyParams
+from .user_list_params import UserListParams as UserListParams
+from .proxy_list_params import ProxyListParams as ProxyListParams
+from .proxy_buy_response import ProxyBuyResponse as ProxyBuyResponse
+from .user_create_params import UserCreateParams as UserCreateParams
+from .user_list_response import UserListResponse as UserListResponse
+from .user_update_params import UserUpdateParams as UserUpdateParams
+from .country_list_params import CountryListParams as CountryListParams
+from .proxy_list_response import ProxyListResponse as ProxyListResponse
+from .proxy_ping_response import ProxyPingResponse as ProxyPingResponse
+from .user_create_response import UserCreateResponse as UserCreateResponse
+from .user_update_response import UserUpdateResponse as UserUpdateResponse
+from .country_list_response import CountryListResponse as CountryListResponse
+from .user_retrieve_response import UserRetrieveResponse as UserRetrieveResponse
+from .proxy_retrieve_response import ProxyRetrieveResponse as ProxyRetrieveResponse
+from .user_list_connections_params import UserListConnectionsParams as UserListConnectionsParams
+from .proxy_list_connections_params import ProxyListConnectionsParams as ProxyListConnectionsParams
+from .user_list_connections_response import UserListConnectionsResponse as UserListConnectionsResponse
+from .proxy_list_connections_response import ProxyListConnectionsResponse as ProxyListConnectionsResponse
diff --git a/src/mobilerun_sdk/types/connect/country_list_params.py b/src/mobilerun_sdk/types/connect/country_list_params.py
new file mode 100644
index 0000000..b3819a9
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/country_list_params.py
@@ -0,0 +1,20 @@
+# 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__ = ["CountryListParams"]
+
+
+class CountryListParams(TypedDict, total=False):
+ page: int
+ """Page number (1-based)."""
+
+ page_size: Annotated[int, PropertyInfo(alias="pageSize")]
+ """Number of items per page."""
+
+ type: Literal["residential"]
+ """Filter to countries offering this proxy type."""
diff --git a/src/mobilerun_sdk/types/connect/country_list_response.py b/src/mobilerun_sdk/types/connect/country_list_response.py
new file mode 100644
index 0000000..cc2b650
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/country_list_response.py
@@ -0,0 +1,51 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["CountryListResponse", "Item", "Pagination"]
+
+
+class Item(BaseModel):
+ code: str
+ """ISO 3166-1 alpha-2 country code (lowercase)."""
+
+ name: str
+
+ proxy_types: List[Literal["residential"]] = FieldInfo(alias="proxyTypes")
+ """Proxy types available to provision in this country."""
+
+
+class Pagination(BaseModel):
+ """Pagination metadata for a list response."""
+
+ has_next: bool = FieldInfo(alias="hasNext")
+ """Whether a next page exists."""
+
+ has_prev: bool = FieldInfo(alias="hasPrev")
+ """Whether a previous page exists."""
+
+ page: int
+ """Current page number (1-based)."""
+
+ pages: int
+ """Total number of pages."""
+
+ page_size: int = FieldInfo(alias="pageSize")
+ """Number of items per page."""
+
+ total: int
+ """Total number of items across all pages."""
+
+
+class CountryListResponse(BaseModel):
+ """A page of countries."""
+
+ items: List[Item]
+
+ pagination: Pagination
+ """Pagination metadata for a list response."""
diff --git a/src/mobilerun_sdk/types/connect/proxy_buy_params.py b/src/mobilerun_sdk/types/connect/proxy_buy_params.py
new file mode 100644
index 0000000..77b9ded
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/proxy_buy_params.py
@@ -0,0 +1,14 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["ProxyBuyParams"]
+
+
+class ProxyBuyParams(TypedDict, total=False):
+ country: Required[str]
+ """ISO 3166-1 alpha-2 country code to provision the proxy in."""
+
+ type: Literal["residential"]
diff --git a/src/mobilerun_sdk/types/connect/proxy_buy_response.py b/src/mobilerun_sdk/types/connect/proxy_buy_response.py
new file mode 100644
index 0000000..52cf24d
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/proxy_buy_response.py
@@ -0,0 +1,48 @@
+# 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__ = ["ProxyBuyResponse"]
+
+
+class ProxyBuyResponse(BaseModel):
+ """A proxy including its password. Returned only on create and single-proxy reads."""
+
+ id: str
+
+ country: str
+ """ISO 3166-1 alpha-2 country code (lowercase)."""
+
+ created_at: datetime = FieldInfo(alias="createdAt")
+
+ host: str
+
+ password: str
+
+ port: int
+
+ status: Literal["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.
+ """
+
+ type: Literal["residential"]
+
+ username: str
+
+ payment_url: Optional[str] = FieldInfo(alias="paymentUrl", default=None)
+ """Checkout URL to complete payment while status is `pending_payment`.
+
+ Null once paid or when no payment was required.
+ """
diff --git a/src/mobilerun_sdk/types/connect/proxy_list_connections_params.py b/src/mobilerun_sdk/types/connect/proxy_list_connections_params.py
new file mode 100644
index 0000000..f921bb2
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/proxy_list_connections_params.py
@@ -0,0 +1,101 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["ProxyListConnectionsParams"]
+
+
+class ProxyListConnectionsParams(TypedDict, total=False):
+ close_reason: Annotated[str, PropertyInfo(alias="closeReason")]
+ """Filter to connections that closed with this reason (closed connections only)."""
+
+ country: str
+ """Filter to connections served from this upstream country (ISO 3166-1 alpha-2)."""
+
+ dst_host: Annotated[str, PropertyInfo(alias="dstHost")]
+ """Filter to connections to this destination host (exact match)."""
+
+ dst_port: Annotated[int, PropertyInfo(alias="dstPort")]
+ """Filter to connections to this destination port."""
+
+ ended_after: Annotated[Union[str, datetime], PropertyInfo(alias="endedAfter", format="iso8601")]
+ """
+ Filter to connections whose last activity was at or after this time (inclusive).
+ """
+
+ ended_before: Annotated[Union[str, datetime], PropertyInfo(alias="endedBefore", format="iso8601")]
+ """
+ Filter to connections whose last activity was at or before this time
+ (inclusive).
+ """
+
+ max_bytes_in: Annotated[int, PropertyInfo(alias="maxBytesIn")]
+ """Filter to connections with at most this many bytes received from upstream."""
+
+ max_bytes_out: Annotated[int, PropertyInfo(alias="maxBytesOut")]
+ """Filter to connections with at most this many bytes sent to upstream."""
+
+ max_duration_ms: Annotated[int, PropertyInfo(alias="maxDurationMs")]
+ """Filter to connections lasting at most this many milliseconds."""
+
+ max_total_bytes: Annotated[int, PropertyInfo(alias="maxTotalBytes")]
+ """
+ Filter to connections with at most this much total traffic (bytesIn + bytesOut).
+ """
+
+ min_bytes_in: Annotated[int, PropertyInfo(alias="minBytesIn")]
+ """Filter to connections with at least this many bytes received from upstream."""
+
+ min_bytes_out: Annotated[int, PropertyInfo(alias="minBytesOut")]
+ """Filter to connections with at least this many bytes sent to upstream."""
+
+ min_duration_ms: Annotated[int, PropertyInfo(alias="minDurationMs")]
+ """Filter to connections lasting at least this many milliseconds."""
+
+ min_total_bytes: Annotated[int, PropertyInfo(alias="minTotalBytes")]
+ """
+ Filter to connections with at least this much total traffic (bytesIn +
+ bytesOut).
+ """
+
+ order: Literal["asc", "desc"]
+ """Sort direction."""
+
+ order_by: Annotated[
+ Literal["startedAt", "endedAt", "bytesIn", "bytesOut", "totalBytes", "durationMs"],
+ PropertyInfo(alias="orderBy"),
+ ]
+ """Property to order the results by."""
+
+ page: int
+ """Page number (1-based)."""
+
+ page_size: Annotated[int, PropertyInfo(alias="pageSize")]
+ """Number of items per page."""
+
+ protocol: Literal["tcp", "udp", "unknown"]
+ """Filter to connections of this transport protocol."""
+
+ provider: str
+ """Filter to connections served by this upstream provider."""
+
+ session_id: Annotated[str, PropertyInfo(alias="sessionId")]
+ """Filter to a single connection by its session id."""
+
+ started_after: Annotated[Union[str, datetime], PropertyInfo(alias="startedAfter", format="iso8601")]
+ """Filter to connections that started at or after this time (inclusive)."""
+
+ started_before: Annotated[Union[str, datetime], PropertyInfo(alias="startedBefore", format="iso8601")]
+ """Filter to connections that started at or before this time (inclusive)."""
+
+ status: Literal["active", "closed"]
+ """Filter by connection status."""
+
+ user_id: Annotated[str, PropertyInfo(alias="userId")]
+ """Filter to connections made by this user."""
diff --git a/src/mobilerun_sdk/types/connect/proxy_list_connections_response.py b/src/mobilerun_sdk/types/connect/proxy_list_connections_response.py
new file mode 100644
index 0000000..bf9a9c4
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/proxy_list_connections_response.py
@@ -0,0 +1,106 @@
+# 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__ = ["ProxyListConnectionsResponse", "Item", "Pagination"]
+
+
+class Item(BaseModel):
+ """A single proxy connection, aggregated across its lifetime.
+
+ Byte counts are totals for the whole connection.
+ """
+
+ bytes_in: int = FieldInfo(alias="bytesIn")
+ """Total bytes received from upstream over the connection's lifetime."""
+
+ bytes_out: int = FieldInfo(alias="bytesOut")
+ """Total bytes sent to upstream over the connection's lifetime."""
+
+ country: str
+ """Upstream country code (ISO 3166-1 alpha-2), or empty if unknown."""
+
+ dst_host: str = FieldInfo(alias="dstHost")
+ """Destination host the client connected to."""
+
+ dst_port: int = FieldInfo(alias="dstPort")
+ """Destination port the client connected to."""
+
+ duration_ms: int = FieldInfo(alias="durationMs")
+ """Elapsed time between startedAt and endedAt, in milliseconds."""
+
+ ended_at: datetime = FieldInfo(alias="endedAt")
+ """Time of the connection's last recorded activity (close time once closed)."""
+
+ protocol: Literal["tcp", "udp", "unknown"]
+ """Transport protocol of a connection."""
+
+ provider: str
+ """Upstream provider that served the connection."""
+
+ proxy_id: str = FieldInfo(alias="proxyId")
+ """The proxy the connection was routed through.
+
+ All-zero when the upstream was unresolved at capture time.
+ """
+
+ session_id: str = FieldInfo(alias="sessionId")
+ """Unique id of this connection."""
+
+ src_ip: str = FieldInfo(alias="srcIp")
+ """Client source IP address."""
+
+ started_at: datetime = FieldInfo(alias="startedAt")
+ """When the connection started."""
+
+ status: Literal["active", "closed"]
+ """
+ `active` while the connection is still open (no terminal record yet); `closed`
+ once it has ended.
+ """
+
+ total_bytes: int = FieldInfo(alias="totalBytes")
+ """bytesIn + bytesOut."""
+
+ user_id: str = FieldInfo(alias="userId")
+ """The user that made the connection."""
+
+ close_reason: Optional[str] = FieldInfo(alias="closeReason", default=None)
+ """Why the connection closed; null while still active."""
+
+
+class Pagination(BaseModel):
+ """Pagination metadata for a list response."""
+
+ has_next: bool = FieldInfo(alias="hasNext")
+ """Whether a next page exists."""
+
+ has_prev: bool = FieldInfo(alias="hasPrev")
+ """Whether a previous page exists."""
+
+ page: int
+ """Current page number (1-based)."""
+
+ pages: int
+ """Total number of pages."""
+
+ page_size: int = FieldInfo(alias="pageSize")
+ """Number of items per page."""
+
+ total: int
+ """Total number of items across all pages."""
+
+
+class ProxyListConnectionsResponse(BaseModel):
+ """A page of connections."""
+
+ items: List[Item]
+
+ pagination: Pagination
+ """Pagination metadata for a list response."""
diff --git a/src/mobilerun_sdk/types/connect/proxy_list_params.py b/src/mobilerun_sdk/types/connect/proxy_list_params.py
new file mode 100644
index 0000000..58dec10
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/proxy_list_params.py
@@ -0,0 +1,20 @@
+# 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__ = ["ProxyListParams"]
+
+
+class ProxyListParams(TypedDict, total=False):
+ country: str
+ """Filter to proxies in this country (ISO 3166-1 alpha-2, lowercase)."""
+
+ page: int
+ """Page number (1-based)."""
+
+ page_size: Annotated[int, PropertyInfo(alias="pageSize")]
+ """Number of items per page."""
diff --git a/src/mobilerun_sdk/types/connect/proxy_list_response.py b/src/mobilerun_sdk/types/connect/proxy_list_response.py
new file mode 100644
index 0000000..b46e7ec
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/proxy_list_response.py
@@ -0,0 +1,71 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+from datetime import datetime
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["ProxyListResponse", "Item", "Pagination"]
+
+
+class Item(BaseModel):
+ """A provisioned proxy without its credentials."""
+
+ id: str
+
+ country: str
+ """ISO 3166-1 alpha-2 country code (lowercase)."""
+
+ created_at: datetime = FieldInfo(alias="createdAt")
+
+ host: str
+
+ port: int
+
+ status: Literal["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.
+ """
+
+ type: Literal["residential"]
+
+ username: str
+
+
+class Pagination(BaseModel):
+ """Pagination metadata for a list response."""
+
+ has_next: bool = FieldInfo(alias="hasNext")
+ """Whether a next page exists."""
+
+ has_prev: bool = FieldInfo(alias="hasPrev")
+ """Whether a previous page exists."""
+
+ page: int
+ """Current page number (1-based)."""
+
+ pages: int
+ """Total number of pages."""
+
+ page_size: int = FieldInfo(alias="pageSize")
+ """Number of items per page."""
+
+ total: int
+ """Total number of items across all pages."""
+
+
+class ProxyListResponse(BaseModel):
+ """A page of proxies."""
+
+ items: List[Item]
+
+ pagination: Pagination
+ """Pagination metadata for a list response."""
diff --git a/src/mobilerun_sdk/types/connect/proxy_ping_response.py b/src/mobilerun_sdk/types/connect/proxy_ping_response.py
new file mode 100644
index 0000000..8ad5243
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/proxy_ping_response.py
@@ -0,0 +1,50 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["ProxyPingResponse", "Latency"]
+
+
+class Latency(BaseModel):
+ """An aggregated latency measurement taken through the proxy."""
+
+ avg_ms: int = FieldInfo(alias="avgMs")
+ """Mean round-trip time over successful probes, in milliseconds."""
+
+ jitter_ms: int = FieldInfo(alias="jitterMs")
+ """Round-trip time spread (max - min) over successful probes, in milliseconds."""
+
+ max_ms: int = FieldInfo(alias="maxMs")
+ """Maximum round-trip time over successful probes, in milliseconds."""
+
+ measured_at: datetime = FieldInfo(alias="measuredAt")
+ """When this measurement was taken."""
+
+ min_ms: int = FieldInfo(alias="minMs")
+ """Minimum round-trip time over successful probes, in milliseconds."""
+
+ packet_loss: float = FieldInfo(alias="packetLoss")
+ """
+ Fraction of probes that failed, 0..1 (1 means the proxy was unreachable; rtt
+ fields are 0).
+ """
+
+ samples: int
+ """Number of probes taken in this measurement."""
+
+ target: str
+ """The host:port the latency was measured against, through the proxy."""
+
+
+class ProxyPingResponse(BaseModel):
+ """The latest cached latency reading for a proxy."""
+
+ latency: Optional[Latency] = None
+ """An aggregated latency measurement taken through the proxy."""
+
+ proxy_id: str = FieldInfo(alias="proxyId")
diff --git a/src/mobilerun_sdk/types/connect/proxy_retrieve_response.py b/src/mobilerun_sdk/types/connect/proxy_retrieve_response.py
new file mode 100644
index 0000000..f594cb5
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/proxy_retrieve_response.py
@@ -0,0 +1,48 @@
+# 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__ = ["ProxyRetrieveResponse"]
+
+
+class ProxyRetrieveResponse(BaseModel):
+ """A proxy including its password. Returned only on create and single-proxy reads."""
+
+ id: str
+
+ country: str
+ """ISO 3166-1 alpha-2 country code (lowercase)."""
+
+ created_at: datetime = FieldInfo(alias="createdAt")
+
+ host: str
+
+ password: str
+
+ port: int
+
+ status: Literal["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.
+ """
+
+ type: Literal["residential"]
+
+ username: str
+
+ payment_url: Optional[str] = FieldInfo(alias="paymentUrl", default=None)
+ """Checkout URL to complete payment while status is `pending_payment`.
+
+ Null once paid or when no payment was required.
+ """
diff --git a/src/mobilerun_sdk/types/connect/user_create_params.py b/src/mobilerun_sdk/types/connect/user_create_params.py
new file mode 100644
index 0000000..c8b7f59
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/user_create_params.py
@@ -0,0 +1,20 @@
+# 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__ = ["UserCreateParams"]
+
+
+class UserCreateParams(TypedDict, total=False):
+ password: str
+ """Desired SOCKS5 password, 1-255 bytes (RFC 1929). Generated when omitted."""
+
+ proxy_id: Annotated[str, PropertyInfo(alias="proxyId")]
+ """Proxy to bind the user to for dedicated routing."""
+
+ username: str
+ """Desired SOCKS5 username, 1-255 bytes (RFC 1929). Generated when omitted."""
diff --git a/src/mobilerun_sdk/types/connect/user_create_response.py b/src/mobilerun_sdk/types/connect/user_create_response.py
new file mode 100644
index 0000000..6235ac3
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/user_create_response.py
@@ -0,0 +1,28 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["UserCreateResponse"]
+
+
+class UserCreateResponse(BaseModel):
+ """A SOCKS5 user including its password.
+
+ Returned only on create and single-user reads.
+ """
+
+ id: str
+
+ created_at: datetime = FieldInfo(alias="createdAt")
+
+ password: str
+
+ username: str
+
+ proxy_id: Optional[str] = FieldInfo(alias="proxyId", default=None)
+ """The proxy this user routes to (dedicated routing), or null if unbound."""
diff --git a/src/mobilerun_sdk/types/connect/user_list_connections_params.py b/src/mobilerun_sdk/types/connect/user_list_connections_params.py
new file mode 100644
index 0000000..c8a242f
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/user_list_connections_params.py
@@ -0,0 +1,101 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["UserListConnectionsParams"]
+
+
+class UserListConnectionsParams(TypedDict, total=False):
+ close_reason: Annotated[str, PropertyInfo(alias="closeReason")]
+ """Filter to connections that closed with this reason (closed connections only)."""
+
+ country: str
+ """Filter to connections served from this upstream country (ISO 3166-1 alpha-2)."""
+
+ dst_host: Annotated[str, PropertyInfo(alias="dstHost")]
+ """Filter to connections to this destination host (exact match)."""
+
+ dst_port: Annotated[int, PropertyInfo(alias="dstPort")]
+ """Filter to connections to this destination port."""
+
+ ended_after: Annotated[Union[str, datetime], PropertyInfo(alias="endedAfter", format="iso8601")]
+ """
+ Filter to connections whose last activity was at or after this time (inclusive).
+ """
+
+ ended_before: Annotated[Union[str, datetime], PropertyInfo(alias="endedBefore", format="iso8601")]
+ """
+ Filter to connections whose last activity was at or before this time
+ (inclusive).
+ """
+
+ max_bytes_in: Annotated[int, PropertyInfo(alias="maxBytesIn")]
+ """Filter to connections with at most this many bytes received from upstream."""
+
+ max_bytes_out: Annotated[int, PropertyInfo(alias="maxBytesOut")]
+ """Filter to connections with at most this many bytes sent to upstream."""
+
+ max_duration_ms: Annotated[int, PropertyInfo(alias="maxDurationMs")]
+ """Filter to connections lasting at most this many milliseconds."""
+
+ max_total_bytes: Annotated[int, PropertyInfo(alias="maxTotalBytes")]
+ """
+ Filter to connections with at most this much total traffic (bytesIn + bytesOut).
+ """
+
+ min_bytes_in: Annotated[int, PropertyInfo(alias="minBytesIn")]
+ """Filter to connections with at least this many bytes received from upstream."""
+
+ min_bytes_out: Annotated[int, PropertyInfo(alias="minBytesOut")]
+ """Filter to connections with at least this many bytes sent to upstream."""
+
+ min_duration_ms: Annotated[int, PropertyInfo(alias="minDurationMs")]
+ """Filter to connections lasting at least this many milliseconds."""
+
+ min_total_bytes: Annotated[int, PropertyInfo(alias="minTotalBytes")]
+ """
+ Filter to connections with at least this much total traffic (bytesIn +
+ bytesOut).
+ """
+
+ order: Literal["asc", "desc"]
+ """Sort direction."""
+
+ order_by: Annotated[
+ Literal["startedAt", "endedAt", "bytesIn", "bytesOut", "totalBytes", "durationMs"],
+ PropertyInfo(alias="orderBy"),
+ ]
+ """Property to order the results by."""
+
+ page: int
+ """Page number (1-based)."""
+
+ page_size: Annotated[int, PropertyInfo(alias="pageSize")]
+ """Number of items per page."""
+
+ protocol: Literal["tcp", "udp", "unknown"]
+ """Filter to connections of this transport protocol."""
+
+ provider: str
+ """Filter to connections served by this upstream provider."""
+
+ proxy_id: Annotated[str, PropertyInfo(alias="proxyId")]
+ """Filter to connections routed through this proxy."""
+
+ session_id: Annotated[str, PropertyInfo(alias="sessionId")]
+ """Filter to a single connection by its session id."""
+
+ started_after: Annotated[Union[str, datetime], PropertyInfo(alias="startedAfter", format="iso8601")]
+ """Filter to connections that started at or after this time (inclusive)."""
+
+ started_before: Annotated[Union[str, datetime], PropertyInfo(alias="startedBefore", format="iso8601")]
+ """Filter to connections that started at or before this time (inclusive)."""
+
+ status: Literal["active", "closed"]
+ """Filter by connection status."""
diff --git a/src/mobilerun_sdk/types/connect/user_list_connections_response.py b/src/mobilerun_sdk/types/connect/user_list_connections_response.py
new file mode 100644
index 0000000..cf0db91
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/user_list_connections_response.py
@@ -0,0 +1,106 @@
+# 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__ = ["UserListConnectionsResponse", "Item", "Pagination"]
+
+
+class Item(BaseModel):
+ """A single proxy connection, aggregated across its lifetime.
+
+ Byte counts are totals for the whole connection.
+ """
+
+ bytes_in: int = FieldInfo(alias="bytesIn")
+ """Total bytes received from upstream over the connection's lifetime."""
+
+ bytes_out: int = FieldInfo(alias="bytesOut")
+ """Total bytes sent to upstream over the connection's lifetime."""
+
+ country: str
+ """Upstream country code (ISO 3166-1 alpha-2), or empty if unknown."""
+
+ dst_host: str = FieldInfo(alias="dstHost")
+ """Destination host the client connected to."""
+
+ dst_port: int = FieldInfo(alias="dstPort")
+ """Destination port the client connected to."""
+
+ duration_ms: int = FieldInfo(alias="durationMs")
+ """Elapsed time between startedAt and endedAt, in milliseconds."""
+
+ ended_at: datetime = FieldInfo(alias="endedAt")
+ """Time of the connection's last recorded activity (close time once closed)."""
+
+ protocol: Literal["tcp", "udp", "unknown"]
+ """Transport protocol of a connection."""
+
+ provider: str
+ """Upstream provider that served the connection."""
+
+ proxy_id: str = FieldInfo(alias="proxyId")
+ """The proxy the connection was routed through.
+
+ All-zero when the upstream was unresolved at capture time.
+ """
+
+ session_id: str = FieldInfo(alias="sessionId")
+ """Unique id of this connection."""
+
+ src_ip: str = FieldInfo(alias="srcIp")
+ """Client source IP address."""
+
+ started_at: datetime = FieldInfo(alias="startedAt")
+ """When the connection started."""
+
+ status: Literal["active", "closed"]
+ """
+ `active` while the connection is still open (no terminal record yet); `closed`
+ once it has ended.
+ """
+
+ total_bytes: int = FieldInfo(alias="totalBytes")
+ """bytesIn + bytesOut."""
+
+ user_id: str = FieldInfo(alias="userId")
+ """The user that made the connection."""
+
+ close_reason: Optional[str] = FieldInfo(alias="closeReason", default=None)
+ """Why the connection closed; null while still active."""
+
+
+class Pagination(BaseModel):
+ """Pagination metadata for a list response."""
+
+ has_next: bool = FieldInfo(alias="hasNext")
+ """Whether a next page exists."""
+
+ has_prev: bool = FieldInfo(alias="hasPrev")
+ """Whether a previous page exists."""
+
+ page: int
+ """Current page number (1-based)."""
+
+ pages: int
+ """Total number of pages."""
+
+ page_size: int = FieldInfo(alias="pageSize")
+ """Number of items per page."""
+
+ total: int
+ """Total number of items across all pages."""
+
+
+class UserListConnectionsResponse(BaseModel):
+ """A page of connections."""
+
+ items: List[Item]
+
+ pagination: Pagination
+ """Pagination metadata for a list response."""
diff --git a/src/mobilerun_sdk/types/connect/user_list_params.py b/src/mobilerun_sdk/types/connect/user_list_params.py
new file mode 100644
index 0000000..1cd7523
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/user_list_params.py
@@ -0,0 +1,23 @@
+# 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__ = ["UserListParams"]
+
+
+class UserListParams(TypedDict, total=False):
+ page: int
+ """Page number (1-based)."""
+
+ page_size: Annotated[int, PropertyInfo(alias="pageSize")]
+ """Number of items per page."""
+
+ proxy_id: Annotated[str, PropertyInfo(alias="proxyId")]
+ """Filter to users bound to this proxy.
+
+ Users not bound to it (including unbound users) are excluded.
+ """
diff --git a/src/mobilerun_sdk/types/connect/user_list_response.py b/src/mobilerun_sdk/types/connect/user_list_response.py
new file mode 100644
index 0000000..2f42145
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/user_list_response.py
@@ -0,0 +1,54 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["UserListResponse", "Item", "Pagination"]
+
+
+class Item(BaseModel):
+ """A SOCKS5 credential without its password."""
+
+ id: str
+
+ created_at: datetime = FieldInfo(alias="createdAt")
+
+ username: str
+
+ proxy_id: Optional[str] = FieldInfo(alias="proxyId", default=None)
+ """The proxy this user routes to (dedicated routing), or null if unbound."""
+
+
+class Pagination(BaseModel):
+ """Pagination metadata for a list response."""
+
+ has_next: bool = FieldInfo(alias="hasNext")
+ """Whether a next page exists."""
+
+ has_prev: bool = FieldInfo(alias="hasPrev")
+ """Whether a previous page exists."""
+
+ page: int
+ """Current page number (1-based)."""
+
+ pages: int
+ """Total number of pages."""
+
+ page_size: int = FieldInfo(alias="pageSize")
+ """Number of items per page."""
+
+ total: int
+ """Total number of items across all pages."""
+
+
+class UserListResponse(BaseModel):
+ """A page of SOCKS5 users."""
+
+ items: List[Item]
+
+ pagination: Pagination
+ """Pagination metadata for a list response."""
diff --git a/src/mobilerun_sdk/types/connect/user_retrieve_response.py b/src/mobilerun_sdk/types/connect/user_retrieve_response.py
new file mode 100644
index 0000000..0096215
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/user_retrieve_response.py
@@ -0,0 +1,28 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["UserRetrieveResponse"]
+
+
+class UserRetrieveResponse(BaseModel):
+ """A SOCKS5 user including its password.
+
+ Returned only on create and single-user reads.
+ """
+
+ id: str
+
+ created_at: datetime = FieldInfo(alias="createdAt")
+
+ password: str
+
+ username: str
+
+ proxy_id: Optional[str] = FieldInfo(alias="proxyId", default=None)
+ """The proxy this user routes to (dedicated routing), or null if unbound."""
diff --git a/src/mobilerun_sdk/types/connect/user_update_params.py b/src/mobilerun_sdk/types/connect/user_update_params.py
new file mode 100644
index 0000000..b8a9f79
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/user_update_params.py
@@ -0,0 +1,19 @@
+# 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__ = ["UserUpdateParams"]
+
+
+class UserUpdateParams(TypedDict, total=False):
+ proxy_id: Annotated[Optional[str], PropertyInfo(alias="proxyId")]
+ """Proxy to rebind to, or null to detach.
+
+ Omit to leave the user's current binding unchanged — only an explicit null
+ detaches.
+ """
diff --git a/src/mobilerun_sdk/types/connect/user_update_response.py b/src/mobilerun_sdk/types/connect/user_update_response.py
new file mode 100644
index 0000000..c2f0535
--- /dev/null
+++ b/src/mobilerun_sdk/types/connect/user_update_response.py
@@ -0,0 +1,23 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["UserUpdateResponse"]
+
+
+class UserUpdateResponse(BaseModel):
+ """A SOCKS5 credential without its password."""
+
+ id: str
+
+ created_at: datetime = FieldInfo(alias="createdAt")
+
+ username: str
+
+ proxy_id: Optional[str] = FieldInfo(alias="proxyId", default=None)
+ """The proxy this user routes to (dedicated routing), or null if unbound."""
diff --git a/src/mobilerun_sdk/types/devices/__init__.py b/src/mobilerun_sdk/types/devices/__init__.py
index ea98848..ab80387 100644
--- a/src/mobilerun_sdk/types/devices/__init__.py
+++ b/src/mobilerun_sdk/types/devices/__init__.py
@@ -4,6 +4,7 @@
from .rect import Rect as Rect
from .file_info import FileInfo as FileInfo
+from .a11_y_node import A11YNode as A11YNode
from .app_list_params import AppListParams as AppListParams
from .state_ui_params import StateUiParams as StateUiParams
from .app_start_params import AppStartParams as AppStartParams
@@ -29,7 +30,6 @@
from .timezone_set_params import TimezoneSetParams as TimezoneSetParams
from .action_global_params import ActionGlobalParams as ActionGlobalParams
from .esim_activate_params import EsimActivateParams as EsimActivateParams
-from .esim_status_response import EsimStatusResponse as EsimStatusResponse
from .file_download_params import FileDownloadParams as FileDownloadParams
from .proxy_connect_params import ProxyConnectParams as ProxyConnectParams
from .keyboard_write_params import KeyboardWriteParams as KeyboardWriteParams
@@ -40,7 +40,6 @@
from .timezone_get_response import TimezoneGetResponse as TimezoneGetResponse
from .esim_activate_response import EsimActivateResponse as EsimActivateResponse
from .file_download_response import FileDownloadResponse as FileDownloadResponse
-from .esim_set_roaming_params import EsimSetRoamingParams as EsimSetRoamingParams
from .state_screenshot_params import StateScreenshotParams as StateScreenshotParams
from .state_screenshot_response import StateScreenshotResponse as StateScreenshotResponse
from .action_overlay_visible_response import ActionOverlayVisibleResponse as ActionOverlayVisibleResponse
diff --git a/src/mobilerun_sdk/types/devices/a11_y_node.py b/src/mobilerun_sdk/types/devices/a11_y_node.py
new file mode 100644
index 0000000..aa4eb12
--- /dev/null
+++ b/src/mobilerun_sdk/types/devices/a11_y_node.py
@@ -0,0 +1,57 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import List, Optional
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["A11YNode", "BoundsInScreen"]
+
+
+class BoundsInScreen(BaseModel):
+ bottom: int
+
+ left: int
+
+ right: int
+
+ top: int
+
+
+class A11YNode(BaseModel):
+ bounds_in_screen: BoundsInScreen = FieldInfo(alias="boundsInScreen")
+
+ children: Optional[List["A11YNode"]] = None
+
+ class_name: str = FieldInfo(alias="className")
+
+ content_description: str = FieldInfo(alias="contentDescription")
+
+ is_checkable: bool = FieldInfo(alias="isCheckable")
+
+ is_checked: bool = FieldInfo(alias="isChecked")
+
+ is_clickable: bool = FieldInfo(alias="isClickable")
+
+ is_enabled: bool = FieldInfo(alias="isEnabled")
+
+ is_focusable: bool = FieldInfo(alias="isFocusable")
+
+ is_focused: bool = FieldInfo(alias="isFocused")
+
+ is_long_clickable: bool = FieldInfo(alias="isLongClickable")
+
+ is_password: bool = FieldInfo(alias="isPassword")
+
+ is_scrollable: bool = FieldInfo(alias="isScrollable")
+
+ is_selected: bool = FieldInfo(alias="isSelected")
+
+ package_name: str = FieldInfo(alias="packageName")
+
+ resource_id: str = FieldInfo(alias="resourceId")
+
+ text: str
diff --git a/src/mobilerun_sdk/types/devices/esim/__init__.py b/src/mobilerun_sdk/types/devices/esim/__init__.py
deleted file mode 100644
index 7fb2236..0000000
--- a/src/mobilerun_sdk/types/devices/esim/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from .apn_create_params import ApnCreateParams as ApnCreateParams
-from .apn_list_response import ApnListResponse as ApnListResponse
-from .apn_select_params import ApnSelectParams as ApnSelectParams
diff --git a/src/mobilerun_sdk/types/devices/esim/apn_create_params.py b/src/mobilerun_sdk/types/devices/esim/apn_create_params.py
deleted file mode 100644
index ffb2434..0000000
--- a/src/mobilerun_sdk/types/devices/esim/apn_create_params.py
+++ /dev/null
@@ -1,29 +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__ = ["ApnCreateParams"]
-
-
-class ApnCreateParams(TypedDict, total=False):
- apn: Required[str]
-
- mcc: Required[str]
-
- mnc: Required[str]
-
- name: Required[str]
-
- protocol: Required[str]
-
- roaming_protocol: Required[Annotated[str, PropertyInfo(alias="roamingProtocol")]]
-
- sub_id: Required[Annotated[int, PropertyInfo(alias="subId")]]
-
- type: Required[str]
-
- x_device_display_id: Annotated[int, PropertyInfo(alias="X-Device-Display-ID")]
diff --git a/src/mobilerun_sdk/types/devices/esim/apn_list_response.py b/src/mobilerun_sdk/types/devices/esim/apn_list_response.py
deleted file mode 100644
index 41bd145..0000000
--- a/src/mobilerun_sdk/types/devices/esim/apn_list_response.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-from typing_extensions import TypeAlias
-
-from pydantic import Field as FieldInfo
-
-from ...._models import BaseModel
-
-__all__ = ["ApnListResponse", "ApnListResponseItem"]
-
-
-class ApnListResponseItem(BaseModel):
- id: int
-
- apn: str
-
- is_preferred: bool = FieldInfo(alias="isPreferred")
-
- mcc: str
-
- mnc: str
-
- name: str
-
- protocol: str
-
- roaming_protocol: str = FieldInfo(alias="roamingProtocol")
-
- sub_id: int = FieldInfo(alias="subId")
-
- type: str
-
-
-ApnListResponse: TypeAlias = List[ApnListResponseItem]
diff --git a/src/mobilerun_sdk/types/devices/esim/apn_select_params.py b/src/mobilerun_sdk/types/devices/esim/apn_select_params.py
deleted file mode 100644
index ca44100..0000000
--- a/src/mobilerun_sdk/types/devices/esim/apn_select_params.py
+++ /dev/null
@@ -1,17 +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__ = ["ApnSelectParams"]
-
-
-class ApnSelectParams(TypedDict, total=False):
- apn_id: Required[Annotated[int, PropertyInfo(alias="apnId")]]
-
- sub_id: Required[Annotated[int, PropertyInfo(alias="subId")]]
-
- x_device_display_id: Annotated[int, PropertyInfo(alias="X-Device-Display-ID")]
diff --git a/src/mobilerun_sdk/types/devices/esim_set_roaming_params.py b/src/mobilerun_sdk/types/devices/esim_set_roaming_params.py
deleted file mode 100644
index 218544c..0000000
--- a/src/mobilerun_sdk/types/devices/esim_set_roaming_params.py
+++ /dev/null
@@ -1,15 +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__ = ["EsimSetRoamingParams"]
-
-
-class EsimSetRoamingParams(TypedDict, total=False):
- enabled: Required[bool]
-
- x_device_display_id: Annotated[int, PropertyInfo(alias="X-Device-Display-ID")]
diff --git a/src/mobilerun_sdk/types/devices/esim_status_response.py b/src/mobilerun_sdk/types/devices/esim_status_response.py
deleted file mode 100644
index 9a42b6e..0000000
--- a/src/mobilerun_sdk/types/devices/esim_status_response.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-from typing_extensions import TypeAlias
-
-from pydantic import Field as FieldInfo
-
-from ..._models import BaseModel
-
-__all__ = ["EsimStatusResponse", "EsimStatusResponseItem"]
-
-
-class EsimStatusResponseItem(BaseModel):
- carrier: str
-
- data_roaming_enabled: bool = FieldInfo(alias="dataRoamingEnabled")
-
- data_state: str = FieldInfo(alias="dataState")
-
- is_roaming: bool = FieldInfo(alias="isRoaming")
-
- mobile_data_enabled: bool = FieldInfo(alias="mobileDataEnabled")
-
- network_type: str = FieldInfo(alias="networkType")
-
- operator: str
-
- phone_type: str = FieldInfo(alias="phoneType")
-
- sim_state: str = FieldInfo(alias="simState")
-
- sub_id: int = FieldInfo(alias="subId")
-
-
-EsimStatusResponse: TypeAlias = List[EsimStatusResponseItem]
diff --git a/src/mobilerun_sdk/types/devices/state_ui_response.py b/src/mobilerun_sdk/types/devices/state_ui_response.py
index bdddd0c..54fa0bc 100644
--- a/src/mobilerun_sdk/types/devices/state_ui_response.py
+++ b/src/mobilerun_sdk/types/devices/state_ui_response.py
@@ -1,5 +1,7 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from __future__ import annotations
+
from typing import Optional
from pydantic import Field as FieldInfo
@@ -42,8 +44,6 @@ class DeviceContext(BaseModel):
screen_bounds: Rect
- screen_size: Rect = FieldInfo(alias="screenSize")
-
class PhoneStateFocusedElement(BaseModel):
class_name: Optional[str] = FieldInfo(alias="className", default=None)
@@ -68,13 +68,16 @@ class PhoneState(BaseModel):
class StateUiResponse(BaseModel):
- a11y_tree: object
+ a11y_tree: "A11YNode"
device_context: DeviceContext
+ ime_tree: "A11YNode"
+
phone_state: PhoneState
schema_: Optional[str] = FieldInfo(alias="$schema", default=None)
"""A URL to the JSON Schema for this object."""
- ime_tree: Optional[object] = None
+
+from .a11_y_node import A11YNode
diff --git a/src/mobilerun_sdk/types/flow.py b/src/mobilerun_sdk/types/flow.py
new file mode 100644
index 0000000..908b874
--- /dev/null
+++ b/src/mobilerun_sdk/types/flow.py
@@ -0,0 +1,46 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from .._models import BaseModel
+
+__all__ = ["Flow"]
+
+
+class Flow(BaseModel):
+ id: str
+
+ blocked_at: Optional[str] = FieldInfo(alias="blockedAt", default=None)
+
+ consecutive_failures: int = FieldInfo(alias="consecutiveFailures")
+
+ cooldown_scope: Literal["flow", "device"] = FieldInfo(alias="cooldownScope")
+
+ cooldown_seconds: Optional[int] = FieldInfo(alias="cooldownSeconds", default=None)
+
+ created_at: Optional[str] = FieldInfo(alias="createdAt", default=None)
+
+ description: Optional[str] = None
+
+ enabled: bool
+
+ last_failure_at: Optional[str] = FieldInfo(alias="lastFailureAt", default=None)
+
+ last_failure_code: Optional[
+ Literal["device_not_found", "permission_denied", "client_error", "transient", "logic"]
+ ] = FieldInfo(alias="lastFailureCode", default=None)
+
+ last_triggered_at: Optional[str] = FieldInfo(alias="lastTriggeredAt", default=None)
+
+ name: str
+
+ status: Literal["healthy", "failing", "blocked"]
+
+ trigger_id: str = FieldInfo(alias="triggerId")
+
+ updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None)
+
+ user_id: str = FieldInfo(alias="userId")
diff --git a/src/mobilerun_sdk/types/hook_test_params.py b/src/mobilerun_sdk/types/hook_test_params.py
new file mode 100644
index 0000000..af5edff
--- /dev/null
+++ b/src/mobilerun_sdk/types/hook_test_params.py
@@ -0,0 +1,13 @@
+# 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__ = ["HookTestParams"]
+
+
+class HookTestParams(TypedDict, total=False):
+ event: Optional[str]
+ """Event type to simulate (default: completed)"""
diff --git a/src/mobilerun_sdk/types/hook_test_response.py b/src/mobilerun_sdk/types/hook_test_response.py
new file mode 100644
index 0000000..8d22bab
--- /dev/null
+++ b/src/mobilerun_sdk/types/hook_test_response.py
@@ -0,0 +1,25 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from pydantic import Field as FieldInfo
+
+from .._models import BaseModel
+
+__all__ = ["HookTestResponse"]
+
+
+class HookTestResponse(BaseModel):
+ """Response after attempting test delivery."""
+
+ id: str
+ """The hook ID"""
+
+ success: bool
+ """Whether delivery succeeded (2xx)"""
+
+ error: Optional[str] = None
+ """Error message if delivery failed"""
+
+ status_code: Optional[int] = FieldInfo(alias="statusCode", default=None)
+ """HTTP status from target"""
diff --git a/src/mobilerun_sdk/types/proxy_lookup_params.py b/src/mobilerun_sdk/types/proxy_lookup_params.py
new file mode 100644
index 0000000..43b7464
--- /dev/null
+++ b/src/mobilerun_sdk/types/proxy_lookup_params.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["ProxyLookupParams", "Socks5"]
+
+
+class ProxyLookupParams(TypedDict, total=False):
+ socks5: Required[Socks5]
+ """SOCKS5 proxy configuration."""
+
+
+class Socks5(TypedDict, total=False):
+ """SOCKS5 proxy configuration."""
+
+ host: Required[str]
+
+ port: Required[int]
+
+ password: str
+
+ user: str
diff --git a/src/mobilerun_sdk/types/proxy_lookup_response.py b/src/mobilerun_sdk/types/proxy_lookup_response.py
new file mode 100644
index 0000000..6e4e88f
--- /dev/null
+++ b/src/mobilerun_sdk/types/proxy_lookup_response.py
@@ -0,0 +1,57 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from pydantic import Field as FieldInfo
+
+from .._models import BaseModel
+
+__all__ = ["ProxyLookupResponse", "Carrier"]
+
+
+class Carrier(BaseModel):
+ """Mobile carrier information."""
+
+ mcc: Optional[str] = None
+ """Mobile Country Code."""
+
+ mnc: Optional[str] = None
+ """Mobile Network Code."""
+
+ name: Optional[str] = None
+ """Carrier name."""
+
+
+class ProxyLookupResponse(BaseModel):
+ ip: str
+ """IP address of the proxy."""
+
+ is_mobile: bool = FieldInfo(alias="isMobile")
+ """Whether the IP is a mobile connection."""
+
+ latitude: float
+ """Latitude of the proxy."""
+
+ longitude: float
+ """Longitude of the proxy."""
+
+ schema_: Optional[str] = FieldInfo(alias="$schema", default=None)
+ """A URL to the JSON Schema for this object."""
+
+ carrier: Optional[Carrier] = None
+ """Mobile carrier information."""
+
+ city: Optional[str] = None
+ """City of the proxy."""
+
+ country: Optional[str] = None
+ """Country of the proxy."""
+
+ country_code: Optional[str] = FieldInfo(alias="countryCode", default=None)
+ """ISO country code."""
+
+ region: Optional[str] = None
+ """Region of the proxy."""
+
+ timezone: Optional[str] = None
+ """Timezone of the proxy."""
diff --git a/src/mobilerun_sdk/types/task.py b/src/mobilerun_sdk/types/task.py
index 4a0f115..cc4dab6 100644
--- a/src/mobilerun_sdk/types/task.py
+++ b/src/mobilerun_sdk/types/task.py
@@ -25,6 +25,8 @@ class Task(BaseModel):
id: Optional[str] = None
+ accessibility: Optional[bool] = None
+
agent_id: Optional[int] = FieldInfo(alias="agentId", default=None)
apps: Optional[List[str]] = None
diff --git a/src/mobilerun_sdk/types/task_get_trajectory_response.py b/src/mobilerun_sdk/types/task_get_trajectory_response.py
index 241c5b1..0405cf9 100644
--- a/src/mobilerun_sdk/types/task_get_trajectory_response.py
+++ b/src/mobilerun_sdk/types/task_get_trajectory_response.py
@@ -212,7 +212,7 @@ class TrajectoryTrajectoryManagerInputEvent(BaseModel):
class TrajectoryTrajectoryManagerPlanEventData(BaseModel):
- """Coordination event from ManagerAgent to DroidAgent.
+ """Coordination event from ManagerAgent to MobileAgent.
Used for workflow step routing only (NOT streamed to frontend).
For internal events with memory_update metadata, see ManagerPlanDetailsEvent.
@@ -231,7 +231,7 @@ class TrajectoryTrajectoryManagerPlanEventData(BaseModel):
class TrajectoryTrajectoryManagerPlanEvent(BaseModel):
data: TrajectoryTrajectoryManagerPlanEventData
- """Coordination event from ManagerAgent to DroidAgent.
+ """Coordination event from ManagerAgent to MobileAgent.
Used for workflow step routing only (NOT streamed to frontend). For internal
events with memory_update metadata, see ManagerPlanDetailsEvent.
diff --git a/src/mobilerun_sdk/types/task_list_response.py b/src/mobilerun_sdk/types/task_list_response.py
index 16c8d1d..12a8a4c 100644
--- a/src/mobilerun_sdk/types/task_list_response.py
+++ b/src/mobilerun_sdk/types/task_list_response.py
@@ -34,6 +34,8 @@ class Item(BaseModel):
user_id: str = FieldInfo(alias="userId")
+ accessibility: Optional[bool] = None
+
agent_id: Optional[int] = FieldInfo(alias="agentId", default=None)
apps: Optional[List[str]] = None
diff --git a/src/mobilerun_sdk/types/task_run_params.py b/src/mobilerun_sdk/types/task_run_params.py
index 3a91df8..8fc6144 100644
--- a/src/mobilerun_sdk/types/task_run_params.py
+++ b/src/mobilerun_sdk/types/task_run_params.py
@@ -18,6 +18,8 @@ class TaskRunParams(TypedDict, total=False):
task: Required[str]
+ accessibility: bool
+
agent_id: Annotated[int, PropertyInfo(alias="agentId")]
apps: SequenceNotStr[str]
@@ -36,7 +38,7 @@ class TaskRunParams(TypedDict, total=False):
llm_model: Annotated[str, PropertyInfo(alias="llmModel")]
"""The LLM model identifier to use for the task (e.g.
- 'google/gemini-3.1-flash-lite-preview')
+ 'google/gemini-3.1-flash-lite')
"""
max_steps: Annotated[int, PropertyInfo(alias="maxSteps")]
diff --git a/src/mobilerun_sdk/types/task_run_streamed_params.py b/src/mobilerun_sdk/types/task_run_streamed_params.py
index 8c03add..1c0cfd6 100644
--- a/src/mobilerun_sdk/types/task_run_streamed_params.py
+++ b/src/mobilerun_sdk/types/task_run_streamed_params.py
@@ -18,6 +18,8 @@ class TaskRunStreamedParams(TypedDict, total=False):
task: Required[str]
+ accessibility: bool
+
agent_id: Annotated[int, PropertyInfo(alias="agentId")]
apps: SequenceNotStr[str]
@@ -36,7 +38,7 @@ class TaskRunStreamedParams(TypedDict, total=False):
llm_model: Annotated[str, PropertyInfo(alias="llmModel")]
"""The LLM model identifier to use for the task (e.g.
- 'google/gemini-3.1-flash-lite-preview')
+ 'google/gemini-3.1-flash-lite')
"""
max_steps: Annotated[int, PropertyInfo(alias="maxSteps")]
diff --git a/src/mobilerun_sdk/types/workflows/__init__.py b/src/mobilerun_sdk/types/workflows/__init__.py
new file mode 100644
index 0000000..89853e2
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/__init__.py
@@ -0,0 +1,56 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .action import Action as Action
+from .user_secret import UserSecret as UserSecret
+from .flow_execution import FlowExecution as FlowExecution
+from .flow_list_params import FlowListParams as FlowListParams
+from .flow_clone_params import FlowCloneParams as FlowCloneParams
+from .action_list_params import ActionListParams as ActionListParams
+from .flow_create_params import FlowCreateParams as FlowCreateParams
+from .flow_list_response import FlowListResponse as FlowListResponse
+from .flow_update_params import FlowUpdateParams as FlowUpdateParams
+from .event_ingest_params import EventIngestParams as EventIngestParams
+from .flow_clone_response import FlowCloneResponse as FlowCloneResponse
+from .trigger_fire_params import TriggerFireParams as TriggerFireParams
+from .trigger_list_params import TriggerListParams as TriggerListParams
+from .action_catalog_entry import ActionCatalogEntry as ActionCatalogEntry
+from .action_create_params import ActionCreateParams as ActionCreateParams
+from .action_list_response import ActionListResponse as ActionListResponse
+from .action_update_params import ActionUpdateParams as ActionUpdateParams
+from .event_dry_run_params import EventDryRunParams as EventDryRunParams
+from .flow_create_response import FlowCreateResponse as FlowCreateResponse
+from .flow_delete_response import FlowDeleteResponse as FlowDeleteResponse
+from .flow_update_response import FlowUpdateResponse as FlowUpdateResponse
+from .secret_create_params import SecretCreateParams as SecretCreateParams
+from .secret_list_response import SecretListResponse as SecretListResponse
+from .event_ingest_response import EventIngestResponse as EventIngestResponse
+from .execution_list_params import ExecutionListParams as ExecutionListParams
+from .flow_unblock_response import FlowUnblockResponse as FlowUnblockResponse
+from .trigger_create_params import TriggerCreateParams as TriggerCreateParams
+from .trigger_fire_response import TriggerFireResponse as TriggerFireResponse
+from .trigger_list_response import TriggerListResponse as TriggerListResponse
+from .trigger_update_params import TriggerUpdateParams as TriggerUpdateParams
+from .action_create_response import ActionCreateResponse as ActionCreateResponse
+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_retrieve_response import FlowRetrieveResponse as FlowRetrieveResponse
+from .secret_create_response import SecretCreateResponse as SecretCreateResponse
+from .secret_delete_response import SecretDeleteResponse as SecretDeleteResponse
+from .timezone_list_response import TimezoneListResponse as TimezoneListResponse
+from .execution_list_response import ExecutionListResponse as ExecutionListResponse
+from .trigger_create_response import TriggerCreateResponse as TriggerCreateResponse
+from .trigger_delete_response import TriggerDeleteResponse as TriggerDeleteResponse
+from .trigger_update_response import TriggerUpdateResponse as TriggerUpdateResponse
+from .action_retrieve_response import ActionRetrieveResponse as ActionRetrieveResponse
+from .trigger_retrieve_response import TriggerRetrieveResponse as TriggerRetrieveResponse
+from .action_catalog_list_params import ActionCatalogListParams as ActionCatalogListParams
+from .execution_retrieve_response import ExecutionRetrieveResponse as ExecutionRetrieveResponse
+from .flow_action_overrides_param import FlowActionOverridesParam as FlowActionOverridesParam
+from .action_catalog_list_response import ActionCatalogListResponse as ActionCatalogListResponse
+from .execution_get_metrics_params import ExecutionGetMetricsParams as ExecutionGetMetricsParams
+from .flow_child_action_input_param import FlowChildActionInputParam as FlowChildActionInputParam
+from .execution_get_metrics_response import ExecutionGetMetricsResponse as ExecutionGetMetricsResponse
+from .action_catalog_retrieve_response import ActionCatalogRetrieveResponse as ActionCatalogRetrieveResponse
diff --git a/src/mobilerun_sdk/types/workflows/action.py b/src/mobilerun_sdk/types/workflows/action.py
new file mode 100644
index 0000000..fb111f1
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/action.py
@@ -0,0 +1,36 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["Action"]
+
+
+class Action(BaseModel):
+ id: str
+
+ catalog_entry_id: str = FieldInfo(alias="catalogEntryId")
+
+ created_at: Optional[str] = FieldInfo(alias="createdAt", default=None)
+
+ description: Optional[str] = None
+
+ is_async: bool = FieldInfo(alias="isAsync")
+
+ method: str
+
+ name: str
+
+ service: Literal["tasks_api", "devices_api", "agents_api", "webhooks"]
+
+ updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None)
+
+ user_id: str = FieldInfo(alias="userId")
+
+ params: Optional[object] = None
+
+ params_schema: Optional[object] = FieldInfo(alias="paramsSchema", default=None)
diff --git a/src/mobilerun_sdk/types/workflows/action_catalog_entry.py b/src/mobilerun_sdk/types/workflows/action_catalog_entry.py
new file mode 100644
index 0000000..4eb711f
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/action_catalog_entry.py
@@ -0,0 +1,30 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["ActionCatalogEntry"]
+
+
+class ActionCatalogEntry(BaseModel):
+ id: str
+
+ created_at: Optional[str] = FieldInfo(alias="createdAt", default=None)
+
+ description: Optional[str] = None
+
+ is_async: bool = FieldInfo(alias="isAsync")
+
+ method: str
+
+ name: str
+
+ service: Literal["tasks_api", "devices_api", "agents_api", "webhooks"]
+
+ updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None)
+
+ params_schema: Optional[object] = FieldInfo(alias="paramsSchema", default=None)
diff --git a/src/mobilerun_sdk/types/workflows/action_catalog_list_params.py b/src/mobilerun_sdk/types/workflows/action_catalog_list_params.py
new file mode 100644
index 0000000..4e756a9
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/action_catalog_list_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 Literal, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["ActionCatalogListParams"]
+
+
+class ActionCatalogListParams(TypedDict, total=False):
+ page: int
+
+ page_size: Annotated[int, PropertyInfo(alias="pageSize")]
+
+ service: Literal["tasks_api", "devices_api", "agents_api", "webhooks"]
diff --git a/src/mobilerun_sdk/types/workflows/action_catalog_list_response.py b/src/mobilerun_sdk/types/workflows/action_catalog_list_response.py
new file mode 100644
index 0000000..967cfd0
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/action_catalog_list_response.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ..._models import BaseModel
+from ..shared.pagination import Pagination
+from .action_catalog_entry import ActionCatalogEntry
+
+__all__ = ["ActionCatalogListResponse"]
+
+
+class ActionCatalogListResponse(BaseModel):
+ items: List[ActionCatalogEntry]
+
+ pagination: Pagination
diff --git a/src/mobilerun_sdk/types/workflows/action_catalog_retrieve_response.py b/src/mobilerun_sdk/types/workflows/action_catalog_retrieve_response.py
new file mode 100644
index 0000000..81d1b5f
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/action_catalog_retrieve_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ..._models import BaseModel
+from .action_catalog_entry import ActionCatalogEntry
+
+__all__ = ["ActionCatalogRetrieveResponse"]
+
+
+class ActionCatalogRetrieveResponse(BaseModel):
+ data: ActionCatalogEntry
diff --git a/src/mobilerun_sdk/types/workflows/action_create_params.py b/src/mobilerun_sdk/types/workflows/action_create_params.py
new file mode 100644
index 0000000..b85ffed
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/action_create_params.py
@@ -0,0 +1,20 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Optional
+from typing_extensions import Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["ActionCreateParams"]
+
+
+class ActionCreateParams(TypedDict, total=False):
+ catalog_entry_id: Required[Annotated[str, PropertyInfo(alias="catalogEntryId")]]
+
+ name: Required[str]
+
+ description: str
+
+ params: Dict[str, Optional[object]]
diff --git a/src/mobilerun_sdk/types/workflows/action_create_response.py b/src/mobilerun_sdk/types/workflows/action_create_response.py
new file mode 100644
index 0000000..acd7aa5
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/action_create_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .action import Action
+from ..._models import BaseModel
+
+__all__ = ["ActionCreateResponse"]
+
+
+class ActionCreateResponse(BaseModel):
+ data: Action
diff --git a/src/mobilerun_sdk/types/workflows/action_delete_response.py b/src/mobilerun_sdk/types/workflows/action_delete_response.py
new file mode 100644
index 0000000..157bb1f
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/action_delete_response.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ..._models import BaseModel
+
+__all__ = ["ActionDeleteResponse"]
+
+
+class ActionDeleteResponse(BaseModel):
+ message: str
diff --git a/src/mobilerun_sdk/types/workflows/action_list_params.py b/src/mobilerun_sdk/types/workflows/action_list_params.py
new file mode 100644
index 0000000..9873843
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/action_list_params.py
@@ -0,0 +1,23 @@
+# 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__ = ["ActionListParams"]
+
+
+class ActionListParams(TypedDict, total=False):
+ order_by: Annotated[Literal["name", "createdAt", "updatedAt"], PropertyInfo(alias="orderBy")]
+
+ order_by_direction: Annotated[Literal["asc", "desc"], PropertyInfo(alias="orderByDirection")]
+
+ page: int
+
+ page_size: Annotated[int, PropertyInfo(alias="pageSize")]
+
+ search: str
+
+ service: Literal["tasks_api", "devices_api", "agents_api", "webhooks"]
diff --git a/src/mobilerun_sdk/types/workflows/action_list_response.py b/src/mobilerun_sdk/types/workflows/action_list_response.py
new file mode 100644
index 0000000..2d5e996
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/action_list_response.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from .action import Action
+from ..._models import BaseModel
+from ..shared.pagination import Pagination
+
+__all__ = ["ActionListResponse"]
+
+
+class ActionListResponse(BaseModel):
+ items: List[Action]
+
+ pagination: Pagination
diff --git a/src/mobilerun_sdk/types/workflows/action_retrieve_response.py b/src/mobilerun_sdk/types/workflows/action_retrieve_response.py
new file mode 100644
index 0000000..7dc33b0
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/action_retrieve_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .action import Action
+from ..._models import BaseModel
+
+__all__ = ["ActionRetrieveResponse"]
+
+
+class ActionRetrieveResponse(BaseModel):
+ data: Action
diff --git a/src/mobilerun_sdk/types/workflows/action_update_params.py b/src/mobilerun_sdk/types/workflows/action_update_params.py
new file mode 100644
index 0000000..4644bac
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/action_update_params.py
@@ -0,0 +1,16 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Optional
+from typing_extensions import TypedDict
+
+__all__ = ["ActionUpdateParams"]
+
+
+class ActionUpdateParams(TypedDict, total=False):
+ description: str
+
+ name: str
+
+ params: Dict[str, Optional[object]]
diff --git a/src/mobilerun_sdk/types/workflows/action_update_response.py b/src/mobilerun_sdk/types/workflows/action_update_response.py
new file mode 100644
index 0000000..4d6b872
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/action_update_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .action import Action
+from ..._models import BaseModel
+
+__all__ = ["ActionUpdateResponse"]
+
+
+class ActionUpdateResponse(BaseModel):
+ data: Action
diff --git a/src/mobilerun_sdk/types/workflows/actions/__init__.py b/src/mobilerun_sdk/types/workflows/actions/__init__.py
new file mode 100644
index 0000000..57284e5
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/actions/__init__.py
@@ -0,0 +1,6 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .service_list_response import ServiceListResponse as ServiceListResponse
+from .service_list_methods_response import ServiceListMethodsResponse as ServiceListMethodsResponse
diff --git a/src/mobilerun_sdk/types/workflows/actions/service_list_methods_response.py b/src/mobilerun_sdk/types/workflows/actions/service_list_methods_response.py
new file mode 100644
index 0000000..0ebef39
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/actions/service_list_methods_response.py
@@ -0,0 +1,38 @@
+# 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
+
+__all__ = ["ServiceListMethodsResponse", "Data", "DataParam"]
+
+
+class DataParam(BaseModel):
+ description: str
+
+ name: str
+
+ required: bool
+
+ type: Literal["string", "number", "boolean", "object", "array"]
+
+ default: Optional[object] = None
+
+ example: Optional[object] = None
+
+
+class Data(BaseModel):
+ is_async: bool = FieldInfo(alias="isAsync")
+
+ method: str
+
+ params: List[DataParam]
+
+ requires_target: bool = FieldInfo(alias="requiresTarget")
+
+
+class ServiceListMethodsResponse(BaseModel):
+ data: List[Data]
diff --git a/src/mobilerun_sdk/types/workflows/actions/service_list_response.py b/src/mobilerun_sdk/types/workflows/actions/service_list_response.py
new file mode 100644
index 0000000..e8e712c
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/actions/service_list_response.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ...._models import BaseModel
+
+__all__ = ["ServiceListResponse"]
+
+
+class ServiceListResponse(BaseModel):
+ data: List[str]
diff --git a/src/mobilerun_sdk/types/workflows/event_dry_run_params.py b/src/mobilerun_sdk/types/workflows/event_dry_run_params.py
new file mode 100644
index 0000000..c55498e
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/event_dry_run_params.py
@@ -0,0 +1,18 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Optional
+from typing_extensions import Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["EventDryRunParams"]
+
+
+class EventDryRunParams(TypedDict, total=False):
+ event_type: Required[Annotated[str, PropertyInfo(alias="eventType")]]
+
+ device_id: Annotated[str, PropertyInfo(alias="deviceId")]
+
+ payload: Dict[str, Optional[object]]
diff --git a/src/mobilerun_sdk/types/workflows/event_dry_run_response.py b/src/mobilerun_sdk/types/workflows/event_dry_run_response.py
new file mode 100644
index 0000000..13df857
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/event_dry_run_response.py
@@ -0,0 +1,105 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, List, Optional
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from ..flow import Flow
+from ..._models import BaseModel
+
+__all__ = [
+ "EventDryRunResponse",
+ "Data",
+ "DataMatchedFlow",
+ "DataMatchedFlowAction",
+ "DataMatchedFlowTrigger",
+ "DataMatchedFlowTriggerScheduleRule",
+ "DataValidation",
+ "DataValidationError",
+]
+
+
+class DataMatchedFlowAction(BaseModel):
+ continue_on_error: bool = FieldInfo(alias="continueOnError")
+
+ method: str
+
+ name: str
+
+ service: Literal["tasks_api", "devices_api", "agents_api", "webhooks"]
+
+ device_id: Optional[str] = FieldInfo(alias="deviceId", default=None)
+
+ params: Optional[Dict[str, Optional[object]]] = None
+
+
+class DataMatchedFlowTriggerScheduleRule(BaseModel):
+ type: Literal["once", "cron", "recurring"]
+
+ date_time: Optional[str] = FieldInfo(alias="dateTime", default=None)
+ """ISO 8601 datetime (for type=once)"""
+
+ expression: Optional[str] = None
+ """Cron expression (for type=cron)"""
+
+ rrule: Optional[str] = None
+ """RRULE string (for type=recurring)"""
+
+
+class DataMatchedFlowTrigger(BaseModel):
+ id: str
+
+ activation: Literal["event", "schedule", "custom"]
+
+ created_at: Optional[str] = FieldInfo(alias="createdAt", default=None)
+
+ custom_payload_schema: Optional[Dict[str, object]] = FieldInfo(alias="customPayloadSchema", default=None)
+
+ description: Optional[str] = None
+
+ event_type: Optional[str] = FieldInfo(alias="eventType", default=None)
+
+ name: str
+
+ schedule_rule: Optional[DataMatchedFlowTriggerScheduleRule] = FieldInfo(alias="scheduleRule", default=None)
+
+ timezone: Optional[str] = None
+
+ updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None)
+
+ user_id: str = FieldInfo(alias="userId")
+
+ conditions: Optional[object] = None
+
+ next_fire_time: Optional[str] = FieldInfo(alias="nextFireTime", default=None)
+
+
+class DataMatchedFlow(BaseModel):
+ actions: List[DataMatchedFlowAction]
+
+ flow: Flow
+
+ trigger: DataMatchedFlowTrigger
+
+
+class DataValidationError(BaseModel):
+ field: str
+
+ message: str
+
+
+class DataValidation(BaseModel):
+ valid: bool
+
+ errors: Optional[List[DataValidationError]] = None
+
+
+class Data(BaseModel):
+ matched_flows: List[DataMatchedFlow] = FieldInfo(alias="matchedFlows")
+
+ validation: DataValidation
+
+
+class EventDryRunResponse(BaseModel):
+ data: Data
diff --git a/src/mobilerun_sdk/types/workflows/event_ingest_params.py b/src/mobilerun_sdk/types/workflows/event_ingest_params.py
new file mode 100644
index 0000000..d8edf19
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/event_ingest_params.py
@@ -0,0 +1,18 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Optional
+from typing_extensions import Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["EventIngestParams"]
+
+
+class EventIngestParams(TypedDict, total=False):
+ event_type: Required[Annotated[str, PropertyInfo(alias="eventType")]]
+
+ device_id: Annotated[str, PropertyInfo(alias="deviceId")]
+
+ payload: Dict[str, Optional[object]]
diff --git a/src/mobilerun_sdk/types/workflows/event_ingest_response.py b/src/mobilerun_sdk/types/workflows/event_ingest_response.py
new file mode 100644
index 0000000..6136565
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/event_ingest_response.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["EventIngestResponse"]
+
+
+class EventIngestResponse(BaseModel):
+ event_id: str = FieldInfo(alias="eventId")
diff --git a/src/mobilerun_sdk/types/workflows/events/__init__.py b/src/mobilerun_sdk/types/workflows/events/__init__.py
new file mode 100644
index 0000000..32807f2
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/events/__init__.py
@@ -0,0 +1,8 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .catalog_list_params import CatalogListParams as CatalogListParams
+from .catalog_list_response import CatalogListResponse as CatalogListResponse
+from .catalog_register_params import CatalogRegisterParams as CatalogRegisterParams
+from .catalog_register_response import CatalogRegisterResponse as CatalogRegisterResponse
diff --git a/src/mobilerun_sdk/types/workflows/events/catalog_list_params.py b/src/mobilerun_sdk/types/workflows/events/catalog_list_params.py
new file mode 100644
index 0000000..ca0def1
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/events/catalog_list_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 Literal, Annotated, TypedDict
+
+from ...._utils import PropertyInfo
+
+__all__ = ["CatalogListParams"]
+
+
+class CatalogListParams(TypedDict, total=False):
+ page: int
+
+ page_size: Annotated[int, PropertyInfo(alias="pageSize")]
+
+ source: Literal["device", "system", "webhook"]
diff --git a/src/mobilerun_sdk/types/workflows/events/catalog_list_response.py b/src/mobilerun_sdk/types/workflows/events/catalog_list_response.py
new file mode 100644
index 0000000..86c96b2
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/events/catalog_list_response.py
@@ -0,0 +1,32 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from pydantic import Field as FieldInfo
+
+from ...._models import BaseModel
+from ...shared.pagination import Pagination
+
+__all__ = ["CatalogListResponse", "Item"]
+
+
+class Item(BaseModel):
+ created_at: Optional[str] = FieldInfo(alias="createdAt", default=None)
+
+ description: Optional[str] = None
+
+ event_type: str = FieldInfo(alias="eventType")
+
+ label: str
+
+ source: Optional[str] = None
+
+ updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None)
+
+ payload_schema: Optional[object] = FieldInfo(alias="payloadSchema", default=None)
+
+
+class CatalogListResponse(BaseModel):
+ items: List[Item]
+
+ pagination: Pagination
diff --git a/src/mobilerun_sdk/types/workflows/events/catalog_register_params.py b/src/mobilerun_sdk/types/workflows/events/catalog_register_params.py
new file mode 100644
index 0000000..da648c3
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/events/catalog_register_params.py
@@ -0,0 +1,26 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Iterable, Optional
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from ...._utils import PropertyInfo
+
+__all__ = ["CatalogRegisterParams", "Event"]
+
+
+class CatalogRegisterParams(TypedDict, total=False):
+ events: Required[Iterable[Event]]
+
+
+class Event(TypedDict, total=False):
+ event_type: Required[Annotated[str, PropertyInfo(alias="eventType")]]
+
+ label: Required[str]
+
+ description: str
+
+ payload_schema: Annotated[Dict[str, Optional[object]], PropertyInfo(alias="payloadSchema")]
+
+ source: Literal["device", "system", "webhook"]
diff --git a/src/mobilerun_sdk/types/workflows/events/catalog_register_response.py b/src/mobilerun_sdk/types/workflows/events/catalog_register_response.py
new file mode 100644
index 0000000..116b6cc
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/events/catalog_register_response.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ...._models import BaseModel
+
+__all__ = ["CatalogRegisterResponse"]
+
+
+class CatalogRegisterResponse(BaseModel):
+ message: str
diff --git a/src/mobilerun_sdk/types/workflows/execution_get_metrics_params.py b/src/mobilerun_sdk/types/workflows/execution_get_metrics_params.py
new file mode 100644
index 0000000..b5d8cda
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/execution_get_metrics_params.py
@@ -0,0 +1,20 @@
+# 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__ = ["ExecutionGetMetricsParams"]
+
+
+class ExecutionGetMetricsParams(TypedDict, total=False):
+ flow_id: Annotated[str, PropertyInfo(alias="flowId")]
+
+ from_: Annotated[Optional[str], PropertyInfo(alias="from")]
+
+ to: Optional[str]
+
+ trigger_id: Annotated[str, PropertyInfo(alias="triggerId")]
diff --git a/src/mobilerun_sdk/types/workflows/execution_get_metrics_response.py b/src/mobilerun_sdk/types/workflows/execution_get_metrics_response.py
new file mode 100644
index 0000000..774f398
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/execution_get_metrics_response.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["ExecutionGetMetricsResponse", "Data", "DataByStatus"]
+
+
+class DataByStatus(BaseModel):
+ failed: int
+
+ pending: int
+
+ running: int
+
+ success: int
+
+
+class Data(BaseModel):
+ avg_duration_ms: Optional[float] = FieldInfo(alias="avgDurationMs", default=None)
+
+ by_status: DataByStatus = FieldInfo(alias="byStatus")
+
+ last_execution_at: Optional[str] = FieldInfo(alias="lastExecutionAt", default=None)
+
+ total: int
+
+
+class ExecutionGetMetricsResponse(BaseModel):
+ data: Data
diff --git a/src/mobilerun_sdk/types/workflows/execution_list_params.py b/src/mobilerun_sdk/types/workflows/execution_list_params.py
new file mode 100644
index 0000000..2ffa5c9
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/execution_list_params.py
@@ -0,0 +1,32 @@
+# 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, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["ExecutionListParams"]
+
+
+class ExecutionListParams(TypedDict, total=False):
+ flow_id: Annotated[str, PropertyInfo(alias="flowId")]
+
+ from_: Annotated[Optional[str], PropertyInfo(alias="from")]
+
+ order_by: Annotated[Literal["startedAt", "finishedAt", "status"], PropertyInfo(alias="orderBy")]
+
+ order_by_direction: Annotated[Literal["asc", "desc"], PropertyInfo(alias="orderByDirection")]
+
+ page: int
+
+ page_size: Annotated[int, PropertyInfo(alias="pageSize")]
+
+ search: str
+
+ status: Literal["pending", "running", "success", "failed"]
+
+ to: Optional[str]
+
+ trigger_id: Annotated[str, PropertyInfo(alias="triggerId")]
diff --git a/src/mobilerun_sdk/types/workflows/execution_list_response.py b/src/mobilerun_sdk/types/workflows/execution_list_response.py
new file mode 100644
index 0000000..eddf7b3
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/execution_list_response.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ..._models import BaseModel
+from .flow_execution import FlowExecution
+from ..shared.pagination import Pagination
+
+__all__ = ["ExecutionListResponse"]
+
+
+class ExecutionListResponse(BaseModel):
+ items: List[FlowExecution]
+
+ pagination: Pagination
diff --git a/src/mobilerun_sdk/types/workflows/execution_retrieve_response.py b/src/mobilerun_sdk/types/workflows/execution_retrieve_response.py
new file mode 100644
index 0000000..6892a2e
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/execution_retrieve_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ..._models import BaseModel
+from .flow_execution import FlowExecution
+
+__all__ = ["ExecutionRetrieveResponse"]
+
+
+class ExecutionRetrieveResponse(BaseModel):
+ data: FlowExecution
diff --git a/src/mobilerun_sdk/types/workflows/flow_action_overrides_param.py b/src/mobilerun_sdk/types/workflows/flow_action_overrides_param.py
new file mode 100644
index 0000000..5f03d3a
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_action_overrides_param.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Optional
+from typing_extensions import TypedDict
+
+__all__ = ["FlowActionOverridesParam"]
+
+
+class FlowActionOverridesParam(TypedDict, total=False):
+ params: Dict[str, Optional[object]]
diff --git a/src/mobilerun_sdk/types/workflows/flow_child_action_input_param.py b/src/mobilerun_sdk/types/workflows/flow_child_action_input_param.py
new file mode 100644
index 0000000..9c883c4
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_child_action_input_param.py
@@ -0,0 +1,25 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+from .flow_action_overrides_param import FlowActionOverridesParam
+
+__all__ = ["FlowChildActionInputParam"]
+
+
+class FlowChildActionInputParam(TypedDict, total=False):
+ action_id: Required[Annotated[str, PropertyInfo(alias="actionId")]]
+
+ position: Required[int]
+
+ continue_on_error: Annotated[bool, PropertyInfo(alias="continueOnError")]
+
+ device_id: Annotated[str, PropertyInfo(alias="deviceId")]
+
+ name_override: Annotated[str, PropertyInfo(alias="nameOverride")]
+
+ overrides: Optional[FlowActionOverridesParam]
diff --git a/src/mobilerun_sdk/types/workflows/flow_clone_params.py b/src/mobilerun_sdk/types/workflows/flow_clone_params.py
new file mode 100644
index 0000000..e513de2
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_clone_params.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["FlowCloneParams"]
+
+
+class FlowCloneParams(TypedDict, total=False):
+ name: str
diff --git a/src/mobilerun_sdk/types/workflows/flow_clone_response.py b/src/mobilerun_sdk/types/workflows/flow_clone_response.py
new file mode 100644
index 0000000..57a8637
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_clone_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ..flow import Flow
+from ..._models import BaseModel
+
+__all__ = ["FlowCloneResponse"]
+
+
+class FlowCloneResponse(BaseModel):
+ data: Flow
diff --git a/src/mobilerun_sdk/types/workflows/flow_create_params.py b/src/mobilerun_sdk/types/workflows/flow_create_params.py
new file mode 100644
index 0000000..1dcdd12
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_create_params.py
@@ -0,0 +1,44 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable, Optional
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+from .flow_action_overrides_param import FlowActionOverridesParam
+from .flow_child_action_input_param import FlowChildActionInputParam
+
+__all__ = ["FlowCreateParams", "Action"]
+
+
+class FlowCreateParams(TypedDict, total=False):
+ actions: Required[Iterable[Action]]
+
+ name: Required[str]
+
+ trigger_id: Required[Annotated[str, PropertyInfo(alias="triggerId")]]
+
+ cooldown_scope: Annotated[Literal["flow", "device"], PropertyInfo(alias="cooldownScope")]
+
+ cooldown_seconds: Annotated[Optional[int], PropertyInfo(alias="cooldownSeconds")]
+
+ description: str
+
+ enabled: bool
+
+
+class Action(TypedDict, total=False):
+ action_id: Required[Annotated[str, PropertyInfo(alias="actionId")]]
+
+ position: Required[int]
+
+ children: Iterable[FlowChildActionInputParam]
+
+ continue_on_error: Annotated[bool, PropertyInfo(alias="continueOnError")]
+
+ device_id: Annotated[str, PropertyInfo(alias="deviceId")]
+
+ name_override: Annotated[str, PropertyInfo(alias="nameOverride")]
+
+ overrides: Optional[FlowActionOverridesParam]
diff --git a/src/mobilerun_sdk/types/workflows/flow_create_response.py b/src/mobilerun_sdk/types/workflows/flow_create_response.py
new file mode 100644
index 0000000..f9c5fea
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_create_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ..flow import Flow
+from ..._models import BaseModel
+
+__all__ = ["FlowCreateResponse"]
+
+
+class FlowCreateResponse(BaseModel):
+ data: Flow
diff --git a/src/mobilerun_sdk/types/workflows/flow_delete_response.py b/src/mobilerun_sdk/types/workflows/flow_delete_response.py
new file mode 100644
index 0000000..a6243e6
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_delete_response.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ..._models import BaseModel
+
+__all__ = ["FlowDeleteResponse"]
+
+
+class FlowDeleteResponse(BaseModel):
+ message: str
diff --git a/src/mobilerun_sdk/types/workflows/flow_execution.py b/src/mobilerun_sdk/types/workflows/flow_execution.py
new file mode 100644
index 0000000..ba28012
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_execution.py
@@ -0,0 +1,34 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["FlowExecution"]
+
+
+class FlowExecution(BaseModel):
+ id: str
+
+ error: Optional[str] = None
+
+ event_id: Optional[str] = FieldInfo(alias="eventId", default=None)
+
+ finished_at: Optional[str] = FieldInfo(alias="finishedAt", default=None)
+
+ flow_id: str = FieldInfo(alias="flowId")
+
+ flow_name: Optional[str] = FieldInfo(alias="flowName", default=None)
+
+ started_at: Optional[str] = FieldInfo(alias="startedAt", default=None)
+
+ status: Optional[Literal["pending", "running", "success", "failed"]] = None
+
+ trigger_id: str = FieldInfo(alias="triggerId")
+
+ trigger_name: Optional[str] = FieldInfo(alias="triggerName", default=None)
+
+ result: Optional[object] = None
diff --git a/src/mobilerun_sdk/types/workflows/flow_list_params.py b/src/mobilerun_sdk/types/workflows/flow_list_params.py
new file mode 100644
index 0000000..8f00af0
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_list_params.py
@@ -0,0 +1,28 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import List, Optional
+from typing_extensions import Literal, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["FlowListParams"]
+
+
+class FlowListParams(TypedDict, total=False):
+ enabled: Optional[bool]
+
+ order_by: Annotated[Literal["name", "createdAt", "updatedAt"], PropertyInfo(alias="orderBy")]
+
+ order_by_direction: Annotated[Literal["asc", "desc"], PropertyInfo(alias="orderByDirection")]
+
+ page: int
+
+ page_size: Annotated[int, PropertyInfo(alias="pageSize")]
+
+ search: str
+
+ status: List[Literal["healthy", "failing", "blocked"]]
+
+ trigger_id: Annotated[str, PropertyInfo(alias="triggerId")]
diff --git a/src/mobilerun_sdk/types/workflows/flow_list_response.py b/src/mobilerun_sdk/types/workflows/flow_list_response.py
new file mode 100644
index 0000000..ff0feb8
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_list_response.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ..flow import Flow
+from ..._models import BaseModel
+from ..shared.pagination import Pagination
+
+__all__ = ["FlowListResponse"]
+
+
+class FlowListResponse(BaseModel):
+ items: List[Flow]
+
+ pagination: Pagination
diff --git a/src/mobilerun_sdk/types/workflows/flow_retrieve_response.py b/src/mobilerun_sdk/types/workflows/flow_retrieve_response.py
new file mode 100644
index 0000000..0a002a6
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_retrieve_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ..flow import Flow
+from ..._models import BaseModel
+
+__all__ = ["FlowRetrieveResponse"]
+
+
+class FlowRetrieveResponse(BaseModel):
+ data: Flow
diff --git a/src/mobilerun_sdk/types/workflows/flow_unblock_response.py b/src/mobilerun_sdk/types/workflows/flow_unblock_response.py
new file mode 100644
index 0000000..3771e29
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_unblock_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ..flow import Flow
+from ..._models import BaseModel
+
+__all__ = ["FlowUnblockResponse"]
+
+
+class FlowUnblockResponse(BaseModel):
+ data: Flow
diff --git a/src/mobilerun_sdk/types/workflows/flow_update_params.py b/src/mobilerun_sdk/types/workflows/flow_update_params.py
new file mode 100644
index 0000000..8b29afd
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_update_params.py
@@ -0,0 +1,24 @@
+# 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, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["FlowUpdateParams"]
+
+
+class FlowUpdateParams(TypedDict, total=False):
+ cooldown_scope: Annotated[Literal["flow", "device"], PropertyInfo(alias="cooldownScope")]
+
+ cooldown_seconds: Annotated[Optional[int], PropertyInfo(alias="cooldownSeconds")]
+
+ description: str
+
+ enabled: bool
+
+ name: str
+
+ trigger_id: Annotated[str, PropertyInfo(alias="triggerId")]
diff --git a/src/mobilerun_sdk/types/workflows/flow_update_response.py b/src/mobilerun_sdk/types/workflows/flow_update_response.py
new file mode 100644
index 0000000..8725080
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flow_update_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ..flow import Flow
+from ..._models import BaseModel
+
+__all__ = ["FlowUpdateResponse"]
+
+
+class FlowUpdateResponse(BaseModel):
+ data: Flow
diff --git a/src/mobilerun_sdk/types/workflows/flows/__init__.py b/src/mobilerun_sdk/types/workflows/flows/__init__.py
new file mode 100644
index 0000000..fa77a33
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flows/__init__.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .flow_action import FlowAction as FlowAction
+from .action_add_params import ActionAddParams as ActionAddParams
+from .action_add_response import ActionAddResponse as ActionAddResponse
+from .action_list_response import ActionListResponse as ActionListResponse
+from .action_replace_params import ActionReplaceParams as ActionReplaceParams
+from .action_remove_response import ActionRemoveResponse as ActionRemoveResponse
+from .action_replace_response import ActionReplaceResponse as ActionReplaceResponse
diff --git a/src/mobilerun_sdk/types/workflows/flows/action_add_params.py b/src/mobilerun_sdk/types/workflows/flows/action_add_params.py
new file mode 100644
index 0000000..7d71e72
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flows/action_add_params.py
@@ -0,0 +1,30 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable, Optional
+from typing_extensions import Required, Annotated, TypedDict
+
+from ...._utils import PropertyInfo
+from ..flow_action_overrides_param import FlowActionOverridesParam
+from ..flow_child_action_input_param import FlowChildActionInputParam
+
+__all__ = ["ActionAddParams"]
+
+
+class ActionAddParams(TypedDict, total=False):
+ action_id: Required[Annotated[str, PropertyInfo(alias="actionId")]]
+
+ position: Required[int]
+
+ children: Iterable[FlowChildActionInputParam]
+
+ continue_on_error: Annotated[bool, PropertyInfo(alias="continueOnError")]
+
+ device_id: Annotated[str, PropertyInfo(alias="deviceId")]
+
+ name_override: Annotated[str, PropertyInfo(alias="nameOverride")]
+
+ overrides: Optional[FlowActionOverridesParam]
+
+ parent_flow_action_id: Annotated[Optional[str], PropertyInfo(alias="parentFlowActionId")]
diff --git a/src/mobilerun_sdk/types/workflows/flows/action_add_response.py b/src/mobilerun_sdk/types/workflows/flows/action_add_response.py
new file mode 100644
index 0000000..03d4e31
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flows/action_add_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ...._models import BaseModel
+from .flow_action import FlowAction
+
+__all__ = ["ActionAddResponse"]
+
+
+class ActionAddResponse(BaseModel):
+ data: FlowAction
diff --git a/src/mobilerun_sdk/types/workflows/flows/action_list_response.py b/src/mobilerun_sdk/types/workflows/flows/action_list_response.py
new file mode 100644
index 0000000..7f6bd53
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flows/action_list_response.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ...._models import BaseModel
+from .flow_action import FlowAction
+
+__all__ = ["ActionListResponse"]
+
+
+class ActionListResponse(BaseModel):
+ data: List[FlowAction]
diff --git a/src/mobilerun_sdk/types/workflows/flows/action_remove_response.py b/src/mobilerun_sdk/types/workflows/flows/action_remove_response.py
new file mode 100644
index 0000000..a200db1
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flows/action_remove_response.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ...._models import BaseModel
+
+__all__ = ["ActionRemoveResponse"]
+
+
+class ActionRemoveResponse(BaseModel):
+ message: str
diff --git a/src/mobilerun_sdk/types/workflows/flows/action_replace_params.py b/src/mobilerun_sdk/types/workflows/flows/action_replace_params.py
new file mode 100644
index 0000000..2ae1e95
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flows/action_replace_params.py
@@ -0,0 +1,32 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable, Optional
+from typing_extensions import Required, Annotated, TypedDict
+
+from ...._utils import PropertyInfo
+from ..flow_action_overrides_param import FlowActionOverridesParam
+from ..flow_child_action_input_param import FlowChildActionInputParam
+
+__all__ = ["ActionReplaceParams", "Action"]
+
+
+class ActionReplaceParams(TypedDict, total=False):
+ actions: Required[Iterable[Action]]
+
+
+class Action(TypedDict, total=False):
+ action_id: Required[Annotated[str, PropertyInfo(alias="actionId")]]
+
+ position: Required[int]
+
+ children: Iterable[FlowChildActionInputParam]
+
+ continue_on_error: Annotated[bool, PropertyInfo(alias="continueOnError")]
+
+ device_id: Annotated[str, PropertyInfo(alias="deviceId")]
+
+ name_override: Annotated[str, PropertyInfo(alias="nameOverride")]
+
+ overrides: Optional[FlowActionOverridesParam]
diff --git a/src/mobilerun_sdk/types/workflows/flows/action_replace_response.py b/src/mobilerun_sdk/types/workflows/flows/action_replace_response.py
new file mode 100644
index 0000000..2914bfa
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flows/action_replace_response.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ...._models import BaseModel
+from .flow_action import FlowAction
+
+__all__ = ["ActionReplaceResponse"]
+
+
+class ActionReplaceResponse(BaseModel):
+ data: List[FlowAction]
diff --git a/src/mobilerun_sdk/types/workflows/flows/flow_action.py b/src/mobilerun_sdk/types/workflows/flows/flow_action.py
new file mode 100644
index 0000000..cf83cb4
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/flows/flow_action.py
@@ -0,0 +1,35 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+
+from pydantic import Field as FieldInfo
+
+from ...._models import BaseModel
+
+__all__ = ["FlowAction", "Overrides"]
+
+
+class Overrides(BaseModel):
+ params: Optional[Dict[str, Optional[object]]] = None
+
+
+class FlowAction(BaseModel):
+ id: str
+
+ action_id: str = FieldInfo(alias="actionId")
+
+ continue_on_error: bool = FieldInfo(alias="continueOnError")
+
+ created_at: Optional[str] = FieldInfo(alias="createdAt", default=None)
+
+ device_id: Optional[str] = FieldInfo(alias="deviceId", default=None)
+
+ flow_id: str = FieldInfo(alias="flowId")
+
+ name_override: Optional[str] = FieldInfo(alias="nameOverride", default=None)
+
+ overrides: Optional[Overrides] = None
+
+ parent_flow_action_id: Optional[str] = FieldInfo(alias="parentFlowActionId", default=None)
+
+ position: int
diff --git a/src/mobilerun_sdk/types/workflows/secret_create_params.py b/src/mobilerun_sdk/types/workflows/secret_create_params.py
new file mode 100644
index 0000000..88e54de
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/secret_create_params.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["SecretCreateParams"]
+
+
+class SecretCreateParams(TypedDict, total=False):
+ name: Required[str]
+
+ value: Required[str]
+
+ description: str
diff --git a/src/mobilerun_sdk/types/workflows/secret_create_response.py b/src/mobilerun_sdk/types/workflows/secret_create_response.py
new file mode 100644
index 0000000..a05805f
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/secret_create_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ..._models import BaseModel
+from .user_secret import UserSecret
+
+__all__ = ["SecretCreateResponse"]
+
+
+class SecretCreateResponse(BaseModel):
+ data: UserSecret
diff --git a/src/mobilerun_sdk/types/workflows/secret_delete_response.py b/src/mobilerun_sdk/types/workflows/secret_delete_response.py
new file mode 100644
index 0000000..16ec787
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/secret_delete_response.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ..._models import BaseModel
+
+__all__ = ["SecretDeleteResponse"]
+
+
+class SecretDeleteResponse(BaseModel):
+ message: str
diff --git a/src/mobilerun_sdk/types/workflows/secret_list_response.py b/src/mobilerun_sdk/types/workflows/secret_list_response.py
new file mode 100644
index 0000000..5e661ee
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/secret_list_response.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ..._models import BaseModel
+from .user_secret import UserSecret
+
+__all__ = ["SecretListResponse"]
+
+
+class SecretListResponse(BaseModel):
+ data: List[UserSecret]
diff --git a/src/mobilerun_sdk/types/workflows/timezone_list_response.py b/src/mobilerun_sdk/types/workflows/timezone_list_response.py
new file mode 100644
index 0000000..6e49c63
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/timezone_list_response.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ..._models import BaseModel
+
+__all__ = ["TimezoneListResponse"]
+
+
+class TimezoneListResponse(BaseModel):
+ data: List[str]
diff --git a/src/mobilerun_sdk/types/workflows/trigger_create_params.py b/src/mobilerun_sdk/types/workflows/trigger_create_params.py
new file mode 100644
index 0000000..7d8c4b8
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/trigger_create_params.py
@@ -0,0 +1,48 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Iterable
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["TriggerCreateParams", "Conditions", "ScheduleRule"]
+
+
+class TriggerCreateParams(TypedDict, total=False):
+ activation: Required[Literal["event", "schedule", "custom"]]
+
+ name: Required[str]
+
+ conditions: Conditions
+
+ custom_payload_schema: Annotated[Dict[str, object], PropertyInfo(alias="customPayloadSchema")]
+ """Optional JSON Schema for validating payloads sent to this custom trigger"""
+
+ description: str
+
+ event_type: Annotated[str, PropertyInfo(alias="eventType")]
+
+ schedule_rule: Annotated[ScheduleRule, PropertyInfo(alias="scheduleRule")]
+
+ timezone: str
+
+
+class Conditions(TypedDict, total=False):
+ all: Iterable[object]
+
+ any: Iterable[object]
+
+
+class ScheduleRule(TypedDict, total=False):
+ type: Required[Literal["once", "cron", "recurring"]]
+
+ date_time: Annotated[str, PropertyInfo(alias="dateTime")]
+ """ISO 8601 datetime (for type=once)"""
+
+ expression: str
+ """Cron expression (for type=cron)"""
+
+ rrule: str
+ """RRULE string (for type=recurring)"""
diff --git a/src/mobilerun_sdk/types/workflows/trigger_create_response.py b/src/mobilerun_sdk/types/workflows/trigger_create_response.py
new file mode 100644
index 0000000..b2073b1
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/trigger_create_response.py
@@ -0,0 +1,55 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["TriggerCreateResponse", "Data", "DataScheduleRule"]
+
+
+class DataScheduleRule(BaseModel):
+ type: Literal["once", "cron", "recurring"]
+
+ date_time: Optional[str] = FieldInfo(alias="dateTime", default=None)
+ """ISO 8601 datetime (for type=once)"""
+
+ expression: Optional[str] = None
+ """Cron expression (for type=cron)"""
+
+ rrule: Optional[str] = None
+ """RRULE string (for type=recurring)"""
+
+
+class Data(BaseModel):
+ id: str
+
+ activation: Literal["event", "schedule", "custom"]
+
+ created_at: Optional[str] = FieldInfo(alias="createdAt", default=None)
+
+ custom_payload_schema: Optional[Dict[str, Optional[object]]] = FieldInfo(alias="customPayloadSchema", default=None)
+
+ description: Optional[str] = None
+
+ event_type: Optional[str] = FieldInfo(alias="eventType", default=None)
+
+ name: str
+
+ schedule_rule: DataScheduleRule = FieldInfo(alias="scheduleRule")
+
+ timezone: Optional[str] = None
+
+ updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None)
+
+ user_id: str = FieldInfo(alias="userId")
+
+ conditions: Optional[object] = None
+
+ next_fire_time: Optional[str] = FieldInfo(alias="nextFireTime", default=None)
+
+
+class TriggerCreateResponse(BaseModel):
+ data: Data
diff --git a/src/mobilerun_sdk/types/workflows/trigger_delete_response.py b/src/mobilerun_sdk/types/workflows/trigger_delete_response.py
new file mode 100644
index 0000000..5a4cf92
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/trigger_delete_response.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ..._models import BaseModel
+
+__all__ = ["TriggerDeleteResponse"]
+
+
+class TriggerDeleteResponse(BaseModel):
+ message: str
diff --git a/src/mobilerun_sdk/types/workflows/trigger_fire_params.py b/src/mobilerun_sdk/types/workflows/trigger_fire_params.py
new file mode 100644
index 0000000..756af49
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/trigger_fire_params.py
@@ -0,0 +1,26 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict
+from typing_extensions import Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["TriggerFireParams"]
+
+
+class TriggerFireParams(TypedDict, total=False):
+ payload: Required[Dict[str, object]]
+ """Arbitrary JSON object forwarded to every flow attached to this trigger.
+
+ Validated against the trigger's customPayloadSchema when one is configured;
+ otherwise only "must be a JSON object" is enforced.
+ """
+
+ device_id: Annotated[str, PropertyInfo(alias="deviceId")]
+ """Optional device scope.
+
+ When supplied, ownership is verified for the calling user and the value is
+ passed through to each enqueued execution as the default device context.
+ """
diff --git a/src/mobilerun_sdk/types/workflows/trigger_fire_response.py b/src/mobilerun_sdk/types/workflows/trigger_fire_response.py
new file mode 100644
index 0000000..b0b4951
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/trigger_fire_response.py
@@ -0,0 +1,22 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["TriggerFireResponse"]
+
+
+class TriggerFireResponse(BaseModel):
+ enqueued_count: int = FieldInfo(alias="enqueuedCount")
+ """Number of flow executions enqueued.
+
+ May be 0 if no flows are attached to this trigger, or if all attached flows are
+ currently in cooldown.
+ """
+
+ invocation_id: str = FieldInfo(alias="invocationId")
+ """Unique ID for this fire invocation.
+
+ Job IDs in the execution queue are derived from it (one per enqueued flow).
+ """
diff --git a/src/mobilerun_sdk/types/workflows/trigger_list_params.py b/src/mobilerun_sdk/types/workflows/trigger_list_params.py
new file mode 100644
index 0000000..dad1a5f
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/trigger_list_params.py
@@ -0,0 +1,25 @@
+# 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__ = ["TriggerListParams"]
+
+
+class TriggerListParams(TypedDict, total=False):
+ activation: Literal["event", "schedule", "custom"]
+
+ event_type: Annotated[str, PropertyInfo(alias="eventType")]
+
+ order_by: Annotated[Literal["name", "createdAt", "updatedAt"], PropertyInfo(alias="orderBy")]
+
+ order_by_direction: Annotated[Literal["asc", "desc"], PropertyInfo(alias="orderByDirection")]
+
+ page: int
+
+ page_size: Annotated[int, PropertyInfo(alias="pageSize")]
+
+ search: str
diff --git a/src/mobilerun_sdk/types/workflows/trigger_list_response.py b/src/mobilerun_sdk/types/workflows/trigger_list_response.py
new file mode 100644
index 0000000..703fd4c
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/trigger_list_response.py
@@ -0,0 +1,58 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, List, Optional
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+from ..shared.pagination import Pagination
+
+__all__ = ["TriggerListResponse", "Item", "ItemScheduleRule"]
+
+
+class ItemScheduleRule(BaseModel):
+ type: Literal["once", "cron", "recurring"]
+
+ date_time: Optional[str] = FieldInfo(alias="dateTime", default=None)
+ """ISO 8601 datetime (for type=once)"""
+
+ expression: Optional[str] = None
+ """Cron expression (for type=cron)"""
+
+ rrule: Optional[str] = None
+ """RRULE string (for type=recurring)"""
+
+
+class Item(BaseModel):
+ id: str
+
+ activation: Literal["event", "schedule", "custom"]
+
+ created_at: Optional[str] = FieldInfo(alias="createdAt", default=None)
+
+ custom_payload_schema: Optional[Dict[str, object]] = FieldInfo(alias="customPayloadSchema", default=None)
+
+ description: Optional[str] = None
+
+ event_type: Optional[str] = FieldInfo(alias="eventType", default=None)
+
+ name: str
+
+ schedule_rule: Optional[ItemScheduleRule] = FieldInfo(alias="scheduleRule", default=None)
+
+ timezone: Optional[str] = None
+
+ updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None)
+
+ user_id: str = FieldInfo(alias="userId")
+
+ conditions: Optional[object] = None
+
+ next_fire_time: Optional[str] = FieldInfo(alias="nextFireTime", default=None)
+
+
+class TriggerListResponse(BaseModel):
+ items: List[Item]
+
+ pagination: Pagination
diff --git a/src/mobilerun_sdk/types/workflows/trigger_retrieve_response.py b/src/mobilerun_sdk/types/workflows/trigger_retrieve_response.py
new file mode 100644
index 0000000..fc48aa4
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/trigger_retrieve_response.py
@@ -0,0 +1,55 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["TriggerRetrieveResponse", "Data", "DataScheduleRule"]
+
+
+class DataScheduleRule(BaseModel):
+ type: Literal["once", "cron", "recurring"]
+
+ date_time: Optional[str] = FieldInfo(alias="dateTime", default=None)
+ """ISO 8601 datetime (for type=once)"""
+
+ expression: Optional[str] = None
+ """Cron expression (for type=cron)"""
+
+ rrule: Optional[str] = None
+ """RRULE string (for type=recurring)"""
+
+
+class Data(BaseModel):
+ id: str
+
+ activation: Literal["event", "schedule", "custom"]
+
+ created_at: Optional[str] = FieldInfo(alias="createdAt", default=None)
+
+ custom_payload_schema: Optional[Dict[str, object]] = FieldInfo(alias="customPayloadSchema", default=None)
+
+ description: Optional[str] = None
+
+ event_type: Optional[str] = FieldInfo(alias="eventType", default=None)
+
+ name: str
+
+ schedule_rule: Optional[DataScheduleRule] = FieldInfo(alias="scheduleRule", default=None)
+
+ timezone: Optional[str] = None
+
+ updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None)
+
+ user_id: str = FieldInfo(alias="userId")
+
+ conditions: Optional[object] = None
+
+ next_fire_time: Optional[str] = FieldInfo(alias="nextFireTime", default=None)
+
+
+class TriggerRetrieveResponse(BaseModel):
+ data: Data
diff --git a/src/mobilerun_sdk/types/workflows/trigger_update_params.py b/src/mobilerun_sdk/types/workflows/trigger_update_params.py
new file mode 100644
index 0000000..ecf86b7
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/trigger_update_params.py
@@ -0,0 +1,48 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Iterable, Optional
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["TriggerUpdateParams", "Conditions", "ScheduleRule"]
+
+
+class TriggerUpdateParams(TypedDict, total=False):
+ activation: Literal["event", "schedule", "custom"]
+
+ conditions: Conditions
+
+ custom_payload_schema: Annotated[Optional[Dict[str, object]], PropertyInfo(alias="customPayloadSchema")]
+ """Optional JSON Schema for validating payloads sent to this custom trigger"""
+
+ description: str
+
+ event_type: Annotated[str, PropertyInfo(alias="eventType")]
+
+ name: str
+
+ schedule_rule: Annotated[ScheduleRule, PropertyInfo(alias="scheduleRule")]
+
+ timezone: Optional[str]
+
+
+class Conditions(TypedDict, total=False):
+ all: Iterable[object]
+
+ any: Iterable[object]
+
+
+class ScheduleRule(TypedDict, total=False):
+ type: Required[Literal["once", "cron", "recurring"]]
+
+ date_time: Annotated[str, PropertyInfo(alias="dateTime")]
+ """ISO 8601 datetime (for type=once)"""
+
+ expression: str
+ """Cron expression (for type=cron)"""
+
+ rrule: str
+ """RRULE string (for type=recurring)"""
diff --git a/src/mobilerun_sdk/types/workflows/trigger_update_response.py b/src/mobilerun_sdk/types/workflows/trigger_update_response.py
new file mode 100644
index 0000000..a5a9418
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/trigger_update_response.py
@@ -0,0 +1,55 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+from typing_extensions import Literal
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["TriggerUpdateResponse", "Data", "DataScheduleRule"]
+
+
+class DataScheduleRule(BaseModel):
+ type: Literal["once", "cron", "recurring"]
+
+ date_time: Optional[str] = FieldInfo(alias="dateTime", default=None)
+ """ISO 8601 datetime (for type=once)"""
+
+ expression: Optional[str] = None
+ """Cron expression (for type=cron)"""
+
+ rrule: Optional[str] = None
+ """RRULE string (for type=recurring)"""
+
+
+class Data(BaseModel):
+ id: str
+
+ activation: Literal["event", "schedule", "custom"]
+
+ created_at: Optional[str] = FieldInfo(alias="createdAt", default=None)
+
+ custom_payload_schema: Optional[Dict[str, object]] = FieldInfo(alias="customPayloadSchema", default=None)
+
+ description: Optional[str] = None
+
+ event_type: Optional[str] = FieldInfo(alias="eventType", default=None)
+
+ name: str
+
+ schedule_rule: Optional[DataScheduleRule] = FieldInfo(alias="scheduleRule", default=None)
+
+ timezone: Optional[str] = None
+
+ updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None)
+
+ user_id: str = FieldInfo(alias="userId")
+
+ conditions: Optional[object] = None
+
+ next_fire_time: Optional[str] = FieldInfo(alias="nextFireTime", default=None)
+
+
+class TriggerUpdateResponse(BaseModel):
+ data: Data
diff --git a/src/mobilerun_sdk/types/workflows/user_secret.py b/src/mobilerun_sdk/types/workflows/user_secret.py
new file mode 100644
index 0000000..a33cade
--- /dev/null
+++ b/src/mobilerun_sdk/types/workflows/user_secret.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["UserSecret"]
+
+
+class UserSecret(BaseModel):
+ id: str
+
+ created_at: Optional[str] = FieldInfo(alias="createdAt", default=None)
+
+ description: Optional[str] = None
+
+ name: str
+
+ updated_at: Optional[str] = FieldInfo(alias="updatedAt", default=None)
diff --git a/tests/api_resources/devices/esim/__init__.py b/tests/api_resources/agents/__init__.py
similarity index 100%
rename from tests/api_resources/devices/esim/__init__.py
rename to tests/api_resources/agents/__init__.py
diff --git a/tests/api_resources/agents/chat/__init__.py b/tests/api_resources/agents/chat/__init__.py
new file mode 100644
index 0000000..fd8019a
--- /dev/null
+++ b/tests/api_resources/agents/chat/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/agents/chat/test_abort.py b/tests/api_resources/agents/chat/test_abort.py
new file mode 100644
index 0000000..59426a3
--- /dev/null
+++ b/tests/api_resources/agents/chat/test_abort.py
@@ -0,0 +1,136 @@
+# 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.agents.chat import AbortPerformResponse, AbortForceClearResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestAbort:
+ 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_force_clear(self, client: Mobilerun) -> None:
+ abort = client.agents.chat.abort.force_clear()
+ assert_matches_type(AbortForceClearResponse, abort, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_force_clear(self, client: Mobilerun) -> None:
+ response = client.agents.chat.abort.with_raw_response.force_clear()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ abort = response.parse()
+ assert_matches_type(AbortForceClearResponse, abort, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_force_clear(self, client: Mobilerun) -> None:
+ with client.agents.chat.abort.with_streaming_response.force_clear() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ abort = response.parse()
+ assert_matches_type(AbortForceClearResponse, abort, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_perform(self, client: Mobilerun) -> None:
+ abort = client.agents.chat.abort.perform()
+ assert_matches_type(AbortPerformResponse, abort, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_perform(self, client: Mobilerun) -> None:
+ response = client.agents.chat.abort.with_raw_response.perform()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ abort = response.parse()
+ assert_matches_type(AbortPerformResponse, abort, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_perform(self, client: Mobilerun) -> None:
+ with client.agents.chat.abort.with_streaming_response.perform() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ abort = response.parse()
+ assert_matches_type(AbortPerformResponse, abort, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncAbort:
+ 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_force_clear(self, async_client: AsyncMobilerun) -> None:
+ abort = await async_client.agents.chat.abort.force_clear()
+ assert_matches_type(AbortForceClearResponse, abort, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_force_clear(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.chat.abort.with_raw_response.force_clear()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ abort = await response.parse()
+ assert_matches_type(AbortForceClearResponse, abort, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_force_clear(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.chat.abort.with_streaming_response.force_clear() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ abort = await response.parse()
+ assert_matches_type(AbortForceClearResponse, abort, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_perform(self, async_client: AsyncMobilerun) -> None:
+ abort = await async_client.agents.chat.abort.perform()
+ assert_matches_type(AbortPerformResponse, abort, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_perform(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.chat.abort.with_raw_response.perform()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ abort = await response.parse()
+ assert_matches_type(AbortPerformResponse, abort, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_perform(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.chat.abort.with_streaming_response.perform() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ abort = await response.parse()
+ assert_matches_type(AbortPerformResponse, abort, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/agents/chat/test_question.py b/tests/api_resources/agents/chat/test_question.py
new file mode 100644
index 0000000..e200ee4
--- /dev/null
+++ b/tests/api_resources/agents/chat/test_question.py
@@ -0,0 +1,169 @@
+# 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.agents.chat import (
+ QuestionDismissResponse,
+ QuestionDeliverAnswerResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestQuestion:
+ 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_deliver_answer(self, client: Mobilerun) -> None:
+ question = client.agents.chat.question.deliver_answer(
+ answers=[[{"label": "x"}]],
+ question_id="x",
+ )
+ assert_matches_type(QuestionDeliverAnswerResponse, question, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_deliver_answer(self, client: Mobilerun) -> None:
+ response = client.agents.chat.question.with_raw_response.deliver_answer(
+ answers=[[{"label": "x"}]],
+ question_id="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ question = response.parse()
+ assert_matches_type(QuestionDeliverAnswerResponse, question, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_deliver_answer(self, client: Mobilerun) -> None:
+ with client.agents.chat.question.with_streaming_response.deliver_answer(
+ answers=[[{"label": "x"}]],
+ question_id="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ question = response.parse()
+ assert_matches_type(QuestionDeliverAnswerResponse, question, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_dismiss(self, client: Mobilerun) -> None:
+ question = client.agents.chat.question.dismiss(
+ question_id="x",
+ )
+ assert_matches_type(QuestionDismissResponse, question, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_dismiss(self, client: Mobilerun) -> None:
+ response = client.agents.chat.question.with_raw_response.dismiss(
+ question_id="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ question = response.parse()
+ assert_matches_type(QuestionDismissResponse, question, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_dismiss(self, client: Mobilerun) -> None:
+ with client.agents.chat.question.with_streaming_response.dismiss(
+ question_id="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ question = response.parse()
+ assert_matches_type(QuestionDismissResponse, question, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncQuestion:
+ 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_deliver_answer(self, async_client: AsyncMobilerun) -> None:
+ question = await async_client.agents.chat.question.deliver_answer(
+ answers=[[{"label": "x"}]],
+ question_id="x",
+ )
+ assert_matches_type(QuestionDeliverAnswerResponse, question, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_deliver_answer(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.chat.question.with_raw_response.deliver_answer(
+ answers=[[{"label": "x"}]],
+ question_id="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ question = await response.parse()
+ assert_matches_type(QuestionDeliverAnswerResponse, question, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_deliver_answer(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.chat.question.with_streaming_response.deliver_answer(
+ answers=[[{"label": "x"}]],
+ question_id="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ question = await response.parse()
+ assert_matches_type(QuestionDeliverAnswerResponse, question, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_dismiss(self, async_client: AsyncMobilerun) -> None:
+ question = await async_client.agents.chat.question.dismiss(
+ question_id="x",
+ )
+ assert_matches_type(QuestionDismissResponse, question, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_dismiss(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.chat.question.with_raw_response.dismiss(
+ question_id="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ question = await response.parse()
+ assert_matches_type(QuestionDismissResponse, question, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_dismiss(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.chat.question.with_streaming_response.dismiss(
+ question_id="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ question = await response.parse()
+ assert_matches_type(QuestionDismissResponse, question, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/agents/files/__init__.py b/tests/api_resources/agents/files/__init__.py
new file mode 100644
index 0000000..fd8019a
--- /dev/null
+++ b/tests/api_resources/agents/files/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/agents/files/test_file_id.py b/tests/api_resources/agents/files/test_file_id.py
new file mode 100644
index 0000000..372cc6c
--- /dev/null
+++ b/tests/api_resources/agents/files/test_file_id.py
@@ -0,0 +1,327 @@
+# 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.agents.files import (
+ FileIDDeleteFileResponse,
+ FileIDConfirmUploadResponse,
+ FileIDUpdateMetadataResponse,
+ FileIDCancelPendingUploadResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestFileID:
+ 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_cancel_pending_upload(self, client: Mobilerun) -> None:
+ file_id = client.agents.files.file_id.cancel_pending_upload()
+ assert_matches_type(FileIDCancelPendingUploadResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_cancel_pending_upload(self, client: Mobilerun) -> None:
+ response = client.agents.files.file_id.with_raw_response.cancel_pending_upload()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file_id = response.parse()
+ assert_matches_type(FileIDCancelPendingUploadResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_cancel_pending_upload(self, client: Mobilerun) -> None:
+ with client.agents.files.file_id.with_streaming_response.cancel_pending_upload() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file_id = response.parse()
+ assert_matches_type(FileIDCancelPendingUploadResponse, file_id, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_confirm_upload(self, client: Mobilerun) -> None:
+ file_id = client.agents.files.file_id.confirm_upload()
+ assert_matches_type(FileIDConfirmUploadResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_confirm_upload(self, client: Mobilerun) -> None:
+ response = client.agents.files.file_id.with_raw_response.confirm_upload()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file_id = response.parse()
+ assert_matches_type(FileIDConfirmUploadResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_confirm_upload(self, client: Mobilerun) -> None:
+ with client.agents.files.file_id.with_streaming_response.confirm_upload() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file_id = response.parse()
+ assert_matches_type(FileIDConfirmUploadResponse, file_id, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_delete_file(self, client: Mobilerun) -> None:
+ file_id = client.agents.files.file_id.delete_file()
+ assert_matches_type(FileIDDeleteFileResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_delete_file(self, client: Mobilerun) -> None:
+ response = client.agents.files.file_id.with_raw_response.delete_file()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file_id = response.parse()
+ assert_matches_type(FileIDDeleteFileResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_delete_file(self, client: Mobilerun) -> None:
+ with client.agents.files.file_id.with_streaming_response.delete_file() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file_id = response.parse()
+ assert_matches_type(FileIDDeleteFileResponse, file_id, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_download_file(self, client: Mobilerun) -> None:
+ file_id = client.agents.files.file_id.download_file()
+ assert file_id is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_download_file(self, client: Mobilerun) -> None:
+ response = client.agents.files.file_id.with_raw_response.download_file()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file_id = response.parse()
+ assert file_id is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_download_file(self, client: Mobilerun) -> None:
+ with client.agents.files.file_id.with_streaming_response.download_file() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file_id = response.parse()
+ assert file_id is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update_metadata(self, client: Mobilerun) -> None:
+ file_id = client.agents.files.file_id.update_metadata()
+ assert_matches_type(FileIDUpdateMetadataResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update_metadata_with_all_params(self, client: Mobilerun) -> None:
+ file_id = client.agents.files.file_id.update_metadata(
+ display_name="x",
+ enabled=True,
+ )
+ assert_matches_type(FileIDUpdateMetadataResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_update_metadata(self, client: Mobilerun) -> None:
+ response = client.agents.files.file_id.with_raw_response.update_metadata()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file_id = response.parse()
+ assert_matches_type(FileIDUpdateMetadataResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_update_metadata(self, client: Mobilerun) -> None:
+ with client.agents.files.file_id.with_streaming_response.update_metadata() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file_id = response.parse()
+ assert_matches_type(FileIDUpdateMetadataResponse, file_id, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncFileID:
+ 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_cancel_pending_upload(self, async_client: AsyncMobilerun) -> None:
+ file_id = await async_client.agents.files.file_id.cancel_pending_upload()
+ assert_matches_type(FileIDCancelPendingUploadResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_cancel_pending_upload(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.files.file_id.with_raw_response.cancel_pending_upload()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file_id = await response.parse()
+ assert_matches_type(FileIDCancelPendingUploadResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_cancel_pending_upload(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.files.file_id.with_streaming_response.cancel_pending_upload() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file_id = await response.parse()
+ assert_matches_type(FileIDCancelPendingUploadResponse, file_id, 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_upload(self, async_client: AsyncMobilerun) -> None:
+ file_id = await async_client.agents.files.file_id.confirm_upload()
+ assert_matches_type(FileIDConfirmUploadResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_confirm_upload(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.files.file_id.with_raw_response.confirm_upload()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file_id = await response.parse()
+ assert_matches_type(FileIDConfirmUploadResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_confirm_upload(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.files.file_id.with_streaming_response.confirm_upload() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file_id = await response.parse()
+ assert_matches_type(FileIDConfirmUploadResponse, file_id, 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_file(self, async_client: AsyncMobilerun) -> None:
+ file_id = await async_client.agents.files.file_id.delete_file()
+ assert_matches_type(FileIDDeleteFileResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_delete_file(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.files.file_id.with_raw_response.delete_file()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file_id = await response.parse()
+ assert_matches_type(FileIDDeleteFileResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_delete_file(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.files.file_id.with_streaming_response.delete_file() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file_id = await response.parse()
+ assert_matches_type(FileIDDeleteFileResponse, file_id, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_download_file(self, async_client: AsyncMobilerun) -> None:
+ file_id = await async_client.agents.files.file_id.download_file()
+ assert file_id is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_download_file(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.files.file_id.with_raw_response.download_file()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file_id = await response.parse()
+ assert file_id is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_download_file(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.files.file_id.with_streaming_response.download_file() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file_id = await response.parse()
+ assert file_id is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_update_metadata(self, async_client: AsyncMobilerun) -> None:
+ file_id = await async_client.agents.files.file_id.update_metadata()
+ assert_matches_type(FileIDUpdateMetadataResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_update_metadata_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ file_id = await async_client.agents.files.file_id.update_metadata(
+ display_name="x",
+ enabled=True,
+ )
+ assert_matches_type(FileIDUpdateMetadataResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_update_metadata(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.files.file_id.with_raw_response.update_metadata()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file_id = await response.parse()
+ assert_matches_type(FileIDUpdateMetadataResponse, file_id, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_update_metadata(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.files.file_id.with_streaming_response.update_metadata() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file_id = await response.parse()
+ assert_matches_type(FileIDUpdateMetadataResponse, file_id, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/agents/test_chat.py b/tests/api_resources/agents/test_chat.py
new file mode 100644
index 0000000..a5525f6
--- /dev/null
+++ b/tests/api_resources/agents/test_chat.py
@@ -0,0 +1,271 @@
+# 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.agents import (
+ ChatGetChatStateResponse,
+ ChatRehydrateChatResponse,
+ ChatDeliverPermissionResponse,
+ ChatListSlashCommandsResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestChat:
+ 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_deliver_permission(self, client: Mobilerun) -> None:
+ chat = client.agents.chat.deliver_permission(
+ permission_id="x",
+ response="once",
+ )
+ assert_matches_type(ChatDeliverPermissionResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_deliver_permission(self, client: Mobilerun) -> None:
+ response = client.agents.chat.with_raw_response.deliver_permission(
+ permission_id="x",
+ response="once",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(ChatDeliverPermissionResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_deliver_permission(self, client: Mobilerun) -> None:
+ with client.agents.chat.with_streaming_response.deliver_permission(
+ permission_id="x",
+ response="once",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(ChatDeliverPermissionResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_get_chat_state(self, client: Mobilerun) -> None:
+ chat = client.agents.chat.get_chat_state()
+ assert_matches_type(ChatGetChatStateResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_get_chat_state(self, client: Mobilerun) -> None:
+ response = client.agents.chat.with_raw_response.get_chat_state()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(ChatGetChatStateResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_get_chat_state(self, client: Mobilerun) -> None:
+ with client.agents.chat.with_streaming_response.get_chat_state() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(ChatGetChatStateResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_slash_commands(self, client: Mobilerun) -> None:
+ chat = client.agents.chat.list_slash_commands()
+ assert_matches_type(ChatListSlashCommandsResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list_slash_commands(self, client: Mobilerun) -> None:
+ response = client.agents.chat.with_raw_response.list_slash_commands()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(ChatListSlashCommandsResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list_slash_commands(self, client: Mobilerun) -> None:
+ with client.agents.chat.with_streaming_response.list_slash_commands() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(ChatListSlashCommandsResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_rehydrate_chat(self, client: Mobilerun) -> None:
+ chat = client.agents.chat.rehydrate_chat()
+ assert_matches_type(ChatRehydrateChatResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_rehydrate_chat(self, client: Mobilerun) -> None:
+ response = client.agents.chat.with_raw_response.rehydrate_chat()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(ChatRehydrateChatResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_rehydrate_chat(self, client: Mobilerun) -> None:
+ with client.agents.chat.with_streaming_response.rehydrate_chat() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(ChatRehydrateChatResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncChat:
+ 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_deliver_permission(self, async_client: AsyncMobilerun) -> None:
+ chat = await async_client.agents.chat.deliver_permission(
+ permission_id="x",
+ response="once",
+ )
+ assert_matches_type(ChatDeliverPermissionResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_deliver_permission(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.chat.with_raw_response.deliver_permission(
+ permission_id="x",
+ response="once",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(ChatDeliverPermissionResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_deliver_permission(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.chat.with_streaming_response.deliver_permission(
+ permission_id="x",
+ response="once",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(ChatDeliverPermissionResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_get_chat_state(self, async_client: AsyncMobilerun) -> None:
+ chat = await async_client.agents.chat.get_chat_state()
+ assert_matches_type(ChatGetChatStateResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_get_chat_state(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.chat.with_raw_response.get_chat_state()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(ChatGetChatStateResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_get_chat_state(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.chat.with_streaming_response.get_chat_state() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(ChatGetChatStateResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_slash_commands(self, async_client: AsyncMobilerun) -> None:
+ chat = await async_client.agents.chat.list_slash_commands()
+ assert_matches_type(ChatListSlashCommandsResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_list_slash_commands(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.chat.with_raw_response.list_slash_commands()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(ChatListSlashCommandsResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_list_slash_commands(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.chat.with_streaming_response.list_slash_commands() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(ChatListSlashCommandsResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_rehydrate_chat(self, async_client: AsyncMobilerun) -> None:
+ chat = await async_client.agents.chat.rehydrate_chat()
+ assert_matches_type(ChatRehydrateChatResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_rehydrate_chat(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.chat.with_raw_response.rehydrate_chat()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(ChatRehydrateChatResponse, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_rehydrate_chat(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.chat.with_streaming_response.rehydrate_chat() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(ChatRehydrateChatResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/agents/test_files.py b/tests/api_resources/agents/test_files.py
new file mode 100644
index 0000000..133bc30
--- /dev/null
+++ b/tests/api_resources/agents/test_files.py
@@ -0,0 +1,203 @@
+# 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.agents import (
+ FileListFilesResponse,
+ FileMintUploadURLResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+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_list_files(self, client: Mobilerun) -> None:
+ file = client.agents.files.list_files()
+ assert_matches_type(FileListFilesResponse, file, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_files_with_all_params(self, client: Mobilerun) -> None:
+ file = client.agents.files.list_files(
+ zone="user",
+ )
+ assert_matches_type(FileListFilesResponse, file, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list_files(self, client: Mobilerun) -> None:
+ response = client.agents.files.with_raw_response.list_files()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file = response.parse()
+ assert_matches_type(FileListFilesResponse, file, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list_files(self, client: Mobilerun) -> None:
+ with client.agents.files.with_streaming_response.list_files() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file = response.parse()
+ assert_matches_type(FileListFilesResponse, file, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_mint_upload_url(self, client: Mobilerun) -> None:
+ file = client.agents.files.mint_upload_url(
+ filename="x",
+ mime_type="x",
+ size_bytes=1,
+ )
+ assert_matches_type(FileMintUploadURLResponse, file, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_mint_upload_url_with_all_params(self, client: Mobilerun) -> None:
+ file = client.agents.files.mint_upload_url(
+ filename="x",
+ mime_type="x",
+ size_bytes=1,
+ zone="user",
+ idempotency_key="x",
+ )
+ assert_matches_type(FileMintUploadURLResponse, file, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_mint_upload_url(self, client: Mobilerun) -> None:
+ response = client.agents.files.with_raw_response.mint_upload_url(
+ filename="x",
+ mime_type="x",
+ size_bytes=1,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file = response.parse()
+ assert_matches_type(FileMintUploadURLResponse, file, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_mint_upload_url(self, client: Mobilerun) -> None:
+ with client.agents.files.with_streaming_response.mint_upload_url(
+ filename="x",
+ mime_type="x",
+ size_bytes=1,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file = response.parse()
+ assert_matches_type(FileMintUploadURLResponse, file, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncFiles:
+ 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_files(self, async_client: AsyncMobilerun) -> None:
+ file = await async_client.agents.files.list_files()
+ assert_matches_type(FileListFilesResponse, file, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_files_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ file = await async_client.agents.files.list_files(
+ zone="user",
+ )
+ assert_matches_type(FileListFilesResponse, file, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_list_files(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.files.with_raw_response.list_files()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file = await response.parse()
+ assert_matches_type(FileListFilesResponse, file, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_list_files(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.files.with_streaming_response.list_files() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file = await response.parse()
+ assert_matches_type(FileListFilesResponse, 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_mint_upload_url(self, async_client: AsyncMobilerun) -> None:
+ file = await async_client.agents.files.mint_upload_url(
+ filename="x",
+ mime_type="x",
+ size_bytes=1,
+ )
+ assert_matches_type(FileMintUploadURLResponse, file, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_mint_upload_url_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ file = await async_client.agents.files.mint_upload_url(
+ filename="x",
+ mime_type="x",
+ size_bytes=1,
+ zone="user",
+ idempotency_key="x",
+ )
+ assert_matches_type(FileMintUploadURLResponse, file, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_mint_upload_url(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.agents.files.with_raw_response.mint_upload_url(
+ filename="x",
+ mime_type="x",
+ size_bytes=1,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ file = await response.parse()
+ assert_matches_type(FileMintUploadURLResponse, file, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_mint_upload_url(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.agents.files.with_streaming_response.mint_upload_url(
+ filename="x",
+ mime_type="x",
+ size_bytes=1,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ file = await response.parse()
+ assert_matches_type(FileMintUploadURLResponse, file, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/connect/__init__.py b/tests/api_resources/connect/__init__.py
new file mode 100644
index 0000000..fd8019a
--- /dev/null
+++ b/tests/api_resources/connect/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/connect/test_countries.py b/tests/api_resources/connect/test_countries.py
new file mode 100644
index 0000000..e7d88fc
--- /dev/null
+++ b/tests/api_resources/connect/test_countries.py
@@ -0,0 +1,100 @@
+# 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.connect import CountryListResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestCountries:
+ 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:
+ country = client.connect.countries.list()
+ assert_matches_type(CountryListResponse, country, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Mobilerun) -> None:
+ country = client.connect.countries.list(
+ page=1,
+ page_size=1,
+ type="residential",
+ )
+ assert_matches_type(CountryListResponse, country, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Mobilerun) -> None:
+ response = client.connect.countries.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ country = response.parse()
+ assert_matches_type(CountryListResponse, country, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Mobilerun) -> None:
+ with client.connect.countries.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ country = response.parse()
+ assert_matches_type(CountryListResponse, country, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncCountries:
+ 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:
+ country = await async_client.connect.countries.list()
+ assert_matches_type(CountryListResponse, country, 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:
+ country = await async_client.connect.countries.list(
+ page=1,
+ page_size=1,
+ type="residential",
+ )
+ assert_matches_type(CountryListResponse, country, 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.connect.countries.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ country = await response.parse()
+ assert_matches_type(CountryListResponse, country, 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.connect.countries.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ country = await response.parse()
+ assert_matches_type(CountryListResponse, country, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/connect/test_proxies.py b/tests/api_resources/connect/test_proxies.py
new file mode 100644
index 0000000..6442710
--- /dev/null
+++ b/tests/api_resources/connect/test_proxies.py
@@ -0,0 +1,595 @@
+# 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._utils import parse_datetime
+from mobilerun_sdk.types.connect import (
+ ProxyBuyResponse,
+ ProxyListResponse,
+ ProxyPingResponse,
+ ProxyRetrieveResponse,
+ ProxyListConnectionsResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestProxies:
+ 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_retrieve(self, client: Mobilerun) -> None:
+ proxy = client.connect.proxies.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ProxyRetrieveResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Mobilerun) -> None:
+ response = client.connect.proxies.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ proxy = response.parse()
+ assert_matches_type(ProxyRetrieveResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Mobilerun) -> None:
+ with client.connect.proxies.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ proxy = response.parse()
+ assert_matches_type(ProxyRetrieveResponse, proxy, 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.connect.proxies.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Mobilerun) -> None:
+ proxy = client.connect.proxies.list()
+ assert_matches_type(ProxyListResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Mobilerun) -> None:
+ proxy = client.connect.proxies.list(
+ country="country",
+ page=1,
+ page_size=1,
+ )
+ assert_matches_type(ProxyListResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Mobilerun) -> None:
+ response = client.connect.proxies.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ proxy = response.parse()
+ assert_matches_type(ProxyListResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Mobilerun) -> None:
+ with client.connect.proxies.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ proxy = response.parse()
+ assert_matches_type(ProxyListResponse, proxy, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_buy(self, client: Mobilerun) -> None:
+ proxy = client.connect.proxies.buy(
+ country="country",
+ )
+ 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="residential",
+ )
+ 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:
+ response = client.connect.proxies.with_raw_response.buy(
+ country="country",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ proxy = response.parse()
+ assert_matches_type(ProxyBuyResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_buy(self, client: Mobilerun) -> None:
+ with client.connect.proxies.with_streaming_response.buy(
+ country="country",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ proxy = response.parse()
+ assert_matches_type(ProxyBuyResponse, proxy, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_cancel(self, client: Mobilerun) -> None:
+ proxy = client.connect.proxies.cancel(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert proxy is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_cancel(self, client: Mobilerun) -> None:
+ response = client.connect.proxies.with_raw_response.cancel(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ proxy = response.parse()
+ assert proxy is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_cancel(self, client: Mobilerun) -> None:
+ with client.connect.proxies.with_streaming_response.cancel(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ proxy = response.parse()
+ assert proxy is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_cancel(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.connect.proxies.with_raw_response.cancel(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_connections(self, client: Mobilerun) -> None:
+ proxy = client.connect.proxies.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ProxyListConnectionsResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_connections_with_all_params(self, client: Mobilerun) -> None:
+ proxy = client.connect.proxies.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ close_reason="closeReason",
+ country="country",
+ dst_host="dstHost",
+ dst_port=0,
+ ended_after=parse_datetime("2019-12-27T18:11:19.117Z"),
+ ended_before=parse_datetime("2019-12-27T18:11:19.117Z"),
+ max_bytes_in=0,
+ max_bytes_out=0,
+ max_duration_ms=0,
+ max_total_bytes=0,
+ min_bytes_in=0,
+ min_bytes_out=0,
+ min_duration_ms=0,
+ min_total_bytes=0,
+ order="asc",
+ order_by="startedAt",
+ page=1,
+ page_size=1,
+ protocol="tcp",
+ provider="provider",
+ session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ started_after=parse_datetime("2019-12-27T18:11:19.117Z"),
+ started_before=parse_datetime("2019-12-27T18:11:19.117Z"),
+ status="active",
+ user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ProxyListConnectionsResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list_connections(self, client: Mobilerun) -> None:
+ response = client.connect.proxies.with_raw_response.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ proxy = response.parse()
+ assert_matches_type(ProxyListConnectionsResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list_connections(self, client: Mobilerun) -> None:
+ with client.connect.proxies.with_streaming_response.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ proxy = response.parse()
+ assert_matches_type(ProxyListConnectionsResponse, proxy, 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_connections(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.connect.proxies.with_raw_response.list_connections(
+ id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_ping(self, client: Mobilerun) -> None:
+ proxy = client.connect.proxies.ping(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ProxyPingResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_ping(self, client: Mobilerun) -> None:
+ response = client.connect.proxies.with_raw_response.ping(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ proxy = response.parse()
+ assert_matches_type(ProxyPingResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_ping(self, client: Mobilerun) -> None:
+ with client.connect.proxies.with_streaming_response.ping(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ proxy = response.parse()
+ assert_matches_type(ProxyPingResponse, proxy, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_ping(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.connect.proxies.with_raw_response.ping(
+ "",
+ )
+
+
+class TestAsyncProxies:
+ 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_retrieve(self, async_client: AsyncMobilerun) -> None:
+ proxy = await async_client.connect.proxies.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ProxyRetrieveResponse, proxy, 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.connect.proxies.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ proxy = await response.parse()
+ assert_matches_type(ProxyRetrieveResponse, proxy, 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.connect.proxies.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ proxy = await response.parse()
+ assert_matches_type(ProxyRetrieveResponse, proxy, 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.connect.proxies.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncMobilerun) -> None:
+ proxy = await async_client.connect.proxies.list()
+ assert_matches_type(ProxyListResponse, proxy, 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:
+ proxy = await async_client.connect.proxies.list(
+ country="country",
+ page=1,
+ page_size=1,
+ )
+ assert_matches_type(ProxyListResponse, proxy, 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.connect.proxies.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ proxy = await response.parse()
+ assert_matches_type(ProxyListResponse, proxy, 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.connect.proxies.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ proxy = await response.parse()
+ assert_matches_type(ProxyListResponse, proxy, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_buy(self, async_client: AsyncMobilerun) -> None:
+ proxy = await async_client.connect.proxies.buy(
+ country="country",
+ )
+ 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="residential",
+ )
+ 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:
+ response = await async_client.connect.proxies.with_raw_response.buy(
+ country="country",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ proxy = await response.parse()
+ assert_matches_type(ProxyBuyResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_buy(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.connect.proxies.with_streaming_response.buy(
+ country="country",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ proxy = await response.parse()
+ assert_matches_type(ProxyBuyResponse, proxy, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_cancel(self, async_client: AsyncMobilerun) -> None:
+ proxy = await async_client.connect.proxies.cancel(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert proxy is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_cancel(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.connect.proxies.with_raw_response.cancel(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ proxy = await response.parse()
+ assert proxy is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_cancel(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.connect.proxies.with_streaming_response.cancel(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ proxy = await response.parse()
+ assert proxy 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_cancel(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.connect.proxies.with_raw_response.cancel(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_connections(self, async_client: AsyncMobilerun) -> None:
+ proxy = await async_client.connect.proxies.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ProxyListConnectionsResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_connections_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ proxy = await async_client.connect.proxies.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ close_reason="closeReason",
+ country="country",
+ dst_host="dstHost",
+ dst_port=0,
+ ended_after=parse_datetime("2019-12-27T18:11:19.117Z"),
+ ended_before=parse_datetime("2019-12-27T18:11:19.117Z"),
+ max_bytes_in=0,
+ max_bytes_out=0,
+ max_duration_ms=0,
+ max_total_bytes=0,
+ min_bytes_in=0,
+ min_bytes_out=0,
+ min_duration_ms=0,
+ min_total_bytes=0,
+ order="asc",
+ order_by="startedAt",
+ page=1,
+ page_size=1,
+ protocol="tcp",
+ provider="provider",
+ session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ started_after=parse_datetime("2019-12-27T18:11:19.117Z"),
+ started_before=parse_datetime("2019-12-27T18:11:19.117Z"),
+ status="active",
+ user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ProxyListConnectionsResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_list_connections(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.connect.proxies.with_raw_response.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ proxy = await response.parse()
+ assert_matches_type(ProxyListConnectionsResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_list_connections(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.connect.proxies.with_streaming_response.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ proxy = await response.parse()
+ assert_matches_type(ProxyListConnectionsResponse, proxy, 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_connections(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.connect.proxies.with_raw_response.list_connections(
+ id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_ping(self, async_client: AsyncMobilerun) -> None:
+ proxy = await async_client.connect.proxies.ping(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ProxyPingResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_ping(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.connect.proxies.with_raw_response.ping(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ proxy = await response.parse()
+ assert_matches_type(ProxyPingResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_ping(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.connect.proxies.with_streaming_response.ping(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ proxy = await response.parse()
+ assert_matches_type(ProxyPingResponse, proxy, 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_ping(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.connect.proxies.with_raw_response.ping(
+ "",
+ )
diff --git a/tests/api_resources/connect/test_users.py b/tests/api_resources/connect/test_users.py
new file mode 100644
index 0000000..c2e99dc
--- /dev/null
+++ b/tests/api_resources/connect/test_users.py
@@ -0,0 +1,603 @@
+# 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._utils import parse_datetime
+from mobilerun_sdk.types.connect import (
+ UserListResponse,
+ UserCreateResponse,
+ UserUpdateResponse,
+ UserRetrieveResponse,
+ UserListConnectionsResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestUsers:
+ 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:
+ user = client.connect.users.create()
+ assert_matches_type(UserCreateResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params(self, client: Mobilerun) -> None:
+ user = client.connect.users.create(
+ password="x",
+ proxy_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ username="x",
+ )
+ assert_matches_type(UserCreateResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Mobilerun) -> None:
+ response = client.connect.users.with_raw_response.create()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = response.parse()
+ assert_matches_type(UserCreateResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Mobilerun) -> None:
+ with client.connect.users.with_streaming_response.create() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = response.parse()
+ assert_matches_type(UserCreateResponse, user, 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:
+ user = client.connect.users.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(UserRetrieveResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Mobilerun) -> None:
+ response = client.connect.users.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = response.parse()
+ assert_matches_type(UserRetrieveResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Mobilerun) -> None:
+ with client.connect.users.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = response.parse()
+ assert_matches_type(UserRetrieveResponse, user, 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.connect.users.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update(self, client: Mobilerun) -> None:
+ user = client.connect.users.update(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(UserUpdateResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update_with_all_params(self, client: Mobilerun) -> None:
+ user = client.connect.users.update(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ proxy_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(UserUpdateResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_update(self, client: Mobilerun) -> None:
+ response = client.connect.users.with_raw_response.update(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = response.parse()
+ assert_matches_type(UserUpdateResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_update(self, client: Mobilerun) -> None:
+ with client.connect.users.with_streaming_response.update(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = response.parse()
+ assert_matches_type(UserUpdateResponse, user, 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.connect.users.with_raw_response.update(
+ id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Mobilerun) -> None:
+ user = client.connect.users.list()
+ assert_matches_type(UserListResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Mobilerun) -> None:
+ user = client.connect.users.list(
+ page=1,
+ page_size=1,
+ proxy_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(UserListResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Mobilerun) -> None:
+ response = client.connect.users.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = response.parse()
+ assert_matches_type(UserListResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Mobilerun) -> None:
+ with client.connect.users.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = response.parse()
+ assert_matches_type(UserListResponse, user, 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:
+ user = client.connect.users.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert user is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_delete(self, client: Mobilerun) -> None:
+ response = client.connect.users.with_raw_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = response.parse()
+ assert user is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_delete(self, client: Mobilerun) -> None:
+ with client.connect.users.with_streaming_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = response.parse()
+ assert user 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.connect.users.with_raw_response.delete(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_connections(self, client: Mobilerun) -> None:
+ user = client.connect.users.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(UserListConnectionsResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_connections_with_all_params(self, client: Mobilerun) -> None:
+ user = client.connect.users.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ close_reason="closeReason",
+ country="country",
+ dst_host="dstHost",
+ dst_port=0,
+ ended_after=parse_datetime("2019-12-27T18:11:19.117Z"),
+ ended_before=parse_datetime("2019-12-27T18:11:19.117Z"),
+ max_bytes_in=0,
+ max_bytes_out=0,
+ max_duration_ms=0,
+ max_total_bytes=0,
+ min_bytes_in=0,
+ min_bytes_out=0,
+ min_duration_ms=0,
+ min_total_bytes=0,
+ order="asc",
+ order_by="startedAt",
+ page=1,
+ page_size=1,
+ protocol="tcp",
+ provider="provider",
+ proxy_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ started_after=parse_datetime("2019-12-27T18:11:19.117Z"),
+ started_before=parse_datetime("2019-12-27T18:11:19.117Z"),
+ status="active",
+ )
+ assert_matches_type(UserListConnectionsResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list_connections(self, client: Mobilerun) -> None:
+ response = client.connect.users.with_raw_response.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = response.parse()
+ assert_matches_type(UserListConnectionsResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list_connections(self, client: Mobilerun) -> None:
+ with client.connect.users.with_streaming_response.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = response.parse()
+ assert_matches_type(UserListConnectionsResponse, user, 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_connections(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.connect.users.with_raw_response.list_connections(
+ id="",
+ )
+
+
+class TestAsyncUsers:
+ 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:
+ user = await async_client.connect.users.create()
+ assert_matches_type(UserCreateResponse, user, 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:
+ user = await async_client.connect.users.create(
+ password="x",
+ proxy_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ username="x",
+ )
+ assert_matches_type(UserCreateResponse, user, 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.connect.users.with_raw_response.create()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = await response.parse()
+ assert_matches_type(UserCreateResponse, user, 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.connect.users.with_streaming_response.create() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = await response.parse()
+ assert_matches_type(UserCreateResponse, user, 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:
+ user = await async_client.connect.users.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(UserRetrieveResponse, user, 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.connect.users.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = await response.parse()
+ assert_matches_type(UserRetrieveResponse, user, 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.connect.users.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = await response.parse()
+ assert_matches_type(UserRetrieveResponse, user, 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.connect.users.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_update(self, async_client: AsyncMobilerun) -> None:
+ user = await async_client.connect.users.update(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(UserUpdateResponse, user, 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:
+ user = await async_client.connect.users.update(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ proxy_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(UserUpdateResponse, user, 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.connect.users.with_raw_response.update(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = await response.parse()
+ assert_matches_type(UserUpdateResponse, user, 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.connect.users.with_streaming_response.update(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = await response.parse()
+ assert_matches_type(UserUpdateResponse, user, 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.connect.users.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:
+ user = await async_client.connect.users.list()
+ assert_matches_type(UserListResponse, user, 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:
+ user = await async_client.connect.users.list(
+ page=1,
+ page_size=1,
+ proxy_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(UserListResponse, user, 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.connect.users.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = await response.parse()
+ assert_matches_type(UserListResponse, user, 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.connect.users.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = await response.parse()
+ assert_matches_type(UserListResponse, user, 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:
+ user = await async_client.connect.users.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert user 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.connect.users.with_raw_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = await response.parse()
+ assert user 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.connect.users.with_streaming_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = await response.parse()
+ assert user 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.connect.users.with_raw_response.delete(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_connections(self, async_client: AsyncMobilerun) -> None:
+ user = await async_client.connect.users.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(UserListConnectionsResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_connections_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ user = await async_client.connect.users.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ close_reason="closeReason",
+ country="country",
+ dst_host="dstHost",
+ dst_port=0,
+ ended_after=parse_datetime("2019-12-27T18:11:19.117Z"),
+ ended_before=parse_datetime("2019-12-27T18:11:19.117Z"),
+ max_bytes_in=0,
+ max_bytes_out=0,
+ max_duration_ms=0,
+ max_total_bytes=0,
+ min_bytes_in=0,
+ min_bytes_out=0,
+ min_duration_ms=0,
+ min_total_bytes=0,
+ order="asc",
+ order_by="startedAt",
+ page=1,
+ page_size=1,
+ protocol="tcp",
+ provider="provider",
+ proxy_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ started_after=parse_datetime("2019-12-27T18:11:19.117Z"),
+ started_before=parse_datetime("2019-12-27T18:11:19.117Z"),
+ status="active",
+ )
+ assert_matches_type(UserListConnectionsResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_list_connections(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.connect.users.with_raw_response.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = await response.parse()
+ assert_matches_type(UserListConnectionsResponse, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_list_connections(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.connect.users.with_streaming_response.list_connections(
+ id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = await response.parse()
+ assert_matches_type(UserListConnectionsResponse, user, 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_connections(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.connect.users.with_raw_response.list_connections(
+ id="",
+ )
diff --git a/tests/api_resources/devices/esim/test_apn.py b/tests/api_resources/devices/esim/test_apn.py
deleted file mode 100644
index d538cf7..0000000
--- a/tests/api_resources/devices/esim/test_apn.py
+++ /dev/null
@@ -1,430 +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, Optional, cast
-
-import pytest
-
-from tests.utils import assert_matches_type
-from mobilerun_sdk import Mobilerun, AsyncMobilerun
-from mobilerun_sdk.types.devices.esim import ApnListResponse
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestApn:
- 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:
- apn = client.devices.esim.apn.create(
- device_id="deviceId",
- apn="apn",
- mcc="mcc",
- mnc="mnc",
- name="name",
- protocol="protocol",
- roaming_protocol="roamingProtocol",
- sub_id=0,
- type="type",
- )
- assert apn is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_create_with_all_params(self, client: Mobilerun) -> None:
- apn = client.devices.esim.apn.create(
- device_id="deviceId",
- apn="apn",
- mcc="mcc",
- mnc="mnc",
- name="name",
- protocol="protocol",
- roaming_protocol="roamingProtocol",
- sub_id=0,
- type="type",
- x_device_display_id=0,
- )
- assert apn is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_create(self, client: Mobilerun) -> None:
- response = client.devices.esim.apn.with_raw_response.create(
- device_id="deviceId",
- apn="apn",
- mcc="mcc",
- mnc="mnc",
- name="name",
- protocol="protocol",
- roaming_protocol="roamingProtocol",
- sub_id=0,
- type="type",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- apn = response.parse()
- assert apn is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_create(self, client: Mobilerun) -> None:
- with client.devices.esim.apn.with_streaming_response.create(
- device_id="deviceId",
- apn="apn",
- mcc="mcc",
- mnc="mnc",
- name="name",
- protocol="protocol",
- roaming_protocol="roamingProtocol",
- sub_id=0,
- type="type",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- apn = response.parse()
- assert apn is None
-
- 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.esim.apn.with_raw_response.create(
- device_id="",
- apn="apn",
- mcc="mcc",
- mnc="mnc",
- name="name",
- protocol="protocol",
- roaming_protocol="roamingProtocol",
- sub_id=0,
- type="type",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_list(self, client: Mobilerun) -> None:
- apn = client.devices.esim.apn.list(
- device_id="deviceId",
- )
- assert_matches_type(Optional[ApnListResponse], apn, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_list_with_all_params(self, client: Mobilerun) -> None:
- apn = client.devices.esim.apn.list(
- device_id="deviceId",
- x_device_display_id=0,
- )
- assert_matches_type(Optional[ApnListResponse], apn, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_list(self, client: Mobilerun) -> None:
- response = client.devices.esim.apn.with_raw_response.list(
- device_id="deviceId",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- apn = response.parse()
- assert_matches_type(Optional[ApnListResponse], apn, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_list(self, client: Mobilerun) -> None:
- with client.devices.esim.apn.with_streaming_response.list(
- device_id="deviceId",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- apn = response.parse()
- assert_matches_type(Optional[ApnListResponse], apn, 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.esim.apn.with_raw_response.list(
- device_id="",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_select(self, client: Mobilerun) -> None:
- apn = client.devices.esim.apn.select(
- device_id="deviceId",
- apn_id=0,
- sub_id=0,
- )
- assert apn is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_select_with_all_params(self, client: Mobilerun) -> None:
- apn = client.devices.esim.apn.select(
- device_id="deviceId",
- apn_id=0,
- sub_id=0,
- x_device_display_id=0,
- )
- assert apn is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_select(self, client: Mobilerun) -> None:
- response = client.devices.esim.apn.with_raw_response.select(
- device_id="deviceId",
- apn_id=0,
- sub_id=0,
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- apn = response.parse()
- assert apn is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_select(self, client: Mobilerun) -> None:
- with client.devices.esim.apn.with_streaming_response.select(
- device_id="deviceId",
- apn_id=0,
- sub_id=0,
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- apn = response.parse()
- assert apn is None
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_select(self, client: Mobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"):
- client.devices.esim.apn.with_raw_response.select(
- device_id="",
- apn_id=0,
- sub_id=0,
- )
-
-
-class TestAsyncApn:
- 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:
- apn = await async_client.devices.esim.apn.create(
- device_id="deviceId",
- apn="apn",
- mcc="mcc",
- mnc="mnc",
- name="name",
- protocol="protocol",
- roaming_protocol="roamingProtocol",
- sub_id=0,
- type="type",
- )
- assert apn is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_create_with_all_params(self, async_client: AsyncMobilerun) -> None:
- apn = await async_client.devices.esim.apn.create(
- device_id="deviceId",
- apn="apn",
- mcc="mcc",
- mnc="mnc",
- name="name",
- protocol="protocol",
- roaming_protocol="roamingProtocol",
- sub_id=0,
- type="type",
- x_device_display_id=0,
- )
- assert apn is None
-
- @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.esim.apn.with_raw_response.create(
- device_id="deviceId",
- apn="apn",
- mcc="mcc",
- mnc="mnc",
- name="name",
- protocol="protocol",
- roaming_protocol="roamingProtocol",
- sub_id=0,
- type="type",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- apn = await response.parse()
- assert apn is None
-
- @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.esim.apn.with_streaming_response.create(
- device_id="deviceId",
- apn="apn",
- mcc="mcc",
- mnc="mnc",
- name="name",
- protocol="protocol",
- roaming_protocol="roamingProtocol",
- sub_id=0,
- type="type",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- apn = await response.parse()
- assert apn 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_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.esim.apn.with_raw_response.create(
- device_id="",
- apn="apn",
- mcc="mcc",
- mnc="mnc",
- name="name",
- protocol="protocol",
- roaming_protocol="roamingProtocol",
- sub_id=0,
- type="type",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_list(self, async_client: AsyncMobilerun) -> None:
- apn = await async_client.devices.esim.apn.list(
- device_id="deviceId",
- )
- assert_matches_type(Optional[ApnListResponse], apn, 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:
- apn = await async_client.devices.esim.apn.list(
- device_id="deviceId",
- x_device_display_id=0,
- )
- assert_matches_type(Optional[ApnListResponse], apn, 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.esim.apn.with_raw_response.list(
- device_id="deviceId",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- apn = await response.parse()
- assert_matches_type(Optional[ApnListResponse], apn, 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.esim.apn.with_streaming_response.list(
- device_id="deviceId",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- apn = await response.parse()
- assert_matches_type(Optional[ApnListResponse], apn, 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.esim.apn.with_raw_response.list(
- device_id="",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_select(self, async_client: AsyncMobilerun) -> None:
- apn = await async_client.devices.esim.apn.select(
- device_id="deviceId",
- apn_id=0,
- sub_id=0,
- )
- assert apn is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_select_with_all_params(self, async_client: AsyncMobilerun) -> None:
- apn = await async_client.devices.esim.apn.select(
- device_id="deviceId",
- apn_id=0,
- sub_id=0,
- x_device_display_id=0,
- )
- assert apn is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_select(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.devices.esim.apn.with_raw_response.select(
- device_id="deviceId",
- apn_id=0,
- sub_id=0,
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- apn = await response.parse()
- assert apn is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_select(self, async_client: AsyncMobilerun) -> None:
- async with async_client.devices.esim.apn.with_streaming_response.select(
- device_id="deviceId",
- apn_id=0,
- sub_id=0,
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- apn = await response.parse()
- assert apn 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_select(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.esim.apn.with_raw_response.select(
- device_id="",
- apn_id=0,
- sub_id=0,
- )
diff --git a/tests/api_resources/devices/test_apps.py b/tests/api_resources/devices/test_apps.py
index 87c426d..5f86d32 100644
--- a/tests/api_resources/devices/test_apps.py
+++ b/tests/api_resources/devices/test_apps.py
@@ -17,68 +17,6 @@
class TestApps:
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:
- app = client.devices.apps.update(
- package_name="packageName",
- device_id="deviceId",
- )
- assert app is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_update_with_all_params(self, client: Mobilerun) -> None:
- app = client.devices.apps.update(
- package_name="packageName",
- device_id="deviceId",
- x_device_display_id=0,
- )
- assert app is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_update(self, client: Mobilerun) -> None:
- response = client.devices.apps.with_raw_response.update(
- package_name="packageName",
- device_id="deviceId",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- app = response.parse()
- assert app is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_update(self, client: Mobilerun) -> None:
- with client.devices.apps.with_streaming_response.update(
- package_name="packageName",
- device_id="deviceId",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- app = response.parse()
- assert app is None
-
- 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 `device_id` but received ''"):
- client.devices.apps.with_raw_response.update(
- package_name="packageName",
- device_id="",
- )
-
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `package_name` but received ''"):
- client.devices.apps.with_raw_response.update(
- package_name="",
- device_id="deviceId",
- )
-
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_method_list(self, client: Mobilerun) -> None:
@@ -371,16 +309,10 @@ def test_path_params_start(self, client: Mobilerun) -> None:
device_id="deviceId",
)
-
-class TestAsyncApps:
- 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_update(self, async_client: AsyncMobilerun) -> None:
- app = await async_client.devices.apps.update(
+ def test_method_stop(self, client: Mobilerun) -> None:
+ app = client.devices.apps.stop(
package_name="packageName",
device_id="deviceId",
)
@@ -388,8 +320,8 @@ async def test_method_update(self, async_client: AsyncMobilerun) -> None:
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
- async def test_method_update_with_all_params(self, async_client: AsyncMobilerun) -> None:
- app = await async_client.devices.apps.update(
+ def test_method_stop_with_all_params(self, client: Mobilerun) -> None:
+ app = client.devices.apps.stop(
package_name="packageName",
device_id="deviceId",
x_device_display_id=0,
@@ -398,47 +330,53 @@ async def test_method_update_with_all_params(self, async_client: AsyncMobilerun)
@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.devices.apps.with_raw_response.update(
+ def test_raw_response_stop(self, client: Mobilerun) -> None:
+ response = client.devices.apps.with_raw_response.stop(
package_name="packageName",
device_id="deviceId",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- app = await response.parse()
+ app = response.parse()
assert app is None
@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.devices.apps.with_streaming_response.update(
+ def test_streaming_response_stop(self, client: Mobilerun) -> None:
+ with client.devices.apps.with_streaming_response.stop(
package_name="packageName",
device_id="deviceId",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- app = await response.parse()
+ app = response.parse()
assert app 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_update(self, async_client: AsyncMobilerun) -> None:
+ def test_path_params_stop(self, client: Mobilerun) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"):
- await async_client.devices.apps.with_raw_response.update(
+ client.devices.apps.with_raw_response.stop(
package_name="packageName",
device_id="",
)
with pytest.raises(ValueError, match=r"Expected a non-empty value for `package_name` but received ''"):
- await async_client.devices.apps.with_raw_response.update(
+ client.devices.apps.with_raw_response.stop(
package_name="",
device_id="deviceId",
)
+
+class TestAsyncApps:
+ 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:
@@ -730,3 +668,65 @@ async def test_path_params_start(self, async_client: AsyncMobilerun) -> None:
package_name="",
device_id="deviceId",
)
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_stop(self, async_client: AsyncMobilerun) -> None:
+ app = await async_client.devices.apps.stop(
+ package_name="packageName",
+ device_id="deviceId",
+ )
+ assert app is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_stop_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ app = await async_client.devices.apps.stop(
+ package_name="packageName",
+ device_id="deviceId",
+ x_device_display_id=0,
+ )
+ assert app is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_stop(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.devices.apps.with_raw_response.stop(
+ package_name="packageName",
+ device_id="deviceId",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ app = await response.parse()
+ assert app is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_stop(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.devices.apps.with_streaming_response.stop(
+ package_name="packageName",
+ device_id="deviceId",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ app = await response.parse()
+ assert app 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_stop(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.apps.with_raw_response.stop(
+ package_name="packageName",
+ device_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `package_name` but received ''"):
+ await async_client.devices.apps.with_raw_response.stop(
+ package_name="",
+ device_id="deviceId",
+ )
diff --git a/tests/api_resources/devices/test_esim.py b/tests/api_resources/devices/test_esim.py
index 82541c2..3ff9449 100644
--- a/tests/api_resources/devices/test_esim.py
+++ b/tests/api_resources/devices/test_esim.py
@@ -11,7 +11,6 @@
from mobilerun_sdk import Mobilerun, AsyncMobilerun
from mobilerun_sdk.types.devices import (
EsimListResponse,
- EsimStatusResponse,
EsimActivateResponse,
)
@@ -247,113 +246,6 @@ def test_path_params_remove(self, client: Mobilerun) -> None:
sub_id=0,
)
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_set_roaming(self, client: Mobilerun) -> None:
- esim = client.devices.esim.set_roaming(
- device_id="deviceId",
- enabled=True,
- )
- assert esim is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_set_roaming_with_all_params(self, client: Mobilerun) -> None:
- esim = client.devices.esim.set_roaming(
- device_id="deviceId",
- enabled=True,
- x_device_display_id=0,
- )
- assert esim is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_set_roaming(self, client: Mobilerun) -> None:
- response = client.devices.esim.with_raw_response.set_roaming(
- device_id="deviceId",
- enabled=True,
- )
-
- 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_set_roaming(self, client: Mobilerun) -> None:
- with client.devices.esim.with_streaming_response.set_roaming(
- device_id="deviceId",
- enabled=True,
- ) 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_set_roaming(self, client: Mobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"):
- client.devices.esim.with_raw_response.set_roaming(
- device_id="",
- enabled=True,
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_status(self, client: Mobilerun) -> None:
- esim = client.devices.esim.status(
- device_id="deviceId",
- )
- assert_matches_type(Optional[EsimStatusResponse], esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_status_with_all_params(self, client: Mobilerun) -> None:
- esim = client.devices.esim.status(
- device_id="deviceId",
- x_device_display_id=0,
- )
- assert_matches_type(Optional[EsimStatusResponse], esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_status(self, client: Mobilerun) -> None:
- response = client.devices.esim.with_raw_response.status(
- device_id="deviceId",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = response.parse()
- assert_matches_type(Optional[EsimStatusResponse], esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_status(self, client: Mobilerun) -> None:
- with client.devices.esim.with_streaming_response.status(
- device_id="deviceId",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = response.parse()
- assert_matches_type(Optional[EsimStatusResponse], 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_status(self, client: Mobilerun) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `device_id` but received ''"):
- client.devices.esim.with_raw_response.status(
- device_id="",
- )
-
class TestAsyncEsim:
parametrize = pytest.mark.parametrize(
@@ -585,110 +477,3 @@ async def test_path_params_remove(self, async_client: AsyncMobilerun) -> None:
device_id="",
sub_id=0,
)
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_set_roaming(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.devices.esim.set_roaming(
- device_id="deviceId",
- enabled=True,
- )
- assert esim is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_set_roaming_with_all_params(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.devices.esim.set_roaming(
- device_id="deviceId",
- enabled=True,
- x_device_display_id=0,
- )
- assert esim is None
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_set_roaming(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.devices.esim.with_raw_response.set_roaming(
- device_id="deviceId",
- enabled=True,
- )
-
- 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_set_roaming(self, async_client: AsyncMobilerun) -> None:
- async with async_client.devices.esim.with_streaming_response.set_roaming(
- device_id="deviceId",
- enabled=True,
- ) 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_set_roaming(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.esim.with_raw_response.set_roaming(
- device_id="",
- enabled=True,
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_status(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.devices.esim.status(
- device_id="deviceId",
- )
- assert_matches_type(Optional[EsimStatusResponse], esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_status_with_all_params(self, async_client: AsyncMobilerun) -> None:
- esim = await async_client.devices.esim.status(
- device_id="deviceId",
- x_device_display_id=0,
- )
- assert_matches_type(Optional[EsimStatusResponse], esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_status(self, async_client: AsyncMobilerun) -> None:
- response = await async_client.devices.esim.with_raw_response.status(
- device_id="deviceId",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- esim = await response.parse()
- assert_matches_type(Optional[EsimStatusResponse], esim, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_status(self, async_client: AsyncMobilerun) -> None:
- async with async_client.devices.esim.with_streaming_response.status(
- device_id="deviceId",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- esim = await response.parse()
- assert_matches_type(Optional[EsimStatusResponse], 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_status(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.esim.with_raw_response.status(
- device_id="",
- )
diff --git a/tests/api_resources/test_apps.py b/tests/api_resources/test_apps.py
index 887a5ee..7fd88df 100644
--- a/tests/api_resources/test_apps.py
+++ b/tests/api_resources/test_apps.py
@@ -14,6 +14,7 @@
AppDeleteResponse,
AppRetrieveResponse,
AppMarkFailedResponse,
+ AppListVersionsResponse,
AppConfirmUploadResponse,
AppCreateSignedUploadURLResponse,
)
@@ -280,6 +281,48 @@ def test_streaming_response_create_signed_upload_url(self, client: Mobilerun) ->
assert cast(Any, response.is_closed) is True
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_versions(self, client: Mobilerun) -> None:
+ app = client.apps.list_versions(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(AppListVersionsResponse, app, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list_versions(self, client: Mobilerun) -> None:
+ response = client.apps.with_raw_response.list_versions(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ app = response.parse()
+ assert_matches_type(AppListVersionsResponse, app, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list_versions(self, client: Mobilerun) -> None:
+ with client.apps.with_streaming_response.list_versions(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ app = response.parse()
+ assert_matches_type(AppListVersionsResponse, app, 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_versions(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.apps.with_raw_response.list_versions(
+ "",
+ )
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_method_mark_failed(self, client: Mobilerun) -> None:
@@ -584,6 +627,48 @@ async def test_streaming_response_create_signed_upload_url(self, async_client: A
assert cast(Any, response.is_closed) is True
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_versions(self, async_client: AsyncMobilerun) -> None:
+ app = await async_client.apps.list_versions(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(AppListVersionsResponse, app, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_list_versions(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.apps.with_raw_response.list_versions(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ app = await response.parse()
+ assert_matches_type(AppListVersionsResponse, app, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_list_versions(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.apps.with_streaming_response.list_versions(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ app = await response.parse()
+ assert_matches_type(AppListVersionsResponse, app, 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_versions(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.apps.with_raw_response.list_versions(
+ "",
+ )
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_method_mark_failed(self, async_client: AsyncMobilerun) -> None:
diff --git a/tests/api_resources/test_hooks.py b/tests/api_resources/test_hooks.py
index 5d9a9d9..21548ab 100644
--- a/tests/api_resources/test_hooks.py
+++ b/tests/api_resources/test_hooks.py
@@ -11,6 +11,7 @@
from mobilerun_sdk import Mobilerun, AsyncMobilerun
from mobilerun_sdk.types import (
HookListResponse,
+ HookTestResponse,
HookUpdateResponse,
HookPerformResponse,
HookRetrieveResponse,
@@ -264,6 +265,57 @@ def test_streaming_response_subscribe(self, client: Mobilerun) -> None:
assert cast(Any, response.is_closed) is True
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_test(self, client: Mobilerun) -> None:
+ hook = client.hooks.test(
+ hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(HookTestResponse, hook, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_test_with_all_params(self, client: Mobilerun) -> None:
+ hook = client.hooks.test(
+ hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ event="event",
+ )
+ assert_matches_type(HookTestResponse, hook, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_test(self, client: Mobilerun) -> None:
+ response = client.hooks.with_raw_response.test(
+ hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ hook = response.parse()
+ assert_matches_type(HookTestResponse, hook, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_test(self, client: Mobilerun) -> None:
+ with client.hooks.with_streaming_response.test(
+ hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ hook = response.parse()
+ assert_matches_type(HookTestResponse, hook, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_test(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `hook_id` but received ''"):
+ client.hooks.with_raw_response.test(
+ hook_id="",
+ )
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_method_unsubscribe(self, client: Mobilerun) -> None:
@@ -551,6 +603,57 @@ async def test_streaming_response_subscribe(self, async_client: AsyncMobilerun)
assert cast(Any, response.is_closed) is True
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_test(self, async_client: AsyncMobilerun) -> None:
+ hook = await async_client.hooks.test(
+ hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(HookTestResponse, hook, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_test_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ hook = await async_client.hooks.test(
+ hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ event="event",
+ )
+ assert_matches_type(HookTestResponse, hook, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_test(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.hooks.with_raw_response.test(
+ hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ hook = await response.parse()
+ assert_matches_type(HookTestResponse, hook, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_test(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.hooks.with_streaming_response.test(
+ hook_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ hook = await response.parse()
+ assert_matches_type(HookTestResponse, hook, 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_test(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `hook_id` but received ''"):
+ await async_client.hooks.with_raw_response.test(
+ hook_id="",
+ )
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_method_unsubscribe(self, async_client: AsyncMobilerun) -> None:
diff --git a/tests/api_resources/test_proxies.py b/tests/api_resources/test_proxies.py
index 6b09e36..b96cc4d 100644
--- a/tests/api_resources/test_proxies.py
+++ b/tests/api_resources/test_proxies.py
@@ -13,6 +13,7 @@
ProxyListResponse,
ProxyCreateResponse,
ProxyDeleteResponse,
+ ProxyLookupResponse,
ProxyUpdateResponse,
ProxyRetrieveResponse,
)
@@ -352,6 +353,62 @@ def test_path_params_delete(self, client: Mobilerun) -> None:
"",
)
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_lookup(self, client: Mobilerun) -> None:
+ proxy = client.proxies.lookup(
+ socks5={
+ "host": "host",
+ "port": 1,
+ },
+ )
+ assert_matches_type(ProxyLookupResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_lookup_with_all_params(self, client: Mobilerun) -> None:
+ proxy = client.proxies.lookup(
+ socks5={
+ "host": "host",
+ "port": 1,
+ "password": "password",
+ "user": "user",
+ },
+ )
+ assert_matches_type(ProxyLookupResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_lookup(self, client: Mobilerun) -> None:
+ response = client.proxies.with_raw_response.lookup(
+ socks5={
+ "host": "host",
+ "port": 1,
+ },
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ proxy = response.parse()
+ assert_matches_type(ProxyLookupResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_lookup(self, client: Mobilerun) -> None:
+ with client.proxies.with_streaming_response.lookup(
+ socks5={
+ "host": "host",
+ "port": 1,
+ },
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ proxy = response.parse()
+ assert_matches_type(ProxyLookupResponse, proxy, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
class TestAsyncProxies:
parametrize = pytest.mark.parametrize(
@@ -686,3 +743,59 @@ async def test_path_params_delete(self, async_client: AsyncMobilerun) -> None:
await async_client.proxies.with_raw_response.delete(
"",
)
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_lookup(self, async_client: AsyncMobilerun) -> None:
+ proxy = await async_client.proxies.lookup(
+ socks5={
+ "host": "host",
+ "port": 1,
+ },
+ )
+ assert_matches_type(ProxyLookupResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_lookup_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ proxy = await async_client.proxies.lookup(
+ socks5={
+ "host": "host",
+ "port": 1,
+ "password": "password",
+ "user": "user",
+ },
+ )
+ assert_matches_type(ProxyLookupResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_lookup(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.proxies.with_raw_response.lookup(
+ socks5={
+ "host": "host",
+ "port": 1,
+ },
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ proxy = await response.parse()
+ assert_matches_type(ProxyLookupResponse, proxy, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_lookup(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.proxies.with_streaming_response.lookup(
+ socks5={
+ "host": "host",
+ "port": 1,
+ },
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ proxy = await response.parse()
+ assert_matches_type(ProxyLookupResponse, proxy, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_tasks.py b/tests/api_resources/test_tasks.py
index 05fcfdd..5dafda7 100644
--- a/tests/api_resources/test_tasks.py
+++ b/tests/api_resources/test_tasks.py
@@ -249,6 +249,7 @@ def test_method_run_with_all_params(self, client: Mobilerun) -> None:
task = client.tasks.run(
device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
task="x",
+ accessibility=True,
agent_id=0,
apps=["string"],
continue_on_failure=True,
@@ -317,6 +318,7 @@ def test_method_run_streamed_with_all_params(self, client: Mobilerun) -> None:
task = client.tasks.run_streamed(
device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
task="x",
+ accessibility=True,
agent_id=0,
apps=["string"],
continue_on_failure=True,
@@ -688,6 +690,7 @@ async def test_method_run_with_all_params(self, async_client: AsyncMobilerun) ->
task = await async_client.tasks.run(
device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
task="x",
+ accessibility=True,
agent_id=0,
apps=["string"],
continue_on_failure=True,
@@ -756,6 +759,7 @@ async def test_method_run_streamed_with_all_params(self, async_client: AsyncMobi
task = await async_client.tasks.run_streamed(
device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
task="x",
+ accessibility=True,
agent_id=0,
apps=["string"],
continue_on_failure=True,
diff --git a/tests/api_resources/workflows/__init__.py b/tests/api_resources/workflows/__init__.py
new file mode 100644
index 0000000..fd8019a
--- /dev/null
+++ b/tests/api_resources/workflows/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/workflows/actions/__init__.py b/tests/api_resources/workflows/actions/__init__.py
new file mode 100644
index 0000000..fd8019a
--- /dev/null
+++ b/tests/api_resources/workflows/actions/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/workflows/actions/test_services.py b/tests/api_resources/workflows/actions/test_services.py
new file mode 100644
index 0000000..442a3bd
--- /dev/null
+++ b/tests/api_resources/workflows/actions/test_services.py
@@ -0,0 +1,164 @@
+# 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.workflows.actions import ServiceListResponse, ServiceListMethodsResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestServices:
+ 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:
+ service = client.workflows.actions.services.list()
+ assert_matches_type(ServiceListResponse, service, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Mobilerun) -> None:
+ response = client.workflows.actions.services.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ service = response.parse()
+ assert_matches_type(ServiceListResponse, service, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Mobilerun) -> None:
+ with client.workflows.actions.services.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ service = response.parse()
+ assert_matches_type(ServiceListResponse, service, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_methods(self, client: Mobilerun) -> None:
+ service = client.workflows.actions.services.list_methods(
+ "x",
+ )
+ assert_matches_type(ServiceListMethodsResponse, service, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list_methods(self, client: Mobilerun) -> None:
+ response = client.workflows.actions.services.with_raw_response.list_methods(
+ "x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ service = response.parse()
+ assert_matches_type(ServiceListMethodsResponse, service, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list_methods(self, client: Mobilerun) -> None:
+ with client.workflows.actions.services.with_streaming_response.list_methods(
+ "x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ service = response.parse()
+ assert_matches_type(ServiceListMethodsResponse, service, 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_methods(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `service` but received ''"):
+ client.workflows.actions.services.with_raw_response.list_methods(
+ "",
+ )
+
+
+class TestAsyncServices:
+ 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:
+ service = await async_client.workflows.actions.services.list()
+ assert_matches_type(ServiceListResponse, service, 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.workflows.actions.services.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ service = await response.parse()
+ assert_matches_type(ServiceListResponse, service, 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.workflows.actions.services.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ service = await response.parse()
+ assert_matches_type(ServiceListResponse, service, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_methods(self, async_client: AsyncMobilerun) -> None:
+ service = await async_client.workflows.actions.services.list_methods(
+ "x",
+ )
+ assert_matches_type(ServiceListMethodsResponse, service, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_list_methods(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.workflows.actions.services.with_raw_response.list_methods(
+ "x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ service = await response.parse()
+ assert_matches_type(ServiceListMethodsResponse, service, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_list_methods(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.workflows.actions.services.with_streaming_response.list_methods(
+ "x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ service = await response.parse()
+ assert_matches_type(ServiceListMethodsResponse, service, 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_methods(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `service` but received ''"):
+ await async_client.workflows.actions.services.with_raw_response.list_methods(
+ "",
+ )
diff --git a/tests/api_resources/workflows/events/__init__.py b/tests/api_resources/workflows/events/__init__.py
new file mode 100644
index 0000000..fd8019a
--- /dev/null
+++ b/tests/api_resources/workflows/events/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/workflows/events/test_catalog.py b/tests/api_resources/workflows/events/test_catalog.py
new file mode 100644
index 0000000..df97792
--- /dev/null
+++ b/tests/api_resources/workflows/events/test_catalog.py
@@ -0,0 +1,201 @@
+# 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.workflows.events import (
+ CatalogListResponse,
+ CatalogRegisterResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestCatalog:
+ 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:
+ catalog = client.workflows.events.catalog.list()
+ assert_matches_type(CatalogListResponse, catalog, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Mobilerun) -> None:
+ catalog = client.workflows.events.catalog.list(
+ page=1,
+ page_size=1,
+ source="device",
+ )
+ assert_matches_type(CatalogListResponse, catalog, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Mobilerun) -> None:
+ response = client.workflows.events.catalog.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ catalog = response.parse()
+ assert_matches_type(CatalogListResponse, catalog, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Mobilerun) -> None:
+ with client.workflows.events.catalog.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ catalog = response.parse()
+ assert_matches_type(CatalogListResponse, catalog, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_register(self, client: Mobilerun) -> None:
+ catalog = client.workflows.events.catalog.register(
+ events=[
+ {
+ "event_type": "x",
+ "label": "x",
+ }
+ ],
+ )
+ assert_matches_type(CatalogRegisterResponse, catalog, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_register(self, client: Mobilerun) -> None:
+ response = client.workflows.events.catalog.with_raw_response.register(
+ events=[
+ {
+ "event_type": "x",
+ "label": "x",
+ }
+ ],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ catalog = response.parse()
+ assert_matches_type(CatalogRegisterResponse, catalog, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_register(self, client: Mobilerun) -> None:
+ with client.workflows.events.catalog.with_streaming_response.register(
+ events=[
+ {
+ "event_type": "x",
+ "label": "x",
+ }
+ ],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ catalog = response.parse()
+ assert_matches_type(CatalogRegisterResponse, catalog, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncCatalog:
+ 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:
+ catalog = await async_client.workflows.events.catalog.list()
+ assert_matches_type(CatalogListResponse, catalog, 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:
+ catalog = await async_client.workflows.events.catalog.list(
+ page=1,
+ page_size=1,
+ source="device",
+ )
+ assert_matches_type(CatalogListResponse, catalog, 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.workflows.events.catalog.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ catalog = await response.parse()
+ assert_matches_type(CatalogListResponse, catalog, 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.workflows.events.catalog.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ catalog = await response.parse()
+ assert_matches_type(CatalogListResponse, catalog, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_register(self, async_client: AsyncMobilerun) -> None:
+ catalog = await async_client.workflows.events.catalog.register(
+ events=[
+ {
+ "event_type": "x",
+ "label": "x",
+ }
+ ],
+ )
+ assert_matches_type(CatalogRegisterResponse, catalog, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_register(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.workflows.events.catalog.with_raw_response.register(
+ events=[
+ {
+ "event_type": "x",
+ "label": "x",
+ }
+ ],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ catalog = await response.parse()
+ assert_matches_type(CatalogRegisterResponse, catalog, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_register(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.workflows.events.catalog.with_streaming_response.register(
+ events=[
+ {
+ "event_type": "x",
+ "label": "x",
+ }
+ ],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ catalog = await response.parse()
+ assert_matches_type(CatalogRegisterResponse, catalog, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/workflows/flows/__init__.py b/tests/api_resources/workflows/flows/__init__.py
new file mode 100644
index 0000000..fd8019a
--- /dev/null
+++ b/tests/api_resources/workflows/flows/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/workflows/flows/test_actions.py b/tests/api_resources/workflows/flows/test_actions.py
new file mode 100644
index 0000000..0343316
--- /dev/null
+++ b/tests/api_resources/workflows/flows/test_actions.py
@@ -0,0 +1,499 @@
+# 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.workflows.flows import (
+ ActionAddResponse,
+ ActionListResponse,
+ ActionRemoveResponse,
+ ActionReplaceResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestActions:
+ 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:
+ action = client.workflows.flows.actions.list(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ActionListResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Mobilerun) -> None:
+ response = client.workflows.flows.actions.with_raw_response.list(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = response.parse()
+ assert_matches_type(ActionListResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Mobilerun) -> None:
+ with client.workflows.flows.actions.with_streaming_response.list(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = response.parse()
+ assert_matches_type(ActionListResponse, action, 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 `flow_id` but received ''"):
+ client.workflows.flows.actions.with_raw_response.list(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_add(self, client: Mobilerun) -> None:
+ action = client.workflows.flows.actions.add(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ position=0,
+ )
+ assert_matches_type(ActionAddResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_add_with_all_params(self, client: Mobilerun) -> None:
+ action = client.workflows.flows.actions.add(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ position=0,
+ children=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ "continue_on_error": True,
+ "device_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "name_override": "x",
+ "overrides": {"params": {"foo": "bar"}},
+ }
+ ],
+ continue_on_error=True,
+ device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ name_override="x",
+ overrides={"params": {"foo": "bar"}},
+ parent_flow_action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ActionAddResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_add(self, client: Mobilerun) -> None:
+ response = client.workflows.flows.actions.with_raw_response.add(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ position=0,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = response.parse()
+ assert_matches_type(ActionAddResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_add(self, client: Mobilerun) -> None:
+ with client.workflows.flows.actions.with_streaming_response.add(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ position=0,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = response.parse()
+ assert_matches_type(ActionAddResponse, action, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_add(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `flow_id` but received ''"):
+ client.workflows.flows.actions.with_raw_response.add(
+ flow_id="",
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ position=0,
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_remove(self, client: Mobilerun) -> None:
+ action = client.workflows.flows.actions.remove(
+ flow_action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ActionRemoveResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_remove(self, client: Mobilerun) -> None:
+ response = client.workflows.flows.actions.with_raw_response.remove(
+ flow_action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = response.parse()
+ assert_matches_type(ActionRemoveResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_remove(self, client: Mobilerun) -> None:
+ with client.workflows.flows.actions.with_streaming_response.remove(
+ flow_action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = response.parse()
+ assert_matches_type(ActionRemoveResponse, action, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_remove(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `flow_id` but received ''"):
+ client.workflows.flows.actions.with_raw_response.remove(
+ flow_action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ flow_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `flow_action_id` but received ''"):
+ client.workflows.flows.actions.with_raw_response.remove(
+ flow_action_id="",
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_replace(self, client: Mobilerun) -> None:
+ action = client.workflows.flows.actions.replace(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ }
+ ],
+ )
+ assert_matches_type(ActionReplaceResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_replace(self, client: Mobilerun) -> None:
+ response = client.workflows.flows.actions.with_raw_response.replace(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ }
+ ],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = response.parse()
+ assert_matches_type(ActionReplaceResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_replace(self, client: Mobilerun) -> None:
+ with client.workflows.flows.actions.with_streaming_response.replace(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ }
+ ],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = response.parse()
+ assert_matches_type(ActionReplaceResponse, action, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_replace(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `flow_id` but received ''"):
+ client.workflows.flows.actions.with_raw_response.replace(
+ flow_id="",
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ }
+ ],
+ )
+
+
+class TestAsyncActions:
+ 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:
+ action = await async_client.workflows.flows.actions.list(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ActionListResponse, action, 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.workflows.flows.actions.with_raw_response.list(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = await response.parse()
+ assert_matches_type(ActionListResponse, action, 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.workflows.flows.actions.with_streaming_response.list(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = await response.parse()
+ assert_matches_type(ActionListResponse, action, 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 `flow_id` but received ''"):
+ await async_client.workflows.flows.actions.with_raw_response.list(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_add(self, async_client: AsyncMobilerun) -> None:
+ action = await async_client.workflows.flows.actions.add(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ position=0,
+ )
+ assert_matches_type(ActionAddResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_add_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ action = await async_client.workflows.flows.actions.add(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ position=0,
+ children=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ "continue_on_error": True,
+ "device_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "name_override": "x",
+ "overrides": {"params": {"foo": "bar"}},
+ }
+ ],
+ continue_on_error=True,
+ device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ name_override="x",
+ overrides={"params": {"foo": "bar"}},
+ parent_flow_action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ActionAddResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_add(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.workflows.flows.actions.with_raw_response.add(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ position=0,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = await response.parse()
+ assert_matches_type(ActionAddResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_add(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.workflows.flows.actions.with_streaming_response.add(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ position=0,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = await response.parse()
+ assert_matches_type(ActionAddResponse, action, 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_add(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `flow_id` but received ''"):
+ await async_client.workflows.flows.actions.with_raw_response.add(
+ flow_id="",
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ position=0,
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_remove(self, async_client: AsyncMobilerun) -> None:
+ action = await async_client.workflows.flows.actions.remove(
+ flow_action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ActionRemoveResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_remove(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.workflows.flows.actions.with_raw_response.remove(
+ flow_action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = await response.parse()
+ assert_matches_type(ActionRemoveResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_remove(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.workflows.flows.actions.with_streaming_response.remove(
+ flow_action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = await response.parse()
+ assert_matches_type(ActionRemoveResponse, action, 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_remove(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `flow_id` but received ''"):
+ await async_client.workflows.flows.actions.with_raw_response.remove(
+ flow_action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ flow_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `flow_action_id` but received ''"):
+ await async_client.workflows.flows.actions.with_raw_response.remove(
+ flow_action_id="",
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_replace(self, async_client: AsyncMobilerun) -> None:
+ action = await async_client.workflows.flows.actions.replace(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ }
+ ],
+ )
+ assert_matches_type(ActionReplaceResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_replace(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.workflows.flows.actions.with_raw_response.replace(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ }
+ ],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = await response.parse()
+ assert_matches_type(ActionReplaceResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_replace(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.workflows.flows.actions.with_streaming_response.replace(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ }
+ ],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = await response.parse()
+ assert_matches_type(ActionReplaceResponse, action, 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_replace(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `flow_id` but received ''"):
+ await async_client.workflows.flows.actions.with_raw_response.replace(
+ flow_id="",
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ }
+ ],
+ )
diff --git a/tests/api_resources/workflows/test_action_catalog.py b/tests/api_resources/workflows/test_action_catalog.py
new file mode 100644
index 0000000..9f228db
--- /dev/null
+++ b/tests/api_resources/workflows/test_action_catalog.py
@@ -0,0 +1,187 @@
+# 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.workflows import (
+ ActionCatalogListResponse,
+ ActionCatalogRetrieveResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestActionCatalog:
+ 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_retrieve(self, client: Mobilerun) -> None:
+ action_catalog = client.workflows.action_catalog.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ActionCatalogRetrieveResponse, action_catalog, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Mobilerun) -> None:
+ response = client.workflows.action_catalog.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action_catalog = response.parse()
+ assert_matches_type(ActionCatalogRetrieveResponse, action_catalog, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Mobilerun) -> None:
+ with client.workflows.action_catalog.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action_catalog = response.parse()
+ assert_matches_type(ActionCatalogRetrieveResponse, action_catalog, 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 `catalog_entry_id` but received ''"):
+ client.workflows.action_catalog.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Mobilerun) -> None:
+ action_catalog = client.workflows.action_catalog.list()
+ assert_matches_type(ActionCatalogListResponse, action_catalog, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Mobilerun) -> None:
+ action_catalog = client.workflows.action_catalog.list(
+ page=1,
+ page_size=1,
+ service="tasks_api",
+ )
+ assert_matches_type(ActionCatalogListResponse, action_catalog, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Mobilerun) -> None:
+ response = client.workflows.action_catalog.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action_catalog = response.parse()
+ assert_matches_type(ActionCatalogListResponse, action_catalog, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Mobilerun) -> None:
+ with client.workflows.action_catalog.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action_catalog = response.parse()
+ assert_matches_type(ActionCatalogListResponse, action_catalog, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncActionCatalog:
+ 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_retrieve(self, async_client: AsyncMobilerun) -> None:
+ action_catalog = await async_client.workflows.action_catalog.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ActionCatalogRetrieveResponse, action_catalog, 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.workflows.action_catalog.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action_catalog = await response.parse()
+ assert_matches_type(ActionCatalogRetrieveResponse, action_catalog, 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.workflows.action_catalog.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action_catalog = await response.parse()
+ assert_matches_type(ActionCatalogRetrieveResponse, action_catalog, 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 `catalog_entry_id` but received ''"):
+ await async_client.workflows.action_catalog.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncMobilerun) -> None:
+ action_catalog = await async_client.workflows.action_catalog.list()
+ assert_matches_type(ActionCatalogListResponse, action_catalog, 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:
+ action_catalog = await async_client.workflows.action_catalog.list(
+ page=1,
+ page_size=1,
+ service="tasks_api",
+ )
+ assert_matches_type(ActionCatalogListResponse, action_catalog, 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.workflows.action_catalog.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action_catalog = await response.parse()
+ assert_matches_type(ActionCatalogListResponse, action_catalog, 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.workflows.action_catalog.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action_catalog = await response.parse()
+ assert_matches_type(ActionCatalogListResponse, action_catalog, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/workflows/test_actions.py b/tests/api_resources/workflows/test_actions.py
new file mode 100644
index 0000000..9533759
--- /dev/null
+++ b/tests/api_resources/workflows/test_actions.py
@@ -0,0 +1,482 @@
+# 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.workflows import (
+ ActionListResponse,
+ ActionCreateResponse,
+ ActionDeleteResponse,
+ ActionUpdateResponse,
+ ActionRetrieveResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestActions:
+ 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:
+ action = client.workflows.actions.create(
+ catalog_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ name="x",
+ )
+ assert_matches_type(ActionCreateResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params(self, client: Mobilerun) -> None:
+ action = client.workflows.actions.create(
+ catalog_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ name="x",
+ description="description",
+ params={"foo": "bar"},
+ )
+ assert_matches_type(ActionCreateResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Mobilerun) -> None:
+ response = client.workflows.actions.with_raw_response.create(
+ catalog_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ name="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = response.parse()
+ assert_matches_type(ActionCreateResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Mobilerun) -> None:
+ with client.workflows.actions.with_streaming_response.create(
+ catalog_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ name="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = response.parse()
+ assert_matches_type(ActionCreateResponse, action, 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:
+ action = client.workflows.actions.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ActionRetrieveResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Mobilerun) -> None:
+ response = client.workflows.actions.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = response.parse()
+ assert_matches_type(ActionRetrieveResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Mobilerun) -> None:
+ with client.workflows.actions.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = response.parse()
+ assert_matches_type(ActionRetrieveResponse, action, 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 `action_id` but received ''"):
+ client.workflows.actions.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update(self, client: Mobilerun) -> None:
+ action = client.workflows.actions.update(
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ActionUpdateResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update_with_all_params(self, client: Mobilerun) -> None:
+ action = client.workflows.actions.update(
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ description="description",
+ name="x",
+ params={"foo": "bar"},
+ )
+ assert_matches_type(ActionUpdateResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_update(self, client: Mobilerun) -> None:
+ response = client.workflows.actions.with_raw_response.update(
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = response.parse()
+ assert_matches_type(ActionUpdateResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_update(self, client: Mobilerun) -> None:
+ with client.workflows.actions.with_streaming_response.update(
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = response.parse()
+ assert_matches_type(ActionUpdateResponse, action, 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 `action_id` but received ''"):
+ client.workflows.actions.with_raw_response.update(
+ action_id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Mobilerun) -> None:
+ action = client.workflows.actions.list()
+ assert_matches_type(ActionListResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Mobilerun) -> None:
+ action = client.workflows.actions.list(
+ order_by="name",
+ order_by_direction="asc",
+ page=1,
+ page_size=1,
+ search="search",
+ service="tasks_api",
+ )
+ assert_matches_type(ActionListResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Mobilerun) -> None:
+ response = client.workflows.actions.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = response.parse()
+ assert_matches_type(ActionListResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Mobilerun) -> None:
+ with client.workflows.actions.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = response.parse()
+ assert_matches_type(ActionListResponse, action, 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:
+ action = client.workflows.actions.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ActionDeleteResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_delete(self, client: Mobilerun) -> None:
+ response = client.workflows.actions.with_raw_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = response.parse()
+ assert_matches_type(ActionDeleteResponse, action, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_delete(self, client: Mobilerun) -> None:
+ with client.workflows.actions.with_streaming_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = response.parse()
+ assert_matches_type(ActionDeleteResponse, action, 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 `action_id` but received ''"):
+ client.workflows.actions.with_raw_response.delete(
+ "",
+ )
+
+
+class TestAsyncActions:
+ 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:
+ action = await async_client.workflows.actions.create(
+ catalog_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ name="x",
+ )
+ assert_matches_type(ActionCreateResponse, action, 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:
+ action = await async_client.workflows.actions.create(
+ catalog_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ name="x",
+ description="description",
+ params={"foo": "bar"},
+ )
+ assert_matches_type(ActionCreateResponse, action, 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.workflows.actions.with_raw_response.create(
+ catalog_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ name="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = await response.parse()
+ assert_matches_type(ActionCreateResponse, action, 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.workflows.actions.with_streaming_response.create(
+ catalog_entry_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ name="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = await response.parse()
+ assert_matches_type(ActionCreateResponse, action, 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:
+ action = await async_client.workflows.actions.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ActionRetrieveResponse, action, 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.workflows.actions.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = await response.parse()
+ assert_matches_type(ActionRetrieveResponse, action, 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.workflows.actions.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = await response.parse()
+ assert_matches_type(ActionRetrieveResponse, action, 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 `action_id` but received ''"):
+ await async_client.workflows.actions.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_update(self, async_client: AsyncMobilerun) -> None:
+ action = await async_client.workflows.actions.update(
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ActionUpdateResponse, action, 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:
+ action = await async_client.workflows.actions.update(
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ description="description",
+ name="x",
+ params={"foo": "bar"},
+ )
+ assert_matches_type(ActionUpdateResponse, action, 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.workflows.actions.with_raw_response.update(
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = await response.parse()
+ assert_matches_type(ActionUpdateResponse, action, 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.workflows.actions.with_streaming_response.update(
+ action_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = await response.parse()
+ assert_matches_type(ActionUpdateResponse, action, 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 `action_id` but received ''"):
+ await async_client.workflows.actions.with_raw_response.update(
+ action_id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncMobilerun) -> None:
+ action = await async_client.workflows.actions.list()
+ assert_matches_type(ActionListResponse, action, 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:
+ action = await async_client.workflows.actions.list(
+ order_by="name",
+ order_by_direction="asc",
+ page=1,
+ page_size=1,
+ search="search",
+ service="tasks_api",
+ )
+ assert_matches_type(ActionListResponse, action, 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.workflows.actions.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = await response.parse()
+ assert_matches_type(ActionListResponse, action, 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.workflows.actions.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = await response.parse()
+ assert_matches_type(ActionListResponse, action, 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:
+ action = await async_client.workflows.actions.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ActionDeleteResponse, action, 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.workflows.actions.with_raw_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ action = await response.parse()
+ assert_matches_type(ActionDeleteResponse, action, 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.workflows.actions.with_streaming_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ action = await response.parse()
+ assert_matches_type(ActionDeleteResponse, action, 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 `action_id` but received ''"):
+ await async_client.workflows.actions.with_raw_response.delete(
+ "",
+ )
diff --git a/tests/api_resources/workflows/test_events.py b/tests/api_resources/workflows/test_events.py
new file mode 100644
index 0000000..8ca70fa
--- /dev/null
+++ b/tests/api_resources/workflows/test_events.py
@@ -0,0 +1,203 @@
+# 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.workflows import (
+ EventDryRunResponse,
+ EventIngestResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestEvents:
+ 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_dry_run(self, client: Mobilerun) -> None:
+ event = client.workflows.events.dry_run(
+ event_type="x",
+ )
+ assert_matches_type(EventDryRunResponse, event, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_dry_run_with_all_params(self, client: Mobilerun) -> None:
+ event = client.workflows.events.dry_run(
+ event_type="x",
+ device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ payload={"foo": "bar"},
+ )
+ assert_matches_type(EventDryRunResponse, event, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_dry_run(self, client: Mobilerun) -> None:
+ response = client.workflows.events.with_raw_response.dry_run(
+ event_type="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ event = response.parse()
+ assert_matches_type(EventDryRunResponse, event, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_dry_run(self, client: Mobilerun) -> None:
+ with client.workflows.events.with_streaming_response.dry_run(
+ event_type="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ event = response.parse()
+ assert_matches_type(EventDryRunResponse, event, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_ingest(self, client: Mobilerun) -> None:
+ event = client.workflows.events.ingest(
+ event_type="x",
+ )
+ assert_matches_type(EventIngestResponse, event, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_ingest_with_all_params(self, client: Mobilerun) -> None:
+ event = client.workflows.events.ingest(
+ event_type="x",
+ device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ payload={"foo": "bar"},
+ )
+ assert_matches_type(EventIngestResponse, event, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_ingest(self, client: Mobilerun) -> None:
+ response = client.workflows.events.with_raw_response.ingest(
+ event_type="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ event = response.parse()
+ assert_matches_type(EventIngestResponse, event, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_ingest(self, client: Mobilerun) -> None:
+ with client.workflows.events.with_streaming_response.ingest(
+ event_type="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ event = response.parse()
+ assert_matches_type(EventIngestResponse, event, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncEvents:
+ 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_dry_run(self, async_client: AsyncMobilerun) -> None:
+ event = await async_client.workflows.events.dry_run(
+ event_type="x",
+ )
+ assert_matches_type(EventDryRunResponse, event, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_dry_run_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ event = await async_client.workflows.events.dry_run(
+ event_type="x",
+ device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ payload={"foo": "bar"},
+ )
+ assert_matches_type(EventDryRunResponse, event, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_dry_run(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.workflows.events.with_raw_response.dry_run(
+ event_type="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ event = await response.parse()
+ assert_matches_type(EventDryRunResponse, event, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_dry_run(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.workflows.events.with_streaming_response.dry_run(
+ event_type="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ event = await response.parse()
+ assert_matches_type(EventDryRunResponse, event, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_ingest(self, async_client: AsyncMobilerun) -> None:
+ event = await async_client.workflows.events.ingest(
+ event_type="x",
+ )
+ assert_matches_type(EventIngestResponse, event, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_ingest_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ event = await async_client.workflows.events.ingest(
+ event_type="x",
+ device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ payload={"foo": "bar"},
+ )
+ assert_matches_type(EventIngestResponse, event, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_ingest(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.workflows.events.with_raw_response.ingest(
+ event_type="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ event = await response.parse()
+ assert_matches_type(EventIngestResponse, event, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_ingest(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.workflows.events.with_streaming_response.ingest(
+ event_type="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ event = await response.parse()
+ assert_matches_type(EventIngestResponse, event, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/workflows/test_executions.py b/tests/api_resources/workflows/test_executions.py
new file mode 100644
index 0000000..891bd9b
--- /dev/null
+++ b/tests/api_resources/workflows/test_executions.py
@@ -0,0 +1,280 @@
+# 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.workflows import (
+ ExecutionListResponse,
+ ExecutionRetrieveResponse,
+ ExecutionGetMetricsResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestExecutions:
+ 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_retrieve(self, client: Mobilerun) -> None:
+ execution = client.workflows.executions.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ExecutionRetrieveResponse, execution, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Mobilerun) -> None:
+ response = client.workflows.executions.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ execution = response.parse()
+ assert_matches_type(ExecutionRetrieveResponse, execution, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Mobilerun) -> None:
+ with client.workflows.executions.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ execution = response.parse()
+ assert_matches_type(ExecutionRetrieveResponse, execution, 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 `execution_id` but received ''"):
+ client.workflows.executions.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Mobilerun) -> None:
+ execution = client.workflows.executions.list()
+ assert_matches_type(ExecutionListResponse, execution, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Mobilerun) -> None:
+ execution = client.workflows.executions.list(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ from_="from",
+ order_by="startedAt",
+ order_by_direction="asc",
+ page=1,
+ page_size=1,
+ search="search",
+ status="pending",
+ to="to",
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ExecutionListResponse, execution, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Mobilerun) -> None:
+ response = client.workflows.executions.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ execution = response.parse()
+ assert_matches_type(ExecutionListResponse, execution, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Mobilerun) -> None:
+ with client.workflows.executions.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ execution = response.parse()
+ assert_matches_type(ExecutionListResponse, execution, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_get_metrics(self, client: Mobilerun) -> None:
+ execution = client.workflows.executions.get_metrics()
+ assert_matches_type(ExecutionGetMetricsResponse, execution, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_get_metrics_with_all_params(self, client: Mobilerun) -> None:
+ execution = client.workflows.executions.get_metrics(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ from_="from",
+ to="to",
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ExecutionGetMetricsResponse, execution, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_get_metrics(self, client: Mobilerun) -> None:
+ response = client.workflows.executions.with_raw_response.get_metrics()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ execution = response.parse()
+ assert_matches_type(ExecutionGetMetricsResponse, execution, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_get_metrics(self, client: Mobilerun) -> None:
+ with client.workflows.executions.with_streaming_response.get_metrics() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ execution = response.parse()
+ assert_matches_type(ExecutionGetMetricsResponse, execution, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncExecutions:
+ 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_retrieve(self, async_client: AsyncMobilerun) -> None:
+ execution = await async_client.workflows.executions.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ExecutionRetrieveResponse, execution, 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.workflows.executions.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ execution = await response.parse()
+ assert_matches_type(ExecutionRetrieveResponse, execution, 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.workflows.executions.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ execution = await response.parse()
+ assert_matches_type(ExecutionRetrieveResponse, execution, 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 `execution_id` but received ''"):
+ await async_client.workflows.executions.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncMobilerun) -> None:
+ execution = await async_client.workflows.executions.list()
+ assert_matches_type(ExecutionListResponse, execution, 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:
+ execution = await async_client.workflows.executions.list(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ from_="from",
+ order_by="startedAt",
+ order_by_direction="asc",
+ page=1,
+ page_size=1,
+ search="search",
+ status="pending",
+ to="to",
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ExecutionListResponse, execution, 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.workflows.executions.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ execution = await response.parse()
+ assert_matches_type(ExecutionListResponse, execution, 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.workflows.executions.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ execution = await response.parse()
+ assert_matches_type(ExecutionListResponse, execution, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_get_metrics(self, async_client: AsyncMobilerun) -> None:
+ execution = await async_client.workflows.executions.get_metrics()
+ assert_matches_type(ExecutionGetMetricsResponse, execution, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_get_metrics_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ execution = await async_client.workflows.executions.get_metrics(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ from_="from",
+ to="to",
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ExecutionGetMetricsResponse, execution, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_get_metrics(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.workflows.executions.with_raw_response.get_metrics()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ execution = await response.parse()
+ assert_matches_type(ExecutionGetMetricsResponse, execution, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_get_metrics(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.workflows.executions.with_streaming_response.get_metrics() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ execution = await response.parse()
+ assert_matches_type(ExecutionGetMetricsResponse, execution, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/workflows/test_flows.py b/tests/api_resources/workflows/test_flows.py
new file mode 100644
index 0000000..d7640f1
--- /dev/null
+++ b/tests/api_resources/workflows/test_flows.py
@@ -0,0 +1,760 @@
+# 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.workflows import (
+ FlowListResponse,
+ FlowCloneResponse,
+ FlowCreateResponse,
+ FlowDeleteResponse,
+ FlowUpdateResponse,
+ FlowUnblockResponse,
+ FlowRetrieveResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestFlows:
+ 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:
+ flow = client.workflows.flows.create(
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ }
+ ],
+ name="x",
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowCreateResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params(self, client: Mobilerun) -> None:
+ flow = client.workflows.flows.create(
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ "children": [
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ "continue_on_error": True,
+ "device_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "name_override": "x",
+ "overrides": {"params": {"foo": "bar"}},
+ }
+ ],
+ "continue_on_error": True,
+ "device_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "name_override": "x",
+ "overrides": {"params": {"foo": "bar"}},
+ }
+ ],
+ name="x",
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ cooldown_scope="flow",
+ cooldown_seconds=0,
+ description="description",
+ enabled=True,
+ )
+ assert_matches_type(FlowCreateResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Mobilerun) -> None:
+ response = client.workflows.flows.with_raw_response.create(
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ }
+ ],
+ name="x",
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = response.parse()
+ assert_matches_type(FlowCreateResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Mobilerun) -> None:
+ with client.workflows.flows.with_streaming_response.create(
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ }
+ ],
+ name="x",
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = response.parse()
+ assert_matches_type(FlowCreateResponse, flow, 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:
+ flow = client.workflows.flows.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowRetrieveResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Mobilerun) -> None:
+ response = client.workflows.flows.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = response.parse()
+ assert_matches_type(FlowRetrieveResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Mobilerun) -> None:
+ with client.workflows.flows.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = response.parse()
+ assert_matches_type(FlowRetrieveResponse, flow, 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 `flow_id` but received ''"):
+ client.workflows.flows.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update(self, client: Mobilerun) -> None:
+ flow = client.workflows.flows.update(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowUpdateResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update_with_all_params(self, client: Mobilerun) -> None:
+ flow = client.workflows.flows.update(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ cooldown_scope="flow",
+ cooldown_seconds=0,
+ description="description",
+ enabled=True,
+ name="x",
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowUpdateResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_update(self, client: Mobilerun) -> None:
+ response = client.workflows.flows.with_raw_response.update(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = response.parse()
+ assert_matches_type(FlowUpdateResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_update(self, client: Mobilerun) -> None:
+ with client.workflows.flows.with_streaming_response.update(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = response.parse()
+ assert_matches_type(FlowUpdateResponse, flow, 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 `flow_id` but received ''"):
+ client.workflows.flows.with_raw_response.update(
+ flow_id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Mobilerun) -> None:
+ flow = client.workflows.flows.list()
+ assert_matches_type(FlowListResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Mobilerun) -> None:
+ flow = client.workflows.flows.list(
+ enabled=True,
+ order_by="name",
+ order_by_direction="asc",
+ page=1,
+ page_size=1,
+ search="search",
+ status=["healthy"],
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowListResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Mobilerun) -> None:
+ response = client.workflows.flows.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = response.parse()
+ assert_matches_type(FlowListResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Mobilerun) -> None:
+ with client.workflows.flows.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = response.parse()
+ assert_matches_type(FlowListResponse, flow, 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:
+ flow = client.workflows.flows.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowDeleteResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_delete(self, client: Mobilerun) -> None:
+ response = client.workflows.flows.with_raw_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = response.parse()
+ assert_matches_type(FlowDeleteResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_delete(self, client: Mobilerun) -> None:
+ with client.workflows.flows.with_streaming_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = response.parse()
+ assert_matches_type(FlowDeleteResponse, flow, 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 `flow_id` but received ''"):
+ client.workflows.flows.with_raw_response.delete(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_clone(self, client: Mobilerun) -> None:
+ flow = client.workflows.flows.clone(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowCloneResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_clone_with_all_params(self, client: Mobilerun) -> None:
+ flow = client.workflows.flows.clone(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ name="x",
+ )
+ assert_matches_type(FlowCloneResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_clone(self, client: Mobilerun) -> None:
+ response = client.workflows.flows.with_raw_response.clone(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = response.parse()
+ assert_matches_type(FlowCloneResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_clone(self, client: Mobilerun) -> None:
+ with client.workflows.flows.with_streaming_response.clone(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = response.parse()
+ assert_matches_type(FlowCloneResponse, flow, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_clone(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `flow_id` but received ''"):
+ client.workflows.flows.with_raw_response.clone(
+ flow_id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_unblock(self, client: Mobilerun) -> None:
+ flow = client.workflows.flows.unblock(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowUnblockResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_unblock(self, client: Mobilerun) -> None:
+ response = client.workflows.flows.with_raw_response.unblock(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = response.parse()
+ assert_matches_type(FlowUnblockResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_unblock(self, client: Mobilerun) -> None:
+ with client.workflows.flows.with_streaming_response.unblock(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = response.parse()
+ assert_matches_type(FlowUnblockResponse, flow, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_unblock(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `flow_id` but received ''"):
+ client.workflows.flows.with_raw_response.unblock(
+ "",
+ )
+
+
+class TestAsyncFlows:
+ 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:
+ flow = await async_client.workflows.flows.create(
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ }
+ ],
+ name="x",
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowCreateResponse, flow, 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:
+ flow = await async_client.workflows.flows.create(
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ "children": [
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ "continue_on_error": True,
+ "device_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "name_override": "x",
+ "overrides": {"params": {"foo": "bar"}},
+ }
+ ],
+ "continue_on_error": True,
+ "device_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "name_override": "x",
+ "overrides": {"params": {"foo": "bar"}},
+ }
+ ],
+ name="x",
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ cooldown_scope="flow",
+ cooldown_seconds=0,
+ description="description",
+ enabled=True,
+ )
+ assert_matches_type(FlowCreateResponse, flow, 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.workflows.flows.with_raw_response.create(
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ }
+ ],
+ name="x",
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = await response.parse()
+ assert_matches_type(FlowCreateResponse, flow, 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.workflows.flows.with_streaming_response.create(
+ actions=[
+ {
+ "action_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ "position": 0,
+ }
+ ],
+ name="x",
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = await response.parse()
+ assert_matches_type(FlowCreateResponse, 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_retrieve(self, async_client: AsyncMobilerun) -> None:
+ flow = await async_client.workflows.flows.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowRetrieveResponse, flow, 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.workflows.flows.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = await response.parse()
+ assert_matches_type(FlowRetrieveResponse, flow, 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.workflows.flows.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = await response.parse()
+ assert_matches_type(FlowRetrieveResponse, flow, 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 `flow_id` but received ''"):
+ await async_client.workflows.flows.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_update(self, async_client: AsyncMobilerun) -> None:
+ flow = await async_client.workflows.flows.update(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowUpdateResponse, flow, 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:
+ flow = await async_client.workflows.flows.update(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ cooldown_scope="flow",
+ cooldown_seconds=0,
+ description="description",
+ enabled=True,
+ name="x",
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowUpdateResponse, flow, 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.workflows.flows.with_raw_response.update(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = await response.parse()
+ assert_matches_type(FlowUpdateResponse, flow, 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.workflows.flows.with_streaming_response.update(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = await response.parse()
+ assert_matches_type(FlowUpdateResponse, flow, 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 `flow_id` but received ''"):
+ await async_client.workflows.flows.with_raw_response.update(
+ flow_id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncMobilerun) -> None:
+ flow = await async_client.workflows.flows.list()
+ assert_matches_type(FlowListResponse, flow, 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:
+ flow = await async_client.workflows.flows.list(
+ enabled=True,
+ order_by="name",
+ order_by_direction="asc",
+ page=1,
+ page_size=1,
+ search="search",
+ status=["healthy"],
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowListResponse, flow, 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.workflows.flows.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = await response.parse()
+ assert_matches_type(FlowListResponse, flow, 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.workflows.flows.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = await response.parse()
+ assert_matches_type(FlowListResponse, 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_delete(self, async_client: AsyncMobilerun) -> None:
+ flow = await async_client.workflows.flows.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowDeleteResponse, flow, 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.workflows.flows.with_raw_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = await response.parse()
+ assert_matches_type(FlowDeleteResponse, flow, 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.workflows.flows.with_streaming_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = await response.parse()
+ assert_matches_type(FlowDeleteResponse, flow, 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 `flow_id` but received ''"):
+ await async_client.workflows.flows.with_raw_response.delete(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_clone(self, async_client: AsyncMobilerun) -> None:
+ flow = await async_client.workflows.flows.clone(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowCloneResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_clone_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ flow = await async_client.workflows.flows.clone(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ name="x",
+ )
+ assert_matches_type(FlowCloneResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_clone(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.workflows.flows.with_raw_response.clone(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = await response.parse()
+ assert_matches_type(FlowCloneResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_clone(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.workflows.flows.with_streaming_response.clone(
+ flow_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = await response.parse()
+ assert_matches_type(FlowCloneResponse, flow, 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_clone(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `flow_id` but received ''"):
+ await async_client.workflows.flows.with_raw_response.clone(
+ flow_id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_unblock(self, async_client: AsyncMobilerun) -> None:
+ flow = await async_client.workflows.flows.unblock(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(FlowUnblockResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_unblock(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.workflows.flows.with_raw_response.unblock(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ flow = await response.parse()
+ assert_matches_type(FlowUnblockResponse, flow, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_unblock(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.workflows.flows.with_streaming_response.unblock(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ flow = await response.parse()
+ assert_matches_type(FlowUnblockResponse, flow, 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_unblock(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `flow_id` but received ''"):
+ await async_client.workflows.flows.with_raw_response.unblock(
+ "",
+ )
diff --git a/tests/api_resources/workflows/test_secrets.py b/tests/api_resources/workflows/test_secrets.py
new file mode 100644
index 0000000..6d98cae
--- /dev/null
+++ b/tests/api_resources/workflows/test_secrets.py
@@ -0,0 +1,262 @@
+# 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.workflows import (
+ SecretListResponse,
+ SecretCreateResponse,
+ SecretDeleteResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestSecrets:
+ 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:
+ secret = client.workflows.secrets.create(
+ name="name",
+ value="x",
+ )
+ assert_matches_type(SecretCreateResponse, secret, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params(self, client: Mobilerun) -> None:
+ secret = client.workflows.secrets.create(
+ name="name",
+ value="x",
+ description="description",
+ )
+ assert_matches_type(SecretCreateResponse, secret, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Mobilerun) -> None:
+ response = client.workflows.secrets.with_raw_response.create(
+ name="name",
+ value="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ secret = response.parse()
+ assert_matches_type(SecretCreateResponse, secret, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Mobilerun) -> None:
+ with client.workflows.secrets.with_streaming_response.create(
+ name="name",
+ value="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ secret = response.parse()
+ assert_matches_type(SecretCreateResponse, secret, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Mobilerun) -> None:
+ secret = client.workflows.secrets.list()
+ assert_matches_type(SecretListResponse, secret, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Mobilerun) -> None:
+ response = client.workflows.secrets.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ secret = response.parse()
+ assert_matches_type(SecretListResponse, secret, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Mobilerun) -> None:
+ with client.workflows.secrets.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ secret = response.parse()
+ assert_matches_type(SecretListResponse, secret, 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:
+ secret = client.workflows.secrets.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(SecretDeleteResponse, secret, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_delete(self, client: Mobilerun) -> None:
+ response = client.workflows.secrets.with_raw_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ secret = response.parse()
+ assert_matches_type(SecretDeleteResponse, secret, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_delete(self, client: Mobilerun) -> None:
+ with client.workflows.secrets.with_streaming_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ secret = response.parse()
+ assert_matches_type(SecretDeleteResponse, secret, 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 `secret_id` but received ''"):
+ client.workflows.secrets.with_raw_response.delete(
+ "",
+ )
+
+
+class TestAsyncSecrets:
+ 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:
+ secret = await async_client.workflows.secrets.create(
+ name="name",
+ value="x",
+ )
+ assert_matches_type(SecretCreateResponse, secret, 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:
+ secret = await async_client.workflows.secrets.create(
+ name="name",
+ value="x",
+ description="description",
+ )
+ assert_matches_type(SecretCreateResponse, secret, 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.workflows.secrets.with_raw_response.create(
+ name="name",
+ value="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ secret = await response.parse()
+ assert_matches_type(SecretCreateResponse, secret, 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.workflows.secrets.with_streaming_response.create(
+ name="name",
+ value="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ secret = await response.parse()
+ assert_matches_type(SecretCreateResponse, secret, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncMobilerun) -> None:
+ secret = await async_client.workflows.secrets.list()
+ assert_matches_type(SecretListResponse, secret, 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.workflows.secrets.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ secret = await response.parse()
+ assert_matches_type(SecretListResponse, secret, 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.workflows.secrets.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ secret = await response.parse()
+ assert_matches_type(SecretListResponse, secret, 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:
+ secret = await async_client.workflows.secrets.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(SecretDeleteResponse, secret, 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.workflows.secrets.with_raw_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ secret = await response.parse()
+ assert_matches_type(SecretDeleteResponse, secret, 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.workflows.secrets.with_streaming_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ secret = await response.parse()
+ assert_matches_type(SecretDeleteResponse, secret, 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 `secret_id` but received ''"):
+ await async_client.workflows.secrets.with_raw_response.delete(
+ "",
+ )
diff --git a/tests/api_resources/test_agents.py b/tests/api_resources/workflows/test_timezones.py
similarity index 64%
rename from tests/api_resources/test_agents.py
rename to tests/api_resources/workflows/test_timezones.py
index 8087dea..fab060b 100644
--- a/tests/api_resources/test_agents.py
+++ b/tests/api_resources/workflows/test_timezones.py
@@ -9,44 +9,44 @@
from tests.utils import assert_matches_type
from mobilerun_sdk import Mobilerun, AsyncMobilerun
-from mobilerun_sdk.types import AgentListResponse
+from mobilerun_sdk.types.workflows import TimezoneListResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-class TestAgents:
+class TestTimezones:
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:
- agent = client.agents.list()
- assert_matches_type(AgentListResponse, agent, path=["response"])
+ timezone = client.workflows.timezones.list()
+ assert_matches_type(TimezoneListResponse, timezone, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_raw_response_list(self, client: Mobilerun) -> None:
- response = client.agents.with_raw_response.list()
+ response = client.workflows.timezones.with_raw_response.list()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- agent = response.parse()
- assert_matches_type(AgentListResponse, agent, path=["response"])
+ timezone = response.parse()
+ assert_matches_type(TimezoneListResponse, timezone, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_streaming_response_list(self, client: Mobilerun) -> None:
- with client.agents.with_streaming_response.list() as response:
+ with client.workflows.timezones.with_streaming_response.list() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- agent = response.parse()
- assert_matches_type(AgentListResponse, agent, path=["response"])
+ timezone = response.parse()
+ assert_matches_type(TimezoneListResponse, timezone, path=["response"])
assert cast(Any, response.is_closed) is True
-class TestAsyncAgents:
+class TestAsyncTimezones:
parametrize = pytest.mark.parametrize(
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
@@ -54,27 +54,27 @@ class TestAsyncAgents:
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_method_list(self, async_client: AsyncMobilerun) -> None:
- agent = await async_client.agents.list()
- assert_matches_type(AgentListResponse, agent, path=["response"])
+ timezone = await async_client.workflows.timezones.list()
+ assert_matches_type(TimezoneListResponse, timezone, 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.agents.with_raw_response.list()
+ response = await async_client.workflows.timezones.with_raw_response.list()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- agent = await response.parse()
- assert_matches_type(AgentListResponse, agent, path=["response"])
+ timezone = await response.parse()
+ assert_matches_type(TimezoneListResponse, timezone, 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.agents.with_streaming_response.list() as response:
+ async with async_client.workflows.timezones.with_streaming_response.list() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- agent = await response.parse()
- assert_matches_type(AgentListResponse, agent, path=["response"])
+ timezone = await response.parse()
+ assert_matches_type(TimezoneListResponse, timezone, path=["response"])
assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/workflows/test_triggers.py b/tests/api_resources/workflows/test_triggers.py
new file mode 100644
index 0000000..9a71326
--- /dev/null
+++ b/tests/api_resources/workflows/test_triggers.py
@@ -0,0 +1,647 @@
+# 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.workflows import (
+ TriggerFireResponse,
+ TriggerListResponse,
+ TriggerCreateResponse,
+ TriggerDeleteResponse,
+ TriggerUpdateResponse,
+ TriggerRetrieveResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestTriggers:
+ 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:
+ trigger = client.workflows.triggers.create(
+ activation="event",
+ name="x",
+ )
+ assert_matches_type(TriggerCreateResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params(self, client: Mobilerun) -> None:
+ trigger = client.workflows.triggers.create(
+ activation="event",
+ name="x",
+ conditions={
+ "all": [{}],
+ "any": [{}],
+ },
+ custom_payload_schema={"foo": "bar"},
+ description="description",
+ event_type="eventType",
+ schedule_rule={
+ "type": "once",
+ "date_time": "dateTime",
+ "expression": "expression",
+ "rrule": "rrule",
+ },
+ timezone="timezone",
+ )
+ assert_matches_type(TriggerCreateResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Mobilerun) -> None:
+ response = client.workflows.triggers.with_raw_response.create(
+ activation="event",
+ name="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ trigger = response.parse()
+ assert_matches_type(TriggerCreateResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Mobilerun) -> None:
+ with client.workflows.triggers.with_streaming_response.create(
+ activation="event",
+ name="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ trigger = response.parse()
+ assert_matches_type(TriggerCreateResponse, trigger, 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:
+ trigger = client.workflows.triggers.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(TriggerRetrieveResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Mobilerun) -> None:
+ response = client.workflows.triggers.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ trigger = response.parse()
+ assert_matches_type(TriggerRetrieveResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Mobilerun) -> None:
+ with client.workflows.triggers.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ trigger = response.parse()
+ assert_matches_type(TriggerRetrieveResponse, trigger, 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 `trigger_id` but received ''"):
+ client.workflows.triggers.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update(self, client: Mobilerun) -> None:
+ trigger = client.workflows.triggers.update(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(TriggerUpdateResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update_with_all_params(self, client: Mobilerun) -> None:
+ trigger = client.workflows.triggers.update(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ activation="event",
+ conditions={
+ "all": [{}],
+ "any": [{}],
+ },
+ custom_payload_schema={"foo": "bar"},
+ description="description",
+ event_type="eventType",
+ name="x",
+ schedule_rule={
+ "type": "once",
+ "date_time": "dateTime",
+ "expression": "expression",
+ "rrule": "rrule",
+ },
+ timezone="timezone",
+ )
+ assert_matches_type(TriggerUpdateResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_update(self, client: Mobilerun) -> None:
+ response = client.workflows.triggers.with_raw_response.update(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ trigger = response.parse()
+ assert_matches_type(TriggerUpdateResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_update(self, client: Mobilerun) -> None:
+ with client.workflows.triggers.with_streaming_response.update(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ trigger = response.parse()
+ assert_matches_type(TriggerUpdateResponse, trigger, 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 `trigger_id` but received ''"):
+ client.workflows.triggers.with_raw_response.update(
+ trigger_id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Mobilerun) -> None:
+ trigger = client.workflows.triggers.list()
+ assert_matches_type(TriggerListResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Mobilerun) -> None:
+ trigger = client.workflows.triggers.list(
+ activation="event",
+ event_type="eventType",
+ order_by="name",
+ order_by_direction="asc",
+ page=1,
+ page_size=1,
+ search="search",
+ )
+ assert_matches_type(TriggerListResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Mobilerun) -> None:
+ response = client.workflows.triggers.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ trigger = response.parse()
+ assert_matches_type(TriggerListResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Mobilerun) -> None:
+ with client.workflows.triggers.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ trigger = response.parse()
+ assert_matches_type(TriggerListResponse, trigger, 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:
+ trigger = client.workflows.triggers.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(TriggerDeleteResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_delete(self, client: Mobilerun) -> None:
+ response = client.workflows.triggers.with_raw_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ trigger = response.parse()
+ assert_matches_type(TriggerDeleteResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_delete(self, client: Mobilerun) -> None:
+ with client.workflows.triggers.with_streaming_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ trigger = response.parse()
+ assert_matches_type(TriggerDeleteResponse, trigger, 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 `trigger_id` but received ''"):
+ client.workflows.triggers.with_raw_response.delete(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_fire(self, client: Mobilerun) -> None:
+ trigger = client.workflows.triggers.fire(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ payload={"foo": "bar"},
+ )
+ assert_matches_type(TriggerFireResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_fire_with_all_params(self, client: Mobilerun) -> None:
+ trigger = client.workflows.triggers.fire(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ payload={"foo": "bar"},
+ device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(TriggerFireResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_fire(self, client: Mobilerun) -> None:
+ response = client.workflows.triggers.with_raw_response.fire(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ payload={"foo": "bar"},
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ trigger = response.parse()
+ assert_matches_type(TriggerFireResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_fire(self, client: Mobilerun) -> None:
+ with client.workflows.triggers.with_streaming_response.fire(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ payload={"foo": "bar"},
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ trigger = response.parse()
+ assert_matches_type(TriggerFireResponse, trigger, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_fire(self, client: Mobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `trigger_id` but received ''"):
+ client.workflows.triggers.with_raw_response.fire(
+ trigger_id="",
+ payload={"foo": "bar"},
+ )
+
+
+class TestAsyncTriggers:
+ 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:
+ trigger = await async_client.workflows.triggers.create(
+ activation="event",
+ name="x",
+ )
+ assert_matches_type(TriggerCreateResponse, trigger, 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:
+ trigger = await async_client.workflows.triggers.create(
+ activation="event",
+ name="x",
+ conditions={
+ "all": [{}],
+ "any": [{}],
+ },
+ custom_payload_schema={"foo": "bar"},
+ description="description",
+ event_type="eventType",
+ schedule_rule={
+ "type": "once",
+ "date_time": "dateTime",
+ "expression": "expression",
+ "rrule": "rrule",
+ },
+ timezone="timezone",
+ )
+ assert_matches_type(TriggerCreateResponse, trigger, 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.workflows.triggers.with_raw_response.create(
+ activation="event",
+ name="x",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ trigger = await response.parse()
+ assert_matches_type(TriggerCreateResponse, trigger, 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.workflows.triggers.with_streaming_response.create(
+ activation="event",
+ name="x",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ trigger = await response.parse()
+ assert_matches_type(TriggerCreateResponse, trigger, 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:
+ trigger = await async_client.workflows.triggers.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(TriggerRetrieveResponse, trigger, 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.workflows.triggers.with_raw_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ trigger = await response.parse()
+ assert_matches_type(TriggerRetrieveResponse, trigger, 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.workflows.triggers.with_streaming_response.retrieve(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ trigger = await response.parse()
+ assert_matches_type(TriggerRetrieveResponse, trigger, 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 `trigger_id` but received ''"):
+ await async_client.workflows.triggers.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_update(self, async_client: AsyncMobilerun) -> None:
+ trigger = await async_client.workflows.triggers.update(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(TriggerUpdateResponse, trigger, 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:
+ trigger = await async_client.workflows.triggers.update(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ activation="event",
+ conditions={
+ "all": [{}],
+ "any": [{}],
+ },
+ custom_payload_schema={"foo": "bar"},
+ description="description",
+ event_type="eventType",
+ name="x",
+ schedule_rule={
+ "type": "once",
+ "date_time": "dateTime",
+ "expression": "expression",
+ "rrule": "rrule",
+ },
+ timezone="timezone",
+ )
+ assert_matches_type(TriggerUpdateResponse, trigger, 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.workflows.triggers.with_raw_response.update(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ trigger = await response.parse()
+ assert_matches_type(TriggerUpdateResponse, trigger, 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.workflows.triggers.with_streaming_response.update(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ trigger = await response.parse()
+ assert_matches_type(TriggerUpdateResponse, trigger, 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 `trigger_id` but received ''"):
+ await async_client.workflows.triggers.with_raw_response.update(
+ trigger_id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncMobilerun) -> None:
+ trigger = await async_client.workflows.triggers.list()
+ assert_matches_type(TriggerListResponse, trigger, 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:
+ trigger = await async_client.workflows.triggers.list(
+ activation="event",
+ event_type="eventType",
+ order_by="name",
+ order_by_direction="asc",
+ page=1,
+ page_size=1,
+ search="search",
+ )
+ assert_matches_type(TriggerListResponse, trigger, 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.workflows.triggers.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ trigger = await response.parse()
+ assert_matches_type(TriggerListResponse, trigger, 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.workflows.triggers.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ trigger = await response.parse()
+ assert_matches_type(TriggerListResponse, trigger, 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:
+ trigger = await async_client.workflows.triggers.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(TriggerDeleteResponse, trigger, 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.workflows.triggers.with_raw_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ trigger = await response.parse()
+ assert_matches_type(TriggerDeleteResponse, trigger, 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.workflows.triggers.with_streaming_response.delete(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ trigger = await response.parse()
+ assert_matches_type(TriggerDeleteResponse, trigger, 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 `trigger_id` but received ''"):
+ await async_client.workflows.triggers.with_raw_response.delete(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_fire(self, async_client: AsyncMobilerun) -> None:
+ trigger = await async_client.workflows.triggers.fire(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ payload={"foo": "bar"},
+ )
+ assert_matches_type(TriggerFireResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_fire_with_all_params(self, async_client: AsyncMobilerun) -> None:
+ trigger = await async_client.workflows.triggers.fire(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ payload={"foo": "bar"},
+ device_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(TriggerFireResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_fire(self, async_client: AsyncMobilerun) -> None:
+ response = await async_client.workflows.triggers.with_raw_response.fire(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ payload={"foo": "bar"},
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ trigger = await response.parse()
+ assert_matches_type(TriggerFireResponse, trigger, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_fire(self, async_client: AsyncMobilerun) -> None:
+ async with async_client.workflows.triggers.with_streaming_response.fire(
+ trigger_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ payload={"foo": "bar"},
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ trigger = await response.parse()
+ assert_matches_type(TriggerFireResponse, trigger, 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_fire(self, async_client: AsyncMobilerun) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `trigger_id` but received ''"):
+ await async_client.workflows.triggers.with_raw_response.fire(
+ trigger_id="",
+ payload={"foo": "bar"},
+ )