























@@ -11,21 +11,27 @@ function readSchemaProperty(schema: unknown, key: string): Record<string, unknow
1111return property as Record<string, unknown>;
1212}
131314+type HeartbeatResponseDetails = {
15+status?: string;
16+outcome?: string;
17+notify?: boolean;
18+summary?: string;
19+notificationText?: string;
20+priority?: string;
21+nextCheck?: string;
22+};
23+1424describe("createHeartbeatResponseTool", () => {
1525it("uses flat enum schemas for provider portability", () => {
1626const tool = createHeartbeatResponseTool();
17271828const outcome = readSchemaProperty(tool.parameters, "outcome");
1929const priority = readSchemaProperty(tool.parameters, "priority");
203021-expect(outcome).toMatchObject({
22-type: "string",
23-enum: ["no_change", "progress", "done", "blocked", "needs_attention"],
24-});
25-expect(priority).toMatchObject({
26-type: "string",
27-enum: ["low", "normal", "high"],
28-});
31+expect(outcome.type).toBe("string");
32+expect(outcome.enum).toEqual(["no_change", "progress", "done", "blocked", "needs_attention"]);
33+expect(priority.type).toBe("string");
34+expect(priority.enum).toEqual(["low", "normal", "high"]);
2935expect(outcome).not.toHaveProperty("anyOf");
3036expect(priority).not.toHaveProperty("anyOf");
3137});
@@ -40,12 +46,11 @@ describe("createHeartbeatResponseTool", () => {
4046});
41474248expect(tool.name).toBe(HEARTBEAT_RESPONSE_TOOL_NAME);
43-expect(result.details).toMatchObject({
44-status: "recorded",
45-outcome: "no_change",
46-notify: false,
47-summary: "Nothing needs attention.",
48-});
49+const details = result.details as HeartbeatResponseDetails;
50+expect(details.status).toBe("recorded");
51+expect(details.outcome).toBe("no_change");
52+expect(details.notify).toBe(false);
53+expect(details.summary).toBe("Nothing needs attention.");
4954});
50555156it("accepts notification text and optional scheduling metadata", async () => {
@@ -60,15 +65,14 @@ describe("createHeartbeatResponseTool", () => {
6065nextCheck: "2026-05-01T17:00:00Z",
6166});
626763-expect(result.details).toMatchObject({
64-status: "recorded",
65-outcome: "needs_attention",
66-notify: true,
67-summary: "Build is blocked.",
68-notificationText: "Build is blocked on missing credentials.",
69-priority: "high",
70-nextCheck: "2026-05-01T17:00:00Z",
71-});
68+const details = result.details as HeartbeatResponseDetails;
69+expect(details.status).toBe("recorded");
70+expect(details.outcome).toBe("needs_attention");
71+expect(details.notify).toBe(true);
72+expect(details.summary).toBe("Build is blocked.");
73+expect(details.notificationText).toBe("Build is blocked on missing credentials.");
74+expect(details.priority).toBe("high");
75+expect(details.nextCheck).toBe("2026-05-01T17:00:00Z");
7276});
73777478it("rejects missing notify because quiet vs visible delivery must be explicit", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。