@jabezpauls/agentbox 0.1.12 → 0.1.14

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/dist/agentbox.mjs +94 -29
  2. package/package.json +1 -1
package/dist/agentbox.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // agentbox-cli v0.1.12
2
+ // agentbox-cli v0.1.14
3
3
  import { createRequire as __agentboxCreateRequire } from "node:module";
4
4
  const require = __agentboxCreateRequire(import.meta.url);
5
5
  var __create = Object.create;
@@ -3868,7 +3868,7 @@ function parseSize(raw2) {
3868
3868
  }
3869
3869
 
3870
3870
  // src/version.ts
3871
- var VERSION = true ? "v0.1.12" : "0.0.0-dev";
3871
+ var VERSION = true ? "v0.1.14" : "0.0.0-dev";
3872
3872
  var STANDALONE = typeof __AGENTBOX_STANDALONE__ === "boolean" && __AGENTBOX_STANDALONE__;
3873
3873
  var MIN_NODE_MAJOR = 20;
3874
3874
  function nodeMajor(version = process.versions.node) {
@@ -6871,7 +6871,7 @@ function writePrivate2(file, contents, mode = 384) {
6871
6871
  }
6872
6872
 
6873
6873
  // src/node/control.ts
6874
- var COMMANDS = /* @__PURE__ */ new Set(["status", "pause", "resume", "leave", "preview", "preview-list", "preview-stop"]);
6874
+ var COMMANDS = /* @__PURE__ */ new Set(["status", "pause", "resume", "leave", "preview", "preview-list", "preview-stop", "passphrase"]);
6875
6875
  var PIPE_NAME = /^\\\\\.\\pipe\\agentbox-node-[0-9a-f]{32}$/;
6876
6876
  function address(socketPath, platform) {
6877
6877
  if (platform !== "win32") return socketPath;
@@ -7033,6 +7033,7 @@ function decodeControl(payload) {
7033
7033
  import { createHash as createHash3, createHmac, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
7034
7034
  var PROTOCOL_VERSION = 1;
7035
7035
  var LINK_PATH = "/_gate/node";
7036
+ var MAX_STREAMS_PER_LINK = 256;
7036
7037
  var DUPLICATE_BACKOFF_MS = 5 * 6e4;
7037
7038
  var NODE_TOKEN_SHAPE = /^abn_[A-Za-z0-9_-]{43}$/;
7038
7039
  function tokenDigest(token) {
@@ -7997,6 +7998,7 @@ var Roots = class {
7997
7998
  isHidden;
7998
7999
  isWriteDenied;
7999
8000
  refusePath;
8001
+ holdsHidden;
8000
8002
  constructor(opts) {
8001
8003
  this.roots = opts.roots.map((r) => ({ id: r.id, path: path13.resolve(r.path), mode: r.mode, stateDir: path13.resolve(r.stateDir) }));
8002
8004
  const first = this.roots[0];
@@ -8008,6 +8010,7 @@ var Roots = class {
8008
8010
  this.isHidden = opts.isHidden;
8009
8011
  this.isWriteDenied = opts.isWriteDenied;
8010
8012
  this.refusePath = opts.refusePath;
8013
+ this.holdsHidden = opts.holdsHidden;
8011
8014
  }
8012
8015
  byId(id) {
8013
8016
  const root = this.roots.find((r) => r.id === id);
@@ -8133,6 +8136,10 @@ var Roots = class {
8133
8136
  }
8134
8137
  }
8135
8138
  }
8139
+ /** Refuse to copy an entry that holds a hidden path: the copy would show it. */
8140
+ assertCopyable(ref) {
8141
+ if (this.holdsHidden?.(ref.fs)) throw new FilesError(403, `permission denied: ${ref.abs}`, "denied");
8142
+ }
8136
8143
  /** Resolve through every symlink; the destination must stay in the root. */
8137
8144
  async target(input) {
8138
8145
  const loc = this.locate(input);
@@ -8808,6 +8815,7 @@ var FileOps = class {
8808
8815
  async copy(body) {
8809
8816
  const src = await this.roots.entry(body.from);
8810
8817
  await this.roots.assertMovable(src);
8818
+ this.roots.assertCopyable(src);
8811
8819
  const dest = await this.roots.creatable(body.to);
8812
8820
  this.roots.assertMutable(dest);
8813
8821
  if (dest.abs === src.abs) throw new FilesError(409, "a copy needs a different name", "exists");
@@ -8872,6 +8880,7 @@ var Trash = class {
8872
8880
  }
8873
8881
  throw err;
8874
8882
  }
8883
+ this.roots.assertMutable(ref);
8875
8884
  result.trashed.push(await this.put(ref.root, ref.abs, ref.fs));
8876
8885
  }
8877
8886
  return result;
@@ -9293,6 +9302,7 @@ var FilesService = class {
9293
9302
  ...opts.caseInsensitive === void 0 ? {} : { caseInsensitive: opts.caseInsensitive },
9294
9303
  ...opts.isHidden === void 0 ? {} : { isHidden: opts.isHidden },
9295
9304
  ...opts.isWriteDenied === void 0 ? {} : { isWriteDenied: opts.isWriteDenied },
9305
+ ...opts.holdsHidden === void 0 ? {} : { holdsHidden: opts.holdsHidden },
9296
9306
  ...opts.refusePath === void 0 ? {} : { refusePath: opts.refusePath }
9297
9307
  });
9298
9308
  this.git = new GitStatusCache(opts.gitTtlMs === void 0 ? {} : { ttlMs: opts.gitTtlMs });
@@ -9887,6 +9897,7 @@ function refuseWindowsPath(input) {
9887
9897
  for (const part of rest.split("\\")) {
9888
9898
  if (part === "" || part === "." || part === "..") continue;
9889
9899
  if (/[. ]$/.test(part)) return "a name ending in a dot or a space is refused";
9900
+ if (/~\d/.test(part)) return "short (8.3) names, with a ~ and a digit, are refused";
9890
9901
  if (/^(con|prn|aux|nul|com[0-9¹²³]|lpt[0-9¹²³]|conin\$|conout\$)(\..*)?$/i.test(part)) return "DOS device names are refused";
9891
9902
  }
9892
9903
  return null;
@@ -9922,11 +9933,25 @@ function pathRules(o) {
9922
9933
  };
9923
9934
  const gitRuns = (p) => {
9924
9935
  const parts = fold(p).split(P.sep);
9925
- for (let i = 0; i + 1 < parts.length; i++) {
9926
- if (parts[i] === ".git" && (parts[i + 1] === "hooks" || parts[i + 1] === "config")) return true;
9936
+ for (let i = 0; i < parts.length; i++) {
9937
+ if (parts[i] === ".git") return true;
9938
+ if (parts[i]?.endsWith(".git") && (parts[i + 1] === "hooks" || parts[i + 1] === "config")) return true;
9927
9939
  }
9928
9940
  return false;
9929
9941
  };
9942
+ const homeF = fold(o.home);
9943
+ const homeBase = homeF.endsWith(P.sep) ? homeF : homeF + P.sep;
9944
+ const inHomeDot = (p) => {
9945
+ const f = fold(p);
9946
+ if (!f.startsWith(homeBase)) return false;
9947
+ const first = f.slice(homeBase.length).split(P.sep)[0] ?? "";
9948
+ return first.startsWith(".") || platform === "win32" && first === "appdata";
9949
+ };
9950
+ const holds = (p, list) => {
9951
+ const f = fold(p);
9952
+ const base = f.endsWith(P.sep) ? f : f + P.sep;
9953
+ return list.some((e) => e.startsWith(base));
9954
+ };
9930
9955
  const remote = (p) => platform === "win32" && (p.startsWith("\\\\") || p.startsWith("//"));
9931
9956
  return {
9932
9957
  platform,
@@ -9934,7 +9959,8 @@ function pathRules(o) {
9934
9959
  hidden,
9935
9960
  writeDenied,
9936
9961
  isHidden: (p) => remote(p) || under(p, hiddenF),
9937
- isWriteDenied: (p) => remote(p) || under(p, deniedF) || gitRuns(p),
9962
+ isWriteDenied: (p) => remote(p) || under(p, deniedF) || gitRuns(p) || inHomeDot(p) || holds(p, deniedF) || holds(p, hiddenF),
9963
+ holdsHidden: (p) => holds(p, hiddenF),
9938
9964
  refusePath: (input) => platform === "win32" ? refuseWindowsPath(input) : null
9939
9965
  };
9940
9966
  }
@@ -9956,7 +9982,7 @@ function windowsDocuments(env = process.env) {
9956
9982
  const out = [];
9957
9983
  for (const key of ["User Shell Folders", "Shell Folders"]) {
9958
9984
  try {
9959
- const text = execFileSync("reg.exe", ["query", `HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\${key}`, "/v", "Personal"], {
9985
+ const text = execFileSync(path22.win32.join(env.SystemRoot && path22.win32.isAbsolute(env.SystemRoot) ? env.SystemRoot : "C:\\Windows", "System32", "reg.exe"), ["query", `HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\${key}`, "/v", "Personal"], {
9960
9986
  encoding: "utf8",
9961
9987
  timeout: 1e4,
9962
9988
  windowsHide: true,
@@ -9988,6 +10014,7 @@ function filesFor(policy, paths2, rules) {
9988
10014
  caseInsensitive: rules.caseInsensitive,
9989
10015
  isHidden: rules.isHidden,
9990
10016
  isWriteDenied: rules.isWriteDenied,
10017
+ holdsHidden: rules.holdsHidden,
9991
10018
  refusePath: rules.refusePath,
9992
10019
  ...rules.platform === "win32" ? { apiPaths: { toHost: (p) => toHostPath(p, "win32"), toApi: (p) => toApiPath(p, "win32") } } : {}
9993
10020
  });
@@ -10218,6 +10245,8 @@ var NodeLink = class extends EventEmitter {
10218
10245
  stateNow = "stopped";
10219
10246
  running = false;
10220
10247
  paused = false;
10248
+ /** It said `leave`: only then is a close saying "left" taken for one (a gate saying so unasked is a dropped link). */
10249
+ leaving = false;
10221
10250
  failures = 0;
10222
10251
  failingSince = null;
10223
10252
  retryTimer = null;
@@ -10315,6 +10344,7 @@ var NodeLink = class extends EventEmitter {
10315
10344
  clearTimeout(timer);
10316
10345
  resolve(code2 === 4005);
10317
10346
  });
10347
+ this.leaving = true;
10318
10348
  ws.send(encodeControl({ type: "leave" }));
10319
10349
  });
10320
10350
  }
@@ -10362,7 +10392,7 @@ var NodeLink = class extends EventEmitter {
10362
10392
  if (!this.running || this.paused || this.ws) return;
10363
10393
  this.set("connecting");
10364
10394
  const url = `${this.o.box.replace(/^http/, "ws")}${LINK_PATH}`;
10365
- const ws = new import_websocket.default(url, { headers: { authorization: `Bearer ${this.o.token}` }, perMessageDeflate: false, handshakeTimeout: 2e4, followRedirects: false });
10395
+ const ws = new import_websocket.default(url, { headers: { authorization: `Bearer ${this.o.token}` }, perMessageDeflate: false, handshakeTimeout: 2e4, followRedirects: false, maxPayload: STREAM_WINDOW + 16 });
10366
10396
  this.ws = ws;
10367
10397
  let welcomed = false;
10368
10398
  let stopKeepAlive = () => {
@@ -10445,7 +10475,7 @@ var NodeLink = class extends EventEmitter {
10445
10475
  return;
10446
10476
  }
10447
10477
  if (frame.type === FrameType.open) {
10448
- if (!welcomed || this.listenerCount("stream") === 0 || streams.has(frame.stream)) {
10478
+ if (!welcomed || this.listenerCount("stream") === 0 || streams.has(frame.stream) || streams.size >= MAX_STREAMS_PER_LINK) {
10449
10479
  ws.send(encodeFrame(FrameType.close, frame.stream));
10450
10480
  return;
10451
10481
  }
@@ -10460,7 +10490,7 @@ var NodeLink = class extends EventEmitter {
10460
10490
  if (this.ws !== ws) return;
10461
10491
  this.ws = null;
10462
10492
  if (!this.running || this.stateNow === "revoked") return;
10463
- if (code2 === 4005) {
10493
+ if (code2 === 4005 && this.leaving) {
10464
10494
  this.stop("left");
10465
10495
  return;
10466
10496
  }
@@ -10511,16 +10541,29 @@ function presenceAnswer(key, challenge, sessionId, machineId) {
10511
10541
  var PresenceGate = class {
10512
10542
  constructor(o) {
10513
10543
  this.o = o;
10544
+ this.presence = o.presence;
10514
10545
  this.key = Buffer.from(o.presence.key, "base64url");
10515
10546
  this.now = o.now ?? Date.now;
10516
10547
  }
10517
10548
  o;
10518
10549
  key;
10550
+ presence;
10519
10551
  challenges = /* @__PURE__ */ new Map();
10520
10552
  grants = /* @__PURE__ */ new Map();
10521
10553
  failures = [];
10522
10554
  lockedUntil = 0;
10523
10555
  now;
10556
+ /**
10557
+ * A new passphrase (`agentbox node passphrase`), taken at once: every
10558
+ * challenge and every grant the old one earned ends, so channels opened on
10559
+ * them close at the next check.
10560
+ */
10561
+ rekey(presence) {
10562
+ this.presence = presence;
10563
+ this.key = Buffer.from(presence.key, "base64url");
10564
+ this.challenges.clear();
10565
+ this.grants.clear();
10566
+ }
10524
10567
  /** Locked until this time, or `null`. */
10525
10568
  locked() {
10526
10569
  return this.lockedUntil > this.now() ? this.lockedUntil : null;
@@ -10535,7 +10578,7 @@ var PresenceGate = class {
10535
10578
  const challenge = randomBytes10(32).toString("base64url");
10536
10579
  const expiresAt = t2 + CHALLENGE_MS;
10537
10580
  this.challenges.set(challenge, { session, expiresAt });
10538
- return { challenge, salt: this.o.presence.salt, iterations: this.o.presence.iterations, expiresAt };
10581
+ return { challenge, salt: this.presence.salt, iterations: this.presence.iterations, expiresAt };
10539
10582
  }
10540
10583
  answer(session, challenge, answer) {
10541
10584
  if (session === null) return { ok: false, error: "no_session" };
@@ -11703,9 +11746,19 @@ function unitDir(env = process.env, home2 = os9.homedir()) {
11703
11746
  const xdg = env.XDG_CONFIG_HOME;
11704
11747
  return path26.join(xdg && path26.isAbsolute(xdg) ? xdg : path26.join(home2, ".config"), "systemd", "user");
11705
11748
  }
11706
- function execStart(execPath = process.execPath, script = process.argv[1]) {
11707
- const isSea = script === void 0 || path26.resolve(script) === path26.resolve(execPath);
11708
- return isSea ? [execPath, "node", "run"] : [execPath, path26.resolve(script), "node", "run"];
11749
+ function runningAsSea() {
11750
+ try {
11751
+ const sea = process.getBuiltinModule?.("node:sea");
11752
+ return typeof sea?.isSea === "function" && sea.isSea();
11753
+ } catch {
11754
+ return false;
11755
+ }
11756
+ }
11757
+ function isStandalone(execPath, script, sea = runningAsSea()) {
11758
+ return sea || script === void 0 || path26.resolve(script) === path26.resolve(execPath);
11759
+ }
11760
+ function execStart(execPath = process.execPath, script = process.argv[1], sea = runningAsSea()) {
11761
+ return isStandalone(execPath, script, sea) ? [execPath, "node", "run"] : [execPath, path26.resolve(script), "node", "run"];
11709
11762
  }
11710
11763
  function quote(arg) {
11711
11764
  return `"${arg.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/%/g, "%%")}"`;
@@ -11775,11 +11828,12 @@ var CONSOLE_EXE = "agentbox.exe";
11775
11828
  var LOG_MAX_BYTES = 10 * 1024 * 1024;
11776
11829
  var LOG_FILES = 3;
11777
11830
  var RESTART_EXIT = 75;
11778
- function standalone(execPath, script) {
11779
- return script === void 0 || path27.resolve(script) === path27.resolve(execPath);
11831
+ function regExe(env = process.env) {
11832
+ const root = env.SystemRoot && path27.win32.isAbsolute(env.SystemRoot) ? env.SystemRoot : "C:\\Windows";
11833
+ return path27.win32.join(root, "System32", "reg.exe");
11780
11834
  }
11781
- function guiExecutable(execPath = process.execPath, script = process.argv[1]) {
11782
- if (!standalone(execPath, script)) {
11835
+ function guiExecutable(execPath = process.execPath, script = process.argv[1], sea = runningAsSea()) {
11836
+ if (!isStandalone(execPath, script, sea)) {
11783
11837
  return {
11784
11838
  problem: "the Windows sign-in entry needs the standalone agentbox.exe and agentbox-node.exe (this is agentbox.mjs under Node, which would open a console window at every sign-in); run `agentbox node run` yourself, or install the standalone executables"
11785
11839
  };
@@ -11791,8 +11845,8 @@ function guiExecutable(execPath = process.execPath, script = process.argv[1]) {
11791
11845
  function runEntry(gui) {
11792
11846
  return `"${gui}" node supervise`;
11793
11847
  }
11794
- function runCommandLine(execPath = process.execPath, script = process.argv[1]) {
11795
- if (!standalone(execPath, script)) return [execPath, path27.resolve(script), "node", "run"];
11848
+ function runCommandLine(execPath = process.execPath, script = process.argv[1], sea = runningAsSea()) {
11849
+ if (!isStandalone(execPath, script, sea)) return [execPath, path27.resolve(script), "node", "run"];
11796
11850
  const dir = path27.dirname(execPath);
11797
11851
  const exe = path27.basename(execPath).toLowerCase() === GUI_EXE ? path27.join(dir, CONSOLE_EXE) : execPath;
11798
11852
  return [exe, "node", "run"];
@@ -11800,7 +11854,7 @@ function runCommandLine(execPath = process.execPath, script = process.argv[1]) {
11800
11854
  async function installService2(opts) {
11801
11855
  const run4 = opts.run ?? runCommand;
11802
11856
  const entry = runEntry(opts.gui);
11803
- const r = await run4("reg.exe", ["add", RUN_KEY, "/v", RUN_VALUE, "/t", "REG_SZ", "/d", entry, "/f"]);
11857
+ const r = await run4(regExe(), ["add", RUN_KEY, "/v", RUN_VALUE, "/t", "REG_SZ", "/d", entry, "/f"]);
11804
11858
  if (r.code !== 0) throw new Error(`reg add ${RUN_KEY} failed: ${(r.stderr || r.stdout).trim() || `exit ${r.code}`}`);
11805
11859
  if (opts.start !== false) {
11806
11860
  const child = spawn9(opts.gui, ["node", "supervise"], { detached: true, stdio: "ignore", windowsHide: true });
@@ -11811,14 +11865,14 @@ async function installService2(opts) {
11811
11865
  return { entry };
11812
11866
  }
11813
11867
  async function readRunEntry(run4 = runCommand) {
11814
- const r = await run4("reg.exe", ["query", RUN_KEY, "/v", RUN_VALUE]);
11868
+ const r = await run4(regExe(), ["query", RUN_KEY, "/v", RUN_VALUE]);
11815
11869
  if (r.code !== 0) return null;
11816
11870
  return new RegExp(`${RUN_VALUE}\\s+REG_SZ\\s+(.*)`).exec(r.stdout)?.[1]?.trim() ?? null;
11817
11871
  }
11818
11872
  async function removeService2(opts) {
11819
11873
  const run4 = opts.run ?? runCommand;
11820
11874
  const had = await readRunEntry(run4) !== null;
11821
- if (had) await run4("reg.exe", ["delete", RUN_KEY, "/v", RUN_VALUE, "/f"]);
11875
+ if (had) await run4(regExe(), ["delete", RUN_KEY, "/v", RUN_VALUE, "/f"]);
11822
11876
  const pid = supervisorPid(opts.paths);
11823
11877
  if (pid !== null && pid !== process.pid) {
11824
11878
  try {
@@ -12509,6 +12563,7 @@ async function runNode(o) {
12509
12563
  if (await callControl(o.paths.control, o.paths.controlSecret, "status", 2e3) !== null) {
12510
12564
  throw new CliError("a node is already running on this machine (see `agentbox node status`)");
12511
12565
  }
12566
+ process.chdir(o.paths.dir);
12512
12567
  let policy = loadPolicy(o.paths.policy, o.home);
12513
12568
  const claude = claudePaths(o.paths);
12514
12569
  prepareClaude(claude, { home: o.home, machine: creds.name });
@@ -12682,6 +12737,14 @@ async function runNode(o) {
12682
12737
  setPaused(o.paths.policy, false);
12683
12738
  link.resume();
12684
12739
  return { state: link.state };
12740
+ case "passphrase": {
12741
+ const fresh = readCredentials(o.paths.credentials);
12742
+ if (!fresh) throw new Error("credentials.json cannot be read");
12743
+ presence.rekey(fresh.presence);
12744
+ const closed = server.enforce();
12745
+ o.log(`presence: the machines passphrase changed on this machine; every grant ended${closed ? ` (${closed} channel(s) closed)` : ""}`);
12746
+ return {};
12747
+ }
12685
12748
  case "leave": {
12686
12749
  const told = await link.leave();
12687
12750
  setImmediate(() => finish(EXIT.OK));
@@ -12691,7 +12754,7 @@ async function runNode(o) {
12691
12754
  });
12692
12755
  link.on("revoked", () => {
12693
12756
  fs22.rmSync(o.paths.secrets, { recursive: true, force: true });
12694
- writeCredentials(o.paths.credentials, { ...creds, revokedAt: now() });
12757
+ writeCredentials(o.paths.credentials, { ...readCredentials(o.paths.credentials) ?? creds, revokedAt: now() });
12695
12758
  o.log(`${creds.box} revoked this machine. Its shared secrets are wiped; everything else is kept. Re-join it to use it again.`);
12696
12759
  finish(EXIT.OK);
12697
12760
  });
@@ -12704,15 +12767,15 @@ async function runNode(o) {
12704
12767
  if (checking || o.checkUpdates === false) return;
12705
12768
  checking = true;
12706
12769
  try {
12707
- const standalone2 = execStart().length === 3;
12770
+ const standalone = execStart().length === 3;
12708
12771
  const gui = path30.join(path30.dirname(process.execPath), GUI_EXE);
12709
12772
  const report = await checkForUpdate({
12710
12773
  policy: policy.policy.updates,
12711
12774
  running: o.version,
12712
12775
  // Only the standalone executable replaces itself; agentbox.mjs under Node does not.
12713
- nodePath: standalone2 ? process.execPath : null,
12776
+ nodePath: standalone ? process.execPath : null,
12714
12777
  // Windows: the windowless copy beside it, which the sign-in entry starts.
12715
- ...win && standalone2 && fs22.existsSync(gui) ? { nodeGuiPath: gui } : {},
12778
+ ...win && standalone && fs22.existsSync(gui) ? { nodeGuiPath: gui } : {},
12716
12779
  ...fs22.existsSync(herdrBin) ? { herdr: { path: herdrBin, version: HERDR_VERSION } } : {},
12717
12780
  ...installedClaude(claude) ? { claude: { path: claude.bin, version: installedClaude(claude), versionFile: claude.versionFile } } : {},
12718
12781
  // Agents live in herdr: herdr and Claude Code are replaced only while none runs.
@@ -13059,6 +13122,8 @@ var passphrase = command({
13059
13122
  } finally {
13060
13123
  prompt.close();
13061
13124
  }
13125
+ const live = await callControl(np.control, np.controlSecret, "passphrase", 5e3);
13126
+ if (live !== null && live.ok !== true) throw new CliError(`the running node did not take it (${String(live.error ?? "refused")}); restart it`);
13062
13127
  ctx.err("This machine now proves presence with the new passphrase.\n");
13063
13128
  }
13064
13129
  });
@@ -14334,12 +14399,12 @@ function nodeCredentials(env, platform = process.platform) {
14334
14399
  }
14335
14400
  return candidates.find((f) => fs26.existsSync(f)) ?? null;
14336
14401
  }
14337
- function signedUpdatesOnly(env, platform = process.platform, standalone2 = STANDALONE) {
14402
+ function signedUpdatesOnly(env, platform = process.platform, standalone = STANDALONE) {
14338
14403
  const creds = nodeCredentials(env, platform);
14339
14404
  if (creds) {
14340
14405
  return `this machine is joined to a box as a node (${creds}), so agentbox here updates only from signed releases, never from a box: the node checks for them itself (\`updates\` in its policy.json), or see https://github.com/jabezpauls/agentbox/releases`;
14341
14406
  }
14342
- if (standalone2) {
14407
+ if (standalone) {
14343
14408
  return "this is the standalone agentbox, which updates only from signed releases, never from a box; download the latest from https://github.com/jabezpauls/agentbox/releases";
14344
14409
  }
14345
14410
  return null;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jabezpauls/agentbox",
3
3
  "type": "module",
4
- "version": "0.1.12",
4
+ "version": "0.1.14",
5
5
  "description": "agentbox from your own machine: sign in, attach, move files, mount the workspace.",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/jabezpauls/agentbox/blob/main/docs/cli.md",