You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(session): REST→PTY bridge for /session/start (§1.5b)
POST /api/session/start now routes through transport=pty by default,
calling active.acquire(config, PTYTransport) and returning a ws_url
the frontend feeds to /api/session/ws. The legacy tmux+ttyd path is
reachable via transport=ttyd in the body or STUDYLOOP_TRANSPORT=ttyd
env override (operator kill-switch).
Why: closes the §1.5b gap flagged in Amendment #5 — without this
bridge, the new WS route was reachable by tests only. Now the
full request path works: picker POSTs /session/start → server
acquires active session + PTYTransport → returns ws_url →
browser opens WS and gets live PTY stream.
Transport dispatch:
- Body field ``transport: pty|ttyd`` (optional, default pty).
- STUDYLOOP_TRANSPORT env wins over body — operator emergency
switch per plan §1.9 without touching clients.
- On pty path: no tmux check, no ttyd spawn, no tmux metadata in
session_state.json. Writes transport=pty into state for clarity.
Binary missing (503) now returns a structured payload:
{error, agent, binary, install_hint}. Hints cover all five
registered agents (claude, codex, gemini, kiro, opencode) so the
UI — or an agent orchestrating installs — has a concrete next
step. Per-agent "self-heal and retry" is §1.10 follow-up.
Adapter shell wrapping: PTYTransport's build_launch_cmd returns
["/bin/sh", "-c", adapter.launch_cmd(...)]. Adapters legitimately
use pipes/&& (their launch_cmd returns shell strings), so we
execvpe /bin/sh instead of splitting via shlex. Mirrors what
tmux send-keys effectively did.
Tests:
- +5 in test_web_session_start_pty.py: happy path returns ws_url
and bypasses tmux, pty-is-default when unset, 409 when active,
503 with install_hint, env=ttyd overrides body=pty (routes to
legacy branch and trips the tmux check).
- Existing test_web_session.py: 4 legacy guard tests updated to
pass transport=ttyd explicitly — they were testing tmux-based
semantics that only apply to that branch now.
1985 passed, 145 deselected (was 1980 → +5 net). Ruff + format clean.
Plan: Amendment #5 "§1.5b REST→PTY bridge" follow-up is now closed.
Amendment #6 (below) documents the contract for §1.7 frontend.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments