import { afterEach, beforeEach, describe, expect, it, vi } from "vitest" ;
import type { ChannelPlugin } from "../channels/plugins/types.js" ;
import type { OpenClawConfig } from "../config/config.js" ;
import { setActivePluginRegistry } from "../plugins/runtime.js" ;
import { defaultRuntime } from "../runtime.js" ;
import { createTestRegistry } from "../test-utils/channel-plugins.js" ;
import {
__testing,
listAllChannelSupportedActions,
listChannelSupportedActions,
} from "./channel-tools.js" ;
describe("channel tools" , () => {
const errorSpy = vi.spyOn(defaultRuntime, "error" ).mockImplementation(() => undefined);
beforeEach(() => {
const plugin: ChannelPlugin = {
id: "test" ,
meta: {
id: "test" ,
label: "Test" ,
selectionLabel: "Test" ,
docsPath: "/channels/test" ,
blurb: "test plugin" ,
},
capabilities: { chatTypes: ["direct" ] },
config: {
listAccountIds: () => [],
resolveAccount: () => ({}),
},
actions: {
describeMessageTool: () => {
throw new Error("boom" );
},
},
};
__testing.resetLoggedListActionErrors();
errorSpy.mockClear();
setActivePluginRegistry(createTestRegistry([{ pluginId: "test" , source: "test" , plugin }]));
});
afterEach(() => {
setActivePluginRegistry(createTestRegistry([]));
});
it("skips crashing plugins and logs once" , () => {
const cfg = {} as OpenClawConfig;
expect(listAllChannelSupportedActions({ cfg })).toEqual([]);
expect(errorSpy).toHaveBeenCalledTimes(1 );
expect(listAllChannelSupportedActions({ cfg })).toEqual([]);
expect(errorSpy).toHaveBeenCalledTimes(1 );
});
it("does not infer poll actions from outbound adapters when action discovery omits them" , () => {
const plugin: ChannelPlugin = {
id: "polltest" ,
meta: {
id: "polltest" ,
label: "Poll Test" ,
selectionLabel: "Poll Test" ,
docsPath: "/channels/polltest" ,
blurb: "poll plugin" ,
},
capabilities: { chatTypes: ["direct" ], polls: true },
config: {
listAccountIds: () => [],
resolveAccount: () => ({}),
},
actions: {
describeMessageTool: () => ({ actions: [] }),
},
outbound: {
deliveryMode: "gateway" ,
sendPoll: async () => ({ channel: "polltest" , messageId: "poll-1" }),
},
};
setActivePluginRegistry(createTestRegistry([{ pluginId: "polltest" , source: "test" , plugin }]));
const cfg = {} as OpenClawConfig;
expect(listChannelSupportedActions({ cfg, channel: "polltest" })).toEqual([]);
expect(listAllChannelSupportedActions({ cfg })).toEqual([]);
});
it("normalizes channel aliases before listing supported actions" , () => {
const plugin: ChannelPlugin = {
id: "telegram" ,
meta: {
id: "telegram" ,
label: "Telegram" ,
selectionLabel: "Telegram" ,
docsPath: "/channels/telegram" ,
blurb: "telegram plugin" ,
aliases: ["tg" ],
},
capabilities: { chatTypes: ["direct" ] },
config: {
listAccountIds: () => [],
resolveAccount: () => ({}),
},
actions: {
describeMessageTool: () => ({ actions: ["react" ] }),
},
};
setActivePluginRegistry(createTestRegistry([{ pluginId: "telegram" , source: "test" , plugin }]));
const cfg = {} as OpenClawConfig;
expect(listChannelSupportedActions({ cfg, channel: "tg" })).toEqual(["react" ]);
});
it("uses unified message tool discovery" , () => {
const plugin: ChannelPlugin = {
id: "telegram" ,
meta: {
id: "telegram" ,
label: "Telegram" ,
selectionLabel: "Telegram" ,
docsPath: "/channels/telegram" ,
blurb: "telegram plugin" ,
},
capabilities: { chatTypes: ["direct" ] },
config: {
listAccountIds: () => [],
resolveAccount: () => ({}),
},
actions: {
describeMessageTool: () => ({
actions: ["react" ],
}),
},
};
setActivePluginRegistry(createTestRegistry([{ pluginId: "telegram" , source: "test" , plugin }]));
const cfg = {} as OpenClawConfig;
expect(listChannelSupportedActions({ cfg, channel: "telegram" })).toEqual(["react" ]);
});
});
Messung V0.5 in Prozent C=99 H=97 G=97
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-05-26)
¤
*© Formatika GbR, Deutschland