Skip to content

Commit b01b16d

Browse files
feat: add WebSocket process attach and PTY support
1 parent d602cfa commit b01b16d

File tree

8 files changed

+319
-5
lines changed

8 files changed

+319
-5
lines changed

.stats.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
configured_endpoints: 89
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-8e4a29d23d2882fcb0864606091790fd58bffa4f5d5c8d081052b72ad47b215b.yml
3-
openapi_spec_hash: fc82d930dad739ac01e3c2bddba7bf61
4-
config_hash: d0585c44724cd7deecea60a5ffae69df
1+
configured_endpoints: 90
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-6a44c851ec955b997558a8524eb641355ff3097474f40772b8ea2fef5bee4134.yml
3+
openapi_spec_hash: 155ee005a1b43e1c11e843de91e9f509
4+
config_hash: 6cbbf855a29bc675f35ddb1106ea9083

api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ Types:
154154
from kernel.types.browsers import (
155155
ProcessExecResponse,
156156
ProcessKillResponse,
157+
ProcessResizeResponse,
157158
ProcessSpawnResponse,
158159
ProcessStatusResponse,
159160
ProcessStdinResponse,
@@ -165,6 +166,7 @@ Methods:
165166

166167
- <code title="post /browsers/{id}/process/exec">client.browsers.process.<a href="./src/kernel/resources/browsers/process.py">exec</a>(id, \*\*<a href="src/kernel/types/browsers/process_exec_params.py">params</a>) -> <a href="./src/kernel/types/browsers/process_exec_response.py">ProcessExecResponse</a></code>
167168
- <code title="post /browsers/{id}/process/{process_id}/kill">client.browsers.process.<a href="./src/kernel/resources/browsers/process.py">kill</a>(process_id, \*, id, \*\*<a href="src/kernel/types/browsers/process_kill_params.py">params</a>) -> <a href="./src/kernel/types/browsers/process_kill_response.py">ProcessKillResponse</a></code>
169+
- <code title="post /browsers/{id}/process/{process_id}/resize">client.browsers.process.<a href="./src/kernel/resources/browsers/process.py">resize</a>(process_id, \*, id, \*\*<a href="src/kernel/types/browsers/process_resize_params.py">params</a>) -> <a href="./src/kernel/types/browsers/process_resize_response.py">ProcessResizeResponse</a></code>
168170
- <code title="post /browsers/{id}/process/spawn">client.browsers.process.<a href="./src/kernel/resources/browsers/process.py">spawn</a>(id, \*\*<a href="src/kernel/types/browsers/process_spawn_params.py">params</a>) -> <a href="./src/kernel/types/browsers/process_spawn_response.py">ProcessSpawnResponse</a></code>
169171
- <code title="get /browsers/{id}/process/{process_id}/status">client.browsers.process.<a href="./src/kernel/resources/browsers/process.py">status</a>(process_id, \*, id) -> <a href="./src/kernel/types/browsers/process_status_response.py">ProcessStatusResponse</a></code>
170172
- <code title="post /browsers/{id}/process/{process_id}/stdin">client.browsers.process.<a href="./src/kernel/resources/browsers/process.py">stdin</a>(process_id, \*, id, \*\*<a href="src/kernel/types/browsers/process_stdin_params.py">params</a>) -> <a href="./src/kernel/types/browsers/process_stdin_response.py">ProcessStdinResponse</a></code>

src/kernel/resources/browsers/process.py

Lines changed: 142 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,18 @@
1919
)
2020
from ..._streaming import Stream, AsyncStream
2121
from ..._base_client import make_request_options
22-
from ...types.browsers import process_exec_params, process_kill_params, process_spawn_params, process_stdin_params
22+
from ...types.browsers import (
23+
process_exec_params,
24+
process_kill_params,
25+
process_spawn_params,
26+
process_stdin_params,
27+
process_resize_params,
28+
)
2329
from ...types.browsers.process_exec_response import ProcessExecResponse
2430
from ...types.browsers.process_kill_response import ProcessKillResponse
2531
from ...types.browsers.process_spawn_response import ProcessSpawnResponse
2632
from ...types.browsers.process_stdin_response import ProcessStdinResponse
33+
from ...types.browsers.process_resize_response import ProcessResizeResponse
2734
from ...types.browsers.process_status_response import ProcessStatusResponse
2835
from ...types.browsers.process_stdout_stream_response import ProcessStdoutStreamResponse
2936

@@ -156,16 +163,68 @@ def kill(
156163
cast_to=ProcessKillResponse,
157164
)
158165

