From d57405676143cb6d5b79d0ea74e01ce51a2fd014 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 22 Feb 2026 21:17:52 +0100 Subject: [PATCH] fix(control-ui): send stable websocket instance IDs (#23616) Co-authored-by: zq58855371-ui <248869919+zq58855371-ui@users.noreply.github.com> --- CHANGELOG.md | 1 + ui/src/ui/app-gateway.node.test.ts | 1 + ui/src/ui/app-gateway.ts | 2 ++ ui/src/ui/app.ts | 2 ++ 4 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1de5d838f9d..77f1561f7f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ Docs: https://docs.openclaw.ai - Webchat/Chat: apply assistant `final` payload messages directly to chat state so sent turns render without waiting for a full history refresh cycle. (#14928) Thanks @BradGroux. - Webchat/Chat: for out-of-band final events (for example tool-call side runs), append provided final assistant payloads directly instead of forcing a transient history reset. (#11139) Thanks @AkshayNavle. - Webchat/Performance: reload `chat.history` after final events only when the final payload lacks a renderable assistant message, avoiding expensive full-history refreshes on normal turns. (#20588) Thanks @amzzzzzzz. +- Control UI/WebSocket: send a stable per-tab `instanceId` in websocket connect frames so reconnect cycles keep a consistent client identity for diagnostics and presence tracking. (#23616) Thanks @zq58855371-ui. - Config/Memory: allow `"mistral"` in `agents.defaults.memorySearch.provider` and `agents.defaults.memorySearch.fallback` schema validation. (#14934) Thanks @ThomsenDrake. - Security/Feishu: enforce ID-only allowlist matching for DM/group sender authorization, normalize Feishu ID prefixes during checks, and ignore mutable display names so display-name collisions cannot satisfy allowlist entries. This ships in the next npm release. Thanks @jiseoung for reporting. - Security/Group policy: harden `channels.*.groups.*.toolsBySender` matching by requiring explicit sender-key types (`id:`, `e164:`, `username:`, `name:`), preventing cross-identifier collisions across mutable/display-name fields while keeping legacy untyped keys on a deprecated ID-only path. This ships in the next npm release. Thanks @jiseoung for reporting. diff --git a/ui/src/ui/app-gateway.node.test.ts b/ui/src/ui/app-gateway.node.test.ts index b0f91f17310..e3460495708 100644 --- a/ui/src/ui/app-gateway.node.test.ts +++ b/ui/src/ui/app-gateway.node.test.ts @@ -70,6 +70,7 @@ function createHost() { navGroupsCollapsed: {}, }, password: "", + clientInstanceId: "instance-test", client: null, connected: false, hello: null, diff --git a/ui/src/ui/app-gateway.ts b/ui/src/ui/app-gateway.ts index 4b2b0748416..f8ff9ae7a88 100644 --- a/ui/src/ui/app-gateway.ts +++ b/ui/src/ui/app-gateway.ts @@ -46,6 +46,7 @@ import type { type GatewayHost = { settings: UiSettings; password: string; + clientInstanceId: string; client: GatewayBrowserClient | null; connected: boolean; hello: GatewayHelloOk | null; @@ -147,6 +148,7 @@ export function connectGateway(host: GatewayHost) { password: host.password.trim() ? host.password : undefined, clientName: "openclaw-control-ui", mode: "webchat", + instanceId: host.clientInstanceId, onHello: (hello) => { if (host.client !== client) { return; diff --git a/ui/src/ui/app.ts b/ui/src/ui/app.ts index 24b6198481a..7d2cbd0e343 100644 --- a/ui/src/ui/app.ts +++ b/ui/src/ui/app.ts @@ -81,6 +81,7 @@ import type { NostrProfile, } from "./types.ts"; import { type ChatAttachment, type ChatQueueItem, type CronFormState } from "./ui-types.ts"; +import { generateUUID } from "./uuid.ts"; import type { NostrProfileFormState } from "./views/channels.nostr-profile-form.ts"; declare global { @@ -107,6 +108,7 @@ function resolveOnboardingMode(): boolean { @customElement("openclaw-app") export class OpenClawApp extends LitElement { private i18nController = new I18nController(this); + clientInstanceId = generateUUID(); @state() settings: UiSettings = loadSettings(); constructor() { super();