runloop-api-client 1.3.2__py3-none-any.whl → 1.4.0__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.
@@ -86,6 +86,7 @@ from ._exceptions import (
86
86
  APIConnectionError,
87
87
  APIResponseValidationError,
88
88
  )
89
+ from ._utils._json import openapi_dumps
89
90
 
90
91
  log: logging.Logger = logging.getLogger(__name__)
91
92
 
@@ -554,8 +555,10 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
554
555
  kwargs["content"] = options.content
555
556
  elif isinstance(json_data, bytes):
556
557
  kwargs["content"] = json_data
557
- else:
558
- kwargs["json"] = json_data if is_given(json_data) else None
558
+ elif not files:
559
+ # Don't set content when JSON is sent as multipart/form-data,
560
+ # since httpx's content param overrides other body arguments
561
+ kwargs["content"] = openapi_dumps(json_data) if is_given(json_data) and json_data is not None else None
559
562
  kwargs["files"] = files
560
563
  else:
561
564
  headers.pop("Content-Type", None)
@@ -42,6 +42,7 @@ if TYPE_CHECKING:
42
42
  repositories,
43
43
  benchmark_jobs,
44
44
  benchmark_runs,
45
+ gateway_configs,
45
46
  network_policies,
46
47
  )
47
48
  from .resources.agents import AgentsResource, AsyncAgentsResource
@@ -52,6 +53,7 @@ if TYPE_CHECKING:
52
53
  from .resources.repositories import RepositoriesResource, AsyncRepositoriesResource
53
54
  from .resources.benchmark_jobs import BenchmarkJobsResource, AsyncBenchmarkJobsResource
54
55
  from .resources.benchmark_runs import BenchmarkRunsResource, AsyncBenchmarkRunsResource
56
+ from .resources.gateway_configs import GatewayConfigsResource, AsyncGatewayConfigsResource
55
57
  from .resources.network_policies import NetworkPoliciesResource, AsyncNetworkPoliciesResource
56
58
  from .resources.devboxes.devboxes import DevboxesResource, AsyncDevboxesResource
57
59
  from .resources.scenarios.scenarios import ScenariosResource, AsyncScenariosResource
@@ -182,6 +184,12 @@ class Runloop(SyncAPIClient):
182
184
 
183
185
  return NetworkPoliciesResource(self)
184
186
 
187
+ @cached_property
188
+ def gateway_configs(self) -> GatewayConfigsResource:
189
+ from .resources.gateway_configs import GatewayConfigsResource
190
+
191
+ return GatewayConfigsResource(self)
192
+
185
193
  @cached_property
186
194
  def with_raw_response(self) -> RunloopWithRawResponse:
187
195
  return RunloopWithRawResponse(self)
@@ -418,6 +426,12 @@ class AsyncRunloop(AsyncAPIClient):
418
426
 
419
427
  return AsyncNetworkPoliciesResource(self)
420
428
 
429
+ @cached_property
430
+ def gateway_configs(self) -> AsyncGatewayConfigsResource:
431
+ from .resources.gateway_configs import AsyncGatewayConfigsResource
432
+
433
+ return AsyncGatewayConfigsResource(self)
434
+
421
435
  @cached_property
422
436
  def with_raw_response(self) -> AsyncRunloopWithRawResponse:
423
437
  return AsyncRunloopWithRawResponse(self)
@@ -603,6 +617,12 @@ class RunloopWithRawResponse:
603
617
 
604
618
  return NetworkPoliciesResourceWithRawResponse(self._client.network_policies)
605
619
 
620
+ @cached_property
621
+ def gateway_configs(self) -> gateway_configs.GatewayConfigsResourceWithRawResponse:
622
+ from .resources.gateway_configs import GatewayConfigsResourceWithRawResponse
623
+
624
+ return GatewayConfigsResourceWithRawResponse(self._client.gateway_configs)
625
+
606
626
 
607
627
  class AsyncRunloopWithRawResponse:
608
628
  _client: AsyncRunloop
@@ -676,6 +696,12 @@ class AsyncRunloopWithRawResponse:
676
696
 
677
697
  return AsyncNetworkPoliciesResourceWithRawResponse(self._client.network_policies)
678
698
 
