@boxcompute/cli 0.2.1 → 0.2.2
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/README.md +6 -4
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +81 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,9 +61,11 @@ Deploy the server release with both Sandbox API v1 and v2 before publishing CLI
|
|
|
61
61
|
contract. After that, clients need only upgrade the package:
|
|
62
62
|
|
|
63
63
|
```sh
|
|
64
|
-
|
|
64
|
+
bxc update
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
`bxc up` is the short alias. If the automatic update cannot invoke npm, use
|
|
68
|
+
`npm install --global @boxcompute/cli@latest` manually. Updating preserves the
|
|
69
|
+
saved BoxCompute credential and refreshes untouched managed skills before the
|
|
70
|
+
client's next agent session. The new CLI uses v2 for multi-instance sandboxes
|
|
71
|
+
and gives a server-first upgrade message if it reaches an older deployment.
|
package/dist/cli.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export type CliDependencies = {
|
|
|
13
13
|
now?: () => number;
|
|
14
14
|
sleep?: (milliseconds: number) => Promise<void>;
|
|
15
15
|
openBrowser?: (url: string) => void;
|
|
16
|
+
installUpdate?: (version: string) => Promise<void>;
|
|
16
17
|
loadConnection?: (env: NodeJS.ProcessEnv) => Promise<Connection>;
|
|
17
18
|
loadSavedUrl?: (env: NodeJS.ProcessEnv) => Promise<string | null>;
|
|
18
19
|
saveConnection?: (url: string, token: string, env: NodeJS.ProcessEnv) => Promise<void>;
|
package/dist/cli.js
CHANGED
|
@@ -15,6 +15,7 @@ Usage: bxc [options] [command]
|
|
|
15
15
|
Commands:
|
|
16
16
|
|
|
17
17
|
version Print the version number and exit
|
|
18
|
+
update [alias: up] Update the CLI to the latest npm release
|
|
18
19
|
login Log in through BoxCompute in your browser
|
|
19
20
|
logout Revoke and remove the saved CLI credential
|
|
20
21
|
auth [alias: login] Authentication commands
|
|
@@ -48,6 +49,7 @@ Login options:
|
|
|
48
49
|
Examples:
|
|
49
50
|
|
|
50
51
|
$ bxc login
|
|
52
|
+
$ bxc update
|
|
51
53
|
$ bxc skill detect
|
|
52
54
|
$ bxc skill install
|
|
53
55
|
$ bxc workspaces
|
|
@@ -133,6 +135,77 @@ export function openBrowser(url, runtime = {}) {
|
|
|
133
135
|
// polling so headless shells and restricted WSL interop can authenticate.
|
|
134
136
|
}
|
|
135
137
|
}
|
|
138
|
+
function releaseVersion(value) {
|
|
139
|
+
if (typeof value !== "string")
|
|
140
|
+
return null;
|
|
141
|
+
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(value);
|
|
142
|
+
if (!match)
|
|
143
|
+
return null;
|
|
144
|
+
const parts = match.slice(1).map(Number);
|
|
145
|
+
return parts.every(Number.isSafeInteger) ? parts : null;
|
|
146
|
+
}
|
|
147
|
+
function compareReleaseVersions(left, right) {
|
|
148
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
149
|
+
if (left[index] !== right[index])
|
|
150
|
+
return left[index] - right[index];
|
|
151
|
+
}
|
|
152
|
+
return 0;
|
|
153
|
+
}
|
|
154
|
+
async function installCliUpdate(version) {
|
|
155
|
+
const executable = platform() === "win32" ? "npm.cmd" : "npm";
|
|
156
|
+
await new Promise((resolve, reject) => {
|
|
157
|
+
let child;
|
|
158
|
+
try {
|
|
159
|
+
child = spawn(executable, ["install", "--global", `@boxcompute/cli@${version}`], {
|
|
160
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
reject(error);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
child.once("error", reject);
|
|
168
|
+
child.once("exit", (code) => {
|
|
169
|
+
if (code === 0)
|
|
170
|
+
resolve();
|
|
171
|
+
else
|
|
172
|
+
reject(new Error(`npm exited with code ${code ?? "unknown"}`));
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
async function updateCli(dependencies) {
|
|
177
|
+
let response;
|
|
178
|
+
try {
|
|
179
|
+
response = await dependencies.fetch("https://registry.npmjs.org/%40boxcompute%2Fcli/latest", {
|
|
180
|
+
headers: { accept: "application/json" },
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
throw new Error(`Could not check npm for updates: ${error?.message ?? String(error)}`);
|
|
185
|
+
}
|
|
186
|
+
if (!response.ok)
|
|
187
|
+
throw new Error(`Could not check npm for updates (HTTP ${response.status})`);
|
|
188
|
+
const latest = (await response.json()).version;
|
|
189
|
+
const currentParts = releaseVersion(CLI_VERSION);
|
|
190
|
+
const latestParts = releaseVersion(latest);
|
|
191
|
+
if (!currentParts || !latestParts || typeof latest !== "string") {
|
|
192
|
+
throw new Error("npm returned an invalid BoxCompute CLI version");
|
|
193
|
+
}
|
|
194
|
+
if (compareReleaseVersions(latestParts, currentParts) <= 0) {
|
|
195
|
+
emit(dependencies.io, dependencies.json, { updated: false, version: CLI_VERSION }, `BoxCompute CLI is already up to date (${CLI_VERSION}).\n`);
|
|
196
|
+
return 0;
|
|
197
|
+
}
|
|
198
|
+
write(dependencies.io.stderr, `Updating BoxCompute CLI from ${CLI_VERSION} to ${latest}…\n`);
|
|
199
|
+
try {
|
|
200
|
+
await dependencies.install(latest);
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
throw new Error(`Could not install @boxcompute/cli@${latest}: ${error?.message ?? String(error)}. ` +
|
|
204
|
+
`Run \`npm install --global @boxcompute/cli@${latest}\` manually.`);
|
|
205
|
+
}
|
|
206
|
+
emit(dependencies.io, dependencies.json, { updated: true, previousVersion: CLI_VERSION, version: latest }, `Updated BoxCompute CLI to ${latest}.\n`);
|
|
207
|
+
return 0;
|
|
208
|
+
}
|
|
136
209
|
const delay = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
137
210
|
const write = (stream, value) => { stream.write(value); };
|
|
138
211
|
const emit = (io, json, value, human) => {
|
|
@@ -272,6 +345,7 @@ export async function runCli(argv, supplied = {}) {
|
|
|
272
345
|
const now = supplied.now ?? Date.now;
|
|
273
346
|
const sleep = supplied.sleep ?? delay;
|
|
274
347
|
const openBrowserImpl = supplied.openBrowser ?? openBrowser;
|
|
348
|
+
const installUpdate = supplied.installUpdate ?? installCliUpdate;
|
|
275
349
|
const load = supplied.loadConnection ?? loadConnection;
|
|
276
350
|
const savedUrl = supplied.loadSavedUrl ?? loadSavedUrl;
|
|
277
351
|
const save = supplied.saveConnection ?? saveConnection;
|
|
@@ -297,6 +371,8 @@ export async function runCli(argv, supplied = {}) {
|
|
|
297
371
|
let command = args.shift();
|
|
298
372
|
if (command === "login")
|
|
299
373
|
command = "auth";
|
|
374
|
+
if (command === "up")
|
|
375
|
+
command = "update";
|
|
300
376
|
if (command === "skills")
|
|
301
377
|
command = "skill";
|
|
302
378
|
if (command === "list" || command === "ls")
|
|
@@ -345,6 +421,11 @@ export async function runCli(argv, supplied = {}) {
|
|
|
345
421
|
}
|
|
346
422
|
return authenticate(args, { env, io, json, fetch: fetchImpl, now, sleep, openBrowser: openBrowserImpl, loadSavedUrl: savedUrl, saveConnection: save });
|
|
347
423
|
}
|
|
424
|
+
if (command === "update") {
|
|
425
|
+
if (args.length)
|
|
426
|
+
throw new UsageError("update takes no options");
|
|
427
|
+
return updateCli({ fetch: fetchImpl, install: installUpdate, io, json });
|
|
428
|
+
}
|
|
348
429
|
if (command === "skill") {
|
|
349
430
|
let action = args.shift();
|
|
350
431
|
if (!action) {
|