runloop_api_client 1.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. runloop_api_client/__init__.py +95 -0
  2. runloop_api_client/_base_client.py +2127 -0
  3. runloop_api_client/_client.py +866 -0
  4. runloop_api_client/_compat.py +219 -0
  5. runloop_api_client/_constants.py +23 -0
  6. runloop_api_client/_exceptions.py +108 -0
  7. runloop_api_client/_files.py +123 -0
  8. runloop_api_client/_models.py +872 -0
  9. runloop_api_client/_qs.py +150 -0
  10. runloop_api_client/_resource.py +43 -0
  11. runloop_api_client/_response.py +832 -0
  12. runloop_api_client/_streaming.py +518 -0
  13. runloop_api_client/_types.py +270 -0
  14. runloop_api_client/_utils/__init__.py +65 -0
  15. runloop_api_client/_utils/_compat.py +45 -0
  16. runloop_api_client/_utils/_datetime_parse.py +136 -0
  17. runloop_api_client/_utils/_json.py +35 -0
  18. runloop_api_client/_utils/_logs.py +25 -0
  19. runloop_api_client/_utils/_proxy.py +65 -0
  20. runloop_api_client/_utils/_reflection.py +42 -0
  21. runloop_api_client/_utils/_resources_proxy.py +24 -0
  22. runloop_api_client/_utils/_streams.py +12 -0
  23. runloop_api_client/_utils/_sync.py +58 -0
  24. runloop_api_client/_utils/_transform.py +457 -0
  25. runloop_api_client/_utils/_typing.py +156 -0
  26. runloop_api_client/_utils/_utils.py +421 -0
  27. runloop_api_client/_utils/_validation.py +31 -0
  28. runloop_api_client/_version.py +4 -0
  29. runloop_api_client/lib/.keep +4 -0
  30. runloop_api_client/lib/__init__.py +3 -0
  31. runloop_api_client/lib/_ignore.py +496 -0
  32. runloop_api_client/lib/context_loader.py +78 -0
  33. runloop_api_client/lib/polling.py +75 -0
  34. runloop_api_client/lib/polling_async.py +60 -0
  35. runloop_api_client/pagination.py +986 -0
  36. runloop_api_client/py.typed +0 -0
  37. runloop_api_client/resources/__init__.py +173 -0
  38. runloop_api_client/resources/agents.py +431 -0
  39. runloop_api_client/resources/benchmark_jobs.py +394 -0
  40. runloop_api_client/resources/benchmark_runs.py +595 -0
  41. runloop_api_client/resources/benchmarks.py +1085 -0
  42. runloop_api_client/resources/blueprints.py +1563 -0
  43. runloop_api_client/resources/devboxes/__init__.py +89 -0
  44. runloop_api_client/resources/devboxes/browsers.py +267 -0
  45. runloop_api_client/resources/devboxes/computers.py +648 -0
  46. runloop_api_client/resources/devboxes/devboxes.py +3784 -0
  47. runloop_api_client/resources/devboxes/disk_snapshots.py +602 -0
  48. runloop_api_client/resources/devboxes/executions.py +1212 -0
  49. runloop_api_client/resources/devboxes/logs.py +197 -0
  50. runloop_api_client/resources/gateway_configs.py +658 -0
  51. runloop_api_client/resources/network_policies.py +680 -0
  52. runloop_api_client/resources/objects.py +870 -0
  53. runloop_api_client/resources/repositories.py +918 -0
  54. runloop_api_client/resources/scenarios/__init__.py +47 -0
  55. runloop_api_client/resources/scenarios/runs.py +973 -0
  56. runloop_api_client/resources/scenarios/scenarios.py +1101 -0
  57. runloop_api_client/resources/scenarios/scorers.py +629 -0
  58. runloop_api_client/resources/secrets.py +500 -0
  59. runloop_api_client/sdk/__init__.py +117 -0
  60. runloop_api_client/sdk/_helpers.py +49 -0
  61. runloop_api_client/sdk/_types.py +264 -0
  62. runloop_api_client/sdk/agent.py +70 -0
  63. runloop_api_client/sdk/async_.py +1036 -0
  64. runloop_api_client/sdk/async_agent.py +70 -0
  65. runloop_api_client/sdk/async_benchmark.py +169 -0
  66. runloop_api_client/sdk/async_benchmark_run.py +127 -0
  67. runloop_api_client/sdk/async_blueprint.py +104 -0
  68. runloop_api_client/sdk/async_devbox.py +797 -0
  69. runloop_api_client/sdk/async_execution.py +144 -0
  70. runloop_api_client/sdk/async_execution_result.py +175 -0
  71. runloop_api_client/sdk/async_network_policy.py +80 -0
  72. runloop_api_client/sdk/async_scenario.py +118 -0
  73. runloop_api_client/sdk/async_scenario_builder.py +480 -0
  74. runloop_api_client/sdk/async_scenario_run.py +242 -0
  75. runloop_api_client/sdk/async_scorer.py +77 -0
  76. runloop_api_client/sdk/async_snapshot.py +125 -0
  77. runloop_api_client/sdk/async_storage_object.py +188 -0
  78. runloop_api_client/sdk/benchmark.py +167 -0
  79. runloop_api_client/sdk/benchmark_run.py +127 -0
  80. runloop_api_client/sdk/blueprint.py +104 -0
  81. runloop_api_client/sdk/devbox.py +800 -0
  82. runloop_api_client/sdk/execution.py +132 -0
  83. runloop_api_client/sdk/execution_result.py +173 -0
  84. runloop_api_client/sdk/network_policy.py +80 -0
  85. runloop_api_client/sdk/scenario.py +118 -0
  86. runloop_api_client/sdk/scenario_builder.py +480 -0
  87. runloop_api_client/sdk/scenario_run.py +242 -0
  88. runloop_api_client/sdk/scorer.py +77 -0
  89. runloop_api_client/sdk/snapshot.py +125 -0
  90. runloop_api_client/sdk/storage_object.py +188 -0
  91. runloop_api_client/sdk/sync.py +1061 -0
  92. runloop_api_client/types/__init__.py +130 -0
  93. runloop_api_client/types/agent_create_params.py +21 -0
  94. runloop_api_client/types/agent_list_params.py +27 -0
  95. runloop_api_client/types/agent_list_view.py +24 -0
  96. runloop_api_client/types/agent_view.py +30 -0
  97. runloop_api_client/types/benchmark_create_params.py +40 -0
  98. runloop_api_client/types/benchmark_definitions_params.py +15 -0
  99. runloop_api_client/types/benchmark_job_create_params.py +220 -0
  100. runloop_api_client/types/benchmark_job_list_params.py +18 -0
  101. runloop_api_client/types/benchmark_job_list_view.py +19 -0
  102. runloop_api_client/types/benchmark_job_view.py +344 -0
  103. runloop_api_client/types/benchmark_list_params.py +18 -0
  104. runloop_api_client/types/benchmark_list_public_params.py +15 -0
  105. runloop_api_client/types/benchmark_run_list_params.py +21 -0
  106. runloop_api_client/types/benchmark_run_list_scenario_runs_params.py +18 -0
  107. runloop_api_client/types/benchmark_run_list_view.py +19 -0
  108. runloop_api_client/types/benchmark_run_view.py +58 -0
  109. runloop_api_client/types/benchmark_start_run_params.py +29 -0
  110. runloop_api_client/types/benchmark_update_params.py +42 -0
  111. runloop_api_client/types/benchmark_update_scenarios_params.py +18 -0
  112. runloop_api_client/types/benchmark_view.py +49 -0
  113. runloop_api_client/types/blueprint_build_log.py +16 -0
  114. runloop_api_client/types/blueprint_build_logs_list_view.py +16 -0
  115. runloop_api_client/types/blueprint_build_parameters.py +119 -0
  116. runloop_api_client/types/blueprint_create_from_inspection_params.py +49 -0
  117. runloop_api_client/types/blueprint_create_params.py +121 -0
  118. runloop_api_client/types/blueprint_list_params.py +21 -0
  119. runloop_api_client/types/blueprint_list_public_params.py +21 -0
  120. runloop_api_client/types/blueprint_list_view.py +19 -0
  121. runloop_api_client/types/blueprint_preview_params.py +121 -0
  122. runloop_api_client/types/blueprint_preview_view.py +10 -0
  123. runloop_api_client/types/blueprint_view.py +93 -0
  124. runloop_api_client/types/devbox_async_execution_detail_view.py +46 -0
  125. runloop_api_client/types/devbox_create_params.py +124 -0
  126. runloop_api_client/types/devbox_create_ssh_key_response.py +19 -0
  127. runloop_api_client/types/devbox_create_tunnel_params.py +12 -0
  128. runloop_api_client/types/devbox_download_file_params.py +15 -0
  129. runloop_api_client/types/devbox_enable_tunnel_params.py +13 -0
  130. runloop_api_client/types/devbox_execute_async_params.py +33 -0
  131. runloop_api_client/types/devbox_execute_params.py +37 -0
  132. runloop_api_client/types/devbox_execute_sync_params.py +31 -0
  133. runloop_api_client/types/devbox_execution_detail_view.py +24 -0
  134. runloop_api_client/types/devbox_list_disk_snapshots_params.py +32 -0
  135. runloop_api_client/types/devbox_list_params.py +20 -0
  136. runloop_api_client/types/devbox_list_view.py +19 -0
  137. runloop_api_client/types/devbox_read_file_contents_params.py +15 -0
  138. runloop_api_client/types/devbox_read_file_contents_response.py +7 -0
  139. runloop_api_client/types/devbox_remove_tunnel_params.py +12 -0
  140. runloop_api_client/types/devbox_send_std_in_result.py +16 -0
  141. runloop_api_client/types/devbox_snapshot_disk_async_params.py +19 -0
  142. runloop_api_client/types/devbox_snapshot_disk_params.py +19 -0
  143. runloop_api_client/types/devbox_snapshot_list_view.py +19 -0
  144. runloop_api_client/types/devbox_snapshot_view.py +30 -0
  145. runloop_api_client/types/devbox_tunnel_view.py +16 -0
  146. runloop_api_client/types/devbox_update_params.py +16 -0
  147. runloop_api_client/types/devbox_upload_file_params.py +19 -0
  148. runloop_api_client/types/devbox_view.py +121 -0
  149. runloop_api_client/types/devbox_wait_for_command_params.py +28 -0
  150. runloop_api_client/types/devbox_write_file_contents_params.py +18 -0
  151. runloop_api_client/types/devboxes/__init__.py +33 -0
  152. runloop_api_client/types/devboxes/browser_create_params.py +13 -0
  153. runloop_api_client/types/devboxes/browser_view.py +29 -0
  154. runloop_api_client/types/devboxes/computer_create_params.py +26 -0
  155. runloop_api_client/types/devboxes/computer_keyboard_interaction_params.py +16 -0
  156. runloop_api_client/types/devboxes/computer_keyboard_interaction_response.py +15 -0
  157. runloop_api_client/types/devboxes/computer_mouse_interaction_params.py +35 -0
  158. runloop_api_client/types/devboxes/computer_mouse_interaction_response.py +15 -0
  159. runloop_api_client/types/devboxes/computer_screen_interaction_params.py +12 -0
  160. runloop_api_client/types/devboxes/computer_screen_interaction_response.py +15 -0
  161. runloop_api_client/types/devboxes/computer_view.py +23 -0
  162. runloop_api_client/types/devboxes/devbox_logs_list_view.py +39 -0
  163. runloop_api_client/types/devboxes/devbox_snapshot_async_status_view.py +20 -0
  164. runloop_api_client/types/devboxes/disk_snapshot_list_params.py +32 -0
  165. runloop_api_client/types/devboxes/disk_snapshot_update_params.py +19 -0
  166. runloop_api_client/types/devboxes/execution_execute_async_params.py +31 -0
  167. runloop_api_client/types/devboxes/execution_execute_sync_params.py +31 -0
  168. runloop_api_client/types/devboxes/execution_kill_params.py +18 -0
  169. runloop_api_client/types/devboxes/execution_retrieve_params.py +14 -0
  170. runloop_api_client/types/devboxes/execution_send_std_in_params.py +18 -0
  171. runloop_api_client/types/devboxes/execution_stream_stderr_updates_params.py +17 -0
  172. runloop_api_client/types/devboxes/execution_stream_stdout_updates_params.py +17 -0
  173. runloop_api_client/types/devboxes/execution_update_chunk.py +15 -0
  174. runloop_api_client/types/devboxes/log_list_params.py +15 -0
  175. runloop_api_client/types/gateway_config_create_params.py +41 -0
  176. runloop_api_client/types/gateway_config_list_params.py +21 -0
  177. runloop_api_client/types/gateway_config_list_view.py +21 -0
  178. runloop_api_client/types/gateway_config_update_params.py +32 -0
  179. runloop_api_client/types/gateway_config_view.py +47 -0
  180. runloop_api_client/types/input_context.py +19 -0
  181. runloop_api_client/types/input_context_param.py +20 -0
  182. runloop_api_client/types/input_context_update_param.py +16 -0
  183. runloop_api_client/types/inspection_source_param.py +18 -0
  184. runloop_api_client/types/network_policy_create_params.py +40 -0
  185. runloop_api_client/types/network_policy_list_params.py +21 -0
  186. runloop_api_client/types/network_policy_list_view.py +21 -0
  187. runloop_api_client/types/network_policy_update_params.py +30 -0
  188. runloop_api_client/types/network_policy_view.py +52 -0
  189. runloop_api_client/types/object_create_params.py +30 -0
  190. runloop_api_client/types/object_download_params.py +12 -0
  191. runloop_api_client/types/object_download_url_view.py +12 -0
  192. runloop_api_client/types/object_list_params.py +27 -0
  193. runloop_api_client/types/object_list_public_params.py +27 -0
  194. runloop_api_client/types/object_list_view.py +24 -0
  195. runloop_api_client/types/object_view.py +36 -0
  196. runloop_api_client/types/repository_connection_list_view.py +19 -0
  197. runloop_api_client/types/repository_connection_view.py +18 -0
  198. runloop_api_client/types/repository_create_params.py +22 -0
  199. runloop_api_client/types/repository_inspect_params.py +13 -0
  200. runloop_api_client/types/repository_inspection_details.py +83 -0
  201. runloop_api_client/types/repository_inspection_list_view.py +13 -0
  202. runloop_api_client/types/repository_list_params.py +21 -0
  203. runloop_api_client/types/repository_manifest_view.py +174 -0
  204. runloop_api_client/types/repository_refresh_params.py +16 -0
  205. runloop_api_client/types/scenario_create_params.py +53 -0
  206. runloop_api_client/types/scenario_definition_list_view.py +19 -0
  207. runloop_api_client/types/scenario_environment.py +29 -0
  208. runloop_api_client/types/scenario_environment_param.py +31 -0
  209. runloop_api_client/types/scenario_list_params.py +24 -0
  210. runloop_api_client/types/scenario_list_public_params.py +18 -0
  211. runloop_api_client/types/scenario_run_list_view.py +19 -0
  212. runloop_api_client/types/scenario_run_view.py +55 -0
  213. runloop_api_client/types/scenario_start_run_params.py +30 -0
  214. runloop_api_client/types/scenario_update_params.py +49 -0
  215. runloop_api_client/types/scenario_view.py +61 -0
  216. runloop_api_client/types/scenarios/__init__.py +14 -0
  217. runloop_api_client/types/scenarios/run_list_params.py +27 -0
  218. runloop_api_client/types/scenarios/scorer_create_params.py +18 -0
  219. runloop_api_client/types/scenarios/scorer_create_response.py +18 -0
  220. runloop_api_client/types/scenarios/scorer_list_params.py +15 -0
  221. runloop_api_client/types/scenarios/scorer_list_response.py +18 -0
  222. runloop_api_client/types/scenarios/scorer_retrieve_response.py +18 -0
  223. runloop_api_client/types/scenarios/scorer_update_params.py +18 -0
  224. runloop_api_client/types/scenarios/scorer_update_response.py +18 -0
  225. runloop_api_client/types/scenarios/scorer_validate_params.py +17 -0
  226. runloop_api_client/types/scenarios/scorer_validate_response.py +23 -0
  227. runloop_api_client/types/scoring_contract.py +17 -0
  228. runloop_api_client/types/scoring_contract_param.py +19 -0
  229. runloop_api_client/types/scoring_contract_result_view.py +20 -0
  230. runloop_api_client/types/scoring_contract_update_param.py +15 -0
  231. runloop_api_client/types/scoring_function.py +157 -0
  232. runloop_api_client/types/scoring_function_param.py +153 -0
  233. runloop_api_client/types/scoring_function_result_view.py +25 -0
  234. runloop_api_client/types/secret_create_params.py +23 -0
  235. runloop_api_client/types/secret_list_params.py +12 -0
  236. runloop_api_client/types/secret_list_view.py +24 -0
  237. runloop_api_client/types/secret_update_params.py +16 -0
  238. runloop_api_client/types/secret_view.py +26 -0
  239. runloop_api_client/types/shared/__init__.py +10 -0
  240. runloop_api_client/types/shared/after_idle.py +15 -0
  241. runloop_api_client/types/shared/agent_mount.py +31 -0
  242. runloop_api_client/types/shared/agent_source.py +75 -0
  243. runloop_api_client/types/shared/code_mount_parameters.py +24 -0
  244. runloop_api_client/types/shared/launch_parameters.py +86 -0
  245. runloop_api_client/types/shared/mount.py +43 -0
  246. runloop_api_client/types/shared/object_mount.py +21 -0
  247. runloop_api_client/types/shared/run_profile.py +37 -0
  248. runloop_api_client/types/shared_params/__init__.py +10 -0
  249. runloop_api_client/types/shared_params/after_idle.py +15 -0
  250. runloop_api_client/types/shared_params/agent_mount.py +31 -0
  251. runloop_api_client/types/shared_params/agent_source.py +78 -0
  252. runloop_api_client/types/shared_params/code_mount_parameters.py +25 -0
  253. runloop_api_client/types/shared_params/launch_parameters.py +88 -0
  254. runloop_api_client/types/shared_params/mount.py +43 -0
  255. runloop_api_client/types/shared_params/object_mount.py +21 -0
  256. runloop_api_client/types/shared_params/run_profile.py +38 -0
  257. runloop_api_client/types/tunnel_view.py +34 -0
  258. runloop_api_client-1.5.1.dist-info/METADATA +522 -0
  259. runloop_api_client-1.5.1.dist-info/RECORD +261 -0
  260. runloop_api_client-1.5.1.dist-info/WHEEL +4 -0
  261. runloop_api_client-1.5.1.dist-info/licenses/LICENSE +7 -0
