usebeeline 0.1.56 → 0.1.58

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 +255 -54
  2. package/package.json +1 -1
@@ -126,6 +126,152 @@ var init_lifecycle_test_guard = __esm({
126
126
  }
127
127
  });
128
128
 
129
+ // apps/body/dist/trusty-squire-storage.js
130
+ import { homedir as homedir2 } from "node:os";
131
+ import { isAbsolute, resolve as resolve4 } from "node:path";
132
+ function trustySquireLegacyStorePaths(operatorHome = homedir2(), env = process.env) {
133
+ const roots = /* @__PURE__ */ new Set([resolve4(operatorHome, ".config")]);
134
+ const xdgConfig = env.XDG_CONFIG_HOME?.trim();
135
+ if (xdgConfig && isAbsolute(xdgConfig))
136
+ roots.add(resolve4(xdgConfig));
137
+ return [...roots].map((root) => resolve4(root, "trusty-squire"));
138
+ }
139
+ var init_trusty_squire_storage = __esm({
140
+ "apps/body/dist/trusty-squire-storage.js"() {
141
+ "use strict";
142
+ }
143
+ });
144
+
145
+ // apps/body/dist/storage-filesystem.js
146
+ import { chmod, lstat as lstat2, readdir as readdir2, realpath, rm as rm2 } from "node:fs/promises";
147
+ import { resolve as resolve5, sep } from "node:path";
148
+ import { spawn } from "node:child_process";
149
+ function canonicalStoragePath(path) {
150
+ const absolute = resolve5(path);
151
+ return process.platform === "darwin" ? absolute.replace(/^\/(var|tmp|etc)(?=\/|$)/, "/private/$1") : absolute;
152
+ }
153
+ async function ordinaryDirectory(path) {
154
+ const info = await lstat2(path).catch(() => void 0);
155
+ return Boolean(info?.isDirectory() && canonicalStoragePath(await realpath(path)) === canonicalStoragePath(path));
156
+ }
157
+ async function storageTree(root) {
158
+ if (process.platform === "darwin") {
159
+ const tree2 = /* @__PURE__ */ new Map();
160
+ const visit = async (path) => {
161
+ const info = await lstat2(path);
162
+ tree2.set(path, {
163
+ dev: info.dev,
164
+ ino: info.ino,
165
+ blocks: info.blocks * 512,
166
+ links: info.nlink,
167
+ directory: info.isDirectory(),
168
+ lastUsed: Math.max(info.atimeMs, info.mtimeMs)
169
+ });
170
+ if (info.isDirectory() && !isSquirePath(path))
171
+ for (const name of await readdir2(path))
172
+ await visit(resolve5(path, name));
173
+ };
174
+ await visit(root);
175
+ return tree2;
176
+ }
177
+ const child = spawn("/usr/bin/python3", ["-c", TREE_INVENTORY, root], { stdio: ["ignore", "pipe", "pipe"] });
178
+ const tree = /* @__PURE__ */ new Map();
179
+ let pending = "", stderr = "";
180
+ child.stderr.setEncoding("utf8");
181
+ child.stderr.on("data", (chunk) => {
182
+ stderr = (stderr + chunk).slice(-8192);
183
+ });
184
+ const completed = new Promise((done, fail) => {
185
+ child.once("error", fail);
186
+ child.once("close", (code) => code === 0 ? done() : fail(new Error(`storage inventory failed (${code}): ${stderr}`)));
187
+ });
188
+ void completed.catch(() => void 0);
189
+ const add = (line) => {
190
+ const [path, dev, ino, blocks, links, directory, lastUsed] = JSON.parse(line);
191
+ tree.set(path, { dev, ino, blocks, links, directory, lastUsed });
192
+ };
193
+ child.stdout.setEncoding("utf8");
194
+ for await (const chunk of child.stdout) {
195
+ pending += chunk;
196
+ let newline;
197
+ while ((newline = pending.indexOf("\n")) >= 0) {
198
+ add(pending.slice(0, newline));
199
+ pending = pending.slice(newline + 1);
200
+ }
201
+ }
202
+ await completed;
203
+ if (pending)
204
+ add(pending);
205
+ return tree;
206
+ }
207
+ function isSquirePath(path) {
208
+ const absolute = resolve5(path);
209
+ return absolute.split(sep).some((part, index, parts) => [".trusty-squire", "squire-host-config"].includes(part) || part === "trusty-squire" && parts[index - 1] !== "skills") || trustySquireLegacyStorePaths().some((root) => absolute === root || absolute.startsWith(`${root}${sep}`));
210
+ }
211
+ async function removeStoragePath(root, knownTree) {
212
+ const original = knownTree ?? await storageTree(root);
213
+ let index = removalIndexes.get(original);
214
+ if (!index) {
215
+ index = {
216
+ excluded: [...original.keys()].filter(isSquirePath),
217
+ directories: [...original].filter(([, item]) => item.directory).map(([path]) => path).sort()
218
+ };
219
+ removalIndexes.set(original, index);
220
+ }
221
+ const { excluded, directories } = index;
222
+ if (excluded.some((path) => path === root || path.startsWith(`${root}/`)))
223
+ throw new Error("refusing removal of Trusty Squire storage");
224
+ if (isSquirePath(root))
225
+ throw new Error("refusing removal of Trusty Squire storage");
226
+ const prefix = `${root}/`;
227
+ let low = 0, high = directories.length;
228
+ while (low < high) {
229
+ const middle = low + high >>> 1;
230
+ if (directories[middle] < prefix)
231
+ low = middle + 1;
232
+ else
233
+ high = middle;
234
+ }
235
+ const ownedDirectories = original.get(root)?.directory ? [root] : [];
236
+ for (let cursor = low; cursor < directories.length && directories[cursor].startsWith(prefix); cursor++)
237
+ ownedDirectories.push(directories[cursor]);
238
+ for (const path of ownedDirectories) {
239
+ const info = await lstat2(path).catch((error) => {
240
+ if (error.code === "ENOENT")
241
+ return void 0;
242
+ throw error;
243
+ });
244
+ if (!info)
245
+ continue;
246
+ if (info.isDirectory() && process.getuid?.() === info.uid && (info.mode & 448) !== 448)
247
+ await chmod(path, info.mode | 448);
248
+ }
249
+ await rm2(root, { recursive: true, force: true, maxRetries: 3 });
250
+ }
251
+ var TREE_INVENTORY, removalIndexes;
252
+ var init_storage_filesystem = __esm({
253
+ "apps/body/dist/storage-filesystem.js"() {
254
+ "use strict";
255
+ init_trusty_squire_storage();
256
+ TREE_INVENTORY = String.raw`
257
+ import os, sys, json, stat
258
+ root=sys.argv[1]
259
+ def visit(path):
260
+ s=os.lstat(path)
261
+ directory=stat.S_ISDIR(s.st_mode)
262
+ print(json.dumps([path,s.st_dev,s.st_ino,s.st_blocks*512,s.st_nlink,directory,max(s.st_atime_ns,s.st_mtime_ns)/1000000]))
263
+ if directory and not (os.path.basename(path) in ['.trusty-squire','squire-host-config'] or (os.path.basename(path)=='trusty-squire' and os.path.basename(os.path.dirname(path))!='skills')):
264
+ fd=os.open(path,os.O_RDONLY|os.O_DIRECTORY|os.O_NOATIME|os.O_NOFOLLOW)
265
+ try: names=os.listdir(fd)
266
+ finally: os.close(fd)
267
+ for name in names: visit(os.path.join(path,name))
268
+ visit(root)
269
+
270
+ `;
271
+ removalIndexes = /* @__PURE__ */ new WeakMap();
272
+ }
273
+ });
274
+
129
275
  // apps/body/dist/self-update-manifest.js
130
276
  function resolveManifestUrl(env = process.env) {
131
277
  const override = env.BEELINE_UPDATE_MANIFEST_URL?.trim();
@@ -252,6 +398,7 @@ __export(self_update_exports, {
252
398
  nodeVersionAtLeast: () => nodeVersionAtLeast,
253
399
  normalizeLegacyBundleShape: () => normalizeLegacyBundleShape,
254
400
  prepareLatestRelease: () => prepareLatestRelease,
401
+ pruneHelperReleases: () => pruneHelperReleases,
255
402
  readBundleEngineMinimum: () => readBundleEngineMinimum,
256
403
  readInstalledBundleIdentity: () => readInstalledBundleIdentity,
257
404
  readUpdateState: () => readUpdateState,
@@ -264,12 +411,12 @@ __export(self_update_exports, {
264
411
  });
265
412
  import { createHash as createHash3 } from "node:crypto";
266
413
  import { constants as fsConstants } from "node:fs";
267
- import { access, chmod, copyFile, lstat as lstat2, mkdir as mkdir3, open, readFile as readFile2, rename, rm as rm2, symlink, writeFile as writeFile2 } from "node:fs/promises";
268
- import { spawn } from "node:child_process";
269
- import { homedir as homedir2 } from "node:os";
270
- import { dirname as dirname4, join, resolve as resolve4 } from "node:path";
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";
415
+ import { spawn as spawn2 } from "node:child_process";
416
+ import { homedir as homedir3 } from "node:os";
417
+ import { dirname as dirname4, join, resolve as resolve6 } from "node:path";
271
418
  function anchorLayout(rawLibDir) {
272
- const libDir = resolve4(rawLibDir);
419
+ const libDir = resolve6(rawLibDir);
273
420
  const segments = libDir.split(/[/\\]/);
274
421
  const idx = segments.lastIndexOf(RELEASES_SEGMENT);
275
422
  if (idx >= 2 && segments[idx - 1] === "lib") {
@@ -285,9 +432,9 @@ function anchorLayout(rawLibDir) {
285
432
  // prefix's bin, NOT <prefix>/lib/bin — deriving it one level up was the
286
433
  // defect that made activateRelease write its stable forwarders where
287
434
  // nothing executed them, leaving stale raw wrappers in <prefix>/bin.
288
- binDir: resolve4(libDir, "../../bin"),
435
+ binDir: resolve6(libDir, "../../bin"),
289
436
  libDir,
290
- releasesRoot: resolve4(libDir, `../${RELEASES_SEGMENT}`)
437
+ releasesRoot: resolve6(libDir, `../${RELEASES_SEGMENT}`)
291
438
  };
292
439
  }
293
440
  function beelineInstallLayout(env = process.env) {
@@ -299,18 +446,18 @@ function beelineInstallLayout(env = process.env) {
299
446
  function releaseIdFromPath(path) {
300
447
  if (!path?.trim())
301
448
  return void 0;
302
- const segments = resolve4(path.trim()).split(/[/\\]/);
449
+ const segments = resolve6(path.trim()).split(/[/\\]/);
303
450
  const idx = segments.lastIndexOf(RELEASES_SEGMENT);
304
451
  const id = idx >= 0 ? segments[idx + 1] : void 0;
305
452
  return id ? sanitizeReleaseId(id) : void 0;
306
453
  }
307
454
  function runningReleaseId(layout, env = process.env, invocationPath = process.argv[1]) {
308
- const releasesRoot = resolve4(layout.releasesRoot);
309
- const anchor = resolve4(layout.libDir);
455
+ const releasesRoot = resolve6(layout.releasesRoot);
456
+ const anchor = resolve6(layout.libDir);
310
457
  for (const raw of [env.BEELINE_LIB_DIR, invocationPath]) {
311
458
  if (!raw?.trim())
312
459
  continue;
313
- const resolved = resolve4(raw.trim());
460
+ const resolved = resolve6(raw.trim());
314
461
  if (resolved !== anchor && !resolved.startsWith(`${releasesRoot}/`))
315
462
  continue;
316
463
  const id = releaseIdFromPath(resolved);
@@ -320,8 +467,8 @@ function runningReleaseId(layout, env = process.env, invocationPath = process.ar
320
467
  return void 0;
321
468
  }
322
469
  function defaultBeelineInstallLayout(env = process.env) {
323
- const home = env.HOME?.trim() || homedir2();
324
- return anchorLayout(resolve4(home, ".local", "lib", "beeline"));
470
+ const home = env.HOME?.trim() || homedir3();
471
+ return anchorLayout(resolve6(home, ".local", "lib", "beeline"));
325
472
  }
326
473
  function discoveredBeelineInstallLayout(env = process.env) {
327
474
  const explicitAnchor = env.BEELINE_INSTALL_LIB_DIR?.trim();
@@ -329,7 +476,7 @@ function discoveredBeelineInstallLayout(env = process.env) {
329
476
  return anchorLayout(explicitAnchor);
330
477
  const explicitBinDir = env.BEELINE_INSTALL_DIR?.trim();
331
478
  if (explicitBinDir)
332
- return anchorLayout(resolve4(dirname4(resolve4(explicitBinDir)), "lib", "beeline"));
479
+ return anchorLayout(resolve6(dirname4(resolve6(explicitBinDir)), "lib", "beeline"));
333
480
  return defaultBeelineInstallLayout(env);
334
481
  }
335
482
  function hostPlatformKey() {
@@ -422,7 +569,7 @@ function sanitizeReleaseId(id) {
422
569
  }
423
570
  async function pathKind(path) {
424
571
  try {
425
- const info = await lstat2(path);
572
+ const info = await lstat3(path);
426
573
  if (info.isSymbolicLink())
427
574
  return "symlink";
428
575
  return info.isDirectory() ? "directory" : "missing";
@@ -470,7 +617,7 @@ async function fetchText(url, fetchImpl) {
470
617
  }
471
618
  function run(command, args, timeoutMs) {
472
619
  return new Promise((resolveRun) => {
473
- const child = spawn(command, args, { stdio: ["ignore", "ignore", "pipe"] });
620
+ const child = spawn2(command, args, { stdio: ["ignore", "ignore", "pipe"] });
474
621
  let stderr = "";
475
622
  child.stderr?.setEncoding("utf8");
476
623
  child.stderr?.on("data", (chunk) => {
@@ -566,7 +713,7 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
566
713
  }
567
714
  await writeFile2(tempArchive, Buffer.concat(chunks), { mode: 384 });
568
715
  const entries = (await new Promise((resolveList, rejectList) => {
569
- const child = spawn("tar", ["-tzf", tempArchive], { stdio: ["ignore", "pipe", "inherit"] });
716
+ const child = spawn2("tar", ["-tzf", tempArchive], { stdio: ["ignore", "pipe", "inherit"] });
570
717
  const timer = setTimeout(() => child.kill("SIGKILL"), Math.min(3e4, remaining()));
571
718
  let out = "";
572
719
  child.stdout?.on("data", (chunk) => {
@@ -619,10 +766,10 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
619
766
  return releaseId;
620
767
  } catch (error) {
621
768
  if (!previouslyVerified)
622
- await rm2(releaseDir, { recursive: true, force: true });
769
+ await rm3(releaseDir, { recursive: true, force: true });
623
770
  throw error;
624
771
  } finally {
625
- await rm2(tempArchive, { force: true });
772
+ await rm3(tempArchive, { force: true });
626
773
  }
627
774
  }
628
775
  function forwarderScript(tool) {
@@ -656,12 +803,13 @@ function forwarderScript(tool) {
656
803
  async function replaceFile(path, contents, mode) {
657
804
  const temp = `${path}.new-${process.pid}`;
658
805
  await writeFile2(temp, contents, { mode });
659
- await chmod(temp, mode);
806
+ await chmod2(temp, mode);
660
807
  await rename(temp, path);
661
808
  }
662
809
  async function activateRelease(layout, releaseId) {
663
810
  assertInstallTestIsolation(layout);
664
811
  let releaseDir = join(layout.releasesRoot, releaseId);
812
+ let previousReleaseId = await activeReleaseId(layout);
665
813
  await access(join(releaseDir, BUNDLE_ENTRYPOINT), fsConstants.F_OK);
666
814
  await mkdir3(layout.releasesRoot, { recursive: true });
667
815
  await mkdir3(layout.binDir, { recursive: true });
@@ -675,27 +823,36 @@ async function activateRelease(layout, releaseId) {
675
823
  const preservedId = `${legacyId}-${Date.now()}`;
676
824
  await rename(layout.libDir, join(layout.releasesRoot, preservedId));
677
825
  await normalizeLegacyBundleShape(join(layout.releasesRoot, preservedId));
826
+ previousReleaseId = preservedId;
678
827
  } catch {
679
828
  await rename(layout.libDir, legacyDir);
680
829
  await normalizeLegacyBundleShape(legacyDir);
830
+ previousReleaseId = legacyId;
681
831
  }
682
832
  }
683
833
  const tempLink = `${layout.libDir}.new-${process.pid}`;
684
- await rm2(tempLink, { force: true });
834
+ await rm3(tempLink, { force: true });
685
835
  await symlink(join("beeline-releases", releaseId), tempLink);
686
836
  await rename(tempLink, layout.libDir);
687
837
  await fsyncDir(dirname4(layout.libDir));
688
838
  await installRecoveryLauncher(layout, releaseDir);
689
839
  await writeBinForwarders(layout, releaseDir);
840
+ const state = await readUpdateState(layout);
841
+ await writeUpdateState(layout, {
842
+ ...state,
843
+ stagedReleaseId: void 0,
844
+ previousReleaseId: previousReleaseId && previousReleaseId !== releaseId ? previousReleaseId : state.previousReleaseId
845
+ });
846
+ await pruneHelperReleases(layout);
690
847
  }
691
848
  async function installRecoveryLauncher(layout, releaseDir) {
692
849
  const bootstrap = join(releaseDir, "lib/beeline/recovery-cli.mjs");
693
850
  if (await access(bootstrap).then(() => true, () => false)) {
694
- const stable = resolve4(layout.libDir, "../beeline-bootstrap.mjs");
851
+ const stable = resolve6(layout.libDir, "../beeline-bootstrap.mjs");
695
852
  const temporary = `${stable}.${process.pid}.tmp`;
696
853
  await copyFile(bootstrap, temporary);
697
854
  await rename(temporary, stable);
698
- await replaceFile(resolve4(layout.libDir, "../beeline-node-path"), `${process.execPath}
855
+ await replaceFile(resolve6(layout.libDir, "../beeline-node-path"), `${process.execPath}
699
856
  `, 384);
700
857
  }
701
858
  }
@@ -734,7 +891,7 @@ async function writeBinForwarders(layout, activeBundleRoot) {
734
891
  } catch {
735
892
  continue;
736
893
  }
737
- const independent = await access(resolve4(layout.libDir, "../beeline-bootstrap.mjs")).then(() => true, () => false);
894
+ const independent = await access(resolve6(layout.libDir, "../beeline-bootstrap.mjs")).then(() => true, () => false);
738
895
  await replaceFile(join(layout.binDir, name), independent || tool !== "beeline" ? forwarderScript(tool) : forwarderScript("legacy-beeline").replace("/bin/legacy-beeline", "/bin/beeline"), 493);
739
896
  }
740
897
  }
@@ -750,7 +907,7 @@ async function repairInstallForwarders(layout, opts = {}) {
750
907
  } catch {
751
908
  current = void 0;
752
909
  }
753
- const independent = await access(resolve4(layout.libDir, "../beeline-bootstrap.mjs")).then(() => true, () => false);
910
+ const independent = await access(resolve6(layout.libDir, "../beeline-bootstrap.mjs")).then(() => true, () => false);
754
911
  const expected = independent || tool !== "beeline" ? forwarderScript(tool) : forwarderScript("legacy-beeline").replace("/bin/legacy-beeline", "/bin/beeline");
755
912
  return current === expected;
756
913
  };
@@ -789,6 +946,7 @@ async function prepareLatestRelease(layout, options = {}) {
789
946
  deadlineAt: options.deadlineAt
790
947
  });
791
948
  await writeUpdateState(layout, {
949
+ ...await readUpdateState(layout),
792
950
  lastCheckAt: Date.now(),
793
951
  lastCheckResult: "verified",
794
952
  stagedReleaseId: releaseId
@@ -804,10 +962,53 @@ async function prepareLatestRelease(layout, options = {}) {
804
962
  throw error;
805
963
  }
806
964
  }
965
+ async function pruneHelperReleases(layout, loadedRelease) {
966
+ assertInstallTestIsolation(layout);
967
+ if (!await ordinaryDirectory(layout.releasesRoot))
968
+ return [];
969
+ const active = await activeReleaseId(layout);
970
+ if (!active)
971
+ return [];
972
+ const state = await readUpdateState(layout);
973
+ const candidates = [];
974
+ for (const entry of await readdir3(layout.releasesRoot, { withFileTypes: true })) {
975
+ if (entry.name.startsWith("."))
976
+ continue;
977
+ if (entry.isSymbolicLink()) {
978
+ if (![active, state.previousReleaseId, state.stagedReleaseId, loadedRelease].includes(entry.name))
979
+ await rm3(join(layout.releasesRoot, entry.name), { force: true });
980
+ continue;
981
+ }
982
+ if (!entry.isDirectory())
983
+ continue;
984
+ const path = join(layout.releasesRoot, entry.name);
985
+ if (!await ordinaryDirectory(path))
986
+ continue;
987
+ candidates.push({
988
+ id: entry.name,
989
+ modified: (await lstat3(path)).mtimeMs,
990
+ bootable: await access(join(path, BUNDLE_ENTRYPOINT)).then(() => true, () => false)
991
+ });
992
+ }
993
+ const recordedPrevious = candidates.find((entry) => entry.id === state.previousReleaseId && entry.id !== active && entry.bootable)?.id;
994
+ const previous = recordedPrevious ?? candidates.filter((entry) => entry.bootable && entry.id !== active && entry.id !== state.stagedReleaseId).sort((a, b) => b.modified - a.modified)[0]?.id;
995
+ const keep = /* @__PURE__ */ new Set([active, previous, loadedRelease, state.stagedReleaseId]);
996
+ const removed = [];
997
+ for (const entry of candidates) {
998
+ if (keep.has(entry.id))
999
+ continue;
1000
+ await removeStoragePath(join(layout.releasesRoot, entry.id));
1001
+ removed.push(entry.id);
1002
+ }
1003
+ if (previous !== state.previousReleaseId)
1004
+ await writeUpdateState(layout, { ...state, previousReleaseId: previous });
1005
+ return removed;
1006
+ }
807
1007
  var RELEASES_SEGMENT, STAGED_NODE_PATH_FILE, BUNDLE_ENTRYPOINT, PI_MCP_ADAPTER_ENTRYPOINT, CODEGRAPH_ENTRYPOINT, FORWARDER_TOOLS, FORWARDER_ALIASES, LEGACY_FLAT_BUNDLE_FILES, SelfUpdateManager;
808
1008
  var init_self_update = __esm({
809
1009
  "apps/body/dist/self-update.js"() {
810
1010
  "use strict";
1011
+ init_storage_filesystem();
811
1012
  init_lifecycle_test_guard();
812
1013
  init_self_update_manifest();
813
1014
  RELEASES_SEGMENT = "beeline-releases";
@@ -859,10 +1060,10 @@ __export(managed_update_exports, {
859
1060
  versionAtLeast: () => versionAtLeast,
860
1061
  withInstallLock: () => withInstallLock
861
1062
  });
862
- import { spawn as spawn2 } from "node:child_process";
863
- import { resolve as resolve5 } from "node:path";
1063
+ import { spawn as spawn3 } from "node:child_process";
1064
+ import { resolve as resolve7 } from "node:path";
864
1065
  function withInstallLock(layout, work, options = {}) {
865
- return withKernelLock(`beeline-install:${resolve5(layout.libDir)}`, work, options.waitMs);
1066
+ return withKernelLock(`beeline-install:${resolve7(layout.libDir)}`, work, options.waitMs);
866
1067
  }
867
1068
  function versionAtLeast(actual, minimum) {
868
1069
  const parse = (value) => /^v?(\d+)\.(\d+)\.(\d+)$/.exec(value)?.slice(1).map(Number);
@@ -887,9 +1088,9 @@ async function runManagedUpdateWorker() {
887
1088
  }
888
1089
  async function prepareReleaseInWorker(env, deadlineAt, entrypoint) {
889
1090
  const layout = beelineInstallLayout(env);
890
- const bootstrap = entrypoint ?? resolve5(layout.libDir, "../beeline-bootstrap.mjs");
1091
+ const bootstrap = entrypoint ?? resolve7(layout.libDir, "../beeline-bootstrap.mjs");
891
1092
  return new Promise((done, reject) => {
892
- const child = spawn2(process.execPath, [bootstrap, "managed-update-worker"], {
1093
+ const child = spawn3(process.execPath, [bootstrap, "managed-update-worker"], {
893
1094
  detached: true,
894
1095
  env: {
895
1096
  ...env,
@@ -993,7 +1194,7 @@ var init_managed_update = __esm({
993
1194
  if (this.#minimum) {
994
1195
  const identity = await readInstalledBundleIdentity({
995
1196
  ...this.options.layout,
996
- libDir: resolve5(this.options.layout.releasesRoot, releaseId)
1197
+ libDir: resolve7(this.options.layout.releasesRoot, releaseId)
997
1198
  });
998
1199
  if (!identity?.version || !versionAtLeast(identity.version, this.#minimum)) {
999
1200
  this.#prepared = void 0;
@@ -1075,13 +1276,13 @@ var init_managed_update = __esm({
1075
1276
  });
1076
1277
 
1077
1278
  // apps/body/dist/recovery-cli.js
1078
- import { spawn as spawn3 } from "node:child_process";
1079
- import { readFile as readFile4, readdir as readdir3, stat as stat2, unlink } from "node:fs/promises";
1080
- import { resolve as resolve7 } from "node:path";
1279
+ import { spawn as spawn4 } from "node:child_process";
1280
+ import { readFile as readFile4, readdir as readdir5, stat as stat2, unlink } from "node:fs/promises";
1281
+ import { resolve as resolve9 } from "node:path";
1081
1282
 
1082
1283
  // apps/body/dist/recovery.js
1083
- import { readFile as readFile3, readdir as readdir2, stat } from "node:fs/promises";
1084
- import { resolve as resolve6 } from "node:path";
1284
+ import { readFile as readFile3, readdir as readdir4, stat } from "node:fs/promises";
1285
+ import { resolve as resolve8 } from "node:path";
1085
1286
 
1086
1287
  // apps/body/dist/machine-control.js
1087
1288
  import { watch } from "node:fs";
@@ -1449,7 +1650,7 @@ async function prepareMachineRelease(layout, options = {}) {
1449
1650
  return withInstallLock(layout, () => prepareLatestRelease(layout, { ...options, deadlineAt }), {
1450
1651
  waitMs: Math.max(0, deadlineAt - Date.now())
1451
1652
  });
1452
- const stable = resolve6(layout.libDir, "../beeline-bootstrap.mjs");
1653
+ const stable = resolve8(layout.libDir, "../beeline-bootstrap.mjs");
1453
1654
  const entrypoint = env.BEELINE_RECOVERY_ENTRY || await readFile3(stable).then(() => stable, () => process.argv[1]);
1454
1655
  return prepareReleaseInWorker({ ...env, ...options?.force ? { BEELINE_FORCE_REPAIR: "1" } : {} }, deadlineAt, entrypoint);
1455
1656
  }
@@ -1458,9 +1659,9 @@ async function convergeMachine(options = {}) {
1458
1659
  assertLifecycleTestIsolation(env, Boolean(options.run));
1459
1660
  const layout = options.layout ?? beelineInstallLayout(env) ?? discoveredBeelineInstallLayout(env);
1460
1661
  const deadlineAt = options.deadlineAt ?? Date.now() + (options.timeoutMs ?? 6e5);
1461
- const stateRoot = env.XDG_STATE_HOME || resolve6(env.HOME || "", ".local/state");
1462
- const root = resolve6(stateRoot, "beeline/agents");
1463
- const configured = await Promise.all((await readdir2(root).catch(() => [])).filter((id) => /^[0-9a-f]{64}$/i.test(id)).map(async (id) => await stat(resolve6(root, id, "runtime.json")).then(() => true, () => false) && !await stat(resolve6(root, id, "stopped")).then(() => true, () => false) ? id : void 0));
1662
+ const stateRoot = env.XDG_STATE_HOME || resolve8(env.HOME || "", ".local/state");
1663
+ const root = resolve8(stateRoot, "beeline/agents");
1664
+ const configured = await Promise.all((await readdir4(root).catch(() => [])).filter((id) => /^[0-9a-f]{64}$/i.test(id)).map(async (id) => await stat(resolve8(root, id, "runtime.json")).then(() => true, () => false) && !await stat(resolve8(root, id, "stopped")).then(() => true, () => false) ? id : void 0));
1464
1665
  const required = /* @__PURE__ */ new Set([
1465
1666
  ...configured.filter((id) => Boolean(id)),
1466
1667
  ...options.agentIds ?? []
@@ -1481,7 +1682,7 @@ async function convergeMachine(options = {}) {
1481
1682
  let expectedRelease = options.releaseId;
1482
1683
  const targetIdentity = options.releaseId ? await readInstalledBundleIdentity({
1483
1684
  ...layout,
1484
- libDir: resolve6(layout.releasesRoot, options.releaseId)
1685
+ libDir: resolve8(layout.releasesRoot, options.releaseId)
1485
1686
  }) : void 0;
1486
1687
  const request = options.releaseId && hasControl ? {
1487
1688
  operation: "update",
@@ -1528,7 +1729,7 @@ async function bootstrapMachine(env = process.env) {
1528
1729
  } catch (error) {
1529
1730
  const state = await readUpdateState(layout);
1530
1731
  const candidates = [state.stagedReleaseId, await activeReleaseId(layout)];
1531
- const verified = await Promise.all(candidates.map(async (id) => id && /^[0-9a-f]{64}$/i.test((await readFile3(resolve6(layout.releasesRoot, id, ".stage-ok"), "utf8").catch(() => "")).trim()) ? id : void 0));
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));
1532
1733
  const candidate = verified.find(Boolean);
1533
1734
  if (!candidate)
1534
1735
  throw new Error(`startup release selection failed; no verified runnable release: ${String(error)}`);
@@ -1538,7 +1739,7 @@ async function bootstrapMachine(env = process.env) {
1538
1739
  waitMs: Math.max(0, bootDeadlineAt - Date.now())
1539
1740
  });
1540
1741
  }
1541
- const entry = await resolveBundleEntrypoint(resolve6(layout.releasesRoot, releaseId));
1742
+ const entry = await resolveBundleEntrypoint(resolve8(layout.releasesRoot, releaseId));
1542
1743
  if (!entry)
1543
1744
  throw new Error(`selected release ${releaseId} has no body entry`);
1544
1745
  return entry;
@@ -1599,18 +1800,18 @@ async function main() {
1599
1800
  if (args[i] === "--manifest-url" && !args[++i])
1600
1801
  throw new Error("--manifest-url requires a URL");
1601
1802
  }
1602
- const stateRoot2 = process.env.XDG_STATE_HOME || resolve7(process.env.HOME || "", ".local/state");
1803
+ const stateRoot2 = process.env.XDG_STATE_HOME || resolve9(process.env.HOME || "", ".local/state");
1603
1804
  if (args.includes("--status")) {
1604
1805
  const [native, helper] = await Promise.all([
1605
1806
  nativeHelperStatus(),
1606
1807
  requestMachine(stateRoot2, { operation: "status" }, () => true, 2e3).catch(() => void 0)
1607
1808
  ]);
1608
- const root = resolve7(stateRoot2, "beeline/agents");
1609
- const agents = await Promise.all((await readdir3(root).catch(() => [])).filter((id) => /^[0-9a-f]{64}$/.test(id)).map(async (id) => ({
1809
+ const root = resolve9(stateRoot2, "beeline/agents");
1810
+ const agents = await Promise.all((await readdir5(root).catch(() => [])).filter((id) => /^[0-9a-f]{64}$/.test(id)).map(async (id) => ({
1610
1811
  agentId: id,
1611
- enabled: !await stat2(resolve7(root, id, "stopped")).then(() => true, () => false),
1812
+ enabled: !await stat2(resolve9(root, id, "stopped")).then(() => true, () => false),
1612
1813
  ...helper?.agents[id] ?? { state: "not hosted" },
1613
- validRecord: await readFile4(resolve7(root, id, "runtime.json"), "utf8").then((raw) => Boolean(JSON.parse(raw).agent)).catch(() => false)
1814
+ validRecord: await readFile4(resolve9(root, id, "runtime.json"), "utf8").then((raw) => Boolean(JSON.parse(raw).agent)).catch(() => false)
1614
1815
  })));
1615
1816
  console.log(JSON.stringify({
1616
1817
  native,
@@ -1660,7 +1861,7 @@ async function main() {
1660
1861
  console.log(`[beeline] executing release ${status.loadedRelease}; helper ${status.pid}; every enabled agent serving`);
1661
1862
  return;
1662
1863
  }
1663
- const stateRoot = process.env.XDG_STATE_HOME || resolve7(process.env.HOME || "", ".local/state");
1864
+ const stateRoot = process.env.XDG_STATE_HOME || resolve9(process.env.HOME || "", ".local/state");
1664
1865
  let selectedRelease;
1665
1866
  if (command === "start") {
1666
1867
  for (let i = 1; i < args.length; i++) {
@@ -1675,13 +1876,13 @@ async function main() {
1675
1876
  const requested = agentFlag >= 0 ? args[agentFlag + 1] : args[1] && !args[1].startsWith("--") ? args[1] : void 0;
1676
1877
  if (agentFlag >= 0 && !requested)
1677
1878
  throw new Error("--agent requires an agent public key");
1678
- const agentRoot = resolve7(stateRoot, "beeline/agents");
1679
- const ids = (await readdir3(agentRoot).catch(() => [])).filter((id) => /^[0-9a-f]{64}$/.test(id));
1879
+ const agentRoot = resolve9(stateRoot, "beeline/agents");
1880
+ const ids = (await readdir5(agentRoot).catch(() => [])).filter((id) => /^[0-9a-f]{64}$/.test(id));
1680
1881
  const selected = requested ? ids.filter((id) => id.startsWith(requested)) : args.includes("--all") ? ids : [];
1681
1882
  if (requested && selected.length !== 1)
1682
1883
  throw new Error(`no unique paired agent matches ${requested}`);
1683
1884
  for (const id of selected)
1684
- await unlink(resolve7(agentRoot, id, "stopped")).catch((error) => {
1885
+ await unlink(resolve9(agentRoot, id, "stopped")).catch((error) => {
1685
1886
  if (error.code !== "ENOENT")
1686
1887
  throw error;
1687
1888
  });
@@ -1705,7 +1906,7 @@ async function main() {
1705
1906
  const entry = await resolveBundleEntrypoint(layout.libDir);
1706
1907
  if (!entry)
1707
1908
  throw new Error("no installed Beeline body; run npx usebeeline connect");
1708
- const child = spawn3(process.execPath, [entry, ...args], {
1909
+ const child = spawn4(process.execPath, [entry, ...args], {
1709
1910
  env: {
1710
1911
  ...process.env,
1711
1912
  BEELINE_LIB_DIR: layout.libDir,
@@ -1723,7 +1924,7 @@ async function convergeDependencies(layout, deadlineAt) {
1723
1924
  if (!entry)
1724
1925
  throw new Error("dependency phase has no selected body");
1725
1926
  await new Promise((done, reject) => {
1726
- const child = spawn3(process.execPath, [entry, "converge-dependencies"], {
1927
+ const child = spawn4(process.execPath, [entry, "converge-dependencies"], {
1727
1928
  env: { ...process.env, BEELINE_LIB_DIR: layout.libDir, BEELINE_INTERNAL_RECOVERY: "1" },
1728
1929
  stdio: "inherit"
1729
1930
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usebeeline",
3
- "version": "0.1.56",
3
+ "version": "0.1.58",
4
4
  "description": "Connect an AI coding agent to Beeline with one command.",
5
5
  "homepage": "https://usebeeline.app",
6
6
  "bugs": {