699
+ @cached_property
700
+ def gateway_configs(self) -> gateway_configs.AsyncGatewayConfigsResourceWithRawResponse:
701
+ from .resources.gateway_configs import AsyncGatewayConfigsResourceWithRawResponse
702
+
703
+ return AsyncGatewayConfigsResourceWithRawResponse(self._client.gateway_configs)
704
+
679
705
 
680
706
  class RunloopWithStreamedResponse:
681
707
  _client: Runloop
@@ -749,6 +775,12 @@ class RunloopWithStreamedResponse:
749
775
 
750
776
  return NetworkPoliciesResourceWithStreamingResponse(self._client.network_policies)
751
777
 
778
+ @cached_property
779
+ def gateway_configs(self) -> gateway_configs.GatewayConfigsResourceWithStreamingResponse:
780
+ from .resources.gateway_configs import GatewayConfigsResourceWithStreamingResponse
781
+
782
+ return GatewayConfigsResourceWithStreamingResponse(self._client.gateway_configs)
783
+
752
784
 
753
785
  class AsyncRunloopWithStreamedResponse:
754
786
  _client: AsyncRunloop
@@ -822,6 +854,12 @@ class AsyncRunloopWithStreamedResponse:
822
854
 
823
855
  return AsyncNetworkPoliciesResourceWithStreamingResponse(self._client.network_policies)
824
856
 
857
+ @cached_property
858
+ def gateway_configs(self) -> gateway_configs.AsyncGatewayConfigsResourceWithStreamingResponse:
859
+ from .resources.gateway_configs import AsyncGatewayConfigsResourceWithStreamingResponse
860
+
861
+ return AsyncGatewayConfigsResourceWithStreamingResponse(self._client.gateway_configs)
862
+
825
863
 
826
864
  Client = Runloop
827
865
 
@@ -139,6 +139,7 @@ def model_dump(
139
139
  exclude_defaults: bool = False,
140
140
  warnings: bool = True,
141
141
  mode: Literal["json", "python"] = "python",
142
+ by_alias: bool | None = None,
142
143
  ) -> dict[str, Any]:
143
144
  if (not PYDANTIC_V1) or hasattr(model, "model_dump"):
