Files
my-pi/pi-subagents/test/print-mode.test.ts
T

107 lines
2.6 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from "vitest";
vi.mock("../src/agent-runner.js", async () => {
const actual = await vi.importActual<typeof import("../src/agent-runner.js")>("../src/agent-runner.js");
return {
...actual,
runAgent: vi.fn(),
};
});
import { runAgent } from "../src/agent-runner.js";
import subagentsExtension from "../src/index.js";
function makePi() {
const tools = new Map<string, any>();
const handlers = new Map<string, any>();
const eventHandlers = new Map<string, any>();
return {
pi: {
registerMessageRenderer: vi.fn(),
registerTool: vi.fn((tool: any) => {
tools.set(tool.name, tool);
}),
registerCommand: vi.fn(),
on: vi.fn((event: string, handler: any) => {
handlers.set(event, handler);
}),
events: {
emit: vi.fn(),
on: vi.fn((event: string, handler: any) => {
eventHandlers.set(event, handler);
return vi.fn();
}),
},
appendEntry: vi.fn(),
sendMessage: vi.fn(() => {
throw new Error("stale extension context");
}),
} as any,
tools,
handlers,
};
}
function makeHeadlessCtx() {
return {
hasUI: false,
ui: {
setStatus: vi.fn(),
setWidget: vi.fn(),
},
cwd: "/tmp",
model: undefined,
modelRegistry: {
find: vi.fn(),
getAvailable: vi.fn(() => []),
},
sessionManager: {
getSessionId: vi.fn(() => "session-1"),
getBranch: vi.fn(() => []),
},
getSystemPrompt: vi.fn(() => "parent prompt"),
} as any;
}
describe("print mode background notifications", () => {
afterEach(() => {
vi.restoreAllMocks();
vi.useRealTimers();
});
it("ignores stale-context errors from delayed completion nudges", async () => {
vi.mocked(runAgent).mockResolvedValue({
responseText: "done",
session: { dispose: vi.fn() } as any,
aborted: false,
steered: false,
});
const { pi, tools, handlers } = makePi();
subagentsExtension(pi);
vi.useFakeTimers();
const agentTool = tools.get("Agent");
await agentTool.execute(
"tool-call-1",
{
prompt: "reply done",
description: "tiny child",
subagent_type: "general-purpose",
run_in_background: true,
},
undefined,
undefined,
makeHeadlessCtx(),
);
await vi.advanceTimersByTimeAsync(100); // smart-join batch debounce
await vi.advanceTimersByTimeAsync(200); // notification hold window
expect(pi.sendMessage).toHaveBeenCalled();
await handlers.get("session_shutdown")?.({}, makeHeadlessCtx());
});
});