usebeeline 0.0.117 → 0.0.121
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.
- package/README.md +4 -4
- package/dist/usebeeline.mjs +1506 -535
- package/package.json +1 -1
package/dist/usebeeline.mjs
CHANGED
|
@@ -11300,10 +11300,12 @@ __export(self_update_exports, {
|
|
|
11300
11300
|
readInstalledBundleIdentity: () => readInstalledBundleIdentity,
|
|
11301
11301
|
readUpdateAttempt: () => readUpdateAttempt,
|
|
11302
11302
|
readUpdateState: () => readUpdateState,
|
|
11303
|
+
releaseIdFromPath: () => releaseIdFromPath,
|
|
11303
11304
|
repairInstallForwarders: () => repairInstallForwarders,
|
|
11304
11305
|
replaceUpdateAttempt: () => replaceUpdateAttempt,
|
|
11305
11306
|
resolveBundleEntrypoint: () => resolveBundleEntrypoint,
|
|
11306
11307
|
rollbackToPreviousRelease: () => rollbackToPreviousRelease,
|
|
11308
|
+
runningReleaseId: () => runningReleaseId,
|
|
11307
11309
|
settleUpdateAttemptOnStart: () => settleUpdateAttemptOnStart,
|
|
11308
11310
|
stageRelease: () => stageRelease,
|
|
11309
11311
|
updateAttemptPath: () => updateAttemptPath,
|
|
@@ -11314,11 +11316,11 @@ __export(self_update_exports, {
|
|
|
11314
11316
|
import { createHash as createHash8 } from "node:crypto";
|
|
11315
11317
|
import { constants as fsConstants2 } from "node:fs";
|
|
11316
11318
|
import { access, chmod as chmod6, lstat as lstat4, mkdir as mkdir17, open, readFile as readFile10, rename as rename6, rm as rm6, symlink as symlink3, writeFile as writeFile11 } from "node:fs/promises";
|
|
11317
|
-
import { spawn as
|
|
11318
|
-
import { homedir as
|
|
11319
|
-
import { dirname as
|
|
11319
|
+
import { spawn as spawn8 } from "node:child_process";
|
|
11320
|
+
import { homedir as homedir12 } from "node:os";
|
|
11321
|
+
import { dirname as dirname15, join as join13, resolve as resolve26 } from "node:path";
|
|
11320
11322
|
function anchorLayout(rawLibDir) {
|
|
11321
|
-
const libDir =
|
|
11323
|
+
const libDir = resolve26(rawLibDir);
|
|
11322
11324
|
const segments = libDir.split(/[/\\]/);
|
|
11323
11325
|
const idx = segments.lastIndexOf(RELEASES_SEGMENT);
|
|
11324
11326
|
if (idx >= 2 && segments[idx - 1] === "lib") {
|
|
@@ -11334,9 +11336,9 @@ function anchorLayout(rawLibDir) {
|
|
|
11334
11336
|
// prefix's bin, NOT <prefix>/lib/bin — deriving it one level up was the
|
|
11335
11337
|
// defect that made activateRelease write its stable forwarders where
|
|
11336
11338
|
// nothing executed them, leaving stale raw wrappers in <prefix>/bin.
|
|
11337
|
-
binDir:
|
|
11339
|
+
binDir: resolve26(libDir, "../../bin"),
|
|
11338
11340
|
libDir,
|
|
11339
|
-
releasesRoot:
|
|
11341
|
+
releasesRoot: resolve26(libDir, `../${RELEASES_SEGMENT}`)
|
|
11340
11342
|
};
|
|
11341
11343
|
}
|
|
11342
11344
|
function beelineInstallLayout(env = process.env) {
|
|
@@ -11345,9 +11347,32 @@ function beelineInstallLayout(env = process.env) {
|
|
|
11345
11347
|
return void 0;
|
|
11346
11348
|
return anchorLayout(raw);
|
|
11347
11349
|
}
|
|
11350
|
+
function releaseIdFromPath(path) {
|
|
11351
|
+
if (!path?.trim())
|
|
11352
|
+
return void 0;
|
|
11353
|
+
const segments = resolve26(path.trim()).split(/[/\\]/);
|
|
11354
|
+
const idx = segments.lastIndexOf(RELEASES_SEGMENT);
|
|
11355
|
+
const id = idx >= 0 ? segments[idx + 1] : void 0;
|
|
11356
|
+
return id ? sanitizeReleaseId(id) : void 0;
|
|
11357
|
+
}
|
|
11358
|
+
function runningReleaseId(layout, env = process.env, invocationPath = process.argv[1]) {
|
|
11359
|
+
const releasesRoot = resolve26(layout.releasesRoot);
|
|
11360
|
+
const anchor = resolve26(layout.libDir);
|
|
11361
|
+
for (const raw of [env.BEELINE_LIB_DIR, invocationPath]) {
|
|
11362
|
+
if (!raw?.trim())
|
|
11363
|
+
continue;
|
|
11364
|
+
const resolved = resolve26(raw.trim());
|
|
11365
|
+
if (resolved !== anchor && !resolved.startsWith(`${releasesRoot}/`))
|
|
11366
|
+
continue;
|
|
11367
|
+
const id = releaseIdFromPath(resolved);
|
|
11368
|
+
if (id)
|
|
11369
|
+
return id;
|
|
11370
|
+
}
|
|
11371
|
+
return void 0;
|
|
11372
|
+
}
|
|
11348
11373
|
function defaultBeelineInstallLayout(env = process.env) {
|
|
11349
|
-
const home = env.HOME?.trim() ||
|
|
11350
|
-
return anchorLayout(
|
|
11374
|
+
const home = env.HOME?.trim() || homedir12();
|
|
11375
|
+
return anchorLayout(resolve26(home, ".local", "lib", "beeline"));
|
|
11351
11376
|
}
|
|
11352
11377
|
function discoveredBeelineInstallLayout(env = process.env) {
|
|
11353
11378
|
const explicitAnchor = env.BEELINE_INSTALL_LIB_DIR?.trim();
|
|
@@ -11355,7 +11380,7 @@ function discoveredBeelineInstallLayout(env = process.env) {
|
|
|
11355
11380
|
return anchorLayout(explicitAnchor);
|
|
11356
11381
|
const explicitBinDir = env.BEELINE_INSTALL_DIR?.trim();
|
|
11357
11382
|
if (explicitBinDir)
|
|
11358
|
-
return anchorLayout(
|
|
11383
|
+
return anchorLayout(resolve26(dirname15(resolve26(explicitBinDir)), "lib", "beeline"));
|
|
11359
11384
|
return defaultBeelineInstallLayout(env);
|
|
11360
11385
|
}
|
|
11361
11386
|
function hostPlatformKey() {
|
|
@@ -11366,7 +11391,7 @@ function hostPlatformKey() {
|
|
|
11366
11391
|
return `${os}-${arch}`;
|
|
11367
11392
|
}
|
|
11368
11393
|
function bundleJsonCandidates(bundleDir) {
|
|
11369
|
-
return [
|
|
11394
|
+
return [join13(bundleDir, "lib", "beeline", "bundle.json"), join13(bundleDir, "bundle.json")];
|
|
11370
11395
|
}
|
|
11371
11396
|
async function readBundleJson(bundleDir) {
|
|
11372
11397
|
let raw;
|
|
@@ -11390,7 +11415,7 @@ async function readBundleJson(bundleDir) {
|
|
|
11390
11415
|
}
|
|
11391
11416
|
}
|
|
11392
11417
|
function updateStatePath(layout) {
|
|
11393
|
-
return
|
|
11418
|
+
return join13(layout.releasesRoot, ".state", "update-state.json");
|
|
11394
11419
|
}
|
|
11395
11420
|
async function readUpdateState(layout) {
|
|
11396
11421
|
try {
|
|
@@ -11400,7 +11425,7 @@ async function readUpdateState(layout) {
|
|
|
11400
11425
|
}
|
|
11401
11426
|
}
|
|
11402
11427
|
async function writeUpdateState(layout, state) {
|
|
11403
|
-
await mkdir17(
|
|
11428
|
+
await mkdir17(join13(layout.releasesRoot, ".state"), { recursive: true });
|
|
11404
11429
|
await writeFile11(updateStatePath(layout), `${JSON.stringify(state, null, 2)}
|
|
11405
11430
|
`, "utf8");
|
|
11406
11431
|
}
|
|
@@ -11464,7 +11489,7 @@ async function fetchText(url, fetchImpl) {
|
|
|
11464
11489
|
}
|
|
11465
11490
|
function run(command, args, timeoutMs) {
|
|
11466
11491
|
return new Promise((resolveRun) => {
|
|
11467
|
-
const child =
|
|
11492
|
+
const child = spawn8(command, args, { stdio: ["ignore", "ignore", "pipe"] });
|
|
11468
11493
|
let stderr = "";
|
|
11469
11494
|
child.stderr?.setEncoding("utf8");
|
|
11470
11495
|
child.stderr?.on("data", (chunk) => {
|
|
@@ -11482,7 +11507,7 @@ function run(command, args, timeoutMs) {
|
|
|
11482
11507
|
});
|
|
11483
11508
|
}
|
|
11484
11509
|
function entrypointCandidates(bundleDir) {
|
|
11485
|
-
return [
|
|
11510
|
+
return [join13(bundleDir, BUNDLE_ENTRYPOINT), join13(bundleDir, "beeline-cli.mjs")];
|
|
11486
11511
|
}
|
|
11487
11512
|
async function resolveBundleEntrypoint(bundleDir) {
|
|
11488
11513
|
for (const candidate of entrypointCandidates(bundleDir)) {
|
|
@@ -11504,8 +11529,8 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
11504
11529
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
11505
11530
|
const log2 = opts.logger ?? ((line) => console.log(`[body] self-update: ${line}`));
|
|
11506
11531
|
const releaseId = sanitizeReleaseId(published.commit ?? published.version ?? `release-${Date.now()}`);
|
|
11507
|
-
const releaseDir =
|
|
11508
|
-
const okMarker =
|
|
11532
|
+
const releaseDir = join13(layout.releasesRoot, releaseId);
|
|
11533
|
+
const okMarker = join13(releaseDir, ".stage-ok");
|
|
11509
11534
|
let previouslyVerified = false;
|
|
11510
11535
|
try {
|
|
11511
11536
|
const recorded = await readFile10(okMarker, "utf8");
|
|
@@ -11515,7 +11540,7 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
11515
11540
|
} catch {
|
|
11516
11541
|
}
|
|
11517
11542
|
await mkdir17(releaseDir, { recursive: true });
|
|
11518
|
-
const tempArchive =
|
|
11543
|
+
const tempArchive = join13(layout.releasesRoot, `.download-${releaseId}-${process.pid}.tar.gz`);
|
|
11519
11544
|
try {
|
|
11520
11545
|
log2(`downloading ${published.file}`);
|
|
11521
11546
|
const response = await fetchImpl(archiveUrlFor(manifestUrl, published.file), {
|
|
@@ -11537,7 +11562,7 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
11537
11562
|
}
|
|
11538
11563
|
await writeFile11(tempArchive, Buffer.concat(chunks), { mode: 384 });
|
|
11539
11564
|
const entries = (await new Promise((resolveList, rejectList) => {
|
|
11540
|
-
const child =
|
|
11565
|
+
const child = spawn8("tar", ["-tzf", tempArchive], { stdio: ["ignore", "pipe", "inherit"] });
|
|
11541
11566
|
let out = "";
|
|
11542
11567
|
child.stdout?.on("data", (chunk) => {
|
|
11543
11568
|
out += chunk.toString("utf8");
|
|
@@ -11555,13 +11580,13 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
11555
11580
|
throw new Error(`extracting bundle failed: ${extract2.stderr}`);
|
|
11556
11581
|
for (const relative3 of requiredBundlePaths()) {
|
|
11557
11582
|
try {
|
|
11558
|
-
await access(
|
|
11583
|
+
await access(join13(releaseDir, relative3), fsConstants2.F_OK);
|
|
11559
11584
|
} catch {
|
|
11560
11585
|
throw new Error(`staged bundle is missing ${relative3}`);
|
|
11561
11586
|
}
|
|
11562
11587
|
}
|
|
11563
11588
|
if (opts.smokeTestCli !== false) {
|
|
11564
|
-
const probe = await run(process.execPath, [
|
|
11589
|
+
const probe = await run(process.execPath, [join13(releaseDir, BUNDLE_ENTRYPOINT), "--version"], 6e4);
|
|
11565
11590
|
if (probe.status !== 0) {
|
|
11566
11591
|
throw new Error(`staged bundle failed its startup smoke test (--version exited ${probe.status})${probe.stderr ? `: ${probe.stderr.trim()}` : ""}`);
|
|
11567
11592
|
}
|
|
@@ -11599,8 +11624,8 @@ async function replaceFile(path, contents, mode) {
|
|
|
11599
11624
|
await rename6(temp, path);
|
|
11600
11625
|
}
|
|
11601
11626
|
async function activateRelease(layout, releaseId) {
|
|
11602
|
-
const releaseDir =
|
|
11603
|
-
await access(
|
|
11627
|
+
const releaseDir = join13(layout.releasesRoot, releaseId);
|
|
11628
|
+
await access(join13(releaseDir, BUNDLE_ENTRYPOINT), fsConstants2.F_OK);
|
|
11604
11629
|
await mkdir17(layout.releasesRoot, { recursive: true });
|
|
11605
11630
|
await mkdir17(layout.binDir, { recursive: true });
|
|
11606
11631
|
let previousReleaseId = await activeReleaseId(layout);
|
|
@@ -11608,12 +11633,12 @@ async function activateRelease(layout, releaseId) {
|
|
|
11608
11633
|
if (kind === "directory") {
|
|
11609
11634
|
const legacyIdentity = await readBundleJson(layout.libDir);
|
|
11610
11635
|
const legacyId = sanitizeReleaseId(legacyIdentity?.commit ?? legacyIdentity?.version ?? `legacy-${Date.now()}`);
|
|
11611
|
-
const legacyDir =
|
|
11636
|
+
const legacyDir = join13(layout.releasesRoot, legacyId);
|
|
11612
11637
|
try {
|
|
11613
11638
|
await access(legacyDir, fsConstants2.F_OK);
|
|
11614
11639
|
previousReleaseId = `${legacyId}-${Date.now()}`;
|
|
11615
|
-
await rename6(layout.libDir,
|
|
11616
|
-
await normalizeLegacyBundleShape(
|
|
11640
|
+
await rename6(layout.libDir, join13(layout.releasesRoot, previousReleaseId));
|
|
11641
|
+
await normalizeLegacyBundleShape(join13(layout.releasesRoot, previousReleaseId));
|
|
11617
11642
|
} catch {
|
|
11618
11643
|
await rename6(layout.libDir, legacyDir);
|
|
11619
11644
|
await normalizeLegacyBundleShape(legacyDir);
|
|
@@ -11622,18 +11647,18 @@ async function activateRelease(layout, releaseId) {
|
|
|
11622
11647
|
}
|
|
11623
11648
|
const tempLink = `${layout.libDir}.new-${process.pid}`;
|
|
11624
11649
|
await rm6(tempLink, { force: true });
|
|
11625
|
-
await symlink3(
|
|
11650
|
+
await symlink3(join13("beeline-releases", releaseId), tempLink);
|
|
11626
11651
|
await rename6(tempLink, layout.libDir);
|
|
11627
|
-
await fsyncDir(
|
|
11652
|
+
await fsyncDir(dirname15(layout.libDir));
|
|
11628
11653
|
await writeBinForwarders(layout, releaseDir);
|
|
11629
11654
|
return { previousReleaseId };
|
|
11630
11655
|
}
|
|
11631
11656
|
async function normalizeLegacyBundleShape(bundleDir) {
|
|
11632
|
-
const innerLib =
|
|
11657
|
+
const innerLib = join13(bundleDir, "lib", "beeline");
|
|
11633
11658
|
let anyFlat = false;
|
|
11634
11659
|
for (const name of LEGACY_FLAT_BUNDLE_FILES) {
|
|
11635
11660
|
try {
|
|
11636
|
-
await access(
|
|
11661
|
+
await access(join13(bundleDir, name), fsConstants2.F_OK);
|
|
11637
11662
|
anyFlat = true;
|
|
11638
11663
|
break;
|
|
11639
11664
|
} catch {
|
|
@@ -11644,11 +11669,11 @@ async function normalizeLegacyBundleShape(bundleDir) {
|
|
|
11644
11669
|
await mkdir17(innerLib, { recursive: true });
|
|
11645
11670
|
for (const name of LEGACY_FLAT_BUNDLE_FILES) {
|
|
11646
11671
|
try {
|
|
11647
|
-
await access(
|
|
11672
|
+
await access(join13(innerLib, name), fsConstants2.F_OK);
|
|
11648
11673
|
continue;
|
|
11649
11674
|
} catch {
|
|
11650
11675
|
}
|
|
11651
|
-
await rename6(
|
|
11676
|
+
await rename6(join13(bundleDir, name), join13(innerLib, name)).catch(() => void 0);
|
|
11652
11677
|
}
|
|
11653
11678
|
}
|
|
11654
11679
|
async function writeBinForwarders(layout, activeBundleRoot) {
|
|
@@ -11657,13 +11682,13 @@ async function writeBinForwarders(layout, activeBundleRoot) {
|
|
|
11657
11682
|
...Object.entries(FORWARDER_ALIASES).map(([alias, tool]) => [alias, tool])
|
|
11658
11683
|
];
|
|
11659
11684
|
for (const [name, tool] of entries) {
|
|
11660
|
-
const target =
|
|
11685
|
+
const target = join13(activeBundleRoot, "bin", tool);
|
|
11661
11686
|
try {
|
|
11662
11687
|
await access(target, fsConstants2.X_OK);
|
|
11663
11688
|
} catch {
|
|
11664
11689
|
continue;
|
|
11665
11690
|
}
|
|
11666
|
-
await replaceFile(
|
|
11691
|
+
await replaceFile(join13(layout.binDir, name), forwarderScript(tool), 493);
|
|
11667
11692
|
}
|
|
11668
11693
|
}
|
|
11669
11694
|
async function repairInstallForwarders(layout, opts = {}) {
|
|
@@ -11672,7 +11697,7 @@ async function repairInstallForwarders(layout, opts = {}) {
|
|
|
11672
11697
|
const forwarderHealthy = async (name, tool) => {
|
|
11673
11698
|
let current;
|
|
11674
11699
|
try {
|
|
11675
|
-
current = await readFile10(
|
|
11700
|
+
current = await readFile10(join13(layout.binDir, name), "utf8");
|
|
11676
11701
|
} catch {
|
|
11677
11702
|
current = void 0;
|
|
11678
11703
|
}
|
|
@@ -11691,19 +11716,19 @@ async function repairInstallForwarders(layout, opts = {}) {
|
|
|
11691
11716
|
return true;
|
|
11692
11717
|
}
|
|
11693
11718
|
async function rollbackToPreviousRelease(layout, previousReleaseId) {
|
|
11694
|
-
const releaseDir =
|
|
11719
|
+
const releaseDir = join13(layout.releasesRoot, previousReleaseId);
|
|
11695
11720
|
const entrypoint = await resolveBundleEntrypoint(releaseDir);
|
|
11696
11721
|
if (!entrypoint) {
|
|
11697
11722
|
throw new Error(`release ${previousReleaseId} has no runnable CLI entrypoint`);
|
|
11698
11723
|
}
|
|
11699
11724
|
const tempLink = `${layout.libDir}.rollback-${process.pid}`;
|
|
11700
11725
|
await rm6(tempLink, { force: true });
|
|
11701
|
-
await symlink3(
|
|
11726
|
+
await symlink3(join13("beeline-releases", previousReleaseId), tempLink);
|
|
11702
11727
|
await rename6(tempLink, layout.libDir);
|
|
11703
|
-
await fsyncDir(
|
|
11728
|
+
await fsyncDir(dirname15(layout.libDir));
|
|
11704
11729
|
}
|
|
11705
11730
|
function updateAttemptPath(layout) {
|
|
11706
|
-
return
|
|
11731
|
+
return join13(layout.releasesRoot, ".state", "update-attempt.json");
|
|
11707
11732
|
}
|
|
11708
11733
|
async function readUpdateAttempt(layout) {
|
|
11709
11734
|
try {
|
|
@@ -11717,7 +11742,7 @@ async function readUpdateAttempt(layout) {
|
|
|
11717
11742
|
}
|
|
11718
11743
|
}
|
|
11719
11744
|
async function writeUpdateAttempt(layout, record3) {
|
|
11720
|
-
await mkdir17(
|
|
11745
|
+
await mkdir17(join13(layout.releasesRoot, ".state"), { recursive: true });
|
|
11721
11746
|
const path = updateAttemptPath(layout);
|
|
11722
11747
|
const staged = `${path}.${process.pid}.tmp`;
|
|
11723
11748
|
await writeFile11(staged, `${JSON.stringify(record3, null, 2)}
|
|
@@ -11995,7 +12020,7 @@ function configureNetworkFamilyDefaults(network = net) {
|
|
|
11995
12020
|
configureNetworkFamilyDefaults();
|
|
11996
12021
|
|
|
11997
12022
|
// apps/body/dist/cli.js
|
|
11998
|
-
import { dirname as
|
|
12023
|
+
import { dirname as dirname22, resolve as resolve34 } from "node:path";
|
|
11999
12024
|
import { stdin as stdin4, stdout as stdout5 } from "node:process";
|
|
12000
12025
|
|
|
12001
12026
|
// node_modules/@clack/core/dist/index.mjs
|
|
@@ -13444,7 +13469,7 @@ function parseCursorModelsOutput(output) {
|
|
|
13444
13469
|
};
|
|
13445
13470
|
}
|
|
13446
13471
|
async function enumerateCursorModels(env = process.env) {
|
|
13447
|
-
return new Promise((
|
|
13472
|
+
return new Promise((resolve35) => {
|
|
13448
13473
|
const child = spawn("cursor-agent", ["models"], {
|
|
13449
13474
|
env,
|
|
13450
13475
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -13458,11 +13483,11 @@ async function enumerateCursorModels(env = process.env) {
|
|
|
13458
13483
|
});
|
|
13459
13484
|
child.on("error", () => {
|
|
13460
13485
|
clearTimeout(timer);
|
|
13461
|
-
|
|
13486
|
+
resolve35(void 0);
|
|
13462
13487
|
});
|
|
13463
13488
|
child.on("close", (code) => {
|
|
13464
13489
|
clearTimeout(timer);
|
|
13465
|
-
|
|
13490
|
+
resolve35(code === 0 ? parseCursorModelsOutput(output) : void 0);
|
|
13466
13491
|
});
|
|
13467
13492
|
});
|
|
13468
13493
|
}
|
|
@@ -13889,13 +13914,13 @@ var CursorAcpServer = class {
|
|
|
13889
13914
|
consumeLine(line);
|
|
13890
13915
|
});
|
|
13891
13916
|
try {
|
|
13892
|
-
const { code, signal } = await new Promise((
|
|
13917
|
+
const { code, signal } = await new Promise((resolve35) => {
|
|
13893
13918
|
let settled = false;
|
|
13894
13919
|
const finish = (exitCode, exitSignal) => {
|
|
13895
13920
|
if (settled)
|
|
13896
13921
|
return;
|
|
13897
13922
|
settled = true;
|
|
13898
|
-
|
|
13923
|
+
resolve35({ code: exitCode, signal: exitSignal });
|
|
13899
13924
|
};
|
|
13900
13925
|
child.once("error", (error) => {
|
|
13901
13926
|
spawnError = error instanceof Error ? error.message : String(error);
|
|
@@ -14574,6 +14599,132 @@ function parseSandboxMaskEnv(env) {
|
|
|
14574
14599
|
return entries.length ? entries : void 0;
|
|
14575
14600
|
}
|
|
14576
14601
|
|
|
14602
|
+
// apps/body/dist/squire-host.js
|
|
14603
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
14604
|
+
import { existsSync as existsSync4, lstatSync, mkdirSync } from "node:fs";
|
|
14605
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
14606
|
+
import { homedir as homedir2 } from "node:os";
|
|
14607
|
+
import { dirname as dirname3, join as join2, resolve as resolve3 } from "node:path";
|
|
14608
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
14609
|
+
var SQUIRE_BROKER_UNAVAILABLE = "broker unavailable";
|
|
14610
|
+
var TRUSTY_SQUIRE_BROKER_UNIT_NAME = "trusty-squire-broker.service";
|
|
14611
|
+
var SQUIRE_FACADE_FLAG = "--squire-facade";
|
|
14612
|
+
var SQUIRE_BROKER_FLAG = "--squire-broker";
|
|
14613
|
+
var SQUIRE_SERVER_ARGS = ["-y", "@trusty-squire/mcp@latest", "server"];
|
|
14614
|
+
function squireHostPaths(home) {
|
|
14615
|
+
const dir = join2(resolve3(home), ".trusty-squire");
|
|
14616
|
+
return {
|
|
14617
|
+
dir,
|
|
14618
|
+
profileDir: join2(dir, "chrome-profile"),
|
|
14619
|
+
configHome: join2(resolve3(home), ".config"),
|
|
14620
|
+
brokerSocket: join2(dir, "broker.sock")
|
|
14621
|
+
};
|
|
14622
|
+
}
|
|
14623
|
+
function squireHostRewriteEnv(home) {
|
|
14624
|
+
const paths = squireHostPaths(home);
|
|
14625
|
+
return {
|
|
14626
|
+
TRUSTY_SQUIRE_PROFILE_DIR: paths.profileDir,
|
|
14627
|
+
XDG_CONFIG_HOME: paths.configHome,
|
|
14628
|
+
TRUSTY_SQUIRE_BROKER_SOCKET: paths.brokerSocket
|
|
14629
|
+
};
|
|
14630
|
+
}
|
|
14631
|
+
function ensureSquireHostDir(home) {
|
|
14632
|
+
const paths = squireHostPaths(home);
|
|
14633
|
+
mkdirSync(paths.dir, { recursive: true, mode: 448 });
|
|
14634
|
+
mkdirSync(paths.profileDir, { recursive: true, mode: 448 });
|
|
14635
|
+
return paths;
|
|
14636
|
+
}
|
|
14637
|
+
function squireHostBindPaths(home, squireRouteGranted) {
|
|
14638
|
+
if (!squireRouteGranted)
|
|
14639
|
+
return [];
|
|
14640
|
+
return [ensureSquireHostDir(home).dir];
|
|
14641
|
+
}
|
|
14642
|
+
function squireBrokerSocketReady(socketPath) {
|
|
14643
|
+
try {
|
|
14644
|
+
return lstatSync(socketPath).isSocket();
|
|
14645
|
+
} catch {
|
|
14646
|
+
return false;
|
|
14647
|
+
}
|
|
14648
|
+
}
|
|
14649
|
+
function squireFacadeLaunch(home) {
|
|
14650
|
+
const env = squireHostRewriteEnv(home);
|
|
14651
|
+
const meta = "usebeeline:npm";
|
|
14652
|
+
if (meta.startsWith("beeline:")) {
|
|
14653
|
+
const entry = process.argv[1];
|
|
14654
|
+
if (!entry)
|
|
14655
|
+
throw new Error("Squire fa\xE7ade cannot resolve the Beeline CLI entry");
|
|
14656
|
+
return { command: process.execPath, args: [entry, SQUIRE_FACADE_FLAG], env };
|
|
14657
|
+
}
|
|
14658
|
+
const js = fileURLToPath2(new URL("./squire-facade.js", meta));
|
|
14659
|
+
if (existsSync4(js))
|
|
14660
|
+
return { command: process.execPath, args: [js], env };
|
|
14661
|
+
const ts = fileURLToPath2(new URL("./squire-facade.ts", meta));
|
|
14662
|
+
if (existsSync4(ts)) {
|
|
14663
|
+
const tsx = createRequire2(meta).resolve("tsx");
|
|
14664
|
+
return { command: process.execPath, args: ["--import", tsx, ts], env };
|
|
14665
|
+
}
|
|
14666
|
+
throw new Error("Squire fa\xE7ade entry not found next to the Beeline helper");
|
|
14667
|
+
}
|
|
14668
|
+
function squireServerCommand(nodeExecPath = process.execPath) {
|
|
14669
|
+
const binDir = dirname3(nodeExecPath);
|
|
14670
|
+
const sibling = join2(binDir, "npx");
|
|
14671
|
+
const args = [...SQUIRE_SERVER_ARGS];
|
|
14672
|
+
if (existsSync4(sibling))
|
|
14673
|
+
return { command: sibling, args, pathPrefix: binDir };
|
|
14674
|
+
return { command: "npx", args, pathPrefix: binDir };
|
|
14675
|
+
}
|
|
14676
|
+
function trustySquireBrokerUnit() {
|
|
14677
|
+
return `[Unit]
|
|
14678
|
+
Description=Trusty Squire host broker
|
|
14679
|
+
After=network-online.target
|
|
14680
|
+
Wants=network-online.target
|
|
14681
|
+
|
|
14682
|
+
[Service]
|
|
14683
|
+
Type=simple
|
|
14684
|
+
WorkingDirectory=%h
|
|
14685
|
+
Environment=TRUSTY_SQUIRE_PROFILE_DIR=%h/.trusty-squire/chrome-profile
|
|
14686
|
+
Environment=XDG_CONFIG_HOME=%h/.config
|
|
14687
|
+
Environment=TRUSTY_SQUIRE_BROKER_SOCKET=%h/.trusty-squire/broker.sock
|
|
14688
|
+
ExecStartPre=/bin/mkdir -p %h/.trusty-squire
|
|
14689
|
+
ExecStart=%h/.local/bin/beeline ${SQUIRE_BROKER_FLAG}
|
|
14690
|
+
Restart=on-failure
|
|
14691
|
+
RestartSec=5s
|
|
14692
|
+
UMask=0077
|
|
14693
|
+
NoNewPrivileges=yes
|
|
14694
|
+
|
|
14695
|
+
[Install]
|
|
14696
|
+
WantedBy=default.target
|
|
14697
|
+
`;
|
|
14698
|
+
}
|
|
14699
|
+
function spawnSquireServer(env, locateNpx) {
|
|
14700
|
+
const launch = locateNpx ? squireServerCommand() : { command: "npx", args: [...SQUIRE_SERVER_ARGS], pathPrefix: "" };
|
|
14701
|
+
const path = [launch.pathPrefix, env.PATH || "/usr/bin:/bin"].filter(Boolean).join(":");
|
|
14702
|
+
const child = spawn3(launch.command, launch.args, {
|
|
14703
|
+
env: { ...env, PATH: path },
|
|
14704
|
+
stdio: "inherit"
|
|
14705
|
+
});
|
|
14706
|
+
child.on("exit", (code, signal) => {
|
|
14707
|
+
if (signal)
|
|
14708
|
+
process.exit(1);
|
|
14709
|
+
process.exit(code ?? 1);
|
|
14710
|
+
});
|
|
14711
|
+
}
|
|
14712
|
+
function runSquireBroker(env = process.env) {
|
|
14713
|
+
const home = env.HOME?.trim() || homedir2();
|
|
14714
|
+
const paths = ensureSquireHostDir(home);
|
|
14715
|
+
spawnSquireServer({ ...env, ...squireHostRewriteEnv(home), TRUSTY_SQUIRE_BROKER_SOCKET: paths.brokerSocket }, true);
|
|
14716
|
+
}
|
|
14717
|
+
function runSquireFacade(env = process.env) {
|
|
14718
|
+
const socket = env.TRUSTY_SQUIRE_BROKER_SOCKET ?? squireHostPaths(env.HOME?.trim() || homedir2()).brokerSocket;
|
|
14719
|
+
if (!squireBrokerSocketReady(socket)) {
|
|
14720
|
+
process.stderr.write(`${SQUIRE_BROKER_UNAVAILABLE}
|
|
14721
|
+
`);
|
|
14722
|
+
process.exitCode = 1;
|
|
14723
|
+
return;
|
|
14724
|
+
}
|
|
14725
|
+
spawnSquireServer({ ...env, TRUSTY_SQUIRE_BROKER_SOCKET: socket }, false);
|
|
14726
|
+
}
|
|
14727
|
+
|
|
14577
14728
|
// packages/api-contract/dist/agent-access.js
|
|
14578
14729
|
var AGENT_ACCESS_POLICIES = ["everyone", "creator", "allowlist"];
|
|
14579
14730
|
var DEFAULT_AGENT_ACCESS_POLICY = "everyone";
|
|
@@ -14590,10 +14741,10 @@ var ACCESS_REFUSAL_WINDOW_MS = 60 * 60 * 1e3;
|
|
|
14590
14741
|
// apps/body/dist/model-catalog.js
|
|
14591
14742
|
import { mkdtemp, rm } from "node:fs/promises";
|
|
14592
14743
|
import { tmpdir } from "node:os";
|
|
14593
|
-
import { resolve as
|
|
14744
|
+
import { resolve as resolve5 } from "node:path";
|
|
14594
14745
|
|
|
14595
14746
|
// apps/body/dist/acp.js
|
|
14596
|
-
import { spawn as
|
|
14747
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
14597
14748
|
import { EventEmitter } from "node:events";
|
|
14598
14749
|
|
|
14599
14750
|
// apps/body/dist/harness-capabilities.js
|
|
@@ -14656,7 +14807,7 @@ var PROFILES = [
|
|
|
14656
14807
|
match: /(^|[/\\])pi-acp(\.[a-z]+)?$/i,
|
|
14657
14808
|
profile: {
|
|
14658
14809
|
enforcement: "config-isolated",
|
|
14659
|
-
note: "pi-acp
|
|
14810
|
+
note: "pi-acp 0.0.33 still stores session/new mcpServers and never reads them; pi 0.85.1 itself has no MCP client, while optional pi-mcp-adapter reads $PI_CODING_AGENT_DIR/mcp.json and isolated homes exclude the settings.json that would load it"
|
|
14660
14811
|
}
|
|
14661
14812
|
},
|
|
14662
14813
|
{
|
|
@@ -14814,6 +14965,11 @@ function agentMessageChunkText(update) {
|
|
|
14814
14965
|
return "";
|
|
14815
14966
|
}
|
|
14816
14967
|
var CHUNK_CONTINUES_PREVIOUS_WORD = /^[\s'\u2018\u2019\u02bc.,!?;:%)\]}-]/;
|
|
14968
|
+
function continuesPreviousWord(current, delta) {
|
|
14969
|
+
if (/\s$/.test(current))
|
|
14970
|
+
return false;
|
|
14971
|
+
return CHUNK_CONTINUES_PREVIOUS_WORD.test(delta);
|
|
14972
|
+
}
|
|
14817
14973
|
var PI_ACP_HARNESS = /(^|[/\\])pi-acp(?:\.[a-z]+)?$/i;
|
|
14818
14974
|
function isPiAcpHarness(agentLabel) {
|
|
14819
14975
|
return Boolean(agentLabel && PI_ACP_HARNESS.test(agentLabel));
|
|
@@ -14826,17 +14982,12 @@ function agentMessageRuns(updates, agentLabel) {
|
|
|
14826
14982
|
let current = "";
|
|
14827
14983
|
let lastWasText = false;
|
|
14828
14984
|
for (const u4 of updates) {
|
|
14829
|
-
const isToolCall = u4.update.sessionUpdate === "tool_call";
|
|
14830
14985
|
const delta = normalizeStreamDelta(agentMessageChunkText(u4.update), agentLabel);
|
|
14831
14986
|
if (!delta) {
|
|
14832
|
-
if (isToolCall && current) {
|
|
14833
|
-
runs.push(current);
|
|
14834
|
-
current = "";
|
|
14835
|
-
}
|
|
14836
14987
|
lastWasText = false;
|
|
14837
14988
|
continue;
|
|
14838
14989
|
}
|
|
14839
|
-
if (!lastWasText && current &&
|
|
14990
|
+
if (!lastWasText && current && !continuesPreviousWord(current, delta)) {
|
|
14840
14991
|
runs.push(current);
|
|
14841
14992
|
current = "";
|
|
14842
14993
|
}
|
|
@@ -15041,7 +15192,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
15041
15192
|
async start(timeoutMs = 6e4) {
|
|
15042
15193
|
if (this.alive)
|
|
15043
15194
|
return;
|
|
15044
|
-
this.child =
|
|
15195
|
+
this.child = spawn4(this.agentCommand, this.agentArgs, {
|
|
15045
15196
|
// agentEnv is the child's whole environment: buildAgentEnv's allowlist is
|
|
15046
15197
|
// a real boundary, not a decorative one layered over a full inherit.
|
|
15047
15198
|
env: this.inheritProcessEnv ? { ...process.env, ...this.agentEnv } : this.agentEnv,
|
|
@@ -15458,7 +15609,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
15458
15609
|
const current = this.activeRunIds.get(sessionId);
|
|
15459
15610
|
if (current)
|
|
15460
15611
|
return Promise.resolve(current);
|
|
15461
|
-
return new Promise((
|
|
15612
|
+
return new Promise((resolve35, reject) => {
|
|
15462
15613
|
const onUpdate = (update) => {
|
|
15463
15614
|
if (update.sessionId !== sessionId)
|
|
15464
15615
|
return;
|
|
@@ -15466,7 +15617,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
15466
15617
|
if (!runId)
|
|
15467
15618
|
return;
|
|
15468
15619
|
cleanup();
|
|
15469
|
-
|
|
15620
|
+
resolve35(runId);
|
|
15470
15621
|
};
|
|
15471
15622
|
const timer = setTimeout(() => {
|
|
15472
15623
|
cleanup();
|
|
@@ -15550,13 +15701,13 @@ var AcpClient = class extends EventEmitter {
|
|
|
15550
15701
|
}
|
|
15551
15702
|
const id = this.nextId++;
|
|
15552
15703
|
const payload = { jsonrpc: "2.0", id, method, params };
|
|
15553
|
-
return new Promise((
|
|
15704
|
+
return new Promise((resolve35, reject) => {
|
|
15554
15705
|
const timer = setTimeout(() => {
|
|
15555
15706
|
this.pending.delete(id);
|
|
15556
15707
|
reject(new AcpRequestTimeoutError(method, timeoutMs, this.stderrTail, Boolean(onStart), detail));
|
|
15557
15708
|
}, timeoutMs);
|
|
15558
15709
|
this.pending.set(id, {
|
|
15559
|
-
resolve:
|
|
15710
|
+
resolve: resolve35,
|
|
15560
15711
|
reject,
|
|
15561
15712
|
timer,
|
|
15562
15713
|
method,
|
|
@@ -15584,8 +15735,8 @@ function isAllowedAgentModelConfigCategory(category) {
|
|
|
15584
15735
|
}
|
|
15585
15736
|
|
|
15586
15737
|
// apps/body/dist/model-config.js
|
|
15587
|
-
import { lstatSync, readFileSync as readFileSync2 } from "node:fs";
|
|
15588
|
-
import { basename as basename3, resolve as
|
|
15738
|
+
import { lstatSync as lstatSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
15739
|
+
import { basename as basename3, resolve as resolve4 } from "node:path";
|
|
15589
15740
|
var GROK_SESSION_MODEL_AXIS_ID = "beeline:grok-session-model";
|
|
15590
15741
|
var GROK_LAUNCH_EFFORT_AXIS_ID = "beeline:grok-launch-reasoning-effort";
|
|
15591
15742
|
function isGrokAgentCommand(agent) {
|
|
@@ -15754,13 +15905,13 @@ function credentialedProviders(env) {
|
|
|
15754
15905
|
return held;
|
|
15755
15906
|
}
|
|
15756
15907
|
function credentialedPiCustomProviders(env) {
|
|
15757
|
-
const agentDir = env.PI_CODING_AGENT_DIR?.trim() ?
|
|
15908
|
+
const agentDir = env.PI_CODING_AGENT_DIR?.trim() ? resolve4(env.PI_CODING_AGENT_DIR) : env.HOME?.trim() ? resolve4(env.HOME, ".pi/agent") : void 0;
|
|
15758
15909
|
const held = /* @__PURE__ */ new Set();
|
|
15759
15910
|
if (!agentDir)
|
|
15760
15911
|
return held;
|
|
15761
|
-
const path =
|
|
15912
|
+
const path = resolve4(agentDir, "models.json");
|
|
15762
15913
|
try {
|
|
15763
|
-
const stats =
|
|
15914
|
+
const stats = lstatSync2(path);
|
|
15764
15915
|
if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1 || stats.size > 1048576) {
|
|
15765
15916
|
return held;
|
|
15766
15917
|
}
|
|
@@ -15906,7 +16057,7 @@ function modelCatalogProbeEnvironment(agent, agentEnv, scratchCwd) {
|
|
|
15906
16057
|
return agentEnv;
|
|
15907
16058
|
return {
|
|
15908
16059
|
...agentEnv,
|
|
15909
|
-
GOOSE_PATH_ROOT:
|
|
16060
|
+
GOOSE_PATH_ROOT: resolve5(scratchCwd, "goose")
|
|
15910
16061
|
};
|
|
15911
16062
|
}
|
|
15912
16063
|
function filterAgentModelCatalog(agent, raw, agentEnv) {
|
|
@@ -15916,7 +16067,7 @@ function filterAgentModelCatalog(agent, raw, agentEnv) {
|
|
|
15916
16067
|
async function withAgentModelCatalog(agent, agentEnv, selection, inspect, limits = {}) {
|
|
15917
16068
|
const deadline = limits.timeoutMs === void 0 ? void 0 : Date.now() + limits.timeoutMs;
|
|
15918
16069
|
const remaining = () => deadline === void 0 ? void 0 : Math.max(1, deadline - Date.now());
|
|
15919
|
-
const scratchCwd = await mkdtemp(
|
|
16070
|
+
const scratchCwd = await mkdtemp(resolve5(tmpdir(), "beeline-pair-model-check-"));
|
|
15920
16071
|
const probeEnv = modelCatalogProbeEnvironment(agent, agentEnv, scratchCwd);
|
|
15921
16072
|
const client = new AcpClient({
|
|
15922
16073
|
agentCommand: agent.command,
|
|
@@ -16016,7 +16167,7 @@ async function applyRuntimeModelPreflight(config, agent, selection, validate = v
|
|
|
16016
16167
|
// apps/body/dist/model-catalog-sync.js
|
|
16017
16168
|
import { createHash } from "node:crypto";
|
|
16018
16169
|
import { readFile, writeFile as writeFile2 } from "node:fs/promises";
|
|
16019
|
-
import { resolve as
|
|
16170
|
+
import { resolve as resolve6 } from "node:path";
|
|
16020
16171
|
var MODEL_CATALOG_PROBE_TIMEOUT_MS = 3e4;
|
|
16021
16172
|
var MODEL_CATALOG_HASH_FILE = "model-catalog.sha256";
|
|
16022
16173
|
function modelCatalogHash(options, selection, startupUnavailable) {
|
|
@@ -16041,7 +16192,7 @@ async function withTimeout(work, timeoutMs, what) {
|
|
|
16041
16192
|
async function syncAgentModelCatalog(input) {
|
|
16042
16193
|
const log2 = input.log ?? ((line) => console.log(line));
|
|
16043
16194
|
const fetchCatalog = input.fetchCatalog ?? fetchAgentModelCatalog;
|
|
16044
|
-
const hashPath =
|
|
16195
|
+
const hashPath = resolve6(input.runtimeDir, MODEL_CATALOG_HASH_FILE);
|
|
16045
16196
|
try {
|
|
16046
16197
|
const configuration = await input.api.execute("getAgentConfiguration", {
|
|
16047
16198
|
agentId: input.agentId
|
|
@@ -16075,8 +16226,8 @@ async function syncAgentModelCatalog(input) {
|
|
|
16075
16226
|
}
|
|
16076
16227
|
|
|
16077
16228
|
// apps/body/dist/connector-google.js
|
|
16078
|
-
import { mkdirSync, readFileSync as readFileSync4, writeFileSync } from "node:fs";
|
|
16079
|
-
import { dirname as
|
|
16229
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync } from "node:fs";
|
|
16230
|
+
import { dirname as dirname5, join as join4 } from "node:path";
|
|
16080
16231
|
|
|
16081
16232
|
// apps/body/dist/google-workspace-client.js
|
|
16082
16233
|
function credentialsTokenSource(credentials) {
|
|
@@ -16451,11 +16602,11 @@ function googleWorkspaceClient(tokenSource, transport = defaultGoogleApiTranspor
|
|
|
16451
16602
|
}
|
|
16452
16603
|
|
|
16453
16604
|
// apps/body/dist/connector-squire.js
|
|
16454
|
-
import { execFile, spawn as
|
|
16605
|
+
import { execFile, spawn as spawn5 } from "node:child_process";
|
|
16455
16606
|
import { createHash as createHash2 } from "node:crypto";
|
|
16456
|
-
import { lstatSync as
|
|
16457
|
-
import { homedir as
|
|
16458
|
-
import { basename as basename4, dirname as
|
|
16607
|
+
import { lstatSync as lstatSync3, readFileSync as readFileSync3, realpathSync, rmSync } from "node:fs";
|
|
16608
|
+
import { homedir as homedir3, hostname, tmpdir as tmpdir2 } from "node:os";
|
|
16609
|
+
import { basename as basename4, dirname as dirname4, join as join3, resolve as resolve7 } from "node:path";
|
|
16459
16610
|
var SQUIRE_MCP_NAME = "@trusty-squire/mcp";
|
|
16460
16611
|
var SQUIRE_CONNECT_PACKAGE = `${SQUIRE_MCP_NAME}@latest`;
|
|
16461
16612
|
var activeConnectSession;
|
|
@@ -16485,17 +16636,17 @@ function releaseSquireConnectSession(log2) {
|
|
|
16485
16636
|
}
|
|
16486
16637
|
}
|
|
16487
16638
|
function squireChromeProfileDir() {
|
|
16488
|
-
return process.env.TRUSTY_SQUIRE_PROFILE_DIR ??
|
|
16639
|
+
return process.env.TRUSTY_SQUIRE_PROFILE_DIR ?? squireHostPaths(homedir3()).profileDir;
|
|
16489
16640
|
}
|
|
16490
16641
|
function squireProfilePathIdentity(profileDir) {
|
|
16491
|
-
const absolute =
|
|
16642
|
+
const absolute = resolve7(profileDir);
|
|
16492
16643
|
const suffix = [];
|
|
16493
16644
|
let candidate = absolute;
|
|
16494
16645
|
for (; ; ) {
|
|
16495
16646
|
try {
|
|
16496
|
-
return
|
|
16647
|
+
return join3(realpathSync.native(candidate), ...suffix.reverse());
|
|
16497
16648
|
} catch {
|
|
16498
|
-
const parent =
|
|
16649
|
+
const parent = dirname4(candidate);
|
|
16499
16650
|
if (parent === candidate)
|
|
16500
16651
|
return absolute;
|
|
16501
16652
|
suffix.push(basename4(candidate));
|
|
@@ -16505,7 +16656,7 @@ function squireProfilePathIdentity(profileDir) {
|
|
|
16505
16656
|
}
|
|
16506
16657
|
function squireProfileLockPath(profileDir = squireChromeProfileDir(), lockRoot = tmpdir2()) {
|
|
16507
16658
|
const digest = createHash2("sha256").update(squireProfilePathIdentity(profileDir)).digest("hex").slice(0, 24);
|
|
16508
|
-
return
|
|
16659
|
+
return join3(lockRoot, `trusty-squire-profile-${digest}.lock`);
|
|
16509
16660
|
}
|
|
16510
16661
|
var SQUIRE_BROWSER_BUSY_GOOGLE_REASON = "Trusty Squire is still using the browser \u2014 connect Trusty Squire first";
|
|
16511
16662
|
function isSquireBrowserSessionFailure(text2) {
|
|
@@ -16537,7 +16688,7 @@ function lockOwnerIsAlive(owner) {
|
|
|
16537
16688
|
}
|
|
16538
16689
|
function readLockFileOwner(lockPath) {
|
|
16539
16690
|
try {
|
|
16540
|
-
const target =
|
|
16691
|
+
const target = lstatSync3(lockPath).isDirectory() ? join3(lockPath, "owner.json") : lockPath;
|
|
16541
16692
|
const parsed = JSON.parse(readFileSync3(target, "utf8"));
|
|
16542
16693
|
if (typeof parsed.host !== "string" || typeof parsed.pid !== "number")
|
|
16543
16694
|
return void 0;
|
|
@@ -16576,10 +16727,10 @@ function reclaimSquireProfileClaim(options) {
|
|
|
16576
16727
|
options?.log?.(`cleared dead trusty-squire on-disk browser claim (pid ${owner.pid} gone)`);
|
|
16577
16728
|
return { kind: "reclaimed-dead", owner };
|
|
16578
16729
|
}
|
|
16579
|
-
var defaultShellRunner = (command, args) => new Promise((
|
|
16730
|
+
var defaultShellRunner = (command, args) => new Promise((resolve35) => {
|
|
16580
16731
|
execFile(command, [...args], { timeout: 12e4, maxBuffer: 4 * 1024 * 1024, encoding: "utf8" }, (error, stdout6, stderr) => {
|
|
16581
16732
|
const code = error?.code;
|
|
16582
|
-
|
|
16733
|
+
resolve35({
|
|
16583
16734
|
code: typeof code === "number" ? code : error ? 1 : 0,
|
|
16584
16735
|
stdout: String(stdout6 ?? ""),
|
|
16585
16736
|
stderr: String(stderr ?? "")
|
|
@@ -16589,6 +16740,7 @@ var defaultShellRunner = (command, args) => new Promise((resolve33) => {
|
|
|
16589
16740
|
function squireConnectProcessEnv(profileDir = squireChromeProfileDir()) {
|
|
16590
16741
|
return {
|
|
16591
16742
|
...process.env,
|
|
16743
|
+
...squireHostRewriteEnv(homedir3()),
|
|
16592
16744
|
TRUSTY_SQUIRE_PROFILE_DIR: profileDir
|
|
16593
16745
|
};
|
|
16594
16746
|
}
|
|
@@ -16603,8 +16755,8 @@ function killConnectTree(child) {
|
|
|
16603
16755
|
}
|
|
16604
16756
|
child.kill();
|
|
16605
16757
|
}
|
|
16606
|
-
var defaultStreamedRunner = (command, args, env) => new Promise((
|
|
16607
|
-
const child =
|
|
16758
|
+
var defaultStreamedRunner = (command, args, env) => new Promise((resolve35) => {
|
|
16759
|
+
const child = spawn5(command, args, {
|
|
16608
16760
|
stdio: ["ignore", "pipe", "pipe"],
|
|
16609
16761
|
env: env ?? squireConnectProcessEnv(),
|
|
16610
16762
|
detached: true
|
|
@@ -16615,7 +16767,7 @@ var defaultStreamedRunner = (command, args, env) => new Promise((resolve33) => {
|
|
|
16615
16767
|
const safetyTimer = setTimeout(() => {
|
|
16616
16768
|
if (!resolved) {
|
|
16617
16769
|
resolved = true;
|
|
16618
|
-
|
|
16770
|
+
resolve35({ stdout: stdout6, stderr, pid: child.pid ?? void 0, signIn: void 0, abort: () => {
|
|
16619
16771
|
} });
|
|
16620
16772
|
}
|
|
16621
16773
|
killConnectTree(child);
|
|
@@ -16633,18 +16785,22 @@ var defaultStreamedRunner = (command, args, env) => new Promise((resolve33) => {
|
|
|
16633
16785
|
const finish = (result) => {
|
|
16634
16786
|
if (!resolved) {
|
|
16635
16787
|
resolved = true;
|
|
16636
|
-
|
|
16637
|
-
resolve33(result);
|
|
16788
|
+
resolve35(result);
|
|
16638
16789
|
}
|
|
16639
16790
|
};
|
|
16791
|
+
const settle = (result) => {
|
|
16792
|
+
clearTimeout(safetyTimer);
|
|
16793
|
+
finish(result);
|
|
16794
|
+
};
|
|
16640
16795
|
const checkOutput = () => {
|
|
16641
|
-
const
|
|
16642
|
-
${stderr}`;
|
|
16643
|
-
const signIn = parseConnectOutput(combined);
|
|
16796
|
+
const signIn = parseConnectOutput(stdout6) ?? parseConnectOutput(stderr);
|
|
16644
16797
|
if (signIn) {
|
|
16645
16798
|
finish({ stdout: stdout6, stderr, signIn, abort });
|
|
16646
16799
|
}
|
|
16647
16800
|
};
|
|
16801
|
+
const finalSignIn = () => parseConnectOutput(`${stdout6}
|
|
16802
|
+
`) ?? parseConnectOutput(`${stderr}
|
|
16803
|
+
`);
|
|
16648
16804
|
child.stdout?.on("data", (chunk) => {
|
|
16649
16805
|
stdout6 += String(chunk);
|
|
16650
16806
|
checkOutput();
|
|
@@ -16654,11 +16810,17 @@ ${stderr}`;
|
|
|
16654
16810
|
checkOutput();
|
|
16655
16811
|
});
|
|
16656
16812
|
child.on("close", () => {
|
|
16657
|
-
|
|
16658
|
-
|
|
16813
|
+
settle({
|
|
16814
|
+
stdout: stdout6,
|
|
16815
|
+
stderr,
|
|
16816
|
+
pid: child.pid ?? void 0,
|
|
16817
|
+
signIn: finalSignIn(),
|
|
16818
|
+
abort: () => {
|
|
16819
|
+
}
|
|
16820
|
+
});
|
|
16659
16821
|
});
|
|
16660
16822
|
child.on("error", () => {
|
|
16661
|
-
|
|
16823
|
+
settle({ stdout: stdout6, stderr, pid: child.pid ?? void 0, signIn: void 0, abort: () => {
|
|
16662
16824
|
} });
|
|
16663
16825
|
});
|
|
16664
16826
|
});
|
|
@@ -16667,17 +16829,84 @@ var step = (label, status, reason) => ({
|
|
|
16667
16829
|
status,
|
|
16668
16830
|
...reason ? { reason } : {}
|
|
16669
16831
|
});
|
|
16670
|
-
function
|
|
16671
|
-
|
|
16672
|
-
|
|
16673
|
-
|
|
16674
|
-
|
|
16675
|
-
return
|
|
16832
|
+
function isKnownCeremonySurface(url) {
|
|
16833
|
+
try {
|
|
16834
|
+
const parsed = new URL(url);
|
|
16835
|
+
if (parsed.protocol !== "https:")
|
|
16836
|
+
return false;
|
|
16837
|
+
return parsed.hash.startsWith("#p=") || /(^|\/)install(\/|$)/.test(parsed.pathname);
|
|
16838
|
+
} catch {
|
|
16839
|
+
return false;
|
|
16840
|
+
}
|
|
16841
|
+
}
|
|
16842
|
+
function isForeignUrl(url) {
|
|
16843
|
+
try {
|
|
16844
|
+
const parsed = new URL(url);
|
|
16845
|
+
const host = parsed.hostname.toLowerCase();
|
|
16846
|
+
if (host === "developers.cloudflare.com")
|
|
16847
|
+
return true;
|
|
16848
|
+
if (host === "github.com" && parsed.pathname.toLowerCase().startsWith("/npm/cli"))
|
|
16849
|
+
return true;
|
|
16850
|
+
return host === "npmjs.com" || host === "www.npmjs.com";
|
|
16851
|
+
} catch {
|
|
16852
|
+
return true;
|
|
16853
|
+
}
|
|
16854
|
+
}
|
|
16855
|
+
var BOXED_ROW = /^\s*\u2502(.*)\u2502\s*$/;
|
|
16856
|
+
var BOX_BORDER = /^\s*[\u2500-\u257F]+\s*$/;
|
|
16857
|
+
function rejoinBoxRows(cells) {
|
|
16858
|
+
const written = cells.filter((cell) => cell.trim() !== "");
|
|
16859
|
+
const pad2 = (measure) => written.length === 0 ? 0 : Math.min(...written.map(measure));
|
|
16860
|
+
const left = pad2((cell) => cell.length - cell.trimStart().length);
|
|
16861
|
+
const right = pad2((cell) => cell.length - cell.trimEnd().length);
|
|
16862
|
+
const lines = [];
|
|
16863
|
+
let carry;
|
|
16864
|
+
for (const cell of cells) {
|
|
16865
|
+
const content = cell.slice(left, cell.length - right);
|
|
16866
|
+
const text2 = content.replace(/\s+$/, "");
|
|
16867
|
+
carry = (carry ?? "") + text2;
|
|
16868
|
+
if (text2.length < content.length) {
|
|
16869
|
+
lines.push(carry);
|
|
16870
|
+
carry = void 0;
|
|
16871
|
+
}
|
|
16676
16872
|
}
|
|
16677
|
-
if (
|
|
16678
|
-
|
|
16873
|
+
if (carry !== void 0)
|
|
16874
|
+
lines.push(carry);
|
|
16875
|
+
return lines;
|
|
16876
|
+
}
|
|
16877
|
+
function unframeBoxedOutput(output) {
|
|
16878
|
+
const lines = [];
|
|
16879
|
+
let box = [];
|
|
16880
|
+
for (const row of output.split("\n")) {
|
|
16881
|
+
const framed = BOXED_ROW.exec(row);
|
|
16882
|
+
if (framed) {
|
|
16883
|
+
box.push(framed[1] ?? "");
|
|
16884
|
+
continue;
|
|
16885
|
+
}
|
|
16886
|
+
if (box.length > 0 && BOX_BORDER.test(row))
|
|
16887
|
+
lines.push(...rejoinBoxRows(box));
|
|
16888
|
+
box = [];
|
|
16889
|
+
lines.push(row);
|
|
16679
16890
|
}
|
|
16680
|
-
return
|
|
16891
|
+
return lines.join("\n");
|
|
16892
|
+
}
|
|
16893
|
+
function parseConnectOutput(output) {
|
|
16894
|
+
const urls = unframeBoxedOutput(output).match(/https:\/\/[^\s"'<>]+(?=[\s"'<>])/g) ?? [];
|
|
16895
|
+
const preferred = urls.find(isKnownCeremonySurface);
|
|
16896
|
+
if (preferred)
|
|
16897
|
+
return { method: "streamed-page", url: preferred };
|
|
16898
|
+
const fallback = urls.find((url) => !isForeignUrl(url));
|
|
16899
|
+
if (fallback) {
|
|
16900
|
+
console.log(`[body] squire connect: no known ceremony surface matched; using fallback URL ${fallback}`);
|
|
16901
|
+
return { method: "streamed-page", url: fallback };
|
|
16902
|
+
}
|
|
16903
|
+
return void 0;
|
|
16904
|
+
}
|
|
16905
|
+
function parseConnectAlreadyConnected(output) {
|
|
16906
|
+
return /Already connected \(/i.test(output) && /config refreshed/i.test(output);
|
|
16907
|
+
}
|
|
16908
|
+
function withoutForceReloginHint(output) {
|
|
16909
|
+
return output.split("\n").filter((line) => !/--force-relogin/.test(line)).join("\n").trim();
|
|
16681
16910
|
}
|
|
16682
16911
|
async function installedSquireVersion(run2, spec = SQUIRE_CONNECT_PACKAGE, preferOnline = false) {
|
|
16683
16912
|
const probe = await run2("npx", [
|
|
@@ -16760,15 +16989,11 @@ async function installSquire(options) {
|
|
|
16760
16989
|
if (resolution.reResolved) {
|
|
16761
16990
|
log2(`trusty-squire stale copy ${resolution.resolvedVersion ?? "unknown"} re-resolved against current release ${resolution.currentRelease}`);
|
|
16762
16991
|
}
|
|
16763
|
-
const install = await streamRun("npx", [
|
|
16764
|
-
|
|
16765
|
-
|
|
16766
|
-
|
|
16767
|
-
|
|
16768
|
-
"--skip-browser"
|
|
16769
|
-
], squireConnectProcessEnv(profileDir));
|
|
16770
|
-
if (!install.signIn) {
|
|
16771
|
-
const stderr = install.stderr.trim();
|
|
16992
|
+
const install = await streamRun("npx", [...resolution.npxArgs, "connect", "--target=codex"], squireConnectProcessEnv(profileDir));
|
|
16993
|
+
const alreadyConnected = !install.signIn && parseConnectAlreadyConnected(`${install.stdout}
|
|
16994
|
+
${install.stderr}`);
|
|
16995
|
+
if (!install.signIn && !alreadyConnected) {
|
|
16996
|
+
const stderr = withoutForceReloginHint(install.stderr);
|
|
16772
16997
|
let stepReason = stderr || "connect printed no sign-in URL";
|
|
16773
16998
|
let failReason = stderr || "the trusty-squire connect command printed no sign-in surface";
|
|
16774
16999
|
if (isSquireBrowserSessionFailure(stderr)) {
|
|
@@ -16786,7 +17011,7 @@ async function installSquire(options) {
|
|
|
16786
17011
|
const signIn = install.signIn;
|
|
16787
17012
|
const signedInAs = parseSignedInAs(`${install.stdout}
|
|
16788
17013
|
${install.stderr}`);
|
|
16789
|
-
push(step("waiting for sign-in", "done"));
|
|
17014
|
+
push(step("waiting for sign-in", signIn ? "pending" : "done"));
|
|
16790
17015
|
const pair = await pairSquire(options.mcp, options.workspaceId);
|
|
16791
17016
|
if (!pair.ok) {
|
|
16792
17017
|
push(step("paired to workspace", "failed", pair.reason));
|
|
@@ -16799,10 +17024,18 @@ ${install.stderr}`);
|
|
|
16799
17024
|
};
|
|
16800
17025
|
}
|
|
16801
17026
|
push(step("paired to workspace", "done"));
|
|
17027
|
+
if (signIn) {
|
|
17028
|
+
return {
|
|
17029
|
+
status: "installing",
|
|
17030
|
+
steps,
|
|
17031
|
+
signIn,
|
|
17032
|
+
...version ? { squireVersion: version } : {},
|
|
17033
|
+
...signedInAs ? { signedInAs } : {}
|
|
17034
|
+
};
|
|
17035
|
+
}
|
|
16802
17036
|
return {
|
|
16803
17037
|
status: "connected",
|
|
16804
17038
|
steps,
|
|
16805
|
-
signIn,
|
|
16806
17039
|
...version ? { squireVersion: version } : {},
|
|
16807
17040
|
...signedInAs ? { signedInAs } : {}
|
|
16808
17041
|
};
|
|
@@ -16829,6 +17062,15 @@ function stringList(value) {
|
|
|
16829
17062
|
function numberOrNull(value) {
|
|
16830
17063
|
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
16831
17064
|
}
|
|
17065
|
+
function epochSeconds(value) {
|
|
17066
|
+
const numeric = numberOrNull(value);
|
|
17067
|
+
if (numeric !== null)
|
|
17068
|
+
return numeric;
|
|
17069
|
+
if (typeof value !== "string")
|
|
17070
|
+
return null;
|
|
17071
|
+
const parsed = Date.parse(value);
|
|
17072
|
+
return Number.isNaN(parsed) ? null : Math.floor(parsed / 1e3);
|
|
17073
|
+
}
|
|
16832
17074
|
function vaultConnectionMeta(raw) {
|
|
16833
17075
|
const record3 = asRecord2(raw);
|
|
16834
17076
|
const reference = String(record3.reference ?? record3.id ?? "");
|
|
@@ -16838,7 +17080,7 @@ function vaultConnectionMeta(raw) {
|
|
|
16838
17080
|
label: String(record3.label ?? record3.service ?? reference),
|
|
16839
17081
|
fieldNames: stringList(record3.field_names ?? record3.fieldNames),
|
|
16840
17082
|
allowedHosts: stringList(record3.allowed_hosts ?? record3.allowedHosts ?? record3.login_hosts),
|
|
16841
|
-
createdAt:
|
|
17083
|
+
createdAt: epochSeconds(record3.created_at ?? record3.createdAt) ?? 0,
|
|
16842
17084
|
stale: record3.stale === true,
|
|
16843
17085
|
state: record3.state === "error" ? "error" : "active"
|
|
16844
17086
|
};
|
|
@@ -16933,7 +17175,7 @@ async function readGoogleCredentialsFromVault(mcp) {
|
|
|
16933
17175
|
};
|
|
16934
17176
|
}
|
|
16935
17177
|
function manualGoogleCredentialsSearchPaths(home) {
|
|
16936
|
-
return [
|
|
17178
|
+
return [join4(home, "google-credentials.json")];
|
|
16937
17179
|
}
|
|
16938
17180
|
function loadManualGoogleCredentials(home, env = process.env) {
|
|
16939
17181
|
if (env.BEELINE_GOOGLE_ACCESS_TOKEN) {
|
|
@@ -16966,7 +17208,7 @@ function loadManualGoogleCredentials(home, env = process.env) {
|
|
|
16966
17208
|
}
|
|
16967
17209
|
function persistManualGoogleCredentials(home, credentials) {
|
|
16968
17210
|
const path = manualGoogleCredentialsSearchPaths(home)[0];
|
|
16969
|
-
|
|
17211
|
+
mkdirSync2(dirname5(path), { recursive: true, mode: 448 });
|
|
16970
17212
|
writeFileSync(path, `${JSON.stringify({
|
|
16971
17213
|
accessToken: credentials.accessToken,
|
|
16972
17214
|
...credentials.refreshToken ? { refreshToken: credentials.refreshToken } : {},
|
|
@@ -17044,10 +17286,10 @@ function describe(error) {
|
|
|
17044
17286
|
}
|
|
17045
17287
|
|
|
17046
17288
|
// apps/body/dist/squire-mcp-client.js
|
|
17047
|
-
import { spawn as
|
|
17289
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
17290
|
+
import { homedir as homedir4 } from "node:os";
|
|
17048
17291
|
var INITIALIZE_TIMEOUT_MS = 3e4;
|
|
17049
17292
|
var CALL_TIMEOUT_MS = 12e4;
|
|
17050
|
-
var SQUIRE_MCP_SERVER_ARGS = ["-y", "@trusty-squire/mcp@latest", "server"];
|
|
17051
17293
|
var StdioSquireMcpClient = class {
|
|
17052
17294
|
options;
|
|
17053
17295
|
child;
|
|
@@ -17101,7 +17343,8 @@ var StdioSquireMcpClient = class {
|
|
|
17101
17343
|
return this.initialized;
|
|
17102
17344
|
}
|
|
17103
17345
|
initialize() {
|
|
17104
|
-
const
|
|
17346
|
+
const launch = squireFacadeLaunch(homedir4());
|
|
17347
|
+
const child = (this.options.spawn ?? spawn6)(this.options.command ?? launch.command, [...this.options.args ?? launch.args], { env: this.options.env ?? { ...squireConnectProcessEnv(), ...launch.env } });
|
|
17105
17348
|
this.child = child;
|
|
17106
17349
|
this.buffer = "";
|
|
17107
17350
|
child.stdout.setEncoding("utf8");
|
|
@@ -17135,12 +17378,12 @@ var StdioSquireMcpClient = class {
|
|
|
17135
17378
|
const child = this.child;
|
|
17136
17379
|
if (!child)
|
|
17137
17380
|
return Promise.reject(new Error("Squire MCP session is not running"));
|
|
17138
|
-
return new Promise((
|
|
17381
|
+
return new Promise((resolve35, reject) => {
|
|
17139
17382
|
const timer = setTimeout(() => {
|
|
17140
17383
|
this.pending.delete(id);
|
|
17141
17384
|
reject(new Error(`${method} timed out`));
|
|
17142
17385
|
}, method === "initialize" ? INITIALIZE_TIMEOUT_MS : CALL_TIMEOUT_MS);
|
|
17143
|
-
this.pending.set(id, { resolve:
|
|
17386
|
+
this.pending.set(id, { resolve: resolve35, reject, timer });
|
|
17144
17387
|
child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, params })}
|
|
17145
17388
|
`);
|
|
17146
17389
|
});
|
|
@@ -17184,6 +17427,7 @@ function defaultSquireMcpClient() {
|
|
|
17184
17427
|
|
|
17185
17428
|
// apps/body/dist/connector-assignments.js
|
|
17186
17429
|
var CONNECTOR_POLL_INTERVAL_MS = 1e4;
|
|
17430
|
+
var CEREMONY_EXPIRED = "the Trusty Squire sign-in page expired before it was used \xB7 tap Retry to open a new one";
|
|
17187
17431
|
var ConnectorAssignmentLoop = class {
|
|
17188
17432
|
agentId;
|
|
17189
17433
|
api;
|
|
@@ -17356,6 +17600,25 @@ var ConnectorAssignmentLoop = class {
|
|
|
17356
17600
|
}
|
|
17357
17601
|
/** Install Trusty Squire, reporting every step as it settles. */
|
|
17358
17602
|
async runInstall(connectorId) {
|
|
17603
|
+
const claim = squireConnectSession();
|
|
17604
|
+
const spent = claim ? Date.now() - claim.claimedAt >= CONNECT_TIMEOUT_MS : false;
|
|
17605
|
+
if (claim && !spent && isProcessAlive(claim.pid)) {
|
|
17606
|
+
if (!await this.rearmedByHuman(connectorId)) {
|
|
17607
|
+
this.log(`trusty-squire connect still waiting for sign-in (pid ${String(claim.pid)}); leaving it alone`);
|
|
17608
|
+
return;
|
|
17609
|
+
}
|
|
17610
|
+
this.log("trusty-squire re-pair requested; superseding the connect holding the browser");
|
|
17611
|
+
} else if (spent && (await this.connectorRow(connectorId))?.signIn) {
|
|
17612
|
+
releaseSquireConnectSession((message) => this.log(`[trusty-squire] ${message}`));
|
|
17613
|
+
await this.api.execute("postConnectorStatus", {
|
|
17614
|
+
agentId: this.agentId,
|
|
17615
|
+
connectorId,
|
|
17616
|
+
steps: [{ label: "waiting for sign-in", status: "failed", reason: CEREMONY_EXPIRED }],
|
|
17617
|
+
signIn: null,
|
|
17618
|
+
errorMessage: CEREMONY_EXPIRED
|
|
17619
|
+
});
|
|
17620
|
+
return;
|
|
17621
|
+
}
|
|
17359
17622
|
const report = async (steps) => {
|
|
17360
17623
|
try {
|
|
17361
17624
|
await this.api.execute("postConnectorStatus", { agentId: this.agentId, connectorId, steps });
|
|
@@ -17374,6 +17637,7 @@ var ConnectorAssignmentLoop = class {
|
|
|
17374
17637
|
agentId: this.agentId,
|
|
17375
17638
|
connectorId,
|
|
17376
17639
|
steps: result.steps,
|
|
17640
|
+
signIn: null,
|
|
17377
17641
|
errorMessage: result.errorMessage
|
|
17378
17642
|
});
|
|
17379
17643
|
return;
|
|
@@ -17383,8 +17647,7 @@ var ConnectorAssignmentLoop = class {
|
|
|
17383
17647
|
agentId: this.agentId,
|
|
17384
17648
|
connectorId,
|
|
17385
17649
|
...result.squireVersion ? { squireVersion: result.squireVersion } : {},
|
|
17386
|
-
...result.signedInAs ? { signedInAs: result.signedInAs } : {}
|
|
17387
|
-
...result.signIn ? { signIn: result.signIn } : {}
|
|
17650
|
+
...result.signedInAs ? { signedInAs: result.signedInAs } : {}
|
|
17388
17651
|
});
|
|
17389
17652
|
await this.reportVault(connectorId);
|
|
17390
17653
|
return;
|
|
@@ -17393,11 +17656,37 @@ var ConnectorAssignmentLoop = class {
|
|
|
17393
17656
|
agentId: this.agentId,
|
|
17394
17657
|
connectorId,
|
|
17395
17658
|
steps: result.steps,
|
|
17659
|
+
signIn: result.signIn ?? null,
|
|
17396
17660
|
...result.squireVersion ? { squireVersion: result.squireVersion } : {},
|
|
17397
|
-
...result.signedInAs ? { signedInAs: result.signedInAs } : {}
|
|
17398
|
-
...result.signIn ? { signIn: result.signIn } : {}
|
|
17661
|
+
...result.signedInAs ? { signedInAs: result.signedInAs } : {}
|
|
17399
17662
|
});
|
|
17400
17663
|
}
|
|
17664
|
+
/** This connector's own row, or undefined when the server cannot answer. */
|
|
17665
|
+
async connectorRow(connectorId) {
|
|
17666
|
+
try {
|
|
17667
|
+
const status = await this.api.execute("getConnectorStatus", {
|
|
17668
|
+
agentId: this.agentId,
|
|
17669
|
+
connectorId
|
|
17670
|
+
});
|
|
17671
|
+
return status.connectorId === connectorId ? status : void 0;
|
|
17672
|
+
} catch (error) {
|
|
17673
|
+
this.log(`connector status unavailable: ${describe2(error)}`);
|
|
17674
|
+
return void 0;
|
|
17675
|
+
}
|
|
17676
|
+
}
|
|
17677
|
+
/**
|
|
17678
|
+
* True when a human asked for this connector again while a connect of ours
|
|
17679
|
+
* still holds the browser. `pairConnector` re-arms the row to its default
|
|
17680
|
+
* all-pending steps, so a row whose every step is still pending is a fresh
|
|
17681
|
+
* request; the row carrying the ceremony this helper published has settled
|
|
17682
|
+
* ones. An unreadable row is not evidence of a retry.
|
|
17683
|
+
*/
|
|
17684
|
+
async rearmedByHuman(connectorId) {
|
|
17685
|
+
const status = await this.connectorRow(connectorId);
|
|
17686
|
+
if (!status)
|
|
17687
|
+
return false;
|
|
17688
|
+
return status.steps.length > 0 && status.steps.every((step3) => step3.status === "pending");
|
|
17689
|
+
}
|
|
17401
17690
|
/** One vault report covers every live trusty-squire connector on this helper. */
|
|
17402
17691
|
async runSync() {
|
|
17403
17692
|
await this.reportVault();
|
|
@@ -17439,6 +17728,22 @@ function isAgentCommand(value) {
|
|
|
17439
17728
|
}
|
|
17440
17729
|
|
|
17441
17730
|
// packages/api-contract/dist/artifacts.js
|
|
17731
|
+
var ARTIFACT_EXTENSIONS_BY_MIME = {
|
|
17732
|
+
"text/html": [".html", ".htm"],
|
|
17733
|
+
"image/svg+xml": [".svg"],
|
|
17734
|
+
"application/pdf": [".pdf"],
|
|
17735
|
+
"text/markdown": [".md"],
|
|
17736
|
+
"image/png": [".png"],
|
|
17737
|
+
"image/jpeg": [".jpg", ".jpeg"],
|
|
17738
|
+
"image/gif": [".gif"],
|
|
17739
|
+
"image/webp": [".webp"],
|
|
17740
|
+
"text/plain": [".txt", ".log"],
|
|
17741
|
+
"application/json": [".json"],
|
|
17742
|
+
"text/csv": [".csv"],
|
|
17743
|
+
"application/zip": [".zip"],
|
|
17744
|
+
"application/octet-stream": []
|
|
17745
|
+
};
|
|
17746
|
+
var ARTIFACT_MIME_BY_EXTENSION = Object.fromEntries(Object.entries(ARTIFACT_EXTENSIONS_BY_MIME).flatMap(([mime, extensions]) => extensions.map((extension2) => [extension2, mime])));
|
|
17442
17747
|
var ARTIFACT_MAXIMUM_BYTES = 25 * 1024 * 1024;
|
|
17443
17748
|
|
|
17444
17749
|
// packages/api-contract/dist/system-events.js
|
|
@@ -17526,7 +17831,7 @@ function classifyTurnSilence(reason, reasonKind) {
|
|
|
17526
17831
|
if (/command protocol/i.test(text2) || /refusing intake/i.test(text2) || /helper is out of date/i.test(text2)) {
|
|
17527
17832
|
return { kind: "helper-out-of-date" };
|
|
17528
17833
|
}
|
|
17529
|
-
if (/working copy/i.test(text2) || /could not (?:clone|fetch|checkout)/i.test(text2) || /repository not found/i.test(text2) || /could not resolve host/i.test(text2) || /failed to start corner/i.test(text2) || /unable to access/i.test(text2) || /\bgit clone\b/i.test(text2) || /repository state is not verified/i.test(text2) || /incomplete repository binding/i.test(text2) || /no authoritative objective fact/i.test(text2)) {
|
|
17834
|
+
if (/working copy/i.test(text2) || /could not (?:clone|fetch|checkout)/i.test(text2) || /repository not found/i.test(text2) || /could not resolve host/i.test(text2) || /failed to start corner/i.test(text2) || /unable to access/i.test(text2) || /\bgit clone\b/i.test(text2) || /repository state is not verified/i.test(text2) || /incomplete repository binding/i.test(text2) || /no authoritative objective fact/i.test(text2) || /profile_busy/i.test(text2) || /broker unavailable/i.test(text2)) {
|
|
17530
17835
|
return { kind: "workspace-failure", repo: repoFromReason(text2) };
|
|
17531
17836
|
}
|
|
17532
17837
|
if (/helper isn't running/i.test(text2) || /helper is offline/i.test(text2)) {
|
|
@@ -17547,7 +17852,7 @@ function hiccupBackoffMs(attempt) {
|
|
|
17547
17852
|
}
|
|
17548
17853
|
|
|
17549
17854
|
// apps/body/dist/daemon-api-client.js
|
|
17550
|
-
import { resolve as
|
|
17855
|
+
import { resolve as resolve9 } from "node:path";
|
|
17551
17856
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
17552
17857
|
|
|
17553
17858
|
// node_modules/ws/wrapper.mjs
|
|
@@ -17566,9 +17871,9 @@ import { randomBytes as randomBytes5 } from "node:crypto";
|
|
|
17566
17871
|
import { execFile as execFile2 } from "node:child_process";
|
|
17567
17872
|
import { closeSync, openSync, readFileSync as readFileSync5 } from "node:fs";
|
|
17568
17873
|
import { mkdir as mkdir2, readFile as readFile2, readdir, rename as rename2, stat, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
|
|
17569
|
-
import { homedir as
|
|
17570
|
-
import { dirname as
|
|
17571
|
-
import { spawn as
|
|
17874
|
+
import { homedir as homedir5 } from "node:os";
|
|
17875
|
+
import { dirname as dirname6, resolve as resolve8 } from "node:path";
|
|
17876
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
17572
17877
|
import { promisify } from "node:util";
|
|
17573
17878
|
|
|
17574
17879
|
// node_modules/@noble/hashes/_u64.js
|
|
@@ -21955,7 +22260,7 @@ function alphabet(letters) {
|
|
|
21955
22260
|
};
|
|
21956
22261
|
}
|
|
21957
22262
|
// @__NO_SIDE_EFFECTS__
|
|
21958
|
-
function
|
|
22263
|
+
function join5(separator = "") {
|
|
21959
22264
|
astr("join", separator);
|
|
21960
22265
|
return {
|
|
21961
22266
|
encode: (from) => {
|
|
@@ -22085,8 +22390,8 @@ var base64 = hasBase64Builtin ? {
|
|
|
22085
22390
|
decode(s) {
|
|
22086
22391
|
return decodeBase64Builtin(s, false);
|
|
22087
22392
|
}
|
|
22088
|
-
} : /* @__PURE__ */ chain(/* @__PURE__ */ radix2(6), /* @__PURE__ */ alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), /* @__PURE__ */ padding(6), /* @__PURE__ */
|
|
22089
|
-
var BECH_ALPHABET = /* @__PURE__ */ chain(/* @__PURE__ */ alphabet("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), /* @__PURE__ */
|
|
22393
|
+
} : /* @__PURE__ */ chain(/* @__PURE__ */ radix2(6), /* @__PURE__ */ alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), /* @__PURE__ */ padding(6), /* @__PURE__ */ join5(""));
|
|
22394
|
+
var BECH_ALPHABET = /* @__PURE__ */ chain(/* @__PURE__ */ alphabet("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), /* @__PURE__ */ join5(""));
|
|
22090
22395
|
var POLYMOD_GENERATORS = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
22091
22396
|
function bech32Polymod(pre) {
|
|
22092
22397
|
const b = pre >> 25;
|
|
@@ -26104,15 +26409,15 @@ var DEFAULT_AGENT_IDENTITY_NAME = "beeline-agent";
|
|
|
26104
26409
|
var DEFAULT_BODY_IDENTITY_NAME = "beeline-body";
|
|
26105
26410
|
var DEFAULT_DAEMON_MONOLITH_BASE_URL = "https://server.usebeeline.app";
|
|
26106
26411
|
function defaultSupervisorRoot(env = process.env) {
|
|
26107
|
-
return
|
|
26412
|
+
return resolve8(env.XDG_STATE_HOME ?? resolve8(homedir5(), ".local", "state"));
|
|
26108
26413
|
}
|
|
26109
26414
|
function runtimeDirectory(supervisorRoot, publicKey) {
|
|
26110
26415
|
if (!/^[0-9a-f]{64}$/i.test(publicKey))
|
|
26111
26416
|
throw new Error("invalid agent public key");
|
|
26112
|
-
return
|
|
26417
|
+
return resolve8(supervisorRoot, "beeline", "agents", publicKey.toLowerCase());
|
|
26113
26418
|
}
|
|
26114
26419
|
function runtimeConfigPath(supervisorRoot, publicKey) {
|
|
26115
|
-
return
|
|
26420
|
+
return resolve8(runtimeDirectory(supervisorRoot, publicKey), "runtime.json");
|
|
26116
26421
|
}
|
|
26117
26422
|
function identityFromKey(value, name) {
|
|
26118
26423
|
const secretKey = value ? value.startsWith("nsec1") ? decodeNsec(value) : Uint8Array.from(Buffer.from(value, "hex")) : randomBytes5(32);
|
|
@@ -26148,7 +26453,7 @@ function runtimeAgentCommand(runtime, env = process.env) {
|
|
|
26148
26453
|
}
|
|
26149
26454
|
async function writeRuntimeRecord(runtime) {
|
|
26150
26455
|
const path = runtimeConfigPath(runtime.supervisorRoot, runtime.agent.publicKey);
|
|
26151
|
-
await mkdir2(
|
|
26456
|
+
await mkdir2(dirname6(path), { recursive: true, mode: 448 });
|
|
26152
26457
|
const staged = `${path}.${process.pid}.tmp`;
|
|
26153
26458
|
await writeFile3(staged, `${JSON.stringify(runtime, null, 2)}
|
|
26154
26459
|
`, { mode: 384 });
|
|
@@ -26174,7 +26479,7 @@ async function migrateRuntimeRecordAccessPolicy(path) {
|
|
|
26174
26479
|
return { runtime, migrated: true };
|
|
26175
26480
|
}
|
|
26176
26481
|
async function stageMonolithAgentRuntime(input) {
|
|
26177
|
-
const supervisorRoot = input.supervisorRoot ?
|
|
26482
|
+
const supervisorRoot = input.supervisorRoot ? resolve8(input.supervisorRoot) : defaultSupervisorRoot();
|
|
26178
26483
|
const configPath = runtimeConfigPath(supervisorRoot, input.agentIdentity.publicKey);
|
|
26179
26484
|
const configuredBaseUrl = input.monolithBaseUrl ?? DEFAULT_DAEMON_MONOLITH_BASE_URL;
|
|
26180
26485
|
const baseUrl = new URL(configuredBaseUrl).origin;
|
|
@@ -26219,9 +26524,9 @@ async function stageMonolithAgentRuntime(input) {
|
|
|
26219
26524
|
return { runtime, configPath };
|
|
26220
26525
|
}
|
|
26221
26526
|
async function runtimePaths(root) {
|
|
26222
|
-
const agents =
|
|
26527
|
+
const agents = resolve8(root, "beeline", "agents");
|
|
26223
26528
|
const entries = await readdir(agents, { withFileTypes: true }).catch(() => []);
|
|
26224
|
-
return entries.filter((entry) => entry.isDirectory()).map((entry) =>
|
|
26529
|
+
return entries.filter((entry) => entry.isDirectory()).map((entry) => resolve8(agents, entry.name, "runtime.json"));
|
|
26225
26530
|
}
|
|
26226
26531
|
async function findAgentRuntimeConfigPaths(env = process.env, _cwd = process.cwd()) {
|
|
26227
26532
|
return runtimePaths(defaultSupervisorRoot(env));
|
|
@@ -26230,13 +26535,13 @@ async function findRuntimeConfigPaths(cwd = process.cwd(), env = process.env) {
|
|
|
26230
26535
|
return findAgentRuntimeConfigPaths(env, cwd);
|
|
26231
26536
|
}
|
|
26232
26537
|
async function resolveRuntimeConfigPath(path) {
|
|
26233
|
-
return
|
|
26538
|
+
return resolve8(path);
|
|
26234
26539
|
}
|
|
26235
26540
|
async function selectRuntimeConfigPaths(options) {
|
|
26236
26541
|
const hostScope = true;
|
|
26237
26542
|
const configs = await options.findHostRuntimes(options.cwd);
|
|
26238
26543
|
const requestedPubkey = options.requestedPubkey;
|
|
26239
|
-
const paths = requestedPubkey ? configs.filter((path) =>
|
|
26544
|
+
const paths = requestedPubkey ? configs.filter((path) => dirname6(path).endsWith(requestedPubkey)) : [...new Set(configs)];
|
|
26240
26545
|
if (!paths.length)
|
|
26241
26546
|
throw new Error(options.noRuntimeMessage(hostScope));
|
|
26242
26547
|
if (options.requestedPubkey && paths.length > 1)
|
|
@@ -26244,10 +26549,10 @@ async function selectRuntimeConfigPaths(options) {
|
|
|
26244
26549
|
return { paths, hostScope };
|
|
26245
26550
|
}
|
|
26246
26551
|
function daemonPidPath(configPath) {
|
|
26247
|
-
return
|
|
26552
|
+
return resolve8(dirname6(configPath), "daemon.pid");
|
|
26248
26553
|
}
|
|
26249
26554
|
function daemonBirthPath(configPath) {
|
|
26250
|
-
return
|
|
26555
|
+
return resolve8(dirname6(configPath), "daemon.birth");
|
|
26251
26556
|
}
|
|
26252
26557
|
function processBirthIdentity(pid) {
|
|
26253
26558
|
try {
|
|
@@ -26259,7 +26564,7 @@ function processBirthIdentity(pid) {
|
|
|
26259
26564
|
}
|
|
26260
26565
|
}
|
|
26261
26566
|
async function writeDaemonPidRecord(configPath, pid) {
|
|
26262
|
-
const directory =
|
|
26567
|
+
const directory = dirname6(configPath);
|
|
26263
26568
|
await mkdir2(directory, { recursive: true, mode: 448 });
|
|
26264
26569
|
await writeFile3(daemonPidPath(configPath), `${pid}
|
|
26265
26570
|
`, { mode: 384 });
|
|
@@ -26283,11 +26588,11 @@ async function daemonIsThisRuntime(pid, configPath) {
|
|
|
26283
26588
|
try {
|
|
26284
26589
|
const argv = (await readFile2(`/proc/${pid}/cmdline`, "utf8")).split("\0").filter(Boolean);
|
|
26285
26590
|
const flag = argv.lastIndexOf("--config");
|
|
26286
|
-
return flag > 0 && argv[flag - 1] === "daemon" &&
|
|
26591
|
+
return flag > 0 && argv[flag - 1] === "daemon" && resolve8(argv[flag + 1]) === resolve8(configPath);
|
|
26287
26592
|
} catch {
|
|
26288
26593
|
try {
|
|
26289
26594
|
const { stdout: stdout6 } = await execFileAsync("ps", ["-p", String(pid), "-o", "command="]);
|
|
26290
|
-
return stdout6.includes(" daemon ") && stdout6.includes(
|
|
26595
|
+
return stdout6.includes(" daemon ") && stdout6.includes(resolve8(configPath));
|
|
26291
26596
|
} catch {
|
|
26292
26597
|
return false;
|
|
26293
26598
|
}
|
|
@@ -26340,14 +26645,14 @@ async function stopRuntimeDaemon(path, opts = {}) {
|
|
|
26340
26645
|
throw new Error(`agent daemon ${pid} did not stop after ${timeout}ms`);
|
|
26341
26646
|
}
|
|
26342
26647
|
async function launchRuntimeDaemon(configPath, opts = {}) {
|
|
26343
|
-
const directory =
|
|
26648
|
+
const directory = dirname6(configPath);
|
|
26344
26649
|
await mkdir2(directory, { recursive: true, mode: 448 });
|
|
26345
26650
|
const foreground = opts.foreground === true;
|
|
26346
|
-
const output = foreground ? "inherit" : openSync(
|
|
26651
|
+
const output = foreground ? "inherit" : openSync(resolve8(directory, "daemon.log"), "a", 384);
|
|
26347
26652
|
const entrypoint = opts.entrypoint ?? process.argv[1];
|
|
26348
26653
|
if (!entrypoint)
|
|
26349
26654
|
throw new Error("cannot resolve daemon CLI entrypoint");
|
|
26350
|
-
const child =
|
|
26655
|
+
const child = spawn7(process.execPath, [...opts.execArgv ?? [], entrypoint, "daemon", "--config", resolve8(configPath)], {
|
|
26351
26656
|
cwd: directory,
|
|
26352
26657
|
env: opts.env ?? process.env,
|
|
26353
26658
|
detached: !foreground,
|
|
@@ -26609,8 +26914,8 @@ var DaemonApiClient = class {
|
|
|
26609
26914
|
};
|
|
26610
26915
|
async function activateDaemonTransport(path, fetchImpl = fetch) {
|
|
26611
26916
|
const runtime = await readRuntimeRecord(path);
|
|
26612
|
-
const expectedPath =
|
|
26613
|
-
if (
|
|
26917
|
+
const expectedPath = resolve9(runtimeDirectory(runtime.supervisorRoot, runtime.agent.publicKey), "runtime.json");
|
|
26918
|
+
if (resolve9(path) !== expectedPath) {
|
|
26614
26919
|
throw new Error(`refusing daemon token exchange outside canonical runtime path: ${path}`);
|
|
26615
26920
|
}
|
|
26616
26921
|
const transport = runtime.transport;
|
|
@@ -26651,9 +26956,9 @@ async function activateDaemonTransport(path, fetchImpl = fetch) {
|
|
|
26651
26956
|
// apps/body/dist/room-runtime.js
|
|
26652
26957
|
import { execFile as execFile6 } from "node:child_process";
|
|
26653
26958
|
import { createHash as createHash7 } from "node:crypto";
|
|
26654
|
-
import { existsSync as
|
|
26959
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync3 } from "node:fs";
|
|
26655
26960
|
import { mkdir as mkdir14, rm as rm5 } from "node:fs/promises";
|
|
26656
|
-
import { dirname as
|
|
26961
|
+
import { dirname as dirname12, resolve as resolve23 } from "node:path";
|
|
26657
26962
|
import { promisify as promisify4 } from "node:util";
|
|
26658
26963
|
|
|
26659
26964
|
// apps/body/dist/grant-runner.js
|
|
@@ -26661,10 +26966,10 @@ import { execFile as execFile3 } from "node:child_process";
|
|
|
26661
26966
|
import { createHash as createHash3, randomBytes as randomBytes6 } from "node:crypto";
|
|
26662
26967
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
26663
26968
|
import { createServer } from "node:http";
|
|
26664
|
-
import { dirname as
|
|
26969
|
+
import { dirname as dirname8, resolve as resolve12 } from "node:path";
|
|
26665
26970
|
|
|
26666
26971
|
// packages/api-contract/dist/agent-grants.js
|
|
26667
|
-
var AGENT_GRANT_KINDS = ["path", "host", "secret", "device", "budget", "command"];
|
|
26972
|
+
var AGENT_GRANT_KINDS = ["path", "host", "secret", "device", "budget", "command", "mcp"];
|
|
26668
26973
|
var SHELL_METACHARACTERS = /[;&|<>$`\\'"(){}\n\r\t*?[\]~#!]/;
|
|
26669
26974
|
var SECRET_NAME = /^[A-Z][A-Z0-9_]{0,63}$/;
|
|
26670
26975
|
function parseCommandGrantTarget(target) {
|
|
@@ -26884,9 +27189,9 @@ function surfaceAllows(surface, capability) {
|
|
|
26884
27189
|
|
|
26885
27190
|
// apps/body/dist/bwrap-sandbox.js
|
|
26886
27191
|
import { spawnSync } from "node:child_process";
|
|
26887
|
-
import { lstatSync as
|
|
26888
|
-
import { homedir as
|
|
26889
|
-
import { isAbsolute as isAbsolute2, relative, resolve as
|
|
27192
|
+
import { lstatSync as lstatSync4 } from "node:fs";
|
|
27193
|
+
import { homedir as homedir6 } from "node:os";
|
|
27194
|
+
import { isAbsolute as isAbsolute2, relative, resolve as resolve10 } from "node:path";
|
|
26890
27195
|
var DEFAULT_SANDBOX_POLICY = "bwrap";
|
|
26891
27196
|
function isSandboxPolicy(value) {
|
|
26892
27197
|
return value === "bwrap" || value === "off";
|
|
@@ -26922,35 +27227,34 @@ var HARNESS_HOME_STATE_DIRS = [
|
|
|
26922
27227
|
dirs: [".cursor"]
|
|
26923
27228
|
}
|
|
26924
27229
|
];
|
|
26925
|
-
function harnessHomeStateDirs(agentCommand, home =
|
|
27230
|
+
function harnessHomeStateDirs(agentCommand, home = homedir6()) {
|
|
26926
27231
|
if (!agentCommand)
|
|
26927
27232
|
return [];
|
|
26928
27233
|
for (const { match, dirs } of HARNESS_HOME_STATE_DIRS) {
|
|
26929
27234
|
if (match.test(agentCommand))
|
|
26930
|
-
return dirs.map((dir) =>
|
|
27235
|
+
return dirs.map((dir) => resolve10(home, dir));
|
|
26931
27236
|
}
|
|
26932
27237
|
return [];
|
|
26933
27238
|
}
|
|
26934
27239
|
var KNOWN_CREDENTIAL_MASK_PATHS = [
|
|
26935
27240
|
".config/gh",
|
|
26936
|
-
".config/trusty-squire",
|
|
26937
27241
|
".ssh",
|
|
26938
27242
|
".netrc",
|
|
26939
27243
|
".git-credentials",
|
|
26940
27244
|
".secrets.env"
|
|
26941
27245
|
];
|
|
26942
|
-
function credentialMaskPaths(extraPaths, home =
|
|
27246
|
+
function credentialMaskPaths(extraPaths, home = homedir6(), stat5 = (path) => {
|
|
26943
27247
|
try {
|
|
26944
|
-
const info =
|
|
27248
|
+
const info = lstatSync4(path);
|
|
26945
27249
|
return { isDirectory: info.isDirectory() };
|
|
26946
27250
|
} catch {
|
|
26947
27251
|
return void 0;
|
|
26948
27252
|
}
|
|
26949
27253
|
}, requiredPaths = []) {
|
|
26950
|
-
const required = new Set(requiredPaths.map((path) =>
|
|
27254
|
+
const required = new Set(requiredPaths.map((path) => resolve10(path)));
|
|
26951
27255
|
const candidates = [
|
|
26952
|
-
...KNOWN_CREDENTIAL_MASK_PATHS.map((entry) =>
|
|
26953
|
-
...(extraPaths ?? []).map((entry) =>
|
|
27256
|
+
...KNOWN_CREDENTIAL_MASK_PATHS.map((entry) => resolve10(home, entry)),
|
|
27257
|
+
...(extraPaths ?? []).map((entry) => resolve10(entry))
|
|
26954
27258
|
];
|
|
26955
27259
|
const seen = /* @__PURE__ */ new Set();
|
|
26956
27260
|
const masks = [];
|
|
@@ -26977,7 +27281,7 @@ function normalize(paths) {
|
|
|
26977
27281
|
for (const path of paths) {
|
|
26978
27282
|
if (!path)
|
|
26979
27283
|
continue;
|
|
26980
|
-
seen.add(
|
|
27284
|
+
seen.add(resolve10(path));
|
|
26981
27285
|
}
|
|
26982
27286
|
return Array.from(seen).sort();
|
|
26983
27287
|
}
|
|
@@ -27015,7 +27319,7 @@ function sandboxMountPlan(spec) {
|
|
|
27015
27319
|
writable,
|
|
27016
27320
|
quotaTmpfs: spec.workbench ? [
|
|
27017
27321
|
{
|
|
27018
|
-
target:
|
|
27322
|
+
target: resolve10(spec.workbench.dir),
|
|
27019
27323
|
maxBytes: spec.workbench.maxBytes,
|
|
27020
27324
|
maxInodes: spec.workbench.maxInodes,
|
|
27021
27325
|
blockGit: true
|
|
@@ -27070,7 +27374,7 @@ function buildBwrapArgv(input) {
|
|
|
27070
27374
|
for (const binding of quotaTmpfs) {
|
|
27071
27375
|
args.push("--dir", binding.target, "--size", String(binding.maxBytes), "--tmpfs", binding.target);
|
|
27072
27376
|
if (binding.blockGit)
|
|
27073
|
-
args.push("--ro-bind", "/dev/null",
|
|
27377
|
+
args.push("--ro-bind", "/dev/null", resolve10(binding.target, ".git"));
|
|
27074
27378
|
}
|
|
27075
27379
|
args.push("--chdir", input.cwd);
|
|
27076
27380
|
args.push("--die-with-parent");
|
|
@@ -27130,14 +27434,14 @@ function detectBwrapSandbox(options = {}) {
|
|
|
27130
27434
|
}
|
|
27131
27435
|
return {
|
|
27132
27436
|
path: bwrapPath,
|
|
27133
|
-
advisory: `harness OS sandbox ENABLED via ${bwrapPath}: every ACP child gets a read-only filesystem plus a private /tmp and PID namespace, writable only in its own harness state; ambient credential stores (~/.config/gh, ~/.
|
|
27437
|
+
advisory: `harness OS sandbox ENABLED via ${bwrapPath}: every ACP child gets a read-only filesystem plus a private /tmp and PID namespace, writable only in its own harness state; ambient credential stores (~/.config/gh, ~/.ssh, ~/.netrc, ~/.git-credentials) are masked absent; a repository corner adds its worktree and git dir, then receives its linked repository's GitHub App credential. Hygiene boundary, not confinement \u2014 it shapes where sessions write files and does not restrict other access this account has (e.g. sockets, container runtimes, secrets not on the mask list)`
|
|
27134
27438
|
};
|
|
27135
27439
|
}
|
|
27136
27440
|
|
|
27137
27441
|
// apps/body/dist/provider-key-store.js
|
|
27138
27442
|
import { chmod as chmod2, mkdir as mkdir3, readFile as readFile3, writeFile as writeFile4 } from "node:fs/promises";
|
|
27139
|
-
import { homedir as
|
|
27140
|
-
import { dirname as
|
|
27443
|
+
import { homedir as homedir7 } from "node:os";
|
|
27444
|
+
import { dirname as dirname7, resolve as resolve11 } from "node:path";
|
|
27141
27445
|
var PROVIDER_KEY_ENV_VARS = {
|
|
27142
27446
|
openrouter: "OPENROUTER_API_KEY",
|
|
27143
27447
|
openai: "OPENAI_API_KEY",
|
|
@@ -27147,8 +27451,8 @@ var PROVIDER_KEY_ENV_VARS = {
|
|
|
27147
27451
|
};
|
|
27148
27452
|
var GOOGLE_ENV_ALIAS = "GEMINI_API_KEY";
|
|
27149
27453
|
function providerKeyStorePath(env = process.env) {
|
|
27150
|
-
const configRoot = env.XDG_CONFIG_HOME?.trim() ||
|
|
27151
|
-
return
|
|
27454
|
+
const configRoot = env.XDG_CONFIG_HOME?.trim() || resolve11(homedir7(), ".config");
|
|
27455
|
+
return resolve11(configRoot, "beeline", "providers.json");
|
|
27152
27456
|
}
|
|
27153
27457
|
async function readProviderKeyStore(env = process.env) {
|
|
27154
27458
|
const path = providerKeyStorePath(env);
|
|
@@ -27171,7 +27475,7 @@ async function readSavedProviderKey(provider, env = process.env) {
|
|
|
27171
27475
|
async function saveProviderKey(provider, key, env = process.env) {
|
|
27172
27476
|
const path = providerKeyStorePath(env);
|
|
27173
27477
|
const store = { ...await readProviderKeyStore(env), [provider]: key };
|
|
27174
|
-
await mkdir3(
|
|
27478
|
+
await mkdir3(dirname7(path), { recursive: true, mode: 448 });
|
|
27175
27479
|
await writeFile4(path, `${JSON.stringify(store, null, 2)}
|
|
27176
27480
|
`, { mode: 384 });
|
|
27177
27481
|
await chmod2(path, 384);
|
|
@@ -27208,7 +27512,7 @@ function operatorSecretResolver(env = process.env) {
|
|
|
27208
27512
|
if (saved)
|
|
27209
27513
|
return saved;
|
|
27210
27514
|
}
|
|
27211
|
-
const raw = await readFile4(
|
|
27515
|
+
const raw = await readFile4(resolve12(dirname8(providerKeyStorePath(env)), "secrets.json"), "utf8").catch(() => void 0);
|
|
27212
27516
|
if (!raw)
|
|
27213
27517
|
return void 0;
|
|
27214
27518
|
try {
|
|
@@ -27320,9 +27624,9 @@ var GrantCommandRunner = class {
|
|
|
27320
27624
|
...Object.fromEntries(secrets)
|
|
27321
27625
|
};
|
|
27322
27626
|
const cap = this.options.outputCapBytes ?? GRANT_COMMAND_OUTPUT_CAP_BYTES;
|
|
27323
|
-
const
|
|
27627
|
+
const spawn13 = surfaceAllows(policy.surface, "run-host-command") ? { command: argv[0], args: argv.slice(1) } : roomSandboxCommand(policy, room.cwd, argv);
|
|
27324
27628
|
const outcome = await new Promise((resolveRun) => {
|
|
27325
|
-
const child = execFile3(
|
|
27629
|
+
const child = execFile3(spawn13.command, spawn13.args, {
|
|
27326
27630
|
cwd: room.cwd,
|
|
27327
27631
|
env,
|
|
27328
27632
|
timeout: this.options.timeoutMs ?? GRANT_COMMAND_TIMEOUT_MS,
|
|
@@ -27410,8 +27714,8 @@ function scriptCandidates(cwd, scratch, argv) {
|
|
|
27410
27714
|
if (!argument)
|
|
27411
27715
|
return [];
|
|
27412
27716
|
const paths = [
|
|
27413
|
-
|
|
27414
|
-
...scratch ? [
|
|
27717
|
+
resolve12(cwd, argument.path),
|
|
27718
|
+
...scratch ? [resolve12(scratch, argument.path)] : []
|
|
27415
27719
|
];
|
|
27416
27720
|
return [...new Set(paths)];
|
|
27417
27721
|
}
|
|
@@ -27614,17 +27918,17 @@ function captureConnectionUsage(recorder, turn, calls) {
|
|
|
27614
27918
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
27615
27919
|
import { mkdir as mkdir4, writeFile as writeFile5 } from "node:fs/promises";
|
|
27616
27920
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
27617
|
-
import { dirname as
|
|
27921
|
+
import { dirname as dirname9, join as join6 } from "node:path";
|
|
27618
27922
|
var CommandExecutionContext = class {
|
|
27619
27923
|
generationId = randomUUID3();
|
|
27620
27924
|
path;
|
|
27621
27925
|
current;
|
|
27622
27926
|
constructor(root) {
|
|
27623
|
-
this.path =
|
|
27927
|
+
this.path = join6(root ?? tmpdir3(), `beeline-command-${this.generationId}.json`);
|
|
27624
27928
|
}
|
|
27625
27929
|
async enter(command) {
|
|
27626
27930
|
this.current = command;
|
|
27627
|
-
await mkdir4(
|
|
27931
|
+
await mkdir4(dirname9(this.path), { recursive: true });
|
|
27628
27932
|
await writeFile5(this.path, JSON.stringify({
|
|
27629
27933
|
roomId: command.roomId,
|
|
27630
27934
|
requestId: command.turnRequestId,
|
|
@@ -27746,13 +28050,13 @@ async function runServerCommandIntake(options) {
|
|
|
27746
28050
|
}
|
|
27747
28051
|
}
|
|
27748
28052
|
options.onPoll?.();
|
|
27749
|
-
const reconcile = await new Promise((
|
|
28053
|
+
const reconcile = await new Promise((resolve35) => {
|
|
27750
28054
|
const done = (needed) => {
|
|
27751
28055
|
if (timer)
|
|
27752
28056
|
clearTimeout(timer);
|
|
27753
28057
|
signal?.removeEventListener("abort", aborted);
|
|
27754
28058
|
wake = void 0;
|
|
27755
|
-
|
|
28059
|
+
resolve35(needed);
|
|
27756
28060
|
};
|
|
27757
28061
|
const aborted = () => done(false);
|
|
27758
28062
|
wake = done;
|
|
@@ -27780,13 +28084,13 @@ async function runServerCommandIntake(options) {
|
|
|
27780
28084
|
import { execFile as execFile5 } from "node:child_process";
|
|
27781
28085
|
import { createHash as createHash6 } from "node:crypto";
|
|
27782
28086
|
import { mkdir as mkdir13 } from "node:fs/promises";
|
|
27783
|
-
import { homedir as
|
|
27784
|
-
import { join as
|
|
28087
|
+
import { homedir as homedir10 } from "node:os";
|
|
28088
|
+
import { join as join12 } from "node:path";
|
|
27785
28089
|
import { promisify as promisify3 } from "node:util";
|
|
27786
28090
|
|
|
27787
28091
|
// apps/body/dist/agent-home.js
|
|
27788
|
-
var
|
|
27789
|
-
import { existsSync as
|
|
28092
|
+
var import_yaml2 = __toESM(require_dist(), 1);
|
|
28093
|
+
import { existsSync as existsSync5, readFileSync as readFileSync7 } from "node:fs";
|
|
27790
28094
|
|
|
27791
28095
|
// node_modules/smol-toml/dist/date.js
|
|
27792
28096
|
var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
|
|
@@ -28433,15 +28737,164 @@ function parse5(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
|
|
|
28433
28737
|
return res;
|
|
28434
28738
|
}
|
|
28435
28739
|
|
|
28740
|
+
// node_modules/smol-toml/dist/stringify.js
|
|
28741
|
+
var BARE_KEY = /^[a-z0-9-_]+$/i;
|
|
28742
|
+
function extendedTypeOf(obj) {
|
|
28743
|
+
let type = typeof obj;
|
|
28744
|
+
if (type === "object") {
|
|
28745
|
+
if (Array.isArray(obj))
|
|
28746
|
+
return "array";
|
|
28747
|
+
if (typeof obj?.getUTCDate === "function" && obj instanceof Date)
|
|
28748
|
+
return "date";
|
|
28749
|
+
if (globalThis.Temporal && // check for the 'since' property as an early bailout that avoids running all 5 instanceof checks
|
|
28750
|
+
typeof obj?.since === "function" && (obj instanceof Temporal.Instant || obj instanceof Temporal.PlainDate || obj instanceof Temporal.PlainDateTime || obj instanceof Temporal.PlainTime || obj instanceof Temporal.ZonedDateTime)) {
|
|
28751
|
+
return "temporal";
|
|
28752
|
+
}
|
|
28753
|
+
}
|
|
28754
|
+
return type;
|
|
28755
|
+
}
|
|
28756
|
+
function isArrayOfTables(obj) {
|
|
28757
|
+
for (let i3 = 0; i3 < obj.length; i3++) {
|
|
28758
|
+
if (extendedTypeOf(obj[i3]) !== "object")
|
|
28759
|
+
return false;
|
|
28760
|
+
}
|
|
28761
|
+
return obj.length != 0;
|
|
28762
|
+
}
|
|
28763
|
+
function formatString(s) {
|
|
28764
|
+
return JSON.stringify(s).replace(/\x7f/g, "\\u007f");
|
|
28765
|
+
}
|
|
28766
|
+
function stringifyTemporal(temporal) {
|
|
28767
|
+
return temporal.toString({
|
|
28768
|
+
calendarName: "never",
|
|
28769
|
+
timeZoneName: "never"
|
|
28770
|
+
});
|
|
28771
|
+
}
|
|
28772
|
+
function stringifyValue(val, type, depth, numberAsFloat) {
|
|
28773
|
+
if (depth === 0) {
|
|
28774
|
+
throw new Error("Could not stringify the object: maximum object depth exceeded");
|
|
28775
|
+
}
|
|
28776
|
+
switch (type) {
|
|
28777
|
+
// @ts-expect-error -- intentional fallthrough case
|
|
28778
|
+
case "number":
|
|
28779
|
+
if (isNaN(val))
|
|
28780
|
+
return "nan";
|
|
28781
|
+
if (val === Infinity)
|
|
28782
|
+
return "inf";
|
|
28783
|
+
if (val === -Infinity)
|
|
28784
|
+
return "-inf";
|
|
28785
|
+
if (Number.isInteger(val) && (numberAsFloat || !Number.isSafeInteger(val)))
|
|
28786
|
+
return val.toFixed(1);
|
|
28787
|
+
case "bigint":
|
|
28788
|
+
case "boolean":
|
|
28789
|
+
return val.toString();
|
|
28790
|
+
case "string":
|
|
28791
|
+
return formatString(val);
|
|
28792
|
+
case "date":
|
|
28793
|
+
if (isNaN(val.getTime()))
|
|
28794
|
+
throw new TypeError("cannot serialize invalid date");
|
|
28795
|
+
return val.toISOString();
|
|
28796
|
+
case "object":
|
|
28797
|
+
return stringifyInlineTable(val, depth, numberAsFloat);
|
|
28798
|
+
case "array":
|
|
28799
|
+
return stringifyArray(val, depth, numberAsFloat);
|
|
28800
|
+
case "temporal":
|
|
28801
|
+
return stringifyTemporal(val);
|
|
28802
|
+
}
|
|
28803
|
+
}
|
|
28804
|
+
function stringifyInlineTable(obj, depth, numberAsFloat) {
|
|
28805
|
+
let keys = Object.keys(obj);
|
|
28806
|
+
if (keys.length === 0)
|
|
28807
|
+
return "{}";
|
|
28808
|
+
let res = "{ ";
|
|
28809
|
+
for (let i3 = 0; i3 < keys.length; i3++) {
|
|
28810
|
+
let k = keys[i3];
|
|
28811
|
+
if (i3)
|
|
28812
|
+
res += ", ";
|
|
28813
|
+
res += BARE_KEY.test(k) ? k : formatString(k);
|
|
28814
|
+
res += " = ";
|
|
28815
|
+
res += stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat);
|
|
28816
|
+
}
|
|
28817
|
+
return res + " }";
|
|
28818
|
+
}
|
|
28819
|
+
function stringifyArray(array, depth, numberAsFloat) {
|
|
28820
|
+
if (array.length === 0)
|
|
28821
|
+
return "[]";
|
|
28822
|
+
let res = "[ ";
|
|
28823
|
+
for (let i3 = 0; i3 < array.length; i3++) {
|
|
28824
|
+
if (i3)
|
|
28825
|
+
res += ", ";
|
|
28826
|
+
if (array[i3] === null || array[i3] === void 0) {
|
|
28827
|
+
throw new TypeError("arrays cannot contain null or undefined values");
|
|
28828
|
+
}
|
|
28829
|
+
res += stringifyValue(array[i3], extendedTypeOf(array[i3]), depth - 1, numberAsFloat);
|
|
28830
|
+
}
|
|
28831
|
+
return res + " ]";
|
|
28832
|
+
}
|
|
28833
|
+
function stringifyArrayTable(array, key, depth, numberAsFloat) {
|
|
28834
|
+
if (depth === 0) {
|
|
28835
|
+
throw new Error("Could not stringify the object: maximum object depth exceeded");
|
|
28836
|
+
}
|
|
28837
|
+
let res = "";
|
|
28838
|
+
for (let i3 = 0; i3 < array.length; i3++) {
|
|
28839
|
+
res += `${res && "\n"}[[${key}]]
|
|
28840
|
+
`;
|
|
28841
|
+
res += stringifyTable(0, array[i3], key, depth, numberAsFloat);
|
|
28842
|
+
}
|
|
28843
|
+
return res;
|
|
28844
|
+
}
|
|
28845
|
+
function stringifyTable(tableKey, obj, prefix, depth, numberAsFloat) {
|
|
28846
|
+
if (depth === 0) {
|
|
28847
|
+
throw new Error("Could not stringify the object: maximum object depth exceeded");
|
|
28848
|
+
}
|
|
28849
|
+
let preamble = "";
|
|
28850
|
+
let tables = "";
|
|
28851
|
+
let keys = Object.keys(obj);
|
|
28852
|
+
for (let i3 = 0; i3 < keys.length; i3++) {
|
|
28853
|
+
let k = keys[i3];
|
|
28854
|
+
if (obj[k] !== null && obj[k] !== void 0) {
|
|
28855
|
+
let type = extendedTypeOf(obj[k]);
|
|
28856
|
+
if (type === "symbol" || type === "function") {
|
|
28857
|
+
throw new TypeError(`cannot serialize values of type '${type}'`);
|
|
28858
|
+
}
|
|
28859
|
+
let key = BARE_KEY.test(k) ? k : formatString(k);
|
|
28860
|
+
if (type === "array" && isArrayOfTables(obj[k])) {
|
|
28861
|
+
tables += (tables && "\n") + stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat);
|
|
28862
|
+
} else if (type === "object") {
|
|
28863
|
+
let tblKey = prefix ? `${prefix}.${key}` : key;
|
|
28864
|
+
tables += (tables && "\n") + stringifyTable(tblKey, obj[k], tblKey, depth - 1, numberAsFloat);
|
|
28865
|
+
} else {
|
|
28866
|
+
preamble += key;
|
|
28867
|
+
preamble += " = ";
|
|
28868
|
+
preamble += stringifyValue(obj[k], type, depth, numberAsFloat);
|
|
28869
|
+
preamble += "\n";
|
|
28870
|
+
}
|
|
28871
|
+
}
|
|
28872
|
+
}
|
|
28873
|
+
if (tableKey && (preamble || !tables))
|
|
28874
|
+
preamble = preamble ? `[${tableKey}]
|
|
28875
|
+
${preamble}` : `[${tableKey}]`;
|
|
28876
|
+
return preamble && tables ? `${preamble}
|
|
28877
|
+
${tables}` : preamble || tables;
|
|
28878
|
+
}
|
|
28879
|
+
function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
|
|
28880
|
+
if (extendedTypeOf(obj) !== "object") {
|
|
28881
|
+
throw new TypeError("stringify can only be called with an object");
|
|
28882
|
+
}
|
|
28883
|
+
let str = stringifyTable(0, obj, "", maxDepth, numbersAsFloat);
|
|
28884
|
+
if (str[str.length - 1] !== "\n")
|
|
28885
|
+
return str + "\n";
|
|
28886
|
+
return str;
|
|
28887
|
+
}
|
|
28888
|
+
|
|
28436
28889
|
// apps/body/dist/agent-home.js
|
|
28437
28890
|
import { createHash as createHash4, randomUUID as randomUUID4 } from "node:crypto";
|
|
28438
28891
|
import { chmod as chmod3, copyFile, lstat as lstat2, mkdir as mkdir6, readFile as readFile6, readdir as readdir2, realpath, rename as rename3, rm as rm2, symlink, unlink as unlink3, writeFile as writeFile7 } from "node:fs/promises";
|
|
28439
|
-
import { homedir as
|
|
28440
|
-
import { basename as basename5, dirname as
|
|
28892
|
+
import { homedir as homedir8 } from "node:os";
|
|
28893
|
+
import { basename as basename5, dirname as dirname10, join as join8, relative as relative2, resolve as resolve16, sep } from "node:path";
|
|
28441
28894
|
|
|
28442
28895
|
// apps/body/dist/beeline-skill.js
|
|
28443
28896
|
import { readFileSync as readFileSync6 } from "node:fs";
|
|
28444
|
-
import { resolve as
|
|
28897
|
+
import { resolve as resolve13 } from "node:path";
|
|
28445
28898
|
|
|
28446
28899
|
// packages/api-contract/dist/workbench.js
|
|
28447
28900
|
var CONNECTABLE_CONNECTOR_KINDS = [
|
|
@@ -28456,6 +28909,13 @@ var CONNECTABLE_CONNECTOR_KINDS = [
|
|
|
28456
28909
|
var CONNECTOR_OFFER_WINDOW_MS = 2 * 6e4;
|
|
28457
28910
|
var OFFERABLE_CONNECTOR_KINDS = CONNECTABLE_CONNECTOR_KINDS.filter((kind) => kind !== "wallet");
|
|
28458
28911
|
|
|
28912
|
+
// packages/api-contract/dist/phone-guards.js
|
|
28913
|
+
var CLOSED_VIEWER = {
|
|
28914
|
+
identity: { pubkey: "0".repeat(64), kind: "human", name: "" },
|
|
28915
|
+
role: "member",
|
|
28916
|
+
permissions: { send: false, manage: false }
|
|
28917
|
+
};
|
|
28918
|
+
|
|
28459
28919
|
// packages/api-contract/dist/agent-pairing-code.js
|
|
28460
28920
|
var CURRENT_AGENT_PAIRING_CODE = /^[0-9A-F]{8}-[0-9A-F]{8}$/;
|
|
28461
28921
|
var LEGACY_AGENT_PAIRING_CODE = /^BUZZ-(?:[0-9A-F]{8}-[0-9A-F]{8}|[A-HJ-NP-Z2-9]{4}-[A-HJ-NP-Z2-9]{4})$/;
|
|
@@ -28529,7 +28989,7 @@ function runningBeelineReleaseId(env = process.env, read = (path) => readFileSyn
|
|
|
28529
28989
|
const lib = env.BEELINE_LIB_DIR;
|
|
28530
28990
|
if (!lib)
|
|
28531
28991
|
return "source";
|
|
28532
|
-
const manifest = JSON.parse(read(
|
|
28992
|
+
const manifest = JSON.parse(read(resolve13(lib, "bundle.json")));
|
|
28533
28993
|
return [manifest.version, manifest.commit].filter(Boolean).join("-") || "source";
|
|
28534
28994
|
} catch {
|
|
28535
28995
|
return "source";
|
|
@@ -28751,9 +29211,213 @@ var SQUIRE_GOVERNED_TOOLS = [
|
|
|
28751
29211
|
];
|
|
28752
29212
|
var SQUIRE_GOVERNED_TOOL_SET = new Set(SQUIRE_GOVERNED_TOOLS);
|
|
28753
29213
|
|
|
29214
|
+
// apps/body/dist/mcp-route-class.js
|
|
29215
|
+
var CODE_OWNED_HOST_MCP_NAMES = ["squire"];
|
|
29216
|
+
var MCP_ROUTE_CLASS_KEY = "beeline_route";
|
|
29217
|
+
var MCP_ROUTE_HOST = "host";
|
|
29218
|
+
function isCodeOwnedHostMcpName(name) {
|
|
29219
|
+
return CODE_OWNED_HOST_MCP_NAMES.includes(name.trim().toLowerCase());
|
|
29220
|
+
}
|
|
29221
|
+
function classifyImportedMcpServer(input) {
|
|
29222
|
+
const name = input.name.trim();
|
|
29223
|
+
if (isCodeOwnedHostMcpName(name))
|
|
29224
|
+
return "host";
|
|
29225
|
+
const command = input.command ?? mcpLaunchCommand(input.declaration);
|
|
29226
|
+
const args = input.args ?? mcpLaunchArgs(input.declaration);
|
|
29227
|
+
if (command && isTrustySquireMcpLaunch(command, args))
|
|
29228
|
+
return "host";
|
|
29229
|
+
if (operatorMarkedHost(input.declaration))
|
|
29230
|
+
return "host";
|
|
29231
|
+
return "local";
|
|
29232
|
+
}
|
|
29233
|
+
function hostMcpIdentityPrefixes(name) {
|
|
29234
|
+
const lower = name.trim().toLowerCase();
|
|
29235
|
+
const normalized = lower.replace(/[^a-z0-9]+/g, "_");
|
|
29236
|
+
return [
|
|
29237
|
+
`mcp__${lower}__`,
|
|
29238
|
+
`mcp__${normalized}__`,
|
|
29239
|
+
`mcp.${lower}.`,
|
|
29240
|
+
`${lower}.`,
|
|
29241
|
+
`${lower}/`,
|
|
29242
|
+
`${lower}__`
|
|
29243
|
+
];
|
|
29244
|
+
}
|
|
29245
|
+
function isHostMcpIdentity(candidate, hostNames = CODE_OWNED_HOST_MCP_NAMES) {
|
|
29246
|
+
const lowered = candidate.trim().toLowerCase();
|
|
29247
|
+
if (!lowered)
|
|
29248
|
+
return false;
|
|
29249
|
+
return hostNames.some((name) => {
|
|
29250
|
+
const n3 = name.trim().toLowerCase();
|
|
29251
|
+
if (!n3)
|
|
29252
|
+
return false;
|
|
29253
|
+
if (lowered === n3)
|
|
29254
|
+
return true;
|
|
29255
|
+
return hostMcpIdentityPrefixes(n3).some((prefix) => lowered.startsWith(prefix));
|
|
29256
|
+
});
|
|
29257
|
+
}
|
|
29258
|
+
function operatorMarkedHost(declaration) {
|
|
29259
|
+
return declaration?.[MCP_ROUTE_CLASS_KEY] === MCP_ROUTE_HOST;
|
|
29260
|
+
}
|
|
29261
|
+
function mcpLaunchCommand(declaration) {
|
|
29262
|
+
if (!declaration)
|
|
29263
|
+
return void 0;
|
|
29264
|
+
return stringField(declaration.command) ?? stringField(declaration.cmd);
|
|
29265
|
+
}
|
|
29266
|
+
function mcpLaunchArgs(declaration) {
|
|
29267
|
+
return stringArray(declaration?.args);
|
|
29268
|
+
}
|
|
29269
|
+
function stringField(value) {
|
|
29270
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
29271
|
+
}
|
|
29272
|
+
function stringArray(value) {
|
|
29273
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : [];
|
|
29274
|
+
}
|
|
29275
|
+
|
|
29276
|
+
// apps/body/dist/host-mcp-route.js
|
|
29277
|
+
import { join as join7, resolve as resolve14 } from "node:path";
|
|
29278
|
+
var import_yaml = __toESM(require_dist(), 1);
|
|
29279
|
+
function grantedMcpServerNames(grants) {
|
|
29280
|
+
const names = /* @__PURE__ */ new Set();
|
|
29281
|
+
for (const grant of grants ?? []) {
|
|
29282
|
+
if (grant.kind !== "mcp")
|
|
29283
|
+
continue;
|
|
29284
|
+
const name = grant.target.trim();
|
|
29285
|
+
if (name)
|
|
29286
|
+
names.add(name);
|
|
29287
|
+
}
|
|
29288
|
+
return [...names];
|
|
29289
|
+
}
|
|
29290
|
+
function ungatedHostServers(hostServers, granted) {
|
|
29291
|
+
const allowed = new Set(granted);
|
|
29292
|
+
return hostServers.filter((name) => !allowed.has(name));
|
|
29293
|
+
}
|
|
29294
|
+
function grantedHostRoutesFromList(result) {
|
|
29295
|
+
if (!result || typeof result !== "object" || !("grants" in result))
|
|
29296
|
+
return [];
|
|
29297
|
+
const grants = result.grants;
|
|
29298
|
+
if (!Array.isArray(grants))
|
|
29299
|
+
return [];
|
|
29300
|
+
return grantedMcpServerNames(grants.flatMap((entry) => {
|
|
29301
|
+
if (!entry || typeof entry !== "object")
|
|
29302
|
+
return [];
|
|
29303
|
+
const row = entry;
|
|
29304
|
+
return typeof row.kind === "string" && typeof row.target === "string" ? [{ kind: row.kind, target: row.target }] : [];
|
|
29305
|
+
}));
|
|
29306
|
+
}
|
|
29307
|
+
function recordValue(value) {
|
|
29308
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
29309
|
+
}
|
|
29310
|
+
function stringArray2(value) {
|
|
29311
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : [];
|
|
29312
|
+
}
|
|
29313
|
+
function isSquireDeclaration(name, declaration) {
|
|
29314
|
+
if (isCodeOwnedHostMcpName(name))
|
|
29315
|
+
return true;
|
|
29316
|
+
const command = typeof declaration.command === "string" && declaration.command || typeof declaration.cmd === "string" && declaration.cmd || "";
|
|
29317
|
+
return Boolean(command) && isTrustySquireMcpLaunch(command, stringArray2(declaration.args));
|
|
29318
|
+
}
|
|
29319
|
+
function grantedSquireHostRoute(granted, declarations = {}) {
|
|
29320
|
+
return granted.some((name) => {
|
|
29321
|
+
if (isCodeOwnedHostMcpName(name))
|
|
29322
|
+
return true;
|
|
29323
|
+
const declaration = declarations[name];
|
|
29324
|
+
return Boolean(declaration && isSquireDeclaration(name, declaration));
|
|
29325
|
+
});
|
|
29326
|
+
}
|
|
29327
|
+
function hostRouteEnv(hostHome) {
|
|
29328
|
+
return { XDG_CONFIG_HOME: join7(resolve14(hostHome), ".config") };
|
|
29329
|
+
}
|
|
29330
|
+
function rewriteHostMcpDeclaration(name, declaration, hostHome) {
|
|
29331
|
+
const next = { ...declaration };
|
|
29332
|
+
delete next[MCP_ROUTE_CLASS_KEY];
|
|
29333
|
+
const launch = isSquireDeclaration(name, declaration) ? squireFacadeLaunch(hostHome) : void 0;
|
|
29334
|
+
const routeEnv = launch?.env ?? hostRouteEnv(hostHome);
|
|
29335
|
+
const gooseShape = "cmd" in declaration && !("command" in declaration);
|
|
29336
|
+
if (launch) {
|
|
29337
|
+
if (gooseShape)
|
|
29338
|
+
next.cmd = launch.command;
|
|
29339
|
+
else
|
|
29340
|
+
next.command = launch.command;
|
|
29341
|
+
next.args = launch.args;
|
|
29342
|
+
}
|
|
29343
|
+
if (gooseShape)
|
|
29344
|
+
next.envs = { ...recordValue(declaration.envs), ...routeEnv };
|
|
29345
|
+
else
|
|
29346
|
+
next.env = { ...recordValue(declaration.env), ...routeEnv };
|
|
29347
|
+
return next;
|
|
29348
|
+
}
|
|
29349
|
+
function rewriteGrantedHostRoutes(declarations, granted, hostHome) {
|
|
29350
|
+
const allowed = new Set(granted);
|
|
29351
|
+
const rewritten = {};
|
|
29352
|
+
for (const [name, declaration] of Object.entries(declarations)) {
|
|
29353
|
+
if (!allowed.has(name))
|
|
29354
|
+
continue;
|
|
29355
|
+
if (classifyImportedMcpServer({ name, declaration }) !== "host")
|
|
29356
|
+
continue;
|
|
29357
|
+
rewritten[name] = rewriteHostMcpDeclaration(name, declaration, hostHome);
|
|
29358
|
+
}
|
|
29359
|
+
for (const name of granted) {
|
|
29360
|
+
if (rewritten[name] || !isCodeOwnedHostMcpName(name))
|
|
29361
|
+
continue;
|
|
29362
|
+
rewritten[name] = rewriteHostMcpDeclaration(name, {}, hostHome);
|
|
29363
|
+
}
|
|
29364
|
+
return rewritten;
|
|
29365
|
+
}
|
|
29366
|
+
function grantedHostRouteWires(granted, hostHome, declarations = {}) {
|
|
29367
|
+
const routes = rewriteGrantedHostRoutes(declarations, granted, hostHome);
|
|
29368
|
+
return Object.entries(routes).flatMap(([name, declaration]) => {
|
|
29369
|
+
const command = typeof declaration.command === "string" && declaration.command || typeof declaration.cmd === "string" && declaration.cmd || "";
|
|
29370
|
+
if (!command)
|
|
29371
|
+
return [];
|
|
29372
|
+
const envRecord = recordValue(declaration.env) ?? recordValue(declaration.envs) ?? {};
|
|
29373
|
+
const env = Object.entries(envRecord).flatMap(([envName, value]) => typeof value === "string" ? [{ name: envName, value }] : []);
|
|
29374
|
+
return [
|
|
29375
|
+
{
|
|
29376
|
+
name,
|
|
29377
|
+
command,
|
|
29378
|
+
args: stringArray2(declaration.args),
|
|
29379
|
+
...env.length ? { env } : {}
|
|
29380
|
+
}
|
|
29381
|
+
];
|
|
29382
|
+
});
|
|
29383
|
+
}
|
|
29384
|
+
function mergeTomlHostRoutes(existing, routes) {
|
|
29385
|
+
if (Object.keys(routes).length === 0)
|
|
29386
|
+
return existing;
|
|
29387
|
+
const added = stringify({ mcp_servers: routes });
|
|
29388
|
+
const chunk = added.endsWith("\n") ? added : `${added}
|
|
29389
|
+
`;
|
|
29390
|
+
if (!existing?.trim())
|
|
29391
|
+
return chunk;
|
|
29392
|
+
const body = existing.endsWith("\n") ? existing : `${existing}
|
|
29393
|
+
`;
|
|
29394
|
+
return `${body}
|
|
29395
|
+
${chunk}`;
|
|
29396
|
+
}
|
|
29397
|
+
function mergeJsonHostRoutes(existing, routes) {
|
|
29398
|
+
if (Object.keys(routes).length === 0)
|
|
29399
|
+
return existing;
|
|
29400
|
+
return { ...existing ?? {}, ...routes };
|
|
29401
|
+
}
|
|
29402
|
+
function mergeGooseHostRoutes(existing, routes) {
|
|
29403
|
+
if (Object.keys(routes).length === 0)
|
|
29404
|
+
return existing;
|
|
29405
|
+
let parsed = {};
|
|
29406
|
+
if (existing?.trim()) {
|
|
29407
|
+
try {
|
|
29408
|
+
parsed = (0, import_yaml.parse)(existing);
|
|
29409
|
+
} catch {
|
|
29410
|
+
parsed = {};
|
|
29411
|
+
}
|
|
29412
|
+
}
|
|
29413
|
+
const document = recordValue(parsed) ?? {};
|
|
29414
|
+
const extensions = { ...recordValue(document.extensions), ...routes };
|
|
29415
|
+
return (0, import_yaml.stringify)({ ...document, extensions });
|
|
29416
|
+
}
|
|
29417
|
+
|
|
28754
29418
|
// apps/body/dist/openrouter-routing.js
|
|
28755
29419
|
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile6 } from "node:fs/promises";
|
|
28756
|
-
import { resolve as
|
|
29420
|
+
import { resolve as resolve15 } from "node:path";
|
|
28757
29421
|
var OPENROUTER_ENDPOINTS_BASE_URL = "https://openrouter.ai/api/v1/models";
|
|
28758
29422
|
var OPENROUTER_COMPLETIONS_URL = "https://openrouter.ai/api/v1/chat/completions";
|
|
28759
29423
|
var OPENROUTER_ROUTING_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -28855,10 +29519,10 @@ function openRouterRoutingFor(providers, allowFallbacks = true) {
|
|
|
28855
29519
|
};
|
|
28856
29520
|
}
|
|
28857
29521
|
function openRouterRoutingCacheDir(runtimeDir) {
|
|
28858
|
-
return
|
|
29522
|
+
return resolve15(runtimeDir, "openrouter-routing");
|
|
28859
29523
|
}
|
|
28860
29524
|
function cachePath(cacheDir, model) {
|
|
28861
|
-
return
|
|
29525
|
+
return resolve15(cacheDir, `${model.replace(/[^A-Za-z0-9._-]+/g, "_")}.json`);
|
|
28862
29526
|
}
|
|
28863
29527
|
async function readCache(cacheDir, model) {
|
|
28864
29528
|
try {
|
|
@@ -28889,7 +29553,7 @@ async function writeCache(cacheDir, value) {
|
|
|
28889
29553
|
});
|
|
28890
29554
|
}
|
|
28891
29555
|
function probeCachePath(cacheDir, model) {
|
|
28892
|
-
return
|
|
29556
|
+
return resolve15(cacheDir, `${model.replace(/[^A-Za-z0-9._-]+/g, "_")}.probe.json`);
|
|
28893
29557
|
}
|
|
28894
29558
|
async function readProbeCache(cacheDir, model) {
|
|
28895
29559
|
try {
|
|
@@ -29369,6 +30033,10 @@ var PI_CUSTOM_MODEL_CONFIG = {
|
|
|
29369
30033
|
source: ".pi/agent/models.json",
|
|
29370
30034
|
target: "models.json"
|
|
29371
30035
|
};
|
|
30036
|
+
var PI_MCP_CONFIG = {
|
|
30037
|
+
source: ".pi/agent/mcp.json",
|
|
30038
|
+
target: "mcp.json"
|
|
30039
|
+
};
|
|
29372
30040
|
var CODEX_ROOM_AGENT_LOCKDOWN_TOML = "[agents]\nenabled = false\n";
|
|
29373
30041
|
var CODEX_ROOM_WEB_SEARCH_TOML = "[features]\nstandalone_web_search = true\n";
|
|
29374
30042
|
var HOME_SUBDIRS = [
|
|
@@ -29384,8 +30052,8 @@ var HOME_SUBDIRS = [
|
|
|
29384
30052
|
"tmp"
|
|
29385
30053
|
];
|
|
29386
30054
|
async function prepareRoomAgentHome(input) {
|
|
29387
|
-
const root =
|
|
29388
|
-
const operatorHome = input.operatorHome ??
|
|
30055
|
+
const root = resolve16(input.root);
|
|
30056
|
+
const operatorHome = input.operatorHome ?? homedir8();
|
|
29389
30057
|
try {
|
|
29390
30058
|
await mkdir6(root, { recursive: true, mode: 448 });
|
|
29391
30059
|
const rootStats = await lstat2(root);
|
|
@@ -29393,7 +30061,7 @@ async function prepareRoomAgentHome(input) {
|
|
|
29393
30061
|
throw new AgentHomeSecurityError(`agent home root is not an ordinary directory: ${root}`);
|
|
29394
30062
|
}
|
|
29395
30063
|
for (const subdir of HOME_SUBDIRS) {
|
|
29396
|
-
const path =
|
|
30064
|
+
const path = resolve16(root, subdir);
|
|
29397
30065
|
await mkdir6(path, { recursive: true, mode: 448 });
|
|
29398
30066
|
await assertRealContainedDirectory(path, root);
|
|
29399
30067
|
}
|
|
@@ -29404,15 +30072,15 @@ async function prepareRoomAgentHome(input) {
|
|
|
29404
30072
|
return {};
|
|
29405
30073
|
}
|
|
29406
30074
|
for (const credential of SHARED_CREDENTIALS) {
|
|
29407
|
-
const source =
|
|
29408
|
-
const target =
|
|
29409
|
-
if (!
|
|
30075
|
+
const source = resolve16(operatorHome, credential.source);
|
|
30076
|
+
const target = resolve16(root, credential.dir, credential.target);
|
|
30077
|
+
if (!existsSync5(source) || existsSync5(target))
|
|
29410
30078
|
continue;
|
|
29411
|
-
await mkdir6(
|
|
30079
|
+
await mkdir6(dirname10(target), { recursive: true, mode: 448 }).catch(() => void 0);
|
|
29412
30080
|
await symlink(source, target).catch(() => void 0);
|
|
29413
30081
|
}
|
|
29414
30082
|
const prior = agentHomeProvisionQueues.get(root) ?? Promise.resolve();
|
|
29415
|
-
const provision = prior.catch(() => void 0).then(() => provisionAgentSkillsAndMcp(root, operatorHome, input.skillReleaseId ?? runningBeelineReleaseId(), input.failClosed ?? false, input.sharedSkills ?? [], agentSkillDir(input.agentKind), input.openRouterRouting, input.isReviewer ?? false));
|
|
30083
|
+
const provision = prior.catch(() => void 0).then(() => provisionAgentSkillsAndMcp(root, operatorHome, input.skillReleaseId ?? runningBeelineReleaseId(), input.failClosed ?? false, input.sharedSkills ?? [], agentSkillDir(input.agentKind), input.openRouterRouting, input.isReviewer ?? false, input.grantedHostRoutes ?? [], input.agentKind));
|
|
29416
30084
|
agentHomeProvisionQueues.set(root, provision);
|
|
29417
30085
|
try {
|
|
29418
30086
|
await provision;
|
|
@@ -29422,19 +30090,19 @@ async function prepareRoomAgentHome(input) {
|
|
|
29422
30090
|
}
|
|
29423
30091
|
return roomAgentHomeEnv(root);
|
|
29424
30092
|
}
|
|
29425
|
-
async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, failClosed, sharedSkills, skillDir, openRouterRouting, isReviewer) {
|
|
30093
|
+
async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, failClosed, sharedSkills, skillDir, openRouterRouting, isReviewer, grantedHostRoutes, agentKind) {
|
|
29426
30094
|
const managedSkills = [
|
|
29427
30095
|
{ name: USING_BEELINE_SKILL_NAME, content: usingBeelineSkillMarkdown(skillReleaseId) },
|
|
29428
30096
|
{ name: BEELINE_TRIAGE_SKILL_NAME, content: beelineTriageSkillMarkdown(skillReleaseId) },
|
|
29429
30097
|
...isReviewer ? [{ name: BEELINE_REVIEW_SKILL_NAME, content: beelineReviewSkillMarkdown(skillReleaseId) }] : []
|
|
29430
30098
|
];
|
|
29431
30099
|
const shared = await resolveSharedSkillSources(operatorHome, sharedSkills);
|
|
29432
|
-
await provisionManagedSkillsDir(
|
|
30100
|
+
await provisionManagedSkillsDir(resolve16(root, skillDir, "skills"), managedSkills, shared, sharedSkills.length === 0);
|
|
29433
30101
|
for (const config of HARNESS_MCP_CONFIGS) {
|
|
29434
30102
|
try {
|
|
29435
|
-
const source =
|
|
29436
|
-
const target =
|
|
29437
|
-
const mcpSection =
|
|
30103
|
+
const source = resolve16(operatorHome, config.toml);
|
|
30104
|
+
const target = resolve16(root, config.dir, "config.toml");
|
|
30105
|
+
const mcpSection = existsSync5(source) ? localHarnessMcpToml(readFileSync7(source, "utf8")) : void 0;
|
|
29438
30106
|
const section = config.dir === "codex" ? [CODEX_ROOM_AGENT_LOCKDOWN_TOML, CODEX_ROOM_WEB_SEARCH_TOML, mcpSection].filter(Boolean).join("\n") : mcpSection;
|
|
29439
30107
|
if (!section) {
|
|
29440
30108
|
await unlink3(target).catch(() => void 0);
|
|
@@ -29448,13 +30116,14 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
|
|
|
29448
30116
|
}
|
|
29449
30117
|
}
|
|
29450
30118
|
try {
|
|
29451
|
-
const gooseConfigDir =
|
|
30119
|
+
const gooseConfigDir = resolve16(root, "goose", "config");
|
|
29452
30120
|
await mkdir6(gooseConfigDir, { recursive: true, mode: 448 });
|
|
29453
30121
|
for (const name of GOOSE_SHARED_CONFIG_FILES) {
|
|
29454
|
-
const source =
|
|
29455
|
-
const target =
|
|
29456
|
-
if (
|
|
29457
|
-
|
|
30122
|
+
const source = resolve16(operatorHome, ".config", "goose", name);
|
|
30123
|
+
const target = resolve16(gooseConfigDir, name);
|
|
30124
|
+
if (existsSync5(source)) {
|
|
30125
|
+
const body = readFileSync7(source, "utf8");
|
|
30126
|
+
await writeIsolatedHarnessFile(target, name === "config.yaml" ? localGooseConfig(body) : body);
|
|
29458
30127
|
} else {
|
|
29459
30128
|
await unlink3(target).catch(() => void 0);
|
|
29460
30129
|
}
|
|
@@ -29465,9 +30134,9 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
|
|
|
29465
30134
|
console.warn("[body] operator Goose configuration passthrough failed:", error);
|
|
29466
30135
|
}
|
|
29467
30136
|
try {
|
|
29468
|
-
const claudeJson =
|
|
29469
|
-
const claudeTarget =
|
|
29470
|
-
const mcpServers =
|
|
30137
|
+
const claudeJson = resolve16(operatorHome, ".claude.json");
|
|
30138
|
+
const claudeTarget = resolve16(root, "claude", ".claude.json");
|
|
30139
|
+
const mcpServers = existsSync5(claudeJson) ? readClaudeUserScopeMcpServers(claudeJson) : void 0;
|
|
29471
30140
|
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
29472
30141
|
await writeIsolatedHarnessFile(claudeTarget, `${JSON.stringify({ mcpServers }, null, 2)}
|
|
29473
30142
|
`);
|
|
@@ -29479,20 +30148,100 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
|
|
|
29479
30148
|
throw error;
|
|
29480
30149
|
console.warn("[body] operator MCP passthrough failed for claude:", error);
|
|
29481
30150
|
}
|
|
30151
|
+
try {
|
|
30152
|
+
const piJson = resolve16(operatorHome, PI_MCP_CONFIG.source);
|
|
30153
|
+
const piTarget = resolve16(root, "pi", PI_MCP_CONFIG.target);
|
|
30154
|
+
const mcpServers = existsSync5(piJson) ? localMcpServers(recordValue2(readJsonObject(piJson)?.mcpServers) ?? {}) : void 0;
|
|
30155
|
+
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
30156
|
+
await writeIsolatedHarnessFile(piTarget, `${JSON.stringify({ mcpServers }, null, 2)}
|
|
30157
|
+
`);
|
|
30158
|
+
} else {
|
|
30159
|
+
await unlink3(piTarget).catch(() => void 0);
|
|
30160
|
+
}
|
|
30161
|
+
} catch (error) {
|
|
30162
|
+
if (failClosed)
|
|
30163
|
+
throw error;
|
|
30164
|
+
console.warn("[body] operator MCP passthrough failed for pi:", error);
|
|
30165
|
+
}
|
|
29482
30166
|
try {
|
|
29483
30167
|
const settings2 = { permissions: { allow: ["WebSearch", "WebFetch"] } };
|
|
29484
|
-
await writeIsolatedHarnessFile(
|
|
30168
|
+
await writeIsolatedHarnessFile(resolve16(root, "claude", "settings.json"), `${JSON.stringify(settings2, null, 2)}
|
|
29485
30169
|
`);
|
|
29486
30170
|
} catch (error) {
|
|
29487
30171
|
if (failClosed)
|
|
29488
30172
|
throw error;
|
|
29489
30173
|
console.warn("[body] claude web-search settings provisioning failed:", error);
|
|
29490
30174
|
}
|
|
30175
|
+
await applyGrantedHostRoutes(root, operatorHome, grantedHostRoutes, agentKind, failClosed);
|
|
29491
30176
|
await provisionPiCustomModelConfig(root, operatorHome, failClosed, openRouterRouting);
|
|
29492
30177
|
}
|
|
30178
|
+
function appliesToHarness(selected, harness) {
|
|
30179
|
+
return !selected || selected === harness;
|
|
30180
|
+
}
|
|
30181
|
+
async function applyGrantedHostRoutes(root, operatorHome, granted, agentKind, failClosed) {
|
|
30182
|
+
if (granted.length === 0)
|
|
30183
|
+
return;
|
|
30184
|
+
try {
|
|
30185
|
+
if (grantedSquireHostRoute(granted, hostImportedMcpDeclarations({ operatorHome, agentKind })))
|
|
30186
|
+
ensureSquireHostDir(operatorHome);
|
|
30187
|
+
const routesFor = (kind) => rewriteGrantedHostRoutes(hostImportedMcpDeclarations({ operatorHome, agentKind: kind }), granted, operatorHome);
|
|
30188
|
+
for (const config of HARNESS_MCP_CONFIGS) {
|
|
30189
|
+
if (!appliesToHarness(agentKind, config.dir))
|
|
30190
|
+
continue;
|
|
30191
|
+
const routes = routesFor(config.dir);
|
|
30192
|
+
if (Object.keys(routes).length === 0)
|
|
30193
|
+
continue;
|
|
30194
|
+
const target = resolve16(root, config.dir, "config.toml");
|
|
30195
|
+
const existing = existsSync5(target) ? readFileSync7(target, "utf8") : void 0;
|
|
30196
|
+
const merged = mergeTomlHostRoutes(existing, routes);
|
|
30197
|
+
if (merged)
|
|
30198
|
+
await writeIsolatedHarnessFile(target, merged);
|
|
30199
|
+
}
|
|
30200
|
+
if (appliesToHarness(agentKind, "goose")) {
|
|
30201
|
+
const routes = routesFor("goose");
|
|
30202
|
+
if (Object.keys(routes).length > 0) {
|
|
30203
|
+
const gooseConfigDir = resolve16(root, "goose", "config");
|
|
30204
|
+
await mkdir6(gooseConfigDir, { recursive: true, mode: 448 });
|
|
30205
|
+
const target = resolve16(gooseConfigDir, "config.yaml");
|
|
30206
|
+
const existing = existsSync5(target) ? readFileSync7(target, "utf8") : void 0;
|
|
30207
|
+
const merged = mergeGooseHostRoutes(existing, routes);
|
|
30208
|
+
if (merged)
|
|
30209
|
+
await writeIsolatedHarnessFile(target, merged);
|
|
30210
|
+
}
|
|
30211
|
+
}
|
|
30212
|
+
if (appliesToHarness(agentKind, "claude")) {
|
|
30213
|
+
const routes = routesFor("claude");
|
|
30214
|
+
if (Object.keys(routes).length > 0) {
|
|
30215
|
+
const target = resolve16(root, "claude", ".claude.json");
|
|
30216
|
+
const parsed = existsSync5(target) ? readJsonObject(target) : void 0;
|
|
30217
|
+
const merged = mergeJsonHostRoutes(recordValue2(parsed?.mcpServers), routes);
|
|
30218
|
+
if (merged && Object.keys(merged).length > 0) {
|
|
30219
|
+
await writeIsolatedHarnessFile(target, `${JSON.stringify({ mcpServers: merged }, null, 2)}
|
|
30220
|
+
`);
|
|
30221
|
+
}
|
|
30222
|
+
}
|
|
30223
|
+
}
|
|
30224
|
+
if (appliesToHarness(agentKind, "pi")) {
|
|
30225
|
+
const routes = routesFor("pi");
|
|
30226
|
+
if (Object.keys(routes).length > 0) {
|
|
30227
|
+
const target = resolve16(root, "pi", PI_MCP_CONFIG.target);
|
|
30228
|
+
const parsed = existsSync5(target) ? readJsonObject(target) : void 0;
|
|
30229
|
+
const merged = mergeJsonHostRoutes(recordValue2(parsed?.mcpServers), routes);
|
|
30230
|
+
if (merged && Object.keys(merged).length > 0) {
|
|
30231
|
+
await writeIsolatedHarnessFile(target, `${JSON.stringify({ mcpServers: merged }, null, 2)}
|
|
30232
|
+
`);
|
|
30233
|
+
}
|
|
30234
|
+
}
|
|
30235
|
+
}
|
|
30236
|
+
} catch (error) {
|
|
30237
|
+
if (failClosed)
|
|
30238
|
+
throw error;
|
|
30239
|
+
console.warn("[body] granted host MCP route passthrough failed:", error);
|
|
30240
|
+
}
|
|
30241
|
+
}
|
|
29493
30242
|
async function provisionPiCustomModelConfig(root, operatorHome, failClosed, openRouterRouting) {
|
|
29494
|
-
const source =
|
|
29495
|
-
const target =
|
|
30243
|
+
const source = resolve16(operatorHome, PI_CUSTOM_MODEL_CONFIG.source);
|
|
30244
|
+
const target = resolve16(root, "pi", PI_CUSTOM_MODEL_CONFIG.target);
|
|
29496
30245
|
let decision2;
|
|
29497
30246
|
if (openRouterRouting) {
|
|
29498
30247
|
decision2 = await resolveOpenRouterRouting(openRouterRouting);
|
|
@@ -29538,110 +30287,204 @@ async function provisionPiCustomModelConfig(root, operatorHome, failClosed, open
|
|
|
29538
30287
|
function readClaudeUserScopeMcpServers(path) {
|
|
29539
30288
|
try {
|
|
29540
30289
|
const parsed = JSON.parse(readFileSync7(path, "utf8"));
|
|
29541
|
-
|
|
29542
|
-
|
|
29543
|
-
|
|
29544
|
-
return false;
|
|
29545
|
-
const server = value;
|
|
29546
|
-
if (!server || typeof server.command !== "string")
|
|
29547
|
-
return true;
|
|
29548
|
-
const args = Array.isArray(server.args) && server.args.every((arg) => typeof arg === "string") ? server.args : [];
|
|
29549
|
-
return !isTrustySquireMcpLaunch(server.command, args);
|
|
29550
|
-
}));
|
|
29551
|
-
}
|
|
30290
|
+
const servers = recordValue2(parsed.mcpServers);
|
|
30291
|
+
if (servers)
|
|
30292
|
+
return localMcpServers(servers);
|
|
29552
30293
|
} catch {
|
|
29553
30294
|
}
|
|
29554
30295
|
return void 0;
|
|
29555
30296
|
}
|
|
29556
|
-
function
|
|
29557
|
-
|
|
29558
|
-
|
|
29559
|
-
|
|
29560
|
-
}
|
|
29561
|
-
|
|
30297
|
+
function localHarnessMcpToml(source) {
|
|
30298
|
+
let servers;
|
|
30299
|
+
try {
|
|
30300
|
+
servers = recordValue2(parse5(source).mcp_servers);
|
|
30301
|
+
} catch {
|
|
30302
|
+
return void 0;
|
|
30303
|
+
}
|
|
30304
|
+
if (!servers)
|
|
30305
|
+
return void 0;
|
|
30306
|
+
const hostNames = hostMcpServerNames(servers);
|
|
30307
|
+
const childTables = tomlChildTableNames(source, ["mcp_servers"]);
|
|
30308
|
+
if (hostNames.every((name) => childTables.includes(name))) {
|
|
30309
|
+
return extractTomlSections(source, ["mcp_servers"], hostNames);
|
|
30310
|
+
}
|
|
30311
|
+
const bareLocal = Object.fromEntries(Object.entries(servers).filter(([name]) => !childTables.includes(name) && !hostNames.includes(name)));
|
|
30312
|
+
const sections = [
|
|
30313
|
+
Object.keys(bareLocal).length > 0 ? stringify({ mcp_servers: bareLocal }) : void 0,
|
|
30314
|
+
...childTables.filter((name) => !hostNames.includes(name)).map((name) => extractTomlSections(source, ["mcp_servers", name]))
|
|
30315
|
+
].filter((section) => section !== void 0).map((section) => section.endsWith("\n") ? section : `${section}
|
|
30316
|
+
`);
|
|
30317
|
+
return sections.length > 0 ? sections.join("\n") : void 0;
|
|
30318
|
+
}
|
|
30319
|
+
function localGooseConfig(source) {
|
|
30320
|
+
let parsed;
|
|
30321
|
+
try {
|
|
30322
|
+
parsed = (0, import_yaml2.parse)(source);
|
|
30323
|
+
} catch {
|
|
30324
|
+
return source;
|
|
30325
|
+
}
|
|
30326
|
+
const document = recordValue2(parsed);
|
|
30327
|
+
const extensions = recordValue2(document?.extensions);
|
|
30328
|
+
if (!document || !extensions)
|
|
30329
|
+
return source;
|
|
30330
|
+
const local = localMcpServers(extensions);
|
|
30331
|
+
if (Object.keys(local).length === Object.keys(extensions).length)
|
|
30332
|
+
return source;
|
|
30333
|
+
return (0, import_yaml2.stringify)({ ...document, extensions: local });
|
|
30334
|
+
}
|
|
30335
|
+
function isHostMcpDeclaration(name, value) {
|
|
30336
|
+
return classifyImportedMcpServer({ name, declaration: recordValue2(value) ?? {} }) === "host";
|
|
30337
|
+
}
|
|
30338
|
+
function hostMcpServerNames(servers) {
|
|
30339
|
+
return Object.entries(servers).filter(([name, value]) => isHostMcpDeclaration(name, value)).map(([name]) => name);
|
|
30340
|
+
}
|
|
30341
|
+
function localMcpServers(servers) {
|
|
30342
|
+
return Object.fromEntries(Object.entries(servers).filter(([name, value]) => !isHostMcpDeclaration(name, value)));
|
|
30343
|
+
}
|
|
30344
|
+
function recordValue2(value) {
|
|
30345
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
29562
30346
|
}
|
|
29563
30347
|
function mountedImportedMcpServerNames(input = {}) {
|
|
29564
30348
|
const names = /* @__PURE__ */ new Set();
|
|
29565
30349
|
if (input.preparedEnv) {
|
|
29566
30350
|
const env = input.preparedEnv;
|
|
29567
|
-
const home = env.HOME ?? input.operatorHome ??
|
|
30351
|
+
const home = env.HOME ?? input.operatorHome ?? homedir8();
|
|
29568
30352
|
const kind = input.agentKind;
|
|
29569
30353
|
if (!kind || kind === "codex") {
|
|
29570
|
-
addTomlMcpNames(names,
|
|
30354
|
+
addTomlMcpNames(names, resolve16(env.CODEX_HOME ?? resolve16(home, ".codex"), "config.toml"));
|
|
29571
30355
|
}
|
|
29572
30356
|
if (!kind || kind === "grok") {
|
|
29573
|
-
addTomlMcpNames(names,
|
|
30357
|
+
addTomlMcpNames(names, resolve16(env.GROK_HOME ?? resolve16(home, ".grok"), "config.toml"));
|
|
29574
30358
|
}
|
|
29575
30359
|
if (!kind || kind === "claude") {
|
|
29576
|
-
addClaudeMcpNames(names,
|
|
30360
|
+
addClaudeMcpNames(names, resolve16(env.CLAUDE_CONFIG_DIR ?? home, ".claude.json"));
|
|
29577
30361
|
}
|
|
29578
30362
|
if (!kind || kind === "goose") {
|
|
29579
|
-
addGooseExtensionNames(names, env.GOOSE_PATH_ROOT ?
|
|
30363
|
+
addGooseExtensionNames(names, env.GOOSE_PATH_ROOT ? resolve16(env.GOOSE_PATH_ROOT, "config/config.yaml") : resolve16(home, ".config/goose/config.yaml"));
|
|
30364
|
+
}
|
|
30365
|
+
if (!kind || kind === "pi") {
|
|
30366
|
+
addClaudeMcpNames(names, resolve16(env.PI_CODING_AGENT_DIR ?? resolve16(home, ".pi/agent"), PI_MCP_CONFIG.target));
|
|
29580
30367
|
}
|
|
29581
30368
|
} else {
|
|
29582
|
-
collectImportedMcpNames(input.operatorHome ??
|
|
30369
|
+
collectImportedMcpNames(input.operatorHome ?? homedir8(), names, input.agentKind);
|
|
29583
30370
|
}
|
|
29584
30371
|
return [...names].sort((left, right) => left.localeCompare(right));
|
|
29585
30372
|
}
|
|
30373
|
+
function hostImportedMcpDeclarations(input = {}) {
|
|
30374
|
+
const operatorHome = input.operatorHome ?? homedir8();
|
|
30375
|
+
const kind = input.agentKind;
|
|
30376
|
+
const declarations = {};
|
|
30377
|
+
const add = (servers) => {
|
|
30378
|
+
if (!servers)
|
|
30379
|
+
return;
|
|
30380
|
+
for (const [name, value] of Object.entries(servers)) {
|
|
30381
|
+
if (isHostMcpDeclaration(name, value))
|
|
30382
|
+
declarations[name] = recordValue2(value) ?? {};
|
|
30383
|
+
}
|
|
30384
|
+
};
|
|
30385
|
+
if (!kind || kind === "codex")
|
|
30386
|
+
add(readTomlMcpServers(resolve16(operatorHome, ".codex/config.toml")));
|
|
30387
|
+
if (!kind || kind === "grok")
|
|
30388
|
+
add(readTomlMcpServers(resolve16(operatorHome, ".grok/config.toml")));
|
|
30389
|
+
if (!kind || kind === "claude") {
|
|
30390
|
+
add(recordValue2(readJsonObject(resolve16(operatorHome, ".claude.json"))?.mcpServers));
|
|
30391
|
+
}
|
|
30392
|
+
if (!kind || kind === "goose") {
|
|
30393
|
+
add(readGooseExtensions(resolve16(operatorHome, ".config/goose/config.yaml")));
|
|
30394
|
+
}
|
|
30395
|
+
if (!kind || kind === "pi") {
|
|
30396
|
+
add(recordValue2(readJsonObject(resolve16(operatorHome, PI_MCP_CONFIG.source))?.mcpServers));
|
|
30397
|
+
}
|
|
30398
|
+
return declarations;
|
|
30399
|
+
}
|
|
30400
|
+
function hostImportedMcpServerNames(input = {}) {
|
|
30401
|
+
return Object.keys(hostImportedMcpDeclarations(input)).sort((left, right) => left.localeCompare(right));
|
|
30402
|
+
}
|
|
30403
|
+
function grantedSquireHostBindPaths(input) {
|
|
30404
|
+
const operatorHome = input.operatorHome ?? homedir8();
|
|
30405
|
+
const granted = input.grantedHostRoutes ?? [];
|
|
30406
|
+
if (granted.length === 0)
|
|
30407
|
+
return [];
|
|
30408
|
+
return squireHostBindPaths(operatorHome, grantedSquireHostRoute(granted, hostImportedMcpDeclarations({ operatorHome, agentKind: input.agentKind })));
|
|
30409
|
+
}
|
|
30410
|
+
function expectedMountedImportedMcpServerNames(input) {
|
|
30411
|
+
const local = mountedImportedMcpServerNames({
|
|
30412
|
+
operatorHome: input.operatorHome,
|
|
30413
|
+
agentKind: input.agentKind
|
|
30414
|
+
});
|
|
30415
|
+
const allowed = new Set(input.grantedHostRoutes ?? []);
|
|
30416
|
+
const grantedHost = hostImportedMcpServerNames({
|
|
30417
|
+
operatorHome: input.operatorHome,
|
|
30418
|
+
agentKind: input.agentKind
|
|
30419
|
+
}).filter((name) => allowed.has(name));
|
|
30420
|
+
for (const name of allowed) {
|
|
30421
|
+
if (isCodeOwnedHostMcpName(name))
|
|
30422
|
+
grantedHost.push(name);
|
|
30423
|
+
}
|
|
30424
|
+
return [.../* @__PURE__ */ new Set([...local, ...grantedHost])].sort((left, right) => left.localeCompare(right));
|
|
30425
|
+
}
|
|
29586
30426
|
function collectImportedMcpNames(operatorHome, names, kind) {
|
|
29587
30427
|
if (!kind || kind === "codex") {
|
|
29588
|
-
|
|
30428
|
+
addLocalMcpNames(names, readTomlMcpServers(resolve16(operatorHome, ".codex/config.toml")));
|
|
29589
30429
|
}
|
|
29590
30430
|
if (!kind || kind === "grok") {
|
|
29591
|
-
|
|
30431
|
+
addLocalMcpNames(names, readTomlMcpServers(resolve16(operatorHome, ".grok/config.toml")));
|
|
29592
30432
|
}
|
|
29593
30433
|
if (!kind || kind === "claude") {
|
|
29594
|
-
|
|
30434
|
+
addLocalMcpNames(names, recordValue2(readJsonObject(resolve16(operatorHome, ".claude.json"))?.mcpServers));
|
|
29595
30435
|
}
|
|
29596
30436
|
if (!kind || kind === "goose") {
|
|
29597
|
-
|
|
30437
|
+
addLocalMcpNames(names, readGooseExtensions(resolve16(operatorHome, ".config/goose/config.yaml")));
|
|
29598
30438
|
}
|
|
30439
|
+
if (!kind || kind === "pi") {
|
|
30440
|
+
addLocalMcpNames(names, recordValue2(readJsonObject(resolve16(operatorHome, PI_MCP_CONFIG.source))?.mcpServers));
|
|
30441
|
+
}
|
|
30442
|
+
}
|
|
30443
|
+
function addLocalMcpNames(names, servers) {
|
|
30444
|
+
if (!servers)
|
|
30445
|
+
return;
|
|
30446
|
+
for (const name of Object.keys(localMcpServers(servers)))
|
|
30447
|
+
names.add(name);
|
|
30448
|
+
}
|
|
30449
|
+
function addTomlMcpNames(names, path) {
|
|
30450
|
+
addMcpNamesFromMap(names, readTomlMcpServers(path));
|
|
29599
30451
|
}
|
|
29600
|
-
function
|
|
30452
|
+
function addClaudeMcpNames(names, path) {
|
|
30453
|
+
addMcpNamesFromMap(names, recordValue2(readJsonObject(path)?.mcpServers));
|
|
30454
|
+
}
|
|
30455
|
+
function readTomlMcpServers(path) {
|
|
29601
30456
|
const source = readExistingText(path);
|
|
29602
30457
|
if (source === void 0)
|
|
29603
|
-
return;
|
|
29604
|
-
const mountedSource = mode === "imported" ? filteredHarnessMcpToml(source) : source;
|
|
29605
|
-
if (!mountedSource)
|
|
29606
|
-
return;
|
|
29607
|
-
let servers;
|
|
30458
|
+
return void 0;
|
|
29608
30459
|
try {
|
|
29609
|
-
|
|
30460
|
+
return recordValue2(parse5(source).mcp_servers);
|
|
29610
30461
|
} catch {
|
|
29611
|
-
return;
|
|
30462
|
+
return void 0;
|
|
29612
30463
|
}
|
|
29613
|
-
if (!servers || typeof servers !== "object" || Array.isArray(servers))
|
|
29614
|
-
return;
|
|
29615
|
-
for (const name of Object.keys(servers))
|
|
29616
|
-
names.add(name);
|
|
29617
30464
|
}
|
|
29618
|
-
function
|
|
29619
|
-
const servers = mode === "imported" ? readClaudeUserScopeMcpServers(path) : readJsonObject(path)?.mcpServers;
|
|
29620
|
-
if (!servers || typeof servers !== "object" || Array.isArray(servers))
|
|
29621
|
-
return;
|
|
29622
|
-
for (const name of Object.keys(servers))
|
|
29623
|
-
names.add(name);
|
|
29624
|
-
}
|
|
29625
|
-
function addGooseExtensionNames(names, path) {
|
|
30465
|
+
function readGooseExtensions(path) {
|
|
29626
30466
|
const source = readExistingText(path);
|
|
29627
30467
|
if (source === void 0)
|
|
29628
|
-
return;
|
|
30468
|
+
return void 0;
|
|
29629
30469
|
let parsed;
|
|
29630
30470
|
try {
|
|
29631
|
-
parsed = (0,
|
|
30471
|
+
parsed = (0, import_yaml2.parse)(source);
|
|
29632
30472
|
} catch {
|
|
29633
|
-
return;
|
|
30473
|
+
return void 0;
|
|
29634
30474
|
}
|
|
29635
|
-
|
|
29636
|
-
|
|
29637
|
-
|
|
29638
|
-
if (!
|
|
30475
|
+
return recordValue2(recordValue2(parsed)?.extensions);
|
|
30476
|
+
}
|
|
30477
|
+
function addMcpNamesFromMap(names, servers) {
|
|
30478
|
+
if (!servers)
|
|
29639
30479
|
return;
|
|
29640
|
-
for (const name of Object.keys(
|
|
30480
|
+
for (const name of Object.keys(servers))
|
|
29641
30481
|
names.add(name);
|
|
29642
30482
|
}
|
|
30483
|
+
function addGooseExtensionNames(names, path) {
|
|
30484
|
+
addMcpNamesFromMap(names, readGooseExtensions(path));
|
|
30485
|
+
}
|
|
29643
30486
|
function readExistingText(path) {
|
|
29644
|
-
if (!
|
|
30487
|
+
if (!existsSync5(path))
|
|
29645
30488
|
return void 0;
|
|
29646
30489
|
try {
|
|
29647
30490
|
return readFileSync7(path, "utf8");
|
|
@@ -29661,21 +30504,21 @@ function readJsonObject(path) {
|
|
|
29661
30504
|
}
|
|
29662
30505
|
}
|
|
29663
30506
|
async function provisionManagedSkillsDir(target, managedSkills, sharedSkills, optionalShares) {
|
|
29664
|
-
const parent =
|
|
29665
|
-
await assertRealContainedDirectory(parent,
|
|
30507
|
+
const parent = dirname10(target);
|
|
30508
|
+
await assertRealContainedDirectory(parent, dirname10(parent));
|
|
29666
30509
|
const plan = await planManagedSkills(managedSkills, sharedSkills, optionalShares);
|
|
29667
30510
|
if (await materializedSkillManifest(target) === plan.manifest)
|
|
29668
30511
|
return;
|
|
29669
|
-
const staged =
|
|
30512
|
+
const staged = resolve16(parent, `.skills.${process.pid}.${randomUUID4()}.tmp`);
|
|
29670
30513
|
await mkdir6(staged, { mode: 448 });
|
|
29671
30514
|
try {
|
|
29672
30515
|
for (const entry of plan.entries) {
|
|
29673
30516
|
if (entry.kind === "managed") {
|
|
29674
|
-
const skillDir =
|
|
30517
|
+
const skillDir = resolve16(staged, entry.name);
|
|
29675
30518
|
await mkdir6(skillDir, { recursive: true });
|
|
29676
|
-
await writeIsolatedHarnessFile(
|
|
30519
|
+
await writeIsolatedHarnessFile(resolve16(skillDir, "SKILL.md"), entry.content);
|
|
29677
30520
|
} else {
|
|
29678
|
-
await copySafeSkillTree(entry.source,
|
|
30521
|
+
await copySafeSkillTree(entry.source, resolve16(staged, entry.name), entry.source);
|
|
29679
30522
|
}
|
|
29680
30523
|
}
|
|
29681
30524
|
const existing = await lstat2(target).catch(() => void 0);
|
|
@@ -29702,8 +30545,8 @@ async function planManagedSkills(managedSkills, sharedSkills, optionalShares) {
|
|
|
29702
30545
|
try {
|
|
29703
30546
|
const tree = [];
|
|
29704
30547
|
await walkSafeSkillTree(shared.source, shared.source, {
|
|
29705
|
-
directory: async (rel) => void tree.push(`d ${
|
|
29706
|
-
file: async (rel, realPath) => void tree.push(`f ${
|
|
30548
|
+
directory: async (rel) => void tree.push(`d ${join8(shared.name, rel)}`),
|
|
30549
|
+
file: async (rel, realPath) => void tree.push(`f ${join8(shared.name, rel)} ${sha2563(await readFile6(realPath))}`)
|
|
29707
30550
|
});
|
|
29708
30551
|
entries.push({ kind: "shared", name: shared.name, source: shared.source });
|
|
29709
30552
|
lines.push(...tree);
|
|
@@ -29722,8 +30565,8 @@ async function materializedSkillManifest(target) {
|
|
|
29722
30565
|
const lines = [];
|
|
29723
30566
|
const visit = async (directory, prefix) => {
|
|
29724
30567
|
for (const entry of await readdir2(directory)) {
|
|
29725
|
-
const path =
|
|
29726
|
-
const rel = prefix ?
|
|
30568
|
+
const path = resolve16(directory, entry);
|
|
30569
|
+
const rel = prefix ? join8(prefix, entry) : entry;
|
|
29727
30570
|
const entryStats = await lstat2(path);
|
|
29728
30571
|
if (entryStats.isSymbolicLink())
|
|
29729
30572
|
return false;
|
|
@@ -29757,14 +30600,14 @@ async function resolveSharedSkillSources(operatorHome, names) {
|
|
|
29757
30600
|
const resolved = [];
|
|
29758
30601
|
const skipped = [];
|
|
29759
30602
|
for (const relativeRoot of OPERATOR_SKILL_SOURCE_DIRS) {
|
|
29760
|
-
const sourceRoot =
|
|
30603
|
+
const sourceRoot = resolve16(operatorHome, relativeRoot);
|
|
29761
30604
|
const rootStats = await lstat2(sourceRoot).catch(() => void 0);
|
|
29762
30605
|
if (!rootStats?.isDirectory() || rootStats.isSymbolicLink())
|
|
29763
30606
|
continue;
|
|
29764
30607
|
for (const entry of await readdir2(sourceRoot)) {
|
|
29765
30608
|
if (!isSharedSkillName(entry) || seen.has(entry))
|
|
29766
30609
|
continue;
|
|
29767
|
-
const candidate =
|
|
30610
|
+
const candidate = resolve16(sourceRoot, entry);
|
|
29768
30611
|
try {
|
|
29769
30612
|
const candidateStats = await lstat2(candidate);
|
|
29770
30613
|
if (candidateStats.isSymbolicLink()) {
|
|
@@ -29780,7 +30623,7 @@ async function resolveSharedSkillSources(operatorHome, names) {
|
|
|
29780
30623
|
continue;
|
|
29781
30624
|
}
|
|
29782
30625
|
assertContained(sourceRoot, candidate);
|
|
29783
|
-
const skillMd =
|
|
30626
|
+
const skillMd = resolve16(candidate, "SKILL.md");
|
|
29784
30627
|
const skillStats = await lstat2(skillMd).catch((error) => {
|
|
29785
30628
|
if (isMissingPathError(error)) {
|
|
29786
30629
|
skipped.push({ path: candidate, reason: "missing SKILL.md" });
|
|
@@ -29832,8 +30675,8 @@ async function resolveExplicitSkillSources(operatorHome, names) {
|
|
|
29832
30675
|
for (const name of unique) {
|
|
29833
30676
|
const matches = [];
|
|
29834
30677
|
for (const relativeRoot of OPERATOR_SKILL_SOURCE_DIRS) {
|
|
29835
|
-
const sourceRoot =
|
|
29836
|
-
const candidate =
|
|
30678
|
+
const sourceRoot = resolve16(operatorHome, relativeRoot);
|
|
30679
|
+
const candidate = resolve16(sourceRoot, name);
|
|
29837
30680
|
const rootStats = await lstat2(sourceRoot).catch(() => void 0);
|
|
29838
30681
|
const candidateStats = await lstat2(candidate).catch(() => void 0);
|
|
29839
30682
|
if (!candidateStats)
|
|
@@ -29850,7 +30693,7 @@ async function resolveExplicitSkillSources(operatorHome, names) {
|
|
|
29850
30693
|
if (matches.length !== 1) {
|
|
29851
30694
|
throw new Error(matches.length === 0 ? `shared skill is unavailable: ${name}` : `shared skill source is ambiguous: ${name}`);
|
|
29852
30695
|
}
|
|
29853
|
-
const skillMd =
|
|
30696
|
+
const skillMd = resolve16(matches[0], "SKILL.md");
|
|
29854
30697
|
const skillStats = await lstat2(skillMd).catch(() => void 0);
|
|
29855
30698
|
if (!skillStats?.isFile() || skillStats.isSymbolicLink() || skillStats.nlink !== 1) {
|
|
29856
30699
|
throw new Error(`shared skill requires an ordinary SKILL.md: ${name}`);
|
|
@@ -29861,7 +30704,7 @@ async function resolveExplicitSkillSources(operatorHome, names) {
|
|
|
29861
30704
|
}
|
|
29862
30705
|
function assertContained(root, candidate) {
|
|
29863
30706
|
const rel = relative2(root, candidate);
|
|
29864
|
-
if (rel === ".." || rel.startsWith(`..${sep}`) ||
|
|
30707
|
+
if (rel === ".." || rel.startsWith(`..${sep}`) || resolve16(root, rel) !== resolve16(candidate)) {
|
|
29865
30708
|
throw new Error(`path escapes the agent skill boundary: ${candidate}`);
|
|
29866
30709
|
}
|
|
29867
30710
|
}
|
|
@@ -29876,7 +30719,7 @@ var BLOCKED_SHARED_FILENAMES = /^(?:\.env(?:\..*)?|auth\.json|\.credentials\.jso
|
|
|
29876
30719
|
async function walkSafeSkillTree(source, sourceRoot, visitor, rel = "") {
|
|
29877
30720
|
assertContained(sourceRoot, source);
|
|
29878
30721
|
const resolvedSource = await realpath(source);
|
|
29879
|
-
if (resolvedSource !==
|
|
30722
|
+
if (resolvedSource !== resolve16(source)) {
|
|
29880
30723
|
throw new Error(`shared skill path resolves through a link: ${source}`);
|
|
29881
30724
|
}
|
|
29882
30725
|
assertContained(sourceRoot, resolvedSource);
|
|
@@ -29891,7 +30734,7 @@ async function walkSafeSkillTree(source, sourceRoot, visitor, rel = "") {
|
|
|
29891
30734
|
for (const entry of await readdir2(resolvedSource)) {
|
|
29892
30735
|
if (entry === "." || entry === "..")
|
|
29893
30736
|
throw new Error("invalid shared skill entry");
|
|
29894
|
-
await walkSafeSkillTree(
|
|
30737
|
+
await walkSafeSkillTree(resolve16(source, entry), sourceRoot, visitor, rel ? join8(rel, entry) : entry);
|
|
29895
30738
|
}
|
|
29896
30739
|
return;
|
|
29897
30740
|
}
|
|
@@ -29903,22 +30746,22 @@ async function walkSafeSkillTree(source, sourceRoot, visitor, rel = "") {
|
|
|
29903
30746
|
async function copySafeSkillTree(source, target, sourceRoot) {
|
|
29904
30747
|
await walkSafeSkillTree(source, sourceRoot, {
|
|
29905
30748
|
directory: async (rel) => {
|
|
29906
|
-
await mkdir6(
|
|
30749
|
+
await mkdir6(resolve16(target, rel), { mode: 448 });
|
|
29907
30750
|
},
|
|
29908
30751
|
file: async (rel, realPath) => {
|
|
29909
|
-
const destination =
|
|
30752
|
+
const destination = resolve16(target, rel);
|
|
29910
30753
|
await copyFile(realPath, destination);
|
|
29911
30754
|
await chmod3(destination, 384);
|
|
29912
30755
|
}
|
|
29913
30756
|
});
|
|
29914
30757
|
}
|
|
29915
30758
|
async function writeIsolatedHarnessFile(path, content) {
|
|
29916
|
-
const parent =
|
|
30759
|
+
const parent = dirname10(path);
|
|
29917
30760
|
const parentStats = await lstat2(parent);
|
|
29918
30761
|
if (!parentStats.isDirectory() || parentStats.isSymbolicLink()) {
|
|
29919
30762
|
throw new Error(`isolated harness parent is not a real directory: ${parent}`);
|
|
29920
30763
|
}
|
|
29921
|
-
const temporary =
|
|
30764
|
+
const temporary = resolve16(parent, `.${basename5(path)}.${process.pid}.${randomUUID4()}.tmp`);
|
|
29922
30765
|
try {
|
|
29923
30766
|
await writeFile7(temporary, content, { mode: 384, flag: "wx" });
|
|
29924
30767
|
await chmod3(temporary, 384);
|
|
@@ -29928,18 +30771,18 @@ async function writeIsolatedHarnessFile(path, content) {
|
|
|
29928
30771
|
}
|
|
29929
30772
|
}
|
|
29930
30773
|
function roomAgentHomeEnv(root) {
|
|
29931
|
-
const resolved =
|
|
30774
|
+
const resolved = resolve16(root);
|
|
29932
30775
|
return {
|
|
29933
|
-
HOME:
|
|
29934
|
-
CLAUDE_CONFIG_DIR:
|
|
29935
|
-
CODEX_HOME:
|
|
29936
|
-
GOOSE_PATH_ROOT:
|
|
29937
|
-
GROK_HOME:
|
|
29938
|
-
CURSOR_HOME:
|
|
29939
|
-
PI_CODING_AGENT_DIR:
|
|
29940
|
-
XDG_STATE_HOME:
|
|
29941
|
-
XDG_CACHE_HOME:
|
|
29942
|
-
TMPDIR:
|
|
30776
|
+
HOME: resolve16(resolved, "user"),
|
|
30777
|
+
CLAUDE_CONFIG_DIR: resolve16(resolved, "claude"),
|
|
30778
|
+
CODEX_HOME: resolve16(resolved, "codex"),
|
|
30779
|
+
GOOSE_PATH_ROOT: resolve16(resolved, "goose"),
|
|
30780
|
+
GROK_HOME: resolve16(resolved, "grok"),
|
|
30781
|
+
CURSOR_HOME: resolve16(resolved, "cursor"),
|
|
30782
|
+
PI_CODING_AGENT_DIR: resolve16(resolved, "pi"),
|
|
30783
|
+
XDG_STATE_HOME: resolve16(resolved, "state"),
|
|
30784
|
+
XDG_CACHE_HOME: resolve16(resolved, "cache"),
|
|
30785
|
+
TMPDIR: resolve16(resolved, "tmp")
|
|
29943
30786
|
};
|
|
29944
30787
|
}
|
|
29945
30788
|
var HARNESS_STATE_ENV_VARS = [
|
|
@@ -29958,15 +30801,15 @@ function harnessStateDirsFromEnv(env) {
|
|
|
29958
30801
|
for (const name of HARNESS_STATE_ENV_VARS) {
|
|
29959
30802
|
const value = env[name];
|
|
29960
30803
|
if (value)
|
|
29961
|
-
stateDirs.push(
|
|
30804
|
+
stateDirs.push(resolve16(value));
|
|
29962
30805
|
}
|
|
29963
30806
|
const tmp = env.TMPDIR;
|
|
29964
|
-
return { stateDirs, ...tmp ? { tmpDir:
|
|
30807
|
+
return { stateDirs, ...tmp ? { tmpDir: resolve16(tmp) } : {} };
|
|
29965
30808
|
}
|
|
29966
30809
|
|
|
29967
30810
|
// apps/body/dist/attachment-delivery.js
|
|
29968
30811
|
import { mkdir as mkdir7, writeFile as writeFile8 } from "node:fs/promises";
|
|
29969
|
-
import { basename as basename6, extname, join as
|
|
30812
|
+
import { basename as basename6, extname, join as join9 } from "node:path";
|
|
29970
30813
|
var MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024;
|
|
29971
30814
|
var MEDIA_TTL_HOURS = 24;
|
|
29972
30815
|
var EXPIRED_REASON = `expired: attachments are kept for ${MEDIA_TTL_HOURS} hours and these bytes are past that window`;
|
|
@@ -30026,7 +30869,7 @@ async function deliverAttachments(attachments, dir, fetchImpl = fetch) {
|
|
|
30026
30869
|
return { attachment, reason: EXPIRED_REASON };
|
|
30027
30870
|
if (!fetched.ok)
|
|
30028
30871
|
throw new Error(`HTTP ${fetched.status}`);
|
|
30029
|
-
const path =
|
|
30872
|
+
const path = join9(dir, safeFileName(attachment, index, taken));
|
|
30030
30873
|
await writeFile8(path, fetched.bytes);
|
|
30031
30874
|
const bytes = fetched.bytes;
|
|
30032
30875
|
const mimeType = attachment.mimeType ?? fetched.mimeType;
|
|
@@ -30215,6 +31058,12 @@ function durableReplyText(agentText) {
|
|
|
30215
31058
|
var AgentTurnStream = class {
|
|
30216
31059
|
options;
|
|
30217
31060
|
latest = "";
|
|
31061
|
+
/**
|
|
31062
|
+
* The assistant run currently accumulating — what `finalAgentMessageText`
|
|
31063
|
+
* would return if the prompt ended here. The join above is the draft lane's
|
|
31064
|
+
* material; this is the only part of the stream an ending may commit.
|
|
31065
|
+
*/
|
|
31066
|
+
latestRun = "";
|
|
30218
31067
|
/**
|
|
30219
31068
|
* The newest snapshot not yet handed to a write. A draft is a picture of the
|
|
30220
31069
|
* whole answer so far, so an older snapshot that never reached the wire is
|
|
@@ -30238,10 +31087,14 @@ var AgentTurnStream = class {
|
|
|
30238
31087
|
/**
|
|
30239
31088
|
* The ACP delta hook: hand it straight to `sessionPrompt`. `full` is every
|
|
30240
31089
|
* assistant run so far joined — not the final answer — so it is only ever
|
|
30241
|
-
* shown provisionally.
|
|
31090
|
+
* shown provisionally. A caller that cannot name the current run leaves
|
|
31091
|
+
* `lastRunText` empty rather than letting the join stand in for it: an
|
|
31092
|
+
* unknown last run is not an answer, and an ending that reads one must
|
|
31093
|
+
* settle through whatever else it has.
|
|
30242
31094
|
*/
|
|
30243
|
-
onChunk = (_delta, full) => {
|
|
31095
|
+
onChunk = (_delta, full, currentRun) => {
|
|
30244
31096
|
this.latest = full;
|
|
31097
|
+
this.latestRun = currentRun ?? "";
|
|
30245
31098
|
const text2 = sanitizeAgentReply(full);
|
|
30246
31099
|
if (!text2 || this.closed)
|
|
30247
31100
|
return;
|
|
@@ -30278,9 +31131,19 @@ var AgentTurnStream = class {
|
|
|
30278
31131
|
get streamedText() {
|
|
30279
31132
|
return this.latest;
|
|
30280
31133
|
}
|
|
31134
|
+
/**
|
|
31135
|
+
* The LAST assistant run alone — the same text `PromptResult.agentText`
|
|
31136
|
+
* carries when the prompt returns, available to an ending the prompt never
|
|
31137
|
+
* reached. An earlier run is progress narration around tool work and is not
|
|
31138
|
+
* this turn's answer, however the turn ends.
|
|
31139
|
+
*/
|
|
31140
|
+
get lastRunText() {
|
|
31141
|
+
return this.latestRun;
|
|
31142
|
+
}
|
|
30281
31143
|
/** Forget the previous run's stream text; a re-pinned retry starts clean. */
|
|
30282
31144
|
beginRun() {
|
|
30283
31145
|
this.latest = "";
|
|
31146
|
+
this.latestRun = "";
|
|
30284
31147
|
this.pending = void 0;
|
|
30285
31148
|
}
|
|
30286
31149
|
/**
|
|
@@ -30427,7 +31290,7 @@ function mountedMcpSet(servers) {
|
|
|
30427
31290
|
|
|
30428
31291
|
// apps/body/dist/pi-mcp-bridge.js
|
|
30429
31292
|
import { mkdir as mkdir8 } from "node:fs/promises";
|
|
30430
|
-
import { resolve as
|
|
31293
|
+
import { resolve as resolve17 } from "node:path";
|
|
30431
31294
|
var PI_MCP_BRIDGE_FILENAME = "beeline-mcp-bridge.js";
|
|
30432
31295
|
function isPiAcpCommand(agentCommand) {
|
|
30433
31296
|
return Boolean(agentCommand && /(^|[/\\])pi-acp(\.[a-z]+)?$/i.test(agentCommand));
|
|
@@ -30447,8 +31310,8 @@ async function installPiMcpBridge(input) {
|
|
|
30447
31310
|
return void 0;
|
|
30448
31311
|
if (!input.piHome || !input.servers.length)
|
|
30449
31312
|
return void 0;
|
|
30450
|
-
const directory =
|
|
30451
|
-
const path =
|
|
31313
|
+
const directory = resolve17(input.piHome, "extensions");
|
|
31314
|
+
const path = resolve17(directory, PI_MCP_BRIDGE_FILENAME);
|
|
30452
31315
|
try {
|
|
30453
31316
|
await mkdir8(directory, { recursive: true, mode: 448 });
|
|
30454
31317
|
await writeIsolatedHarnessFile(path, piMcpBridgeSource(input.servers));
|
|
@@ -30460,7 +31323,8 @@ async function installPiMcpBridge(input) {
|
|
|
30460
31323
|
}
|
|
30461
31324
|
var BRIDGE_PREAMBLE = `// Generated by Beeline for one Room session. Do not edit: it is rewritten on
|
|
30462
31325
|
// every activation. It republishes this session's MCP servers as pi tools,
|
|
30463
|
-
// because pi has no MCP client of its own
|
|
31326
|
+
// because pi 0.85.1 has no MCP client of its own and pi-acp 0.0.33 still
|
|
31327
|
+
// drops session/new mcpServers (apps/body/src/pi-mcp-bridge.ts).
|
|
30464
31328
|
import { spawn } from 'node:child_process';
|
|
30465
31329
|
|
|
30466
31330
|
`;
|
|
@@ -30648,7 +31512,7 @@ async function contains(git, head, ancestor) {
|
|
|
30648
31512
|
}
|
|
30649
31513
|
|
|
30650
31514
|
// apps/body/dist/room-session.js
|
|
30651
|
-
import { resolve as
|
|
31515
|
+
import { resolve as resolve18 } from "node:path";
|
|
30652
31516
|
|
|
30653
31517
|
// apps/body/dist/read-only-policy.js
|
|
30654
31518
|
var READ_ONLY_MCP_SERVER_NAME = "beeline-readonly-mcp";
|
|
@@ -30794,22 +31658,14 @@ var AGENT_SURFACE_TOOL_NAMES = [
|
|
|
30794
31658
|
"write_scratch_file",
|
|
30795
31659
|
"fetch_image"
|
|
30796
31660
|
];
|
|
30797
|
-
|
|
30798
|
-
"mcp__squire__",
|
|
30799
|
-
"mcp.squire.",
|
|
30800
|
-
"squire.",
|
|
30801
|
-
"squire/",
|
|
30802
|
-
// grok's qualified `<server>__<tool>` spelling, inside `use_tool` or as the
|
|
30803
|
-
// relabelled title.
|
|
30804
|
-
"squire__"
|
|
30805
|
-
];
|
|
30806
|
-
function isSquireMcpPermissionRequest(request) {
|
|
31661
|
+
function isHostMcpPermissionRequest(request, hostServers = CODE_OWNED_HOST_MCP_NAMES) {
|
|
30807
31662
|
const rawInput = request.toolCall?.rawInput;
|
|
30808
31663
|
if (rawInput && typeof rawInput === "object" && !Array.isArray(rawInput)) {
|
|
30809
|
-
|
|
31664
|
+
const server = rawInput.server;
|
|
31665
|
+
if (typeof server === "string" && isHostMcpIdentity(server, hostServers))
|
|
30810
31666
|
return true;
|
|
30811
31667
|
}
|
|
30812
|
-
return toolIdentityCandidates(request.toolCall).some((candidate) =>
|
|
31668
|
+
return toolIdentityCandidates(request.toolCall).some((candidate) => isHostMcpIdentity(candidate, hostServers));
|
|
30813
31669
|
}
|
|
30814
31670
|
function isBeelineAgentMcpPermissionRequest(request) {
|
|
30815
31671
|
const toolCall = request.toolCall;
|
|
@@ -31115,14 +31971,14 @@ function readOnlyMcpServer(config, cwd, agentMemoryDir) {
|
|
|
31115
31971
|
command: config.readonlyMcpCommand,
|
|
31116
31972
|
args: [...config.readonlyMcpArgs ?? []],
|
|
31117
31973
|
env: [
|
|
31118
|
-
{ name: "BEELINE_READONLY_ROOT", value:
|
|
31974
|
+
{ name: "BEELINE_READONLY_ROOT", value: resolve18(cwd) },
|
|
31119
31975
|
...config.agentHomeRoot ? [
|
|
31120
31976
|
{
|
|
31121
31977
|
name: "BEELINE_READONLY_AGENT_SKILLS_ROOT",
|
|
31122
|
-
value:
|
|
31978
|
+
value: resolve18(config.agentHomeRoot, skillDir, "skills")
|
|
31123
31979
|
}
|
|
31124
31980
|
] : [],
|
|
31125
|
-
...agentMemoryDir ? [{ name: "BEELINE_READONLY_AGENT_MEMORY_ROOT", value:
|
|
31981
|
+
...agentMemoryDir ? [{ name: "BEELINE_READONLY_AGENT_MEMORY_ROOT", value: resolve18(agentMemoryDir) }] : []
|
|
31126
31982
|
]
|
|
31127
31983
|
};
|
|
31128
31984
|
}
|
|
@@ -31142,7 +31998,7 @@ function youtubeMcpServer(config, accessToken) {
|
|
|
31142
31998
|
|
|
31143
31999
|
// apps/body/dist/pi-turn-record.js
|
|
31144
32000
|
import { readdir as readdir3, readFile as readFile7 } from "node:fs/promises";
|
|
31145
|
-
import { resolve as
|
|
32001
|
+
import { resolve as resolve19 } from "node:path";
|
|
31146
32002
|
function summarizeProviderError(errorMessage2) {
|
|
31147
32003
|
const trimmed = errorMessage2.trim();
|
|
31148
32004
|
const statusMatch = /^(\d{3}):\s*([\s\S]*)$/.exec(trimmed);
|
|
@@ -31163,7 +32019,7 @@ function summarizeProviderError(errorMessage2) {
|
|
|
31163
32019
|
}
|
|
31164
32020
|
async function sessionFileFromMap(home, sessionId) {
|
|
31165
32021
|
try {
|
|
31166
|
-
const raw = await readFile7(
|
|
32022
|
+
const raw = await readFile7(resolve19(home, ".pi", "pi-acp", "session-map.json"), "utf8");
|
|
31167
32023
|
const map = JSON.parse(raw);
|
|
31168
32024
|
const file = map.sessions?.[sessionId]?.sessionFile;
|
|
31169
32025
|
return typeof file === "string" && file ? file : void 0;
|
|
@@ -31172,7 +32028,7 @@ async function sessionFileFromMap(home, sessionId) {
|
|
|
31172
32028
|
}
|
|
31173
32029
|
}
|
|
31174
32030
|
async function sessionFileFromLayout(piDir, sessionId) {
|
|
31175
|
-
const sessionsRoot =
|
|
32031
|
+
const sessionsRoot = resolve19(piDir, "sessions");
|
|
31176
32032
|
const suffix = `_${sessionId}.jsonl`;
|
|
31177
32033
|
let projects;
|
|
31178
32034
|
try {
|
|
@@ -31181,7 +32037,7 @@ async function sessionFileFromLayout(piDir, sessionId) {
|
|
|
31181
32037
|
return void 0;
|
|
31182
32038
|
}
|
|
31183
32039
|
for (const project of projects) {
|
|
31184
|
-
const dir =
|
|
32040
|
+
const dir = resolve19(sessionsRoot, project);
|
|
31185
32041
|
let files;
|
|
31186
32042
|
try {
|
|
31187
32043
|
files = await readdir3(dir);
|
|
@@ -31190,7 +32046,7 @@ async function sessionFileFromLayout(piDir, sessionId) {
|
|
|
31190
32046
|
}
|
|
31191
32047
|
const match = files.find((file) => file.endsWith(suffix));
|
|
31192
32048
|
if (match)
|
|
31193
|
-
return
|
|
32049
|
+
return resolve19(dir, match);
|
|
31194
32050
|
}
|
|
31195
32051
|
return void 0;
|
|
31196
32052
|
}
|
|
@@ -31365,7 +32221,7 @@ async function withTurnReceiptHeartbeat(api, receipt, task, onHeartbeatError) {
|
|
|
31365
32221
|
|
|
31366
32222
|
// apps/body/dist/turn-trace.js
|
|
31367
32223
|
import { appendFile, mkdir as mkdir9, readdir as readdir4, rm as rm3 } from "node:fs/promises";
|
|
31368
|
-
import { resolve as
|
|
32224
|
+
import { resolve as resolve20 } from "node:path";
|
|
31369
32225
|
import { performance as performance2 } from "node:perf_hooks";
|
|
31370
32226
|
var TURN_PHASES = [
|
|
31371
32227
|
/** Enqueued on `SessionScheduler` until this turn holds a slot. A capacity wait lives here. */
|
|
@@ -31595,7 +32451,7 @@ function formatTurnTraceLine(record3) {
|
|
|
31595
32451
|
return [head, ...record3.attempts.map((attempt) => formatTurnAttempt(attempt))].join("\n ");
|
|
31596
32452
|
}
|
|
31597
32453
|
function turnTraceDirectory(runtimeDir) {
|
|
31598
|
-
return
|
|
32454
|
+
return resolve20(runtimeDir, "turn-traces");
|
|
31599
32455
|
}
|
|
31600
32456
|
var TURN_TRACE_RETENTION_DAYS = 7;
|
|
31601
32457
|
function traceFileName(date) {
|
|
@@ -31612,7 +32468,7 @@ var TurnTraceFile = class {
|
|
|
31612
32468
|
this.options = options;
|
|
31613
32469
|
}
|
|
31614
32470
|
path(now2 = (this.options.clock ?? (() => /* @__PURE__ */ new Date()))()) {
|
|
31615
|
-
return
|
|
32471
|
+
return resolve20(this.directory, traceFileName(now2));
|
|
31616
32472
|
}
|
|
31617
32473
|
write(record3) {
|
|
31618
32474
|
this.tail = this.tail.catch(() => void 0).then(async () => {
|
|
@@ -31636,15 +32492,15 @@ var TurnTraceFile = class {
|
|
|
31636
32492
|
this.prunedDay = day;
|
|
31637
32493
|
const cutoff = traceFileName(new Date(now2.getTime() - TURN_TRACE_RETENTION_DAYS * 864e5));
|
|
31638
32494
|
const names = await readdir4(this.directory).catch(() => []);
|
|
31639
|
-
await Promise.all(names.filter((name) => /^turns-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name) && name < cutoff).map((name) => rm3(
|
|
32495
|
+
await Promise.all(names.filter((name) => /^turns-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name) && name < cutoff).map((name) => rm3(resolve20(this.directory, name), { force: true })));
|
|
31640
32496
|
}
|
|
31641
32497
|
};
|
|
31642
32498
|
|
|
31643
32499
|
// apps/body/dist/corner-github-auth.js
|
|
31644
32500
|
import { chmod as chmod4, mkdir as mkdir10, writeFile as writeFile9 } from "node:fs/promises";
|
|
31645
|
-
import { delimiter as delimiter2, resolve as
|
|
32501
|
+
import { delimiter as delimiter2, resolve as resolve21 } from "node:path";
|
|
31646
32502
|
async function installCornerGitHubWrappers(input) {
|
|
31647
|
-
const bin =
|
|
32503
|
+
const bin = resolve21(input.root, "beeline-github-bin");
|
|
31648
32504
|
await mkdir10(bin, { recursive: true, mode: 448 });
|
|
31649
32505
|
const common = {
|
|
31650
32506
|
node: process.execPath,
|
|
@@ -31654,13 +32510,13 @@ async function installCornerGitHubWrappers(input) {
|
|
|
31654
32510
|
featureBranch: input.featureBranch,
|
|
31655
32511
|
targetBranch: input.targetBranch
|
|
31656
32512
|
};
|
|
31657
|
-
await writeLauncher(
|
|
32513
|
+
await writeLauncher(resolve21(bin, "git"), {
|
|
31658
32514
|
...common,
|
|
31659
32515
|
command: input.gitBinary,
|
|
31660
32516
|
launcher: "git"
|
|
31661
32517
|
});
|
|
31662
32518
|
if (input.ghBinary)
|
|
31663
|
-
await writeLauncher(
|
|
32519
|
+
await writeLauncher(resolve21(bin, "gh"), {
|
|
31664
32520
|
...common,
|
|
31665
32521
|
command: input.ghBinary,
|
|
31666
32522
|
launcher: "gh"
|
|
@@ -31798,22 +32654,22 @@ process.exit(result.status ?? 1);
|
|
|
31798
32654
|
import { createHash as createHash5, randomUUID as randomUUID5 } from "node:crypto";
|
|
31799
32655
|
import { constants as fsConstants } from "node:fs";
|
|
31800
32656
|
import { chmod as chmod5, copyFile as copyFile2, link, lstat as lstat3, mkdir as mkdir11, readdir as readdir5, readFile as readFile8, readlink, rename as rename4, rm as rm4, stat as stat2, symlink as symlink2, utimes } from "node:fs/promises";
|
|
31801
|
-
import { dirname as
|
|
32657
|
+
import { dirname as dirname11, join as join10, resolve as resolve22 } from "node:path";
|
|
31802
32658
|
var STORE_FORMAT = "v1";
|
|
31803
32659
|
var STAGING_PREFIX = ".beeline-warm-";
|
|
31804
32660
|
var STAGING_SWEEP_MS = 24 * 60 * 60 * 1e3;
|
|
31805
32661
|
var WARM_STORE_MAX_ENTRIES = 3;
|
|
31806
32662
|
function sharedNpmCacheDir(supervisorRoot) {
|
|
31807
|
-
return
|
|
32663
|
+
return resolve22(supervisorRoot, "beeline", "npm-cache");
|
|
31808
32664
|
}
|
|
31809
32665
|
function warmNodeModulesStoreDir(supervisorRoot) {
|
|
31810
|
-
return
|
|
32666
|
+
return resolve22(supervisorRoot, "beeline", "node-modules");
|
|
31811
32667
|
}
|
|
31812
32668
|
function isPlanRefusal(value) {
|
|
31813
32669
|
return "failure" in value;
|
|
31814
32670
|
}
|
|
31815
32671
|
async function readWarmPlan(worktreePath) {
|
|
31816
|
-
const lockfile = await readFile8(
|
|
32672
|
+
const lockfile = await readFile8(resolve22(worktreePath, "package-lock.json")).catch(() => void 0);
|
|
31817
32673
|
if (!lockfile)
|
|
31818
32674
|
return { failure: "no-lockfile" };
|
|
31819
32675
|
const packages = parseLockfilePackages(lockfile);
|
|
@@ -31852,11 +32708,11 @@ async function seedWarmNodeModules(input) {
|
|
|
31852
32708
|
return { reason: plan.failure, ...plan.detail ? { detail: plan.detail } : {} };
|
|
31853
32709
|
}
|
|
31854
32710
|
for (const tree of plan.trees) {
|
|
31855
|
-
if (await pathExists(
|
|
32711
|
+
if (await pathExists(resolve22(input.worktreePath, tree))) {
|
|
31856
32712
|
return { reason: "present", key: plan.key };
|
|
31857
32713
|
}
|
|
31858
32714
|
}
|
|
31859
|
-
const entry =
|
|
32715
|
+
const entry = resolve22(input.storeRoot, plan.key);
|
|
31860
32716
|
if (!await isDirectory(entry))
|
|
31861
32717
|
return { reason: "cold", key: plan.key };
|
|
31862
32718
|
const [storeDevice, checkoutDevice] = await Promise.all([
|
|
@@ -31866,19 +32722,19 @@ async function seedWarmNodeModules(input) {
|
|
|
31866
32722
|
if (storeDevice === void 0 || storeDevice !== checkoutDevice) {
|
|
31867
32723
|
return { reason: "cross-device", key: plan.key };
|
|
31868
32724
|
}
|
|
31869
|
-
const staging =
|
|
32725
|
+
const staging = resolve22(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID5()}`);
|
|
31870
32726
|
const placed = [];
|
|
31871
32727
|
const now2 = (input.now ?? Date.now)();
|
|
31872
32728
|
try {
|
|
31873
32729
|
await sweepStaleStaging(input.storeRoot, now2);
|
|
31874
32730
|
await utimes(entry, now2 / 1e3, now2 / 1e3).catch(() => void 0);
|
|
31875
32731
|
for (const tree of plan.trees) {
|
|
31876
|
-
await cloneTree(
|
|
32732
|
+
await cloneTree(resolve22(entry, tree), resolve22(staging, tree), seedFile);
|
|
31877
32733
|
}
|
|
31878
32734
|
for (const tree of plan.trees) {
|
|
31879
|
-
const target =
|
|
31880
|
-
await mkdir11(
|
|
31881
|
-
await rename4(
|
|
32735
|
+
const target = resolve22(input.worktreePath, tree);
|
|
32736
|
+
await mkdir11(dirname11(target), { recursive: true });
|
|
32737
|
+
await rename4(resolve22(staging, tree), target);
|
|
31882
32738
|
placed.push(target);
|
|
31883
32739
|
}
|
|
31884
32740
|
return { reason: "seeded", key: plan.key };
|
|
@@ -31896,11 +32752,11 @@ async function harvestWarmNodeModules(input) {
|
|
|
31896
32752
|
if (isPlanRefusal(plan)) {
|
|
31897
32753
|
return { reason: plan.failure, ...plan.detail ? { detail: plan.detail } : {} };
|
|
31898
32754
|
}
|
|
31899
|
-
const entry =
|
|
32755
|
+
const entry = resolve22(input.storeRoot, plan.key);
|
|
31900
32756
|
if (await pathExists(entry))
|
|
31901
32757
|
return { reason: "already-warm", key: plan.key };
|
|
31902
32758
|
for (const tree of plan.trees) {
|
|
31903
|
-
if (!await isDirectory(
|
|
32759
|
+
if (!await isDirectory(resolve22(input.worktreePath, tree))) {
|
|
31904
32760
|
return { reason: "no-node-modules", key: plan.key, detail: tree };
|
|
31905
32761
|
}
|
|
31906
32762
|
}
|
|
@@ -31912,12 +32768,12 @@ async function harvestWarmNodeModules(input) {
|
|
|
31912
32768
|
detail: `${missing.length} absent, e.g. ${missing.slice(0, 3).join(", ")}`
|
|
31913
32769
|
};
|
|
31914
32770
|
}
|
|
31915
|
-
const staging =
|
|
32771
|
+
const staging = resolve22(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID5()}`);
|
|
31916
32772
|
try {
|
|
31917
32773
|
await mkdir11(input.storeRoot, { recursive: true, mode: 493 });
|
|
31918
32774
|
await sweepStaleStaging(input.storeRoot, (input.now ?? Date.now)());
|
|
31919
32775
|
for (const tree of plan.trees) {
|
|
31920
|
-
await cloneTree(
|
|
32776
|
+
await cloneTree(resolve22(input.worktreePath, tree), resolve22(staging, tree), harvestFile);
|
|
31921
32777
|
}
|
|
31922
32778
|
await input.onCopied?.();
|
|
31923
32779
|
if (!await stagedTreeIsPublishable(input.worktreePath, staging, plan.key)) {
|
|
@@ -31938,18 +32794,18 @@ async function stagedTreeIsPublishable(worktreePath, staging, key) {
|
|
|
31938
32794
|
const settled = await readWarmPlan(worktreePath);
|
|
31939
32795
|
if (isPlanRefusal(settled) || settled.key !== key)
|
|
31940
32796
|
return false;
|
|
31941
|
-
const hidden =
|
|
32797
|
+
const hidden = join10("node_modules", ".package-lock.json");
|
|
31942
32798
|
const [copied, current] = await Promise.all([
|
|
31943
|
-
readFile8(
|
|
31944
|
-
readFile8(
|
|
32799
|
+
readFile8(resolve22(staging, hidden)).catch(() => void 0),
|
|
32800
|
+
readFile8(resolve22(worktreePath, hidden)).catch(() => void 0)
|
|
31945
32801
|
]);
|
|
31946
32802
|
if (!copied || !current || !copied.equals(current))
|
|
31947
32803
|
return false;
|
|
31948
32804
|
return (await missingInstalledPackages(worktreePath, staging)).length === 0;
|
|
31949
32805
|
}
|
|
31950
32806
|
async function missingInstalledPackages(worktreePath, treeRoot = worktreePath) {
|
|
31951
|
-
const wanted = parseLockfilePackages(await readFile8(
|
|
31952
|
-
const installed = parseLockfilePackages(await readFile8(
|
|
32807
|
+
const wanted = parseLockfilePackages(await readFile8(resolve22(worktreePath, "package-lock.json")).catch(() => void 0));
|
|
32808
|
+
const installed = parseLockfilePackages(await readFile8(resolve22(treeRoot, "node_modules", ".package-lock.json")).catch(() => void 0));
|
|
31953
32809
|
if (!wanted)
|
|
31954
32810
|
return ["package-lock.json is unreadable"];
|
|
31955
32811
|
if (!installed)
|
|
@@ -31969,14 +32825,14 @@ async function missingInstalledPackages(worktreePath, treeRoot = worktreePath) {
|
|
|
31969
32825
|
required.push(path);
|
|
31970
32826
|
}
|
|
31971
32827
|
await mapWithLimit(required, INTEGRITY_READ_CONCURRENCY, async (path) => {
|
|
31972
|
-
if (!(path in installed) || !await isInstalledPackage(
|
|
32828
|
+
if (!(path in installed) || !await isInstalledPackage(resolve22(treeRoot, path))) {
|
|
31973
32829
|
missing.push(path);
|
|
31974
32830
|
}
|
|
31975
32831
|
});
|
|
31976
32832
|
return missing.sort();
|
|
31977
32833
|
}
|
|
31978
32834
|
async function isInstalledPackage(path) {
|
|
31979
|
-
return stat2(
|
|
32835
|
+
return stat2(join10(path, "package.json")).then((info) => info.isFile(), () => false);
|
|
31980
32836
|
}
|
|
31981
32837
|
var INTEGRITY_READ_CONCURRENCY = 64;
|
|
31982
32838
|
async function mapWithLimit(values, limit, visit) {
|
|
@@ -32010,8 +32866,8 @@ function isContainedTreePath(value) {
|
|
|
32010
32866
|
async function cloneTree(source, target, file, topLevel = true) {
|
|
32011
32867
|
await mkdir11(target, { recursive: true, mode: 493 });
|
|
32012
32868
|
for (const entry of await readdir5(source, { withFileTypes: true })) {
|
|
32013
|
-
const from =
|
|
32014
|
-
const to =
|
|
32869
|
+
const from = join10(source, entry.name);
|
|
32870
|
+
const to = join10(target, entry.name);
|
|
32015
32871
|
if (entry.isSymbolicLink()) {
|
|
32016
32872
|
await symlink2(await readlink(from), to);
|
|
32017
32873
|
continue;
|
|
@@ -32041,13 +32897,13 @@ async function pruneWarmStore(storeRoot, keep) {
|
|
|
32041
32897
|
const names = (await readdir5(storeRoot).catch(() => [])).filter((name) => !name.startsWith(STAGING_PREFIX));
|
|
32042
32898
|
const entries = [];
|
|
32043
32899
|
for (const name of names) {
|
|
32044
|
-
const info = await lstat3(
|
|
32900
|
+
const info = await lstat3(join10(storeRoot, name)).catch(() => void 0);
|
|
32045
32901
|
if (info?.isDirectory())
|
|
32046
32902
|
entries.push({ name, usedAt: info.mtimeMs });
|
|
32047
32903
|
}
|
|
32048
32904
|
const dropped = entries.sort((a2, b) => b.usedAt - a2.usedAt || a2.name.localeCompare(b.name)).slice(keep);
|
|
32049
32905
|
for (const entry of dropped) {
|
|
32050
|
-
await rm4(
|
|
32906
|
+
await rm4(join10(storeRoot, entry.name), { recursive: true, force: true }).catch(() => void 0);
|
|
32051
32907
|
}
|
|
32052
32908
|
return dropped.map((entry) => entry.name);
|
|
32053
32909
|
}
|
|
@@ -32056,7 +32912,7 @@ async function sweepStaleStaging(storeRoot, now2) {
|
|
|
32056
32912
|
for (const name of entries) {
|
|
32057
32913
|
if (!name.startsWith(STAGING_PREFIX))
|
|
32058
32914
|
continue;
|
|
32059
|
-
const path =
|
|
32915
|
+
const path = join10(storeRoot, name);
|
|
32060
32916
|
const info = await lstat3(path).catch(() => void 0);
|
|
32061
32917
|
if (!info || now2 - info.mtimeMs < STAGING_SWEEP_MS)
|
|
32062
32918
|
continue;
|
|
@@ -32078,8 +32934,8 @@ function describe3(error) {
|
|
|
32078
32934
|
|
|
32079
32935
|
// apps/body/dist/monolith-room-turn.js
|
|
32080
32936
|
import { mkdir as mkdir12 } from "node:fs/promises";
|
|
32081
|
-
import { homedir as
|
|
32082
|
-
import { join as
|
|
32937
|
+
import { homedir as homedir9 } from "node:os";
|
|
32938
|
+
import { join as join11 } from "node:path";
|
|
32083
32939
|
|
|
32084
32940
|
// packages/api-contract/dist/scheduled-prompts.js
|
|
32085
32941
|
var SCHEDULE_SCHEDULER_NAME = "Beeline Scheduler";
|
|
@@ -32087,8 +32943,8 @@ var SCHEDULE_RAN_VERB = "ran a schedule for";
|
|
|
32087
32943
|
|
|
32088
32944
|
// apps/body/dist/monolith-room-turn.js
|
|
32089
32945
|
var ROOM_PROMPT_INACTIVITY_TIMEOUT_MS = 18e4;
|
|
32090
|
-
function isRoomMcpPermissionRequest(request, mountedServers = ROOM_MOUNTED_MCP_SERVERS) {
|
|
32091
|
-
if (
|
|
32946
|
+
function isRoomMcpPermissionRequest(request, mountedServers = ROOM_MOUNTED_MCP_SERVERS, hostServers = CODE_OWNED_HOST_MCP_NAMES) {
|
|
32947
|
+
if (isHostMcpPermissionRequest(request, hostServers))
|
|
32092
32948
|
return false;
|
|
32093
32949
|
return isMountedMcpToolPermissionRequest(request, mountedServers);
|
|
32094
32950
|
}
|
|
@@ -32229,7 +33085,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
32229
33085
|
...this.options.config.bwrapPath ? { bwrapPath: this.options.config.bwrapPath } : {},
|
|
32230
33086
|
...this.sessionScratchDir ? { scratch: this.sessionScratchDir } : {},
|
|
32231
33087
|
...this.sessionStateDirs.length ? { harnessStateDirs: this.sessionStateDirs } : {},
|
|
32232
|
-
maskPaths: credentialMaskPaths(this.options.config.sandboxMaskPaths, this.options.config.operatorHome ??
|
|
33088
|
+
maskPaths: credentialMaskPaths(this.options.config.sandboxMaskPaths, this.options.config.operatorHome ?? homedir9())
|
|
32233
33089
|
};
|
|
32234
33090
|
}
|
|
32235
33091
|
/**
|
|
@@ -32296,7 +33152,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
32296
33152
|
const cached = this.deliveredAttachments.get(item.id);
|
|
32297
33153
|
if (cached)
|
|
32298
33154
|
return cached;
|
|
32299
|
-
const delivered = await deliverAttachments(item.attachments,
|
|
33155
|
+
const delivered = await deliverAttachments(item.attachments, join11(this.attachmentDir, item.id.replace(/[^\w-]/g, "_")), this.options.fetchImpl);
|
|
32300
33156
|
this.deliveredAttachments.set(item.id, withoutImageData(delivered));
|
|
32301
33157
|
return delivered;
|
|
32302
33158
|
}
|
|
@@ -32329,12 +33185,13 @@ var MonolithRoomTurnLoop = class {
|
|
|
32329
33185
|
return await this.currentSessionFingerprint() === this.sessionFingerprint;
|
|
32330
33186
|
}
|
|
32331
33187
|
async currentSessionFingerprint() {
|
|
32332
|
-
const [configuration, roster] = await Promise.all([
|
|
33188
|
+
const [configuration, roster, grantedHostRoutes] = await Promise.all([
|
|
32333
33189
|
this.options.api.execute("getAgentConfiguration", {
|
|
32334
33190
|
agentId: this.agent.publicKey,
|
|
32335
33191
|
roomId: this.options.roomId
|
|
32336
33192
|
}),
|
|
32337
|
-
this.roster()
|
|
33193
|
+
this.roster(),
|
|
33194
|
+
this.grantedHostRoutes()
|
|
32338
33195
|
]);
|
|
32339
33196
|
const self = roster.members.find((member) => member.identityId === this.agent.publicKey);
|
|
32340
33197
|
return sessionConfigFingerprint({
|
|
@@ -32342,9 +33199,22 @@ var MonolithRoomTurnLoop = class {
|
|
|
32342
33199
|
effort: configuration.effort ?? this.options.config.modelSelection?.effort,
|
|
32343
33200
|
soul: configuration.soul ?? self?.soul,
|
|
32344
33201
|
agentName: self?.name ?? this.agent.name,
|
|
32345
|
-
mcpServers:
|
|
33202
|
+
mcpServers: expectedMountedImportedMcpServerNames({
|
|
33203
|
+
operatorHome: this.options.config.operatorHome,
|
|
33204
|
+
agentKind: this.options.config.agentKind,
|
|
33205
|
+
grantedHostRoutes
|
|
33206
|
+
})
|
|
32346
33207
|
});
|
|
32347
33208
|
}
|
|
33209
|
+
async grantedHostRoutes() {
|
|
33210
|
+
try {
|
|
33211
|
+
return grantedHostRoutesFromList(await this.options.api.execute("listAgentGrants", {
|
|
33212
|
+
agentId: this.agent.publicKey
|
|
33213
|
+
}));
|
|
33214
|
+
} catch {
|
|
33215
|
+
return [];
|
|
33216
|
+
}
|
|
33217
|
+
}
|
|
32348
33218
|
mountedMcpServers(preparedEnv) {
|
|
32349
33219
|
return mountedImportedMcpServerNames({
|
|
32350
33220
|
operatorHome: this.options.config.operatorHome,
|
|
@@ -32356,13 +33226,14 @@ var MonolithRoomTurnLoop = class {
|
|
|
32356
33226
|
if (this.client?.isAlive && this.sessionId)
|
|
32357
33227
|
return this.sessionId;
|
|
32358
33228
|
trace?.noteActivation("cold");
|
|
32359
|
-
const [configuration, roster, repositoryState] = await Promise.all([
|
|
33229
|
+
const [configuration, roster, repositoryState, grantedHostRoutes] = await Promise.all([
|
|
32360
33230
|
this.options.api.execute("getAgentConfiguration", {
|
|
32361
33231
|
agentId: this.agent.publicKey,
|
|
32362
33232
|
roomId: this.options.roomId
|
|
32363
33233
|
}),
|
|
32364
33234
|
this.roster(),
|
|
32365
|
-
this.repositoryState()
|
|
33235
|
+
this.repositoryState(),
|
|
33236
|
+
this.grantedHostRoutes()
|
|
32366
33237
|
]);
|
|
32367
33238
|
const self = roster.members.find((member) => member.identityId === this.agent.publicKey);
|
|
32368
33239
|
const directMessage = Array.isArray(repositoryState.directParticipants) && repositoryState.directParticipants.length === 2;
|
|
@@ -32370,10 +33241,12 @@ var MonolithRoomTurnLoop = class {
|
|
|
32370
33241
|
const selectionModel = configuration.model ?? this.options.config.modelSelection?.model;
|
|
32371
33242
|
const selectionEffort = configuration.effort ?? this.options.config.modelSelection?.effort;
|
|
32372
33243
|
const selection = selectionModel || selectionEffort ? { model: selectionModel, effort: selectionEffort } : void 0;
|
|
33244
|
+
const operatorHome = this.options.config.operatorHome ?? homedir9();
|
|
32373
33245
|
const homeOverlay = this.options.config.agentHomeRoot ? await prepareRoomAgentHome({
|
|
32374
33246
|
root: this.options.config.agentHomeRoot,
|
|
32375
33247
|
sharedSkills: this.options.config.sharedSkills ?? [],
|
|
32376
33248
|
isReviewer: isConfiguredReviewer(self?.handle, configuration.reviewerHandle),
|
|
33249
|
+
grantedHostRoutes,
|
|
32377
33250
|
...this.options.config.agentKind ? { agentKind: this.options.config.agentKind } : {},
|
|
32378
33251
|
...this.options.config.operatorHome ? { operatorHome: this.options.config.operatorHome } : {},
|
|
32379
33252
|
...openRouterRoutingInput(this.options.config, selection, this.options.fetchImpl, {
|
|
@@ -32396,7 +33269,11 @@ var MonolithRoomTurnLoop = class {
|
|
|
32396
33269
|
effort: configuration.effort ?? this.options.config.modelSelection?.effort,
|
|
32397
33270
|
soul: configuration.soul ?? self?.soul,
|
|
32398
33271
|
agentName: self?.name ?? this.agent.name,
|
|
32399
|
-
mcpServers:
|
|
33272
|
+
mcpServers: expectedMountedImportedMcpServerNames({
|
|
33273
|
+
operatorHome: this.options.config.operatorHome,
|
|
33274
|
+
agentKind: this.options.config.agentKind,
|
|
33275
|
+
grantedHostRoutes
|
|
33276
|
+
})
|
|
32400
33277
|
});
|
|
32401
33278
|
this.agentEnv = agentEnv;
|
|
32402
33279
|
const agentArgs = agentArgsWithModelSelection({
|
|
@@ -32404,9 +33281,8 @@ var MonolithRoomTurnLoop = class {
|
|
|
32404
33281
|
command,
|
|
32405
33282
|
args: this.options.config.agentArgs ?? []
|
|
32406
33283
|
}, selection);
|
|
32407
|
-
const operatorHome = this.options.config.operatorHome ?? homedir7();
|
|
32408
33284
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
32409
|
-
this.attachmentDir = tmpDir ?
|
|
33285
|
+
this.attachmentDir = tmpDir ? join11(tmpDir, "beeline-attachments") : void 0;
|
|
32410
33286
|
this.sessionScratchDir = tmpDir;
|
|
32411
33287
|
this.sessionStateDirs = stateDirs;
|
|
32412
33288
|
const homeStateDirs = harnessHomeStateDirs(harnessLabel, agentEnv.HOME ?? operatorHome);
|
|
@@ -32422,7 +33298,14 @@ var MonolithRoomTurnLoop = class {
|
|
|
32422
33298
|
harnessStateDirs: stateDirs,
|
|
32423
33299
|
harnessHomeStateDirs: homeStateDirs,
|
|
32424
33300
|
...tmpDir ? { tmpDir } : {},
|
|
32425
|
-
|
|
33301
|
+
additionalWritablePaths: [
|
|
33302
|
+
...attachScratchRoot ? [attachScratchRoot] : [],
|
|
33303
|
+
...grantedSquireHostBindPaths({
|
|
33304
|
+
operatorHome,
|
|
33305
|
+
agentKind: this.options.config.agentKind,
|
|
33306
|
+
grantedHostRoutes
|
|
33307
|
+
})
|
|
33308
|
+
],
|
|
32426
33309
|
maskPaths: credentialMaskPaths(this.options.config.sandboxMaskPaths, operatorHome)
|
|
32427
33310
|
},
|
|
32428
33311
|
command,
|
|
@@ -32447,12 +33330,24 @@ var MonolithRoomTurnLoop = class {
|
|
|
32447
33330
|
const youtube = youtubeMcpServer(this.options.config, this.options.youtubeAccessToken);
|
|
32448
33331
|
if (youtube)
|
|
32449
33332
|
servers.push(youtube);
|
|
33333
|
+
const grantedRouteServers = grantedHostRouteWires(grantedHostRoutes, operatorHome, hostImportedMcpDeclarations({
|
|
33334
|
+
operatorHome,
|
|
33335
|
+
agentKind: this.options.config.agentKind
|
|
33336
|
+
}));
|
|
32450
33337
|
await installPiMcpBridge({
|
|
32451
33338
|
agentCommand: harnessLabel,
|
|
32452
33339
|
piHome: agentEnv.PI_CODING_AGENT_DIR,
|
|
32453
|
-
servers
|
|
33340
|
+
servers: [...servers, ...grantedRouteServers]
|
|
32454
33341
|
});
|
|
32455
|
-
const mountedServers =
|
|
33342
|
+
const mountedServers = [
|
|
33343
|
+
...servers.map((server) => server.name),
|
|
33344
|
+
...grantedRouteServers.map((server) => server.name),
|
|
33345
|
+
...this.mountedMcpServers(agentEnv)
|
|
33346
|
+
];
|
|
33347
|
+
const hostServers = ungatedHostServers(hostImportedMcpServerNames({
|
|
33348
|
+
operatorHome: this.options.config.operatorHome,
|
|
33349
|
+
agentKind: this.options.config.agentKind
|
|
33350
|
+
}), grantedHostRoutes);
|
|
32456
33351
|
const clientOptions = {
|
|
32457
33352
|
agentCommand: spawnCommand.command,
|
|
32458
33353
|
agentArgs: spawnCommand.args,
|
|
@@ -32463,7 +33358,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
32463
33358
|
// (`config.ts`), which is exactly when `wrapAgentCommand` above wraps.
|
|
32464
33359
|
osSandbox: Boolean(this.options.config.bwrapPath),
|
|
32465
33360
|
autoApprovePermissions: false,
|
|
32466
|
-
permissionAllowlist: (request) => isRoomMcpPermissionRequest(request, mountedServers)
|
|
33361
|
+
permissionAllowlist: (request) => isRoomMcpPermissionRequest(request, mountedServers, hostServers)
|
|
32467
33362
|
};
|
|
32468
33363
|
this.client = (this.options.createAcpClient ?? ((value) => new AcpClient(value)))(clientOptions);
|
|
32469
33364
|
await this.client.start();
|
|
@@ -32688,9 +33583,9 @@ ${JSON.stringify((corners.corners ?? []).filter((corner) => !corner.archived))}`
|
|
|
32688
33583
|
try {
|
|
32689
33584
|
stream.beginRun();
|
|
32690
33585
|
trace.promptSent();
|
|
32691
|
-
result2 = await this.client.sessionPrompt(this.sessionId, nextPrompt, ROOM_PROMPT_INACTIVITY_TIMEOUT_MS, (delta, full) => {
|
|
33586
|
+
result2 = await this.client.sessionPrompt(this.sessionId, nextPrompt, ROOM_PROMPT_INACTIVITY_TIMEOUT_MS, (delta, full, currentRun) => {
|
|
32692
33587
|
trace.firstModelOutput();
|
|
32693
|
-
stream.onChunk(delta, full);
|
|
33588
|
+
stream.onChunk(delta, full, currentRun);
|
|
32694
33589
|
}, void 0, (calls) => {
|
|
32695
33590
|
trace.toolCalls(calls);
|
|
32696
33591
|
if (openedACorner(openCornerToolCall(calls)))
|
|
@@ -32723,8 +33618,8 @@ ${JSON.stringify((corners.corners ?? []).filter((corner) => !corner.archived))}`
|
|
|
32723
33618
|
trace.promptSettled();
|
|
32724
33619
|
let openCornerCall = openCornerToolCall(result.toolCalls);
|
|
32725
33620
|
let cornerOpened = openedACorner(openCornerCall);
|
|
32726
|
-
let explained =
|
|
32727
|
-
if (explained && shouldRetryEmptyTurn(explained)) {
|
|
33621
|
+
let explained = await this.explainEmpty(result);
|
|
33622
|
+
if (!cornerOpened && explained && shouldRetryEmptyTurn(explained)) {
|
|
32728
33623
|
const silent = this.servingProviders();
|
|
32729
33624
|
const next = await this.repinNextProvider(trace, explained.reason);
|
|
32730
33625
|
if (next) {
|
|
@@ -32733,7 +33628,7 @@ ${JSON.stringify((corners.corners ?? []).filter((corner) => !corner.archived))}`
|
|
|
32733
33628
|
trace.promptSettled();
|
|
32734
33629
|
openCornerCall = openCornerToolCall(result.toolCalls);
|
|
32735
33630
|
cornerOpened = openedACorner(openCornerCall);
|
|
32736
|
-
explained =
|
|
33631
|
+
explained = await this.explainEmpty(result);
|
|
32737
33632
|
}
|
|
32738
33633
|
}
|
|
32739
33634
|
if (active.cancelled) {
|
|
@@ -32760,15 +33655,14 @@ ${JSON.stringify((corners.corners ?? []).filter((corner) => !corner.archived))}`
|
|
|
32760
33655
|
}
|
|
32761
33656
|
stream.close();
|
|
32762
33657
|
let reply = durableReplyText(result.agentText);
|
|
32763
|
-
if (!reply && explained) {
|
|
32764
|
-
reply =
|
|
32765
|
-
|
|
32766
|
-
|
|
32767
|
-
|
|
32768
|
-
console.warn(`[thin-core] monolith Room ${this.options.roomId} turn ${item.id}: ${explained.reason}`);
|
|
33658
|
+
if (!reply && explained?.recoveredText) {
|
|
33659
|
+
reply = durableReplyText(explained.recoveredText);
|
|
33660
|
+
}
|
|
33661
|
+
if (!reply && explained && !cornerOpened) {
|
|
33662
|
+
throw new Error(turnFailureReasonWithProvider(explained.reason, this.servingProviders()));
|
|
32769
33663
|
}
|
|
32770
|
-
if (
|
|
32771
|
-
|
|
33664
|
+
if (reply && explained) {
|
|
33665
|
+
console.warn(`[thin-core] monolith Room ${this.options.roomId} turn ${item.id}: ${explained.reason}`);
|
|
32772
33666
|
}
|
|
32773
33667
|
await trace.measure("publish", () => stream.settle(reply, reply ? {
|
|
32774
33668
|
triggerMessageId: item.id
|
|
@@ -32792,9 +33686,14 @@ ${JSON.stringify((corners.corners ?? []).filter((corner) => !corner.archived))}`
|
|
|
32792
33686
|
if (liveCornerOpened && error instanceof AcpRequestTimeoutError && error.inactivity && error.method === "session/prompt") {
|
|
32793
33687
|
console.log(`[thin-core] monolith Room ${this.options.roomId} turn ${item.id}: inactivity timeout after opening a corner; the work continues in the corner`);
|
|
32794
33688
|
this.options.onCornerOpened?.();
|
|
32795
|
-
|
|
32796
|
-
|
|
32797
|
-
|
|
33689
|
+
const lastRun = liveStream?.lastRunText ?? "";
|
|
33690
|
+
const streamed = isPureRetryNarration(lastRun) ? "" : durableReplyText(lastRun);
|
|
33691
|
+
if (liveStream) {
|
|
33692
|
+
await liveStream.settle(streamed, streamed ? { triggerMessageId: item.id } : {}).catch((settleError) => {
|
|
33693
|
+
console.error(`[thin-core] monolith Room ${this.options.roomId} draft settle failed:`, settleError);
|
|
33694
|
+
});
|
|
33695
|
+
await liveStream.retract();
|
|
33696
|
+
}
|
|
32798
33697
|
await api.execute("postAgentTurnReceipt", {
|
|
32799
33698
|
agentId: this.agent.publicKey,
|
|
32800
33699
|
roomId: this.options.roomId,
|
|
@@ -32880,7 +33779,7 @@ var TOOL_OUTPUT_MAX_BYTES = 3200;
|
|
|
32880
33779
|
var TOOL_PATH_LIMIT = 12;
|
|
32881
33780
|
function cornerMergeInstruction(yoloMode, reviewerHandle) {
|
|
32882
33781
|
if (reviewerHandle)
|
|
32883
|
-
return `Commit, push, open the PR, and reply with the URL; do not merge until @${reviewerHandle}
|
|
33782
|
+
return `Commit, push, open the PR, and reply with the URL; do not merge until @${reviewerHandle} has reviewed \u2014 you are woken when that review ends, whether or not it tags you \u2014 then call pr_checks_status and merge with gh pr merge --squash --match-head-commit <sha> only if the complete gate passes.`;
|
|
32884
33783
|
return yoloMode ? "Yolo is on: when the gate passes, merge this pull request with gh." : "Yolo is off: never merge; wait for a human owner to turn yolo on or merge the pull request themselves.";
|
|
32885
33784
|
}
|
|
32886
33785
|
function cornerReviewerInstruction(input) {
|
|
@@ -33203,12 +34102,13 @@ var MonolithCornerTurnLoop = class {
|
|
|
33203
34102
|
return await this.currentSessionFingerprint() === this.sessionFingerprint;
|
|
33204
34103
|
}
|
|
33205
34104
|
async currentSessionFingerprint() {
|
|
33206
|
-
const [configuration, roster] = await Promise.all([
|
|
34105
|
+
const [configuration, roster, grantedHostRoutes] = await Promise.all([
|
|
33207
34106
|
this.options.api.execute("getAgentConfiguration", {
|
|
33208
34107
|
agentId: this.agent.publicKey,
|
|
33209
34108
|
roomId: this.options.cornerId
|
|
33210
34109
|
}),
|
|
33211
|
-
this.roster()
|
|
34110
|
+
this.roster(),
|
|
34111
|
+
this.grantedHostRoutes()
|
|
33212
34112
|
]);
|
|
33213
34113
|
const self = roster.members.find((member) => member.identityId === this.agent.publicKey);
|
|
33214
34114
|
return sessionConfigFingerprint({
|
|
@@ -33217,27 +34117,34 @@ var MonolithCornerTurnLoop = class {
|
|
|
33217
34117
|
soul: configuration.soul ?? self?.soul,
|
|
33218
34118
|
agentName: self?.name ?? this.agent.name,
|
|
33219
34119
|
yoloMode: configuration.yoloMode,
|
|
33220
|
-
mcpServers:
|
|
34120
|
+
mcpServers: expectedMountedImportedMcpServerNames({
|
|
34121
|
+
operatorHome: this.options.config.operatorHome,
|
|
34122
|
+
agentKind: this.options.config.agentKind,
|
|
34123
|
+
grantedHostRoutes
|
|
34124
|
+
}),
|
|
33221
34125
|
reviewerHandle: configuration.reviewerHandle
|
|
33222
34126
|
});
|
|
33223
34127
|
}
|
|
33224
|
-
|
|
33225
|
-
|
|
33226
|
-
|
|
33227
|
-
|
|
33228
|
-
|
|
33229
|
-
}
|
|
34128
|
+
async grantedHostRoutes() {
|
|
34129
|
+
try {
|
|
34130
|
+
return grantedHostRoutesFromList(await this.options.api.execute("listAgentGrants", {
|
|
34131
|
+
agentId: this.agent.publicKey
|
|
34132
|
+
}));
|
|
34133
|
+
} catch {
|
|
34134
|
+
return [];
|
|
34135
|
+
}
|
|
33230
34136
|
}
|
|
33231
34137
|
async activate(trace) {
|
|
33232
34138
|
if (this.client?.isAlive && this.sessionId)
|
|
33233
34139
|
return this.sessionId;
|
|
33234
34140
|
trace?.noteActivation("cold");
|
|
33235
|
-
const [configuration, roster] = await Promise.all([
|
|
34141
|
+
const [configuration, roster, grantedHostRoutes] = await Promise.all([
|
|
33236
34142
|
this.options.api.execute("getAgentConfiguration", {
|
|
33237
34143
|
agentId: this.agent.publicKey,
|
|
33238
34144
|
roomId: this.options.cornerId
|
|
33239
34145
|
}),
|
|
33240
|
-
this.roster()
|
|
34146
|
+
this.roster(),
|
|
34147
|
+
this.grantedHostRoutes()
|
|
33241
34148
|
]);
|
|
33242
34149
|
const self = roster.members.find((member) => member.identityId === this.agent.publicKey);
|
|
33243
34150
|
this.yoloMode = configuration.yoloMode;
|
|
@@ -33268,6 +34175,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
33268
34175
|
root: this.options.config.agentHomeRoot,
|
|
33269
34176
|
sharedSkills: this.options.config.sharedSkills ?? [],
|
|
33270
34177
|
isReviewer: isConfiguredReviewer(self?.handle, configuration.reviewerHandle),
|
|
34178
|
+
grantedHostRoutes,
|
|
33271
34179
|
...this.options.config.agentKind ? { agentKind: this.options.config.agentKind } : {},
|
|
33272
34180
|
...this.options.config.operatorHome ? { operatorHome: this.options.config.operatorHome } : {},
|
|
33273
34181
|
...openRouterRoutingInput(this.options.config, selection, this.options.fetchImpl, {
|
|
@@ -33309,13 +34217,18 @@ var MonolithCornerTurnLoop = class {
|
|
|
33309
34217
|
...githubEnv,
|
|
33310
34218
|
npm_config_cache: npmCacheDir
|
|
33311
34219
|
};
|
|
34220
|
+
const operatorHome = this.options.config.operatorHome ?? homedir10();
|
|
33312
34221
|
const fingerprint = sessionConfigFingerprint({
|
|
33313
34222
|
model: configuration.model ?? this.options.config.modelSelection?.model,
|
|
33314
34223
|
effort: configuration.effort ?? this.options.config.modelSelection?.effort,
|
|
33315
34224
|
soul: configuration.soul ?? self?.soul,
|
|
33316
34225
|
agentName: self?.name ?? this.agent.name,
|
|
33317
34226
|
yoloMode: configuration.yoloMode,
|
|
33318
|
-
mcpServers:
|
|
34227
|
+
mcpServers: expectedMountedImportedMcpServerNames({
|
|
34228
|
+
operatorHome: this.options.config.operatorHome,
|
|
34229
|
+
agentKind: this.options.config.agentKind,
|
|
34230
|
+
grantedHostRoutes
|
|
34231
|
+
}),
|
|
33319
34232
|
reviewerHandle: configuration.reviewerHandle
|
|
33320
34233
|
});
|
|
33321
34234
|
this.agentEnv = agentEnv;
|
|
@@ -33324,9 +34237,8 @@ var MonolithCornerTurnLoop = class {
|
|
|
33324
34237
|
command,
|
|
33325
34238
|
args: this.options.config.agentArgs ?? []
|
|
33326
34239
|
}, selection);
|
|
33327
|
-
const operatorHome = this.options.config.operatorHome ?? homedir8();
|
|
33328
34240
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
33329
|
-
this.attachmentDir = tmpDir ?
|
|
34241
|
+
this.attachmentDir = tmpDir ? join12(tmpDir, "beeline-attachments") : void 0;
|
|
33330
34242
|
this.sessionScratchDir = tmpDir;
|
|
33331
34243
|
const homeStateDirs = harnessHomeStateDirs(harnessLabel, agentEnv.HOME ?? operatorHome);
|
|
33332
34244
|
await Promise.all(homeStateDirs.map((dir) => mkdir13(dir, { recursive: true })));
|
|
@@ -33349,7 +34261,12 @@ var MonolithCornerTurnLoop = class {
|
|
|
33349
34261
|
// The shared npm cache. npm writes to its cache on every install,
|
|
33350
34262
|
// and this one is deliberately outside the per-corner home so the
|
|
33351
34263
|
// download is paid once per host rather than once per corner.
|
|
33352
|
-
npmCacheDir
|
|
34264
|
+
npmCacheDir,
|
|
34265
|
+
...grantedSquireHostBindPaths({
|
|
34266
|
+
operatorHome,
|
|
34267
|
+
agentKind: this.options.config.agentKind,
|
|
34268
|
+
grantedHostRoutes
|
|
34269
|
+
})
|
|
33353
34270
|
],
|
|
33354
34271
|
maskPaths: credentialMaskPaths(this.options.config.sandboxMaskPaths, operatorHome)
|
|
33355
34272
|
},
|
|
@@ -33403,10 +34320,14 @@ var MonolithCornerTurnLoop = class {
|
|
|
33403
34320
|
const youtube = youtubeMcpServer(this.options.config, this.options.youtubeAccessToken);
|
|
33404
34321
|
if (youtube)
|
|
33405
34322
|
servers.push(youtube);
|
|
34323
|
+
const grantedRouteServers = grantedHostRouteWires(grantedHostRoutes, operatorHome, hostImportedMcpDeclarations({
|
|
34324
|
+
operatorHome,
|
|
34325
|
+
agentKind: this.options.config.agentKind
|
|
34326
|
+
}));
|
|
33406
34327
|
await installPiMcpBridge({
|
|
33407
34328
|
agentCommand: harnessLabel,
|
|
33408
34329
|
piHome: agentEnv.PI_CODING_AGENT_DIR,
|
|
33409
|
-
servers
|
|
34330
|
+
servers: [...servers, ...grantedRouteServers]
|
|
33410
34331
|
});
|
|
33411
34332
|
const persona = configuration.soul ?? self?.soul;
|
|
33412
34333
|
const identityInstructions = `Your Beeline identity is ${self?.name ?? this.agent.name}.`;
|
|
@@ -33431,11 +34352,15 @@ var MonolithCornerTurnLoop = class {
|
|
|
33431
34352
|
selfReviewerInstruction ?? cornerMergeInstruction(configuration.yoloMode, configuration.reviewerHandle)
|
|
33432
34353
|
],
|
|
33433
34354
|
"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.",
|
|
33434
|
-
"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
|
|
34355
|
+
"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 to be woken. 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 end of that review wakes you, tag or no tag, 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."
|
|
33435
34356
|
] : [
|
|
33436
|
-
"This is a
|
|
34357
|
+
"This is a no-code corner with no repository checkout and no GitHub workflow.",
|
|
33437
34358
|
"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.",
|
|
33438
|
-
"Do not initialize a repository, create a branch, push, open a pull request, or wait for GitHub checks."
|
|
34359
|
+
"Do not initialize a repository, create a branch, commit, push, open a pull request, or wait for GitHub checks.",
|
|
34360
|
+
// This lane has no pull request URL and no merge card, so the
|
|
34361
|
+
// artifacts and the tag ARE the completion signal. Without the
|
|
34362
|
+
// tag the person who asked is never told the work finished.
|
|
34363
|
+
this.options.requesterHandle ? `Deliver the result as artifacts: post_artifact everything the objective asked for, then finish by replying with @${this.options.requesterHandle} and one line on what you posted. That reply is this corner's only completion signal.` : `Deliver the result as artifacts: post_artifact everything the objective asked for, then finish by replying with one line on what you posted. That reply is this corner's only completion signal.`
|
|
33439
34364
|
]
|
|
33440
34365
|
].filter(Boolean).join("\n\n")
|
|
33441
34366
|
});
|
|
@@ -33554,7 +34479,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
33554
34479
|
const [conversation, roster, delivered] = await trace.measure("context-fetch", () => Promise.all([
|
|
33555
34480
|
api.execute("getRoomConversation", { roomId: cornerId, limit: 200 }),
|
|
33556
34481
|
this.roster(),
|
|
33557
|
-
this.attachmentDir && attachments.length ? deliverAttachments(attachments,
|
|
34482
|
+
this.attachmentDir && attachments.length ? deliverAttachments(attachments, join12(this.attachmentDir, requestId.replace(/[^\w-]/g, "_")), this.options.fetchImpl) : Promise.resolve([])
|
|
33558
34483
|
]));
|
|
33559
34484
|
const names = new Map(roster.members.map((member) => [member.identityId, member.name]));
|
|
33560
34485
|
const requestedBy = requester && !requester.name && names.get(requester.pubkey) ? { ...requester, name: names.get(requester.pubkey) } : requester;
|
|
@@ -33686,7 +34611,7 @@ ${trigger}`,
|
|
|
33686
34611
|
completedNarrationRuns.push(currentNarrationRun);
|
|
33687
34612
|
currentNarrationRun = currentRun;
|
|
33688
34613
|
}
|
|
33689
|
-
stream.onChunk(delta, full);
|
|
34614
|
+
stream.onChunk(delta, full, currentRun);
|
|
33690
34615
|
}, void 0, (calls) => {
|
|
33691
34616
|
trace.toolCalls(calls);
|
|
33692
34617
|
publishToolCalls(calls, true);
|
|
@@ -34336,12 +35261,12 @@ function isStandingCornerStartFault(error) {
|
|
|
34336
35261
|
async function materializeCornerWorktree(input) {
|
|
34337
35262
|
const remote = roomCheckoutRemote(input.remote);
|
|
34338
35263
|
const repositoryHash = createHash7("sha256").update(remote).digest("hex").slice(0, 24);
|
|
34339
|
-
const gitCommonDir =
|
|
34340
|
-
const path =
|
|
34341
|
-
await mkdir14(
|
|
34342
|
-
await mkdir14(
|
|
35264
|
+
const gitCommonDir = resolve23(input.supervisorRoot, "beeline", "repositories", `${repositoryHash}.git`);
|
|
35265
|
+
const path = resolve23(input.supervisorRoot, "beeline", "corners", input.cornerId);
|
|
35266
|
+
await mkdir14(dirname12(gitCommonDir), { recursive: true, mode: 448 });
|
|
35267
|
+
await mkdir14(dirname12(path), { recursive: true, mode: 448 });
|
|
34343
35268
|
const authEnv = githubGitEnv(input.token);
|
|
34344
|
-
if (!
|
|
35269
|
+
if (!existsSync6(resolve23(gitCommonDir, "HEAD"))) {
|
|
34345
35270
|
await execFileAsync4("git", ["clone", "--bare", remote, gitCommonDir], {
|
|
34346
35271
|
env: authEnv,
|
|
34347
35272
|
maxBuffer: 4 * 1024 * 1024
|
|
@@ -34360,7 +35285,7 @@ async function materializeCornerWorktree(input) {
|
|
|
34360
35285
|
"origin",
|
|
34361
35286
|
`+refs/heads/${input.featureBranch}:refs/remotes/origin/${input.featureBranch}`
|
|
34362
35287
|
], { env: authEnv, maxBuffer: 4 * 1024 * 1024 }).then(() => true, () => false);
|
|
34363
|
-
if (!
|
|
35288
|
+
if (!existsSync6(resolve23(path, ".git"))) {
|
|
34364
35289
|
await rm5(path, { recursive: true, force: true });
|
|
34365
35290
|
await execFileAsync4("git", [
|
|
34366
35291
|
`--git-dir=${gitCommonDir}`,
|
|
@@ -34411,7 +35336,7 @@ async function materializeCornerWorktree(input) {
|
|
|
34411
35336
|
`${input.committer.publicKey.slice(0, 16)}@users.noreply.github.com`
|
|
34412
35337
|
]);
|
|
34413
35338
|
const top = await execFileAsync4("git", ["-C", path, "rev-parse", "--show-toplevel"]);
|
|
34414
|
-
if (
|
|
35339
|
+
if (resolve23(top.stdout.trim()) !== resolve23(path)) {
|
|
34415
35340
|
throw new Error(`corner worktree escaped its isolated root: ${top.stdout.trim()}`);
|
|
34416
35341
|
}
|
|
34417
35342
|
return { path, gitCommonDir };
|
|
@@ -34432,7 +35357,7 @@ async function mapWithConcurrency(values, limit, visit) {
|
|
|
34432
35357
|
async function removeCornerWorktreeAndBranches(worktree) {
|
|
34433
35358
|
const localRef = `refs/heads/${worktree.branch}`;
|
|
34434
35359
|
const remoteRef = `refs/heads/${worktree.branch}`;
|
|
34435
|
-
const worktreeExists =
|
|
35360
|
+
const worktreeExists = existsSync6(worktree.path);
|
|
34436
35361
|
const localExists = await gitRefExists(worktree.gitCommonDir, localRef);
|
|
34437
35362
|
if (worktreeExists) {
|
|
34438
35363
|
const checkedOut = await execFileAsync4("git", [
|
|
@@ -34477,8 +35402,8 @@ async function removeCornerWorktreeAndBranches(worktree) {
|
|
|
34477
35402
|
}
|
|
34478
35403
|
var execFileAsync4 = promisify4(execFile6);
|
|
34479
35404
|
async function removeCornerScratchWorkspace(input) {
|
|
34480
|
-
const expected =
|
|
34481
|
-
if (
|
|
35405
|
+
const expected = resolve23(input.roomRoot, "scratch");
|
|
35406
|
+
if (resolve23(input.scratchPath) !== expected) {
|
|
34482
35407
|
throw new Error(`refusing to remove scratch outside corner ${input.cornerId}`);
|
|
34483
35408
|
}
|
|
34484
35409
|
await rm5(expected, { recursive: true, force: true });
|
|
@@ -34699,17 +35624,17 @@ var RoomRuntimeCoordinator = class {
|
|
|
34699
35624
|
return this.runtime.rooms.find((room) => room.channelId === roomId);
|
|
34700
35625
|
}
|
|
34701
35626
|
roomRoot(roomId) {
|
|
34702
|
-
return this.roomRecord(roomId)?.root ??
|
|
35627
|
+
return this.roomRecord(roomId)?.root ?? resolve23(dirname12(this.configPath), "rooms", roomId);
|
|
34703
35628
|
}
|
|
34704
35629
|
roomAgentHomeRoot(workspaceRoot, required = false) {
|
|
34705
35630
|
const flag = process.env.BUZZY_BODY_ROOM_HOME;
|
|
34706
35631
|
if (!required && flag === "0")
|
|
34707
35632
|
return void 0;
|
|
34708
|
-
const home =
|
|
34709
|
-
if (!required && flag !== "1" && !
|
|
35633
|
+
const home = resolve23(workspaceRoot, "agent-home");
|
|
35634
|
+
if (!required && flag !== "1" && !existsSync6(home) && existsSync6(workspaceRoot))
|
|
34710
35635
|
return void 0;
|
|
34711
35636
|
try {
|
|
34712
|
-
|
|
35637
|
+
mkdirSync3(home, { recursive: true, mode: 448 });
|
|
34713
35638
|
return home;
|
|
34714
35639
|
} catch (error) {
|
|
34715
35640
|
console.error(`[thin-core] per-room agent home unavailable at ${home}:`, error);
|
|
@@ -34721,10 +35646,10 @@ var RoomRuntimeCoordinator = class {
|
|
|
34721
35646
|
return {
|
|
34722
35647
|
...this.baseConfig,
|
|
34723
35648
|
workspaceRoot,
|
|
34724
|
-
agentPrivateRoot:
|
|
34725
|
-
agentMemoryRoot:
|
|
34726
|
-
openRouterRoutingCacheDir: openRouterRoutingCacheDir(
|
|
34727
|
-
turnTraceDir: turnTraceDirectory(
|
|
35649
|
+
agentPrivateRoot: resolve23(workspaceRoot, "agent-private"),
|
|
35650
|
+
agentMemoryRoot: resolve23(dirname12(this.configPath), "memory"),
|
|
35651
|
+
openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname12(this.configPath)),
|
|
35652
|
+
turnTraceDir: turnTraceDirectory(dirname12(this.configPath)),
|
|
34728
35653
|
...agentHomeRoot ? { agentHomeRoot } : {}
|
|
34729
35654
|
};
|
|
34730
35655
|
}
|
|
@@ -34802,11 +35727,11 @@ var RoomRuntimeCoordinator = class {
|
|
|
34802
35727
|
const remote = roomCheckoutRemote(repository.remote);
|
|
34803
35728
|
const targetBranch = repository.targetBranch || "main";
|
|
34804
35729
|
const checkoutId = createHash7("sha256").update(`${remote}\0${targetBranch}`).digest("hex").slice(0, 24);
|
|
34805
|
-
const path =
|
|
34806
|
-
await mkdir14(
|
|
35730
|
+
const path = resolve23(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
|
|
35731
|
+
await mkdir14(dirname12(path), { recursive: true, mode: 448 });
|
|
34807
35732
|
const token = remote.startsWith("https://github.com/") ? await this.options.daemonApi.execute("getRoomGitHubToken", { roomId }) : void 0;
|
|
34808
35733
|
const env = token ? githubGitEnv(token.token) : process.env;
|
|
34809
|
-
if (!
|
|
35734
|
+
if (!existsSync6(resolve23(path, ".git"))) {
|
|
34810
35735
|
await execFileAsync4("git", ["clone", "--no-checkout", remote, path], {
|
|
34811
35736
|
env,
|
|
34812
35737
|
maxBuffer: 4 * 1024 * 1024
|
|
@@ -34855,7 +35780,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
34855
35780
|
const objective = (restore.objective ?? "").trim();
|
|
34856
35781
|
if (!objective)
|
|
34857
35782
|
throw new Error("corner has no authoritative objective fact");
|
|
34858
|
-
const repositoryBacked = repository.resolution === "repository";
|
|
35783
|
+
const repositoryBacked = repository.resolution === "repository" && restore.lane !== "no_code";
|
|
34859
35784
|
const targetBranch = repositoryBacked ? repository.targetBranch || "main" : void 0;
|
|
34860
35785
|
const featureBranch = repositoryBacked ? restore.featureBranch ?? `feature/corner-${corner.cornerId.replaceAll("-", "").slice(0, 12)}` : void 0;
|
|
34861
35786
|
const granted = repositoryBacked ? await this.options.daemonApi.execute("getRoomGitHubToken", {
|
|
@@ -34868,7 +35793,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
34868
35793
|
featureBranch,
|
|
34869
35794
|
token: granted.token
|
|
34870
35795
|
}) : void 0;
|
|
34871
|
-
const workspacePath = worktree?.path ??
|
|
35796
|
+
const workspacePath = worktree?.path ?? resolve23(this.roomRoot(corner.cornerId), "scratch");
|
|
34872
35797
|
if (!worktree)
|
|
34873
35798
|
await mkdir14(workspacePath, { recursive: true, mode: 448 });
|
|
34874
35799
|
const isOpener = !corner.openedBy || corner.openedBy === this.agent.publicKey;
|
|
@@ -34894,6 +35819,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
34894
35819
|
...corner.openedBy ? { openedBy: corner.openedBy } : {},
|
|
34895
35820
|
objective,
|
|
34896
35821
|
worktreePath: workspacePath,
|
|
35822
|
+
...restore.requesterHandle ? { requesterHandle: restore.requesterHandle } : {},
|
|
34897
35823
|
...worktree ? {
|
|
34898
35824
|
repository: {
|
|
34899
35825
|
featureBranch,
|
|
@@ -34946,7 +35872,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
34946
35872
|
});
|
|
34947
35873
|
this.standingCornerStartFaults.delete(corner.cornerId);
|
|
34948
35874
|
this.reportedCornerStartFailures.delete(corner.cornerId);
|
|
34949
|
-
console.log(worktree ? `[thin-core] serving corner ${corner.cornerId} on ${featureBranch} at ${workspacePath}` : `[thin-core] serving
|
|
35875
|
+
console.log(worktree ? `[thin-core] serving corner ${corner.cornerId} on ${featureBranch} at ${workspacePath}` : `[thin-core] serving no-code corner ${corner.cornerId} at ${workspacePath}`);
|
|
34950
35876
|
} catch (error) {
|
|
34951
35877
|
console.error(`[thin-core] failed to start corner ${corner.cornerId}:`, error);
|
|
34952
35878
|
const reported = await this.reportCornerStartFailure(corner.cornerId, error);
|
|
@@ -35260,13 +36186,13 @@ var ThinDaemonCore = class {
|
|
|
35260
36186
|
|
|
35261
36187
|
// apps/body/dist/agent-retirement.js
|
|
35262
36188
|
import { mkdir as mkdir16, rename as rename5 } from "node:fs/promises";
|
|
35263
|
-
import { dirname as
|
|
36189
|
+
import { dirname as dirname14, resolve as resolve25 } from "node:path";
|
|
35264
36190
|
|
|
35265
36191
|
// apps/body/dist/systemd.js
|
|
35266
36192
|
import { execFile as execFile7 } from "node:child_process";
|
|
35267
36193
|
import { mkdir as mkdir15, readFile as readFile9, stat as stat3, writeFile as writeFile10 } from "node:fs/promises";
|
|
35268
|
-
import { homedir as
|
|
35269
|
-
import { dirname as
|
|
36194
|
+
import { homedir as homedir11 } from "node:os";
|
|
36195
|
+
import { dirname as dirname13, resolve as resolve24 } from "node:path";
|
|
35270
36196
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
35271
36197
|
import { promisify as promisify5 } from "node:util";
|
|
35272
36198
|
var execFileAsync5 = promisify5(execFile7);
|
|
@@ -35288,6 +36214,7 @@ StartLimitBurst=10
|
|
|
35288
36214
|
Type=notify
|
|
35289
36215
|
NotifyAccess=all
|
|
35290
36216
|
Environment=BEELINE_MANAGED_BY_SYSTEMD=1
|
|
36217
|
+
Environment=PATH=%h/.local/bin:/usr/local/bin:/usr/bin:/bin
|
|
35291
36218
|
ExecStart=%h/.local/bin/beeline daemon --agent %i
|
|
35292
36219
|
Restart=always
|
|
35293
36220
|
RestartSec=5s
|
|
@@ -35308,10 +36235,10 @@ WantedBy=default.target
|
|
|
35308
36235
|
`;
|
|
35309
36236
|
}
|
|
35310
36237
|
function isCanonicalInstalledLauncher(env = process.env, invocationPath = process.argv[1]) {
|
|
35311
|
-
const home = env.HOME?.trim() ||
|
|
35312
|
-
const expectedLibDir =
|
|
36238
|
+
const home = env.HOME?.trim() || homedir11();
|
|
36239
|
+
const expectedLibDir = resolve24(home, ".local", "lib", "beeline");
|
|
35313
36240
|
const expectedPrefix = `${expectedLibDir}/`;
|
|
35314
|
-
return
|
|
36241
|
+
return resolve24(env.BEELINE_LIB_DIR?.trim() || "/") === expectedLibDir && Boolean(invocationPath) && resolve24(invocationPath).startsWith(expectedPrefix);
|
|
35315
36242
|
}
|
|
35316
36243
|
function assertCanonicalInstalledLauncher(env, invocationPath) {
|
|
35317
36244
|
if (isCanonicalInstalledLauncher(env, invocationPath))
|
|
@@ -35319,8 +36246,28 @@ function assertCanonicalInstalledLauncher(env, invocationPath) {
|
|
|
35319
36246
|
throw new Error("refusing to modify the shared Beeline systemd unit outside the canonical ~/.local/bin/beeline launcher");
|
|
35320
36247
|
}
|
|
35321
36248
|
function systemdUserUnitPath(env = process.env) {
|
|
35322
|
-
const configRoot = env.XDG_CONFIG_HOME?.trim() ||
|
|
35323
|
-
return
|
|
36249
|
+
const configRoot = env.XDG_CONFIG_HOME?.trim() || resolve24(homedir11(), ".config");
|
|
36250
|
+
return resolve24(configRoot, "systemd", "user", SYSTEMD_UNIT_NAME);
|
|
36251
|
+
}
|
|
36252
|
+
function systemdBrokerUnitPath(env = process.env) {
|
|
36253
|
+
const configRoot = env.XDG_CONFIG_HOME?.trim() || resolve24(homedir11(), ".config");
|
|
36254
|
+
return resolve24(configRoot, "systemd", "user", TRUSTY_SQUIRE_BROKER_UNIT_NAME);
|
|
36255
|
+
}
|
|
36256
|
+
async function installTrustySquireBrokerService(options = {}) {
|
|
36257
|
+
const env = options.env ?? process.env;
|
|
36258
|
+
assertCanonicalInstalledLauncher(env, options.invocationPath);
|
|
36259
|
+
const home = env.HOME?.trim() || homedir11();
|
|
36260
|
+
ensureSquireHostDir(home);
|
|
36261
|
+
const path = systemdBrokerUnitPath(env);
|
|
36262
|
+
const content = trustySquireBrokerUnit();
|
|
36263
|
+
const existing = await readFile9(path, "utf8").catch(() => "");
|
|
36264
|
+
if (existing !== content) {
|
|
36265
|
+
await mkdir15(dirname13(path), { recursive: true, mode: 448 });
|
|
36266
|
+
await writeFile10(path, content, { mode: 384 });
|
|
36267
|
+
}
|
|
36268
|
+
const run2 = options.run ?? runSystemctl;
|
|
36269
|
+
await run2(["daemon-reload"]);
|
|
36270
|
+
await run2(["enable", "--now", TRUSTY_SQUIRE_BROKER_UNIT_NAME]);
|
|
35324
36271
|
}
|
|
35325
36272
|
var AGENT_SERVICE = /^beeline-agent@([0-9a-f]{64})\.service$/i;
|
|
35326
36273
|
var runSystemctl = async (args) => {
|
|
@@ -35339,7 +36286,7 @@ async function installAgentService(publicKey, options = {}) {
|
|
|
35339
36286
|
const content = agentServiceUnit();
|
|
35340
36287
|
const existing = await readFile9(path, "utf8").catch(() => "");
|
|
35341
36288
|
if (existing !== content) {
|
|
35342
|
-
await mkdir15(
|
|
36289
|
+
await mkdir15(dirname13(path), { recursive: true, mode: 448 });
|
|
35343
36290
|
await writeFile10(path, content, { mode: 384 });
|
|
35344
36291
|
}
|
|
35345
36292
|
const run2 = options.run ?? runSystemctl;
|
|
@@ -35479,15 +36426,15 @@ var SystemdNotifier = class {
|
|
|
35479
36426
|
|
|
35480
36427
|
// apps/body/dist/agent-retirement.js
|
|
35481
36428
|
async function retireRemovedAgent(runtime, options = {}) {
|
|
35482
|
-
const deletedRoot =
|
|
35483
|
-
const target =
|
|
36429
|
+
const deletedRoot = resolve25(runtime.supervisorRoot, "beeline", "deleted-runtimes");
|
|
36430
|
+
const target = resolve25(deletedRoot, `${runtime.agent.publicKey}-${Date.now()}`);
|
|
35484
36431
|
return relocateAgentRuntime(runtime, target, {
|
|
35485
36432
|
...options.run ? { run: options.run } : {}
|
|
35486
36433
|
});
|
|
35487
36434
|
}
|
|
35488
36435
|
async function relocateAgentRuntime(runtime, target, options = {}) {
|
|
35489
36436
|
const source = runtimeDirectory(runtime.supervisorRoot, runtime.agent.publicKey);
|
|
35490
|
-
const destination =
|
|
36437
|
+
const destination = resolve25(target);
|
|
35491
36438
|
if (destination === source || destination.startsWith(`${source}/`)) {
|
|
35492
36439
|
throw new Error("agent runtime destination must be outside the live runtime");
|
|
35493
36440
|
}
|
|
@@ -35496,13 +36443,13 @@ async function relocateAgentRuntime(runtime, target, options = {}) {
|
|
|
35496
36443
|
...options.run ? { run: options.run } : {}
|
|
35497
36444
|
});
|
|
35498
36445
|
}
|
|
35499
|
-
await mkdir16(
|
|
36446
|
+
await mkdir16(dirname14(destination), { recursive: true, mode: 448 });
|
|
35500
36447
|
await rename5(source, destination);
|
|
35501
36448
|
return destination;
|
|
35502
36449
|
}
|
|
35503
36450
|
|
|
35504
36451
|
// apps/body/dist/start-command.js
|
|
35505
|
-
import { basename as basename7, dirname as
|
|
36452
|
+
import { basename as basename7, dirname as dirname18 } from "node:path";
|
|
35506
36453
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
35507
36454
|
|
|
35508
36455
|
// apps/body/dist/self-update-cli.js
|
|
@@ -35512,22 +36459,22 @@ init_self_update_manifest();
|
|
|
35512
36459
|
|
|
35513
36460
|
// apps/body/dist/managed-update.js
|
|
35514
36461
|
init_self_update();
|
|
35515
|
-
import { spawn as
|
|
36462
|
+
import { spawn as spawn9 } from "node:child_process";
|
|
35516
36463
|
import { mkdir as mkdir19, rm as rm7, stat as stat4, writeFile as writeFile13 } from "node:fs/promises";
|
|
35517
|
-
import { dirname as
|
|
36464
|
+
import { dirname as dirname17, resolve as resolve28 } from "node:path";
|
|
35518
36465
|
|
|
35519
36466
|
// apps/body/dist/update-rollback-alert.js
|
|
35520
36467
|
import { mkdir as mkdir18, readFile as readFile11, rename as rename7, unlink as unlink4, writeFile as writeFile12 } from "node:fs/promises";
|
|
35521
|
-
import { dirname as
|
|
36468
|
+
import { dirname as dirname16, resolve as resolve27 } from "node:path";
|
|
35522
36469
|
var REPORT_INTERVAL_MS = 60 * 60 * 1e3;
|
|
35523
36470
|
var lastLogged = /* @__PURE__ */ new Map();
|
|
35524
36471
|
function updateRollbackAlertPath(runtimeDir) {
|
|
35525
|
-
return
|
|
36472
|
+
return resolve27(runtimeDir, "update-rollback-alert.json");
|
|
35526
36473
|
}
|
|
35527
36474
|
async function writeAlert(runtimeDir, alert) {
|
|
35528
36475
|
const path = updateRollbackAlertPath(runtimeDir);
|
|
35529
36476
|
const staged = `${path}.${process.pid}.tmp`;
|
|
35530
|
-
await mkdir18(
|
|
36477
|
+
await mkdir18(dirname16(path), { recursive: true });
|
|
35531
36478
|
await writeFile12(staged, `${JSON.stringify(alert, null, 2)}
|
|
35532
36479
|
`, { mode: 384 });
|
|
35533
36480
|
await rename7(staged, path);
|
|
@@ -35591,13 +36538,13 @@ var LOCK_STALE_MS = UPDATE_WORKER_DEADLINE_MS + 5 * 6e4;
|
|
|
35591
36538
|
var DEFAULT_UPDATE_INITIAL_DELAY_MS = 0;
|
|
35592
36539
|
async function withInstallLock(layout, work, options = {}) {
|
|
35593
36540
|
const now2 = options.now ?? Date.now;
|
|
35594
|
-
const lock =
|
|
36541
|
+
const lock = resolve28(layout.releasesRoot, ".state", "install.lock");
|
|
35595
36542
|
const deadline = now2() + (options.waitMs ?? 1e4);
|
|
35596
|
-
await mkdir19(
|
|
36543
|
+
await mkdir19(dirname17(lock), { recursive: true });
|
|
35597
36544
|
for (; ; ) {
|
|
35598
36545
|
try {
|
|
35599
36546
|
await mkdir19(lock);
|
|
35600
|
-
await writeFile13(
|
|
36547
|
+
await writeFile13(resolve28(lock, "owner"), `${process.pid}
|
|
35601
36548
|
${now2()}
|
|
35602
36549
|
`, "utf8");
|
|
35603
36550
|
break;
|
|
@@ -35645,10 +36592,11 @@ var ManagedUpdateHandoff = class _ManagedUpdateHandoff {
|
|
|
35645
36592
|
this.#nextUpdateCheckAt = this.#now() + numberEnv(this.#env, "BEELINE_UPDATE_INITIAL_DELAY_MS", DEFAULT_UPDATE_INITIAL_DELAY_MS);
|
|
35646
36593
|
}
|
|
35647
36594
|
static async create(layout, runtimeDir, now2 = Date.now, options = {}) {
|
|
36595
|
+
const env = options.env ?? process.env;
|
|
35648
36596
|
return new _ManagedUpdateHandoff({
|
|
35649
36597
|
layout,
|
|
35650
36598
|
runtimeDir,
|
|
35651
|
-
loadedRelease: await activeReleaseId(layout),
|
|
36599
|
+
loadedRelease: runningReleaseId(layout, env) ?? await activeReleaseId(layout),
|
|
35652
36600
|
now: now2,
|
|
35653
36601
|
...options
|
|
35654
36602
|
});
|
|
@@ -35720,7 +36668,7 @@ var ManagedUpdateHandoff = class _ManagedUpdateHandoff {
|
|
|
35720
36668
|
if (!attempt || attempt.releaseId !== desiredRelease || attempt.status !== "pending") {
|
|
35721
36669
|
const from = await readInstalledBundleIdentity({
|
|
35722
36670
|
...this.#layout,
|
|
35723
|
-
libDir:
|
|
36671
|
+
libDir: resolve28(this.#layout.releasesRoot, this.#loadedRelease)
|
|
35724
36672
|
}).catch(() => void 0) ?? {};
|
|
35725
36673
|
const to = await readInstalledBundleIdentity(this.#layout).catch(() => void 0) ?? {};
|
|
35726
36674
|
const record3 = {
|
|
@@ -35926,7 +36874,7 @@ async function runManagedUpdateWorkerProcess() {
|
|
|
35926
36874
|
if (!entrypoint)
|
|
35927
36875
|
throw new Error("cannot resolve the current Beeline entrypoint");
|
|
35928
36876
|
await new Promise((resolveWorker, rejectWorker) => {
|
|
35929
|
-
const child =
|
|
36877
|
+
const child = spawn9(process.execPath, [entrypoint, "managed-update-worker"], {
|
|
35930
36878
|
detached: true,
|
|
35931
36879
|
env: { ...process.env, BEELINE_INTERNAL_UPDATE_WORKER: "1" },
|
|
35932
36880
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -36007,7 +36955,7 @@ async function proveLoadedReleaseReady(layout, runtimeDir, loadedRelease, option
|
|
|
36007
36955
|
});
|
|
36008
36956
|
if (!accepted)
|
|
36009
36957
|
return false;
|
|
36010
|
-
await writeFile13(
|
|
36958
|
+
await writeFile13(resolve28(runtimeDir, "daemon-ready.json"), `${JSON.stringify({
|
|
36011
36959
|
readyAt: (options.now ?? Date.now)(),
|
|
36012
36960
|
loadedRelease,
|
|
36013
36961
|
functionalProof: options.functionalProof
|
|
@@ -36253,7 +37201,7 @@ async function startStoredRuntime(configPath, opts = {}, dependencyOverrides = {
|
|
|
36253
37201
|
return { status: "started", pid };
|
|
36254
37202
|
}
|
|
36255
37203
|
function agentStartId(configPath) {
|
|
36256
|
-
return basename7(
|
|
37204
|
+
return basename7(dirname18(configPath));
|
|
36257
37205
|
}
|
|
36258
37206
|
async function startRuntime(configPath, spinnerHandle) {
|
|
36259
37207
|
const report = (text2) => spinnerHandle ? spinnerHandle.message(text2) : console.log(text2);
|
|
@@ -36261,6 +37209,11 @@ async function startRuntime(configPath, spinnerHandle) {
|
|
|
36261
37209
|
const selectedAgent = runtimeAgentCommand(runtime);
|
|
36262
37210
|
report(`[body] agent ${runtime.agent.publicKey} binary: ${formatAgentCommand(selectedAgent)}`);
|
|
36263
37211
|
if (process.platform === "linux" && process.env.BEELINE_SYSTEMD_USER !== "0") {
|
|
37212
|
+
try {
|
|
37213
|
+
await installTrustySquireBrokerService();
|
|
37214
|
+
} catch (error) {
|
|
37215
|
+
report(`[beeline] trusty-squire host broker not installed: ${error instanceof Error ? error.message : String(error)}`);
|
|
37216
|
+
}
|
|
36264
37217
|
const existingPid = await runtimeDaemonPid(configPath);
|
|
36265
37218
|
if (existingPid) {
|
|
36266
37219
|
report(`[beeline] agent already running (pid ${existingPid})`);
|
|
@@ -36314,7 +37267,7 @@ async function runStartCommand(args, interactiveUi, dependencyOverrides = {}) {
|
|
|
36314
37267
|
for (const path of unique) {
|
|
36315
37268
|
const id = agentStartId(path);
|
|
36316
37269
|
const spinnerHandle = interactiveUi ? spinner() : void 0;
|
|
36317
|
-
spinnerHandle?.start(`Starting ${
|
|
37270
|
+
spinnerHandle?.start(`Starting ${dirname18(path)}\u2026`);
|
|
36318
37271
|
try {
|
|
36319
37272
|
const outcome = await deps.startOne(path, spinnerHandle);
|
|
36320
37273
|
const report = { id, path, ...outcome };
|
|
@@ -36346,11 +37299,11 @@ async function runStartCommand(args, interactiveUi, dependencyOverrides = {}) {
|
|
|
36346
37299
|
}
|
|
36347
37300
|
|
|
36348
37301
|
// apps/body/dist/connect-command.js
|
|
36349
|
-
import { spawn as
|
|
37302
|
+
import { spawn as spawn11 } from "node:child_process";
|
|
36350
37303
|
import { createHash as createHash9, randomUUID as randomUUID6 } from "node:crypto";
|
|
36351
37304
|
import { chmod as chmod7, mkdir as mkdir20, readFile as readFile12, unlink as unlink5, writeFile as writeFile14 } from "node:fs/promises";
|
|
36352
|
-
import { homedir as
|
|
36353
|
-
import { dirname as
|
|
37305
|
+
import { homedir as homedir13, hostname as hostname2 } from "node:os";
|
|
37306
|
+
import { dirname as dirname19, resolve as resolve29 } from "node:path";
|
|
36354
37307
|
import { stdin as stdin3, stdout as stdout4 } from "node:process";
|
|
36355
37308
|
|
|
36356
37309
|
// apps/body/dist/clack-support.js
|
|
@@ -36434,7 +37387,7 @@ async function verifyProviderKey(input) {
|
|
|
36434
37387
|
}
|
|
36435
37388
|
|
|
36436
37389
|
// apps/body/dist/pair-agent-selection.js
|
|
36437
|
-
import { spawn as
|
|
37390
|
+
import { spawn as spawn10 } from "node:child_process";
|
|
36438
37391
|
import { stdin as stdin2, stdout as stdout3 } from "node:process";
|
|
36439
37392
|
var NO_AGENT_MESSAGE = `No supported ACP-capable coding agent was detected.
|
|
36440
37393
|
Install one of these supported agents:
|
|
@@ -36463,7 +37416,7 @@ async function clackSelectAgent(candidates) {
|
|
|
36463
37416
|
}
|
|
36464
37417
|
async function installAdapter(install, opts) {
|
|
36465
37418
|
await new Promise((resolveInstall, rejectInstall) => {
|
|
36466
|
-
const child =
|
|
37419
|
+
const child = spawn10(install.command, install.args, {
|
|
36467
37420
|
cwd: opts.cwd,
|
|
36468
37421
|
env: opts.env ?? process.env,
|
|
36469
37422
|
stdio: "inherit"
|
|
@@ -36646,7 +37599,17 @@ async function pairDevice(grant, options = {}) {
|
|
|
36646
37599
|
throw new Error("monolith daemon transport activation failed");
|
|
36647
37600
|
let pid;
|
|
36648
37601
|
try {
|
|
36649
|
-
pid = await (options.launch ?? (async (configPath, publicKey) =>
|
|
37602
|
+
pid = await (options.launch ?? (async (configPath, publicKey) => {
|
|
37603
|
+
if (process.platform === "linux" && process.env.BEELINE_SYSTEMD_USER !== "0") {
|
|
37604
|
+
try {
|
|
37605
|
+
await installTrustySquireBrokerService();
|
|
37606
|
+
} catch (error) {
|
|
37607
|
+
console.warn(`[beeline] trusty-squire host broker not installed: ${error instanceof Error ? error.message : String(error)}`);
|
|
37608
|
+
}
|
|
37609
|
+
return installAgentService(publicKey);
|
|
37610
|
+
}
|
|
37611
|
+
return launchRuntimeDaemon(configPath);
|
|
37612
|
+
}))(staged.configPath, agentIdentity.publicKey);
|
|
36650
37613
|
} catch (error) {
|
|
36651
37614
|
throw new Error(`agent ${agentIdentity.publicKey} is connected, but its daemon did not start: ${error instanceof Error ? error.message : String(error)}. Run \`beeline start --agent ${agentIdentity.publicKey}\`.`, { cause: error });
|
|
36652
37615
|
}
|
|
@@ -36968,8 +37931,8 @@ function parseConnectSubscriptions(value) {
|
|
|
36968
37931
|
];
|
|
36969
37932
|
}
|
|
36970
37933
|
async function readMachineId(env = process.env) {
|
|
36971
|
-
const configDir =
|
|
36972
|
-
const machineIdPath =
|
|
37934
|
+
const configDir = resolve29(env.XDG_CONFIG_HOME ?? resolve29(homedir13(), ".config"), "beeline");
|
|
37935
|
+
const machineIdPath = resolve29(configDir, "machine-id");
|
|
36973
37936
|
let machineId;
|
|
36974
37937
|
let machineName = hostname2();
|
|
36975
37938
|
try {
|
|
@@ -37042,7 +38005,7 @@ async function installCurrentRelease(fetchImpl) {
|
|
|
37042
38005
|
});
|
|
37043
38006
|
await activateRelease(layout, releaseId);
|
|
37044
38007
|
return {
|
|
37045
|
-
binary:
|
|
38008
|
+
binary: resolve29(layout.binDir, "beeline"),
|
|
37046
38009
|
version: published.version ?? releaseId
|
|
37047
38010
|
};
|
|
37048
38011
|
}
|
|
@@ -37065,7 +38028,7 @@ function providerEnvironment(selection) {
|
|
|
37065
38028
|
};
|
|
37066
38029
|
}
|
|
37067
38030
|
async function writePrivateJson(path, value) {
|
|
37068
|
-
await mkdir20(
|
|
38031
|
+
await mkdir20(dirname19(path), { recursive: true, mode: 448 });
|
|
37069
38032
|
await writeFile14(path, `${JSON.stringify(value, null, 2)}
|
|
37070
38033
|
`, { mode: 384 });
|
|
37071
38034
|
await chmod7(path, 384);
|
|
@@ -37074,8 +38037,8 @@ async function writeProviderEnv(selection, agentPubkey) {
|
|
|
37074
38037
|
const values = providerEnvironment(selection);
|
|
37075
38038
|
if (Object.keys(values).length === 0)
|
|
37076
38039
|
return void 0;
|
|
37077
|
-
const path =
|
|
37078
|
-
await mkdir20(
|
|
38040
|
+
const path = resolve29(defaultSupervisorRoot(process.env), "beeline", "connect", `${agentPubkey}.env`);
|
|
38041
|
+
await mkdir20(dirname19(path), { recursive: true, mode: 448 });
|
|
37079
38042
|
const contents = Object.entries(values).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join("\n");
|
|
37080
38043
|
await writeFile14(path, `${contents}
|
|
37081
38044
|
`, { mode: 384 });
|
|
@@ -37084,7 +38047,7 @@ async function writeProviderEnv(selection, agentPubkey) {
|
|
|
37084
38047
|
}
|
|
37085
38048
|
async function runInstalledFinish(binary, grantPath) {
|
|
37086
38049
|
await new Promise((resolveRun, rejectRun) => {
|
|
37087
|
-
const child =
|
|
38050
|
+
const child = spawn11(binary, ["connect-finish", grantPath], {
|
|
37088
38051
|
stdio: ["ignore", "pipe", "pipe"]
|
|
37089
38052
|
});
|
|
37090
38053
|
let diagnostic = "";
|
|
@@ -37144,7 +38107,7 @@ async function runConnectWizard(code, fetchImpl, eventSubscriptions, accessPolic
|
|
|
37144
38107
|
await finishConnectedAgentPairing(baseUrl, pairingCode, grant.workspace_joined, eventSubscriptions, fetchImpl);
|
|
37145
38108
|
const installedRelease = await brassSpinner("Installing the Beeline daemon\u2026", () => installCurrentRelease(fetchImpl), (release) => `Installed Beeline helper ${release.version}`);
|
|
37146
38109
|
const llmEnvFile = await writeProviderEnv(selection, grant.agent_pubkey);
|
|
37147
|
-
const grantPath =
|
|
38110
|
+
const grantPath = resolve29(defaultSupervisorRoot(process.env), "beeline", "connect", `grant-${process.pid}-${Date.now()}.json`);
|
|
37148
38111
|
await writePrivateJson(grantPath, {
|
|
37149
38112
|
agentSecretKey: grant.agent_secret_key,
|
|
37150
38113
|
bodySecretKey: grant.body_secret_key,
|
|
@@ -37229,18 +38192,18 @@ async function runConnectFinishCommand(path) {
|
|
|
37229
38192
|
throw new Error("connect-finish may run only from the canonical installed Beeline launcher");
|
|
37230
38193
|
}
|
|
37231
38194
|
try {
|
|
37232
|
-
const grant = JSON.parse(await readFile12(
|
|
38195
|
+
const grant = JSON.parse(await readFile12(resolve29(path), "utf8"));
|
|
37233
38196
|
if (!isDevicePairingGrant(grant))
|
|
37234
38197
|
throw new Error("device connection grant is invalid");
|
|
37235
38198
|
const connected = await completeDevicePairing(grant);
|
|
37236
|
-
await unlink5(
|
|
38199
|
+
await unlink5(resolve29(path));
|
|
37237
38200
|
const providerEnv = grant.llmEnvFile ? await readFile12(grant.llmEnvFile, "utf8").catch(() => "") : "";
|
|
37238
38201
|
const apiKey = (/^OPENROUTER_API_KEY=(\S+)/m.exec(providerEnv)?.[1] ?? "").replace(/^["']|["']$/g, "");
|
|
37239
38202
|
const model = openRouterModelId(grant.model, { OPENROUTER_API_KEY: apiKey });
|
|
37240
38203
|
if (model) {
|
|
37241
38204
|
const decision2 = await resolveOpenRouterRouting({
|
|
37242
38205
|
model,
|
|
37243
|
-
cacheDir: openRouterRoutingCacheDir(
|
|
38206
|
+
cacheDir: openRouterRoutingCacheDir(dirname19(connected.configPath)),
|
|
37244
38207
|
...apiKey ? { apiKey } : {},
|
|
37245
38208
|
probeTimeoutMs: 1e4
|
|
37246
38209
|
});
|
|
@@ -37259,11 +38222,11 @@ init_self_update();
|
|
|
37259
38222
|
|
|
37260
38223
|
// apps/body/dist/daemon-failure.js
|
|
37261
38224
|
import { mkdir as mkdir21, readFile as readFile13, rename as rename8, rm as rm8, writeFile as writeFile15 } from "node:fs/promises";
|
|
37262
|
-
import { dirname as
|
|
38225
|
+
import { dirname as dirname20, resolve as resolve30 } from "node:path";
|
|
37263
38226
|
var DAEMON_FAILURE_LIMIT = 3;
|
|
37264
38227
|
var DAEMON_FAILURE_WINDOW_MS = 5 * 6e4;
|
|
37265
38228
|
function daemonFailurePath(runtimeDir) {
|
|
37266
|
-
return
|
|
38229
|
+
return resolve30(runtimeDir, "daemon-distress.json");
|
|
37267
38230
|
}
|
|
37268
38231
|
async function readFailureRecord(runtimeDir) {
|
|
37269
38232
|
try {
|
|
@@ -37279,7 +38242,7 @@ async function readFailureRecord(runtimeDir) {
|
|
|
37279
38242
|
async function writeFailureRecord(runtimeDir, record3) {
|
|
37280
38243
|
const path = daemonFailurePath(runtimeDir);
|
|
37281
38244
|
const staged = `${path}.${process.pid}.tmp`;
|
|
37282
|
-
await mkdir21(
|
|
38245
|
+
await mkdir21(dirname20(path), { recursive: true, mode: 448 });
|
|
37283
38246
|
await writeFile15(staged, `${JSON.stringify(record3, null, 2)}
|
|
37284
38247
|
`, { mode: 384 });
|
|
37285
38248
|
await rename8(staged, path);
|
|
@@ -37303,8 +38266,8 @@ async function clearDaemonStartFailures(runtimeDir) {
|
|
|
37303
38266
|
|
|
37304
38267
|
// apps/body/dist/update-functional-probe.js
|
|
37305
38268
|
import { mkdir as mkdir22, rm as rm9 } from "node:fs/promises";
|
|
37306
|
-
import { homedir as
|
|
37307
|
-
import { resolve as
|
|
38269
|
+
import { homedir as homedir14 } from "node:os";
|
|
38270
|
+
import { resolve as resolve31 } from "node:path";
|
|
37308
38271
|
var UPDATE_PROBE_SESSION_TIMEOUT_MS = 1e4;
|
|
37309
38272
|
var UPDATE_PROBE_SESSION_OPEN_TIMEOUT_MS = 2e4;
|
|
37310
38273
|
var UPDATE_PROBE_TURN_TIMEOUT_MS = 45e3;
|
|
@@ -37424,9 +38387,9 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
37424
38387
|
modelAnswerReason: `${detail} (the current release has the same host sandbox failure)`
|
|
37425
38388
|
};
|
|
37426
38389
|
}
|
|
37427
|
-
const root = input.probeRoot ??
|
|
37428
|
-
const cwd =
|
|
37429
|
-
const homeRoot =
|
|
38390
|
+
const root = input.probeRoot ?? resolve31(input.runtimeDir, "update-functional-probe");
|
|
38391
|
+
const cwd = resolve31(root, "checkout");
|
|
38392
|
+
const homeRoot = resolve31(root, "agent-home");
|
|
37430
38393
|
await rm9(root, { recursive: true, force: true });
|
|
37431
38394
|
await mkdir22(cwd, { recursive: true, mode: 448 });
|
|
37432
38395
|
let client;
|
|
@@ -37435,7 +38398,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
37435
38398
|
...input.config.agentEnv,
|
|
37436
38399
|
...await prepareRoomAgentHome({
|
|
37437
38400
|
root: homeRoot,
|
|
37438
|
-
operatorHome: input.config.operatorHome ??
|
|
38401
|
+
operatorHome: input.config.operatorHome ?? homedir14(),
|
|
37439
38402
|
sharedSkills: input.config.sharedSkills ?? [],
|
|
37440
38403
|
...input.config.agentKind ? { agentKind: input.config.agentKind } : {},
|
|
37441
38404
|
skillReleaseId: input.releaseId,
|
|
@@ -37456,7 +38419,7 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
37456
38419
|
let turnCompleted = true;
|
|
37457
38420
|
if (input.config.bwrapPath) {
|
|
37458
38421
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
37459
|
-
const operatorHome = input.config.operatorHome ??
|
|
38422
|
+
const operatorHome = input.config.operatorHome ?? homedir14();
|
|
37460
38423
|
const homeStateDirs = harnessHomeStateDirs(harnessLabel, agentEnv.HOME ?? operatorHome);
|
|
37461
38424
|
await Promise.all(homeStateDirs.map((dir) => mkdir22(dir, { recursive: true })));
|
|
37462
38425
|
spawnCommand = wrapAgentCommand({
|
|
@@ -37607,8 +38570,8 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
37607
38570
|
}
|
|
37608
38571
|
|
|
37609
38572
|
// apps/body/dist/current-release-probe.js
|
|
37610
|
-
import { spawn as
|
|
37611
|
-
import { dirname as
|
|
38573
|
+
import { spawn as spawn12 } from "node:child_process";
|
|
38574
|
+
import { dirname as dirname21, join as join14 } from "node:path";
|
|
37612
38575
|
init_self_update();
|
|
37613
38576
|
var CURRENT_RELEASE_PROBE_TIMEOUT_MS = 12e4;
|
|
37614
38577
|
var UPDATE_PROBE_COMMAND = "update-probe";
|
|
@@ -37651,14 +38614,14 @@ function outcomeFromReport(report) {
|
|
|
37651
38614
|
}
|
|
37652
38615
|
}
|
|
37653
38616
|
async function probeReleaseInSubprocess(input) {
|
|
37654
|
-
const bundleDir =
|
|
38617
|
+
const bundleDir = join14(input.layout.releasesRoot, input.releaseId);
|
|
37655
38618
|
const entrypoint = await resolveBundleEntrypoint(bundleDir);
|
|
37656
38619
|
if (!entrypoint) {
|
|
37657
38620
|
return { kind: "unavailable", reason: `release ${input.releaseId} has no runnable CLI entrypoint` };
|
|
37658
38621
|
}
|
|
37659
38622
|
const timeoutMs = input.timeoutMs ?? CURRENT_RELEASE_PROBE_TIMEOUT_MS;
|
|
37660
|
-
return new Promise((
|
|
37661
|
-
const child =
|
|
38623
|
+
return new Promise((resolve35) => {
|
|
38624
|
+
const child = spawn12(input.execPath ?? process.execPath, [entrypoint, UPDATE_PROBE_COMMAND, "--config", input.runtimeConfigPath], { env: input.env ?? process.env, stdio: ["ignore", "pipe", "pipe"] });
|
|
37662
38625
|
let stdout6 = "";
|
|
37663
38626
|
let stderr = "";
|
|
37664
38627
|
let settled = false;
|
|
@@ -37667,7 +38630,7 @@ async function probeReleaseInSubprocess(input) {
|
|
|
37667
38630
|
return;
|
|
37668
38631
|
settled = true;
|
|
37669
38632
|
clearTimeout(timer);
|
|
37670
|
-
|
|
38633
|
+
resolve35(outcome);
|
|
37671
38634
|
};
|
|
37672
38635
|
const timer = setTimeout(() => {
|
|
37673
38636
|
child.kill("SIGKILL");
|
|
@@ -37714,7 +38677,7 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
37714
38677
|
const runtime = await readRuntimeRecord(configPath);
|
|
37715
38678
|
const agent = runtimeAgentCommand(runtime);
|
|
37716
38679
|
const config = loadBodyConfig({
|
|
37717
|
-
workspaceRoot:
|
|
38680
|
+
workspaceRoot: join14(dirname21(configPath), "workspace"),
|
|
37718
38681
|
llmEnvFile: runtime.llmEnvFile,
|
|
37719
38682
|
env: { ...env, BUZZ_AGENT_BIN: agent.command, BUZZ_DEV_MCP_BIN: runtime.mcpBinary },
|
|
37720
38683
|
agent
|
|
@@ -37732,7 +38695,7 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
37732
38695
|
}
|
|
37733
38696
|
const layout = beelineInstallLayout(env);
|
|
37734
38697
|
const releaseId = (layout && await activeReleaseId(layout).catch(() => void 0)) ?? "unknown";
|
|
37735
|
-
const runtimeDir =
|
|
38698
|
+
const runtimeDir = dirname21(configPath);
|
|
37736
38699
|
const outcome = await probeOutcome(() => (options.probe ?? runUpdateFunctionalProbe)({
|
|
37737
38700
|
config,
|
|
37738
38701
|
runtimeDir,
|
|
@@ -37740,7 +38703,7 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
37740
38703
|
sandboxRequired: runtime.sandbox !== "off",
|
|
37741
38704
|
sandboxUnavailableDetail: sandbox.advisory,
|
|
37742
38705
|
// The successor's probe still holds `<runtimeDir>/update-functional-probe`.
|
|
37743
|
-
probeRoot:
|
|
38706
|
+
probeRoot: join14(runtimeDir, "current-release-probe")
|
|
37744
38707
|
}));
|
|
37745
38708
|
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 };
|
|
37746
38709
|
write(JSON.stringify(report));
|
|
@@ -37748,7 +38711,7 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
37748
38711
|
|
|
37749
38712
|
// apps/body/dist/release-status.js
|
|
37750
38713
|
import { readFile as readFile14, readdir as readdir6, rename as rename9, writeFile as writeFile16 } from "node:fs/promises";
|
|
37751
|
-
import { resolve as
|
|
38714
|
+
import { resolve as resolve32 } from "node:path";
|
|
37752
38715
|
var DAEMON_RELEASE_STATUS_FILE = "release-status.json";
|
|
37753
38716
|
var RELEASE_VERSION = /^v\d+\.\d+\.\d+$/;
|
|
37754
38717
|
var SOURCE_SHA = /^[0-9a-f]{7,64}$/;
|
|
@@ -37765,7 +38728,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
|
|
|
37765
38728
|
pid: options.pid ?? process.pid,
|
|
37766
38729
|
readyAt: (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString()
|
|
37767
38730
|
};
|
|
37768
|
-
const target =
|
|
38731
|
+
const target = resolve32(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
|
|
37769
38732
|
const temporary = `${target}.${status.pid}.tmp`;
|
|
37770
38733
|
await writeFile16(temporary, `${JSON.stringify(status, null, 2)}
|
|
37771
38734
|
`, { mode: 384 });
|
|
@@ -37775,7 +38738,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
|
|
|
37775
38738
|
|
|
37776
38739
|
// apps/body/dist/scratch-sweep.js
|
|
37777
38740
|
import { lstat as lstat5, readdir as readdir7, rmdir, unlink as unlink6 } from "node:fs/promises";
|
|
37778
|
-
import { resolve as
|
|
38741
|
+
import { resolve as resolve33 } from "node:path";
|
|
37779
38742
|
var DEFAULT_SCRATCH_TTL_HOURS = 72;
|
|
37780
38743
|
var NEVER_SWEEP_SUBDIR_NAMES = new Set(HOME_SUBDIRS.filter((name) => name !== "tmp"));
|
|
37781
38744
|
function scratchTtlMs(env = process.env) {
|
|
@@ -37784,7 +38747,7 @@ function scratchTtlMs(env = process.env) {
|
|
|
37784
38747
|
return (Number.isFinite(hours) && hours > 0 ? hours : DEFAULT_SCRATCH_TTL_HOURS) * 60 * 60 * 1e3;
|
|
37785
38748
|
}
|
|
37786
38749
|
async function discoverAttachScratchRoots(runtimeDir) {
|
|
37787
|
-
const roomsDir =
|
|
38750
|
+
const roomsDir = resolve33(runtimeDir, "rooms");
|
|
37788
38751
|
let entries;
|
|
37789
38752
|
try {
|
|
37790
38753
|
entries = await readdir7(roomsDir, { withFileTypes: true });
|
|
@@ -37795,7 +38758,7 @@ async function discoverAttachScratchRoots(runtimeDir) {
|
|
|
37795
38758
|
for (const entry of entries) {
|
|
37796
38759
|
if (!entry.isDirectory())
|
|
37797
38760
|
continue;
|
|
37798
|
-
const home =
|
|
38761
|
+
const home = resolve33(roomsDir, entry.name, "agent-home");
|
|
37799
38762
|
const stats = await lstat5(home).catch(() => void 0);
|
|
37800
38763
|
if (stats?.isDirectory())
|
|
37801
38764
|
roots.push(home);
|
|
@@ -37814,7 +38777,7 @@ async function removeStaleFiles(dir, cutoffMs, protectNamesHere) {
|
|
|
37814
38777
|
for (const entry of entries) {
|
|
37815
38778
|
if (protectNamesHere && NEVER_SWEEP_SUBDIR_NAMES.has(entry.name))
|
|
37816
38779
|
continue;
|
|
37817
|
-
const path =
|
|
38780
|
+
const path = resolve33(dir, entry.name);
|
|
37818
38781
|
const stats = await lstat5(path).catch(() => void 0);
|
|
37819
38782
|
if (!stats || stats.isSymbolicLink())
|
|
37820
38783
|
continue;
|
|
@@ -37902,7 +38865,7 @@ var DaemonExitError = class extends Error {
|
|
|
37902
38865
|
};
|
|
37903
38866
|
async function runStoredDaemon(pathOrPointer) {
|
|
37904
38867
|
const configPath = await resolveRuntimeConfigPath(pathOrPointer);
|
|
37905
|
-
daemonFailureRuntimeDir =
|
|
38868
|
+
daemonFailureRuntimeDir = dirname22(configPath);
|
|
37906
38869
|
const accessMigration = await migrateRuntimeRecordAccessPolicy(configPath);
|
|
37907
38870
|
let runtime = accessMigration.runtime;
|
|
37908
38871
|
if (!runtime.transport) {
|
|
@@ -37921,7 +38884,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
37921
38884
|
BUZZ_DEV_MCP_BIN: runtime.mcpBinary
|
|
37922
38885
|
};
|
|
37923
38886
|
const config = loadBodyConfig({
|
|
37924
|
-
workspaceRoot:
|
|
38887
|
+
workspaceRoot: resolve34(dirname22(configPath), "workspace"),
|
|
37925
38888
|
llmEnvFile: runtime.llmEnvFile,
|
|
37926
38889
|
env,
|
|
37927
38890
|
agent
|
|
@@ -37956,7 +38919,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
37956
38919
|
const stop = () => controller.abort();
|
|
37957
38920
|
process.once("SIGINT", stop);
|
|
37958
38921
|
process.once("SIGTERM", stop);
|
|
37959
|
-
const runtimeDir =
|
|
38922
|
+
const runtimeDir = dirname22(configPath);
|
|
37960
38923
|
const layout = beelineInstallLayout(process.env);
|
|
37961
38924
|
const notifier = new SystemdNotifier();
|
|
37962
38925
|
let rollbackAlertDrain;
|
|
@@ -38136,6 +39099,14 @@ async function main() {
|
|
|
38136
39099
|
await runCursorAcpStdioServer();
|
|
38137
39100
|
return;
|
|
38138
39101
|
}
|
|
39102
|
+
if (command === SQUIRE_FACADE_FLAG) {
|
|
39103
|
+
runSquireFacade();
|
|
39104
|
+
return;
|
|
39105
|
+
}
|
|
39106
|
+
if (command === SQUIRE_BROKER_FLAG) {
|
|
39107
|
+
runSquireBroker();
|
|
39108
|
+
return;
|
|
39109
|
+
}
|
|
38139
39110
|
if (command === "--help" || command === "-h")
|
|
38140
39111
|
usage(0);
|
|
38141
39112
|
if (command === "managed-update-worker") {
|
|
@@ -38152,7 +39123,7 @@ async function main() {
|
|
|
38152
39123
|
const roomId = roomFlag >= 0 ? args[roomFlag + 1] : void 0;
|
|
38153
39124
|
if (!configPath || !roomId)
|
|
38154
39125
|
throw new Error("corner-read-token requires --config and --room");
|
|
38155
|
-
const activated = await activateDaemonTransport(
|
|
39126
|
+
const activated = await activateDaemonTransport(resolve34(configPath));
|
|
38156
39127
|
if (!activated)
|
|
38157
39128
|
throw new Error("corner-read-token requires monolith transport");
|
|
38158
39129
|
const credential = await activated.client.execute("getRoomGitHubToken", { roomId });
|
|
@@ -38206,14 +39177,14 @@ async function main() {
|
|
|
38206
39177
|
}
|
|
38207
39178
|
if (!configPath && agentPubkey) {
|
|
38208
39179
|
const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
|
|
38209
|
-
configPath = configs.find((candidate) =>
|
|
39180
|
+
configPath = configs.find((candidate) => dirname22(candidate).endsWith(agentPubkey));
|
|
38210
39181
|
}
|
|
38211
39182
|
if (!configPath && agentPubkey) {
|
|
38212
39183
|
throw new DaemonExitError(`unknown agent ${agentPubkey}: no durable runtime exists; refusing systemd restart loop`, UNKNOWN_AGENT_EXIT_STATUS);
|
|
38213
39184
|
}
|
|
38214
39185
|
if (!configPath)
|
|
38215
39186
|
throw new Error("daemon requires --config <runtime.json> or --agent <pubkey>");
|
|
38216
|
-
await runStoredDaemon(
|
|
39187
|
+
await runStoredDaemon(resolve34(configPath));
|
|
38217
39188
|
return;
|
|
38218
39189
|
}
|
|
38219
39190
|
if (command === "update") {
|
|
@@ -38234,7 +39205,7 @@ async function main() {
|
|
|
38234
39205
|
if (!agentPubkey)
|
|
38235
39206
|
throw new Error("stop requires --agent <pubkey>");
|
|
38236
39207
|
const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
|
|
38237
|
-
const configPath = configs.find((candidate) =>
|
|
39208
|
+
const configPath = configs.find((candidate) => dirname22(candidate).endsWith(agentPubkey));
|
|
38238
39209
|
if (!configPath)
|
|
38239
39210
|
throw new Error(`no stored runtime found for agent ${agentPubkey}`);
|
|
38240
39211
|
const runtime = await readRuntimeRecord(configPath);
|