usebeeline 0.1.58 → 0.1.59

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/usebeeline.mjs +31 -33
  2. package/package.json +1 -1
@@ -411,7 +411,7 @@ __export(self_update_exports, {
411
411
  });
412
412
  import { createHash as createHash3 } from "node:crypto";
413
413
  import { constants as fsConstants } from "node:fs";
414
- import { access, chmod as chmod2, copyFile, lstat as lstat3, mkdir as mkdir3, open, readFile as readFile2, readdir as readdir3, rename, rm as rm3, symlink, writeFile as writeFile2 } from "node:fs/promises";
414
+ import { access, chmod as chmod2, copyFile, lstat as lstat3, mkdir as mkdir3, open, readFile as readFile2, readdir as readdir3, rename as rename2, rm as rm3, symlink, writeFile as writeFile2 } from "node:fs/promises";
415
415
  import { spawn as spawn2 } from "node:child_process";
416
416
  import { homedir as homedir3 } from "node:os";
417
417
  import { dirname as dirname4, join, resolve as resolve6 } from "node:path";
@@ -554,7 +554,7 @@ async function writeUpdateState(layout, state) {
554
554
  } finally {
555
555
  await handle.close();
556
556
  }
557
- await rename(temporary, path);
557
+ await rename2(temporary, path);
558
558
  await fsyncDir(dirname4(path));
559
559
  }
