usebeeline 0.1.25 → 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 +168 -84
  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;
@@ -17359,7 +17442,7 @@ var ACCESS_REFUSAL_WINDOW_MS = 60 * 60 * 1e3;
17359
17442
  import { createHash as createHash2, randomBytes } from "node:crypto";
17360
17443
  import { lookup } from "node:dns/promises";
17361
17444
  import { createRequire as createRequire4 } from "node:module";
17362
- 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";
17363
17446
  import { createConnection as createConnection3, createServer as createServer2, isIPv4, isIPv6 } from "node:net";
17364
17447
  import { homedir as homedir5 } from "node:os";
17365
17448
  import { dirname as dirname3, join as join3 } from "node:path";
@@ -17506,7 +17589,7 @@ function registryMcpStatePath(connectorId, home = homedir5()) {
17506
17589
  }
17507
17590
  function readState(path) {
17508
17591
  try {
17509
- const parsed = JSON.parse(readFileSync2(path, "utf8"));
17592
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
17510
17593
  return parsed?.status === "pending" || parsed?.status === "connected" ? parsed : void 0;
17511
17594
  } catch {
17512
17595
  return void 0;
@@ -17595,7 +17678,7 @@ async function installRegistryMcp(input) {
17595
17678
  });
17596
17679
  if (claimed.status !== "ready" || typeof claimed.code !== "string") {
17597
17680
  if (claimed.status === "expired") {
17598
- rmSync(path, { force: true });
17681
+ rmSync2(path, { force: true });
17599
17682
  return {
17600
17683
  status: "error",
17601
17684
  steps: steps("connect", CEREMONY_EXPIRED),
@@ -17978,7 +18061,7 @@ var RegistryMcpHostBroker = class {
17978
18061
  return;
17979
18062
  mkdirSync2(registryMcpStateRoot(this.home), { recursive: true, mode: 448 });
17980
18063
  mkdirSync2(dirname3(this.socketPath), { recursive: true, mode: 448 });
17981
- rmSync(this.socketPath, { force: true });
18064
+ rmSync2(this.socketPath, { force: true });
17982
18065
  this.server = createServer2({ allowHalfOpen: true }, (socket) => {
17983
18066
  let buffer = "";
17984
18067
  socket.setEncoding("utf8");
@@ -18019,7 +18102,7 @@ var RegistryMcpHostBroker = class {
18019
18102
  this.server = void 0;
18020
18103
  if (server)
18021
18104
  await new Promise((resolve49) => server.close(() => resolve49()));
18022
- rmSync(this.socketPath, { force: true });
18105
+ rmSync2(this.socketPath, { force: true });
18023
18106
  }
18024
18107
  };
18025
18108
  async function brokerRequest(socketPath, request) {
@@ -18066,7 +18149,7 @@ function runRegistryMcpBroker(env = process.env) {
18066
18149
  }
18067
18150
  let turn;
18068
18151
  try {
18069
- turn = readTurnContext(JSON.parse(readFileSync2(turnContextPath, "utf8")));
18152
+ turn = readTurnContext(JSON.parse(readFileSync3(turnContextPath, "utf8")));
18070
18153
  } catch {
18071
18154
  turn = void 0;
18072
18155
  }
@@ -19686,7 +19769,7 @@ async function reportAgentSignInResult(api, agentId, attemptId, cards, result, l
19686
19769
  // apps/body/dist/runtime.js
19687
19770
  import { randomBytes as randomBytes8 } from "node:crypto";
19688
19771
  import { execFile as execFile5 } from "node:child_process";
19689
- import { closeSync, openSync, readFileSync as readFileSync3 } from "node:fs";
19772
+ import { closeSync, openSync, readFileSync as readFileSync4 } from "node:fs";
19690
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";
19691
19774
  import { homedir as homedir10 } from "node:os";
19692
19775
  import { dirname as dirname9, resolve as resolve8 } from "node:path";
@@ -28798,7 +28881,7 @@ function daemonBirthPath(configPath) {
28798
28881
  }
28799
28882
  function processBirthIdentity(pid) {
28800
28883
  try {
28801
- const statText = readFileSync3(`/proc/${pid}/stat`, "utf8");
28884
+ const statText = readFileSync4(`/proc/${pid}/stat`, "utf8");
28802
28885
  const close = statText.lastIndexOf(")");
28803
28886
  return close < 0 ? void 0 : statText.slice(close + 2).split(" ")[19];
28804
28887
  } catch {
@@ -29766,7 +29849,7 @@ import { EventEmitter } from "node:events";
29766
29849
  // apps/body/dist/acp-resource-scope.js
29767
29850
  import { execFile as execFile6 } from "node:child_process";
29768
29851
  import { randomUUID as randomUUID6 } from "node:crypto";
29769
- import { readFileSync as readFileSync4 } from "node:fs";
29852
+ import { readFileSync as readFileSync5 } from "node:fs";
29770
29853
  import { totalmem } from "node:os";
29771
29854
  import { promisify as promisify5 } from "node:util";
29772
29855
  var execFileAsync5 = promisify5(execFile6);
@@ -29836,7 +29919,7 @@ function managedServiceUnit() {
29836
29919
  if (process.env.BEELINE_MANAGED_BY_SYSTEMD !== "1")
29837
29920
  return void 0;
29838
29921
  try {
29839
- const cgroup = readFileSync4("/proc/self/cgroup", "utf8");
29922
+ const cgroup = readFileSync5("/proc/self/cgroup", "utf8");
29840
29923
  const path = cgroup.split("\n").find((line) => line.startsWith("0::"))?.slice(3);
29841
29924
  return path?.split("/").find((part) => /^beeline-(?:helper|agent@.+)\.service$/.test(part));
29842
29925
  } catch {
@@ -31150,7 +31233,7 @@ ${String(error)}`);
31150
31233
 
31151
31234
  // apps/body/dist/agent-home.js
31152
31235
  var import_yaml2 = __toESM(require_dist(), 1);
31153
- import { existsSync as existsSync7, readFileSync as readFileSync6, watch } from "node:fs";
31236
+ import { existsSync as existsSync7, readFileSync as readFileSync7, watch } from "node:fs";
31154
31237
 
31155
31238
  // node_modules/smol-toml/dist/date.js
31156
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;
@@ -32073,7 +32156,7 @@ function androidAgentEnv(input) {
32073
32156
  }
32074
32157
 
32075
32158
  // apps/body/dist/beeline-skill.js
32076
- import { readFileSync as readFileSync5 } from "node:fs";
32159
+ import { readFileSync as readFileSync6 } from "node:fs";
32077
32160
  import { resolve as resolve13 } from "node:path";
32078
32161
 
32079
32162
  // packages/api-contract/dist/phone-types.js
@@ -32580,7 +32663,7 @@ var BEELINE_ROOM_MECHANICS = [
32580
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.",
32581
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."
32582
32665
  ].join(" ");
32583
- function runningBeelineReleaseId(env = process.env, read2 = (path) => readFileSync5(path, "utf8")) {
32666
+ function runningBeelineReleaseId(env = process.env, read2 = (path) => readFileSync6(path, "utf8")) {
32584
32667
  try {
32585
32668
  const lib = env.BEELINE_LIB_DIR;
32586
32669
  if (!lib)
@@ -34050,7 +34133,7 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
34050
34133
  try {
34051
34134
  const source = resolve16(operatorHome, config.toml);
34052
34135
  const target = resolve16(root, config.dir, "config.toml");
34053
- const mcpSection = existsSync7(source) ? localHarnessMcpToml(readFileSync6(source, "utf8")) : void 0;
34136
+ const mcpSection = existsSync7(source) ? localHarnessMcpToml(readFileSync7(source, "utf8")) : void 0;
34054
34137
  const section = config.dir === "codex" ? [CODEX_ROOM_AGENT_LOCKDOWN_TOML, CODEX_ROOM_WEB_SEARCH_TOML, mcpSection].filter(Boolean).join("\n") : mcpSection;
34055
34138
  if (!section) {
34056
34139
  await unlink5(target).catch(() => void 0);
@@ -34070,7 +34153,7 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
34070
34153
  const source = resolve16(operatorHome, ".config", "goose", name);
34071
34154
  const target = resolve16(gooseConfigDir, name);
34072
34155
  if (existsSync7(source)) {
34073
- const body = readFileSync6(source, "utf8");
34156
+ const body = readFileSync7(source, "utf8");
34074
34157
  await writeIsolatedHarnessFile(target, name === "config.yaml" ? localGooseConfig(body) : body);
34075
34158
  } else {
34076
34159
  await unlink5(target).catch(() => void 0);
@@ -34148,7 +34231,7 @@ async function applyGrantedHostRoutes(root, operatorHome, granted, agentKind, fa
34148
34231
  if (Object.keys(routes).length === 0)
34149
34232
  continue;
34150
34233
  const target = resolve16(root, config.dir, "config.toml");
34151
- const existing = existsSync7(target) ? readFileSync6(target, "utf8") : void 0;
34234
+ const existing = existsSync7(target) ? readFileSync7(target, "utf8") : void 0;
34152
34235
  const merged = mergeTomlHostRoutes(existing, routes);
34153
34236
  if (merged)
34154
34237
  await writeIsolatedHarnessFile(target, merged);
@@ -34159,7 +34242,7 @@ async function applyGrantedHostRoutes(root, operatorHome, granted, agentKind, fa
34159
34242
  const gooseConfigDir = resolve16(root, "goose", "config");
34160
34243
  await mkdir11(gooseConfigDir, { recursive: true, mode: 448 });
34161
34244
  const target = resolve16(gooseConfigDir, "config.yaml");
34162
- const existing = existsSync7(target) ? readFileSync6(target, "utf8") : void 0;
34245
+ const existing = existsSync7(target) ? readFileSync7(target, "utf8") : void 0;
34163
34246
  const merged = mergeGooseHostRoutes(existing, routes);
34164
34247
  if (merged)
34165
34248
  await writeIsolatedHarnessFile(target, merged);
@@ -34234,7 +34317,7 @@ async function provisionPiCustomModelConfig(root, operatorHome, failClosed, open
34234
34317
  if (resolvedSource !== source) {
34235
34318
  throw new AgentHomeSecurityError(`Pi custom model config resolves through a link: ${source}`);
34236
34319
  }
34237
- const sourceValue = JSON.parse(readFileSync6(resolvedSource, "utf8"));
34320
+ const sourceValue = JSON.parse(readFileSync7(resolvedSource, "utf8"));
34238
34321
  await writeIsolatedHarnessFile(target, `${JSON.stringify(withOpenRouterModelRouting(sourceValue, pin), null, 2)}
34239
34322
  `);
34240
34323
  } catch (error) {
@@ -34246,7 +34329,7 @@ async function provisionPiCustomModelConfig(root, operatorHome, failClosed, open
34246
34329
  }
34247
34330
  function readClaudeUserScopeMcpServers(path) {
34248
34331
  try {
34249
- const parsed = JSON.parse(readFileSync6(path, "utf8"));
34332
+ const parsed = JSON.parse(readFileSync7(path, "utf8"));
34250
34333
  const servers = recordValue2(parsed.mcpServers);
34251
34334
  if (servers)
34252
34335
  return localMcpServers(servers);
@@ -34447,7 +34530,7 @@ function readExistingText(path) {
34447
34530
  if (!existsSync7(path))
34448
34531
  return void 0;
34449
34532
  try {
34450
- return readFileSync6(path, "utf8");
34533
+ return readFileSync7(path, "utf8");
34451
34534
  } catch {
34452
34535
  return void 0;
34453
34536
  }
@@ -34779,7 +34862,7 @@ function harnessStateDirsFromEnv(env) {
34779
34862
 
34780
34863
  // apps/body/dist/bwrap-sandbox.js
34781
34864
  import { execFile as execFile7, spawnSync } from "node:child_process";
34782
- 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";
34783
34866
  import { homedir as homedir12 } from "node:os";
34784
34867
  import { basename as basename4, dirname as dirname13, isAbsolute as isAbsolute2, relative as relative2, resolve as resolve17 } from "node:path";
34785
34868
  var DEFAULT_SANDBOX_POLICY = "bwrap";
@@ -34840,7 +34923,7 @@ var KNOWN_CREDENTIAL_MASK_PATHS = [
34840
34923
  ];
34841
34924
  function credentialMaskPaths(extraPaths, home = homedir12(), stat11 = (path) => {
34842
34925
  try {
34843
- const info = lstatSync(path);
34926
+ const info = lstatSync2(path);
34844
34927
  return { isDirectory: info.isDirectory() };
34845
34928
  } catch {
34846
34929
  return void 0;
@@ -35092,7 +35175,7 @@ function readInstallFailure(stateDir) {
35092
35175
  if (!stateDir)
35093
35176
  return void 0;
35094
35177
  try {
35095
- const at = Number.parseInt(readFileSync7(installFailureMarker(stateDir), "utf8").trim(), 10);
35178
+ const at = Number.parseInt(readFileSync8(installFailureMarker(stateDir), "utf8").trim(), 10);
35096
35179
  return Number.isFinite(at) ? at : void 0;
35097
35180
  } catch {
35098
35181
  return void 0;
@@ -35111,7 +35194,7 @@ function clearInstallFailure(stateDir) {
35111
35194
  if (!stateDir)
35112
35195
  return;
35113
35196
  try {
35114
- rmSync2(installFailureMarker(stateDir), { force: true });
35197
+ rmSync3(installFailureMarker(stateDir), { force: true });
35115
35198
  } catch {
35116
35199
  }
35117
35200
  }
@@ -35410,7 +35493,7 @@ function isAllowedAgentModelConfigCategory(category, id) {
35410
35493
  }
35411
35494
 
35412
35495
  // apps/body/dist/model-config.js
35413
- import { lstatSync as lstatSync2, readFileSync as readFileSync8 } from "node:fs";
35496
+ import { lstatSync as lstatSync3, readFileSync as readFileSync9 } from "node:fs";
35414
35497
  import { basename as basename5, resolve as resolve19 } from "node:path";
35415
35498
 
35416
35499
  // apps/body/dist/transient-provider-error.js
@@ -35632,11 +35715,11 @@ function credentialedPiCustomProviders(env) {
35632
35715
  return held;
35633
35716
  const path = resolve19(agentDir, "models.json");
35634
35717
  try {
35635
- const stats = lstatSync2(path);
35718
+ const stats = lstatSync3(path);
35636
35719
  if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1 || stats.size > 1048576) {
35637
35720
  return held;
35638
35721
  }
35639
- const parsed = JSON.parse(readFileSync8(path, "utf8"));
35722
+ const parsed = JSON.parse(readFileSync9(path, "utf8"));
35640
35723
  const providers = parsed.providers;
35641
35724
  const remember = (name, config) => {
35642
35725
  if (typeof name !== "string" || !name.trim() || !config || typeof config !== "object")
@@ -35860,8 +35943,6 @@ function describeCurrentReleaseOutcome(outcome) {
35860
35943
  return `the current release got a different refusal (${outcome.reason})`;
35861
35944
  case "sandbox-unavailable":
35862
35945
  return `the current release has the same unavailable sandbox (${outcome.reason})`;
35863
- case "model-unavailable":
35864
- return `the current release cannot serve that model either (${outcome.reason})`;
35865
35946
  case "unavailable":
35866
35947
  return `the current release could not be compared (${outcome.reason})`;
35867
35948
  }
@@ -35889,29 +35970,6 @@ async function runUpdateFunctionalProbe(input) {
35889
35970
  command
35890
35971
  });
35891
35972
  const harness = input.config.agentKind ?? command;
35892
- if (input.config.modelUnavailable) {
35893
- const detail = input.config.modelUnavailable.detail;
35894
- if (!input.compareWithCurrentRelease) {
35895
- throw new UpdateFunctionalProbeError("model-unavailable", detail);
35896
- }
35897
- const current = await input.compareWithCurrentRelease({
35898
- kind: "model-unavailable",
35899
- reason: detail
35900
- });
35901
- if (current.kind !== "model-unavailable" && current.kind !== "unavailable") {
35902
- throw new UpdateFunctionalProbeError("model-unavailable", `${detail}; ${describeCurrentReleaseOutcome(current)}`);
35903
- }
35904
- 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");
35905
- return {
35906
- harness,
35907
- sandboxed: false,
35908
- sessionStarted: false,
35909
- turnCompleted: false,
35910
- nativeTools: [],
35911
- modelAnswer: "unavailable",
35912
- modelAnswerReason: `${detail} (the current release cannot serve that model either)`
35913
- };
35914
- }
35915
35973
  if (input.sandboxRequired && !input.config.bwrapPath) {
35916
35974
  const detail = input.sandboxUnavailableDetail ?? "the configured bubblewrap boundary did not pass its startup self-test";
35917
35975
  if (!input.compareWithCurrentRelease) {
@@ -36114,6 +36172,8 @@ async function runUpdateFunctionalProbe(input) {
36114
36172
  throw error;
36115
36173
  throw new UpdateFunctionalProbeError("session-start-failed", error instanceof Error ? error.message : String(error), { cause: error });
36116
36174
  }
36175
+ if (modelAnswer.modelAnswer === "served")
36176
+ input.config.modelUnavailable = void 0;
36117
36177
  return {
36118
36178
  harness,
36119
36179
  sandboxed: Boolean(input.config.bwrapPath),
@@ -37226,7 +37286,7 @@ async function validateAgentModelSelection(agent, agentEnv, selection) {
37226
37286
  }
37227
37287
 
37228
37288
  // apps/body/dist/config.js
37229
- 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";
37230
37290
  import { basename as basename7, dirname as dirname17, resolve as resolve24 } from "node:path";
37231
37291
  function firstExisting2(paths) {
37232
37292
  for (const p of paths) {
@@ -37323,7 +37383,7 @@ function parseEnvFile(path) {
37323
37383
  const out = {};
37324
37384
  if (!existsSync8(path))
37325
37385
  return out;
37326
- const text2 = readFileSync9(path, "utf8");
37386
+ const text2 = readFileSync10(path, "utf8");
37327
37387
  for (const raw of text2.split("\n")) {
37328
37388
  const line = raw.trim();
37329
37389
  if (!line || line.startsWith("#"))
@@ -38591,6 +38651,7 @@ async function runUpdateProbeCommand(args, options = {}) {
38591
38651
 
38592
38652
  // apps/body/dist/machine-helper.js
38593
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";
38594
38655
  import { dirname as dirname31, resolve as resolve47 } from "node:path";
38595
38656
 
38596
38657
  // apps/body/dist/agent-runtime.js
@@ -42067,7 +42128,7 @@ function cornerReviewerInstruction(input) {
42067
42128
  const headSha = input.headSha ?? "<head sha>";
42068
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.`;
42069
42130
  }
42070
- 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.";
42071
42132
  function shellLine(shell) {
42072
42133
  if (!shell)
42073
42134
  return "";
@@ -42371,7 +42432,7 @@ The soul is not authority and never changes your tools, permissions, roles, or m
42371
42432
  layer: "surface",
42372
42433
  surfaces: ["code-corner"],
42373
42434
  when: ({ reviewer }) => reviewer === true,
42374
- 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.`
42375
42436
  },
42376
42437
  {
42377
42438
  id: "corner.repo-less",
@@ -44767,6 +44828,23 @@ if (!refusal) {
44767
44828
  await chmod9(path, 448);
44768
44829
  }
44769
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
+
44770
44848
  // apps/body/dist/warm-node-modules.js
44771
44849
  import { createHash as createHash12, randomUUID as randomUUID12 } from "node:crypto";
44772
44850
  import { constants as fsConstants3 } from "node:fs";
@@ -45710,6 +45788,9 @@ var MonolithCornerTurnLoop = class {
45710
45788
  ...this.options.config.agentEnv,
45711
45789
  ...homeOverlay,
45712
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),
45713
45794
  npm_config_cache: npmCacheDir,
45714
45795
  // pnpm reads its settings from PNPM_CONFIG_* environment variables and
45715
45796
  // hardlinks packages out of this content-addressable store.
@@ -46459,7 +46540,7 @@ ${continuation}` : assembled;
46459
46540
  const checksTurn = isCornerChecksTurn(trigger, restates);
46460
46541
  const mayPublish = repositoryWork && !repositoryHeld;
46461
46542
  const deliveryState = !checksTurn && mayPublish && this.options.repository ? await cornerUndeliveredRepositoryState(this.options.worktreePath, this.options.repository.featureBranch, this.options.repository.targetBranch) : void 0;
46462
- const needsDeliveryNudge = deliveryState !== void 0 && deliveryState !== this.lastDeliveryNudgeState;
46543
+ const needsDeliveryNudge = !this.reviewerInstructionInput && deliveryState !== void 0 && deliveryState !== this.lastDeliveryNudgeState;
46463
46544
  let refreshedReviewerInstruction;
46464
46545
  let reviewerSecondPass = false;
46465
46546
  let reviewerTargetChanged = false;
@@ -47409,13 +47490,14 @@ async function materializeCornerWorktree(input) {
47409
47490
  "credential.https://github.com.helper",
47410
47491
  "!f() { echo username=x-access-token; echo password=$GH_TOKEN; }; f"
47411
47492
  ]);
47493
+ const identity = agentGitIdentity(input.committer);
47412
47494
  await execFileAsync11("git", [
47413
47495
  "-C",
47414
47496
  path,
47415
47497
  "config",
47416
47498
  "--worktree",
47417
47499
  "user.name",
47418
- input.committer.name
47500
+ identity.name
47419
47501
  ]);
47420
47502
  await execFileAsync11("git", [
47421
47503
  "-C",
@@ -47423,7 +47505,7 @@ async function materializeCornerWorktree(input) {
47423
47505
  "config",
47424
47506
  "--worktree",
47425
47507
  "user.email",
47426
- `${input.committer.publicKey.slice(0, 16)}@users.noreply.github.com`
47508
+ identity.email
47427
47509
  ]);
47428
47510
  const top = (await execFileAsync11("git", ["-C", path, "rev-parse", "--show-toplevel"])).stdout.trim();
47429
47511
  if (await realpath3(top) !== await realpath3(path)) {
@@ -49045,7 +49127,7 @@ var ThinDaemonCore = class {
49045
49127
  };
49046
49128
 
49047
49129
  // apps/body/dist/force-update-journal.js
49048
- 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";
49049
49131
  import { resolve as resolve41 } from "node:path";
49050
49132
  var NAME = "force-update-interruptions.json";
49051
49133
  function pathFor(runtimeDir) {
@@ -49053,7 +49135,7 @@ function pathFor(runtimeDir) {
49053
49135
  }
49054
49136
  function read(runtimeDir) {
49055
49137
  try {
49056
- const rows = JSON.parse(readFileSync10(pathFor(runtimeDir), "utf8"));
49138
+ const rows = JSON.parse(readFileSync11(pathFor(runtimeDir), "utf8"));
49057
49139
  if (!Array.isArray(rows))
49058
49140
  throw new Error("invalid force-update interruption journal");
49059
49141
  return rows.map((row) => {
@@ -49076,7 +49158,7 @@ function write(runtimeDir, rows) {
49076
49158
  const temporary = `${target}.${process.pid}.tmp`;
49077
49159
  writeFileSync5(temporary, `${JSON.stringify(rows)}
49078
49160
  `, { mode: 384 });
49079
- renameSync(temporary, target);
49161
+ renameSync2(temporary, target);
49080
49162
  }
49081
49163
  function journalInterruptedTurns(runtimeDir, turns) {
49082
49164
  if (!turns.length)
@@ -49663,6 +49745,7 @@ var ForceUpdateCoordinator = class {
49663
49745
  init_launchd();
49664
49746
  init_self_update();
49665
49747
  init_systemd();
49748
+ init_squire_host();
49666
49749
 
49667
49750
  // apps/body/dist/host-disk-retention.js
49668
49751
  import { execFile as execFile18 } from "node:child_process";
@@ -49818,11 +49901,12 @@ async function runMachineHelper(options = {}) {
49818
49901
  }
49819
49902
  loadedRelease = await activeReleaseId(layout);
49820
49903
  loadedReleaseIdentity = await readInstalledBundleIdentity(layout);
49821
- if (settle.kind === "pending") {
49904
+ if (settle.kind === "pending" || !squireBrokerMeetsComputerUseMinimum(env.HOME?.trim() || homedir20())) {
49905
+ const squireUpdateMode = settle.kind === "pending" ? "latest" : "minimum";
49822
49906
  if (managedBy === "systemd")
49823
- 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)}`));
49824
49908
  else if (managedBy === "launchd")
49825
- 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)}`));
49826
49910
  }
49827
49911
  }
49828
49912
  if (managedBy === "systemd")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usebeeline",
3
- "version": "0.1.25",
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": {