usebeeline 0.1.24 → 0.1.26

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 +187 -85
  2. package/package.json +1 -1
@@ -563,7 +563,7 @@ var init_squire_broker_squatter = __esm({
563
563
 
564
564
  // apps/body/dist/squire-host.js
565
565
  import { spawn as spawn4 } from "node:child_process";
566
- import { accessSync, constants as fsConstants, existsSync as existsSync3, mkdirSync, realpathSync as realpathSync2, statSync, writeFileSync } from "node:fs";
566
+ import { accessSync, constants as fsConstants, existsSync as existsSync3, lstatSync, mkdirSync, mkdtempSync, readFileSync as readFileSync2, realpathSync as realpathSync2, renameSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
567
567
  import { createRequire as createRequire3 } from "node:module";
568
568
  import { createConnection as createConnection2 } from "node:net";
569
569
  import { homedir } from "node:os";
@@ -666,18 +666,90 @@ function squireBrokerInstallDir(home) {
666
666
  function squireBrokerInstallEntry(home) {
667
667
  return join2(squireBrokerInstallDir(home), "node_modules", "@trusty-squire", "mcp", "dist", "bin.js");
668
668
  }
669
- async function ensureSquireBrokerInstall(home, options = {}) {
669
+ function versionParts(version) {
670
+ if (!/^\d+\.\d+\.\d+$/.test(version))
671
+ return void 0;
672
+ return version.split(".").map(Number);
673
+ }
674
+ function compareSquireVersions(left, right) {
675
+ const a2 = versionParts(left);
676
+ const b = versionParts(right);
677
+ if (!a2 || !b)
678
+ throw new Error(`Invalid Trusty Squire version: ${!a2 ? left : right}`);
679
+ for (let i3 = 0; i3 < 3; i3++) {
680
+ if (a2[i3] !== b[i3])
681
+ return a2[i3] - b[i3];
682
+ }
683
+ return 0;
684
+ }
685
+ function squireBrokerInstalledVersion(home) {
686
+ if (!existsSync3(squireBrokerInstallEntry(home)))
687
+ return void 0;
688
+ try {
689
+ const version = JSON.parse(readFileSync2(squirePackagePath(squireBrokerInstallDir(home)), "utf8")).version;
690
+ return typeof version === "string" && versionParts(version) ? version : void 0;
691
+ } catch {
692
+ return void 0;
693
+ }
694
+ }
695
+ function squireBrokerMeetsComputerUseMinimum(home) {
696
+ const version = squireBrokerInstalledVersion(home);
697
+ return version !== void 0 && compareSquireVersions(version, SQUIRE_COMPUTER_USE_MIN_VERSION) >= 0;
698
+ }
699
+ async function updateSquireBrokerInstall(home, options = {}) {
670
700
  const entry = squireBrokerInstallEntry(home);
671
- if (existsSync3(entry))
672
- return entry;
701
+ const installed = squireBrokerInstalledVersion(home);
702
+ if (options.mode === "minimum" && installed && compareSquireVersions(installed, SQUIRE_COMPUTER_USE_MIN_VERSION) >= 0)
703
+ return { entry, changed: false };
673
704
  const dir = squireBrokerInstallDir(home);
674
- mkdirSync(dir, { recursive: true, mode: 448 });
705
+ mkdirSync(dirname2(dir), { recursive: true, mode: 448 });
675
706
  const run2 = options.run ?? defaultSquireInstallRunner;
676
- const spec = options.spec ?? `${SQUIRE_MCP_PACKAGE_NAME}@latest`;
677
- const result = await run2("npm", ["install", "--prefix", dir, spec, "--no-save", "--no-audit", "--no-fund", "--no-package-lock"], { cwd: dir });
678
- if (result.code !== 0 || !existsSync3(entry))
679
- throw new Error(`Trusty Squire broker install failed: ${result.stderr.trim() || `${entry} is missing`}`);
680
- return entry;
707
+ const view = await run2("npm", ["view", `${SQUIRE_MCP_PACKAGE_NAME}@latest`, "version"], { cwd: dirname2(dir) });
708
+ const latest = view.stdout?.trim() ?? "";
709
+ if (view.code !== 0 || !versionParts(latest))
710
+ throw new Error(`Trusty Squire version lookup failed: ${view.stderr.trim() || latest || "no version returned"}`);
711
+ if (compareSquireVersions(latest, SQUIRE_COMPUTER_USE_MIN_VERSION) < 0)
712
+ throw new Error(`Trusty Squire ${latest} is older than required ${SQUIRE_COMPUTER_USE_MIN_VERSION}`);
713
+ if (installed && compareSquireVersions(installed, latest) >= 0)
714
+ return { entry, changed: false };
715
+ const candidate = mkdtempSync(join2(dirname2(dir), `${SQUIRE_BROKER_INSTALL_DIRNAME}-next-`));
716
+ const link2 = join2(dirname2(dir), `${SQUIRE_BROKER_INSTALL_DIRNAME}-link-${basename2(candidate)}`);
717
+ let activated = false;
718
+ try {
719
+ const install = await run2("npm", ["install", "--prefix", candidate, `${SQUIRE_MCP_PACKAGE_NAME}@${latest}`, "--no-save", "--no-audit", "--no-fund", "--no-package-lock"], { cwd: candidate });
720
+ let candidateVersion;
721
+ try {
722
+ candidateVersion = JSON.parse(readFileSync2(squirePackagePath(candidate), "utf8")).version;
723
+ } catch {
724
+ }
725
+ if (install.code !== 0 || !existsSync3(squireEntryPath(candidate)) || candidateVersion !== latest)
726
+ throw new Error(`Trusty Squire broker install failed: ${install.stderr.trim() || "candidate entry or version is missing"}`);
727
+ symlinkSync(basename2(candidate), link2);
728
+ if (existsSync3(dir)) {
729
+ const previous = realpathSync2(dir);
730
+ const backup = join2(dirname2(dir), `${SQUIRE_BROKER_INSTALL_DIRNAME}.bak-${installed ?? "unknown"}-${basename2(candidate)}`);
731
+ if (!lstatSync(dir).isSymbolicLink()) {
732
+ renameSync(dir, backup);
733
+ try {
734
+ renameSync(link2, dir);
735
+ } catch (error) {
736
+ renameSync(backup, dir);
737
+ throw error;
738
+ }
739
+ } else {
740
+ symlinkSync(previous, backup);
741
+ renameSync(link2, dir);
742
+ }
743
+ } else {
744
+ renameSync(link2, dir);
745
+ }
746
+ activated = true;
747
+ return { entry, changed: true };
748
+ } finally {
749
+ if (!activated)
750
+ rmSync(candidate, { recursive: true, force: true });
751
+ rmSync(link2, { force: true });
752
+ }
681
753
  }
682
754
  function trustySquireBrokerUnit(nodeExecPath = process.execPath) {
683
755
  return `[Unit]
@@ -728,7 +800,9 @@ async function runSquireBroker(env = process.env) {
728
800
  }
729
801
  let entry;
730
802
  try {
731
- entry = await ensureSquireBrokerInstall(home);
803
+ entry = squireBrokerInstallEntry(home);
804
+ if (!existsSync3(entry))
805
+ throw new Error("durable broker entry is missing");
732
806
  } catch (error) {
733
807
  process.stderr.write(`[beeline] Trusty Squire broker not started: ${error instanceof Error ? error.message : String(error)}
734
808
  `);
@@ -759,7 +833,7 @@ async function runSquireFacade(env = process.env) {
759
833
  });
760
834
  process.exit(ok ? 0 : 1);
761
835
  }
762
- var SQUIRE_BROKER_UNAVAILABLE, TRUSTY_SQUIRE_BROKER_UNIT_NAME, SQUIRE_FACADE_FLAG, SQUIRE_BROKER_FLAG, SQUIRE_MCP_PACKAGE_NAME, SQUIRE_BROKER_START_LIMIT_INTERVAL_SEC, SQUIRE_BROKER_START_LIMIT_BURST, SQUIRE_BROKER_UNIT_MARKER_FILE, SQUIRE_BROKER_INSTALL_DIRNAME, defaultSquireInstallRunner;
836
+ var SQUIRE_BROKER_UNAVAILABLE, TRUSTY_SQUIRE_BROKER_UNIT_NAME, SQUIRE_FACADE_FLAG, SQUIRE_BROKER_FLAG, SQUIRE_MCP_PACKAGE_NAME, SQUIRE_COMPUTER_USE_MIN_VERSION, SQUIRE_BROKER_START_LIMIT_INTERVAL_SEC, SQUIRE_BROKER_START_LIMIT_BURST, SQUIRE_BROKER_UNIT_MARKER_FILE, SQUIRE_BROKER_INSTALL_DIRNAME, defaultSquireInstallRunner, squirePackagePath, squireEntryPath;
763
837
  var init_squire_host = __esm({
764
838
  "apps/body/dist/squire-host.js"() {
765
839
  "use strict";
@@ -770,19 +844,26 @@ var init_squire_host = __esm({
770
844
  SQUIRE_FACADE_FLAG = "--squire-facade";
771
845
  SQUIRE_BROKER_FLAG = "--squire-broker";
772
846
  SQUIRE_MCP_PACKAGE_NAME = "@trusty-squire/mcp";
847
+ SQUIRE_COMPUTER_USE_MIN_VERSION = "1.1.32";
773
848
  SQUIRE_BROKER_START_LIMIT_INTERVAL_SEC = 60;
774
849
  SQUIRE_BROKER_START_LIMIT_BURST = 6;
775
850
  SQUIRE_BROKER_UNIT_MARKER_FILE = ".trusty-squire-broker-unit.json";
776
851
  SQUIRE_BROKER_INSTALL_DIRNAME = "mcp-broker-install";
777
852
  defaultSquireInstallRunner = (command, args, options) => new Promise((resolveRun) => {
778
- const child = spawn4(command, [...args], { cwd: options.cwd, stdio: ["ignore", "ignore", "pipe"] });
853
+ const child = spawn4(command, [...args], { cwd: options.cwd, stdio: ["ignore", "pipe", "pipe"] });
779
854
  let stderr = "";
855
+ let stdout6 = "";
856
+ child.stdout?.on("data", (chunk) => {
857
+ stdout6 += chunk.toString("utf8");
858
+ });
780
859
  child.stderr?.on("data", (chunk) => {
781
860
  stderr += chunk.toString("utf8");
782
861
  });
783
862
  child.once("error", (error) => resolveRun({ code: 1, stderr: error.message }));
784
- child.once("close", (code) => resolveRun({ code, stderr }));
863
+ child.once("close", (code) => resolveRun({ code, stderr, stdout: stdout6 }));
785
864
  });
865
+ squirePackagePath = (dir) => join2(dir, "node_modules", "@trusty-squire", "mcp", "package.json");
866
+ squireEntryPath = (dir) => join2(dir, "node_modules", "@trusty-squire", "mcp", "dist", "bin.js");
786
867
  }
787
868
  });
788
869
 
@@ -4684,7 +4765,7 @@ async function installTrustySquireBrokerService(options = {}) {
4684
4765
  assertCanonicalInstalledLauncher(env, options.invocationPath);
4685
4766
  const home = env.HOME?.trim() || homedir6();
4686
4767
  writeSquireBrokerUnitMarker(home);
4687
- await ensureSquireBrokerInstall(home, options.squireInstallRun ? { run: options.squireInstallRun } : {});
4768
+ const install = await updateSquireBrokerInstall(home, { ...options.squireInstallRun ? { run: options.squireInstallRun } : {}, mode: options.squireUpdateMode ?? "latest" });
4688
4769
  const path = systemdBrokerUnitPath(env);
4689
4770
  const content = trustySquireBrokerUnit();
4690
4771
  const existing = await readFile6(path, "utf8").catch(() => "");
@@ -4696,7 +4777,7 @@ async function installTrustySquireBrokerService(options = {}) {
4696
4777
  const run2 = options.run ?? runSystemctl;
4697
4778
  await run2(["daemon-reload"]);
4698
4779
  await run2(["enable", TRUSTY_SQUIRE_BROKER_UNIT_NAME]);
4699
- if (changed || options.restart) {
4780
+ if (changed || install.changed || options.restart) {
4700
4781
  await run2(["restart", "--no-block", TRUSTY_SQUIRE_BROKER_UNIT_NAME]);
4701
4782
  } else {
4702
4783
  await run2(["start", TRUSTY_SQUIRE_BROKER_UNIT_NAME]);
@@ -4708,7 +4789,6 @@ async function convergeTrustySquireBrokerService(options) {
4708
4789
  await installTrustySquireBrokerService({
4709
4790
  env: { ...env, BEELINE_LIB_DIR: options.libDir },
4710
4791
  invocationPath: resolve3(options.libDir, "lib", "beeline", "beeline-cli.mjs"),
4711
- restart: true,
4712
4792
  ...options.run ? { run: options.run } : {}
4713
4793
  });
4714
4794
  return true;
@@ -5318,13 +5398,17 @@ async function installLaunchdTrustySquireBrokerService(options = {}) {
5318
5398
  assertCanonicalInstalledLauncher2(env, options.invocationPath);
5319
5399
  const home = launchdHome(env);
5320
5400
  writeSquireBrokerUnitMarker(home);
5401
+ const install = await updateSquireBrokerInstall(home, {
5402
+ ...options.squireInstallRun ? { run: options.squireInstallRun } : {},
5403
+ mode: options.squireUpdateMode ?? "latest"
5404
+ });
5321
5405
  await mkdir5(resolve4(home, "Library", "Logs", "Beeline"), { recursive: true, mode: 448 });
5322
5406
  const plistPath = launchdBrokerPlistPath(env);
5323
5407
  const changed = await writeManagedFile(plistPath, launchdBrokerPlist(env), 384);
5324
5408
  const run2 = options.run ?? runLaunchctl;
5325
5409
  const domain = launchdUserDomain();
5326
5410
  const target = `${domain}/${LAUNCHD_BROKER_LABEL}`;
5327
- if (changed || options.restart)
5411
+ if (changed || install.changed || options.restart)
5328
5412
  await bootoutIfLoaded(run2, target);
5329
5413
  await run2(["enable", target]);
5330
5414
  if ((await launchdStatus(run2, target)).state === "unloaded") {
@@ -5339,7 +5423,6 @@ async function convergeLaunchdTrustySquireBrokerService(options) {
5339
5423
  await installLaunchdTrustySquireBrokerService({
5340
5424
  env: { ...env, BEELINE_LIB_DIR: options.libDir },
5341
5425
  invocationPath: resolve4(options.libDir, "lib", "beeline", "beeline-cli.mjs"),
5342
- restart: true,
5343
5426
  ...options.run ? { run: options.run } : {}
5344
5427
  });
5345
5428
  return true;
@@ -16843,6 +16926,7 @@ var SquireTaskRelay = class {
16843
16926
  authorize;
16844
16927
  makeClient;
16845
16928
  onApprovalDecided;
16929
+ onSessionEnded;
16846
16930
  server;
16847
16931
  url;
16848
16932
  token = randomUUID3();
@@ -16863,6 +16947,7 @@ var SquireTaskRelay = class {
16863
16947
  log: callbacks.onDiagnostic,
16864
16948
  onNotification: callbacks.onNotification
16865
16949
  }), onApprovalDecided = () => {
16950
+ }, onSessionEnded = () => {
16866
16951
  }) {
16867
16952
  this.agentId = agentId;
16868
16953
  this.roomId = roomId;
@@ -16870,6 +16955,11 @@ var SquireTaskRelay = class {
16870
16955
  this.authorize = authorize;
16871
16956
  this.makeClient = makeClient;
16872
16957
  this.onApprovalDecided = onApprovalDecided;
16958
+ this.onSessionEnded = onSessionEnded;
16959
+ }
16960
+ ended(ids) {
16961
+ for (const id of ids)
16962
+ this.onSessionEnded(id);
16873
16963
  }
16874
16964
  async listen() {
16875
16965
  if (this.closed)
@@ -17011,6 +17101,7 @@ var SquireTaskRelay = class {
17011
17101
  sessionId: redactedSessionId(task.sessions.values().next().value)
17012
17102
  });
17013
17103
  forgetSquireSessions(task.sessions);
17104
+ this.ended(task.sessions);
17014
17105
  task.sessions.clear();
17015
17106
  task.pendingApprovals.clear();
17016
17107
  }
@@ -17062,6 +17153,7 @@ var SquireTaskRelay = class {
17062
17153
  });
17063
17154
  this.task.client.close();
17064
17155
  forgetSquireSessions(this.task.sessions);
17156
+ this.ended(this.task.sessions);
17065
17157
  this.task.sessions.clear();
17066
17158
  this.task.pendingApprovals.clear();
17067
17159
  this.task = void 0;
@@ -17145,6 +17237,7 @@ var SquireTaskRelay = class {
17145
17237
  for (const id of requestedIds)
17146
17238
  task.sessions.delete(id);
17147
17239
  forgetSquireSessions(requestedIds);
17240
+ this.ended(requestedIds);
17148
17241
  this.releasePendingApprovals(task, requestedIds);
17149
17242
  this.log("call-error", task, {
17150
17243
  method: input.method,
@@ -17160,6 +17253,7 @@ var SquireTaskRelay = class {
17160
17253
  for (const id of requestedIds)
17161
17254
  task.sessions.delete(id);
17162
17255
  forgetSquireSessions(requestedIds);
17256
+ this.ended(requestedIds);
17163
17257
  this.releasePendingApprovals(task, requestedIds);
17164
17258
  } else if (usingOwnConnection) {
17165
17259
  const created = sessionIds(result);
@@ -17209,6 +17303,7 @@ var SquireTaskRelay = class {
17209
17303
  } catch (error) {
17210
17304
  if (error instanceof Error && /timed out/.test(error.message)) {
17211
17305
  task.dead = true;
17306
+ this.ended(task.sessions);
17212
17307
  task.sessions.clear();
17213
17308
  task.pendingApprovals.clear();
17214
17309
  task.client.close();
@@ -17347,7 +17442,7 @@ var ACCESS_REFUSAL_WINDOW_MS = 60 * 60 * 1e3;
17347
17442
  import { createHash as createHash2, randomBytes } from "node:crypto";
17348
17443
  import { lookup } from "node:dns/promises";
17349
17444
  import { createRequire as createRequire4 } from "node:module";
17350
- import { chmodSync, existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
17445
+ import { chmodSync, existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync3, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
17351
17446
  import { createConnection as createConnection3, createServer as createServer2, isIPv4, isIPv6 } from "node:net";
17352
17447
  import { homedir as homedir5 } from "node:os";
17353
17448
  import { dirname as dirname3, join as join3 } from "node:path";
@@ -17494,7 +17589,7 @@ function registryMcpStatePath(connectorId, home = homedir5()) {
17494
17589
  }
17495
17590
  function readState(path) {
17496
17591
  try {
17497
- const parsed = JSON.parse(readFileSync2(path, "utf8"));
17592
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
17498
17593
  return parsed?.status === "pending" || parsed?.status === "connected" ? parsed : void 0;
17499
17594
  } catch {
17500
17595
  return void 0;
@@ -17583,7 +17678,7 @@ async function installRegistryMcp(input) {
17583
17678
  });
17584
17679
  if (claimed.status !== "ready" || typeof claimed.code !== "string") {
17585
17680
  if (claimed.status === "expired") {
17586
- rmSync(path, { force: true });
17681
+ rmSync2(path, { force: true });
17587
17682
  return {
17588
17683
  status: "error",
17589
17684
  steps: steps("connect", CEREMONY_EXPIRED),
@@ -17966,7 +18061,7 @@ var RegistryMcpHostBroker = class {
17966
18061
  return;
17967
18062
  mkdirSync2(registryMcpStateRoot(this.home), { recursive: true, mode: 448 });
17968
18063
  mkdirSync2(dirname3(this.socketPath), { recursive: true, mode: 448 });
17969
- rmSync(this.socketPath, { force: true });
18064
+ rmSync2(this.socketPath, { force: true });
17970
18065
  this.server = createServer2({ allowHalfOpen: true }, (socket) => {
17971
18066
  let buffer = "";
17972
18067
  socket.setEncoding("utf8");
@@ -18007,7 +18102,7 @@ var RegistryMcpHostBroker = class {
18007
18102
  this.server = void 0;
18008
18103
  if (server)
18009
18104
  await new Promise((resolve49) => server.close(() => resolve49()));
18010
- rmSync(this.socketPath, { force: true });
18105
+ rmSync2(this.socketPath, { force: true });
18011
18106
  }
18012
18107
  };
18013
18108
  async function brokerRequest(socketPath, request) {
@@ -18054,7 +18149,7 @@ function runRegistryMcpBroker(env = process.env) {
18054
18149
  }
18055
18150
  let turn;
18056
18151
  try {
18057
- turn = readTurnContext(JSON.parse(readFileSync2(turnContextPath, "utf8")));
18152
+ turn = readTurnContext(JSON.parse(readFileSync3(turnContextPath, "utf8")));
18058
18153
  } catch {
18059
18154
  turn = void 0;
18060
18155
  }
@@ -19674,7 +19769,7 @@ async function reportAgentSignInResult(api, agentId, attemptId, cards, result, l
19674
19769
  // apps/body/dist/runtime.js
19675
19770
  import { randomBytes as randomBytes8 } from "node:crypto";
19676
19771
  import { execFile as execFile5 } from "node:child_process";
19677
- import { closeSync, openSync, readFileSync as readFileSync3 } from "node:fs";
19772
+ import { closeSync, openSync, readFileSync as readFileSync4 } from "node:fs";
19678
19773
  import { chmod as chmod4, mkdir as mkdir8, readFile as readFile11, readdir as readdir3, rename as rename5, stat as stat4, unlink as unlink4, writeFile as writeFile6 } from "node:fs/promises";
19679
19774
  import { homedir as homedir10 } from "node:os";
19680
19775
  import { dirname as dirname9, resolve as resolve8 } from "node:path";
@@ -28786,7 +28881,7 @@ function daemonBirthPath(configPath) {
28786
28881
  }
28787
28882
  function processBirthIdentity(pid) {
28788
28883
  try {
28789
- const statText = readFileSync3(`/proc/${pid}/stat`, "utf8");
28884
+ const statText = readFileSync4(`/proc/${pid}/stat`, "utf8");
28790
28885
  const close = statText.lastIndexOf(")");
28791
28886
  return close < 0 ? void 0 : statText.slice(close + 2).split(" ")[19];
28792
28887
  } catch {
@@ -29754,7 +29849,7 @@ import { EventEmitter } from "node:events";
29754
29849
  // apps/body/dist/acp-resource-scope.js
29755
29850
  import { execFile as execFile6 } from "node:child_process";
29756
29851
  import { randomUUID as randomUUID6 } from "node:crypto";
29757
- import { readFileSync as readFileSync4 } from "node:fs";
29852
+ import { readFileSync as readFileSync5 } from "node:fs";
29758
29853
  import { totalmem } from "node:os";
29759
29854
  import { promisify as promisify5 } from "node:util";
29760
29855
  var execFileAsync5 = promisify5(execFile6);
@@ -29824,7 +29919,7 @@ function managedServiceUnit() {
29824
29919
  if (process.env.BEELINE_MANAGED_BY_SYSTEMD !== "1")
29825
29920
  return void 0;
29826
29921
  try {
29827
- const cgroup = readFileSync4("/proc/self/cgroup", "utf8");
29922
+ const cgroup = readFileSync5("/proc/self/cgroup", "utf8");
29828
29923
  const path = cgroup.split("\n").find((line) => line.startsWith("0::"))?.slice(3);
29829
29924
  return path?.split("/").find((part) => /^beeline-(?:helper|agent@.+)\.service$/.test(part));
29830
29925
  } catch {
@@ -31138,7 +31233,7 @@ ${String(error)}`);
31138
31233
 
31139
31234
  // apps/body/dist/agent-home.js
31140
31235
  var import_yaml2 = __toESM(require_dist(), 1);
31141
- import { existsSync as existsSync7, readFileSync as readFileSync6, watch } from "node:fs";
31236
+ import { existsSync as existsSync7, readFileSync as readFileSync7, watch } from "node:fs";
31142
31237
 
31143
31238
  // node_modules/smol-toml/dist/date.js
31144
31239
  var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
@@ -32061,7 +32156,7 @@ function androidAgentEnv(input) {
32061
32156
  }
32062
32157
 
32063
32158
  // apps/body/dist/beeline-skill.js
32064
- import { readFileSync as readFileSync5 } from "node:fs";
32159
+ import { readFileSync as readFileSync6 } from "node:fs";
32065
32160
  import { resolve as resolve13 } from "node:path";
32066
32161
 
32067
32162
  // packages/api-contract/dist/phone-types.js
@@ -32568,7 +32663,7 @@ var BEELINE_ROOM_MECHANICS = [
32568
32663
  "If you need reach outside the sandbox, call beeline-agent request_grant. If you already know discrete options, call beeline-agent ask_choice (one human, optional) or open_poll (every human in this Room, required deadline). A poll is refused below two electors and above fifty, and in a DM. A plurality is a fact, never permission to deploy, delete, merge, or spend. Open-ended asks stay tagged prose. Never put Always / Once / No on a preference.",
32569
32664
  "To state something that happened so the Room and other agents can act on it, call beeline-agent emit_event with your own agent:<slug> kind, one sentence, and optionally the agent members to wake. Chains of events are bounded and a refused emit posts nothing."
32570
32665
  ].join(" ");
32571
- function runningBeelineReleaseId(env = process.env, read2 = (path) => readFileSync5(path, "utf8")) {
32666
+ function runningBeelineReleaseId(env = process.env, read2 = (path) => readFileSync6(path, "utf8")) {
32572
32667
  try {
32573
32668
  const lib = env.BEELINE_LIB_DIR;
32574
32669
  if (!lib)
@@ -32599,7 +32694,7 @@ Follow your own owner first, then this Workspace's owner and admins, then member
32599
32694
 
32600
32695
  A **tool** is something you can use once a human adds it; a **key** is the credential that tool holds for that human. You spend a key through the mounted connector and never see the credential itself.
32601
32696
 
32602
- The tools this build knows, what each is for, and which the owner of this machine already has are one call away: beeline-agent connectors_status. That read is the Connectors page for the machine and owner you actually run on, not the person who asked. Connected apps are listed once per app with a stable ID. Their sign-in and credentials stay with the server. Trusty Squire signs up and signs in to any website hands-off for the person; its vault holds keys when needed. operate_drive drives a whole flow, and flat steps (operate_click, operate_type, operate_select, operate_press, operate_scroll, operate_wait, operate_navigate, operate_read_inbox, operate_extract, and the rest of its flat operate_* actions) handle one action at a time. Tailscale installs its CLI on the selected helper and opens Tailscale's own browser sign-in; once connected, use the CLI for tailnet resources and tailscale file cp or tailscale file get for Taildrop. The wallet is created only from the Connectors page. When you cannot reach a tool, say: I can't reach X on this machine because Y; to fix it, Z. Give one explanation, then take or offer Z.
32697
+ The tools this build knows, what each is for, and which the owner of this machine already has are one call away: beeline-agent connectors_status. That read is the Connectors page for the machine and owner you actually run on, not the person who asked. Connected apps are listed once per app with a stable ID. Their sign-in and credentials stay with the server. Trusty Squire signs up and signs in to any website hands-off for the person; its vault holds keys when needed. operate_drive drives a whole flow, and flat steps (operate_click, operate_type, operate_select, operate_press, operate_scroll, operate_wait, operate_navigate, operate_read_inbox, operate_extract, and the rest of its flat operate_* actions) handle one action at a time. When you are stuck in an existing browser, call share_browser. The call waits for a person to hand the browser back; do not touch the browser again until that call returns. Tailscale installs its CLI on the selected helper and opens Tailscale's own browser sign-in; once connected, use the CLI for tailnet resources and tailscale file cp or tailscale file get for Taildrop. The wallet is created only from the Connectors page. When you cannot reach a tool, say: I can't reach X on this machine because Y; to fix it, Z. Give one explanation, then take or offer Z.
32603
32698
 
32604
32699
  **Inspect your own host before answering.** When a question is about a system on the machine you run on, inspect its live state with the tools you have: processes, logs, local endpoints or service status. Say what you checked. Memory and Room history are not evidence of current state.
32605
32700
 
@@ -34038,7 +34133,7 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
34038
34133
  try {
34039
34134
  const source = resolve16(operatorHome, config.toml);
34040
34135
  const target = resolve16(root, config.dir, "config.toml");
34041
- const mcpSection = existsSync7(source) ? localHarnessMcpToml(readFileSync6(source, "utf8")) : void 0;
34136
+ const mcpSection = existsSync7(source) ? localHarnessMcpToml(readFileSync7(source, "utf8")) : void 0;
34042
34137
  const section = config.dir === "codex" ? [CODEX_ROOM_AGENT_LOCKDOWN_TOML, CODEX_ROOM_WEB_SEARCH_TOML, mcpSection].filter(Boolean).join("\n") : mcpSection;
34043
34138
  if (!section) {
34044
34139
  await unlink5(target).catch(() => void 0);
@@ -34058,7 +34153,7 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
34058
34153
  const source = resolve16(operatorHome, ".config", "goose", name);
34059
34154
  const target = resolve16(gooseConfigDir, name);
34060
34155
  if (existsSync7(source)) {
34061
- const body = readFileSync6(source, "utf8");
34156
+ const body = readFileSync7(source, "utf8");
34062
34157
  await writeIsolatedHarnessFile(target, name === "config.yaml" ? localGooseConfig(body) : body);
34063
34158
  } else {
34064
34159
  await unlink5(target).catch(() => void 0);
@@ -34136,7 +34231,7 @@ async function applyGrantedHostRoutes(root, operatorHome, granted, agentKind, fa
34136
34231
  if (Object.keys(routes).length === 0)
34137
34232
  continue;
34138
34233
  const target = resolve16(root, config.dir, "config.toml");
34139
- const existing = existsSync7(target) ? readFileSync6(target, "utf8") : void 0;
34234
+ const existing = existsSync7(target) ? readFileSync7(target, "utf8") : void 0;
34140
34235
  const merged = mergeTomlHostRoutes(existing, routes);
34141
34236
  if (merged)
34142
34237
  await writeIsolatedHarnessFile(target, merged);
@@ -34147,7 +34242,7 @@ async function applyGrantedHostRoutes(root, operatorHome, granted, agentKind, fa
34147
34242
  const gooseConfigDir = resolve16(root, "goose", "config");
34148
34243
  await mkdir11(gooseConfigDir, { recursive: true, mode: 448 });
34149
34244
  const target = resolve16(gooseConfigDir, "config.yaml");
34150
- const existing = existsSync7(target) ? readFileSync6(target, "utf8") : void 0;
34245
+ const existing = existsSync7(target) ? readFileSync7(target, "utf8") : void 0;
34151
34246
  const merged = mergeGooseHostRoutes(existing, routes);
34152
34247
  if (merged)
34153
34248
  await writeIsolatedHarnessFile(target, merged);
@@ -34222,7 +34317,7 @@ async function provisionPiCustomModelConfig(root, operatorHome, failClosed, open
34222
34317
  if (resolvedSource !== source) {
34223
34318
  throw new AgentHomeSecurityError(`Pi custom model config resolves through a link: ${source}`);
34224
34319
  }
34225
- const sourceValue = JSON.parse(readFileSync6(resolvedSource, "utf8"));
34320
+ const sourceValue = JSON.parse(readFileSync7(resolvedSource, "utf8"));
34226
34321
  await writeIsolatedHarnessFile(target, `${JSON.stringify(withOpenRouterModelRouting(sourceValue, pin), null, 2)}
34227
34322
  `);
34228
34323
  } catch (error) {
@@ -34234,7 +34329,7 @@ async function provisionPiCustomModelConfig(root, operatorHome, failClosed, open
34234
34329
  }
34235
34330
  function readClaudeUserScopeMcpServers(path) {
34236
34331
  try {
34237
- const parsed = JSON.parse(readFileSync6(path, "utf8"));
34332
+ const parsed = JSON.parse(readFileSync7(path, "utf8"));
34238
34333
  const servers = recordValue2(parsed.mcpServers);
34239
34334
  if (servers)
34240
34335
  return localMcpServers(servers);
@@ -34435,7 +34530,7 @@ function readExistingText(path) {
34435
34530
  if (!existsSync7(path))
34436
34531
  return void 0;
34437
34532
  try {
34438
- return readFileSync6(path, "utf8");
34533
+ return readFileSync7(path, "utf8");
34439
34534
  } catch {
34440
34535
  return void 0;
34441
34536
  }
@@ -34767,7 +34862,7 @@ function harnessStateDirsFromEnv(env) {
34767
34862
 
34768
34863
  // apps/body/dist/bwrap-sandbox.js
34769
34864
  import { execFile as execFile7, spawnSync } from "node:child_process";
34770
- import { lstatSync, readdirSync as readdirSync3, readFileSync as readFileSync7, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
34865
+ import { lstatSync as lstatSync2, readdirSync as readdirSync3, readFileSync as readFileSync8, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "node:fs";
34771
34866
  import { homedir as homedir12 } from "node:os";
34772
34867
  import { basename as basename4, dirname as dirname13, isAbsolute as isAbsolute2, relative as relative2, resolve as resolve17 } from "node:path";
34773
34868
  var DEFAULT_SANDBOX_POLICY = "bwrap";
@@ -34828,7 +34923,7 @@ var KNOWN_CREDENTIAL_MASK_PATHS = [
34828
34923
  ];
34829
34924
  function credentialMaskPaths(extraPaths, home = homedir12(), stat11 = (path) => {
34830
34925
  try {
34831
- const info = lstatSync(path);
34926
+ const info = lstatSync2(path);
34832
34927
  return { isDirectory: info.isDirectory() };
34833
34928
  } catch {
34834
34929
  return void 0;
@@ -35080,7 +35175,7 @@ function readInstallFailure(stateDir) {
35080
35175
  if (!stateDir)
35081
35176
  return void 0;
35082
35177
  try {
35083
- const at = Number.parseInt(readFileSync7(installFailureMarker(stateDir), "utf8").trim(), 10);
35178
+ const at = Number.parseInt(readFileSync8(installFailureMarker(stateDir), "utf8").trim(), 10);
35084
35179
  return Number.isFinite(at) ? at : void 0;
35085
35180
  } catch {
35086
35181
  return void 0;
@@ -35099,7 +35194,7 @@ function clearInstallFailure(stateDir) {
35099
35194
  if (!stateDir)
35100
35195
  return;
35101
35196
  try {
35102
- rmSync2(installFailureMarker(stateDir), { force: true });
35197
+ rmSync3(installFailureMarker(stateDir), { force: true });
35103
35198
  } catch {
35104
35199
  }
35105
35200
  }
@@ -35398,7 +35493,7 @@ function isAllowedAgentModelConfigCategory(category, id) {
35398
35493
  }
35399
35494
 
35400
35495
  // apps/body/dist/model-config.js
35401
- import { lstatSync as lstatSync2, readFileSync as readFileSync8 } from "node:fs";
35496
+ import { lstatSync as lstatSync3, readFileSync as readFileSync9 } from "node:fs";
35402
35497
  import { basename as basename5, resolve as resolve19 } from "node:path";
35403
35498
 
35404
35499
  // apps/body/dist/transient-provider-error.js
@@ -35620,11 +35715,11 @@ function credentialedPiCustomProviders(env) {
35620
35715
  return held;
35621
35716
  const path = resolve19(agentDir, "models.json");
35622
35717
  try {
35623
- const stats = lstatSync2(path);
35718
+ const stats = lstatSync3(path);
35624
35719
  if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1 || stats.size > 1048576) {
35625
35720
  return held;
35626
35721
  }
35627
- const parsed = JSON.parse(readFileSync8(path, "utf8"));
35722
+ const parsed = JSON.parse(readFileSync9(path, "utf8"));
35628
35723
  const providers = parsed.providers;
35629
35724
  const remember = (name, config) => {
35630
35725
  if (typeof name !== "string" || !name.trim() || !config || typeof config !== "object")
@@ -35848,8 +35943,6 @@ function describeCurrentReleaseOutcome(outcome) {
35848
35943
  return `the current release got a different refusal (${outcome.reason})`;
35849
35944
  case "sandbox-unavailable":
35850
35945
  return `the current release has the same unavailable sandbox (${outcome.reason})`;
35851
- case "model-unavailable":
35852
- return `the current release cannot serve that model either (${outcome.reason})`;
35853
35946
  case "unavailable":
35854
35947
  return `the current release could not be compared (${outcome.reason})`;
35855
35948
  }
@@ -35877,29 +35970,6 @@ async function runUpdateFunctionalProbe(input) {
35877
35970
  command
35878
35971
  });
35879
35972
  const harness = input.config.agentKind ?? command;
35880
- if (input.config.modelUnavailable) {
35881
- const detail = input.config.modelUnavailable.detail;
35882
- if (!input.compareWithCurrentRelease) {
35883
- throw new UpdateFunctionalProbeError("model-unavailable", detail);
35884
- }
35885
- const current = await input.compareWithCurrentRelease({
35886
- kind: "model-unavailable",
35887
- reason: detail
35888
- });
35889
- if (current.kind !== "model-unavailable" && current.kind !== "unavailable") {
35890
- throw new UpdateFunctionalProbeError("model-unavailable", `${detail}; ${describeCurrentReleaseOutcome(current)}`);
35891
- }
35892
- console.warn("[body] update probe: the configured model is unavailable to this release and the current release alike; that is the account catalog, not the bundle, so the probe passes without a model answer");
35893
- return {
35894
- harness,
35895
- sandboxed: false,
35896
- sessionStarted: false,
35897
- turnCompleted: false,
35898
- nativeTools: [],
35899
- modelAnswer: "unavailable",
35900
- modelAnswerReason: `${detail} (the current release cannot serve that model either)`
35901
- };
35902
- }
35903
35973
  if (input.sandboxRequired && !input.config.bwrapPath) {
35904
35974
  const detail = input.sandboxUnavailableDetail ?? "the configured bubblewrap boundary did not pass its startup self-test";
35905
35975
  if (!input.compareWithCurrentRelease) {
@@ -36102,6 +36172,8 @@ async function runUpdateFunctionalProbe(input) {
36102
36172
  throw error;
36103
36173
  throw new UpdateFunctionalProbeError("session-start-failed", error instanceof Error ? error.message : String(error), { cause: error });
36104
36174
  }
36175
+ if (modelAnswer.modelAnswer === "served")
36176
+ input.config.modelUnavailable = void 0;
36105
36177
  return {
36106
36178
  harness,
36107
36179
  sandboxed: Boolean(input.config.bwrapPath),
@@ -37214,7 +37286,7 @@ async function validateAgentModelSelection(agent, agentEnv, selection) {
37214
37286
  }
37215
37287
 
37216
37288
  // apps/body/dist/config.js
37217
- import { accessSync as accessSync3, constants as constants2, existsSync as existsSync8, readFileSync as readFileSync9 } from "node:fs";
37289
+ import { accessSync as accessSync3, constants as constants2, existsSync as existsSync8, readFileSync as readFileSync10 } from "node:fs";
37218
37290
  import { basename as basename7, dirname as dirname17, resolve as resolve24 } from "node:path";
37219
37291
  function firstExisting2(paths) {
37220
37292
  for (const p of paths) {
@@ -37311,7 +37383,7 @@ function parseEnvFile(path) {
37311
37383
  const out = {};
37312
37384
  if (!existsSync8(path))
37313
37385
  return out;
37314
- const text2 = readFileSync9(path, "utf8");
37386
+ const text2 = readFileSync10(path, "utf8");
37315
37387
  for (const raw of text2.split("\n")) {
37316
37388
  const line = raw.trim();
37317
37389
  if (!line || line.startsWith("#"))
@@ -38579,6 +38651,7 @@ async function runUpdateProbeCommand(args, options = {}) {
38579
38651
 
38580
38652
  // apps/body/dist/machine-helper.js
38581
38653
  import { mkdir as mkdir29, rename as rename13, stat as stat10, writeFile as writeFile22 } from "node:fs/promises";
38654
+ import { homedir as homedir20 } from "node:os";
38582
38655
  import { dirname as dirname31, resolve as resolve47 } from "node:path";
38583
38656
 
38584
38657
  // apps/body/dist/agent-runtime.js
@@ -42055,7 +42128,7 @@ function cornerReviewerInstruction(input) {
42055
42128
  const headSha = input.headSha ?? "<head sha>";
42056
42129
  return `Checks are green on PR #${number} at ${headSha}${input.briefRevision ? ` with assigned brief revision ${input.briefRevision}` : ""}. Review it now with the beeline-review skill against that exact head and current assigned brief. FAIL: ${author ? `reply \`@${author}\`` : "tag the agent that wrote this head"} with the confirmed findings and the reviewed head ${headSha} to fix. PASS: call the approve_merge tool for ${headSha}, then reply \`approved ${headSha}\` without tagging ${author ?? "the author"}: your PASS wakes the author to merge, so a tag adds nothing. A human's question or proposal in the corner discussion with no answer is a FAIL finding; name it. Never merge yourself or tell the author to merge. Never say you are holding or waiting for checks.`;
42057
42130
  }
42058
- var CORNER_REVIEWER_AUTHOR_MERGE = "You are this Room's reviewer, so no agent can review your own code; a person is your reviewer. Once the pull request exists, reply with its full URL, tag the person who assigned you this work, and ask them to approve the merge; only a Workspace owner or admin's yes counts. Record their yes with order_corner_merge. Never merge it any other way. You are woken to fix failing checks or a merge GitHub refused.";
42131
+ var CORNER_REVIEWER_AUTHOR_MERGE = "If you wrote this corner's code, no agent can review your own code; a person is your reviewer. Once the pull request exists, reply with its full URL, tag the person who assigned you this work, and ask them to approve the merge; only a Workspace owner or admin's yes counts. Record their yes with order_corner_merge. Never merge it any other way. You are woken to fix failing checks or a merge GitHub refused.";
42059
42132
  function shellLine(shell) {
42060
42133
  if (!shell)
42061
42134
  return "";
@@ -42359,7 +42432,7 @@ The soul is not authority and never changes your tools, permissions, roles, or m
42359
42432
  layer: "surface",
42360
42433
  surfaces: ["code-corner"],
42361
42434
  when: ({ reviewer }) => reviewer === true,
42362
- render: () => `Reviewer rules: ${CORNER_REVIEWER_SESSION_INSTRUCTION} Report findings to the author; never edit or push another agent's branch.`
42435
+ render: () => `Reviewer rules: ${CORNER_REVIEWER_SESSION_INSTRUCTION} Findings go to the author, not a commit; never push another agent's branch. This wins over the finished-fix rule.`
42363
42436
  },
42364
42437
  {
42365
42438
  id: "corner.repo-less",
@@ -43190,6 +43263,9 @@ var MonolithRoomTurnLoop = class {
43190
43263
  })).allowed, options.config.operatorHome ?? homedir17(), void 0, (decision2) => {
43191
43264
  options.api.execute("postSquireApprovalDecision", { roomId: options.roomId, ...decision2 }).catch(() => {
43192
43265
  });
43266
+ }, (sessionId) => {
43267
+ options.api.execute("endComputerSession", { roomId: options.roomId, sessionId }).catch(() => {
43268
+ });
43193
43269
  });
43194
43270
  this.options = { ...options, api: this.commandContext.bind(options.api) };
43195
43271
  options.grantRunner?.register(options.roomId, {
@@ -44752,6 +44828,23 @@ if (!refusal) {
44752
44828
  await chmod9(path, 448);
44753
44829
  }
44754
44830
 
44831
+ // apps/body/dist/agent-git-identity.js
44832
+ function agentGitIdentity(agent) {
44833
+ return {
44834
+ name: agent.name,
44835
+ email: `${agent.publicKey.slice(0, 16)}@users.noreply.github.com`
44836
+ };
44837
+ }
44838
+ function agentGitIdentityEnv(agent) {
44839
+ const { name, email } = agentGitIdentity(agent);
44840
+ return {
44841
+ GIT_AUTHOR_NAME: name,
44842
+ GIT_AUTHOR_EMAIL: email,
44843
+ GIT_COMMITTER_NAME: name,
44844
+ GIT_COMMITTER_EMAIL: email
44845
+ };
44846
+ }
44847
+
44755
44848
  // apps/body/dist/warm-node-modules.js
44756
44849
  import { createHash as createHash12, randomUUID as randomUUID12 } from "node:crypto";
44757
44850
  import { constants as fsConstants3 } from "node:fs";
@@ -45359,6 +45452,9 @@ var MonolithCornerTurnLoop = class {
45359
45452
  })).allowed, options.config.operatorHome ?? homedir18(), void 0, (decision2) => {
45360
45453
  options.api.execute("postSquireApprovalDecision", { roomId: options.cornerId, ...decision2 }).catch(() => {
45361
45454
  });
45455
+ }, (sessionId) => {
45456
+ options.api.execute("endComputerSession", { roomId: options.cornerId, sessionId }).catch(() => {
45457
+ });
45362
45458
  });
45363
45459
  this.options = { ...options, api: this.commandContext.bind(options.api) };
45364
45460
  options.grantRunner?.register(options.cornerId, {
@@ -45692,6 +45788,9 @@ var MonolithCornerTurnLoop = class {
45692
45788
  ...this.options.config.agentEnv,
45693
45789
  ...homeOverlay,
45694
45790
  ...githubEnv,
45791
+ // Git reads these before any config, so this session commits as itself
45792
+ // no matter which session last prepared the shared corner worktree.
45793
+ ...agentGitIdentityEnv(this.agent),
45695
45794
  npm_config_cache: npmCacheDir,
45696
45795
  // pnpm reads its settings from PNPM_CONFIG_* environment variables and
45697
45796
  // hardlinks packages out of this content-addressable store.
@@ -46441,7 +46540,7 @@ ${continuation}` : assembled;
46441
46540
  const checksTurn = isCornerChecksTurn(trigger, restates);
46442
46541
  const mayPublish = repositoryWork && !repositoryHeld;
46443
46542
  const deliveryState = !checksTurn && mayPublish && this.options.repository ? await cornerUndeliveredRepositoryState(this.options.worktreePath, this.options.repository.featureBranch, this.options.repository.targetBranch) : void 0;
46444
- const needsDeliveryNudge = deliveryState !== void 0 && deliveryState !== this.lastDeliveryNudgeState;
46543
+ const needsDeliveryNudge = !this.reviewerInstructionInput && deliveryState !== void 0 && deliveryState !== this.lastDeliveryNudgeState;
46445
46544
  let refreshedReviewerInstruction;
46446
46545
  let reviewerSecondPass = false;
46447
46546
  let reviewerTargetChanged = false;
@@ -47391,13 +47490,14 @@ async function materializeCornerWorktree(input) {
47391
47490
  "credential.https://github.com.helper",
47392
47491
  "!f() { echo username=x-access-token; echo password=$GH_TOKEN; }; f"
47393
47492
  ]);
47493
+ const identity = agentGitIdentity(input.committer);
47394
47494
  await execFileAsync11("git", [
47395
47495
  "-C",
47396
47496
  path,
47397
47497
  "config",
47398
47498
  "--worktree",
47399
47499
  "user.name",
47400
- input.committer.name
47500
+ identity.name
47401
47501
  ]);
47402
47502
  await execFileAsync11("git", [
47403
47503
  "-C",
@@ -47405,7 +47505,7 @@ async function materializeCornerWorktree(input) {
47405
47505
  "config",
47406
47506
  "--worktree",
47407
47507
  "user.email",
47408
- `${input.committer.publicKey.slice(0, 16)}@users.noreply.github.com`
47508
+ identity.email
47409
47509
  ]);
47410
47510
  const top = (await execFileAsync11("git", ["-C", path, "rev-parse", "--show-toplevel"])).stdout.trim();
47411
47511
  if (await realpath3(top) !== await realpath3(path)) {
@@ -49027,7 +49127,7 @@ var ThinDaemonCore = class {
49027
49127
  };
49028
49128
 
49029
49129
  // apps/body/dist/force-update-journal.js
49030
- import { mkdirSync as mkdirSync4, readFileSync as readFileSync10, renameSync, writeFileSync as writeFileSync5 } from "node:fs";
49130
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync11, renameSync as renameSync2, writeFileSync as writeFileSync5 } from "node:fs";
49031
49131
  import { resolve as resolve41 } from "node:path";
49032
49132
  var NAME = "force-update-interruptions.json";
49033
49133
  function pathFor(runtimeDir) {
@@ -49035,7 +49135,7 @@ function pathFor(runtimeDir) {
49035
49135
  }
49036
49136
  function read(runtimeDir) {
49037
49137
  try {
49038
- const rows = JSON.parse(readFileSync10(pathFor(runtimeDir), "utf8"));
49138
+ const rows = JSON.parse(readFileSync11(pathFor(runtimeDir), "utf8"));
49039
49139
  if (!Array.isArray(rows))
49040
49140
  throw new Error("invalid force-update interruption journal");
49041
49141
  return rows.map((row) => {
@@ -49058,7 +49158,7 @@ function write(runtimeDir, rows) {
49058
49158
  const temporary = `${target}.${process.pid}.tmp`;
49059
49159
  writeFileSync5(temporary, `${JSON.stringify(rows)}
49060
49160
  `, { mode: 384 });
49061
- renameSync(temporary, target);
49161
+ renameSync2(temporary, target);
49062
49162
  }
49063
49163
  function journalInterruptedTurns(runtimeDir, turns) {
49064
49164
  if (!turns.length)
@@ -49645,6 +49745,7 @@ var ForceUpdateCoordinator = class {
49645
49745
  init_launchd();
49646
49746
  init_self_update();
49647
49747
  init_systemd();
49748
+ init_squire_host();
49648
49749
 
49649
49750
  // apps/body/dist/host-disk-retention.js
49650
49751
  import { execFile as execFile18 } from "node:child_process";
@@ -49800,11 +49901,12 @@ async function runMachineHelper(options = {}) {
49800
49901
  }
49801
49902
  loadedRelease = await activeReleaseId(layout);
49802
49903
  loadedReleaseIdentity = await readInstalledBundleIdentity(layout);
49803
- if (settle.kind === "pending") {
49904
+ if (settle.kind === "pending" || !squireBrokerMeetsComputerUseMinimum(env.HOME?.trim() || homedir20())) {
49905
+ const squireUpdateMode = settle.kind === "pending" ? "latest" : "minimum";
49804
49906
  if (managedBy === "systemd")
49805
- await installTrustySquireBrokerService({ env }).catch((error) => console.error(`[beeline] host Squire broker unit not converged: ${error instanceof Error ? error.message : String(error)}`));
49907
+ await installTrustySquireBrokerService({ env, squireUpdateMode }).catch((error) => console.error(`[beeline] host Squire broker unit not converged: ${error instanceof Error ? error.message : String(error)}`));
49806
49908
  else if (managedBy === "launchd")
49807
- await installLaunchdTrustySquireBrokerService({ env }).catch((error) => console.error(`[beeline] host Squire broker launchd job not converged: ${error instanceof Error ? error.message : String(error)}`));
49909
+ await installLaunchdTrustySquireBrokerService({ env, squireUpdateMode }).catch((error) => console.error(`[beeline] host Squire broker launchd job not converged: ${error instanceof Error ? error.message : String(error)}`));
49808
49910
  }
49809
49911
  }
49810
49912
  if (managedBy === "systemd")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usebeeline",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "description": "Connect an AI coding agent to Beeline with one command.",
5
5
  "homepage": "https://usebeeline.app",
6
6
  "bugs": {