server

package
v0.35.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 22, 2026 License: MIT Imports: 25 Imported by: 0

README

Server Package (internal/server)

HTTP/WebSocket transport layer for HotPlex.

Overview

This package provides the core HTTP and WebSocket handlers that bridge web clients to the HotPlex Engine. It implements OpenCode-compatible HTTP endpoints and native WebSocket protocol.

Key Components

Component Description
ExecutionController Main execution orchestration
HotPlexWebSocket Native WebSocket handler
OpenCodeHTTP OpenCode-compatible HTTP endpoints
Observability Metrics and health endpoints
BridgeServer WebSocket gateway for external platform adapters

Usage

import "github.com/hrygo/hotplex/internal/server"

// Create execution controller
ctrl := server.NewExecutionController(engine, logger)

// Execute request
err := ctrl.Execute(ctx, server.ExecutionRequest{
    SessionID:    "session-123",
    Prompt:       "Write a hello world program",
    Instructions: "Use Python 3.14",
    SystemPrompt: "You are a senior engineer",
    WorkDir:      "/tmp/sandbox",
    Timeout:      15 * time.Minute,
}, callback)

Endpoints

Endpoint Method Description
/ws/v1/agent WebSocket Native HotPlex Agent WebSocket
/session POST Create OpenCode-compatible session
/session/{id}/message POST Send prompt (OpenCode compatible)
/global/event GET/SSE Global event stream (SSE)
/api/v1/admin/ ANY Enhanced Admin API (Sessions, Stats, Doctor)
`/health[/ready /live]` GET
/metrics GET Prometheus metrics
/bridge/v1/{platform} WebSocket External platform adapter gateway (BridgeServer)

Security

  • Path Validation: Prevents directory traversal attacks
  • Timeout Enforcement: All requests have configurable timeouts
  • Input Sanitization: WorkDir paths are validated
  • BridgeServer Token Auth: Bridge connections authenticated via Authorization: Bearer <token> header (or deprecated query param ?token=). Configured via bridge_token in server YAML or HOTPLEX_BRIDGE_TOKEN env var.

Files

File Purpose
controller.go Execution orchestration
hotplex_ws.go WebSocket handler
opencode_http.go OpenCode HTTP compatibility
observability.go Metrics and health
security.go Security utilities
bridge.go BridgeServer WebSocket gateway for external platform adapters

BridgeServer and External Adapters

BridgeServer exposes /bridge/v1/{platform} as a WebSocket endpoint. External platform adapters (e.g., DingTalk, WeChat) connect as WebSocket clients and communicate via the Bridge Wire Protocol defined in internal/bridgewire/. See BridgeClient for the corresponding client-side implementation and protocol reference.

Documentation

Overview

Package server provides the BridgeServer for external platform adapters.

BridgeServer implements a WebSocket gateway that allows external platform adapters (e.g., DingTalk, WeChat) to connect to HotPlex without being compiled into the same binary. External adapters connect as WebSocket clients and communicate via the Bridge Wire Protocol.

Architecture:

External Adapter (DingTalk) ──WebSocket──> BridgeServer ──ChatAdapter──> Engine
                                          <────────────── reply ───────────────

BridgePlatform implements base.ChatAdapter, so HotPlex's engine handler is agnostic to whether the platform is built-in or external via BridgeServer.

Package server provides HTTP utilities shared across handlers.

Index

Constants

View Source
const (
	BridgeMsgTypeRegister = bridgewire.MsgTypeRegister
	BridgeMsgTypeMessage  = bridgewire.MsgTypeMessage
	BridgeMsgTypeReply    = bridgewire.MsgTypeReply
	BridgeMsgTypeEvent    = bridgewire.MsgTypeEvent
	BridgeMsgTypeError    = bridgewire.MsgTypeError
)

BridgeMsgType* aliases are kept for backward compatibility within the server package.

View Source
const (
	CapText    = bridgewire.CapText
	CapImage   = bridgewire.CapImage
	CapCard    = bridgewire.CapCard
	CapButtons = bridgewire.CapButtons
	CapTyping  = bridgewire.CapTyping
	CapEdit    = bridgewire.CapEdit
	CapDelete  = bridgewire.CapDelete
	CapReact   = bridgewire.CapReact
	CapThread  = bridgewire.CapThread
)

Cap* aliases for internal use (mirrors bridgewire constants).

