|
1 | | -import type { ExtensionAPI, ToolDefinition } from "@mariozechner/pi-coding-agent"; |
2 | | -import { describe, expect, it, vi } from "vitest"; |
3 | | -import extension from "../src/index.js"; |
| 1 | +import type { |
| 2 | + BeforeAgentStartEvent, |
| 3 | + ExtensionAPI, |
| 4 | + ExtensionHandler, |
| 5 | + ToolDefinition, |
| 6 | +} from "@mariozechner/pi-coding-agent"; |
| 7 | +import { describe, expect, it } from "vitest"; |
| 8 | +import extension, { BASH_BG_SYSTEM_PROMPT_SECTION } from "../src/index.js"; |
| 9 | + |
| 10 | +type HandlerMap = Map<string, ExtensionHandler<never>[]>; |
| 11 | + |
| 12 | +function makeFakePi(): { pi: ExtensionAPI; handlers: HandlerMap; tools: ToolDefinition[] } { |
| 13 | + const handlers: HandlerMap = new Map(); |
| 14 | + const tools: ToolDefinition[] = []; |
| 15 | + const pi = { |
| 16 | + on(event: string, handler: ExtensionHandler<never>) { |
| 17 | + const list = handlers.get(event) ?? []; |
| 18 | + list.push(handler); |
| 19 | + handlers.set(event, list); |
| 20 | + }, |
| 21 | + registerTool(tool: ToolDefinition) { |
| 22 | + tools.push(tool); |
| 23 | + }, |
| 24 | + } as unknown as ExtensionAPI; |
| 25 | + return { pi, handlers, tools }; |
| 26 | +} |
4 | 27 |
|
5 | 28 | describe("pi-bash-bg extension", () => { |
6 | | - it("appends background job guidance to the bash tool description", () => { |
7 | | - const tools: ToolDefinition[] = []; |
8 | | - const pi = { |
9 | | - registerTool(tool) { |
10 | | - tools.push(tool); |
11 | | - }, |
12 | | - on: vi.fn(), |
13 | | - } as unknown as ExtensionAPI; |
| 29 | + it("does not re-register the bash tool (preserves pi's commandPrefix/shellPath/spawnHook)", () => { |
| 30 | + const { pi, tools } = makeFakePi(); |
| 31 | + extension(pi); |
| 32 | + expect(tools.find((tool) => tool.name === "bash")).toBeUndefined(); |
| 33 | + // The extension must not register any tool; it only hooks events. |
| 34 | + expect(tools).toHaveLength(0); |
| 35 | + }); |
| 36 | + |
| 37 | + it("registers tool_call and before_agent_start handlers", () => { |
| 38 | + const { pi, handlers } = makeFakePi(); |
| 39 | + extension(pi); |
| 40 | + expect(handlers.get("tool_call")?.length).toBe(1); |
| 41 | + expect(handlers.get("before_agent_start")?.length).toBe(1); |
| 42 | + }); |
14 | 43 |
|
| 44 | + it("appends background-job guidance to the system prompt", async () => { |
| 45 | + const { pi, handlers } = makeFakePi(); |
15 | 46 | extension(pi); |
| 47 | + const handler = handlers.get("before_agent_start")?.[0]; |
| 48 | + expect(handler).toBeDefined(); |
| 49 | + |
| 50 | + const event: BeforeAgentStartEvent = { |
| 51 | + type: "before_agent_start", |
| 52 | + prompt: "hello", |
| 53 | + systemPrompt: "You are a coding agent.", |
| 54 | + systemPromptOptions: {} as BeforeAgentStartEvent["systemPromptOptions"], |
| 55 | + }; |
| 56 | + const result = await (handler as (e: BeforeAgentStartEvent) => Promise<{ systemPrompt?: string } | undefined>)( |
| 57 | + event, |
| 58 | + ); |
16 | 59 |
|
17 | | - const bashTool = tools.find((tool) => tool.name === "bash"); |
18 | | - expect(bashTool).toBeDefined(); |
19 | | - expect(bashTool?.description).toContain("Background jobs continue running after the command returns."); |
20 | | - expect(bashTool?.description).toContain( |
21 | | - "Their output is captured to a log file even without explicit redirection.", |
| 60 | + expect(result?.systemPrompt).toBeDefined(); |
| 61 | + expect(result?.systemPrompt).toContain("You are a coding agent."); |
| 62 | + expect(result?.systemPrompt).toContain(BASH_BG_SYSTEM_PROMPT_SECTION); |
| 63 | + expect(result?.systemPrompt).toContain("Background jobs (`command &`)"); |
| 64 | + expect(result?.systemPrompt).toContain("[bg] pid="); |
| 65 | + }); |
| 66 | + |
| 67 | + it("does not duplicate the guidance if it is already present", async () => { |
| 68 | + const { pi, handlers } = makeFakePi(); |
| 69 | + extension(pi); |
| 70 | + const handler = handlers.get("before_agent_start")?.[0]; |
| 71 | + const event: BeforeAgentStartEvent = { |
| 72 | + type: "before_agent_start", |
| 73 | + prompt: "hello", |
| 74 | + systemPrompt: `You are a coding agent.\n\n${BASH_BG_SYSTEM_PROMPT_SECTION}`, |
| 75 | + systemPromptOptions: {} as BeforeAgentStartEvent["systemPromptOptions"], |
| 76 | + }; |
| 77 | + const result = await (handler as (e: BeforeAgentStartEvent) => Promise<{ systemPrompt?: string } | undefined>)( |
| 78 | + event, |
22 | 79 | ); |
23 | | - expect(bashTool?.description).toContain("The PID and log path will be returned."); |
| 80 | + expect(result).toBeUndefined(); |
24 | 81 | }); |
25 | 82 | }); |
0 commit comments