144
145
  return model.model_dump(
@@ -148,13 +149,12 @@ def model_dump(
148
149
  exclude_defaults=exclude_defaults,
149
150
  # warnings are not supported in Pydantic v1
150
151
  warnings=True if PYDANTIC_V1 else warnings,
152
+ by_alias=by_alias,
151
153
  )
152
154
  return cast(
153
155
  "dict[str, Any]",
154
156
  model.dict( # pyright: ignore[reportDeprecated, reportUnnecessaryCast]
155
- exclude=exclude,
156
- exclude_unset=exclude_unset,
157
- exclude_defaults=exclude_defaults,
157
+ exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, by_alias=bool(by_alias)
158
158
  ),
159
159
  )
160
160
 
@@ -0,0 +1,35 @@
1
+ import json
2
+ from typing import Any
3
+ from datetime import datetime
4
+ from typing_extensions import override
5
+
6
+ import pydantic
7
+
8
+ from .._compat import model_dump
9
+
10
+
11
+ def openapi_dumps(obj: Any) -> bytes:
12
+ """
13
+ Serialize an object to UTF-8 encoded JSON bytes.
14
+
15
+ Extends the standard json.dumps with support for additional types
16
+ commonly used in the SDK, such as `datetime`, `pydantic.BaseModel`, etc.
17
+ """
18
+ return json.dumps(
19
+ obj,
20
+ cls=_CustomEncoder,
21
+ # Uses the same defaults as httpx's JSON serialization
22
+ ensure_ascii=False,
23
+ separators=(",", ":"),
24
+ allow_nan=False,
25
+ ).encode()
26
+
27
+
28
+ class _CustomEncoder(json.JSONEncoder):
29
+ @override
30
+ def default(self, o: Any) -> Any:
31
+ if isinstance(o, datetime):
32
+ return o.isoformat()
33
+ if isinstance(o, pydantic.BaseModel):
34
+ return model_dump(o, exclude_unset=True, mode="json", by_alias=True)
35
+ return super().default(o)
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "runloop_api_client"
4
- __version__ = "1.3.2" # x-release-please-version
4
+ __version__ = "1.4.0" # x-release-please-version
@@ -30,6 +30,8 @@ __all__ = [
30
30
  "AsyncObjectsCursorIDPage",
31
31
  "SyncNetworkPoliciesCursorIDPage",
32
32
  "AsyncNetworkPoliciesCursorIDPage",
33
+ "SyncGatewayConfigsCursorIDPage",
34
+ "AsyncGatewayConfigsCursorIDPage",
33
35
  ]
34
36
 
35
37
  _T = TypeVar("_T")
@@ -95,6 +97,11 @@ class NetworkPoliciesCursorIDPageItem(Protocol):
95
97
  id: str
96
98
 
97
99
 
100
+ @runtime_checkable
101
+ class GatewayConfigsCursorIDPageItem(Protocol):
102
+ id: str
103
+
104
+
98
105
  class SyncBlueprintsCursorIDPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
99
106
  blueprints: List[_T]
100
107
  has_more: Optional[bool] = None
@@ -909,3 +916,71 @@ class AsyncNetworkPoliciesCursorIDPage(BaseAsyncPage[_T], BasePage[_T], Generic[
909
916
  return None
910
917
 
911
918
  return PageInfo(params={"starting_after": item.id})
919
+
920
+
921
+ class SyncGatewayConfigsCursorIDPage(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
922
+ gateway_configs: List[_T]
923
+ has_more: Optional[bool] = None
924
+ total_count: Optional[int] = None
925
+
926
+ @override
927
+ def _get_page_items(self) -> List[_T]:
928
+ gateway_configs = self.gateway_configs
929
+ if not gateway_configs:
930
+ return []
931
+ return gateway_configs
932
+
933
+ @override
934
+ def has_next_page(self) -> bool:
935
+ has_more = self.has_more
936
+ if has_more is not None and has_more is False:
937
+ return False
938
+
939
+ return super().has_next_page()
940
+
941
+ @override
942
+ def next_page_info(self) -> Optional[PageInfo]:
943
+ gateway_configs = self.gateway_configs
944
+ if not gateway_configs:
945
+ return None
946
+
947
+ item = cast(Any, gateway_configs[-1])
948
+ if not isinstance(item, GatewayConfigsCursorIDPageItem) or item.id is None: # pyright: ignore[reportUnnecessaryComparison]
949
+ # TODO emit warning log
950
+ return None
951
+
952
+ return PageInfo(params={"starting_after": item.id})
953
+
954
+
955
+ class AsyncGatewayConfigsCursorIDPage(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
956
+ gateway_configs: List[_T]
957
+ has_more: Optional[bool] = None
958
+ total_count: Optional[int] = None
959
+
960
+ @override
961
+ def _get_page_items(self) -> List[_T]:
962
+ gateway_configs = self.gateway_configs
963
+ if not gateway_configs:
964
+ return []
965
+ return gateway_configs
966
+
967
+ @override
968
+ def has_next_page(self) -> bool:
969
+ has_more = self.has_more
970
+ if has_more is not None and has_more is False:
971
+ return False
972
+
973
+ return super().has_next_page()
974
+
975
+ @override
976
+ def next_page_info(self) -> Optional[PageInfo]:
977
+ gateway_configs = self.gateway_configs
978
+ if not gateway_configs:
979
+ return None
980
+
981
+ item = cast(Any, gateway_configs[-1])
982
+ if not isinstance(item, GatewayConfigsCursorIDPageItem) or item.id is None: # pyright: ignore[reportUnnecessaryComparison]
983
+ # TODO emit warning log
984
+ return None
985
+
986
+ return PageInfo(params={"starting_after": item.id})
@@ -80,6 +80,14 @@ from .benchmark_runs import (
80
80
  BenchmarkRunsResourceWithStreamingResponse,
81
81
  AsyncBenchmarkRunsResourceWithStreamingResponse,
82
82
  )
83
+ from .gateway_configs import (
84
+ GatewayConfigsResource,
85
+ AsyncGatewayConfigsResource,
86
+ GatewayConfigsResourceWithRawResponse,
87
+ AsyncGatewayConfigsResourceWithRawResponse,
88
+ GatewayConfigsResourceWithStreamingResponse,
89
+ AsyncGatewayConfigsResourceWithStreamingResponse,
90
+ )
83
91
  from .network_policies import (
84
92
  NetworkPoliciesResource,
85
93
  AsyncNetworkPoliciesResource,
@@ -156,4 +164,10 @@ __all__ = [
156
164
  "AsyncNetworkPoliciesResourceWithRawResponse",
157
165
  "NetworkPoliciesResourceWithStreamingResponse",
158
166
  "AsyncNetworkPoliciesResourceWithStreamingResponse",
167
+ "GatewayConfigsResource",
168
+ "AsyncGatewayConfigsResource",
169
+ "GatewayConfigsResourceWithRawResponse",
170
+ "AsyncGatewayConfigsResourceWithRawResponse",
171
+ "GatewayConfigsResourceWithStreamingResponse",
172
+ "AsyncGatewayConfigsResourceWithStreamingResponse",
159
173
  ]
@@ -185,6 +185,7 @@ class DevboxesResource(SyncAPIResource):
185
185
  entrypoint: Optional[str] | Omit = omit,
186
186
  environment_variables: Optional[Dict[str, str]] | Omit = omit,
187
187
  file_mounts: Optional[Dict[str, str]] | Omit = omit,
188
+ gateways: Optional[Dict[str, devbox_create_params.Gateways]] | Omit = omit,
188
189
  launch_parameters: Optional[LaunchParameters] | Omit = omit,
189
190
  metadata: Optional[Dict[str, str]] | Omit = omit,
190
191
  mounts: Optional[Iterable[Mount]] | Omit = omit,
@@ -192,6 +193,7 @@ class DevboxesResource(SyncAPIResource):
192
193
  repo_connection_id: Optional[str] | Omit = omit,
193
194
  secrets: Optional[Dict[str, str]] | Omit = omit,
194
195
  snapshot_id: Optional[str] | Omit = omit,
196
+ tunnel: Optional[devbox_create_params.Tunnel] | Omit = omit,
195
197
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
196
198
  # The extra values given here take precedence over values defined on the client or passed to this method.
197
199
  extra_headers: Headers | None = None,
@@ -227,6 +229,12 @@ class DevboxesResource(SyncAPIResource):
227
229
 
228
230
  file_mounts: Map of paths and file contents to write before setup. Use mounts instead.
229
231
 
232
+ gateways: [Beta] (Optional) Gateway specifications for credential proxying. Map key is the
233
+ environment variable prefix (e.g., 'GWS_ANTHROPIC'). The gateway will proxy
234
+ requests to external APIs using the specified credential without exposing the
235
+ real API key. Example: {'GWS_ANTHROPIC': {'gateway': 'anthropic', 'secret':
236
+ 'my_claude_key'}}
237
+
230
238
  launch_parameters: Parameters to configure the resources and launch time behavior of the Devbox.
231
239
 
232
240
  metadata: User defined metadata to attach to the devbox for organization.
@@ -245,6 +253,10 @@ class DevboxesResource(SyncAPIResource):
245
253
  snapshot_id: Snapshot ID to use for the Devbox. Only one of (Snapshot ID, Blueprint ID,
246
254
  Blueprint name) should be specified.
247
255
 
256
+ tunnel: (Optional) Configuration for creating a V2 tunnel at Devbox launch time. When
257
+ specified, a tunnel will be automatically provisioned and the tunnel details
258
+ will be included in the Devbox response.
259
+
248
260
  extra_headers: Send extra headers
249
261
 
250
262
  extra_query: Add additional query parameters to the request
@@ -265,6 +277,7 @@ class DevboxesResource(SyncAPIResource):
265
277
  "entrypoint": entrypoint,
266
278
  "environment_variables": environment_variables,
267
279
  "file_mounts": file_mounts,
280
+ "gateways": gateways,
268
281
  "launch_parameters": launch_parameters,
269
282
  "metadata": metadata,
270
283
  "mounts": mounts,
@@ -272,6 +285,7 @@ class DevboxesResource(SyncAPIResource):
272
285
  "repo_connection_id": repo_connection_id,
273
286
  "secrets": secrets,
274
287
  "snapshot_id": snapshot_id,
288
+ "tunnel": tunnel,
275
289
  },
276
290
  devbox_create_params.DevboxCreateParams,
277
291
  ),
@@ -480,6 +494,7 @@ class DevboxesResource(SyncAPIResource):
480
494
  entrypoint: Optional[str] | Omit = omit,
481
495
  environment_variables: Optional[Dict[str, str]] | Omit = omit,
482
496
  file_mounts: Optional[Dict[str, str]] | Omit = omit,
497
+ gateways: Optional[Dict[str, devbox_create_params.Gateways]] | Omit = omit,
483
498
  launch_parameters: Optional[LaunchParameters] | Omit = omit,
484
499
  metadata: Optional[Dict[str, str]] | Omit = omit,
485
500
  mounts: Optional[Iterable[Mount]] | Omit = omit,
@@ -488,6 +503,7 @@ class DevboxesResource(SyncAPIResource):
488
503
  repo_connection_id: Optional[str] | Omit = omit,
489
504
  secrets: Optional[Dict[str, str]] | Omit = omit,
490
505
  snapshot_id: Optional[str] | Omit = omit,
506
+ tunnel: Optional[devbox_create_params.Tunnel] | Omit = omit,
491
507
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
492
508
  # The extra values given here take precedence over values defined on the client or passed to this method.
493
509
  extra_headers: Headers | None = None,
@@ -519,6 +535,7 @@ class DevboxesResource(SyncAPIResource):
519
535
  entrypoint=entrypoint,
520
536
  environment_variables=environment_variables,
521
537
  file_mounts=file_mounts,
538
+ gateways=gateways,
522
539
  launch_parameters=launch_parameters,
523
540
  metadata=metadata,
524
541
  mounts=mounts,
@@ -526,6 +543,7 @@ class DevboxesResource(SyncAPIResource):
526
543
  repo_connection_id=repo_connection_id,
527
544
  secrets=secrets,
528
545
  snapshot_id=snapshot_id,
546
+ tunnel=tunnel,
529
547
  extra_headers=extra_headers,
530
548
  extra_query=extra_query,
531
549
  extra_body=extra_body,
@@ -632,6 +650,7 @@ class DevboxesResource(SyncAPIResource):
632
650
  cast_to=DevboxCreateSSHKeyResponse,
633
651
  )
634
652
 
653
+ @typing_extensions.deprecated("deprecated")
635
654
  def create_tunnel(
636
655
  self,
637
656
  id: str,
@@ -645,8 +664,11 @@ class DevboxesResource(SyncAPIResource):
645
664
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
646
665
  idempotency_key: str | None = None,
647
666
  ) -> DevboxTunnelView:
648
- """
649
- Create a live tunnel to an available port on the Devbox.
667
+ """[Deprecated] Use POST /v1/devboxes/{id}/enable_tunnel instead.
668
+
669
+ This endpoint
670
+ creates a legacy tunnel. The new enable_tunnel endpoint provides improved tunnel
671
+ functionality with authentication options.
650
672
 
651
673
  Args:
652
674
  port: Devbox port that tunnel will expose.
@@ -1197,6 +1219,7 @@ class DevboxesResource(SyncAPIResource):
1197
1219
  cast_to=str,
1198
1220
  )
1199
1221
 
1222
+ @typing_extensions.deprecated("deprecated")
1200
1223
  def remove_tunnel(
1201
1224
  self,
1202
1225
  id: str,
@@ -1210,8 +1233,10 @@ class DevboxesResource(SyncAPIResource):
1210
1233
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
1211
1234
  idempotency_key: str | None = None,
1212
1235
  ) -> object:
1213
- """
1214
- Remove a previously opened tunnel on the Devbox.
1236
+ """[Deprecated] Tunnels remain active until devbox is shutdown.
1237
+
1238
+ This endpoint
1239
+ removes a legacy tunnel.
1215
1240
 
1216
1241
  Args:
1217
1242
  port: Devbox port that tunnel will expose.
@@ -1723,6 +1748,7 @@ class AsyncDevboxesResource(AsyncAPIResource):
1723
1748
  entrypoint: Optional[str] | Omit = omit,
1724
1749
  environment_variables: Optional[Dict[str, str]] | Omit = omit,
1725
1750
  file_mounts: Optional[Dict[str, str]] | Omit = omit,
1751
+ gateways: Optional[Dict[str, devbox_create_params.Gateways]] | Omit = omit,
1726
1752
  launch_parameters: Optional[LaunchParameters] | Omit = omit,
1727
1753
  metadata: Optional[Dict[str, str]] | Omit = omit,
1728
1754
  mounts: Optional[Iterable[Mount]] | Omit = omit,
@@ -1730,6 +1756,7 @@ class AsyncDevboxesResource(AsyncAPIResource):
1730
1756
  repo_connection_id: Optional[str] | Omit = omit,
1731
1757
  secrets: Optional[Dict[str, str]] | Omit = omit,
1732
1758
  snapshot_id: Optional[str] | Omit = omit,
1759
+ tunnel: Optional[devbox_create_params.Tunnel] | Omit = omit,
1733
1760
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
1734
1761
  # The extra values given here take precedence over values defined on the client or passed to this method.
1735
1762
  extra_headers: Headers | None = None,
@@ -1765,6 +1792,12 @@ class AsyncDevboxesResource(AsyncAPIResource):
1765
1792
 
1766
1793
  file_mounts: Map of paths and file contents to write before setup. Use mounts instead.
1767
1794
 
1795
+ gateways: [Beta] (Optional) Gateway specifications for credential proxying. Map key is the
1796
+ environment variable prefix (e.g., 'GWS_ANTHROPIC'). The gateway will proxy
1797
+ requests to external APIs using the specified credential without exposing the
1798
+ real API key. Example: {'GWS_ANTHROPIC': {'gateway': 'anthropic', 'secret':
1799
+ 'my_claude_key'}}
1800
+
1768
1801
  launch_parameters: Parameters to configure the resources and launch time behavior of the Devbox.
1769
1802
 
1770
1803
  metadata: User defined metadata to attach to the devbox for organization.
@@ -1783,6 +1816,10 @@ class AsyncDevboxesResource(AsyncAPIResource):
1783
1816
  snapshot_id: Snapshot ID to use for the Devbox. Only one of (Snapshot ID, Blueprint ID,
1784
1817
  Blueprint name) should be specified.
1785
1818
 
1819
+ tunnel: (Optional) Configuration for creating a V2 tunnel at Devbox launch time. When
1820
+ specified, a tunnel will be automatically provisioned and the tunnel details
1821
+ will be included in the Devbox response.
1822
+
1786
1823
  extra_headers: Send extra headers
1787
1824
 
1788
1825
  extra_query: Add additional query parameters to the request
@@ -1803,6 +1840,7 @@ class AsyncDevboxesResource(AsyncAPIResource):
1803
1840
  "entrypoint": entrypoint,
1804
1841
  "environment_variables": environment_variables,
1805
1842
  "file_mounts": file_mounts,
1843
+ "gateways": gateways,
1806
1844
  "launch_parameters": launch_parameters,
1807
1845
  "metadata": metadata,
1808
1846
  "mounts": mounts,
@@ -1810,6 +1848,7 @@ class AsyncDevboxesResource(AsyncAPIResource):
1810
1848
  "repo_connection_id": repo_connection_id,
1811
1849
  "secrets": secrets,
1812
1850
  "snapshot_id": snapshot_id,
1851
+ "tunnel": tunnel,
1813
1852
  },
1814
1853
  devbox_create_params.DevboxCreateParams,
1815
1854
  ),