View Source
const (
	EnvAllowedOrigins = "HOTPLEX_ALLOWED_ORIGINS"
	EnvAPIKey         = "HOTPLEX_API_KEY"  // Single API key (for simplicity)
	EnvAPIKeys        = "HOTPLEX_API_KEYS" // Multiple API keys (comma-separated)
)

Environment variable names

Variables

View Source
var DefaultAllowedOrigins = []string{
	"http://localhost:3000",
	"http://localhost:8080",
	"http://127.0.0.1:3000",
	"http://127.0.0.1:8080",
}

DefaultAllowedOrigins are used when no environment variable is set.

Functions

func WriteError added in v0.35.1

func WriteError(w http.ResponseWriter, status int, message string, logger *slog.Logger)

WriteError writes a JSON error response with status code and message.

func WriteJSON added in v0.35.1

func WriteJSON(w http.ResponseWriter, status int, v any, logger *slog.Logger)

WriteJSON writes a JSON response with the given status code.

Types

type BridgePlatform added in v0.34.0

type BridgePlatform struct {
	// contains filtered or unexported fields
}

BridgePlatform implements base.ChatAdapter for an external platform connected via BridgeServer WebSocket. It translates between the Bridge Wire Protocol and HotPlex's internal ChatMessage type.

func (*BridgePlatform) HandleMessage added in v0.34.0

func (bp *BridgePlatform) HandleMessage(ctx context.Context, msg *base.ChatMessage) error

HandleMessage is not used for bridge platforms (they receive via WebSocket).

func (*BridgePlatform) Platform added in v0.34.0

func (bp *BridgePlatform) Platform() string

Platform returns the platform name.

func (*BridgePlatform) SendMessage added in v0.34.0

func (bp *BridgePlatform) SendMessage(ctx context.Context, sessionID string, msg *base.ChatMessage) error

SendMessage sends a ChatMessage to the external platform via WebSocket.

func (*BridgePlatform) SetHandler added in v0.34.0

func (bp *BridgePlatform) SetHandler(h base.MessageHandler)

SetHandler sets the MessageHandler for incoming messages.

func (*BridgePlatform) Start added in v0.34.0

func (bp *BridgePlatform) Start(ctx context.Context) error

Start starts the bridge platform (no-op; connection is established externally).

func (*BridgePlatform) Stop added in v0.34.0

func (bp *BridgePlatform) Stop() error

Stop stops the bridge platform.

func (*BridgePlatform) SystemPrompt added in v0.34.0

func (bp *BridgePlatform) SystemPrompt() string

SystemPrompt returns a default system prompt for bridge platforms.

type BridgeServer added in v0.34.0

type BridgeServer struct {
	// contains filtered or unexported fields
}

BridgeServer is a WebSocket gateway for external platform adapters. It implements http.Handler and bridges the Bridge Wire Protocol to HotPlex's internal ChatMessage types.

func NewBridgeServer added in v0.34.0

func NewBridgeServer(port int, token string, logger *slog.Logger) *BridgeServer

NewBridgeServer creates a new BridgeServer.

func (*BridgeServer) Close added in v0.34.0

func (s *BridgeServer) Close()

Close gracefully shuts down all bridge connections.

func (*BridgeServer) GetPlatform added in v0.34.0

func (s *BridgeServer) GetPlatform(name string) *BridgePlatform

GetPlatform returns the BridgePlatform for a registered platform, or nil.

func (*BridgeServer) InjectAdapterManager added in v0.34.0

func (s *BridgeServer) InjectAdapterManager(adapterMgr any)

InjectAdapterManager injects the chatapps AdapterManager for registering bridge platforms so they can receive events via the standard event pipeline. Pass nil to disable event routing for bridge platforms.

func (*BridgeServer) ListPlatforms added in v0.34.0

func (s *BridgeServer) ListPlatforms() []string

ListPlatforms returns all registered platform names.

func (*BridgeServer) ListenAndServe added in v0.34.0

func (s *BridgeServer) ListenAndServe(addr string) error

ListenAndServe starts the BridgeServer HTTP listener. It blocks until the server is closed.

func (*BridgeServer) ServeHTTP added in v0.34.0

func (s *BridgeServer) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler for the /bridge/v1/ endpoint.

func (*BridgeServer) SetHandler added in v0.34.0

