diff --git a/src/agents/btw.test.ts b/src/agents/btw.test.ts index c504f8895a37..1388a0e7cb96 100644 --- a/src/agents/btw.test.ts +++ b/src/agents/btw.test.ts @@ -44,6 +44,7 @@ const diagDebugMock = vi.fn(); const ensureSelectedAgentHarnessPluginMock = vi.fn(); const createAgentHarnessHostCapabilitiesMock = vi.fn(); const loadTranscriptEventsMock = vi.fn(); +const builtInOpenClawHarnesses = new WeakSet(); const shouldPreferExplicitConfigApiKeyAuthMock = vi.fn((..._args: unknown[]) => false); const hasUsableCustomProviderApiKeyMock = vi.fn((..._args: unknown[]) => false); const resolveProviderEntryApiKeyProfileReferenceMock = vi.fn((_params?: unknown): unknown => ({ @@ -204,17 +205,27 @@ vi.mock("./harness/runtime-plugin.js", () => ({ ensureSelectedAgentHarnessPluginMock(...args), })); -vi.mock("./harness/host-capability.js", async () => { - const actual = await vi.importActual( - "./harness/host-capability.js", - ); +// Selection and host-capability owner suites execute the embedded runner and capability surface. +// BTW only needs their identities while it verifies side-question orchestration. +vi.mock("./harness/builtin-openclaw.js", () => ({ + createOpenClawAgentHarness: (): AgentHarness => { + const harness: AgentHarness = { + id: "openclaw", + label: "OpenClaw embedded agent", + supports: () => ({ supported: true, priority: 0 }), + runAttempt: vi.fn(), + }; + builtInOpenClawHarnesses.add(harness); + return harness; + }, + isBuiltInOpenClawAgentHarness: (harness: AgentHarness) => builtInOpenClawHarnesses.has(harness), +})); + +vi.mock("./harness/host-capability.js", () => { return { - ...actual, - createAgentHarnessHostCapabilities: ( - params: Parameters[0], - ) => { + createAgentHarnessHostCapabilities: (params: unknown) => { createAgentHarnessHostCapabilitiesMock(params); - return actual.createAgentHarnessHostCapabilities(params); + return { capabilities: {}, close: vi.fn() }; }, }; }); @@ -303,15 +314,9 @@ vi.mock("../logging/diagnostic.js", () => ({ }, })); -vi.mock("../config/sessions/session-accessor.js", async () => { - const actual = await vi.importActual( - "../config/sessions/session-accessor.js", - ); - return { - ...actual, - loadTranscriptEvents: (...args: unknown[]) => loadTranscriptEventsMock(...args), - }; -}); +vi.mock("../config/sessions/session-accessor.js", () => ({ + loadTranscriptEvents: (...args: unknown[]) => loadTranscriptEventsMock(...args), +})); const { runBtwSideQuestion } = await import("./btw.js"); const { clearAgentHarnesses, registerAgentHarness } = await import("./harness/registry.js"); @@ -1407,34 +1412,6 @@ describe("runBtwSideQuestion", () => { expect(mockArg(codexSideQuestionMock, 0, 0)).toMatchObject({ toolsAllow: [] }); }); - it("prepares a narrow global policy before calling a plugin side-question hook", async () => { - const codexSideQuestionMock = registerCodexSideQuestionHarness(); - mockOpenAIPlatformProfile(); - resolveModelWithRegistryMock.mockReturnValue({ - provider: "openai", - id: "gpt-5.5", - api: "openai-responses", - }); - resolveModelAsyncMock.mockResolvedValue({ - model: { - provider: "openai", - id: "gpt-5.5", - api: "openai-responses", - baseUrl: "https://api.openai.com/v1", - }, - }); - - await runSideQuestion({ - cfg: { tools: { allow: ["message"] } } as never, - provider: "openai", - model: "gpt-5.5", - sessionKey: DEFAULT_SESSION_KEY, - }); - - expect(codexSideQuestionMock).toHaveBeenCalledOnce(); - expect(mockArg(codexSideQuestionMock, 0, 0)).toMatchObject({ toolsAllow: [] }); - }); - it("does not fall back to the direct provider call when Codex lacks BTW support", async () => { registerAgentHarness({ id: "codex",