balladeer 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/balladeer.js +35 -10
- package/package.json +1 -1
package/bin/balladeer.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
const { createHash } = require("node:crypto");
|
|
13
13
|
const { existsSync, mkdtempSync, writeFileSync, rmSync } = require("node:fs");
|
|
14
14
|
const { tmpdir } = require("node:os");
|
|
15
|
-
const { join } = require("node:path");
|
|
15
|
+
const { join, sep } = require("node:path");
|
|
16
16
|
const { spawnSync } = require("node:child_process");
|
|
17
17
|
const readline = require("node:readline");
|
|
18
18
|
|
|
@@ -82,17 +82,34 @@ async function main() {
|
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
// Volta
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
// split-brain
|
|
89
|
-
//
|
|
90
|
-
|
|
85
|
+
// Volta, two traps (both hit live on a Volta machine): (1) it prepends its real-node bin dir
|
|
86
|
+
// to a child tool's PATH, so a bare `npm` here is the RAW npm that installs into the node
|
|
87
|
+
// image's globals — while the user's `balladeer` stays Volta's shim serving THIS bootstrapper
|
|
88
|
+
// (split-brain: every run is the installer again); (2) it stamps _VOLTA_TOOL_RECURSION into a
|
|
89
|
+
// shimmed tool's env, and the shim npm passes straight through to the raw npm when it sees it,
|
|
90
|
+
// so merely routing through $VOLTA_HOME/bin/npm changes nothing. Fix: spawn Volta's npm shim
|
|
91
|
+
// WITH the recursion guard scrubbed, so its global-install interception updates the package
|
|
92
|
+
// image the user's shim actually serves.
|
|
93
|
+
const childEnv = { ...process.env };
|
|
94
|
+
delete childEnv._VOLTA_TOOL_RECURSION;
|
|
95
|
+
// Volta detection cannot rely on env: inside a shimmed tool VOLTA_HOME is absent (the env
|
|
96
|
+
// carries only _VOLTA_TOOL_RECURSION). Our own node binary IS Volta's
|
|
97
|
+
// (<volta>/tools/image/node/<v>/bin/node), so derive the root from execPath, honoring
|
|
98
|
+
// VOLTA_HOME when it is set (custom install locations).
|
|
99
|
+
const voltaMarker = `${sep}.volta${sep}`;
|
|
100
|
+
const voltaRoot =
|
|
101
|
+
process.env.VOLTA_HOME ??
|
|
102
|
+
(process.execPath.includes(voltaMarker)
|
|
103
|
+
? process.execPath.slice(0, process.execPath.indexOf(voltaMarker) + voltaMarker.length - 1)
|
|
104
|
+
: null);
|
|
105
|
+
const voltaBin = voltaRoot ? join(voltaRoot, "bin") : null;
|
|
106
|
+
const voltaNpm = voltaBin ? join(voltaBin, "npm") : null;
|
|
91
107
|
const npmCmd = voltaNpm && existsSync(voltaNpm) ? voltaNpm : "npm";
|
|
92
108
|
// --ignore-scripts: the client has no install hooks, and this keeps a hostile tarball from
|
|
93
109
|
// running code at install time (the same flag the script installer passes).
|
|
94
110
|
const r = spawnSync(npmCmd, ["install", "-g", "--ignore-scripts", file], {
|
|
95
111
|
stdio: "inherit",
|
|
112
|
+
env: childEnv,
|
|
96
113
|
shell: process.platform === "win32",
|
|
97
114
|
});
|
|
98
115
|
try {
|
|
@@ -102,9 +119,17 @@ async function main() {
|
|
|
102
119
|
fail(`error: npm install -g failed (exit ${r.status ?? "?"}). Fix the npm error above and re-run \`balladeer\`.`, r.status ?? 1);
|
|
103
120
|
}
|
|
104
121
|
|
|
105
|
-
// Never report success on npm's exit code alone: prove the world changed
|
|
106
|
-
//
|
|
107
|
-
|
|
122
|
+
// Never report success on npm's exit code alone: prove the world changed — AS THE USER'S SHELL
|
|
123
|
+
// SEES IT. Probe the Volta shim by absolute path when Volta is present (this process's PATH has
|
|
124
|
+
// Volta's image dirs prepended, so a bare probe can hit a copy the user's shell never resolves),
|
|
125
|
+
// with the recursion guard scrubbed so the shim re-resolves instead of echoing this bootstrapper.
|
|
126
|
+
const voltaShim = voltaBin ? join(voltaBin, "balladeer") : null;
|
|
127
|
+
const probeCmd = voltaShim && existsSync(voltaShim) ? voltaShim : "balladeer";
|
|
128
|
+
const probe = spawnSync(probeCmd, ["--version"], {
|
|
129
|
+
encoding: "utf8",
|
|
130
|
+
env: childEnv,
|
|
131
|
+
shell: process.platform === "win32",
|
|
132
|
+
});
|
|
108
133
|
const probedVersion = (probe.stdout ?? "").trim();
|
|
109
134
|
if (probe.status !== 0 || !/^\d+\.\d+\.\d+/.test(probedVersion)) {
|
|
110
135
|
fail(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "balladeer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Installer for the Balladeer client (decision memory for engineering teams and their AI agents): downloads the sha256-verified client from get.balladeer.ai and installs it globally.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"homepage": "https://balladeer.ai",
|