Skip to content

Commit 36d6a36

Browse files
fix(clawsweeper): address review for automerge-openclaw-openclaw-86017 (1)
Co-authored-by: NianJiu <[email protected]> Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
1 parent 236733f commit 36d6a36

3 files changed

Lines changed: 83 additions & 2 deletions

File tree

extensions/feishu/src/channel.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,43 @@ describe("feishuPlugin actions", () => {
445445
).toBe(false);
446446
});
447447

448+
it("renders legacy web_app presentation buttons as native Feishu link buttons", async () => {
449+
sendCardFeishuMock.mockResolvedValueOnce({ messageId: "om_card", chatId: "oc_group_1" });
450+
451+
await feishuPlugin.actions?.handleAction?.({
452+
action: "send",
453+
params: {
454+
to: "chat:oc_group_1",
455+
presentation: {
456+
blocks: [
457+
{
458+
type: "buttons",
459+
buttons: [{ label: "Open app", web_app: { url: "https://example.com/app" } }],
460+
},
461+
],
462+
},
463+
},
464+
cfg,
465+
accountId: undefined,
466+
toolContext: {},
467+
} as never);
468+
469+
const sendCardArgs = requireRecord(
470+
mockCallArg(sendCardFeishuMock, 0, 0, "sendCardFeishu"),
471+
"send card args",
472+
);
473+
const card = requireRecord(sendCardArgs.card, "card");
474+
const elements = requireArray(requireRecord(card.body, "card body").elements, "card elements");
475+
expect(elements).toEqual([
476+
{
477+
tag: "button",
478+
text: { tag: "plain_text", content: "Open app" },
479+
type: "default",
480+
behaviors: [{ type: "open_url", default_url: "https://example.com/app" }],
481+
},
482+
]);
483+
});
484+
448485
it("does not duplicate title-only presentation cards in the body fallback", async () => {
449486
sendCardFeishuMock.mockResolvedValueOnce({ messageId: "om_card", chatId: "oc_group_1" });
450487

extensions/feishu/src/outbound.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,45 @@ describe("feishuOutbound.sendPayload native cards", () => {
490490
expectFeishuResult(result, "native_card_msg");
491491
});
492492

493+
it("renders webApp presentation buttons into Feishu channelData link buttons", async () => {
494+
const presentation: MessagePresentation = {
495+
blocks: [
496+
{
497+
type: "buttons",
498+
buttons: [{ label: "Open app", webApp: { url: "https://example.com/app" } }],
499+
},
500+
],
501+
};
502+
const payload = { presentation };
503+
const rendered = await feishuOutbound.renderPresentation?.({
504+
payload,
505+
presentation,
506+
ctx: {
507+
cfg: emptyConfig,
508+
to: "chat_1",
509+
text: "",
510+
accountId: "main",
511+
payload,
512+
},
513+
});
514+
515+
if (!rendered) {
516+
throw new Error("expected Feishu presentation renderer to return a payload");
517+
}
518+
expect(rendered.text).toBe("- Open app: https://example.com/app");
519+
const renderedChannelData = rendered.channelData as
520+
| { feishu?: { card?: Record<string, any> } }
521+
| undefined;
522+
expect(renderedChannelData?.feishu?.card?.body?.elements).toEqual([
523+
{
524+
tag: "button",
525+
text: { tag: "plain_text", content: "Open app" },
526+
type: "default",
527+
behaviors: [{ type: "open_url", default_url: "https://example.com/app" }],
528+
},
529+
]);
530+
});
531+
493532
it("does not duplicate title-only presentation cards in outbound fallbacks", async () => {
494533
const presentation: MessagePresentation = {
495534
title: "Status",

extensions/feishu/src/presentation-card.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ function resolveSafeFeishuButtonUrl(url: string | undefined): string | undefined
3636
}
3737
}
3838

39+
function resolveFeishuButtonUrl(button: MessagePresentationButton): string | undefined {
40+
return button.url ?? button.webApp?.url ?? button.web_app?.url;
41+
}
42+
3943
function mapFeishuButtonType(style: MessagePresentationButton["style"]) {
4044
if (style === "primary" || style === "success") {
4145
return "primary";
@@ -58,8 +62,9 @@ function buildFeishuPayloadButton(
5862
},
5963
type: mapFeishuButtonType(button.style),
6064
};
61-
if (button.url) {
62-
const safeUrl = resolveSafeFeishuButtonUrl(button.url);
65+
const url = resolveFeishuButtonUrl(button);
66+
if (url) {
67+
const safeUrl = resolveSafeFeishuButtonUrl(url);
6368
if (safeUrl) {
6469
behaviors.push({ type: "open_url", default_url: safeUrl });
6570
}

0 commit comments

Comments
 (0)