Skip to content

Commit 71620a1

Browse files
feat(devbox): add new tunnel APIs and deprecate old tunnel API (#7227)
1 parent 08e0586 commit 71620a1

5 files changed

Lines changed: 146 additions & 59 deletions

File tree

.stats.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 111
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-c89b52af46573ea81341b7115e59ee3f995ff9fe5b48a04318176d9b30e7eb79.yml
3-
openapi_spec_hash: a8b42cc79a4fc993c8cc5cc13fc443a2
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-debd1f9a9d599b009905cbaaea3095c025fe290493c8a836f54ece22265579c1.yml
3+
openapi_spec_hash: ee42d2c73aaad86888360147d9ed0766
44
config_hash: 22f65246be4646c23dde9f69f51252e7

src/runloop_api_client/resources/devboxes/devboxes.py

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ def create(
193193
repo_connection_id: Optional[str] | Omit = omit,
194194
secrets: Optional[Dict[str, str]] | Omit = omit,
195195
snapshot_id: Optional[str] | Omit = omit,
196+
tunnel: Optional[devbox_create_params.Tunnel] | Omit = omit,
196197
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
197198
# The extra values given here take precedence over values defined on the client or passed to this method.
198199
extra_headers: Headers | None = None,
@@ -252,6 +253,10 @@ def create(
252253
snapshot_id: Snapshot ID to use for the Devbox. Only one of (Snapshot ID, Blueprint ID,
253254
Blueprint name) should be specified.
254255
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+
255260
extra_headers: Send extra headers
256261
257262
extra_query: Add additional query parameters to the request
@@ -280,6 +285,7 @@ def create(
280285
"repo_connection_id": repo_connection_id,
281286
"secrets": secrets,
282287
"snapshot_id": snapshot_id,
288+
"tunnel": tunnel,
283289
},
284290
devbox_create_params.DevboxCreateParams,
285291
),
@@ -640,6 +646,7 @@ def create_ssh_key(
640646
cast_to=DevboxCreateSSHKeyResponse,
641647
)
642648

649+
@typing_extensions.deprecated("deprecated")
643650
def create_tunnel(
644651
self,
645652
id: str,
@@ -653,8 +660,11 @@ def create_tunnel(
653660
timeout: float | httpx.Timeout | None | NotGiven = not_given,
654661
idempotency_key: str | None = None,
655662
) -> DevboxTunnelView:
656-
"""
657-
Create a live tunnel to an available port on the Devbox.
663+
"""[Deprecated] Use POST /v1/devboxes/{id}/enable_tunnel instead.
664+
665+
This endpoint
666+
creates a legacy tunnel. The new enable_tunnel endpoint provides improved tunnel
667+
functionality with authentication options.
658668
659669
Args:
660670
port: Devbox port that tunnel will expose.
@@ -1739,6 +1749,7 @@ async def create(
17391749
repo_connection_id: Optional[str] | Omit = omit,
17401750
secrets: Optional[Dict[str, str]] | Omit = omit,
17411751
snapshot_id: Optional[str] | Omit = omit,
1752+
tunnel: Optional[devbox_create_params.Tunnel] | Omit = omit,
17421753
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
17431754
# The extra values given here take precedence over values defined on the client or passed to this method.
17441755
extra_headers: Headers | None = None,
@@ -1798,6 +1809,10 @@ async def create(
17981809
snapshot_id: Snapshot ID to use for the Devbox. Only one of (Snapshot ID, Blueprint ID,
17991810
Blueprint name) should be specified.
18001811
1812+
tunnel: (Optional) Configuration for creating a V2 tunnel at Devbox launch time. When
1813+
specified, a tunnel will be automatically provisioned and the tunnel details
1814+
will be included in the Devbox response.
1815+
18011816
extra_headers: Send extra headers
18021817
18031818
extra_query: Add additional query parameters to the request
@@ -1826,6 +1841,7 @@ async def create(
18261841
"repo_connection_id": repo_connection_id,
18271842
"secrets": secrets,
18281843
"snapshot_id": snapshot_id,
1844+
"tunnel": tunnel,
18291845
},
18301846
devbox_create_params.DevboxCreateParams,
18311847
),
@@ -2183,6 +2199,7 @@ async def create_ssh_key(
21832199
cast_to=DevboxCreateSSHKeyResponse,
21842200
)
21852201

2202+
@typing_extensions.deprecated("deprecated")
21862203
async def create_tunnel(
21872204
self,
21882205
id: str,
@@ -2196,8 +2213,11 @@ async def create_tunnel(
21962213
timeout: float | httpx.Timeout | None | NotGiven = not_given,
21972214
idempotency_key: str | None = None,
21982215
) -> DevboxTunnelView:
2199-
"""
2200-
Create a live tunnel to an available port on the Devbox.
2216+
"""[Deprecated] Use POST /v1/devboxes/{id}/enable_tunnel instead.
2217+
2218+
This endpoint
2219+
creates a legacy tunnel. The new enable_tunnel endpoint provides improved tunnel
2220+
functionality with authentication options.
22012221
22022222
Args:
22032223
port: Devbox port that tunnel will expose.
@@ -3247,8 +3267,10 @@ def __init__(self, devboxes: DevboxesResource) -> None:
32473267
self.create_ssh_key = to_raw_response_wrapper(
32483268
devboxes.create_ssh_key,
32493269
)
3250-
self.create_tunnel = to_raw_response_wrapper(
3251-
devboxes.create_tunnel,
3270+
self.create_tunnel = ( # pyright: ignore[reportDeprecated]
3271+
to_raw_response_wrapper(
3272+
devboxes.create_tunnel, # pyright: ignore[reportDeprecated],
3273+
)
32523274
)
32533275
self.delete_disk_snapshot = to_raw_response_wrapper(
32543276
devboxes.delete_disk_snapshot,
@@ -3345,8 +3367,10 @@ def __init__(self, devboxes: AsyncDevboxesResource) -> None:
33453367
self.create_ssh_key = async_to_raw_response_wrapper(
33463368
devboxes.create_ssh_key,
33473369
)
3348-
self.create_tunnel = async_to_raw_response_wrapper(
3349-
devboxes.create_tunnel,
3370+
self.create_tunnel = ( # pyright: ignore[reportDeprecated]
3371+
async_to_raw_response_wrapper(
3372+
devboxes.create_tunnel, # pyright: ignore[reportDeprecated],
3373+
)
33503374
)
33513375
self.delete_disk_snapshot = async_to_raw_response_wrapper(
33523376
devboxes.delete_disk_snapshot,
@@ -3443,8 +3467,10 @@ def __init__(self, devboxes: DevboxesResource) -> None:
34433467
self.create_ssh_key = to_streamed_response_wrapper(
34443468
devboxes.create_ssh_key,
34453469
)
3446-
self.create_tunnel = to_streamed_response_wrapper(
3447-
devboxes.create_tunnel,
3470+
self.create_tunnel = ( # pyright: ignore[reportDeprecated]
3471+
to_streamed_response_wrapper(
3472+
devboxes.create_tunnel, # pyright: ignore[reportDeprecated],
3473+
)
34483474
)
34493475
self.delete_disk_snapshot = to_streamed_response_wrapper(
34503476
devboxes.delete_disk_snapshot,
@@ -3541,8 +3567,10 @@ def __init__(self, devboxes: AsyncDevboxesResource) -> None:
35413567
self.create_ssh_key = async_to_streamed_response_wrapper(
35423568
devboxes.create_ssh_key,
35433569
)
3544-
self.create_tunnel = async_to_streamed_response_wrapper(
3545-
devboxes.create_tunnel,
3570+
self.create_tunnel = ( # pyright: ignore[reportDeprecated]
3571+
async_to_streamed_response_wrapper(
3572+
devboxes.create_tunnel, # pyright: ignore[reportDeprecated],
3573+
)
35463574
)
35473575
self.delete_disk_snapshot = async_to_streamed_response_wrapper(
35483576
devboxes.delete_disk_snapshot,

src/runloop_api_client/types/devbox_create_params.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
from __future__ import annotations
44

55
from typing import Dict, Iterable, Optional
6-
from typing_extensions import Required, TypedDict
6+
from typing_extensions import Literal, Required, TypedDict
77

88
from .shared_params.mount import Mount
99
from .shared_params.launch_parameters import LaunchParameters
1010
from .shared_params.code_mount_parameters import CodeMountParameters
1111

12-
__all__ = ["DevboxCreateParams", "Gateways"]
12+
__all__ = ["DevboxCreateParams", "Gateways", "Tunnel"]
1313

1414
# We split up the original DevboxCreateParams into two nested types to enable us to
1515
# omit blueprint_id, blueprint_name, and snapshot_id when we unpack the TypedDict
@@ -94,6 +94,13 @@ class DevboxCreateParams(DevboxBaseCreateParams, total=False):
9494
Only one of (Snapshot ID, Blueprint ID, Blueprint name) should be specified.
9595
"""
9696

97+
tunnel: Optional[Tunnel]
98+
"""(Optional) Configuration for creating a V2 tunnel at Devbox launch time.
99+
100+
When specified, a tunnel will be automatically provisioned and the tunnel
101+
details will be included in the Devbox response.
102+
"""
103+
97104

98105
class Gateways(TypedDict, total=False):
99106
"""
@@ -105,3 +112,13 @@ class Gateways(TypedDict, total=False):
105112

106113
secret: Required[str]
107114
"""The secret containing the credential. Can be a secret ID or name."""
115+
116+
117+
class Tunnel(TypedDict, total=False):
118+
"""(Optional) Configuration for creating a V2 tunnel at Devbox launch time.
119+
120+
When specified, a tunnel will be automatically provisioned and the tunnel details will be included in the Devbox response.
121+
"""
122+
123+
auth_mode: Optional[Literal["open", "authenticated"]]
124+
"""Authentication mode for the tunnel. Defaults to 'public' if not specified."""

src/runloop_api_client/types/devbox_view.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from .._models import BaseModel
77
from .shared.launch_parameters import LaunchParameters
88

9-
__all__ = ["DevboxView", "StateTransition", "GatewaySpecs"]
9+
__all__ = ["DevboxView", "StateTransition", "GatewaySpecs", "Tunnel"]
1010

1111

1212
class StateTransition(BaseModel):
@@ -38,6 +38,30 @@ class GatewaySpecs(BaseModel):
3838
"""The ID of the secret containing the credential."""
3939

4040

41+
class Tunnel(BaseModel):
42+
"""
43+
V2 tunnel information if a tunnel was created at launch time or via the createTunnel API.
44+
"""
45+
46+
auth_mode: Literal["public_", "authenticated"]
47+
"""The authentication mode for the tunnel."""
48+
49+
create_time_ms: int
50+
"""Creation time of the tunnel (Unix timestamp milliseconds)."""
51+
52+
tunnel_key: str
53+
"""The encrypted tunnel key used to construct the tunnel URL.
54+
55+
URL format: https://{port}-{tunnel_key}.tunnel.runloop.{domain}
56+
"""
57+
58+
auth_token: Optional[str] = None
59+
"""Bearer token for tunnel authentication.
60+
61+
Only present when auth_mode is 'authenticated'.
62+
"""
63+
64+
4165
class DevboxView(BaseModel):
4266
"""A Devbox represents a virtual development environment.
4367
@@ -112,3 +136,9 @@ class DevboxView(BaseModel):
112136
The Snapshot ID used in creation of the Devbox, if the devbox was created from a
113137
Snapshot.
114138
"""
139+
140+
tunnel: Optional[Tunnel] = None
141+
"""
142+
V2 tunnel information if a tunnel was created at launch time or via the
143+
createTunnel API.
144+
"""

0 commit comments

Comments
 (0)