Files
reverse-engineering-anything/tests/fixtures/buildComputerMcp.ts
T
morluto 4082375e73 fix(verifiers): preserve results and own cleanup through completion
Attempt independent resource cleanup without losing primary failures, retain unresolved owners, and publish completion after release. Bound existing producer commands, preserve helper return values, and settle startup and fixture children on failure.

Validation: 29 focused boundary tests passed; actual helper-value and import-bound filesystem cleanup controls passed. The real inert-child termination control and targeted JavaScript binding checks passed, alongside typecheck, lint and formatting. Live Ghidra, Cutter, Electron GUI and Windows addon qualification was not run.
2026-11-10 17:03:59 -05:00

129 lines
4.6 KiB
TypeScript

import type { BuildComputerDefaults } from "../../src/desktop/BuildComputerEnvironment.js";
import { closeVerifierResources } from "../../scripts/lib/verifier-cleanup.mjs";
import { mkdir, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { Client, InMemoryTransport } from "@modelcontextprotocol/client";
import type { CallToolResult } from "@modelcontextprotocol/server";
import { expect, onTestFinished } from "vitest";
import type { BuildSettle } from "../../src/application/desktop/DesktopBuildSettle.js";
import { toolContract } from "../../src/contracts/toolContracts.js";
import type { SettleTiming } from "../../src/domain/desktop/appSettle.js";
import { createServer } from "../../src/server/createServer.js";
import { createTestBinarySession } from "./binarySession.js";
import {
fakeAgentEnvRunner,
isolatedBuildDefaults,
startFakeComputer,
type FakeAgentEnvRunner,
type FakeComputer,
type FakeComputerOptions,
} from "./fakeAgentEnvComputer.js";
import { createTestTempDirectory } from "./temporaryDirectory.js";
/** The host's environment without the settings the opt-in real test exports, which would reach past the fakes. */
const hostEnvironment = Object.fromEntries(
Object.entries(process.env).filter(
([name]) =>
![
"REA_AGENT_ENV_COMMAND",
"REA_DOCKER_COMMAND",
"REA_BUILD_COMPUTER_REA_ARCHIVE",
].includes(name),
),
);
/** A check grades its first read, for tests whose app changes nothing while it is checked. */
export const FIRST_READ: SettleTiming = {
intervalMs: 0,
windowMs: 0,
boundMs: 0,
};
/** An MCP client of a REA server whose build computers reach the fakes through `environment` and read apps with `settle`. */
export const connectBuildServer = async (
environment: Readonly<Record<string, string>>,
settle: BuildSettle = FIRST_READ,
defaults?: BuildComputerDefaults,
): Promise<Client> => {
const session = createTestBinarySession(() => {
throw new Error("build computers must not start a deep provider");
});
const server = createServer(
{ kind: "session", session },
{
environment: {
...hostEnvironment,
REA_MCP_INPUT_SCHEMA_PROFILE: "full",
...environment,
},
desktopBuildSettle: settle,
desktopBuildDefaults: defaults ?? (await isolatedBuildDefaults()),
},
);
const client = new Client({ name: "build-computer-mcp", version: "1" });
onTestFinished(async () => {
await closeVerifierResources([
() => client.close(),
() => server.close(),
async () => {
const closed = await session.close();
if (!closed.ok) throw closed.error;
},
]);
});
const [clientTransport, serverTransport] =
InMemoryTransport.createLinkedPair();
await server.connect(serverTransport);
await client.connect(clientTransport);
return client;
};
/** A fake computer and the fake runner that hands it out. */
export const buildComputerFakes = async (
options: FakeComputerOptions = {},
): Promise<{ computer: FakeComputer; runner: FakeAgentEnvRunner }> => {
const computer = await startFakeComputer(options);
onTestFinished(() => computer.close());
const runner = await fakeAgentEnvRunner(computer);
return { computer, runner };
};
/** An exported bundle's folder as far as the fake runner reads it; given a fake computer, the runner hands that one out for it. */
export const bundleFolder = async (
computer?: Pick<FakeComputer, "url">,
): Promise<string> => {
const bundle = await createTestTempDirectory("exported-bundle-");
await mkdir(join(bundle, "tasks"));
await writeFile(join(bundle, "tasks", "smoke.json"), "[]\n");
if (computer !== undefined)
await writeFile(join(bundle, "fake-computer-url"), computer.url);
return bundle;
};
/** Call a tool and fail the test with its result when it is an error. */
export const callOk = async (
client: Client,
name: string,
args: Record<string, unknown>,
): Promise<CallToolResult> => {
const result = await client.callTool({ name, arguments: args });
expect(result.isError, JSON.stringify(result)).not.toBe(true);
return result as CallToolResult;
};
/** Start a build computer and return its id. */
export const startBuildComputer = async (
client: Client,
source: Record<string, unknown>,
): Promise<string> =>
toolContract("start_build_computer").outputSchema.parse(
(await callOk(client, "start_build_computer", { source }))
.structuredContent,
).computer_id;
/** No delivered text, success or failure, may hold the control token. */
export const expectNoToken = (computer: FakeComputer, result: unknown) =>
expect(JSON.stringify(result)).not.toContain(computer.token);