40a940304b
- Create enhanced health endpoints with /health and /health/db - Add comprehensive docstrings to all API endpoints - Add Pydantic response models with Field descriptions - Create apps/api/README.md with setup guide - Create ADR-001 for session auth decision - Create ADR-002 for async SQLAlchemy decision - Quality gates: Python syntax OK, TypeScript OK
3.6 KiB
3.6 KiB
Tool Terminal Specification
Requirements
Functional Requirements
- WebSocket Terminal: Provide terminal sessions via WebSocket at
/ws/tool-instances/{instance_id}/terminal - Terminal I/O: Stream stdin/stdout/stderr bidirectionally in real-time
- Terminal Resize: Support dynamic resize with COLS/ROWS updates
- Session Management: Multiple independent sessions per instance, cleanup on disconnect
- Access Control: Only instance owners can access, reject unauthorized with 403
- Shell Spawn: Spawn
/bin/bashor/bin/shinside container viadocker exec
Non-Functional Requirements
- Latency: Character input to display < 50ms
- Concurrent Sessions: Support 10+ simultaneous terminal sessions
- Browser Support: Chrome, Firefox, Safari, Edge
- 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):
{
"type": "resize",
"cols": 80,
"rows": 24
}
Response (Server → Client):
{
"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:
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:
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:
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-fitxterm-addon-web-links
Migration Plan
- Install xterm.js dependencies
- Create backend WebSocket endpoint
- Create TerminalManager and TerminalSession
- Create frontend TerminalComponent
- Add terminal route and navigation
- 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