diff --git a/src/acp/translator.error-kind.test.ts b/src/acp/translator.error-kind.test.ts index 2f5bde7a98d..87e5cdf3a2d 100644 --- a/src/acp/translator.error-kind.test.ts +++ b/src/acp/translator.error-kind.test.ts @@ -1,88 +1,9 @@ -import type { PromptRequest } from "@agentclientprotocol/sdk"; -import { describe, expect, it, vi } from "vitest"; -import type { GatewayClient } from "../gateway/client.js"; -import type { EventFrame } from "../gateway/protocol/index.js"; -import { createInMemorySessionStore } from "./session.js"; -import { AcpGatewayAgent } from "./translator.js"; -import { createAcpConnection, createAcpGateway } from "./translator.test-helpers.js"; - -type PendingPromptHarness = { - agent: AcpGatewayAgent; - promptPromise: ReturnType; - runId: string; -}; - -const DEFAULT_SESSION_ID = "session-1"; -const DEFAULT_SESSION_KEY = "agent:main:main"; -const DEFAULT_PROMPT_TEXT = "hello"; - -function createSessionAgentHarness( - request: GatewayClient["request"], - options: { sessionId?: string; sessionKey?: string; cwd?: string } = {}, -) { - const sessionId = options.sessionId ?? DEFAULT_SESSION_ID; - const sessionKey = options.sessionKey ?? DEFAULT_SESSION_KEY; - const sessionStore = createInMemorySessionStore(); - sessionStore.createSession({ - sessionId, - sessionKey, - cwd: options.cwd ?? "/tmp", - }); - const agent = new AcpGatewayAgent(createAcpConnection(), createAcpGateway(request), { - sessionStore, - }); - - return { - agent, - sessionId, - sessionKey, - sessionStore, - }; -} - -function promptAgent( - agent: AcpGatewayAgent, - sessionId = DEFAULT_SESSION_ID, - text = DEFAULT_PROMPT_TEXT, -) { - return agent.prompt({ - sessionId, - prompt: [{ type: "text", text }], - _meta: {}, - } as unknown as PromptRequest); -} - -async function createPendingPromptHarness(): Promise { - let runId: string | undefined; - const request = vi.fn(async (method: string, params?: Record) => { - if (method === "chat.send") { - runId = params?.idempotencyKey as string | undefined; - return new Promise(() => {}); - } - return {}; - }) as GatewayClient["request"]; - - const { agent, sessionId } = createSessionAgentHarness(request); - const promptPromise = promptAgent(agent, sessionId); - - await vi.waitFor(() => { - expect(runId).toBeDefined(); - }); - - return { - agent, - promptPromise, - runId: runId!, - }; -} - -function createChatEvent(payload: Record): EventFrame { - return { - type: "event", - event: "chat", - payload, - } as EventFrame; -} +import { describe, expect, it } from "vitest"; +import { + createChatEvent, + createPendingPromptHarness, + DEFAULT_SESSION_KEY, +} from "./translator.prompt-harness.test-support.js"; describe("acp translator errorKind mapping", () => { it("maps errorKind: refusal to stopReason: refusal", async () => { diff --git a/src/acp/translator.prompt-harness.test-support.ts b/src/acp/translator.prompt-harness.test-support.ts new file mode 100644 index 00000000000..ef384c60e11 --- /dev/null +++ b/src/acp/translator.prompt-harness.test-support.ts @@ -0,0 +1,94 @@ +import type { PromptRequest } from "@agentclientprotocol/sdk"; +import { expect, vi } from "vitest"; +import type { GatewayClient } from "../gateway/client.js"; +import type { EventFrame } from "../gateway/protocol/index.js"; +import { createInMemorySessionStore } from "./session.js"; +import { AcpGatewayAgent } from "./translator.js"; +import { createAcpConnection, createAcpGateway } from "./translator.test-helpers.js"; + +export type PendingPromptHarness = { + agent: AcpGatewayAgent; + promptPromise: ReturnType; + runId: string; +}; + +export const DEFAULT_SESSION_ID = "session-1"; +export const DEFAULT_SESSION_KEY = "agent:main:main"; +export const DEFAULT_PROMPT_TEXT = "hello"; + +export function createSessionAgentHarness( + request: GatewayClient["request"], + options: { sessionId?: string; sessionKey?: string; cwd?: string } = {}, +) { + const sessionId = options.sessionId ?? DEFAULT_SESSION_ID; + const sessionKey = options.sessionKey ?? DEFAULT_SESSION_KEY; + const sessionStore = createInMemorySessionStore(); + sessionStore.createSession({ + sessionId, + sessionKey, + cwd: options.cwd ?? "/tmp", + }); + const agent = new AcpGatewayAgent(createAcpConnection(), createAcpGateway(request), { + sessionStore, + }); + + return { + agent, + sessionId, + sessionKey, + sessionStore, + }; +} + +export function promptAgent( + agent: AcpGatewayAgent, + sessionId = DEFAULT_SESSION_ID, + text = DEFAULT_PROMPT_TEXT, +) { + return agent.prompt({ + sessionId, + prompt: [{ type: "text", text }], + _meta: {}, + } as unknown as PromptRequest); +} + +export function observeSettlement(promise: ReturnType) { + const settleSpy = vi.fn(); + void promise.then( + (value) => settleSpy({ kind: "resolve", value }), + (error) => settleSpy({ kind: "reject", error }), + ); + return settleSpy; +} + +export async function createPendingPromptHarness(): Promise { + let runId: string | undefined; + const request = vi.fn(async (method: string, params?: Record) => { + if (method === "chat.send") { + runId = params?.idempotencyKey as string | undefined; + return new Promise(() => {}); + } + return {}; + }) as GatewayClient["request"]; + + const { agent, sessionId } = createSessionAgentHarness(request); + const promptPromise = promptAgent(agent, sessionId); + + await vi.waitFor(() => { + expect(runId).toBeDefined(); + }); + + return { + agent, + promptPromise, + runId: runId!, + }; +} + +export function createChatEvent(payload: Record): EventFrame { + return { + type: "event", + event: "chat", + payload, + } as EventFrame; +} diff --git a/src/acp/translator.stop-reason.test.ts b/src/acp/translator.stop-reason.test.ts index a30fbcd8a55..f110f23c06c 100644 --- a/src/acp/translator.stop-reason.test.ts +++ b/src/acp/translator.stop-reason.test.ts @@ -1,98 +1,17 @@ import type { PromptRequest } from "@agentclientprotocol/sdk"; import { describe, expect, it, vi } from "vitest"; import type { GatewayClient } from "../gateway/client.js"; -import type { EventFrame } from "../gateway/protocol/index.js"; import { createInMemorySessionStore } from "./session.js"; import { AcpGatewayAgent } from "./translator.js"; +import { + createChatEvent, + createPendingPromptHarness, + createSessionAgentHarness, + observeSettlement, + promptAgent, +} from "./translator.prompt-harness.test-support.js"; import { createAcpConnection, createAcpGateway } from "./translator.test-helpers.js"; -type PendingPromptHarness = { - agent: AcpGatewayAgent; - promptPromise: ReturnType; - runId: string; -}; - -const DEFAULT_SESSION_ID = "session-1"; -const DEFAULT_SESSION_KEY = "agent:main:main"; -const DEFAULT_PROMPT_TEXT = "hello"; - -function createSessionAgentHarness( - request: GatewayClient["request"], - options: { sessionId?: string; sessionKey?: string; cwd?: string } = {}, -) { - const sessionId = options.sessionId ?? DEFAULT_SESSION_ID; - const sessionKey = options.sessionKey ?? DEFAULT_SESSION_KEY; - const sessionStore = createInMemorySessionStore(); - sessionStore.createSession({ - sessionId, - sessionKey, - cwd: options.cwd ?? "/tmp", - }); - const agent = new AcpGatewayAgent(createAcpConnection(), createAcpGateway(request), { - sessionStore, - }); - - return { - agent, - sessionId, - sessionKey, - sessionStore, - }; -} - -function promptAgent( - agent: AcpGatewayAgent, - sessionId = DEFAULT_SESSION_ID, - text = DEFAULT_PROMPT_TEXT, -) { - return agent.prompt({ - sessionId, - prompt: [{ type: "text", text }], - _meta: {}, - } as unknown as PromptRequest); -} - -function observeSettlement(promise: ReturnType) { - const settleSpy = vi.fn(); - void promise.then( - (value) => settleSpy({ kind: "resolve", value }), - (error) => settleSpy({ kind: "reject", error }), - ); - return settleSpy; -} - -async function createPendingPromptHarness(): Promise { - let runId: string | undefined; - const request = vi.fn(async (method: string, params?: Record) => { - if (method === "chat.send") { - runId = params?.idempotencyKey as string | undefined; - return new Promise(() => {}); - } - return {}; - }) as GatewayClient["request"]; - - const { agent, sessionId } = createSessionAgentHarness(request); - const promptPromise = promptAgent(agent, sessionId); - - await vi.waitFor(() => { - expect(runId).toBeDefined(); - }); - - return { - agent, - promptPromise, - runId: runId!, - }; -} - -function createChatEvent(payload: Record): EventFrame { - return { - type: "event", - event: "chat", - payload, - } as EventFrame; -} - describe("acp translator stop reason mapping", () => { it("error state resolves as end_turn, not refusal", async () => { const { agent, promptPromise, runId } = await createPendingPromptHarness();