molecule-core/platform/internal/handlers/socket.go
Hongming Wang 24fec62d7f initial commit — Molecule AI platform
Forked clean from public hackathon repo (Starfire-AgentTeam, BSL 1.1)
with full rebrand to Molecule AI under github.com/Molecule-AI/molecule-monorepo.

Brand: Starfire → Molecule AI.
Slug: starfire / agent-molecule → molecule.
Env vars: STARFIRE_* → MOLECULE_*.
Go module: github.com/agent-molecule/platform → github.com/Molecule-AI/molecule-monorepo/platform.
Python packages: starfire_plugin → molecule_plugin, starfire_agent → molecule_agent.
DB: agentmolecule → molecule.

History truncated; see public repo for prior commits and contributor
attribution. Verified green: go test -race ./... (platform), pytest
(workspace-template 1129 + sdk 132), vitest (canvas 352), build (mcp).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 11:55:37 -07:00

69 lines
1.7 KiB
Go

package handlers
import (
"log"
"net/http"
"os"
"strings"
"github.com/Molecule-AI/molecule-monorepo/platform/internal/metrics"
"github.com/Molecule-AI/molecule-monorepo/platform/internal/ws"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
// In production, validate against CORS_ORIGINS. In dev, allow all.
origins := os.Getenv("CORS_ORIGINS")
if origins == "" {
return true // dev mode — no restriction
}
origin := r.Header.Get("Origin")
for _, allowed := range strings.Split(origins, ",") {
if strings.EqualFold(strings.TrimSpace(allowed), origin) {
return true
}
}
return false
},
}
type SocketHandler struct {
hub *ws.Hub
}
func NewSocketHandler(hub *ws.Hub) *SocketHandler {
return &SocketHandler{hub: hub}
}
// HandleConnect handles WebSocket upgrade at GET /ws.
// Canvas clients connect without X-Workspace-ID — they receive all events.
// Workspace agents send X-Workspace-ID — events are filtered by CanCommunicate.
func (h *SocketHandler) HandleConnect(c *gin.Context) {
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
log.Printf("WebSocket upgrade error: %v", err)
return
}
workspaceID := c.GetHeader("X-Workspace-ID")
client := &ws.Client{
Conn: conn,
WorkspaceID: workspaceID,
Send: make(chan []byte, 256),
}
h.hub.Register <- client
metrics.TrackWSConnect()
// Wrap WritePump and ReadPump so the gauge is decremented exactly once
// when the client's write goroutine exits (WritePump owns conn lifetime).
go func() {
ws.WritePump(client)
metrics.TrackWSDisconnect()
}()
go ws.ReadPump(client, h.hub)
}