ws

package
v0.149.4 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// Wing → Relay
	TypeWingRegister  = "wing.register"
	TypeWingHeartbeat = "wing.heartbeat"

	// PTY routing. Input/output payloads are application-encrypted; lifecycle
	// envelopes remain visible. Resize/kill use the encrypted tunnel in current
	// clients, and current wings reject their legacy plaintext relay forms.
	TypePTYStart        = "pty.start"         // browser → relay → wing
	TypePTYStarted      = "pty.started"       // wing → relay → browser
	TypePTYOutput       = "pty.output"        // wing → relay → browser
	TypePTYInput        = "pty.input"         // browser → relay → wing
	TypePTYResize       = "pty.resize"        // legacy relay form; current wings reject it
	TypePTYExited       = "pty.exited"        // wing → relay → browser
	TypePTYAttach       = "pty.attach"        // browser → relay → wing (reattach)
	TypePTYKill         = "pty.kill"          // legacy relay form; current wings reject it
	TypePTYDetach       = "pty.detach"        // browser → relay (explicit detach before disconnect)
	TypePTYAttentionAck = "pty.attention_ack" // browser → relay → wing (notification seen)
	TypePTYPreview      = "pty.preview"       // wing → relay → browser (ephemeral)
	TypePTYBrowserOpen  = "pty.browser_open"  // wing → relay → browser (URL open request)
	TypePTYMigrate      = "pty.migrate"       // browser → relay → wing (request P2P migration)
	TypePTYPing         = "pty.ping"          // browser → relay (terminal socket liveness)
	TypePTYPong         = "pty.pong"          // relay → browser
	TypePTYMigrated     = "pty.migrated"      // wing → relay → browser (P2P migration complete)
	TypePTYFallback     = "pty.fallback"      // wing → relay → browser (P2P failed, back to relay)

	// Encrypted tunnel (browser ↔ wing, relay is opaque forwarder)
	TypeTunnelRequest  = "tunnel.req"    // browser → relay → wing
	TypeTunnelResponse = "tunnel.res"    // wing → relay → browser
	TypeTunnelStream   = "tunnel.stream" // wing → relay → browser (streaming)

	// Wing → Relay (session attention broadcast)
	TypeSessionAttention = "session.attention"

	// Relay → Browser/Wing (bandwidth)
	TypeBandwidthExceeded = "bandwidth.exceeded"

	// Passkey challenge-response (wing ↔ browser, relay is passthrough)
	TypePasskeyChallenge = "passkey.challenge"
	TypePasskeyResponse  = "passkey.response"

	// Relay → Wing (passkey lifecycle event)
	TypePasskeyRegistered = "passkey.registered"

	// Wing → Relay (config change)
	TypeWingConfig = "wing.config"

	// Relay → Wing (control)
	TypeRegistered   = "registered"
	TypeRelayRestart = "relay.restart" // relay → all: server shutting down, reconnect
	TypeWingOffline  = "wing.offline"  // relay → PTY browsers: wing disconnected
	TypeError        = "error"

	TunnelPurposeSignal    = "webrtc-signal"
	TunnelPurposeDiscovery = "wing-discovery"
	TunnelPurposePasskey   = "passkey-auth"
	TunnelPurposeControl   = "wing-control"

	HostedRelayAllow = "allow"
	HostedRelayDeny  = "deny"

	MaxCoordinationTunnelPayload = 256 * 1024
)

Message types for the relay WebSocket protocol.

Variables

View Source
var ErrAuthRejected = errors.New("relay rejected authentication (401)")

ErrAuthRejected is returned when the relay rejects the WebSocket handshake with 401.

Functions

func HostedRelayAllowed added in v0.145.0

func HostedRelayAllowed(policy string) bool

HostedRelayAllowed preserves compatibility with older wings that omit the additive policy. Unknown explicit values fail closed.

func IsCoordinationTunnelPurpose added in v0.145.0

func IsCoordinationTunnelPurpose(purpose string) bool

func TunnelPurposeForInnerType added in v0.145.0

func TunnelPurposeForInnerType(innerType string) string

TunnelPurposeForInnerType declares the coordinator-visible class of an otherwise encrypted tunnel request. Direct-only accounts may use only the bounded coordination classes; the wing verifies the declaration after it decrypts the inner type.

