From 5a431f57fc1883dc097b28fbff6028cb64eeb569 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 13 Feb 2026 16:50:57 +0000 Subject: [PATCH] refactor(infra): split heartbeat event filters --- src/infra/heartbeat-events-filter.ts | 62 +++++++++++++++++++++++++ src/infra/heartbeat-runner.ts | 67 +++------------------------- 2 files changed, 68 insertions(+), 61 deletions(-) create mode 100644 src/infra/heartbeat-events-filter.ts diff --git a/src/infra/heartbeat-events-filter.ts b/src/infra/heartbeat-events-filter.ts new file mode 100644 index 0000000000..f5042bb0bd --- /dev/null +++ b/src/infra/heartbeat-events-filter.ts @@ -0,0 +1,62 @@ +import { HEARTBEAT_TOKEN } from "../auto-reply/tokens.js"; + +// Build a dynamic prompt for cron events by embedding the actual event content. +// This ensures the model sees the reminder text directly instead of relying on +// "shown in the system messages above" which may not be visible in context. +export function buildCronEventPrompt(pendingEvents: string[]): string { + const eventText = pendingEvents.join("\n").trim(); + if (!eventText) { + return ( + "A scheduled cron event was triggered, but no event content was found. " + + "Reply HEARTBEAT_OK." + ); + } + return ( + "A scheduled reminder has been triggered. The reminder content is:\n\n" + + eventText + + "\n\nPlease relay this reminder to the user in a helpful and friendly way." + ); +} + +const HEARTBEAT_OK_PREFIX = HEARTBEAT_TOKEN.toLowerCase(); + +// Detect heartbeat-specific noise so cron reminders don't trigger on non-reminder events. +function isHeartbeatAckEvent(evt: string): boolean { + const trimmed = evt.trim(); + if (!trimmed) { + return false; + } + const lower = trimmed.toLowerCase(); + if (!lower.startsWith(HEARTBEAT_OK_PREFIX)) { + return false; + } + const suffix = lower.slice(HEARTBEAT_OK_PREFIX.length); + if (suffix.length === 0) { + return true; + } + return !/[a-z0-9_]/.test(suffix[0]); +} + +function isHeartbeatNoiseEvent(evt: string): boolean { + const lower = evt.trim().toLowerCase(); + if (!lower) { + return false; + } + return ( + isHeartbeatAckEvent(lower) || + lower.includes("heartbeat poll") || + lower.includes("heartbeat wake") + ); +} + +export function isExecCompletionEvent(evt: string): boolean { + return evt.toLowerCase().includes("exec finished"); +} + +// Returns true when a system event should be treated as real cron reminder content. +export function isCronSystemEvent(evt: string) { + if (!evt.trim()) { + return false; + } + return !isHeartbeatNoiseEvent(evt) && !isExecCompletionEvent(evt); +} diff --git a/src/infra/heartbeat-runner.ts b/src/infra/heartbeat-runner.ts index fe5783fd0e..d90a978bde 100644 --- a/src/infra/heartbeat-runner.ts +++ b/src/infra/heartbeat-runner.ts @@ -41,6 +41,11 @@ import { normalizeAgentId, toAgentStoreSessionKey } from "../routing/session-key import { defaultRuntime, type RuntimeEnv } from "../runtime.js"; import { formatErrorMessage } from "./errors.js"; import { isWithinActiveHours } from "./heartbeat-active-hours.js"; +import { + buildCronEventPrompt, + isCronSystemEvent, + isExecCompletionEvent, +} from "./heartbeat-events-filter.js"; import { emitHeartbeatEvent, resolveIndicatorType } from "./heartbeat-events.js"; import { resolveHeartbeatVisibility } from "./heartbeat-visibility.js"; import { @@ -95,67 +100,7 @@ const EXEC_EVENT_PROMPT = "An async command you ran earlier has completed. The result is shown in the system messages above. " + "Please relay the command output to the user in a helpful way. If the command succeeded, share the relevant output. " + "If it failed, explain what went wrong."; - -// Build a dynamic prompt for cron events by embedding the actual event content. -// This ensures the model sees the reminder text directly instead of relying on -// "shown in the system messages above" which may not be visible in context. -function buildCronEventPrompt(pendingEvents: string[]): string { - const eventText = pendingEvents.join("\n").trim(); - if (!eventText) { - return ( - "A scheduled cron event was triggered, but no event content was found. " + - "Reply HEARTBEAT_OK." - ); - } - return ( - "A scheduled reminder has been triggered. The reminder content is:\n\n" + - eventText + - "\n\nPlease relay this reminder to the user in a helpful and friendly way." - ); -} - -const HEARTBEAT_OK_PREFIX = HEARTBEAT_TOKEN.toLowerCase(); - -// Detect heartbeat-specific noise so cron reminders don't trigger on non-reminder events. -function isHeartbeatAckEvent(evt: string): boolean { - const trimmed = evt.trim(); - if (!trimmed) { - return false; - } - const lower = trimmed.toLowerCase(); - if (!lower.startsWith(HEARTBEAT_OK_PREFIX)) { - return false; - } - const suffix = lower.slice(HEARTBEAT_OK_PREFIX.length); - if (suffix.length === 0) { - return true; - } - return !/[a-z0-9_]/.test(suffix[0]); -} - -function isHeartbeatNoiseEvent(evt: string): boolean { - const lower = evt.trim().toLowerCase(); - if (!lower) { - return false; - } - return ( - isHeartbeatAckEvent(lower) || - lower.includes("heartbeat poll") || - lower.includes("heartbeat wake") - ); -} - -function isExecCompletionEvent(evt: string): boolean { - return evt.toLowerCase().includes("exec finished"); -} - -// Returns true when a system event should be treated as real cron reminder content. -export function isCronSystemEvent(evt: string) { - if (!evt.trim()) { - return false; - } - return !isHeartbeatNoiseEvent(evt) && !isExecCompletionEvent(evt); -} +export { isCronSystemEvent }; type HeartbeatAgentState = { agentId: string;