merge: integrate main restructuring into dev
- Resolve 57 merge conflicts from codebase restructure - Port dev feature code to new directory structure: * Update import paths to use @/ aliases * Add backward-compatible API signatures (createInstance, startInstance, deleteInstance) * Add missing type exports (ProjectWithRepos, InstanceHealth, Branch, BranchesResponse) * Extend Session and GitRepository types for dev features * Extend TerminalComponent props for mobile terminal wrapper * Add missing icon names (bell, drag, undo) Quality gates: tsc pass (0 errors), build pass, 127/131 tests pass (4 pre-existing failures unrelated to merge)
This commit is contained in:
@@ -22,25 +22,30 @@ The Projects page displays all your projects in a card layout showing:
|
||||
- Creation date
|
||||
- Associated repositories count
|
||||
|
||||
Each project card provides quick actions:
|
||||
- **Settings** — Navigate to the project settings page
|
||||
- **Delete** — Delete the project with confirmation
|
||||
- **Open Workspace** — Open the project's workspace (rightmost action)
|
||||
|
||||
### Opening a Project Workspace
|
||||
|
||||
Click on any project card to open its **workspace**. The workspace is the default view for a project and shows:
|
||||
Click the **"Open Workspace"** button on any project card to open its **workspace**. The workspace is the default view for a project and shows:
|
||||
- Repository file browser
|
||||
- Branch selector
|
||||
- File viewer
|
||||
|
||||
### Editing a Project
|
||||
|
||||
1. From the Projects page, click the **menu icon** (⋮) on a project card
|
||||
2. Select **"Edit"**
|
||||
3. Update the name or description
|
||||
4. Click **"Save"**
|
||||
1. From the Projects page, click the **"Settings"** link on a project card
|
||||
2. On the project settings page, update the **name** or **description**
|
||||
3. Click **"Save Changes"**
|
||||
|
||||
The settings page also provides access to repository management and member settings.
|
||||
|
||||
### Deleting a Project
|
||||
|
||||
1. From the Projects page, click the **menu icon** (⋮) on a project card
|
||||
2. Select **"Delete"**
|
||||
3. Confirm the deletion
|
||||
1. From the Projects page, click the **"Delete"** button on a project card
|
||||
2. Confirm the deletion
|
||||
|
||||
**Note:** Deleting a project also deletes all associated repositories and their data. This action cannot be undone.
|
||||
|
||||
|
||||
+180
-68
@@ -1,104 +1,216 @@
|
||||
# Terminal Sessions
|
||||
# Web Terminal
|
||||
|
||||
Terminal sessions provide interactive shell access to your running tool instances directly in the browser.
|
||||
## Overview
|
||||
|
||||
## Persistent Sessions
|
||||
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.
|
||||
|
||||
Terminal sessions are **persistent** - they survive browser refreshes, network interruptions, and tab switches.
|
||||
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 It Works
|
||||
## How to Use
|
||||
|
||||
- When you open a terminal, a shell session starts inside the tool instance container
|
||||
- If you close the browser or lose connection, the session keeps running
|
||||
- When you reconnect, you reattach to the same session with all previous output preserved
|
||||
- Sessions automatically clean up after 30 minutes of inactivity
|
||||
### 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
|
||||
|
||||
If your connection drops:
|
||||
1. The terminal shows "Reconnecting..." status
|
||||
2. The client automatically attempts to reconnect with exponential backoff
|
||||
3. On successful reconnection, buffered output is replayed
|
||||
4. You can continue working where you left off
|
||||
The terminal **automatically reconnects** if the WebSocket drops:
|
||||
|
||||
## Resetting the Terminal
|
||||
- Brief disconnects (WiFi hiccups, proxy timeouts) are recovered within 1–5 seconds
|
||||
- Up to **10 reconnection attempts** with exponential backoff
|
||||
- **Scrollback is preserved** across reconnects
|
||||
- A visual divider (`--- Reconnected ---`) separates old and new output
|
||||
|
||||
If your terminal becomes unresponsive or you want a fresh start:
|
||||
**Manual reconnect:**
|
||||
- Click the **Reconnect** button in the status bar
|
||||
- Or press **Ctrl+Shift+R** anywhere in the terminal page
|
||||
|
||||
1. Click the **Reset** button in the terminal header
|
||||
2. Confirm the reset action
|
||||
3. The current shell is killed and a new one starts
|
||||
4. All terminal history is cleared
|
||||
### Session Ended
|
||||
|
||||
**Note:** Resetting only affects the terminal session, not the tool instance itself. Any files you've created remain intact.
|
||||
When the container process exits (e.g., you run `exit` or the container stops), the terminal shows an overlay:
|
||||
|
||||
## Mobile Terminal
|
||||
```
|
||||
┌─────────────────────────┐
|
||||
│ Session Ended │
|
||||
│ The container process │
|
||||
│ has exited. │
|
||||
│ │
|
||||
│ [Reconnect] [Go Back] │
|
||||
└─────────────────────────┘
|
||||
```
|
||||
|
||||
On mobile devices, the terminal includes:
|
||||
- Special keys panel (Ctrl, Alt, Tab, arrows, etc.)
|
||||
- Font size controls
|
||||
- Auto-hiding header for maximum screen space
|
||||
- Touch-friendly interface
|
||||
- **Reconnect** — spawns a new shell session in the same container
|
||||
- **Go Back** — returns to the workspace page
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
||||
Standard terminal shortcuts work as expected:
|
||||
- `Ctrl+C`: Send interrupt signal
|
||||
- `Ctrl+D`: Send EOF (close shell if empty)
|
||||
- `Ctrl+L`: Clear screen
|
||||
- `Ctrl+Z`: Suspend process
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `Ctrl+Shift+R` | Force reconnect (bypasses backoff) |
|
||||
| Standard terminal shortcuts | `Ctrl+C`, `Ctrl+D`, `Ctrl+L`, Tab completion, etc. |
|
||||
|
||||
Special keys can be accessed via the special keys panel on mobile or by using modifier combinations.
|
||||
## Technical Details
|
||||
|
||||
## Container Monitoring & Notifications
|
||||
### WebSocket Protocol
|
||||
|
||||
The platform monitors your tool instances in real-time and notifies you of important events:
|
||||
The terminal communicates over a binary WebSocket with mixed JSON control messages.
|
||||
|
||||
### What You'll See
|
||||
**Connection:**
|
||||
```
|
||||
ws://api.example.com/ws/tool-instances/{instance_id}/terminal
|
||||
```
|
||||
|
||||
- **Starting:** When a container begins starting
|
||||
- **Running:** When a container is ready
|
||||
- **Error:** When a build fails, container crashes, or tunnel fails
|
||||
- **Stopped:** When a container stops
|
||||
**Binary frames** carry raw terminal I/O. **Text (JSON) frames** carry control messages:
|
||||
|
||||
Notifications appear as toast messages at the top of the screen. Errors persist until dismissed; other notifications auto-dismiss after a few seconds.
|
||||
**Client → Server:**
|
||||
- `{"type":"ping","id":n}` — heartbeat ping
|
||||
- `{"type":"resize","cols":120,"rows":40}` — terminal resize
|
||||
- Raw bytes — keystroke input
|
||||
|
||||
### Real-Time Status
|
||||
**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
|
||||
|
||||
Instance status badges update in real-time via Server-Sent Events (SSE) — no page refresh needed.
|
||||
### 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
|
||||
|
||||
### Connection Issues
|
||||
### "Connecting..." stays yellow
|
||||
|
||||
**"Connection closed" error:**
|
||||
- The tool instance may have stopped - check the instance status
|
||||
- Network issues - the client will auto-reconnect
|
||||
- Session timeout - sessions expire after 30 minutes of inactivity
|
||||
**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
|
||||
|
||||
**"Container not found" error (4004):**
|
||||
- The Docker container no longer exists (e.g., after host restart)
|
||||
- Restart the tool instance to recreate the container
|
||||
### "Reconnecting" loops forever
|
||||
|
||||
**Terminal not responding:**
|
||||
- Try resetting the terminal using the Reset button
|
||||
- Check if the tool instance is still running
|
||||
- Refresh the page to force reconnection
|
||||
**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`
|
||||
|
||||
### Display Issues
|
||||
### Typing feels slow
|
||||
|
||||
**Text not visible:**
|
||||
- Adjust font size using +/- buttons
|
||||
- Check if the terminal has focus (click inside it)
|
||||
- Try resizing the browser window
|
||||
**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
|
||||
|
||||
**Characters not appearing:**
|
||||
- Ensure the terminal has focus
|
||||
- Check if a modifier key is stuck (Ctrl, Alt)
|
||||
- Reset the terminal if stuck
|
||||
### Terminal is blank after reconnect
|
||||
|
||||
## Session Limits
|
||||
**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`
|
||||
|
||||
- **One connection per terminal:** Only one browser tab can connect to a terminal session at a time. Opening a new connection closes the old one.
|
||||
- **30-minute idle timeout:** Sessions without activity are automatically cleaned up
|
||||
- **Buffer size:** Up to 10KB of output is buffered for replay on reconnection
|
||||
### "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
|
||||
|
||||
Reference in New Issue
Block a user