mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
fix(feishu): reopen retryable bot menu replay
This commit is contained in:
@@ -216,6 +216,26 @@ export async function recordProcessedFeishuMessage(
|
||||
return await tryRecordMessagePersistent(normalizedMessageId, namespace, log);
|
||||
}
|
||||
|
||||
export async function forgetProcessedFeishuMessage(
|
||||
messageId: string | undefined | null,
|
||||
namespace = "global",
|
||||
log?: (...args: unknown[]) => void,
|
||||
): Promise<boolean> {
|
||||
const normalizedNamespace = normalizeNamespace(namespace);
|
||||
const normalizedMessageId = normalizeMessageId(messageId);
|
||||
if (!normalizedMessageId) {
|
||||
return false;
|
||||
}
|
||||
memory.delete(memoryKey(normalizedNamespace, normalizedMessageId));
|
||||
const key = dedupeStoreKey(normalizedNamespace, normalizedMessageId);
|
||||
try {
|
||||
return openDedupStore(normalizedNamespace).delete(key);
|
||||
} catch (error) {
|
||||
log?.(`feishu-dedup: persistent delete failed: ${String(error)}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function hasProcessedFeishuMessage(
|
||||
messageId: string | undefined | null,
|
||||
namespace = "global",
|
||||
|
||||
@@ -4,6 +4,7 @@ import { handleFeishuMessage, type FeishuMessageEvent } from "./bot.js";
|
||||
import { maybeHandleFeishuQuickActionMenu } from "./card-ux-launcher.js";
|
||||
import {
|
||||
claimUnprocessedFeishuMessage,
|
||||
forgetProcessedFeishuMessage,
|
||||
recordProcessedFeishuMessage,
|
||||
releaseFeishuMessageProcessing,
|
||||
} from "./dedup.js";
|
||||
@@ -131,18 +132,20 @@ export function createFeishuBotMenuHandler(params: {
|
||||
.then(async (handledMenu) => {
|
||||
if (handledMenu) {
|
||||
await recordProcessedFeishuMessage(syntheticMessageId, accountId, log);
|
||||
releaseFeishuMessageProcessing(syntheticMessageId, accountId);
|
||||
return;
|
||||
}
|
||||
return await handleLegacyMenu();
|
||||
})
|
||||
.catch(async (err) => {
|
||||
if (isFeishuRetryableSyntheticEventError(err)) {
|
||||
releaseFeishuMessageProcessing(syntheticMessageId, accountId);
|
||||
await forgetProcessedFeishuMessage(syntheticMessageId, accountId, log);
|
||||
} else {
|
||||
await recordProcessedFeishuMessage(syntheticMessageId, accountId, log);
|
||||
}
|
||||
throw err;
|
||||
})
|
||||
.finally(() => {
|
||||
releaseFeishuMessageProcessing(syntheticMessageId, accountId);
|
||||
});
|
||||
if (fireAndForget) {
|
||||
promise.catch((err) => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ClawdbotConfig } from "../runtime-api.js";
|
||||
import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js";
|
||||
import { expectFirstSentCardUsesFillWidthOnly } from "./card-test-helpers.js";
|
||||
import { createFeishuBotMenuHandler } from "./monitor.bot-menu-handler.js";
|
||||
|
||||
@@ -40,15 +40,18 @@ function createBotMenuEvent(params: { eventKey: string; timestamp: string }) {
|
||||
};
|
||||
}
|
||||
|
||||
async function registerHandlers() {
|
||||
return createFeishuBotMenuHandler({
|
||||
cfg: {} as ClawdbotConfig,
|
||||
accountId: "default",
|
||||
runtime: {
|
||||
async function registerHandlers(params: { runtime?: RuntimeEnv } = {}) {
|
||||
const runtime =
|
||||
params.runtime ??
|
||||
({
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
exit: vi.fn(),
|
||||
},
|
||||
} as RuntimeEnv);
|
||||
return createFeishuBotMenuHandler({
|
||||
cfg: {} as ClawdbotConfig,
|
||||
accountId: "default",
|
||||
runtime,
|
||||
chatHistories: new Map(),
|
||||
fireAndForget: true,
|
||||
getBotOpenId: () => "ou_bot",
|
||||
@@ -163,7 +166,8 @@ describe("Feishu bot menu handler", () => {
|
||||
});
|
||||
|
||||
it("reopens replay for explicit retryable fallback failures", async () => {
|
||||
const onBotMenu = await registerHandlers();
|
||||
const runtime = { log: vi.fn(), error: vi.fn(), exit: vi.fn() } as RuntimeEnv;
|
||||
const onBotMenu = await registerHandlers({ runtime });
|
||||
sendCardFeishuMock
|
||||
.mockImplementationOnce(async () => {
|
||||
throw new Error("boom");
|
||||
@@ -180,9 +184,16 @@ describe("Feishu bot menu handler", () => {
|
||||
.mockResolvedValueOnce(undefined);
|
||||
|
||||
await onBotMenu(createBotMenuEvent({ eventKey: "quick-actions", timestamp: "1700000000004" }));
|
||||
await vi.waitFor(() => {
|
||||
expect(runtime.error).toHaveBeenCalledWith(
|
||||
"feishu[default]: error handling bot menu event: FeishuRetryableSyntheticEventError: retry me",
|
||||
);
|
||||
});
|
||||
await onBotMenu(createBotMenuEvent({ eventKey: "quick-actions", timestamp: "1700000000004" }));
|
||||
|
||||
expect(sendCardFeishuMock).toHaveBeenCalledTimes(2);
|
||||
expect(handleFeishuMessageMock).toHaveBeenCalledTimes(1);
|
||||
await vi.waitFor(() => {
|
||||
expect(handleFeishuMessageMock).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
"dist/extensions/signal/runtime-api.js",
|
||||
"dist/extensions/telegram/runtime-api.js",
|
||||
"dist/extensions/telegram/runtime-setter-api.js",
|
||||
"dist/extensions/tokenjuice/runtime-api.js",
|
||||
"dist/extensions/webhooks/runtime-api.js",
|
||||
"dist/extensions/workboard/runtime-api.js",
|
||||
"dist/extensions/zai/runtime-api.js"
|
||||
|
||||
Reference in New Issue
Block a user