balladeer 1.0.5 → 1.0.6
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/dist/cli.js +0 -0
- package/dist/install.js +102 -12
- package/dist/wire.d.ts +2 -2
- package/dist/wire.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
File without changes
|
package/dist/install.js
CHANGED
|
@@ -23,9 +23,10 @@ function commandOnPath(name, env) {
|
|
|
23
23
|
}
|
|
24
24
|
return undefined;
|
|
25
25
|
}
|
|
26
|
-
function execute(command, args, env) {
|
|
26
|
+
function execute(command, args, env, cwd) {
|
|
27
27
|
return execFileSync(command, args, {
|
|
28
28
|
env,
|
|
29
|
+
...(cwd ? { cwd } : {}),
|
|
29
30
|
encoding: "utf8",
|
|
30
31
|
stdio: ["ignore", "pipe", "pipe"],
|
|
31
32
|
timeout: 120_000,
|
|
@@ -33,14 +34,14 @@ function execute(command, args, env) {
|
|
|
33
34
|
}).trim();
|
|
34
35
|
}
|
|
35
36
|
/** Inspect package ownership before executing a command from PATH. */
|
|
36
|
-
function packageVersion(command, env) {
|
|
37
|
+
function packageVersion(command, env, cwd) {
|
|
37
38
|
let entry = realpathSync(command);
|
|
38
39
|
if (basename(entry) === "volta-shim") {
|
|
39
40
|
const volta = commandOnPath("volta", env);
|
|
40
41
|
if (!volta)
|
|
41
42
|
return undefined;
|
|
42
43
|
try {
|
|
43
|
-
entry = realpathSync(execute(volta, ["which", "balladeer"], env));
|
|
44
|
+
entry = realpathSync(execute(volta, ["which", "balladeer"], env, cwd));
|
|
44
45
|
}
|
|
45
46
|
catch {
|
|
46
47
|
return undefined;
|
|
@@ -121,25 +122,114 @@ function shellProfiles(env, bin) {
|
|
|
121
122
|
return { path, text, previous: old };
|
|
122
123
|
});
|
|
123
124
|
}
|
|
125
|
+
function atLeastCurrent(version) {
|
|
126
|
+
if (!/^\d+\.\d+\.\d+$/.test(version))
|
|
127
|
+
return false;
|
|
128
|
+
const actual = version.split(".").map(Number), expected = CLI_VERSION.split(".").map(Number);
|
|
129
|
+
for (let i = 0; i < 3; i++) {
|
|
130
|
+
if (actual[i] !== expected[i])
|
|
131
|
+
return actual[i] > expected[i];
|
|
132
|
+
}
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
/** npm exec may put the actual Node-image bin ahead of Volta's registered shim. */
|
|
136
|
+
function installWithVolta(env) {
|
|
137
|
+
const home = env.VOLTA_HOME ?? (env.HOME ? join(env.HOME, ".volta") : undefined);
|
|
138
|
+
const volta = commandOnPath("volta", env);
|
|
139
|
+
if (!home || !isAbsolute(home) || !volta)
|
|
140
|
+
return undefined;
|
|
141
|
+
const bin = join(home, "bin"), shim = join(bin, "balladeer");
|
|
142
|
+
const nodeShim = join(bin, "node");
|
|
143
|
+
// Merely having Volta somewhere on PATH must not select it for another toolchain.
|
|
144
|
+
const onPath = (env.PATH ?? "")
|
|
145
|
+
.split(delimiter)
|
|
146
|
+
.some((part) => resolve(part || ".") === resolve(bin));
|
|
147
|
+
const managedNode = existsSync(nodeShim) && basename(realpathSync(nodeShim)) === "volta-shim";
|
|
148
|
+
const imageDirectory = join(home, "tools/image/node");
|
|
149
|
+
const imageRoot = existsSync(imageDirectory)
|
|
150
|
+
? realpathSync(imageDirectory)
|
|
151
|
+
: resolve(imageDirectory);
|
|
152
|
+
const selectedNode = commandOnPath("node", env);
|
|
153
|
+
const actualNode = selectedNode ? realpathSync(selectedNode) : undefined;
|
|
154
|
+
const activeToolchain = actualNode !== undefined &&
|
|
155
|
+
((managedNode && actualNode === realpathSync(nodeShim)) ||
|
|
156
|
+
actualNode.startsWith(imageRoot + "/"));
|
|
157
|
+
if (!onPath || !managedNode || !activeToolchain)
|
|
158
|
+
return undefined;
|
|
159
|
+
const bootstrap = env.npm_command === "exec";
|
|
160
|
+
const parentEnv = {
|
|
161
|
+
...env,
|
|
162
|
+
PATH: (env.PATH ?? "")
|
|
163
|
+
.split(delimiter)
|
|
164
|
+
.filter((part) => {
|
|
165
|
+
const full = resolve(part || ".");
|
|
166
|
+
if (full.split(/[\\/]/).includes("node_modules"))
|
|
167
|
+
return false;
|
|
168
|
+
return !(bootstrap &&
|
|
169
|
+
(existsSync(full) ? realpathSync(full) : full).startsWith(imageRoot + "/") &&
|
|
170
|
+
basename(full) === "bin");
|
|
171
|
+
})
|
|
172
|
+
.join(delimiter),
|
|
173
|
+
};
|
|
174
|
+
const selected = commandOnPath("balladeer", parentEnv);
|
|
175
|
+
if (selected && resolve(selected) !== resolve(shim))
|
|
176
|
+
throw new InstallError(`Another command precedes Volta at ${selected}. Resolve that PATH conflict before installing; nothing was overwritten.`);
|
|
177
|
+
if (existsSync(shim) && basename(realpathSync(shim)) !== "volta-shim")
|
|
178
|
+
throw new InstallError("Another command owns Volta's balladeer path. Nothing was overwritten.");
|
|
179
|
+
const neutral = mkdtempSync(join(tmpdir(), "balladeer-volta-install-"));
|
|
180
|
+
const installEnv = { ...parentEnv, npm_config_cache: join(neutral, "npm-cache") };
|
|
181
|
+
try {
|
|
182
|
+
let version = existsSync(shim) ? packageVersion(shim, installEnv, neutral) : undefined;
|
|
183
|
+
if (existsSync(shim) && version === undefined)
|
|
184
|
+
throw new InstallError("Volta's registered Balladeer package cannot be verified. Repair the toolchain before pairing.");
|
|
185
|
+
const alreadyCurrent = version !== undefined && atLeastCurrent(version);
|
|
186
|
+
if (!alreadyCurrent) {
|
|
187
|
+
try {
|
|
188
|
+
execute(volta, ["install", `balladeer@${CLI_VERSION}`], installEnv, neutral);
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
throw new InstallError("Volta could not install the exact Balladeer release. Check network and toolchain write access, then repeat npx -y balladeer@latest install. No pairing has started.");
|
|
192
|
+
}
|
|
193
|
+
version = existsSync(shim) ? packageVersion(shim, installEnv, neutral) : undefined;
|
|
194
|
+
if (version !== CLI_VERSION)
|
|
195
|
+
throw new InstallError("Volta finished, but its registered default is not the expected Balladeer release. No pairing has started.");
|
|
196
|
+
}
|
|
197
|
+
// Verify both the global default and what an ordinary fresh child in the
|
|
198
|
+
// caller's directory sees. A project override is never mistaken for a default.
|
|
199
|
+
if (!version ||
|
|
200
|
+
execute(shim, ["--version"], installEnv, neutral) !== version ||
|
|
201
|
+
commandOnPath("balladeer", parentEnv) !== shim ||
|
|
202
|
+
execute(shim, ["--version"], parentEnv) !== version)
|
|
203
|
+
throw new InstallError("Volta's default was checked, but this terminal or project selects a different Balladeer. Resolve its PATH or project tool pin before pairing.");
|
|
204
|
+
const shell = execute("/bin/sh", ["-c", "command -v balladeer; balladeer --version"], parentEnv).split("\n");
|
|
205
|
+
if (shell[0] !== shim || shell[1] !== version)
|
|
206
|
+
throw new InstallError("The fresh terminal PATH does not select the verified Volta command. No pairing has started.");
|
|
207
|
+
env.PATH = parentEnv.PATH;
|
|
208
|
+
return {
|
|
209
|
+
status: alreadyCurrent ? "current" : "installed",
|
|
210
|
+
command: shim,
|
|
211
|
+
version,
|
|
212
|
+
restartRequired: false,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
finally {
|
|
216
|
+
rmSync(neutral, { recursive: true, force: true });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
124
219
|
export function ensureInstalled(options) {
|
|
125
220
|
const env = options.environment;
|
|
126
221
|
const platform = options.platform ?? process.platform;
|
|
127
222
|
if (platform === "win32")
|
|
128
223
|
throw new InstallError("Automatic command installation currently supports macOS and Linux. On Windows, use npm install --global balladeer@latest, then verify balladeer --version. No files or pairing were changed.");
|
|
224
|
+
const managed = installWithVolta(env);
|
|
225
|
+
if (managed)
|
|
226
|
+
return managed;
|
|
129
227
|
const current = commandOnPath("balladeer", env);
|
|
130
228
|
if (current) {
|
|
131
229
|
const version = packageVersion(current, env);
|
|
132
230
|
if (version === undefined)
|
|
133
231
|
throw new InstallError(`Another command already owns ${current}. Keep it intact and resolve that command conflict before installing Balladeer.`);
|
|
134
|
-
|
|
135
|
-
version
|
|
136
|
-
.split(".")
|
|
137
|
-
.map(Number)
|
|
138
|
-
.some((part, index, parts) => part > Number(CLI_VERSION.split(".")[index]) &&
|
|
139
|
-
parts
|
|
140
|
-
.slice(0, index)
|
|
141
|
-
.every((value, before) => value === Number(CLI_VERSION.split(".")[before])));
|
|
142
|
-
if (version === CLI_VERSION || newer) {
|
|
232
|
+
if (atLeastCurrent(version)) {
|
|
143
233
|
if (execute(current, ["--version"], env) !== version)
|
|
144
234
|
throw new InstallError("The installed Balladeer command does not run the expected version. Repair the installation before pairing.");
|
|
145
235
|
return { status: "current", command: current, restartRequired: false, version };
|
package/dist/wire.d.ts
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* runtime dependency at all: Node 22 builtins and global fetch, nothing else.
|
|
6
6
|
* A contract test compares the scope list below against the server's.
|
|
7
7
|
*/
|
|
8
|
-
export declare const CLI_VERSION = "1.0.
|
|
8
|
+
export declare const CLI_VERSION = "1.0.6";
|
|
9
9
|
export declare const CLI_INVOCATION = "npx -y balladeer@latest";
|
|
10
10
|
export declare const CLIENT_HEADER = "x-balladeer-client";
|
|
11
|
-
export declare const CLIENT_HEADER_VALUE = "balladeer/1.0.
|
|
11
|
+
export declare const CLIENT_HEADER_VALUE = "balladeer/1.0.6";
|
|
12
12
|
export declare const DEFAULT_CONTROL_PLANE = "https://envelopes.balladeer.ai";
|
|
13
13
|
export type DelegatedScope = "repository:enroll" | "agent:issue" | "ci:connect" | "workspace:invite" | "candidate:propose";
|
|
14
14
|
export declare const DELEGATED_SCOPES: readonly DelegatedScope[];
|
package/dist/wire.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* runtime dependency at all: Node 22 builtins and global fetch, nothing else.
|
|
6
6
|
* A contract test compares the scope list below against the server's.
|
|
7
7
|
*/
|
|
8
|
-
export const CLI_VERSION = "1.0.
|
|
8
|
+
export const CLI_VERSION = "1.0.6";
|
|
9
9
|
export const CLI_INVOCATION = "npx -y balladeer@latest";
|
|
10
10
|
export const CLIENT_HEADER = "x-balladeer-client";
|
|
11
11
|
export const CLIENT_HEADER_VALUE = `balladeer/${CLI_VERSION}`;
|