Files
headquarter/openspec/changes/tool-terminal/specs/spec.md
T
Fusion e344e961d6 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 ✓
2026-05-19 21:11:29 +02:00

166 lines
3.6 KiB
Markdown

# Tool Terminal Specification
## Requirements
### Functional Requirements
1. **WebSocket Terminal**: Provide terminal sessions via WebSocket at `/ws/tool-instances/{instance_id}/terminal`
2. **Terminal I/O**: Stream stdin/stdout/stderr bidirectionally in real-time
3. **Terminal Resize**: Support dynamic resize with COLS/ROWS updates
4. **Session Management**: Multiple independent sessions per instance, cleanup on disconnect
5. **Access Control**: Only instance owners can access, reject unauthorized with 403
6. **Shell Spawn**: Spawn `/bin/bash` or `/bin/sh` inside container via `docker exec`
### Non-Functional Requirements
1. **Latency**: Character input to display < 50ms
2. **Concurrent Sessions**: Support 10+ simultaneous terminal sessions
3. **Browser Support**: Chrome, Firefox, Safari, Edge
4. **Container Lifecycle**: Terminal closes when container stops
## API Specification
### WebSocket Endpoint
**URL:** `wss://{api_host}/ws/tool-instances/{instance_id}/terminal`
**Protocol:**
- Connection requires valid session cookie
- Binary frame: terminal output (stdout/stderr)
- Text frame: control messages (JSON)
**Control Messages:**
Request (Client → Server):
```json
{
"type": "resize",
"cols": 80,
"rows": 24
}
```
Response (Server → Client):
```json
{
"type": "status",
"status": "connected"
}
```
### REST Endpoint
**GET /tool-instances/{instance_id}/terminal** (HTML page)
- Returns terminal page for the instance
- Verifies ownership
- Returns 404 if instance not found
- Returns 403 if unauthorized
## Frontend Specification
### TerminalComponent
**Props:**
```typescript
interface TerminalProps {
instanceId: string;
instanceName: string;
onClose?: () => void;
}
```
**Features:**
- xterm.js terminal with custom theme
- WebSocket connection management
- Auto-fit to parent container
- Connection status indicator
- Reconnect on disconnect (3 retries)
### TerminalPage
**Route:** `/instances/:instanceId/terminal`
- Full-page terminal view
- Shows instance name in header
- Back button to instance list
- Connection status badge
## Backend Specification
### TerminalManager
**Methods:**
```python
class TerminalManager:
async def create_session(
self,
instance_id: uuid.UUID,
user_id: uuid.UUID,
websocket: WebSocket
) -> TerminalSession
async def handle_resize(
self,
session_id: str,
cols: int,
rows: int
) -> None
async def close_session(self, session_id: str) -> None
```
### TerminalSession
**Responsibilities:**
- Manage docker exec subprocess
- Stream I/O between WebSocket and PTY
- Handle resize signals
- Cleanup on disconnect
**Docker Command:**
```python
async def spawn_shell(container_id: str) -> subprocess.Process:
proc = await asyncio.create_subprocess_exec(
"docker", "exec", "-i", container_id, "/bin/bash",
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.STDOUT,
)
return proc
```
## Dependencies
**Backend:**
- FastAPI WebSocket support
- asyncio subprocess
- docker CLI
**Frontend:**
- `xterm` (v5.x)
- `xterm-addon-fit`
- `xterm-addon-web-links`
## Migration Plan
1. Install xterm.js dependencies
2. Create backend WebSocket endpoint
3. Create TerminalManager and TerminalSession
4. Create frontend TerminalComponent
5. Add terminal route and navigation
6. Test with running instances
## Testing
- Unit: TerminalSession I/O streaming
- Integration: WebSocket connection lifecycle
- Manual: Terminal functionality with real containers
## Quality Gates
- pytest
- mypy
- ruff
- npm run typecheck
- npm run lint
- npm run build