@@ -1865,6 +1904,7 @@ class AsyncDevboxesResource(AsyncAPIResource):
1865
1904
  entrypoint: Optional[str] | Omit = omit,
1866
1905
  environment_variables: Optional[Dict[str, str]] | Omit = omit,
1867
1906
  file_mounts: Optional[Dict[str, str]] | Omit = omit,
1907
+ gateways: Optional[Dict[str, devbox_create_params.Gateways]] | Omit = omit,
1868
1908
  launch_parameters: Optional[LaunchParameters] | Omit = omit,
1869
1909
  metadata: Optional[Dict[str, str]] | Omit = omit,
1870
1910
  mounts: Optional[Iterable[Mount]] | Omit = omit,
@@ -1873,6 +1913,7 @@ class AsyncDevboxesResource(AsyncAPIResource):
1873
1913
  repo_connection_id: Optional[str] | Omit = omit,
1874
1914
  secrets: Optional[Dict[str, str]] | Omit = omit,
1875
1915
  snapshot_id: Optional[str] | Omit = omit,
1916
+ tunnel: Optional[devbox_create_params.Tunnel] | Omit = omit,
1876
1917
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
1877
1918
  # The extra values given here take precedence over values defined on the client or passed to this method.
1878
1919
  extra_headers: Headers | None = None,
