Files
pi-goals/test/intercom.test.ts
T
wassname 489298d58b Replace supervision mailbox polling with pi-intercom
Scope messages to each pairing, wait for supervisor readiness, retain instructions in session history until acknowledgment, and rejoin after disconnect. Reuse installed Intercom or load the package dependency. Validate over an isolated real broker; existing user panes are untouched.
2026-09-08 16:31:58 +08:00

65 lines
3.1 KiB
TypeScript

import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
import { describe, expect, it, vi } from "vitest";
import { GoalIntercom } from "../src/intercom.js";
import { intercomFixture } from "./intercom-fixture.js";
function setup(role: "worker" | "supervisor", entries: any[] = []) {
const fixture = intercomFixture();
const hooks = new Map<string, any>();
const ctx = { sessionManager: { getEntries: () => entries }, ui: { notify: vi.fn() } };
const api = { events: fixture.events, on: (name: string, hook: any) => hooks.set(name, hook), appendEntry: (customType: string, data: unknown) => entries.push({ type: "custom", customType, data }) };
const link = new GoalIntercom(api as unknown as ExtensionAPI);
link.configure("binding", role, ctx as any);
return { link, fixture, entries, ctx, hooks };
}
describe("pi-intercom transport", () => {
it("receives exact advice once, acknowledges it and rejects unrelated peers", async () => {
const runtime = setup("worker");
await runtime.link.waitReady();
const instruction = "Check the Modal dependency.\nKeep the local queue paused.";
const delivered = vi.fn();
runtime.link.onSteer = delivered;
const message = { binding: "binding", role: "supervisor", kind: "steer", id: "instruction", text: instruction };
runtime.fixture.receive({ ...message, binding: "other" });
runtime.fixture.receive(message, "wrong-peer");
expect(delivered).not.toHaveBeenCalled();
runtime.fixture.receive(message);
runtime.fixture.receive(message);
expect(delivered).toHaveBeenCalledExactlyOnceWith(instruction);
expect(runtime.fixture.sent.filter(message => message.kind === "received")).toHaveLength(2);
await runtime.hooks.get("session_shutdown")();
runtime.fixture.receive({ ...message, id: "late" });
expect(delivered).toHaveBeenCalledTimes(1);
});
it("restores an unacknowledged steer on reconnect and stops replay after acknowledgment", async () => {
const first = setup("supervisor");
first.link.markReady();
await first.link.waitReady();
const id = first.link.steer("Read the full output.");
await first.hooks.get("session_shutdown")();
const resumed = setup("supervisor", [...first.entries]);
resumed.link.markReady();
await resumed.link.waitReady();
expect(resumed.fixture.sent.filter(message => message.kind === "steer")).toMatchObject([{ id, text: "Read the full output." }]);
resumed.fixture.receive({ binding: "binding", role: "worker", kind: "received", id });
resumed.fixture.connect(false);
expect(resumed.link.connected).toBe(false);
expect(() => resumed.link.steer("Must not send.")).toThrow("disconnected");
resumed.fixture.connect(true);
await resumed.link.waitReady();
expect(resumed.fixture.sent.filter(message => message.kind === "steer")).toHaveLength(1);
});
it("cancels a readiness wait on shutdown", async () => {
const runtime = setup("worker");
await runtime.link.waitReady();
runtime.fixture.connect(false);
const wait = runtime.link.waitReady();
const rejection = expect(wait).rejects.toThrow("Session ended");
await runtime.hooks.get("session_shutdown")();
await rejection;
});
});