import { fileURLToPath } from "node:url"; import type { CompactionEntry } from "@earendil-works/pi-coding-agent"; import { afterEach, describe, expect, it, vi } from "vitest"; import { createPiSession, type PiSession, } from "../../../test/fixture/create-pi-session.ts"; let session: PiSession | undefined; afterEach(async () => { await session?.dispose(); session = undefined; }); function continuityPath(): string { return fileURLToPath(new URL("../index.ts", import.meta.url)); } describe("continuity contract", () => { it("loads through the owned fixture", async () => { const extensionPath = continuityPath(); session = await createPiSession({ extensionPaths: [extensionPath] }); expect(session.errors).toEqual([]); expect(session.extensions).toHaveLength(1); expect(session.extensions[0]?.path).toBe(extensionPath); }); it("dispatches a hidden follow-up through the real Pi binding", async () => { session = await createPiSession({ extensionPaths: [continuityPath()] }); const send = vi .spyOn(session.session, "sendCustomMessage") .mockResolvedValue(undefined); await session.session.extensionRunner.emit({ type: "session_compact", compactionEntry: { id: "compact-real" } as CompactionEntry, fromExtension: false, reason: "manual", willRetry: false, }); await new Promise((resolve) => setTimeout(resolve, 10)); expect(send).toHaveBeenCalledOnce(); expect(send).toHaveBeenCalledWith( expect.objectContaining({ customType: "continuity-resume", display: false, }), { triggerTurn: true, deliverAs: "followUp" }, ); }); });