test(coding-agent): add session lifecycle characterization suite
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import type { AgentTool } from "@mariozechner/pi-agent-core";
|
||||
import { fauxAssistantMessage, fauxToolCall } from "@mariozechner/pi-ai";
|
||||
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
||||
import { Type } from "@sinclair/typebox";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { createHarness, getAssistantTexts, getUserTexts, type Harness } from "../harness.js";
|
||||
|
||||
describe("issue #2023 queued slash-command follow-up", () => {
|
||||
const harnesses: Harness[] = [];
|
||||
|
||||
afterEach(() => {
|
||||
while (harnesses.length > 0) {
|
||||
harnesses.pop()?.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
it("treats extension-origin queued slash-command follow-ups as raw user text instead of dispatching the command", async () => {
|
||||
let extensionApi: ExtensionAPI | undefined;
|
||||
const commandRuns: string[] = [];
|
||||
let releaseToolExecution: (() => void) | undefined;
|
||||
const toolRelease = new Promise<void>((resolve) => {
|
||||
releaseToolExecution = resolve;
|
||||
});
|
||||
const waitTool: AgentTool = {
|
||||
name: "wait",
|
||||
label: "Wait",
|
||||
description: "Wait for the test to release execution",
|
||||
parameters: Type.Object({}),
|
||||
execute: async () => {
|
||||
await toolRelease;
|
||||
return {
|
||||
content: [{ type: "text", text: "released" }],
|
||||
details: {},
|
||||
};
|
||||
},
|
||||
};
|
||||
const harness = await createHarness({
|
||||
tools: [waitTool],
|
||||
extensionFactories: [
|
||||
(pi) => {
|
||||
extensionApi = pi;
|
||||
pi.registerCommand("testcmd", {
|
||||
description: "Test command",
|
||||
handler: async (args) => {
|
||||
commandRuns.push(args);
|
||||
},
|
||||
});
|
||||
},
|
||||
],
|
||||
});
|
||||
harnesses.push(harness);
|
||||
|
||||
harness.setResponses([
|
||||
fauxAssistantMessage(fauxToolCall("wait", {}), { stopReason: "toolUse" }),
|
||||
fauxAssistantMessage("first turn complete"),
|
||||
fauxAssistantMessage("queued follow-up handled by model"),
|
||||
]);
|
||||
|
||||
const sawToolStart = new Promise<void>((resolve) => {
|
||||
const unsubscribe = harness.session.subscribe((event) => {
|
||||
if (event.type === "tool_execution_start" && event.toolName === "wait") {
|
||||
unsubscribe();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const promptPromise = harness.session.prompt("start");
|
||||
await sawToolStart;
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
extensionApi?.sendUserMessage("/testcmd queued", { deliverAs: "followUp" });
|
||||
releaseToolExecution?.();
|
||||
await promptPromise;
|
||||
|
||||
expect(commandRuns).toEqual([]);
|
||||
expect(getUserTexts(harness)).toEqual(["start", "/testcmd queued"]);
|
||||
expect(getAssistantTexts(harness)).toContain("queued follow-up handled by model");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user