func (s *BridgeServer) SetHandler(h base.MessageHandler)

SetHandler sets the MessageHandler that receives all messages from bridge adapters. This is called by main.go after the chatapps EngineMessageHandler is created.

func (*BridgeServer) Shutdown added in v0.34.0

func (s *BridgeServer) Shutdown(ctx context.Context) error

Shutdown gracefully shuts down the BridgeServer.

type ClientRequest

type ClientRequest struct {
	RequestID    int    `json:"request_id,omitempty"`    // Optional request ID for request-response correlation
	Type         string `json:"type"`                    // "execute", "stop", "stats", "version"
	SessionID    string `json:"session_id"`              // Provide session_id to hot-multiplex
	Prompt       string `json:"prompt,omitempty"`        // The user input (for "execute")
	Instructions string `json:"instructions,omitempty"`  // Per-task instructions (for "execute")
	SystemPrompt string `json:"system_prompt,omitempty"` // Session-level system prompt override (for "execute")
	WorkDir      string `json:"work_dir,omitempty"`      // Working directory for CLI (for "execute")
	Reason       string `json:"reason,omitempty"`        // Reason for stopping (for "stop")
}

ClientRequest represents the JSON payload expected from the WebSocket client.

type ExecutionController added in v0.8.1

type ExecutionController struct {
	// contains filtered or unexported fields
}

func NewExecutionController added in v0.8.1

func NewExecutionController(engine hotplex.HotPlexClient, logger *slog.Logger) *ExecutionController

func (*ExecutionController) Execute added in v0.8.1

type ExecutionRequest added in v0.8.1

type ExecutionRequest struct {
	SessionID    string
	Prompt       string
	Instructions string
	SystemPrompt string // Session-level system prompt override
	WorkDir      string
	Timeout      time.Duration
}

type HealthHandler added in v0.9.0

type HealthHandler struct {
	// contains filtered or unexported fields
}

HealthHandler provides HTTP endpoints for health checking and metrics.

func NewHealthHandler added in v0.9.0

func NewHealthHandler() *HealthHandler

NewHealthHandler creates a new HealthHandler.

func (*HealthHandler) ServeHTTP added in v0.9.0

