instabox 0.8.40 → 0.8.42

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/instabox.mjs CHANGED
@@ -20,6 +20,7 @@ import { fileURLToPath } from 'node:url';
20
20
  import { createClient } from '../lib/api.mjs';
21
21
  import { orderBoxes } from '../lib/boxes.mjs';
22
22
  import { guestUserNote, localGuestUser } from '../lib/guestuser.mjs';
23
+ import { resolveImage } from '../lib/image.mjs';
23
24
  import {
24
25
  bundledCli,
25
26
  checkCli,
@@ -45,7 +46,8 @@ const API = (
45
46
  process.env.INSTABOX_API ||
46
47
  'https://api.instabox.sh'
47
48
  ).replace(/\/$/, '');
48
- // The template a new box starts from: the CLI's and dashboard's default (shown as standard).
49
+ // The template a new box starts from: the CLI's and dashboard's default (shown as standard). An
50
+ // official template wins over a snapshot of the same name; snapshot:<name> picks the snapshot.
49
51
  const IMAGE = process.env.INSTABOX_IMAGE || 'agent-browser';
50
52
  // SSH certificate lifetime for a box with no timeout of its own.
51
53
  const CERT_MIN = 120;
@@ -77,6 +79,9 @@ function usage() {
77
79
  --no-skills do not install the instabox agent skills
78
80
  npx instabox@latest <command> run an instabox CLI command (instabox help lists them)
79
81
 
82
+ INSTABOX_IMAGE=<template> picks the template sh starts from (default agent-browser);
83
+ INSTABOX_IMAGE=snapshot:<name> starts from a snapshot of yours instead.
84
+
80
85
  Usage data (steps and outcomes, never names or arguments) goes to the instabox team;
81
86
  INSTABOX_NO_TELEMETRY=1 or DO_NOT_TRACK=1 turns it off.
82
87
  `);
@@ -190,19 +195,25 @@ async function quotaFull(err) {
190
195
  }
191
196
 
192
197
  async function newBox() {
193
- const { images } = await client.call('GET', '/v1/images');
194
- const named = images.filter((i) => i.name === IMAGE || i.id === IMAGE);
195
- const img = named.find((i) => i.official) || named[0];
198
+ const src = await resolveImage(IMAGE, {
199
+ // Unreadable: null, and the name goes to the server as a template.
200
+ templates: () =>
201
+ client.call('GET', '/v1/templates').then(
202
+ (r) => r?.templates ?? null,
203
+ () => null,
204
+ ),
205
+ snapshots: () => client.call('GET', '/v1/images').then((r) => r?.images ?? []),
206
+ });
207
+ if (src.missing) throw new Error(`no snapshot named ${src.missing} (instabox snapshot ls lists yours)`);
196
208
  const body = {
197
209
  name: `box-${randomBytes(3).toString('hex')}`,
198
210
  desiredState: 'running',
211
+ ...src,
199
212
  };
200
- if (img) body.imageId = img.id;
201
- else body.templateId = IMAGE;
202
213
  // The box's Linux user is named after yours, so `ssh <box>` over your own network works. A
203
214
  // box from one of your own snapshots keeps the snapshot's user.
204
215
  const user = localGuestUser();
205
- if (user.name && (!img || img.official)) body.guestUser = user.name;
216
+ if (user.name && src.templateId) body.guestUser = user.name;
206
217
  const op = await waitOp(await client.call('POST', '/v1/machines', body));
207
218
  return { id: op.machineId, name: body.name, user };
208
219
  }
package/cli/SHA256SUMS CHANGED
@@ -1,6 +1,6 @@
1
- 4ac8957ca170a605025f3506e6ddc2edce2df67230f9d7b9d06b315ab837dc22 instabox-darwin-amd64
2
- cdff54464dd57a5b21b64bef08a791fb16bcab8ac0076462aa87c9399bd540af instabox-darwin-arm64
3
- da930996e671d53ac63dbf3f7f5c8303083deb2eea5c50f2a46a9a42b3ca3383 instabox-linux-amd64
4
- e10bb94c0a800824560856eebf0abed30885f00e9cfa6518804cba7c52ec2bc8 instabox-linux-arm64
5
- cf22c363a9cce8928d9bcc42de52472aa8dca237ad3b67cdefc58be894333d38 instabox-windows-amd64.exe
6
- 79f74cd8f1947f17e3ef03a23c0ae66a2bffd6a38480805d936f26002922b10c instabox-windows-arm64.exe
1
+ d3e09346083f2cbde79a52d16e9dfa16fea085e5e268e4b3d3fa7cb902b7cd5a instabox-darwin-amd64
2
+ 2132ff4338baeecc0748288393a5cc1b985f9823118b7df54f84c45855ab780d instabox-darwin-arm64
3
+ b2028004acee0159f35c2464e79bc3d230f266abde7ca446055107e5232c4141 instabox-linux-amd64
4
+ d59a285821e6737d05f7358713392cfacaea0e304936405b6919ec2bad55ec3c instabox-linux-arm64
5
+ f3be1d0da240de3280fd2d918c4e1a8717fbe6b46301470c63f620dfae846368 instabox-windows-amd64.exe
6
+ 35d0320acaed1ae82a308ace922faa03eed0917dd3788aa2cb468253ae92d0d2 instabox-windows-arm64.exe
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/lib/image.mjs ADDED
@@ -0,0 +1,32 @@
1
+ // What INSTABOX_IMAGE names: an official template (GET /v1/templates), as `id` or `id@version`.
2
+ // A snapshot of yours is named with `snapshot:<name or id>`, so one that shares a template's name
3
+ // never stands in for it. A bare name that is no template still finds a snapshot of that name.
4
+
5
+ export const SNAPSHOT_PREFIX = 'snapshot:';
6
+
7
+ // The snapshot named want: by id first, else by name.
8
+ function findSnapshot(snapshots, want) {
9
+ const list = Array.isArray(snapshots) ? snapshots.filter((s) => s && typeof s.id === 'string') : [];
10
+ return list.find((s) => s.id === want) || list.find((s) => s.name === want) || null;
11
+ }
12
+
13
+ // isTemplate: whether image (id or id@version) is one of templates. templates null (the list
14
+ // could not be read): treated as a template, so the server decides and a snapshot never wins.
15
+ export function isTemplate(image, templates) {
16
+ if (!Array.isArray(templates)) return true;
17
+ const id = image.split('@')[0];
18
+ return templates.some((t) => t && t.id === id);
19
+ }
20
+
21
+ // resolveImage turns image into the create request's source: { templateId } or { imageId }, or
22
+ // { missing } for a snapshot: name that matches none. snapshots is read only when needed.
23
+ export async function resolveImage(image, { templates, snapshots }) {
24
+ if (image.startsWith(SNAPSHOT_PREFIX)) {
25
+ const want = image.slice(SNAPSHOT_PREFIX.length);
26
+ const s = findSnapshot(await snapshots(), want);
27
+ return s ? { imageId: s.id } : { missing: want };
28
+ }
29
+ if (isTemplate(image, await templates())) return { templateId: image };
30
+ const s = findSnapshot(await snapshots(), image);
31
+ return s ? { imageId: s.id } : { templateId: image };
32
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instabox",
3
- "version": "0.8.40",
3
+ "version": "0.8.42",
4
4
  "description": "A cloud box for your coding agent, the instabox CLI and its agent skills in one command: npx instabox@latest",
5
5
  "type": "module",
6
6
  "bin": {