




















@@ -217,38 +217,67 @@ async function hasPersistedMatrixPluginStateDedupeEntry(params: {
217217eventId: string;
218218roomId: string;
219219stateDir: string;
220-}) {
221-const databasePath = path.join(params.stateDir, "state", "openclaw.sqlite");
220+}): Promise<string | null> {
222221const entryKey = buildMatrixInboundDedupePluginStateKey({
223222accountId: params.accountId,
224223eventId: params.eventId,
225224roomId: params.roomId,
226225});
226+const databasePaths = await findFilesByName({
227+filename: "openclaw.sqlite",
228+rootDir: params.stateDir,
229+maxDepth: 4,
230+});
231+if (databasePaths.length === 0) {
232+databasePaths.push(path.join(params.stateDir, "state", "openclaw.sqlite"));
233+}
234+const now = Date.now();
235+const isExpectedValue = (raw: unknown) => {
236+if (typeof raw !== "string") {
237+return false;
238+}
239+try {
240+const parsed = JSON.parse(raw) as unknown;
241+return (
242+isRecord(parsed) && parsed.roomId === params.roomId && parsed.eventId === params.eventId
243+);
244+} catch {
245+return false;
246+}
247+};
227248try {
228-await fs.access(databasePath);
229249const sqlite = await import("node:sqlite");
230-const db = new sqlite.DatabaseSync(databasePath, { readOnly: true });
231-try {
232-const row = db
233-.prepare(
234-`SELECT 1 AS ok
235- FROM plugin_state_entries
236- WHERE plugin_id = ?
237- AND namespace = ?
238- AND entry_key = ?
239- AND (expires_at IS NULL OR expires_at > ?)
240- LIMIT 1`,
241-)
242-.get(MATRIX_PLUGIN_ID, MATRIX_INBOUND_DEDUPE_NAMESPACE, entryKey, Date.now()) as
243-| { ok?: unknown }
244-| undefined;
245-return row?.ok === 1;
246-} finally {
247-db.close();
250+for (const databasePath of databasePaths) {
251+try {
252+await fs.access(databasePath);
253+const db = new sqlite.DatabaseSync(databasePath, { readOnly: true });
254+try {
255+const rows = db
256+.prepare(
257+`SELECT entry_key AS entryKey, value_json AS valueJson
258+ FROM plugin_state_entries
259+ WHERE plugin_id = ?
260+ AND namespace = ?
261+ AND (expires_at IS NULL OR expires_at > ?)`,
262+)
263+.all(MATRIX_PLUGIN_ID, MATRIX_INBOUND_DEDUPE_NAMESPACE, now) as Array<{
264+entryKey?: unknown;
265+valueJson?: unknown;
266+}>;
267+if (rows.some((row) => row.entryKey === entryKey || isExpectedValue(row.valueJson))) {
268+return databasePath;
269+}
270+} finally {
271+db.close();
272+}
273+} catch {
274+continue;
275+}
248276}
249277} catch {
250-return false;
278+return null;
251279}
280+return null;
252281}
253282254283export async function waitForMatrixInboundDedupeEntry(params: {
@@ -260,15 +289,14 @@ export async function waitForMatrixInboundDedupeEntry(params: {
260289}) {
261290const startedAt = Date.now();
262291while (Date.now() - startedAt < params.timeoutMs) {
263-if (
264-await hasPersistedMatrixPluginStateDedupeEntry({
265-accountId: params.context.sutAccountId ?? "sut",
266-eventId: params.eventId,
267-roomId: params.roomId,
268-stateDir: params.stateDir,
269-})
270-) {
271-return path.join(params.stateDir, "state", "openclaw.sqlite");
292+const sqlitePath = await hasPersistedMatrixPluginStateDedupeEntry({
293+accountId: params.context.sutAccountId ?? "sut",
294+eventId: params.eventId,
295+roomId: params.roomId,
296+stateDir: params.stateDir,
297+});
298+if (sqlitePath) {
299+return sqlitePath;
272300}
273301const pathname = await resolveBestMatrixStateFile({
274302context: params.context,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。