
















@@ -33,19 +33,34 @@ describe("runHeartbeatOnce heartbeat response tool", () => {
3333tmpDir: string;
3434storePath: string;
3535visibleReplies?: "automatic" | "message_tool";
36+groupVisibleReplies?: "automatic" | "message_tool";
3637agentRuntimeId?: string;
38+modelRuntimeId?: string;
3739model?: string;
40+target?: "telegram" | "last";
3841}): OpenClawConfig {
3942return {
4043agents: {
4144defaults: {
4245workspace: params.tmpDir,
43-heartbeat: { every: "5m", target: "telegram" },
46+heartbeat: { every: "5m", target: params.target ?? "telegram" },
4447 ...(params.model ? { model: params.model } : {}),
48+ ...(params.model && params.modelRuntimeId
49+ ? { models: { [params.model]: { agentRuntime: { id: params.modelRuntimeId } } } }
50+ : {}),
4551 ...(params.agentRuntimeId ? { agentRuntime: { id: params.agentRuntimeId } } : {}),
4652},
4753},
48- ...(params.visibleReplies ? { messages: { visibleReplies: params.visibleReplies } } : {}),
54+ ...(params.visibleReplies || params.groupVisibleReplies
55+ ? {
56+messages: {
57+ ...(params.visibleReplies ? { visibleReplies: params.visibleReplies } : {}),
58+ ...(params.groupVisibleReplies
59+ ? { groupChat: { visibleReplies: params.groupVisibleReplies } }
60+ : {}),
61+},
62+}
63+ : {}),
4964channels: {
5065telegram: {
5166token: "test-token",
@@ -228,6 +243,15 @@ describe("runHeartbeatOnce heartbeat response tool", () => {
228243expectHeartbeatToolPrompt(result, ["notify=false"]);
229244});
230245246+it("uses the heartbeat response tool prompt for group message-tool mode", async () => {
247+const result = await runPromptScenario({
248+config: { groupVisibleReplies: "message_tool", target: "last" },
249+session: { lastTo: "group:redacted" },
250+});
251+252+expectHeartbeatToolPrompt(result, ["notify=false"]);
253+});
254+231255it("uses the heartbeat response tool prompt for Codex harness sessions by default", async () => {
232256const result = await runPromptScenario({
233257session: { agentHarnessId: "codex" },
@@ -316,6 +340,31 @@ describe("runHeartbeatOnce heartbeat response tool", () => {
316340expectHeartbeatToolPrompt(result);
317341});
318342343+it("uses the heartbeat response tool prompt for model-specific Codex runtimes", async () => {
344+const result = await runPromptScenario({
345+config: {
346+model: "openai/gpt-5.5",
347+modelRuntimeId: "codex",
348+},
349+});
350+351+expectHeartbeatToolPrompt(result);
352+});
353+354+it("honors model-specific non-Codex runtimes over default Codex heartbeat mode", async () => {
355+const result = await runPromptScenario({
356+config: {
357+agentRuntimeId: "codex",
358+model: "openai/gpt-5.5",
359+modelRuntimeId: "pi",
360+},
361+});
362+363+expect(result.calledCtx.Body).toContain("HEARTBEAT_OK");
364+expect(result.calledCtx.Body).not.toContain("heartbeat_respond");
365+expect(result.calledOpts.sourceReplyDeliveryMode).toBeUndefined();
366+});
367+319368it("uses the heartbeat response tool prompt when the Codex runtime is env-forced", async () => {
320369vi.stubEnv("OPENCLAW_AGENT_RUNTIME", "codex");
321370const result = await runPromptScenario({
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。