fix: require gateway client id
# Conflicts: # apps/macos/Sources/Clawdbot/GatewayChannel.swift # docs/concepts/typebox.md # docs/gateway/index.md # src/commands/onboard-non-interactive.gateway-auth.test.ts # src/commands/onboard-non-interactive.lan-auto-token.test.ts # src/gateway/call.ts # src/gateway/client.ts # src/gateway/gateway.wizard.e2e.test.ts # src/gateway/probe.ts # src/gateway/protocol/schema.ts # src/gateway/server.auth.test.ts # src/gateway/server.health.test.ts # src/gateway/server.ts # src/gateway/test-helpers.ts # src/tui/gateway-chat.ts
This commit is contained in:
@@ -18,12 +18,12 @@ provide quick operator visibility.
|
||||
|
||||
Presence entries are structured objects with fields like:
|
||||
|
||||
- `instanceId` (optional but strongly recommended): stable client identity
|
||||
- `instanceId` (optional but strongly recommended): stable client identity (usually `connect.client.instanceId`)
|
||||
- `host`: human‑friendly host name
|
||||
- `ip`: best‑effort IP address
|
||||
- `version`: client version string
|
||||
- `deviceFamily` / `modelIdentifier`: hardware hints
|
||||
- `mode`: `gateway`, `app`, `webchat`, `cli`, `node`, ...
|
||||
- `mode`: `ui`, `webchat`, `cli`, `backend`, `probe`, `test`, `node`, ...
|
||||
- `lastInputSeconds`: “seconds since last user input” (if known)
|
||||
- `reason`: `self`, `connect`, `node-connected`, `periodic`, ...
|
||||
- `ts`: last update timestamp (ms since epoch)
|
||||
@@ -62,7 +62,7 @@ for that node and refreshes it periodically so it doesn’t expire.
|
||||
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.
|
||||
- The best key is a stable `instanceId` (from `connect.client.instanceId`) that survives restarts.
|
||||
- Keys are case‑insensitive.
|
||||
|
||||
If a client reconnects without a stable `instanceId`, it may show up as a
|
||||
@@ -94,6 +94,6 @@ indicator (Active/Idle/Stale) based on the age of the last update.
|
||||
|
||||
- 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 clients send a stable `client.instanceId` in the handshake
|
||||
- confirm periodic beacons use the same `instanceId`
|
||||
- check whether the connection‑derived entry is missing `instanceId` (duplicates are expected)
|
||||
|
||||
@@ -109,7 +109,7 @@ CLAWDBOT_CONFIG_PATH=~/.clawdbot/b.json CLAWDBOT_STATE_DIR=~/.clawdbot-b clawdbo
|
||||
- After handshake:
|
||||
- Requests: `{type:"req", id, method, params}` → `{type:"res", id, ok, payload|error}`
|
||||
- Events: `{type:"event", event, payload, seq?, stateVersion?}`
|
||||
- Structured presence entries: `{host, ip, version, platform?, deviceFamily?, modelIdentifier?, mode, lastInputSeconds?, ts, reason?, tags?[], instanceId? }`.
|
||||
- Structured presence entries: `{host, ip, version, platform?, deviceFamily?, modelIdentifier?, mode, lastInputSeconds?, ts, reason?, tags?[], instanceId? }` (for WS clients, `instanceId` comes from `connect.client.instanceId`).
|
||||
- `agent` responses are two-stage: first `res` ack `{runId,status:"accepted"}`, then a final `res` `{runId,status:"ok"|"error",summary}` after the run finishes; streamed output arrives as `event:"agent"`.
|
||||
|
||||
## Methods (initial set)
|
||||
@@ -124,7 +124,7 @@ CLAWDBOT_CONFIG_PATH=~/.clawdbot/b.json CLAWDBOT_STATE_DIR=~/.clawdbot-b clawdbo
|
||||
- `node.invoke` — invoke a command on a node (e.g. `canvas.*`, `camera.*`).
|
||||
- `node.pair.*` — pairing lifecycle (`request`, `list`, `approve`, `reject`, `verify`).
|
||||
|
||||
See also: [Presence](/concepts/presence) for how presence is produced/deduped and why `instanceId` matters.
|
||||
See also: [Presence](/concepts/presence) for how presence is produced/deduped and why a stable `client.instanceId` matters.
|
||||
|
||||
## Events
|
||||
- `agent` — streamed tool/output events from the agent run (seq-tagged).
|
||||
|
||||
@@ -1588,8 +1588,10 @@ export async function startGatewayServer(
|
||||
const authMethod = authResult.method ?? "none";
|
||||
|
||||
const shouldTrackPresence = !isGatewayCliClient(connectParams.client);
|
||||
const clientId = connectParams.client.id;
|
||||
const instanceId = connectParams.client.instanceId;
|
||||
const presenceKey = shouldTrackPresence
|
||||
? connectParams.client.instanceId || connId
|
||||
? (instanceId ?? connId)
|
||||
: undefined;
|
||||
|
||||
logWs("in", "connect", {
|
||||
@@ -1598,7 +1600,7 @@ export async function startGatewayServer(
|
||||
clientDisplayName: connectParams.client.displayName,
|
||||
version: connectParams.client.version,
|
||||
mode: connectParams.client.mode,
|
||||
instanceId: connectParams.client.instanceId,
|
||||
clientId,
|
||||
platform: connectParams.client.platform,
|
||||
auth: authMethod,
|
||||
});
|
||||
@@ -1621,7 +1623,7 @@ export async function startGatewayServer(
|
||||
deviceFamily: connectParams.client.deviceFamily,
|
||||
modelIdentifier: connectParams.client.modelIdentifier,
|
||||
mode: connectParams.client.mode,
|
||||
instanceId: connectParams.client.instanceId,
|
||||
instanceId,
|
||||
reason: "connect",
|
||||
});
|
||||
presenceVersion += 1;
|
||||
|
||||
@@ -543,6 +543,8 @@ export async function connectReq(
|
||||
version: string;
|
||||
platform: string;
|
||||
mode: string;
|
||||
deviceFamily?: string;
|
||||
modelIdentifier?: string;
|
||||
instanceId?: string;
|
||||
};
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user