diff --git a/CHANGELOG.md b/CHANGELOG.md index 760bab5ea93..8c85d61b44b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,7 +82,7 @@ Docs: https://docs.openclaw.ai - Providers/Mistral: send `reasoning_effort` for `mistral/mistral-small-latest` (Mistral Small 4) with thinking-level mapping, and mark the catalog entry as reasoning-capable so adjustable reasoning matches Mistral’s Chat Completions API. (#62162) Thanks @neeravmakwana. - OpenAI TTS/Groq: send `wav` to Groq-compatible speech endpoints, honor explicit `responseFormat` overrides on OpenAI-compatible paths, and only mark voice-note output as voice-compatible when the actual format is `opus`. (#62233) Thanks @neeravmakwana. - BlueBubbles/network: respect explicit private-network opt-out for loopback and private `serverUrl` values across account resolution, status probes, monitor startup, and attachment downloads, while keeping public-host attachment hostname pinning intact. (#59373) Thanks @jpreagan. - +- Agents/heartbeat: keep heartbeat runs pinned to the main session so active subagent transcripts are not overwritten by heartbeat status messages. (#61803) thanks @100yenadmin. ## 2026.4.5 ### Breaking diff --git a/src/infra/heartbeat-runner.ts b/src/infra/heartbeat-runner.ts index 753c9b31fb3..11390af43a4 100644 --- a/src/infra/heartbeat-runner.ts +++ b/src/infra/heartbeat-runner.ts @@ -44,6 +44,7 @@ import { CommandLane } from "../process/lanes.js"; import { isSubagentSessionKey, normalizeAgentId, + parseAgentSessionKey, resolveAgentIdFromSessionKey, toAgentStoreSessionKey, } from "../routing/session-key.js"; @@ -592,7 +593,11 @@ export async function runHeartbeatOnce(opts: { }): Promise { const cfg = opts.cfg ?? loadConfig(); const explicitAgentId = typeof opts.agentId === "string" ? opts.agentId.trim() : ""; - const agentId = normalizeAgentId(explicitAgentId || resolveDefaultAgentId(cfg)); + const forcedSessionAgentId = + explicitAgentId.length > 0 ? undefined : parseAgentSessionKey(opts.sessionKey)?.agentId; + const agentId = normalizeAgentId( + explicitAgentId || forcedSessionAgentId || resolveDefaultAgentId(cfg), + ); const heartbeat = opts.heartbeat ?? resolveHeartbeatConfig(cfg, agentId); if (!areHeartbeatsEnabled()) { return { status: "skipped", reason: "disabled" };