refactor: migrate messaging plugins to sdk

This commit is contained in:
Peter Steinberger
2026-01-18 08:32:19 +00:00
parent 9241e21114
commit c5e19f5c67
63 changed files with 4082 additions and 376 deletions

View File

@@ -1,40 +1,33 @@
import type { ChannelId, ChannelOutboundAdapter } from "../types.js";
import type { ChatChannelId } from "../../registry.js";
import type { PluginRegistry } from "../../../plugins/registry.js";
import { getActivePluginRegistry } from "../../../plugins/runtime.js";
type OutboundLoader = () => Promise<ChannelOutboundAdapter>;
// Channel docking: outbound sends should stay cheap to import.
//
// The full channel plugins (src/channels/plugins/*.ts) pull in status,
// onboarding, gateway monitors, etc. Outbound delivery only needs chunking +
// send primitives, so we keep a dedicated, lightweight loader here.
const LOADERS: Record<ChatChannelId, OutboundLoader> = {
telegram: async () => (await import("./telegram.js")).telegramOutbound,
whatsapp: async () => (await import("./whatsapp.js")).whatsappOutbound,
discord: async () => (await import("./discord.js")).discordOutbound,
slack: async () => (await import("./slack.js")).slackOutbound,
signal: async () => (await import("./signal.js")).signalOutbound,
imessage: async () => (await import("./imessage.js")).imessageOutbound,
};
const cache = new Map<ChannelId, ChannelOutboundAdapter>();
let lastRegistry: PluginRegistry | null = null;
function ensureCacheForRegistry(registry: PluginRegistry | null) {
if (registry === lastRegistry) return;
cache.clear();
lastRegistry = registry;
}
export async function loadChannelOutboundAdapter(
id: ChannelId,
): Promise<ChannelOutboundAdapter | undefined> {
const registry = getActivePluginRegistry();
ensureCacheForRegistry(registry);
const cached = cache.get(id);
if (cached) return cached;
const registry = getActivePluginRegistry();
const pluginEntry = registry?.channels.find((entry) => entry.plugin.id === id);
const outbound = pluginEntry?.plugin.outbound;
if (outbound) {
cache.set(id, outbound);
return outbound;
}
const loader = LOADERS[id as ChatChannelId];
if (!loader) return undefined;
const loaded = await loader();
cache.set(id, loaded);
return loaded;
return undefined;
}

View File

@@ -1,6 +1,6 @@
import { chunkText } from "../../../auto-reply/chunk.js";
import { shouldLogVerbose } from "../../../globals.js";
import { sendMessageWhatsApp, sendPollWhatsApp } from "../../../web/outbound.js";
import { sendPollWhatsApp } from "../../../web/outbound.js";
import { isWhatsAppGroupJid, normalizeWhatsAppTarget } from "../../../whatsapp/normalize.js";
import type { ChannelOutboundAdapter } from "../types.js";
import { missingTargetError } from "../../../infra/outbound/target-errors.js";
@@ -57,7 +57,8 @@ export const whatsappOutbound: ChannelOutboundAdapter = {
};
},
sendText: async ({ to, text, accountId, deps, gifPlayback }) => {
const send = deps?.sendWhatsApp ?? sendMessageWhatsApp;
const send =
deps?.sendWhatsApp ?? (await import("../../../web/outbound.js")).sendMessageWhatsApp;
const result = await send(to, text, {
verbose: false,
accountId: accountId ?? undefined,
@@ -66,7 +67,8 @@ export const whatsappOutbound: ChannelOutboundAdapter = {
return { channel: "whatsapp", ...result };
},
sendMedia: async ({ to, text, mediaUrl, accountId, deps, gifPlayback }) => {
const send = deps?.sendWhatsApp ?? sendMessageWhatsApp;
const send =
deps?.sendWhatsApp ?? (await import("../../../web/outbound.js")).sendMessageWhatsApp;
const result = await send(to, text, {
verbose: false,
mediaUrl,