runner

πŸƒ Runner Service – REPL Runtime Engine

The runner/ service is the runtime component of the Devex platform.
It is a lightweight WebSocket server embedded inside the user’s REPL pod. The runner connects directly to the frontend, allowing real-time:
  • β€’File browsing and editing
  • β€’Terminal interaction via PTY
  • β€’Bi-directional event-driven communication

πŸ“ Directory Structure

PathDescription
cmd/Entrypoint and route setup
services/repl/route.goWebSocket endpoint handler
pkg/wsWebSocket abstraction and event routing layer
pkg/fsFilesystem utils: read directory, patch files
pkg/ptyTerminal session manager using PTY

🌐 API Endpoint

GET /api/v1/repl/ws

Defined in route.go, this WebSocket endpoint serves as the main connection point between the frontend and the REPL container.

πŸ”„ WebSocket Event Flow

The WebSocket connection is event-based, using custom handlers via the pkg/ws system.
Here’s how each event is handled inside the runner:

πŸ“‘ Connection

  • β€’Triggered: When the frontend successfully connects
  • β€’Action: Emits the Loaded event with the directory tree at /workspaces
go
ws.On("Connection", func(data any) { rootContents, _ := fs.FetchDir("/workspaces", "") ws.Emit("Loaded", map[string]any{ "rootContents": rootContents, }) })

πŸ“ fetchDir

  • β€’
    Purpose: Fetches the contents of a directory (files & subfolders)
  • β€’
    Payload:
    json
    { "dir": "subdir/path" }
  • β€’
    Emits: fetchDirResponse with folder contents
go
ws.Emit("fetchDirResponse", { "contents": [...], "path": "subdir/path" })

πŸ“„ fetchContent

  • β€’
    Purpose: Fetches the content of a single file
  • β€’
    Payload:
    json
    { "path": "index.js" }
  • β€’
    Emits: fetchContentResponse with file content or error

πŸ’Ύ updateContent

  • β€’
    Purpose: Applies a patch to a file (diff-based updates)
  • β€’
    Payload:
    json
    { "path": "index.js", "patch": [...] }
  • β€’
    Emits: updateContentResponse with success or error

πŸ–₯️ requestTerminal

  • β€’
    Purpose: Starts a new PTY terminal session for the user
  • β€’
    Flow:
    1. β€’A session is created using pty.CreateSession
    2. β€’On receiving terminal data, it emits terminalResponse
    3. β€’On close, emits terminalClosed
go
session.SetOnDataCallback(func(data []byte) { ws.Emit("terminalResponse", string(data)) })

⌨️ terminalInput

  • β€’
    Purpose: Sends user input to the terminal session
  • β€’
    Payload:
    json
    { "data": "ls -la\n" }

🧱 Internal Packages

Each major functionality is implemented in modular packages. See individual documentation for detailed internals:

pkg/ws

WebSocket handler with event routing system Handles On, Emit, custom event types, and JSON marshalling.

pkg/fs

Filesystem abstraction layer Supports reading directories, fetching files, and applying patches.

pkg/pty

Terminal session manager using PTY Manages session creation, input, data output, and session lifecycle.

πŸ§ͺ Runtime Environment

The runner is deployed inside each user’s REPL pod via Kubernetes, and interacts with the user-specific volume mounted at /workspaces.
  • β€’Runner container is built from the main Dockerfile
  • β€’Connects automatically with the frontend once the pod is ready
  • β€’Exposes internal REST/WebSocket interface at /api/v1/repl/ws

🧩 Responsibilities

TaskHandled by
Serve WebSocket Endpointservices/repl/route.go
Emit & Handle Eventspkg/ws
File operationspkg/fs
Terminal sessionpkg/pty

πŸ”§ Future Improvements

  • β€’Add support for file uploads and deletions
  • β€’Terminal resize support
  • β€’Rate limiting or sandbox enforcement per session

πŸ”— Related

  • β€’Main backend API: /core
  • β€’Kubernetes setup: /k8s
  • β€’Templates used at REPL creation: /templates