Runtime: lazy-load Telegram and Slack channel ops

This commit is contained in:
Vincent Koc
2026-03-16 02:20:09 -07:00
parent 1447e2e384
commit 898d6840dc
5 changed files with 231 additions and 57 deletions

View File

@@ -84,8 +84,28 @@ import { createRuntimeTelegram } from "./runtime-telegram.js";
import { createRuntimeWhatsApp } from "./runtime-whatsapp.js";
import type { PluginRuntime } from "./types.js";
function defineCachedValue<T extends object, K extends PropertyKey>(
target: T,
key: K,
create: () => unknown,
): void {
let cached: unknown;
let ready = false;
Object.defineProperty(target, key, {
configurable: true,
enumerable: true,
get() {
if (!ready) {
cached = create();
ready = true;
}
return cached;
},
});
}
export function createRuntimeChannel(): PluginRuntime["channel"] {
return {
const channelRuntime = {
text: {
chunkByNewline,
chunkMarkdownText,
@@ -167,12 +187,6 @@ export function createRuntimeChannel(): PluginRuntime["channel"] {
shouldComputeCommandAuthorized,
shouldHandleTextCommands,
},
discord: createRuntimeDiscord(),
slack: createRuntimeSlack(),
telegram: createRuntimeTelegram(),
signal: createRuntimeSignal(),
imessage: createRuntimeIMessage(),
whatsapp: createRuntimeWhatsApp(),
line: {
listLineAccountIds,
resolveDefaultLineAccountId,
@@ -190,5 +204,23 @@ export function createRuntimeChannel(): PluginRuntime["channel"] {
buildTemplateMessageFromPayload,
monitorLineProvider,
},
};
} satisfies Omit<
PluginRuntime["channel"],
"discord" | "slack" | "telegram" | "signal" | "imessage" | "whatsapp"
> &
Partial<
Pick<
PluginRuntime["channel"],
"discord" | "slack" | "telegram" | "signal" | "imessage" | "whatsapp"
>
>;
defineCachedValue(channelRuntime, "discord", createRuntimeDiscord);
defineCachedValue(channelRuntime, "slack", createRuntimeSlack);
defineCachedValue(channelRuntime, "telegram", createRuntimeTelegram);
defineCachedValue(channelRuntime, "signal", createRuntimeSignal);
defineCachedValue(channelRuntime, "imessage", createRuntimeIMessage);
defineCachedValue(channelRuntime, "whatsapp", createRuntimeWhatsApp);
return channelRuntime as PluginRuntime["channel"];
}

View File

@@ -0,0 +1,10 @@
export {
listSlackDirectoryGroupsLive,
listSlackDirectoryPeersLive,
} from "../../../extensions/slack/src/directory-live.js";
export { monitorSlackProvider } from "../../../extensions/slack/src/index.js";
export { probeSlack } from "../../../extensions/slack/src/probe.js";
export { resolveSlackChannelAllowlist } from "../../../extensions/slack/src/resolve-channels.js";
export { resolveSlackUserAllowlist } from "../../../extensions/slack/src/resolve-users.js";
export { sendMessageSlack } from "../../../extensions/slack/src/send.js";
export { handleSlackAction } from "../../agents/tools/slack-actions.js";

View File

@@ -1,24 +1,71 @@
import {
listSlackDirectoryGroupsLive,
listSlackDirectoryPeersLive,
} from "../../../extensions/slack/src/directory-live.js";
import { monitorSlackProvider } from "../../../extensions/slack/src/index.js";
import { probeSlack } from "../../../extensions/slack/src/probe.js";
import { resolveSlackChannelAllowlist } from "../../../extensions/slack/src/resolve-channels.js";
import { resolveSlackUserAllowlist } from "../../../extensions/slack/src/resolve-users.js";
import { sendMessageSlack } from "../../../extensions/slack/src/send.js";
import { handleSlackAction } from "../../agents/tools/slack-actions.js";
import type { PluginRuntimeChannel } from "./types-channel.js";
let runtimeSlackOpsPromise: Promise<typeof import("./runtime-slack-ops.runtime.js")> | null = null;
function loadRuntimeSlackOps() {
runtimeSlackOpsPromise ??= import("./runtime-slack-ops.runtime.js");
return runtimeSlackOpsPromise;
}
const listDirectoryGroupsLiveLazy: PluginRuntimeChannel["slack"]["listDirectoryGroupsLive"] =
async (...args) => {
const { listSlackDirectoryGroupsLive } = await loadRuntimeSlackOps();
return listSlackDirectoryGroupsLive(...args);
};
const listDirectoryPeersLiveLazy: PluginRuntimeChannel["slack"]["listDirectoryPeersLive"] = async (
...args
) => {
const { listSlackDirectoryPeersLive } = await loadRuntimeSlackOps();
return listSlackDirectoryPeersLive(...args);
};
const probeSlackLazy: PluginRuntimeChannel["slack"]["probeSlack"] = async (...args) => {
const { probeSlack } = await loadRuntimeSlackOps();
return probeSlack(...args);
};
const resolveChannelAllowlistLazy: PluginRuntimeChannel["slack"]["resolveChannelAllowlist"] =
async (...args) => {
const { resolveSlackChannelAllowlist } = await loadRuntimeSlackOps();
return resolveSlackChannelAllowlist(...args);
};
const resolveUserAllowlistLazy: PluginRuntimeChannel["slack"]["resolveUserAllowlist"] = async (
...args
) => {
const { resolveSlackUserAllowlist } = await loadRuntimeSlackOps();
return resolveSlackUserAllowlist(...args);
};
const sendMessageSlackLazy: PluginRuntimeChannel["slack"]["sendMessageSlack"] = async (...args) => {
const { sendMessageSlack } = await loadRuntimeSlackOps();
return sendMessageSlack(...args);
};
const monitorSlackProviderLazy: PluginRuntimeChannel["slack"]["monitorSlackProvider"] = async (
...args
) => {
const { monitorSlackProvider } = await loadRuntimeSlackOps();
return monitorSlackProvider(...args);
};
const handleSlackActionLazy: PluginRuntimeChannel["slack"]["handleSlackAction"] = async (
...args
) => {
const { handleSlackAction } = await loadRuntimeSlackOps();
return handleSlackAction(...args);
};
export function createRuntimeSlack(): PluginRuntimeChannel["slack"] {
return {
listDirectoryGroupsLive: listSlackDirectoryGroupsLive,
listDirectoryPeersLive: listSlackDirectoryPeersLive,
probeSlack,
resolveChannelAllowlist: resolveSlackChannelAllowlist,
resolveUserAllowlist: resolveSlackUserAllowlist,
sendMessageSlack,
monitorSlackProvider,
handleSlackAction,
listDirectoryGroupsLive: listDirectoryGroupsLiveLazy,
listDirectoryPeersLive: listDirectoryPeersLiveLazy,
probeSlack: probeSlackLazy,
resolveChannelAllowlist: resolveChannelAllowlistLazy,
resolveUserAllowlist: resolveUserAllowlistLazy,
sendMessageSlack: sendMessageSlackLazy,
monitorSlackProvider: monitorSlackProviderLazy,
handleSlackAction: handleSlackActionLazy,
};
}

View File

@@ -0,0 +1,18 @@
export {
auditTelegramGroupMembership,
collectTelegramUnmentionedGroupIds,
} from "../../../extensions/telegram/src/audit.js";
export { monitorTelegramProvider } from "../../../extensions/telegram/src/monitor.js";
export { probeTelegram } from "../../../extensions/telegram/src/probe.js";
export {
deleteMessageTelegram,
editMessageReplyMarkupTelegram,
editMessageTelegram,
pinMessageTelegram,
renameForumTopicTelegram,
sendMessageTelegram,
sendPollTelegram,
sendTypingTelegram,
unpinMessageTelegram,
} from "../../../extensions/telegram/src/send.js";
export { resolveTelegramToken } from "../../../extensions/telegram/src/token.js";

View File

@@ -1,21 +1,5 @@
import {
auditTelegramGroupMembership,
collectTelegramUnmentionedGroupIds,
} from "../../../extensions/telegram/src/audit.js";
import { collectTelegramUnmentionedGroupIds } from "../../../extensions/telegram/src/audit.js";
import { telegramMessageActions } from "../../../extensions/telegram/src/channel-actions.js";
import { monitorTelegramProvider } from "../../../extensions/telegram/src/monitor.js";
import { probeTelegram } from "../../../extensions/telegram/src/probe.js";
import {
deleteMessageTelegram,
editMessageReplyMarkupTelegram,
editMessageTelegram,
pinMessageTelegram,
renameForumTopicTelegram,
sendMessageTelegram,
sendPollTelegram,
sendTypingTelegram,
unpinMessageTelegram,
} from "../../../extensions/telegram/src/send.js";
import {
setTelegramThreadBindingIdleTimeoutBySessionKey,
setTelegramThreadBindingMaxAgeBySessionKey,
@@ -24,22 +8,105 @@ import { resolveTelegramToken } from "../../../extensions/telegram/src/token.js"
import { createTelegramTypingLease } from "./runtime-telegram-typing.js";
import type { PluginRuntimeChannel } from "./types-channel.js";
let runtimeTelegramOpsPromise: Promise<typeof import("./runtime-telegram-ops.runtime.js")> | null =
null;
function loadRuntimeTelegramOps() {
runtimeTelegramOpsPromise ??= import("./runtime-telegram-ops.runtime.js");
return runtimeTelegramOpsPromise;
}
const auditGroupMembershipLazy: PluginRuntimeChannel["telegram"]["auditGroupMembership"] = async (
...args
) => {
const { auditTelegramGroupMembership } = await loadRuntimeTelegramOps();
return auditTelegramGroupMembership(...args);
};
const probeTelegramLazy: PluginRuntimeChannel["telegram"]["probeTelegram"] = async (...args) => {
const { probeTelegram } = await loadRuntimeTelegramOps();
return probeTelegram(...args);
};
const sendMessageTelegramLazy: PluginRuntimeChannel["telegram"]["sendMessageTelegram"] = async (
...args
) => {
const { sendMessageTelegram } = await loadRuntimeTelegramOps();
return sendMessageTelegram(...args);
};
const sendPollTelegramLazy: PluginRuntimeChannel["telegram"]["sendPollTelegram"] = async (
...args
) => {
const { sendPollTelegram } = await loadRuntimeTelegramOps();
return sendPollTelegram(...args);
};
const monitorTelegramProviderLazy: PluginRuntimeChannel["telegram"]["monitorTelegramProvider"] =
async (...args) => {
const { monitorTelegramProvider } = await loadRuntimeTelegramOps();
return monitorTelegramProvider(...args);
};
const sendTypingTelegramLazy: PluginRuntimeChannel["telegram"]["typing"]["pulse"] = async (
...args
) => {
const { sendTypingTelegram } = await loadRuntimeTelegramOps();
return sendTypingTelegram(...args);
};
const editMessageTelegramLazy: PluginRuntimeChannel["telegram"]["conversationActions"]["editMessage"] =
async (...args) => {
const { editMessageTelegram } = await loadRuntimeTelegramOps();
return editMessageTelegram(...args);
};
const editMessageReplyMarkupTelegramLazy: PluginRuntimeChannel["telegram"]["conversationActions"]["editReplyMarkup"] =
async (...args) => {
const { editMessageReplyMarkupTelegram } = await loadRuntimeTelegramOps();
return editMessageReplyMarkupTelegram(...args);
};
const deleteMessageTelegramLazy: PluginRuntimeChannel["telegram"]["conversationActions"]["deleteMessage"] =
async (...args) => {
const { deleteMessageTelegram } = await loadRuntimeTelegramOps();
return deleteMessageTelegram(...args);
};
const renameForumTopicTelegramLazy: PluginRuntimeChannel["telegram"]["conversationActions"]["renameTopic"] =
async (...args) => {
const { renameForumTopicTelegram } = await loadRuntimeTelegramOps();
return renameForumTopicTelegram(...args);
};
const pinMessageTelegramLazy: PluginRuntimeChannel["telegram"]["conversationActions"]["pinMessage"] =
async (...args) => {
const { pinMessageTelegram } = await loadRuntimeTelegramOps();
return pinMessageTelegram(...args);
};
const unpinMessageTelegramLazy: PluginRuntimeChannel["telegram"]["conversationActions"]["unpinMessage"] =
async (...args) => {
const { unpinMessageTelegram } = await loadRuntimeTelegramOps();
return unpinMessageTelegram(...args);
};
export function createRuntimeTelegram(): PluginRuntimeChannel["telegram"] {
return {
auditGroupMembership: auditTelegramGroupMembership,
auditGroupMembership: auditGroupMembershipLazy,
collectUnmentionedGroupIds: collectTelegramUnmentionedGroupIds,
probeTelegram,
probeTelegram: probeTelegramLazy,
resolveTelegramToken,
sendMessageTelegram,
sendPollTelegram,
monitorTelegramProvider,
sendMessageTelegram: sendMessageTelegramLazy,
sendPollTelegram: sendPollTelegramLazy,
monitorTelegramProvider: monitorTelegramProviderLazy,
messageActions: telegramMessageActions,
threadBindings: {
setIdleTimeoutBySessionKey: setTelegramThreadBindingIdleTimeoutBySessionKey,
setMaxAgeBySessionKey: setTelegramThreadBindingMaxAgeBySessionKey,
},
typing: {
pulse: sendTypingTelegram,
pulse: sendTypingTelegramLazy,
start: async ({ to, accountId, cfg, intervalMs, messageThreadId }) =>
await createTelegramTypingLease({
to,
@@ -48,7 +115,7 @@ export function createRuntimeTelegram(): PluginRuntimeChannel["telegram"] {
intervalMs,
messageThreadId,
pulse: async ({ to, accountId, cfg, messageThreadId }) =>
await sendTypingTelegram(to, {
await sendTypingTelegramLazy(to, {
accountId,
cfg,
messageThreadId,
@@ -56,14 +123,14 @@ export function createRuntimeTelegram(): PluginRuntimeChannel["telegram"] {
}),
},
conversationActions: {
editMessage: editMessageTelegram,
editReplyMarkup: editMessageReplyMarkupTelegram,
editMessage: editMessageTelegramLazy,
editReplyMarkup: editMessageReplyMarkupTelegramLazy,
clearReplyMarkup: async (chatIdInput, messageIdInput, opts = {}) =>
await editMessageReplyMarkupTelegram(chatIdInput, messageIdInput, [], opts),
deleteMessage: deleteMessageTelegram,
renameTopic: renameForumTopicTelegram,
pinMessage: pinMessageTelegram,
unpinMessage: unpinMessageTelegram,
await editMessageReplyMarkupTelegramLazy(chatIdInput, messageIdInput, [], opts),
deleteMessage: deleteMessageTelegramLazy,
renameTopic: renameForumTopicTelegramLazy,
pinMessage: pinMessageTelegramLazy,
unpinMessage: unpinMessageTelegramLazy,
},
};
}