|
15 | 15 | SandboxRuntimeSession, |
16 | 16 | SandboxSnapshotListParams, |
17 | 17 | SandboxSnapshotListResponse, |
| 18 | + SandboxUnexposeResult, |
18 | 19 | StartSandboxFromSnapshotParams, |
19 | 20 | ) |
20 | 21 | from ....models.session import BasicResponse |
@@ -113,6 +114,10 @@ def token_expires_at(self): |
113 | 114 | def session_url(self) -> str: |
114 | 115 | return self._detail.session_url |
115 | 116 |
|
| 117 | + @property |
| 118 | + def exposed_ports(self): |
| 119 | + return self._detail.exposed_ports |
| 120 | + |
116 | 121 | def to_dict(self): |
117 | 122 | return self._detail.model_dump() |
118 | 123 |
|
@@ -152,7 +157,27 @@ async def create_memory_snapshot( |
152 | 157 | async def expose(self, params: SandboxExposeParams) -> SandboxExposeResult: |
153 | 158 | if not isinstance(params, SandboxExposeParams): |
154 | 159 | raise TypeError("params must be a SandboxExposeParams instance") |
155 | | - return await self._service.expose(self.id, params, runtime=self.runtime) |
| 160 | + result = await self._service.expose(self.id, params, runtime=self.runtime) |
| 161 | + exposed_ports = [ |
| 162 | + port for port in self._detail.exposed_ports if port.port != result.port |
| 163 | + ] |
| 164 | + exposed_ports.append(result) |
| 165 | + exposed_ports.sort(key=lambda port: port.port) |
| 166 | + self._detail = self._detail.model_copy(update={"exposed_ports": exposed_ports}) |
| 167 | + return result |
| 168 | + |
| 169 | + async def unexpose(self, port: int) -> SandboxUnexposeResult: |
| 170 | + result = await self._service.unexpose(self.id, port) |
| 171 | + self._detail = self._detail.model_copy( |
| 172 | + update={ |
| 173 | + "exposed_ports": [ |
| 174 | + exposed_port |
| 175 | + for exposed_port in self._detail.exposed_ports |
| 176 | + if exposed_port.port != port |
| 177 | + ] |
| 178 | + } |
| 179 | + ) |
| 180 | + return result |
156 | 181 |
|
157 | 182 | def get_exposed_url(self, port: int) -> str: |
158 | 183 | return _build_sandbox_exposed_url(self.runtime, port) |
@@ -372,11 +397,17 @@ async def expose( |
372 | 397 | data=params.model_dump(exclude_none=True, by_alias=True), |
373 | 398 | ) |
374 | 399 | target_runtime = runtime or (await self.get_detail(sandbox_id)).runtime |
375 | | - return SandboxExposeResult( |
376 | | - port=payload["port"], |
377 | | - auth=payload["auth"], |
378 | | - url=_build_sandbox_exposed_url(target_runtime, payload["port"]), |
| 400 | + if "url" not in payload: |
| 401 | + payload["url"] = _build_sandbox_exposed_url(target_runtime, payload["port"]) |
| 402 | + return SandboxExposeResult(**payload) |
| 403 | + |
| 404 | + async def unexpose(self, sandbox_id: str, port: int) -> SandboxUnexposeResult: |
| 405 | + payload = await self._request( |
| 406 | + "POST", |
| 407 | + f"/sandbox/{sandbox_id}/unexpose", |
| 408 | + data={"port": port}, |
379 | 409 | ) |
| 410 | + return SandboxUnexposeResult(**payload) |
380 | 411 |
|
381 | 412 | async def _create_detail(self, params: CreateSandboxParams) -> SandboxDetail: |
382 | 413 | payload = await self._request( |
|
0 commit comments