Files
rea/scripts/verify-package-update.mjs
T
Cursor Agent 2f2110a8ba feat(clients): register Grok Build and Grok Bot during setup
Detect both clients and install the local REA MCP registration the same
way setup already handles the other agents. Grok Build edits only the
REA tables in its TOML config, sets startup_timeout_sec to 30, and
removes rea from disabled_mcp_servers. Grok Bot writes mcpServers.rea
into mcp.json. Setup does not call the account API.

Uninstall keeps comments in an inline table whose only server was REA.
2026-10-08 21:33:27 +00:00

183 lines
6.6 KiB
JavaScript

import { createHash } from "node:crypto";
import { createServer } from "node:http";
import { readFile, writeFile, mkdir } from "node:fs/promises";
import { dirname, join } from "node:path";
import { pathToFileURL } from "node:url";
import { exec, json } from "./lib/verify-package-core.mjs";
/** Exercise the packaged updater with real npm and a local release registry fixture. */
export async function verifyPackageUpdate({
prefix,
packageRoot,
tarball,
workspace,
environment,
}) {
const metadataPath = join(packageRoot, "package.json");
const metadata = json(await readFile(metadataPath, "utf8"));
const archive = await readFile(tarball);
const entry = join(packageRoot, "scripts", "rea.mjs");
const home = join(workspace, "update-home");
const codexPath = join(home, ".codex", "config.toml");
const originalConfig =
'[mcp_servers.rea]\ncommand = "npx"\nargs = ["-y", "rea-agents@0.0.0", "mcp"]\n';
await mkdir(dirname(codexPath), { recursive: true });
await writeFile(codexPath, originalConfig);
const server = createServer((request, response) => {
void serveRegistry(request, response).catch((error) => {
response.writeHead(500);
response.end(String(error));
});
});
let registry;
async function serveRegistry(request, response) {
const pathname = new URL(request.url, registry).pathname;
if (pathname === "/rea-agents") {
response.setHeader("Content-Type", "application/json");
response.end(
JSON.stringify({
name: metadata.name,
"dist-tags": { latest: metadata.version },
versions: {
[metadata.version]: {
...metadata,
dist: {
tarball: `${registry}/release.tgz`,
integrity: `sha512-${createHash("sha512").update(archive).digest("base64")}`,
},
},
},
}),
);
} else if (pathname === "/release.tgz") {
response.end(archive);
} else if (request.method === "POST") {
response.setHeader("Content-Type", "application/json");
response.end("{}");
} else {
const upstream = await fetch(`https://registry.npmjs.org${request.url}`);
response.writeHead(upstream.status, {
"Content-Type":
upstream.headers.get("content-type") ?? "application/octet-stream",
});
response.end(Buffer.from(await upstream.arrayBuffer()));
}
}
await new Promise((resolveListen, reject) => {
server.once("error", reject);
server.listen(0, "127.0.0.1", resolveListen);
});
try {
const address = server.address();
if (typeof address !== "object" || address === null)
throw new Error("Registry fixture did not bind");
registry = `http://127.0.0.1:${address.port}`;
// Model an older installed release's identity while retaining the new updater
// under test. The registry supplies the unmodified packed target artifact.
const generatedPath = join(
packageRoot,
"dist",
"generatedPackageMetadata.js",
);
const generated = await readFile(generatedPath, "utf8");
const previousVersion = "0.0.0";
const previousGenerated = generated.replace(
`version: "${metadata.version}"`,
`version: "${previousVersion}"`,
);
if (previousGenerated === generated)
throw new Error("Could not create previous-release identity fixture");
await writeFile(generatedPath, previousGenerated);
await writeFile(
metadataPath,
JSON.stringify({ ...metadata, version: previousVersion }),
);
const runtimeEnvironment = {
...environment,
HOME: home,
USERPROFILE: home,
APPDATA: join(home, "AppData", "Roaming"),
CLAUDE_CONFIG_DIR: home,
CODEX_HOME: join(home, ".codex"),
COPILOT_HOME: join(home, ".copilot"),
GROK_HOME: join(home, ".grok"),
SAND_DATA_ROOT: join(home, ".grokbot"),
XDG_CONFIG_HOME: join(home, ".config"),
OPENCODE_CONFIG: join(home, ".config", "opencode", "opencode.json"),
npm_config_prefix: prefix,
npm_config_registry: registry,
};
const previous = (
await exec(process.execPath, [entry, "--version"], {
env: runtimeEnvironment,
})
).stdout.trim();
if (previous !== previousVersion)
throw new Error(`Previous-release fixture reported ${previous}`);
const harness = join(workspace, "verify-update.mjs");
await writeFile(
harness,
`
import { runUpdate } from ${JSON.stringify(pathToFileURL(join(packageRoot, "dist/application/Update.js")).href)};
import { systemUpdateHost } from ${JSON.stringify(pathToFileURL(join(packageRoot, "dist/application/UpdateRuntime.js")).href)};
const host = systemUpdateHost(${JSON.stringify(packageRoot)}, ${JSON.stringify(home)});
const result = await runUpdate(${JSON.stringify(previousVersion)}, host, "structured");
process.stdout.write(JSON.stringify(result));
if (result.status === "failed") process.exitCode = 1;
`,
);
const result = json(
(
await exec(process.execPath, [harness], {
env: runtimeEnvironment,
maxBuffer: 16 * 1024 * 1024,
})
).stdout,
);
if (
result.status !== "updated" ||
result.installedVersion !== metadata.version ||
result.command.at(-1) !== `${metadata.name}@${metadata.version}` ||
result.maintenance.status !== "planned" ||
result.maintenance.scope.clients.join(",") !== "codex" ||
result.maintenance.scope.skill !== false
)
throw new Error(
`Packaged updater failed its exact-release contract: ${JSON.stringify(result)}`,
);
if ((await readFile(codexPath, "utf8")) !== originalConfig)
throw new Error(
"Update applied integration maintenance without approval",
);
const current = (
await exec(process.execPath, [entry, "--version"], {
env: runtimeEnvironment,
})
).stdout.trim();
if (current !== metadata.version)
throw new Error(`Updated executable reported ${current}`);
const help = (
await exec(process.execPath, [entry, "--help"], {
env: runtimeEnvironment,
})
).stdout;
if (!/^\s{2}update\s/mu.test(help) || /^\s{2}upgrade\s/mu.test(help))
throw new Error(
"Updated CLI did not expose update as its sole maintenance command",
);
return {
installed_version: result.installedVersion,
exact_release: true,
maintenance_read_only: true,
};
} finally {
server.closeAllConnections();
await new Promise((resolveClose, reject) =>
server.close((error) =>
error === undefined ? resolveClose() : reject(error),
),
);
}
}