CUB-200: implement WebSocket gateway client with v3 protocol
Replace REST poller with WebSocket client as primary gateway connection: - wsclient.go: WebSocket client with v3 handshake (connect.challenge → connect → hello-ok), frame routing (req/res/event), JSON-RPC Send(), auto-reconnect with exponential backoff (1s → 30s max) - sync.go: Initial sync via agents.list + sessions.list RPCs, merge session runtime state into AgentCardData, broadcast fleet.update - events.go: Real-time event handlers for sessions.changed, presence, and agent.config — DB update first, then SSE broadcast - client.go: REST poller retained as fallback (WS is primary) - config.go: Add GATEWAY_WS_URL and OPENCLAW_GATEWAY_TOKEN env vars - main.go: Wire WS client as primary, REST as fallback - .env.example: Document new WS config vars Fallback: If WS connection fails, seeded demo data + REST polling remain available.
This commit is contained in:
@@ -63,16 +63,29 @@ func main() {
|
||||
Broker: broker,
|
||||
})
|
||||
|
||||
// ── Gateway client (polls OpenClaw for agent states) ───────────────────
|
||||
gwClient := gateway.NewClient(gateway.Config{
|
||||
// ── Gateway: WS primary + REST fallback ────────────────────────────────
|
||||
// WebSocket client (primary — real-time events via OpenClaw v3 protocol)
|
||||
wsClient := gateway.NewWSClient(gateway.WSConfig{
|
||||
URL: cfg.WSGatewayURL,
|
||||
AuthToken: cfg.WSGatewayToken,
|
||||
}, agentRepo, broker, logger)
|
||||
|
||||
// REST polling client (fallback — only used if WS connection fails)
|
||||
restClient := gateway.NewClient(gateway.Config{
|
||||
URL: cfg.GatewayURL,
|
||||
PollInterval: cfg.GatewayPollInterval,
|
||||
}, agentRepo, broker)
|
||||
|
||||
// Wire them: WS notifies REST to stand down on successful connect
|
||||
wsClient.SetRESTClient(restClient)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
go gwClient.Start(ctx)
|
||||
// Start WS client first (primary)
|
||||
go wsClient.Start(ctx)
|
||||
// Start REST client (fallback polling)
|
||||
go restClient.Start(ctx)
|
||||
|
||||
// ── Server ─────────────────────────────────────────────────────────────
|
||||
srv := &http.Server{
|
||||
@@ -98,7 +111,7 @@ func main() {
|
||||
<-quit
|
||||
slog.Info("shutting down server...")
|
||||
|
||||
cancel() // stop gateway polling
|
||||
cancel() // stop gateway clients
|
||||
|
||||
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer shutdownCancel()
|
||||
@@ -122,4 +135,4 @@ func parseLogLevel(level string) slog.Level {
|
||||
default:
|
||||
return slog.LevelInfo
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user