From 03415bb69675339a8c362d166e3d2f44b9032b4e Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sat, 30 May 2026 05:46:38 +0200 Subject: [PATCH] refactor: share MSTeams outbound send resolvers --- extensions/msteams/src/outbound.ts | 107 ++++++++++++++--------------- 1 file changed, 51 insertions(+), 56 deletions(-) diff --git a/extensions/msteams/src/outbound.ts b/extensions/msteams/src/outbound.ts index 4032a0b8492..8099d9f688e 100644 --- a/extensions/msteams/src/outbound.ts +++ b/extensions/msteams/src/outbound.ts @@ -1,4 +1,7 @@ -import { resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-outbound"; +import { + resolveOutboundSendDep, + type OutboundSendDeps, +} from "openclaw/plugin-sdk/channel-outbound"; import { attachChannelToResult, createAttachedChannelResultAdapter, @@ -25,6 +28,48 @@ function asObjectRecord(value: unknown): Record | undefined { const MSTEAMS_TEXT_CHUNK_LIMIT = 4000; +type MSTeamsSendConfig = Parameters[0]["cfg"]; +type MSTeamsSendResult = { messageId: string; conversationId: string }; +type MSTeamsMediaSendOptions = { + mediaUrl?: string; + mediaLocalRoots?: readonly string[]; + mediaReadFile?: (filePath: string) => Promise; +}; +type MSTeamsTextSendFn = (to: string, text: string) => Promise; +type MSTeamsMediaSendFn = ( + to: string, + text: string, + opts?: MSTeamsMediaSendOptions, +) => Promise; + +function resolveMSTeamsTextSend(params: { + cfg: MSTeamsSendConfig; + deps?: OutboundSendDeps; +}): MSTeamsTextSendFn { + return ( + resolveOutboundSendDep(params.deps, "msteams") ?? + ((to, text) => sendMessageMSTeams({ cfg: params.cfg, to, text })) + ); +} + +function resolveMSTeamsMediaSend(params: { + cfg: MSTeamsSendConfig; + deps?: OutboundSendDeps; +}): MSTeamsMediaSendFn { + return ( + resolveOutboundSendDep(params.deps, "msteams") ?? + ((to, text, opts) => + sendMessageMSTeams({ + cfg: params.cfg, + to, + text, + mediaUrl: opts?.mediaUrl, + mediaLocalRoots: opts?.mediaLocalRoots, + mediaReadFile: opts?.mediaReadFile, + })) + ); +} + export const msteamsOutbound: ChannelOutboundAdapter = { deliveryMode: "direct", chunker: chunkTextForOutbound, @@ -91,26 +136,7 @@ export const msteamsOutbound: ChannelOutboundAdapter = { }), ); if (mediaUrls.length > 0) { - type SendFn = ( - to: string, - text: string, - opts?: { - mediaUrl?: string; - mediaLocalRoots?: readonly string[]; - mediaReadFile?: (filePath: string) => Promise; - }, - ) => Promise<{ messageId: string; conversationId: string }>; - const send = - resolveOutboundSendDep(deps, "msteams") ?? - ((to, text, opts) => - sendMessageMSTeams({ - cfg, - to, - text, - mediaUrl: opts?.mediaUrl, - mediaLocalRoots: opts?.mediaLocalRoots, - mediaReadFile: opts?.mediaReadFile, - })); + const send = resolveMSTeamsMediaSend({ cfg, deps }); const result = await sendPayloadMediaSequence({ text, mediaUrls, @@ -122,18 +148,12 @@ export const msteamsOutbound: ChannelOutboundAdapter = { } } if (text.trim()) { - type SendFn = ( - to: string, - text: string, - ) => Promise<{ messageId: string; conversationId: string }>; - const send = - resolveOutboundSendDep(deps, "msteams") ?? - ((to, text) => sendMessageMSTeams({ cfg, to, text })); + const send = resolveMSTeamsTextSend({ cfg, deps }); const chunks = resolveTextChunksWithFallback( text, chunkTextForOutbound(text, MSTEAMS_TEXT_CHUNK_LIMIT), ); - let result: Awaited>; + let result: Awaited>; for (const chunk of chunks) { result = await send(to, chunk); } @@ -144,36 +164,11 @@ export const msteamsOutbound: ChannelOutboundAdapter = { ...createAttachedChannelResultAdapter({ channel: "msteams", sendText: async ({ cfg, to, text, deps }) => { - type SendFn = ( - to: string, - text: string, - ) => Promise<{ messageId: string; conversationId: string }>; - const send = - resolveOutboundSendDep(deps, "msteams") ?? - ((to, text) => sendMessageMSTeams({ cfg, to, text })); + const send = resolveMSTeamsTextSend({ cfg, deps }); return await send(to, text); }, sendMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, mediaReadFile, deps }) => { - type SendFn = ( - to: string, - text: string, - opts?: { - mediaUrl?: string; - mediaLocalRoots?: readonly string[]; - mediaReadFile?: (filePath: string) => Promise; - }, - ) => Promise<{ messageId: string; conversationId: string }>; - const send = - resolveOutboundSendDep(deps, "msteams") ?? - ((to, text, opts) => - sendMessageMSTeams({ - cfg, - to, - text, - mediaUrl: opts?.mediaUrl, - mediaLocalRoots: opts?.mediaLocalRoots, - mediaReadFile: opts?.mediaReadFile, - })); + const send = resolveMSTeamsMediaSend({ cfg, deps }); return await send(to, text, { mediaUrl, mediaLocalRoots, mediaReadFile }); }, sendPoll: async ({ cfg, to, poll }) => {