openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
112 lines (111 loc) • 4.17 kB
JavaScript
import { r as logVerbose } from "./globals-GTrXU4s9.js";
import "./runtime-env-D_2q8-VK.js";
import { u as getIMessageRuntime } from "./monitor-reply-cache-DUH5oJzE.js";
import { createHash } from "node:crypto";
//#region extensions/imessage/src/monitor/persisted-echo-cache.ts
const IMESSAGE_SENT_ECHOES_TTL_MS = 720 * 60 * 1e3;
const IMESSAGE_SENT_ECHOES_NAMESPACE = "imessage.sent-echoes";
function normalizeText(text) {
return text?.replace(/\r\n?/g, "\n").trim() || void 0;
}
function normalizeMessageId(messageId) {
const normalized = messageId?.trim();
if (!normalized || normalized === "ok" || normalized === "unknown") return;
return normalized;
}
let mirror = null;
let persistenceFailureLogged = false;
function reportFailure(scope, err) {
if (persistenceFailureLogged) return;
persistenceFailureLogged = true;
logVerbose(`imessage echo-cache: ${scope} disabled after first failure: ${String(err)}`);
}
function resolveIMessageSentEchoEntryKey(entry) {
return createHash("sha256").update(JSON.stringify([
entry.scope,
entry.text ?? "",
entry.messageId ?? "",
entry.timestamp
])).digest("hex").slice(0, 32);
}
function openPersistedEchoStore() {
return getIMessageRuntime().state.openSyncKeyedStore({
namespace: IMESSAGE_SENT_ECHOES_NAMESPACE,
maxEntries: 256
});
}
function remainingTtlMs(timestamp) {
const remaining = IMESSAGE_SENT_ECHOES_TTL_MS - Math.max(0, Date.now() - timestamp);
return remaining > 0 ? remaining : void 0;
}
function resolveEntryTtlMs(entry, ttlMs) {
if (typeof ttlMs === "number" && Number.isFinite(ttlMs) && ttlMs > 0) return ttlMs;
return remainingTtlMs(entry.timestamp);
}
function isLiveEntry(entry, now = Date.now()) {
const cutoff = now - IMESSAGE_SENT_ECHOES_TTL_MS;
return entry.timestamp >= cutoff && (entry.expiresAt == null || entry.expiresAt > now);
}
function loadMirrorFromStore() {
try {
mirror = openPersistedEchoStore().entries().map(({ value }) => value).filter((entry) => isLiveEntry(entry)).toSorted((a, b) => a.timestamp - b.timestamp).slice(-256);
} catch (err) {
reportFailure("read", err);
mirror = [];
}
}
function readRecentEntries() {
loadMirrorFromStore();
return mirror ?? [];
}
function persistEntry(entry, ttlMs) {
const effectiveTtlMs = resolveEntryTtlMs(entry, ttlMs);
if (!effectiveTtlMs) return;
const key = resolveIMessageSentEchoEntryKey(entry);
try {
openPersistedEchoStore().register(key, entry, { ttlMs: effectiveTtlMs });
} catch (err) {
reportFailure("write", err);
return;
}
return key;
}
function rememberPersistedIMessageEcho(params) {
const text = normalizeText(params.text);
const messageId = normalizeMessageId(params.messageId);
const entry = {
scope: params.scope,
timestamp: Date.now(),
...text ? { text } : {},
...messageId ? { messageId } : {},
...params.pending ? { pending: true } : {}
};
if (typeof params.ttlMs === "number" && Number.isFinite(params.ttlMs) && params.ttlMs > 0) entry.expiresAt = entry.timestamp + params.ttlMs;
if (!entry.text && !entry.messageId) return;
loadMirrorFromStore();
const key = persistEntry(entry, params.ttlMs);
mirror = [...mirror ?? [], entry].filter((candidate) => isLiveEntry(candidate)).slice(-256);
return key;
}
function forgetPersistedIMessageEchoKey(key) {
if (!key) return;
try {
openPersistedEchoStore().delete(key);
} catch (err) {
reportFailure("delete", err);
}
mirror = (mirror ?? []).filter((entry) => resolveIMessageSentEchoEntryKey(entry) !== key);
}
function hasPersistedIMessageEcho(params) {
const text = normalizeText(params.text);
const messageId = normalizeMessageId(params.messageId);
if (!text && !messageId) return false;
for (const entry of readRecentEntries()) {
if (entry.scope !== params.scope) continue;
if (messageId && entry.messageId === messageId) return true;
if (text && entry.text === text && (!entry.pending || params.includePendingText)) return true;
}
return false;
}
//#endregion
export { rememberPersistedIMessageEcho as a, hasPersistedIMessageEcho as i, IMESSAGE_SENT_ECHOES_TTL_MS as n, resolveIMessageSentEchoEntryKey as o, forgetPersistedIMessageEchoKey as r, IMESSAGE_SENT_ECHOES_NAMESPACE as t };