Files
headquarter/docs/features/terminal.md
T
alex a01e6252f5 docs: add responsive terminal documentation
- Add docs/features/terminal.md with user guide, connection states,
  keyboard shortcuts, protocol details, and troubleshooting
- Update docs/architecture/frontend.md with terminal component stack,
  connection hook behavior, and data flow diagrams
- Update docs/architecture/backend.md with terminal system architecture,
  protocol reference, message batching, and reconnect behavior
- Update docs/README.md to include terminal in feature list
2026-05-27 21:46:57 +02:00

217 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Web Terminal
## Overview
The web terminal provides an interactive shell session inside running tool instances directly from your browser. It uses xterm.js to render a full terminal emulator connected via WebSocket to a PTY-backed docker exec session.
The terminal is designed to feel as close to a local terminal as possible, with features for network resilience, low-latency typing, and session continuity.
## How to Use
### Opening a Terminal
1. Navigate to a **project** and select a **repository**
2. Go to the repository **workspace**
3. Start or select a **tool instance** that supports the terminal interface
4. Click the **"Open Terminal"** button
The terminal opens in full-page mode with a status bar at the top.
### Terminal Layout
```
┌─────────────────────────────────────────────┐
│ ● Connected [Reconnect] [×] │
├─────────────────────────────────────────────┤
│ │
│ user@container:~$ ls -la │
│ total 128 │
│ drwxr-xr-x 5 user user 4096 May 27 10:00 │
│ ... │
│ │
└─────────────────────────────────────────────┘
```
**Status bar (top):**
- **Connection dot** — color indicates connection health
- **Status text** — shows current state and latency
- **Reconnect button** — appears when disconnected
- **Close button** — returns to the previous page
### Connection States
| Indicator | Meaning | Action |
|-----------|---------|--------|
| 🟡 **Yellow dot** + "Connecting..." | Opening WebSocket | Wait or check network |
| 🟢 **Green dot** + "Connected" | Healthy connection (<100ms) | Ready to use |
| 🟡 **Yellow dot** + "Slow (150ms)" | Elevated latency | Connection usable but laggy |
| 🟡 **Yellow dot** + "Reconnecting (2)" | Connection lost, retrying | Wait for auto-reconnect |
| ⚪ **Gray dot** + "Disconnected" | Max retries exceeded | Click Reconnect or refresh |
**Hover the status dot** to see the current round-trip latency in milliseconds.
### Typing
Type normally as you would in a local terminal. The terminal supports:
- **Printable characters** appear instantly (local echo)
- **Special keys** (Tab, Enter, Ctrl+C, arrow keys) are sent to the server
- **Password prompts** automatically suppress local echo
- **Unicode** input and output
### Reconnecting
The terminal **automatically reconnects** if the WebSocket drops:
- Brief disconnects (WiFi hiccups, proxy timeouts) are recovered within 15 seconds
- Up to **10 reconnection attempts** with exponential backoff
- **Scrollback is preserved** across reconnects
- A visual divider (`--- Reconnected ---`) separates old and new output
**Manual reconnect:**
- Click the **Reconnect** button in the status bar
- Or press **Ctrl+Shift+R** anywhere in the terminal page
### Session Ended
When the container process exits (e.g., you run `exit` or the container stops), the terminal shows an overlay:
```
┌─────────────────────────┐
│ Session Ended │
│ The container process │
│ has exited. │
│ │
│ [Reconnect] [Go Back] │
└─────────────────────────┘
```
- **Reconnect** — spawns a new shell session in the same container
- **Go Back** — returns to the workspace page
## Keyboard Shortcuts
| Shortcut | Action |
|----------|--------|
| `Ctrl+Shift+R` | Force reconnect (bypasses backoff) |
| Standard terminal shortcuts | `Ctrl+C`, `Ctrl+D`, `Ctrl+L`, Tab completion, etc. |
## Technical Details
### WebSocket Protocol
The terminal communicates over a binary WebSocket with mixed JSON control messages.
**Connection:**
```
ws://api.example.com/ws/tool-instances/{instance_id}/terminal
```
**Binary frames** carry raw terminal I/O. **Text (JSON) frames** carry control messages:
**Client → Server:**
- `{"type":"ping","id":n}` — heartbeat ping
- `{"type":"resize","cols":120,"rows":40}` — terminal resize
- Raw bytes — keystroke input
**Server → Client:**
- `{"type":"pong","id":n}` — heartbeat response
- `{"type":"status","status":"connected"}` — session ready
- `{"type":"set_echo_state","enabled":false}` — disable local echo
- `{"type":"session_ended","reason":"process_exit"}` — session ended
- Raw bytes — terminal output
### Architecture
```
Browser Backend
┌──────────────────────┐ ┌─────────────────────────────┐
│ TerminalComponent │ │ terminal.py (WS endpoint) │
│ ├─ xterm.js │◄───────►│ ├─ auth + session mgmt │
│ ├─ FitAddon │ WS │ └─ echo state detection │
│ ├─ SerializeAddon │ │ │
│ └─ useTerminalConn. │ │ TerminalManager │
│ ├─ heartbeat │ │ ├─ read_loop (batching) │
│ ├─ reconnect │ │ ├─ write_loop │
│ ├─ local echo │ │ └─ heartbeat_loop │
│ └─ resize throttle│ │ │
│ │ │ TerminalSession │
│ sessionStorage │ │ ├─ PTY + docker exec │
│ (scrollback backup) │ │ └─ termios echo detection │
└──────────────────────┘ └─────────────────────────────┘
```
### Reconnect Behavior
On disconnect:
1. The client serializes terminal scrollback to `sessionStorage`
2. Backoff timer starts (1s, 2s, 4s, 8s, 16s, then caps at 30s)
3. On reconnect, scrollback is restored + divider line
4. A new `docker exec` session is spawned transparently
**Note:** The underlying docker exec PTY is not resumable. Reconnect creates a new shell, but scrollback continuity makes this transparent.
### Performance
- **Local echo** makes printable characters appear in <1ms
- **Message batching** on the backend reduces WebSocket frame overhead
- **Resize debouncing** (200ms) + throttling (500ms) prevents server spam
- **Heartbeat interval** is 15s to balance detection speed with server load
## Troubleshooting
### "Connecting..." stays yellow
**Issue:** WebSocket cannot open
**Check:**
1. Is the API server running?
2. Is the tool instance in "running" status?
3. Check browser console for connection errors
4. Verify the `VITE_API_BASE_URL` points to the correct API
### "Reconnecting" loops forever
**Issue:** Max reconnection attempts exceeded
**Check:**
1. Is the container still running? (`docker ps`)
2. Did the container crash or get stopped?
3. Check server logs for `Terminal session error`
### Typing feels slow
**Issue:** High latency or no local echo
**Check:**
1. Hover the status dot — latency >100ms is shown as "Slow"
2. Local echo only works for printable ASCII characters
3. Password prompts intentionally disable echo
4. Very high latency may indicate a congested network
### Terminal is blank after reconnect
**Issue:** Scrollback not restored
**Check:**
1. `sessionStorage` may have been cleared (new browser session)
2. The scrollback cap is 10,000 lines — very long sessions may truncate
3. Browser privacy settings may block `sessionStorage`
### "Session Ended" immediately
**Issue:** Container process exits right away
**Check:**
1. The container's default command may have finished
2. Check the tool type's Docker Compose template
3. Some tools (like one-off scripts) are not meant for persistent terminal sessions
## Configuration
No additional configuration is required. The terminal adapts automatically to:
- Browser window size (via ResizeObserver)
- System light/dark theme preference
- Network conditions (reconnect backoff)
## Related Features
- [Workspace](workspace.md) — Open the terminal from the repository workspace
- [Tool Types](tool-types.md) — Configure which tools expose a terminal interface
- [SSH Keys](ssh-keys.md) — Manage SSH keys for repository access from within the terminal