Skills: clean up remote node cache on disconnect

This commit is contained in:
Vignesh Natarajan
2026-02-14 18:02:14 -08:00
parent 6f6954fb34
commit dabfcbe941
3 changed files with 42 additions and 0 deletions

View File

@@ -6,6 +6,7 @@ import type { ResolvedGatewayAuth } from "../auth.js";
import type { GatewayRequestContext, GatewayRequestHandlers } from "../server-methods/types.js";
import type { GatewayWsClient } from "./ws-types.js";
import { resolveCanvasHostUrl } from "../../infra/canvas-host-url.js";
import { removeRemoteNodeInfo } from "../../infra/skills-remote.js";
import { listSystemPresence, upsertPresence } from "../../infra/system-presence.js";
import { truncateUtf16Safe } from "../../utils.js";
import { isWebchatClient } from "../../utils/message-channel.js";
@@ -243,6 +244,7 @@ export function attachGatewayWsConnectionHandler(params: {
const context = buildRequestContext();
const nodeId = context.nodeRegistry.unregister(connId);
if (nodeId) {
removeRemoteNodeInfo(nodeId);
context.nodeUnsubscribeAll(nodeId);
}
}

View File

@@ -0,0 +1,36 @@
import { randomUUID } from "node:crypto";
import { describe, expect, it } from "vitest";
import {
getRemoteSkillEligibility,
recordRemoteNodeBins,
recordRemoteNodeInfo,
removeRemoteNodeInfo,
} from "./skills-remote.js";
describe("skills-remote", () => {
it("removes disconnected nodes from remote skill eligibility", () => {
const nodeId = `node-${randomUUID()}`;
const bin = `bin-${randomUUID()}`;
recordRemoteNodeInfo({
nodeId,
displayName: "Remote Mac",
platform: "darwin",
commands: ["system.run"],
});
recordRemoteNodeBins(nodeId, [bin]);
expect(getRemoteSkillEligibility()?.hasBin(bin)).toBe(true);
removeRemoteNodeInfo(nodeId);
expect(getRemoteSkillEligibility()?.hasBin(bin) ?? false).toBe(false);
});
it("supports idempotent remote node removal", () => {
const nodeId = `node-${randomUUID()}`;
expect(() => {
removeRemoteNodeInfo(nodeId);
removeRemoteNodeInfo(nodeId);
}).not.toThrow();
});
});

View File

@@ -168,6 +168,10 @@ export function recordRemoteNodeBins(nodeId: string, bins: string[]) {
upsertNode({ nodeId, bins });
}
export function removeRemoteNodeInfo(nodeId: string) {
remoteNodes.delete(nodeId);
}
function listWorkspaceDirs(cfg: OpenClawConfig): string[] {
const dirs = new Set<string>();
const list = cfg.agents?.list;