From 20b1bc02f83887e61ce7de0fd7529c4f2591069a Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 16 Jul 2026 15:44:54 -0700 Subject: [PATCH] test: avoid redundant heartbeat runtime integration (#109371) --- src/agents/thinking-runtime.test.ts | 10 ++- .../heartbeat-runner.tool-response.test.ts | 90 +++++++------------ 2 files changed, 40 insertions(+), 60 deletions(-) diff --git a/src/agents/thinking-runtime.test.ts b/src/agents/thinking-runtime.test.ts index 12c6f916dcd6..dbd7bff12ea0 100644 --- a/src/agents/thinking-runtime.test.ts +++ b/src/agents/thinking-runtime.test.ts @@ -120,7 +120,7 @@ describe("resolveEffectiveAgentRuntime", () => { expect(supports).not.toHaveBeenCalled(); }); - it("prefers explicit session overrides and treats legacy harness ids as observational", () => { + it("prefers explicit session overrides", () => { const cfg = openAIConfig("openclaw"); expect( resolveEffectiveAgentRuntime({ @@ -130,6 +130,10 @@ describe("resolveEffectiveAgentRuntime", () => { sessionEntry: { agentRuntimeOverride: "codex", agentHarnessId: "openclaw" }, }), ).toBe("codex"); + }); + + it("ignores legacy harness ids when choosing a runtime", () => { + const cfg = openAIConfig("openclaw"); expect( resolveEffectiveAgentRuntime({ cfg, @@ -138,6 +142,10 @@ describe("resolveEffectiveAgentRuntime", () => { sessionEntry: { agentHarnessId: "codex" }, }), ).toBe("openclaw"); + }); + + it("uses configured runtime policy without session hints", () => { + const cfg = openAIConfig("openclaw"); expect( resolveEffectiveAgentRuntime({ cfg, diff --git a/src/infra/heartbeat-runner.tool-response.test.ts b/src/infra/heartbeat-runner.tool-response.test.ts index 4f5541682992..86e41f3be6ff 100644 --- a/src/infra/heartbeat-runner.tool-response.test.ts +++ b/src/infra/heartbeat-runner.tool-response.test.ts @@ -17,6 +17,7 @@ import { } from "../auto-reply/reply/agent-runner-failure-copy.js"; import type { OpenClawConfig } from "../config/config.js"; import { patchSessionEntry } from "../config/sessions/session-accessor.js"; +import { stripTrailingHeartbeatNotifyFalse } from "./heartbeat-delivery-normalization.js"; import { getLastHeartbeatEvent, resetHeartbeatEventsForTest } from "./heartbeat-events.js"; import { runHeartbeatOnce, testing, type HeartbeatDeps } from "./heartbeat-runner.js"; import { installHeartbeatRunnerTestRuntime } from "./heartbeat-runner.test-harness.js"; @@ -565,25 +566,31 @@ describe("runHeartbeatOnce heartbeat response tool", () => { }); }); - it.each(["", "\n", "\r\n"])( - "converts trailing notify=false fallback text into silent Telegram delivery with suffix %j", - async (suffix) => { - const { result, sendTelegram, cfg } = await runPlainFallbackReply( - `No interruption needed.\n\nnotify=false${suffix}`, - ); + it("converts trailing notify=false fallback text into silent Telegram delivery", async () => { + const { result, sendTelegram, cfg } = await runPlainFallbackReply( + "No interruption needed.\n\nnotify=false", + ); - expect(result.status).toBe("ran"); - expectTelegramSend(sendTelegram, { - text: "No interruption needed.", - cfg, - silent: true, - }); - expect(getLastHeartbeatEvent()).toMatchObject({ - status: "sent", - preview: "No interruption needed.", - channel: "telegram", - silent: true, - }); + expect(result.status).toBe("ran"); + expectTelegramSend(sendTelegram, { + text: "No interruption needed.", + cfg, + silent: true, + }); + expect(getLastHeartbeatEvent()).toMatchObject({ + status: "sent", + preview: "No interruption needed.", + channel: "telegram", + silent: true, + }); + }); + + it.each(["\n", "\r\n"])( + "strips trailing notify=false with suffix %j without rerunning a heartbeat", + (suffix) => { + expect( + stripTrailingHeartbeatNotifyFalse(`No interruption needed.\n\nnotify=false${suffix}`), + ).toEqual({ text: "No interruption needed.", silent: true }); }, ); @@ -636,55 +643,20 @@ describe("runHeartbeatOnce heartbeat response tool", () => { expectHeartbeatToolPrompt(result); }); - it.each([ - { - name: "uses the isolated Codex runtime instead of the base OpenClaw runtime", + it("uses the isolated Codex runtime instead of the base OpenClaw runtime", async () => { + // One direction proves prompt recalculation after isolation. Reciprocal + // runtime precedence is covered directly by thinking-runtime.test.ts. + const result = await runPromptScenario({ config: { isolatedSession: true }, session: { modelProvider: "anthropic", model: "claude-sonnet-4-6", agentRuntimeOverride: "openclaw", }, - expectedToolPrompt: true, - }, - { - name: "uses the isolated OpenClaw runtime instead of the base Codex runtime", - config: { - isolatedSession: true, - model: "anthropic/claude-sonnet-4-6", - }, - session: { - modelProvider: "openai", - model: "gpt-5.6-sol", - agentRuntimeOverride: "codex", - }, - expectedToolPrompt: false, - }, - ])("$name", async ({ config, session, expectedToolPrompt }) => { - const result = await runPromptScenario({ config, session }); - - expect(result.calledCtx.SessionKey).toMatch(/:heartbeat$/); - if (expectedToolPrompt) { - expectHeartbeatToolPrompt(result); - return; - } - expect(result.calledCtx.Body).toContain("HEARTBEAT_OK"); - expect(result.calledCtx.Body).not.toContain("heartbeat_respond"); - expect(result.calledOpts.sourceReplyDeliveryMode).toBeUndefined(); - }); - - it.each([ - ["observational harness id", { agentHarnessId: "codex" }], - ["provider-incompatible override", { agentRuntimeOverride: "codex" }], - ])("does not let a %s select the next heartbeat runtime", async (_label, session) => { - const result = await runPromptScenario({ - config: { model: "anthropic/claude-sonnet-4-6" }, - session, }); - expect(result.calledCtx.Body).toContain("HEARTBEAT_OK"); - expect(result.calledCtx.Body).not.toContain("heartbeat_respond"); - expect(result.calledOpts.sourceReplyDeliveryMode).toBeUndefined(); + expect(result.calledCtx.SessionKey).toMatch(/:heartbeat$/); + expectHeartbeatToolPrompt(result); }); it("delivers Codex runtime failure notices during Codex heartbeat message-tool mode", async () => {