sdk

package
v0.5.4 Latest Latest
Warning

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

Go to latest
Published: Mar 28, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package sdk provides reusable daemon-client infrastructure for agent CLI tools. It is game-agnostic; all game-specific behavior is injected via callbacks.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func HTTPGET

func HTTPGET(url string) (string, error)

HTTPGET performs a GET request and returns the response body as a compact JSON string if the body is valid JSON, or the raw trimmed string otherwise.

func IsTerminal

func IsTerminal(f *os.File) bool

IsTerminal returns true if f is connected to a TTY (best-effort; defaults to false).

func SaveSession

func SaveSession(path string, s SessionState) error

SaveSession writes the session state to path, creating or overwriting the file. The file is written with mode 0600 (owner read/write only).

func SocketPath

func SocketPath(sessionPath string) string

SocketPath returns the canonical Unix socket path for a given session file path. Uses the first 12 hex chars of a SHA-256 hash to keep the path short and unique.

func WSURLToHTTP

func WSURLToHTTP(wsURL string) string

WSURLToHTTP converts a WebSocket URL to its HTTP equivalent and strips the path so that only the base URL (scheme + host) is returned. Examples:

ws://localhost:8080/ws  →  http://localhost:8080
wss://api.example.com/ws  →  https://api.example.com

Types

type CommandClient

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

CommandClient sends commands to a running daemon via its Unix socket.

func NewCommandClient

func NewCommandClient(sockPath string) *CommandClient

NewCommandClient creates a CommandClient that talks to the daemon at sockPath.

func (*CommandClient) IsRunning

func (c *CommandClient) IsRunning() bool

IsRunning returns true if a daemon is listening on the socket path.

func (*CommandClient) Send

func (c *CommandClient) Send(cmd string) ([]byte, error)

Send sends cmd to the daemon and returns the response bytes. Returns an error if the daemon is not reachable or the command fails.

type CommandHandler

type CommandHandler func(cmd string, sess *SessionState) (response []byte, err error)

CommandHandler is called by IPCServer for each incoming command. cmd is the raw command string sent by the client. sess is the current session state (may be modified in place; caller saves it). Return (response, nil) to send a JSON response, or (nil, err) to send an error.

type DaemonClient

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

DaemonClient maintains a persistent WebSocket connection, appends all received messages to an events file, and provides fan-out delivery to registered subscribers.

func NewDaemonClient

func NewDaemonClient(cfg DaemonConfig) *DaemonClient

NewDaemonClient creates a DaemonClient with the given configuration. Call Run to start it.

func (*DaemonClient) ConnectionID

func (d *DaemonClient) ConnectionID() string

ConnectionID returns the server-assigned connection ID received in the welcome message.

func (*DaemonClient) IsBroadcast

func (d *DaemonClient) IsBroadcast(data []byte) bool

IsBroadcast delegates to DaemonConfig.BroadcastFilter. Returns false if no filter is configured.

func (*DaemonClient) Run

func (d *DaemonClient) Run(ctx context.Context) error

Run connects to the WebSocket, performs session resume if a token is stored, writes a PID file, opens the events file, then blocks until ctx is cancelled or the WebSocket connection is lost.

func (*DaemonClient) SendWS

func (d *DaemonClient) SendWS(data []byte) error

SendWS sends raw bytes as a WebSocket text message.

func (*DaemonClient) Session

func (d *DaemonClient) Session() *SessionState

Session returns a pointer to the current session state.

func (*DaemonClient) Subscribe

func (d *DaemonClient) Subscribe() *ResponseSubscriber

Subscribe registers a new ResponseSubscriber to receive all subsequent WebSocket messages. Unsubscribe when done to avoid leaking goroutines.

func (*DaemonClient) Unsubscribe

func (d *DaemonClient) Unsubscribe(sub *ResponseSubscriber)

Unsubscribe removes a subscriber registered with Subscribe.

func (*DaemonClient) WSConn

func (d *DaemonClient) WSConn() *websocket.Conn

WSConn returns the underlying WebSocket connection. Do NOT read from it directly — the daemon's reader goroutine is the sole reader.

type DaemonConfig

type DaemonConfig struct {
	// WSURL is the WebSocket URL to connect to (e.g. "ws://localhost:8080/ws").
	WSURL string
	// SessionPath is the path to the session JSON file.
	// The daemon also writes a PID file at SessionPath+".pid" and events at
	// SessionPath+".events".
	SessionPath string
	// OnMessage is called for every WebSocket message received, including the
	// welcome message.  It is called from the dispatcher goroutine; do not block.
	OnMessage func(data []byte)
	// BroadcastFilter returns true if data is a known server broadcast that
	// should never be treated as a direct response to a command.  Used by the
	// IPC server to skip stale messages while waiting for command responses.
	// If nil, no filtering is applied.
	BroadcastFilter func(data []byte) bool
}

DaemonConfig configures a DaemonClient.

type EventEntry

type EventEntry struct {
	Seq int             `json:"seq"`
	Ts  string          `json:"ts"`
	Msg json.RawMessage `json:"msg"`
}

EventEntry is one line in the JSONL events file.

type EventWriter

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

EventWriter appends JSONL event entries to a file in a goroutine-safe manner. Each call to Append assigns a monotonically increasing sequence number.

func NewEventWriter

func NewEventWriter(path string) (*EventWriter, error)

NewEventWriter opens (or creates) the file at path in append mode and returns an EventWriter ready to use. The caller must call Close when done.

func (*EventWriter) Append

func (w *EventWriter) Append(raw []byte) int64

Append writes raw as a JSON event entry (with seq + timestamp) and returns the assigned sequence number. Errors writing to disk are silently ignored to avoid disrupting the caller's read loop.

func (*EventWriter) Close

func (w *EventWriter) Close() error

Close flushes and closes the underlying file.

type IPCServer

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

IPCServer listens on a Unix socket and dispatches incoming commands to a CommandHandler. Each connection is handled in its own goroutine.

func NewIPCServer

func NewIPCServer(sockPath string) (*IPCServer, error)

NewIPCServer creates a Unix socket listener at sockPath, removing any stale socket file first.

func (*IPCServer) Close

func (s *IPCServer) Close() error

Close stops the server.

func (*IPCServer) Serve

func (s *IPCServer) Serve(handler CommandHandler)

Serve accepts connections and calls handler for each command. It blocks until the listener is closed. Callers typically run it in a goroutine. The socket file is removed when Serve returns.

type ResponseSubscriber

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

ResponseSubscriber receives a copy of every WebSocket message via fan-out. Register one with DaemonClient.Subscribe before sending a command to ensure no messages are missed between send and receive.

func (*ResponseSubscriber) C

func (s *ResponseSubscriber) C() <-chan []byte

C returns the channel on which messages are delivered.

type SessionState

type SessionState struct {
	GameID           string         `json:"gameId"`
	LastConnectionID string         `json:"lastConnectionId"`
	Token            string         `json:"token,omitempty"`
	Custom           map[string]any `json:"custom,omitempty"` // app-specific state
}

SessionState is persisted to disk between daemon-mode invocations so that reconnecting clients can resume their identity and active game/room.

func LoadSession

func LoadSession(path string) SessionState

LoadSession reads a session file and returns the state. Returns a zero value if the file is missing or unreadable.

Jump to

Keyboard shortcuts

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