From 73e497f9be08c1d647aed20c6e4f78704361c0da Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 18 Apr 2026 20:19:37 +0100 Subject: [PATCH] refactor: cache hot channel imports --- .../discord/src/monitor/preflight-audio.ts | 11 +++++++++- extensions/discord/src/outbound-adapter.ts | 18 +++++++++++++++-- .../matrix/src/matrix/monitor/handler.ts | 17 ++++++++++++++-- .../telegram/src/bot-message-context.body.ts | 20 +++++++++++++++++-- 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/extensions/discord/src/monitor/preflight-audio.ts b/extensions/discord/src/monitor/preflight-audio.ts index 97bbbdd273d..03e883948a1 100644 --- a/extensions/discord/src/monitor/preflight-audio.ts +++ b/extensions/discord/src/monitor/preflight-audio.ts @@ -1,6 +1,15 @@ import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; import { logVerbose } from "openclaw/plugin-sdk/runtime-env"; +type DiscordPreflightAudioRuntime = typeof import("./preflight-audio.runtime.js"); + +let discordPreflightAudioRuntimePromise: Promise | undefined; + +function loadDiscordPreflightAudioRuntime(): Promise { + discordPreflightAudioRuntimePromise ??= import("./preflight-audio.runtime.js"); + return discordPreflightAudioRuntimePromise; +} + type DiscordAudioAttachment = { content_type?: string; url?: string; @@ -50,7 +59,7 @@ export async function resolveDiscordPreflightAudioMentionContext(params: { }; } try { - const { transcribeFirstAudio } = await import("./preflight-audio.runtime.js"); + const { transcribeFirstAudio } = await loadDiscordPreflightAudioRuntime(); if (params.abortSignal?.aborted) { return { hasAudioAttachment, diff --git a/extensions/discord/src/outbound-adapter.ts b/extensions/discord/src/outbound-adapter.ts index 08991f424b1..2302422f483 100644 --- a/extensions/discord/src/outbound-adapter.ts +++ b/extensions/discord/src/outbound-adapter.ts @@ -26,9 +26,13 @@ export const DISCORD_TEXT_CHUNK_LIMIT = 2000; type DiscordSendRuntime = typeof import("./send.js"); type DiscordSendFn = DiscordSendRuntime["sendMessageDiscord"]; type DiscordComponentSendFn = typeof import("./send.components.js").sendDiscordComponentMessage; +type DiscordSharedInteractiveModule = typeof import("./shared-interactive.js"); +type DiscordThreadBindingsModule = typeof import("./monitor/thread-bindings.js"); let discordSendRuntimePromise: Promise | undefined; let discordComponentSendPromise: Promise | undefined; +let discordSharedInteractivePromise: Promise | undefined; +let discordThreadBindingsPromise: Promise | undefined; async function loadDiscordSendRuntime(): Promise { discordSendRuntimePromise ??= import("./send.js"); @@ -46,6 +50,16 @@ async function sendDiscordComponentMessageLazy( )(...args); } +function loadDiscordSharedInteractive(): Promise { + discordSharedInteractivePromise ??= import("./shared-interactive.js"); + return discordSharedInteractivePromise; +} + +function loadDiscordThreadBindings(): Promise { + discordThreadBindingsPromise ??= import("./monitor/thread-bindings.js"); + return discordThreadBindingsPromise; +} + function hasApprovalChannelData(payload: { channelData?: unknown }): boolean { const channelData = payload.channelData; if (!channelData || typeof channelData !== "object" || Array.isArray(channelData)) { @@ -113,7 +127,7 @@ async function maybeSendDiscordWebhookText(params: { if (!threadId) { return null; } - const { getThreadBindingManager } = await import("./monitor/thread-bindings.js"); + const { getThreadBindingManager } = await loadDiscordThreadBindings(); const manager = getThreadBindingManager(params.accountId ?? undefined); if (!manager) { return null; @@ -158,7 +172,7 @@ export const discordOutbound: ChannelOutboundAdapter = { const rawComponentSpec = discordData?.components ?? (payload.interactive - ? (await import("./shared-interactive.js")).buildDiscordInteractiveComponents( + ? (await loadDiscordSharedInteractive()).buildDiscordInteractiveComponents( payload.interactive, ) : undefined); diff --git a/extensions/matrix/src/matrix/monitor/handler.ts b/extensions/matrix/src/matrix/monitor/handler.ts index 848e6fe0c6e..24ad2c9f79f 100644 --- a/extensions/matrix/src/matrix/monitor/handler.ts +++ b/extensions/matrix/src/matrix/monitor/handler.ts @@ -78,6 +78,8 @@ let acpBindingRuntimePromise: let sessionBindingRuntimePromise: | Promise | undefined; +let matrixReactionEventsPromise: Promise | undefined; +let matrixDraftStreamPromise: Promise | undefined; function loadMatrixSendModule(): Promise { matrixSendModulePromise ??= import("../send.js"); @@ -97,6 +99,17 @@ function loadSessionBindingRuntime(): Promise< sessionBindingRuntimePromise ??= import("openclaw/plugin-sdk/session-binding-runtime"); return sessionBindingRuntimePromise; } + +function loadMatrixReactionEvents(): Promise { + matrixReactionEventsPromise ??= import("./reaction-events.js"); + return matrixReactionEventsPromise; +} + +function loadMatrixDraftStream(): Promise { + matrixDraftStreamPromise ??= import("../draft-stream.js"); + return matrixDraftStreamPromise; +} + const MAX_TRACKED_PAIRING_REPLY_SENDERS = 512; const MAX_TRACKED_SHARED_DM_CONTEXT_NOTICES = 512; type MatrixAllowBotsMode = "off" | "mentions" | "all"; @@ -739,7 +752,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam if (isReactionEvent) { const senderName = await getSenderName(); - const { handleInboundMatrixReaction } = await import("./reaction-events.js"); + const { handleInboundMatrixReaction } = await loadMatrixReactionEvents(); await handleInboundMatrixReaction({ client, core, @@ -1366,7 +1379,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam const quietDraftStreaming = streaming === "quiet"; const draftReplyToId = replyToMode !== "off" && !threadTarget ? _messageId : undefined; const draftStream: MatrixDraftStreamHandle | undefined = draftStreamingEnabled - ? await import("../draft-stream.js").then(({ createMatrixDraftStream }) => + ? await loadMatrixDraftStream().then(({ createMatrixDraftStream }) => createMatrixDraftStream({ roomId, client, diff --git a/extensions/telegram/src/bot-message-context.body.ts b/extensions/telegram/src/bot-message-context.body.ts index 5177bf143da..b66cfa09605 100644 --- a/extensions/telegram/src/bot-message-context.body.ts +++ b/extensions/telegram/src/bot-message-context.body.ts @@ -49,6 +49,22 @@ import { buildTelegramGroupPeerId } from "./bot/helpers.js"; import type { TelegramContext } from "./bot/types.js"; import { isTelegramForumServiceMessage } from "./forum-service-message.js"; +type StickerVisionRuntime = typeof import("./sticker-vision.runtime.js"); +type MediaUnderstandingRuntime = typeof import("./media-understanding.runtime.js"); + +let stickerVisionRuntimePromise: Promise | undefined; +let mediaUnderstandingRuntimePromise: Promise | undefined; + +function loadStickerVisionRuntime(): Promise { + stickerVisionRuntimePromise ??= import("./sticker-vision.runtime.js"); + return stickerVisionRuntimePromise; +} + +function loadMediaUnderstandingRuntime(): Promise { + mediaUnderstandingRuntimePromise ??= import("./media-understanding.runtime.js"); + return mediaUnderstandingRuntimePromise; +} + export type TelegramInboundBodyResult = { bodyText: string; rawBody: string; @@ -66,7 +82,7 @@ async function resolveStickerVisionSupport(params: { agentId?: string; }): Promise { try { - const { resolveStickerVisionSupportRuntime } = await import("./sticker-vision.runtime.js"); + const { resolveStickerVisionSupportRuntime } = await loadStickerVisionRuntime(); return await resolveStickerVisionSupportRuntime(params); } catch { return false; @@ -193,7 +209,7 @@ export async function resolveTelegramInboundBody(params: { if (needsPreflightTranscription) { try { - const { transcribeFirstAudio } = await import("./media-understanding.runtime.js"); + const { transcribeFirstAudio } = await loadMediaUnderstandingRuntime(); const tempCtx: MsgContext = { MediaPaths: allMedia.length > 0 ? allMedia.map((m) => m.path) : undefined, MediaTypes: