import { describe, expect, it } from "vitest"; import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { execute } from "@paperclipai/adapter-pi-local/server"; async function writeFakePiCommand(commandPath: string): Promise { const script = `#!/usr/bin/env node if (process.argv.includes("--list-models")) { console.log("provider model"); console.log("google gemini-3-flash-preview"); process.exit(0); } console.log(JSON.stringify({ type: "agent_start" })); console.log(JSON.stringify({ type: "turn_start" })); console.log(JSON.stringify({ type: "turn_end", message: { role: "assistant", content: "" }, toolResults: [] })); console.log(JSON.stringify({ type: "agent_end", messages: [] })); console.log(JSON.stringify({ type: "auto_retry_end", success: false, attempt: 3, finalError: "Cloud Code Assist API error (429): RESOURCE_EXHAUSTED" })); process.exit(0); `; await fs.writeFile(commandPath, script, "utf8"); await fs.chmod(commandPath, 0o755); } describe("pi_local execute", () => { it("fails the run when Pi exhausts automatic retries despite exiting 0", async () => { const root = await fs.mkdtemp(path.join(os.tmpdir(), "paperclip-pi-execute-")); const workspace = path.join(root, "workspace"); const commandPath = path.join(root, "pi"); await fs.mkdir(workspace, { recursive: true }); await writeFakePiCommand(commandPath); const previousHome = process.env.HOME; process.env.HOME = root; try { const result = await execute({ runId: "run-pi-quota-exhausted", agent: { id: "agent-1", companyId: "company-1", name: "Pi Agent", adapterType: "pi_local", adapterConfig: {}, }, runtime: { sessionId: null, sessionParams: null, sessionDisplayId: null, taskKey: null, }, config: { command: commandPath, cwd: workspace, model: "google/gemini-3-flash-preview", promptTemplate: "Keep working.", }, context: {}, authToken: "run-jwt-token", onLog: async () => {}, }); expect(result.exitCode).toBe(1); expect(result.errorMessage).toContain("RESOURCE_EXHAUSTED"); } finally { if (previousHome === undefined) delete process.env.HOME; else process.env.HOME = previousHome; await fs.rm(root, { recursive: true, force: true }); } }); });