fix: v2.5.2 — plugin bootstrap exports before it runs (v2.5.1 update crash)

v2.5.1's update died at "bootstrap" on every platform: boot.npmCommand is
not a function. Run as the entry, plugin-bootstrap.js calls bootstrap() →
plugin-open.js, which requires plugin-bootstrap back and got the module.exports
of that moment — {} — because it was assigned at the bottom, below the entry
block. plugin-open.js already exported first for the same reason.

- module.exports moved above the entry block in plugin-bootstrap.js
- A test checks both entry scripts assign module.exports before their entry
  block (it fails on v2.5.1's file); requiring the module, as the other tests
  do, never takes the entry path
This commit is contained in:
2026-10-06 19:17:52 +07:00
parent be75572977
commit f8acd5fc29
7 changed files with 53 additions and 32 deletions
+30 -26
View File
@@ -853,32 +853,10 @@ function main() {
child.unref();
}
if (require.main === module) {
const force = process.argv.includes("--force");
if (force || process.argv.includes("--worker")) {
// `--force` (from /agenthub-update) runs in the foreground so the user sees the
// npm output and the result.
const result = bootstrap(runtimeDir(), { force });
if (force) {
console.log(
result === "ok"
? "AgentHub runtime refreshed."
: result === "superseded"
? "A newer AgentHub plugin build is already installed — this one did nothing on purpose.\n" +
"Restart Claude Code so it loads the new build, then try again."
: `bootstrap: ${result}`
);
if (result !== "ok") process.exitCode = 1;
}
} else {
try {
main();
} catch {
// A bootstrap failure must never break a Claude Code session.
}
}
}
// Exported before the entry block below, not after it: `bootstrap()` requires
// plugin-open.js, which requires this module back (`npmCommand`, `runtimeDir`),
// and when this file is the entry that require resolves to whatever is on
// module.exports at that moment — an empty object if it is assigned last.
module.exports = {
MIN_NODE,
LOCK_STALE_MS,
@@ -911,3 +889,29 @@ module.exports = {
startDashboard,
bootstrap,
};
if (require.main === module) {
const force = process.argv.includes("--force");
if (force || process.argv.includes("--worker")) {
// `--force` (from /agenthub-update) runs in the foreground so the user sees the
// npm output and the result.
const result = bootstrap(runtimeDir(), { force });
if (force) {
console.log(
result === "ok"
? "AgentHub runtime refreshed."
: result === "superseded"
? "A newer AgentHub plugin build is already installed — this one did nothing on purpose.\n" +
"Restart Claude Code so it loads the new build, then try again."
: `bootstrap: ${result}`
);
if (result !== "ok") process.exitCode = 1;
}
} else {
try {
main();
} catch {
// A bootstrap failure must never break a Claude Code session.
}
}
}