v0.12.0
v0.12.0 (2026-03-25)
This release is published under the Apache-2.0 License.
Bug Fixes
- sandbox: Always enqueue output sentinel on cancellation (
e680f4c)
CancelledError is a BaseException, bypassing the except Exception handler. The if not cancelled guard in the finally block skipped the output_queue sentinel, leaving StreamReader consumers hanging forever. Remove the guard so the sentinel is always enqueued.
Fixes both _exec_streaming_async and _exec_streaming_tty_async.
Documentation
- Add interactive shells guide (
1ecd912)
Cover SDK shell() usage, terminal resize, stdin/stdout streaming, and a comparison table for choosing between exec and shell.
Features
- cli: Add shell command (
0838e2a)
Remote debugging and interactive workflows need direct terminal access to sandboxes without writing Python.
Add cwsandbox sh with raw mode, SIGWINCH resize, and terminal state restore on exit.
- sandbox: Add TTY exec and shell method (
8ff5de4)
Add _exec_streaming_tty_async for raw-byte TTY streaming with resize support, and the public shell() method that returns a TerminalSession. Widen _on_exec_complete to accept TerminalResult.
- types: Add terminal types (
94e55a5)
Make StreamReader a Generic[_S] parameterized over str (text streams) and bytes (raw TTY output). Add TerminalResult and TerminalSession types for interactive TTY sessions. Update Waitable type alias and all exports.
Testing
- sandbox: Add TTY streaming tests (
2602959)
Cover _exec_streaming_tty_async paths: happy path, server errors, gRPC transport errors, stdin forwarding, resize, and early failure propagation. Fold TestShellCancellation into the new class with shared helpers to reduce setup duplication.
- sandbox: Add xfail test for cancelled TTY session output hang (
8d665d8)
Demonstrates a bug where cancelling a TerminalSession future leaves the output StreamReader hanging forever. The CancelledError path in _exec_streaming_tty_async skips the output_queue sentinel (if not cancelled), so consumers block indefinitely.
The fix is to remove the if not cancelled guard so the sentinel is always enqueued. Cross-review confirmed no double-sentinel risk.
Marked xfail(strict=True) — will flip to XPASS once the guard is removed, signaling the marker should be dropped.
Detailed Changes: v0.11.2...v0.12.0