feat(heartbeat): add skipIfRunActive option + cron directive tag sanitization#29659
feat(heartbeat): add skipIfRunActive option + cron directive tag sanitization#29659Imccccc wants to merge 6 commits intoopenclaw:mainfrom
Conversation
- Add skipIfRunActive config to heartbeat settings - Skip heartbeat tick if an embedded Pi run is currently active - Add unit tests for the new functionality
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2cf1810617
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| * | ||
| * Default: false. | ||
| */ | ||
| skipIfRunActive?: boolean; |
There was a problem hiding this comment.
Add skipIfRunActive to heartbeat config schema
skipIfRunActive is introduced in the heartbeat config type and read by runHeartbeatOnce, but the runtime validator is still strict and does not allow this key (HeartbeatSchema in src/config/zod-schema.agent-runtime.ts only lists existing fields and uses .strict()). In practice, adding agents.defaults.heartbeat.skipIfRunActive to a real config will fail validation as an unrecognized property, so the new option cannot actually be configured by users.
Useful? React with 👍 / 👎.
Greptile SummaryThis PR adds a Main feature (
Secondary fix (context limit display):
Test coverage:
Both changes are well-implemented with appropriate tests. Confidence Score: 5/5
Last reviewed commit: 463b2e0 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 463b2e0c7e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (heartbeat?.skipIfRunActive && sessionId && isEmbeddedPiRunActive(sessionId)) { | ||
| return { status: "skipped", reason: "run-active" }; |
There was a problem hiding this comment.
Retry wake-triggered heartbeats after run-active skips
This new early return for skipIfRunActive runs before preflight inspects wake reasons, so wake-triggered heartbeats (including exec/cron events) can now be skipped while a run is active and then silently dropped until the next interval. In src/infra/heartbeat-wake.ts:156-164, retries are only scheduled for requests-in-flight, not run-active, so users with longer heartbeat intervals can see delayed or missed timely event summaries despite a wake already being queued.
Useful? React with 👍 / 👎.
…cation, hook bridge Comprehensive cron subsystem reliability overhaul addressing 9 open issues: **Configurable retry policy (openclaw#29527, openclaw#29546)** - Extract backoff logic into `retry-policy.ts` with configurable `cron.retryBackoff` schedule and `cron.stuckRunTimeoutMs` config fields - Classify execution errors as transient (retry with backoff) or terminal (disable job immediately) to prevent futile retry storms - Add Zod validation for new config fields **Fix delivery status reporting (openclaw#29660)** - `resolveDeliveryStatus` now accepts `deliveryAttempted` and returns "not-delivered" when delivery was attempted but not confirmed - Add explicit `delivered: false` to all error paths in delivery-dispatch.ts - Pass `deliveryAttempted` through the full result chain **Configurable response prefix (openclaw#29687)** - Add `responsePrefix` to CronServiceDeps (defaults to "Cron") - Use dep-injected prefix for main session summary messages **Strip directive tags from cron output (openclaw#29646)** - Strip `[[reply_to_current]]`, `[[reply_to:<id>]]`, `[[audio_as_voice]]` from isolated cron run output before delivery **Startup schedule preservation (openclaw#29690)** - Use maintenance-only recompute in `start()` to avoid advancing past-due `nextRunAtMs` values for jobs that `runMissedJobs` intentionally skipped - Clear `nextRunAtMs` for interrupted jobs so they get fresh schedule computation **Internal hook bridge (openclaw#29682)** - Add "cron" to `InternalHookEventType` with `CronExecutionHookEvent` type - Bridge `emitJobFinished` to `triggerInternalHook` so extensions can react to cron job completions (alerting, chaining, etc.) - Add `isCronExecutionEvent` type guard **Per-job skip-if-active flag (openclaw#29659)** - Add `skipIfRunActive?: boolean` to CronJob type for semantic overlap prevention Tests: 290 cron tests + 21 new retry-policy tests pass. Fixes: openclaw#29527, openclaw#29546, openclaw#29601, openclaw#29646, openclaw#29659, openclaw#29660, openclaw#29682, openclaw#29687, openclaw#29690
Prevent [[reply_to_current]] and [[audio_as_voice]] tags from leaking to users via direct cron/heartbeat delivery paths. The strip pass already handles summary/outputText/synthesizedText, but direct delivery uses pickLastDeliverablePayload which was not sanitized. Fixes PR review comment.
|
Thanks for the contribution. Closing this PR because it bundles multiple unrelated behavior changes in one patch:
This scope is too broad/risky for safe landing. Please split into small focused PRs with isolated regression coverage. |
Summary
Implements feature request #29537: Add
skipIfRunActiveoption to heartbeat configuration.Changes
1. Heartbeat skipIfRunActive Feature
Config Type (
src/config/types.agent-defaults.ts):skipIfRunActive?: booleanto heartbeat configZod Schema (
src/config/zod-schema.agent-runtime.ts):skipIfRunActiveto HeartbeatSchema for runtime validationHeartbeat Runner (
src/infra/heartbeat-runner.ts):isEmbeddedPiRunActive()to check if an agent run is in progressskipIfRunActive: trueand a run is active{ status: "skipped", reason: "run-active" }when skippedTests (
src/infra/heartbeat-runner.returns-default-unset.test.ts):2. Cron Directive Tag Sanitization
src/cron/isolated-agent/helpers.ts):pickLastDeliverablePayload()[[reply_to_current]]and[[audio_as_voice]]tags from leaking to users via direct cron/heartbeat delivery pathsUsage
{ "agents": { "defaults": { "heartbeat": { "every": "30m", "skipIfRunActive": true } } } }When enabled, the heartbeat will not fire while the agent is actively executing (e.g., during long coding sessions, research chains, or multi-tool workflows).
Closes #29537