Outbound: allow text-only plugin adapters

This commit is contained in:
liuxiaopai-ai
2026-03-03 16:40:45 +08:00
committed by Shakker
parent e6f0203ef3
commit efdf2ca0d7
3 changed files with 44 additions and 5 deletions

View File

@@ -890,6 +890,37 @@ describe("deliverOutboundPayloads", () => {
expect(results).toEqual([{ channel: "line", messageId: "ln-1" }]);
});
it("falls back to sendText when plugin outbound omits sendMedia", async () => {
const sendText = vi.fn().mockResolvedValue({ channel: "matrix", messageId: "mx-1" });
setActivePluginRegistry(
createTestRegistry([
{
pluginId: "matrix",
source: "test",
plugin: createOutboundTestPlugin({
id: "matrix",
outbound: { deliveryMode: "direct", sendText },
}),
},
]),
);
const results = await deliverOutboundPayloads({
cfg: {},
channel: "matrix",
to: "!room:1",
payloads: [{ text: "caption", mediaUrl: "https://example.com/file.png" }],
});
expect(sendText).toHaveBeenCalledTimes(1);
expect(sendText).toHaveBeenCalledWith(
expect.objectContaining({
text: "caption",
}),
);
expect(results).toEqual([{ channel: "matrix", messageId: "mx-1" }]);
});
it("emits message_sent failure when delivery errors", async () => {
hookMocks.runner.hasHooks.mockReturnValue(true);
const sendWhatsApp = vi.fn().mockRejectedValue(new Error("downstream failed"));

View File

@@ -149,7 +149,7 @@ function createPluginHandler(
params: ChannelHandlerParams & { outbound?: ChannelOutboundAdapter },
): ChannelHandler | null {
const outbound = params.outbound;
if (!outbound?.sendText || !outbound?.sendMedia) {
if (!outbound?.sendText) {
return null;
}
const baseCtx = createChannelOutboundContextBase(params);
@@ -183,12 +183,19 @@ function createPluginHandler(
...resolveCtx(overrides),
text,
}),
sendMedia: async (caption, mediaUrl, overrides) =>
sendMedia({
sendMedia: async (caption, mediaUrl, overrides) => {
if (sendMedia) {
return sendMedia({
...resolveCtx(overrides),
text: caption,
mediaUrl,
});
}
return sendText({
...resolveCtx(overrides),
text: caption,
mediaUrl,
}),
});
},
};
}