mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
fix: refresh node plugin tools after plugin load
This commit is contained in:
@@ -837,6 +837,34 @@ describe("gateway/node-registry", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("refreshes node-hosted plugin tools after plugin descriptors load", () => {
|
||||
const registry = createTestNodeRegistry();
|
||||
registry.register(
|
||||
makeClient("conn-1", "node-1", [], {
|
||||
commands: ["demo.echo"],
|
||||
nodePluginTools: [
|
||||
{
|
||||
pluginId: "demo",
|
||||
name: "demo_echo",
|
||||
description: "Echo through the node",
|
||||
command: "demo.echo",
|
||||
},
|
||||
],
|
||||
}),
|
||||
{},
|
||||
);
|
||||
|
||||
expect(registry.get("node-1")?.nodePluginTools).toEqual([]);
|
||||
|
||||
registerDemoNodePluginTool({ name: "demo_echo", command: "demo.echo" });
|
||||
registry.refreshNodePluginTools();
|
||||
|
||||
expect(registry.get("node-1")?.nodePluginTools.map((tool) => tool.name)).toEqual(["demo_echo"]);
|
||||
expect(listConnectedNodePluginTools().map((entry) => entry.descriptor.name)).toEqual([
|
||||
"demo_echo",
|
||||
]);
|
||||
});
|
||||
|
||||
it("ignores node plugin tool updates from stale connections", () => {
|
||||
registerDemoNodePluginTool({ name: "demo_echo", command: "demo.echo" });
|
||||
const registry = createTestNodeRegistry();
|
||||
|
||||
@@ -208,6 +208,28 @@ export class NodeRegistry {
|
||||
});
|
||||
}
|
||||
|
||||
private replaceEffectiveNodePluginTools(node: NodeSession): void {
|
||||
const nodePluginTools = this.normalizePluginToolDescriptors({
|
||||
tools: node.declaredNodePluginTools,
|
||||
allowedCommands: node.commands,
|
||||
});
|
||||
node.nodePluginTools = nodePluginTools;
|
||||
node.client.connect.nodePluginTools = nodePluginTools;
|
||||
replaceConnectedNodePluginTools({
|
||||
nodeId: node.nodeId,
|
||||
displayName: node.displayName,
|
||||
platform: node.platform,
|
||||
remoteIp: node.remoteIp,
|
||||
tools: nodePluginTools,
|
||||
});
|
||||
}
|
||||
|
||||
refreshNodePluginTools(): void {
|
||||
for (const node of this.nodesById.values()) {
|
||||
this.replaceEffectiveNodePluginTools(node);
|
||||
}
|
||||
}
|
||||
|
||||
/** Register a websocket client as the current connection for its node id. */
|
||||
register(client: GatewayWsClient, opts: { remoteIp?: string | undefined }) {
|
||||
const connect = client.connect;
|
||||
@@ -238,9 +260,9 @@ export class NodeRegistry {
|
||||
typeof (connect as { pathEnv?: string }).pathEnv === "string"
|
||||
? (connect as { pathEnv?: string }).pathEnv
|
||||
: undefined;
|
||||
const declaredNodePluginTools = this.normalizePluginToolDescriptors({
|
||||
tools: Array.isArray(connect.nodePluginTools) ? connect.nodePluginTools : [],
|
||||
});
|
||||
const declaredNodePluginTools = Array.isArray(connect.nodePluginTools)
|
||||
? [...connect.nodePluginTools]
|
||||
: [];
|
||||
const nodePluginTools = this.normalizePluginToolDescriptors({
|
||||
tools: declaredNodePluginTools,
|
||||
allowedCommands: commands,
|
||||
@@ -422,23 +444,8 @@ export class NodeRegistry {
|
||||
if (!node || node.connId !== connId) {
|
||||
return null;
|
||||
}
|
||||
const declaredNodePluginTools = this.normalizePluginToolDescriptors({
|
||||
tools,
|
||||
});
|
||||
const nodePluginTools = this.normalizePluginToolDescriptors({
|
||||
tools: declaredNodePluginTools,
|
||||
allowedCommands: node.commands,
|
||||
});
|
||||
node.declaredNodePluginTools = declaredNodePluginTools;
|
||||
node.nodePluginTools = nodePluginTools;
|
||||
node.client.connect.nodePluginTools = nodePluginTools;
|
||||
replaceConnectedNodePluginTools({
|
||||
nodeId,
|
||||
displayName: node.displayName,
|
||||
platform: node.platform,
|
||||
remoteIp: node.remoteIp,
|
||||
tools: nodePluginTools,
|
||||
});
|
||||
node.declaredNodePluginTools = [...tools];
|
||||
this.replaceEffectiveNodePluginTools(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -460,18 +467,7 @@ export class NodeRegistry {
|
||||
const nextCommands = surface.commands.filter((command) => declaredCommands.has(command));
|
||||
node.commands = nextCommands;
|
||||
(node.client.connect as { commands?: string[] }).commands = nextCommands;
|
||||
node.nodePluginTools = this.normalizePluginToolDescriptors({
|
||||
tools: node.declaredNodePluginTools,
|
||||
allowedCommands: nextCommands,
|
||||
});
|
||||
node.client.connect.nodePluginTools = node.nodePluginTools;
|
||||
replaceConnectedNodePluginTools({
|
||||
nodeId,
|
||||
displayName: node.displayName,
|
||||
platform: node.platform,
|
||||
remoteIp: node.remoteIp,
|
||||
tools: node.nodePluginTools,
|
||||
});
|
||||
this.replaceEffectiveNodePluginTools(node);
|
||||
|
||||
if ("caps" in surface) {
|
||||
const declaredCaps = new Set(node.declaredCaps);
|
||||
|
||||
@@ -1229,6 +1229,7 @@ export async function startGatewayServer(
|
||||
);
|
||||
pinActivePluginHttpRouteRegistry(pluginRegistry);
|
||||
pinActivePluginChannelRegistry(pluginRegistry);
|
||||
nodeRegistry.refreshNodePluginTools();
|
||||
};
|
||||
const refreshAttachedGatewayDiscovery = async (nextPluginRegistry: typeof pluginRegistry) => {
|
||||
if (minimalTestGateway) {
|
||||
|
||||
Reference in New Issue
Block a user