


















1-import { afterEach, describe, expect, it } from "vitest";
2-import { resetGlobalHookRunner } from "../../plugins/hook-runner-global.js";
1+import { afterEach, describe, expect, it, vi } from "vitest";
2+import {
3+initializeGlobalHookRunner,
4+resetGlobalHookRunner,
5+} from "../../plugins/hook-runner-global.js";
6+import { createMockPluginRegistry } from "../../plugins/hooks.test-helpers.js";
37import { resolveAgentHarnessBeforePromptBuildResult } from "./prompt-compaction-hook-helpers.js";
4859afterEach(() => {
@@ -63,4 +67,84 @@ describe("resolveAgentHarnessBeforePromptBuildResult", () => {
6367promptInputRange: { start: 17, end: 17 },
6468});
6569});
70+71+it("runs heartbeat_prompt_contribution on a heartbeat turn and prepends its contribution", async () => {
72+initializeGlobalHookRunner(
73+createMockPluginRegistry([
74+{
75+hookName: "heartbeat_prompt_contribution",
76+handler: () => ({ prependContext: "Run the base-heartbeat skill." }),
77+},
78+]),
79+);
80+81+const result = await resolveAgentHarnessBeforePromptBuildResult({
82+prompt: "Read HEARTBEAT.md.",
83+developerInstructions: "base instructions",
84+messages: [],
85+ctx: { trigger: "heartbeat", agentId: "agent-1", sessionKey: "session-1" },
86+});
87+88+expect(result.prompt).toBe("Run the base-heartbeat skill.\n\nRead HEARTBEAT.md.");
89+// The heartbeat contribution affects only the prompt, not developer instructions.
90+expect(result.developerInstructions).toBe("base instructions");
91+});
92+93+it("runs heartbeat contributions before other prompt-build hooks", async () => {
94+const calls: string[] = [];
95+initializeGlobalHookRunner(
96+createMockPluginRegistry([
97+{
98+hookName: "heartbeat_prompt_contribution",
99+handler: () => {
100+calls.push("heartbeat");
101+return { prependContext: "heartbeat context" };
102+},
103+},
104+{
105+hookName: "before_prompt_build",
106+handler: () => {
107+calls.push("before_prompt_build");
108+return { prependContext: "prompt context" };
109+},
110+},
111+{
112+hookName: "before_agent_start",
113+handler: () => {
114+calls.push("before_agent_start");
115+return { prependContext: "agent-start context" };
116+},
117+},
118+]),
119+);
120+121+const result = await resolveAgentHarnessBeforePromptBuildResult({
122+prompt: "hello",
123+developerInstructions: "base instructions",
124+messages: [],
125+ctx: { trigger: "heartbeat", agentId: "agent-1", sessionKey: "session-1" },
126+});
127+128+expect(calls).toEqual(["heartbeat", "before_prompt_build", "before_agent_start"]);
129+expect(result.prompt).toBe(
130+"heartbeat context\n\nprompt context\n\nagent-start context\n\nhello",
131+);
132+});
133+134+it("skips heartbeat_prompt_contribution off a heartbeat turn", async () => {
135+const handler = vi.fn(() => ({ prependContext: "should not appear" }));
136+initializeGlobalHookRunner(
137+createMockPluginRegistry([{ hookName: "heartbeat_prompt_contribution", handler }]),
138+);
139+140+const result = await resolveAgentHarnessBeforePromptBuildResult({
141+prompt: "hello",
142+developerInstructions: "base instructions",
143+messages: [],
144+ctx: { trigger: "user", agentId: "agent-1", sessionKey: "session-1" },
145+});
146+147+expect(handler).not.toHaveBeenCalled();
148+expect(result.prompt).toBe("hello");
149+});
66150});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。