Files
viettranx bdb60de7ae chore: upgrade Go 1.25 → 1.26 and apply go fix modernizations
- Update go.mod and Dockerfile to Go 1.26
- Apply `go fix ./...` stdlib modernizations across 170+ files
- Add `go fix` to post-implementation checklist in CLAUDE.md
- Fix go fix misapplied rewrite in loop_history.go
2026-03-10 00:09:15 +07:00

107 lines
3.3 KiB
Go

// Package protocol defines the wire format for the GoClaw Gateway WebSocket protocol.
// This package is importable by Service 2 and other clients.
package protocol
import "encoding/json"
// Protocol version. Clients must negotiate this during connect handshake.
const ProtocolVersion = 3
// Frame types
const (
FrameTypeRequest = "req"
FrameTypeResponse = "res"
FrameTypeEvent = "event"
)
// RawFrame is used for initial parsing to determine frame type.
type RawFrame struct {
Type string `json:"type"`
Raw json.RawMessage `json:"-"` // original bytes for re-parsing
}
// RequestFrame is sent by clients to invoke an RPC method.
type RequestFrame struct {
Type string `json:"type"` // always "req"
ID string `json:"id"` // unique request ID (client-generated)
Method string `json:"method"` // RPC method name
Params json.RawMessage `json:"params,omitempty"`
}
// ResponseFrame is sent by the server in response to a request.
type ResponseFrame struct {
Type string `json:"type"` // always "res"
ID string `json:"id"` // matches request ID
OK bool `json:"ok"` // true if success
Payload any `json:"payload,omitempty"` // response data (when ok=true)
Error *ErrorShape `json:"error,omitempty"` // error info (when ok=false)
}
// ErrorShape describes a protocol error.
type ErrorShape struct {
Code string `json:"code"`
Message string `json:"message"`
Details any `json:"details,omitempty"`
Retryable bool `json:"retryable,omitempty"`
RetryAfterMs int `json:"retryAfterMs,omitempty"`
}
// EventFrame is pushed from server to client without a preceding request.
type EventFrame struct {
Type string `json:"type"` // always "event"
Event string `json:"event"` // event name
Payload any `json:"payload,omitempty"` // event data
Seq int64 `json:"seq,omitempty"` // ordering sequence number
StateVersion *StateVersion `json:"stateVersion,omitempty"` // version counters for state sync
}
// StateVersion tracks version counters for optimistic state sync.
type StateVersion struct {
Presence int64 `json:"presence"`
Health int64 `json:"health"`
}
// NewOKResponse creates a success response frame.
func NewOKResponse(id string, payload any) *ResponseFrame {
return &ResponseFrame{
Type: FrameTypeResponse,
ID: id,
OK: true,
Payload: payload,
}
}
// NewErrorResponse creates an error response frame.
func NewErrorResponse(id string, code, message string) *ResponseFrame {
return &ResponseFrame{
Type: FrameTypeResponse,
ID: id,
OK: false,
Error: &ErrorShape{
Code: code,
Message: message,
},
}
}
// NewEvent creates an event frame.
func NewEvent(event string, payload any) *EventFrame {
return &EventFrame{
Type: FrameTypeEvent,
Event: event,
Payload: payload,
}
}
// ParseFrameType extracts the frame type from raw JSON bytes.
// Returns the type string and remaining bytes for re-parsing.
func ParseFrameType(data []byte) (string, error) {
var raw struct {
Type string `json:"type"`
}
if err := json.Unmarshal(data, &raw); err != nil {
return "", err
}
return raw.Type, nil
}