func TunnelPurposeMatches added in v0.145.0

func TunnelPurposeMatches(purpose, innerType string) bool

func TunnelRespond added in v0.148.0

func TunnelRespond(gcm cipher.AEAD, requestID string, result any, write PTYWriteFunc)

TunnelRespond encrypts a JSON response and sends it as a tunnel.res message.

func TunnelStreamChunk added in v0.148.0

func TunnelStreamChunk(gcm cipher.AEAD, requestID string, chunk []byte, done bool, write PTYWriteFunc) error

TunnelStreamChunk encrypts a streaming chunk and sends it as a tunnel.stream message.

func ValidSessionID added in v0.145.0

func ValidSessionID(sessionID string) bool

ValidSessionID reports whether an ID is safe to use as one filesystem path component and as a bounded in-memory routing key. Relay-created IDs are compact UUID-derived values, while the broader character set preserves compatibility with older short local sessions and human-readable test/automation IDs.

func WritePTYMessage added in v0.148.0

func WritePTYMessage(write PTYWriteFunc, message any)

Types

type BandwidthExceeded added in v0.23.0

type BandwidthExceeded struct {
	Type    string `json:"type"`
	Message string `json:"message"`
}

BandwidthExceeded is sent to browser/wing when monthly cap is hit.

type Client

type Client struct {
	RoostURL string // e.g. "wss://ws.wingthing.ai/ws/wing"
	Token    string // device auth token
	WingID   string
	Hostname string // display name (os.Hostname)
	Platform string // runtime.GOOS
	Version  string // build version

	Agents     []string
	Skills     []string
	Labels     []string
	Identities []string
	Projects   []WingProject
	OrgSlug    string
	RootDir    string

	PublicKey string // X25519 identity key (base64)

	Locked       bool
	AllowedCount int
	DirectMCP    bool
	HostedRelay  string

	// RelayPubKey is the relay's EC P-256 public key (base64 DER), received during registration.
	// Used for JWT verification in direct mode.
	RelayPubKey string

	OnPTY               PTYHandler
	OnTunnel            TunnelHandler
	OnOrphanKill        func(ctx context.Context, sessionID string) // kill egg with no active goroutine
	OnReconnect         func(ctx context.Context)                   // called after re-registration with relay
	OnPasskeyRegistered func(msg PasskeyRegistered)                 // called when a user registers a passkey
	OnRegistered        func(msg RegisteredMsg)                     // additive coordinator runtime policy
	OnHostedRelayDenied func(operation string)                      // content-free local policy audit hook
	OnStateChange       func(state string, err error)               // called on connection state transitions
	OwnerForRelay       func(string) string                         // wing-administered owner binding for authenticated relay users

	// PTYRoutes is supplied by the wing, independently of relay connectivity.
	PTYRoutes *PTYRegistry
	// contains filtered or unexported fields
}

Client is an outbound WebSocket client that connects a wing to the roost.

func (*Client) HasPTYSession added in v0.16.1

func (c *Client) HasPTYSession(sessionID string) bool

HasPTYSession returns true if a goroutine is already handling this session.

func (*Client) PTYWriter added in v0.149.0

func (c *Client) PTYWriter(ctx context.Context) PTYWriteFunc

PTYWriter is the optional relay output subscriber for local routing.

func (*Client) PushPTYInput added in v0.108.0

func (c *Client) PushPTYInput(sessionID string, data []byte) bool

PushPTYInput pushes raw data into a session's input channel from outside the WebSocket read loop. Used by P2P DataChannels to route messages into the session handler. Returns true if the session exists and the message was delivered.

func (*Client) RegisterPTYSession added in v0.7.35

func (c *Client) RegisterPTYSession(ctx context.Context, sessionID string) (write PTYWriteFunc, input <-chan []byte, cleanup func(), registered bool)

RegisterPTYSession creates an input channel for a reclaimed session so allowed relay messages and trusted P2P controls can be routed to it. Plaintext relay resize/kill messages are rejected in connectAndServe before reaching this channel. Returns the input channel and a write function. The caller must start a goroutine to handle the session and clean up when done.

func (*Client) RelayPublicKey added in v0.145.0

