From 34a126a6d7adc0ac45794460ff86dd90a56d315a Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 21 Jan 2026 04:47:09 +0000 Subject: [PATCH] fix: allow mobile node client ids (#1354) (thanks @vignesh07) --- CHANGELOG.md | 1 + .../java/com/clawdbot/android/NodeRuntime.kt | 2 +- src/gateway/protocol/client-info.ts | 1 + src/gateway/server.ios-client-id.test.ts | 30 ++++++++++++++++--- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5058a6ce3..cf57a27e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ Docs: https://docs.clawd.bot - CLI: keep `clawdbot logs` output resilient to broken pipes while preserving progress output. - Model catalog: avoid caching import failures, log transient discovery errors, and keep partial results. (#1332) — thanks @dougvk. - Doctor: clarify plugin auto-enable hint text in the startup banner. +- Gateway: allow mobile node client ids for iOS + Android handshake validation. (#1354) — thanks @vignesh07. - Gateway: clarify unauthorized handshake responses with token/password mismatch guidance. - Gateway: clarify connect/validation errors for gateway params. (#1347) — thanks @vignesh07. - Gateway: preserve restart wake routing + thread replies across restarts. (#1337) — thanks @John-Rood. diff --git a/apps/android/app/src/main/java/com/clawdbot/android/NodeRuntime.kt b/apps/android/app/src/main/java/com/clawdbot/android/NodeRuntime.kt index 8d051a421..603e4b82b 100644 --- a/apps/android/app/src/main/java/com/clawdbot/android/NodeRuntime.kt +++ b/apps/android/app/src/main/java/com/clawdbot/android/NodeRuntime.kt @@ -529,7 +529,7 @@ class NodeRuntime(context: Context) { caps = buildCapabilities(), commands = buildInvokeCommands(), permissions = emptyMap(), - client = buildClientInfo(clientId = "node-host", clientMode = "node"), + client = buildClientInfo(clientId = "clawdbot-android", clientMode = "node"), userAgent = buildUserAgent(), ) } diff --git a/src/gateway/protocol/client-info.ts b/src/gateway/protocol/client-info.ts index 3831cd0c8..d855e463d 100644 --- a/src/gateway/protocol/client-info.ts +++ b/src/gateway/protocol/client-info.ts @@ -6,6 +6,7 @@ export const GATEWAY_CLIENT_IDS = { GATEWAY_CLIENT: "gateway-client", MACOS_APP: "clawdbot-macos", IOS_APP: "clawdbot-ios", + ANDROID_APP: "clawdbot-android", NODE_HOST: "node-host", TEST: "test", FINGERPRINT: "fingerprint", diff --git a/src/gateway/server.ios-client-id.test.ts b/src/gateway/server.ios-client-id.test.ts index 6b8d71aee..64f87abcd 100644 --- a/src/gateway/server.ios-client-id.test.ts +++ b/src/gateway/server.ios-client-id.test.ts @@ -6,7 +6,7 @@ import { getFreePort, onceMessage, startGatewayServer } from "./test-helpers.ser function connectReq( ws: WebSocket, - params: { token?: string; password?: string } = {}, + params: { clientId: string; platform: string; token?: string; password?: string }, ): Promise<{ ok: boolean; error?: { message?: string } }> { const id = `c-${Math.random().toString(16).slice(2)}`; ws.send( @@ -18,9 +18,9 @@ function connectReq( minProtocol: PROTOCOL_VERSION, maxProtocol: PROTOCOL_VERSION, client: { - id: "clawdbot-ios", + id: params.clientId, version: "dev", - platform: "ios", + platform: params.platform, mode: "node", }, auth: { @@ -48,7 +48,29 @@ test("accepts clawdbot-ios as a valid gateway client id", async () => { const ws = new WebSocket(`ws://127.0.0.1:${port}`); await new Promise((resolve) => ws.once("open", resolve)); - const res = await connectReq(ws); + const res = await connectReq(ws, { clientId: "clawdbot-ios", platform: "ios" }); + // We don't care if auth fails here; we only care that schema validation accepts the client id. + // A schema rejection would close the socket before sending a response. + if (!res.ok) { + // allow unauthorized error when gateway requires auth + // but reject schema validation errors + const message = String(res.error?.message ?? ""); + if (message.includes("invalid connect params")) { + throw new Error(message); + } + } + + ws.close(); + await server.close(); +}); + +test("accepts clawdbot-android as a valid gateway client id", async () => { + const port = await getFreePort(); + const server = await startGatewayServer(port); + const ws = new WebSocket(`ws://127.0.0.1:${port}`); + await new Promise((resolve) => ws.once("open", resolve)); + + const res = await connectReq(ws, { clientId: "clawdbot-android", platform: "android" }); // We don't care if auth fails here; we only care that schema validation accepts the client id. // A schema rejection would close the socket before sending a response. if (!res.ok) {