e344e961d6
- 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 ✓
140 lines
3.9 KiB
Markdown
140 lines
3.9 KiB
Markdown
# 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;
|
|
}
|
|
```
|