mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-18 20:47:27 +00:00
fix(feishu): parse code blocks and share_chat messages (openclaw#28591) thanks @kevinWangSheng
Verified: - pnpm install --frozen-lockfile - pnpm build - pnpm check - pnpm test:macmini Co-authored-by: kevinWangSheng <118158941+kevinWangSheng@users.noreply.github.com> Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
@@ -22,6 +22,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Feishu/Typing backoff: re-throw Feishu typing add/remove rate-limit and quota errors (`429`, `99991400`, `99991403`) and detect SDK non-throwing backoff responses so the typing keepalive circuit breaker can stop retries instead of looping indefinitely. (#28494)
|
||||
- Feishu/Probe status caching: cache successful `probeFeishu()` bot-info results for 10 minutes (bounded cache with per-account keying) to reduce repeated status/onboarding probe API calls, while bypassing cache for failures and exceptions. (#28907) Thanks @Glucksberg.
|
||||
- Feishu/Opus media send type: send `.opus` attachments with `msg_type: "audio"` (instead of `"media"`) so Feishu voice messages deliver correctly while `.mp4` remains `msg_type: "media"` and documents remain `msg_type: "file"`. (#28269) Thanks @Glucksberg.
|
||||
- Feishu/Inbound rich-text parsing: preserve `share_chat` payload summaries when available and add explicit parsing for rich-text `code`/`code_block`/`pre` tags so forwarded and code-heavy messages keep useful context in agent input. (#28591) Thanks @kevinWangSheng.
|
||||
- Feishu/Local media sends: propagate `mediaLocalRoots` through Feishu outbound media sending into `loadWebMedia` so local path attachments work with post-CVE local-root enforcement. (#27884) Thanks @joelnishanth.
|
||||
- Security/Feishu webhook ingress: bound unauthenticated webhook rate-limit state with stale-window pruning and a hard key cap to prevent unbounded pre-auth memory growth from rotating source keys. (#26050) Thanks @bmendonca3.
|
||||
- Security/Compaction audit: remove the post-compaction audit injection message. (#28507) Thanks @fuller-stack-dev and @vincentkoc.
|
||||
|
||||
@@ -36,6 +36,20 @@ function makePostEvent(content: unknown) {
|
||||
};
|
||||
}
|
||||
|
||||
function makeShareChatEvent(content: unknown) {
|
||||
return {
|
||||
sender: { sender_id: { user_id: "u1", open_id: "ou_sender" } },
|
||||
message: {
|
||||
message_id: "msg_1",
|
||||
chat_id: "oc_chat1",
|
||||
chat_type: "group",
|
||||
message_type: "share_chat",
|
||||
content: JSON.stringify(content),
|
||||
mentions: [],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
describe("parseFeishuMessageEvent – mentionedBot", () => {
|
||||
const BOT_OPEN_ID = "ou_bot_123";
|
||||
|
||||
@@ -127,4 +141,36 @@ describe("parseFeishuMessageEvent – mentionedBot", () => {
|
||||
const ctx = parseFeishuMessageEvent(event as any, "ou_bot_123");
|
||||
expect(ctx.mentionedBot).toBe(false);
|
||||
});
|
||||
|
||||
it("preserves post code and code_block content", () => {
|
||||
const event = makePostEvent({
|
||||
content: [
|
||||
[
|
||||
{ tag: "text", text: "before " },
|
||||
{ tag: "code", text: "inline()" },
|
||||
],
|
||||
[{ tag: "code_block", language: "ts", text: "const x = 1;" }],
|
||||
],
|
||||
});
|
||||
const ctx = parseFeishuMessageEvent(event as any, "ou_bot_123");
|
||||
expect(ctx.content).toContain("before `inline()`");
|
||||
expect(ctx.content).toContain("```ts\nconst x = 1;\n```");
|
||||
});
|
||||
|
||||
it("uses share_chat body when available", () => {
|
||||
const event = makeShareChatEvent({
|
||||
body: "Merged and Forwarded Message",
|
||||
share_chat_id: "sc_abc123",
|
||||
});
|
||||
const ctx = parseFeishuMessageEvent(event as any, "ou_bot_123");
|
||||
expect(ctx.content).toBe("Merged and Forwarded Message");
|
||||
});
|
||||
|
||||
it("falls back to share_chat identifier when body is unavailable", () => {
|
||||
const event = makeShareChatEvent({
|
||||
share_chat_id: "sc_abc123",
|
||||
});
|
||||
const ctx = parseFeishuMessageEvent(event as any, "ou_bot_123");
|
||||
expect(ctx.content).toBe("[Forwarded message: sc_abc123]");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -188,6 +188,26 @@ function parseMessageContent(content: string, messageType: string): string {
|
||||
const { textContent } = parsePostContent(content);
|
||||
return textContent;
|
||||
}
|
||||
if (messageType === "share_chat") {
|
||||
// Preserve available summary text for merged/forwarded chat messages.
|
||||
if (parsed && typeof parsed === "object") {
|
||||
const share = parsed as {
|
||||
body?: unknown;
|
||||
summary?: unknown;
|
||||
share_chat_id?: unknown;
|
||||
};
|
||||
if (typeof share.body === "string" && share.body.trim().length > 0) {
|
||||
return share.body.trim();
|
||||
}
|
||||
if (typeof share.summary === "string" && share.summary.trim().length > 0) {
|
||||
return share.summary.trim();
|
||||
}
|
||||
if (typeof share.share_chat_id === "string" && share.share_chat_id.trim().length > 0) {
|
||||
return `[Forwarded message: ${share.share_chat_id.trim()}]`;
|
||||
}
|
||||
}
|
||||
return "[Forwarded message]";
|
||||
}
|
||||
return content;
|
||||
} catch {
|
||||
return content;
|
||||
@@ -293,6 +313,29 @@ function parsePostContent(content: string): {
|
||||
if (imageKey) {
|
||||
imageKeys.push(imageKey);
|
||||
}
|
||||
} else if (element.tag === "code") {
|
||||
// Inline code
|
||||
const code =
|
||||
typeof element.text === "string"
|
||||
? element.text
|
||||
: typeof element.content === "string"
|
||||
? element.content
|
||||
: "";
|
||||
if (code) {
|
||||
textContent += `\`${code}\``;
|
||||
}
|
||||
} else if (element.tag === "code_block" || element.tag === "pre") {
|
||||
// Multiline code block
|
||||
const lang = typeof element.language === "string" ? element.language : "";
|
||||
const code =
|
||||
typeof element.text === "string"
|
||||
? element.text
|
||||
: typeof element.content === "string"
|
||||
? element.content
|
||||
: "";
|
||||
if (code) {
|
||||
textContent += `\n\`\`\`${lang}\n${code}\n\`\`\`\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
textContent += "\n";
|
||||
|
||||
Reference in New Issue
Block a user