@@ -1905,6 +1946,7 @@ class AsyncDevboxesResource(AsyncAPIResource):
1905
1946
  entrypoint=entrypoint,
1906
1947
  environment_variables=environment_variables,
1907
1948
  file_mounts=file_mounts,
1949
+ gateways=gateways,
1908
1950
  launch_parameters=launch_parameters,
1909
1951
  metadata=metadata,
1910
1952
  mounts=mounts,
@@ -1912,6 +1954,7 @@ class AsyncDevboxesResource(AsyncAPIResource):
1912
1954
  repo_connection_id=repo_connection_id,
1913
1955
  secrets=secrets,
1914
1956
  snapshot_id=snapshot_id,
1957
+ tunnel=tunnel,
1915
1958
  extra_headers=extra_headers,
1916
1959
  extra_query=extra_query,
1917
1960
  extra_body=extra_body,
@@ -2167,6 +2210,7 @@ class AsyncDevboxesResource(AsyncAPIResource):
2167
2210
  cast_to=DevboxCreateSSHKeyResponse,
2168
2211
  )
2169
2212
 
2213
+ @typing_extensions.deprecated("deprecated")
2170
2214
  async def create_tunnel(
2171
2215
  self,
2172
2216
  id: str,
@@ -2180,8 +2224,11 @@ class AsyncDevboxesResource(AsyncAPIResource):
2180
2224
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
2181
2225
  idempotency_key: str | None = None,
2182
2226
  ) -> DevboxTunnelView:
