feat: implement web terminal for tool instances

- Add TerminalSession backend service for docker exec subprocess management
- Add TerminalManager for WebSocket session lifecycle management
- Create WebSocket endpoint at /ws/tool-instances/{id}/terminal
- Add session cookie authentication and instance ownership verification
- Install xterm.js with fit and web-links addons
- Create TerminalComponent with xterm.js integration
- Create TerminalPage with full-screen terminal view
- Add terminal route at /instances/:id/terminal
- Add terminal button to InstanceList for running instances
- Add terminal and arrow-left icons to icon registry
- Add comprehensive terminal CSS styles (dark theme, responsive)

Quality gates: typecheck ✓, lint ✓, build ✓, Python syntax ✓
This commit is contained in:
Fusion
2026-05-19 21:11:29 +02:00
parent d6b3e8b804
commit e344e961d6
23 changed files with 1136 additions and 4 deletions
+139
View File
@@ -0,0 +1,139 @@
# Tool Terminal - Design
## Architecture
```
Browser Backend Container
│ │ │
│ WebSocket connect │ │
│─────────────────────────>│ │
│ │ docker exec -it bash │
│ │───────────────────────────>│
│ │ │
│ stdin (keystrokes) │ stdin │
│─────────────────────────>│───────────────────────────>│
│ │ │
│ stdout/stderr │ stdout/stderr │
│<─────────────────────────│<───────────────────────────│
│ │ │
│ resize (cols, rows) │ pty resize │
│─────────────────────────>│───────────────────────────>│
│ │ │
```
## Component Design
### Backend
**TerminalManager:**
- Manages active terminal sessions
- Maps WebSocket connections to container processes
- Handles session lifecycle (create, resize, cleanup)
**WebSocket Endpoint:**
- `GET /ws/tool-instances/{instance_id}/terminal`
- Authenticates user via session cookie
- Establishes bidirectional WebSocket
- Spawns `docker exec -it` with pseudo-TTY
**Docker PTY:**
- Uses `docker exec` with TTY allocation
- Streams stdin/stdout/stderr via subprocess
- Handles resize via `stty` or docker API
### Frontend
**TerminalComponent:**
- Wraps xterm.js terminal
- Manages WebSocket connection
- Handles terminal resize
- Fits container to parent element
**TerminalPage:**
- Full-page terminal view
- Shows instance name in header
- Connection status indicator
- Reconnect on disconnect
## Data Flow
1. User clicks "Terminal" on running instance
2. Frontend opens WebSocket connection
3. Backend verifies ownership and spawns shell
4. Bidirectional streaming begins
5. User types → WebSocket → docker exec stdin
6. Container output → docker exec stdout → WebSocket → xterm.js
7. Resize events forwarded to adjust PTY dimensions
## Session Lifecycle
```
Connect
Authenticate ──> Reject (403)
Spawn Shell
Stream I/O ◄───> Resize
Disconnect
Cleanup Process
```
## Access Control
- WebSocket handshake validates session cookie
- Backend verifies user owns the instance
- Reject connection with 403 if unauthorized
- Close connection if instance stops running
## Technical Details
**Backend Libraries:**
- `asyncio` for WebSocket handling
- `subprocess` with `docker exec -it`
- `fcntl` for PTY resize (Linux)
**Frontend Libraries:**
- `xterm` - Terminal emulator
- `xterm-addon-fit` - Auto-fit to container
- `xterm-addon-web-links` - Clickable URLs
**Docker Commands:**
```bash
# Spawn shell
docker exec -it {container_id} /bin/bash
# Alternative with explicit TTY
docker exec -i {container_id} sh -c 'exec bash'
```
## Error Handling
- Connection refused → Show error message
- Container not running → Disable terminal button
- Shell spawn failed → Show error and close
- Network disconnect → Attempt reconnect
## CSS Integration
```css
.terminal-container {
width: 100%;
height: 100%;
min-height: 400px;
background: #1e1e1e;
border-radius: 8px;
overflow: hidden;
}
.terminal-container .xterm {
padding: 8px;
}
```