Files
pi-plan/test/notice-display.test.ts
wassnameandPI/OpenAI 0a35869be9 Show sampled fortune after substantive goal updates without model work
Append a UI-only saved entry after supervisor or solo final updates; omit short unchanged waits. Remove the prompt instructions to sample fortunes, and cover the non-context renderer and lifecycle.

Co-Authored-By: PI/OpenAI <288921227+claudypoo@users.noreply.github.com>
2026-09-23 12:07:14 +08:00

83 lines
5.7 KiB
TypeScript

import { type ExtensionAPI, type ExtensionContext, getMarkdownTheme, initTheme } from "@earendil-works/pi-coding-agent";
import { Markdown, visibleWidth } from "@earendil-works/pi-tui";
import { expect, it, vi } from "vitest";
import { noticeDisplay } from "../src/notice-display.js";
it("collapses mirrored prompts only in the UI, expands the exact text, and restores by branch", () => {
initTheme("dark");
const theme = { fg: (_color: string, text: string) => text };
const pi = { registerMarkdownTransformer: vi.fn(), registerEntryRenderer: vi.fn(), registerMessageRenderer: vi.fn(), appendEntry: vi.fn(), sendMessage: vi.fn() };
const display = noticeDisplay(pi as unknown as ExtensionAPI);
const transform = pi.registerMarkdownTransformer.mock.calls[0][0];
const render = pi.registerEntryRenderer.mock.calls[0][1];
const renderPrompt = pi.registerMessageRenderer.mock.calls[0][1];
const content = "[pi-goals]\nPlan changed. Inspect the evidence.\n\n# Output\n\nKeep this entire requirement.\n\nFinal evidence line.";
expect(transform(content, { messageType: "user" })).toBe(content);
display.mirror(content);
expect(pi.appendEntry).toHaveBeenCalledExactlyOnceWith("pi-goals-notice", { content });
expect(transform(content, { messageType: "user" })).toBe("");
expect(transform(content, { messageType: "assistant" })).toBe(content);
expect(transform("[pi-goals]\nA human quotation", { messageType: "user" })).toBe("[pi-goals]\nA human quotation");
const rolePrompt = "[pi-goals]\nFor this plan, continue as the supervisor.";
display.compact(rolePrompt);
expect(pi.appendEntry).toHaveBeenLastCalledWith("pi-goals-compact-prompt", { content: rolePrompt });
expect(transform(rolePrompt, { messageType: "user" })).toBe("[pi-goals] Goal instructions");
display.prompt(content);
expect(pi.sendMessage).toHaveBeenCalledExactlyOnceWith({ customType: "pi-goals-prompt", content, display: true }, { triggerTurn: true, deliverAs: "followUp" });
const prompt = { role: "custom", customType: "pi-goals-prompt", content, display: true };
expect(renderPrompt(prompt, { expanded: false }, theme).render(80).join("\n")).toContain("Plan changed · review requested");
expect(renderPrompt(prompt, { expanded: true }, theme).render(80)).toEqual(new Markdown(content, 0, 0, getMarkdownTheme()).render(80));
const activity = "[pi-goals: plan activity]\nTask or evidence bookkeeping changed.";
display.passive(activity);
expect(pi.sendMessage).toHaveBeenLastCalledWith({ customType: "pi-goals-prompt", content: activity, display: true }, { deliverAs: "nextTurn" });
expect(renderPrompt({ role: "custom", customType: "pi-goals-prompt", content: activity }, { expanded: false }, theme).render(80).join("\n")).toContain("Plan activity recorded");
const entry = { type: "custom", customType: "pi-goals-notice", data: { content } };
const collapsed = render(entry, { expanded: false }, theme);
for (const width of [24, 80]) {
const lines = collapsed.render(width);
expect(lines).toHaveLength(1);
expect(visibleWidth(lines[0])).toBeLessThanOrEqual(width);
expect(lines.join("\n")).not.toContain("Final evidence line");
}
const expanded = render(entry, { expanded: true }, theme);
expect(expanded.render(80)).toEqual(new Markdown(content, 0, 0, getMarkdownTheme()).render(80));
const review = "[pi-goals]\n## Selected worker-stop reviews\n\n- event run-1: output ready (eventId worker:run-1)";
display.mirror(review);
const reviewCollapsed = render({ type: "custom", customType: "pi-goals-notice", data: { content: review } }, { expanded: false }, theme);
expect(reviewCollapsed.render(80).join("\n")).toContain("Selected worker-stop reviews");
const status = "[pi-goals: worker status]\n## Worker status: waiting\n\nPueue 1552 is running.";
display.mirror(status);
const statusCollapsed = render({ type: "custom", customType: "pi-goals-notice", data: { content: status } }, { expanded: false }, theme);
expect(statusCollapsed.render(80).join("\n")).toContain("Worker status");
const deliveredReview = "## Worker stop review: changes_requested\n\nCorrect output.txt.";
display.hide(deliveredReview);
expect(transform(deliveredReview, { messageType: "user" })).toBe("");
display.restore({ sessionManager: { getBranch: () => [] } } as unknown as ExtensionContext, ["pi-goals-report-review"]);
expect(transform(content, { messageType: "user" })).toBe(content);
expect(transform(rolePrompt, { messageType: "user" })).toBe(rolePrompt);
const reviewEntry = { type: "custom", customType: "pi-goals-report-review", data: { content: deliveredReview } };
const compactEntry = { type: "custom", customType: "pi-goals-compact-prompt", data: { content: rolePrompt } };
display.restore({ sessionManager: { getBranch: () => [entry, reviewEntry, compactEntry] } } as unknown as ExtensionContext, ["pi-goals-report-review"]);
expect(transform(content, { messageType: "user" })).toBe("");
expect(transform(deliveredReview, { messageType: "user" })).toBe("");
expect(transform(rolePrompt, { messageType: "user" })).toBe("[pi-goals] Goal instructions");
expect(entry.data.content).toBe(content);
});
it("renders a saved sampled fortune without sending it to the model", () => {
initTheme("dark");
const pi = { registerMarkdownTransformer: vi.fn(), registerEntryRenderer: vi.fn(), registerMessageRenderer: vi.fn(), appendEntry: vi.fn(), sendMessage: vi.fn() };
const display = noticeDisplay(pi as unknown as ExtensionAPI);
display.fortune();
const [type, data] = pi.appendEntry.mock.calls[0];
expect(type).toBe("pi-goals-fortune");
expect(data.content).toMatch(/ -- /);
const renderer = pi.registerEntryRenderer.mock.calls.find(([name]) => name === type)?.[1];
expect(renderer({ data }, { expanded: false }, {})).toBeInstanceOf(Markdown);
expect(pi.sendMessage).not.toHaveBeenCalled();
});