2183
- """
2184
- Create a live tunnel to an available port on the Devbox.
2227
+ """[Deprecated] Use POST /v1/devboxes/{id}/enable_tunnel instead.
2228
+
2229
+ This endpoint
2230
+ creates a legacy tunnel. The new enable_tunnel endpoint provides improved tunnel
2231
+ functionality with authentication options.
2185
2232
 
2186
2233
  Args:
2187
2234
  port: Devbox port that tunnel will expose.
@@ -2733,6 +2780,7 @@ class AsyncDevboxesResource(AsyncAPIResource):
2733
2780
  cast_to=str,
2734
2781
  )
2735
2782
 
2783
+ @typing_extensions.deprecated("deprecated")
2736
2784
  async def remove_tunnel(
2737
2785
  self,
2738
2786
  id: str,
@@ -2746,8 +2794,10 @@ class AsyncDevboxesResource(AsyncAPIResource):
2746
2794
  timeout: float | httpx.Timeout | None | NotGiven = not_given,
2747
2795
  idempotency_key: str | None = None,
2748
2796
  ) -> object:
2749
- """
2750
- Remove a previously opened tunnel on the Devbox.
2797
+ """[Deprecated] Tunnels remain active until devbox is shutdown.
2798
+
2799
+ This endpoint
2800
+ removes a legacy tunnel.
2751
2801
 
