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:
@@ -7233,7 +7233,7 @@ exports[`screen snapshots > Settings — about 1`] = `
|
|||||||
<p
|
<p
|
||||||
class="text-[10px] text-status-warning/90 mt-1"
|
class="text-[10px] text-status-warning/90 mt-1"
|
||||||
>
|
>
|
||||||
UI build v2.5.1 (rebuild client to match)
|
UI build v2.5.2 (rebuild client to match)
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
openapi: 3.0.3
|
openapi: 3.0.3
|
||||||
info:
|
info:
|
||||||
title: Agent Dashboard for Claude Code API
|
title: Agent Dashboard for Claude Code API
|
||||||
version: 2.5.1
|
version: 2.5.2
|
||||||
description: HTTP API for real-time Claude Code session monitoring, agent lifecycle tracking, analytics, pricing, hooks ingestion, and workflow intelligence.
|
description: HTTP API for real-time Claude Code session monitoring, agent lifecycle tracking, analytics, pricing, hooks ingestion, and workflow intelligence.
|
||||||
contact:
|
contact:
|
||||||
name: Nguyễn Ngọc Trí Vĩ
|
name: Nguyễn Ngọc Trí Vĩ
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "agenthub",
|
"name": "agenthub",
|
||||||
"version": "2.5.1",
|
"version": "2.5.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "agenthub",
|
"name": "agenthub",
|
||||||
"version": "2.5.1",
|
"version": "2.5.2",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "agenthub",
|
"name": "agenthub",
|
||||||
"version": "2.5.1",
|
"version": "2.5.2",
|
||||||
"bin": {
|
"bin": {
|
||||||
"agenthub": "bin/agenthub.js"
|
"agenthub": "bin/agenthub.js"
|
||||||
},
|
},
|
||||||
|
|||||||
+30
-26
@@ -853,32 +853,10 @@ function main() {
|
|||||||
child.unref();
|
child.unref();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (require.main === module) {
|
// Exported before the entry block below, not after it: `bootstrap()` requires
|
||||||
const force = process.argv.includes("--force");
|
// plugin-open.js, which requires this module back (`npmCommand`, `runtimeDir`),
|
||||||
if (force || process.argv.includes("--worker")) {
|
// and when this file is the entry that require resolves to whatever is on
|
||||||
// `--force` (from /agenthub-update) runs in the foreground so the user sees the
|
// module.exports at that moment — an empty object if it is assigned last.
|
||||||
// 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.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
MIN_NODE,
|
MIN_NODE,
|
||||||
LOCK_STALE_MS,
|
LOCK_STALE_MS,
|
||||||
@@ -911,3 +889,29 @@ module.exports = {
|
|||||||
startDashboard,
|
startDashboard,
|
||||||
bootstrap,
|
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.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -693,3 +693,20 @@ describe("npmCommand", () => {
|
|||||||
assert.deepEqual(npm.args, ["-v"]);
|
assert.deepEqual(npm.args, ["-v"]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("entry scripts export before they run", () => {
|
||||||
|
// plugin-bootstrap.js run as the entry calls bootstrap() → plugin-open.js,
|
||||||
|
// which requires plugin-bootstrap back and gets whatever module.exports holds
|
||||||
|
// at that moment. Assigned after the entry block it was still {}, and v2.5.1's
|
||||||
|
// update died with "boot.npmCommand is not a function". Requiring the module
|
||||||
|
// (as every other test here does) never takes that path, hence this check.
|
||||||
|
for (const file of ["plugin-bootstrap.js", "plugin-open.js"]) {
|
||||||
|
it(file, () => {
|
||||||
|
const src = fs.readFileSync(path.join(__dirname, "..", "..", "scripts", file), "utf8");
|
||||||
|
const exportsAt = src.indexOf("\nmodule.exports = {");
|
||||||
|
const entryAt = src.indexOf("\nif (require.main === module)");
|
||||||
|
assert.ok(exportsAt > 0 && entryAt > 0, "both markers present");
|
||||||
|
assert.ok(exportsAt < entryAt, "module.exports must be assigned before the entry block");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user