From df4331da04333521f98d2df53221612afcdd98a1 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 10 Dec 2025 11:48:17 +0000 Subject: [PATCH] gateway: dedupe system-event presence --- src/gateway/server.ts | 40 ++++++++++++++++++++++++++++++---- src/infra/system-presence.ts | 42 ++++++++++++++++++++++++++++++++---- 2 files changed, 74 insertions(+), 8 deletions(-) diff --git a/src/gateway/server.ts b/src/gateway/server.ts index b82e385e8..6f901c8f7 100644 --- a/src/gateway/server.ts +++ b/src/gateway/server.ts @@ -856,9 +856,8 @@ export async function startGatewayServer(port = 18789): Promise { break; } case "system-event": { - const text = String( - (req.params as { text?: unknown } | undefined)?.text ?? "", - ).trim(); + const params = (req.params ?? {}) as Record; + const text = String(params.text ?? "").trim(); if (!text) { respond( false, @@ -867,7 +866,40 @@ export async function startGatewayServer(port = 18789): Promise { ); break; } - updateSystemPresence(text); + const instanceId = + typeof params.instanceId === "string" + ? params.instanceId + : undefined; + const host = + typeof params.host === "string" ? params.host : undefined; + const ip = typeof params.ip === "string" ? params.ip : undefined; + const mode = + typeof params.mode === "string" ? params.mode : undefined; + const version = + typeof params.version === "string" ? params.version : undefined; + const lastInputSeconds = + typeof params.lastInputSeconds === "number" && + Number.isFinite(params.lastInputSeconds) + ? params.lastInputSeconds + : undefined; + const reason = + typeof params.reason === "string" ? params.reason : undefined; + const tags = + Array.isArray(params.tags) && + params.tags.every((t) => typeof t === "string") + ? (params.tags as string[]) + : undefined; + updateSystemPresence({ + text, + instanceId, + host, + ip, + mode, + version, + lastInputSeconds, + reason, + tags, + }); enqueueSystemEvent(text); presenceVersion += 1; broadcast( diff --git a/src/infra/system-presence.ts b/src/infra/system-presence.ts index a8be85aae..7dc0c2329 100644 --- a/src/infra/system-presence.ts +++ b/src/infra/system-presence.ts @@ -100,12 +100,46 @@ function parsePresence(text: string): SystemPresence { }; } -export function updateSystemPresence(text: string) { +type SystemPresencePayload = { + text: string; + instanceId?: string; + host?: string; + ip?: string; + version?: string; + lastInputSeconds?: number; + mode?: string; + reason?: string; + tags?: string[]; +}; + +export function updateSystemPresence(payload: SystemPresencePayload) { ensureSelfPresence(); - const parsed = parsePresence(text); + const parsed = parsePresence(payload.text); const key = - parsed.host?.toLowerCase() || parsed.ip || parsed.text.slice(0, 64); - entries.set(key, parsed); + payload.instanceId?.toLowerCase() || + parsed.instanceId?.toLowerCase() || + parsed.host?.toLowerCase() || + parsed.ip || + parsed.text.slice(0, 64) || + os.hostname().toLowerCase(); + const existing = entries.get(key) ?? ({} as SystemPresence); + const merged: SystemPresence = { + ...existing, + ...parsed, + host: payload.host ?? parsed.host ?? existing.host, + ip: payload.ip ?? parsed.ip ?? existing.ip, + version: payload.version ?? parsed.version ?? existing.version, + mode: payload.mode ?? parsed.mode ?? existing.mode, + lastInputSeconds: + payload.lastInputSeconds ?? + parsed.lastInputSeconds ?? + existing.lastInputSeconds, + reason: payload.reason ?? parsed.reason ?? existing.reason, + instanceId: payload.instanceId ?? parsed.instanceId ?? existing.instanceId, + text: payload.text || parsed.text || existing.text, + ts: Date.now(), + }; + entries.set(key, merged); } export function upsertPresence(key: string, presence: Partial) {