pr/6e4e30251 featssh server ac 01 add sshremoteserver#256
Merged
plusplusoneplusplus merged 7 commits intoJun 1, 2026
Merged
Conversation
Owner
plusplusoneplusplus
commented
Jun 1, 2026
- feat(ssh-server): AC-01 — add SshRemoteServer data model
- fix(dashboard): clear Ralph session pane when clicking New Chat
- feat(ralph): add resume route for stuck executing sessions
- fix(ralph): allow /continue for NO_SIGNAL sessions regardless of cap position
- feat(servers): implement SshConnector for SSH tunnel remote servers (AC-02)
- feat(servers): add SSH Tunnel radio and fields to AddServerDialog
- feat(coc): auto-reconnect on unexpected SSH exit + SSH route integration tests
- Add SshRemoteServer interface (kind: 'ssh', host: string, localPort: number) to remote-server-types.ts; extend RemoteServerKind, RemoteServer, RemoteServerCreateInput, and RemoteServerUpdateInput unions - Mirror SshRemoteServer, RemoteServerInput, and RemoteServerPatch in packages/coc-client/src/contracts/servers.ts - Add normalizeSshHost / normalizeSshLocalPort helpers in remote-server-store.ts; update parseRemoteServer, buildCreateInput, buildUpdateInput, create, and update to handle ssh kind - Update remote-server-routes.ts: toRuntime handles ssh (idle stub until AC-02); /api/servers/test endpoint handles ssh input; import SshRemoteServer type - Add SSH store tests: CRUD lifecycle, validation, and persistence round-trip Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The onNewChat handler in RepoChatTab was not clearing selectedRalphSessionId, so clicking "New chat" while viewing a Ralph session left the Ralph workflow pane mounted (it takes priority over ChatDetailPane in the render path). Now the handler also resets the Ralph selection and updates the URL hash. Co-authored-by: Cursor <cursoragent@cursor.com>
When a Ralph iteration task fails, is cancelled, or the server crashes mid-loop, the session stays in phase=executing with no in-flight task. Previously there was no way to continue such sessions — /continue only works for completed-at-cap sessions and /new-loop requires RALPH_COMPLETE. Add POST .../ralph-sessions/:sessionId/resume that detects stuck executing sessions (phase=executing, under cap, no queued/running task) and enqueues the next iteration without changing maxIterations. - Server: new ralph-resume-routes.ts with full validation - Store: appendResumeMarker() for progress.md audit trail - Client: resumeRalphSession() in coc-client WorkspacesClient - UI: amber "Resume" button in RalphWorkflowPane for stuck sessions - Tests: route tests, store tests, and UI component tests (24 new) - Docs: updated ralph.md and rest-api.md references Co-authored-by: Cursor <cursoragent@cursor.com>
…position The /continue route previously only accepted NO_SIGNAL sessions where currentIteration >= maxIterations (cap-reached). This left early NO_SIGNAL stops (agent failure mid-run, iteration 2 of 20) with no recovery path — neither /continue, /resume, nor /new-loop accepted them. Expand isResumableTerminalState to accept any NO_SIGNAL-terminated session, and update the UI isContinuable check to match. This covers the real-world scenario where an agent crashes or fails to emit a RALPH_NEXT signal before hitting the iteration cap. - Server: isResumableTerminalState now accepts all NO_SIGNAL sessions - UI: renamed isCapHit → isContinuable, removed cap position guard - Tests: flipped the NO_SIGNAL-under-cap test from reject to accept Co-authored-by: Cursor <cursoragent@cursor.com>
…AC-02) - Add SshConnector class (ssh-connector.ts) modeled on DevTunnelConnector: spawns 'ssh -N <host>', polls health at http://127.0.0.1:<port>/api/health, marks 'online' on success, 'failed' on timeout or unexpected exit - Surfaces 'ssh binary not found on PATH' when process emits ENOENT error - Supports connect, disconnect, reconnect, connectConfigured, dispose - Wire SshConnector into remote-server-routes (toRuntime, connect/disconnect/ reconnect endpoints now handle ssh kind alongside devtunnel) - Instantiate SshConnector in server/index.ts and routes/index.ts; call connectConfigured on startup; dispose on server close - Add 14 unit tests covering connect-success, dedup, timeout, binary-not-found, unexpected-exit, reconnect, old-exit-guard, disconnect, getState, getStates, dispose, connectConfigured, and already-online short-circuit Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add third radio option 'SSH Tunnel' (kind='ssh') to the connection type fieldset, always visible alongside Direct URL and DevTunnel ID. - Selecting SSH Tunnel reveals two inputs: Host alias (maps to server.host, placeholder 'ubuntu-arm') and Local port (number, placeholder '4000', validated 1-65535). - Update buildInput to handle ssh kind; submit emits RemoteServerInput with kind/host/localPort. - Update inputFromServer to pre-populate SSH fields when editing an existing ssh-kind server. - Test indicator shows 'Connecting SSH...' while debounce is pending and shows localPort in the ok description (same as devtunnel). - Add 9 new tests covering: radio visibility, field rendering, submit enable/disable validation, submit payload, test indicator text, and EditServerDialog pre-population for ssh-kind servers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ion tests GAP-01: Add exponential-backoff auto-reconnect to SshConnector - New options: initialReconnectBackoffMs (default 2s), maxReconnectBackoffMs (default 30s) - When SSH child exits unexpectedly (intentionalStop false), scheduleReconnect fires after backoff, doubles for next attempt (capped at maxReconnectBackoffMs) - Backoff resets to initial on successful reconnect - disconnect() and reconnect() clear any pending reconnect timer - Added ManagedSshConnection.reconnectTimer and reconnectBackoffMs fields - New unit test: 'auto-reconnects after unexpected exit' verifies second child is spawned and reaches online after unexpected exit event GAP-02: SSH-specific integration tests in remote-server-routes.test.ts - Added SshConnector import and optional sshConnector param to startApi() - ssh-kind routes describe block with 4 tests: - POST /connect calls sshConnector.connect, returns online state - POST /disconnect calls sshConnector.disconnect, returns idle state - POST /reconnect (success) calls reconnect, returns online state - POST /reconnect (failure) connector throws, returns failed state - New lifecycle test: autoconnects configured SSH entries and disposes SshConnector on close All 29 ssh-connector + remote-server-routes tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.