From c0c32445ab25f2fc294643b467c7133cfa0dda7b Mon Sep 17 00:00:00 2001 From: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> Date: Fri, 27 Mar 2026 21:17:08 -0500 Subject: [PATCH] fix(regression): restore feishu cold-runtime chunking --- extensions/feishu/src/channel.ts | 3 ++- extensions/feishu/src/outbound.test.ts | 10 ++++++++++ extensions/feishu/src/outbound.ts | 4 ++-- src/plugin-sdk/feishu.ts | 1 + 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/extensions/feishu/src/channel.ts b/extensions/feishu/src/channel.ts index be307b47a15..49196bd7ffc 100644 --- a/extensions/feishu/src/channel.ts +++ b/extensions/feishu/src/channel.ts @@ -26,6 +26,7 @@ import type { ChannelMeta, ChannelPlugin, ClawdbotConfig } from "../runtime-api. import { buildChannelConfigSchema, buildProbeChannelStatusSummary, + chunkTextForOutbound, createActionGate, createDefaultChannelRuntimeState, DEFAULT_ACCOUNT_ID, @@ -1053,7 +1054,7 @@ export const feishuPlugin: ChannelPlugin getFeishuRuntime().channel.text.chunkMarkdownText(text, limit), + chunker: chunkTextForOutbound, chunkerMode: "markdown", textChunkLimit: 4000, ...createRuntimeOutboundDelegates({ diff --git a/extensions/feishu/src/outbound.test.ts b/extensions/feishu/src/outbound.test.ts index 7462f65ed3e..53bdadc87f3 100644 --- a/extensions/feishu/src/outbound.test.ts +++ b/extensions/feishu/src/outbound.test.ts @@ -53,6 +53,16 @@ describe("feishuOutbound.sendText local-image auto-convert", () => { resetOutboundMocks(); }); + it("chunks outbound text without requiring Feishu runtime initialization", () => { + const chunker = feishuOutbound.chunker; + if (!chunker) { + throw new Error("feishuOutbound.chunker missing"); + } + + expect(() => chunker("hello world", 5)).not.toThrow(); + expect(chunker("hello world", 5)).toEqual(["hello", "world"]); + }); + async function createTmpImage(ext = ".png"): Promise<{ dir: string; file: string }> { const dir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-feishu-outbound-")); const file = path.join(dir, `sample${ext}`); diff --git a/extensions/feishu/src/outbound.ts b/extensions/feishu/src/outbound.ts index 0c449f82bd2..1c6f21e656a 100644 --- a/extensions/feishu/src/outbound.ts +++ b/extensions/feishu/src/outbound.ts @@ -1,7 +1,7 @@ import fs from "fs"; import path from "path"; import { createAttachedChannelResultAdapter } from "openclaw/plugin-sdk/channel-send-result"; -import type { ChannelOutboundAdapter } from "../runtime-api.js"; +import { chunkTextForOutbound, type ChannelOutboundAdapter } from "../runtime-api.js"; import { resolveFeishuAccount } from "./accounts.js"; import { sendMediaFeishu } from "./media.js"; import { getFeishuRuntime } from "./runtime.js"; @@ -79,7 +79,7 @@ async function sendOutboundText(params: { export const feishuOutbound: ChannelOutboundAdapter = { deliveryMode: "direct", - chunker: (text, limit) => getFeishuRuntime().channel.text.chunkMarkdownText(text, limit), + chunker: chunkTextForOutbound, chunkerMode: "markdown", textChunkLimit: 4000, ...createAttachedChannelResultAdapter({ diff --git a/src/plugin-sdk/feishu.ts b/src/plugin-sdk/feishu.ts index 15e5bed50b9..c7f03dd2a20 100644 --- a/src/plugin-sdk/feishu.ts +++ b/src/plugin-sdk/feishu.ts @@ -13,6 +13,7 @@ export { logTypingFailure } from "../channels/logging.js"; export type { AllowlistMatch } from "../channels/plugins/allowlist-match.js"; export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js"; export { createActionGate } from "../agents/tools/common.js"; +export { chunkTextForOutbound } from "./text-chunking.js"; export { buildSingleChannelSecretPromptState, addWildcardAllowFrom,