From 4ec51f2d5f2c6d38ff44bcf938f2a8923ff58b95 Mon Sep 17 00:00:00 2001 From: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> Date: Fri, 27 Mar 2026 21:46:42 -0500 Subject: [PATCH] fix(regression): align msteams send helper runtime usage --- extensions/msteams/src/send.test.ts | 52 +++++++++++++++++++++++++++-- extensions/msteams/src/send.ts | 6 ++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/extensions/msteams/src/send.test.ts b/extensions/msteams/src/send.test.ts index 78805e15ae4..7c4a9d544e6 100644 --- a/extensions/msteams/src/send.test.ts +++ b/extensions/msteams/src/send.test.ts @@ -5,6 +5,10 @@ import { deleteMessageMSTeams, editMessageMSTeams, sendMessageMSTeams } from "./ const mockState = vi.hoisted(() => ({ loadOutboundMediaFromUrl: vi.fn(), resolveMSTeamsSendContext: vi.fn(), + resolveMarkdownTableMode: vi.fn(() => "off"), + convertMarkdownTables: vi.fn((text: string) => text), + runtimeResolveMarkdownTableMode: vi.fn(() => "off"), + runtimeConvertMarkdownTables: vi.fn((text: string) => text), requiresFileConsent: vi.fn(), prepareFileConsentActivity: vi.fn(), extractFilename: vi.fn(async () => "fallback.bin"), @@ -18,6 +22,14 @@ vi.mock("../runtime-api.js", () => ({ loadOutboundMediaFromUrl: mockState.loadOutboundMediaFromUrl, })); +vi.mock("openclaw/plugin-sdk/config-runtime", () => ({ + resolveMarkdownTableMode: mockState.resolveMarkdownTableMode, +})); + +vi.mock("openclaw/plugin-sdk/text-runtime", () => ({ + convertMarkdownTables: mockState.convertMarkdownTables, +})); + vi.mock("./send-context.js", () => ({ resolveMSTeamsSendContext: mockState.resolveMSTeamsSendContext, })); @@ -41,8 +53,8 @@ vi.mock("./runtime.js", () => ({ getMSTeamsRuntime: () => ({ channel: { text: { - resolveMarkdownTableMode: () => "off", - convertMarkdownTables: (text: string) => text, + resolveMarkdownTableMode: mockState.runtimeResolveMarkdownTableMode, + convertMarkdownTables: mockState.runtimeConvertMarkdownTables, }, }, }), @@ -140,6 +152,14 @@ describe("sendMessageMSTeams", () => { beforeEach(() => { mockState.loadOutboundMediaFromUrl.mockReset(); mockState.resolveMSTeamsSendContext.mockReset(); + mockState.resolveMarkdownTableMode.mockReset(); + mockState.resolveMarkdownTableMode.mockReturnValue("off"); + mockState.convertMarkdownTables.mockReset(); + mockState.convertMarkdownTables.mockImplementation((text: string) => text); + mockState.runtimeResolveMarkdownTableMode.mockReset(); + mockState.runtimeResolveMarkdownTableMode.mockReturnValue("off"); + mockState.runtimeConvertMarkdownTables.mockReset(); + mockState.runtimeConvertMarkdownTables.mockImplementation((text: string) => text); mockState.requiresFileConsent.mockReset(); mockState.prepareFileConsentActivity.mockReset(); mockState.extractFilename.mockReset(); @@ -201,6 +221,34 @@ describe("sendMessageMSTeams", () => { ); }); + it("sends with provided cfg even when Teams runtime text helpers are unavailable", async () => { + mockState.runtimeResolveMarkdownTableMode.mockImplementation(() => { + throw new Error("MSTeams runtime not initialized"); + }); + mockState.runtimeConvertMarkdownTables.mockImplementation(() => { + throw new Error("MSTeams runtime not initialized"); + }); + mockState.resolveMarkdownTableMode.mockReturnValue("off"); + mockState.convertMarkdownTables.mockReturnValue("hello"); + + await expect( + sendMessageMSTeams({ + cfg: {} as OpenClawConfig, + to: "conversation:19:conversation@thread.tacv2", + text: "hello", + }), + ).resolves.toEqual({ + messageId: "message-1", + conversationId: "19:conversation@thread.tacv2", + }); + + expect(mockState.resolveMarkdownTableMode).toHaveBeenCalledWith({ + cfg: {}, + channel: "msteams", + }); + expect(mockState.convertMarkdownTables).toHaveBeenCalledWith("hello", "off"); + }); + it("uses graphChatId instead of conversationId when uploading to SharePoint", async () => { // Simulates a group chat where Bot Framework conversationId is valid but we have // a resolved Graph chat ID cached from a prior send. diff --git a/extensions/msteams/src/send.ts b/extensions/msteams/src/send.ts index 02648a0c6aa..2fae95a4fa8 100644 --- a/extensions/msteams/src/send.ts +++ b/extensions/msteams/src/send.ts @@ -1,3 +1,5 @@ +import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/config-runtime"; +import { convertMarkdownTables } from "openclaw/plugin-sdk/text-runtime"; import type { OpenClawConfig } from "../runtime-api.js"; import { loadOutboundMediaFromUrl } from "../runtime-api.js"; import { createMSTeamsConversationStoreFs } from "./conversation-store-fs.js"; @@ -97,11 +99,11 @@ export async function sendMessageMSTeams( params: SendMSTeamsMessageParams, ): Promise { const { cfg, to, text, mediaUrl, filename, mediaLocalRoots } = params; - const tableMode = getMSTeamsRuntime().channel.text.resolveMarkdownTableMode({ + const tableMode = resolveMarkdownTableMode({ cfg, channel: "msteams", }); - const messageText = getMSTeamsRuntime().channel.text.convertMarkdownTables(text ?? "", tableMode); + const messageText = convertMarkdownTables(text ?? "", tableMode); const ctx = await resolveMSTeamsSendContext({ cfg, to }); const { adapter,