func (c *Client) RelayPublicKey() string

RelayPublicKey returns the last coordinator signing key received at registration.

func (*Client) Run

func (c *Client) Run(ctx context.Context) error

Run connects to the relay and processes tasks until ctx is cancelled. Automatically reconnects on disconnect with exponential backoff. Returns ErrAuthRejected if the relay rejects the token with 401.

func (*Client) SendAttention added in v0.44.4

func (c *Client) SendAttention(ctx context.Context, sessionID string) error

SendAttention sends a session.attention message to the relay (bell detected).

func (*Client) SendConfig added in v0.37.0

func (c *Client) SendConfig(ctx context.Context) error

SendConfig pushes the wing's current lock state to the relay.

func (*Client) UpdateAccessConfig added in v0.145.0

func (c *Client) UpdateAccessConfig(locked bool, allowedCount int)

UpdateAccessConfig publishes lock/allowlist changes made by a tunnel request.

func (*Client) UpdateRuntimeConfig added in v0.145.0

func (c *Client) UpdateRuntimeConfig(locked bool, allowedCount int, directMCP bool, labels []string, rootDir string)

UpdateRuntimeConfig atomically publishes the hot-reloadable registration fields so reconnect and config-push goroutines never observe a torn policy.

type DirEntry added in v0.6.3

type DirEntry struct {
	Name  string `json:"name"`
	IsDir bool   `json:"is_dir"`
	Path  string `json:"path"`
}

DirEntry is a single entry in a directory listing.

type Envelope

type Envelope struct {
	Type string `json:"type"`
}

Envelope wraps every WebSocket message with a type field for routing.

type ErrorMsg

type ErrorMsg struct {
	Type         string `json:"type"`
	Message      string `json:"message"`
	RequestID    string `json:"request_id,omitempty"`
	SessionID    string `json:"session_id,omitempty"`
	ViewerID     string `json:"viewer_id,omitempty"`
	ControllerID string `json:"controller_id,omitempty"`
}

ErrorMsg is sent for protocol/session errors. Session and viewer IDs let a relay route an authorization failure back to the pending attach attempt.

type PTYAttach

type PTYAttach struct {
	ControllerID string   `json:"controller_id,omitempty"` // relay-assigned connection attempt
	Takeover     bool     `json:"takeover,omitempty"`      // deliberate writer replacement
	Type         string   `json:"type"`
	SessionID    string   `json:"session_id"`
	PublicKey    string   `json:"public_key,omitempty"` // new browser ephemeral key
	WingID       string   `json:"wing_id,omitempty"`    // target wing (for relay routing)
	AuthToken    string   `json:"auth_token,omitempty"` // cached passkey auth token
	UserID       string   `json:"user_id,omitempty"`    // relay-injected
	OrgRole      string   `json:"org_role,omitempty"`   // relay-injected: "owner", "admin", "member", ""
	Cols         uint32   `json:"cols,omitempty"`       // browser terminal cols (for resize-before-snapshot)
	Rows         uint32   `json:"rows,omitempty"`       // browser terminal rows (for resize-before-snapshot)
	Spectate     bool     `json:"spectate,omitempty"`   // read-only spectator mode
	ViewerID     string   `json:"viewer_id,omitempty"`  // relay-assigned attach attempt ID
	Email        string   `json:"email,omitempty"`      // relay-injected user email
	Passkeys     []string `json:"passkeys,omitempty"`   // relay-injected passkey attestation
}

PTYAttach requests reattachment to an existing PTY session.

type PTYAttentionAck added in v0.12.8

type PTYAttentionAck struct {
	Type      string `json:"type"`
	SessionID string `json:"session_id"`
}

PTYAttentionAck acknowledges a notification was seen by the browser.

type PTYBrowserOpen added in v0.68.0

type PTYBrowserOpen struct {
	Type      string `json:"type"` // "pty.browser_open"
	SessionID string `json:"session_id"`
	URL       string `json:"url"`
}

PTYBrowserOpen notifies the browser that an agent requested a URL open.

type PTYDetach added in v0.7.19

type PTYDetach struct {
	ControllerID string `json:"controller_id,omitempty"`
	ViewerID     string `json:"viewer_id,omitempty"`
	Type         string `json:"type"`
	SessionID    string `json:"session_id"`
}

