instabox 0.8.41 → 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
- 26c52b54bfee75b2aa4ca84e7cc4610ddfc80af77bb2caacfd0c542c4dc317f9 instabox-darwin-amd64
2
- 8c83fe4626e0f9d81400292ba458d8e5876645c69fd983b2ba2461fb2003592f instabox-darwin-arm64
3
- dd63b071935b1734e8e1e88ea305784098932b5fcfb40aa37d1eea8a33aef74b instabox-linux-amd64
4
- 73bbe8ca2a61f12b46c4ea6dae4c768c21778fa4f81ef04b34d0e1bb1dadee70 instabox-linux-arm64
5
- e1f5b0ba29703f94a8971f1f4c89c59ba706a1ccda212675cfb7f6a37a48fb72 instabox-windows-amd64.exe
6
- 33368d3fc99e29b4d375917db75226603c3d98074b344b00742bef1ccf5e4117 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.41",
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": {