560
560
  async function readInstalledBundleIdentity(layout, _state = {}) {
@@ -804,9 +804,9 @@ async function replaceFile(path, contents, mode) {
804
804
  const temp = `${path}.new-${process.pid}`;
805
805
  await writeFile2(temp, contents, { mode });
806
806
  await chmod2(temp, mode);
807
- await rename(temp, path);
807
+ await rename2(temp, path);
808
808
  }
809
- async function activateRelease(layout, releaseId) {
809
+ async function activateRelease(layout, releaseId, options = {}) {
810
810
  assertInstallTestIsolation(layout);
811
811
  let releaseDir = join(layout.releasesRoot, releaseId);
812
812
  let previousReleaseId = await activeReleaseId(layout);
@@ -821,11 +821,11 @@ async function activateRelease(layout, releaseId) {
821
821
  try {
822
822
  await access(legacyDir, fsConstants.F_OK);
823
823
  const preservedId = `${legacyId}-${Date.now()}`;
824
- await rename(layout.libDir, join(layout.releasesRoot, preservedId));
824
+ await rename2(layout.libDir, join(layout.releasesRoot, preservedId));
825
825
  await normalizeLegacyBundleShape(join(layout.releasesRoot, preservedId));
826
826
  previousReleaseId = preservedId;
827
827
  } catch {
828
- await rename(layout.libDir, legacyDir);
828
+ await rename2(layout.libDir, legacyDir);
829
829
  await normalizeLegacyBundleShape(legacyDir);
830
830
  previousReleaseId = legacyId;
831
831
  }
@@ -833,7 +833,7 @@ async function activateRelease(layout, releaseId) {
833
833
  const tempLink = `${layout.libDir}.new-${process.pid}`;
834
834
  await rm3(tempLink, { force: true });
835
835
  await symlink(join("beeline-releases", releaseId), tempLink);
836
- await rename(tempLink, layout.libDir);
836
+ await rename2(tempLink, layout.libDir);
837
837
  await fsyncDir(dirname4(layout.libDir));
838
838
  await installRecoveryLauncher(layout, releaseDir);
839
839
  await writeBinForwarders(layout, releaseDir);
@@ -843,7 +843,8 @@ async function activateRelease(layout, releaseId) {
843
843
  stagedReleaseId: void 0,
844
844
  previousReleaseId: previousReleaseId && previousReleaseId !== releaseId ? previousReleaseId : state.previousReleaseId
845
845
  });
846
- await pruneHelperReleases(layout);
846
+ if (!options.deferPruning)
847
+ await pruneHelperReleases(layout);
847
848
  }
848
849
  async function installRecoveryLauncher(layout, releaseDir) {
849
850
  const bootstrap = join(releaseDir, "lib/beeline/recovery-cli.mjs");
@@ -851,7 +852,7 @@ async function installRecoveryLauncher(layout, releaseDir) {
851
852
  const stable = resolve6(layout.libDir, "../beeline-bootstrap.mjs");
852
853
  const temporary = `${stable}.${process.pid}.tmp`;
853
854
  await copyFile(bootstrap, temporary);
854
- await rename(temporary, stable);
855
+ await rename2(temporary, stable);
855
856
  await replaceFile(resolve6(layout.libDir, "../beeline-node-path"), `${process.execPath}
856
857
  `, 384);
857
858
  }
@@ -876,7 +877,7 @@ async function normalizeLegacyBundleShape(bundleDir) {
876
877
  continue;
877
878
  } catch {
878
879
  }
879
- await rename(join(bundleDir, name), join(innerLib, name)).catch(() => void 0);
880
+ await rename2(join(bundleDir, name), join(innerLib, name)).catch(() => void 0);
880
881
  }
881
882
  }
882
883
  async function writeBinForwarders(layout, activeBundleRoot) {
@@ -1394,7 +1395,7 @@ async function requestMachine(stateRoot, request, accept, timeoutMs = 6e5) {
1394
1395
  init_kernel_lock();
1395
1396
  init_lifecycle_test_guard();
1396
1397
  import { execFile } from "node:child_process";
1397
- import { mkdir as mkdir2, readFile, readdir, rm, writeFile } from "node:fs/promises";
1398
+ import { mkdir as mkdir2, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
1398
1399
  import { homedir } from "node:os";
1399
1400
  import { resolve as resolve3 } from "node:path";
1400
1401
  import { promisify } from "node:util";
@@ -1416,9 +1417,7 @@ Environment=PATH=%h/.local/bin:/usr/local/bin:/usr/bin:/bin
1416
1417
  ExecStart=%h/.local/bin/beeline helper-bootstrap
1417
1418
  ExecReload=/bin/kill -HUP $MAINPID
1418
1419
  Restart=always
1419
- RestartSec=5s
1420
- RestartSteps=5
1421
- RestartMaxDelaySec=60s
1420
+ RestartSec=1s
1422
1421
  WatchdogSec=180s
1423
1422
  CPUWeight=1000
1424
1423
  IOWeight=1000
@@ -1713,32 +1712,31 @@ async function bootstrapMachine(env = process.env) {
1713
1712
  if (!pid || ![Number(env.BEELINE_BOOT_LAUNCHER_PID), Number(env.BEELINE_BOOT_LAUNCHER_PARENT_PID)].includes(pid))
1714
1713
  throw new Error("helper bootstrap requires native service ownership; run beeline start");
1715
1714
  const layout = beelineInstallLayout(env) ?? discoveredBeelineInstallLayout(env);
1715
+ const state = await readUpdateState(layout);
1716
+ const active = await activeReleaseId(layout);
1716
1717
  let releaseId;
1717
- try {
1718
+ for (const id of [state.stagedReleaseId, active]) {
1719
+ if (!id || !/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(id))
1720
+ continue;
1721
+ const digest = await readFile3(resolve8(layout.releasesRoot, id, ".stage-ok"), "utf8").catch(() => "");
1722
+ if (/^[0-9a-f]{64}$/i.test(digest.trim()) && await resolveBundleEntrypoint(resolve8(layout.releasesRoot, id))) {
1723
+ releaseId = id;
1724
+ break;
1725
+ }
1726
+ }
1727
+ if (!releaseId) {
1718
1728
  if (env.BEELINE_UPDATE_DISABLE === "1")
1719
- throw new Error("automatic release selection disabled by BEELINE_UPDATE_DISABLE");
1720
- const prepared = await prepareMachineRelease(layout, {
1729
+ throw new Error("automatic release selection disabled; no verified runnable release");
1730
+ releaseId = (await prepareMachineRelease(layout, {
1721
1731
  env,
1722
1732
  deadlineAt: Date.now() + 18e4,
1723
1733
  logger: (line) => console.error(line)
1724
- });
1725
- releaseId = prepared.releaseId;
1726
- await withInstallLock(layout, () => activateRelease(layout, releaseId), {
1727
- waitMs: Math.max(0, bootDeadlineAt - Date.now())
1728
- });
1729
- } catch (error) {
1730
- const state = await readUpdateState(layout);
1731
- const candidates = [state.stagedReleaseId, await activeReleaseId(layout)];
1732
- const verified = await Promise.all(candidates.map(async (id) => id && /^[0-9a-f]{64}$/i.test((await readFile3(resolve8(layout.releasesRoot, id, ".stage-ok"), "utf8").catch(() => "")).trim()) ? id : void 0));
1733
- const candidate = verified.find(Boolean);
1734
- if (!candidate)
1735
- throw new Error(`startup release selection failed; no verified runnable release: ${String(error)}`);
1736
- releaseId = candidate;
1737
- console.error(`[beeline] serving verified ${releaseId}; release freshness unconfirmed: ${String(error)}`);
1738
- await withInstallLock(layout, () => activateRelease(layout, releaseId), {
1734
+ })).releaseId;
1735
+ }
1736
+ if (releaseId !== active)
1737
+ await withInstallLock(layout, () => activateRelease(layout, releaseId, { deferPruning: true }), {
1739
1738
  waitMs: Math.max(0, bootDeadlineAt - Date.now())
1740
1739
  });
1741
- }
1742
1740
  const entry = await resolveBundleEntrypoint(resolve8(layout.releasesRoot, releaseId));
1743
1741
  if (!entry)
1744
1742
  throw new Error(`selected release ${releaseId} has no body entry`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usebeeline",
3
- "version": "0.1.58",
3
+ "version": "0.1.59",
4
4
  "description": "Connect an AI coding agent to Beeline with one command.",
5
5
  "homepage": "https://usebeeline.app",
6
6
  "bugs": {