Files
goclaw/websocket-protocol.md
T
yatulandClaude Opus 5 ea4890c257 fix(pairing): address review — docs, error mapping, approve feedback, unreadable expiry
- docs: device.pair.update and the `permanent` option on approve in
  docs/04-gateway-protocol.md, docs/19-websocket-rpc.md and
  websocket-protocol.md; the paired-device TTL row in docs/09-security.md
  now mentions the admin opt-out.
- store.ErrPairedDeviceNotFound: SetPairingPermanent wraps it in both stores.
  device.pair.update maps it to NOT_FOUND and any other store error to
  INTERNAL, so a DB failure no longer reads as "not found".
- web UI: approve and make-permanent/set-expiry now toast the server error
  and reload the list in `finally`. A partially applied approve (paired, but
  the permanent write failed) shows up in the table instead of leaving the
  dialog dead-ended.
- SQLite ListPaired: a stored expiry that fails to parse stays 0 (expires,
  date unknown) rather than being mistaken for permanent; the UI renders it
  as "--" instead of a 1970 date.

Tests: gateway handler error mapping (NOT_FOUND / INTERNAL / OK), sentinel
checks in the PG and SQLite store tests, SQLite unreadable-expiry case.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 19:26:43 +04:00

2.7 KiB

WebSocket Protocol (v3)

Frame types: req (client request), res (server response), event (server push).

Authentication

The first request must be a connect handshake. Authentication supports three paths:

// Path 1: Token-based (admin role)
{"type": "req", "id": 1, "method": "connect", "params": {"token": "your-gateway-token", "user_id": "alice"}}

// Path 2: Browser pairing reconnect (operator role)
{"type": "req", "id": 1, "method": "connect", "params": {"sender_id": "previously-paired-id", "user_id": "alice"}}

// Path 3: No token — initiates browser pairing flow (returns pairing code)
{"type": "req", "id": 1, "method": "connect", "params": {"user_id": "alice"}}

Methods

Method Description
connect Authentication handshake (must be first request)
health Server health check
status Server status and metadata
chat.send Send a message to an agent
chat.history Retrieve session history
chat.abort Abort a running agent request
agent Get agent info
sessions.list List active sessions
sessions.delete Delete a session
sessions.label Label a session
skills.list List available skills
cron.list List scheduled jobs
cron.create Create a cron job
cron.delete Delete a cron job
cron.toggle Enable/disable a cron job
models.list List available AI models
browser.pairing.status Poll pairing approval status
device.pair.request Request device pairing
device.pair.approve Approve a pairing code
device.pair.list List pending and approved pairings
device.pair.revoke Revoke a pairing
device.pair.update Make a pairing permanent or restore the default TTL

Events (server push)

Event Description
chunk Streaming token from LLM (payload: {content})
tool.call Agent invoking a tool (payload: {name, id})
tool.result Tool execution result
run.started Agent started processing
run.completed Agent finished processing
shutdown Server shutting down

Frame Format

Request (client to server)

{
  "type": "req",
  "id": "unique-request-id",
  "method": "chat.send",
  "params": { ... }
}

Response (server to client)

{
  "type": "res",
  "id": "matching-request-id",
  "ok": true,
  "payload": { ... }
}

Error Response

{
  "type": "res",
  "id": "matching-request-id",
  "ok": false,
  "error": {
    "code": "error_code",
    "message": "Human-readable error message"
  }
}

Event (server push)

{
  "type": "event",
  "event": "chunk",
  "payload": { "content": "streaming text..." }
}