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:
@@ -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;
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user