mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 22:58:26 +00:00
fix: heartbeat prompt + dedupe (#980) (thanks @voidserf)
- tighten default heartbeat prompt guidance - suppress duplicate heartbeat alerts within 24h Co-authored-by: void <voidserf@users.noreply.github.com>
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
||||
resolveAgentIdFromSessionKey,
|
||||
resolveMainSessionKey,
|
||||
resolveStorePath,
|
||||
saveSessionStore,
|
||||
updateSessionStore,
|
||||
} from "../config/sessions.js";
|
||||
import { formatErrorMessage } from "../infra/errors.js";
|
||||
@@ -277,6 +278,35 @@ export async function runHeartbeatOnce(opts: {
|
||||
|
||||
const mediaUrls =
|
||||
replyPayload.mediaUrls ?? (replyPayload.mediaUrl ? [replyPayload.mediaUrl] : []);
|
||||
|
||||
// Suppress duplicate heartbeats (same payload) within a short window.
|
||||
// This prevents "nagging" when nothing changed but the model repeats the same items.
|
||||
const prevHeartbeatText = typeof entry?.lastHeartbeatText === "string" ? entry.lastHeartbeatText : "";
|
||||
const prevHeartbeatAt = typeof entry?.lastHeartbeatSentAt === "number" ? entry.lastHeartbeatSentAt : undefined;
|
||||
const isDuplicateMain =
|
||||
!shouldSkipMain &&
|
||||
!mediaUrls.length &&
|
||||
Boolean(prevHeartbeatText.trim()) &&
|
||||
normalized.text.trim() === prevHeartbeatText.trim() &&
|
||||
typeof prevHeartbeatAt === "number" &&
|
||||
startedAt - prevHeartbeatAt < 24 * 60 * 60 * 1000;
|
||||
|
||||
if (isDuplicateMain) {
|
||||
await restoreHeartbeatUpdatedAt({
|
||||
storePath,
|
||||
sessionKey,
|
||||
updatedAt: previousUpdatedAt,
|
||||
});
|
||||
emitHeartbeatEvent({
|
||||
status: "skipped",
|
||||
reason: "duplicate",
|
||||
preview: normalized.text.slice(0, 200),
|
||||
durationMs: Date.now() - startedAt,
|
||||
hasMedia: false,
|
||||
});
|
||||
return { status: "ran", durationMs: Date.now() - startedAt };
|
||||
}
|
||||
|
||||
// Reasoning payloads are text-only; any attachments stay on the main reply.
|
||||
const previewText = shouldSkipMain
|
||||
? reasoningPayloads
|
||||
@@ -339,6 +369,20 @@ export async function runHeartbeatOnce(opts: {
|
||||
deps: opts.deps,
|
||||
});
|
||||
|
||||
// Record last delivered heartbeat payload for dedupe.
|
||||
if (!shouldSkipMain && normalized.text.trim()) {
|
||||
const store = loadSessionStore(storePath);
|
||||
const current = store[sessionKey];
|
||||
if (current) {
|
||||
store[sessionKey] = {
|
||||
...current,
|
||||
lastHeartbeatText: normalized.text,
|
||||
lastHeartbeatSentAt: startedAt,
|
||||
};
|
||||
await saveSessionStore(storePath, store);
|
||||
}
|
||||
}
|
||||
|
||||
emitHeartbeatEvent({
|
||||
status: "sent",
|
||||
to: delivery.to,
|
||||
|
||||
Reference in New Issue
Block a user