@@ -0,0 +1,1036 @@
1
+ """Asynchronous SDK entry points and management interfaces."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ from typing import Dict, Mapping, Optional
7
+ from pathlib import Path
8
+ from datetime import timedelta
9
+ from typing_extensions import Unpack
10
+
11
+ import httpx
12
+
13
+ from ._types import (
14
+ LongRequestOptions,
15
+ SDKAgentListParams,
16
+ SDKDevboxListParams,
17
+ SDKObjectListParams,
18
+ SDKScorerListParams,
19
+ SDKAgentCreateParams,
20
+ SDKDevboxCreateParams,
21
+ SDKObjectCreateParams,
22
+ SDKScenarioListParams,
23
+ SDKScorerCreateParams,
24
+ SDKBenchmarkListParams,
25
+ SDKBlueprintListParams,
26
+ SDKBenchmarkCreateParams,
27
+ SDKBlueprintCreateParams,
28
+ SDKDiskSnapshotListParams,
29
+ SDKNetworkPolicyListParams,
30
+ SDKNetworkPolicyCreateParams,
31
+ SDKDevboxCreateFromImageParams,
32
+ )
33
+ from .._types import Timeout, NotGiven, not_given
34
+ from .._client import DEFAULT_MAX_RETRIES, AsyncRunloop
35
+ from ._helpers import detect_content_type
36
+ from .async_agent import AsyncAgent
37
+ from .async_devbox import AsyncDevbox
38
+ from .async_scorer import AsyncScorer
39
+ from .async_scenario import AsyncScenario
40
+ from .async_snapshot import AsyncSnapshot
41
+ from .async_benchmark import AsyncBenchmark
42
+ from .async_blueprint import AsyncBlueprint
43
+ from ..lib.context_loader import TarFilter, build_directory_tar
44
+ from .async_network_policy import AsyncNetworkPolicy
45
+ from .async_storage_object import AsyncStorageObject
46
+ from .async_scenario_builder import AsyncScenarioBuilder
47
+ from ..types.object_create_params import ContentType
48
+ from ..types.shared_params.agent_source import Git, Npm, Pip, Object
49
+
50
+
51
+ class AsyncDevboxOps:
52
+ """High-level async manager for creating and managing AsyncDevbox instances.
53
+
54
+ Accessed via ``runloop.devbox`` from :class:`AsyncRunloopSDK`, provides
55
+ coroutines to create devboxes from scratch, blueprints, or snapshots, and to
56
+ list existing devboxes.
57
+
58
+ Example:
59
+ >>> runloop = AsyncRunloopSDK()
60
+ >>> devbox = await runloop.devbox.create(name="my-devbox")
61
+ >>> devboxes = await runloop.devbox.list(limit=10)
62
+ """
63
+
64
+ def __init__(self, client: AsyncRunloop) -> None:
65
+ """Initialize the manager.
66
+
67
+ :param client: Generated AsyncRunloop client to wrap
68
+ :type client: AsyncRunloop
69
+ """
70
+ self._client = client
71
+
72
+ async def create(
73
+ self,
74
+ **params: Unpack[SDKDevboxCreateParams],
75
+ ) -> AsyncDevbox:
76
+ """Provision a new devbox and wait until it reaches ``running`` state.
77
+
78
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKDevboxCreateParams` for available parameters
79
+ :return: Wrapper bound to the newly created devbox
80
+ :rtype: AsyncDevbox
81
+ """
82
+ devbox_view = await self._client.devboxes.create_and_await_running(
83
+ **params,
84
+ )
85
+ return AsyncDevbox(self._client, devbox_view.id)
86
+
87
+ async def create_from_blueprint_id(
88
+ self,
89
+ blueprint_id: str,
90
+ **params: Unpack[SDKDevboxCreateFromImageParams],
91
+ ) -> AsyncDevbox:
92
+ """Create a devbox from an existing blueprint by identifier.
93
+
94
+ :param blueprint_id: Blueprint ID to create from
95
+ :type blueprint_id: str
96
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKDevboxCreateFromImageParams` for available parameters
97
+ :return: Wrapper bound to the newly created devbox
98
+ :rtype: AsyncDevbox
99
+ """
100
+ devbox_view = await self._client.devboxes.create_and_await_running(
101
+ blueprint_id=blueprint_id,
102
+ **params,
103
+ )
104
+ return AsyncDevbox(self._client, devbox_view.id)
105
+
106
+ async def create_from_blueprint_name(
107
+ self,
108
+ blueprint_name: str,
109
+ **params: Unpack[SDKDevboxCreateFromImageParams],
110
+ ) -> AsyncDevbox:
111
+ """Create a devbox from the latest blueprint with the given name.
112
+
113
+ :param blueprint_name: Blueprint name to create from
114
+ :type blueprint_name: str
115
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKDevboxCreateFromImageParams` for available parameters
116
+ :return: Wrapper bound to the newly created devbox
117
+ :rtype: AsyncDevbox
118
+ """
119
+ devbox_view = await self._client.devboxes.create_and_await_running(
120
+ blueprint_name=blueprint_name,
121
+ **params,
122
+ )
123
+ return AsyncDevbox(self._client, devbox_view.id)
124
+
125
+ async def create_from_snapshot(
126
+ self,
127
+ snapshot_id: str,
128
+ **params: Unpack[SDKDevboxCreateFromImageParams],
129
+ ) -> AsyncDevbox:
130
+ """Create a devbox initialized from a snapshot.
131
+
132
+ :param snapshot_id: Snapshot ID to create from
133
+ :type snapshot_id: str
134
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKDevboxCreateFromImageParams` for available parameters
135
+ :return: Wrapper bound to the newly created devbox
136
+ :rtype: AsyncDevbox
137
+ """
138
+ devbox_view = await self._client.devboxes.create_and_await_running(
139
+ snapshot_id=snapshot_id,
140
+ **params,
141
+ )
142
+ return AsyncDevbox(self._client, devbox_view.id)
143
+
144
+ def from_id(self, devbox_id: str) -> AsyncDevbox:
145
+ """Attach to an existing devbox by ID.
146
+
147
+ Returns immediately without waiting for the devbox to reach ``running``
148
+ state. Call ``await_running()`` on the returned :class:`AsyncDevbox` if
149
+ you need to wait for readiness (contrast with the synchronous SDK, which blocks).
150
+
151
+ :param devbox_id: Existing devbox ID
152
+ :type devbox_id: str
153
+ :return: Wrapper bound to the requested devbox
154
+ :rtype: AsyncDevbox
155
+ """
156
+ return AsyncDevbox(self._client, devbox_id)
157
+
158
+ async def list(
159
+ self,
160
+ **params: Unpack[SDKDevboxListParams],
161
+ ) -> list[AsyncDevbox]:
162
+ """List devboxes accessible to the caller.
163
+
164
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKDevboxListParams` for available parameters
165
+ :return: Collection of devbox wrappers
166
+ :rtype: list[AsyncDevbox]
167
+ """
168
+ page = await self._client.devboxes.list(
169
+ **params,
170
+ )
171
+ return [AsyncDevbox(self._client, item.id) for item in page.devboxes]
172
+
173
+
174
+ class AsyncSnapshotOps:
175
+ """High-level async manager for working with disk snapshots.
176
+
177
+ Accessed via ``runloop.snapshot`` from :class:`AsyncRunloopSDK`, provides
178
+ coroutines to list snapshots and access snapshot details.
179
+
180
+ Example:
181
+ >>> runloop = AsyncRunloopSDK()
182
+ >>> snapshots = await runloop.snapshot.list(devbox_id="dev-123")
183
+ >>> snapshot = await runloop.snapshot.from_id("snap-123")
184
+ """
185
+
186
+ def __init__(self, client: AsyncRunloop) -> None:
187
+ """Initialize the manager.
188
+
189
+ :param client: Generated AsyncRunloop client to wrap
190
+ :type client: AsyncRunloop
191
+ """
192
+ self._client = client
193
+
194
+ async def list(
195
+ self,
196
+ **params: Unpack[SDKDiskSnapshotListParams],
197
+ ) -> list[AsyncSnapshot]:
198
+ """List snapshots created from devboxes.
199
+
200
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKDiskSnapshotListParams` for available parameters
201
+ :return: Snapshot wrappers for each record
202
+ :rtype: list[AsyncSnapshot]
203
+ """
204
+ page = await self._client.devboxes.disk_snapshots.list(
205
+ **params,
206
+ )
207
+ return [AsyncSnapshot(self._client, item.id) for item in page.snapshots]
208
+
209
+ def from_id(self, snapshot_id: str) -> AsyncSnapshot:
210
+ """Return a snapshot wrapper for the given ID.
211
+
212
+ :param snapshot_id: Snapshot ID to wrap
213
+ :type snapshot_id: str
214
+ :return: Wrapper for the snapshot resource
215
+ :rtype: AsyncSnapshot
216
+ """
217
+ return AsyncSnapshot(self._client, snapshot_id)
218
+
219
+
220
+ class AsyncBlueprintOps:
221
+ """High-level async manager for creating and managing blueprints.
222
+
223
+ Accessed via ``runloop.blueprint`` from :class:`AsyncRunloopSDK`, provides
224
+ coroutines to create Dockerfile-based blueprints, inspect build logs,
225
+ and list existing blueprints.
226
+
227
+ Example:
228
+ >>> runloop = AsyncRunloopSDK()
229
+ >>> blueprint = await runloop.blueprint.create(
230
+ ... name="my-blueprint",
231
+ ... dockerfile="FROM ubuntu:22.04\\nRUN apt-get update",
232
+ ... )
233
+ >>> blueprints = await runloop.blueprint.list()
234
+
235
+ To use a local directory as a build context, use an object.
236
+
237
+ Example:
238
+ >>> from datetime import timedelta
239
+ >>> from runloop_api_client.types.blueprint_build_parameters import BuildContext
240
+ >>> runloop = AsyncRunloopSDK()
241
+ >>> obj = await runloop.object_storage.upload_from_dir(
242
+ ... "./",
243
+ ... ttl=timedelta(hours=1),
244
+ ... )
245
+ >>> blueprint = await runloop.blueprint.create(
246
+ ... name="my-blueprint",
247
+ ... dockerfile="FROM ubuntu:22.04\\nCOPY . .\\n",
248
+ ... build_context=BuildContext(type="object", object_id=obj.id),
249
+ ... )
250
+ """
251
+
252
+ def __init__(self, client: AsyncRunloop) -> None:
253
+ """Initialize the manager.
254
+
255
+ :param client: Generated AsyncRunloop client to wrap
256
+ :type client: AsyncRunloop
257
+ """
258
+ self._client = client
259
+
260
+ async def create(
261
+ self,
262
+ **params: Unpack[SDKBlueprintCreateParams],
263
+ ) -> AsyncBlueprint:
264
+ """Create a blueprint and wait for the build to finish.
265
+
266
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKBlueprintCreateParams` for available parameters
267
+ :return: Wrapper bound to the finished blueprint
268
+ :rtype: AsyncBlueprint
269
+ """
270
+ blueprint = await self._client.blueprints.create_and_await_build_complete(
271
+ **params,
272
+ )
273
+ return AsyncBlueprint(self._client, blueprint.id)
274
+
275
+ def from_id(self, blueprint_id: str) -> AsyncBlueprint:
276
+ """Return a blueprint wrapper for the given ID.
277
+
278
+ :param blueprint_id: Blueprint ID to wrap
279
+ :type blueprint_id: str
280
+ :return: Wrapper for the blueprint resource
281
+ :rtype: AsyncBlueprint
282
+ """
283
+ return AsyncBlueprint(self._client, blueprint_id)
284
+
285
+ async def list(
286
+ self,
287
+ **params: Unpack[SDKBlueprintListParams],
288
+ ) -> list[AsyncBlueprint]:
289
+ """List available blueprints.
290
+
291
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKBlueprintListParams` for available parameters
292
+ :return: Blueprint wrappers for each record
293
+ :rtype: list[AsyncBlueprint]
294
+ """
295
+ page = await self._client.blueprints.list(
296
+ **params,
297
+ )
298
+ return [AsyncBlueprint(self._client, item.id) for item in page.blueprints]
299
+
300
+
301
+ class AsyncStorageObjectOps:
302
+ """High-level async manager for creating and managing storage objects.
303
+
304
+ Accessed via ``runloop.storage_object`` from :class:`AsyncRunloopSDK`, provides
305
+ coroutines to create, upload, download, and list storage objects with convenient
306
+ helpers for file and text uploads.
307
+
308
+ Example:
309
+ >>> runloop = AsyncRunloopSDK()
310
+ >>> obj = await runloop.storage_object.upload_from_text("Hello!", "greeting.txt")
311
+ >>> content = await obj.download_as_text()
312
+ >>> objects = await runloop.storage_object.list()
313
+ """
314
+
315
+ def __init__(self, client: AsyncRunloop) -> None:
316
+ """Initialize the manager.
317
+
318
+ :param client: Generated AsyncRunloop client to wrap
319
+ :type client: AsyncRunloop
320
+ """
321
+ self._client = client
322
+
323
+ async def create(
324
+ self,
325
+ **params: Unpack[SDKObjectCreateParams],
326
+ ) -> AsyncStorageObject:
327
+ """Create a storage object and obtain an upload URL.
328
+
329
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKObjectCreateParams` for available parameters
330
+ :return: Wrapper with upload URL set for immediate uploads
331
+ :rtype: AsyncStorageObject
332
+ """
333
+ obj = await self._client.objects.create(**params)
334
+ return AsyncStorageObject(self._client, obj.id, upload_url=obj.upload_url)
335
+
336
+ def from_id(self, object_id: str) -> AsyncStorageObject:
337
+ """Return a storage object wrapper by identifier.
338
+
339
+ :param object_id: Storage object identifier to wrap
340
+ :type object_id: str
341
+ :return: Wrapper for the storage object resource
342
+ :rtype: AsyncStorageObject
343
+ """
344
+ return AsyncStorageObject(self._client, object_id, upload_url=None)
345
+
346
+ async def list(
347
+ self,
348
+ **params: Unpack[SDKObjectListParams],
349
+ ) -> list[AsyncStorageObject]:
350
+ """List storage objects owned by the caller.
351
+
352
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKObjectListParams` for available parameters
353
+ :return: Storage object wrappers for each record
354
+ :rtype: list[AsyncStorageObject]
355
+ """
356
+ page = await self._client.objects.list(
357
+ **params,
358
+ )
359
+ return [AsyncStorageObject(self._client, item.id, upload_url=item.upload_url) for item in page.objects]
360
+
361
+ async def upload_from_file(
362
+ self,
363
+ file_path: str | Path,
364
+ *,
365
+ name: Optional[str] = None,
366
+ content_type: Optional[ContentType] = None,
367
+ metadata: Optional[Dict[str, str]] = None,
368
+ ttl: Optional[timedelta] = None,
369
+ **options: Unpack[LongRequestOptions],
370
+ ) -> AsyncStorageObject:
371
+ """Create and upload an object from a local file path.
372
+
373
+ :param file_path: Local filesystem path to read
374
+ :type file_path: str | Path
375
+ :param name: Optional object name; defaults to the file name
376
+ :type name: Optional[str]
377
+ :param content_type: Optional MIME type to apply to the object
378
+ :type content_type: Optional[ContentType]
379
+ :param metadata: Optional key-value metadata
380
+ :type metadata: Optional[Dict[str, str]]
381
+ :param ttl: Optional Time-To-Live, after which the object is automatically deleted
382
+ :type ttl: Optional[timedelta]
383
+ :param options: See :typeddict:`~runloop_api_client.sdk._types.LongRequestOptions` for available options
384
+ :return: Wrapper for the uploaded object
385
+ :rtype: AsyncStorageObject
386
+ :raises OSError: If the local file cannot be read
387
+ """
388
+ path = Path(file_path)
389
+
390
+ try:
391
+ content = await asyncio.to_thread(lambda: path.read_bytes())
392
+ except OSError as error:
393
+ raise OSError(f"Failed to read file {path}: {error}") from error
394
+
395
+ name = name or path.name
396
+ content_type = content_type or detect_content_type(str(file_path))
397
+ ttl_ms = int(ttl.total_seconds()) * 1000 if ttl else None
398
+ obj = await self.create(name=name, content_type=content_type, metadata=metadata, ttl_ms=ttl_ms, **options)
399
+ await obj.upload_content(content)
400
+ await obj.complete()
401
+ return obj
402
+
403
+ async def upload_from_dir(
404
+ self,
405
+ dir_path: str | Path,
406
+ *,
407
+ name: Optional[str] = None,
408
+ metadata: Optional[Dict[str, str]] = None,
409
+ ttl: Optional[timedelta] = None,
410
+ ignore: TarFilter | None = None,
411
+ **options: Unpack[LongRequestOptions],
412
+ ) -> AsyncStorageObject:
413
+ """Create and upload an object from a local directory.
414
+
415
+ The resulting object will be uploaded as a compressed tarball.
416
+
417
+ :param dir_path: Local filesystem directory path to tar
418
+ :type dir_path: str | Path
419
+ :param name: Optional object name; defaults to the directory name + '.tar.gz'
420
+ :type name: Optional[str]
421
+ :param metadata: Optional key-value metadata
422
+ :type metadata: Optional[Dict[str, str]]
423
+ :param ttl: Optional Time-To-Live, after which the object is automatically deleted
424
+ :type ttl: Optional[timedelta]
425
+ :param ignore: Optional tar filter function compatible with
426
+ :meth:`tarfile.TarFile.add`. If provided, it will be called for each
427
+ member to allow modification or exclusion (by returning ``None``).
428
+ :type ignore: Optional[TarFilter]
429
+ :param options: See :typeddict:`~runloop_api_client.sdk._types.LongRequestOptions`
430
+ for available options
431
+ :return: Wrapper for the uploaded object
432
+ :rtype: AsyncStorageObject
433
+ :raises OSError: If the local directory cannot be read
434
+ :raises ValueError: If ``dir_path`` does not point to a directory
435
+ """
436
+ path = Path(dir_path)
437
+ if not path.is_dir():
438
+ raise ValueError(f"dir_path must be a directory, got: {path}")
439
+
440
+ name = name or f"{path.name}.tar.gz"
441
+ ttl_ms = int(ttl.total_seconds()) * 1000 if ttl else None
442
+
443
+ def synchronous_io() -> bytes:
444
+ return build_directory_tar(path, tar_filter=ignore)
445
+
446
+ tar_bytes = await asyncio.to_thread(synchronous_io)
447
+
448
+ obj = await self.create(name=name, content_type="tgz", metadata=metadata, ttl_ms=ttl_ms, **options)
449
+ await obj.upload_content(tar_bytes)
450
+ await obj.complete()
451
+ return obj
452
+
453
+ async def upload_from_text(
454
+ self,
455
+ text: str,
456
+ *,
457
+ name: str,
458
+ metadata: Optional[Dict[str, str]] = None,
459
+ ttl: Optional[timedelta] = None,
460
+ **options: Unpack[LongRequestOptions],
461
+ ) -> AsyncStorageObject:
462
+ """Create and upload an object from a text payload.
463
+
464
+ :param text: Text content to upload
465
+ :type text: str
466
+ :param name: Object display name
467
+ :type name: str
468
+ :param metadata: Optional key-value metadata
469
+ :type metadata: Optional[Dict[str, str]]
470
+ :param ttl: Optional Time-To-Live, after which the object is automatically deleted
471
+ :type ttl: Optional[timedelta]
472
+ :param options: See :typeddict:`~runloop_api_client.sdk._types.LongRequestOptions` for available options
473
+ :return: Wrapper for the uploaded object
474
+ :rtype: AsyncStorageObject
475
+ """
476
+ ttl_ms = int(ttl.total_seconds()) * 1000 if ttl else None
477
+ obj = await self.create(name=name, content_type="text", metadata=metadata, ttl_ms=ttl_ms, **options)
478
+ await obj.upload_content(text)
479
+ await obj.complete()
480
+ return obj
481
+
482
+ async def upload_from_bytes(
483
+ self,
484
+ data: bytes,
485
+ *,
486
+ name: str,
487
+ content_type: ContentType,
488
+ metadata: Optional[Dict[str, str]] = None,
489
+ ttl: Optional[timedelta] = None,
490
+ **options: Unpack[LongRequestOptions],
491
+ ) -> AsyncStorageObject:
492
+ """Create and upload an object from a bytes payload.
493
+
494
+ :param data: Binary payload to upload
495
+ :type data: bytes
496
+ :param name: Object display name
497
+ :type name: str
498
+ :param content_type: MIME type describing the payload
499
+ :type content_type: ContentType
500
+ :param metadata: Optional key-value metadata
501
+ :type metadata: Optional[Dict[str, str]]
502
+ :param ttl: Optional Time-To-Live, after which the object is automatically deleted
503
+ :type ttl: Optional[timedelta]
504
+ :param options: See :typeddict:`~runloop_api_client.sdk._types.LongRequestOptions` for available options
505
+ :return: Wrapper for the uploaded object
506
+ :rtype: AsyncStorageObject
507
+ """
508
+ ttl_ms = int(ttl.total_seconds()) * 1000 if ttl else None
509
+ obj = await self.create(name=name, content_type=content_type, metadata=metadata, ttl_ms=ttl_ms, **options)
510
+ await obj.upload_content(data)
511
+ await obj.complete()
512
+ return obj
513
+
514
+
515
+ class AsyncScorerOps:
516
+ """Create and manage custom scorers (async). Access via ``runloop.scorer``.
517
+
518
+ Example:
519
+ >>> runloop = AsyncRunloopSDK()
520
+ >>> scorer = await runloop.scorer.create(type="my_scorer", bash_script="echo 'score=1.0'")
521
+ >>> all_scorers = await runloop.scorer.list()
522
+ """
523
+
524
+ def __init__(self, client: AsyncRunloop) -> None:
525
+ """Initialize AsyncScorerOps.
526
+
527
+ :param client: AsyncRunloop client instance
528
+ :type client: AsyncRunloop
529
+ """
530
+ self._client = client
531
+
532
+ async def create(self, **params: Unpack[SDKScorerCreateParams]) -> AsyncScorer:
533
+ """Create a new scorer with the given type and bash script.
534
+
535
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKScorerCreateParams` for available parameters
536
+ :return: The newly created scorer
537
+ :rtype: AsyncScorer
538
+ """
539
+ response = await self._client.scenarios.scorers.create(**params)
540
+ return AsyncScorer(self._client, response.id)
541
+
542
+ def from_id(self, scorer_id: str) -> AsyncScorer:
543
+ """Get an AsyncScorer instance for an existing scorer ID.
544
+
545
+ :param scorer_id: ID of the scorer
546
+ :type scorer_id: str
547
+ :return: AsyncScorer instance for the given ID
548
+ :rtype: AsyncScorer
549
+ """
550
+ return AsyncScorer(self._client, scorer_id)
551
+
552
+ async def list(self, **params: Unpack[SDKScorerListParams]) -> list[AsyncScorer]:
553
+ """List all scorers, optionally filtered by parameters.
554
+
555
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKScorerListParams` for available parameters
556
+ :return: List of scorers
557
+ :rtype: list[AsyncScorer]
558
+ """
559
+ page = await self._client.scenarios.scorers.list(**params)
560
+ return [AsyncScorer(self._client, item.id) async for item in page]
561
+
562
+
563
+ class AsyncAgentOps:
564
+ """High-level async manager for creating and managing agents.
565
+
566
+ Accessed via ``runloop.agent`` from :class:`AsyncRunloopSDK`, provides
567
+ coroutines to create, retrieve, and list agents from various sources (npm, pip, git, object storage).
568
+
569
+ Example:
570
+ >>> runloop = AsyncRunloopSDK()
571
+ >>> # Create agent from NPM package
572
+ >>> agent = await runloop.agent.create_from_npm(name="my-agent", package_name="@runloop/example-agent")
573
+ >>> # Create agent from Git repository
574
+ >>> agent = await runloop.agent.create_from_git(
575
+ ... name="git-agent", repository="https://github.com/user/agent-repo", ref="main"
576
+ ... )
577
+ >>> # List all agents
578
+ >>> agents = await runloop.agent.list(limit=10)
579
+ """
580
+
581
+ def __init__(self, client: AsyncRunloop) -> None:
582
+ """Initialize the manager.
583
+
584
+ :param client: Generated AsyncRunloop client to wrap
585
+ :type client: AsyncRunloop
586
+ """
587
+ self._client = client
588
+
589
+ async def create(
590
+ self,
591
+ **params: Unpack[SDKAgentCreateParams],
592
+ ) -> AsyncAgent:
593
+ """Create a new agent.
594
+
595
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKAgentCreateParams` for available parameters
596
+ :return: Wrapper bound to the newly created agent
597
+ :rtype: AsyncAgent
598
+ """
599
+ agent_view = await self._client.agents.create(
600
+ **params,
601
+ )
602
+ return AsyncAgent(self._client, agent_view.id, agent_view)
603
+
604
+ async def create_from_npm(
605
+ self,
606
+ *,
607
+ package_name: str,
608
+ registry_url: Optional[str] = None,
609
+ agent_setup: Optional[list[str]] = None,
610
+ **params: Unpack[SDKAgentCreateParams],
611
+ ) -> AsyncAgent:
612
+ """Create an agent from an NPM package.
613
+
614
+ :param package_name: NPM package name
615
+ :type package_name: str
616
+ :param registry_url: NPM registry URL, defaults to None
617
+ :type registry_url: Optional[str], optional
618
+ :param agent_setup: Setup commands to run after installation, defaults to None
619
+ :type agent_setup: Optional[list[str]], optional
620
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKAgentCreateParams` for additional parameters (excluding 'source')
621
+ :return: Wrapper bound to the newly created agent
622
+ :rtype: AsyncAgent
623
+ :raises ValueError: If 'source' is provided in params
624
+ """
625
+ if "source" in params:
626
+ raise ValueError(
627
+ "Cannot specify 'source' when using create_from_npm(); source is automatically set to npm configuration"
628
+ )
629
+
630
+ npm_config: Npm = {"package_name": package_name}
631
+ if registry_url is not None:
632
+ npm_config["registry_url"] = registry_url
633
+ if agent_setup is not None:
634
+ npm_config["agent_setup"] = agent_setup
635
+
636
+ params["source"] = {"type": "npm", "npm": npm_config}
637
+ return await self.create(**params)
638
+
639
+ async def create_from_pip(
640
+ self,
641
+ *,
642
+ package_name: str,
643
+ registry_url: Optional[str] = None,
644
+ agent_setup: Optional[list[str]] = None,
645
+ **params: Unpack[SDKAgentCreateParams],
646
+ ) -> AsyncAgent:
647
+ """Create an agent from a Pip package.
648
+
649
+ :param package_name: Pip package name
650
+ :type package_name: str
651
+ :param registry_url: Pip registry URL, defaults to None
652
+ :type registry_url: Optional[str], optional
653
+ :param agent_setup: Setup commands to run after installation, defaults to None
654
+ :type agent_setup: Optional[list[str]], optional
655
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKAgentCreateParams` for additional parameters (excluding 'source')
656
+ :return: Wrapper bound to the newly created agent
657
+ :rtype: AsyncAgent
658
+ :raises ValueError: If 'source' is provided in params
659
+ """
660
+ if "source" in params:
661
+ raise ValueError(
662
+ "Cannot specify 'source' when using create_from_pip(); source is automatically set to pip configuration"
663
+ )
664
+
665
+ pip_config: Pip = {"package_name": package_name}
666
+ if registry_url is not None:
667
+ pip_config["registry_url"] = registry_url
668
+ if agent_setup is not None:
669
+ pip_config["agent_setup"] = agent_setup
670
+
671
+ params["source"] = {"type": "pip", "pip": pip_config}
672
+ return await self.create(**params)
673
+
674
+ async def create_from_git(
675
+ self,
676
+ *,
677
+ repository: str,
678
+ ref: Optional[str] = None,
679
+ agent_setup: Optional[list[str]] = None,
680
+ **params: Unpack[SDKAgentCreateParams],
681
+ ) -> AsyncAgent:
682
+ """Create an agent from a Git repository.
683
+
684
+ :param repository: Git repository URL
685
+ :type repository: str
686
+ :param ref: Optional Git ref (branch/tag/commit), defaults to main/HEAD
687
+ :type ref: Optional[str], optional
688
+ :param agent_setup: Setup commands to run after cloning, defaults to None
689
+ :type agent_setup: Optional[list[str]], optional
690
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKAgentCreateParams` for additional parameters (excluding 'source')
691
+ :return: Wrapper bound to the newly created agent
692
+ :rtype: AsyncAgent
693
+ :raises ValueError: If 'source' is provided in params
694
+ """
695
+ if "source" in params:
696
+ raise ValueError(
697
+ "Cannot specify 'source' when using create_from_git(); source is automatically set to git configuration"
698
+ )
699
+
700
+ git_config: Git = {"repository": repository}
701
+ if ref is not None:
702
+ git_config["ref"] = ref
703
+ if agent_setup is not None:
704
+ git_config["agent_setup"] = agent_setup
705
+
706
+ params["source"] = {"type": "git", "git": git_config}
707
+ return await self.create(**params)
708
+
709
+ async def create_from_object(
710
+ self,
711
+ *,
712
+ object_id: str,
713
+ agent_setup: Optional[list[str]] = None,
714
+ **params: Unpack[SDKAgentCreateParams],
715
+ ) -> AsyncAgent:
716
+ """Create an agent from a storage object.
717
+
718
+ :param object_id: Storage object ID
719
+ :type object_id: str
720
+ :param agent_setup: Setup commands to run after unpacking, defaults to None
721
+ :type agent_setup: Optional[list[str]], optional
722
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKAgentCreateParams` for additional parameters (excluding 'source')
723
+ :return: Wrapper bound to the newly created agent
724
+ :rtype: AsyncAgent
725
+ :raises ValueError: If 'source' is provided in params
726
+ """
727
+ if "source" in params:
728
+ raise ValueError(
729
+ "Cannot specify 'source' when using create_from_object(); source is automatically set to object configuration"
730
+ )
731
+
732
+ object_config: Object = {"object_id": object_id}
733
+ if agent_setup is not None:
734
+ object_config["agent_setup"] = agent_setup
735
+
736
+ params["source"] = {"type": "object", "object": object_config}
737
+ return await self.create(**params)
738
+
739
+ def from_id(self, agent_id: str) -> AsyncAgent:
740
+ """Attach to an existing agent by ID.
741
+
742
+ :param agent_id: Existing agent ID
743
+ :type agent_id: str
744
+ :return: Wrapper bound to the requested agent
745
+ :rtype: AsyncAgent
746
+ """
747
+ return AsyncAgent(self._client, agent_id)
748
+
749
+ async def list(
750
+ self,
751
+ **params: Unpack[SDKAgentListParams],
752
+ ) -> list[AsyncAgent]:
753
+ """List agents accessible to the caller.
754
+
755
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKAgentListParams` for available parameters
756
+ :return: Collection of agent wrappers
757
+ :rtype: list[AsyncAgent]
758
+ """
759
+ page = await self._client.agents.list(
760
+ **params,
761
+ )
762
+ return [AsyncAgent(self._client, item.id, item) for item in page.agents]
763
+
764
+
765
+ class AsyncScenarioOps:
766
+ """Manage scenarios (async). Access via ``runloop.scenario``.
767
+
768
+ Example:
769
+ >>> runloop = AsyncRunloopSDK()
770
+ >>> scenario = runloop.scenario.from_id("scn-xxx")
771
+ >>> run = await scenario.run()
772
+ >>> scenarios = await runloop.scenario.list()
773
+
774
+ Example using builder:
775
+ >>> builder = (
776
+ ... runloop.scenario.builder("my-scenario")
777
+ ... .from_blueprint(blueprint)
778
+ ... .with_problem_statement("Fix the bug")
779
+ ... .add_test_command_scorer("tests", test_command="pytest")
780
+ ... )
781
+ >>> params = builder.build()
782
+ >>> scenario = await runloop.scenario.create(**params) # equivalent to builder.push()
783
+ """
784
+
785
+ def __init__(self, client: AsyncRunloop) -> None:
786
+ """Initialize AsyncScenarioOps.
787
+
788
+ :param client: AsyncRunloop client instance
789
+ :type client: AsyncRunloop
790
+ """
791
+ self._client = client
792
+
793
+ def builder(self, name: str) -> AsyncScenarioBuilder:
794
+ """Create a new scenario builder.
795
+
796
+ :param name: Name for the scenario
797
+ :type name: str
798
+ :return: A new AsyncScenarioBuilder instance
799
+ :rtype: AsyncScenarioBuilder
800
+ """
801
+ return AsyncScenarioBuilder(name, self._client)
802
+
803
+ def from_id(self, scenario_id: str) -> AsyncScenario:
804
+ """Get an AsyncScenario instance for an existing scenario ID.
805
+
806
+ :param scenario_id: ID of the scenario
807
+ :type scenario_id: str
808
+ :return: AsyncScenario instance for the given ID
809
+ :rtype: AsyncScenario
810
+ """
811
+ return AsyncScenario(self._client, scenario_id)
812
+
813
+ async def list(self, **params: Unpack[SDKScenarioListParams]) -> list[AsyncScenario]:
814
+ """List all scenarios, optionally filtered by parameters.
815
+
816
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKScenarioListParams` for available parameters
817
+ :return: List of scenarios
818
+ :rtype: list[AsyncScenario]
819
+ """
820
+ page = await self._client.scenarios.list(**params)
821
+ return [AsyncScenario(self._client, item.id) async for item in page]
822
+
823
+
824
+ class AsyncBenchmarkOps:
825
+ """Manage benchmarks (async). Access via ``runloop.benchmark``.
826
+
827
+ Example:
828
+ >>> runloop = AsyncRunloopSDK()
829
+ >>> benchmarks = await runloop.benchmark.list()
830
+ >>> benchmark = runloop.benchmark.from_id("bmd_xxx")
831
+ >>> run = await benchmark.start_run(run_name="evaluation-v1")
832
+ """
833
+
834
+ def __init__(self, client: AsyncRunloop) -> None:
835
+ """Initialize AsyncBenchmarkOps.
836
+
837
+ :param client: AsyncRunloop client instance
838
+ :type client: AsyncRunloop
839
+ """
840
+ self._client = client
841
+
842
+ async def create(self, **params: Unpack[SDKBenchmarkCreateParams]) -> AsyncBenchmark:
843
+ """Create a new benchmark.
844
+
845
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKBenchmarkCreateParams` for available parameters
846
+ :return: The newly created benchmark
847
+ :rtype: AsyncBenchmark
848
+ """
849
+ response = await self._client.benchmarks.create(**params)
850
+ return AsyncBenchmark(self._client, response.id)
851
+
852
+ def from_id(self, benchmark_id: str) -> AsyncBenchmark:
853
+ """Get an AsyncBenchmark instance for an existing benchmark ID.
854
+
855
+ :param benchmark_id: ID of the benchmark
856
+ :type benchmark_id: str
857
+ :return: AsyncBenchmark instance for the given ID
858
+ :rtype: AsyncBenchmark
859
+ """
860
+ return AsyncBenchmark(self._client, benchmark_id)
861
+
862
+ async def list(self, **params: Unpack[SDKBenchmarkListParams]) -> list[AsyncBenchmark]:
863
+ """List all benchmarks, optionally filtered by parameters.
864
+
865
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKBenchmarkListParams` for available parameters
866
+ :return: List of benchmarks
867
+ :rtype: list[AsyncBenchmark]
868
+ """
869
+ page = await self._client.benchmarks.list(**params)
870
+ return [AsyncBenchmark(self._client, item.id) for item in page.benchmarks]
871
+
872
+
873
+ class AsyncNetworkPolicyOps:
874
+ """High-level async manager for creating and managing network policies.
875
+
876
+ Accessed via ``runloop.network_policy`` from :class:`AsyncRunloopSDK`, provides
877
+ coroutines to create, retrieve, update, delete, and list network policies.
878
+
879
+ Example:
880
+ >>> runloop = AsyncRunloopSDK()
881
+ >>> policy = await runloop.network_policy.create(
882
+ ... name="my-policy",
883
+ ... allowed_hostnames=["github.com", "*.npmjs.org"],
884
+ ... )
885
+ >>> policies = await runloop.network_policy.list()
886
+ """
887
+
888
+ def __init__(self, client: AsyncRunloop) -> None:
889
+ """Initialize AsyncNetworkPolicyOps.
890
+
891
+ :param client: AsyncRunloop client instance
892
+ :type client: AsyncRunloop
893
+ """
894
+ self._client = client
895
+
896
+ async def create(self, **params: Unpack[SDKNetworkPolicyCreateParams]) -> AsyncNetworkPolicy:
897
+ """Create a new network policy.
898
+
899
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKNetworkPolicyCreateParams` for available parameters
900
+ :return: The newly created network policy
901
+ :rtype: AsyncNetworkPolicy
902
+ """
903
+ response = await self._client.network_policies.create(**params)
904
+ return AsyncNetworkPolicy(self._client, response.id)
905
+
906
+ def from_id(self, network_policy_id: str) -> AsyncNetworkPolicy:
907
+ """Get an AsyncNetworkPolicy instance for an existing network policy ID.
908
+
909
+ :param network_policy_id: ID of the network policy
910
+ :type network_policy_id: str
911
+ :return: AsyncNetworkPolicy instance for the given ID
912
+ :rtype: AsyncNetworkPolicy
913
+ """
914
+ return AsyncNetworkPolicy(self._client, network_policy_id)
915
+
916
+ async def list(self, **params: Unpack[SDKNetworkPolicyListParams]) -> list[AsyncNetworkPolicy]:
917
+ """List all network policies, optionally filtered by parameters.
918
+
919
+ :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKNetworkPolicyListParams` for available parameters
920
+ :return: List of network policies
921
+ :rtype: list[AsyncNetworkPolicy]
922
+ """
923
+ page = self._client.network_policies.list(**params)
924
+ return [AsyncNetworkPolicy(self._client, item.id) async for item in page]
925
+
926
+
927
+ class AsyncRunloopSDK:
928
+ """High-level asynchronous entry point for the Runloop SDK.
929
+
930
+ Provides a Pythonic, object-oriented interface for managing devboxes,
931
+ blueprints, snapshots, and storage objects. Exposes the generated async REST
932
+ client via the ``api`` attribute for advanced use cases.
933
+
934
+ :ivar api: Direct access to the generated async REST API client
935
+ :vartype api: AsyncRunloop
936
+ :ivar agent: High-level async interface for agent management.
937
+ :vartype agent: AsyncAgentOps
938
+ :ivar benchmark: High-level async interface for benchmark management
939
+ :vartype benchmark: AsyncBenchmarkOps
940
+ :ivar devbox: High-level async interface for devbox management
941
+ :vartype devbox: AsyncDevboxOps
942
+ :ivar blueprint: High-level async interface for blueprint management
943
+ :vartype blueprint: AsyncBlueprintOps
944
+ :ivar scenario: High-level async interface for scenario management
945
+ :vartype scenario: AsyncScenarioOps
946
+ :ivar scorer: High-level async interface for scorer management
947
+ :vartype scorer: AsyncScorerOps
948
+ :ivar snapshot: High-level async interface for snapshot management
949
+ :vartype snapshot: AsyncSnapshotOps
950
+ :ivar storage_object: High-level async interface for storage object management
951
+ :vartype storage_object: AsyncStorageObjectOps
952
+ :ivar network_policy: High-level async interface for network policy management
953
+ :vartype network_policy: AsyncNetworkPolicyOps
954
+
955
+ Example:
956
+ >>> runloop = AsyncRunloopSDK() # Uses RUNLOOP_API_KEY env var
957
+ >>> devbox = await runloop.devbox.create(name="my-devbox")
958
+ >>> result = await devbox.cmd.exec("echo 'hello'")
959
+ >>> print(await result.stdout())
960
+ >>> await devbox.shutdown()
961
+ """
962
+
963
+ api: AsyncRunloop
964
+ agent: AsyncAgentOps
965
+ benchmark: AsyncBenchmarkOps
966
+ devbox: AsyncDevboxOps
967
+ blueprint: AsyncBlueprintOps
968
+ network_policy: AsyncNetworkPolicyOps
969
+ scenario: AsyncScenarioOps
970
+ scorer: AsyncScorerOps
971
+ snapshot: AsyncSnapshotOps
972
+ storage_object: AsyncStorageObjectOps
973
+
974
+ def __init__(
975
+ self,
976
+ *,
977
+ bearer_token: str | None = None,
978
+ base_url: str | httpx.URL | None = None,
979
+ timeout: float | Timeout | None | NotGiven = not_given,
980
+ max_retries: int = DEFAULT_MAX_RETRIES,
981
+ default_headers: Mapping[str, str] | None = None,
982
+ default_query: Mapping[str, object] | None = None,
983
+ http_client: httpx.AsyncClient | None = None,
984
+ ) -> None:
985
+ """Configure the asynchronous SDK wrapper.
986
+
987
+ :param bearer_token: API token; falls back to ``RUNLOOP_API_KEY`` env var, defaults to None
988
+ :type bearer_token: str | None, optional
989
+ :param base_url: Override the API base URL, defaults to None
990
+ :type base_url: str | httpx.URL | None, optional
991
+ :param timeout: Request timeout (seconds) or ``Timeout`` object, defaults to not_given
992
+ :type timeout: float | Timeout | None | NotGiven, optional
993
+ :param max_retries: Maximum automatic retry attempts, defaults to DEFAULT_MAX_RETRIES
994
+ :type max_retries: int, optional
995
+ :param default_headers: Headers merged into every request, defaults to None
996
+ :type default_headers: Mapping[str, str] | None, optional
997
+ :param default_query: Default query parameters merged into every request, defaults to None
998
+ :type default_query: Mapping[str, object] | None, optional
999
+ :param http_client: Custom ``httpx.AsyncClient`` instance to reuse, defaults to None
1000
+ :type http_client: httpx.AsyncClient | None, optional
1001
+ """
1002
+ self.api = AsyncRunloop(
1003
+ bearer_token=bearer_token,
1004
+ base_url=base_url,
1005
+ timeout=timeout,
1006
+ max_retries=max_retries,
1007
+ default_headers=default_headers,
1008
+ default_query=default_query,
1009
+ http_client=http_client,
1010
+ )
1011
+
1012
+ self.agent = AsyncAgentOps(self.api)
1013
+ self.benchmark = AsyncBenchmarkOps(self.api)
1014
+ self.devbox = AsyncDevboxOps(self.api)
1015
+ self.blueprint = AsyncBlueprintOps(self.api)
1016
+ self.network_policy = AsyncNetworkPolicyOps(self.api)
1017
+ self.scenario = AsyncScenarioOps(self.api)
1018
+ self.scorer = AsyncScorerOps(self.api)
1019
+ self.snapshot = AsyncSnapshotOps(self.api)
1020
+ self.storage_object = AsyncStorageObjectOps(self.api)
1021
+
1022
+ async def aclose(self) -> None:
1023
+ """Close the underlying HTTP client and release resources."""
1024
+ await self.api.close()
1025
+
1026
+ async def __aenter__(self) -> "AsyncRunloopSDK":
1027
+ """Allow ``async with AsyncRunloopSDK() as runloop`` usage.
1028
+
1029
+ :return: The active SDK instance
1030
+ :rtype: AsyncRunloopSDK
1031
+ """
1032
+ return self
1033
+
1034
+ async def __aexit__(self, *_exc_info: object) -> None:
1035
+ """Ensure the API client closes when leaving the context manager."""
1036
+ await self.aclose()