func (h *HealthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP handles /health requests.

type HealthResponse added in v0.9.0

type HealthResponse struct {
	Status    telemetry.HealthStatus `json:"status"`
	Timestamp string                 `json:"timestamp"`
	Uptime    string                 `json:"uptime"`
	Checks    map[string]bool        `json:"checks,omitempty"`
}

HealthResponse represents the health check response.

type HotPlexWSHandler added in v0.8.0

type HotPlexWSHandler struct {
	// contains filtered or unexported fields
}

HotPlexWSHandler manages a WebSocket connection to a HotPlex Engine.

func NewHotPlexWSHandler added in v0.8.0

func NewHotPlexWSHandler(engine hotplex.HotPlexClient, logger *slog.Logger, cors *SecurityConfig) *HotPlexWSHandler

NewHotPlexWSHandler creates a new handler with security configuration.

func (*HotPlexWSHandler) ServeHTTP added in v0.8.0

func (h *HotPlexWSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP upgrades the HTTP connection and starts the read loop.

type LiveHandler added in v0.9.0

type LiveHandler struct {
	// contains filtered or unexported fields
}

LiveHandler handles /health/live requests (Kubernetes liveness probe).

func NewLiveHandler added in v0.9.0

func NewLiveHandler() *LiveHandler

NewLiveHandler creates a new LiveHandler.

func (*LiveHandler) ServeHTTP added in v0.9.0

func (h *LiveHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

type MetricsHandler added in v0.9.0

type MetricsHandler struct {
	// contains filtered or unexported fields
}

MetricsHandler handles /metrics requests (Prometheus format).

func NewMetricsHandler added in v0.9.0

func NewMetricsHandler() *MetricsHandler

NewMetricsHandler creates a new MetricsHandler.

func (*MetricsHandler) ServeHTTP added in v0.9.0

func (h *MetricsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

type OpenCodeHTTPHandler added in v0.8.0

type OpenCodeHTTPHandler struct {
	// contains filtered or unexported fields
}

OpenCodeHTTPHandler implements a server compatible with OpenCode's HTTP/SSE protocol.

func NewOpenCodeHTTPHandler added in v0.8.0

func NewOpenCodeHTTPHandler(engine hotplex.HotPlexClient, logger *slog.Logger, cors *SecurityConfig) *OpenCodeHTTPHandler

NewOpenCodeHTTPHandler creates a new OpenCodeHTTPHandler instance.

func (*OpenCodeHTTPHandler) RegisterRoutes added in v0.8.0

func (s *OpenCodeHTTPHandler) RegisterRoutes(r *mux.Router)

RegisterRoutes registers the OpenCode compatibility routes to a router.

type ReadyHandler added in v0.9.0

type ReadyHandler struct {
	// contains filtered or unexported fields
}

ReadyHandler handles /health/ready requests (Kubernetes readiness probe).

func NewReadyHandler added in v0.9.0

func NewReadyHandler(engineReady func() bool) *ReadyHandler

NewReadyHandler creates a new ReadyHandler.

func (*ReadyHandler) ServeHTTP added in v0.9.0

func (h *ReadyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

type RelayHandler added in v0.35.1

type RelayHandler struct {
	// contains filtered or unexported fields
}

RelayHandler handles incoming relay messages from remote agents.

func NewRelayHandler added in v0.35.1

func NewRelayHandler(engine hotplex.HotPlexClient, logger *slog.Logger, wafDetector *security.Detector) *RelayHandler

NewRelayHandler creates a new RelayHandler.

func (*RelayHandler) RegisterRoutes added in v0.35.1

func (h *RelayHandler) RegisterRoutes(r *mux.Router)

RegisterRoutes registers the relay handler on the given router.

func (*RelayHandler) ServeHTTP added in v0.35.1

func (h *RelayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP handles POST /relay requests. Note: Method validation is handled by mux router (Methods(http.MethodPost)).

type SecurityConfig added in v0.8.0

type SecurityConfig struct {
	// contains filtered or unexported fields
}

SecurityConfig holds the allowed origins and API key for WebSocket security validation.

func NewSecurityConfig added in v0.8.0

func NewSecurityConfig(logger *slog.Logger, cfgKeys ...string) *SecurityConfig

NewSecurityConfig creates a new SecurityConfig from environment variables and optional configuration. - HOTPLEX_ALLOWED_ORIGINS: Comma-separated list of allowed origins (defaults to localhost) - HOTPLEX_API_KEY: Single API key for authentication - HOTPLEX_API_KEYS: Multiple API keys (comma-separated, takes precedence over HOTPLEX_API_KEY)

func (*SecurityConfig) AddAPIKey added in v0.8.0

func (c *SecurityConfig) AddAPIKey(key string)

AddAPIKey adds a new API key at runtime.

func (*SecurityConfig) AddOrigin added in v0.8.0

func (c *SecurityConfig) AddOrigin(origin string)

AddOrigin adds a new allowed origin at runtime.

func (*SecurityConfig) CheckOrigin added in v0.8.0

func (c *SecurityConfig) CheckOrigin() func(r *http.Request) bool

CheckOrigin returns a function suitable for websocket.Upgrader.CheckOrigin. It validates both Origin header and API key (if enabled).

func (*SecurityConfig) IsAPIKeyEnabled added in v0.8.0

func (c *SecurityConfig) IsAPIKeyEnabled() bool

IsAPIKeyEnabled returns whether API key authentication is enabled.

func (*SecurityConfig) ListOrigins added in v0.8.0

func (c *SecurityConfig) ListOrigins() []string

ListOrigins returns a copy of the current allowed origins.

func (*SecurityConfig) RemoveAPIKey added in v0.8.0

func (c *SecurityConfig) RemoveAPIKey(key string)

RemoveAPIKey removes an API key.

func (*SecurityConfig) RemoveOrigin added in v0.8.0

func (c *SecurityConfig) RemoveOrigin(origin string)

RemoveOrigin removes an origin from the allowed list.

type ServerResponse

type ServerResponse struct {
	RequestID int    `json:"request_id,omitempty"` // Echo back request_id for correlation
	Event     string `json:"event"`
	Data      any    `json:"data"`
}

ServerResponse represents the JSON payload sent to the WebSocket client.

type WireMessage added in v0.34.0

type WireMessage = bridgewire.WireMessage

WireMessage and WireMetadata are type aliases to the shared bridgewire package.

type WireMetadata added in v0.34.0

type WireMetadata = bridgewire.WireMetadata

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL