usebeeline 0.0.114 → 0.0.115

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 +1368 -730
  2. package/package.json +1 -1
@@ -2415,7 +2415,7 @@ var require_websocket = __commonJS({
2415
2415
  var http = __require("http");
2416
2416
  var net2 = __require("net");
2417
2417
  var tls = __require("tls");
2418
- var { randomBytes: randomBytes7, createHash: createHash9 } = __require("crypto");
2418
+ var { randomBytes: randomBytes7, createHash: createHash10 } = __require("crypto");
2419
2419
  var { Duplex, Readable } = __require("stream");
2420
2420
  var { URL: URL2 } = __require("url");
2421
2421
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -3083,7 +3083,7 @@ var require_websocket = __commonJS({
3083
3083
  abortHandshake(websocket, socket, "Invalid Upgrade header");
3084
3084
  return;
3085
3085
  }
3086
- const digest = createHash9("sha1").update(key + GUID).digest("base64");
3086
+ const digest = createHash10("sha1").update(key + GUID).digest("base64");
3087
3087
  if (res.headers["sec-websocket-accept"] !== digest) {
3088
3088
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
3089
3089
  return;
@@ -3452,7 +3452,7 @@ var require_websocket_server = __commonJS({
3452
3452
  var EventEmitter2 = __require("events");
3453
3453
  var http = __require("http");
3454
3454
  var { Duplex } = __require("stream");
3455
- var { createHash: createHash9 } = __require("crypto");
3455
+ var { createHash: createHash10 } = __require("crypto");
3456
3456
  var extension2 = require_extension();
3457
3457
  var PerMessageDeflate2 = require_permessage_deflate();
3458
3458
  var subprotocol2 = require_subprotocol();
@@ -3759,7 +3759,7 @@ var require_websocket_server = __commonJS({
3759
3759
  );
3760
3760
  }
3761
3761
  if (this._state > RUNNING) return abortHandshake(socket, 503);
3762
- const digest = createHash9("sha1").update(key + GUID).digest("base64");
3762
+ const digest = createHash10("sha1").update(key + GUID).digest("base64");
3763
3763
  const headers = [
3764
3764
  "HTTP/1.1 101 Switching Protocols",
3765
3765
  "Upgrade: websocket",
@@ -3984,14 +3984,14 @@ __export(self_update_exports, {
3984
3984
  writeUpdateAttemptFixture: () => writeUpdateAttemptFixture,
3985
3985
  writeUpdateState: () => writeUpdateState
3986
3986
  });
3987
- import { createHash as createHash7 } from "node:crypto";
3987
+ import { createHash as createHash8 } from "node:crypto";
3988
3988
  import { constants as fsConstants2 } from "node:fs";
3989
3989
  import { access, chmod as chmod5, lstat as lstat3, mkdir as mkdir15, open, readFile as readFile10, rename as rename4, rm as rm6, symlink as symlink3, writeFile as writeFile10 } from "node:fs/promises";
3990
- import { spawn as spawn7 } from "node:child_process";
3991
- import { homedir as homedir9 } from "node:os";
3992
- import { dirname as dirname11, join as join10, resolve as resolve22 } from "node:path";
3990
+ import { spawn as spawn8 } from "node:child_process";
3991
+ import { homedir as homedir10 } from "node:os";
3992
+ import { dirname as dirname12, join as join11, resolve as resolve23 } from "node:path";
3993
3993
  function anchorLayout(rawLibDir) {
3994
- const libDir = resolve22(rawLibDir);
3994
+ const libDir = resolve23(rawLibDir);
3995
3995
  const segments = libDir.split(/[/\\]/);
3996
3996
  const idx = segments.lastIndexOf(RELEASES_SEGMENT);
3997
3997
  if (idx >= 2 && segments[idx - 1] === "lib") {
@@ -4007,9 +4007,9 @@ function anchorLayout(rawLibDir) {
4007
4007
  // prefix's bin, NOT <prefix>/lib/bin — deriving it one level up was the
4008
4008
  // defect that made activateRelease write its stable forwarders where
4009
4009
  // nothing executed them, leaving stale raw wrappers in <prefix>/bin.
4010
- binDir: resolve22(libDir, "../../bin"),
4010
+ binDir: resolve23(libDir, "../../bin"),
4011
4011
  libDir,
4012
- releasesRoot: resolve22(libDir, `../${RELEASES_SEGMENT}`)
4012
+ releasesRoot: resolve23(libDir, `../${RELEASES_SEGMENT}`)
4013
4013
  };
4014
4014
  }
4015
4015
  function beelineInstallLayout(env = process.env) {
@@ -4019,8 +4019,8 @@ function beelineInstallLayout(env = process.env) {
4019
4019
  return anchorLayout(raw);
4020
4020
  }
4021
4021
  function defaultBeelineInstallLayout(env = process.env) {
4022
- const home = env.HOME?.trim() || homedir9();
4023
- return anchorLayout(resolve22(home, ".local", "lib", "beeline"));
4022
+ const home = env.HOME?.trim() || homedir10();
4023
+ return anchorLayout(resolve23(home, ".local", "lib", "beeline"));
4024
4024
  }
4025
4025
  function discoveredBeelineInstallLayout(env = process.env) {
4026
4026
  const explicitAnchor = env.BEELINE_INSTALL_LIB_DIR?.trim();
@@ -4028,7 +4028,7 @@ function discoveredBeelineInstallLayout(env = process.env) {
4028
4028
  return anchorLayout(explicitAnchor);
4029
4029
  const explicitBinDir = env.BEELINE_INSTALL_DIR?.trim();
4030
4030
  if (explicitBinDir)
4031
- return anchorLayout(resolve22(dirname11(resolve22(explicitBinDir)), "lib", "beeline"));
4031
+ return anchorLayout(resolve23(dirname12(resolve23(explicitBinDir)), "lib", "beeline"));
4032
4032
  return defaultBeelineInstallLayout(env);
4033
4033
  }
4034
4034
  function hostPlatformKey() {
@@ -4039,7 +4039,7 @@ function hostPlatformKey() {
4039
4039
  return `${os}-${arch}`;
4040
4040
  }
4041
4041
  function bundleJsonCandidates(bundleDir) {
4042
- return [join10(bundleDir, "lib", "beeline", "bundle.json"), join10(bundleDir, "bundle.json")];
4042
+ return [join11(bundleDir, "lib", "beeline", "bundle.json"), join11(bundleDir, "bundle.json")];
4043
4043
  }
4044
4044
  async function readBundleJson(bundleDir) {
4045
4045
  let raw;
@@ -4063,7 +4063,7 @@ async function readBundleJson(bundleDir) {
4063
4063
  }
4064
4064
  }
4065
4065
  function updateStatePath(layout) {
4066
- return join10(layout.releasesRoot, ".state", "update-state.json");
4066
+ return join11(layout.releasesRoot, ".state", "update-state.json");
4067
4067
  }
4068
4068
  async function readUpdateState(layout) {
4069
4069
  try {
@@ -4073,7 +4073,7 @@ async function readUpdateState(layout) {
4073
4073
  }
4074
4074
  }
4075
4075
  async function writeUpdateState(layout, state) {
4076
- await mkdir15(join10(layout.releasesRoot, ".state"), { recursive: true });
4076
+ await mkdir15(join11(layout.releasesRoot, ".state"), { recursive: true });
4077
4077
  await writeFile10(updateStatePath(layout), `${JSON.stringify(state, null, 2)}
4078
4078
  `, "utf8");
4079
4079
  }
@@ -4137,7 +4137,7 @@ async function fetchText(url, fetchImpl) {
4137
4137
  }
4138
4138
  function run(command, args, timeoutMs) {
4139
4139
  return new Promise((resolveRun) => {
4140
- const child = spawn7(command, args, { stdio: ["ignore", "ignore", "pipe"] });
4140
+ const child = spawn8(command, args, { stdio: ["ignore", "ignore", "pipe"] });
4141
4141
  let stderr = "";
4142
4142
  child.stderr?.setEncoding("utf8");
4143
4143
  child.stderr?.on("data", (chunk) => {
@@ -4155,7 +4155,7 @@ function run(command, args, timeoutMs) {
4155
4155
  });
4156
4156
  }
4157
4157
  function entrypointCandidates(bundleDir) {
4158
- return [join10(bundleDir, BUNDLE_ENTRYPOINT), join10(bundleDir, "beeline-cli.mjs")];
4158
+ return [join11(bundleDir, BUNDLE_ENTRYPOINT), join11(bundleDir, "beeline-cli.mjs")];
4159
4159
  }
4160
4160
  async function resolveBundleEntrypoint(bundleDir) {
4161
4161
  for (const candidate of entrypointCandidates(bundleDir)) {
@@ -4177,8 +4177,8 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
4177
4177
  const fetchImpl = opts.fetchImpl ?? fetch;
4178
4178
  const log2 = opts.logger ?? ((line) => console.log(`[body] self-update: ${line}`));
4179
4179
  const releaseId = sanitizeReleaseId(published.commit ?? published.version ?? `release-${Date.now()}`);
4180
- const releaseDir = join10(layout.releasesRoot, releaseId);
4181
- const okMarker = join10(releaseDir, ".stage-ok");
4180
+ const releaseDir = join11(layout.releasesRoot, releaseId);
4181
+ const okMarker = join11(releaseDir, ".stage-ok");
4182
4182
  let previouslyVerified = false;
4183
4183
  try {
4184
4184
  const recorded = await readFile10(okMarker, "utf8");
@@ -4188,7 +4188,7 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
4188
4188
  } catch {
4189
4189
  }
4190
4190
  await mkdir15(releaseDir, { recursive: true });
4191
- const tempArchive = join10(layout.releasesRoot, `.download-${releaseId}-${process.pid}.tar.gz`);
4191
+ const tempArchive = join11(layout.releasesRoot, `.download-${releaseId}-${process.pid}.tar.gz`);
4192
4192
  try {
4193
4193
  log2(`downloading ${published.file}`);
4194
4194
  const response = await fetchImpl(archiveUrlFor(manifestUrl, published.file), {
@@ -4197,7 +4197,7 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
4197
4197
  if (!response.ok || !response.body) {
4198
4198
  throw new Error(`downloading ${published.file} failed: HTTP ${response.status}`);
4199
4199
  }
4200
- const hash = createHash7("sha256");
4200
+ const hash = createHash8("sha256");
4201
4201
  const chunks = [];
4202
4202
  for await (const chunk of response.body) {
4203
4203
  const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
@@ -4210,7 +4210,7 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
4210
4210
  }
4211
4211
  await writeFile10(tempArchive, Buffer.concat(chunks), { mode: 384 });
4212
4212
  const entries = (await new Promise((resolveList, rejectList) => {
4213
- const child = spawn7("tar", ["-tzf", tempArchive], { stdio: ["ignore", "pipe", "inherit"] });
4213
+ const child = spawn8("tar", ["-tzf", tempArchive], { stdio: ["ignore", "pipe", "inherit"] });
4214
4214
  let out = "";
4215
4215
  child.stdout?.on("data", (chunk) => {
4216
4216
  out += chunk.toString("utf8");
@@ -4228,13 +4228,13 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
4228
4228
  throw new Error(`extracting bundle failed: ${extract2.stderr}`);
4229
4229
  for (const relative3 of requiredBundlePaths()) {
4230
4230
  try {
4231
- await access(join10(releaseDir, relative3), fsConstants2.F_OK);
4231
+ await access(join11(releaseDir, relative3), fsConstants2.F_OK);
4232
4232
  } catch {
4233
4233
  throw new Error(`staged bundle is missing ${relative3}`);
4234
4234
  }
4235
4235
  }
4236
4236
  if (opts.smokeTestCli !== false) {
4237
- const probe = await run(process.execPath, [join10(releaseDir, BUNDLE_ENTRYPOINT), "--version"], 6e4);
4237
+ const probe = await run(process.execPath, [join11(releaseDir, BUNDLE_ENTRYPOINT), "--version"], 6e4);
4238
4238
  if (probe.status !== 0) {
4239
4239
  throw new Error(`staged bundle failed its startup smoke test (--version exited ${probe.status})${probe.stderr ? `: ${probe.stderr.trim()}` : ""}`);
4240
4240
  }
@@ -4272,8 +4272,8 @@ async function replaceFile(path, contents, mode) {
4272
4272
  await rename4(temp, path);
4273
4273
  }
4274
4274
  async function activateRelease(layout, releaseId) {
4275
- const releaseDir = join10(layout.releasesRoot, releaseId);
4276
- await access(join10(releaseDir, BUNDLE_ENTRYPOINT), fsConstants2.F_OK);
4275
+ const releaseDir = join11(layout.releasesRoot, releaseId);
4276
+ await access(join11(releaseDir, BUNDLE_ENTRYPOINT), fsConstants2.F_OK);
4277
4277
  await mkdir15(layout.releasesRoot, { recursive: true });
4278
4278
  await mkdir15(layout.binDir, { recursive: true });
4279
4279
  let previousReleaseId = await activeReleaseId(layout);
@@ -4281,12 +4281,12 @@ async function activateRelease(layout, releaseId) {
4281
4281
  if (kind === "directory") {
4282
4282
  const legacyIdentity = await readBundleJson(layout.libDir);
4283
4283
  const legacyId = sanitizeReleaseId(legacyIdentity?.commit ?? legacyIdentity?.version ?? `legacy-${Date.now()}`);
4284
- const legacyDir = join10(layout.releasesRoot, legacyId);
4284
+ const legacyDir = join11(layout.releasesRoot, legacyId);
4285
4285
  try {
4286
4286
  await access(legacyDir, fsConstants2.F_OK);
4287
4287
  previousReleaseId = `${legacyId}-${Date.now()}`;
4288
- await rename4(layout.libDir, join10(layout.releasesRoot, previousReleaseId));
4289
- await normalizeLegacyBundleShape(join10(layout.releasesRoot, previousReleaseId));
4288
+ await rename4(layout.libDir, join11(layout.releasesRoot, previousReleaseId));
4289
+ await normalizeLegacyBundleShape(join11(layout.releasesRoot, previousReleaseId));
4290
4290
  } catch {
4291
4291
  await rename4(layout.libDir, legacyDir);
4292
4292
  await normalizeLegacyBundleShape(legacyDir);
@@ -4295,18 +4295,18 @@ async function activateRelease(layout, releaseId) {
4295
4295
  }
4296
4296
  const tempLink = `${layout.libDir}.new-${process.pid}`;
4297
4297
  await rm6(tempLink, { force: true });
4298
- await symlink3(join10("beeline-releases", releaseId), tempLink);
4298
+ await symlink3(join11("beeline-releases", releaseId), tempLink);
4299
4299
  await rename4(tempLink, layout.libDir);
4300
- await fsyncDir(dirname11(layout.libDir));
4300
+ await fsyncDir(dirname12(layout.libDir));
4301
4301
  await writeBinForwarders(layout, releaseDir);
4302
4302
  return { previousReleaseId };
4303
4303
  }
4304
4304
  async function normalizeLegacyBundleShape(bundleDir) {
4305
- const innerLib = join10(bundleDir, "lib", "beeline");
4305
+ const innerLib = join11(bundleDir, "lib", "beeline");
4306
4306
  let anyFlat = false;
4307
4307
  for (const name of LEGACY_FLAT_BUNDLE_FILES) {
4308
4308
  try {
4309
- await access(join10(bundleDir, name), fsConstants2.F_OK);
4309
+ await access(join11(bundleDir, name), fsConstants2.F_OK);
4310
4310
  anyFlat = true;
4311
4311
  break;
4312
4312
  } catch {
@@ -4317,11 +4317,11 @@ async function normalizeLegacyBundleShape(bundleDir) {
4317
4317
  await mkdir15(innerLib, { recursive: true });
4318
4318
  for (const name of LEGACY_FLAT_BUNDLE_FILES) {
4319
4319
  try {
4320
- await access(join10(innerLib, name), fsConstants2.F_OK);
4320
+ await access(join11(innerLib, name), fsConstants2.F_OK);
4321
4321
  continue;
4322
4322
  } catch {
4323
4323
  }
4324
- await rename4(join10(bundleDir, name), join10(innerLib, name)).catch(() => void 0);
4324
+ await rename4(join11(bundleDir, name), join11(innerLib, name)).catch(() => void 0);
4325
4325
  }
4326
4326
  }
4327
4327
  async function writeBinForwarders(layout, activeBundleRoot) {
@@ -4330,13 +4330,13 @@ async function writeBinForwarders(layout, activeBundleRoot) {
4330
4330
  ...Object.entries(FORWARDER_ALIASES).map(([alias, tool]) => [alias, tool])
4331
4331
  ];
4332
4332
  for (const [name, tool] of entries) {
4333
- const target = join10(activeBundleRoot, "bin", tool);
4333
+ const target = join11(activeBundleRoot, "bin", tool);
4334
4334
  try {
4335
4335
  await access(target, fsConstants2.X_OK);
4336
4336
  } catch {
4337
4337
  continue;
4338
4338
  }
4339
- await replaceFile(join10(layout.binDir, name), forwarderScript(tool), 493);
4339
+ await replaceFile(join11(layout.binDir, name), forwarderScript(tool), 493);
4340
4340
  }
4341
4341
  }
4342
4342
  async function repairInstallForwarders(layout, opts = {}) {
@@ -4345,7 +4345,7 @@ async function repairInstallForwarders(layout, opts = {}) {
4345
4345
  const forwarderHealthy = async (name, tool) => {
4346
4346
  let current;
4347
4347
  try {
4348
- current = await readFile10(join10(layout.binDir, name), "utf8");
4348
+ current = await readFile10(join11(layout.binDir, name), "utf8");
4349
4349
  } catch {
4350
4350
  current = void 0;
4351
4351
  }
@@ -4364,19 +4364,19 @@ async function repairInstallForwarders(layout, opts = {}) {
4364
4364
  return true;
4365
4365
  }
4366
4366
  async function rollbackToPreviousRelease(layout, previousReleaseId) {
4367
- const releaseDir = join10(layout.releasesRoot, previousReleaseId);
4367
+ const releaseDir = join11(layout.releasesRoot, previousReleaseId);
4368
4368
  const entrypoint = await resolveBundleEntrypoint(releaseDir);
4369
4369
  if (!entrypoint) {
4370
4370
  throw new Error(`release ${previousReleaseId} has no runnable CLI entrypoint`);
4371
4371
  }
4372
4372
  const tempLink = `${layout.libDir}.rollback-${process.pid}`;
4373
4373
  await rm6(tempLink, { force: true });
4374
- await symlink3(join10("beeline-releases", previousReleaseId), tempLink);
4374
+ await symlink3(join11("beeline-releases", previousReleaseId), tempLink);
4375
4375
  await rename4(tempLink, layout.libDir);
4376
- await fsyncDir(dirname11(layout.libDir));
4376
+ await fsyncDir(dirname12(layout.libDir));
4377
4377
  }
4378
4378
  function updateAttemptPath(layout) {
4379
- return join10(layout.releasesRoot, ".state", "update-attempt.json");
4379
+ return join11(layout.releasesRoot, ".state", "update-attempt.json");
4380
4380
  }
4381
4381
  async function readUpdateAttempt(layout) {
4382
4382
  try {
@@ -4390,7 +4390,7 @@ async function readUpdateAttempt(layout) {
4390
4390
  }
4391
4391
  }
4392
4392
  async function writeUpdateAttempt(layout, record3) {
4393
- await mkdir15(join10(layout.releasesRoot, ".state"), { recursive: true });
4393
+ await mkdir15(join11(layout.releasesRoot, ".state"), { recursive: true });
4394
4394
  const path = updateAttemptPath(layout);
4395
4395
  const staged = `${path}.${process.pid}.tmp`;
4396
4396
  await writeFile10(staged, `${JSON.stringify(record3, null, 2)}
@@ -4668,7 +4668,7 @@ function configureNetworkFamilyDefaults(network = net) {
4668
4668
  configureNetworkFamilyDefaults();
4669
4669
 
4670
4670
  // apps/body/dist/cli.js
4671
- import { dirname as dirname17, resolve as resolve30 } from "node:path";
4671
+ import { dirname as dirname18, resolve as resolve31 } from "node:path";
4672
4672
  import { readFile as readFile15, unlink as unlink5, writeFile as writeFile16 } from "node:fs/promises";
4673
4673
  import { stdin as stdin4, stdout as stdout5 } from "node:process";
4674
4674
 
@@ -6079,13 +6079,496 @@ ${r2}
6079
6079
  var import_picocolors3 = __toESM(require_picocolors(), 1);
6080
6080
 
6081
6081
  // apps/body/dist/config.js
6082
- import { accessSync as accessSync2, constants as constants2, existsSync as existsSync2, readFileSync } from "node:fs";
6082
+ import { accessSync as accessSync2, constants as constants2, existsSync as existsSync3, readFileSync } from "node:fs";
6083
6083
  import { basename, dirname, resolve as resolve2 } from "node:path";
6084
6084
 
6085
6085
  // apps/body/dist/agent-command.js
6086
- import { accessSync, constants, existsSync, readdirSync } from "node:fs";
6086
+ import { accessSync, constants, existsSync as existsSync2, readdirSync } from "node:fs";
6087
6087
  import { homedir } from "node:os";
6088
6088
  import { delimiter, isAbsolute, join, resolve } from "node:path";
6089
+
6090
+ // apps/body/dist/cursor-acp-bridge.js
6091
+ import { spawn as spawn2 } from "node:child_process";
6092
+ import { existsSync } from "node:fs";
6093
+ import { createRequire } from "node:module";
6094
+ import { createInterface as createInterface2 } from "node:readline";
6095
+ import { resolve as resolvePath } from "node:path";
6096
+ import { fileURLToPath } from "node:url";
6097
+ import { randomUUID } from "node:crypto";
6098
+
6099
+ // apps/body/dist/cursor-models.js
6100
+ import { spawn } from "node:child_process";
6101
+ var CURSOR_MODELS_TIMEOUT_MS = 1e4;
6102
+ function parseCursorModelsOutput(output) {
6103
+ const options = [];
6104
+ for (const line of output.split(/\r?\n/)) {
6105
+ const match = /^\s*([A-Za-z0-9][A-Za-z0-9._-]*)\s+-\s+(\S.*?)\s*$/.exec(line);
6106
+ if (!match)
6107
+ continue;
6108
+ const id = match[1];
6109
+ const name = match[2].replace(/\s*\(current, default\)\s*$/i, "").trim();
6110
+ options.push({ id, ...name && name !== id ? { name } : {} });
6111
+ }
6112
+ if (!options.length)
6113
+ return void 0;
6114
+ return {
6115
+ currentValue: options.some((option) => option.id === "auto") ? "auto" : options[0].id,
6116
+ options
6117
+ };
6118
+ }
6119
+ async function enumerateCursorModels(env = process.env) {
6120
+ return new Promise((resolve32) => {
6121
+ const child = spawn("cursor-agent", ["models"], {
6122
+ env,
6123
+ stdio: ["ignore", "pipe", "ignore"]
6124
+ });
6125
+ let output = "";
6126
+ const timer = setTimeout(() => {
6127
+ child.kill("SIGKILL");
6128
+ }, CURSOR_MODELS_TIMEOUT_MS);
6129
+ child.stdout?.on("data", (chunk) => {
6130
+ output += chunk.toString();
6131
+ });
6132
+ child.on("error", () => {
6133
+ clearTimeout(timer);
6134
+ resolve32(void 0);
6135
+ });
6136
+ child.on("close", (code) => {
6137
+ clearTimeout(timer);
6138
+ resolve32(code === 0 ? parseCursorModelsOutput(output) : void 0);
6139
+ });
6140
+ });
6141
+ }
6142
+
6143
+ // apps/body/dist/cursor-acp-bridge.js
6144
+ var CURSOR_ACP_BRIDGE_FLAG = "--cursor-acp-bridge";
6145
+ var CURSOR_ACP_BRIDGE_LABEL = "cursor-acp-bridge";
6146
+ var CURSOR_AGENT_FORCE_FLAG = "--force";
6147
+ var CURSOR_AGENT_TRUST_FLAG = "--trust";
6148
+ var CURSOR_HARNESS_COMMAND = /(^|[/\\])(cursor-acp-bridge|cursor-agent-acp)(\.[a-z]+)?$/i;
6149
+ var STDERR_TAIL_MAX_CHARS = 2e3;
6150
+ var MODEL_AXIS_ID = "model";
6151
+ function harnessIdentityLabel(agent) {
6152
+ if (agent.kind === "cursor")
6153
+ return CURSOR_ACP_BRIDGE_LABEL;
6154
+ return agent.command ?? "";
6155
+ }
6156
+ function cursorAcpBridgeLaunch() {
6157
+ const meta = "usebeeline:npm";
6158
+ if (meta === "beeline:bundle" || meta.startsWith("beeline:")) {
6159
+ const entry = process.argv[1];
6160
+ if (!entry) {
6161
+ throw new Error("Cursor ACP bridge cannot resolve the Beeline CLI entry");
6162
+ }
6163
+ return { command: process.execPath, args: [entry, CURSOR_ACP_BRIDGE_FLAG] };
6164
+ }
6165
+ const js = fileURLToPath(new URL("./cursor-acp-bridge.js", meta));
6166
+ const ts = fileURLToPath(new URL("./cursor-acp-bridge.ts", meta));
6167
+ if (existsSync(js))
6168
+ return { command: process.execPath, args: [js] };
6169
+ if (existsSync(ts)) {
6170
+ const tsx = createRequire(meta).resolve("tsx");
6171
+ return { command: process.execPath, args: ["--import", tsx, ts] };
6172
+ }
6173
+ throw new Error("Cursor ACP bridge entry not found next to the Beeline helper");
6174
+ }
6175
+ function cursorAgentArgv(input) {
6176
+ const argv = [
6177
+ "--print",
6178
+ "--output-format",
6179
+ "stream-json",
6180
+ CURSOR_AGENT_TRUST_FLAG,
6181
+ CURSOR_AGENT_FORCE_FLAG
6182
+ ];
6183
+ if (input.model && input.model !== "auto")
6184
+ argv.push("--model", input.model);
6185
+ argv.push(input.prompt);
6186
+ return argv;
6187
+ }
6188
+ function asRecord(value) {
6189
+ return value && typeof value === "object" ? value : void 0;
6190
+ }
6191
+ function textChunksFromContent(content) {
6192
+ if (typeof content === "string" && content)
6193
+ return [content];
6194
+ if (!Array.isArray(content))
6195
+ return [];
6196
+ const chunks = [];
6197
+ for (const block2 of content) {
6198
+ const record3 = asRecord(block2);
6199
+ if (!record3)
6200
+ continue;
6201
+ if (record3.type === "text" && typeof record3.text === "string" && record3.text) {
6202
+ chunks.push(record3.text);
6203
+ }
6204
+ }
6205
+ return chunks;
6206
+ }
6207
+ function thoughtText(event) {
6208
+ if (typeof event.text === "string")
6209
+ return event.text;
6210
+ const record3 = asRecord(event);
6211
+ if (!record3)
6212
+ return "";
6213
+ if (typeof record3.delta === "string")
6214
+ return record3.delta;
6215
+ return textChunksFromContent(record3.content).join("");
6216
+ }
6217
+ function assistantTexts(event) {
6218
+ if (typeof event.text === "string" && event.text)
6219
+ return [event.text];
6220
+ const message = asRecord(event.message);
6221
+ if (message)
6222
+ return textChunksFromContent(message.content);
6223
+ return textChunksFromContent(asRecord(event)?.content);
6224
+ }
6225
+ function chunkUpdate(sessionUpdate, text2) {
6226
+ return { sessionUpdate, content: { type: "text", text: text2 } };
6227
+ }
6228
+ function translateCursorStreamEvent(event) {
6229
+ if (event.type === "thinking") {
6230
+ if (event.subtype === "completed")
6231
+ return [];
6232
+ const text2 = thoughtText(event);
6233
+ return text2 ? [chunkUpdate("agent_thought_chunk", text2)] : [];
6234
+ }
6235
+ if (event.type === "assistant") {
6236
+ return assistantTexts(event).map((text2) => chunkUpdate("agent_message_chunk", text2));
6237
+ }
6238
+ return [];
6239
+ }
6240
+ function resultEventText(event) {
6241
+ if (typeof event.result === "string")
6242
+ return event.result;
6243
+ const record3 = asRecord(event.result);
6244
+ if (record3 && typeof record3.text === "string")
6245
+ return record3.text;
6246
+ return "";
6247
+ }
6248
+ function isCursorResultEvent(event) {
6249
+ return event.type === "result";
6250
+ }
6251
+ function cursorResultIsError(event) {
6252
+ return event.is_error === true || event.subtype === "error";
6253
+ }
6254
+ function trimReason(value) {
6255
+ return value.replace(/\s+/g, " ").trim().slice(0, 200);
6256
+ }
6257
+ function describeCursorTurnFailure(input) {
6258
+ if (input.spawnError) {
6259
+ return trimReason(`cursor-agent failed to start: ${input.spawnError}`);
6260
+ }
6261
+ const stderr = input.stderr?.trim() ?? "";
6262
+ if (input.isError) {
6263
+ const named = input.resultText?.trim() || stderr || "cursor-agent reported an error with no answer text";
6264
+ return trimReason(`cursor-agent reported an error: ${named}`);
6265
+ }
6266
+ if (input.signal) {
6267
+ return trimReason(`cursor-agent terminated by ${input.signal}${stderr ? `: ${stderr}` : ""}`);
6268
+ }
6269
+ if (input.exitCode !== 0 && input.exitCode !== null) {
6270
+ return trimReason(`cursor-agent exited ${input.exitCode}${stderr ? `: ${stderr}` : " with no answer text"}`);
6271
+ }
6272
+ return void 0;
6273
+ }
6274
+ function promptTextFromParams(params, systemPrompt) {
6275
+ const record3 = asRecord(params);
6276
+ const blocks = Array.isArray(record3?.prompt) ? record3.prompt : [];
6277
+ const user = blocks.map((block2) => {
6278
+ const item = asRecord(block2);
6279
+ return item?.type === "text" && typeof item.text === "string" ? item.text : "";
6280
+ }).filter(Boolean).join("\n");
6281
+ return systemPrompt ? `${systemPrompt}
6282
+
6283
+ ${user}` : user;
6284
+ }
6285
+ function defaultSpawnCursorAgent(input) {
6286
+ return spawn2("cursor-agent", input.argv, {
6287
+ cwd: input.cwd,
6288
+ env: input.env,
6289
+ stdio: ["ignore", "pipe", "pipe"]
6290
+ });
6291
+ }
6292
+ var CursorAcpServer = class {
6293
+ write;
6294
+ spawnCursorAgent;
6295
+ enumerateModels;
6296
+ env;
6297
+ sessions = /* @__PURE__ */ new Map();
6298
+ models;
6299
+ modelsLoaded = false;
6300
+ constructor(options) {
6301
+ this.write = options.write;
6302
+ this.spawnCursorAgent = options.spawnCursorAgent ?? defaultSpawnCursorAgent;
6303
+ this.enumerateModels = options.enumerateModels ?? enumerateCursorModels;
6304
+ this.env = options.env ?? process.env;
6305
+ }
6306
+ async handle(message) {
6307
+ const method = typeof message.method === "string" ? message.method : "";
6308
+ const id = message.id;
6309
+ if (!method)
6310
+ return;
6311
+ if (id === void 0) {
6312
+ if (method === "session/cancel")
6313
+ this.cancel(message.params);
6314
+ return;
6315
+ }
6316
+ try {
6317
+ const result = await this.dispatch(method, message.params);
6318
+ this.write({ jsonrpc: "2.0", id, result });
6319
+ } catch (error) {
6320
+ const rpcError = error;
6321
+ this.write({
6322
+ jsonrpc: "2.0",
6323
+ id,
6324
+ error: {
6325
+ code: typeof rpcError.code === "number" ? rpcError.code : -32e3,
6326
+ message: error instanceof Error ? error.message : String(error)
6327
+ }
6328
+ });
6329
+ }
6330
+ }
6331
+ async dispatch(method, params) {
6332
+ switch (method) {
6333
+ case "initialize":
6334
+ return {
6335
+ protocolVersion: 1,
6336
+ agentCapabilities: { promptCapabilities: { image: false } }
6337
+ };
6338
+ case "session/new":
6339
+ return this.sessionNew(params);
6340
+ case "session/prompt":
6341
+ return this.sessionPrompt(params);
6342
+ case "session/set_config_option":
6343
+ return this.setConfigOption(params);
6344
+ case "session/set_model":
6345
+ return this.setModel(params);
6346
+ case "shutdown":
6347
+ this.shutdown();
6348
+ return {};
6349
+ default:
6350
+ return {};
6351
+ }
6352
+ }
6353
+ async loadModels() {
6354
+ if (this.modelsLoaded) {
6355
+ return this.models ?? { currentValue: "auto", options: [{ id: "auto", name: "Auto" }] };
6356
+ }
6357
+ this.modelsLoaded = true;
6358
+ this.models = await this.enumerateModels(this.env);
6359
+ return this.models ?? { currentValue: "auto", options: [{ id: "auto", name: "Auto" }] };
6360
+ }
6361
+ async sessionNew(params) {
6362
+ const record3 = asRecord(params);
6363
+ const cwd = typeof record3?.cwd === "string" && record3.cwd ? record3.cwd : process.cwd();
6364
+ const systemPrompt = typeof record3?.systemPrompt === "string" ? record3.systemPrompt : void 0;
6365
+ const catalog = await this.loadModels();
6366
+ const session = {
6367
+ id: randomUUID(),
6368
+ cwd,
6369
+ ...systemPrompt ? { systemPrompt } : {},
6370
+ model: catalog.currentValue
6371
+ };
6372
+ this.sessions.set(session.id, session);
6373
+ return {
6374
+ sessionId: session.id,
6375
+ configOptions: [
6376
+ {
6377
+ id: MODEL_AXIS_ID,
6378
+ category: "model",
6379
+ currentValue: session.model,
6380
+ options: catalog.options.map((option) => ({
6381
+ id: option.id,
6382
+ ...option.name ? { name: option.name } : {}
6383
+ }))
6384
+ }
6385
+ ]
6386
+ };
6387
+ }
6388
+ session(params) {
6389
+ const record3 = asRecord(params);
6390
+ const sessionId = typeof record3?.sessionId === "string" ? record3.sessionId : "";
6391
+ const session = this.sessions.get(sessionId);
6392
+ if (!session) {
6393
+ const error = new Error(`unknown ACP session ${sessionId || "(missing)"}`);
6394
+ error.code = -32602;
6395
+ throw error;
6396
+ }
6397
+ return session;
6398
+ }
6399
+ setConfigOption(params) {
6400
+ const session = this.session(params);
6401
+ const record3 = asRecord(params);
6402
+ if (record3?.configId === MODEL_AXIS_ID && typeof record3.value === "string" && record3.value) {
6403
+ session.model = record3.value;
6404
+ }
6405
+ return {};
6406
+ }
6407
+ setModel(params) {
6408
+ const session = this.session(params);
6409
+ const record3 = asRecord(params);
6410
+ if (typeof record3?.modelId === "string" && record3.modelId)
6411
+ session.model = record3.modelId;
6412
+ return {};
6413
+ }
6414
+ emitUpdate(sessionId, update) {
6415
+ this.write({
6416
+ jsonrpc: "2.0",
6417
+ method: "session/update",
6418
+ params: { sessionId, update }
6419
+ });
6420
+ }
6421
+ async sessionPrompt(params) {
6422
+ const session = this.session(params);
6423
+ if (session.child) {
6424
+ throw new Error("cursor-agent is already running a turn for this session");
6425
+ }
6426
+ const prompt = promptTextFromParams(params, session.systemPrompt);
6427
+ const argv = cursorAgentArgv({ prompt, model: session.model });
6428
+ let stderr = "";
6429
+ let spawnError;
6430
+ let sawAssistant = false;
6431
+ let resultEvent;
6432
+ const pending = [];
6433
+ const consumeLine = (line) => {
6434
+ const trimmed = line.trim();
6435
+ if (!trimmed)
6436
+ return;
6437
+ let event;
6438
+ try {
6439
+ event = JSON.parse(trimmed);
6440
+ } catch {
6441
+ return;
6442
+ }
6443
+ if (isCursorResultEvent(event)) {
6444
+ resultEvent = event;
6445
+ return;
6446
+ }
6447
+ for (const update of translateCursorStreamEvent(event)) {
6448
+ if (update.sessionUpdate === "agent_message_chunk")
6449
+ sawAssistant = true;
6450
+ this.emitUpdate(session.id, update);
6451
+ }
6452
+ };
6453
+ const child = this.spawnCursorAgent({ argv, cwd: session.cwd, env: this.env });
6454
+ session.child = child;
6455
+ child.stderr?.setEncoding("utf8");
6456
+ child.stderr?.on("data", (chunk) => {
6457
+ stderr = `${stderr}${chunk}`.slice(-STDERR_TAIL_MAX_CHARS);
6458
+ });
6459
+ child.stdout?.setEncoding("utf8");
6460
+ child.stdout?.on("data", (chunk) => {
6461
+ pending.push(chunk);
6462
+ const joined = pending.join("");
6463
+ const lines = joined.split(/\r?\n/);
6464
+ pending.length = 0;
6465
+ const rest = lines.pop();
6466
+ if (rest)
6467
+ pending.push(rest);
6468
+ for (const line of lines)
6469
+ consumeLine(line);
6470
+ });
6471
+ try {
6472
+ const { code, signal } = await new Promise((resolve32) => {
6473
+ let settled = false;
6474
+ const finish = (exitCode, exitSignal) => {
6475
+ if (settled)
6476
+ return;
6477
+ settled = true;
6478
+ resolve32({ code: exitCode, signal: exitSignal });
6479
+ };
6480
+ child.once("error", (error) => {
6481
+ spawnError = error instanceof Error ? error.message : String(error);
6482
+ finish(1, null);
6483
+ });
6484
+ child.once("close", (exitCode, exitSignal) => {
6485
+ finish(exitCode, exitSignal);
6486
+ });
6487
+ });
6488
+ if (pending.length)
6489
+ consumeLine(pending.join(""));
6490
+ const failure = describeCursorTurnFailure({
6491
+ isError: resultEvent ? cursorResultIsError(resultEvent) : false,
6492
+ resultText: resultEvent ? resultEventText(resultEvent) : void 0,
6493
+ exitCode: spawnError ? 1 : code,
6494
+ signal,
6495
+ stderr,
6496
+ spawnError
6497
+ });
6498
+ if (failure)
6499
+ throw new Error(failure);
6500
+ if (!sawAssistant) {
6501
+ const fallback = resultEvent && !cursorResultIsError(resultEvent) ? resultEventText(resultEvent) : "";
6502
+ if (fallback)
6503
+ this.emitUpdate(session.id, chunkUpdate("agent_message_chunk", fallback));
6504
+ }
6505
+ return { stopReason: "end_turn" };
6506
+ } finally {
6507
+ session.child = void 0;
6508
+ }
6509
+ }
6510
+ cancel(params) {
6511
+ const record3 = asRecord(params);
6512
+ const sessionId = typeof record3?.sessionId === "string" ? record3.sessionId : "";
6513
+ const session = this.sessions.get(sessionId);
6514
+ if (!session?.child?.pid)
6515
+ return;
6516
+ try {
6517
+ session.child.kill("SIGTERM");
6518
+ } catch {
6519
+ }
6520
+ }
6521
+ shutdown() {
6522
+ for (const session of this.sessions.values()) {
6523
+ if (!session.child?.pid)
6524
+ continue;
6525
+ try {
6526
+ session.child.kill("SIGTERM");
6527
+ } catch {
6528
+ }
6529
+ }
6530
+ this.sessions.clear();
6531
+ }
6532
+ };
6533
+ async function runCursorAcpStdioServer(options = {}) {
6534
+ const server = new CursorAcpServer({
6535
+ ...options,
6536
+ write: (message) => {
6537
+ process.stdout.write(`${JSON.stringify(message)}
6538
+ `);
6539
+ }
6540
+ });
6541
+ const lines = createInterface2({ input: process.stdin });
6542
+ for await (const line of lines) {
6543
+ const trimmed = line.trim();
6544
+ if (!trimmed)
6545
+ continue;
6546
+ let message;
6547
+ try {
6548
+ message = JSON.parse(trimmed);
6549
+ } catch {
6550
+ continue;
6551
+ }
6552
+ await server.handle(message);
6553
+ if (message.method === "shutdown")
6554
+ break;
6555
+ }
6556
+ }
6557
+ function isDirectBridgeRun() {
6558
+ const entry = process.argv[1];
6559
+ if (!entry || entry.includes(".test."))
6560
+ return false;
6561
+ try {
6562
+ return resolvePath(entry) === resolvePath(fileURLToPath("usebeeline:npm"));
6563
+ } catch {
6564
+ return false;
6565
+ }
6566
+ }
6567
+ if (isDirectBridgeRun()) {
6568
+ void runCursorAcpStdioServer();
6569
+ }
6570
+
6571
+ // apps/body/dist/agent-command.js
6089
6572
  var AGENT_KINDS = [
6090
6573
  "codex",
6091
6574
  "claude",
@@ -6117,10 +6600,6 @@ var ADAPTER_INSTALL_COMMANDS = {
6117
6600
  pi: {
6118
6601
  command: "npm",
6119
6602
  args: ["install", "-g", "pi-acp"]
6120
- },
6121
- cursor: {
6122
- command: "npm",
6123
- args: ["install", "-g", "cursor-agent-acp"]
6124
6603
  }
6125
6604
  };
6126
6605
  function adapterInstallHint(kind) {
@@ -6190,7 +6669,7 @@ function describeExecutableSearch(env = process.env) {
6190
6669
  return augmentedSearchDirectories(env).join(", ");
6191
6670
  }
6192
6671
  function firstExisting(paths) {
6193
- return paths.find((path) => path && existsSync(path));
6672
+ return paths.find((path) => path && existsSync2(path));
6194
6673
  }
6195
6674
  function executableOnPath(name, env = process.env) {
6196
6675
  for (const directory of augmentedSearchDirectories(env)) {
@@ -6303,8 +6782,8 @@ function resolveAgentCommand(opts) {
6303
6782
  }
6304
6783
  if (typedKind === "cursor") {
6305
6784
  requireExecutable("cursor-agent", env, cwd, "Cursor Agent CLI not found. Install it from https://cursor.com/docs/cli, then retry with `--agent cursor`.");
6306
- const command2 = requireExecutable("cursor-agent-acp", env, cwd, `Cursor ACP adapter not found. Install it with \`${adapterInstallHint("cursor")}\`, then retry with \`--agent cursor\`.`);
6307
- return { kind: typedKind, command: command2, args: [] };
6785
+ const bridge = cursorAcpBridgeLaunch();
6786
+ return { kind: typedKind, command: bridge.command, args: bridge.args };
6308
6787
  }
6309
6788
  if (typedKind === "grok") {
6310
6789
  const command2 = requireExecutable("grok", env, cwd, "Grok CLI not found. Install it with `curl -fsSL https://x.ai/cli/install.sh | bash`, then retry with `--agent grok`.");
@@ -6341,7 +6820,7 @@ function detectInstalledAgentCommands(opts = {}) {
6341
6820
  agent: resolveAgentCommand({ kind, env, cwd: opts.cwd })
6342
6821
  });
6343
6822
  } catch {
6344
- if (kind !== "goose" && kind !== "grok") {
6823
+ if (kind !== "goose" && kind !== "grok" && kind !== "cursor") {
6345
6824
  detected.push({
6346
6825
  kind,
6347
6826
  status: "missing-adapter",
@@ -6365,7 +6844,7 @@ function formatAdapterInstallCommand(install) {
6365
6844
  // apps/body/dist/config.js
6366
6845
  function firstExisting2(paths) {
6367
6846
  for (const p of paths) {
6368
- if (p && existsSync2(p))
6847
+ if (p && existsSync3(p))
6369
6848
  return p;
6370
6849
  }
6371
6850
  return void 0;
@@ -6418,7 +6897,7 @@ function resolveReadonlyMcpCommand(env = process.env) {
6418
6897
  if (binary)
6419
6898
  return { command: binary, args: [] };
6420
6899
  const script = env.BEELINE_READONLY_MCP_SCRIPT;
6421
- if (script && existsSync2(script))
6900
+ if (script && existsSync3(script))
6422
6901
  return { command: process.execPath, args: [script] };
6423
6902
  const built = firstExisting2([
6424
6903
  resolve2(process.cwd(), "apps", "body", "dist", "read-only-mcp.js"),
@@ -6453,7 +6932,7 @@ function resolveCodegraphCommand(env = process.env) {
6453
6932
  }
6454
6933
  function parseEnvFile(path) {
6455
6934
  const out = {};
6456
- if (!existsSync2(path))
6935
+ if (!existsSync3(path))
6457
6936
  return out;
6458
6937
  const text2 = readFileSync(path, "utf8");
6459
6938
  for (const raw of text2.split("\n")) {
@@ -6694,7 +7173,7 @@ import { tmpdir } from "node:os";
6694
7173
  import { resolve as resolve4 } from "node:path";
6695
7174
 
6696
7175
  // apps/body/dist/acp.js
6697
- import { spawn } from "node:child_process";
7176
+ import { spawn as spawn3 } from "node:child_process";
6698
7177
  import { EventEmitter } from "node:events";
6699
7178
 
6700
7179
  // apps/body/dist/harness-capabilities.js
@@ -6775,10 +7254,10 @@ var PROFILES = [
6775
7254
  }
6776
7255
  },
6777
7256
  {
6778
- match: /(^|[/\\])cursor-agent-acp(\.[a-z]+)?$/i,
7257
+ match: CURSOR_HARNESS_COMMAND,
6779
7258
  profile: {
6780
7259
  enforcement: "config-isolated",
6781
- note: "cursor-agent-acp bridges cursor-agent to ACP; cursor-agent loads MCP servers from ~/.cursor/mcp.json, so an isolated CURSOR_HOME scopes the session"
7260
+ note: "cursor-acp-bridge drives cursor-agent; cursor-agent loads MCP servers from ~/.cursor/mcp.json, so an isolated CURSOR_HOME scopes the session"
6782
7261
  }
6783
7262
  }
6784
7263
  ];
@@ -6800,7 +7279,7 @@ function matchProfile(agentCommand) {
6800
7279
  }
6801
7280
 
6802
7281
  // apps/body/dist/acp.js
6803
- var STDERR_TAIL_MAX_CHARS = 2e3;
7282
+ var STDERR_TAIL_MAX_CHARS2 = 2e3;
6804
7283
  function braceDelta(line) {
6805
7284
  let delta = 0;
6806
7285
  for (const char of line) {
@@ -7015,7 +7494,7 @@ function agentStreamSnapshot(updates, agentLabel) {
7015
7494
  const completedMessages = [];
7016
7495
  let messageText2 = "";
7017
7496
  let lastWasMessage = false;
7018
- let thoughtText = "";
7497
+ let thoughtText2 = "";
7019
7498
  let thoughtRunOpen = false;
7020
7499
  for (const { update } of updates) {
7021
7500
  const kind = typeof update.sessionUpdate === "string" ? update.sessionUpdate : "";
@@ -7044,8 +7523,8 @@ function agentStreamSnapshot(updates, agentLabel) {
7044
7523
  if (!delta)
7045
7524
  continue;
7046
7525
  if (!thoughtRunOpen)
7047
- thoughtText = "";
7048
- thoughtText += delta;
7526
+ thoughtText2 = "";
7527
+ thoughtText2 += delta;
7049
7528
  thoughtRunOpen = true;
7050
7529
  } else {
7051
7530
  thoughtRunOpen = false;
@@ -7053,7 +7532,7 @@ function agentStreamSnapshot(updates, agentLabel) {
7053
7532
  }
7054
7533
  return {
7055
7534
  messageText: messageText2,
7056
- ...thoughtText || completedMessages.length ? { thoughtText: thoughtText || completedMessages.at(-1) } : {}
7535
+ ...thoughtText2 || completedMessages.length ? { thoughtText: thoughtText2 || completedMessages.at(-1) } : {}
7057
7536
  };
7058
7537
  }
7059
7538
  function toolCallEntries(updates) {
@@ -7139,7 +7618,7 @@ var AcpClient = class extends EventEmitter {
7139
7618
  async start(timeoutMs = 6e4) {
7140
7619
  if (this.alive)
7141
7620
  return;
7142
- this.child = spawn(this.agentCommand, this.agentArgs, {
7621
+ this.child = spawn3(this.agentCommand, this.agentArgs, {
7143
7622
  // agentEnv is the child's whole environment: buildAgentEnv's allowlist is
7144
7623
  // a real boundary, not a decorative one layered over a full inherit.
7145
7624
  env: this.inheritProcessEnv ? { ...process.env, ...this.agentEnv } : this.agentEnv,
@@ -7154,7 +7633,7 @@ var AcpClient = class extends EventEmitter {
7154
7633
  this.stderrTail = "";
7155
7634
  this.child.stderr.setEncoding("utf8");
7156
7635
  this.child.stderr.on("data", (chunk) => {
7157
- this.stderrTail = (this.stderrTail + chunk).slice(-STDERR_TAIL_MAX_CHARS);
7636
+ this.stderrTail = (this.stderrTail + chunk).slice(-STDERR_TAIL_MAX_CHARS2);
7158
7637
  this.emit("stderr", chunk);
7159
7638
  });
7160
7639
  this.child.stdout.setEncoding("utf8");
@@ -7553,7 +8032,7 @@ var AcpClient = class extends EventEmitter {
7553
8032
  const current = this.activeRunIds.get(sessionId);
7554
8033
  if (current)
7555
8034
  return Promise.resolve(current);
7556
- return new Promise((resolve31, reject) => {
8035
+ return new Promise((resolve32, reject) => {
7557
8036
  const onUpdate = (update) => {
7558
8037
  if (update.sessionId !== sessionId)
7559
8038
  return;
@@ -7561,7 +8040,7 @@ var AcpClient = class extends EventEmitter {
7561
8040
  if (!runId)
7562
8041
  return;
7563
8042
  cleanup();
7564
- resolve31(runId);
8043
+ resolve32(runId);
7565
8044
  };
7566
8045
  const timer = setTimeout(() => {
7567
8046
  cleanup();
@@ -7645,13 +8124,13 @@ var AcpClient = class extends EventEmitter {
7645
8124
  }
7646
8125
  const id = this.nextId++;
7647
8126
  const payload = { jsonrpc: "2.0", id, method, params };
7648
- return new Promise((resolve31, reject) => {
8127
+ return new Promise((resolve32, reject) => {
7649
8128
  const timer = setTimeout(() => {
7650
8129
  this.pending.delete(id);
7651
8130
  reject(new AcpRequestTimeoutError(method, timeoutMs, this.stderrTail, Boolean(onStart), detail));
7652
8131
  }, timeoutMs);
7653
8132
  this.pending.set(id, {
7654
- resolve: resolve31,
8133
+ resolve: resolve32,
7655
8134
  reject,
7656
8135
  timer,
7657
8136
  method,
@@ -8170,8 +8649,8 @@ async function syncAgentModelCatalog(input) {
8170
8649
  }
8171
8650
 
8172
8651
  // apps/body/dist/connector-google.js
8173
- import { readFileSync as readFileSync3 } from "node:fs";
8174
- import { join as join2 } from "node:path";
8652
+ import { readFileSync as readFileSync4 } from "node:fs";
8653
+ import { join as join3 } from "node:path";
8175
8654
 
8176
8655
  // apps/body/dist/google-workspace-client.js
8177
8656
  function credentialsTokenSource(credentials) {
@@ -8391,182 +8870,164 @@ function googleWorkspaceClient(tokenSource, transport = defaultGoogleApiTranspor
8391
8870
  };
8392
8871
  }
8393
8872
 
8394
- // apps/body/dist/connector-google.js
8395
- var GOOGLE_TOOL_SCOPES = {
8396
- "google-gmail": [
8397
- "https://www.googleapis.com/auth/gmail.send",
8398
- "https://www.googleapis.com/auth/gmail.readonly",
8399
- "https://www.googleapis.com/auth/gmail.compose"
8400
- ],
8401
- "google-calendar": ["https://www.googleapis.com/auth/calendar.events", "https://www.googleapis.com/auth/calendar.readonly"],
8402
- "google-drive": ["https://www.googleapis.com/auth/drive.readonly"],
8403
- "google-youtube": ["https://www.googleapis.com/auth/youtube.readonly"]
8404
- };
8405
- function isGoogleToolConnectorType(type) {
8406
- return type in GOOGLE_TOOL_SCOPES;
8873
+ // apps/body/dist/connector-squire.js
8874
+ import { execFile, spawn as spawn4 } from "node:child_process";
8875
+ import { createHash as createHash2 } from "node:crypto";
8876
+ import { lstatSync as lstatSync2, readFileSync as readFileSync3, realpathSync, rmSync } from "node:fs";
8877
+ import { homedir as homedir2, hostname, tmpdir as tmpdir2 } from "node:os";
8878
+ import { basename as basename3, dirname as dirname2, join as join2, resolve as resolve6 } from "node:path";
8879
+ var SQUIRE_MCP_NAME = "@trusty-squire/mcp";
8880
+ var SQUIRE_CONNECT_PACKAGE = `${SQUIRE_MCP_NAME}@latest`;
8881
+ var activeConnectSession;
8882
+ function squireConnectSession() {
8883
+ return activeConnectSession;
8407
8884
  }
8408
- async function readGoogleCredentialsFromVault(mcp) {
8409
- if (!mcp)
8410
- return { source: "unavailable", reason: "no Trusty Squire connector is paired" };
8411
- let raw;
8885
+ function isProcessAlive(pid) {
8886
+ if (pid === void 0 || pid <= 0)
8887
+ return false;
8412
8888
  try {
8413
- raw = await mcp.call("google_oauth_credentials", {});
8889
+ process.kill(pid, 0);
8890
+ return true;
8414
8891
  } catch (error) {
8415
- return {
8416
- source: "unavailable",
8417
- reason: `Squire has no Google OAuth grant on record yet (connect your Google account in Squire first: ${describe(error)})`
8418
- };
8892
+ return error?.code === "EPERM";
8419
8893
  }
8420
- const record3 = raw && typeof raw === "object" ? raw : {};
8421
- const inner = record3.credentials && typeof record3.credentials === "object" ? record3.credentials : record3;
8422
- const accessToken = inner.accessToken ?? inner.access_token;
8423
- if (!accessToken || typeof accessToken !== "string") {
8424
- return { source: "unavailable", reason: "Squire returned a Google grant without an access token" };
8894
+ }
8895
+ function releaseSquireConnectSession(log2) {
8896
+ const claim = activeConnectSession;
8897
+ activeConnectSession = void 0;
8898
+ if (!claim)
8899
+ return;
8900
+ if (isProcessAlive(claim.pid)) {
8901
+ log2?.(`released trusty-squire connect session claim (pid ${String(claim.pid)} still live \u2014 a fresh connect owns the browser now)`);
8902
+ claim.abort();
8903
+ } else {
8904
+ log2?.("cleared dead trusty-squire connect session claim (owner process gone)");
8425
8905
  }
8426
- return {
8427
- source: "squire",
8428
- credentials: {
8429
- accessToken,
8430
- refreshToken: typeof record3.refreshToken === "string" ? record3.refreshToken : typeof record3.refresh_token === "string" ? record3.refresh_token : void 0,
8431
- expiresAt: typeof record3.expiresAt === "number" ? record3.expiresAt : void 0,
8432
- accountEmail: typeof record3.accountEmail === "string" ? record3.accountEmail : typeof record3.email === "string" ? record3.email : void 0
8433
- }
8434
- };
8435
8906
  }
8436
- function manualGoogleCredentialsSearchPaths(home) {
8437
- return [join2(home, "google-credentials.json")];
8907
+ function squireChromeProfileDir() {
8908
+ return process.env.TRUSTY_SQUIRE_PROFILE_DIR ?? join2(homedir2(), ".trusty-squire", "chrome-profile");
8438
8909
  }
8439
- function loadManualGoogleCredentials(home, env = process.env) {
8440
- if (env.BEELINE_GOOGLE_ACCESS_TOKEN) {
8441
- return {
8442
- source: "manual",
8443
- credentials: { accessToken: env.BEELINE_GOOGLE_ACCESS_TOKEN }
8444
- };
8445
- }
8446
- for (const path of manualGoogleCredentialsSearchPaths(home)) {
8910
+ function squireProfilePathIdentity(profileDir) {
8911
+ const absolute = resolve6(profileDir);
8912
+ const suffix = [];
8913
+ let candidate = absolute;
8914
+ for (; ; ) {
8447
8915
  try {
8448
- const parsed = JSON.parse(readFileSync3(path, "utf8"));
8449
- if (typeof parsed.accessToken === "string" || typeof parsed.access_token === "string") {
8450
- return {
8451
- source: "manual",
8452
- credentials: {
8453
- accessToken: parsed.accessToken ?? parsed.access_token,
8454
- refreshToken: typeof parsed.refreshToken === "string" ? parsed.refreshToken : void 0,
8455
- accountEmail: typeof parsed.accountEmail === "string" ? parsed.accountEmail : void 0
8456
- }
8457
- };
8458
- }
8916
+ return join2(realpathSync.native(candidate), ...suffix.reverse());
8459
8917
  } catch {
8918
+ const parent = dirname2(candidate);
8919
+ if (parent === candidate)
8920
+ return absolute;
8921
+ suffix.push(basename3(candidate));
8922
+ candidate = parent;
8460
8923
  }
8461
8924
  }
8462
- return {
8463
- source: "manual-missing",
8464
- reason: `no Google credentials found. Put a google-credentials.json (OAuth access token) at ${manualGoogleCredentialsSearchPaths(home)[0]} or connect your Google account in Trusty Squire first.`
8465
- };
8466
8925
  }
8467
- var step = (label, status, extra) => ({
8468
- label,
8469
- status,
8470
- ...extra
8471
- });
8472
- function outputTail(text2, maxChars = 800) {
8473
- const trimmed = text2.trim();
8474
- return trimmed.length <= maxChars ? trimmed : `\u2026${trimmed.slice(-maxChars)}`;
8926
+ function squireProfileLockPath(profileDir = squireChromeProfileDir(), lockRoot = tmpdir2()) {
8927
+ const digest = createHash2("sha256").update(squireProfilePathIdentity(profileDir)).digest("hex").slice(0, 24);
8928
+ return join2(lockRoot, `trusty-squire-profile-${digest}.lock`);
8475
8929
  }
8476
- async function installGoogleTool(options) {
8477
- const steps = [step("helper reached", "done")];
8478
- const emit = () => options.onProgress?.([...steps]);
8479
- const push = (next) => {
8480
- steps.push(next);
8481
- emit();
8482
- };
8483
- const fail = (label, reason, output) => {
8484
- push(step(label, "failed", { reason, ...output ? { output } : {} }));
8485
- return { status: "error", steps, errorMessage: reason };
8486
- };
8487
- emit();
8488
- if (!isGoogleToolConnectorType(options.connectorType)) {
8489
- return fail("connector type", `${options.connectorType} is not a Google tool connector`);
8490
- }
8491
- push(step("Google credentials resolved", "running", { output: "resolving\u2026" }));
8492
- const resolved = options.resolvedCredentials ? await options.resolvedCredentials : options.resolveCredentials ? await options.resolveCredentials() : await (async () => {
8493
- const oneClick = await readGoogleCredentialsFromVault(options.squire);
8494
- return oneClick.source === "squire" ? { ...oneClick } : { ...loadManualGoogleCredentials(options.home, options.env) };
8495
- })();
8496
- if (!("credentials" in resolved)) {
8497
- const reason = resolved.reason;
8498
- steps[1] = step("Google credentials resolved", "failed", { reason, output: outputTail(reason) });
8499
- emit();
8500
- return { status: "error", steps, errorMessage: reason };
8501
- }
8502
- steps[1] = step("Google credentials resolved", "done", {
8503
- output: resolved.source === "squire" ? "one-click: read the Google grant from Trusty Squire" : "manual: local google-credentials.json"
8504
- });
8505
- emit();
8506
- const client = options.client ?? googleWorkspaceClient(credentialsTokenSource(resolved.credentials));
8507
- push(step("authorized with Google", "running", { output: "verifying the grant with Google\u2026" }));
8508
- const verify = await client.verify();
8509
- if (!verify.ok) {
8510
- return fail("authorized with Google", verify.reason, outputTail(verify.reason));
8511
- }
8512
- steps[2] = step("authorized with Google", "done", {
8513
- ...verify.account ? { output: `signed in as ${verify.account}` } : {}
8514
- });
8515
- emit();
8516
- push(step("tools enabled", "done", {
8517
- output: `${GOOGLE_TOOL_SCOPES[options.connectorType].length} Google scopes granted`
8518
- }));
8519
- return {
8520
- status: "connected",
8521
- steps,
8522
- ...verify.account ? { signedInAs: verify.account } : {}
8523
- };
8930
+ var SQUIRE_BROWSER_BUSY_GOOGLE_REASON = "Trusty Squire is still using the browser \u2014 connect Trusty Squire first";
8931
+ function isSquireBrowserSessionFailure(text2) {
8932
+ if (typeof text2 !== "string" || text2.length === 0)
8933
+ return false;
8934
+ return /Trusty Squire[\s\S]{0,80}browser/i.test(text2) || /browser[\s\S]{0,80}Trusty Squire/i.test(text2);
8524
8935
  }
8525
- function describe(error) {
8526
- return error instanceof Error ? error.message : String(error);
8936
+ function squireForeignClaimAction(owner) {
8937
+ return `Trusty Squire's browser is in use by another process (pid ${owner.pid}). Finish or close that Trusty Squire session, then press Connect again.`;
8527
8938
  }
8528
-
8529
- // apps/body/dist/connector-squire.js
8530
- import { execFile, spawn as spawn2 } from "node:child_process";
8531
- var SQUIRE_MCP_NAME = "@trusty-squire/mcp";
8532
- var SQUIRE_CONNECT_PACKAGE = `${SQUIRE_MCP_NAME}@latest`;
8533
- var activeConnectSession;
8534
- function isProcessAlive(pid) {
8535
- if (pid === void 0 || pid <= 0)
8536
- return false;
8939
+ function readLinuxStartTime(pid) {
8537
8940
  try {
8538
- process.kill(pid, 0);
8941
+ const stat4 = readFileSync3(`/proc/${pid}/stat`, "utf8");
8942
+ const close = stat4.lastIndexOf(")");
8943
+ return close < 0 ? void 0 : stat4.slice(close + 2).split(" ")[19];
8944
+ } catch {
8945
+ return void 0;
8946
+ }
8947
+ }
8948
+ function lockOwnerIsAlive(owner) {
8949
+ if (!isProcessAlive(owner.pid))
8950
+ return false;
8951
+ if (owner.startTime === null || owner.startTime === "unknown")
8539
8952
  return true;
8540
- } catch (error) {
8541
- return error?.code === "EPERM";
8953
+ const actual = readLinuxStartTime(owner.pid);
8954
+ if (actual === void 0)
8955
+ return true;
8956
+ return actual === owner.startTime;
8957
+ }
8958
+ function readLockFileOwner(lockPath) {
8959
+ try {
8960
+ const target = lstatSync2(lockPath).isDirectory() ? join2(lockPath, "owner.json") : lockPath;
8961
+ const parsed = JSON.parse(readFileSync3(target, "utf8"));
8962
+ if (typeof parsed.host !== "string" || typeof parsed.pid !== "number")
8963
+ return void 0;
8964
+ return {
8965
+ host: parsed.host,
8966
+ pid: parsed.pid,
8967
+ startTime: typeof parsed.start_time === "string" ? parsed.start_time : null
8968
+ };
8969
+ } catch {
8970
+ return void 0;
8542
8971
  }
8543
8972
  }
8544
- function releaseSquireConnectSession(log2) {
8545
- const claim = activeConnectSession;
8546
- activeConnectSession = void 0;
8547
- if (!claim)
8548
- return;
8549
- if (isProcessAlive(claim.pid)) {
8550
- log2?.(`released trusty-squire connect session claim (pid ${String(claim.pid)} still live \u2014 a fresh connect owns the browser now)`);
8551
- claim.abort();
8552
- } else {
8553
- log2?.("cleared dead trusty-squire connect session claim (owner process gone)");
8973
+ function removeProfileLock(lockPath) {
8974
+ rmSync(lockPath, { recursive: true, force: true });
8975
+ }
8976
+ function reclaimSquireProfileClaim(options) {
8977
+ const profileDir = options?.profileDir ?? squireChromeProfileDir();
8978
+ const lockRoot = options?.lockRoot ?? tmpdir2();
8979
+ const lockPath = squireProfileLockPath(profileDir, lockRoot);
8980
+ const owner = readLockFileOwner(lockPath);
8981
+ if (!owner) {
8982
+ return { kind: "free" };
8983
+ }
8984
+ const ours = (options?.ourPids ?? []).includes(owner.pid);
8985
+ if (ours) {
8986
+ removeProfileLock(lockPath);
8987
+ options?.log?.(`released our trusty-squire on-disk browser claim (pid ${owner.pid})`);
8988
+ return { kind: "released-ours", owner };
8989
+ }
8990
+ if (owner.host !== hostname() || lockOwnerIsAlive(owner)) {
8991
+ const action = squireForeignClaimAction(owner);
8992
+ options?.log?.(`trusty-squire browser claim blocked by live pid ${owner.pid} \u2014 not superseding a foreign session`);
8993
+ return { kind: "blocked-foreign", owner, action };
8554
8994
  }
8995
+ removeProfileLock(lockPath);
8996
+ options?.log?.(`cleared dead trusty-squire on-disk browser claim (pid ${owner.pid} gone)`);
8997
+ return { kind: "reclaimed-dead", owner };
8555
8998
  }
8556
- var defaultShellRunner = (command, args) => new Promise((resolve31) => {
8999
+ var defaultShellRunner = (command, args) => new Promise((resolve32) => {
8557
9000
  execFile(command, [...args], { timeout: 12e4, maxBuffer: 4 * 1024 * 1024, encoding: "utf8" }, (error, stdout6, stderr) => {
8558
9001
  const code = error?.code;
8559
- resolve31({
9002
+ resolve32({
8560
9003
  code: typeof code === "number" ? code : error ? 1 : 0,
8561
9004
  stdout: String(stdout6 ?? ""),
8562
9005
  stderr: String(stderr ?? "")
8563
9006
  });
8564
9007
  });
8565
9008
  });
9009
+ function squireConnectProcessEnv(profileDir = squireChromeProfileDir()) {
9010
+ return {
9011
+ ...process.env,
9012
+ TRUSTY_SQUIRE_PROFILE_DIR: profileDir
9013
+ };
9014
+ }
8566
9015
  var CONNECT_TIMEOUT_MS = 3e5;
8567
- var defaultStreamedRunner = (command, args) => new Promise((resolve31) => {
8568
- const child = spawn2(command, args, {
8569
- stdio: ["ignore", "pipe", "pipe"]
9016
+ function killConnectTree(child) {
9017
+ const pid = child.pid;
9018
+ if (pid !== void 0) {
9019
+ try {
9020
+ process.kill(-pid, "SIGTERM");
9021
+ } catch {
9022
+ }
9023
+ }
9024
+ child.kill();
9025
+ }
9026
+ var defaultStreamedRunner = (command, args, env) => new Promise((resolve32) => {
9027
+ const child = spawn4(command, args, {
9028
+ stdio: ["ignore", "pipe", "pipe"],
9029
+ env: env ?? squireConnectProcessEnv(),
9030
+ detached: true
8570
9031
  });
8571
9032
  let stdout6 = "";
8572
9033
  let stderr = "";
@@ -8574,14 +9035,14 @@ var defaultStreamedRunner = (command, args) => new Promise((resolve31) => {
8574
9035
  const safetyTimer = setTimeout(() => {
8575
9036
  if (!resolved) {
8576
9037
  resolved = true;
8577
- resolve31({ stdout: stdout6, stderr, pid: child.pid ?? void 0, signIn: void 0, abort: () => {
9038
+ resolve32({ stdout: stdout6, stderr, pid: child.pid ?? void 0, signIn: void 0, abort: () => {
8578
9039
  } });
8579
9040
  }
8580
- child.kill();
9041
+ killConnectTree(child);
8581
9042
  }, CONNECT_TIMEOUT_MS);
8582
9043
  const abort = () => {
8583
9044
  clearTimeout(safetyTimer);
8584
- child.kill();
9045
+ killConnectTree(child);
8585
9046
  };
8586
9047
  const claim = {
8587
9048
  pid: child.pid ?? void 0,
@@ -8593,7 +9054,7 @@ var defaultStreamedRunner = (command, args) => new Promise((resolve31) => {
8593
9054
  if (!resolved) {
8594
9055
  resolved = true;
8595
9056
  clearTimeout(safetyTimer);
8596
- resolve31(result);
9057
+ resolve32(result);
8597
9058
  }
8598
9059
  };
8599
9060
  const checkOutput = () => {
@@ -8621,7 +9082,7 @@ ${stderr}`;
8621
9082
  } });
8622
9083
  });
8623
9084
  });
8624
- var step2 = (label, status, reason) => ({
9085
+ var step = (label, status, reason) => ({
8625
9086
  label,
8626
9087
  status,
8627
9088
  ...reason ? { reason } : {}
@@ -8685,142 +9146,311 @@ function parseSignedInAs(output) {
8685
9146
  return output.match(/signed in as ([^\s,;]+)/i)?.[1];
8686
9147
  }
8687
9148
  async function installSquire(options) {
9149
+ const profileDir = options.profileDir ?? squireChromeProfileDir();
9150
+ const lockRoot = options.lockRoot ?? tmpdir2();
8688
9151
  const run2 = options.run ?? defaultShellRunner;
8689
9152
  const streamRun = options.streamRun ?? defaultStreamedRunner;
8690
9153
  const log2 = options.log ?? (() => {
8691
9154
  });
9155
+ const steps = [step("helper reached", "done")];
9156
+ const emit = () => options.onProgress?.([...steps]);
9157
+ const push = (next) => {
9158
+ steps.push(next);
9159
+ emit();
9160
+ };
9161
+ const fail = (reason) => {
9162
+ steps.push(step("waiting for sign-in", "pending"));
9163
+ emit();
9164
+ return { status: "error", steps, errorMessage: reason };
9165
+ };
9166
+ emit();
9167
+ const previousPid = squireConnectSession()?.pid;
9168
+ releaseSquireConnectSession(log2);
9169
+ const claim = reclaimSquireProfileClaim({
9170
+ log: log2,
9171
+ profileDir,
9172
+ lockRoot,
9173
+ ...previousPid !== void 0 ? { ourPids: [previousPid] } : {}
9174
+ });
9175
+ if (claim.kind === "blocked-foreign") {
9176
+ push(step("trusty-squire installed", "failed", claim.action));
9177
+ return fail(claim.action);
9178
+ }
9179
+ const resolution = await resolveSquireConnectSpec(run2);
9180
+ if (resolution.reResolved) {
9181
+ log2(`trusty-squire stale copy ${resolution.resolvedVersion ?? "unknown"} re-resolved against current release ${resolution.currentRelease}`);
9182
+ }
9183
+ const install = await streamRun("npx", [
9184
+ ...resolution.npxArgs,
9185
+ "connect",
9186
+ "--force-relogin=google",
9187
+ "--target=codex",
9188
+ "--skip-browser"
9189
+ ], squireConnectProcessEnv(profileDir));
9190
+ if (!install.signIn) {
9191
+ const stderr = install.stderr.trim();
9192
+ let stepReason = stderr || "connect printed no sign-in URL";
9193
+ let failReason = stderr || "the trusty-squire connect command printed no sign-in surface";
9194
+ if (isSquireBrowserSessionFailure(stderr)) {
9195
+ const again = reclaimSquireProfileClaim({ log: log2, profileDir, lockRoot });
9196
+ if (again.kind === "blocked-foreign") {
9197
+ stepReason = again.action;
9198
+ failReason = again.action;
9199
+ }
9200
+ }
9201
+ push(step("trusty-squire installed", "failed", stepReason));
9202
+ return fail(failReason);
9203
+ }
9204
+ const version = resolution.resolvedVersion;
9205
+ push(step(`trusty-squire${version ? ` ${version}` : ""} installed`, "done"));
9206
+ const signIn = install.signIn;
9207
+ const signedInAs = parseSignedInAs(`${install.stdout}
9208
+ ${install.stderr}`);
9209
+ push(step("waiting for sign-in", "done"));
9210
+ const pair = await pairSquire(options.mcp, options.workspaceId);
9211
+ if (!pair.ok) {
9212
+ push(step("paired to workspace", "failed", pair.reason));
9213
+ return {
9214
+ status: "installing",
9215
+ steps,
9216
+ signIn,
9217
+ ...version ? { squireVersion: version } : {},
9218
+ ...signedInAs ? { signedInAs } : {}
9219
+ };
9220
+ }
9221
+ push(step("paired to workspace", "done"));
9222
+ return {
9223
+ status: "connected",
9224
+ steps,
9225
+ signIn,
9226
+ ...version ? { squireVersion: version } : {},
9227
+ ...signedInAs ? { signedInAs } : {}
9228
+ };
9229
+ }
9230
+ async function pairSquire(mcp, _workspaceId) {
9231
+ if (!mcp)
9232
+ return { ok: false, reason: "the Squire MCP surface is not mounted on this helper" };
9233
+ try {
9234
+ await mcp.call("list_credentials", { fields: "summary" });
9235
+ return { ok: true };
9236
+ } catch (error) {
9237
+ return { ok: false, reason: error instanceof Error ? error.message : String(error) };
9238
+ }
9239
+ }
9240
+ function asRecord2(value) {
9241
+ return value && typeof value === "object" ? value : {};
9242
+ }
9243
+ function asArray(value) {
9244
+ return Array.isArray(value) ? value : [];
9245
+ }
9246
+ function stringList(value) {
9247
+ return asArray(value).filter((entry) => typeof entry === "string");
9248
+ }
9249
+ function numberOrNull(value) {
9250
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
9251
+ }
9252
+ function vaultConnectionMeta(raw) {
9253
+ const record3 = asRecord2(raw);
9254
+ const reference = String(record3.reference ?? record3.id ?? "");
9255
+ return {
9256
+ reference,
9257
+ service: typeof record3.service === "string" ? record3.service : null,
9258
+ label: String(record3.label ?? record3.service ?? reference),
9259
+ fieldNames: stringList(record3.field_names ?? record3.fieldNames),
9260
+ allowedHosts: stringList(record3.allowed_hosts ?? record3.allowedHosts ?? record3.login_hosts),
9261
+ createdAt: numberOrNull(record3.created_at ?? record3.createdAt) ?? 0,
9262
+ stale: record3.stale === true,
9263
+ state: record3.state === "error" ? "error" : "active"
9264
+ };
9265
+ }
9266
+ async function readVault(mcp) {
9267
+ const result = asRecord2(await mcp.call("list_credentials"));
9268
+ return asArray(result.credentials ?? result.items ?? result).map(vaultConnectionMeta);
9269
+ }
9270
+ function connectionGrant(raw) {
9271
+ const record3 = asRecord2(raw);
9272
+ return {
9273
+ grantId: String(record3.grant_id ?? record3.grantId ?? record3.id ?? ""),
9274
+ credentialRef: String(record3.credential_ref ?? record3.credentialRef ?? record3.reference ?? ""),
9275
+ createdAt: numberOrNull(record3.created_at ?? record3.createdAt) ?? 0,
9276
+ ...numberOrNull(record3.revoked_at ?? record3.revokedAt) !== null ? { revokedAt: numberOrNull(record3.revoked_at ?? record3.revokedAt) } : {},
9277
+ ...numberOrNull(record3.rate_limit_per_hour) !== null ? { rateLimitPerHour: numberOrNull(record3.rate_limit_per_hour) } : {},
9278
+ ...numberOrNull(record3.spend_cap_usd) !== null ? { spendCapUsd: numberOrNull(record3.spend_cap_usd) } : {}
9279
+ };
9280
+ }
9281
+ async function readGrants(mcp, ref) {
9282
+ const result = asRecord2(await mcp.call("list_app_access", {}));
9283
+ return asArray(result.grants ?? result.items ?? result).map(connectionGrant).filter((grant) => grant.credentialRef === ref && grant.revokedAt === void 0);
9284
+ }
9285
+ async function revokeGrants(mcp, ref) {
9286
+ const grants = await readGrants(mcp, ref);
9287
+ let revoked = 0;
9288
+ let failed = 0;
9289
+ for (const grant of grants) {
9290
+ try {
9291
+ const result = asRecord2(await mcp.call("revoke_app_access", { grant_id: grant.grantId }));
9292
+ if (result.revoked === false)
9293
+ failed += 1;
9294
+ else
9295
+ revoked += 1;
9296
+ } catch {
9297
+ failed += 1;
9298
+ }
9299
+ }
9300
+ return { revoked, failed };
9301
+ }
9302
+
9303
+ // apps/body/dist/connector-google.js
9304
+ var GOOGLE_TOOL_SCOPES = {
9305
+ "google-gmail": [
9306
+ "https://www.googleapis.com/auth/gmail.send",
9307
+ "https://www.googleapis.com/auth/gmail.readonly",
9308
+ "https://www.googleapis.com/auth/gmail.compose"
9309
+ ],
9310
+ "google-calendar": ["https://www.googleapis.com/auth/calendar.events", "https://www.googleapis.com/auth/calendar.readonly"],
9311
+ "google-drive": ["https://www.googleapis.com/auth/drive.readonly"],
9312
+ "google-youtube": ["https://www.googleapis.com/auth/youtube.readonly"]
9313
+ };
9314
+ function isGoogleToolConnectorType(type) {
9315
+ return type in GOOGLE_TOOL_SCOPES;
9316
+ }
9317
+ async function readGoogleCredentialsFromVault(mcp) {
9318
+ if (!mcp)
9319
+ return { source: "unavailable", reason: "no Trusty Squire connector is paired" };
9320
+ let raw;
9321
+ try {
9322
+ raw = await mcp.call("google_oauth_credentials", {});
9323
+ } catch (error) {
9324
+ const detail = describe(error);
9325
+ if (isSquireBrowserSessionFailure(detail)) {
9326
+ return {
9327
+ source: "unavailable",
9328
+ reason: SQUIRE_BROWSER_BUSY_GOOGLE_REASON
9329
+ };
9330
+ }
9331
+ return {
9332
+ source: "unavailable",
9333
+ reason: `Squire has no Google OAuth grant on record yet (connect your Google account in Squire first: ${detail})`
9334
+ };
9335
+ }
9336
+ const record3 = raw && typeof raw === "object" ? raw : {};
9337
+ const inner = record3.credentials && typeof record3.credentials === "object" ? record3.credentials : record3;
9338
+ const accessToken = inner.accessToken ?? inner.access_token;
9339
+ if (!accessToken || typeof accessToken !== "string") {
9340
+ return { source: "unavailable", reason: "Squire returned a Google grant without an access token" };
9341
+ }
9342
+ return {
9343
+ source: "squire",
9344
+ credentials: {
9345
+ accessToken,
9346
+ refreshToken: typeof record3.refreshToken === "string" ? record3.refreshToken : typeof record3.refresh_token === "string" ? record3.refresh_token : void 0,
9347
+ expiresAt: typeof record3.expiresAt === "number" ? record3.expiresAt : void 0,
9348
+ accountEmail: typeof record3.accountEmail === "string" ? record3.accountEmail : typeof record3.email === "string" ? record3.email : void 0
9349
+ }
9350
+ };
9351
+ }
9352
+ function manualGoogleCredentialsSearchPaths(home) {
9353
+ return [join3(home, "google-credentials.json")];
9354
+ }
9355
+ function loadManualGoogleCredentials(home, env = process.env) {
9356
+ if (env.BEELINE_GOOGLE_ACCESS_TOKEN) {
9357
+ return {
9358
+ source: "manual",
9359
+ credentials: { accessToken: env.BEELINE_GOOGLE_ACCESS_TOKEN }
9360
+ };
9361
+ }
9362
+ for (const path of manualGoogleCredentialsSearchPaths(home)) {
9363
+ try {
9364
+ const parsed = JSON.parse(readFileSync4(path, "utf8"));
9365
+ if (typeof parsed.accessToken === "string" || typeof parsed.access_token === "string") {
9366
+ return {
9367
+ source: "manual",
9368
+ credentials: {
9369
+ accessToken: parsed.accessToken ?? parsed.access_token,
9370
+ refreshToken: typeof parsed.refreshToken === "string" ? parsed.refreshToken : void 0,
9371
+ accountEmail: typeof parsed.accountEmail === "string" ? parsed.accountEmail : void 0
9372
+ }
9373
+ };
9374
+ }
9375
+ } catch {
9376
+ }
9377
+ }
9378
+ return {
9379
+ source: "manual-missing",
9380
+ reason: `no Google credentials found. Put a google-credentials.json (OAuth access token) at ${manualGoogleCredentialsSearchPaths(home)[0]} or connect your Google account in Trusty Squire first.`
9381
+ };
9382
+ }
9383
+ var step2 = (label, status, extra) => ({
9384
+ label,
9385
+ status,
9386
+ ...extra
9387
+ });
9388
+ function outputTail(text2, maxChars = 800) {
9389
+ const trimmed = text2.trim();
9390
+ return trimmed.length <= maxChars ? trimmed : `\u2026${trimmed.slice(-maxChars)}`;
9391
+ }
9392
+ async function installGoogleTool(options) {
8692
9393
  const steps = [step2("helper reached", "done")];
8693
9394
  const emit = () => options.onProgress?.([...steps]);
8694
9395
  const push = (next) => {
8695
9396
  steps.push(next);
8696
9397
  emit();
8697
9398
  };
8698
- const fail = (reason) => {
8699
- steps.push(step2("waiting for sign-in", "pending"));
8700
- emit();
9399
+ const fail = (label, reason, output) => {
9400
+ push(step2(label, "failed", { reason, ...output ? { output } : {} }));
8701
9401
  return { status: "error", steps, errorMessage: reason };
8702
9402
  };
8703
9403
  emit();
8704
- releaseSquireConnectSession(log2);
8705
- const resolution = await resolveSquireConnectSpec(run2);
8706
- if (resolution.reResolved) {
8707
- log2(`trusty-squire stale copy ${resolution.resolvedVersion ?? "unknown"} re-resolved against current release ${resolution.currentRelease}`);
9404
+ if (!isGoogleToolConnectorType(options.connectorType)) {
9405
+ return fail("connector type", `${options.connectorType} is not a Google tool connector`);
8708
9406
  }
8709
- const install = await streamRun("npx", [
8710
- ...resolution.npxArgs,
8711
- "connect",
8712
- "--force-relogin=google",
8713
- "--target=codex",
8714
- "--skip-browser"
8715
- ]);
8716
- if (!install.signIn) {
8717
- const stderr = install.stderr.trim();
8718
- push(step2("trusty-squire installed", "failed", stderr || "connect printed no sign-in URL"));
8719
- return fail(stderr || "the trusty-squire connect command printed no sign-in surface");
9407
+ push(step2("Google credentials resolved", "running", { output: "resolving\u2026" }));
9408
+ const resolved = options.resolvedCredentials ? await options.resolvedCredentials : options.resolveCredentials ? await options.resolveCredentials() : await (async () => {
9409
+ const oneClick = await readGoogleCredentialsFromVault(options.squire);
9410
+ if (oneClick.source === "squire")
9411
+ return oneClick;
9412
+ if (isSquireBrowserSessionFailure(oneClick.reason))
9413
+ return oneClick;
9414
+ return loadManualGoogleCredentials(options.home, options.env);
9415
+ })();
9416
+ if (!("credentials" in resolved)) {
9417
+ const reason = resolved.reason;
9418
+ steps[1] = step2("Google credentials resolved", "failed", { reason, output: outputTail(reason) });
9419
+ emit();
9420
+ return { status: "error", steps, errorMessage: reason };
8720
9421
  }
8721
- const version = resolution.resolvedVersion;
8722
- push(step2(`trusty-squire${version ? ` ${version}` : ""} installed`, "done"));
8723
- const signIn = install.signIn;
8724
- const signedInAs = parseSignedInAs(`${install.stdout}
8725
- ${install.stderr}`);
8726
- push(step2("waiting for sign-in", "done"));
8727
- const pair = await pairSquire(options.mcp, options.workspaceId);
8728
- if (!pair.ok) {
8729
- push(step2("paired to workspace", "failed", pair.reason));
8730
- return {
8731
- status: "installing",
8732
- steps,
8733
- signIn,
8734
- ...version ? { squireVersion: version } : {},
8735
- ...signedInAs ? { signedInAs } : {}
8736
- };
9422
+ steps[1] = step2("Google credentials resolved", "done", {
9423
+ output: resolved.source === "squire" ? "one-click: read the Google grant from Trusty Squire" : "manual: local google-credentials.json"
9424
+ });
9425
+ emit();
9426
+ const client = options.client ?? googleWorkspaceClient(credentialsTokenSource(resolved.credentials));
9427
+ push(step2("authorized with Google", "running", { output: "verifying the grant with Google\u2026" }));
9428
+ const verify = await client.verify();
9429
+ if (!verify.ok) {
9430
+ return fail("authorized with Google", verify.reason, outputTail(verify.reason));
8737
9431
  }
8738
- push(step2("paired to workspace", "done"));
9432
+ steps[2] = step2("authorized with Google", "done", {
9433
+ ...verify.account ? { output: `signed in as ${verify.account}` } : {}
9434
+ });
9435
+ emit();
9436
+ push(step2("tools enabled", "done", {
9437
+ output: `${GOOGLE_TOOL_SCOPES[options.connectorType].length} Google scopes granted`
9438
+ }));
8739
9439
  return {
8740
9440
  status: "connected",
8741
9441
  steps,
8742
- signIn,
8743
- ...version ? { squireVersion: version } : {},
8744
- ...signedInAs ? { signedInAs } : {}
8745
- };
8746
- }
8747
- async function pairSquire(mcp, _workspaceId) {
8748
- if (!mcp)
8749
- return { ok: false, reason: "the Squire MCP surface is not mounted on this helper" };
8750
- try {
8751
- await mcp.call("list_credentials", { fields: "summary" });
8752
- return { ok: true };
8753
- } catch (error) {
8754
- return { ok: false, reason: error instanceof Error ? error.message : String(error) };
8755
- }
8756
- }
8757
- function asRecord(value) {
8758
- return value && typeof value === "object" ? value : {};
8759
- }
8760
- function asArray(value) {
8761
- return Array.isArray(value) ? value : [];
8762
- }
8763
- function stringList(value) {
8764
- return asArray(value).filter((entry) => typeof entry === "string");
8765
- }
8766
- function numberOrNull(value) {
8767
- return typeof value === "number" && Number.isFinite(value) ? value : null;
8768
- }
8769
- function vaultConnectionMeta(raw) {
8770
- const record3 = asRecord(raw);
8771
- const reference = String(record3.reference ?? record3.id ?? "");
8772
- return {
8773
- reference,
8774
- service: typeof record3.service === "string" ? record3.service : null,
8775
- label: String(record3.label ?? record3.service ?? reference),
8776
- fieldNames: stringList(record3.field_names ?? record3.fieldNames),
8777
- allowedHosts: stringList(record3.allowed_hosts ?? record3.allowedHosts ?? record3.login_hosts),
8778
- createdAt: numberOrNull(record3.created_at ?? record3.createdAt) ?? 0,
8779
- stale: record3.stale === true,
8780
- state: record3.state === "error" ? "error" : "active"
8781
- };
8782
- }
8783
- async function readVault(mcp) {
8784
- const result = asRecord(await mcp.call("list_credentials"));
8785
- return asArray(result.credentials ?? result.items ?? result).map(vaultConnectionMeta);
8786
- }
8787
- function connectionGrant(raw) {
8788
- const record3 = asRecord(raw);
8789
- return {
8790
- grantId: String(record3.grant_id ?? record3.grantId ?? record3.id ?? ""),
8791
- credentialRef: String(record3.credential_ref ?? record3.credentialRef ?? record3.reference ?? ""),
8792
- createdAt: numberOrNull(record3.created_at ?? record3.createdAt) ?? 0,
8793
- ...numberOrNull(record3.revoked_at ?? record3.revokedAt) !== null ? { revokedAt: numberOrNull(record3.revoked_at ?? record3.revokedAt) } : {},
8794
- ...numberOrNull(record3.rate_limit_per_hour) !== null ? { rateLimitPerHour: numberOrNull(record3.rate_limit_per_hour) } : {},
8795
- ...numberOrNull(record3.spend_cap_usd) !== null ? { spendCapUsd: numberOrNull(record3.spend_cap_usd) } : {}
9442
+ ...verify.account ? { signedInAs: verify.account } : {}
8796
9443
  };
8797
9444
  }
8798
- async function readGrants(mcp, ref) {
8799
- const result = asRecord(await mcp.call("list_app_access", {}));
8800
- return asArray(result.grants ?? result.items ?? result).map(connectionGrant).filter((grant) => grant.credentialRef === ref && grant.revokedAt === void 0);
8801
- }
8802
- async function revokeGrants(mcp, ref) {
8803
- const grants = await readGrants(mcp, ref);
8804
- let revoked = 0;
8805
- let failed = 0;
8806
- for (const grant of grants) {
8807
- try {
8808
- const result = asRecord(await mcp.call("revoke_app_access", { grant_id: grant.grantId }));
8809
- if (result.revoked === false)
8810
- failed += 1;
8811
- else
8812
- revoked += 1;
8813
- } catch {
8814
- failed += 1;
8815
- }
8816
- }
8817
- return { revoked, failed };
9445
+ function describe(error) {
9446
+ return error instanceof Error ? error.message : String(error);
8818
9447
  }
8819
9448
 
8820
9449
  // apps/body/dist/squire-mcp-client.js
8821
- import { spawn as spawn3 } from "node:child_process";
9450
+ import { spawn as spawn5 } from "node:child_process";
8822
9451
  var INITIALIZE_TIMEOUT_MS = 3e4;
8823
9452
  var CALL_TIMEOUT_MS = 12e4;
9453
+ var SQUIRE_MCP_SERVER_ARGS = ["-y", "@trusty-squire/mcp@latest", "server"];
8824
9454
  var StdioSquireMcpClient = class {
8825
9455
  options;
8826
9456
  child;
@@ -8874,12 +9504,7 @@ var StdioSquireMcpClient = class {
8874
9504
  return this.initialized;
8875
9505
  }
8876
9506
  initialize() {
8877
- const child = (this.options.spawn ?? spawn3)(this.options.command ?? "npx", [
8878
- // `@latest`: the current release, never a source-level version pin
8879
- // (captain). Only the vault MCP server the agent spawns; the connect
8880
- // install path verifies freshness itself (connector-squire.ts).
8881
- ...this.options.args ?? ["-y", "@trusty-squire/mcp@latest"]
8882
- ]);
9507
+ const child = (this.options.spawn ?? spawn5)(this.options.command ?? "npx", [...this.options.args ?? [...SQUIRE_MCP_SERVER_ARGS]], { env: this.options.env ?? squireConnectProcessEnv() });
8883
9508
  this.child = child;
8884
9509
  this.buffer = "";
8885
9510
  child.stdout.setEncoding("utf8");
@@ -8913,12 +9538,12 @@ var StdioSquireMcpClient = class {
8913
9538
  const child = this.child;
8914
9539
  if (!child)
8915
9540
  return Promise.reject(new Error("Squire MCP session is not running"));
8916
- return new Promise((resolve31, reject) => {
9541
+ return new Promise((resolve32, reject) => {
8917
9542
  const timer = setTimeout(() => {
8918
9543
  this.pending.delete(id);
8919
9544
  reject(new Error(`${method} timed out`));
8920
9545
  }, method === "initialize" ? INITIALIZE_TIMEOUT_MS : CALL_TIMEOUT_MS);
8921
- this.pending.set(id, { resolve: resolve31, reject, timer });
9546
+ this.pending.set(id, { resolve: resolve32, reject, timer });
8922
9547
  child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, params })}
8923
9548
  `);
8924
9549
  });
@@ -9034,6 +9659,7 @@ var ConnectorAssignmentLoop = class {
9034
9659
  this.log(`connector assignments unavailable: ${describe2(error)}`);
9035
9660
  return;
9036
9661
  }
9662
+ const squireWork = [];
9037
9663
  let googleBatch;
9038
9664
  for (const assignment of assignments) {
9039
9665
  const key = `${assignment.kind}:${assignment.connectorId}`;
@@ -9049,17 +9675,15 @@ var ConnectorAssignmentLoop = class {
9049
9675
  if (this.inFlight.has(key))
9050
9676
  continue;
9051
9677
  this.inFlight.add(key);
9052
- void this.handle(assignment).catch((error) => this.log(`connector assignment ${key} failed: ${describe2(error)}`)).finally(() => this.inFlight.delete(key));
9678
+ squireWork.push(this.handle(assignment).catch((error) => this.log(`connector assignment ${key} failed: ${describe2(error)}`)).finally(() => this.inFlight.delete(key)));
9679
+ }
9680
+ if (googleBatch) {
9681
+ const keys = googleBatch.map((assignment) => `${assignment.kind}:${assignment.connectorId}`);
9682
+ void Promise.all(squireWork).then(() => this.runGoogleBatch(googleBatch)).catch((error) => this.log(`google connector installs failed: ${describe2(error)}`)).finally(() => {
9683
+ for (const key of keys)
9684
+ this.inFlight.delete(key);
9685
+ });
9053
9686
  }
9054
- if (googleBatch)
9055
- this.flushGoogleBatch(googleBatch);
9056
- }
9057
- flushGoogleBatch(batch) {
9058
- const keys = batch.map((a2) => `${a2.kind}:${a2.connectorId}`);
9059
- void this.runGoogleBatch(batch).catch((error) => this.log(`google connector installs failed: ${describe2(error)}`)).finally(() => {
9060
- for (const key of keys)
9061
- this.inFlight.delete(key);
9062
- });
9063
9687
  }
9064
9688
  /** The Google tool connectors ride ONE grant: every install in the batch
9065
9689
  * shares one credential resolution (the single Google consent) and the
@@ -9083,6 +9707,8 @@ var ConnectorAssignmentLoop = class {
9083
9707
  const oneClick = await readGoogleCredentialsFromVault(this.squire());
9084
9708
  if (oneClick.source === "squire")
9085
9709
  return oneClick;
9710
+ if (isSquireBrowserSessionFailure(oneClick.reason))
9711
+ return oneClick;
9086
9712
  } catch (error) {
9087
9713
  this.log(`google one-click grant lookup failed: ${describe2(error)}`);
9088
9714
  }
@@ -9227,12 +9853,13 @@ var SERVER_EVENT_KINDS = [
9227
9853
  "check-failed",
9228
9854
  "merged",
9229
9855
  "grant-decided",
9856
+ "connector-offer-decided",
9230
9857
  "turn-cancelled"
9231
9858
  ];
9232
9859
 
9233
9860
  // apps/body/dist/daemon-api-client.js
9234
- import { resolve as resolve7 } from "node:path";
9235
- import { randomUUID } from "node:crypto";
9861
+ import { resolve as resolve8 } from "node:path";
9862
+ import { randomUUID as randomUUID2 } from "node:crypto";
9236
9863
 
9237
9864
  // node_modules/ws/wrapper.mjs
9238
9865
  var import_stream = __toESM(require_stream(), 1);
@@ -9250,9 +9877,9 @@ import { randomBytes as randomBytes5 } from "node:crypto";
9250
9877
  import { execFile as execFile2 } from "node:child_process";
9251
9878
  import { closeSync, openSync } from "node:fs";
9252
9879
  import { mkdir, readFile as readFile2, readdir, rename, stat, writeFile as writeFile2 } from "node:fs/promises";
9253
- import { homedir as homedir2 } from "node:os";
9254
- import { dirname as dirname2, resolve as resolve6 } from "node:path";
9255
- import { spawn as spawn4 } from "node:child_process";
9880
+ import { homedir as homedir3 } from "node:os";
9881
+ import { dirname as dirname3, resolve as resolve7 } from "node:path";
9882
+ import { spawn as spawn6 } from "node:child_process";
9256
9883
  import { promisify } from "node:util";
9257
9884
 
9258
9885
  // node_modules/@noble/hashes/_u64.js
@@ -13639,7 +14266,7 @@ function alphabet(letters) {
13639
14266
  };
13640
14267
  }
13641
14268
  // @__NO_SIDE_EFFECTS__
13642
- function join3(separator = "") {
14269
+ function join4(separator = "") {
13643
14270
  astr("join", separator);
13644
14271
  return {
13645
14272
  encode: (from) => {
@@ -13769,8 +14396,8 @@ var base64 = hasBase64Builtin ? {
13769
14396
  decode(s) {
13770
14397
  return decodeBase64Builtin(s, false);
13771
14398
  }
13772
- } : /* @__PURE__ */ chain(/* @__PURE__ */ radix2(6), /* @__PURE__ */ alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), /* @__PURE__ */ padding(6), /* @__PURE__ */ join3(""));
13773
- var BECH_ALPHABET = /* @__PURE__ */ chain(/* @__PURE__ */ alphabet("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), /* @__PURE__ */ join3(""));
14399
+ } : /* @__PURE__ */ chain(/* @__PURE__ */ radix2(6), /* @__PURE__ */ alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), /* @__PURE__ */ padding(6), /* @__PURE__ */ join4(""));
14400
+ var BECH_ALPHABET = /* @__PURE__ */ chain(/* @__PURE__ */ alphabet("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), /* @__PURE__ */ join4(""));
13774
14401
  var POLYMOD_GENERATORS = [996825010, 642813549, 513874426, 1027748829, 705979059];
13775
14402
  function bech32Polymod(pre) {
13776
14403
  const b = pre >> 25;
@@ -17788,15 +18415,15 @@ var DEFAULT_AGENT_IDENTITY_NAME = "beeline-agent";
17788
18415
  var DEFAULT_BODY_IDENTITY_NAME = "beeline-body";
17789
18416
  var DEFAULT_DAEMON_MONOLITH_BASE_URL = "https://server.usebeeline.app";
17790
18417
  function defaultSupervisorRoot(env = process.env) {
17791
- return resolve6(env.XDG_STATE_HOME ?? resolve6(homedir2(), ".local", "state"));
18418
+ return resolve7(env.XDG_STATE_HOME ?? resolve7(homedir3(), ".local", "state"));
17792
18419
  }
17793
18420
  function runtimeDirectory(supervisorRoot, publicKey) {
17794
18421
  if (!/^[0-9a-f]{64}$/i.test(publicKey))
17795
18422
  throw new Error("invalid agent public key");
17796
- return resolve6(supervisorRoot, "beeline", "agents", publicKey.toLowerCase());
18423
+ return resolve7(supervisorRoot, "beeline", "agents", publicKey.toLowerCase());
17797
18424
  }
17798
18425
  function runtimeConfigPath(supervisorRoot, publicKey) {
17799
- return resolve6(runtimeDirectory(supervisorRoot, publicKey), "runtime.json");
18426
+ return resolve7(runtimeDirectory(supervisorRoot, publicKey), "runtime.json");
17800
18427
  }
17801
18428
  function identityFromKey(value, name) {
17802
18429
  const secretKey = value ? value.startsWith("nsec1") ? decodeNsec(value) : Uint8Array.from(Buffer.from(value, "hex")) : randomBytes5(32);
@@ -17817,7 +18444,13 @@ function runtimeIdentity(identity) {
17817
18444
  throw new Error("stored identity public key mismatch");
17818
18445
  return restored;
17819
18446
  }
17820
- function runtimeAgentCommand(runtime) {
18447
+ function runtimeAgentCommand(runtime, env = process.env) {
18448
+ if (runtime.agentKind === "cursor") {
18449
+ try {
18450
+ return resolveAgentCommand({ kind: "cursor", env });
18451
+ } catch {
18452
+ }
18453
+ }
17821
18454
  return {
17822
18455
  kind: runtime.agentKind ?? "reference",
17823
18456
  command: runtime.agentCommand ?? runtime.agentBinary,
@@ -17826,7 +18459,7 @@ function runtimeAgentCommand(runtime) {
17826
18459
  }
17827
18460
  async function writeRuntimeRecord(runtime) {
17828
18461
  const path = runtimeConfigPath(runtime.supervisorRoot, runtime.agent.publicKey);
17829
- await mkdir(dirname2(path), { recursive: true, mode: 448 });
18462
+ await mkdir(dirname3(path), { recursive: true, mode: 448 });
17830
18463
  const staged = `${path}.${process.pid}.tmp`;
17831
18464
  await writeFile2(staged, `${JSON.stringify(runtime, null, 2)}
17832
18465
  `, { mode: 384 });
@@ -17852,7 +18485,7 @@ async function migrateRuntimeRecordAccessPolicy(path) {
17852
18485
  return { runtime, migrated: true };
17853
18486
  }
17854
18487
  async function stageMonolithAgentRuntime(input) {
17855
- const supervisorRoot = input.supervisorRoot ? resolve6(input.supervisorRoot) : defaultSupervisorRoot();
18488
+ const supervisorRoot = input.supervisorRoot ? resolve7(input.supervisorRoot) : defaultSupervisorRoot();
17856
18489
  const configPath = runtimeConfigPath(supervisorRoot, input.agentIdentity.publicKey);
17857
18490
  const configuredBaseUrl = input.monolithBaseUrl ?? DEFAULT_DAEMON_MONOLITH_BASE_URL;
17858
18491
  const baseUrl = new URL(configuredBaseUrl).origin;
@@ -17897,9 +18530,9 @@ async function stageMonolithAgentRuntime(input) {
17897
18530
  return { runtime, configPath };
17898
18531
  }
17899
18532
  async function runtimePaths(root) {
17900
- const agents = resolve6(root, "beeline", "agents");
18533
+ const agents = resolve7(root, "beeline", "agents");
17901
18534
  const entries = await readdir(agents, { withFileTypes: true }).catch(() => []);
17902
- return entries.filter((entry) => entry.isDirectory()).map((entry) => resolve6(agents, entry.name, "runtime.json"));
18535
+ return entries.filter((entry) => entry.isDirectory()).map((entry) => resolve7(agents, entry.name, "runtime.json"));
17903
18536
  }
17904
18537
  async function findAgentRuntimeConfigPaths(env = process.env, _cwd = process.cwd()) {
17905
18538
  return runtimePaths(defaultSupervisorRoot(env));
@@ -17908,13 +18541,13 @@ async function findRuntimeConfigPaths(cwd = process.cwd(), env = process.env) {
17908
18541
  return findAgentRuntimeConfigPaths(env, cwd);
17909
18542
  }
17910
18543
  async function resolveRuntimeConfigPath(path) {
17911
- return resolve6(path);
18544
+ return resolve7(path);
17912
18545
  }
17913
18546
  async function selectRuntimeConfigPaths(options) {
17914
18547
  const hostScope = true;
17915
18548
  const configs = await options.findHostRuntimes(options.cwd);
17916
18549
  const requestedPubkey = options.requestedPubkey;
17917
- const paths = requestedPubkey ? configs.filter((path) => dirname2(path).endsWith(requestedPubkey)) : [...new Set(configs)];
18550
+ const paths = requestedPubkey ? configs.filter((path) => dirname3(path).endsWith(requestedPubkey)) : [...new Set(configs)];
17918
18551
  if (!paths.length)
17919
18552
  throw new Error(options.noRuntimeMessage(hostScope));
17920
18553
  if (options.requestedPubkey && paths.length > 1)
@@ -17923,7 +18556,7 @@ async function selectRuntimeConfigPaths(options) {
17923
18556
  }
17924
18557
  async function runtimeDaemonPid(configPath) {
17925
18558
  try {
17926
- const pid = Number((await readFile2(resolve6(dirname2(configPath), "daemon.pid"), "utf8")).trim());
18559
+ const pid = Number((await readFile2(resolve7(dirname3(configPath), "daemon.pid"), "utf8")).trim());
17927
18560
  if (!Number.isSafeInteger(pid) || pid <= 0)
17928
18561
  return null;
17929
18562
  process.kill(pid, 0);
@@ -17936,11 +18569,11 @@ async function daemonIsThisRuntime(pid, configPath) {
17936
18569
  try {
17937
18570
  const argv = (await readFile2(`/proc/${pid}/cmdline`, "utf8")).split("\0").filter(Boolean);
17938
18571
  const flag = argv.lastIndexOf("--config");
17939
- return flag > 0 && argv[flag - 1] === "daemon" && resolve6(argv[flag + 1]) === resolve6(configPath);
18572
+ return flag > 0 && argv[flag - 1] === "daemon" && resolve7(argv[flag + 1]) === resolve7(configPath);
17940
18573
  } catch {
17941
18574
  try {
17942
18575
  const { stdout: stdout6 } = await execFileAsync("ps", ["-p", String(pid), "-o", "command="]);
17943
- return stdout6.includes(" daemon ") && stdout6.includes(resolve6(configPath));
18576
+ return stdout6.includes(" daemon ") && stdout6.includes(resolve7(configPath));
17944
18577
  } catch {
17945
18578
  return false;
17946
18579
  }
@@ -17966,14 +18599,14 @@ async function stopRuntimeDaemon(path, opts = {}) {
17966
18599
  throw new Error(`agent daemon ${pid} did not stop after ${timeout}ms`);
17967
18600
  }
17968
18601
  async function launchRuntimeDaemon(configPath, opts = {}) {
17969
- const directory = dirname2(configPath);
18602
+ const directory = dirname3(configPath);
17970
18603
  await mkdir(directory, { recursive: true, mode: 448 });
17971
18604
  const foreground = opts.foreground === true;
17972
- const output = foreground ? "inherit" : openSync(resolve6(directory, "daemon.log"), "a", 384);
18605
+ const output = foreground ? "inherit" : openSync(resolve7(directory, "daemon.log"), "a", 384);
17973
18606
  const entrypoint = opts.entrypoint ?? process.argv[1];
17974
18607
  if (!entrypoint)
17975
18608
  throw new Error("cannot resolve daemon CLI entrypoint");
17976
- const child = spawn4(process.execPath, [...opts.execArgv ?? [], entrypoint, "daemon", "--config", resolve6(configPath)], {
18609
+ const child = spawn6(process.execPath, [...opts.execArgv ?? [], entrypoint, "daemon", "--config", resolve7(configPath)], {
17977
18610
  cwd: directory,
17978
18611
  env: opts.env ?? process.env,
17979
18612
  detached: !foreground,
@@ -17990,9 +18623,9 @@ async function launchRuntimeDaemon(configPath, opts = {}) {
17990
18623
  }
17991
18624
  async function removeAgentRuntime(runtime) {
17992
18625
  const source = runtimeDirectory(runtime.supervisorRoot, runtime.agent.publicKey);
17993
- const deletedRoot = resolve6(runtime.supervisorRoot, "beeline", "deleted-runtimes");
18626
+ const deletedRoot = resolve7(runtime.supervisorRoot, "beeline", "deleted-runtimes");
17994
18627
  await mkdir(deletedRoot, { recursive: true, mode: 448 });
17995
- const target = resolve6(deletedRoot, `${runtime.agent.publicKey}-${Date.now()}`);
18628
+ const target = resolve7(deletedRoot, `${runtime.agent.publicKey}-${Date.now()}`);
17996
18629
  await rename(source, target);
17997
18630
  return target;
17998
18631
  }
@@ -18033,7 +18666,7 @@ var DaemonApiClient = class {
18033
18666
  agentId;
18034
18667
  fetchImpl;
18035
18668
  webSocketFactory;
18036
- presenceLifecycleId = randomUUID();
18669
+ presenceLifecycleId = randomUUID2();
18037
18670
  liveSocket;
18038
18671
  liveReconnect;
18039
18672
  liveReconnectDelayMs = 1e3;
@@ -18227,8 +18860,8 @@ var DaemonApiClient = class {
18227
18860
  };
18228
18861
  async function activateDaemonTransport(path, fetchImpl = fetch) {
18229
18862
  const runtime = await readRuntimeRecord(path);
18230
- const expectedPath = resolve7(runtimeDirectory(runtime.supervisorRoot, runtime.agent.publicKey), "runtime.json");
18231
- if (resolve7(path) !== expectedPath) {
18863
+ const expectedPath = resolve8(runtimeDirectory(runtime.supervisorRoot, runtime.agent.publicKey), "runtime.json");
18864
+ if (resolve8(path) !== expectedPath) {
18232
18865
  throw new Error(`refusing daemon token exchange outside canonical runtime path: ${path}`);
18233
18866
  }
18234
18867
  const transport = runtime.transport;
@@ -18268,18 +18901,18 @@ async function activateDaemonTransport(path, fetchImpl = fetch) {
18268
18901
 
18269
18902
  // apps/body/dist/room-runtime.js
18270
18903
  import { execFile as execFile6 } from "node:child_process";
18271
- import { createHash as createHash6 } from "node:crypto";
18272
- import { existsSync as existsSync4, mkdirSync } from "node:fs";
18904
+ import { createHash as createHash7 } from "node:crypto";
18905
+ import { existsSync as existsSync5, mkdirSync } from "node:fs";
18273
18906
  import { mkdir as mkdir13, rm as rm5 } from "node:fs/promises";
18274
- import { dirname as dirname8, resolve as resolve20 } from "node:path";
18907
+ import { dirname as dirname9, resolve as resolve21 } from "node:path";
18275
18908
  import { promisify as promisify4 } from "node:util";
18276
18909
 
18277
18910
  // apps/body/dist/grant-runner.js
18278
18911
  import { execFile as execFile3 } from "node:child_process";
18279
- import { createHash as createHash2, randomBytes as randomBytes6 } from "node:crypto";
18912
+ import { createHash as createHash3, randomBytes as randomBytes6 } from "node:crypto";
18280
18913
  import { readFile as readFile4 } from "node:fs/promises";
18281
18914
  import { createServer } from "node:http";
18282
- import { dirname as dirname4, resolve as resolve10 } from "node:path";
18915
+ import { dirname as dirname5, resolve as resolve11 } from "node:path";
18283
18916
 
18284
18917
  // packages/api-contract/dist/agent-grants.js
18285
18918
  var AGENT_GRANT_KINDS = ["path", "host", "secret", "device", "budget", "command"];
@@ -18502,9 +19135,9 @@ function surfaceAllows(surface, capability) {
18502
19135
 
18503
19136
  // apps/body/dist/bwrap-sandbox.js
18504
19137
  import { spawnSync } from "node:child_process";
18505
- import { lstatSync as lstatSync2 } from "node:fs";
18506
- import { homedir as homedir3 } from "node:os";
18507
- import { isAbsolute as isAbsolute2, relative, resolve as resolve8 } from "node:path";
19138
+ import { lstatSync as lstatSync3 } from "node:fs";
19139
+ import { homedir as homedir4 } from "node:os";
19140
+ import { isAbsolute as isAbsolute2, relative, resolve as resolve9 } from "node:path";
18508
19141
  var DEFAULT_SANDBOX_POLICY = "bwrap";
18509
19142
  function isSandboxPolicy(value) {
18510
19143
  return value === "bwrap" || value === "off";
@@ -18536,16 +19169,16 @@ var HARNESS_HOME_STATE_DIRS = [
18536
19169
  dirs: [".grok"]
18537
19170
  },
18538
19171
  {
18539
- match: /(^|[/\\])cursor-agent-acp(\.[a-z]+)?$/i,
19172
+ match: CURSOR_HARNESS_COMMAND,
18540
19173
  dirs: [".cursor"]
18541
19174
  }
18542
19175
  ];
18543
- function harnessHomeStateDirs(agentCommand, home = homedir3()) {
19176
+ function harnessHomeStateDirs(agentCommand, home = homedir4()) {
18544
19177
  if (!agentCommand)
18545
19178
  return [];
18546
19179
  for (const { match, dirs } of HARNESS_HOME_STATE_DIRS) {
18547
19180
  if (match.test(agentCommand))
18548
- return dirs.map((dir) => resolve8(home, dir));
19181
+ return dirs.map((dir) => resolve9(home, dir));
18549
19182
  }
18550
19183
  return [];
18551
19184
  }
@@ -18557,18 +19190,18 @@ var KNOWN_CREDENTIAL_MASK_PATHS = [
18557
19190
  ".git-credentials",
18558
19191
  ".secrets.env"
18559
19192
  ];
18560
- function credentialMaskPaths(extraPaths, home = homedir3(), stat4 = (path) => {
19193
+ function credentialMaskPaths(extraPaths, home = homedir4(), stat4 = (path) => {
18561
19194
  try {
18562
- const info = lstatSync2(path);
19195
+ const info = lstatSync3(path);
18563
19196
  return { isDirectory: info.isDirectory() };
18564
19197
  } catch {
18565
19198
  return void 0;
18566
19199
  }
18567
19200
  }, requiredPaths = []) {
18568
- const required = new Set(requiredPaths.map((path) => resolve8(path)));
19201
+ const required = new Set(requiredPaths.map((path) => resolve9(path)));
18569
19202
  const candidates = [
18570
- ...KNOWN_CREDENTIAL_MASK_PATHS.map((entry) => resolve8(home, entry)),
18571
- ...(extraPaths ?? []).map((entry) => resolve8(entry))
19203
+ ...KNOWN_CREDENTIAL_MASK_PATHS.map((entry) => resolve9(home, entry)),
19204
+ ...(extraPaths ?? []).map((entry) => resolve9(entry))
18572
19205
  ];
18573
19206
  const seen = /* @__PURE__ */ new Set();
18574
19207
  const masks = [];
@@ -18595,7 +19228,7 @@ function normalize(paths) {
18595
19228
  for (const path of paths) {
18596
19229
  if (!path)
18597
19230
  continue;
18598
- seen.add(resolve8(path));
19231
+ seen.add(resolve9(path));
18599
19232
  }
18600
19233
  return Array.from(seen).sort();
18601
19234
  }
@@ -18633,7 +19266,7 @@ function sandboxMountPlan(spec) {
18633
19266
  writable,
18634
19267
  quotaTmpfs: spec.workbench ? [
18635
19268
  {
18636
- target: resolve8(spec.workbench.dir),
19269
+ target: resolve9(spec.workbench.dir),
18637
19270
  maxBytes: spec.workbench.maxBytes,
18638
19271
  maxInodes: spec.workbench.maxInodes,
18639
19272
  blockGit: true
@@ -18688,7 +19321,7 @@ function buildBwrapArgv(input) {
18688
19321
  for (const binding of quotaTmpfs) {
18689
19322
  args.push("--dir", binding.target, "--size", String(binding.maxBytes), "--tmpfs", binding.target);
18690
19323
  if (binding.blockGit)
18691
- args.push("--ro-bind", "/dev/null", resolve8(binding.target, ".git"));
19324
+ args.push("--ro-bind", "/dev/null", resolve9(binding.target, ".git"));
18692
19325
  }
18693
19326
  args.push("--chdir", input.cwd);
18694
19327
  args.push("--die-with-parent");
@@ -18754,8 +19387,8 @@ function detectBwrapSandbox(options = {}) {
18754
19387
 
18755
19388
  // apps/body/dist/provider-key-store.js
18756
19389
  import { chmod, mkdir as mkdir2, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
18757
- import { homedir as homedir4 } from "node:os";
18758
- import { dirname as dirname3, resolve as resolve9 } from "node:path";
19390
+ import { homedir as homedir5 } from "node:os";
19391
+ import { dirname as dirname4, resolve as resolve10 } from "node:path";
18759
19392
  var PROVIDER_KEY_ENV_VARS = {
18760
19393
  openrouter: "OPENROUTER_API_KEY",
18761
19394
  openai: "OPENAI_API_KEY",
@@ -18765,8 +19398,8 @@ var PROVIDER_KEY_ENV_VARS = {
18765
19398
  };
18766
19399
  var GOOGLE_ENV_ALIAS = "GEMINI_API_KEY";
18767
19400
  function providerKeyStorePath(env = process.env) {
18768
- const configRoot = env.XDG_CONFIG_HOME?.trim() || resolve9(homedir4(), ".config");
18769
- return resolve9(configRoot, "beeline", "providers.json");
19401
+ const configRoot = env.XDG_CONFIG_HOME?.trim() || resolve10(homedir5(), ".config");
19402
+ return resolve10(configRoot, "beeline", "providers.json");
18770
19403
  }
18771
19404
  async function readProviderKeyStore(env = process.env) {
18772
19405
  const path = providerKeyStorePath(env);
@@ -18789,7 +19422,7 @@ async function readSavedProviderKey(provider, env = process.env) {
18789
19422
  async function saveProviderKey(provider, key, env = process.env) {
18790
19423
  const path = providerKeyStorePath(env);
18791
19424
  const store = { ...await readProviderKeyStore(env), [provider]: key };
18792
- await mkdir2(dirname3(path), { recursive: true, mode: 448 });
19425
+ await mkdir2(dirname4(path), { recursive: true, mode: 448 });
18793
19426
  await writeFile3(path, `${JSON.stringify(store, null, 2)}
18794
19427
  `, { mode: 384 });
18795
19428
  await chmod(path, 384);
@@ -18826,7 +19459,7 @@ function operatorSecretResolver(env = process.env) {
18826
19459
  if (saved)
18827
19460
  return saved;
18828
19461
  }
18829
- const raw = await readFile4(resolve10(dirname4(providerKeyStorePath(env)), "secrets.json"), "utf8").catch(() => void 0);
19462
+ const raw = await readFile4(resolve11(dirname5(providerKeyStorePath(env)), "secrets.json"), "utf8").catch(() => void 0);
18830
19463
  if (!raw)
18831
19464
  return void 0;
18832
19465
  try {
@@ -18938,9 +19571,9 @@ var GrantCommandRunner = class {
18938
19571
  ...Object.fromEntries(secrets)
18939
19572
  };
18940
19573
  const cap = this.options.outputCapBytes ?? GRANT_COMMAND_OUTPUT_CAP_BYTES;
18941
- const spawn11 = surfaceAllows(policy.surface, "run-host-command") ? { command: argv[0], args: argv.slice(1) } : roomSandboxCommand(policy, room.cwd, argv);
19574
+ const spawn12 = surfaceAllows(policy.surface, "run-host-command") ? { command: argv[0], args: argv.slice(1) } : roomSandboxCommand(policy, room.cwd, argv);
18942
19575
  const outcome = await new Promise((resolveRun) => {
18943
- const child = execFile3(spawn11.command, spawn11.args, {
19576
+ const child = execFile3(spawn12.command, spawn12.args, {
18944
19577
  cwd: room.cwd,
18945
19578
  env,
18946
19579
  timeout: this.options.timeoutMs ?? GRANT_COMMAND_TIMEOUT_MS,
@@ -19018,7 +19651,7 @@ ${ROOM_WRITE_REFUSED_NOTE}` : outcome.output, secrets), cap);
19018
19651
  if (!script || script.path !== argument.path) {
19019
19652
  throw new Error(`${argument.path} is a script no human has read: this grant was approved without it. Ask with request_grant kind=command so the card carries what the command runs.`);
19020
19653
  }
19021
- if (createHash2("sha256").update(bytes).digest("hex") !== script.sha256) {
19654
+ if (createHash3("sha256").update(bytes).digest("hex") !== script.sha256) {
19022
19655
  throw new Error(`${argument.path} changed after it was approved, so the approval no longer covers it. Ask with request_grant kind=command again so a human reads what runs now.`);
19023
19656
  }
19024
19657
  }
@@ -19028,8 +19661,8 @@ function scriptCandidates(cwd, scratch, argv) {
19028
19661
  if (!argument)
19029
19662
  return [];
19030
19663
  const paths = [
19031
- resolve10(cwd, argument.path),
19032
- ...scratch ? [resolve10(scratch, argument.path)] : []
19664
+ resolve11(cwd, argument.path),
19665
+ ...scratch ? [resolve11(scratch, argument.path)] : []
19033
19666
  ];
19034
19667
  return [...new Set(paths)];
19035
19668
  }
@@ -19210,20 +19843,20 @@ function captureConnectionUsage(recorder, turn, calls) {
19210
19843
  }
19211
19844
 
19212
19845
  // apps/body/dist/server-command-intake.js
19213
- import { randomUUID as randomUUID2 } from "node:crypto";
19846
+ import { randomUUID as randomUUID3 } from "node:crypto";
19214
19847
  import { mkdir as mkdir3, writeFile as writeFile4 } from "node:fs/promises";
19215
- import { tmpdir as tmpdir2 } from "node:os";
19216
- import { dirname as dirname5, join as join4 } from "node:path";
19848
+ import { tmpdir as tmpdir3 } from "node:os";
19849
+ import { dirname as dirname6, join as join5 } from "node:path";
19217
19850
  var CommandExecutionContext = class {
19218
- generationId = randomUUID2();
19851
+ generationId = randomUUID3();
19219
19852
  path;
19220
19853
  current;
19221
19854
  constructor(root) {
19222
- this.path = join4(root ?? tmpdir2(), `beeline-command-${this.generationId}.json`);
19855
+ this.path = join5(root ?? tmpdir3(), `beeline-command-${this.generationId}.json`);
19223
19856
  }
19224
19857
  async enter(command) {
19225
19858
  this.current = command;
19226
- await mkdir3(dirname5(this.path), { recursive: true });
19859
+ await mkdir3(dirname6(this.path), { recursive: true });
19227
19860
  await writeFile4(this.path, JSON.stringify({
19228
19861
  roomId: command.roomId,
19229
19862
  requestId: command.turnRequestId,
@@ -19345,13 +19978,13 @@ async function runServerCommandIntake(options) {
19345
19978
  }
19346
19979
  }
19347
19980
  options.onPoll?.();
19348
- const reconcile = await new Promise((resolve31) => {
19981
+ const reconcile = await new Promise((resolve32) => {
19349
19982
  const done = (needed) => {
19350
19983
  if (timer)
19351
19984
  clearTimeout(timer);
19352
19985
  signal?.removeEventListener("abort", aborted);
19353
19986
  wake = void 0;
19354
- resolve31(needed);
19987
+ resolve32(needed);
19355
19988
  };
19356
19989
  const aborted = () => done(false);
19357
19990
  wake = done;
@@ -19377,22 +20010,35 @@ async function runServerCommandIntake(options) {
19377
20010
 
19378
20011
  // apps/body/dist/monolith-corner-turn.js
19379
20012
  import { execFile as execFile5 } from "node:child_process";
19380
- import { createHash as createHash5 } from "node:crypto";
20013
+ import { createHash as createHash6 } from "node:crypto";
19381
20014
  import { mkdir as mkdir12 } from "node:fs/promises";
19382
- import { homedir as homedir7 } from "node:os";
19383
- import { join as join9 } from "node:path";
20015
+ import { homedir as homedir8 } from "node:os";
20016
+ import { join as join10 } from "node:path";
19384
20017
  import { promisify as promisify3 } from "node:util";
19385
20018
 
19386
20019
  // apps/body/dist/agent-home.js
19387
- import { existsSync as existsSync3, readFileSync as readFileSync5 } from "node:fs";
19388
- import { createHash as createHash3, randomUUID as randomUUID3 } from "node:crypto";
20020
+ import { existsSync as existsSync4, readFileSync as readFileSync6 } from "node:fs";
20021
+ import { createHash as createHash4, randomUUID as randomUUID4 } from "node:crypto";
19389
20022
  import { chmod as chmod2, copyFile, lstat, mkdir as mkdir5, readFile as readFile6, readdir as readdir2, realpath, rename as rename2, rm as rm2, symlink, unlink, writeFile as writeFile6 } from "node:fs/promises";
19390
- import { homedir as homedir5 } from "node:os";
19391
- import { basename as basename3, dirname as dirname6, join as join5, relative as relative2, resolve as resolve13, sep } from "node:path";
20023
+ import { homedir as homedir6 } from "node:os";
20024
+ import { basename as basename4, dirname as dirname7, join as join6, relative as relative2, resolve as resolve14, sep } from "node:path";
19392
20025
 
19393
20026
  // apps/body/dist/beeline-skill.js
19394
- import { readFileSync as readFileSync4 } from "node:fs";
19395
- import { resolve as resolve11 } from "node:path";
20027
+ import { readFileSync as readFileSync5 } from "node:fs";
20028
+ import { resolve as resolve12 } from "node:path";
20029
+
20030
+ // packages/api-contract/dist/workbench.js
20031
+ var CONNECTABLE_CONNECTOR_KINDS = [
20032
+ "trusty-squire",
20033
+ "google-gmail",
20034
+ "google-calendar",
20035
+ "google-drive",
20036
+ "google-youtube"
20037
+ ];
20038
+
20039
+ // packages/api-contract/dist/connector-offers.js
20040
+ var CONNECTOR_OFFER_WINDOW_MS = 2 * 6e4;
20041
+ var OFFERABLE_CONNECTOR_KINDS = CONNECTABLE_CONNECTOR_KINDS.filter((kind) => kind !== "wallet");
19396
20042
 
19397
20043
  // packages/api-contract/dist/agent-pairing-code.js
19398
20044
  var CURRENT_AGENT_PAIRING_CODE = /^[0-9A-F]{8}-[0-9A-F]{8}$/;
@@ -19457,12 +20103,12 @@ function beelineCapabilityContextForHarness(agentCommand, repository, directMess
19457
20103
  ...harnessHonorsSessionSystemPrompt(agentCommand) ? {} : { compatibilityTurnPrefix: primer }
19458
20104
  };
19459
20105
  }
19460
- function runningBeelineReleaseId(env = process.env, read = (path) => readFileSync4(path, "utf8")) {
20106
+ function runningBeelineReleaseId(env = process.env, read = (path) => readFileSync5(path, "utf8")) {
19461
20107
  try {
19462
20108
  const lib = env.BEELINE_LIB_DIR;
19463
20109
  if (!lib)
19464
20110
  return "source";
19465
- const manifest = JSON.parse(read(resolve11(lib, "bundle.json")));
20111
+ const manifest = JSON.parse(read(resolve12(lib, "bundle.json")));
19466
20112
  return [manifest.version, manifest.commit].filter(Boolean).join("-") || "source";
19467
20113
  } catch {
19468
20114
  return "source";
@@ -19484,13 +20130,17 @@ When your corner's pull request is ready, merging is your step: once the configu
19484
20130
 
19485
20131
  ## Tools and the Workbench
19486
20132
 
19487
- A **tool** is something you can use once a human pairs 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.
20133
+ 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.
19488
20134
 
19489
- This build knows one tool: Trusty Squire - vaulted credentials and a browser that signs in for you. Wallet and Tailscale are named in the Workbench but not yet available.
20135
+ The tools this build knows, what each is for, and which the person you are answering already has are one call away: beeline-agent workbench_status. Trusty Squire is vaulted credentials plus a browser that signs up and signs in for you; the Google tools (Gmail, Calendar, Drive, YouTube) work through the person's own Google sign-in. The wallet is created only from the Workbench page, and Tailscale is not available yet.
19490
20136
 
19491
- You NEVER pair a tool and never ask for a raw credential in chat. When a task needs one you do not have, say so plainly, name the tool that would solve it, and tell the person exactly where to go: Settings \u2192 Workbench \u2192 Tools.
20137
+ **Offer the tool at the moment you need it.** When the work in front of you needs a tool the person does not have, do not send them to a settings page and do not stop at naming it. Call workbench_status first - a tool they already have is used, not offered. Then call offer_connector with the connectorType and one short reason: a card appears in this Room, spoken by you, addressed to the person you are answering, with one action. Only that person or a Workspace admin can accept it; accepting adds the tool on your machine, and the sign-in or keys stay theirs. Your turn pauses on the card - say in prose what you are waiting for and end the turn; you are woken when it is added, and then you carry on.
19492
20138
 
19493
- Keys are sovereign: they belong to the human who provisioned them. You cannot use another member's key and must not ask a member to share one.
20139
+ **Research before you offer, and say so.** Never offer a tool you cannot describe. If someone asks you to install or add something you do not already know - by name, by purpose, or by what it will hold - say plainly that you are looking it up first, find out what it is and what it does with credentials, and state what you learned in your reply BEFORE the card appears. A person reading "Add X?" must already have read, in your own words, what X is. Refusing to act blind is part of being trusted with keys.
20140
+
20141
+ An offer is setup, never authority: it does not replace a grant, write permission, target-branch confirmation, or the merge gate, and it never needs a raw credential in chat. You never pair a tool yourself and never ask anyone for a key value; once a tool is added, provisioning happens inside it and receipts reach the person through the tool's own status message.
20142
+
20143
+ Keys are sovereign: they belong to the human who provisioned them. You cannot use another member's key and must not ask a member to share one. The Workbench page remains the place a person manages tools and keys by hand (Settings \u2192 Workbench); you point there to MANAGE what exists, not to add what you need.
19494
20144
 
19495
20145
  ## Showing a mock
19496
20146
 
@@ -19644,7 +20294,7 @@ var SQUIRE_GOVERNED_TOOL_SET = new Set(SQUIRE_GOVERNED_TOOLS);
19644
20294
 
19645
20295
  // apps/body/dist/openrouter-routing.js
19646
20296
  import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile5 } from "node:fs/promises";
19647
- import { resolve as resolve12 } from "node:path";
20297
+ import { resolve as resolve13 } from "node:path";
19648
20298
  var OPENROUTER_ENDPOINTS_BASE_URL = "https://openrouter.ai/api/v1/models";
19649
20299
  var OPENROUTER_COMPLETIONS_URL = "https://openrouter.ai/api/v1/chat/completions";
19650
20300
  var OPENROUTER_ROUTING_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
@@ -19746,10 +20396,10 @@ function openRouterRoutingFor(providers, allowFallbacks = true) {
19746
20396
  };
19747
20397
  }
19748
20398
  function openRouterRoutingCacheDir(runtimeDir) {
19749
- return resolve12(runtimeDir, "openrouter-routing");
20399
+ return resolve13(runtimeDir, "openrouter-routing");
19750
20400
  }
19751
20401
  function cachePath(cacheDir, model) {
19752
- return resolve12(cacheDir, `${model.replace(/[^A-Za-z0-9._-]+/g, "_")}.json`);
20402
+ return resolve13(cacheDir, `${model.replace(/[^A-Za-z0-9._-]+/g, "_")}.json`);
19753
20403
  }
19754
20404
  async function readCache(cacheDir, model) {
19755
20405
  try {
@@ -19780,7 +20430,7 @@ async function writeCache(cacheDir, value) {
19780
20430
  });
19781
20431
  }
19782
20432
  function probeCachePath(cacheDir, model) {
19783
- return resolve12(cacheDir, `${model.replace(/[^A-Za-z0-9._-]+/g, "_")}.probe.json`);
20433
+ return resolve13(cacheDir, `${model.replace(/[^A-Za-z0-9._-]+/g, "_")}.probe.json`);
19784
20434
  }
19785
20435
  async function readProbeCache(cacheDir, model) {
19786
20436
  try {
@@ -20220,8 +20870,8 @@ var SHARED_CREDENTIALS = [
20220
20870
  // shape as codex).
20221
20871
  { dir: "grok", source: ".grok/auth.json", target: "auth.json" },
20222
20872
  { dir: "pi", source: ".pi/agent/auth.json", target: "auth.json" },
20223
- // Cursor CLI stores auth state under ~/.cursor/; cursor-agent-acp
20224
- // reads CURSOR_HOME to relocate the data directory.
20873
+ // Cursor CLI stores auth state under ~/.cursor/; cursor-agent reads
20874
+ // CURSOR_HOME to relocate the data directory.
20225
20875
  { dir: "cursor", source: ".cursor/agent-cli-state.json", target: "agent-cli-state.json" }
20226
20876
  ];
20227
20877
  var GOOSE_SHARED_CONFIG_FILES = ["config.yaml", "secrets.yaml"];
@@ -20270,8 +20920,8 @@ var HOME_SUBDIRS = [
20270
20920
  "tmp"
20271
20921
  ];
20272
20922
  async function prepareRoomAgentHome(input) {
20273
- const root = resolve13(input.root);
20274
- const operatorHome = input.operatorHome ?? homedir5();
20923
+ const root = resolve14(input.root);
20924
+ const operatorHome = input.operatorHome ?? homedir6();
20275
20925
  try {
20276
20926
  await mkdir5(root, { recursive: true, mode: 448 });
20277
20927
  const rootStats = await lstat(root);
@@ -20279,7 +20929,7 @@ async function prepareRoomAgentHome(input) {
20279
20929
  throw new AgentHomeSecurityError(`agent home root is not an ordinary directory: ${root}`);
20280
20930
  }
20281
20931
  for (const subdir of HOME_SUBDIRS) {
20282
- const path = resolve13(root, subdir);
20932
+ const path = resolve14(root, subdir);
20283
20933
  await mkdir5(path, { recursive: true, mode: 448 });
20284
20934
  await assertRealContainedDirectory(path, root);
20285
20935
  }
@@ -20290,9 +20940,9 @@ async function prepareRoomAgentHome(input) {
20290
20940
  return {};
20291
20941
  }
20292
20942
  for (const credential of SHARED_CREDENTIALS) {
20293
- const source = resolve13(operatorHome, credential.source);
20294
- const target = resolve13(root, credential.dir, credential.target);
20295
- if (!existsSync3(source) || existsSync3(target))
20943
+ const source = resolve14(operatorHome, credential.source);
20944
+ const target = resolve14(root, credential.dir, credential.target);
20945
+ if (!existsSync4(source) || existsSync4(target))
20296
20946
  continue;
20297
20947
  await symlink(source, target).catch(() => void 0);
20298
20948
  }
@@ -20314,12 +20964,12 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
20314
20964
  ...isReviewer ? [{ name: BEELINE_REVIEW_SKILL_NAME, content: beelineReviewSkillMarkdown(skillReleaseId) }] : []
20315
20965
  ];
20316
20966
  const shared = await resolveSharedSkillSources(operatorHome, sharedSkills);
20317
- await provisionManagedSkillsDir(resolve13(root, skillDir, "skills"), managedSkills, shared, sharedSkills.length === 0);
20967
+ await provisionManagedSkillsDir(resolve14(root, skillDir, "skills"), managedSkills, shared, sharedSkills.length === 0);
20318
20968
  for (const config of HARNESS_MCP_CONFIGS) {
20319
20969
  try {
20320
- const source = resolve13(operatorHome, config.toml);
20321
- const target = resolve13(root, config.dir, "config.toml");
20322
- const mcpSection = existsSync3(source) ? filteredHarnessMcpToml(readFileSync5(source, "utf8")) : void 0;
20970
+ const source = resolve14(operatorHome, config.toml);
20971
+ const target = resolve14(root, config.dir, "config.toml");
20972
+ const mcpSection = existsSync4(source) ? filteredHarnessMcpToml(readFileSync6(source, "utf8")) : void 0;
20323
20973
  const section = config.dir === "codex" ? [CODEX_ROOM_AGENT_LOCKDOWN_TOML, CODEX_ROOM_WEB_SEARCH_TOML, mcpSection].filter(Boolean).join("\n") : mcpSection;
20324
20974
  if (!section) {
20325
20975
  await unlink(target).catch(() => void 0);
@@ -20333,13 +20983,13 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
20333
20983
  }
20334
20984
  }
20335
20985
  try {
20336
- const gooseConfigDir = resolve13(root, "goose", "config");
20986
+ const gooseConfigDir = resolve14(root, "goose", "config");
20337
20987
  await mkdir5(gooseConfigDir, { recursive: true, mode: 448 });
20338
20988
  for (const name of GOOSE_SHARED_CONFIG_FILES) {
20339
- const source = resolve13(operatorHome, ".config", "goose", name);
20340
- const target = resolve13(gooseConfigDir, name);
20341
- if (existsSync3(source)) {
20342
- await writeIsolatedHarnessFile(target, readFileSync5(source, "utf8"));
20989
+ const source = resolve14(operatorHome, ".config", "goose", name);
20990
+ const target = resolve14(gooseConfigDir, name);
20991
+ if (existsSync4(source)) {
20992
+ await writeIsolatedHarnessFile(target, readFileSync6(source, "utf8"));
20343
20993
  } else {
20344
20994
  await unlink(target).catch(() => void 0);
20345
20995
  }
@@ -20350,9 +21000,9 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
20350
21000
  console.warn("[body] operator Goose configuration passthrough failed:", error);
20351
21001
  }
20352
21002
  try {
20353
- const claudeJson = resolve13(operatorHome, ".claude.json");
20354
- const claudeTarget = resolve13(root, "claude", ".claude.json");
20355
- const mcpServers = existsSync3(claudeJson) ? readClaudeUserScopeMcpServers(claudeJson) : void 0;
21003
+ const claudeJson = resolve14(operatorHome, ".claude.json");
21004
+ const claudeTarget = resolve14(root, "claude", ".claude.json");
21005
+ const mcpServers = existsSync4(claudeJson) ? readClaudeUserScopeMcpServers(claudeJson) : void 0;
20356
21006
  if (mcpServers && Object.keys(mcpServers).length > 0) {
20357
21007
  await writeIsolatedHarnessFile(claudeTarget, `${JSON.stringify({ mcpServers }, null, 2)}
20358
21008
  `);
@@ -20366,7 +21016,7 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
20366
21016
  }
20367
21017
  try {
20368
21018
  const settings2 = { permissions: { allow: ["WebSearch", "WebFetch"] } };
20369
- await writeIsolatedHarnessFile(resolve13(root, "claude", "settings.json"), `${JSON.stringify(settings2, null, 2)}
21019
+ await writeIsolatedHarnessFile(resolve14(root, "claude", "settings.json"), `${JSON.stringify(settings2, null, 2)}
20370
21020
  `);
20371
21021
  } catch (error) {
20372
21022
  if (failClosed)
@@ -20376,8 +21026,8 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
20376
21026
  await provisionPiCustomModelConfig(root, operatorHome, failClosed, openRouterRouting);
20377
21027
  }
20378
21028
  async function provisionPiCustomModelConfig(root, operatorHome, failClosed, openRouterRouting) {
20379
- const source = resolve13(operatorHome, PI_CUSTOM_MODEL_CONFIG.source);
20380
- const target = resolve13(root, "pi", PI_CUSTOM_MODEL_CONFIG.target);
21029
+ const source = resolve14(operatorHome, PI_CUSTOM_MODEL_CONFIG.source);
21030
+ const target = resolve14(root, "pi", PI_CUSTOM_MODEL_CONFIG.target);
20381
21031
  let decision2;
20382
21032
  if (openRouterRouting) {
20383
21033
  decision2 = await resolveOpenRouterRouting(openRouterRouting);
@@ -20410,7 +21060,7 @@ async function provisionPiCustomModelConfig(root, operatorHome, failClosed, open
20410
21060
  if (resolvedSource !== source) {
20411
21061
  throw new AgentHomeSecurityError(`Pi custom model config resolves through a link: ${source}`);
20412
21062
  }
20413
- const sourceValue = JSON.parse(readFileSync5(resolvedSource, "utf8"));
21063
+ const sourceValue = JSON.parse(readFileSync6(resolvedSource, "utf8"));
20414
21064
  await writeIsolatedHarnessFile(target, `${JSON.stringify(withOpenRouterModelRouting(sourceValue, pin), null, 2)}
20415
21065
  `);
20416
21066
  } catch (error) {
@@ -20422,7 +21072,7 @@ async function provisionPiCustomModelConfig(root, operatorHome, failClosed, open
20422
21072
  }
20423
21073
  function readClaudeUserScopeMcpServers(path) {
20424
21074
  try {
20425
- const parsed = JSON.parse(readFileSync5(path, "utf8"));
21075
+ const parsed = JSON.parse(readFileSync6(path, "utf8"));
20426
21076
  if (parsed && typeof parsed.mcpServers === "object" && parsed.mcpServers !== null) {
20427
21077
  return Object.fromEntries(Object.entries(parsed.mcpServers).filter(([name, value]) => {
20428
21078
  if (name === "squire")
@@ -20446,21 +21096,21 @@ function filteredHarnessMcpToml(source) {
20446
21096
  return extractTomlSections(source, ["mcp_servers"], excluded);
20447
21097
  }
20448
21098
  async function provisionManagedSkillsDir(target, managedSkills, sharedSkills, optionalShares) {
20449
- const parent = dirname6(target);
20450
- await assertRealContainedDirectory(parent, dirname6(parent));
21099
+ const parent = dirname7(target);
21100
+ await assertRealContainedDirectory(parent, dirname7(parent));
20451
21101
  const plan = await planManagedSkills(managedSkills, sharedSkills, optionalShares);
20452
21102
  if (await materializedSkillManifest(target) === plan.manifest)
20453
21103
  return;
20454
- const staged = resolve13(parent, `.skills.${process.pid}.${randomUUID3()}.tmp`);
21104
+ const staged = resolve14(parent, `.skills.${process.pid}.${randomUUID4()}.tmp`);
20455
21105
  await mkdir5(staged, { mode: 448 });
20456
21106
  try {
20457
21107
  for (const entry of plan.entries) {
20458
21108
  if (entry.kind === "managed") {
20459
- const skillDir = resolve13(staged, entry.name);
21109
+ const skillDir = resolve14(staged, entry.name);
20460
21110
  await mkdir5(skillDir, { recursive: true });
20461
- await writeIsolatedHarnessFile(resolve13(skillDir, "SKILL.md"), entry.content);
21111
+ await writeIsolatedHarnessFile(resolve14(skillDir, "SKILL.md"), entry.content);
20462
21112
  } else {
20463
- await copySafeSkillTree(entry.source, resolve13(staged, entry.name), entry.source);
21113
+ await copySafeSkillTree(entry.source, resolve14(staged, entry.name), entry.source);
20464
21114
  }
20465
21115
  }
20466
21116
  const existing = await lstat(target).catch(() => void 0);
@@ -20487,8 +21137,8 @@ async function planManagedSkills(managedSkills, sharedSkills, optionalShares) {
20487
21137
  try {
20488
21138
  const tree = [];
20489
21139
  await walkSafeSkillTree(shared.source, shared.source, {
20490
- directory: async (rel) => void tree.push(`d ${join5(shared.name, rel)}`),
20491
- file: async (rel, realPath) => void tree.push(`f ${join5(shared.name, rel)} ${sha2563(await readFile6(realPath))}`)
21140
+ directory: async (rel) => void tree.push(`d ${join6(shared.name, rel)}`),
21141
+ file: async (rel, realPath) => void tree.push(`f ${join6(shared.name, rel)} ${sha2563(await readFile6(realPath))}`)
20492
21142
  });
20493
21143
  entries.push({ kind: "shared", name: shared.name, source: shared.source });
20494
21144
  lines.push(...tree);
@@ -20507,8 +21157,8 @@ async function materializedSkillManifest(target) {
20507
21157
  const lines = [];
20508
21158
  const visit = async (directory, prefix) => {
20509
21159
  for (const entry of await readdir2(directory)) {
20510
- const path = resolve13(directory, entry);
20511
- const rel = prefix ? join5(prefix, entry) : entry;
21160
+ const path = resolve14(directory, entry);
21161
+ const rel = prefix ? join6(prefix, entry) : entry;
20512
21162
  const entryStats = await lstat(path);
20513
21163
  if (entryStats.isSymbolicLink())
20514
21164
  return false;
@@ -20533,7 +21183,7 @@ async function materializedSkillManifest(target) {
20533
21183
  return lines.sort().join("\n");
20534
21184
  }
20535
21185
  function sha2563(value) {
20536
- return createHash3("sha256").update(value).digest("hex");
21186
+ return createHash4("sha256").update(value).digest("hex");
20537
21187
  }
20538
21188
  async function resolveSharedSkillSources(operatorHome, names) {
20539
21189
  if (names.length > 0)
@@ -20542,14 +21192,14 @@ async function resolveSharedSkillSources(operatorHome, names) {
20542
21192
  const resolved = [];
20543
21193
  const skipped = [];
20544
21194
  for (const relativeRoot of OPERATOR_SKILL_SOURCE_DIRS) {
20545
- const sourceRoot = resolve13(operatorHome, relativeRoot);
21195
+ const sourceRoot = resolve14(operatorHome, relativeRoot);
20546
21196
  const rootStats = await lstat(sourceRoot).catch(() => void 0);
20547
21197
  if (!rootStats?.isDirectory() || rootStats.isSymbolicLink())
20548
21198
  continue;
20549
21199
  for (const entry of await readdir2(sourceRoot)) {
20550
21200
  if (!isSharedSkillName(entry) || seen.has(entry))
20551
21201
  continue;
20552
- const candidate = resolve13(sourceRoot, entry);
21202
+ const candidate = resolve14(sourceRoot, entry);
20553
21203
  try {
20554
21204
  const candidateStats = await lstat(candidate);
20555
21205
  if (candidateStats.isSymbolicLink()) {
@@ -20565,7 +21215,7 @@ async function resolveSharedSkillSources(operatorHome, names) {
20565
21215
  continue;
20566
21216
  }
20567
21217
  assertContained(sourceRoot, candidate);
20568
- const skillMd = resolve13(candidate, "SKILL.md");
21218
+ const skillMd = resolve14(candidate, "SKILL.md");
20569
21219
  const skillStats = await lstat(skillMd).catch((error) => {
20570
21220
  if (isMissingPathError(error)) {
20571
21221
  skipped.push({ path: candidate, reason: "missing SKILL.md" });
@@ -20617,8 +21267,8 @@ async function resolveExplicitSkillSources(operatorHome, names) {
20617
21267
  for (const name of unique) {
20618
21268
  const matches = [];
20619
21269
  for (const relativeRoot of OPERATOR_SKILL_SOURCE_DIRS) {
20620
- const sourceRoot = resolve13(operatorHome, relativeRoot);
20621
- const candidate = resolve13(sourceRoot, name);
21270
+ const sourceRoot = resolve14(operatorHome, relativeRoot);
21271
+ const candidate = resolve14(sourceRoot, name);
20622
21272
  const rootStats = await lstat(sourceRoot).catch(() => void 0);
20623
21273
  const candidateStats = await lstat(candidate).catch(() => void 0);
20624
21274
  if (!candidateStats)
@@ -20635,7 +21285,7 @@ async function resolveExplicitSkillSources(operatorHome, names) {
20635
21285
  if (matches.length !== 1) {
20636
21286
  throw new Error(matches.length === 0 ? `shared skill is unavailable: ${name}` : `shared skill source is ambiguous: ${name}`);
20637
21287
  }
20638
- const skillMd = resolve13(matches[0], "SKILL.md");
21288
+ const skillMd = resolve14(matches[0], "SKILL.md");
20639
21289
  const skillStats = await lstat(skillMd).catch(() => void 0);
20640
21290
  if (!skillStats?.isFile() || skillStats.isSymbolicLink() || skillStats.nlink !== 1) {
20641
21291
  throw new Error(`shared skill requires an ordinary SKILL.md: ${name}`);
@@ -20646,7 +21296,7 @@ async function resolveExplicitSkillSources(operatorHome, names) {
20646
21296
  }
20647
21297
  function assertContained(root, candidate) {
20648
21298
  const rel = relative2(root, candidate);
20649
- if (rel === ".." || rel.startsWith(`..${sep}`) || resolve13(root, rel) !== resolve13(candidate)) {
21299
+ if (rel === ".." || rel.startsWith(`..${sep}`) || resolve14(root, rel) !== resolve14(candidate)) {
20650
21300
  throw new Error(`path escapes the agent skill boundary: ${candidate}`);
20651
21301
  }
20652
21302
  }
@@ -20661,14 +21311,14 @@ var BLOCKED_SHARED_FILENAMES = /^(?:\.env(?:\..*)?|auth\.json|\.credentials\.jso
20661
21311
  async function walkSafeSkillTree(source, sourceRoot, visitor, rel = "") {
20662
21312
  assertContained(sourceRoot, source);
20663
21313
  const resolvedSource = await realpath(source);
20664
- if (resolvedSource !== resolve13(source)) {
21314
+ if (resolvedSource !== resolve14(source)) {
20665
21315
  throw new Error(`shared skill path resolves through a link: ${source}`);
20666
21316
  }
20667
21317
  assertContained(sourceRoot, resolvedSource);
20668
21318
  const stats = await lstat(resolvedSource);
20669
21319
  if (stats.isSymbolicLink())
20670
21320
  throw new Error(`shared skill contains a symlink: ${source}`);
20671
- if (BLOCKED_SHARED_FILENAMES.test(basename3(source))) {
21321
+ if (BLOCKED_SHARED_FILENAMES.test(basename4(source))) {
20672
21322
  throw new Error(`shared skill contains credential or configuration material: ${source}`);
20673
21323
  }
20674
21324
  if (stats.isDirectory()) {
@@ -20676,7 +21326,7 @@ async function walkSafeSkillTree(source, sourceRoot, visitor, rel = "") {
20676
21326
  for (const entry of await readdir2(resolvedSource)) {
20677
21327
  if (entry === "." || entry === "..")
20678
21328
  throw new Error("invalid shared skill entry");
20679
- await walkSafeSkillTree(resolve13(source, entry), sourceRoot, visitor, rel ? join5(rel, entry) : entry);
21329
+ await walkSafeSkillTree(resolve14(source, entry), sourceRoot, visitor, rel ? join6(rel, entry) : entry);
20680
21330
  }
20681
21331
  return;
20682
21332
  }
@@ -20688,22 +21338,22 @@ async function walkSafeSkillTree(source, sourceRoot, visitor, rel = "") {
20688
21338
  async function copySafeSkillTree(source, target, sourceRoot) {
20689
21339
  await walkSafeSkillTree(source, sourceRoot, {
20690
21340
  directory: async (rel) => {
20691
- await mkdir5(resolve13(target, rel), { mode: 448 });
21341
+ await mkdir5(resolve14(target, rel), { mode: 448 });
20692
21342
  },
20693
21343
  file: async (rel, realPath) => {
20694
- const destination = resolve13(target, rel);
21344
+ const destination = resolve14(target, rel);
20695
21345
  await copyFile(realPath, destination);
20696
21346
  await chmod2(destination, 384);
20697
21347
  }
20698
21348
  });
20699
21349
  }
20700
21350
  async function writeIsolatedHarnessFile(path, content) {
20701
- const parent = dirname6(path);
21351
+ const parent = dirname7(path);
20702
21352
  const parentStats = await lstat(parent);
20703
21353
  if (!parentStats.isDirectory() || parentStats.isSymbolicLink()) {
20704
21354
  throw new Error(`isolated harness parent is not a real directory: ${parent}`);
20705
21355
  }
20706
- const temporary = resolve13(parent, `.${basename3(path)}.${process.pid}.${randomUUID3()}.tmp`);
21356
+ const temporary = resolve14(parent, `.${basename4(path)}.${process.pid}.${randomUUID4()}.tmp`);
20707
21357
  try {
20708
21358
  await writeFile6(temporary, content, { mode: 384, flag: "wx" });
20709
21359
  await chmod2(temporary, 384);
@@ -20713,18 +21363,18 @@ async function writeIsolatedHarnessFile(path, content) {
20713
21363
  }
20714
21364
  }
20715
21365
  function roomAgentHomeEnv(root) {
20716
- const resolved = resolve13(root);
21366
+ const resolved = resolve14(root);
20717
21367
  return {
20718
- HOME: resolve13(resolved, "user"),
20719
- CLAUDE_CONFIG_DIR: resolve13(resolved, "claude"),
20720
- CODEX_HOME: resolve13(resolved, "codex"),
20721
- GOOSE_PATH_ROOT: resolve13(resolved, "goose"),
20722
- GROK_HOME: resolve13(resolved, "grok"),
20723
- CURSOR_HOME: resolve13(resolved, "cursor"),
20724
- PI_CODING_AGENT_DIR: resolve13(resolved, "pi"),
20725
- XDG_STATE_HOME: resolve13(resolved, "state"),
20726
- XDG_CACHE_HOME: resolve13(resolved, "cache"),
20727
- TMPDIR: resolve13(resolved, "tmp")
21368
+ HOME: resolve14(resolved, "user"),
21369
+ CLAUDE_CONFIG_DIR: resolve14(resolved, "claude"),
21370
+ CODEX_HOME: resolve14(resolved, "codex"),
21371
+ GOOSE_PATH_ROOT: resolve14(resolved, "goose"),
21372
+ GROK_HOME: resolve14(resolved, "grok"),
21373
+ CURSOR_HOME: resolve14(resolved, "cursor"),
21374
+ PI_CODING_AGENT_DIR: resolve14(resolved, "pi"),
21375
+ XDG_STATE_HOME: resolve14(resolved, "state"),
21376
+ XDG_CACHE_HOME: resolve14(resolved, "cache"),
21377
+ TMPDIR: resolve14(resolved, "tmp")
20728
21378
  };
20729
21379
  }
20730
21380
  var HARNESS_STATE_ENV_VARS = [
@@ -20743,22 +21393,22 @@ function harnessStateDirsFromEnv(env) {
20743
21393
  for (const name of HARNESS_STATE_ENV_VARS) {
20744
21394
  const value = env[name];
20745
21395
  if (value)
20746
- stateDirs.push(resolve13(value));
21396
+ stateDirs.push(resolve14(value));
20747
21397
  }
20748
21398
  const tmp = env.TMPDIR;
20749
- return { stateDirs, ...tmp ? { tmpDir: resolve13(tmp) } : {} };
21399
+ return { stateDirs, ...tmp ? { tmpDir: resolve14(tmp) } : {} };
20750
21400
  }
20751
21401
 
20752
21402
  // apps/body/dist/attachment-delivery.js
20753
21403
  import { mkdir as mkdir6, writeFile as writeFile7 } from "node:fs/promises";
20754
- import { basename as basename4, extname, join as join6 } from "node:path";
21404
+ import { basename as basename5, extname, join as join7 } from "node:path";
20755
21405
  var MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024;
20756
21406
  var MEDIA_TTL_HOURS = 24;
20757
21407
  var EXPIRED_REASON = `expired: attachments are kept for ${MEDIA_TTL_HOURS} hours and these bytes are past that window`;
20758
21408
  var FETCH_TIMEOUT_MS = 3e4;
20759
21409
  var MAX_INLINE_IMAGE_BYTES = 5 * 1024 * 1024;
20760
21410
  function safeFileName(attachment, index, taken) {
20761
- const raw = basename4(attachment.name ?? "").replace(/[^\w.-]+/g, "_").replace(/^\.+/, "");
21411
+ const raw = basename5(attachment.name ?? "").replace(/[^\w.-]+/g, "_").replace(/^\.+/, "");
20762
21412
  let name = raw || `attachment-${index + 1}`;
20763
21413
  if (taken.has(name)) {
20764
21414
  const ext = extname(name);
@@ -20795,7 +21445,7 @@ async function deliverAttachments(attachments, dir, fetchImpl = fetch) {
20795
21445
  const bytes = Buffer.from(await response.arrayBuffer());
20796
21446
  if (bytes.length > MAX_ATTACHMENT_BYTES)
20797
21447
  return tooLarge(bytes.length);
20798
- const path = join6(dir, safeFileName(attachment, index, taken));
21448
+ const path = join7(dir, safeFileName(attachment, index, taken));
20799
21449
  await writeFile7(path, bytes);
20800
21450
  const mimeType = attachment.mimeType ?? response.headers.get("content-type") ?? "";
20801
21451
  if (!mimeType.startsWith("image/"))
@@ -21186,7 +21836,7 @@ function sessionConfigFingerprint(input) {
21186
21836
 
21187
21837
  // apps/body/dist/pi-mcp-bridge.js
21188
21838
  import { mkdir as mkdir7 } from "node:fs/promises";
21189
- import { resolve as resolve14 } from "node:path";
21839
+ import { resolve as resolve15 } from "node:path";
21190
21840
  var PI_MCP_BRIDGE_FILENAME = "beeline-mcp-bridge.js";
21191
21841
  function harnessMountsSessionMcpServers(agentCommand) {
21192
21842
  return !(agentCommand && /(^|[/\\])pi-acp(\.[a-z]+)?$/i.test(agentCommand));
@@ -21206,8 +21856,8 @@ async function installPiMcpBridge(input) {
21206
21856
  return void 0;
21207
21857
  if (!input.piHome || !input.servers.length)
21208
21858
  return void 0;
21209
- const directory = resolve14(input.piHome, "extensions");
21210
- const path = resolve14(directory, PI_MCP_BRIDGE_FILENAME);
21859
+ const directory = resolve15(input.piHome, "extensions");
21860
+ const path = resolve15(directory, PI_MCP_BRIDGE_FILENAME);
21211
21861
  try {
21212
21862
  await mkdir7(directory, { recursive: true, mode: 448 });
21213
21863
  await writeIsolatedHarnessFile(path, piMcpBridgeSource(input.servers));
@@ -21407,7 +22057,7 @@ async function contains(git, head, ancestor) {
21407
22057
  }
21408
22058
 
21409
22059
  // apps/body/dist/room-session.js
21410
- import { resolve as resolve15 } from "node:path";
22060
+ import { resolve as resolve16 } from "node:path";
21411
22061
 
21412
22062
  // apps/body/dist/read-only-policy.js
21413
22063
  var READ_ONLY_MCP_SERVER_NAME = "beeline-readonly-mcp";
@@ -21632,21 +22282,21 @@ function readOnlyMcpServer(config, cwd, agentMemoryDir) {
21632
22282
  command: config.readonlyMcpCommand,
21633
22283
  args: [...config.readonlyMcpArgs ?? []],
21634
22284
  env: [
21635
- { name: "BEELINE_READONLY_ROOT", value: resolve15(cwd) },
22285
+ { name: "BEELINE_READONLY_ROOT", value: resolve16(cwd) },
21636
22286
  ...config.agentHomeRoot ? [
21637
22287
  {
21638
22288
  name: "BEELINE_READONLY_AGENT_SKILLS_ROOT",
21639
- value: resolve15(config.agentHomeRoot, skillDir, "skills")
22289
+ value: resolve16(config.agentHomeRoot, skillDir, "skills")
21640
22290
  }
21641
22291
  ] : [],
21642
- ...agentMemoryDir ? [{ name: "BEELINE_READONLY_AGENT_MEMORY_ROOT", value: resolve15(agentMemoryDir) }] : []
22292
+ ...agentMemoryDir ? [{ name: "BEELINE_READONLY_AGENT_MEMORY_ROOT", value: resolve16(agentMemoryDir) }] : []
21643
22293
  ]
21644
22294
  };
21645
22295
  }
21646
22296
 
21647
22297
  // apps/body/dist/pi-turn-record.js
21648
22298
  import { readdir as readdir3, readFile as readFile7 } from "node:fs/promises";
21649
- import { resolve as resolve16 } from "node:path";
22299
+ import { resolve as resolve17 } from "node:path";
21650
22300
  function summarizeProviderError(errorMessage2) {
21651
22301
  const trimmed = errorMessage2.trim();
21652
22302
  const statusMatch = /^(\d{3}):\s*([\s\S]*)$/.exec(trimmed);
@@ -21667,7 +22317,7 @@ function summarizeProviderError(errorMessage2) {
21667
22317
  }
21668
22318
  async function sessionFileFromMap(home, sessionId) {
21669
22319
  try {
21670
- const raw = await readFile7(resolve16(home, ".pi", "pi-acp", "session-map.json"), "utf8");
22320
+ const raw = await readFile7(resolve17(home, ".pi", "pi-acp", "session-map.json"), "utf8");
21671
22321
  const map = JSON.parse(raw);
21672
22322
  const file = map.sessions?.[sessionId]?.sessionFile;
21673
22323
  return typeof file === "string" && file ? file : void 0;
@@ -21676,7 +22326,7 @@ async function sessionFileFromMap(home, sessionId) {
21676
22326
  }
21677
22327
  }
21678
22328
  async function sessionFileFromLayout(piDir, sessionId) {
21679
- const sessionsRoot = resolve16(piDir, "sessions");
22329
+ const sessionsRoot = resolve17(piDir, "sessions");
21680
22330
  const suffix = `_${sessionId}.jsonl`;
21681
22331
  let projects;
21682
22332
  try {
@@ -21685,7 +22335,7 @@ async function sessionFileFromLayout(piDir, sessionId) {
21685
22335
  return void 0;
21686
22336
  }
21687
22337
  for (const project of projects) {
21688
- const dir = resolve16(sessionsRoot, project);
22338
+ const dir = resolve17(sessionsRoot, project);
21689
22339
  let files;
21690
22340
  try {
21691
22341
  files = await readdir3(dir);
@@ -21694,7 +22344,7 @@ async function sessionFileFromLayout(piDir, sessionId) {
21694
22344
  }
21695
22345
  const match = files.find((file) => file.endsWith(suffix));
21696
22346
  if (match)
21697
- return resolve16(dir, match);
22347
+ return resolve17(dir, match);
21698
22348
  }
21699
22349
  return void 0;
21700
22350
  }
@@ -21869,7 +22519,7 @@ async function withTurnReceiptHeartbeat(api, receipt, task, onHeartbeatError) {
21869
22519
 
21870
22520
  // apps/body/dist/turn-trace.js
21871
22521
  import { appendFile, mkdir as mkdir8, readdir as readdir4, rm as rm3 } from "node:fs/promises";
21872
- import { resolve as resolve17 } from "node:path";
22522
+ import { resolve as resolve18 } from "node:path";
21873
22523
  import { performance as performance2 } from "node:perf_hooks";
21874
22524
  var TURN_PHASES = [
21875
22525
  /** Enqueued on `SessionScheduler` until this turn holds a slot. A capacity wait lives here. */
@@ -22099,7 +22749,7 @@ function formatTurnTraceLine(record3) {
22099
22749
  return [head, ...record3.attempts.map((attempt) => formatTurnAttempt(attempt))].join("\n ");
22100
22750
  }
22101
22751
  function turnTraceDirectory(runtimeDir) {
22102
- return resolve17(runtimeDir, "turn-traces");
22752
+ return resolve18(runtimeDir, "turn-traces");
22103
22753
  }
22104
22754
  var TURN_TRACE_RETENTION_DAYS = 7;
22105
22755
  function traceFileName(date) {
@@ -22116,7 +22766,7 @@ var TurnTraceFile = class {
22116
22766
  this.options = options;
22117
22767
  }
22118
22768
  path(now2 = (this.options.clock ?? (() => /* @__PURE__ */ new Date()))()) {
22119
- return resolve17(this.directory, traceFileName(now2));
22769
+ return resolve18(this.directory, traceFileName(now2));
22120
22770
  }
22121
22771
  write(record3) {
22122
22772
  this.tail = this.tail.catch(() => void 0).then(async () => {
@@ -22140,15 +22790,15 @@ var TurnTraceFile = class {
22140
22790
  this.prunedDay = day;
22141
22791
  const cutoff = traceFileName(new Date(now2.getTime() - TURN_TRACE_RETENTION_DAYS * 864e5));
22142
22792
  const names = await readdir4(this.directory).catch(() => []);
22143
- await Promise.all(names.filter((name) => /^turns-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name) && name < cutoff).map((name) => rm3(resolve17(this.directory, name), { force: true })));
22793
+ await Promise.all(names.filter((name) => /^turns-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name) && name < cutoff).map((name) => rm3(resolve18(this.directory, name), { force: true })));
22144
22794
  }
22145
22795
  };
22146
22796
 
22147
22797
  // apps/body/dist/corner-github-auth.js
22148
22798
  import { chmod as chmod3, mkdir as mkdir9, writeFile as writeFile8 } from "node:fs/promises";
22149
- import { delimiter as delimiter2, resolve as resolve18 } from "node:path";
22799
+ import { delimiter as delimiter2, resolve as resolve19 } from "node:path";
22150
22800
  async function installCornerGitHubWrappers(input) {
22151
- const bin = resolve18(input.root, "beeline-github-bin");
22801
+ const bin = resolve19(input.root, "beeline-github-bin");
22152
22802
  await mkdir9(bin, { recursive: true, mode: 448 });
22153
22803
  const common = {
22154
22804
  node: process.execPath,
@@ -22158,13 +22808,13 @@ async function installCornerGitHubWrappers(input) {
22158
22808
  featureBranch: input.featureBranch,
22159
22809
  targetBranch: input.targetBranch
22160
22810
  };
22161
- await writeLauncher(resolve18(bin, "git"), {
22811
+ await writeLauncher(resolve19(bin, "git"), {
22162
22812
  ...common,
22163
22813
  command: input.gitBinary,
22164
22814
  launcher: "git"
22165
22815
  });
22166
22816
  if (input.ghBinary)
22167
- await writeLauncher(resolve18(bin, "gh"), {
22817
+ await writeLauncher(resolve19(bin, "gh"), {
22168
22818
  ...common,
22169
22819
  command: input.ghBinary,
22170
22820
  launcher: "gh"
@@ -22299,25 +22949,25 @@ process.exit(result.status ?? 1);
22299
22949
  }
22300
22950
 
22301
22951
  // apps/body/dist/warm-node-modules.js
22302
- import { createHash as createHash4, randomUUID as randomUUID4 } from "node:crypto";
22952
+ import { createHash as createHash5, randomUUID as randomUUID5 } from "node:crypto";
22303
22953
  import { constants as fsConstants } from "node:fs";
22304
22954
  import { chmod as chmod4, copyFile as copyFile2, link, lstat as lstat2, mkdir as mkdir10, readdir as readdir5, readFile as readFile8, readlink, rename as rename3, rm as rm4, stat as stat2, symlink as symlink2, utimes } from "node:fs/promises";
22305
- import { dirname as dirname7, join as join7, resolve as resolve19 } from "node:path";
22955
+ import { dirname as dirname8, join as join8, resolve as resolve20 } from "node:path";
22306
22956
  var STORE_FORMAT = "v1";
22307
22957
  var STAGING_PREFIX = ".beeline-warm-";
22308
22958
  var STAGING_SWEEP_MS = 24 * 60 * 60 * 1e3;
22309
22959
  var WARM_STORE_MAX_ENTRIES = 3;
22310
22960
  function sharedNpmCacheDir(supervisorRoot) {
22311
- return resolve19(supervisorRoot, "beeline", "npm-cache");
22961
+ return resolve20(supervisorRoot, "beeline", "npm-cache");
22312
22962
  }
22313
22963
  function warmNodeModulesStoreDir(supervisorRoot) {
22314
- return resolve19(supervisorRoot, "beeline", "node-modules");
22964
+ return resolve20(supervisorRoot, "beeline", "node-modules");
22315
22965
  }
22316
22966
  function isPlanRefusal(value) {
22317
22967
  return "failure" in value;
22318
22968
  }
22319
22969
  async function readWarmPlan(worktreePath) {
22320
- const lockfile = await readFile8(resolve19(worktreePath, "package-lock.json")).catch(() => void 0);
22970
+ const lockfile = await readFile8(resolve20(worktreePath, "package-lock.json")).catch(() => void 0);
22321
22971
  if (!lockfile)
22322
22972
  return { failure: "no-lockfile" };
22323
22973
  const packages = parseLockfilePackages(lockfile);
@@ -22332,7 +22982,7 @@ async function readWarmPlan(worktreePath) {
22332
22982
  const unsafe = trees.find((tree) => !isContainedTreePath(tree));
22333
22983
  if (unsafe)
22334
22984
  return { failure: "unsafe-lockfile", detail: unsafe };
22335
- const key = createHash4("sha256").update(`${STORE_FORMAT}\0${process.platform}\0${process.arch}\0${process.versions.modules}\0`).update(lockfile).digest("hex").slice(0, 32);
22985
+ const key = createHash5("sha256").update(`${STORE_FORMAT}\0${process.platform}\0${process.arch}\0${process.versions.modules}\0`).update(lockfile).digest("hex").slice(0, 32);
22336
22986
  return { key, trees };
22337
22987
  }
22338
22988
  function nodeModulesTreePaths(packages) {
@@ -22356,11 +23006,11 @@ async function seedWarmNodeModules(input) {
22356
23006
  return { reason: plan.failure, ...plan.detail ? { detail: plan.detail } : {} };
22357
23007
  }
22358
23008
  for (const tree of plan.trees) {
22359
- if (await pathExists(resolve19(input.worktreePath, tree))) {
23009
+ if (await pathExists(resolve20(input.worktreePath, tree))) {
22360
23010
  return { reason: "present", key: plan.key };
22361
23011
  }
22362
23012
  }
22363
- const entry = resolve19(input.storeRoot, plan.key);
23013
+ const entry = resolve20(input.storeRoot, plan.key);
22364
23014
  if (!await isDirectory(entry))
22365
23015
  return { reason: "cold", key: plan.key };
22366
23016
  const [storeDevice, checkoutDevice] = await Promise.all([
@@ -22370,19 +23020,19 @@ async function seedWarmNodeModules(input) {
22370
23020
  if (storeDevice === void 0 || storeDevice !== checkoutDevice) {
22371
23021
  return { reason: "cross-device", key: plan.key };
22372
23022
  }
22373
- const staging = resolve19(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID4()}`);
23023
+ const staging = resolve20(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID5()}`);
22374
23024
  const placed = [];
22375
23025
  const now2 = (input.now ?? Date.now)();
22376
23026
  try {
22377
23027
  await sweepStaleStaging(input.storeRoot, now2);
22378
23028
  await utimes(entry, now2 / 1e3, now2 / 1e3).catch(() => void 0);
22379
23029
  for (const tree of plan.trees) {
22380
- await cloneTree(resolve19(entry, tree), resolve19(staging, tree), seedFile);
23030
+ await cloneTree(resolve20(entry, tree), resolve20(staging, tree), seedFile);
22381
23031
  }
22382
23032
  for (const tree of plan.trees) {
22383
- const target = resolve19(input.worktreePath, tree);
22384
- await mkdir10(dirname7(target), { recursive: true });
22385
- await rename3(resolve19(staging, tree), target);
23033
+ const target = resolve20(input.worktreePath, tree);
23034
+ await mkdir10(dirname8(target), { recursive: true });
23035
+ await rename3(resolve20(staging, tree), target);
22386
23036
  placed.push(target);
22387
23037
  }
22388
23038
  return { reason: "seeded", key: plan.key };
@@ -22400,11 +23050,11 @@ async function harvestWarmNodeModules(input) {
22400
23050
  if (isPlanRefusal(plan)) {
22401
23051
  return { reason: plan.failure, ...plan.detail ? { detail: plan.detail } : {} };
22402
23052
  }
22403
- const entry = resolve19(input.storeRoot, plan.key);
23053
+ const entry = resolve20(input.storeRoot, plan.key);
22404
23054
  if (await pathExists(entry))
22405
23055
  return { reason: "already-warm", key: plan.key };
22406
23056
  for (const tree of plan.trees) {
22407
- if (!await isDirectory(resolve19(input.worktreePath, tree))) {
23057
+ if (!await isDirectory(resolve20(input.worktreePath, tree))) {
22408
23058
  return { reason: "no-node-modules", key: plan.key, detail: tree };
22409
23059
  }
22410
23060
  }
@@ -22416,12 +23066,12 @@ async function harvestWarmNodeModules(input) {
22416
23066
  detail: `${missing.length} absent, e.g. ${missing.slice(0, 3).join(", ")}`
22417
23067
  };
22418
23068
  }
22419
- const staging = resolve19(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID4()}`);
23069
+ const staging = resolve20(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID5()}`);
22420
23070
  try {
22421
23071
  await mkdir10(input.storeRoot, { recursive: true, mode: 493 });
22422
23072
  await sweepStaleStaging(input.storeRoot, (input.now ?? Date.now)());
22423
23073
  for (const tree of plan.trees) {
22424
- await cloneTree(resolve19(input.worktreePath, tree), resolve19(staging, tree), harvestFile);
23074
+ await cloneTree(resolve20(input.worktreePath, tree), resolve20(staging, tree), harvestFile);
22425
23075
  }
22426
23076
  await input.onCopied?.();
22427
23077
  if (!await stagedTreeIsPublishable(input.worktreePath, staging, plan.key)) {
@@ -22442,18 +23092,18 @@ async function stagedTreeIsPublishable(worktreePath, staging, key) {
22442
23092
  const settled = await readWarmPlan(worktreePath);
22443
23093
  if (isPlanRefusal(settled) || settled.key !== key)
22444
23094
  return false;
22445
- const hidden = join7("node_modules", ".package-lock.json");
23095
+ const hidden = join8("node_modules", ".package-lock.json");
22446
23096
  const [copied, current] = await Promise.all([
22447
- readFile8(resolve19(staging, hidden)).catch(() => void 0),
22448
- readFile8(resolve19(worktreePath, hidden)).catch(() => void 0)
23097
+ readFile8(resolve20(staging, hidden)).catch(() => void 0),
23098
+ readFile8(resolve20(worktreePath, hidden)).catch(() => void 0)
22449
23099
  ]);
22450
23100
  if (!copied || !current || !copied.equals(current))
22451
23101
  return false;
22452
23102
  return (await missingInstalledPackages(worktreePath, staging)).length === 0;
22453
23103
  }
22454
23104
  async function missingInstalledPackages(worktreePath, treeRoot = worktreePath) {
22455
- const wanted = parseLockfilePackages(await readFile8(resolve19(worktreePath, "package-lock.json")).catch(() => void 0));
22456
- const installed = parseLockfilePackages(await readFile8(resolve19(treeRoot, "node_modules", ".package-lock.json")).catch(() => void 0));
23105
+ const wanted = parseLockfilePackages(await readFile8(resolve20(worktreePath, "package-lock.json")).catch(() => void 0));
23106
+ const installed = parseLockfilePackages(await readFile8(resolve20(treeRoot, "node_modules", ".package-lock.json")).catch(() => void 0));
22457
23107
  if (!wanted)
22458
23108
  return ["package-lock.json is unreadable"];
22459
23109
  if (!installed)
@@ -22473,14 +23123,14 @@ async function missingInstalledPackages(worktreePath, treeRoot = worktreePath) {
22473
23123
  required.push(path);
22474
23124
  }
22475
23125
  await mapWithLimit(required, INTEGRITY_READ_CONCURRENCY, async (path) => {
22476
- if (!(path in installed) || !await isInstalledPackage(resolve19(treeRoot, path))) {
23126
+ if (!(path in installed) || !await isInstalledPackage(resolve20(treeRoot, path))) {
22477
23127
  missing.push(path);
22478
23128
  }
22479
23129
  });
22480
23130
  return missing.sort();
22481
23131
  }
22482
23132
  async function isInstalledPackage(path) {
22483
- return stat2(join7(path, "package.json")).then((info) => info.isFile(), () => false);
23133
+ return stat2(join8(path, "package.json")).then((info) => info.isFile(), () => false);
22484
23134
  }
22485
23135
  var INTEGRITY_READ_CONCURRENCY = 64;
22486
23136
  async function mapWithLimit(values, limit, visit) {
@@ -22514,8 +23164,8 @@ function isContainedTreePath(value) {
22514
23164
  async function cloneTree(source, target, file, topLevel = true) {
22515
23165
  await mkdir10(target, { recursive: true, mode: 493 });
22516
23166
  for (const entry of await readdir5(source, { withFileTypes: true })) {
22517
- const from = join7(source, entry.name);
22518
- const to = join7(target, entry.name);
23167
+ const from = join8(source, entry.name);
23168
+ const to = join8(target, entry.name);
22519
23169
  if (entry.isSymbolicLink()) {
22520
23170
  await symlink2(await readlink(from), to);
22521
23171
  continue;
@@ -22545,13 +23195,13 @@ async function pruneWarmStore(storeRoot, keep) {
22545
23195
  const names = (await readdir5(storeRoot).catch(() => [])).filter((name) => !name.startsWith(STAGING_PREFIX));
22546
23196
  const entries = [];
22547
23197
  for (const name of names) {
22548
- const info = await lstat2(join7(storeRoot, name)).catch(() => void 0);
23198
+ const info = await lstat2(join8(storeRoot, name)).catch(() => void 0);
22549
23199
  if (info?.isDirectory())
22550
23200
  entries.push({ name, usedAt: info.mtimeMs });
22551
23201
  }
22552
23202
  const dropped = entries.sort((a2, b) => b.usedAt - a2.usedAt || a2.name.localeCompare(b.name)).slice(keep);
22553
23203
  for (const entry of dropped) {
22554
- await rm4(join7(storeRoot, entry.name), { recursive: true, force: true }).catch(() => void 0);
23204
+ await rm4(join8(storeRoot, entry.name), { recursive: true, force: true }).catch(() => void 0);
22555
23205
  }
22556
23206
  return dropped.map((entry) => entry.name);
22557
23207
  }
@@ -22560,7 +23210,7 @@ async function sweepStaleStaging(storeRoot, now2) {
22560
23210
  for (const name of entries) {
22561
23211
  if (!name.startsWith(STAGING_PREFIX))
22562
23212
  continue;
22563
- const path = join7(storeRoot, name);
23213
+ const path = join8(storeRoot, name);
22564
23214
  const info = await lstat2(path).catch(() => void 0);
22565
23215
  if (!info || now2 - info.mtimeMs < STAGING_SWEEP_MS)
22566
23216
  continue;
@@ -22582,8 +23232,8 @@ function describe3(error) {
22582
23232
 
22583
23233
  // apps/body/dist/monolith-room-turn.js
22584
23234
  import { mkdir as mkdir11 } from "node:fs/promises";
22585
- import { homedir as homedir6 } from "node:os";
22586
- import { join as join8 } from "node:path";
23235
+ import { homedir as homedir7 } from "node:os";
23236
+ import { join as join9 } from "node:path";
22587
23237
 
22588
23238
  // packages/api-contract/dist/scheduled-prompts.js
22589
23239
  var SCHEDULE_SCHEDULER_NAME = "Beeline Scheduler";
@@ -22615,9 +23265,23 @@ function inboxItemPromptBody(item) {
22615
23265
  return isScheduledPrompt(item) ? item.systemEvent?.consequence ?? item.body : item.body;
22616
23266
  }
22617
23267
  function pendingGrantToolCall(call) {
22618
- if (!/(?:^|[._:/-])request_grant$/i.test(call.title ?? ""))
23268
+ if (!/(?:^|[._:/-])(?:request_grant|offer_connector)$/i.test(call.title ?? ""))
22619
23269
  return false;
22620
- return /pending, card posted/i.test(typeof call.content === "string" ? call.content : JSON.stringify(call.content ?? ""));
23270
+ return /(?:pending|already offered), card (?:posted|still open)/i.test(typeof call.content === "string" ? call.content : JSON.stringify(call.content ?? ""));
23271
+ }
23272
+ function resumePrompt(item) {
23273
+ if (item.systemEvent?.kind === "connector-offer-decided") {
23274
+ return [
23275
+ `This is the answer to your connector offer: ${item.body}.`,
23276
+ "Your paused work resumes now. The tool is being installed on your machine; its sign-in and status reach the person through the tool\u2019s own status message, not through you.",
23277
+ 'Acknowledge in one short line (for example "Adding Trusty Squire now.") and continue the work that needed it, or say plainly what still has to happen before you can.'
23278
+ ].join(" ");
23279
+ }
23280
+ return [
23281
+ "This is the answer to your grant request; your paused work resumes now.",
23282
+ "If it was approved and it is a command grant, run it with run_granted_command and the exact argv.",
23283
+ "If it was declined, try another way or say plainly what you cannot do."
23284
+ ].join(" ");
22621
23285
  }
22622
23286
  function roomMentionDirectory(roster, selfId) {
22623
23287
  const rows = [];
@@ -22719,7 +23383,7 @@ var MonolithRoomTurnLoop = class {
22719
23383
  ...this.options.config.bwrapPath ? { bwrapPath: this.options.config.bwrapPath } : {},
22720
23384
  ...this.sessionScratchDir ? { scratch: this.sessionScratchDir } : {},
22721
23385
  ...this.sessionStateDirs.length ? { harnessStateDirs: this.sessionStateDirs } : {},
22722
- maskPaths: credentialMaskPaths(this.options.config.sandboxMaskPaths, this.options.config.operatorHome ?? homedir6())
23386
+ maskPaths: credentialMaskPaths(this.options.config.sandboxMaskPaths, this.options.config.operatorHome ?? homedir7())
22723
23387
  };
22724
23388
  }
22725
23389
  /**
@@ -22786,7 +23450,7 @@ var MonolithRoomTurnLoop = class {
22786
23450
  const cached = this.deliveredAttachments.get(item.id);
22787
23451
  if (cached)
22788
23452
  return cached;
22789
- const delivered = await deliverAttachments(item.attachments, join8(this.attachmentDir, item.id.replace(/[^\w-]/g, "_")), this.options.fetchImpl);
23453
+ const delivered = await deliverAttachments(item.attachments, join9(this.attachmentDir, item.id.replace(/[^\w-]/g, "_")), this.options.fetchImpl);
22790
23454
  this.deliveredAttachments.set(item.id, withoutImageData(delivered));
22791
23455
  return delivered;
22792
23456
  }
@@ -22873,6 +23537,10 @@ var MonolithRoomTurnLoop = class {
22873
23537
  })
22874
23538
  }) : {};
22875
23539
  const command = this.options.config.agentCommand ?? this.options.config.agentBinary;
23540
+ const harnessLabel = harnessIdentityLabel({
23541
+ kind: this.options.config.agentKind,
23542
+ command
23543
+ });
22876
23544
  const agentEnv = { ...this.options.config.agentEnv, ...homeOverlay };
22877
23545
  this.agentEnv = agentEnv;
22878
23546
  const agentArgs = agentArgsWithModelSelection({
@@ -22880,12 +23548,12 @@ var MonolithRoomTurnLoop = class {
22880
23548
  command,
22881
23549
  args: this.options.config.agentArgs ?? []
22882
23550
  }, selection);
22883
- const operatorHome = this.options.config.operatorHome ?? homedir6();
23551
+ const operatorHome = this.options.config.operatorHome ?? homedir7();
22884
23552
  const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
22885
- this.attachmentDir = tmpDir ? join8(tmpDir, "beeline-attachments") : void 0;
23553
+ this.attachmentDir = tmpDir ? join9(tmpDir, "beeline-attachments") : void 0;
22886
23554
  this.sessionScratchDir = tmpDir;
22887
23555
  this.sessionStateDirs = stateDirs;
22888
- const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
23556
+ const homeStateDirs = harnessHomeStateDirs(harnessLabel, agentEnv.HOME ?? operatorHome);
22889
23557
  await Promise.all(homeStateDirs.map((dir) => mkdir11(dir, { recursive: true })));
22890
23558
  const attachScratchRoot = this.options.config.agentHomeRoot ?? tmpDir;
22891
23559
  if (attachScratchRoot)
@@ -22921,7 +23589,7 @@ var MonolithRoomTurnLoop = class {
22921
23589
  })
22922
23590
  ];
22923
23591
  await installPiMcpBridge({
22924
- agentCommand: command,
23592
+ agentCommand: harnessLabel,
22925
23593
  piHome: agentEnv.PI_CODING_AGENT_DIR,
22926
23594
  servers
22927
23595
  });
@@ -22931,7 +23599,7 @@ var MonolithRoomTurnLoop = class {
22931
23599
  agentArgs: spawnCommand.args,
22932
23600
  agentEnv,
22933
23601
  agentCwd: this.options.cwd,
22934
- agentLabel: command,
23602
+ agentLabel: harnessLabel,
22935
23603
  // `bwrapPath` is set only when `detectBwrapSandbox` passed its self-test
22936
23604
  // (`config.ts`), which is exactly when `wrapAgentCommand` above wraps.
22937
23605
  osSandbox: Boolean(this.options.config.bwrapPath),
@@ -23007,7 +23675,10 @@ var MonolithRoomTurnLoop = class {
23007
23675
  if (durableReplyText(result.agentText))
23008
23676
  return void 0;
23009
23677
  return explainEmptyAgentTurn({
23010
- agentLabel: this.options.config.agentCommand ?? this.options.config.agentBinary,
23678
+ agentLabel: harnessIdentityLabel({
23679
+ kind: this.options.config.agentKind,
23680
+ command: this.options.config.agentCommand ?? this.options.config.agentBinary
23681
+ }),
23011
23682
  agentEnv: this.agentEnv,
23012
23683
  sessionId: this.sessionId,
23013
23684
  result
@@ -23129,11 +23800,7 @@ var MonolithRoomTurnLoop = class {
23129
23800
  const buildPrompt = () => [
23130
23801
  this.turnInstructionPrefix,
23131
23802
  WarmTranscript.render(this.warmTranscript.select(this.sessionId, transcriptRows), "Room conversation so far:", "New in the Room since your last turn (the earlier conversation is already in this session):"),
23132
- grantDecision ? [
23133
- "This is the answer to your grant request; your paused work resumes now.",
23134
- "If it was approved and it is a command grant, run it with run_granted_command and the exact argv.",
23135
- "If it was declined, try another way or say plainly what you cannot do."
23136
- ].join(" ") : "",
23803
+ grantDecision ? resumePrompt(item) : "",
23137
23804
  roomMentionDirectory(roster, this.agent.publicKey),
23138
23805
  (corners.corners ?? []).some((corner) => !corner.archived) ? `Current corners you belong to (use the exact cornerId with steer_corner):
23139
23806
  ${JSON.stringify((corners.corners ?? []).filter((corner) => !corner.archived))}` : "",
@@ -23219,7 +23886,7 @@ ${JSON.stringify((corners.corners ?? []).filter((corner) => !corner.archived))}`
23219
23886
  this.pausedOnGrantRequestId = item.id;
23220
23887
  console.log(`[thin-core] monolith Room ${this.options.roomId} turn ${item.id} paused on a grant card`);
23221
23888
  } else if (resumedRequestId) {
23222
- console.log(`[thin-core] monolith Room ${this.options.roomId} turn ${resumedRequestId} resumed by grant decision ${item.id}`);
23889
+ console.log(`[thin-core] monolith Room ${this.options.roomId} turn ${resumedRequestId} resumed by card decision ${item.id}`);
23223
23890
  }
23224
23891
  if (openCornerCall) {
23225
23892
  console.log(`[thin-core] monolith Room ${this.options.roomId} tool call: ${openCornerCall.title} (${openCornerCall.status ?? "no status"})`);
@@ -23323,7 +23990,7 @@ ${JSON.stringify((corners.corners ?? []).filter((corner) => !corner.archived))}`
23323
23990
  const item = {
23324
23991
  ...command.source,
23325
23992
  id: command.turnRequestId,
23326
- body: command.action === "resume" ? `Resume the paused turn. The server supplied this grant decision: ${command.source.body}` : command.source.body
23993
+ body: command.action === "resume" ? `Resume the paused turn. The server supplied this answer: ${command.source.body}` : command.source.body
23327
23994
  };
23328
23995
  this.startPrompt(item);
23329
23996
  await this.activeTurn?.promise;
@@ -23502,7 +24169,7 @@ function toolArguments(call) {
23502
24169
  return input ? { input: clampBytes(redactToolDetail(input), TOOL_ARGUMENT_MAX_BYTES) } : {};
23503
24170
  }
23504
24171
  function toolCallKey(call, index) {
23505
- return call.id ? `id-${createHash5("sha256").update(call.id).digest("hex")}` : `tool-${index}`;
24172
+ return call.id ? `id-${createHash6("sha256").update(call.id).digest("hex")}` : `tool-${index}`;
23506
24173
  }
23507
24174
  function toolCallSettled(call) {
23508
24175
  if (call.resultReceived)
@@ -23752,6 +24419,10 @@ var MonolithCornerTurnLoop = class {
23752
24419
  })
23753
24420
  }) : {};
23754
24421
  const command = this.options.config.agentCommand ?? this.options.config.agentBinary;
24422
+ const harnessLabel = harnessIdentityLabel({
24423
+ kind: this.options.config.agentKind,
24424
+ command
24425
+ });
23755
24426
  const repository = this.options.repository;
23756
24427
  let githubEnv = repository ? { GH_TOKEN: repository.githubToken, GITHUB_TOKEN: repository.githubToken } : {};
23757
24428
  if (repository && this.options.config.runtimeConfigPath && this.options.config.agentHomeRoot) {
@@ -23783,11 +24454,11 @@ var MonolithCornerTurnLoop = class {
23783
24454
  command,
23784
24455
  args: this.options.config.agentArgs ?? []
23785
24456
  }, selection);
23786
- const operatorHome = this.options.config.operatorHome ?? homedir7();
24457
+ const operatorHome = this.options.config.operatorHome ?? homedir8();
23787
24458
  const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
23788
- this.attachmentDir = tmpDir ? join9(tmpDir, "beeline-attachments") : void 0;
24459
+ this.attachmentDir = tmpDir ? join10(tmpDir, "beeline-attachments") : void 0;
23789
24460
  this.sessionScratchDir = tmpDir;
23790
- const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
24461
+ const homeStateDirs = harnessHomeStateDirs(harnessLabel, agentEnv.HOME ?? operatorHome);
23791
24462
  await Promise.all(homeStateDirs.map((dir) => mkdir12(dir, { recursive: true })));
23792
24463
  const attachScratchRoot = this.options.config.agentHomeRoot ?? tmpDir;
23793
24464
  if (attachScratchRoot)
@@ -23820,7 +24491,7 @@ var MonolithCornerTurnLoop = class {
23820
24491
  agentArgs: spawnCommand.args,
23821
24492
  agentEnv,
23822
24493
  agentCwd: this.options.worktreePath,
23823
- agentLabel: command,
24494
+ agentLabel: harnessLabel,
23824
24495
  autoApprovePermissions: true,
23825
24496
  permissionHandler: () => Promise.resolve("allow")
23826
24497
  };
@@ -23860,7 +24531,7 @@ var MonolithCornerTurnLoop = class {
23860
24531
  })
23861
24532
  ];
23862
24533
  await installPiMcpBridge({
23863
- agentCommand: command,
24534
+ agentCommand: harnessLabel,
23864
24535
  piHome: agentEnv.PI_CODING_AGENT_DIR,
23865
24536
  servers
23866
24537
  });
@@ -23887,7 +24558,7 @@ var MonolithCornerTurnLoop = class {
23887
24558
  selfReviewerInstruction ?? cornerMergeInstruction(configuration.yoloMode, configuration.reviewerHandle)
23888
24559
  ],
23889
24560
  "Do not tag the user when a corner turn finishes: the server posts the merge summary card and its push already cover completion. Tag a human only mid-turn, and only when you need a decision or input.",
23890
- "Never restate server check or merge notes. On a checks turn, say nothing unless you merge or push a fix, then use one short line. Never merge while approvalPending is true. When approval is pending, wait for the reviewer to tag you. Never merge another pull request. Never create a schedule to poll pr_checks_status or the merge gate: the green transition wakes the reviewer and the reviewer's approval tag wakes you, and tagging any agent other than the configured reviewer cannot clear the gate. If a schedule wakes you in this corner anyway, follow the same rule as a checks turn: say nothing unless you merge, push a fix, or report a genuinely new blocker."
24561
+ "Never restate server check or merge notes. On a checks turn, say nothing unless you merge or push a fix, then use one short line. When asked whether the reviewer was woken, call pr_checks_status and report reviewerWake; do not invent a cause. Never merge while approvalPending is true. When approval is pending, wait for the reviewer to tag you. Never merge another pull request. Never create a schedule to poll pr_checks_status or the merge gate: the green transition wakes the reviewer and the reviewer's approval tag wakes you, and tagging any agent other than the configured reviewer cannot clear the gate. If a schedule wakes you in this corner anyway, follow the same rule as a checks turn: say nothing unless you merge, push a fix, or report a genuinely new blocker."
23891
24562
  ] : [
23892
24563
  "This is a chat-only corner with no repository or GitHub workflow.",
23893
24564
  "Work in this corner's writable workspace. Use write_scratch_file or ordinary tools to create files, then post_artifact with the path to send them back to the corner.",
@@ -23937,7 +24608,10 @@ var MonolithCornerTurnLoop = class {
23937
24608
  if (durableReplyText(result.agentText))
23938
24609
  return void 0;
23939
24610
  return explainEmptyAgentTurn({
23940
- agentLabel: this.options.config.agentCommand ?? this.options.config.agentBinary,
24611
+ agentLabel: harnessIdentityLabel({
24612
+ kind: this.options.config.agentKind,
24613
+ command: this.options.config.agentCommand ?? this.options.config.agentBinary
24614
+ }),
23941
24615
  agentEnv: this.agentEnv,
23942
24616
  sessionId: this.sessionId,
23943
24617
  result
@@ -24006,7 +24680,7 @@ var MonolithCornerTurnLoop = class {
24006
24680
  const [conversation, roster, delivered] = await trace.measure("context-fetch", () => Promise.all([
24007
24681
  api.execute("getRoomConversation", { roomId: cornerId, limit: 200 }),
24008
24682
  this.roster(),
24009
- this.attachmentDir && attachments.length ? deliverAttachments(attachments, join9(this.attachmentDir, requestId.replace(/[^\w-]/g, "_")), this.options.fetchImpl) : Promise.resolve([])
24683
+ this.attachmentDir && attachments.length ? deliverAttachments(attachments, join10(this.attachmentDir, requestId.replace(/[^\w-]/g, "_")), this.options.fetchImpl) : Promise.resolve([])
24010
24684
  ]));
24011
24685
  const names = new Map(roster.members.map((member) => [member.identityId, member.name]));
24012
24686
  const requestedBy = requester && !requester.name && names.get(requester.pubkey) ? { ...requester, name: names.get(requester.pubkey) } : requester;
@@ -24773,13 +25447,13 @@ function shouldPostInitialCornerWorkingState(restore, isOpener = true) {
24773
25447
  }
24774
25448
  async function materializeCornerWorktree(input) {
24775
25449
  const remote = roomCheckoutRemote(input.remote);
24776
- const repositoryHash = createHash6("sha256").update(remote).digest("hex").slice(0, 24);
24777
- const gitCommonDir = resolve20(input.supervisorRoot, "beeline", "repositories", `${repositoryHash}.git`);
24778
- const path = resolve20(input.supervisorRoot, "beeline", "corners", input.cornerId);
24779
- await mkdir13(dirname8(gitCommonDir), { recursive: true, mode: 448 });
24780
- await mkdir13(dirname8(path), { recursive: true, mode: 448 });
25450
+ const repositoryHash = createHash7("sha256").update(remote).digest("hex").slice(0, 24);
25451
+ const gitCommonDir = resolve21(input.supervisorRoot, "beeline", "repositories", `${repositoryHash}.git`);
25452
+ const path = resolve21(input.supervisorRoot, "beeline", "corners", input.cornerId);
25453
+ await mkdir13(dirname9(gitCommonDir), { recursive: true, mode: 448 });
25454
+ await mkdir13(dirname9(path), { recursive: true, mode: 448 });
24781
25455
  const authEnv = githubGitEnv(input.token);
24782
- if (!existsSync4(resolve20(gitCommonDir, "HEAD"))) {
25456
+ if (!existsSync5(resolve21(gitCommonDir, "HEAD"))) {
24783
25457
  await execFileAsync4("git", ["clone", "--bare", remote, gitCommonDir], {
24784
25458
  env: authEnv,
24785
25459
  maxBuffer: 4 * 1024 * 1024
@@ -24798,7 +25472,7 @@ async function materializeCornerWorktree(input) {
24798
25472
  "origin",
24799
25473
  `+refs/heads/${input.featureBranch}:refs/remotes/origin/${input.featureBranch}`
24800
25474
  ], { env: authEnv, maxBuffer: 4 * 1024 * 1024 }).then(() => true, () => false);
24801
- if (!existsSync4(resolve20(path, ".git"))) {
25475
+ if (!existsSync5(resolve21(path, ".git"))) {
24802
25476
  await rm5(path, { recursive: true, force: true });
24803
25477
  await execFileAsync4("git", [
24804
25478
  `--git-dir=${gitCommonDir}`,
@@ -24849,7 +25523,7 @@ async function materializeCornerWorktree(input) {
24849
25523
  `${input.committer.publicKey.slice(0, 16)}@users.noreply.github.com`
24850
25524
  ]);
24851
25525
  const top = await execFileAsync4("git", ["-C", path, "rev-parse", "--show-toplevel"]);
24852
- if (resolve20(top.stdout.trim()) !== resolve20(path)) {
25526
+ if (resolve21(top.stdout.trim()) !== resolve21(path)) {
24853
25527
  throw new Error(`corner worktree escaped its isolated root: ${top.stdout.trim()}`);
24854
25528
  }
24855
25529
  return { path, gitCommonDir };
@@ -24870,7 +25544,7 @@ async function mapWithConcurrency(values, limit, visit) {
24870
25544
  async function removeCornerWorktreeAndBranches(worktree) {
24871
25545
  const localRef = `refs/heads/${worktree.branch}`;
24872
25546
  const remoteRef = `refs/heads/${worktree.branch}`;
24873
- const worktreeExists = existsSync4(worktree.path);
25547
+ const worktreeExists = existsSync5(worktree.path);
24874
25548
  const localExists = await gitRefExists(worktree.gitCommonDir, localRef);
24875
25549
  if (worktreeExists) {
24876
25550
  const checkedOut = await execFileAsync4("git", [
@@ -24915,8 +25589,8 @@ async function removeCornerWorktreeAndBranches(worktree) {
24915
25589
  }
24916
25590
  var execFileAsync4 = promisify4(execFile6);
24917
25591
  async function removeCornerScratchWorkspace(input) {
24918
- const expected = resolve20(input.roomRoot, "scratch");
24919
- if (resolve20(input.scratchPath) !== expected) {
25592
+ const expected = resolve21(input.roomRoot, "scratch");
25593
+ if (resolve21(input.scratchPath) !== expected) {
24920
25594
  throw new Error(`refusing to remove scratch outside corner ${input.cornerId}`);
24921
25595
  }
24922
25596
  await rm5(expected, { recursive: true, force: true });
@@ -25130,14 +25804,14 @@ var RoomRuntimeCoordinator = class {
25130
25804
  return this.runtime.rooms.find((room) => room.channelId === roomId);
25131
25805
  }
25132
25806
  roomRoot(roomId) {
25133
- return this.roomRecord(roomId)?.root ?? resolve20(dirname8(this.configPath), "rooms", roomId);
25807
+ return this.roomRecord(roomId)?.root ?? resolve21(dirname9(this.configPath), "rooms", roomId);
25134
25808
  }
25135
25809
  roomAgentHomeRoot(workspaceRoot, required = false) {
25136
25810
  const flag = process.env.BUZZY_BODY_ROOM_HOME;
25137
25811
  if (!required && flag === "0")
25138
25812
  return void 0;
25139
- const home = resolve20(workspaceRoot, "agent-home");
25140
- if (!required && flag !== "1" && !existsSync4(home) && existsSync4(workspaceRoot))
25813
+ const home = resolve21(workspaceRoot, "agent-home");
25814
+ if (!required && flag !== "1" && !existsSync5(home) && existsSync5(workspaceRoot))
25141
25815
  return void 0;
25142
25816
  try {
25143
25817
  mkdirSync(home, { recursive: true, mode: 448 });
@@ -25152,10 +25826,10 @@ var RoomRuntimeCoordinator = class {
25152
25826
  return {
25153
25827
  ...this.baseConfig,
25154
25828
  workspaceRoot,
25155
- agentPrivateRoot: resolve20(workspaceRoot, "agent-private"),
25156
- agentMemoryRoot: resolve20(dirname8(this.configPath), "memory"),
25157
- openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname8(this.configPath)),
25158
- turnTraceDir: turnTraceDirectory(dirname8(this.configPath)),
25829
+ agentPrivateRoot: resolve21(workspaceRoot, "agent-private"),
25830
+ agentMemoryRoot: resolve21(dirname9(this.configPath), "memory"),
25831
+ openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname9(this.configPath)),
25832
+ turnTraceDir: turnTraceDirectory(dirname9(this.configPath)),
25159
25833
  ...agentHomeRoot ? { agentHomeRoot } : {}
25160
25834
  };
25161
25835
  }
@@ -25221,12 +25895,12 @@ var RoomRuntimeCoordinator = class {
25221
25895
  return this.roomRoot(roomId);
25222
25896
  const remote = roomCheckoutRemote(repository.remote);
25223
25897
  const targetBranch = repository.targetBranch || "main";
25224
- const checkoutId = createHash6("sha256").update(`${remote}\0${targetBranch}`).digest("hex").slice(0, 24);
25225
- const path = resolve20(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
25226
- await mkdir13(dirname8(path), { recursive: true, mode: 448 });
25898
+ const checkoutId = createHash7("sha256").update(`${remote}\0${targetBranch}`).digest("hex").slice(0, 24);
25899
+ const path = resolve21(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
25900
+ await mkdir13(dirname9(path), { recursive: true, mode: 448 });
25227
25901
  const token = remote.startsWith("https://github.com/") ? await this.options.daemonApi.execute("getRoomGitHubToken", { roomId }) : void 0;
25228
25902
  const env = token ? githubGitEnv(token.token) : process.env;
25229
- if (!existsSync4(resolve20(path, ".git"))) {
25903
+ if (!existsSync5(resolve21(path, ".git"))) {
25230
25904
  await execFileAsync4("git", ["clone", "--no-checkout", remote, path], {
25231
25905
  env,
25232
25906
  maxBuffer: 4 * 1024 * 1024
@@ -25279,7 +25953,7 @@ var RoomRuntimeCoordinator = class {
25279
25953
  featureBranch,
25280
25954
  token: granted.token
25281
25955
  }) : void 0;
25282
- const workspacePath = worktree?.path ?? resolve20(this.roomRoot(corner.cornerId), "scratch");
25956
+ const workspacePath = worktree?.path ?? resolve21(this.roomRoot(corner.cornerId), "scratch");
25283
25957
  if (!worktree)
25284
25958
  await mkdir13(workspacePath, { recursive: true, mode: 448 });
25285
25959
  const isOpener = !corner.openedBy || corner.openedBy === this.agent.publicKey;
@@ -25668,8 +26342,8 @@ var ThinDaemonCore = class {
25668
26342
  // apps/body/dist/systemd.js
25669
26343
  import { execFile as execFile7 } from "node:child_process";
25670
26344
  import { mkdir as mkdir14, readFile as readFile9, writeFile as writeFile9 } from "node:fs/promises";
25671
- import { homedir as homedir8 } from "node:os";
25672
- import { dirname as dirname9, resolve as resolve21 } from "node:path";
26345
+ import { homedir as homedir9 } from "node:os";
26346
+ import { dirname as dirname10, resolve as resolve22 } from "node:path";
25673
26347
  import { setTimeout as sleep } from "node:timers/promises";
25674
26348
  import { promisify as promisify5 } from "node:util";
25675
26349
  var execFileAsync5 = promisify5(execFile7);
@@ -25710,10 +26384,10 @@ WantedBy=default.target
25710
26384
  `;
25711
26385
  }
25712
26386
  function isCanonicalInstalledLauncher(env = process.env, invocationPath = process.argv[1]) {
25713
- const home = env.HOME?.trim() || homedir8();
25714
- const expectedLibDir = resolve21(home, ".local", "lib", "beeline");
26387
+ const home = env.HOME?.trim() || homedir9();
26388
+ const expectedLibDir = resolve22(home, ".local", "lib", "beeline");
25715
26389
  const expectedPrefix = `${expectedLibDir}/`;
25716
- return resolve21(env.BEELINE_LIB_DIR?.trim() || "/") === expectedLibDir && Boolean(invocationPath) && resolve21(invocationPath).startsWith(expectedPrefix);
26390
+ return resolve22(env.BEELINE_LIB_DIR?.trim() || "/") === expectedLibDir && Boolean(invocationPath) && resolve22(invocationPath).startsWith(expectedPrefix);
25717
26391
  }
25718
26392
  function assertCanonicalInstalledLauncher(env, invocationPath) {
25719
26393
  if (isCanonicalInstalledLauncher(env, invocationPath))
@@ -25721,8 +26395,8 @@ function assertCanonicalInstalledLauncher(env, invocationPath) {
25721
26395
  throw new Error("refusing to modify the shared Beeline systemd unit outside the canonical ~/.local/bin/beeline launcher");
25722
26396
  }
25723
26397
  function systemdUserUnitPath(env = process.env) {
25724
- const configRoot = env.XDG_CONFIG_HOME?.trim() || resolve21(homedir8(), ".config");
25725
- return resolve21(configRoot, "systemd", "user", SYSTEMD_UNIT_NAME);
26398
+ const configRoot = env.XDG_CONFIG_HOME?.trim() || resolve22(homedir9(), ".config");
26399
+ return resolve22(configRoot, "systemd", "user", SYSTEMD_UNIT_NAME);
25726
26400
  }
25727
26401
  var runSystemctl = async (args) => {
25728
26402
  const result = await execFileAsync5("systemctl", ["--user", ...args], {
@@ -25740,7 +26414,7 @@ async function installAgentService(publicKey, options = {}) {
25740
26414
  const content = agentServiceUnit();
25741
26415
  const existing = await readFile9(path, "utf8").catch(() => "");
25742
26416
  if (existing !== content) {
25743
- await mkdir14(dirname9(path), { recursive: true, mode: 448 });
26417
+ await mkdir14(dirname10(path), { recursive: true, mode: 448 });
25744
26418
  await writeFile9(path, content, { mode: 384 });
25745
26419
  }
25746
26420
  const run2 = options.run ?? runSystemctl;
@@ -25821,7 +26495,7 @@ async function retireRemovedAgent(runtime, options = {}) {
25821
26495
  }
25822
26496
 
25823
26497
  // apps/body/dist/start-command.js
25824
- import { dirname as dirname10 } from "node:path";
26498
+ import { dirname as dirname11 } from "node:path";
25825
26499
  var import_picocolors = __toESM(require_picocolors(), 1);
25826
26500
  var DEFAULT_RESTART_DRAIN_TIMEOUT_MS = 30 * 6e4;
25827
26501
  var RESTART_WAIT_REPORT_INTERVAL_MS = 3e4;
@@ -25896,7 +26570,7 @@ async function runStartCommand(args, interactiveUi) {
25896
26570
  continue;
25897
26571
  }
25898
26572
  const spinnerHandle = spinner();
25899
- spinnerHandle.start(`Starting ${dirname10(path)}\u2026`);
26573
+ spinnerHandle.start(`Starting ${dirname11(path)}\u2026`);
25900
26574
  try {
25901
26575
  await startRuntime(path, spinnerHandle);
25902
26576
  spinnerHandle.stop(import_picocolors.default.green("Started."));
@@ -25911,11 +26585,11 @@ async function runStartCommand(args, interactiveUi) {
25911
26585
  }
25912
26586
 
25913
26587
  // apps/body/dist/connect-command.js
25914
- import { spawn as spawn8 } from "node:child_process";
25915
- import { createHash as createHash8, randomUUID as randomUUID5 } from "node:crypto";
26588
+ import { spawn as spawn9 } from "node:child_process";
26589
+ import { createHash as createHash9, randomUUID as randomUUID6 } from "node:crypto";
25916
26590
  import { chmod as chmod6, mkdir as mkdir16, readFile as readFile11, unlink as unlink2, writeFile as writeFile11 } from "node:fs/promises";
25917
- import { homedir as homedir10, hostname } from "node:os";
25918
- import { dirname as dirname12, resolve as resolve23 } from "node:path";
26591
+ import { homedir as homedir11, hostname as hostname2 } from "node:os";
26592
+ import { dirname as dirname13, resolve as resolve24 } from "node:path";
25919
26593
  import { stdin as stdin3, stdout as stdout4 } from "node:process";
25920
26594
 
25921
26595
  // apps/body/dist/clack-support.js
@@ -25939,50 +26613,6 @@ function unwrapPrompt(value, cancelMessage = "Cancelled.") {
25939
26613
  return value;
25940
26614
  }
25941
26615
 
25942
- // apps/body/dist/cursor-models.js
25943
- import { spawn as spawn5 } from "node:child_process";
25944
- var CURSOR_MODELS_TIMEOUT_MS = 1e4;
25945
- function parseCursorModelsOutput(output) {
25946
- const options = [];
25947
- for (const line of output.split(/\r?\n/)) {
25948
- const match = /^\s*([A-Za-z0-9][A-Za-z0-9._-]*)\s+-\s+(\S.*?)\s*$/.exec(line);
25949
- if (!match)
25950
- continue;
25951
- const id = match[1];
25952
- const name = match[2].replace(/\s*\(current, default\)\s*$/i, "").trim();
25953
- options.push({ id, ...name && name !== id ? { name } : {} });
25954
- }
25955
- if (!options.length)
25956
- return void 0;
25957
- return {
25958
- currentValue: options.some((option) => option.id === "auto") ? "auto" : options[0].id,
25959
- options
25960
- };
25961
- }
25962
- async function enumerateCursorModels(env = process.env) {
25963
- return new Promise((resolve31) => {
25964
- const child = spawn5("cursor-agent", ["models"], {
25965
- env,
25966
- stdio: ["ignore", "pipe", "ignore"]
25967
- });
25968
- let output = "";
25969
- const timer = setTimeout(() => {
25970
- child.kill("SIGKILL");
25971
- }, CURSOR_MODELS_TIMEOUT_MS);
25972
- child.stdout?.on("data", (chunk) => {
25973
- output += chunk.toString();
25974
- });
25975
- child.on("error", () => {
25976
- clearTimeout(timer);
25977
- resolve31(void 0);
25978
- });
25979
- child.on("close", (code) => {
25980
- clearTimeout(timer);
25981
- resolve31(code === 0 ? parseCursorModelsOutput(output) : void 0);
25982
- });
25983
- });
25984
- }
25985
-
25986
26616
  // apps/body/dist/provider-key-check.js
25987
26617
  var PROVIDER_LABELS = {
25988
26618
  openrouter: "OpenRouter",
@@ -26043,7 +26673,7 @@ async function verifyProviderKey(input) {
26043
26673
  }
26044
26674
 
26045
26675
  // apps/body/dist/pair-agent-selection.js
26046
- import { spawn as spawn6 } from "node:child_process";
26676
+ import { spawn as spawn7 } from "node:child_process";
26047
26677
  import { stdin as stdin2, stdout as stdout3 } from "node:process";
26048
26678
  var NO_AGENT_MESSAGE = `No supported ACP-capable coding agent was detected.
26049
26679
  Install one of these supported agents:
@@ -26052,7 +26682,7 @@ Install one of these supported agents:
26052
26682
  goose https://block.github.io/goose/docs/getting-started/installation/
26053
26683
  pi npm install -g @mariozechner/pi-coding-agent pi-acp
26054
26684
  grok curl -fsSL https://x.ai/cli/install.sh | bash
26055
- cursor npm install -g cursor-agent-acp
26685
+ cursor Install Cursor Agent CLI from https://cursor.com/docs/cli
26056
26686
  Then retry, or explicitly use \`--agent reference\` with an LLM key.
26057
26687
  For another ACP server, use \`--agent custom --agent-command "<cmd> [args...]"\`.`;
26058
26688
  async function clackConfirmInstall(message) {
@@ -26072,7 +26702,7 @@ async function clackSelectAgent(candidates) {
26072
26702
  }
26073
26703
  async function installAdapter(install, opts) {
26074
26704
  await new Promise((resolveInstall, rejectInstall) => {
26075
- const child = spawn6(install.command, install.args, {
26705
+ const child = spawn7(install.command, install.args, {
26076
26706
  cwd: opts.cwd,
26077
26707
  env: opts.env ?? process.env,
26078
26708
  stdio: "inherit"
@@ -26583,23 +27213,23 @@ function parseConnectSubscriptions(value) {
26583
27213
  ];
26584
27214
  }
26585
27215
  async function readMachineId(env = process.env) {
26586
- const configDir = resolve23(env.XDG_CONFIG_HOME ?? resolve23(homedir10(), ".config"), "beeline");
26587
- const machineIdPath = resolve23(configDir, "machine-id");
27216
+ const configDir = resolve24(env.XDG_CONFIG_HOME ?? resolve24(homedir11(), ".config"), "beeline");
27217
+ const machineIdPath = resolve24(configDir, "machine-id");
26588
27218
  let machineId;
26589
- let machineName = hostname();
27219
+ let machineName = hostname2();
26590
27220
  try {
26591
27221
  const existing = await readFile11(machineIdPath, "utf8");
26592
27222
  machineId = existing.trim();
26593
27223
  if (!/^[0-9a-f-]{32,}$/.test(machineId))
26594
27224
  throw new Error("invalid persisted machine id");
26595
27225
  } catch {
26596
- machineId = randomUUID5();
27226
+ machineId = randomUUID6();
26597
27227
  try {
26598
27228
  await mkdir16(configDir, { recursive: true, mode: 448 });
26599
27229
  await writeFile11(machineIdPath, `${machineId}
26600
27230
  `, { mode: 384 });
26601
27231
  } catch {
26602
- machineId = createHash8("sha256").update(machineName).digest("hex").slice(0, 36);
27232
+ machineId = createHash9("sha256").update(machineName).digest("hex").slice(0, 36);
26603
27233
  }
26604
27234
  }
26605
27235
  return { machineId, machineName };
@@ -26608,7 +27238,7 @@ function requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl, machine
26608
27238
  const normalizedPairingCode = normalizeAgentPairingCode(pairingCode);
26609
27239
  if (!normalizedPairingCode)
26610
27240
  throw new Error("invalid pairing code");
26611
- const avatarSeed = createHash8("sha256").update(normalizedPairingCode.toUpperCase()).digest("hex").slice(0, 32);
27241
+ const avatarSeed = createHash9("sha256").update(normalizedPairingCode.toUpperCase()).digest("hex").slice(0, 32);
26612
27242
  return jsonRequest(`${baseUrl}/auth/agent/connect`, {
26613
27243
  pairing_code: normalizedPairingCode,
26614
27244
  harness: selection.harness,
@@ -26657,7 +27287,7 @@ async function installCurrentRelease(fetchImpl) {
26657
27287
  });
26658
27288
  await activateRelease(layout, releaseId);
26659
27289
  return {
26660
- binary: resolve23(layout.binDir, "beeline"),
27290
+ binary: resolve24(layout.binDir, "beeline"),
26661
27291
  version: published.version ?? releaseId
26662
27292
  };
26663
27293
  }
@@ -26680,7 +27310,7 @@ function providerEnvironment(selection) {
26680
27310
  };
26681
27311
  }
26682
27312
  async function writePrivateJson(path, value) {
26683
- await mkdir16(dirname12(path), { recursive: true, mode: 448 });
27313
+ await mkdir16(dirname13(path), { recursive: true, mode: 448 });
26684
27314
  await writeFile11(path, `${JSON.stringify(value, null, 2)}
26685
27315
  `, { mode: 384 });
26686
27316
  await chmod6(path, 384);
@@ -26689,8 +27319,8 @@ async function writeProviderEnv(selection, agentPubkey) {
26689
27319
  const values = providerEnvironment(selection);
26690
27320
  if (Object.keys(values).length === 0)
26691
27321
  return void 0;
26692
- const path = resolve23(defaultSupervisorRoot(process.env), "beeline", "connect", `${agentPubkey}.env`);
26693
- await mkdir16(dirname12(path), { recursive: true, mode: 448 });
27322
+ const path = resolve24(defaultSupervisorRoot(process.env), "beeline", "connect", `${agentPubkey}.env`);
27323
+ await mkdir16(dirname13(path), { recursive: true, mode: 448 });
26694
27324
  const contents = Object.entries(values).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join("\n");
26695
27325
  await writeFile11(path, `${contents}
26696
27326
  `, { mode: 384 });
@@ -26699,7 +27329,7 @@ async function writeProviderEnv(selection, agentPubkey) {
26699
27329
  }
26700
27330
  async function runInstalledFinish(binary, grantPath) {
26701
27331
  await new Promise((resolveRun, rejectRun) => {
26702
- const child = spawn8(binary, ["connect-finish", grantPath], {
27332
+ const child = spawn9(binary, ["connect-finish", grantPath], {
26703
27333
  stdio: ["ignore", "pipe", "pipe"]
26704
27334
  });
26705
27335
  let diagnostic = "";
@@ -26756,7 +27386,7 @@ async function runConnectWizard(code, fetchImpl, eventSubscriptions, accessPolic
26756
27386
  await finishConnectedAgentPairing(baseUrl, pairingCode, grant.workspace_joined, eventSubscriptions, fetchImpl);
26757
27387
  const installedRelease = await brassSpinner("Installing the Beeline daemon\u2026", () => installCurrentRelease(fetchImpl), (release) => `Installed Beeline helper ${release.version}`);
26758
27388
  const llmEnvFile = await writeProviderEnv(selection, grant.agent_pubkey);
26759
- const grantPath = resolve23(defaultSupervisorRoot(process.env), "beeline", "connect", `grant-${process.pid}-${Date.now()}.json`);
27389
+ const grantPath = resolve24(defaultSupervisorRoot(process.env), "beeline", "connect", `grant-${process.pid}-${Date.now()}.json`);
26760
27390
  await writePrivateJson(grantPath, {
26761
27391
  agentSecretKey: grant.agent_secret_key,
26762
27392
  bodySecretKey: grant.body_secret_key,
@@ -26841,18 +27471,18 @@ async function runConnectFinishCommand(path) {
26841
27471
  throw new Error("connect-finish may run only from the canonical installed Beeline launcher");
26842
27472
  }
26843
27473
  try {
26844
- const grant = JSON.parse(await readFile11(resolve23(path), "utf8"));
27474
+ const grant = JSON.parse(await readFile11(resolve24(path), "utf8"));
26845
27475
  if (!isDevicePairingGrant(grant))
26846
27476
  throw new Error("device connection grant is invalid");
26847
27477
  const connected = await completeDevicePairing(grant);
26848
- await unlink2(resolve23(path));
27478
+ await unlink2(resolve24(path));
26849
27479
  const providerEnv = grant.llmEnvFile ? await readFile11(grant.llmEnvFile, "utf8").catch(() => "") : "";
26850
27480
  const apiKey = (/^OPENROUTER_API_KEY=(\S+)/m.exec(providerEnv)?.[1] ?? "").replace(/^["']|["']$/g, "");
26851
27481
  const model = openRouterModelId(grant.model, { OPENROUTER_API_KEY: apiKey });
26852
27482
  if (model) {
26853
27483
  const decision2 = await resolveOpenRouterRouting({
26854
27484
  model,
26855
- cacheDir: openRouterRoutingCacheDir(dirname12(connected.configPath)),
27485
+ cacheDir: openRouterRoutingCacheDir(dirname13(connected.configPath)),
26856
27486
  ...apiKey ? { apiKey } : {},
26857
27487
  probeTimeoutMs: 1e4
26858
27488
  });
@@ -26873,22 +27503,22 @@ init_self_update_manifest();
26873
27503
 
26874
27504
  // apps/body/dist/managed-update.js
26875
27505
  init_self_update();
26876
- import { spawn as spawn9 } from "node:child_process";
27506
+ import { spawn as spawn10 } from "node:child_process";
26877
27507
  import { mkdir as mkdir18, rm as rm7, stat as stat3, writeFile as writeFile13 } from "node:fs/promises";
26878
- import { dirname as dirname14, resolve as resolve25 } from "node:path";
27508
+ import { dirname as dirname15, resolve as resolve26 } from "node:path";
26879
27509
 
26880
27510
  // apps/body/dist/update-rollback-alert.js
26881
27511
  import { mkdir as mkdir17, readFile as readFile12, rename as rename5, unlink as unlink3, writeFile as writeFile12 } from "node:fs/promises";
26882
- import { dirname as dirname13, resolve as resolve24 } from "node:path";
27512
+ import { dirname as dirname14, resolve as resolve25 } from "node:path";
26883
27513
  var REPORT_INTERVAL_MS = 60 * 60 * 1e3;
26884
27514
  var lastLogged = /* @__PURE__ */ new Map();
26885
27515
  function updateRollbackAlertPath(runtimeDir) {
26886
- return resolve24(runtimeDir, "update-rollback-alert.json");
27516
+ return resolve25(runtimeDir, "update-rollback-alert.json");
26887
27517
  }
26888
27518
  async function writeAlert(runtimeDir, alert) {
26889
27519
  const path = updateRollbackAlertPath(runtimeDir);
26890
27520
  const staged = `${path}.${process.pid}.tmp`;
26891
- await mkdir17(dirname13(path), { recursive: true });
27521
+ await mkdir17(dirname14(path), { recursive: true });
26892
27522
  await writeFile12(staged, `${JSON.stringify(alert, null, 2)}
26893
27523
  `, { mode: 384 });
26894
27524
  await rename5(staged, path);
@@ -26952,13 +27582,13 @@ var LOCK_STALE_MS = UPDATE_WORKER_DEADLINE_MS + 5 * 6e4;
26952
27582
  var DEFAULT_UPDATE_INITIAL_DELAY_MS = 0;
26953
27583
  async function withInstallLock(layout, work, options = {}) {
26954
27584
  const now2 = options.now ?? Date.now;
26955
- const lock = resolve25(layout.releasesRoot, ".state", "install.lock");
27585
+ const lock = resolve26(layout.releasesRoot, ".state", "install.lock");
26956
27586
  const deadline = now2() + (options.waitMs ?? 1e4);
26957
- await mkdir18(dirname14(lock), { recursive: true });
27587
+ await mkdir18(dirname15(lock), { recursive: true });
26958
27588
  for (; ; ) {
26959
27589
  try {
26960
27590
  await mkdir18(lock);
26961
- await writeFile13(resolve25(lock, "owner"), `${process.pid}
27591
+ await writeFile13(resolve26(lock, "owner"), `${process.pid}
26962
27592
  ${now2()}
26963
27593
  `, "utf8");
26964
27594
  break;
@@ -27081,7 +27711,7 @@ var ManagedUpdateHandoff = class _ManagedUpdateHandoff {
27081
27711
  if (!attempt || attempt.releaseId !== desiredRelease || attempt.status !== "pending") {
27082
27712
  const from = await readInstalledBundleIdentity({
27083
27713
  ...this.#layout,
27084
- libDir: resolve25(this.#layout.releasesRoot, this.#loadedRelease)
27714
+ libDir: resolve26(this.#layout.releasesRoot, this.#loadedRelease)
27085
27715
  }).catch(() => void 0) ?? {};
27086
27716
  const to = await readInstalledBundleIdentity(this.#layout).catch(() => void 0) ?? {};
27087
27717
  const record3 = {
@@ -27287,7 +27917,7 @@ async function runManagedUpdateWorkerProcess() {
27287
27917
  if (!entrypoint)
27288
27918
  throw new Error("cannot resolve the current Beeline entrypoint");
27289
27919
  await new Promise((resolveWorker, rejectWorker) => {
27290
- const child = spawn9(process.execPath, [entrypoint, "managed-update-worker"], {
27920
+ const child = spawn10(process.execPath, [entrypoint, "managed-update-worker"], {
27291
27921
  detached: true,
27292
27922
  env: { ...process.env, BEELINE_INTERNAL_UPDATE_WORKER: "1" },
27293
27923
  stdio: ["ignore", "pipe", "pipe"]
@@ -27368,7 +27998,7 @@ async function proveLoadedReleaseReady(layout, runtimeDir, loadedRelease, option
27368
27998
  });
27369
27999
  if (!accepted)
27370
28000
  return false;
27371
- await writeFile13(resolve25(runtimeDir, "daemon-ready.json"), `${JSON.stringify({
28001
+ await writeFile13(resolve26(runtimeDir, "daemon-ready.json"), `${JSON.stringify({
27372
28002
  readyAt: (options.now ?? Date.now)(),
27373
28003
  loadedRelease,
27374
28004
  functionalProof: options.functionalProof
@@ -27597,11 +28227,11 @@ init_self_update();
27597
28227
 
27598
28228
  // apps/body/dist/daemon-failure.js
27599
28229
  import { mkdir as mkdir19, readFile as readFile13, rename as rename6, rm as rm8, writeFile as writeFile14 } from "node:fs/promises";
27600
- import { dirname as dirname15, resolve as resolve26 } from "node:path";
28230
+ import { dirname as dirname16, resolve as resolve27 } from "node:path";
27601
28231
  var DAEMON_FAILURE_LIMIT = 3;
27602
28232
  var DAEMON_FAILURE_WINDOW_MS = 5 * 6e4;
27603
28233
  function daemonFailurePath(runtimeDir) {
27604
- return resolve26(runtimeDir, "daemon-distress.json");
28234
+ return resolve27(runtimeDir, "daemon-distress.json");
27605
28235
  }
27606
28236
  async function readFailureRecord(runtimeDir) {
27607
28237
  try {
@@ -27617,7 +28247,7 @@ async function readFailureRecord(runtimeDir) {
27617
28247
  async function writeFailureRecord(runtimeDir, record3) {
27618
28248
  const path = daemonFailurePath(runtimeDir);
27619
28249
  const staged = `${path}.${process.pid}.tmp`;
27620
- await mkdir19(dirname15(path), { recursive: true, mode: 448 });
28250
+ await mkdir19(dirname16(path), { recursive: true, mode: 448 });
27621
28251
  await writeFile14(staged, `${JSON.stringify(record3, null, 2)}
27622
28252
  `, { mode: 384 });
27623
28253
  await rename6(staged, path);
@@ -27641,8 +28271,8 @@ async function clearDaemonStartFailures(runtimeDir) {
27641
28271
 
27642
28272
  // apps/body/dist/update-functional-probe.js
27643
28273
  import { mkdir as mkdir20, rm as rm9 } from "node:fs/promises";
27644
- import { homedir as homedir11 } from "node:os";
27645
- import { resolve as resolve27 } from "node:path";
28274
+ import { homedir as homedir12 } from "node:os";
28275
+ import { resolve as resolve28 } from "node:path";
27646
28276
  var UPDATE_PROBE_SESSION_TIMEOUT_MS = 1e4;
27647
28277
  var UPDATE_PROBE_SESSION_OPEN_TIMEOUT_MS = 2e4;
27648
28278
  var UPDATE_PROBE_TURN_TIMEOUT_MS = 45e3;
@@ -27709,6 +28339,10 @@ function describeCurrentReleaseOutcome(outcome) {
27709
28339
  }
27710
28340
  async function runUpdateFunctionalProbe(input) {
27711
28341
  const command = input.config.agentCommand ?? input.config.agentBinary;
28342
+ const harnessLabel = harnessIdentityLabel({
28343
+ kind: input.config.agentKind,
28344
+ command
28345
+ });
27712
28346
  const harness = input.config.agentKind ?? command;
27713
28347
  if (input.config.modelUnavailable) {
27714
28348
  throw new UpdateFunctionalProbeError("model-unavailable", input.config.modelUnavailable.detail);
@@ -27736,9 +28370,9 @@ async function runUpdateFunctionalProbe(input) {
27736
28370
  modelAnswerReason: `${detail} (the current release has the same host sandbox failure)`
27737
28371
  };
27738
28372
  }
27739
- const root = input.probeRoot ?? resolve27(input.runtimeDir, "update-functional-probe");
27740
- const cwd = resolve27(root, "checkout");
27741
- const homeRoot = resolve27(root, "agent-home");
28373
+ const root = input.probeRoot ?? resolve28(input.runtimeDir, "update-functional-probe");
28374
+ const cwd = resolve28(root, "checkout");
28375
+ const homeRoot = resolve28(root, "agent-home");
27742
28376
  await rm9(root, { recursive: true, force: true });
27743
28377
  await mkdir20(cwd, { recursive: true, mode: 448 });
27744
28378
  let client;
@@ -27747,7 +28381,7 @@ async function runUpdateFunctionalProbe(input) {
27747
28381
  ...input.config.agentEnv,
27748
28382
  ...await prepareRoomAgentHome({
27749
28383
  root: homeRoot,
27750
- operatorHome: input.config.operatorHome ?? homedir11(),
28384
+ operatorHome: input.config.operatorHome ?? homedir12(),
27751
28385
  sharedSkills: input.config.sharedSkills ?? [],
27752
28386
  ...input.config.agentKind ? { agentKind: input.config.agentKind } : {},
27753
28387
  skillReleaseId: input.releaseId,
@@ -27768,8 +28402,8 @@ async function runUpdateFunctionalProbe(input) {
27768
28402
  let turnCompleted = true;
27769
28403
  if (input.config.bwrapPath) {
27770
28404
  const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
27771
- const operatorHome = input.config.operatorHome ?? homedir11();
27772
- const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
28405
+ const operatorHome = input.config.operatorHome ?? homedir12();
28406
+ const homeStateDirs = harnessHomeStateDirs(harnessLabel, agentEnv.HOME ?? operatorHome);
27773
28407
  await Promise.all(homeStateDirs.map((dir) => mkdir20(dir, { recursive: true })));
27774
28408
  spawnCommand = wrapAgentCommand({
27775
28409
  bwrapPath: input.config.bwrapPath,
@@ -27788,7 +28422,7 @@ async function runUpdateFunctionalProbe(input) {
27788
28422
  client = new AcpClient({
27789
28423
  agentCommand: spawnCommand.command,
27790
28424
  agentArgs: spawnCommand.args,
27791
- agentLabel: command,
28425
+ agentLabel: harnessLabel,
27792
28426
  agentEnv,
27793
28427
  agentCwd: cwd,
27794
28428
  autoApprovePermissions: true
@@ -27819,7 +28453,7 @@ async function runUpdateFunctionalProbe(input) {
27819
28453
  modelAnswer = { modelAnswer: "served" };
27820
28454
  } else {
27821
28455
  const explained = await explainEmptyAgentTurn({
27822
- agentLabel: command,
28456
+ agentLabel: harnessLabel,
27823
28457
  agentEnv,
27824
28458
  sessionId,
27825
28459
  result: served
@@ -27919,8 +28553,8 @@ async function runUpdateFunctionalProbe(input) {
27919
28553
  }
27920
28554
 
27921
28555
  // apps/body/dist/current-release-probe.js
27922
- import { spawn as spawn10 } from "node:child_process";
27923
- import { dirname as dirname16, join as join11 } from "node:path";
28556
+ import { spawn as spawn11 } from "node:child_process";
28557
+ import { dirname as dirname17, join as join12 } from "node:path";
27924
28558
  init_self_update();
27925
28559
  var CURRENT_RELEASE_PROBE_TIMEOUT_MS = 12e4;
27926
28560
  var UPDATE_PROBE_COMMAND = "update-probe";
@@ -27963,14 +28597,14 @@ function outcomeFromReport(report) {
27963
28597
  }
27964
28598
  }
27965
28599
  async function probeReleaseInSubprocess(input) {
27966
- const bundleDir = join11(input.layout.releasesRoot, input.releaseId);
28600
+ const bundleDir = join12(input.layout.releasesRoot, input.releaseId);
27967
28601
  const entrypoint = await resolveBundleEntrypoint(bundleDir);
27968
28602
  if (!entrypoint) {
27969
28603
  return { kind: "unavailable", reason: `release ${input.releaseId} has no runnable CLI entrypoint` };
27970
28604
  }
27971
28605
  const timeoutMs = input.timeoutMs ?? CURRENT_RELEASE_PROBE_TIMEOUT_MS;
27972
- return new Promise((resolve31) => {
27973
- const child = spawn10(input.execPath ?? process.execPath, [entrypoint, UPDATE_PROBE_COMMAND, "--config", input.runtimeConfigPath], { env: input.env ?? process.env, stdio: ["ignore", "pipe", "pipe"] });
28606
+ return new Promise((resolve32) => {
28607
+ const child = spawn11(input.execPath ?? process.execPath, [entrypoint, UPDATE_PROBE_COMMAND, "--config", input.runtimeConfigPath], { env: input.env ?? process.env, stdio: ["ignore", "pipe", "pipe"] });
27974
28608
  let stdout6 = "";
27975
28609
  let stderr = "";
27976
28610
  let settled = false;
@@ -27979,7 +28613,7 @@ async function probeReleaseInSubprocess(input) {
27979
28613
  return;
27980
28614
  settled = true;
27981
28615
  clearTimeout(timer);
27982
- resolve31(outcome);
28616
+ resolve32(outcome);
27983
28617
  };
27984
28618
  const timer = setTimeout(() => {
27985
28619
  child.kill("SIGKILL");
@@ -28026,7 +28660,7 @@ async function runUpdateProbeCommand(args, options = {}) {
28026
28660
  const runtime = await readRuntimeRecord(configPath);
28027
28661
  const agent = runtimeAgentCommand(runtime);
28028
28662
  const config = loadBodyConfig({
28029
- workspaceRoot: join11(dirname16(configPath), "workspace"),
28663
+ workspaceRoot: join12(dirname17(configPath), "workspace"),
28030
28664
  llmEnvFile: runtime.llmEnvFile,
28031
28665
  env: { ...env, BUZZ_AGENT_BIN: agent.command, BUZZ_DEV_MCP_BIN: runtime.mcpBinary },
28032
28666
  agent
@@ -28044,7 +28678,7 @@ async function runUpdateProbeCommand(args, options = {}) {
28044
28678
  }
28045
28679
  const layout = beelineInstallLayout(env);
28046
28680
  const releaseId = (layout && await activeReleaseId(layout).catch(() => void 0)) ?? "unknown";
28047
- const runtimeDir = dirname16(configPath);
28681
+ const runtimeDir = dirname17(configPath);
28048
28682
  const outcome = await probeOutcome(() => (options.probe ?? runUpdateFunctionalProbe)({
28049
28683
  config,
28050
28684
  runtimeDir,
@@ -28052,7 +28686,7 @@ async function runUpdateProbeCommand(args, options = {}) {
28052
28686
  sandboxRequired: runtime.sandbox !== "off",
28053
28687
  sandboxUnavailableDetail: sandbox.advisory,
28054
28688
  // The successor's probe still holds `<runtimeDir>/update-functional-probe`.
28055
- probeRoot: join11(runtimeDir, "current-release-probe")
28689
+ probeRoot: join12(runtimeDir, "current-release-probe")
28056
28690
  }));
28057
28691
  const report = outcome.kind === "served" ? { probe: "served" } : outcome.kind === "refused" ? { probe: "refused", status: outcome.status, reason: outcome.reason } : outcome.kind === "sandbox-unavailable" ? { probe: "sandbox-unavailable", reason: outcome.reason } : { probe: "failed", reason: outcome.reason };
28058
28692
  write(JSON.stringify(report));
@@ -28060,7 +28694,7 @@ async function runUpdateProbeCommand(args, options = {}) {
28060
28694
 
28061
28695
  // apps/body/dist/release-status.js
28062
28696
  import { readFile as readFile14, readdir as readdir6, rename as rename7, writeFile as writeFile15 } from "node:fs/promises";
28063
- import { resolve as resolve28 } from "node:path";
28697
+ import { resolve as resolve29 } from "node:path";
28064
28698
  var DAEMON_RELEASE_STATUS_FILE = "release-status.json";
28065
28699
  var RELEASE_VERSION = /^v\d+\.\d+\.\d+$/;
28066
28700
  var SOURCE_SHA = /^[0-9a-f]{7,64}$/;
@@ -28077,7 +28711,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
28077
28711
  pid: options.pid ?? process.pid,
28078
28712
  readyAt: (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString()
28079
28713
  };
28080
- const target = resolve28(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
28714
+ const target = resolve29(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
28081
28715
  const temporary = `${target}.${status.pid}.tmp`;
28082
28716
  await writeFile15(temporary, `${JSON.stringify(status, null, 2)}
28083
28717
  `, { mode: 384 });
@@ -28087,7 +28721,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
28087
28721
 
28088
28722
  // apps/body/dist/scratch-sweep.js
28089
28723
  import { lstat as lstat4, readdir as readdir7, rmdir, unlink as unlink4 } from "node:fs/promises";
28090
- import { resolve as resolve29 } from "node:path";
28724
+ import { resolve as resolve30 } from "node:path";
28091
28725
  var DEFAULT_SCRATCH_TTL_HOURS = 72;
28092
28726
  var NEVER_SWEEP_SUBDIR_NAMES = new Set(HOME_SUBDIRS.filter((name) => name !== "tmp"));
28093
28727
  function scratchTtlMs(env = process.env) {
@@ -28096,7 +28730,7 @@ function scratchTtlMs(env = process.env) {
28096
28730
  return (Number.isFinite(hours) && hours > 0 ? hours : DEFAULT_SCRATCH_TTL_HOURS) * 60 * 60 * 1e3;
28097
28731
  }
28098
28732
  async function discoverAttachScratchRoots(runtimeDir) {
28099
- const roomsDir = resolve29(runtimeDir, "rooms");
28733
+ const roomsDir = resolve30(runtimeDir, "rooms");
28100
28734
  let entries;
28101
28735
  try {
28102
28736
  entries = await readdir7(roomsDir, { withFileTypes: true });
@@ -28107,7 +28741,7 @@ async function discoverAttachScratchRoots(runtimeDir) {
28107
28741
  for (const entry of entries) {
28108
28742
  if (!entry.isDirectory())
28109
28743
  continue;
28110
- const home = resolve29(roomsDir, entry.name, "agent-home");
28744
+ const home = resolve30(roomsDir, entry.name, "agent-home");
28111
28745
  const stats = await lstat4(home).catch(() => void 0);
28112
28746
  if (stats?.isDirectory())
28113
28747
  roots.push(home);
@@ -28126,7 +28760,7 @@ async function removeStaleFiles(dir, cutoffMs, protectNamesHere) {
28126
28760
  for (const entry of entries) {
28127
28761
  if (protectNamesHere && NEVER_SWEEP_SUBDIR_NAMES.has(entry.name))
28128
28762
  continue;
28129
- const path = resolve29(dir, entry.name);
28763
+ const path = resolve30(dir, entry.name);
28130
28764
  const stats = await lstat4(path).catch(() => void 0);
28131
28765
  if (!stats || stats.isSymbolicLink())
28132
28766
  continue;
@@ -28213,7 +28847,7 @@ var DaemonExitError = class extends Error {
28213
28847
  };
28214
28848
  async function runStoredDaemon(pathOrPointer) {
28215
28849
  const configPath = await resolveRuntimeConfigPath(pathOrPointer);
28216
- daemonFailureRuntimeDir = dirname17(configPath);
28850
+ daemonFailureRuntimeDir = dirname18(configPath);
28217
28851
  const accessMigration = await migrateRuntimeRecordAccessPolicy(configPath);
28218
28852
  let runtime = accessMigration.runtime;
28219
28853
  if (!runtime.transport) {
@@ -28225,7 +28859,7 @@ async function runStoredDaemon(pathOrPointer) {
28225
28859
  runtime = activated.runtime;
28226
28860
  const daemonApi = activated.client;
28227
28861
  const agent = runtimeAgentCommand(runtime);
28228
- await writeFile16(resolve30(dirname17(configPath), "daemon.pid"), `${process.pid}
28862
+ await writeFile16(resolve31(dirname18(configPath), "daemon.pid"), `${process.pid}
28229
28863
  `, { mode: 384 });
28230
28864
  const env = {
28231
28865
  ...process.env,
@@ -28233,7 +28867,7 @@ async function runStoredDaemon(pathOrPointer) {
28233
28867
  BUZZ_DEV_MCP_BIN: runtime.mcpBinary
28234
28868
  };
28235
28869
  const config = loadBodyConfig({
28236
- workspaceRoot: resolve30(dirname17(configPath), "workspace"),
28870
+ workspaceRoot: resolve31(dirname18(configPath), "workspace"),
28237
28871
  llmEnvFile: runtime.llmEnvFile,
28238
28872
  env,
28239
28873
  agent
@@ -28268,7 +28902,7 @@ async function runStoredDaemon(pathOrPointer) {
28268
28902
  const stop = () => controller.abort();
28269
28903
  process.once("SIGINT", stop);
28270
28904
  process.once("SIGTERM", stop);
28271
- const runtimeDir = dirname17(configPath);
28905
+ const runtimeDir = dirname18(configPath);
28272
28906
  const layout = beelineInstallLayout(process.env);
28273
28907
  const notifier = new SystemdNotifier();
28274
28908
  let rollbackAlertDrain;
@@ -28424,7 +29058,7 @@ async function runStoredDaemon(pathOrPointer) {
28424
29058
  } finally {
28425
29059
  clearInterval(scratchSweepTimer);
28426
29060
  await notifier.stopping(stoppingStatus).catch(() => void 0);
28427
- const pidPath = resolve30(dirname17(configPath), "daemon.pid");
29061
+ const pidPath = resolve31(dirname18(configPath), "daemon.pid");
28428
29062
  const recorded = Number((await readFile15(pidPath, "utf8").catch(() => "")).trim());
28429
29063
  if (recorded === process.pid) {
28430
29064
  await unlink5(pidPath).catch(() => void 0);
@@ -28436,6 +29070,10 @@ async function main() {
28436
29070
  if (args.length === 0)
28437
29071
  usage();
28438
29072
  const command = args[0];
29073
+ if (command === CURSOR_ACP_BRIDGE_FLAG) {
29074
+ await runCursorAcpStdioServer();
29075
+ return;
29076
+ }
28439
29077
  if (command === "--help" || command === "-h")
28440
29078
  usage(0);
28441
29079
  if (command === "managed-update-worker") {
@@ -28452,7 +29090,7 @@ async function main() {
28452
29090
  const roomId = roomFlag >= 0 ? args[roomFlag + 1] : void 0;
28453
29091
  if (!configPath || !roomId)
28454
29092
  throw new Error("corner-read-token requires --config and --room");
28455
- const activated = await activateDaemonTransport(resolve30(configPath));
29093
+ const activated = await activateDaemonTransport(resolve31(configPath));
28456
29094
  if (!activated)
28457
29095
  throw new Error("corner-read-token requires monolith transport");
28458
29096
  const credential = await activated.client.execute("getRoomGitHubToken", { roomId });
@@ -28501,14 +29139,14 @@ async function main() {
28501
29139
  const agentPubkey = agentFlag >= 0 ? args[agentFlag + 1] : void 0;
28502
29140
  if (!configPath && agentPubkey) {
28503
29141
  const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
28504
- configPath = configs.find((candidate) => dirname17(candidate).endsWith(agentPubkey));
29142
+ configPath = configs.find((candidate) => dirname18(candidate).endsWith(agentPubkey));
28505
29143
  }
28506
29144
  if (!configPath && agentPubkey) {
28507
29145
  throw new DaemonExitError(`unknown agent ${agentPubkey}: no durable runtime exists; refusing systemd restart loop`, UNKNOWN_AGENT_EXIT_STATUS);
28508
29146
  }
28509
29147
  if (!configPath)
28510
29148
  throw new Error("daemon requires --config <runtime.json> or --agent <pubkey>");
28511
- await runStoredDaemon(resolve30(configPath));
29149
+ await runStoredDaemon(resolve31(configPath));
28512
29150
  return;
28513
29151
  }
28514
29152
  if (command === "update") {
@@ -28529,7 +29167,7 @@ async function main() {
28529
29167
  if (!agentPubkey)
28530
29168
  throw new Error("stop requires --agent <pubkey>");
28531
29169
  const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
28532
- const configPath = configs.find((candidate) => dirname17(candidate).endsWith(agentPubkey));
29170
+ const configPath = configs.find((candidate) => dirname18(candidate).endsWith(agentPubkey));
28533
29171
  if (!configPath)
28534
29172
  throw new Error(`no stored runtime found for agent ${agentPubkey}`);
28535
29173
  const runtime = await readRuntimeRecord(configPath);