PTYDetach explicitly detaches the browser from a PTY session.

type PTYExited

type PTYExited struct {
	Type      string `json:"type"`
	SessionID string `json:"session_id"`
	ExitCode  int    `json:"exit_code"`
	Error     string `json:"error,omitempty"`     // crash/error info for display
	ViewerID  string `json:"viewer_id,omitempty"` // spectator viewer ID (for relay routing)
}

PTYExited tells the browser the process exited.

type PTYFallback added in v0.108.0

type PTYFallback struct {
	Type      string `json:"type"`
	SessionID string `json:"session_id"`
}

PTYFallback notifies the browser that a P2P DataChannel died and I/O is back on the relay.

type PTYHandler

type PTYHandler func(ctx context.Context, start PTYStart, write PTYWriteFunc, input <-chan []byte)

PTYHandler is called when the wing receives a pty.start request. It should spawn the agent in a PTY and manage I/O. The write function sends messages back through the relay to the browser. The input channel receives raw JSON messages from the browser. Plaintext resize/kill messages from the relay are rejected; remote controls arrive through the encrypted tunnel, while trusted P2P controls use PushPTYInput.

type PTYInput

type PTYInput struct {
	Type      string `json:"type"`
	SessionID string `json:"session_id"`
	Data      string `json:"data"` // base64-encoded
}

PTYInput carries keystrokes from browser to wing.

type PTYKill

type PTYKill struct {
	Type      string `json:"type"`
	SessionID string `json:"session_id"`
}

PTYKill requests termination of a PTY session.

type PTYMigrate added in v0.108.0

type PTYMigrate struct {
	Type      string `json:"type"`
	SessionID string `json:"session_id"`
	AuthToken string `json:"auth_token,omitempty"` // passkey auth token for re-validation
}

PTYMigrate requests migration of a PTY session to a P2P DataChannel.

type PTYMigrated added in v0.108.0

type PTYMigrated struct {
	Type      string `json:"type"`
	SessionID string `json:"session_id"`
}

PTYMigrated confirms a PTY session has been migrated to a P2P DataChannel.

type PTYOutput

type PTYOutput struct {
	Type       string `json:"type"`
	SessionID  string `json:"session_id"`
	Data       string `json:"data"`                 // base64-encoded
	Compressed bool   `json:"compressed,omitempty"` // gzip before encrypt
	ViewerID   string `json:"viewer_id,omitempty"`  // spectator viewer ID (for relay routing)
}

PTYOutput carries raw terminal bytes from wing to browser.

type PTYPreview added in v0.63.0

type PTYPreview struct {
	Type      string `json:"type"`
	SessionID string `json:"session_id"`
	Data      string `json:"data"`                // base64(AES-GCM encrypted JSON)
	ViewerID  string `json:"viewer_id,omitempty"` // spectator viewer ID (for relay routing)
}

PTYPreview carries preview panel data (URL or markdown) from wing to browser.

type PTYRegistry added in v0.149.0

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

PTYRegistry belongs to the wing runtime, before any relay connects. The relay and direct adapters subscribe to this local input routing; disconnecting either transport does not remove an accepted session.

func (*PTYRegistry) HasPTYSession added in v0.149.0

func (r *PTYRegistry) HasPTYSession(id string) bool

func (*PTYRegistry) Register added in v0.149.0

func (r *PTYRegistry) Register(id string) (<-chan []byte, func(), bool)

Register installs local input routing synchronously, without relay access.

type PTYResize

type PTYResize struct {
	ControllerID string `json:"controller_id,omitempty"`
	Type         string `json:"type"`
	SessionID    string `json:"session_id"`
	Cols         int    `json:"cols"`
	Rows         int    `json:"rows"`
}

PTYResize tells the wing to resize the terminal.

type PTYStart

