Spaces:
Configuration error
Configuration error
| import { resolveMainSessionKeyFromConfig } from "../../config/sessions.js"; | |
| import { getLastHeartbeatEvent } from "../../infra/heartbeat-events.js"; | |
| import { setHeartbeatsEnabled } from "../../infra/heartbeat-runner.js"; | |
| import { enqueueSystemEvent, isSystemEventContextChanged } from "../../infra/system-events.js"; | |
| import { listSystemPresence, updateSystemPresence } from "../../infra/system-presence.js"; | |
| import { ErrorCodes, errorShape } from "../protocol/index.js"; | |
| import type { GatewayRequestHandlers } from "./types.js"; | |
| export const systemHandlers: GatewayRequestHandlers = { | |
| "last-heartbeat": ({ respond }) => { | |
| respond(true, getLastHeartbeatEvent(), undefined); | |
| }, | |
| "set-heartbeats": ({ params, respond }) => { | |
| const enabled = params.enabled; | |
| if (typeof enabled !== "boolean") { | |
| respond( | |
| false, | |
| undefined, | |
| errorShape( | |
| ErrorCodes.INVALID_REQUEST, | |
| "invalid set-heartbeats params: enabled (boolean) required", | |
| ), | |
| ); | |
| return; | |
| } | |
| setHeartbeatsEnabled(enabled); | |
| respond(true, { ok: true, enabled }, undefined); | |
| }, | |
| "system-presence": ({ respond }) => { | |
| const presence = listSystemPresence(); | |
| respond(true, presence, undefined); | |
| }, | |
| "system-event": ({ params, respond, context }) => { | |
| const text = typeof params.text === "string" ? params.text.trim() : ""; | |
| if (!text) { | |
| respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, "text required")); | |
| return; | |
| } | |
| const sessionKey = resolveMainSessionKeyFromConfig(); | |
| const deviceId = typeof params.deviceId === "string" ? params.deviceId : undefined; | |
| 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 platform = typeof params.platform === "string" ? params.platform : undefined; | |
| const deviceFamily = typeof params.deviceFamily === "string" ? params.deviceFamily : undefined; | |
| const modelIdentifier = | |
| typeof params.modelIdentifier === "string" ? params.modelIdentifier : undefined; | |
| const lastInputSeconds = | |
| typeof params.lastInputSeconds === "number" && Number.isFinite(params.lastInputSeconds) | |
| ? params.lastInputSeconds | |
| : undefined; | |
| const reason = typeof params.reason === "string" ? params.reason : undefined; | |
| const roles = | |
| Array.isArray(params.roles) && params.roles.every((t) => typeof t === "string") | |
| ? (params.roles as string[]) | |
| : undefined; | |
| const scopes = | |
| Array.isArray(params.scopes) && params.scopes.every((t) => typeof t === "string") | |
| ? (params.scopes as string[]) | |
| : undefined; | |
| const tags = | |
| Array.isArray(params.tags) && params.tags.every((t) => typeof t === "string") | |
| ? (params.tags as string[]) | |
| : undefined; | |
| const presenceUpdate = updateSystemPresence({ | |
| text, | |
| deviceId, | |
| instanceId, | |
| host, | |
| ip, | |
| mode, | |
| version, | |
| platform, | |
| deviceFamily, | |
| modelIdentifier, | |
| lastInputSeconds, | |
| reason, | |
| roles, | |
| scopes, | |
| tags, | |
| }); | |
| const isNodePresenceLine = text.startsWith("Node:"); | |
| if (isNodePresenceLine) { | |
| const next = presenceUpdate.next; | |
| const changed = new Set(presenceUpdate.changedKeys); | |
| const reasonValue = next.reason ?? reason; | |
| const normalizedReason = (reasonValue ?? "").toLowerCase(); | |
| const ignoreReason = | |
| normalizedReason.startsWith("periodic") || normalizedReason === "heartbeat"; | |
| const hostChanged = changed.has("host"); | |
| const ipChanged = changed.has("ip"); | |
| const versionChanged = changed.has("version"); | |
| const modeChanged = changed.has("mode"); | |
| const reasonChanged = changed.has("reason") && !ignoreReason; | |
| const hasChanges = hostChanged || ipChanged || versionChanged || modeChanged || reasonChanged; | |
| if (hasChanges) { | |
| const contextChanged = isSystemEventContextChanged(sessionKey, presenceUpdate.key); | |
| const parts: string[] = []; | |
| if (contextChanged || hostChanged || ipChanged) { | |
| const hostLabel = next.host?.trim() || "Unknown"; | |
| const ipLabel = next.ip?.trim(); | |
| parts.push(`Node: ${hostLabel}${ipLabel ? ` (${ipLabel})` : ""}`); | |
| } | |
| if (versionChanged) { | |
| parts.push(`app ${next.version?.trim() || "unknown"}`); | |
| } | |
| if (modeChanged) { | |
| parts.push(`mode ${next.mode?.trim() || "unknown"}`); | |
| } | |
| if (reasonChanged) { | |
| parts.push(`reason ${reasonValue?.trim() || "event"}`); | |
| } | |
| const deltaText = parts.join(" · "); | |
| if (deltaText) { | |
| enqueueSystemEvent(deltaText, { | |
| sessionKey, | |
| contextKey: presenceUpdate.key, | |
| }); | |
| } | |
| } | |
| } else { | |
| enqueueSystemEvent(text, { sessionKey }); | |
| } | |
| const nextPresenceVersion = context.incrementPresenceVersion(); | |
| context.broadcast( | |
| "presence", | |
| { presence: listSystemPresence() }, | |
| { | |
| dropIfSlow: true, | |
| stateVersion: { | |
| presence: nextPresenceVersion, | |
| health: context.getHealthVersion(), | |
| }, | |
| }, | |
| ); | |
| respond(true, { ok: true }, undefined); | |
| }, | |
| }; | |