2752
2802
  Args:
2753
2803
  port: Devbox port that tunnel will expose.
@@ -3231,8 +3281,10 @@ class DevboxesResourceWithRawResponse:
3231
3281
  self.create_ssh_key = to_raw_response_wrapper(
3232
3282
  devboxes.create_ssh_key,
3233
3283
  )
3234
- self.create_tunnel = to_raw_response_wrapper(
3235
- devboxes.create_tunnel,
3284
+ self.create_tunnel = ( # pyright: ignore[reportDeprecated]
3285
+ to_raw_response_wrapper(
3286
+ devboxes.create_tunnel, # pyright: ignore[reportDeprecated],
3287
+ )
3236
3288
  )
3237
3289
  self.delete_disk_snapshot = to_raw_response_wrapper(
3238
3290
  devboxes.delete_disk_snapshot,
@@ -3261,8 +3313,10 @@ class DevboxesResourceWithRawResponse:
3261
3313
  self.read_file_contents = to_raw_response_wrapper(
3262
3314
  devboxes.read_file_contents,
3263
3315
  )
3264
- self.remove_tunnel = to_raw_response_wrapper(
3265
- devboxes.remove_tunnel,
3316
+ self.remove_tunnel = ( # pyright: ignore[reportDeprecated]
3317
+ to_raw_response_wrapper(
3318
+ devboxes.remove_tunnel, # pyright: ignore[reportDeprecated],
3319
+ )
3266
3320
  )
3267
3321
  self.resume = to_raw_response_wrapper(
3268
3322
  devboxes.resume,
@@ -3329,8 +3383,10 @@ class AsyncDevboxesResourceWithRawResponse:
3329
3383
  self.create_ssh_key = async_to_raw_response_wrapper(
3330
3384
  devboxes.create_ssh_key,
3331
3385
  )
3332
- self.create_tunnel = async_to_raw_response_wrapper(
3333
- devboxes.create_tunnel,
3386
+ self.create_tunnel = ( # pyright: ignore[reportDeprecated]
3387
+ async_to_raw_response_wrapper(
3388
+ devboxes.create_tunnel, # pyright: ignore[reportDeprecated],
3389
+ )
3334
3390
  )
3335
3391
  self.delete_disk_snapshot = async_to_raw_response_wrapper(
3336
3392
  devboxes.delete_disk_snapshot,
@@ -3359,8 +3415,10 @@ class AsyncDevboxesResourceWithRawResponse:
3359
3415
  self.read_file_contents = async_to_raw_response_wrapper(
3360
3416
  devboxes.read_file_contents,
3361
3417
  )
3362
- self.remove_tunnel = async_to_raw_response_wrapper(
3363
- devboxes.remove_tunnel,
3418
+ self.remove_tunnel = ( # pyright: ignore[reportDeprecated]
3419
+ async_to_raw_response_wrapper(
3420
+ devboxes.remove_tunnel, # pyright: ignore[reportDeprecated],
3421
+ )
3364
3422
  )
3365
3423
  self.resume = async_to_raw_response_wrapper(
3366
3424
  devboxes.resume,
@@ -3427,8 +3485,10 @@ class DevboxesResourceWithStreamingResponse:
3427
3485
  self.create_ssh_key = to_streamed_response_wrapper(
3428
3486
  devboxes.create_ssh_key,
3429
3487
  )
3430
- self.create_tunnel = to_streamed_response_wrapper(
3431
- devboxes.create_tunnel,
3488
+ self.create_tunnel = ( # pyright: ignore[reportDeprecated]
3489
+ to_streamed_response_wrapper(
3490
+ devboxes.create_tunnel, # pyright: ignore[reportDeprecated],
3491
+ )
3432
3492
  )
3433
3493
  self.delete_disk_snapshot = to_streamed_response_wrapper(
3434
3494
  devboxes.delete_disk_snapshot,
@@ -3457,8 +3517,10 @@ class DevboxesResourceWithStreamingResponse:
3457
3517
  self.read_file_contents = to_streamed_response_wrapper(
3458
3518
  devboxes.read_file_contents,
3459
3519
  )
3460
- self.remove_tunnel = to_streamed_response_wrapper(
3461
- devboxes.remove_tunnel,
3520
+ self.remove_tunnel = ( # pyright: ignore[reportDeprecated]
3521
+ to_streamed_response_wrapper(
3522
+ devboxes.remove_tunnel, # pyright: ignore[reportDeprecated],
3523
+ )
3462
3524
  )
3463
3525
  self.resume = to_streamed_response_wrapper(
3464
3526
  devboxes.resume,
@@ -3525,8 +3587,10 @@ class AsyncDevboxesResourceWithStreamingResponse:
3525
3587
  self.create_ssh_key = async_to_streamed_response_wrapper(
3526
3588
  devboxes.create_ssh_key,
3527
3589
  )
3528
- self.create_tunnel = async_to_streamed_response_wrapper(
3529
- devboxes.create_tunnel,
3590
+ self.create_tunnel = ( # pyright: ignore[reportDeprecated]
3591
+ async_to_streamed_response_wrapper(
3592
+ devboxes.create_tunnel, # pyright: ignore[reportDeprecated],
3593
+ )
3530
3594
  )
3531
3595
  self.delete_disk_snapshot = async_to_streamed_response_wrapper(
3532
3596
  devboxes.delete_disk_snapshot,
@@ -3555,8 +3619,10 @@ class AsyncDevboxesResourceWithStreamingResponse:
3555
3619
  self.read_file_contents = async_to_streamed_response_wrapper(
3556
3620
  devboxes.read_file_contents,
3557
3621
  )
3558
- self.remove_tunnel = async_to_streamed_response_wrapper(
3559
- devboxes.remove_tunnel,
3622
+ self.remove_tunnel = ( # pyright: ignore[reportDeprecated]
3623
+ async_to_streamed_response_wrapper(
3624
+ devboxes.remove_tunnel, # pyright: ignore[reportDeprecated],
3625
+ )
3560
3626
  )
3561
3627
  self.resume = async_to_streamed_response_wrapper(
3562
3628
  devboxes.resume,