type PTYStart struct {
	ControllerID        string   `json:"controller_id,omitempty"` // relay-assigned connection attempt
	Type                string   `json:"type"`
	SessionID           string   `json:"session_id"`
	Agent               string   `json:"agent"` // "claude", "codex", "ollama"
	Cols                int      `json:"cols"`
	Rows                int      `json:"rows"`
	PublicKey           string   `json:"public_key,omitempty"`            // browser's ephemeral X25519 (base64)
	CWD                 string   `json:"cwd,omitempty"`                   // working directory for the agent
	WingID              string   `json:"wing_id,omitempty"`               // target wing (picks first if empty)
	PasskeyCredentialID string   `json:"passkey_credential_id,omitempty"` // base64url credential ID
	AuthToken           string   `json:"auth_token,omitempty"`            // cached passkey auth token
	UserID              string   `json:"user_id,omitempty"`               // relay-injected creator user ID
	Email               string   `json:"email,omitempty"`                 // relay-injected user email
	DisplayName         string   `json:"display_name,omitempty"`          // relay-injected display name (Google full name, GitHub login)
	OrgRole             string   `json:"org_role,omitempty"`              // relay-injected: "owner", "admin", "member", ""
	Passkeys            []string `json:"passkeys,omitempty"`              // relay-injected: base64 raw P-256 public keys
	ResumeSessionID     string   `json:"resume_session_id,omitempty"`     // prior Wingthing session to resume provider-natively
}

PTYStart requests a new interactive terminal session on the wing.

type PTYStarted

type PTYStarted struct {
	ControllerID         string `json:"controller_id,omitempty"`
	Type                 string `json:"type"`
	SessionID            string `json:"session_id"`
	Agent                string `json:"agent"`
	PublicKey            string `json:"public_key,omitempty"`              // wing's X25519 (base64)
	CWD                  string `json:"cwd,omitempty"`                     // resolved working directory
	AuthToken            string `json:"auth_token,omitempty"`              // passkey auth token
	ViewerID             string `json:"viewer_id,omitempty"`               // spectator viewer ID (relay-assigned)
	ResumedFromSessionID string `json:"resumed_from_session_id,omitempty"` // exact Wingthing source session selected
}

PTYStarted confirms the PTY session is running.

type PTYWriteFunc

type PTYWriteFunc func(v any) error

PTYWriteFunc sends a message back to the relay over the wing's WebSocket.

type PasskeyChallenge added in v0.34.0

type PasskeyChallenge struct {
	Type      string `json:"type"`
	SessionID string `json:"session_id"`
	Challenge string `json:"challenge"` // base64url random 32 bytes
	RPID      string `json:"rp_id"`     // wing-configured WebAuthn relying-party ID
	ViewerID  string `json:"viewer_id,omitempty"`
}

PasskeyChallenge is sent from wing to browser requesting passkey verification.

type PasskeyRegistered added in v0.62.0

type PasskeyRegistered struct {
	Type   string `json:"type"`
	UserID string `json:"user_id"`
	Email  string `json:"email,omitempty"`
}

PasskeyRegistered is sent from relay to wings when a user registers a new passkey. Lightweight event — actual key data flows through relay-enriched messages at auth time.

type PasskeyResponse added in v0.34.0

type PasskeyResponse struct {
	Type              string `json:"type"`
	SessionID         string `json:"session_id"`
	ViewerID          string `json:"viewer_id,omitempty"`
	CredentialID      string `json:"credential_id"`      // base64url
	AuthenticatorData string `json:"authenticator_data"` // base64
	ClientDataJSON    string `json:"client_data_json"`   // base64
	Signature         string `json:"signature"`          // base64 (ASN.1 DER)
}

PasskeyResponse is sent from browser to wing with the passkey assertion.

type RegisteredMsg

type RegisteredMsg struct {
	Type           string   `json:"type"`
	WingID         string   `json:"wing_id"`
	RelayPubKey    string   `json:"relay_pub_key,omitempty"` // base64 DER EC P-256 public key for JWT verification
	PasskeyRPID    string   `json:"passkey_rp_id,omitempty"`
	PasskeyOrigins []string `json:"passkey_origins,omitempty"`
}

RegisteredMsg is the relay's acknowledgment of a successful wing registration.

type RelayRestart added in v0.23.0

type RelayRestart struct {
	Type string `json:"type"`
}

RelayRestart is sent to all connected WebSockets when the server is shutting down.

type SessionAttention added in v0.44.4