166+
def resize(
167+
self,
168+
process_id: str,
169+
*,
170+
id: str,
171+
cols: int,
172+
rows: int,
173+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
174+
# The extra values given here take precedence over values defined on the client or passed to this method.
175+
extra_headers: Headers | None = None,
176+
extra_query: Query | None = None,
177+
extra_body: Body | None = None,
178+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
179+
) -> ProcessResizeResponse:
180+
"""
181+
Resize a PTY-backed process terminal
182+
183+
Args:
184+
cols: New terminal columns.
185+
186+
rows: New terminal rows.
187+
188+
extra_headers: Send extra headers
189+
190+
extra_query: Add additional query parameters to the request
191+
192+
extra_body: Add additional JSON properties to the request
193+
194+
timeout: Override the client-level default timeout for this request, in seconds
195+
"""
196+
if not id:
197+
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
198+
if not process_id:
199+
raise ValueError(f"Expected a non-empty value for `process_id` but received {process_id!r}")
200+
return self._post(
201+
f"/browsers/{id}/process/{process_id}/resize",
202+
body=maybe_transform(
203+
{
204+
"cols": cols,
205+
"rows": rows,
206+
},
207+
process_resize_params.ProcessResizeParams,
208+
),
209+
options=make_request_options(
210+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
211+
),
212+
cast_to=ProcessResizeResponse,
213+
)
214+
159215
def spawn(
160216
self,
161217
id: str,
162218
*,
163219
command: str,
220+
allocate_tty: bool | Omit = omit,
164221
args: SequenceNotStr[str] | Omit = omit,
165222
as_root: bool | Omit = omit,
166223
as_user: Optional[str] | Omit = omit,
224+
cols: int | Omit = omit,
167225
cwd: Optional[str] | Omit = omit,
168226
env: Dict[str, str] | Omit = omit,
227+
rows: int | Omit = omit,
169228
timeout_sec: Optional[int] | Omit = omit,
170229
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
171230
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -180,16 +239,22 @@ def spawn(
180239
Args:
181240
command: Executable or shell command to run.
182241
242+
allocate_tty: Allocate a pseudo-terminal (PTY) for interactive shells.
243+
183244
args: Command arguments.
184245
185246
as_root: Run the process with root privileges.
186247
187248
as_user: Run the process as this user.
188249
250+
cols: Initial terminal columns. Only used when allocate_tty is true.
251+
189252
cwd: Working directory (absolute path) to run the command in.
190253
191254
env: Environment variables to set for the process.
192255
256+
rows: Initial terminal rows. Only used when allocate_tty is true.
257+
193258
timeout_sec: Maximum execution time in seconds.
194259
195260
extra_headers: Send extra headers
@@ -207,11 +272,14 @@ def spawn(
207272
body=maybe_transform(
208273
{
209274
"command": command,
275+
"allocate_tty": allocate_tty,
210276
"args": args,
211277
"as_root": as_root,
212278
"as_user": as_user,
279+
"cols": cols,
213280
"cwd": cwd,
214281
"env": env,
282+
"rows": rows,
215283
"timeout_sec": timeout_sec,
216284
},
217285
process_spawn_params.ProcessSpawnParams,
@@ -464,16 +532,68 @@ async def kill(
464532
cast_to=ProcessKillResponse,
465533
)
466534

535+
async def resize(
536+
self,
537+
process_id: str,
538+
*,
539+
id: str,
540+
cols: int,
541+
rows: int,
542+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
543+
# The extra values given here take precedence over values defined on the client or passed to this method.
544+
extra_headers: Headers | None = None,
545+
extra_query: Query | None = None,
546+
extra_body: Body | None = None,
547+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
548+
) -> ProcessResizeResponse:
549+
"""
550+
Resize a PTY-backed process terminal
551+
552+
Args:
553+
cols: New terminal columns.
554+
555+
rows: New terminal rows.
556+
557+
extra_headers: Send extra headers
558+
559+
extra_query: Add additional query parameters to the request
560+
561+
extra_body: Add additional JSON properties to the request
562+
563+
timeout: Override the client-level default timeout for this request, in seconds
564+
"""
565+
if not id:
566+
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
567+
if not process_id:
568+
raise ValueError(f"Expected a non-empty value for `process_id` but received {process_id!r}")
569+
return await self._post(
570+
f"/browsers/{id}/process/{process_id}/resize",
571+
body=await async_maybe_transform(
572+
{
573+
"cols": cols,
574+
"rows": rows,
575+
},
576+
process_resize_params.ProcessResizeParams,
577+
),
578+
options=make_request_options(
579+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
580+
),
581+
cast_to=ProcessResizeResponse,
582+
)
583+
467584
async def spawn(
468585
self,
469586
id: str,
470587
*,
471588
command: str,
589+
allocate_tty: bool | Omit = omit,
472590
args: SequenceNotStr[str] | Omit = omit,
473591
as_root: bool | Omit = omit,
474592
as_user: Optional[str] | Omit = omit,
593+
cols: int | Omit = omit,
475594
cwd: Optional[str] | Omit = omit,
476595
env: Dict[str, str] | Omit = omit,
596+
rows: int | Omit = omit,
477597
timeout_sec: Optional[int] | Omit = omit,
478598
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
479599
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -488,16 +608,22 @@ async def spawn(
488608
Args:
489609
command: Executable or shell command to run.
490610
611+
allocate_tty: Allocate a pseudo-terminal (PTY) for interactive shells.
612+
491613
args: Command arguments.
492614
493615
as_root: Run the process with root privileges.
494616
495617
as_user: Run the process as this user.
496618
619+
cols: Initial terminal columns. Only used when allocate_tty is true.
620+
497621
cwd: Working directory (absolute path) to run the command in.
498622
499623
env: Environment variables to set for the process.
500624
625+
rows: Initial terminal rows. Only used when allocate_tty is true.
626+
501627
timeout_sec: Maximum execution time in seconds.
502628
503629
extra_headers: Send extra headers
@@ -515,11 +641,14 @@ async def spawn(
515641
body=await async_maybe_transform(
516642
{
517643
"command": command,
644+
"allocate_tty": allocate_tty,
518645
"args": args,
519646
"as_root": as_root,
520647
"as_user": as_user,
648+
"cols": cols,
521649
"cwd": cwd,
522650
"env": env,
651+
"rows": rows,
523652
"timeout_sec": timeout_sec,
524653
},
525654
process_spawn_params.ProcessSpawnParams,
@@ -656,6 +785,9 @@ def __init__(self, process: ProcessResource) -> None:
656785
self.kill = to_raw_response_wrapper(
657786
process.kill,
658787
)
788+
self.resize = to_raw_response_wrapper(
789+
process.resize,
790+
)
659791
self.spawn = to_raw_response_wrapper(
660792
process.spawn,
661793
)
@@ -680,6 +812,9 @@ def __init__(self, process: AsyncProcessResource) -> None:
680812
self.kill = async_to_raw_response_wrapper(
681813
process.kill,
682814
)
815+
self.resize = async_to_raw_response_wrapper(
816+
process.resize,
817+
)
683818
self.spawn = async_to_raw_response_wrapper(
684819
process.spawn,
685820
)
@@ -704,6 +839,9 @@ def __init__(self, process: ProcessResource) -> None:
704839
self.kill = to_streamed_response_wrapper(
705840
process.kill,
706841
)
842+
self.resize = to_streamed_response_wrapper(
843+
process.resize,
844+
)
707845
self.spawn = to_streamed_response_wrapper(
708846
process.spawn,
709847
)
@@ -728,6 +866,9 @@ def __init__(self, process: AsyncProcessResource) -> None:
728866
self.kill = async_to_streamed_response_wrapper(
729867
process.kill,
730868
)
869+
self.resize = async_to_streamed_response_wrapper(
870+
process.resize,
871+
)
731872
self.spawn = async_to_streamed_response_wrapper(
732873
process.spawn,
733874
)

src/kernel/types/browsers/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@
2121
from .f_list_files_response import FListFilesResponse as FListFilesResponse
2222
from .process_exec_response import ProcessExecResponse as ProcessExecResponse
2323
from .process_kill_response import ProcessKillResponse as ProcessKillResponse
24+
from .process_resize_params import ProcessResizeParams as ProcessResizeParams
2425
from .replay_start_response import ReplayStartResponse as ReplayStartResponse
2526
from .computer_scroll_params import ComputerScrollParams as ComputerScrollParams
2627
from .process_spawn_response import ProcessSpawnResponse as ProcessSpawnResponse
2728
from .process_stdin_response import ProcessStdinResponse as ProcessStdinResponse
29+
from .process_resize_response import ProcessResizeResponse as ProcessResizeResponse
2830
from .process_status_response import ProcessStatusResponse as ProcessStatusResponse
2931
from .computer_press_key_params import ComputerPressKeyParams as ComputerPressKeyParams
3032
from .computer_type_text_params import ComputerTypeTextParams as ComputerTypeTextParams
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from __future__ import annotations
4+
5+
from typing_extensions import Required, TypedDict
6+
7+
__all__ = ["ProcessResizeParams"]
8+
9+
10+
class ProcessResizeParams(TypedDict, total=False):
11+
id: Required[str]
12+
13+
cols: Required[int]
14+
"""New terminal columns."""
15+
16+
rows: Required[int]
17+
"""New terminal rows."""
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from ..._models import BaseModel
4+
5+
__all__ = ["ProcessResizeResponse"]
6+
7+
8+
class ProcessResizeResponse(BaseModel):
9+
"""Generic OK response."""
10+
11+
ok: bool
12+
"""Indicates success."""

src/kernel/types/browsers/process_spawn_params.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ class ProcessSpawnParams(TypedDict, total=False):
1414
command: Required[str]
1515
"""Executable or shell command to run."""
1616

17+
allocate_tty: bool
18+
"""Allocate a pseudo-terminal (PTY) for interactive shells."""
19+
1720
args: SequenceNotStr[str]
1821
"""Command arguments."""
1922

@@ -23,11 +26,17 @@ class ProcessSpawnParams(TypedDict, total=False):
2326
as_user: Optional[str]
2427
"""Run the process as this user."""
2528

29+
cols: int
30+
"""Initial terminal columns. Only used when allocate_tty is true."""
31+
2632
cwd: Optional[str]
2733
"""Working directory (absolute path) to run the command in."""
2834

2935
env: Dict[str, str]
3036
"""Environment variables to set for the process."""
3137

38+
rows: int
39+
"""Initial terminal rows. Only used when allocate_tty is true."""
40+
3241
timeout_sec: Optional[int]
3342
"""Maximum execution time in seconds."""

0 commit comments

Comments
 (0)