diff --git a/extensions/discord/src/monitor/inbound-worker.ts b/extensions/discord/src/monitor/inbound-worker.ts index fb34e7e87d8..03be2c234ea 100644 --- a/extensions/discord/src/monitor/inbound-worker.ts +++ b/extensions/discord/src/monitor/inbound-worker.ts @@ -11,12 +11,13 @@ import { } from "./inbound-dedupe.js"; import { materializeDiscordInboundJob, type DiscordInboundJob } from "./inbound-job.js"; import type { RuntimeEnv } from "./message-handler.preflight.types.js"; -import { processDiscordMessage } from "./message-handler.process.js"; -import { deliverDiscordReply } from "./reply-delivery.js"; import type { DiscordMonitorStatusSink } from "./status.js"; import { resolveDiscordReplyDeliveryPlan } from "./threading.js"; import { normalizeDiscordInboundWorkerTimeoutMs, runDiscordTaskWithTimeout } from "./timeouts.js"; +type ProcessDiscordMessage = typeof import("./message-handler.process.js").processDiscordMessage; +type DeliverDiscordReply = typeof import("./reply-delivery.js").deliverDiscordReply; + type DiscordInboundWorkerParams = { runtime: RuntimeEnv; setStatus?: DiscordMonitorStatusSink; @@ -32,10 +33,25 @@ export type DiscordInboundWorker = { }; export type DiscordInboundWorkerTestingHooks = { - processDiscordMessage?: typeof processDiscordMessage; - deliverDiscordReply?: typeof deliverDiscordReply; + processDiscordMessage?: ProcessDiscordMessage; + deliverDiscordReply?: DeliverDiscordReply; }; +let messageProcessRuntimePromise: + | Promise + | undefined; +let replyDeliveryRuntimePromise: Promise | undefined; + +async function loadMessageProcessRuntime() { + messageProcessRuntimePromise ??= import("./message-handler.process.js"); + return await messageProcessRuntimePromise; +} + +async function loadReplyDeliveryRuntime() { + replyDeliveryRuntimePromise ??= import("./reply-delivery.js"); + return await replyDeliveryRuntimePromise; +} + function formatDiscordRunContextSuffix(job: DiscordInboundJob): string { const channelId = job.payload.messageChannelId?.trim(); const messageId = job.payload.data?.message?.id?.trim(); @@ -62,7 +78,9 @@ async function processDiscordInboundJob(params: { let finalReplyStarted = false; let createdThreadId: string | undefined; let sessionKey: string | undefined; - const processDiscordMessageImpl = params.testing?.processDiscordMessage ?? processDiscordMessage; + const processDiscordMessageImpl = + params.testing?.processDiscordMessage ?? + (await loadMessageProcessRuntime()).processDiscordMessage; try { await runDiscordTaskWithTimeout({ run: async (abortSignal) => { @@ -135,7 +153,7 @@ async function sendDiscordInboundWorkerTimeoutReply(params: { contextSuffix: string; createdThreadId?: string; sessionKey?: string; - deliverDiscordReplyImpl?: typeof deliverDiscordReply; + deliverDiscordReplyImpl?: DeliverDiscordReply; }) { const messageChannelId = params.job.payload.messageChannelId?.trim(); const messageId = params.job.payload.message?.id?.trim(); @@ -158,7 +176,9 @@ async function sendDiscordInboundWorkerTimeoutReply(params: { }); try { - await (params.deliverDiscordReplyImpl ?? deliverDiscordReply)({ + const deliverDiscordReplyImpl = + params.deliverDiscordReplyImpl ?? (await loadReplyDeliveryRuntime()).deliverDiscordReply; + await deliverDiscordReplyImpl({ cfg: params.job.payload.cfg, replies: [{ text: "Discord inbound worker timed out.", isError: true }], target: deliveryPlan.deliverTarget, diff --git a/extensions/discord/src/monitor/message-handler.ts b/extensions/discord/src/monitor/message-handler.ts index 56c6dbc7d1e..b63cf304a01 100644 --- a/extensions/discord/src/monitor/message-handler.ts +++ b/extensions/discord/src/monitor/message-handler.ts @@ -20,7 +20,6 @@ import { } from "./inbound-worker.js"; import type { DiscordMessageEvent, DiscordMessageHandler } from "./listeners.js"; import { applyImplicitReplyBatchGate } from "./message-handler.batch-gate.js"; -import { preflightDiscordMessage } from "./message-handler.preflight.js"; import type { DiscordMessagePreflightParams } from "./message-handler.preflight.types.js"; import { hasDiscordMessageStickers, @@ -29,6 +28,9 @@ import { } from "./message-utils.js"; import type { DiscordMonitorStatusSink } from "./status.js"; +type PreflightDiscordMessage = + typeof import("./message-handler.preflight.js").preflightDiscordMessage; + type DiscordMessageHandlerParams = Omit< DiscordMessagePreflightParams, "ackReactionScope" | "groupPolicy" | "data" | "client" @@ -40,9 +42,18 @@ type DiscordMessageHandlerParams = Omit< }; type DiscordMessageHandlerTestingHooks = DiscordInboundWorkerTestingHooks & { - preflightDiscordMessage?: typeof preflightDiscordMessage; + preflightDiscordMessage?: PreflightDiscordMessage; }; +let messagePreflightRuntimePromise: + | Promise + | undefined; + +async function loadMessagePreflightRuntime() { + messagePreflightRuntimePromise ??= import("./message-handler.preflight.js"); + return await messagePreflightRuntimePromise; +} + export type DiscordMessageHandlerWithLifecycle = DiscordMessageHandler & { deactivate: () => void; }; @@ -63,8 +74,7 @@ export function createDiscordMessageHandler( params.discordConfig?.ackReactionScope ?? params.cfg.messages?.ackReactionScope ?? "group-mentions"; - const preflightDiscordMessageImpl = - params.__testing?.preflightDiscordMessage ?? preflightDiscordMessage; + const preflightDiscordMessageImpl = params.__testing?.preflightDiscordMessage; const replayGuard = createDiscordInboundReplayGuard(); const inboundWorker = createDiscordInboundWorker({ runtime: params.runtime, @@ -130,7 +140,10 @@ export function createDiscordMessageHandler( } try { if (entries.length === 1) { - const ctx = await preflightDiscordMessageImpl({ + const preflight = + preflightDiscordMessageImpl ?? + (await loadMessagePreflightRuntime()).preflightDiscordMessage; + const ctx = await preflight({ ...params, ackReactionScope, groupPolicy, @@ -167,7 +180,10 @@ export function createDiscordMessageHandler( ...last.data, message: syntheticMessage, }; - const ctx = await preflightDiscordMessageImpl({ + const preflight = + preflightDiscordMessageImpl ?? + (await loadMessagePreflightRuntime()).preflightDiscordMessage; + const ctx = await preflight({ ...params, ackReactionScope, groupPolicy,