type SessionAttention struct {
	Type      string `json:"type"`
	SessionID string `json:"session_id"`
	Agent     string `json:"agent,omitempty"`
	CWD       string `json:"cwd,omitempty"`
	Nonce     string `json:"nonce,omitempty"` // dedup key: same nonce = same attention episode
}

SessionAttention is sent by the wing when a session needs user attention (bell detected).

type SessionInfo added in v0.7.32

type SessionInfo struct {
	ConversationID        string         `json:"conversation_id,omitempty"`
	RootConversationID    string         `json:"root_conversation_id,omitempty"`
	ParentConversationID  string         `json:"parent_conversation_id,omitempty"`
	ConversationRole      string         `json:"conversation_role,omitempty"`
	Lifecycle             map[string]any `json:"lifecycle,omitempty"`
	SessionID             string         `json:"session_id"`
	Name                  string         `json:"name,omitempty"`
	Title                 string         `json:"title,omitempty"` // agent-set terminal title, display only
	Agent                 string         `json:"agent"`
	CWD                   string         `json:"cwd,omitempty"`
	EggConfig             string         `json:"-"` // server-only effective YAML config snapshot
	NeedsAttention        bool           `json:"needs_attention,omitempty"`
	Audit                 bool           `json:"audit,omitempty"` // true if session has audit recording
	Chat                  bool           `json:"chat,omitempty"`  // true if session has chat history
	UserID                string         `json:"user_id,omitempty"`
	Email                 string         `json:"email,omitempty"`
	Forkable              bool           `json:"forkable,omitempty"`
	ForkUnavailableReason string         `json:"fork_unavailable_reason,omitempty"`
}

SessionInfo describes one active session on a wing (used in tunnel sessions.list responses).

type TunnelClient added in v0.122.0

type TunnelClient struct {
	RelayURL       string           // HTTP base URL (e.g. "https://wingthing.ai")
	DeviceToken    string           // Bearer token for relay auth
	PrivKey        *ecdh.PrivateKey // native client's identity key
	KnownWingsPath string           // optional TOFU identity pin store
	HTTPClient     *http.Client     // optional roster client; defaults to a bounded client
	// contains filtered or unexported fields
}

TunnelClient sends encrypted tunnel requests to a wing via the relay.

func (*TunnelClient) DiscoverWing added in v0.122.0

func (tc *TunnelClient) DiscoverWing(ctx context.Context, wingID string) (*WingInfo, error)

DiscoverWing finds and pins a wing's public key from the relay API.

func (*TunnelClient) ListWings added in v0.144.0

func (tc *TunnelClient) ListWings(ctx context.Context) ([]WingInfo, error)

ListWings returns the online wings the authenticated relay account may use. The relay roster intentionally contains routing identity only; callers use an encrypted wing.info request when they need host or capability details.

func (*TunnelClient) Stream added in v0.122.0

func (tc *TunnelClient) Stream(ctx context.Context, wingID, wingPubKey string, inner any, onChunk func([]byte) error) error

Stream opens a WebSocket to the relay, sends an encrypted tunnel request, and collects streaming response chunks. The onChunk callback receives decrypted JSON payloads. The stream ends when a chunk with done:true is received.

func (*TunnelClient) VerifyWingIdentity added in v0.144.0

func (tc *TunnelClient) VerifyWingIdentity(wing WingInfo) error

VerifyWingIdentity applies the native client's TOFU policy to a relay roster entry. First-use pin updates are serialized so concurrent wing connections do not lose one another's entries.

type TunnelHandler added in v0.34.0

type TunnelHandler func(ctx context.Context, req TunnelRequest, write PTYWriteFunc)

TunnelHandler is called when the wing receives an encrypted tunnel request.

type TunnelRequest added in v0.34.0

type TunnelRequest struct {
	Type           string   `json:"type"`
	WingID         string   `json:"wing_id"`
	RequestID      string   `json:"request_id"`
	Purpose        string   `json:"purpose,omitempty"`
	SenderPub      string   `json:"sender_pub,omitempty"`      // browser X25519 identity pubkey
	Payload        string   `json:"payload"`                   // base64(AES-GCM encrypted)
	SenderUserID   string   `json:"sender_user_id,omitempty"`  // relay-injected user ID
	SenderOrgRole  string   `json:"sender_org_role,omitempty"` // relay-injected: "owner", "admin", "member", ""
	SenderEmail    string   `json:"sender_email,omitempty"`    // relay-injected user email
	SenderPasskeys []string `json:"sender_passkeys,omitempty"` // relay-injected: base64 raw P-256 public keys
}

TunnelRequest is an encrypted request from browser to wing via relay.

type TunnelResponse added in v0.34.0

type TunnelResponse struct {
	Type      string `json:"type"`
	RequestID string `json:"request_id"`
	Payload   string `json:"payload"` // base64(AES-GCM encrypted)
}

TunnelResponse is an encrypted response from wing to browser via relay.

type TunnelStream added in v0.34.0

type TunnelStream struct {
	Type      string `json:"type"`
	RequestID string `json:"request_id"`
	Payload   string `json:"payload"` // base64(AES-GCM encrypted)
	Done      bool   `json:"done"`
}

TunnelStream is an encrypted streaming chunk from wing to browser via relay.

type WingConfig added in v0.37.0

type WingConfig struct {
	Type         string `json:"type"`
	WingID       string `json:"wing_id"`
	Locked       bool   `json:"locked"`
	AllowedCount int    `json:"allowed_count"`
	DirectMCP    bool   `json:"direct_mcp,omitempty"`
	HostedRelay  string `json:"hosted_relay,omitempty"`
}

WingConfig is sent by the wing when lock state changes (e.g. lock/unlock, allow/revoke).

type WingHeartbeat

type WingHeartbeat struct {
	Type   string `json:"type"`
	WingID string `json:"wing_id"`
}

WingHeartbeat is sent by the wing every 30s.

type WingInfo added in v0.122.0

type WingInfo struct {
	WingID         string `json:"wing_id"`
	PublicKey      string `json:"public_key"`
	LatestVersion  string `json:"latest_version,omitempty"`
	OrgID          string `json:"org_id,omitempty"`
	UserID         string `json:"user_id,omitempty"`
	Owner          string `json:"owner,omitempty"`
	RemoteNode     string `json:"remote_node,omitempty"`
	Locked         bool   `json:"locked,omitempty"`
	AllowedCount   int    `json:"allowed_count,omitempty"`
	PurposeBinding bool   `json:"purpose_binding,omitempty"`
	DirectMCP      bool   `json:"direct_mcp,omitempty"`
	HostedRelay    string `json:"hosted_relay,omitempty"`
}

WingInfo holds the minimal info needed to connect to a wing.

type WingProject added in v0.6.0

type WingProject struct {
	Name    string `json:"name"`               // directory name (e.g. "wingthing")
	Path    string `json:"path"`               // absolute path (e.g. "/workspace/project")
	ModTime int64  `json:"mod_time,omitempty"` // unix timestamp of last modification
}

WingProject is a project directory discovered on the wing.

type WingRegister

type WingRegister struct {
	Type         string        `json:"type"`
	WingID       string        `json:"wing_id"`
	Hostname     string        `json:"hostname,omitempty"`
	Platform     string        `json:"platform,omitempty"` // runtime.GOOS (e.g. "darwin", "linux")
	Version      string        `json:"version,omitempty"`  // build version (e.g. "v0.7.35")
	Agents       []string      `json:"agents"`
	Skills       []string      `json:"skills"`
	Labels       []string      `json:"labels"`
	Identities   []string      `json:"identities"`
	Projects     []WingProject `json:"projects,omitempty"`
	OrgSlug      string        `json:"org_slug,omitempty"`
	RootDir      string        `json:"root_dir,omitempty"`
	PublicKey    string        `json:"public_key,omitempty"`    // wing's X25519 identity key (base64)
	Locked       bool          `json:"locked"`                  // explicit locked flag from wing.yaml
	AllowedCount int           `json:"allowed_count,omitempty"` // number of allowed keys
	// PurposeBinding means this wing verifies the coordinator-visible tunnel
	// purpose against the decrypted inner message before dispatch.
	PurposeBinding bool   `json:"purpose_binding,omitempty"`
	DirectMCP      bool   `json:"direct_mcp,omitempty"`
	HostedRelay    string `json:"hosted_relay,omitempty"`
}

WingRegister is sent by the wing on connect.

Jump to

Keyboard shortcuts

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