balladeer 0.0.3 → 0.0.4

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.
Files changed (2) hide show
  1. package/bin/balladeer.js +23 -3
  2. package/package.json +1 -1
package/bin/balladeer.js CHANGED
@@ -10,7 +10,7 @@
10
10
  * Flags: --yes/-y skip the prompt; --download-only fetch + verify, print the path.
11
11
  */
12
12
  const { createHash } = require("node:crypto");
13
- const { mkdtempSync, writeFileSync, rmSync } = require("node:fs");
13
+ const { existsSync, mkdtempSync, writeFileSync, rmSync } = require("node:fs");
14
14
  const { tmpdir } = require("node:os");
15
15
  const { join } = require("node:path");
16
16
  const { spawnSync } = require("node:child_process");
@@ -82,9 +82,16 @@ async function main() {
82
82
  return;
83
83
  }
84
84
 
85
+ // Volta prepends its real-node bin dir to a child tool's PATH, so a bare `npm` spawned from
86
+ // here resolves to the RAW npm inside the node image and installs into that image's globals,
87
+ // while the `balladeer` on the user's PATH stays Volta's shim serving THIS bootstrapper — a
88
+ // split-brain where every run is the installer again. Route the install through Volta's own
89
+ // npm shim so its interception updates the package image the shim actually serves.
90
+ const voltaNpm = process.env.VOLTA_HOME ? join(process.env.VOLTA_HOME, "bin", "npm") : null;
91
+ const npmCmd = voltaNpm && existsSync(voltaNpm) ? voltaNpm : "npm";
85
92
  // --ignore-scripts: the client has no install hooks, and this keeps a hostile tarball from
86
93
  // running code at install time (the same flag the script installer passes).
87
- const r = spawnSync("npm", ["install", "-g", "--ignore-scripts", file], {
94
+ const r = spawnSync(npmCmd, ["install", "-g", "--ignore-scripts", file], {
88
95
  stdio: "inherit",
89
96
  shell: process.platform === "win32",
90
97
  });
@@ -95,6 +102,19 @@ async function main() {
95
102
  fail(`error: npm install -g failed (exit ${r.status ?? "?"}). Fix the npm error above and re-run \`balladeer\`.`, r.status ?? 1);
96
103
  }
97
104
 
105
+ // Never report success on npm's exit code alone: prove the world changed. If `balladeer` still
106
+ // resolves to this installer (or to nothing), say so honestly instead of claiming victory.
107
+ const probe = spawnSync("balladeer", ["--version"], { encoding: "utf8", shell: process.platform === "win32" });
108
+ const probedVersion = (probe.stdout ?? "").trim();
109
+ if (probe.status !== 0 || !/^\d+\.\d+\.\d+/.test(probedVersion)) {
110
+ fail(
111
+ `error: npm reported success, but \`balladeer\` on your PATH is not the client yet.\n` +
112
+ `Your npm setup may install globals somewhere this shell does not look, or a version\n` +
113
+ `manager may be serving a stale copy. Try a fresh shell and \`balladeer --version\`,\n` +
114
+ `or use the script installer:\n\n curl -fsSL ${BASE} | sh\n`,
115
+ );
116
+ }
117
+
98
118
  // Plain `balladeer login` (the client defaults to hosted central). BASE is the INSTALL host
99
119
  // (get.balladeer.ai), an alias that exists only for downloading — teaching it as --server
100
120
  // would store it as the machine's permanent server URL. A custom BALLADEER_INSTALL_BASE
@@ -105,7 +125,7 @@ async function main() {
105
125
  ? "balladeer login"
106
126
  : "balladeer login --server <your central server URL>";
107
127
  console.error(
108
- `\n✓ Balladeer client installed.\n\n` +
128
+ `\n✓ Balladeer client installed (${probedVersion}).\n\n` +
109
129
  ` next ${pairHint} # approve in your browser; no token to copy\n` +
110
130
  ` then your coding agent gains get_context / consult / propose_decision\n` +
111
131
  ` agent or let your agent finish the wiring: paste into it -> Read ${BASE}/agent and follow it.\n\n` +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "balladeer",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
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",