Skip to content

fix(sdk): support sending stdin through the PTY command handle#1502

Open
mishushakov wants to merge 2 commits into
mainfrom
mishushakov/pty-send-stdin-error
Open

fix(sdk): support sending stdin through the PTY command handle#1502
mishushakov wants to merge 2 commits into
mainfrom
mishushakov/pty-send-stdin-error

Conversation

@mishushakov

Copy link
Copy Markdown
Member

Summary

Calling send_stdin/sendStdin on the handle returned by pty.create()/pty.connect() previously raised "Sending stdin is not supported for this command handle" because the PTY path never wired up the handle's stdin callback — unlike regular command handles. This wires it up across the JS and Python (sync + async) SDKs, makes PTY input methods also accept str (encoded as UTF-8), and in JS adds pty.sendStdin() as the canonical method (mirroring commands.sendStdin()) with pty.sendInput() kept as a deprecated alias.

Usage

terminal = sandbox.pty.create(size=PtySize(rows=24, cols=80))
terminal.send_stdin(b"whoami\n")   # now works on the handle
terminal.send_stdin("exit\n")       # str is accepted too
terminal.wait(on_pty=lambda data: print(data.decode(), end=""))
const terminal = await sandbox.pty.create({ cols: 80, rows: 24, onData: () => {} })
await terminal.sendStdin('whoami\n')        // on the handle
await sandbox.pty.sendStdin(terminal.pid, 'exit\n')  // new canonical module method

Tests

Added handle-level and str-input tests for sync/async Python and JS (plus a JS test for the deprecated sendInput alias); all pass against a live sandbox.

Wire up `handle_send_stdin`/`handleSendStdin` on the handle returned by
`pty.create()`/`pty.connect()` across the JS and Python (sync + async)
SDKs, so `handle.send_stdin(...)`/`handle.sendStdin(...)` works the same
as for regular command handles instead of raising "Sending stdin is not
supported for this command handle." PTY input methods now also accept
`str`, encoding it as UTF-8.

In the JS SDK, `pty.sendStdin()` is added as the canonical PTY input
method to mirror `commands.sendStdin()`, with `pty.sendInput()` kept as
a deprecated alias.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 342824c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@e2b/python-sdk Patch
@e2b/cli Patch
e2b Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@cursor

cursor Bot commented Jun 29, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
SDK API additions and wiring with backward-compatible aliases; no auth or server-side changes.

Overview
PTY handles from pty.create() / pty.connect() previously had no stdin callback, so handle.sendStdin / handle.send_stdin failed with "Sending stdin is not supported for this command handle." The JS and Python SDKs now pass a sendStdin handler into the command handle on create and connect.

PTY stdin APIs accept str (UTF-8) as well as bytes/Uint8Array. In JS, sandbox.pty.sendStdin() is the canonical PID-based method; sendInput() is a deprecated alias. The CLI terminal path calls sendStdin() instead of sendInput().

Reviewed by Cursor Bugbot for commit 342824c. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Package Artifacts

Built from 90789b1. Download artifacts from this workflow run.

JS SDK (e2b@2.31.1-mishushakov-pty-send-stdin-error.0):

npm install ./e2b-2.31.1-mishushakov-pty-send-stdin-error.0.tgz

CLI (@e2b/cli@2.13.1-mishushakov-pty-send-stdin-error.0):

npm install ./e2b-cli-2.13.1-mishushakov-pty-send-stdin-error.0.tgz

Python SDK (e2b==2.30.0+mishushakov-pty-send-stdin-error):

pip install ./e2b-2.30.0+mishushakov.pty.send.stdin.error-py3-none-any.whl

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — small, well-tested fix that mirrors the existing pattern for regular command handles.

Extended reasoning...

Overview

This PR fixes a real bug where calling send_stdin/sendStdin on the handle returned by pty.create()/pty.connect() raised "Sending stdin is not supported for this command handle." The PTY paths in the JS, Python sync, and Python async SDKs now pass a handle_send_stdin callback to CommandHandle/AsyncCommandHandle, mirroring the wiring already used by commands.start()/commands.connect(). It also broadens PTY input methods to accept str (encoded as UTF-8), and in JS adds pty.sendStdin() as the canonical name with pty.sendInput() kept as a deprecated alias.

Security risks

None. This is an SDK convenience fix that routes user-supplied input through an existing, authenticated gRPC method. No auth, crypto, or permission surfaces are touched, and the underlying wire format is unchanged — str is just UTF-8 encoded client-side before reaching the same ProcessInput.pty bytes field.

Level of scrutiny

Low. The change is mechanical: it slots a callback into a constructor position that the sibling commands module already populates, and the JS CommandHandle constructor's parameter at that index (handleSendStdin) matches the new lambda's signature. Both Python CommandHandle classes accept handle_send_stdin as a keyword arg and already had the runtime check that raises the prior error message. Tests were added for all three SDKs (JS, Python sync, Python async) covering both the module-level method and the new handle-level method, including str input.

Other factors

The one bug-hunter finding (the CLI at packages/cli/src/terminal.ts:29 still calls the freshly-deprecated sendInput) is a true nit — the alias delegates to sendStdin so behavior is identical; only an IDE deprecation strikethrough is introduced. It does not block approval. The closure captures pid into a local variable before passing it to the lambdas, which also incidentally fixes a latent staleness pattern in the prior lambda: self.kill(start_event.event.start.pid) form.

Comment thread packages/js-sdk/src/sandbox/commands/pty.ts
Addresses PR review: the CLI was the one internal consumer still calling
the now-deprecated `pty.sendInput`, which would emit a self-inflicted
deprecation warning. Switch it to the canonical `pty.sendStdin` (identical
behavior, the alias just delegates).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mishushakov mishushakov requested a review from huv1k June 30, 2026 11:26
@mishushakov mishushakov enabled auto-merge (squash) June 30, 2026 13:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant