mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 04:15:48 -06:00
fix(feishu): preserve all accepted voice fallback content (#128130)
This commit is contained in:
committed by
GitHub
parent
1475b67111
commit
8a0ddd3311
@@ -74,12 +74,17 @@ export function mergeFeishuReplyDeliveryResults(
|
||||
content?: string,
|
||||
): FeishuReplyDeliveryResult {
|
||||
const visible = results.filter((result) => result.visibleReplySent === true);
|
||||
const acceptedContent = visible.flatMap((result) =>
|
||||
result.content === undefined ? [] : [result.content],
|
||||
);
|
||||
return createFeishuReplyDeliveryResult({
|
||||
results: visible,
|
||||
visibleReplySent: visible.length > 0,
|
||||
content:
|
||||
content === undefined
|
||||
? results.find((result) => result.content !== undefined)?.content
|
||||
? acceptedContent.length > 0
|
||||
? acceptedContent.join("\n\n")
|
||||
: undefined
|
||||
: content,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2381,6 +2381,71 @@ describe("createFeishuReplyDispatcher streaming behavior", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("reports every accepted voice upload fallback in the successful delivery result", async () => {
|
||||
sendMediaFeishuMock
|
||||
.mockRejectedValueOnce(new Error("first upload failed"))
|
||||
.mockRejectedValueOnce(new Error("second upload failed"));
|
||||
sendMessageFeishuMock
|
||||
.mockResolvedValueOnce({ messageId: "om-first-fallback" })
|
||||
.mockResolvedValueOnce({ messageId: "om-second-fallback" });
|
||||
const { options } = createDispatcherHarness();
|
||||
|
||||
const delivery = await options.deliver(
|
||||
{
|
||||
text: "spoken reply",
|
||||
mediaUrls: ["https://example.com/first.mp3", "https://example.com/second.mp3"],
|
||||
audioAsVoice: true,
|
||||
},
|
||||
{ kind: "final" },
|
||||
);
|
||||
|
||||
expect(delivery).toMatchObject({
|
||||
messageIds: ["om-first-fallback", "om-second-fallback"],
|
||||
visibleReplySent: true,
|
||||
content:
|
||||
"spoken reply\n\n📎 https://example.com/first.mp3\n\n📎 https://example.com/second.mp3",
|
||||
});
|
||||
expect(sendMessageFeishuMock).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("retains every accepted voice upload fallback when a later fallback fails", async () => {
|
||||
sendMediaFeishuMock
|
||||
.mockRejectedValueOnce(new Error("first upload failed"))
|
||||
.mockRejectedValueOnce(new Error("second upload failed"))
|
||||
.mockRejectedValueOnce(new Error("third upload failed"));
|
||||
sendMessageFeishuMock
|
||||
.mockResolvedValueOnce({ messageId: "om-first-fallback" })
|
||||
.mockResolvedValueOnce({ messageId: "om-second-fallback" })
|
||||
.mockRejectedValueOnce(new Error("third fallback failed"));
|
||||
const { options } = createDispatcherHarness();
|
||||
|
||||
const error = await options
|
||||
.deliver(
|
||||
{
|
||||
text: "spoken reply",
|
||||
mediaUrls: [
|
||||
"https://example.com/first.mp3",
|
||||
"https://example.com/second.mp3",
|
||||
"https://example.com/third.mp3",
|
||||
],
|
||||
audioAsVoice: true,
|
||||
},
|
||||
{ kind: "final" },
|
||||
)
|
||||
.catch((caught: unknown) => caught);
|
||||
|
||||
expect(error).toMatchObject({
|
||||
code: "CHANNEL_PARTIAL_DELIVERY",
|
||||
deliveryResult: {
|
||||
messageIds: ["om-first-fallback", "om-second-fallback"],
|
||||
visibleReplySent: true,
|
||||
content:
|
||||
"spoken reply\n\n📎 https://example.com/first.mp3\n\n📎 https://example.com/second.mp3",
|
||||
},
|
||||
});
|
||||
expect(sendMessageFeishuMock).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
it("does not leak local media paths in the upload failure fallback", async () => {
|
||||
const mediaPath = path.join(os.tmpdir(), "openclaw-feishu-reply-local-voice.mp3");
|
||||
sendMediaFeishuMock.mockRejectedValueOnce(new Error("media failed"));
|
||||
|
||||
@@ -1495,7 +1495,8 @@ export function createFeishuReplyDispatcher(params: CreateFeishuReplyDispatcherP
|
||||
hasVoiceMedia && hasText ? { fallbackText: text } : undefined,
|
||||
);
|
||||
}
|
||||
const result = mergeFeishuReplyDeliveryResults(deliveredResults, text);
|
||||
const deliveredContent = hasVoiceMedia ? (deliveredResults.at(-1)?.content ?? text) : text;
|
||||
const result = mergeFeishuReplyDeliveryResults(deliveredResults, deliveredContent);
|
||||
if (priorClosedStreamingSettlement?.error !== undefined) {
|
||||
throw createFeishuPartialReplyDeliveryError(
|
||||
isChannelPartialDeliveryError(priorClosedStreamingSettlement.error) &&
|
||||
|
||||
Reference in New Issue
Block a user