diff --git a/src/agents/pi-embedded-runner.test.ts b/src/agents/pi-embedded-runner.test.ts index 4ed2e5e6f..342fff1c2 100644 --- a/src/agents/pi-embedded-runner.test.ts +++ b/src/agents/pi-embedded-runner.test.ts @@ -5,16 +5,6 @@ import "./test-helpers/fast-coding-tools.js"; import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../config/config.js"; -type PiAiMockState = { - lastModel: { provider?: string; id?: string; compat?: unknown } | null; -}; - -const piAiMockState = vi.hoisted( - (): PiAiMockState => ({ - lastModel: null, - }), -); - function createMockUsage(input: number, output: number) { return { input, @@ -33,28 +23,9 @@ function createMockUsage(input: number, output: number) { } vi.mock("@mariozechner/pi-coding-agent", async () => { - const actual = await vi.importActual( + return await vi.importActual( "@mariozechner/pi-coding-agent", ); - - return { - ...actual, - createAgentSession: async ( - ...args: Parameters - ): ReturnType => { - const result = await actual.createAgentSession(...args); - const modelId = (args[0] as { model?: { id?: string } } | undefined)?.model?.id; - if (modelId === "mock-throw") { - const session = result.session as { prompt?: (...params: unknown[]) => Promise }; - if (session && typeof session.prompt === "function") { - session.prompt = async () => { - throw new Error("transport failed"); - }; - } - } - return result; - }, - }; }); vi.mock("@mariozechner/pi-ai", async () => { @@ -98,7 +69,6 @@ vi.mock("@mariozechner/pi-ai", async () => { return buildAssistantMessage(model); }, streamSimple: (model: { api: string; provider: string; id: string }) => { - piAiMockState.lastModel = model as { provider?: string; id?: string; compat?: unknown }; const stream = actual.createAssistantMessageEventStream(); queueMicrotask(() => { stream.push({ @@ -244,112 +214,32 @@ const runDefaultEmbeddedTurn = async (sessionFile: string, prompt: string, sessi }); }; -const makeMoonshotConfig = (modelIds: string[]) => - ({ - models: { - providers: { - moonshot: { - api: "openai-completions", - apiKey: "sk-test", - baseUrl: "https://api.moonshot.ai/v1", - models: modelIds.map((id) => ({ - id, - name: `Moonshot ${id}`, - reasoning: false, - input: ["text", "image"], - cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, - contextWindow: 256_000, - maxTokens: 8_192, - })), - }, - }, - }, - }) satisfies OpenClawConfig; - describe("runEmbeddedPiAgent", () => { - it("normalizes moonshot models to disable developer-role payloads in runner calls", async () => { - piAiMockState.lastModel = null; + it("handles prompt error paths without dropping user state", async () => { const sessionFile = nextSessionFile(); + const cfg = makeOpenAiConfig(["mock-error"]); const sessionKey = nextSessionKey(); - const cfg = makeMoonshotConfig(["kimi-k2.5"]); - - await runEmbeddedPiAgent({ + const result = await runEmbeddedPiAgent({ sessionId: "session:test", sessionKey, sessionFile, workspaceDir, config: cfg, - prompt: "reply with ok", - provider: "moonshot", - model: "kimi-k2.5", + prompt: "boom", + provider: "openai", + model: "mock-error", timeoutMs: 5_000, agentDir, - runId: nextRunId("moonshot-compat"), + runId: nextRunId("prompt-error"), enqueue: immediateEnqueue, }); + expect(result.payloads?.[0]?.isError).toBe(true); - const capturedModel = piAiMockState.lastModel as { - provider?: string; - id?: string; - compat?: unknown; - } | null; - expect(capturedModel?.provider).toBe("moonshot"); - expect(capturedModel?.id).toBe("kimi-k2.5"); - expect( - (capturedModel?.compat as { supportsDeveloperRole?: boolean } | undefined) - ?.supportsDeveloperRole, - ).toBe(false); - }); - - it("handles prompt error paths without dropping user state", async () => { - for (const testCase of [ - { - label: "assistant error response keeps user message", - model: "mock-error", - prompt: "boom", - runIdPrefix: "prompt-error", - expectReject: false, - }, - { - label: "transport error fails fast before writing transcript", - model: "mock-throw", - prompt: "transport error", - runIdPrefix: "transport-error", - expectReject: true, - }, - ] as const) { - const sessionFile = nextSessionFile(); - const cfg = makeOpenAiConfig([testCase.model]); - const sessionKey = nextSessionKey(); - const execution = runEmbeddedPiAgent({ - sessionId: "session:test", - sessionKey, - sessionFile, - workspaceDir, - config: cfg, - prompt: testCase.prompt, - provider: "openai", - model: testCase.model, - timeoutMs: 5_000, - agentDir, - runId: nextRunId(testCase.runIdPrefix), - enqueue: immediateEnqueue, - }); - - if (testCase.expectReject) { - await expect(execution, testCase.label).rejects.toThrow("transport failed"); - await expect(fs.stat(sessionFile), testCase.label).rejects.toBeTruthy(); - } else { - const result = await execution; - expect(result.payloads?.[0]?.isError, testCase.label).toBe(true); - - const messages = await readSessionMessages(sessionFile); - const userIndex = messages.findIndex( - (message) => message?.role === "user" && textFromContent(message.content) === "boom", - ); - expect(userIndex, testCase.label).toBeGreaterThanOrEqual(0); - } - } + const messages = await readSessionMessages(sessionFile); + const userIndex = messages.findIndex( + (message) => message?.role === "user" && textFromContent(message.content) === "boom", + ); + expect(userIndex).toBeGreaterThanOrEqual(0); }); it(