Files
headquarter/openspec/changes/archive/2026-05-19-tool-terminal/specs/spec.md
T
Fusion 40a940304b docs: comprehensive API documentation
- 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
2026-05-19 21:31:20 +02:00

3.6 KiB

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):

{
  "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-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