diff --git a/docs/api/terminal.md b/docs/api/terminal.md new file mode 100644 index 0000000..ae4a3a7 --- /dev/null +++ b/docs/api/terminal.md @@ -0,0 +1,134 @@ +# Terminal API + +The Terminal API provides WebSocket-based terminal access to running tool instances. + +## WebSocket Endpoint + +### Connect to Terminal + +``` +GET /ws/tool-instances/{instance_id}/terminal +``` + +Establishes a WebSocket connection to an interactive terminal session inside a running tool instance container. + +**Authentication:** Requires valid session cookie. + +**Path Parameters:** +- `instance_id` (string, UUID): The tool instance ID + +**Connection Flow:** +1. Client connects to WebSocket endpoint +2. Server authenticates user and verifies instance ownership +3. Server creates or reattaches to existing terminal session +4. Server sends `{"type": "status", "status": "connected"}` message +5. Bidirectional communication begins + +**Message Types:** + +#### Client to Server + +**Terminal Input (bytes or string)** +- Send raw bytes for terminal input (key presses) +- Send text for terminal input (will be encoded as UTF-8) + +**Resize Command (JSON)** +```json +{ + "type": "resize", + "cols": 80, + "rows": 24 +} +``` + +**Reset Command (JSON)** +```json +{ + "type": "reset" +} +``` +Kills the current terminal session and starts a fresh one. + +**Pong Response (JSON)** +```json +{ + "type": "pong" +} +``` +Sent automatically in response to server ping messages. + +#### Server to Client + +**Terminal Output (bytes)** +Raw terminal output as binary data (Blob in browser). + +**Status Messages (JSON)** +```json +{"type": "status", "status": "connected"} +{"type": "status", "status": "resetting"} +``` + +**Ping Messages (JSON)** +```json +{"type": "ping"} +``` +Sent every 30 seconds to detect disconnections. Client should respond with `{"type": "pong"}`. + +### Session Persistence + +Terminal sessions persist across WebSocket disconnections: +- When a client disconnects, the terminal session remains active +- On reconnection, the client reattaches to the existing session +- Buffered output is replayed to the client on reconnection +- Sessions are cleaned up after 30 minutes of inactivity + +### Concurrent Connections + +Only one WebSocket connection is allowed per terminal session: +- New connections close existing connections with code 4000 +- Previous client receives "New connection established" reason + +## HTTP Endpoints + +### Reset Terminal Session + +``` +POST /api/projects/{project_id}/repositories/{repo_id}/instances/{instance_id}/terminal/reset +``` + +Resets the terminal session for a tool instance, killing the current shell and starting fresh. + +**Authentication:** Required + +**Path Parameters:** +- `project_id` (string, UUID): Project ID +- `repo_id` (string, UUID): Repository ID +- `instance_id` (string, UUID): Instance ID + +**Response:** +```json +{ + "status": "success", + "message": "Terminal session reset successfully", + "instance_id": "...", + "session_id": "..." +} +``` + +**Error Responses:** +- `404 Not Found`: Instance not found +- `400 Bad Request`: Instance is not running +- `500 Internal Server Error`: Failed to reset terminal session + +## Error Codes + +WebSocket close codes: +- `1000`: Normal closure +- `4000`: Error/reset +- `4001`: Invalid instance ID +- `4003`: Unauthorized/Forbidden +- `4004`: Instance not found or not running + +## Heartbeat + +The server sends ping messages every 30 seconds. If no ping is received for 60 seconds, the client should assume the connection is dead and reconnect. diff --git a/docs/features/terminal-troubleshooting.md b/docs/features/terminal-troubleshooting.md new file mode 100644 index 0000000..3925357 --- /dev/null +++ b/docs/features/terminal-troubleshooting.md @@ -0,0 +1,172 @@ +# Terminal Troubleshooting Guide + +## Common Issues + +### Cannot Connect to Terminal + +**Symptom:** Terminal shows "Connection closed" or "Error" status immediately. + +**Solutions:** +1. Verify the tool instance is running: + - Check instance status in the UI + - Start the instance if it's stopped + +2. Check browser console for errors: + - Open browser DevTools (F12) + - Look for WebSocket connection errors + - Check for CORS or authentication errors + +3. Verify network connectivity: + - Ensure you can reach the API server + - Check if WebSocket connections are blocked by firewall/proxy + - Try accessing from a different network + +**If the issue persists:** +- Reset the terminal session +- Refresh the page +- Check server logs for errors + +### Terminal Freezes or Becomes Unresponsive + +**Symptom:** Terminal accepts no input or stops updating. + +**Solutions:** +1. **Reset the terminal:** + - Click the Reset button in the terminal header + - Confirm the reset action + - Wait for the new session to start + +2. **Check for stuck processes:** + - Try Ctrl+C to interrupt any running process + - If that doesn't work, reset the terminal + +3. **Browser issues:** + - Close and reopen the browser tab + - Clear browser cache and cookies + - Try a different browser + +### Output Not Showing + +**Symptom:** Commands execute but no output appears. + +**Solutions:** +1. Check terminal focus: + - Click inside the terminal area + - Look for the cursor indicator + +2. Resize the terminal: + - The terminal may need a resize event to render properly + - Try resizing the browser window slightly + +3. Reset the terminal session + +### Reconnection Loop + +**Symptom:** Terminal keeps disconnecting and reconnecting repeatedly. + +**Solutions:** +1. Check instance health: + - The instance may be unhealthy or restarting + - Check instance logs for errors + +2. Network stability: + - Unstable network causes repeated disconnections + - Try on a more stable connection + +3. Multiple tabs: + - Only one tab can connect to a terminal session + - Close other tabs with the same terminal open + +## Diagnostic Steps + +### Check WebSocket Connection + +1. Open browser DevTools (F12) +2. Go to Network tab +3. Filter by "WS" (WebSocket) +4. Look for the terminal WebSocket connection +5. Check: + - Connection status (should be 101 Switching Protocols) + - Messages tab for ping/pong traffic + - Any error messages in the connection + +### Verify Terminal Session + +To check if a terminal session exists on the server: + +```bash +# Check server logs for session activity +docker logs hq-api | grep -i "terminal" +``` + +Look for: +- "Terminal session ready" - session created successfully +- "Reattaching to existing terminal session" - reconnecting to existing session +- "Cleaning up idle terminal session" - session expired + +### Test Basic Connectivity + +```bash +# Test if the WebSocket endpoint is reachable +curl -i -N \ + -H "Connection: Upgrade" \ + -H "Upgrade: websocket" \ + -H "Sec-WebSocket-Key: test" \ + -H "Sec-WebSocket-Version: 13" \ + https://your-api-domain/ws/tool-instances/test/terminal +``` + +Expected: HTTP 400 (invalid instance ID) or redirect to auth + +## Error Codes + +### WebSocket Close Codes + +- **1000**: Normal closure - connection closed cleanly +- **4000**: Generic error - check server logs +- **4001**: Invalid instance ID - verify the instance exists +- **4003**: Unauthorized - session expired or invalid +- **4004**: Instance not running - start the instance first + +### HTTP Status Codes + +- **404**: Instance not found - verify instance ID +- **400**: Instance not running - start the instance +- **500**: Server error - check server logs + +## Resetting Everything + +If all else fails: + +1. **Reset terminal session:** + ``` + POST /api/projects/{project_id}/repositories/{repo_id}/instances/{instance_id}/terminal/reset + ``` + +2. **Restart the tool instance:** + - Stop the instance + - Start the instance again + - Reconnect to the terminal + +3. **Clear browser data:** + - Clear cookies for the domain + - Clear local storage + - Hard refresh the page (Ctrl+F5) + +## Getting Help + +If issues persist: + +1. Collect diagnostic information: + - Browser console logs + - Network tab WebSocket messages + - Server logs (`docker logs hq-api`) + - Instance status and health + +2. Check the [Terminal API documentation](/docs/api/terminal.md) for protocol details + +3. Report issues with: + - Steps to reproduce + - Expected vs actual behavior + - Browser and OS version + - Instance type and configuration diff --git a/docs/features/terminal.md b/docs/features/terminal.md new file mode 100644 index 0000000..9f2b6c5 --- /dev/null +++ b/docs/features/terminal.md @@ -0,0 +1,83 @@ +# Terminal Sessions + +Terminal sessions provide interactive shell access to your running tool instances directly in the browser. + +## Persistent Sessions + +Terminal sessions are **persistent** - they survive browser refreshes, network interruptions, and tab switches. + +### How It Works + +- 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 + +### 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 + +## Resetting the Terminal + +If your terminal becomes unresponsive or you want a fresh start: + +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 + +**Note:** Resetting only affects the terminal session, not the tool instance itself. Any files you've created remain intact. + +## Mobile Terminal + +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 + +## 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 + +Special keys can be accessed via the special keys panel on mobile or by using modifier combinations. + +## Troubleshooting + +### Connection Issues + +**"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 + +**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 + +### Display Issues + +**Text not visible:** +- Adjust font size using +/- buttons +- Check if the terminal has focus (click inside it) +- Try resizing the browser window + +**Characters not appearing:** +- Ensure the terminal has focus +- Check if a modifier key is stuck (Ctrl, Alt) +- Reset the terminal if stuck + +## Session Limits + +- **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 diff --git a/openspec/changes/persistent-terminal-sessions/tasks.md b/openspec/changes/persistent-terminal-sessions/tasks.md index a234a6e..65ec048 100644 --- a/openspec/changes/persistent-terminal-sessions/tasks.md +++ b/openspec/changes/persistent-terminal-sessions/tasks.md @@ -59,6 +59,6 @@ ## 8. Documentation -- [ ] 8.1 Update API documentation with new reset endpoint -- [ ] 8.2 Update user documentation about persistent terminals -- [ ] 8.3 Add troubleshooting guide for terminal issues +- [x] 8.1 Update API documentation with new reset endpoint +- [x] 8.2 Update user documentation about persistent terminals +- [x] 8.3 Add troubleshooting guide for terminal issues