* fix(hopper): keep automated Linux setup off non-x86_64 hosts Every pinned Linux Hopper package (deb, rpm, Arch) is x86_64-only, but hopperSetupSupported was derived from os-release alone. Setup therefore planned and confirmed an amd64 package install on arm64 Ubuntu 24.04 and the other tested distributions. Classify installer support with the host architecture where the distribution is parsed, so setup planning, preflight, installation and package verification share one decision. Setup now takes its Linux distribution from the doctor host, as it already does for the macOS version, and the supported-host remediation text has a single owner. Fixes #3419 * fix(hopper): install Linux Hopper from the setup host's distribution facts systemLinuxHopperInstallHost read os-release with process.arch on its own, while setup planning used the doctor host's injected architecture. Both agree in production, but a doctor host composed with another architecture could plan one answer and install with another. The install host now takes its distribution reader from the caller, and systemSetupHost passes the doctor host's, so planning, preflight and installation share one host-fact owner. The unused default host on installLinuxHopper, the other ambient reader, is removed. * fix(verify-package): require Hopper readiness only where Linux setup installs it packageSetupSupport required doctor Hopper readiness on every Linux host whose host check passed, including installer-untested distributions and, after the architecture gate, arm64 hosts where setup never provides Hopper. On Linux, readiness now also requires automated installer applicability; macOS is unchanged. This narrows the readiness assertion from #2973 on hosts outside the installer matrix, such as Kali and ubuntu-24.04-arm. --------- Co-authored-by: DavidFB-creator <220631175+DavidFB-creator@users.noreply.github.com> Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
116 lines
4.2 KiB
JavaScript
116 lines
4.2 KiB
JavaScript
import { json, run, runWithStatus } from "./lib/verify-package-core.mjs";
|
|
|
|
const REQUIRED_HELP_COMMANDS = [
|
|
"setup",
|
|
"update",
|
|
"inspect-artifact",
|
|
"extract-artifact",
|
|
"import-reference-source",
|
|
"list-browser-targets",
|
|
"inspect-web-page",
|
|
"analyze-javascript-application",
|
|
"compare",
|
|
];
|
|
|
|
const REQUIRED_LLM_TOPICS = [
|
|
"decompile",
|
|
"function",
|
|
"search",
|
|
"inspect",
|
|
"xrefs",
|
|
"trace",
|
|
"capabilities",
|
|
"providers",
|
|
"inspect-artifact",
|
|
"list-browser-targets",
|
|
"inspect-web-page",
|
|
"analyze-javascript-application",
|
|
];
|
|
|
|
/**
|
|
* Derive agent setup support from the doctor node check and automated Hopper
|
|
* installer applicability from the facts their owners parse.
|
|
*
|
|
* Host readiness and installer applicability are different facts: a
|
|
* distribution REA supports can still be absent from the Hopper package's
|
|
* tested list, or run on an architecture the package lacks, so the doctor host
|
|
* check cannot answer the second question. On Linux, Hopper readiness is
|
|
* required only where the automated installer applies; elsewhere setup never
|
|
* provides Hopper. Applicability stays undefined when its owning fact is
|
|
* unavailable, which is distinct from a host known to lack an automated
|
|
* installer.
|
|
*/
|
|
export function packageSetupSupport(checks, host) {
|
|
const supportedSetupHost =
|
|
checks?.find(({ name }) => name === "node")?.ok === true;
|
|
const hostCheckOk = checks?.find(({ name }) => name === "host")?.ok;
|
|
const hopperSetupSupported = hopperInstallerSupported(host, hostCheckOk);
|
|
const hopperReadinessRequired =
|
|
host.platform !== "win32" &&
|
|
hostCheckOk === true &&
|
|
(host.platform !== "linux" || hopperSetupSupported === true);
|
|
return { supportedSetupHost, hopperReadinessRequired, hopperSetupSupported };
|
|
}
|
|
|
|
/**
|
|
* Whether `rea setup --install-hopper` can install Hopper automatically here.
|
|
* On macOS the doctor host check already is the owner's installer predicate
|
|
* (macOS 12 or later); on Linux it reports REA host support instead, so the
|
|
* distribution's own parsed applicability governs.
|
|
*/
|
|
function hopperInstallerSupported(host, hostCheckOk) {
|
|
if (host.platform === "win32") return false;
|
|
if (host.platform === "linux")
|
|
return host.linuxDistribution?.hopperSetupSupported;
|
|
return hostCheckOk;
|
|
}
|
|
|
|
/**
|
|
* The distribution facts the Hopper installer owner parses, taken from the
|
|
* built application so the verifier follows the predicate the package ships.
|
|
* Loaded only where a distribution can exist, which also keeps the derivation
|
|
* above testable without a build.
|
|
*/
|
|
async function readHostLinuxDistribution() {
|
|
if (process.platform !== "linux") return undefined;
|
|
const { readLinuxDistribution } =
|
|
await import("../dist/application/LinuxHopper.js");
|
|
return readLinuxDistribution(process.arch);
|
|
}
|
|
|
|
/** Validate --help, --llms, and doctor output and determine host setup support. */
|
|
export async function verifyPackageDiscovery({ cli, environment }) {
|
|
const help = await run(cli, ["--help"], environment);
|
|
const llms = await run(cli, ["--llms"], environment);
|
|
const doctorExecution = await runWithStatus(
|
|
cli,
|
|
["doctor", "--json"],
|
|
environment,
|
|
);
|
|
const doctor = json(doctorExecution.stdout);
|
|
const { supportedSetupHost, hopperReadinessRequired, hopperSetupSupported } =
|
|
packageSetupSupport(doctor.checks, {
|
|
platform: process.platform,
|
|
linuxDistribution: await readHostLinuxDistribution(),
|
|
});
|
|
const hopperReady = doctor.checks?.find(({ name }) => name === "hopper")?.ok;
|
|
const expectedDoctorHealth = doctor.checks?.every(({ ok }) => ok) === true;
|
|
const missingHelp = REQUIRED_HELP_COMMANDS.filter(
|
|
(command) => !help.includes(command),
|
|
);
|
|
const missingLlms = REQUIRED_LLM_TOPICS.filter(
|
|
(topic) => !llms.includes(topic),
|
|
);
|
|
if (
|
|
missingHelp.length !== 0 ||
|
|
missingLlms.length !== 0 ||
|
|
doctor.healthy !== expectedDoctorHealth ||
|
|
doctorExecution.status !== (expectedDoctorHealth ? 0 : 1) ||
|
|
(hopperReadinessRequired && hopperReady !== true)
|
|
)
|
|
throw new Error(
|
|
`packaged CLI discovery or doctor failed: ${JSON.stringify({ helpSetup: help.includes("setup"), llmsDecompile: llms.includes("decompile"), doctor })}`,
|
|
);
|
|
return { supportedSetupHost, hopperSetupSupported };
|
|
}
|