Documentation
¶
Overview ¶
Package rpc implements gmcli's local control surface: newline-delimited JSON-RPC 2.0 over a unix domain socket. `gmcli serve` hosts the server; the bundled Go client (client.go), the gmtui Rust client, and any agent runtime that can speak NDJSON are consumers.
Wire format, one JSON document per line:
-> {"jsonrpc":"2.0","id":1,"method":"chats.list","params":{"limit":20}}
<- {"jsonrpc":"2.0","id":1,"result":[...]}
After a client calls "subscribe", the server pushes events as JSON-RPC notifications:
<- {"jsonrpc":"2.0","method":"event","params":{"type":"message.new","data":{...}}}
Index ¶
Constants ¶
const ( CodeParse = -32700 CodeInvalidRequest = -32600 CodeMethodNotFound = -32601 CodeInvalidParams = -32602 CodeInternal = -32603 // CodeSendsDisabled: the daemon was started read-only (the default); // nothing may touch the phone. CodeSendsDisabled = 1001 // CodeNotFound: the referenced entity does not exist. CodeNotFound = 1002 // CodeAlreadyResolved: the approval was resolved by someone else first. CodeAlreadyResolved = 1003 CodeUnavailable = 1004 )
Standard JSON-RPC codes plus gmcli application codes.
const ( EventMessageNew = "message.new" EventConversationUpdated = "conversation.updated" EventSyncStatus = "sync.status" EventApprovalRequested = "approval.requested" EventApprovalResolved = "approval.resolved" // Pairing flow (auth.pair): the QR to render, then success or error. // After pair.success the daemon restarts itself to load the new // session; clients reconnect and refetch. EventPairQR = "pair.qr" EventPairEmoji = "pair.emoji" EventPairSuccess = "pair.success" EventPairError = "pair.error" )
Event types pushed to subscribed clients.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a minimal Go client for the gmcli daemon socket. Safe for concurrent Call use; events arrive on the channel returned by Events after Subscribe.
func Dial ¶
Dial connects to the daemon socket. Returns a wrapped error mentioning `gmcli serve` when nothing is listening, since that is by far the most common failure.
func (*Client) Call ¶
Call performs one RPC round trip, decoding the result into result when non-nil. Server-side failures come back as *Error.
func (*Client) Close ¶
Close tears down the connection. Pending calls fail once the read loop notices the closed socket; the events channel closes with it.
type Deps ¶
type Deps struct {
Store *store.Store
Client *gm.Client
Pump *gmsync.Pump
Logger zerolog.Logger
Version string
SendMode SendMode
LiveTimeout time.Duration // 0 means defaultLiveTimeout
// Layout enables the in-daemon pairing flow (auth.pair). Zero value
// disables it (tests).
Layout paths.Layout
// IdleExit, when > 0, arms the Idle() signal: it fires once the server
// has had no client connections for this long (including never having
// had one). Used by auto-started daemons to retire themselves.
IdleExit time.Duration
}
Deps carries everything the server needs. Client and Pump may be nil in tests that only exercise store-backed methods; phone-touching methods then return CodeUnavailable.
type Error ¶
type Error struct {
Code int `json:"code"`
Message string `json:"message"`
Data any `json:"data,omitempty"`
}
Error is a JSON-RPC error object.
type Notification ¶
type Notification struct {
JSONRPC string `json:"jsonrpc"`
Method string `json:"method"`
Params Event `json:"params"`
}
Notification is a server-initiated push (no ID). The only method the server emits is "event".
type Request ¶
type Request struct {
JSONRPC string `json:"jsonrpc,omitempty"`
ID json.RawMessage `json:"id,omitempty"`
Method string `json:"method"`
Params json.RawMessage `json:"params,omitempty"`
}
Request is one inbound JSON-RPC call.
type Response ¶
type Response struct {
JSONRPC string `json:"jsonrpc"`
ID json.RawMessage `json:"id,omitempty"`
Result any `json:"result,omitempty"`
Error *Error `json:"error,omitempty"`
}
Response is one outbound JSON-RPC reply.
type SendMode ¶
type SendMode string
SendMode controls how the daemon treats phone-mutating requests.
const ( // SendOff blocks all sends (daemon started with --read-only, the default). SendOff SendMode = "off" // SendApprove queues send.text requests as approvals; a human resolves // them via approvals.approve (TUI, `gmcli approvals approve`). SendApprove SendMode = "approve" // SendDirect performs send.text immediately. An audit row is still // written to the approvals table with a terminal status. SendDirect SendMode = "direct" )
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server hosts the RPC surface. Construct with NewServer, run with Serve.
func (*Server) HandleGMEvent ¶
HandleGMEvent converts libgm events into subscriber pushes. Register it on gm.Client *after* the sync pump so the store row already exists when a client reacts to the event.
func (*Server) Idle ¶
func (s *Server) Idle() <-chan struct{}
Idle fires once when the server has been client-free for Deps.IdleExit. Returns nil (blocks forever in a select) when idle exit is disabled.
func (*Server) MarkAuthExpired ¶ added in v0.3.4
func (s *Server) MarkAuthExpired()
MarkAuthExpired flags the pairing as dead (also broadcast as a sync.status logged_out event by HandleGMEvent).
func (*Server) Serve ¶
Serve accepts connections until ctx is cancelled or the listener fails. It closes the listener (and removes the socket file) on return.
func (*Server) ShutdownRequested ¶ added in v0.3.4
func (s *Server) ShutdownRequested() <-chan struct{}
ShutdownRequested fires when a client asked the daemon to exit (daemon.shutdown — used by `gmcli auth` to hand over a fresh session).