100 lines
3.3 KiB
Markdown
100 lines
3.3 KiB
Markdown
---
|
||
summary: "How Clawdbot presence entries are produced, merged, and displayed"
|
||
read_when:
|
||
- Debugging the Instances tab
|
||
- Investigating duplicate or stale instance rows
|
||
- Changing gateway WS connect or system-event beacons
|
||
---
|
||
# Presence
|
||
|
||
Clawdbot “presence” is a lightweight, best‑effort view of:
|
||
- the **Gateway** itself, and
|
||
- **clients connected to the Gateway** (mac app, WebChat, CLI, etc.)
|
||
|
||
Presence is used primarily to render the macOS app’s **Instances** tab and to
|
||
provide quick operator visibility.
|
||
|
||
## Presence fields (what shows up)
|
||
|
||
Presence entries are structured objects with fields like:
|
||
|
||
- `instanceId` (optional but strongly recommended): stable client identity
|
||
- `host`: human‑friendly host name
|
||
- `ip`: best‑effort IP address
|
||
- `version`: client version string
|
||
- `deviceFamily` / `modelIdentifier`: hardware hints
|
||
- `mode`: `gateway`, `app`, `webchat`, `cli`, `node`, ...
|
||
- `lastInputSeconds`: “seconds since last user input” (if known)
|
||
- `reason`: `self`, `connect`, `node-connected`, `periodic`, ...
|
||
- `ts`: last update timestamp (ms since epoch)
|
||
|
||
## Producers (where presence comes from)
|
||
|
||
Presence entries are produced by multiple sources and **merged**.
|
||
|
||
### 1) Gateway self entry
|
||
|
||
The Gateway always seeds a “self” entry at startup so UIs show the gateway host
|
||
even before any clients connect.
|
||
|
||
### 2) WebSocket connect
|
||
|
||
Every WS client begins with a `connect` request. On successful handshake the
|
||
Gateway upserts a presence entry for that connection.
|
||
|
||
#### Why one‑off CLI commands don’t show up
|
||
|
||
The CLI often connects for short, one‑off commands. To avoid spamming the
|
||
Instances list, `client.mode === "cli"` is **not** turned into a presence entry.
|
||
|
||
### 3) `system-event` beacons
|
||
|
||
Clients can send richer periodic beacons via the `system-event` method. The mac
|
||
app uses this to report host name, IP, and `lastInputSeconds`.
|
||
|
||
### 4) Node bridge beacons
|
||
|
||
When a node bridge connection authenticates, the Gateway emits a presence entry
|
||
for that node and refreshes it periodically so it doesn’t expire.
|
||
|
||
## Merge + dedupe rules (why `instanceId` matters)
|
||
|
||
Presence entries are stored in a single in‑memory map:
|
||
|
||
- Entries are keyed by a **presence key**.
|
||
- The best key is a stable `instanceId` that survives restarts.
|
||
- Keys are case‑insensitive.
|
||
|
||
If a client reconnects without a stable `instanceId`, it may show up as a
|
||
**duplicate** row.
|
||
|
||
## TTL and bounded size
|
||
|
||
Presence is intentionally ephemeral:
|
||
|
||
- **TTL:** entries older than 5 minutes are pruned
|
||
- **Max entries:** 200 (oldest dropped first)
|
||
|
||
This keeps the list fresh and avoids unbounded memory growth.
|
||
|
||
## Remote/tunnel caveat (loopback IPs)
|
||
|
||
When a client connects over an SSH tunnel / local port forward, the Gateway may
|
||
see the remote address as `127.0.0.1`. To avoid overwriting a good client‑reported
|
||
IP, loopback remote addresses are ignored.
|
||
|
||
## Consumers
|
||
|
||
### macOS Instances tab
|
||
|
||
The macOS app renders the output of `system-presence` and applies a small status
|
||
indicator (Active/Idle/Stale) based on the age of the last update.
|
||
|
||
## Debugging tips
|
||
|
||
- To see the raw list, call `system-presence` against the Gateway.
|
||
- If you see duplicates:
|
||
- confirm clients send a stable `instanceId` in the handshake
|
||
- confirm periodic beacons use the same `instanceId`
|
||
- check whether the connection‑derived entry is missing `instanceId` (duplicates are expected)
|