usebeeline 0.0.132 → 0.0.134
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/dist/usebeeline.mjs +906 -1407
- package/package.json +1 -1
package/dist/usebeeline.mjs
CHANGED
|
@@ -8713,13 +8713,13 @@ var init_esm = __esm({
|
|
|
8713
8713
|
let count = last - first;
|
|
8714
8714
|
while (count > 0) {
|
|
8715
8715
|
let it = first;
|
|
8716
|
-
let
|
|
8717
|
-
it +=
|
|
8716
|
+
let step3 = Math.floor(count / 2);
|
|
8717
|
+
it += step3;
|
|
8718
8718
|
if (cmp(arr[it])) {
|
|
8719
8719
|
first = ++it;
|
|
8720
|
-
count -=
|
|
8720
|
+
count -= step3 + 1;
|
|
8721
8721
|
} else {
|
|
8722
|
-
count =
|
|
8722
|
+
count = step3;
|
|
8723
8723
|
}
|
|
8724
8724
|
}
|
|
8725
8725
|
return first;
|
|
@@ -9349,10 +9349,210 @@ var init_runtime = __esm({
|
|
|
9349
9349
|
}
|
|
9350
9350
|
});
|
|
9351
9351
|
|
|
9352
|
+
// apps/body/dist/squire-broker-link.js
|
|
9353
|
+
import { randomUUID } from "node:crypto";
|
|
9354
|
+
import { createConnection } from "node:net";
|
|
9355
|
+
function frameLines(chunk, buffered, receive) {
|
|
9356
|
+
let input = Buffer.concat([buffered, chunk]);
|
|
9357
|
+
for (; ; ) {
|
|
9358
|
+
const end = input.indexOf(10);
|
|
9359
|
+
if (end < 0)
|
|
9360
|
+
return input;
|
|
9361
|
+
receive(input.subarray(0, end).toString("utf8"));
|
|
9362
|
+
input = input.subarray(end + 1);
|
|
9363
|
+
}
|
|
9364
|
+
}
|
|
9365
|
+
async function runSquireBrokerLink(options) {
|
|
9366
|
+
const { agentId, socketPath, giveUpMs = SQUIRE_RELAY_GIVE_UP_MS, input = process.stdin, output = process.stdout, logError = (message) => process.stderr.write(`${message}
|
|
9367
|
+
`), connect = (path) => createConnection(path), onShutdownSignal = (handler) => {
|
|
9368
|
+
process.once("SIGHUP", handler);
|
|
9369
|
+
process.once("SIGTERM", handler);
|
|
9370
|
+
process.once("SIGINT", handler);
|
|
9371
|
+
} } = options;
|
|
9372
|
+
let socket;
|
|
9373
|
+
let retryTimer;
|
|
9374
|
+
let disconnectedSince;
|
|
9375
|
+
let inBuffer = Buffer.alloc(0);
|
|
9376
|
+
let outBuffer = Buffer.alloc(0);
|
|
9377
|
+
let initializeLine;
|
|
9378
|
+
let initializedLine;
|
|
9379
|
+
let replayId;
|
|
9380
|
+
let delayMs = SQUIRE_RELAY_INITIAL_DELAY_MS;
|
|
9381
|
+
let stopped = false;
|
|
9382
|
+
let gaveUp = false;
|
|
9383
|
+
let connectedOnce = false;
|
|
9384
|
+
let ready = false;
|
|
9385
|
+
const pending = /* @__PURE__ */ new Map();
|
|
9386
|
+
const queued = [];
|
|
9387
|
+
let resolveDone;
|
|
9388
|
+
const done = new Promise((resolve40) => {
|
|
9389
|
+
resolveDone = resolve40;
|
|
9390
|
+
});
|
|
9391
|
+
const failResponse = (id) => `${JSON.stringify({
|
|
9392
|
+
jsonrpc: "2.0",
|
|
9393
|
+
id,
|
|
9394
|
+
error: { code: -32e3, message: "Trusty Squire broker connection lost" }
|
|
9395
|
+
})}
|
|
9396
|
+
`;
|
|
9397
|
+
const flush = () => {
|
|
9398
|
+
while (queued.length) {
|
|
9399
|
+
const line = queued.shift();
|
|
9400
|
+
const frame = JSON.parse(line);
|
|
9401
|
+
if (frame.id !== void 0 && frame.method)
|
|
9402
|
+
pending.set(JSON.stringify(frame.id), frame.id);
|
|
9403
|
+
socket?.write(`${line}
|
|
9404
|
+
`);
|
|
9405
|
+
}
|
|
9406
|
+
};
|
|
9407
|
+
function stop(ok2) {
|
|
9408
|
+
if (stopped)
|
|
9409
|
+
return;
|
|
9410
|
+
stopped = true;
|
|
9411
|
+
if (retryTimer)
|
|
9412
|
+
clearTimeout(retryTimer);
|
|
9413
|
+
socket?.destroy();
|
|
9414
|
+
resolveDone(ok2);
|
|
9415
|
+
}
|
|
9416
|
+
const giveUp = () => {
|
|
9417
|
+
if (gaveUp)
|
|
9418
|
+
return;
|
|
9419
|
+
gaveUp = true;
|
|
9420
|
+
logError(`${SQUIRE_BROKER_UNAVAILABLE}: ${TRUSTY_SQUIRE_BROKER_UNIT_NAME} is not reachable at ${socketPath}`);
|
|
9421
|
+
for (const id of pending.values())
|
|
9422
|
+
output.write(failResponse(id));
|
|
9423
|
+
pending.clear();
|
|
9424
|
+
for (const line of queued.splice(0)) {
|
|
9425
|
+
const frame = JSON.parse(line);
|
|
9426
|
+
if (frame.id !== void 0 && frame.method)
|
|
9427
|
+
output.write(failResponse(frame.id));
|
|
9428
|
+
}
|
|
9429
|
+
stop(false);
|
|
9430
|
+
};
|
|
9431
|
+
const reconnect = () => {
|
|
9432
|
+
if (stopped || retryTimer || gaveUp)
|
|
9433
|
+
return;
|
|
9434
|
+
disconnectedSince ??= Date.now();
|
|
9435
|
+
if (Date.now() - disconnectedSince >= giveUpMs) {
|
|
9436
|
+
giveUp();
|
|
9437
|
+
return;
|
|
9438
|
+
}
|
|
9439
|
+
retryTimer = setTimeout(() => {
|
|
9440
|
+
retryTimer = void 0;
|
|
9441
|
+
doConnect();
|
|
9442
|
+
}, delayMs);
|
|
9443
|
+
delayMs = Math.min(delayMs * 2, SQUIRE_RELAY_MAX_DELAY_MS);
|
|
9444
|
+
};
|
|
9445
|
+
const attach = (peer) => {
|
|
9446
|
+
if (stopped) {
|
|
9447
|
+
peer.destroy();
|
|
9448
|
+
return;
|
|
9449
|
+
}
|
|
9450
|
+
socket = peer;
|
|
9451
|
+
outBuffer = Buffer.alloc(0);
|
|
9452
|
+
peer.once("connect", () => {
|
|
9453
|
+
delayMs = SQUIRE_RELAY_INITIAL_DELAY_MS;
|
|
9454
|
+
disconnectedSince = void 0;
|
|
9455
|
+
peer.write(`${agentId}
|
|
9456
|
+
`);
|
|
9457
|
+
if (connectedOnce && initializeLine) {
|
|
9458
|
+
replayId = `beeline-squire-relay-${randomUUID()}`;
|
|
9459
|
+
const frame = JSON.parse(initializeLine);
|
|
9460
|
+
peer.write(`${JSON.stringify({ ...frame, id: replayId })}
|
|
9461
|
+
`);
|
|
9462
|
+
} else {
|
|
9463
|
+
ready = true;
|
|
9464
|
+
flush();
|
|
9465
|
+
}
|
|
9466
|
+
connectedOnce = true;
|
|
9467
|
+
});
|
|
9468
|
+
peer.on("data", (chunk) => {
|
|
9469
|
+
outBuffer = frameLines(chunk, outBuffer, (line) => {
|
|
9470
|
+
const frame = JSON.parse(line);
|
|
9471
|
+
if (frame.id === replayId) {
|
|
9472
|
+
replayId = void 0;
|
|
9473
|
+
if (frame.error) {
|
|
9474
|
+
peer.destroy(new Error("broker rejected relay initialization"));
|
|
9475
|
+
return;
|
|
9476
|
+
}
|
|
9477
|
+
if (initializedLine)
|
|
9478
|
+
peer.write(`${initializedLine}
|
|
9479
|
+
`);
|
|
9480
|
+
ready = true;
|
|
9481
|
+
flush();
|
|
9482
|
+
return;
|
|
9483
|
+
}
|
|
9484
|
+
if (frame.id !== void 0 && !frame.method)
|
|
9485
|
+
pending.delete(JSON.stringify(frame.id));
|
|
9486
|
+
output.write(`${line}
|
|
9487
|
+
`);
|
|
9488
|
+
});
|
|
9489
|
+
});
|
|
9490
|
+
peer.on("error", (error) => {
|
|
9491
|
+
if (!stopped)
|
|
9492
|
+
logError(`squire relay: ${error instanceof Error ? error.message : String(error)}`);
|
|
9493
|
+
});
|
|
9494
|
+
peer.once("close", () => {
|
|
9495
|
+
if (socket !== peer || stopped)
|
|
9496
|
+
return;
|
|
9497
|
+
socket = void 0;
|
|
9498
|
+
ready = false;
|
|
9499
|
+
replayId = void 0;
|
|
9500
|
+
for (const id of pending.values())
|
|
9501
|
+
output.write(failResponse(id));
|
|
9502
|
+
pending.clear();
|
|
9503
|
+
reconnect();
|
|
9504
|
+
});
|
|
9505
|
+
};
|
|
9506
|
+
const doConnect = () => {
|
|
9507
|
+
if (stopped)
|
|
9508
|
+
return;
|
|
9509
|
+
try {
|
|
9510
|
+
attach(connect(socketPath));
|
|
9511
|
+
} catch {
|
|
9512
|
+
reconnect();
|
|
9513
|
+
}
|
|
9514
|
+
};
|
|
9515
|
+
input.on("data", (chunk) => {
|
|
9516
|
+
inBuffer = frameLines(chunk, inBuffer, (line) => {
|
|
9517
|
+
const frame = JSON.parse(line);
|
|
9518
|
+
if (gaveUp) {
|
|
9519
|
+
if (frame.id !== void 0 && frame.method)
|
|
9520
|
+
output.write(failResponse(frame.id));
|
|
9521
|
+
return;
|
|
9522
|
+
}
|
|
9523
|
+
if (frame.method === "initialize")
|
|
9524
|
+
initializeLine = line;
|
|
9525
|
+
if (frame.method === "notifications/initialized")
|
|
9526
|
+
initializedLine = line;
|
|
9527
|
+
queued.push(line);
|
|
9528
|
+
if (ready)
|
|
9529
|
+
flush();
|
|
9530
|
+
});
|
|
9531
|
+
});
|
|
9532
|
+
const close = () => stop(!gaveUp);
|
|
9533
|
+
input.once("end", close);
|
|
9534
|
+
input.once("close", close);
|
|
9535
|
+
onShutdownSignal(close);
|
|
9536
|
+
doConnect();
|
|
9537
|
+
const ok = await done;
|
|
9538
|
+
return { ok };
|
|
9539
|
+
}
|
|
9540
|
+
var SQUIRE_RELAY_INITIAL_DELAY_MS, SQUIRE_RELAY_MAX_DELAY_MS, SQUIRE_RELAY_GIVE_UP_MS;
|
|
9541
|
+
var init_squire_broker_link = __esm({
|
|
9542
|
+
"apps/body/dist/squire-broker-link.js"() {
|
|
9543
|
+
"use strict";
|
|
9544
|
+
init_squire_host();
|
|
9545
|
+
SQUIRE_RELAY_INITIAL_DELAY_MS = 100;
|
|
9546
|
+
SQUIRE_RELAY_MAX_DELAY_MS = 1e3;
|
|
9547
|
+
SQUIRE_RELAY_GIVE_UP_MS = 1e4;
|
|
9548
|
+
}
|
|
9549
|
+
});
|
|
9550
|
+
|
|
9352
9551
|
// apps/body/dist/squire-host.js
|
|
9353
9552
|
import { spawn as spawn3 } from "node:child_process";
|
|
9354
|
-
import { existsSync as existsSync2,
|
|
9553
|
+
import { accessSync, constants as fsConstants, existsSync as existsSync2, mkdirSync } from "node:fs";
|
|
9355
9554
|
import { createRequire as createRequire2 } from "node:module";
|
|
9555
|
+
import { createConnection as createConnection2 } from "node:net";
|
|
9356
9556
|
import { homedir as homedir2 } from "node:os";
|
|
9357
9557
|
import { dirname as dirname2, join as join2, resolve as resolve2 } from "node:path";
|
|
9358
9558
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -9362,7 +9562,8 @@ function squireHostPaths(home) {
|
|
|
9362
9562
|
dir,
|
|
9363
9563
|
profileDir: join2(dir, "chrome-profile"),
|
|
9364
9564
|
configHome: join2(resolve2(home), ".config"),
|
|
9365
|
-
brokerSocket: join2(dir, "broker.sock")
|
|
9565
|
+
brokerSocket: join2(dir, "broker.sock"),
|
|
9566
|
+
mcpSocket: join2(dir, "mcp.sock")
|
|
9366
9567
|
};
|
|
9367
9568
|
}
|
|
9368
9569
|
function squireHostRewriteEnv(home) {
|
|
@@ -9379,13 +9580,27 @@ function ensureSquireHostDir(home) {
|
|
|
9379
9580
|
mkdirSync(paths.profileDir, { recursive: true, mode: 448 });
|
|
9380
9581
|
return paths;
|
|
9381
9582
|
}
|
|
9382
|
-
function
|
|
9583
|
+
function squireHostDirWritable(socketPath) {
|
|
9383
9584
|
try {
|
|
9384
|
-
|
|
9585
|
+
accessSync(dirname2(socketPath), fsConstants.W_OK);
|
|
9586
|
+
return true;
|
|
9385
9587
|
} catch {
|
|
9386
9588
|
return false;
|
|
9387
9589
|
}
|
|
9388
9590
|
}
|
|
9591
|
+
async function squireBrokerSocketReady(socketPath) {
|
|
9592
|
+
return await new Promise((resolveReady) => {
|
|
9593
|
+
const probe = createConnection2(socketPath);
|
|
9594
|
+
probe.once("connect", () => {
|
|
9595
|
+
probe.destroy();
|
|
9596
|
+
resolveReady(true);
|
|
9597
|
+
});
|
|
9598
|
+
probe.once("error", () => {
|
|
9599
|
+
probe.destroy();
|
|
9600
|
+
resolveReady(false);
|
|
9601
|
+
});
|
|
9602
|
+
});
|
|
9603
|
+
}
|
|
9389
9604
|
function squireFacadeLaunch(home, scope) {
|
|
9390
9605
|
if (!scope.agentId || !scope.roomId)
|
|
9391
9606
|
throw new Error("Squire agent and Room IDs are required");
|
|
@@ -9461,20 +9676,26 @@ function runSquireBroker(env = process.env) {
|
|
|
9461
9676
|
const paths = ensureSquireHostDir(home);
|
|
9462
9677
|
spawnSquireServer({ ...env, ...squireHostRewriteEnv(home), TRUSTY_SQUIRE_BROKER_SOCKET: paths.brokerSocket }, true, SQUIRE_BROKER_ARGS);
|
|
9463
9678
|
}
|
|
9464
|
-
function runSquireFacade(env = process.env) {
|
|
9679
|
+
async function runSquireFacade(env = process.env) {
|
|
9465
9680
|
const socket = env.TRUSTY_SQUIRE_BROKER_SOCKET ?? squireHostPaths(env.HOME?.trim() || homedir2()).brokerSocket;
|
|
9466
|
-
if (!squireBrokerSocketReady(socket)) {
|
|
9467
|
-
process.stderr.write(`${SQUIRE_BROKER_UNAVAILABLE}
|
|
9681
|
+
if (!squireHostDirWritable(socket) || !await squireBrokerSocketReady(socket)) {
|
|
9682
|
+
process.stderr.write(`${SQUIRE_BROKER_UNAVAILABLE}: ${TRUSTY_SQUIRE_BROKER_UNIT_NAME} is not reachable at ${socket}
|
|
9468
9683
|
`);
|
|
9469
9684
|
process.exitCode = 1;
|
|
9470
9685
|
return;
|
|
9471
9686
|
}
|
|
9472
|
-
|
|
9687
|
+
const mcpSocket = join2(dirname2(socket), "mcp.sock");
|
|
9688
|
+
const { ok } = await runSquireBrokerLink({
|
|
9689
|
+
agentId: env.TRUSTY_SQUIRE_AGENT_IDENTITY?.trim() || "unknown",
|
|
9690
|
+
socketPath: mcpSocket
|
|
9691
|
+
});
|
|
9692
|
+
process.exit(ok ? 0 : 1);
|
|
9473
9693
|
}
|
|
9474
9694
|
var SQUIRE_BROKER_UNAVAILABLE, TRUSTY_SQUIRE_BROKER_UNIT_NAME, SQUIRE_FACADE_FLAG, SQUIRE_BROKER_FLAG, SQUIRE_SERVER_ARGS, SQUIRE_BROKER_ARGS;
|
|
9475
9695
|
var init_squire_host = __esm({
|
|
9476
9696
|
"apps/body/dist/squire-host.js"() {
|
|
9477
9697
|
"use strict";
|
|
9698
|
+
init_squire_broker_link();
|
|
9478
9699
|
SQUIRE_BROKER_UNAVAILABLE = "broker unavailable";
|
|
9479
9700
|
TRUSTY_SQUIRE_BROKER_UNIT_NAME = "trusty-squire-broker.service";
|
|
9480
9701
|
SQUIRE_FACADE_FLAG = "--squire-facade";
|
|
@@ -9513,7 +9734,7 @@ RestartPreventExitStatus=${DAEMON_DISTRESS_EXIT_STATUS} ${DELIBERATE_REMOVAL_EXI
|
|
|
9513
9734
|
SuccessExitStatus=${UNKNOWN_AGENT_EXIT_STATUS}
|
|
9514
9735
|
WatchdogSec=180s
|
|
9515
9736
|
TimeoutStartSec=90s
|
|
9516
|
-
TimeoutStopSec=
|
|
9737
|
+
TimeoutStopSec=90s
|
|
9517
9738
|
KillMode=control-group
|
|
9518
9739
|
UMask=0077
|
|
9519
9740
|
# A desktop-launched user manager may inherit Ubuntu's unprivileged_userns
|
|
@@ -9736,7 +9957,7 @@ var init_systemd = __esm({
|
|
|
9736
9957
|
UNKNOWN_AGENT_EXIT_STATUS = 79;
|
|
9737
9958
|
SYSTEMD_UNIT_NAME = "beeline-agent@.service";
|
|
9738
9959
|
SYSTEMD_COMMAND_TIMEOUT_MS = 15e3;
|
|
9739
|
-
SYSTEMD_RESTART_WAIT_MS =
|
|
9960
|
+
SYSTEMD_RESTART_WAIT_MS = 9e4 + 3e4;
|
|
9740
9961
|
AGENT_SERVICE = /^beeline-agent@([0-9a-f]{64})\.service$/i;
|
|
9741
9962
|
runSystemctl = async (args) => {
|
|
9742
9963
|
const result = await execFileAsync2("systemctl", ["--user", ...args], {
|
|
@@ -10180,7 +10401,7 @@ __export(self_update_exports, {
|
|
|
10180
10401
|
writeUpdateState: () => writeUpdateState
|
|
10181
10402
|
});
|
|
10182
10403
|
import { createHash } from "node:crypto";
|
|
10183
|
-
import { constants as
|
|
10404
|
+
import { constants as fsConstants2 } from "node:fs";
|
|
10184
10405
|
import { access, chmod as chmod2, lstat, mkdir as mkdir4, open, readFile as readFile5, rename as rename3, rm as rm2, symlink, writeFile as writeFile4 } from "node:fs/promises";
|
|
10185
10406
|
import { spawn as spawn4 } from "node:child_process";
|
|
10186
10407
|
import { homedir as homedir5 } from "node:os";
|
|
@@ -10378,7 +10599,7 @@ function entrypointCandidates(bundleDir) {
|
|
|
10378
10599
|
async function resolveBundleEntrypoint(bundleDir) {
|
|
10379
10600
|
for (const candidate of entrypointCandidates(bundleDir)) {
|
|
10380
10601
|
try {
|
|
10381
|
-
await access(candidate,
|
|
10602
|
+
await access(candidate, fsConstants2.F_OK);
|
|
10382
10603
|
return candidate;
|
|
10383
10604
|
} catch {
|
|
10384
10605
|
}
|
|
@@ -10443,7 +10664,7 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
10443
10664
|
throw new Error(`extracting bundle failed: ${extract2.stderr}`);
|
|
10444
10665
|
for (const relative4 of requiredBundlePaths()) {
|
|
10445
10666
|
try {
|
|
10446
|
-
await access(join3(releaseDir, relative4),
|
|
10667
|
+
await access(join3(releaseDir, relative4), fsConstants2.F_OK);
|
|
10447
10668
|
} catch {
|
|
10448
10669
|
throw new Error(`staged bundle is missing ${relative4}`);
|
|
10449
10670
|
}
|
|
@@ -10488,7 +10709,7 @@ async function replaceFile(path, contents, mode) {
|
|
|
10488
10709
|
}
|
|
10489
10710
|
async function activateRelease(layout, releaseId) {
|
|
10490
10711
|
const releaseDir = join3(layout.releasesRoot, releaseId);
|
|
10491
|
-
await access(join3(releaseDir, BUNDLE_ENTRYPOINT),
|
|
10712
|
+
await access(join3(releaseDir, BUNDLE_ENTRYPOINT), fsConstants2.F_OK);
|
|
10492
10713
|
await mkdir4(layout.releasesRoot, { recursive: true });
|
|
10493
10714
|
await mkdir4(layout.binDir, { recursive: true });
|
|
10494
10715
|
let previousReleaseId = await activeReleaseId(layout);
|
|
@@ -10498,7 +10719,7 @@ async function activateRelease(layout, releaseId) {
|
|
|
10498
10719
|
const legacyId = sanitizeReleaseId(legacyIdentity?.commit ?? legacyIdentity?.version ?? `legacy-${Date.now()}`);
|
|
10499
10720
|
const legacyDir = join3(layout.releasesRoot, legacyId);
|
|
10500
10721
|
try {
|
|
10501
|
-
await access(legacyDir,
|
|
10722
|
+
await access(legacyDir, fsConstants2.F_OK);
|
|
10502
10723
|
previousReleaseId = `${legacyId}-${Date.now()}`;
|
|
10503
10724
|
await rename3(layout.libDir, join3(layout.releasesRoot, previousReleaseId));
|
|
10504
10725
|
await normalizeLegacyBundleShape(join3(layout.releasesRoot, previousReleaseId));
|
|
@@ -10521,7 +10742,7 @@ async function normalizeLegacyBundleShape(bundleDir) {
|
|
|
10521
10742
|
let anyFlat = false;
|
|
10522
10743
|
for (const name of LEGACY_FLAT_BUNDLE_FILES) {
|
|
10523
10744
|
try {
|
|
10524
|
-
await access(join3(bundleDir, name),
|
|
10745
|
+
await access(join3(bundleDir, name), fsConstants2.F_OK);
|
|
10525
10746
|
anyFlat = true;
|
|
10526
10747
|
break;
|
|
10527
10748
|
} catch {
|
|
@@ -10532,7 +10753,7 @@ async function normalizeLegacyBundleShape(bundleDir) {
|
|
|
10532
10753
|
await mkdir4(innerLib, { recursive: true });
|
|
10533
10754
|
for (const name of LEGACY_FLAT_BUNDLE_FILES) {
|
|
10534
10755
|
try {
|
|
10535
|
-
await access(join3(innerLib, name),
|
|
10756
|
+
await access(join3(innerLib, name), fsConstants2.F_OK);
|
|
10536
10757
|
continue;
|
|
10537
10758
|
} catch {
|
|
10538
10759
|
}
|
|
@@ -10547,7 +10768,7 @@ async function writeBinForwarders(layout, activeBundleRoot) {
|
|
|
10547
10768
|
for (const [name, tool] of entries) {
|
|
10548
10769
|
const target = join3(activeBundleRoot, "bin", tool);
|
|
10549
10770
|
try {
|
|
10550
|
-
await access(target,
|
|
10771
|
+
await access(target, fsConstants2.X_OK);
|
|
10551
10772
|
} catch {
|
|
10552
10773
|
continue;
|
|
10553
10774
|
}
|
|
@@ -11028,7 +11249,7 @@ import { createRequire as createRequire3 } from "node:module";
|
|
|
11028
11249
|
import { createInterface as createInterface3 } from "node:readline";
|
|
11029
11250
|
import { basename, dirname as dirname7, resolve as resolvePath } from "node:path";
|
|
11030
11251
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
11031
|
-
import { randomUUID } from "node:crypto";
|
|
11252
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
11032
11253
|
function harnessIdentityLabel(agent) {
|
|
11033
11254
|
if (agent.kind === "cursor")
|
|
11034
11255
|
return CURSOR_ACP_BRIDGE_LABEL;
|
|
@@ -11092,7 +11313,7 @@ async function writeIsolatedCursorFile(path, content) {
|
|
|
11092
11313
|
if (!parentStats.isDirectory() || parentStats.isSymbolicLink()) {
|
|
11093
11314
|
throw new Error(`isolated cursor parent is not a real directory: ${parent}`);
|
|
11094
11315
|
}
|
|
11095
|
-
const temporary = resolvePath(parent, `.${basename(path)}.${process.pid}.${
|
|
11316
|
+
const temporary = resolvePath(parent, `.${basename(path)}.${process.pid}.${randomUUID2()}.tmp`);
|
|
11096
11317
|
try {
|
|
11097
11318
|
await writeFile5(temporary, content, { mode: 384, flag: "wx" });
|
|
11098
11319
|
await chmod3(temporary, 384);
|
|
@@ -11384,7 +11605,7 @@ var init_cursor_acp_bridge = __esm({
|
|
|
11384
11605
|
});
|
|
11385
11606
|
const catalog = await this.loadModels();
|
|
11386
11607
|
const session = {
|
|
11387
|
-
id:
|
|
11608
|
+
id: randomUUID2(),
|
|
11388
11609
|
cwd,
|
|
11389
11610
|
...systemPrompt ? { systemPrompt } : {},
|
|
11390
11611
|
model: catalog.currentValue
|
|
@@ -11507,7 +11728,7 @@ var init_cursor_acp_bridge = __esm({
|
|
|
11507
11728
|
});
|
|
11508
11729
|
if (pending.length)
|
|
11509
11730
|
consumeLine(pending.join(""));
|
|
11510
|
-
const
|
|
11731
|
+
const failure = describeCursorTurnFailure({
|
|
11511
11732
|
isError: resultEvent ? cursorResultIsError(resultEvent) : false,
|
|
11512
11733
|
resultText: resultEvent ? resultEventText(resultEvent) : void 0,
|
|
11513
11734
|
exitCode: spawnError ? 1 : code,
|
|
@@ -11515,8 +11736,8 @@ var init_cursor_acp_bridge = __esm({
|
|
|
11515
11736
|
stderr,
|
|
11516
11737
|
spawnError
|
|
11517
11738
|
});
|
|
11518
|
-
if (
|
|
11519
|
-
throw new Error(
|
|
11739
|
+
if (failure)
|
|
11740
|
+
throw new Error(failure);
|
|
11520
11741
|
if (!sawAssistant) {
|
|
11521
11742
|
const fallback = resultEvent && !cursorResultIsError(resultEvent) ? resultEventText(resultEvent) : "";
|
|
11522
11743
|
if (fallback)
|
|
@@ -11558,7 +11779,7 @@ var init_cursor_acp_bridge = __esm({
|
|
|
11558
11779
|
|
|
11559
11780
|
// apps/body/dist/agent-command.js
|
|
11560
11781
|
import { execFile as execFile4, spawn as spawn7 } from "node:child_process";
|
|
11561
|
-
import { accessSync, constants, existsSync as existsSync4, readdirSync } from "node:fs";
|
|
11782
|
+
import { accessSync as accessSync2, constants, existsSync as existsSync4, readdirSync } from "node:fs";
|
|
11562
11783
|
import { readFile as readFile7 } from "node:fs/promises";
|
|
11563
11784
|
import { homedir as homedir6 } from "node:os";
|
|
11564
11785
|
import { delimiter, isAbsolute, join as join4, resolve as resolve7 } from "node:path";
|
|
@@ -11697,7 +11918,7 @@ function executableOnPath(name, env = process.env) {
|
|
|
11697
11918
|
for (const directory of augmentedSearchDirectories(env)) {
|
|
11698
11919
|
const candidate = resolve7(directory, name);
|
|
11699
11920
|
try {
|
|
11700
|
-
|
|
11921
|
+
accessSync2(candidate, constants.X_OK);
|
|
11701
11922
|
return candidate;
|
|
11702
11923
|
} catch {
|
|
11703
11924
|
}
|
|
@@ -11709,7 +11930,7 @@ function requireExecutable(command, env, cwd, missingMessage) {
|
|
|
11709
11930
|
const candidate = pathLike ? resolve7(cwd, command) : executableOnPath(command, env);
|
|
11710
11931
|
if (candidate) {
|
|
11711
11932
|
try {
|
|
11712
|
-
|
|
11933
|
+
accessSync2(candidate, constants.X_OK);
|
|
11713
11934
|
return candidate;
|
|
11714
11935
|
} catch {
|
|
11715
11936
|
}
|
|
@@ -14158,7 +14379,7 @@ var require_websocket = __commonJS({
|
|
|
14158
14379
|
var http = __require("http");
|
|
14159
14380
|
var net2 = __require("net");
|
|
14160
14381
|
var tls = __require("tls");
|
|
14161
|
-
var { randomBytes: randomBytes8, createHash:
|
|
14382
|
+
var { randomBytes: randomBytes8, createHash: createHash13 } = __require("crypto");
|
|
14162
14383
|
var { Duplex, Readable } = __require("stream");
|
|
14163
14384
|
var { URL: URL2 } = __require("url");
|
|
14164
14385
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -14826,7 +15047,7 @@ var require_websocket = __commonJS({
|
|
|
14826
15047
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
14827
15048
|
return;
|
|
14828
15049
|
}
|
|
14829
|
-
const digest =
|
|
15050
|
+
const digest = createHash13("sha1").update(key + GUID).digest("base64");
|
|
14830
15051
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
14831
15052
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
14832
15053
|
return;
|
|
@@ -15195,7 +15416,7 @@ var require_websocket_server = __commonJS({
|
|
|
15195
15416
|
var EventEmitter2 = __require("events");
|
|
15196
15417
|
var http = __require("http");
|
|
15197
15418
|
var { Duplex } = __require("stream");
|
|
15198
|
-
var { createHash:
|
|
15419
|
+
var { createHash: createHash13 } = __require("crypto");
|
|
15199
15420
|
var extension2 = require_extension();
|
|
15200
15421
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
15201
15422
|
var subprotocol2 = require_subprotocol();
|
|
@@ -15502,7 +15723,7 @@ var require_websocket_server = __commonJS({
|
|
|
15502
15723
|
);
|
|
15503
15724
|
}
|
|
15504
15725
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
15505
|
-
const digest =
|
|
15726
|
+
const digest = createHash13("sha1").update(key + GUID).digest("base64");
|
|
15506
15727
|
const headers = [
|
|
15507
15728
|
"HTTP/1.1 101 Switching Protocols",
|
|
15508
15729
|
"Upgrade: websocket",
|
|
@@ -22925,8 +23146,6 @@ import { readFile } from "node:fs/promises";
|
|
|
22925
23146
|
import { createInterface } from "node:readline";
|
|
22926
23147
|
|
|
22927
23148
|
// packages/api-contract/dist/app-connections.js
|
|
22928
|
-
var APP_TRANSPORTS = ["registry-mcp", "squire-api", "squire-browser"];
|
|
22929
|
-
var APP_ROUTES = ["workbench", ...APP_TRANSPORTS];
|
|
22930
23149
|
var APP_KEY_MAX_LENGTH = 63;
|
|
22931
23150
|
var APP_INPUT_MAX_LENGTH = 200;
|
|
22932
23151
|
var SECOND_LEVEL_SUFFIXES = /* @__PURE__ */ new Set(["co", "com", "net", "org", "gov", "edu", "ac"]);
|
|
@@ -23003,108 +23222,11 @@ function squireCallAppKeys(args) {
|
|
|
23003
23222
|
return [...keys].sort();
|
|
23004
23223
|
}
|
|
23005
23224
|
|
|
23006
|
-
// packages/api-contract/dist/connector-adapter.js
|
|
23007
|
-
var CONNECTOR_ADAPTER_DENIED = "connector not found (access denied)";
|
|
23008
|
-
function ownerOnly(offered, action, requester) {
|
|
23009
|
-
if (!offered.includes(action) || requester !== "owner") {
|
|
23010
|
-
return { allowed: false, reason: CONNECTOR_ADAPTER_DENIED };
|
|
23011
|
-
}
|
|
23012
|
-
return { allowed: true };
|
|
23013
|
-
}
|
|
23014
|
-
var SQUIRE_ACTIONS = [
|
|
23015
|
-
"connect",
|
|
23016
|
-
"reconnect",
|
|
23017
|
-
"disconnect",
|
|
23018
|
-
"revoke-grants"
|
|
23019
|
-
];
|
|
23020
|
-
var SQUIRE_CONNECTOR_ADAPTER = {
|
|
23021
|
-
kind: "trusty-squire",
|
|
23022
|
-
actions: SQUIRE_ACTIONS,
|
|
23023
|
-
authorize: (action, requester) => ownerOnly(SQUIRE_ACTIONS, action, requester),
|
|
23024
|
-
workbenchActions: (status) => {
|
|
23025
|
-
switch (status) {
|
|
23026
|
-
case "installing":
|
|
23027
|
-
return ["disconnect"];
|
|
23028
|
-
case "connected":
|
|
23029
|
-
return ["reconnect", "disconnect", "revoke-grants"];
|
|
23030
|
-
case "error":
|
|
23031
|
-
return ["connect", "reconnect", "disconnect"];
|
|
23032
|
-
default:
|
|
23033
|
-
return ["connect"];
|
|
23034
|
-
}
|
|
23035
|
-
},
|
|
23036
|
-
assignmentKinds: (status) => {
|
|
23037
|
-
if (status === "installing")
|
|
23038
|
-
return ["install"];
|
|
23039
|
-
if (status === "disconnected")
|
|
23040
|
-
return ["uninstall"];
|
|
23041
|
-
return [];
|
|
23042
|
-
}
|
|
23043
|
-
};
|
|
23044
|
-
var YOUTUBE_ACTIONS = [
|
|
23045
|
-
"connect",
|
|
23046
|
-
"reconnect",
|
|
23047
|
-
"disconnect"
|
|
23048
|
-
];
|
|
23049
|
-
var YOUTUBE_CONNECTOR_ADAPTER = {
|
|
23050
|
-
kind: "google-youtube",
|
|
23051
|
-
actions: YOUTUBE_ACTIONS,
|
|
23052
|
-
authorize: (action, requester) => ownerOnly(YOUTUBE_ACTIONS, action, requester),
|
|
23053
|
-
workbenchActions: (status) => {
|
|
23054
|
-
switch (status) {
|
|
23055
|
-
case "installing":
|
|
23056
|
-
return ["disconnect"];
|
|
23057
|
-
case "connected":
|
|
23058
|
-
return ["reconnect", "disconnect"];
|
|
23059
|
-
case "error":
|
|
23060
|
-
return ["connect", "reconnect", "disconnect"];
|
|
23061
|
-
default:
|
|
23062
|
-
return ["connect"];
|
|
23063
|
-
}
|
|
23064
|
-
},
|
|
23065
|
-
assignmentKinds: (status) => {
|
|
23066
|
-
if (status === "installing")
|
|
23067
|
-
return ["install"];
|
|
23068
|
-
if (status === "disconnected")
|
|
23069
|
-
return ["uninstall"];
|
|
23070
|
-
if (status === "connected")
|
|
23071
|
-
return ["refresh-google-grant"];
|
|
23072
|
-
return [];
|
|
23073
|
-
}
|
|
23074
|
-
};
|
|
23075
|
-
var ADAPTERS = {
|
|
23076
|
-
"trusty-squire": SQUIRE_CONNECTOR_ADAPTER,
|
|
23077
|
-
"google-youtube": YOUTUBE_CONNECTOR_ADAPTER
|
|
23078
|
-
};
|
|
23079
|
-
function connectorAdapter(kind) {
|
|
23080
|
-
return ADAPTERS[kind];
|
|
23081
|
-
}
|
|
23082
|
-
|
|
23083
23225
|
// packages/api-contract/dist/workbench.js
|
|
23084
23226
|
var CONNECTABLE_CONNECTOR_KINDS = [
|
|
23085
23227
|
"trusty-squire",
|
|
23086
|
-
"tailscale"
|
|
23087
|
-
"google-gmail",
|
|
23088
|
-
"google-calendar",
|
|
23089
|
-
"google-drive",
|
|
23090
|
-
"google-youtube"
|
|
23228
|
+
"tailscale"
|
|
23091
23229
|
];
|
|
23092
|
-
var GOOGLE_TOOL_SCOPES = {
|
|
23093
|
-
"google-gmail": [
|
|
23094
|
-
"https://www.googleapis.com/auth/gmail.send",
|
|
23095
|
-
"https://www.googleapis.com/auth/gmail.readonly",
|
|
23096
|
-
"https://www.googleapis.com/auth/gmail.compose"
|
|
23097
|
-
],
|
|
23098
|
-
"google-calendar": [
|
|
23099
|
-
"https://www.googleapis.com/auth/calendar.events",
|
|
23100
|
-
"https://www.googleapis.com/auth/calendar.readonly"
|
|
23101
|
-
],
|
|
23102
|
-
"google-drive": ["https://www.googleapis.com/auth/drive.readonly"],
|
|
23103
|
-
"google-youtube": [
|
|
23104
|
-
"https://www.googleapis.com/auth/youtube.readonly",
|
|
23105
|
-
"https://www.googleapis.com/auth/yt-analytics.readonly"
|
|
23106
|
-
]
|
|
23107
|
-
};
|
|
23108
23230
|
|
|
23109
23231
|
// apps/body/dist/resource-mcp-facade.js
|
|
23110
23232
|
var RESOURCE_FACADE_FLAG = "--resource-mcp-facade";
|
|
@@ -23603,7 +23725,7 @@ function configureNetworkFamilyDefaults(network = net) {
|
|
|
23603
23725
|
configureNetworkFamilyDefaults();
|
|
23604
23726
|
|
|
23605
23727
|
// apps/body/dist/cli.js
|
|
23606
|
-
import { dirname as
|
|
23728
|
+
import { dirname as dirname26, resolve as resolve39 } from "node:path";
|
|
23607
23729
|
import { stdin as stdin4, stdout as stdout5 } from "node:process";
|
|
23608
23730
|
|
|
23609
23731
|
// node_modules/@clack/core/dist/index.mjs
|
|
@@ -25014,7 +25136,7 @@ var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
|
25014
25136
|
|
|
25015
25137
|
// apps/body/dist/config.js
|
|
25016
25138
|
init_agent_command();
|
|
25017
|
-
import { accessSync as
|
|
25139
|
+
import { accessSync as accessSync3, constants as constants2, existsSync as existsSync5, readFileSync as readFileSync2 } from "node:fs";
|
|
25018
25140
|
import { basename as basename2, dirname as dirname8, resolve as resolve8 } from "node:path";
|
|
25019
25141
|
function firstExisting2(paths) {
|
|
25020
25142
|
for (const p of paths) {
|
|
@@ -25036,7 +25158,7 @@ function commandInRunningBundle(command) {
|
|
|
25036
25158
|
];
|
|
25037
25159
|
for (const candidate of candidates) {
|
|
25038
25160
|
try {
|
|
25039
|
-
|
|
25161
|
+
accessSync3(candidate, constants2.X_OK);
|
|
25040
25162
|
return candidate;
|
|
25041
25163
|
} catch {
|
|
25042
25164
|
}
|
|
@@ -25061,7 +25183,7 @@ function resolveReadonlyMcpCommand(env = process.env) {
|
|
|
25061
25183
|
const configuredBinary = env.BEELINE_READONLY_MCP_BIN;
|
|
25062
25184
|
if (configuredBinary) {
|
|
25063
25185
|
try {
|
|
25064
|
-
|
|
25186
|
+
accessSync3(configuredBinary, constants2.X_OK);
|
|
25065
25187
|
return { command: resolve8(configuredBinary), args: [] };
|
|
25066
25188
|
} catch {
|
|
25067
25189
|
throw new Error(`read-only tools unavailable: BEELINE_READONLY_MCP_BIN is not executable: ${configuredBinary}`);
|
|
@@ -25099,7 +25221,7 @@ function resolveCodegraphCommand(env = process.env) {
|
|
|
25099
25221
|
const configured = env.BEELINE_CODEGRAPH_BIN ?? env.BUZZ_CODEGRAPH_BIN;
|
|
25100
25222
|
if (configured) {
|
|
25101
25223
|
try {
|
|
25102
|
-
|
|
25224
|
+
accessSync3(configured, constants2.X_OK);
|
|
25103
25225
|
return resolve8(configured);
|
|
25104
25226
|
} catch {
|
|
25105
25227
|
return void 0;
|
|
@@ -25153,6 +25275,7 @@ var AGENT_ENV_PASSTHROUGH_NAMES = [
|
|
|
25153
25275
|
"NODE_EXTRA_CA_CERTS",
|
|
25154
25276
|
"NODE_OPTIONS",
|
|
25155
25277
|
"OPENCODE_API_KEY",
|
|
25278
|
+
"GOOGLE_API_KEY",
|
|
25156
25279
|
"http_proxy",
|
|
25157
25280
|
"https_proxy",
|
|
25158
25281
|
"no_proxy",
|
|
@@ -25194,7 +25317,6 @@ var AGENT_ENV_PASSTHROUGH_PREFIXES = [
|
|
|
25194
25317
|
"OPENROUTER_",
|
|
25195
25318
|
"AZURE_",
|
|
25196
25319
|
"AWS_",
|
|
25197
|
-
"GOOGLE_",
|
|
25198
25320
|
"GEMINI_",
|
|
25199
25321
|
"VERTEX_",
|
|
25200
25322
|
"BEDROCK_",
|
|
@@ -25337,7 +25459,7 @@ init_cursor_acp_bridge();
|
|
|
25337
25459
|
init_squire_host();
|
|
25338
25460
|
|
|
25339
25461
|
// apps/body/dist/squire-task-relay.js
|
|
25340
|
-
import { createHash as createHash2, randomUUID as
|
|
25462
|
+
import { createHash as createHash2, randomUUID as randomUUID3 } from "node:crypto";
|
|
25341
25463
|
import { createServer } from "node:http";
|
|
25342
25464
|
import { readFile as readFile8 } from "node:fs/promises";
|
|
25343
25465
|
import { createInterface as createInterface4 } from "node:readline";
|
|
@@ -26017,6 +26139,43 @@ function sessionIds(value, depth = 0) {
|
|
|
26017
26139
|
function redactedSessionId(id) {
|
|
26018
26140
|
return id ? createHash2("sha256").update(id).digest("hex").slice(0, 16) : null;
|
|
26019
26141
|
}
|
|
26142
|
+
function staleLeaseResult(value) {
|
|
26143
|
+
if (!value || typeof value !== "object")
|
|
26144
|
+
return false;
|
|
26145
|
+
const result = value;
|
|
26146
|
+
if (result.isError !== true || !Array.isArray(result.content))
|
|
26147
|
+
return false;
|
|
26148
|
+
const text2 = result.content.find((entry) => entry && typeof entry === "object" && entry.type === "text")?.text;
|
|
26149
|
+
if (!text2)
|
|
26150
|
+
return false;
|
|
26151
|
+
try {
|
|
26152
|
+
const body = JSON.parse(text2);
|
|
26153
|
+
return body.error?.code === "stale_lease";
|
|
26154
|
+
} catch {
|
|
26155
|
+
return false;
|
|
26156
|
+
}
|
|
26157
|
+
}
|
|
26158
|
+
function resultStatus(value, depth = 0) {
|
|
26159
|
+
if (depth > 8 || !value)
|
|
26160
|
+
return void 0;
|
|
26161
|
+
if (typeof value === "string") {
|
|
26162
|
+
if (value.length > 1e5 || !value.trimStart().startsWith("{"))
|
|
26163
|
+
return void 0;
|
|
26164
|
+
try {
|
|
26165
|
+
return resultStatus(JSON.parse(value), depth + 1);
|
|
26166
|
+
} catch {
|
|
26167
|
+
return void 0;
|
|
26168
|
+
}
|
|
26169
|
+
}
|
|
26170
|
+
if (Array.isArray(value))
|
|
26171
|
+
return value.map((item2) => resultStatus(item2, depth + 1)).find(Boolean);
|
|
26172
|
+
if (typeof value !== "object")
|
|
26173
|
+
return void 0;
|
|
26174
|
+
const item = value;
|
|
26175
|
+
if (typeof item.status === "string")
|
|
26176
|
+
return item.status;
|
|
26177
|
+
return Object.values(item).map((entry) => resultStatus(entry, depth + 1)).find(Boolean);
|
|
26178
|
+
}
|
|
26020
26179
|
var SquireTaskRelay = class {
|
|
26021
26180
|
agentId;
|
|
26022
26181
|
roomId;
|
|
@@ -26025,10 +26184,11 @@ var SquireTaskRelay = class {
|
|
|
26025
26184
|
makeClient;
|
|
26026
26185
|
server;
|
|
26027
26186
|
url;
|
|
26028
|
-
token =
|
|
26187
|
+
token = randomUUID3();
|
|
26029
26188
|
active;
|
|
26030
26189
|
task;
|
|
26031
26190
|
leaseTimer;
|
|
26191
|
+
approvalRequestId;
|
|
26032
26192
|
closed = false;
|
|
26033
26193
|
callTail = Promise.resolve();
|
|
26034
26194
|
constructor(agentId, roomId, contextFile, authorize, home = homedir9(), makeClient = (callbacks) => new StdioSquireMcpClient({ scope: { agentId, roomId }, home, processGroup: true, ...callbacks })) {
|
|
@@ -26078,46 +26238,59 @@ var SquireTaskRelay = class {
|
|
|
26078
26238
|
if (this.leaseTimer)
|
|
26079
26239
|
clearTimeout(this.leaseTimer);
|
|
26080
26240
|
this.leaseTimer = void 0;
|
|
26081
|
-
if (this.task && this.task.taskId !== command.rootCommandId)
|
|
26082
|
-
this.retire("task-ended");
|
|
26083
26241
|
this.active = {
|
|
26084
26242
|
roomId: command.roomId,
|
|
26085
26243
|
requestId: command.turnRequestId,
|
|
26086
26244
|
taskId: command.rootCommandId,
|
|
26087
26245
|
generationId
|
|
26088
26246
|
};
|
|
26089
|
-
if (this.task)
|
|
26247
|
+
if (this.task) {
|
|
26248
|
+
this.task.taskId = command.rootCommandId;
|
|
26090
26249
|
this.task.lastRequestId = command.turnRequestId;
|
|
26250
|
+
}
|
|
26091
26251
|
}
|
|
26092
|
-
deactivate(requestId,
|
|
26252
|
+
deactivate(requestId, approvalRequestId) {
|
|
26093
26253
|
if (this.active?.requestId !== requestId)
|
|
26094
26254
|
return;
|
|
26095
|
-
const taskId = this.active.taskId;
|
|
26096
26255
|
this.active = void 0;
|
|
26097
|
-
|
|
26256
|
+
this.approvalRequestId = approvalRequestId;
|
|
26257
|
+
if (approvalRequestId)
|
|
26098
26258
|
return;
|
|
26099
|
-
|
|
26100
|
-
|
|
26259
|
+
this.scheduleIdle();
|
|
26260
|
+
}
|
|
26261
|
+
scheduleIdle() {
|
|
26262
|
+
if (this.leaseTimer)
|
|
26263
|
+
clearTimeout(this.leaseTimer);
|
|
26264
|
+
this.leaseTimer = void 0;
|
|
26265
|
+
if (!this.task || this.approvalRequestId || this.task.pendingApprovals.size)
|
|
26101
26266
|
return;
|
|
26102
|
-
|
|
26267
|
+
const task = this.task;
|
|
26103
26268
|
this.leaseTimer = setTimeout(() => {
|
|
26104
26269
|
this.leaseTimer = void 0;
|
|
26105
|
-
if (!this.active && this.task
|
|
26106
|
-
this.retire("
|
|
26270
|
+
if (!this.active && !this.approvalRequestId && !task.pendingApprovals.size && this.task === task)
|
|
26271
|
+
this.retire("conversation-idle");
|
|
26107
26272
|
}, SQUIRE_TASK_IDLE_LEASE_MS);
|
|
26108
26273
|
this.leaseTimer.unref?.();
|
|
26109
26274
|
}
|
|
26110
26275
|
cancel(requestId) {
|
|
26111
|
-
if (this.active?.requestId !== requestId)
|
|
26276
|
+
if (this.active?.requestId !== requestId && this.approvalRequestId !== requestId && ![...this.task?.pendingApprovals.values() ?? []].some((approval) => approval.requestId === requestId))
|
|
26112
26277
|
return;
|
|
26113
|
-
this.active
|
|
26114
|
-
|
|
26278
|
+
if (this.active?.requestId === requestId)
|
|
26279
|
+
this.active = void 0;
|
|
26280
|
+
if (this.approvalRequestId === requestId)
|
|
26281
|
+
this.approvalRequestId = void 0;
|
|
26282
|
+
for (const [id, approval] of this.task?.pendingApprovals ?? [])
|
|
26283
|
+
if (approval.requestId === requestId)
|
|
26284
|
+
this.task?.pendingApprovals.delete(id);
|
|
26285
|
+
if (!this.active && !this.approvalRequestId)
|
|
26286
|
+
this.scheduleIdle();
|
|
26115
26287
|
}
|
|
26116
26288
|
close() {
|
|
26117
26289
|
if (this.closed)
|
|
26118
26290
|
return;
|
|
26119
26291
|
this.closed = true;
|
|
26120
26292
|
this.active = void 0;
|
|
26293
|
+
this.approvalRequestId = void 0;
|
|
26121
26294
|
this.retire("helper-exit");
|
|
26122
26295
|
this.server?.close();
|
|
26123
26296
|
}
|
|
@@ -26126,6 +26299,7 @@ var SquireTaskRelay = class {
|
|
|
26126
26299
|
console.info("[squire-task]", JSON.stringify({
|
|
26127
26300
|
event,
|
|
26128
26301
|
agentId: this.agentId,
|
|
26302
|
+
conversationId: this.roomId,
|
|
26129
26303
|
taskId: task.taskId,
|
|
26130
26304
|
requestId: this.active?.requestId ?? task.lastRequestId,
|
|
26131
26305
|
squireSessionId: sessionId ?? null,
|
|
@@ -26141,8 +26315,9 @@ var SquireTaskRelay = class {
|
|
|
26141
26315
|
const task = {
|
|
26142
26316
|
taskId,
|
|
26143
26317
|
lastRequestId: this.active?.requestId ?? "",
|
|
26144
|
-
connectionId:
|
|
26318
|
+
connectionId: randomUUID3(),
|
|
26145
26319
|
sessions: /* @__PURE__ */ new Set(),
|
|
26320
|
+
pendingApprovals: /* @__PURE__ */ new Map(),
|
|
26146
26321
|
dead: false
|
|
26147
26322
|
};
|
|
26148
26323
|
task.client = this.makeClient({
|
|
@@ -26155,6 +26330,7 @@ var SquireTaskRelay = class {
|
|
|
26155
26330
|
sessionId: redactedSessionId(task.sessions.values().next().value)
|
|
26156
26331
|
});
|
|
26157
26332
|
task.sessions.clear();
|
|
26333
|
+
task.pendingApprovals.clear();
|
|
26158
26334
|
}
|
|
26159
26335
|
});
|
|
26160
26336
|
this.task = task;
|
|
@@ -26172,6 +26348,7 @@ var SquireTaskRelay = class {
|
|
|
26172
26348
|
});
|
|
26173
26349
|
this.task.client.close();
|
|
26174
26350
|
this.task.sessions.clear();
|
|
26351
|
+
this.task.pendingApprovals.clear();
|
|
26175
26352
|
this.task = void 0;
|
|
26176
26353
|
}
|
|
26177
26354
|
handle(input) {
|
|
@@ -26208,9 +26385,13 @@ var SquireTaskRelay = class {
|
|
|
26208
26385
|
this.log("call-end", task, { method: input.method, source: "cached" });
|
|
26209
26386
|
return task.tools;
|
|
26210
26387
|
}
|
|
26388
|
+
if (input.method === "tools/call" && task.dead && toolName2 !== "operate_start") {
|
|
26389
|
+
this.log("call-refused", task, { reason: "connection-died" });
|
|
26390
|
+
throw new Error("Squire MCP connection died and its browser session is gone; call operate_start");
|
|
26391
|
+
}
|
|
26211
26392
|
if (input.method === "tools/call" && (!safeToolName || requestedIds.some((id) => !task.sessions.has(id)))) {
|
|
26212
26393
|
this.log("call-refused", task, { reason: "session-not-owned" });
|
|
26213
|
-
throw new Error("Squire browser session is no longer owned by this
|
|
26394
|
+
throw new Error("Squire browser session is no longer owned by this conversation; call operate_start");
|
|
26214
26395
|
}
|
|
26215
26396
|
if (input.method === "tools/call" && !await this.authorize({
|
|
26216
26397
|
...active,
|
|
@@ -26234,8 +26415,47 @@ var SquireTaskRelay = class {
|
|
|
26234
26415
|
throw new Error("Squire task ended while the call was running");
|
|
26235
26416
|
if (input.method === "tools/list")
|
|
26236
26417
|
task.tools = result;
|
|
26237
|
-
|
|
26238
|
-
|
|
26418
|
+
if (staleLeaseResult(result)) {
|
|
26419
|
+
for (const id of requestedIds)
|
|
26420
|
+
task.sessions.delete(id);
|
|
26421
|
+
this.releasePendingApprovals(task, requestedIds);
|
|
26422
|
+
this.log("call-error", task, {
|
|
26423
|
+
method: input.method,
|
|
26424
|
+
tool: safeToolName ?? null,
|
|
26425
|
+
reason: "stale-lease",
|
|
26426
|
+
sessionId: redactedSessionId(requestedIds[0])
|
|
26427
|
+
});
|
|
26428
|
+
return { isError: true, content: [{ type: "text", text: JSON.stringify({
|
|
26429
|
+
error: { code: "stale_lease", message: "Squire browser session is gone; call operate_start for a fresh session" }
|
|
26430
|
+
}) }] };
|
|
26431
|
+
}
|
|
26432
|
+
if (safeToolName === "operate_finish" && !(result && typeof result === "object" && result.isError === true)) {
|
|
26433
|
+
for (const id of requestedIds)
|
|
26434
|
+
task.sessions.delete(id);
|
|
26435
|
+
this.releasePendingApprovals(task, requestedIds);
|
|
26436
|
+
} else {
|
|
26437
|
+
for (const id of sessionIds(result))
|
|
26438
|
+
task.sessions.add(id);
|
|
26439
|
+
}
|
|
26440
|
+
const approval = input.method === "tools/call" && squireApprovalFromMcp({ id: 1, method: input.method, params: input.params }, { id: 1, result });
|
|
26441
|
+
if (approval) {
|
|
26442
|
+
const ids = requestedIds.length ? requestedIds : [...task.sessions];
|
|
26443
|
+
const approvalKey = createHash2("sha256").update(approval.approvalId ?? approval.approvalUrl).digest("hex");
|
|
26444
|
+
const status = resultStatus(result);
|
|
26445
|
+
const pending = status === "approval_pending" || status === "pending_approval";
|
|
26446
|
+
if (pending && ids.length) {
|
|
26447
|
+
task.pendingApprovals.set(approvalKey, {
|
|
26448
|
+
requestId: active.requestId,
|
|
26449
|
+
sessionIds: new Set(ids)
|
|
26450
|
+
});
|
|
26451
|
+
this.log("approval-pending", task, {
|
|
26452
|
+
tool: safeToolName ?? null,
|
|
26453
|
+
sessionId: redactedSessionId(ids[0])
|
|
26454
|
+
});
|
|
26455
|
+
} else if (!pending) {
|
|
26456
|
+
task.pendingApprovals.delete(approvalKey);
|
|
26457
|
+
}
|
|
26458
|
+
}
|
|
26239
26459
|
this.log("call-end", task, {
|
|
26240
26460
|
method: input.method,
|
|
26241
26461
|
tool: safeToolName ?? null,
|
|
@@ -26246,6 +26466,7 @@ var SquireTaskRelay = class {
|
|
|
26246
26466
|
if (error instanceof Error && /timed out/.test(error.message)) {
|
|
26247
26467
|
task.dead = true;
|
|
26248
26468
|
task.sessions.clear();
|
|
26469
|
+
task.pendingApprovals.clear();
|
|
26249
26470
|
task.client.close();
|
|
26250
26471
|
}
|
|
26251
26472
|
this.log("call-error", task, {
|
|
@@ -26253,9 +26474,19 @@ var SquireTaskRelay = class {
|
|
|
26253
26474
|
tool: safeToolName ?? null,
|
|
26254
26475
|
sessionId: redactedSessionId(requestedIds[0] ?? task.sessions.values().next().value)
|
|
26255
26476
|
});
|
|
26477
|
+
if (task.dead)
|
|
26478
|
+
throw new Error("Squire MCP connection died and its browser session is gone; call operate_start");
|
|
26256
26479
|
throw error;
|
|
26257
26480
|
}
|
|
26258
26481
|
}
|
|
26482
|
+
releasePendingApprovals(task, sessionIdsToRelease) {
|
|
26483
|
+
for (const [id, approval] of task.pendingApprovals) {
|
|
26484
|
+
for (const sessionId of sessionIdsToRelease)
|
|
26485
|
+
approval.sessionIds.delete(sessionId);
|
|
26486
|
+
if (!approval.sessionIds.size)
|
|
26487
|
+
task.pendingApprovals.delete(id);
|
|
26488
|
+
}
|
|
26489
|
+
}
|
|
26259
26490
|
};
|
|
26260
26491
|
function runSquireTaskProxy(env = process.env) {
|
|
26261
26492
|
const url = env.BEELINE_SQUIRE_RELAY_URL;
|
|
@@ -26310,7 +26541,7 @@ function isAllowedAgentModelConfigCategory(category, id) {
|
|
|
26310
26541
|
}
|
|
26311
26542
|
|
|
26312
26543
|
// apps/body/dist/model-config.js
|
|
26313
|
-
import { lstatSync
|
|
26544
|
+
import { lstatSync, readFileSync as readFileSync3 } from "node:fs";
|
|
26314
26545
|
import { basename as basename3, resolve as resolve9 } from "node:path";
|
|
26315
26546
|
var GROK_SESSION_MODEL_AXIS_ID = "beeline:grok-session-model";
|
|
26316
26547
|
var GROK_LAUNCH_EFFORT_AXIS_ID = "beeline:grok-launch-reasoning-effort";
|
|
@@ -26486,7 +26717,7 @@ function credentialedPiCustomProviders(env) {
|
|
|
26486
26717
|
return held;
|
|
26487
26718
|
const path = resolve9(agentDir, "models.json");
|
|
26488
26719
|
try {
|
|
26489
|
-
const stats =
|
|
26720
|
+
const stats = lstatSync(path);
|
|
26490
26721
|
if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1 || stats.size > 1048576) {
|
|
26491
26722
|
return held;
|
|
26492
26723
|
}
|
|
@@ -27923,519 +28154,12 @@ async function syncAgentModelCatalog(input) {
|
|
|
27923
28154
|
}
|
|
27924
28155
|
}
|
|
27925
28156
|
|
|
27926
|
-
// apps/body/dist/connector-google.js
|
|
27927
|
-
import { mkdirSync as mkdirSync2, writeFileSync } from "node:fs";
|
|
27928
|
-
import { dirname as dirname9, join as join5 } from "node:path";
|
|
27929
|
-
|
|
27930
|
-
// apps/body/dist/google-workspace-client.js
|
|
27931
|
-
function credentialsTokenSource(credentials) {
|
|
27932
|
-
return {
|
|
27933
|
-
accessToken: () => Promise.resolve(credentials.accessToken),
|
|
27934
|
-
accountEmail: credentials.accountEmail ? () => credentials.accountEmail : void 0
|
|
27935
|
-
};
|
|
27936
|
-
}
|
|
27937
|
-
var googleOAuthTokenTransport = {
|
|
27938
|
-
async request(method, url, body) {
|
|
27939
|
-
const fields = body && typeof body === "object" ? body : {};
|
|
27940
|
-
const response = await fetch(url, {
|
|
27941
|
-
method,
|
|
27942
|
-
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
27943
|
-
body: new URLSearchParams(fields).toString()
|
|
27944
|
-
});
|
|
27945
|
-
let json = null;
|
|
27946
|
-
const text2 = await response.text();
|
|
27947
|
-
if (text2) {
|
|
27948
|
-
try {
|
|
27949
|
-
json = JSON.parse(text2);
|
|
27950
|
-
} catch {
|
|
27951
|
-
json = { raw: text2 };
|
|
27952
|
-
}
|
|
27953
|
-
}
|
|
27954
|
-
return { status: response.status, json };
|
|
27955
|
-
}
|
|
27956
|
-
};
|
|
27957
|
-
async function refreshGoogleAccessToken(credentials, clientId, clientSecret, transport = googleOAuthTokenTransport) {
|
|
27958
|
-
if (!credentials.refreshToken) {
|
|
27959
|
-
throw new GoogleApiError(401, "Google grant has no refresh token; reconnect Google Workspace");
|
|
27960
|
-
}
|
|
27961
|
-
const response = await transport.request("POST", "https://oauth2.googleapis.com/token", {
|
|
27962
|
-
client_id: clientId,
|
|
27963
|
-
client_secret: clientSecret,
|
|
27964
|
-
refresh_token: credentials.refreshToken,
|
|
27965
|
-
grant_type: "refresh_token"
|
|
27966
|
-
});
|
|
27967
|
-
if (response.status >= 300) {
|
|
27968
|
-
throw new GoogleApiError(response.status, "Google refused to refresh the access token");
|
|
27969
|
-
}
|
|
27970
|
-
const payload = response.json;
|
|
27971
|
-
if (!payload.access_token) {
|
|
27972
|
-
throw new GoogleApiError(401, "Google refresh returned no access token");
|
|
27973
|
-
}
|
|
27974
|
-
return {
|
|
27975
|
-
...credentials,
|
|
27976
|
-
accessToken: payload.access_token,
|
|
27977
|
-
expiresAt: typeof payload.expires_in === "number" ? Date.now() + payload.expires_in * 1e3 : void 0
|
|
27978
|
-
};
|
|
27979
|
-
}
|
|
27980
|
-
function refreshableTokenSource(credentials, clientId, clientSecret, transport = googleOAuthTokenTransport) {
|
|
27981
|
-
let current = credentials;
|
|
27982
|
-
return {
|
|
27983
|
-
async accessToken() {
|
|
27984
|
-
const stale = current.expiresAt !== void 0 && current.expiresAt <= Date.now() + 3e4;
|
|
27985
|
-
if (stale && clientId && clientSecret && current.refreshToken) {
|
|
27986
|
-
current = await refreshGoogleAccessToken(current, clientId, clientSecret, transport);
|
|
27987
|
-
}
|
|
27988
|
-
return current.accessToken;
|
|
27989
|
-
},
|
|
27990
|
-
accountEmail: current.accountEmail ? () => current.accountEmail : void 0
|
|
27991
|
-
};
|
|
27992
|
-
}
|
|
27993
|
-
var defaultGoogleApiTransport = {
|
|
27994
|
-
async request(method, url, body, headers) {
|
|
27995
|
-
const response = await fetch(url, {
|
|
27996
|
-
method,
|
|
27997
|
-
headers: {
|
|
27998
|
-
"content-type": "application/json",
|
|
27999
|
-
...headers
|
|
28000
|
-
},
|
|
28001
|
-
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
28002
|
-
});
|
|
28003
|
-
let json = null;
|
|
28004
|
-
const text2 = await response.text();
|
|
28005
|
-
if (text2) {
|
|
28006
|
-
try {
|
|
28007
|
-
json = JSON.parse(text2);
|
|
28008
|
-
} catch {
|
|
28009
|
-
json = { raw: text2 };
|
|
28010
|
-
}
|
|
28011
|
-
}
|
|
28012
|
-
return { status: response.status, json };
|
|
28013
|
-
}
|
|
28014
|
-
};
|
|
28015
|
-
var GoogleApiError = class extends Error {
|
|
28016
|
-
status;
|
|
28017
|
-
detail;
|
|
28018
|
-
constructor(status, detail) {
|
|
28019
|
-
super(`Google API ${status}: ${detail}`);
|
|
28020
|
-
this.status = status;
|
|
28021
|
-
this.detail = detail;
|
|
28022
|
-
}
|
|
28023
|
-
};
|
|
28024
|
-
var MAX_RESULTS = 25;
|
|
28025
|
-
function assertOk(status, json) {
|
|
28026
|
-
if (status >= 200 && status < 300)
|
|
28027
|
-
return;
|
|
28028
|
-
const detail = json && typeof json === "object" && "error" in json ? JSON.stringify(json.error) : `HTTP ${status}`;
|
|
28029
|
-
throw new GoogleApiError(status, detail);
|
|
28030
|
-
}
|
|
28031
|
-
var YOUTUBE_ANALYTICS_OWNER_LIMIT = "YouTube Analytics requires the Google account that owns the channel, not a manager.";
|
|
28032
|
-
function defaultAnalyticsDateRange(days = 28, now2 = /* @__PURE__ */ new Date()) {
|
|
28033
|
-
const end = new Date(Date.UTC(now2.getUTCFullYear(), now2.getUTCMonth(), now2.getUTCDate()));
|
|
28034
|
-
const start = new Date(end);
|
|
28035
|
-
start.setUTCDate(start.getUTCDate() - days);
|
|
28036
|
-
return { startDate: start.toISOString().slice(0, 10), endDate: end.toISOString().slice(0, 10) };
|
|
28037
|
-
}
|
|
28038
|
-
function rfc822(input) {
|
|
28039
|
-
return `To: ${input.to}\r
|
|
28040
|
-
Subject: ${input.subject}\r
|
|
28041
|
-
Content-Type: text/plain; charset="UTF-8"\r
|
|
28042
|
-
\r
|
|
28043
|
-
${input.body}`;
|
|
28044
|
-
}
|
|
28045
|
-
function googleWorkspaceClient(tokenSource, transport = defaultGoogleApiTransport) {
|
|
28046
|
-
const authorized = {
|
|
28047
|
-
async request(method, url, body) {
|
|
28048
|
-
const token = await tokenSource.accessToken();
|
|
28049
|
-
const response = await transport.request(method, url, body, {
|
|
28050
|
-
authorization: `Bearer ${token}`
|
|
28051
|
-
});
|
|
28052
|
-
if (response.status === 401) {
|
|
28053
|
-
throw new GoogleApiError(401, "access token rejected; reconnect the Google tool");
|
|
28054
|
-
}
|
|
28055
|
-
return response;
|
|
28056
|
-
}
|
|
28057
|
-
};
|
|
28058
|
-
const gmailFetch = async (path) => {
|
|
28059
|
-
const { status, json } = await authorized.request("GET", `https://gmail.googleapis.com/gmail/v1/users/me${path}`);
|
|
28060
|
-
assertOk(status, json);
|
|
28061
|
-
return json;
|
|
28062
|
-
};
|
|
28063
|
-
return {
|
|
28064
|
-
gmail: {
|
|
28065
|
-
async listMessages(query) {
|
|
28066
|
-
const params = new URLSearchParams({ maxResults: String(MAX_RESULTS) });
|
|
28067
|
-
if (query)
|
|
28068
|
-
params.set("q", query);
|
|
28069
|
-
const { status, json } = await authorized.request("GET", `https://gmail.googleapis.com/gmail/v1/users/me/messages?${params}`);
|
|
28070
|
-
assertOk(status, json);
|
|
28071
|
-
const messages = json.messages ?? [];
|
|
28072
|
-
return messages.map((entry) => ({ id: entry.id, snippet: entry.snippet }));
|
|
28073
|
-
},
|
|
28074
|
-
async getMessage(id) {
|
|
28075
|
-
const message = await gmailFetch(`/messages/${encodeURIComponent(id)}?format=metadata`);
|
|
28076
|
-
const snippet = typeof message.snippet === "string" ? message.snippet : void 0;
|
|
28077
|
-
const payload = message.payload;
|
|
28078
|
-
const subject = payload?.headers?.find((header) => header.name === "Subject")?.value;
|
|
28079
|
-
const bodyText = payload?.body?.data !== void 0 ? Buffer.from(payload.body.data, "base64url").toString("utf8") : void 0;
|
|
28080
|
-
return { id, snippet: subject ?? snippet, body: bodyText };
|
|
28081
|
-
},
|
|
28082
|
-
async createDraft(input) {
|
|
28083
|
-
const { status, json } = await authorized.request("POST", "https://gmail.googleapis.com/gmail/v1/users/me/drafts", { message: { raw: Buffer.from(rfc822(input), "utf8").toString("base64url") } });
|
|
28084
|
-
assertOk(status, json);
|
|
28085
|
-
return { id: String(json.id) };
|
|
28086
|
-
},
|
|
28087
|
-
async sendMessage(input) {
|
|
28088
|
-
const raw = Buffer.from(rfc822(input), "utf8").toString("base64url");
|
|
28089
|
-
const { status, json } = await authorized.request("POST", "https://gmail.googleapis.com/gmail/v1/users/me/messages/send", { raw });
|
|
28090
|
-
assertOk(status, json);
|
|
28091
|
-
return { id: String(json.id) };
|
|
28092
|
-
}
|
|
28093
|
-
},
|
|
28094
|
-
calendar: {
|
|
28095
|
-
async listEvents(input) {
|
|
28096
|
-
const params = new URLSearchParams({
|
|
28097
|
-
maxResults: String(input?.maxResults ?? MAX_RESULTS),
|
|
28098
|
-
singleEvents: "true",
|
|
28099
|
-
orderBy: "startTime",
|
|
28100
|
-
timeMin: (/* @__PURE__ */ new Date()).toISOString()
|
|
28101
|
-
});
|
|
28102
|
-
const { status, json } = await authorized.request("GET", `https://www.googleapis.com/calendar/v3/calendars/primary/events?${params}`);
|
|
28103
|
-
assertOk(status, json);
|
|
28104
|
-
const events = json.items ?? [];
|
|
28105
|
-
return events.map((event) => ({
|
|
28106
|
-
id: String(event.id),
|
|
28107
|
-
summary: typeof event.summary === "string" ? event.summary : void 0,
|
|
28108
|
-
start: event.start?.dateTime,
|
|
28109
|
-
end: event.end?.dateTime
|
|
28110
|
-
}));
|
|
28111
|
-
},
|
|
28112
|
-
async createEvent(input) {
|
|
28113
|
-
const { status, json } = await authorized.request("POST", `https://www.googleapis.com/calendar/v3/calendars/${encodeURIComponent(input.calendarId ?? "primary")}/events`, {
|
|
28114
|
-
summary: input.summary,
|
|
28115
|
-
...input.description ? { description: input.description } : {},
|
|
28116
|
-
start: { dateTime: input.start },
|
|
28117
|
-
end: { dateTime: input.end }
|
|
28118
|
-
});
|
|
28119
|
-
assertOk(status, json);
|
|
28120
|
-
const event = json;
|
|
28121
|
-
return { id: event.id, ...event.htmlLink ? { htmlLink: event.htmlLink } : {} };
|
|
28122
|
-
}
|
|
28123
|
-
},
|
|
28124
|
-
drive: {
|
|
28125
|
-
async listFiles() {
|
|
28126
|
-
const params = new URLSearchParams({
|
|
28127
|
-
q: "trashed = false",
|
|
28128
|
-
pageSize: String(MAX_RESULTS),
|
|
28129
|
-
fields: "files(id,name,mimeType)"
|
|
28130
|
-
});
|
|
28131
|
-
const { status, json } = await authorized.request("GET", `https://www.googleapis.com/drive/v3/files?${params}`);
|
|
28132
|
-
assertOk(status, json);
|
|
28133
|
-
return (json.files ?? []).map((file) => ({
|
|
28134
|
-
id: String(file.id),
|
|
28135
|
-
name: typeof file.name === "string" ? file.name : void 0,
|
|
28136
|
-
mimeType: typeof file.mimeType === "string" ? file.mimeType : void 0
|
|
28137
|
-
}));
|
|
28138
|
-
},
|
|
28139
|
-
async searchFiles(query) {
|
|
28140
|
-
const params = new URLSearchParams({
|
|
28141
|
-
q: `name contains '${query.replace(/'/g, "\\'")}' and trashed = false`,
|
|
28142
|
-
pageSize: String(MAX_RESULTS),
|
|
28143
|
-
fields: "files(id,name,mimeType)"
|
|
28144
|
-
});
|
|
28145
|
-
const { status, json } = await authorized.request("GET", `https://www.googleapis.com/drive/v3/files?${params}`);
|
|
28146
|
-
assertOk(status, json);
|
|
28147
|
-
return (json.files ?? []).map((file) => ({
|
|
28148
|
-
id: String(file.id),
|
|
28149
|
-
name: typeof file.name === "string" ? file.name : void 0,
|
|
28150
|
-
mimeType: typeof file.mimeType === "string" ? file.mimeType : void 0
|
|
28151
|
-
}));
|
|
28152
|
-
},
|
|
28153
|
-
async readFile(fileId) {
|
|
28154
|
-
const meta = await authorized.request("GET", `https://www.googleapis.com/drive/v3/files/${encodeURIComponent(fileId)}?fields=id,name`);
|
|
28155
|
-
assertOk(meta.status, meta.json);
|
|
28156
|
-
const content = await authorized.request("GET", `https://www.googleapis.com/drive/v3/files/${encodeURIComponent(fileId)}?alt=media`);
|
|
28157
|
-
assertOk(content.status, content.json);
|
|
28158
|
-
const body = content.json;
|
|
28159
|
-
return {
|
|
28160
|
-
id: fileId,
|
|
28161
|
-
name: meta.json.name,
|
|
28162
|
-
content: body.raw ?? JSON.stringify(content.json)
|
|
28163
|
-
};
|
|
28164
|
-
}
|
|
28165
|
-
},
|
|
28166
|
-
youtube: {
|
|
28167
|
-
async getChannel(mine = true) {
|
|
28168
|
-
const params = new URLSearchParams({
|
|
28169
|
-
part: "snippet,statistics",
|
|
28170
|
-
maxResults: "1",
|
|
28171
|
-
...mine ? { mine: "true" } : {}
|
|
28172
|
-
});
|
|
28173
|
-
const { status, json } = await authorized.request("GET", `https://www.googleapis.com/youtube/v3/channels?${params}`);
|
|
28174
|
-
assertOk(status, json);
|
|
28175
|
-
const item = (json.items ?? [])[0];
|
|
28176
|
-
if (!item)
|
|
28177
|
-
throw new GoogleApiError(404, "no YouTube channel on this Google account");
|
|
28178
|
-
const snippet = item.snippet ?? {};
|
|
28179
|
-
const statistics = item.statistics ?? {};
|
|
28180
|
-
return {
|
|
28181
|
-
id: String(item.id),
|
|
28182
|
-
...typeof snippet.title === "string" ? { title: snippet.title } : {},
|
|
28183
|
-
...typeof snippet.customUrl === "string" ? { handle: snippet.customUrl } : {},
|
|
28184
|
-
...typeof statistics.subscriberCount === "string" ? { subscriberCount: statistics.subscriberCount } : {}
|
|
28185
|
-
};
|
|
28186
|
-
},
|
|
28187
|
-
async listVideos() {
|
|
28188
|
-
const params = new URLSearchParams({
|
|
28189
|
-
part: "snippet",
|
|
28190
|
-
forMine: "true",
|
|
28191
|
-
type: "video",
|
|
28192
|
-
maxResults: String(MAX_RESULTS)
|
|
28193
|
-
});
|
|
28194
|
-
const { status, json } = await authorized.request("GET", `https://www.googleapis.com/youtube/v3/search?${params}`);
|
|
28195
|
-
assertOk(status, json);
|
|
28196
|
-
return (json.items ?? []).map((item) => ({
|
|
28197
|
-
videoId: String(item.id?.videoId ?? item.id),
|
|
28198
|
-
title: item.snippet?.title
|
|
28199
|
-
}));
|
|
28200
|
-
},
|
|
28201
|
-
async getVideo(videoId) {
|
|
28202
|
-
const params = new URLSearchParams({
|
|
28203
|
-
part: "snippet,statistics",
|
|
28204
|
-
id: videoId
|
|
28205
|
-
});
|
|
28206
|
-
const { status, json } = await authorized.request("GET", `https://www.googleapis.com/youtube/v3/videos?${params}`);
|
|
28207
|
-
assertOk(status, json);
|
|
28208
|
-
const item = (json.items ?? [])[0];
|
|
28209
|
-
if (!item)
|
|
28210
|
-
throw new GoogleApiError(404, `video ${videoId} was not found`);
|
|
28211
|
-
const snippet = item.snippet ?? {};
|
|
28212
|
-
const statistics = item.statistics ?? {};
|
|
28213
|
-
return {
|
|
28214
|
-
id: String(item.id),
|
|
28215
|
-
...typeof snippet.title === "string" ? { title: snippet.title } : {},
|
|
28216
|
-
...typeof snippet.description === "string" ? { description: snippet.description } : {},
|
|
28217
|
-
...typeof statistics.viewCount === "string" ? { viewCount: statistics.viewCount } : {}
|
|
28218
|
-
};
|
|
28219
|
-
},
|
|
28220
|
-
async listPlaylists(mine = true) {
|
|
28221
|
-
const params = new URLSearchParams({
|
|
28222
|
-
part: "snippet",
|
|
28223
|
-
maxResults: String(MAX_RESULTS),
|
|
28224
|
-
...mine ? { mine: "true" } : {}
|
|
28225
|
-
});
|
|
28226
|
-
const { status, json } = await authorized.request("GET", `https://www.googleapis.com/youtube/v3/playlists?${params}`);
|
|
28227
|
-
assertOk(status, json);
|
|
28228
|
-
return (json.items ?? []).map((item) => ({
|
|
28229
|
-
id: String(item.id),
|
|
28230
|
-
title: item.snippet?.title
|
|
28231
|
-
}));
|
|
28232
|
-
},
|
|
28233
|
-
async listPlaylistItems(playlistId) {
|
|
28234
|
-
const params = new URLSearchParams({
|
|
28235
|
-
part: "snippet",
|
|
28236
|
-
maxResults: String(MAX_RESULTS),
|
|
28237
|
-
playlistId
|
|
28238
|
-
});
|
|
28239
|
-
const { status, json } = await authorized.request("GET", `https://www.googleapis.com/youtube/v3/playlistItems?${params}`);
|
|
28240
|
-
assertOk(status, json);
|
|
28241
|
-
return (json.items ?? []).map((item) => ({
|
|
28242
|
-
videoId: String(item.snippet?.resourceId?.videoId ?? item.id),
|
|
28243
|
-
title: item.snippet?.title
|
|
28244
|
-
}));
|
|
28245
|
-
},
|
|
28246
|
-
async getTranscript(videoId) {
|
|
28247
|
-
const params = new URLSearchParams({ lang: "en", v: videoId });
|
|
28248
|
-
const { status, json } = await authorized.request("GET", `https://video.google.com/timedtext?${params}`);
|
|
28249
|
-
if (status < 200 || status >= 300) {
|
|
28250
|
-
throw new GoogleApiError(status, `no caption track could be fetched for ${videoId} (timedtext ${status})`);
|
|
28251
|
-
}
|
|
28252
|
-
const raw = json.raw ?? "";
|
|
28253
|
-
const transcript = raw.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
28254
|
-
if (!transcript) {
|
|
28255
|
-
throw new GoogleApiError(404, `video ${videoId} has no fetchable captions`);
|
|
28256
|
-
}
|
|
28257
|
-
return { videoId, transcript };
|
|
28258
|
-
},
|
|
28259
|
-
async analyticsQuery(input) {
|
|
28260
|
-
const range = input.startDate && input.endDate ? { startDate: input.startDate, endDate: input.endDate } : defaultAnalyticsDateRange();
|
|
28261
|
-
const params = new URLSearchParams({
|
|
28262
|
-
ids: "channel==MINE",
|
|
28263
|
-
startDate: range.startDate,
|
|
28264
|
-
endDate: range.endDate,
|
|
28265
|
-
metrics: input.metrics
|
|
28266
|
-
});
|
|
28267
|
-
if (input.dimensions)
|
|
28268
|
-
params.set("dimensions", input.dimensions);
|
|
28269
|
-
if (input.filters)
|
|
28270
|
-
params.set("filters", input.filters);
|
|
28271
|
-
if (input.sort)
|
|
28272
|
-
params.set("sort", input.sort);
|
|
28273
|
-
if (input.maxResults)
|
|
28274
|
-
params.set("maxResults", String(input.maxResults));
|
|
28275
|
-
const { status, json } = await authorized.request("GET", `https://youtubeanalytics.googleapis.com/v2/reports?${params}`);
|
|
28276
|
-
if (status === 403) {
|
|
28277
|
-
throw new GoogleApiError(403, YOUTUBE_ANALYTICS_OWNER_LIMIT);
|
|
28278
|
-
}
|
|
28279
|
-
assertOk(status, json);
|
|
28280
|
-
const report = json;
|
|
28281
|
-
const columns = (report.columnHeaders ?? []).map((header) => header.name);
|
|
28282
|
-
const results = (report.rows ?? []).map((row) => {
|
|
28283
|
-
const record6 = {};
|
|
28284
|
-
columns.forEach((column, index) => {
|
|
28285
|
-
record6[column] = row[index];
|
|
28286
|
-
});
|
|
28287
|
-
return record6;
|
|
28288
|
-
});
|
|
28289
|
-
return {
|
|
28290
|
-
startDate: range.startDate,
|
|
28291
|
-
endDate: range.endDate,
|
|
28292
|
-
columns,
|
|
28293
|
-
results,
|
|
28294
|
-
totalRows: results.length
|
|
28295
|
-
};
|
|
28296
|
-
}
|
|
28297
|
-
},
|
|
28298
|
-
async verify() {
|
|
28299
|
-
try {
|
|
28300
|
-
const { status, json } = await authorized.request("GET", "https://www.googleapis.com/oauth2/v3/userinfo");
|
|
28301
|
-
if (status === 401)
|
|
28302
|
-
return { ok: false, reason: "Google rejected the access token" };
|
|
28303
|
-
assertOk(status, json);
|
|
28304
|
-
const email = json.email;
|
|
28305
|
-
return { ok: true, ...email ? { account: email } : {} };
|
|
28306
|
-
} catch (error) {
|
|
28307
|
-
return {
|
|
28308
|
-
ok: false,
|
|
28309
|
-
reason: error instanceof Error ? error.message : String(error)
|
|
28310
|
-
};
|
|
28311
|
-
}
|
|
28312
|
-
}
|
|
28313
|
-
};
|
|
28314
|
-
}
|
|
28315
|
-
|
|
28316
|
-
// apps/body/dist/connector-google.js
|
|
28317
|
-
function isGoogleToolConnectorType(type) {
|
|
28318
|
-
return Object.hasOwn(GOOGLE_TOOL_SCOPES, type);
|
|
28319
|
-
}
|
|
28320
|
-
function manualGoogleCredentialsSearchPaths(home) {
|
|
28321
|
-
return [join5(home, "google-credentials.json")];
|
|
28322
|
-
}
|
|
28323
|
-
function persistManualGoogleCredentials(home, credentials) {
|
|
28324
|
-
const path = manualGoogleCredentialsSearchPaths(home)[0];
|
|
28325
|
-
mkdirSync2(dirname9(path), { recursive: true, mode: 448 });
|
|
28326
|
-
writeFileSync(path, `${JSON.stringify({
|
|
28327
|
-
accessToken: credentials.accessToken,
|
|
28328
|
-
...credentials.expiresAt ? { expiresAt: credentials.expiresAt } : {},
|
|
28329
|
-
...credentials.accountEmail ? { accountEmail: credentials.accountEmail } : {},
|
|
28330
|
-
...credentials.scopes ? { scopes: credentials.scopes } : {}
|
|
28331
|
-
})}
|
|
28332
|
-
`, { encoding: "utf8", mode: 384 });
|
|
28333
|
-
return path;
|
|
28334
|
-
}
|
|
28335
|
-
var step2 = (label, status, extra) => ({
|
|
28336
|
-
label,
|
|
28337
|
-
status,
|
|
28338
|
-
...extra
|
|
28339
|
-
});
|
|
28340
|
-
function outputTail(text2, maxChars = 800) {
|
|
28341
|
-
const trimmed = text2.trim();
|
|
28342
|
-
return trimmed.length <= maxChars ? trimmed : `\u2026${trimmed.slice(-maxChars)}`;
|
|
28343
|
-
}
|
|
28344
|
-
async function installGoogleTool(options) {
|
|
28345
|
-
const steps2 = [step2("helper reached", "done")];
|
|
28346
|
-
const emit = () => options.onProgress?.([...steps2]);
|
|
28347
|
-
const push = (next) => {
|
|
28348
|
-
steps2.push(next);
|
|
28349
|
-
emit();
|
|
28350
|
-
};
|
|
28351
|
-
const fail = (label, reason, output) => {
|
|
28352
|
-
push(step2(label, "failed", { reason, ...output ? { output } : {} }));
|
|
28353
|
-
return { status: "error", steps: steps2, errorMessage: reason };
|
|
28354
|
-
};
|
|
28355
|
-
emit();
|
|
28356
|
-
if (!isGoogleToolConnectorType(options.connectorType)) {
|
|
28357
|
-
return fail("connector type", `${options.connectorType} is not a Google tool connector`);
|
|
28358
|
-
}
|
|
28359
|
-
push(step2("Google credentials resolved", "running", { output: "resolving\u2026" }));
|
|
28360
|
-
const resolved = options.resolvedCredentials ? await options.resolvedCredentials : options.resolveCredentials ? await options.resolveCredentials() : { source: "pending", reason: "waiting for Google sign-in" };
|
|
28361
|
-
if (!("credentials" in resolved)) {
|
|
28362
|
-
const reason = resolved.reason;
|
|
28363
|
-
steps2[1] = step2("Google credentials resolved", resolved.source === "pending" ? "running" : "failed", { ...resolved.source === "error" ? { reason } : {}, output: outputTail(reason) });
|
|
28364
|
-
emit();
|
|
28365
|
-
return resolved.source === "pending" ? { status: "installing", steps: steps2 } : { status: "error", steps: steps2, errorMessage: reason };
|
|
28366
|
-
}
|
|
28367
|
-
steps2[1] = step2("Google credentials resolved", "done", {
|
|
28368
|
-
output: "Google sign-in completed through Beeline"
|
|
28369
|
-
});
|
|
28370
|
-
emit();
|
|
28371
|
-
const missing = GOOGLE_TOOL_SCOPES[options.connectorType].filter((scope) => !resolved.credentials.scopes?.includes(scope));
|
|
28372
|
-
if (missing.length)
|
|
28373
|
-
return fail("tools enabled", `Google did not grant ${options.connectorType} permission`);
|
|
28374
|
-
const client = options.client ?? googleWorkspaceClient(refreshableTokenSource(resolved.credentials, options.env?.BEELINE_GOOGLE_CLIENT_ID, options.env?.BEELINE_GOOGLE_CLIENT_SECRET));
|
|
28375
|
-
push(step2("authorized with Google", "running", { output: "verifying the grant with Google\u2026" }));
|
|
28376
|
-
const verify = await client.verify();
|
|
28377
|
-
if (!verify.ok) {
|
|
28378
|
-
return fail("authorized with Google", verify.reason, outputTail(verify.reason));
|
|
28379
|
-
}
|
|
28380
|
-
steps2[2] = step2("authorized with Google", "done", {
|
|
28381
|
-
...verify.account ? { output: `signed in as ${verify.account}` } : {}
|
|
28382
|
-
});
|
|
28383
|
-
emit();
|
|
28384
|
-
push(step2("tools enabled", "running", { output: "verifying this Google tool\u2026" }));
|
|
28385
|
-
try {
|
|
28386
|
-
switch (options.connectorType) {
|
|
28387
|
-
case "google-gmail":
|
|
28388
|
-
await client.gmail.listMessages();
|
|
28389
|
-
break;
|
|
28390
|
-
case "google-calendar":
|
|
28391
|
-
await client.calendar.listEvents({ maxResults: 1 });
|
|
28392
|
-
break;
|
|
28393
|
-
case "google-drive":
|
|
28394
|
-
await client.drive.searchFiles("");
|
|
28395
|
-
break;
|
|
28396
|
-
case "google-youtube":
|
|
28397
|
-
await client.youtube.listVideos();
|
|
28398
|
-
break;
|
|
28399
|
-
}
|
|
28400
|
-
} catch (error) {
|
|
28401
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
28402
|
-
steps2[3] = step2("tools enabled", "failed", { reason, output: outputTail(reason) });
|
|
28403
|
-
emit();
|
|
28404
|
-
return { status: "error", steps: steps2, errorMessage: reason };
|
|
28405
|
-
}
|
|
28406
|
-
steps2[3] = step2("tools enabled", "done", {
|
|
28407
|
-
output: `${GOOGLE_TOOL_SCOPES[options.connectorType].length} Google scopes granted; tool verified`
|
|
28408
|
-
});
|
|
28409
|
-
emit();
|
|
28410
|
-
if (options.connectorType === "google-youtube")
|
|
28411
|
-
persistManualGoogleCredentials(options.home, resolved.credentials);
|
|
28412
|
-
return {
|
|
28413
|
-
status: "connected",
|
|
28414
|
-
steps: steps2,
|
|
28415
|
-
...verify.account ? { signedInAs: verify.account } : {}
|
|
28416
|
-
};
|
|
28417
|
-
}
|
|
28418
|
-
|
|
28419
|
-
// apps/body/dist/connector-adapters.js
|
|
28420
|
-
import { unlinkSync } from "node:fs";
|
|
28421
|
-
function isAdaptedYoutube(type) {
|
|
28422
|
-
return type !== void 0 && connectorAdapter(type)?.kind === "google-youtube";
|
|
28423
|
-
}
|
|
28424
|
-
function clearYoutubeGrant(home, log2) {
|
|
28425
|
-
try {
|
|
28426
|
-
unlinkSync(manualGoogleCredentialsSearchPaths(home)[0]);
|
|
28427
|
-
} catch (error) {
|
|
28428
|
-
if (error.code !== "ENOENT")
|
|
28429
|
-
log2(`could not clear YouTube grant: ${error instanceof Error ? error.message : String(error)}`);
|
|
28430
|
-
}
|
|
28431
|
-
}
|
|
28432
|
-
|
|
28433
28157
|
// apps/body/dist/connector-tailscale.js
|
|
28434
28158
|
import { execFile as execFile6 } from "node:child_process";
|
|
28435
|
-
import { randomUUID as
|
|
28159
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
28436
28160
|
import { rm as rm4 } from "node:fs/promises";
|
|
28437
28161
|
import { tmpdir as tmpdir2, userInfo } from "node:os";
|
|
28438
|
-
import { join as
|
|
28162
|
+
import { join as join5 } from "node:path";
|
|
28439
28163
|
var COMMAND_TIMEOUT_MS = 2 * 6e4;
|
|
28440
28164
|
var OUTPUT_LIMIT = 32 * 1024;
|
|
28441
28165
|
var LOGIN_URL = /https:\/\/login\.tailscale\.com\/[A-Za-z0-9_/-]+/u;
|
|
@@ -28470,7 +28194,7 @@ function accountName(status) {
|
|
|
28470
28194
|
const user = userId === void 0 ? void 0 : status.User?.[String(userId)];
|
|
28471
28195
|
return user?.LoginName ?? user?.DisplayName ?? status.CurrentTailnet?.Name;
|
|
28472
28196
|
}
|
|
28473
|
-
function
|
|
28197
|
+
function step2(label, status, details = {}) {
|
|
28474
28198
|
return { label, status, ...details };
|
|
28475
28199
|
}
|
|
28476
28200
|
async function readStatus(run2) {
|
|
@@ -28508,7 +28232,7 @@ async function ensureInstalled(run2, onProgress, platform) {
|
|
|
28508
28232
|
if (version.code === 0) {
|
|
28509
28233
|
return {
|
|
28510
28234
|
ok: true,
|
|
28511
|
-
steps: [
|
|
28235
|
+
steps: [step2("Tailscale installed", "done", { output: version.stdout.trim() })]
|
|
28512
28236
|
};
|
|
28513
28237
|
}
|
|
28514
28238
|
if (platform !== "linux") {
|
|
@@ -28517,17 +28241,17 @@ async function ensureInstalled(run2, onProgress, platform) {
|
|
|
28517
28241
|
ok: false,
|
|
28518
28242
|
result: {
|
|
28519
28243
|
status: "error",
|
|
28520
|
-
steps: [
|
|
28244
|
+
steps: [step2("Tailscale installed", "failed", { reason })],
|
|
28521
28245
|
errorMessage: reason
|
|
28522
28246
|
}
|
|
28523
28247
|
};
|
|
28524
28248
|
}
|
|
28525
|
-
const script =
|
|
28249
|
+
const script = join5(tmpdir2(), `beeline-tailscale-install-${process.pid}-${randomUUID4()}.sh`);
|
|
28526
28250
|
const steps2 = [
|
|
28527
|
-
|
|
28251
|
+
step2("Tailscale installed", "running", {
|
|
28528
28252
|
command: "curl -fsSL https://tailscale.com/install.sh"
|
|
28529
28253
|
}),
|
|
28530
|
-
|
|
28254
|
+
step2("Tailnet signed in", "pending")
|
|
28531
28255
|
];
|
|
28532
28256
|
onProgress(steps2);
|
|
28533
28257
|
try {
|
|
@@ -28538,7 +28262,7 @@ async function ensureInstalled(run2, onProgress, platform) {
|
|
|
28538
28262
|
ok: false,
|
|
28539
28263
|
result: {
|
|
28540
28264
|
status: "error",
|
|
28541
|
-
steps: [
|
|
28265
|
+
steps: [step2("Tailscale installed", "failed", { reason })],
|
|
28542
28266
|
errorMessage: reason
|
|
28543
28267
|
}
|
|
28544
28268
|
};
|
|
@@ -28550,14 +28274,14 @@ async function ensureInstalled(run2, onProgress, platform) {
|
|
|
28550
28274
|
ok: false,
|
|
28551
28275
|
result: {
|
|
28552
28276
|
status: "error",
|
|
28553
|
-
steps: [
|
|
28277
|
+
steps: [step2("Tailscale installed", "failed", { reason })],
|
|
28554
28278
|
errorMessage: reason
|
|
28555
28279
|
}
|
|
28556
28280
|
};
|
|
28557
28281
|
}
|
|
28558
28282
|
return {
|
|
28559
28283
|
ok: true,
|
|
28560
|
-
steps: [
|
|
28284
|
+
steps: [step2("Tailscale installed", "done", { output: install.stdout.trim() })]
|
|
28561
28285
|
};
|
|
28562
28286
|
} finally {
|
|
28563
28287
|
await rm4(script, { force: true }).catch(() => {
|
|
@@ -28576,14 +28300,14 @@ async function installTailscale(options = {}) {
|
|
|
28576
28300
|
if (current?.BackendState === "Running") {
|
|
28577
28301
|
return {
|
|
28578
28302
|
status: "connected",
|
|
28579
|
-
steps: [...installed.steps,
|
|
28303
|
+
steps: [...installed.steps, step2("Tailnet signed in", "done")],
|
|
28580
28304
|
...accountName(current) ? { signedInAs: accountName(current) } : {}
|
|
28581
28305
|
};
|
|
28582
28306
|
}
|
|
28583
28307
|
if (options.signIn) {
|
|
28584
28308
|
const steps3 = [
|
|
28585
28309
|
...installed.steps,
|
|
28586
|
-
|
|
28310
|
+
step2("Tailnet signed in", "running", { command: "tailscale up" })
|
|
28587
28311
|
];
|
|
28588
28312
|
return { status: "installing", steps: steps3, signIn: options.signIn };
|
|
28589
28313
|
}
|
|
@@ -28591,13 +28315,13 @@ async function installTailscale(options = {}) {
|
|
|
28591
28315
|
if (pendingUrl) {
|
|
28592
28316
|
return {
|
|
28593
28317
|
status: "installing",
|
|
28594
|
-
steps: [...installed.steps,
|
|
28318
|
+
steps: [...installed.steps, step2("Tailnet signed in", "running", { command: "tailscale up" })],
|
|
28595
28319
|
signIn: { method: "oauth", url: pendingUrl, browserLocation: { kind: "none" } }
|
|
28596
28320
|
};
|
|
28597
28321
|
}
|
|
28598
28322
|
const steps2 = [
|
|
28599
28323
|
...installed.steps,
|
|
28600
|
-
|
|
28324
|
+
step2("Tailnet signed in", "running", { command: "tailscale up" })
|
|
28601
28325
|
];
|
|
28602
28326
|
onProgress(steps2);
|
|
28603
28327
|
let accountUsername;
|
|
@@ -28616,7 +28340,7 @@ async function installTailscale(options = {}) {
|
|
|
28616
28340
|
if (after?.BackendState === "Running") {
|
|
28617
28341
|
return {
|
|
28618
28342
|
status: "connected",
|
|
28619
|
-
steps: [...installed.steps,
|
|
28343
|
+
steps: [...installed.steps, step2("Tailnet signed in", "done")],
|
|
28620
28344
|
...accountName(after) ? { signedInAs: accountName(after) } : {}
|
|
28621
28345
|
};
|
|
28622
28346
|
}
|
|
@@ -28633,7 +28357,7 @@ ${up.stderr}`;
|
|
|
28633
28357
|
const reason = (up.stderr || up.stdout || "Tailscale could not start on this helper").trim();
|
|
28634
28358
|
return {
|
|
28635
28359
|
status: "error",
|
|
28636
|
-
steps: [...installed.steps,
|
|
28360
|
+
steps: [...installed.steps, step2("Tailnet signed in", "failed", { reason })],
|
|
28637
28361
|
errorMessage: reason
|
|
28638
28362
|
};
|
|
28639
28363
|
}
|
|
@@ -28642,10 +28366,10 @@ ${up.stderr}`;
|
|
|
28642
28366
|
import { createHash as createHash4, randomBytes as randomBytes6 } from "node:crypto";
|
|
28643
28367
|
import { lookup } from "node:dns/promises";
|
|
28644
28368
|
import { createRequire as createRequire4 } from "node:module";
|
|
28645
|
-
import { chmodSync, existsSync as existsSync6, mkdirSync as
|
|
28646
|
-
import { createConnection, createServer as createServer2, isIPv4, isIPv6 } from "node:net";
|
|
28369
|
+
import { chmodSync, existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync4, rmSync, writeFileSync } from "node:fs";
|
|
28370
|
+
import { createConnection as createConnection3, createServer as createServer2, isIPv4, isIPv6 } from "node:net";
|
|
28647
28371
|
import { homedir as homedir10 } from "node:os";
|
|
28648
|
-
import { dirname as
|
|
28372
|
+
import { dirname as dirname9, join as join6 } from "node:path";
|
|
28649
28373
|
import { createInterface as createInterface5 } from "node:readline";
|
|
28650
28374
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
28651
28375
|
|
|
@@ -28780,12 +28504,12 @@ async function assertNotOwnMachine(url, remoteIsOwnMachine, resolveHost) {
|
|
|
28780
28504
|
return url;
|
|
28781
28505
|
}
|
|
28782
28506
|
function registryMcpStateRoot(home = homedir10()) {
|
|
28783
|
-
return
|
|
28507
|
+
return join6(home, ".beeline", "registry-mcp");
|
|
28784
28508
|
}
|
|
28785
28509
|
function registryMcpStatePath(connectorId, home = homedir10()) {
|
|
28786
28510
|
if (!/^[0-9a-f-]{20,}$/i.test(connectorId))
|
|
28787
28511
|
throw new Error("Registry connector id is invalid");
|
|
28788
|
-
return
|
|
28512
|
+
return join6(registryMcpStateRoot(home), `${connectorId}.json`);
|
|
28789
28513
|
}
|
|
28790
28514
|
function readState(path) {
|
|
28791
28515
|
try {
|
|
@@ -28796,8 +28520,8 @@ function readState(path) {
|
|
|
28796
28520
|
}
|
|
28797
28521
|
}
|
|
28798
28522
|
function writeState(path, state) {
|
|
28799
|
-
|
|
28800
|
-
|
|
28523
|
+
mkdirSync2(dirname9(path), { recursive: true, mode: 448 });
|
|
28524
|
+
writeFileSync(path, `${JSON.stringify(state)}
|
|
28801
28525
|
`, { mode: 384 });
|
|
28802
28526
|
}
|
|
28803
28527
|
function challengeParameter(header, key) {
|
|
@@ -28821,13 +28545,13 @@ var CONNECTOR_STEPS = [
|
|
|
28821
28545
|
{ key: "connect", label: "Connect provider account" }
|
|
28822
28546
|
];
|
|
28823
28547
|
function steps(active, failed) {
|
|
28824
|
-
const activeIndex = CONNECTOR_STEPS.findIndex((
|
|
28825
|
-
return CONNECTOR_STEPS.map((
|
|
28548
|
+
const activeIndex = CONNECTOR_STEPS.findIndex((step3) => step3.key === active);
|
|
28549
|
+
return CONNECTOR_STEPS.map((step3, index) => {
|
|
28826
28550
|
if (activeIndex < 0 || index < activeIndex)
|
|
28827
|
-
return { label:
|
|
28551
|
+
return { label: step3.label, status: "done" };
|
|
28828
28552
|
if (index > activeIndex)
|
|
28829
|
-
return { label:
|
|
28830
|
-
return failed ? { label:
|
|
28553
|
+
return { label: step3.label, status: "pending" };
|
|
28554
|
+
return failed ? { label: step3.label, status: "failed", reason: failed } : { label: step3.label, status: "running" };
|
|
28831
28555
|
});
|
|
28832
28556
|
}
|
|
28833
28557
|
var CEREMONY_EXPIRED = "the Trusty Squire sign-in page expired before it was used \xB7 tap Retry to open a new one";
|
|
@@ -29108,7 +28832,7 @@ function registryMcpHostDeclarations(routes, turnContextPath, brokerSocket = pro
|
|
|
29108
28832
|
}));
|
|
29109
28833
|
}
|
|
29110
28834
|
function registryMcpHostBindPaths(routes, brokerSocket = process.env.BEELINE_REGISTRY_MCP_BROKER_SOCKET) {
|
|
29111
|
-
return routes?.length && brokerSocket ? [
|
|
28835
|
+
return routes?.length && brokerSocket ? [dirname9(brokerSocket)] : [];
|
|
29112
28836
|
}
|
|
29113
28837
|
async function refresh(state, transport) {
|
|
29114
28838
|
if (!state.refreshToken || !state.tokenEndpoint || !state.clientId)
|
|
@@ -29171,7 +28895,7 @@ function jsonRpcToolName(line) {
|
|
|
29171
28895
|
}
|
|
29172
28896
|
}
|
|
29173
28897
|
function brokerSocketPath(home = homedir10()) {
|
|
29174
|
-
return
|
|
28898
|
+
return join6(home, ".beeline", "registry-mcp-broker", `${process.pid}.sock`);
|
|
29175
28899
|
}
|
|
29176
28900
|
var RegistryMcpHostBroker = class {
|
|
29177
28901
|
home;
|
|
@@ -29247,8 +28971,8 @@ var RegistryMcpHostBroker = class {
|
|
|
29247
28971
|
async start() {
|
|
29248
28972
|
if (this.server)
|
|
29249
28973
|
return;
|
|
29250
|
-
|
|
29251
|
-
|
|
28974
|
+
mkdirSync2(registryMcpStateRoot(this.home), { recursive: true, mode: 448 });
|
|
28975
|
+
mkdirSync2(dirname9(this.socketPath), { recursive: true, mode: 448 });
|
|
29252
28976
|
rmSync(this.socketPath, { force: true });
|
|
29253
28977
|
this.server = createServer2({ allowHalfOpen: true }, (socket) => {
|
|
29254
28978
|
let buffer = "";
|
|
@@ -29295,7 +29019,7 @@ var RegistryMcpHostBroker = class {
|
|
|
29295
29019
|
};
|
|
29296
29020
|
async function brokerRequest(socketPath, request) {
|
|
29297
29021
|
return new Promise((resolve40, reject) => {
|
|
29298
|
-
const socket =
|
|
29022
|
+
const socket = createConnection3(socketPath);
|
|
29299
29023
|
let output = "";
|
|
29300
29024
|
socket.setEncoding("utf8");
|
|
29301
29025
|
socket.setTimeout(125e3, () => socket.destroy(new Error("Registry MCP broker timed out")));
|
|
@@ -29375,11 +29099,9 @@ var ConnectorAssignmentLoop = class {
|
|
|
29375
29099
|
api;
|
|
29376
29100
|
log;
|
|
29377
29101
|
install;
|
|
29378
|
-
installGoogle;
|
|
29379
29102
|
installTailscale;
|
|
29380
29103
|
watchTailscaleSignIn;
|
|
29381
29104
|
tailscaleWatch;
|
|
29382
|
-
googleHomeDir;
|
|
29383
29105
|
registryHomeDir;
|
|
29384
29106
|
installRegistry;
|
|
29385
29107
|
/** When each registry sign-in attempt's SERVER clock ends, so one can time
|
|
@@ -29402,15 +29124,8 @@ var ConnectorAssignmentLoop = class {
|
|
|
29402
29124
|
this.log = options.log ?? (() => {
|
|
29403
29125
|
});
|
|
29404
29126
|
this.install = options.install ?? installSquire;
|
|
29405
|
-
this.installGoogle = options.installGoogle ?? ((connectorType, onProgress, sharedCredentials) => installGoogleTool({
|
|
29406
|
-
connectorType,
|
|
29407
|
-
home: this.googleHome(),
|
|
29408
|
-
onProgress,
|
|
29409
|
-
resolvedCredentials: sharedCredentials ? sharedCredentials() : Promise.resolve({ source: "pending", reason: "waiting for Google sign-in" })
|
|
29410
|
-
}));
|
|
29411
29127
|
this.installTailscale = options.installTailscale ?? installTailscale;
|
|
29412
29128
|
this.watchTailscaleSignIn = options.watchTailscaleSignIn ?? watchTailscaleSignIn;
|
|
29413
|
-
this.googleHomeDir = options.googleHome ?? process.env.BEELINE_AGENT_HOME ?? process.cwd();
|
|
29414
29129
|
this.registryHomeDir = options.registryHome ?? process.env.HOME ?? process.cwd();
|
|
29415
29130
|
this.installRegistry = options.installRegistry ?? installRegistryMcp;
|
|
29416
29131
|
this.readVaultFn = options.readVault ?? readVault;
|
|
@@ -29463,61 +29178,15 @@ var ConnectorAssignmentLoop = class {
|
|
|
29463
29178
|
this.log(`connector assignments unavailable: ${describe(error)}`);
|
|
29464
29179
|
return;
|
|
29465
29180
|
}
|
|
29466
|
-
const youtubeRows = assignments.filter((assignment) => isAdaptedYoutube(assignment.connectorType));
|
|
29467
|
-
if (youtubeRows.some((assignment) => assignment.kind === "uninstall") && youtubeRows.every((assignment) => assignment.kind === "uninstall")) {
|
|
29468
|
-
clearYoutubeGrant(this.googleHome(), (message) => this.log(message));
|
|
29469
|
-
}
|
|
29470
|
-
let googleBatch;
|
|
29471
29181
|
for (const assignment of assignments) {
|
|
29472
29182
|
const key = `${assignment.kind}:${assignment.connectorId}`;
|
|
29473
29183
|
if (assignment.kind === "uninstall")
|
|
29474
29184
|
continue;
|
|
29475
|
-
if (assignment.kind === "install" && isGoogleToolConnectorType(assignment.connectorType)) {
|
|
29476
|
-
if (this.inFlight.has(key))
|
|
29477
|
-
continue;
|
|
29478
|
-
this.inFlight.add(key);
|
|
29479
|
-
(googleBatch ??= []).push(assignment);
|
|
29480
|
-
continue;
|
|
29481
|
-
}
|
|
29482
29185
|
if (this.inFlight.has(key))
|
|
29483
29186
|
continue;
|
|
29484
29187
|
this.inFlight.add(key);
|
|
29485
29188
|
void this.handle(assignment).catch((error) => this.log(`connector assignment ${key} failed: ${describe(error)}`)).finally(() => this.inFlight.delete(key));
|
|
29486
29189
|
}
|
|
29487
|
-
if (googleBatch) {
|
|
29488
|
-
const keys = googleBatch.map((assignment) => `${assignment.kind}:${assignment.connectorId}`);
|
|
29489
|
-
void this.runGoogleBatch(googleBatch).catch((error) => this.log(`google connector installs failed: ${describe(error)}`)).finally(() => {
|
|
29490
|
-
for (const key of keys)
|
|
29491
|
-
this.inFlight.delete(key);
|
|
29492
|
-
});
|
|
29493
|
-
}
|
|
29494
|
-
}
|
|
29495
|
-
/** Google tools share a machine grant, but each connector has its own OAuth
|
|
29496
|
-
* readiness. Resolve it per connector while installs run sequentially. */
|
|
29497
|
-
async runGoogleBatch(batch) {
|
|
29498
|
-
for (const assignment of batch) {
|
|
29499
|
-
await this.runGoogleInstall(assignment.connectorId, assignment.connectorType, () => this.resolveGoogleCredentials(assignment.connectorId), assignment.kind === "install" ? assignment.pairingGeneration : void 0);
|
|
29500
|
-
}
|
|
29501
|
-
}
|
|
29502
|
-
/** A failed grant lookup becomes an error for this connector. */
|
|
29503
|
-
resolveGoogleCredentials(connectorId) {
|
|
29504
|
-
return (async () => {
|
|
29505
|
-
try {
|
|
29506
|
-
const grant = await this.api.execute("getGoogleOAuthGrant", {
|
|
29507
|
-
agentId: this.agentId,
|
|
29508
|
-
connectorId
|
|
29509
|
-
});
|
|
29510
|
-
if (grant.status === "ready" && grant.credentials)
|
|
29511
|
-
return { source: "beeline", credentials: grant.credentials };
|
|
29512
|
-
} catch (error) {
|
|
29513
|
-
this.log(`Google grant lookup failed: ${describe(error)}`);
|
|
29514
|
-
return {
|
|
29515
|
-
source: "error",
|
|
29516
|
-
reason: "Beeline could not read the Google grant; retry the connection"
|
|
29517
|
-
};
|
|
29518
|
-
}
|
|
29519
|
-
return { source: "pending", reason: "waiting for Google sign-in" };
|
|
29520
|
-
})();
|
|
29521
29190
|
}
|
|
29522
29191
|
squire() {
|
|
29523
29192
|
this.mcp ??= defaultSquireMcpClient({ agentId: this.agentId, roomId: "connector" });
|
|
@@ -29526,7 +29195,19 @@ var ConnectorAssignmentLoop = class {
|
|
|
29526
29195
|
async handle(assignment) {
|
|
29527
29196
|
const pairingGeneration = assignment.kind === "install" || assignment.kind === "uninstall" ? assignment.pairingGeneration : void 0;
|
|
29528
29197
|
if (assignment.kind === "install") {
|
|
29529
|
-
if (assignment.connectorType
|
|
29198
|
+
if (assignment.connectorType?.startsWith("google-")) {
|
|
29199
|
+
await this.api.execute("postConnectorStatus", {
|
|
29200
|
+
agentId: this.agentId,
|
|
29201
|
+
connectorId: assignment.connectorId,
|
|
29202
|
+
steps: [{
|
|
29203
|
+
label: "Connect app",
|
|
29204
|
+
status: "failed",
|
|
29205
|
+
reason: "Reconnect through Connect an app"
|
|
29206
|
+
}],
|
|
29207
|
+
errorMessage: "Reconnect through Connect an app",
|
|
29208
|
+
...pairingGeneration !== void 0 ? { pairingGeneration } : {}
|
|
29209
|
+
});
|
|
29210
|
+
} else if (assignment.connectorType === "registry-mcp") {
|
|
29530
29211
|
await this.runRegistryMcpInstall(assignment);
|
|
29531
29212
|
} else if (assignment.connectorType === "tailscale") {
|
|
29532
29213
|
await this.runTailscaleInstall(assignment.connectorId, pairingGeneration);
|
|
@@ -29538,9 +29219,7 @@ var ConnectorAssignmentLoop = class {
|
|
|
29538
29219
|
} else if (assignment.kind === "sync") {
|
|
29539
29220
|
await this.runSync();
|
|
29540
29221
|
} else if (assignment.kind === "refresh-google-grant") {
|
|
29541
|
-
|
|
29542
|
-
if ("credentials" in grant)
|
|
29543
|
-
persistManualGoogleCredentials(this.googleHome(), grant.credentials);
|
|
29222
|
+
this.log("retired Google grant assignment ignored; reconnect through Connect an app");
|
|
29544
29223
|
} else if (assignment.kind === "revoke-grants")
|
|
29545
29224
|
await this.runRevoke(assignment.connectorId, assignment.reference);
|
|
29546
29225
|
}
|
|
@@ -29655,49 +29334,6 @@ var ConnectorAssignmentLoop = class {
|
|
|
29655
29334
|
this.wake();
|
|
29656
29335
|
});
|
|
29657
29336
|
}
|
|
29658
|
-
/** Google tool connectors keep their manual credentials next to the runtime. */
|
|
29659
|
-
googleHome() {
|
|
29660
|
-
return this.googleHomeDir;
|
|
29661
|
-
}
|
|
29662
|
-
/** Install one Google tool connector (Gmail/Calendar/Drive/YouTube),
|
|
29663
|
-
* riding the drain's shared grant resolution. */
|
|
29664
|
-
async runGoogleInstall(connectorId, connectorType, sharedCredentials, pairingGeneration) {
|
|
29665
|
-
const generation = pairingGeneration !== void 0 ? { pairingGeneration } : {};
|
|
29666
|
-
const report = async (steps2) => {
|
|
29667
|
-
try {
|
|
29668
|
-
await this.api.execute("postConnectorStatus", {
|
|
29669
|
-
agentId: this.agentId,
|
|
29670
|
-
connectorId,
|
|
29671
|
-
steps: steps2,
|
|
29672
|
-
...generation
|
|
29673
|
-
});
|
|
29674
|
-
} catch (error) {
|
|
29675
|
-
this.log(`step report failed: ${describe(error)}`);
|
|
29676
|
-
}
|
|
29677
|
-
};
|
|
29678
|
-
const result = await this.installGoogle(connectorType, report, sharedCredentials);
|
|
29679
|
-
if (result.status === "installing")
|
|
29680
|
-
return;
|
|
29681
|
-
if (result.status === "error") {
|
|
29682
|
-
if (isAdaptedYoutube(connectorType)) {
|
|
29683
|
-
clearYoutubeGrant(this.googleHome(), (message) => this.log(message));
|
|
29684
|
-
}
|
|
29685
|
-
await this.api.execute("postConnectorStatus", {
|
|
29686
|
-
agentId: this.agentId,
|
|
29687
|
-
connectorId,
|
|
29688
|
-
steps: result.steps,
|
|
29689
|
-
errorMessage: result.errorMessage,
|
|
29690
|
-
...generation
|
|
29691
|
-
});
|
|
29692
|
-
return;
|
|
29693
|
-
}
|
|
29694
|
-
await this.api.execute("installConnector", {
|
|
29695
|
-
agentId: this.agentId,
|
|
29696
|
-
connectorId,
|
|
29697
|
-
...result.signedInAs ? { signedInAs: result.signedInAs } : {},
|
|
29698
|
-
...generation
|
|
29699
|
-
});
|
|
29700
|
-
}
|
|
29701
29337
|
/** Install Trusty Squire, reporting every step as it settles. */
|
|
29702
29338
|
async runInstall(connectorId, pairingGeneration) {
|
|
29703
29339
|
const generation = pairingGeneration !== void 0 ? { pairingGeneration } : {};
|
|
@@ -29795,7 +29431,7 @@ var ConnectorAssignmentLoop = class {
|
|
|
29795
29431
|
const status = await this.connectorRow(connectorId);
|
|
29796
29432
|
if (!status)
|
|
29797
29433
|
return false;
|
|
29798
|
-
return status.steps.length > 0 && status.steps.every((
|
|
29434
|
+
return status.steps.length > 0 && status.steps.every((step3) => step3.status === "pending");
|
|
29799
29435
|
}
|
|
29800
29436
|
/** One vault report covers every live trusty-squire connector on this helper. */
|
|
29801
29437
|
async runSync() {
|
|
@@ -30585,7 +30221,7 @@ var InstitutionalMemoryShadowWorker = class {
|
|
|
30585
30221
|
leaseToken: job.leaseToken,
|
|
30586
30222
|
error: errorText(error),
|
|
30587
30223
|
retryable: true
|
|
30588
|
-
}).catch((
|
|
30224
|
+
}).catch((failure) => this.log(`shadow failure report failed: ${errorText(failure)}`));
|
|
30589
30225
|
}
|
|
30590
30226
|
return false;
|
|
30591
30227
|
} finally {
|
|
@@ -30600,7 +30236,7 @@ var InstitutionalMemoryShadowWorker = class {
|
|
|
30600
30236
|
|
|
30601
30237
|
// apps/body/dist/daemon-api-client.js
|
|
30602
30238
|
import { resolve as resolve13 } from "node:path";
|
|
30603
|
-
import { randomUUID as
|
|
30239
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
30604
30240
|
|
|
30605
30241
|
// node_modules/ws/wrapper.mjs
|
|
30606
30242
|
var import_stream = __toESM(require_stream(), 1);
|
|
@@ -30622,10 +30258,10 @@ function helperVersionHeader(value) {
|
|
|
30622
30258
|
}
|
|
30623
30259
|
|
|
30624
30260
|
// apps/body/dist/host-read-budget.js
|
|
30625
|
-
import { createHash as createHash5, randomUUID as
|
|
30261
|
+
import { createHash as createHash5, randomUUID as randomUUID5 } from "node:crypto";
|
|
30626
30262
|
import { mkdir as mkdir7, open as open3, readFile as readFile10, readdir as readdir3, stat as stat5, unlink as unlink4, writeFile as writeFile7 } from "node:fs/promises";
|
|
30627
30263
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
30628
|
-
import { join as
|
|
30264
|
+
import { join as join7 } from "node:path";
|
|
30629
30265
|
var READ_SLOTS = 6;
|
|
30630
30266
|
var BACKGROUND_SLOTS = 4;
|
|
30631
30267
|
var MAX_WAITERS = 256;
|
|
@@ -30656,15 +30292,15 @@ var HostReadBudget = class {
|
|
|
30656
30292
|
const uid = process.getuid?.() ?? "unknown";
|
|
30657
30293
|
const origin = new URL(baseUrl).origin;
|
|
30658
30294
|
const key = createHash5("sha256").update(origin).digest("hex").slice(0, 16);
|
|
30659
|
-
this.directory =
|
|
30295
|
+
this.directory = join7(root, `beeline-read-budget-${uid}-${key}`);
|
|
30660
30296
|
}
|
|
30661
30297
|
metrics() {
|
|
30662
30298
|
return { waiting: this.waiting, active: this.active, totalWaitMs: this.totalWaitMs };
|
|
30663
30299
|
}
|
|
30664
30300
|
async acquire(priority, deadlineAt) {
|
|
30665
30301
|
await mkdir7(this.directory, { recursive: true, mode: 448 });
|
|
30666
|
-
const ticket = `wait-${priority === "urgent" ? "0" : "1"}-${String(Date.now()).padStart(13, "0")}-${
|
|
30667
|
-
const ticketPath =
|
|
30302
|
+
const ticket = `wait-${priority === "urgent" ? "0" : "1"}-${String(Date.now()).padStart(13, "0")}-${randomUUID5()}`;
|
|
30303
|
+
const ticketPath = join7(this.directory, ticket);
|
|
30668
30304
|
const tickets = (await readdir3(this.directory)).filter((name) => name.startsWith("wait-"));
|
|
30669
30305
|
if (tickets.length >= MAX_WAITERS)
|
|
30670
30306
|
throw new ReadBudgetFullError();
|
|
@@ -30676,14 +30312,14 @@ var HostReadBudget = class {
|
|
|
30676
30312
|
const queue = (await readdir3(this.directory)).filter((name) => name.startsWith("wait-")).sort();
|
|
30677
30313
|
for (const name of queue.slice(0, READ_SLOTS)) {
|
|
30678
30314
|
if (name !== ticket)
|
|
30679
|
-
await this.reapStaleTicket(
|
|
30315
|
+
await this.reapStaleTicket(join7(this.directory, name));
|
|
30680
30316
|
}
|
|
30681
30317
|
const liveQueue = (await readdir3(this.directory)).filter((name) => name.startsWith("wait-")).sort();
|
|
30682
30318
|
const rank = liveQueue.indexOf(ticket);
|
|
30683
30319
|
const available = priority === "urgent" ? READ_SLOTS : BACKGROUND_SLOTS;
|
|
30684
30320
|
if (rank >= 0 && rank < available) {
|
|
30685
30321
|
for (let slot = 0; slot < available; slot += 1) {
|
|
30686
|
-
const slotPath =
|
|
30322
|
+
const slotPath = join7(this.directory, `slot-${slot}`);
|
|
30687
30323
|
try {
|
|
30688
30324
|
const handle2 = await open3(slotPath, "wx", 384);
|
|
30689
30325
|
try {
|
|
@@ -30754,7 +30390,7 @@ var HostReadBudget = class {
|
|
|
30754
30390
|
await unlink4(path).catch(() => void 0);
|
|
30755
30391
|
}
|
|
30756
30392
|
async takeRateToken(deadlineAt) {
|
|
30757
|
-
const lock =
|
|
30393
|
+
const lock = join7(this.directory, "rate.lock");
|
|
30758
30394
|
let handle2;
|
|
30759
30395
|
try {
|
|
30760
30396
|
handle2 = await open3(lock, "wx", 384);
|
|
@@ -30765,7 +30401,7 @@ var HostReadBudget = class {
|
|
|
30765
30401
|
return false;
|
|
30766
30402
|
}
|
|
30767
30403
|
try {
|
|
30768
|
-
const path =
|
|
30404
|
+
const path = join7(this.directory, "next-admission");
|
|
30769
30405
|
const next = Number(await readFile10(path, "utf8").catch(() => "0")) || 0;
|
|
30770
30406
|
const now2 = Date.now();
|
|
30771
30407
|
if (next > now2 || now2 >= deadlineAt)
|
|
@@ -30842,7 +30478,7 @@ var DaemonApiClient = class {
|
|
|
30842
30478
|
agentId;
|
|
30843
30479
|
fetchImpl;
|
|
30844
30480
|
webSocketFactory;
|
|
30845
|
-
presenceLifecycleId =
|
|
30481
|
+
presenceLifecycleId = randomUUID6();
|
|
30846
30482
|
liveSocket;
|
|
30847
30483
|
liveReconnect;
|
|
30848
30484
|
liveReconnectDelayMs = 1e3;
|
|
@@ -31288,10 +30924,10 @@ async function activateDaemonTransport(path, fetchImpl = fetch) {
|
|
|
31288
30924
|
|
|
31289
30925
|
// apps/body/dist/room-runtime.js
|
|
31290
30926
|
import { execFile as execFile12 } from "node:child_process";
|
|
31291
|
-
import { createHash as
|
|
31292
|
-
import { existsSync as existsSync8, mkdirSync as
|
|
31293
|
-
import { mkdir as mkdir20, readdir as readdir8, realpath as realpath2, rm as rm9 } from "node:fs/promises";
|
|
31294
|
-
import { dirname as
|
|
30927
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
30928
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3 } from "node:fs";
|
|
30929
|
+
import { cp, mkdir as mkdir20, readdir as readdir8, realpath as realpath2, rm as rm9 } from "node:fs/promises";
|
|
30930
|
+
import { dirname as dirname18, relative as relative3, resolve as resolve29, sep as sep2 } from "node:path";
|
|
31295
30931
|
import { promisify as promisify8 } from "node:util";
|
|
31296
30932
|
|
|
31297
30933
|
// apps/body/dist/grant-runner.js
|
|
@@ -31299,7 +30935,7 @@ import { execFile as execFile8 } from "node:child_process";
|
|
|
31299
30935
|
import { createHash as createHash6, randomBytes as randomBytes7 } from "node:crypto";
|
|
31300
30936
|
import { readFile as readFile12 } from "node:fs/promises";
|
|
31301
30937
|
import { createServer as createServer3 } from "node:http";
|
|
31302
|
-
import { dirname as
|
|
30938
|
+
import { dirname as dirname11, resolve as resolve16 } from "node:path";
|
|
31303
30939
|
|
|
31304
30940
|
// packages/api-contract/dist/agent-grants.js
|
|
31305
30941
|
var AGENT_GRANT_KINDS = [
|
|
@@ -31546,7 +31182,7 @@ function surfaceAllows(surface, capability) {
|
|
|
31546
31182
|
init_agent_command();
|
|
31547
31183
|
init_cursor_acp_bridge();
|
|
31548
31184
|
import { execFile as execFile7, spawnSync } from "node:child_process";
|
|
31549
|
-
import { lstatSync as
|
|
31185
|
+
import { lstatSync as lstatSync2, readFileSync as readFileSync5, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
31550
31186
|
import { homedir as homedir11 } from "node:os";
|
|
31551
31187
|
import { isAbsolute as isAbsolute2, relative, resolve as resolve14 } from "node:path";
|
|
31552
31188
|
var DEFAULT_SANDBOX_POLICY = "bwrap";
|
|
@@ -31607,7 +31243,7 @@ var KNOWN_CREDENTIAL_MASK_PATHS = [
|
|
|
31607
31243
|
];
|
|
31608
31244
|
function credentialMaskPaths(extraPaths, home = homedir11(), stat8 = (path) => {
|
|
31609
31245
|
try {
|
|
31610
|
-
const info =
|
|
31246
|
+
const info = lstatSync2(path);
|
|
31611
31247
|
return { isDirectory: info.isDirectory() };
|
|
31612
31248
|
} catch {
|
|
31613
31249
|
return void 0;
|
|
@@ -31825,7 +31461,7 @@ function recordInstallFailure(stateDir, at) {
|
|
|
31825
31461
|
if (!stateDir)
|
|
31826
31462
|
return;
|
|
31827
31463
|
try {
|
|
31828
|
-
|
|
31464
|
+
writeFileSync2(installFailureMarker(stateDir), `${at}
|
|
31829
31465
|
`, "utf8");
|
|
31830
31466
|
} catch {
|
|
31831
31467
|
}
|
|
@@ -31950,7 +31586,7 @@ async function ensureBwrapSandbox(options = {}) {
|
|
|
31950
31586
|
// apps/body/dist/provider-key-store.js
|
|
31951
31587
|
import { chmod as chmod4, mkdir as mkdir8, readFile as readFile11, writeFile as writeFile8 } from "node:fs/promises";
|
|
31952
31588
|
import { homedir as homedir12 } from "node:os";
|
|
31953
|
-
import { dirname as
|
|
31589
|
+
import { dirname as dirname10, resolve as resolve15 } from "node:path";
|
|
31954
31590
|
var PROVIDER_KEY_ENV_VARS = {
|
|
31955
31591
|
openrouter: "OPENROUTER_API_KEY",
|
|
31956
31592
|
openai: "OPENAI_API_KEY",
|
|
@@ -31984,7 +31620,7 @@ async function readSavedProviderKey(provider, env = process.env) {
|
|
|
31984
31620
|
async function saveProviderKey(provider, key, env = process.env) {
|
|
31985
31621
|
const path = providerKeyStorePath(env);
|
|
31986
31622
|
const store = { ...await readProviderKeyStore(env), [provider]: key };
|
|
31987
|
-
await mkdir8(
|
|
31623
|
+
await mkdir8(dirname10(path), { recursive: true, mode: 448 });
|
|
31988
31624
|
await writeFile8(path, `${JSON.stringify(store, null, 2)}
|
|
31989
31625
|
`, { mode: 384 });
|
|
31990
31626
|
await chmod4(path, 384);
|
|
@@ -32022,7 +31658,7 @@ function operatorSecretResolver(env = process.env) {
|
|
|
32022
31658
|
if (saved)
|
|
32023
31659
|
return saved;
|
|
32024
31660
|
}
|
|
32025
|
-
const raw = await readFile12(resolve16(
|
|
31661
|
+
const raw = await readFile12(resolve16(dirname11(providerKeyStorePath(env)), "secrets.json"), "utf8").catch(() => void 0);
|
|
32026
31662
|
if (!raw)
|
|
32027
31663
|
return void 0;
|
|
32028
31664
|
try {
|
|
@@ -32152,13 +31788,13 @@ var GrantCommandRunner = class {
|
|
|
32152
31788
|
encoding: "utf8"
|
|
32153
31789
|
}, (error, stdout6, stderr) => {
|
|
32154
31790
|
const combined = [stdout6, stderr].filter(Boolean).join(stderr && stdout6 ? "\n" : "");
|
|
32155
|
-
const
|
|
32156
|
-
const spawnFailure = Boolean(
|
|
31791
|
+
const failure = error;
|
|
31792
|
+
const spawnFailure = Boolean(failure && typeof failure.code === "string");
|
|
32157
31793
|
resolveRun({
|
|
32158
|
-
exitCode: spawnFailure ? null : child.exitCode ?? (typeof
|
|
32159
|
-
...
|
|
32160
|
-
timedOut: Boolean(
|
|
32161
|
-
output: spawnFailure ? `${combined}${combined ? "\n" : ""}${
|
|
31794
|
+
exitCode: spawnFailure ? null : child.exitCode ?? (typeof failure?.code === "number" ? failure.code : 0),
|
|
31795
|
+
...failure?.signal ? { signal: failure.signal } : {},
|
|
31796
|
+
timedOut: Boolean(failure?.killed && failure?.signal === "SIGKILL"),
|
|
31797
|
+
output: spawnFailure ? `${combined}${combined ? "\n" : ""}${failure.message}` : combined
|
|
32162
31798
|
});
|
|
32163
31799
|
});
|
|
32164
31800
|
});
|
|
@@ -32294,16 +31930,16 @@ var GrantRunnerServer = class {
|
|
|
32294
31930
|
await new Promise((resolveClose) => server.close(() => resolveClose()));
|
|
32295
31931
|
}
|
|
32296
31932
|
async handle(request, response, token) {
|
|
32297
|
-
const
|
|
31933
|
+
const send = (status, body) => {
|
|
32298
31934
|
response.writeHead(status, { "content-type": "application/json" });
|
|
32299
31935
|
response.end(JSON.stringify(body));
|
|
32300
31936
|
};
|
|
32301
31937
|
if (request.headers.authorization !== `Bearer ${token}`) {
|
|
32302
|
-
|
|
31938
|
+
send(401, { error: "grant runner token required" });
|
|
32303
31939
|
return;
|
|
32304
31940
|
}
|
|
32305
31941
|
if (request.method !== "POST" || request.url !== "/run") {
|
|
32306
|
-
|
|
31942
|
+
send(404, { error: "not found" });
|
|
32307
31943
|
return;
|
|
32308
31944
|
}
|
|
32309
31945
|
const chunks = [];
|
|
@@ -32311,9 +31947,9 @@ var GrantRunnerServer = class {
|
|
|
32311
31947
|
chunks.push(chunk);
|
|
32312
31948
|
try {
|
|
32313
31949
|
const body = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
32314
|
-
|
|
31950
|
+
send(200, await this.runner.run({ roomId: body.roomId, argv: body.argv }));
|
|
32315
31951
|
} catch (error) {
|
|
32316
|
-
|
|
31952
|
+
send(400, { error: error instanceof Error ? error.message : String(error) });
|
|
32317
31953
|
}
|
|
32318
31954
|
}
|
|
32319
31955
|
};
|
|
@@ -32324,11 +31960,6 @@ function toolName(call) {
|
|
|
32324
31960
|
const match = raw.match(/(?:^|__|\b)(use_credential|fetch_credential|grant_app_access|revoke_app_access)\b/);
|
|
32325
31961
|
return match?.[1] ?? "";
|
|
32326
31962
|
}
|
|
32327
|
-
function youtubeToolName(call) {
|
|
32328
|
-
const raw = `${call.title ?? ""} ${call.kind ?? ""}`;
|
|
32329
|
-
const match = raw.match(/(?:^|__|\.|\/)(youtube_[a-z0-9_]+)\b/);
|
|
32330
|
-
return match?.[1] ?? "";
|
|
32331
|
-
}
|
|
32332
31963
|
var SQUIRE_EVENT_CLASS = {
|
|
32333
31964
|
fetch_credential: "approval",
|
|
32334
31965
|
// the credential was read in clear
|
|
@@ -32415,23 +32046,9 @@ var ConnectorUsageRecorder = class {
|
|
|
32415
32046
|
}
|
|
32416
32047
|
}
|
|
32417
32048
|
};
|
|
32418
|
-
function youtubeUsageFromToolCall(call) {
|
|
32419
|
-
const tool = youtubeToolName(call);
|
|
32420
|
-
if (!tool.startsWith("youtube_"))
|
|
32421
|
-
return void 0;
|
|
32422
|
-
const result = record4(call.content ?? call.rawOutput);
|
|
32423
|
-
const resultPayload = record4(result.content ?? result);
|
|
32424
|
-
return {
|
|
32425
|
-
ref: "google-youtube",
|
|
32426
|
-
service: "youtube",
|
|
32427
|
-
operation: tool.slice(0, 300),
|
|
32428
|
-
statusCode: typeof resultPayload.status === "number" ? resultPayload.status : /failed|error|denied/i.test(call.status ?? "") ? 0 : 200,
|
|
32429
|
-
bytes: serializedSize(resultPayload)
|
|
32430
|
-
};
|
|
32431
|
-
}
|
|
32432
32049
|
function captureConnectionUsage(recorder, turn, calls) {
|
|
32433
32050
|
for (const call of calls) {
|
|
32434
|
-
const usage2 = squireUsageFromToolCall(call)
|
|
32051
|
+
const usage2 = squireUsageFromToolCall(call);
|
|
32435
32052
|
if (usage2)
|
|
32436
32053
|
recorder.record(turn, usage2);
|
|
32437
32054
|
}
|
|
@@ -32610,20 +32227,20 @@ async function readHarnessTurnUsage(input) {
|
|
|
32610
32227
|
}
|
|
32611
32228
|
|
|
32612
32229
|
// apps/body/dist/server-command-intake.js
|
|
32613
|
-
import { randomUUID as
|
|
32230
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
32614
32231
|
import { mkdir as mkdir9, writeFile as writeFile9 } from "node:fs/promises";
|
|
32615
32232
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
32616
|
-
import { dirname as
|
|
32233
|
+
import { dirname as dirname12, join as join8 } from "node:path";
|
|
32617
32234
|
var CommandExecutionContext = class {
|
|
32618
|
-
generationId =
|
|
32235
|
+
generationId = randomUUID7();
|
|
32619
32236
|
path;
|
|
32620
32237
|
current;
|
|
32621
32238
|
constructor(root) {
|
|
32622
|
-
this.path =
|
|
32239
|
+
this.path = join8(root ?? tmpdir5(), `beeline-command-${this.generationId}.json`);
|
|
32623
32240
|
}
|
|
32624
32241
|
async enter(command) {
|
|
32625
32242
|
this.current = command;
|
|
32626
|
-
await mkdir9(
|
|
32243
|
+
await mkdir9(dirname12(this.path), { recursive: true });
|
|
32627
32244
|
await writeFile9(this.path, JSON.stringify({
|
|
32628
32245
|
roomId: command.roomId,
|
|
32629
32246
|
requestId: command.turnRequestId,
|
|
@@ -32788,10 +32405,10 @@ async function runServerCommandIntake(options) {
|
|
|
32788
32405
|
|
|
32789
32406
|
// apps/body/dist/monolith-corner-turn.js
|
|
32790
32407
|
import { execFile as execFile11 } from "node:child_process";
|
|
32791
|
-
import { createHash as
|
|
32408
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
32792
32409
|
import { mkdir as mkdir18, readFile as readFile19, writeFile as writeFile14 } from "node:fs/promises";
|
|
32793
32410
|
import { homedir as homedir14, hostname } from "node:os";
|
|
32794
|
-
import { dirname as
|
|
32411
|
+
import { dirname as dirname16, join as join13, resolve as resolve28 } from "node:path";
|
|
32795
32412
|
import { promisify as promisify7 } from "node:util";
|
|
32796
32413
|
|
|
32797
32414
|
// apps/body/dist/agent-home.js
|
|
@@ -33593,10 +33210,10 @@ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
|
|
|
33593
33210
|
}
|
|
33594
33211
|
|
|
33595
33212
|
// apps/body/dist/agent-home.js
|
|
33596
|
-
import { createHash as createHash7, randomUUID as
|
|
33213
|
+
import { createHash as createHash7, randomUUID as randomUUID8 } from "node:crypto";
|
|
33597
33214
|
import { chmod as chmod5, copyFile, lstat as lstat3, mkdir as mkdir11, readFile as readFile16, readlink, readdir as readdir5, realpath, rename as rename5, rm as rm6, symlink as symlink2, unlink as unlink5, writeFile as writeFile11 } from "node:fs/promises";
|
|
33598
33215
|
import { homedir as homedir13 } from "node:os";
|
|
33599
|
-
import { basename as basename4, dirname as
|
|
33216
|
+
import { basename as basename4, dirname as dirname13, join as join10, relative as relative2, resolve as resolve21, sep } from "node:path";
|
|
33600
33217
|
|
|
33601
33218
|
// apps/body/dist/draw-avatar-skill.js
|
|
33602
33219
|
var DRAW_AVATAR_SKILL_NAME = "draw-avatar";
|
|
@@ -33768,11 +33385,9 @@ Follow your own owner first, then this Workspace's owner and admins, then member
|
|
|
33768
33385
|
|
|
33769
33386
|
A **tool** is something you can use once a human adds it; a **key** is the credential that tool holds for that human. You spend a key through the mounted connector and never see the credential itself.
|
|
33770
33387
|
|
|
33771
|
-
The tools this build knows, what each is for, and which the owner of this machine already has are one call away: beeline-agent workbench_status. That read is the Workbench of the machine and owner you actually run on, not the person who asked.
|
|
33388
|
+
The tools this build knows, what each is for, and which the owner of this machine already has are one call away: beeline-agent workbench_status. That read is the Workbench of the machine and owner you actually run on, not the person who asked. Connected apps are listed once per app with a stable ID. Their sign-in and credentials stay with the server. Trusty Squire is vaulted credentials plus a browser for the separate key and browser routes. Tailscale installs its CLI on the selected helper and opens Tailscale's own browser sign-in; once connected, use the CLI for tailnet resources and tailscale file cp or tailscale file get for Taildrop. The wallet is created only from the Workbench page. When you cannot reach a tool, say: I can't reach X on this machine because Y; to fix it, Z. Give one explanation, then take or offer Z.
|
|
33772
33389
|
|
|
33773
|
-
When you
|
|
33774
|
-
|
|
33775
|
-
**Offer the tool at the moment you need it.** When the work in front of you needs a tool the person does not have, do not send them to a settings page and do not stop at naming it. Call workbench_status first - a tool they already have is used, not offered. Then call offer_connector with the connectorType and one short reason: a card appears in this Room, spoken by you, addressed to the person you are answering, with one action. Only that person or a Workspace admin can accept it; accepting adds the tool on your machine, and the sign-in or keys stay theirs. Your turn pauses on the card - say in prose what you are waiting for and end the turn; you are woken when it is added, and then you carry on.
|
|
33390
|
+
**Offer the tool at the moment you need it.** When the work in front of you needs a tool the person does not have, do not send them to a settings page and do not stop at naming it. Call workbench_status first - a tool they already have is used, not offered. Then call offer_connector with the connectorType and one short reason: a card appears in this Room, spoken by you, addressed to the person you are answering, with one action. Your turn pauses on the card - say in prose what you are waiting for and end the turn; you are woken when it is added, and then you carry on.
|
|
33776
33391
|
|
|
33777
33392
|
**Research before you offer, and say so.** Never offer a tool you cannot describe. If someone asks you to install or add something you do not already know - by name, by purpose, or by what it will hold - say plainly that you are looking it up first, find out what it is and what it does with credentials, and state what you learned in your reply BEFORE the card appears. A person reading "Add X?" must already have read, in your own words, what X is. Refusing to act blind is part of being trusted with keys.
|
|
33778
33393
|
|
|
@@ -33782,13 +33397,9 @@ Keys belong to the human who provisioned them. Your owner's keys serve whoever a
|
|
|
33782
33397
|
|
|
33783
33398
|
## Connect an app
|
|
33784
33399
|
|
|
33785
|
-
When a request needs an app or service
|
|
33400
|
+
When a request needs an app or service, call beeline-agent \`workbench_status\` first. For a connected app, use its ID with \`list_app_tools\`, then call \`execute_app_tool\` with the selected tool slug and arguments. The server executes against that person\u2019s account and decides permission on every call. An empty tool list or \`needs_connection\` means the account must be reconnected; \`needs_permission\` means wait for the connected person's decision. Do not switch paths after denial or provider unavailability. No app token, provider key, or sign-in URL belongs in chat or a model prompt.
|
|
33786
33401
|
|
|
33787
|
-
|
|
33788
|
-
2. Call \`connect_app\` and do exactly what its \`next\` says. Repeating the call is safe and is how you report a finished step.
|
|
33789
|
-
3. Trusty Squire handles every sign-in, sign-up and payment, on every route - including an MCP server's OAuth page (\`authorizationUrl\`: \`operate_start\`, \`operate_login\`, \`operate_observe\`, \`operate_finish\`). Any passkey or vouch step goes to the owner through Squire. Never paste a sign-in link or a key into chat. If Squire is not connected, offer it with \`offer_connector\` (trusty-squire) and call \`connect_app\` again once it is added.
|
|
33790
|
-
4. On the API route, store the key with Squire's \`store_credential\` under the service the result names, call \`connect_app\` again, then call the API with \`use_credential\`. Pass \`noApi: true\` only when you established that the app offers no API at all.
|
|
33791
|
-
5. Every use of the app, whichever route serves it, is authorized as \`app:<key>\` and recorded once. A refusal or a pending approval is final for that call: wait for the owner's decision, and never try another route to get around it.
|
|
33402
|
+
For an app that is not connected, call \`connect_app\` with its name, one short reason, and a request-specific \`continuation\`: one sentence stating what you will do right after sign-in. Do not include a link, credential, account identifier, or private data in that sentence. The server chooses the route and returns \`next\`. A managed OAuth app presents a sign-in card to its owner; end the turn and wait for the connection wake. If the provider reports managed OAuth unsupported, follow the server's Squire route and its instructions. A provider outage is unavailable, not permission to change routes. After the person connects, read Workbench again and use the app ID. Trusty Squire handles the separate API key and browser routes; never ask for a raw key in chat. Every use is authorized as \`app:<key>\` and recorded once.
|
|
33792
33403
|
|
|
33793
33404
|
## Showing a mock
|
|
33794
33405
|
|
|
@@ -34065,7 +33676,7 @@ var SQUIRE_GOVERNED_TOOLS = [
|
|
|
34065
33676
|
var SQUIRE_GOVERNED_TOOL_SET = new Set(SQUIRE_GOVERNED_TOOLS);
|
|
34066
33677
|
|
|
34067
33678
|
// apps/body/dist/host-mcp-route.js
|
|
34068
|
-
import { join as
|
|
33679
|
+
import { join as join9, resolve as resolve19 } from "node:path";
|
|
34069
33680
|
var import_yaml = __toESM(require_dist(), 1);
|
|
34070
33681
|
init_squire_host();
|
|
34071
33682
|
function grantedMcpServerNames(grants) {
|
|
@@ -34120,7 +33731,7 @@ function grantedSquireHostRouteNames(granted, declarations = {}) {
|
|
|
34120
33731
|
});
|
|
34121
33732
|
}
|
|
34122
33733
|
function hostRouteEnv(hostHome) {
|
|
34123
|
-
return { XDG_CONFIG_HOME:
|
|
33734
|
+
return { XDG_CONFIG_HOME: join9(resolve19(hostHome), ".config") };
|
|
34124
33735
|
}
|
|
34125
33736
|
function rewriteHostMcpDeclaration(name, declaration, hostHome, resourceAuthFile, squireScope) {
|
|
34126
33737
|
const next = { ...declaration };
|
|
@@ -34143,10 +33754,6 @@ function rewriteHostMcpDeclaration(name, declaration, hostHome, resourceAuthFile
|
|
|
34143
33754
|
next.envs = { ...recordValue(declaration.envs), ...routeEnv };
|
|
34144
33755
|
else
|
|
34145
33756
|
next.env = { ...recordValue(declaration.env), ...routeEnv };
|
|
34146
|
-
if (launch) {
|
|
34147
|
-
delete next.env?.TRUSTY_SQUIRE_AGENT_IDENTITY;
|
|
34148
|
-
delete next.envs?.TRUSTY_SQUIRE_AGENT_IDENTITY;
|
|
34149
|
-
}
|
|
34150
33757
|
if (resourceAuthFile) {
|
|
34151
33758
|
const target = explicitResourceTarget ?? (isSquireDeclaration(name, declaration) ? "squire" : name);
|
|
34152
33759
|
const env = {
|
|
@@ -34520,7 +34127,7 @@ async function resolveUptimeRouting(input) {
|
|
|
34520
34127
|
if (cached?.input !== void 0 && now2() - cached.fetchedAt < OPENROUTER_ROUTING_CACHE_TTL_MS) {
|
|
34521
34128
|
return decision(input.model, cached.providers, cached.bar, "cache", void 0, true, cached.input ?? void 0);
|
|
34522
34129
|
}
|
|
34523
|
-
let
|
|
34130
|
+
let failure;
|
|
34524
34131
|
try {
|
|
34525
34132
|
const doFetch = input.fetchImpl ?? fetch;
|
|
34526
34133
|
const response = await doFetch(`${OPENROUTER_ENDPOINTS_BASE_URL}/${input.model}/endpoints`, {
|
|
@@ -34546,12 +34153,12 @@ async function resolveUptimeRouting(input) {
|
|
|
34546
34153
|
}).catch(() => void 0);
|
|
34547
34154
|
return decision(input.model, selected.providers, selected.bar, "live", void 0, true, modelInput);
|
|
34548
34155
|
} catch (error) {
|
|
34549
|
-
|
|
34156
|
+
failure = error instanceof Error ? error.message : String(error);
|
|
34550
34157
|
}
|
|
34551
34158
|
if (cached) {
|
|
34552
|
-
return decision(input.model, cached.providers, cached.bar, "stale-cache", `api unreachable: ${
|
|
34159
|
+
return decision(input.model, cached.providers, cached.bar, "stale-cache", `api unreachable: ${failure}`, true, cached.input ?? void 0);
|
|
34553
34160
|
}
|
|
34554
|
-
return decision(input.model, OPENROUTER_FALLBACK_PROVIDERS, null, "fallback", `api unreachable: ${
|
|
34161
|
+
return decision(input.model, OPENROUTER_FALLBACK_PROVIDERS, null, "fallback", `api unreachable: ${failure}`);
|
|
34555
34162
|
}
|
|
34556
34163
|
var inFlightProbes = /* @__PURE__ */ new Map();
|
|
34557
34164
|
function answeringProviders(probe, candidates) {
|
|
@@ -34927,7 +34534,7 @@ async function repairRoomAgentCredentialLinks(input) {
|
|
|
34927
34534
|
if (!existsSync7(source))
|
|
34928
34535
|
continue;
|
|
34929
34536
|
const target = resolve21(root, credential.dir, credential.target);
|
|
34930
|
-
await mkdir11(
|
|
34537
|
+
await mkdir11(dirname13(target), { recursive: true, mode: 448 });
|
|
34931
34538
|
const stats = await lstat3(target).catch((error) => {
|
|
34932
34539
|
if (isMissingPathError(error))
|
|
34933
34540
|
return void 0;
|
|
@@ -34935,11 +34542,11 @@ async function repairRoomAgentCredentialLinks(input) {
|
|
|
34935
34542
|
});
|
|
34936
34543
|
if (stats?.isSymbolicLink()) {
|
|
34937
34544
|
const linked = await readlink(target);
|
|
34938
|
-
if (resolve21(
|
|
34545
|
+
if (resolve21(dirname13(target), linked) === source)
|
|
34939
34546
|
continue;
|
|
34940
34547
|
}
|
|
34941
34548
|
if (stats) {
|
|
34942
|
-
const quarantine = `${target}.beeline-quarantine-${Date.now()}-${
|
|
34549
|
+
const quarantine = `${target}.beeline-quarantine-${Date.now()}-${randomUUID8()}`;
|
|
34943
34550
|
await rename5(target, quarantine);
|
|
34944
34551
|
}
|
|
34945
34552
|
await symlink2(source, target);
|
|
@@ -35392,12 +34999,12 @@ function readJsonObject(path) {
|
|
|
35392
34999
|
}
|
|
35393
35000
|
}
|
|
35394
35001
|
async function provisionManagedSkillsDir(target, managedSkills, sharedSkills, optionalShares) {
|
|
35395
|
-
const parent =
|
|
35396
|
-
await assertRealContainedDirectory(parent,
|
|
35002
|
+
const parent = dirname13(target);
|
|
35003
|
+
await assertRealContainedDirectory(parent, dirname13(parent));
|
|
35397
35004
|
const plan = await planManagedSkills(managedSkills, sharedSkills, optionalShares);
|
|
35398
35005
|
if (await materializedSkillManifest(target) === plan.manifest)
|
|
35399
35006
|
return;
|
|
35400
|
-
const staged = resolve21(parent, `.skills.${process.pid}.${
|
|
35007
|
+
const staged = resolve21(parent, `.skills.${process.pid}.${randomUUID8()}.tmp`);
|
|
35401
35008
|
await mkdir11(staged, { mode: 448 });
|
|
35402
35009
|
try {
|
|
35403
35010
|
for (const entry of plan.entries) {
|
|
@@ -35433,8 +35040,8 @@ async function planManagedSkills(managedSkills, sharedSkills, optionalShares) {
|
|
|
35433
35040
|
try {
|
|
35434
35041
|
const tree = [];
|
|
35435
35042
|
await walkSafeSkillTree(shared.source, shared.source, {
|
|
35436
|
-
directory: async (rel) => void tree.push(`d ${
|
|
35437
|
-
file: async (rel, realPath) => void tree.push(`f ${
|
|
35043
|
+
directory: async (rel) => void tree.push(`d ${join10(shared.name, rel)}`),
|
|
35044
|
+
file: async (rel, realPath) => void tree.push(`f ${join10(shared.name, rel)} ${sha2563(await readFile16(realPath))}`)
|
|
35438
35045
|
});
|
|
35439
35046
|
entries.push({ kind: "shared", name: shared.name, source: shared.source });
|
|
35440
35047
|
lines.push(...tree);
|
|
@@ -35454,7 +35061,7 @@ async function materializedSkillManifest(target) {
|
|
|
35454
35061
|
const visit = async (directory, prefix) => {
|
|
35455
35062
|
for (const entry of await readdir5(directory)) {
|
|
35456
35063
|
const path = resolve21(directory, entry);
|
|
35457
|
-
const rel = prefix ?
|
|
35064
|
+
const rel = prefix ? join10(prefix, entry) : entry;
|
|
35458
35065
|
const entryStats = await lstat3(path);
|
|
35459
35066
|
if (entryStats.isSymbolicLink())
|
|
35460
35067
|
return false;
|
|
@@ -35622,7 +35229,7 @@ async function walkSafeSkillTree(source, sourceRoot, visitor, rel = "") {
|
|
|
35622
35229
|
for (const entry of await readdir5(resolvedSource)) {
|
|
35623
35230
|
if (entry === "." || entry === "..")
|
|
35624
35231
|
throw new Error("invalid shared skill entry");
|
|
35625
|
-
await walkSafeSkillTree(resolve21(source, entry), sourceRoot, visitor, rel ?
|
|
35232
|
+
await walkSafeSkillTree(resolve21(source, entry), sourceRoot, visitor, rel ? join10(rel, entry) : entry);
|
|
35626
35233
|
}
|
|
35627
35234
|
return;
|
|
35628
35235
|
}
|
|
@@ -35644,12 +35251,12 @@ async function copySafeSkillTree(source, target, sourceRoot) {
|
|
|
35644
35251
|
});
|
|
35645
35252
|
}
|
|
35646
35253
|
async function writeIsolatedHarnessFile(path, content) {
|
|
35647
|
-
const parent =
|
|
35254
|
+
const parent = dirname13(path);
|
|
35648
35255
|
const parentStats = await lstat3(parent);
|
|
35649
35256
|
if (!parentStats.isDirectory() || parentStats.isSymbolicLink()) {
|
|
35650
35257
|
throw new Error(`isolated harness parent is not a real directory: ${parent}`);
|
|
35651
35258
|
}
|
|
35652
|
-
const temporary = resolve21(parent, `.${basename4(path)}.${process.pid}.${
|
|
35259
|
+
const temporary = resolve21(parent, `.${basename4(path)}.${process.pid}.${randomUUID8()}.tmp`);
|
|
35653
35260
|
try {
|
|
35654
35261
|
await writeFile11(temporary, content, { mode: 384, flag: "wx" });
|
|
35655
35262
|
await chmod5(temporary, 384);
|
|
@@ -35717,7 +35324,7 @@ function agentCommandCatalogPublisher(input) {
|
|
|
35717
35324
|
|
|
35718
35325
|
// apps/body/dist/attachment-delivery.js
|
|
35719
35326
|
import { mkdir as mkdir12, writeFile as writeFile12 } from "node:fs/promises";
|
|
35720
|
-
import { basename as basename5, extname, join as
|
|
35327
|
+
import { basename as basename5, extname, join as join11 } from "node:path";
|
|
35721
35328
|
var MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024;
|
|
35722
35329
|
var EXPIRED_REASON = "expired: these attachment bytes are past their retention window";
|
|
35723
35330
|
var FETCH_TIMEOUT_MS = 3e4;
|
|
@@ -35776,7 +35383,7 @@ async function deliverAttachments(attachments, dir, fetchImpl = fetch) {
|
|
|
35776
35383
|
return { attachment, reason: EXPIRED_REASON };
|
|
35777
35384
|
if (!fetched.ok)
|
|
35778
35385
|
throw new Error(`HTTP ${fetched.status}`);
|
|
35779
|
-
const path =
|
|
35386
|
+
const path = join11(dir, safeFileName(attachment, index, taken));
|
|
35780
35387
|
await writeFile12(path, fetched.bytes);
|
|
35781
35388
|
const bytes = fetched.bytes;
|
|
35782
35389
|
const mimeType = attachment.mimeType ?? fetched.mimeType;
|
|
@@ -36711,288 +36318,7 @@ function isMcpShapedPermissionRequest(request, hostServers = CODE_OWNED_HOST_MCP
|
|
|
36711
36318
|
return /^mcp__[^_].*__[^_]/.test(title) || /^mcp\.[^.]+\.[^.]/.test(title);
|
|
36712
36319
|
}
|
|
36713
36320
|
|
|
36714
|
-
// apps/body/dist/youtube-mcp.js
|
|
36715
|
-
import { createInterface as createInterface6 } from "node:readline";
|
|
36716
|
-
import { readFileSync as readFileSync8 } from "node:fs";
|
|
36717
|
-
var YOUTUBE_MCP_SERVER_NAME = "youtube";
|
|
36718
|
-
var YOUTUBE_MCP_SURFACE = "youtube";
|
|
36719
|
-
var dateProps = {
|
|
36720
|
-
startDate: { type: "string", description: "YYYY-MM-DD. Defaults to 28 days ago." },
|
|
36721
|
-
endDate: { type: "string", description: "YYYY-MM-DD. Defaults to today (UTC)." }
|
|
36722
|
-
};
|
|
36723
|
-
var analyticsOwnerNote = ` ${YOUTUBE_ANALYTICS_OWNER_LIMIT}`;
|
|
36724
|
-
var YOUTUBE_MCP_TOOLS = [
|
|
36725
|
-
{
|
|
36726
|
-
name: "youtube_get_channel",
|
|
36727
|
-
description: "Get the signed-in channel (id, title, handle, subscribers).",
|
|
36728
|
-
inputSchema: { type: "object", properties: {}, additionalProperties: false }
|
|
36729
|
-
},
|
|
36730
|
-
{
|
|
36731
|
-
name: "youtube_list_videos",
|
|
36732
|
-
description: "List videos on the signed-in channel.",
|
|
36733
|
-
inputSchema: { type: "object", properties: {}, additionalProperties: false }
|
|
36734
|
-
},
|
|
36735
|
-
{
|
|
36736
|
-
name: "youtube_get_video",
|
|
36737
|
-
description: "Get one video\u2019s title, description, and view count.",
|
|
36738
|
-
inputSchema: {
|
|
36739
|
-
type: "object",
|
|
36740
|
-
required: ["videoId"],
|
|
36741
|
-
properties: { videoId: { type: "string", minLength: 1 } },
|
|
36742
|
-
additionalProperties: false
|
|
36743
|
-
}
|
|
36744
|
-
},
|
|
36745
|
-
{
|
|
36746
|
-
name: "youtube_list_playlists",
|
|
36747
|
-
description: "List playlists on the signed-in channel.",
|
|
36748
|
-
inputSchema: { type: "object", properties: {}, additionalProperties: false }
|
|
36749
|
-
},
|
|
36750
|
-
{
|
|
36751
|
-
name: "youtube_list_playlist_items",
|
|
36752
|
-
description: "List videos in one playlist.",
|
|
36753
|
-
inputSchema: {
|
|
36754
|
-
type: "object",
|
|
36755
|
-
required: ["playlistId"],
|
|
36756
|
-
properties: { playlistId: { type: "string", minLength: 1 } },
|
|
36757
|
-
additionalProperties: false
|
|
36758
|
-
}
|
|
36759
|
-
},
|
|
36760
|
-
{
|
|
36761
|
-
name: "youtube_get_transcript",
|
|
36762
|
-
description: "Fetch captions for a video when a public timedtext track exists.",
|
|
36763
|
-
inputSchema: {
|
|
36764
|
-
type: "object",
|
|
36765
|
-
required: ["videoId"],
|
|
36766
|
-
properties: { videoId: { type: "string", minLength: 1 } },
|
|
36767
|
-
additionalProperties: false
|
|
36768
|
-
}
|
|
36769
|
-
},
|
|
36770
|
-
{
|
|
36771
|
-
name: "youtube_analytics_overview",
|
|
36772
|
-
description: `Channel views, watch time, subscribers, likes for a date range.${analyticsOwnerNote}`,
|
|
36773
|
-
inputSchema: { type: "object", properties: dateProps, additionalProperties: false }
|
|
36774
|
-
},
|
|
36775
|
-
{
|
|
36776
|
-
name: "youtube_analytics_top_videos",
|
|
36777
|
-
description: `Top long-form videos by views (excludes Shorts).${analyticsOwnerNote}`,
|
|
36778
|
-
inputSchema: {
|
|
36779
|
-
type: "object",
|
|
36780
|
-
properties: {
|
|
36781
|
-
...dateProps,
|
|
36782
|
-
maxResults: { type: "integer", minimum: 1, maximum: 25 }
|
|
36783
|
-
},
|
|
36784
|
-
additionalProperties: false
|
|
36785
|
-
}
|
|
36786
|
-
},
|
|
36787
|
-
{
|
|
36788
|
-
name: "youtube_analytics_traffic_sources",
|
|
36789
|
-
description: `How viewers found the channel (search, suggested, browse\u2026).${analyticsOwnerNote}`,
|
|
36790
|
-
inputSchema: { type: "object", properties: dateProps, additionalProperties: false }
|
|
36791
|
-
},
|
|
36792
|
-
{
|
|
36793
|
-
name: "youtube_analytics_demographics",
|
|
36794
|
-
description: `Audience age-group and gender breakdown.${analyticsOwnerNote}`,
|
|
36795
|
-
inputSchema: { type: "object", properties: dateProps, additionalProperties: false }
|
|
36796
|
-
}
|
|
36797
|
-
];
|
|
36798
|
-
function stringArg2(args, key) {
|
|
36799
|
-
const value = args[key];
|
|
36800
|
-
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
36801
|
-
}
|
|
36802
|
-
function dateArgs(args) {
|
|
36803
|
-
const startDate = stringArg2(args, "startDate");
|
|
36804
|
-
const endDate = stringArg2(args, "endDate");
|
|
36805
|
-
if (startDate && endDate)
|
|
36806
|
-
return { startDate, endDate };
|
|
36807
|
-
return defaultAnalyticsDateRange();
|
|
36808
|
-
}
|
|
36809
|
-
function youtubeClientFromToken(accessToken) {
|
|
36810
|
-
return googleWorkspaceClient(credentialsTokenSource({ accessToken }));
|
|
36811
|
-
}
|
|
36812
|
-
async function callYoutubeTool(name, args, client) {
|
|
36813
|
-
try {
|
|
36814
|
-
return JSON.stringify(await invokeYoutubeTool(name, args, client));
|
|
36815
|
-
} catch (error) {
|
|
36816
|
-
if (error instanceof GoogleApiError && error.status === 403 && name.startsWith("youtube_analytics_")) {
|
|
36817
|
-
throw new Error(YOUTUBE_ANALYTICS_OWNER_LIMIT);
|
|
36818
|
-
}
|
|
36819
|
-
throw error;
|
|
36820
|
-
}
|
|
36821
|
-
}
|
|
36822
|
-
async function invokeYoutubeTool(name, args, client) {
|
|
36823
|
-
switch (name) {
|
|
36824
|
-
case "youtube_get_channel":
|
|
36825
|
-
return client.youtube.getChannel(true);
|
|
36826
|
-
case "youtube_list_videos":
|
|
36827
|
-
return client.youtube.listVideos();
|
|
36828
|
-
case "youtube_get_video": {
|
|
36829
|
-
const videoId = stringArg2(args, "videoId");
|
|
36830
|
-
if (!videoId)
|
|
36831
|
-
throw new Error("videoId is required");
|
|
36832
|
-
return client.youtube.getVideo(videoId);
|
|
36833
|
-
}
|
|
36834
|
-
case "youtube_list_playlists":
|
|
36835
|
-
return client.youtube.listPlaylists(true);
|
|
36836
|
-
case "youtube_list_playlist_items": {
|
|
36837
|
-
const playlistId = stringArg2(args, "playlistId");
|
|
36838
|
-
if (!playlistId)
|
|
36839
|
-
throw new Error("playlistId is required");
|
|
36840
|
-
return client.youtube.listPlaylistItems(playlistId);
|
|
36841
|
-
}
|
|
36842
|
-
case "youtube_get_transcript": {
|
|
36843
|
-
const videoId = stringArg2(args, "videoId");
|
|
36844
|
-
if (!videoId)
|
|
36845
|
-
throw new Error("videoId is required");
|
|
36846
|
-
return client.youtube.getTranscript(videoId);
|
|
36847
|
-
}
|
|
36848
|
-
case "youtube_analytics_overview":
|
|
36849
|
-
return client.youtube.analyticsQuery({
|
|
36850
|
-
metrics: "views,estimatedMinutesWatched,averageViewDuration,subscribersGained,subscribersLost,likes,comments,shares",
|
|
36851
|
-
...dateArgs(args)
|
|
36852
|
-
});
|
|
36853
|
-
case "youtube_analytics_top_videos":
|
|
36854
|
-
return client.youtube.analyticsQuery({
|
|
36855
|
-
metrics: "views,estimatedMinutesWatched,averageViewDuration,likes,comments,shares",
|
|
36856
|
-
dimensions: "video",
|
|
36857
|
-
filters: "creatorContentType==video_on_demand",
|
|
36858
|
-
sort: "-views",
|
|
36859
|
-
maxResults: typeof args.maxResults === "number" ? args.maxResults : 20,
|
|
36860
|
-
...dateArgs(args)
|
|
36861
|
-
});
|
|
36862
|
-
case "youtube_analytics_traffic_sources":
|
|
36863
|
-
return client.youtube.analyticsQuery({
|
|
36864
|
-
metrics: "views,estimatedMinutesWatched",
|
|
36865
|
-
dimensions: "insightTrafficSourceType",
|
|
36866
|
-
sort: "-views",
|
|
36867
|
-
...dateArgs(args)
|
|
36868
|
-
});
|
|
36869
|
-
case "youtube_analytics_demographics":
|
|
36870
|
-
return client.youtube.analyticsQuery({
|
|
36871
|
-
metrics: "viewerPercentage",
|
|
36872
|
-
dimensions: "ageGroup,gender",
|
|
36873
|
-
sort: "-viewerPercentage",
|
|
36874
|
-
...dateArgs(args)
|
|
36875
|
-
});
|
|
36876
|
-
default:
|
|
36877
|
-
throw new Error(`unknown YouTube tool: ${name}`);
|
|
36878
|
-
}
|
|
36879
|
-
}
|
|
36880
|
-
function youtubeAccessToken(env = process.env) {
|
|
36881
|
-
let token = env.BEELINE_YOUTUBE_ACCESS_TOKEN?.trim();
|
|
36882
|
-
const path = env.BEELINE_GOOGLE_CREDENTIALS_PATH;
|
|
36883
|
-
if (path) {
|
|
36884
|
-
try {
|
|
36885
|
-
const stored = JSON.parse(readFileSync8(path, "utf8"));
|
|
36886
|
-
token = stored.accessToken?.trim();
|
|
36887
|
-
} catch {
|
|
36888
|
-
token = void 0;
|
|
36889
|
-
}
|
|
36890
|
-
}
|
|
36891
|
-
if (!token) {
|
|
36892
|
-
throw new Error("YouTube is not signed in on this helper. Connect Google Workspace from the Workbench \u2014 the same in-app sign-in, not a second overlay.");
|
|
36893
|
-
}
|
|
36894
|
-
return token;
|
|
36895
|
-
}
|
|
36896
|
-
function asObject(value) {
|
|
36897
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
36898
|
-
}
|
|
36899
|
-
function send(message) {
|
|
36900
|
-
process.stdout.write(`${JSON.stringify(message)}
|
|
36901
|
-
`);
|
|
36902
|
-
}
|
|
36903
|
-
function success(id, result) {
|
|
36904
|
-
send({ jsonrpc: "2.0", id: id ?? null, result });
|
|
36905
|
-
}
|
|
36906
|
-
function failure(id, code, message) {
|
|
36907
|
-
send({ jsonrpc: "2.0", id: id ?? null, error: { code, message } });
|
|
36908
|
-
}
|
|
36909
|
-
async function handleYoutubeMcpLine(line, clientFactory = () => youtubeClientFromToken(youtubeAccessToken())) {
|
|
36910
|
-
let request;
|
|
36911
|
-
try {
|
|
36912
|
-
request = JSON.parse(line);
|
|
36913
|
-
} catch {
|
|
36914
|
-
failure(null, -32700, "invalid JSON");
|
|
36915
|
-
return;
|
|
36916
|
-
}
|
|
36917
|
-
if (request.id === void 0)
|
|
36918
|
-
return;
|
|
36919
|
-
try {
|
|
36920
|
-
if (request.method === "initialize") {
|
|
36921
|
-
const params = asObject(request.params);
|
|
36922
|
-
success(request.id, {
|
|
36923
|
-
protocolVersion: typeof params.protocolVersion === "string" ? params.protocolVersion : "2024-11-05",
|
|
36924
|
-
capabilities: { tools: {} },
|
|
36925
|
-
serverInfo: { name: YOUTUBE_MCP_SERVER_NAME, version: "1.0.0" }
|
|
36926
|
-
});
|
|
36927
|
-
return;
|
|
36928
|
-
}
|
|
36929
|
-
if (request.method === "ping") {
|
|
36930
|
-
success(request.id, {});
|
|
36931
|
-
return;
|
|
36932
|
-
}
|
|
36933
|
-
if (request.method === "tools/list") {
|
|
36934
|
-
success(request.id, { tools: YOUTUBE_MCP_TOOLS });
|
|
36935
|
-
return;
|
|
36936
|
-
}
|
|
36937
|
-
if (request.method === "tools/call") {
|
|
36938
|
-
const params = asObject(request.params);
|
|
36939
|
-
if (typeof params.name !== "string")
|
|
36940
|
-
throw new Error("tool name must be a string");
|
|
36941
|
-
try {
|
|
36942
|
-
const output = await callYoutubeTool(params.name, asObject(params.arguments), clientFactory());
|
|
36943
|
-
success(request.id, { content: [{ type: "text", text: output }] });
|
|
36944
|
-
} catch (error) {
|
|
36945
|
-
success(request.id, {
|
|
36946
|
-
content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }],
|
|
36947
|
-
isError: true
|
|
36948
|
-
});
|
|
36949
|
-
}
|
|
36950
|
-
return;
|
|
36951
|
-
}
|
|
36952
|
-
failure(request.id, -32601, `method not found: ${request.method ?? ""}`);
|
|
36953
|
-
} catch (error) {
|
|
36954
|
-
failure(request.id, -32602, error instanceof Error ? error.message : String(error));
|
|
36955
|
-
}
|
|
36956
|
-
}
|
|
36957
|
-
function listenYoutubeMcpStdio() {
|
|
36958
|
-
const lines = createInterface6({ input: process.stdin, crlfDelay: Infinity });
|
|
36959
|
-
lines.on("line", (line) => void handleYoutubeMcpLine(line));
|
|
36960
|
-
}
|
|
36961
|
-
if (/(?:^|\/)youtube-mcp\.(?:js|mjs|ts)$/.test(process.argv[1] ?? "")) {
|
|
36962
|
-
listenYoutubeMcpStdio();
|
|
36963
|
-
}
|
|
36964
|
-
|
|
36965
|
-
// apps/body/dist/google-drive-mcp.js
|
|
36966
|
-
var GOOGLE_DRIVE_MCP_SURFACE = "google-drive";
|
|
36967
|
-
var GOOGLE_DRIVE_MCP_SERVER_NAME = "google-drive";
|
|
36968
|
-
|
|
36969
36321
|
// apps/body/dist/room-session.js
|
|
36970
|
-
function googleDriveMcpServer(config, accessToken, resourceAuthFile) {
|
|
36971
|
-
if (!accessToken || !config.readonlyMcpCommand)
|
|
36972
|
-
return void 0;
|
|
36973
|
-
const server = {
|
|
36974
|
-
name: GOOGLE_DRIVE_MCP_SERVER_NAME,
|
|
36975
|
-
command: config.readonlyMcpCommand,
|
|
36976
|
-
args: [...config.readonlyMcpArgs ?? []],
|
|
36977
|
-
env: [
|
|
36978
|
-
{ name: "BEELINE_MCP_SURFACE", value: GOOGLE_DRIVE_MCP_SURFACE },
|
|
36979
|
-
{ name: "BEELINE_GOOGLE_DRIVE_ACCESS_TOKEN", value: accessToken }
|
|
36980
|
-
]
|
|
36981
|
-
};
|
|
36982
|
-
if (!resourceAuthFile)
|
|
36983
|
-
return server;
|
|
36984
|
-
const route = rewriteHostMcpDeclaration(server.name, {
|
|
36985
|
-
command: server.command,
|
|
36986
|
-
args: server.args,
|
|
36987
|
-
env: Object.fromEntries((server.env ?? []).map((entry) => [entry.name, entry.value]))
|
|
36988
|
-
}, config.operatorHome ?? "", resourceAuthFile);
|
|
36989
|
-
return {
|
|
36990
|
-
name: server.name,
|
|
36991
|
-
command: String(route.command),
|
|
36992
|
-
args: route.args,
|
|
36993
|
-
env: Object.entries(route.env).map(([name, value]) => ({ name, value }))
|
|
36994
|
-
};
|
|
36995
|
-
}
|
|
36996
36322
|
var ReadOnlyToolsUnavailableError = class extends Error {
|
|
36997
36323
|
name = "ReadOnlyToolsUnavailableError";
|
|
36998
36324
|
};
|
|
@@ -37049,79 +36375,18 @@ function readOnlyMcpServer(config, cwd, agentMemoryDir) {
|
|
|
37049
36375
|
]
|
|
37050
36376
|
};
|
|
37051
36377
|
}
|
|
37052
|
-
function youtubeMcpServer(config, accessToken, resourceAuthFile) {
|
|
37053
|
-
if (!accessToken || !config.readonlyMcpCommand)
|
|
37054
|
-
return void 0;
|
|
37055
|
-
const server = {
|
|
37056
|
-
name: YOUTUBE_MCP_SERVER_NAME,
|
|
37057
|
-
command: config.readonlyMcpCommand,
|
|
37058
|
-
args: [...config.readonlyMcpArgs ?? []],
|
|
37059
|
-
env: [
|
|
37060
|
-
{ name: "BEELINE_MCP_SURFACE", value: YOUTUBE_MCP_SURFACE },
|
|
37061
|
-
{ name: "BEELINE_YOUTUBE_ACCESS_TOKEN", value: accessToken },
|
|
37062
|
-
{
|
|
37063
|
-
name: "BEELINE_GOOGLE_CREDENTIALS_PATH",
|
|
37064
|
-
value: resolve23(process.env.BEELINE_AGENT_HOME ?? process.cwd(), "google-credentials.json")
|
|
37065
|
-
}
|
|
37066
|
-
]
|
|
37067
|
-
};
|
|
37068
|
-
if (!resourceAuthFile)
|
|
37069
|
-
return server;
|
|
37070
|
-
const route = rewriteHostMcpDeclaration(server.name, {
|
|
37071
|
-
command: server.command,
|
|
37072
|
-
args: server.args,
|
|
37073
|
-
env: Object.fromEntries((server.env ?? []).map((entry) => [entry.name, entry.value]))
|
|
37074
|
-
}, config.operatorHome ?? "", resourceAuthFile);
|
|
37075
|
-
return {
|
|
37076
|
-
name: server.name,
|
|
37077
|
-
command: String(route.command),
|
|
37078
|
-
args: route.args,
|
|
37079
|
-
env: Object.entries(route.env).map(([name, value]) => ({ name, value }))
|
|
37080
|
-
};
|
|
37081
|
-
}
|
|
37082
|
-
|
|
37083
|
-
// apps/body/dist/room-google-grant.js
|
|
37084
|
-
import { createHash as createHash8 } from "node:crypto";
|
|
37085
|
-
async function roomGoogleToolTokens(api, roomId) {
|
|
37086
|
-
try {
|
|
37087
|
-
let timeout;
|
|
37088
|
-
const grant = await Promise.race([
|
|
37089
|
-
api.execute("getRoomGoogleGrant", { roomId }),
|
|
37090
|
-
new Promise((_resolve, reject) => {
|
|
37091
|
-
timeout = setTimeout(() => reject(new Error("Google grant lookup timed out")), 3e3);
|
|
37092
|
-
})
|
|
37093
|
-
]).finally(() => {
|
|
37094
|
-
if (timeout)
|
|
37095
|
-
clearTimeout(timeout);
|
|
37096
|
-
});
|
|
37097
|
-
if (grant.status !== "ready" || !grant.credentials)
|
|
37098
|
-
return {};
|
|
37099
|
-
const { accessToken, scopes } = grant.credentials;
|
|
37100
|
-
const types = grant.connectedTypes ?? [];
|
|
37101
|
-
const hasScopes = (type) => GOOGLE_TOOL_SCOPES[type].every((scope) => scopes.includes(scope));
|
|
37102
|
-
return {
|
|
37103
|
-
...(types.includes("google-gmail") || types.includes("google-drive")) && hasScopes("google-drive") ? { drive: accessToken } : {},
|
|
37104
|
-
...types.includes("google-youtube") && hasScopes("google-youtube") ? { youtube: accessToken } : {}
|
|
37105
|
-
};
|
|
37106
|
-
} catch {
|
|
37107
|
-
return {};
|
|
37108
|
-
}
|
|
37109
|
-
}
|
|
37110
|
-
function roomGoogleToolFingerprint(tokens) {
|
|
37111
|
-
return Object.entries(tokens).map(([name, token]) => `google-${name}:${createHash8("sha256").update(token).digest("hex")}`);
|
|
37112
|
-
}
|
|
37113
36378
|
|
|
37114
36379
|
// apps/body/dist/codegraph.js
|
|
37115
36380
|
import { execFile as execFile10 } from "node:child_process";
|
|
37116
36381
|
import { access as access2, appendFile, mkdir as mkdir14, readFile as readFile17 } from "node:fs/promises";
|
|
37117
|
-
import { dirname as
|
|
36382
|
+
import { dirname as dirname14, isAbsolute as isAbsolute3, resolve as resolve24 } from "node:path";
|
|
37118
36383
|
import { promisify as promisify6 } from "node:util";
|
|
37119
36384
|
var execFileAsync6 = promisify6(execFile10);
|
|
37120
36385
|
var CODEGRAPH_MCP_SERVER_NAME = "codegraph";
|
|
37121
36386
|
var CODEGRAPH_INDEX_PATH = ".codegraph/codegraph.db";
|
|
37122
36387
|
var CODEGRAPH_PREPARE_TIMEOUT_MS = 12e4;
|
|
37123
36388
|
function codegraphIndexDirectory(cwd) {
|
|
37124
|
-
return resolve24(cwd,
|
|
36389
|
+
return resolve24(cwd, dirname14(CODEGRAPH_INDEX_PATH));
|
|
37125
36390
|
}
|
|
37126
36391
|
function codegraphMcpServer(config, cwd, options) {
|
|
37127
36392
|
if (!config.codegraphCommand)
|
|
@@ -37162,7 +36427,7 @@ async function excludeIndexFromGitStatus(cwd) {
|
|
|
37162
36427
|
if (!gitPath)
|
|
37163
36428
|
return;
|
|
37164
36429
|
const path = isAbsolute3(gitPath) ? gitPath : resolve24(cwd, gitPath);
|
|
37165
|
-
await mkdir14(
|
|
36430
|
+
await mkdir14(dirname14(path), { recursive: true });
|
|
37166
36431
|
const existing = await readFile17(path, "utf8").catch(() => "");
|
|
37167
36432
|
if (existing.split("\n").includes(".codegraph/"))
|
|
37168
36433
|
return;
|
|
@@ -37255,6 +36520,57 @@ function isAccountOrProviderRefusal(record6) {
|
|
|
37255
36520
|
// apps/body/dist/monolith-corner-turn.js
|
|
37256
36521
|
init_runtime();
|
|
37257
36522
|
|
|
36523
|
+
// apps/body/dist/transcript-budget.js
|
|
36524
|
+
function budgetTranscript(lines, modelContextTokens, otherPromptBytes) {
|
|
36525
|
+
const context = modelContextTokens && modelContextTokens > 0 ? modelContextTokens : 32768;
|
|
36526
|
+
const reserveTokens = Math.max(4096, Math.ceil(context * 0.3));
|
|
36527
|
+
const available = Math.max(0, context - Math.ceil(otherPromptBytes / 2) - reserveTokens);
|
|
36528
|
+
const budget = Math.max(0, Math.min(24e3, Math.floor(context * 0.25), available * 2) - 128);
|
|
36529
|
+
if (!budget)
|
|
36530
|
+
return [];
|
|
36531
|
+
const selected = [];
|
|
36532
|
+
let used = 0;
|
|
36533
|
+
const rowLimit = Math.min(4096, Math.floor(budget / 2));
|
|
36534
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
36535
|
+
const row = boundMessageText(lines[index], rowLimit);
|
|
36536
|
+
const bytes = Buffer.byteLength(row) + 1;
|
|
36537
|
+
if (used + bytes > budget)
|
|
36538
|
+
break;
|
|
36539
|
+
selected.push(row);
|
|
36540
|
+
used += bytes;
|
|
36541
|
+
}
|
|
36542
|
+
selected.reverse();
|
|
36543
|
+
if (selected.length < lines.length) {
|
|
36544
|
+
selected.unshift(`[${lines.length - selected.length} older messages omitted from this prompt]`);
|
|
36545
|
+
}
|
|
36546
|
+
return selected;
|
|
36547
|
+
}
|
|
36548
|
+
function boundRoomTaskBody(body, modelContextTokens) {
|
|
36549
|
+
const context = modelContextTokens && modelContextTokens > 0 ? modelContextTokens : 32768;
|
|
36550
|
+
return boundMessageText(body, Math.min(8e3, Math.floor(context / 4)));
|
|
36551
|
+
}
|
|
36552
|
+
function boundMessageText(original, maxBytes) {
|
|
36553
|
+
const sanitized = stripInlineData(original);
|
|
36554
|
+
const clean4 = sanitized === original ? original : sanitized + fetchPointer(original, "inline content omitted");
|
|
36555
|
+
return Buffer.byteLength(clean4) > maxBytes ? truncateRow(clean4, maxBytes) : clean4;
|
|
36556
|
+
}
|
|
36557
|
+
function stripInlineData(text2) {
|
|
36558
|
+
return text2.replace(/data:[^\s"'<>)]*/gi, "[inline data omitted]").replace(/\b[A-Za-z0-9+/]{512,}={0,2}\b/g, (candidate) => /[A-Z]/.test(candidate) && /[a-z]/.test(candidate) && /[0-9+/]/.test(candidate) ? "[inline binary data omitted]" : candidate);
|
|
36559
|
+
}
|
|
36560
|
+
function truncateRow(row, maxBytes) {
|
|
36561
|
+
const pointer = fetchPointer(row, "message truncated");
|
|
36562
|
+
const contentBytes = Math.max(0, maxBytes - Buffer.byteLength(pointer));
|
|
36563
|
+
let prefix = Buffer.from(row).subarray(0, contentBytes).toString("utf8");
|
|
36564
|
+
prefix = prefix.replace(/\uFFFD$/, "");
|
|
36565
|
+
return prefix + pointer;
|
|
36566
|
+
}
|
|
36567
|
+
function fetchPointer(row, reason) {
|
|
36568
|
+
const id = /^\[message id: ([^\]\n]+)\]/.exec(row)?.[1];
|
|
36569
|
+
return id ? `
|
|
36570
|
+
[${reason}; call get_room_message with messageId "${id}" and offset 0 for the full text]` : `
|
|
36571
|
+
[${reason}; read the source conversation for the full text]`;
|
|
36572
|
+
}
|
|
36573
|
+
|
|
37258
36574
|
// apps/body/dist/prompt-assembly.js
|
|
37259
36575
|
var PROMPT_SURFACES = [
|
|
37260
36576
|
"room",
|
|
@@ -37756,7 +37072,23 @@ ${task.body}`,
|
|
|
37756
37072
|
}
|
|
37757
37073
|
];
|
|
37758
37074
|
function assembleTurnPrompt(context) {
|
|
37759
|
-
const
|
|
37075
|
+
const boundedContext = ROOMS.includes(context.surface) ? {
|
|
37076
|
+
...context,
|
|
37077
|
+
task: {
|
|
37078
|
+
...context.task,
|
|
37079
|
+
body: boundRoomTaskBody(context.task.body, context.modelContextTokens)
|
|
37080
|
+
}
|
|
37081
|
+
} : context;
|
|
37082
|
+
const withoutTranscript = applicable(TURN_SECTIONS, {
|
|
37083
|
+
...boundedContext,
|
|
37084
|
+
transcript: void 0
|
|
37085
|
+
});
|
|
37086
|
+
const otherBytes = withoutTranscript.reduce((sum, entry) => sum + Buffer.byteLength(entry.text) + 2, 0);
|
|
37087
|
+
const lines = budgetTranscript(boundedContext.transcript?.lines ?? [], boundedContext.modelContextTokens, otherBytes);
|
|
37088
|
+
const entries = applicable(TURN_SECTIONS, {
|
|
37089
|
+
...boundedContext,
|
|
37090
|
+
transcript: boundedContext.transcript ? { ...boundedContext.transcript, lines } : void 0
|
|
37091
|
+
});
|
|
37760
37092
|
return {
|
|
37761
37093
|
text: entries.map((entry) => entry.text).join("\n\n"),
|
|
37762
37094
|
report: entries.map(({ section, text: text2 }) => ({
|
|
@@ -38264,10 +37596,10 @@ process.exit(result.status ?? 1);
|
|
|
38264
37596
|
}
|
|
38265
37597
|
|
|
38266
37598
|
// apps/body/dist/warm-node-modules.js
|
|
38267
|
-
import { createHash as
|
|
38268
|
-
import { constants as
|
|
37599
|
+
import { createHash as createHash8, randomUUID as randomUUID9 } from "node:crypto";
|
|
37600
|
+
import { constants as fsConstants3 } from "node:fs";
|
|
38269
37601
|
import { chmod as chmod7, copyFile as copyFile2, link, lstat as lstat4, mkdir as mkdir17, readdir as readdir7, readFile as readFile18, readlink as readlink2, rename as rename6, rm as rm8, stat as stat6, symlink as symlink3, utimes } from "node:fs/promises";
|
|
38270
|
-
import { dirname as
|
|
37602
|
+
import { dirname as dirname15, join as join12, resolve as resolve27 } from "node:path";
|
|
38271
37603
|
var STORE_FORMAT = "v1";
|
|
38272
37604
|
var STAGING_PREFIX = ".beeline-warm-";
|
|
38273
37605
|
var STAGING_SWEEP_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -38303,7 +37635,7 @@ async function readWarmPlan(worktreePath) {
|
|
|
38303
37635
|
const unsafe = trees.find((tree) => !isContainedTreePath(tree));
|
|
38304
37636
|
if (unsafe)
|
|
38305
37637
|
return { failure: "unsafe-lockfile", detail: unsafe };
|
|
38306
|
-
const key =
|
|
37638
|
+
const key = createHash8("sha256").update(`${STORE_FORMAT}\0${process.platform}\0${process.arch}\0${process.versions.modules}\0`).update(lockfile).digest("hex").slice(0, 32);
|
|
38307
37639
|
return { key, trees };
|
|
38308
37640
|
}
|
|
38309
37641
|
function nodeModulesTreePaths(packages) {
|
|
@@ -38341,7 +37673,7 @@ async function seedWarmNodeModules(input) {
|
|
|
38341
37673
|
if (storeDevice === void 0 || storeDevice !== checkoutDevice) {
|
|
38342
37674
|
return { reason: "cross-device", key: plan.key };
|
|
38343
37675
|
}
|
|
38344
|
-
const staging = resolve27(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${
|
|
37676
|
+
const staging = resolve27(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID9()}`);
|
|
38345
37677
|
const placed = [];
|
|
38346
37678
|
const now2 = (input.now ?? Date.now)();
|
|
38347
37679
|
try {
|
|
@@ -38352,7 +37684,7 @@ async function seedWarmNodeModules(input) {
|
|
|
38352
37684
|
}
|
|
38353
37685
|
for (const tree of plan.trees) {
|
|
38354
37686
|
const target = resolve27(input.worktreePath, tree);
|
|
38355
|
-
await mkdir17(
|
|
37687
|
+
await mkdir17(dirname15(target), { recursive: true });
|
|
38356
37688
|
await rename6(resolve27(staging, tree), target);
|
|
38357
37689
|
placed.push(target);
|
|
38358
37690
|
}
|
|
@@ -38387,7 +37719,7 @@ async function harvestWarmNodeModules(input) {
|
|
|
38387
37719
|
detail: `${missing.length} absent, e.g. ${missing.slice(0, 3).join(", ")}`
|
|
38388
37720
|
};
|
|
38389
37721
|
}
|
|
38390
|
-
const staging = resolve27(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${
|
|
37722
|
+
const staging = resolve27(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID9()}`);
|
|
38391
37723
|
try {
|
|
38392
37724
|
await mkdir17(input.storeRoot, { recursive: true, mode: 493 });
|
|
38393
37725
|
await sweepStaleStaging(input.storeRoot, (input.now ?? Date.now)());
|
|
@@ -38413,7 +37745,7 @@ async function stagedTreeIsPublishable(worktreePath, staging, key) {
|
|
|
38413
37745
|
const settled = await readWarmPlan(worktreePath);
|
|
38414
37746
|
if (isPlanRefusal(settled) || settled.key !== key)
|
|
38415
37747
|
return false;
|
|
38416
|
-
const hidden =
|
|
37748
|
+
const hidden = join12("node_modules", ".package-lock.json");
|
|
38417
37749
|
const [copied, current] = await Promise.all([
|
|
38418
37750
|
readFile18(resolve27(staging, hidden)).catch(() => void 0),
|
|
38419
37751
|
readFile18(resolve27(worktreePath, hidden)).catch(() => void 0)
|
|
@@ -38451,7 +37783,7 @@ async function missingInstalledPackages(worktreePath, treeRoot = worktreePath) {
|
|
|
38451
37783
|
return missing.sort();
|
|
38452
37784
|
}
|
|
38453
37785
|
async function isInstalledPackage(path) {
|
|
38454
|
-
return stat6(
|
|
37786
|
+
return stat6(join12(path, "package.json")).then((info) => info.isFile(), () => false);
|
|
38455
37787
|
}
|
|
38456
37788
|
var INTEGRITY_READ_CONCURRENCY = 64;
|
|
38457
37789
|
async function mapWithLimit(values, limit, visit) {
|
|
@@ -38485,8 +37817,8 @@ function isContainedTreePath(value) {
|
|
|
38485
37817
|
async function cloneTree(source, target, file, topLevel = true) {
|
|
38486
37818
|
await mkdir17(target, { recursive: true, mode: 493 });
|
|
38487
37819
|
for (const entry of await readdir7(source, { withFileTypes: true })) {
|
|
38488
|
-
const from =
|
|
38489
|
-
const to =
|
|
37820
|
+
const from = join12(source, entry.name);
|
|
37821
|
+
const to = join12(target, entry.name);
|
|
38490
37822
|
if (entry.isSymbolicLink()) {
|
|
38491
37823
|
await symlink3(await readlink2(from), to);
|
|
38492
37824
|
continue;
|
|
@@ -38500,7 +37832,7 @@ async function cloneTree(source, target, file, topLevel = true) {
|
|
|
38500
37832
|
}
|
|
38501
37833
|
}
|
|
38502
37834
|
var harvestFile = async (source, target) => {
|
|
38503
|
-
await copyFile2(source, target,
|
|
37835
|
+
await copyFile2(source, target, fsConstants3.COPYFILE_FICLONE);
|
|
38504
37836
|
const info = await stat6(source);
|
|
38505
37837
|
await chmod7(target, info.mode & 4095 & ~146);
|
|
38506
37838
|
};
|
|
@@ -38516,13 +37848,13 @@ async function pruneWarmStore(storeRoot, keep) {
|
|
|
38516
37848
|
const names = (await readdir7(storeRoot).catch(() => [])).filter((name) => !name.startsWith(STAGING_PREFIX));
|
|
38517
37849
|
const entries = [];
|
|
38518
37850
|
for (const name of names) {
|
|
38519
|
-
const info = await lstat4(
|
|
37851
|
+
const info = await lstat4(join12(storeRoot, name)).catch(() => void 0);
|
|
38520
37852
|
if (info?.isDirectory())
|
|
38521
37853
|
entries.push({ name, usedAt: info.mtimeMs });
|
|
38522
37854
|
}
|
|
38523
37855
|
const dropped = entries.sort((a2, b) => b.usedAt - a2.usedAt || a2.name.localeCompare(b.name)).slice(keep);
|
|
38524
37856
|
for (const entry of dropped) {
|
|
38525
|
-
await rm8(
|
|
37857
|
+
await rm8(join12(storeRoot, entry.name), { recursive: true, force: true }).catch(() => void 0);
|
|
38526
37858
|
}
|
|
38527
37859
|
return dropped.map((entry) => entry.name);
|
|
38528
37860
|
}
|
|
@@ -38531,7 +37863,7 @@ async function sweepStaleStaging(storeRoot, now2) {
|
|
|
38531
37863
|
for (const name of entries) {
|
|
38532
37864
|
if (!name.startsWith(STAGING_PREFIX))
|
|
38533
37865
|
continue;
|
|
38534
|
-
const path =
|
|
37866
|
+
const path = join12(storeRoot, name);
|
|
38535
37867
|
const info = await lstat4(path).catch(() => void 0);
|
|
38536
37868
|
if (!info || now2 - info.mtimeMs < STAGING_SWEEP_MS)
|
|
38537
37869
|
continue;
|
|
@@ -38692,7 +38024,7 @@ function filePaths(value, worktreePath) {
|
|
|
38692
38024
|
visit(value);
|
|
38693
38025
|
return [...paths];
|
|
38694
38026
|
}
|
|
38695
|
-
function
|
|
38027
|
+
function resultStatus2(call) {
|
|
38696
38028
|
const content = record5(call.content) ?? (typeof call.content === "string" ? (() => {
|
|
38697
38029
|
try {
|
|
38698
38030
|
return record5(JSON.parse(call.content));
|
|
@@ -38721,7 +38053,7 @@ function spentAuthorityOnLaneUpgrade(call) {
|
|
|
38721
38053
|
return /(?:^|[._:/-])upgrade_corner_to_code$/i.test(call.title ?? "") && isCompletedToolCall(call);
|
|
38722
38054
|
}
|
|
38723
38055
|
function toolCallKey(call, index) {
|
|
38724
|
-
return call.id ? `id-${
|
|
38056
|
+
return call.id ? `id-${createHash9("sha256").update(call.id).digest("hex")}` : `tool-${index}`;
|
|
38725
38057
|
}
|
|
38726
38058
|
function toolCallSettled(call) {
|
|
38727
38059
|
if (call.resultReceived)
|
|
@@ -38753,7 +38085,7 @@ async function cornerToolActivity(call, worktreePath, requestedBy) {
|
|
|
38753
38085
|
kind: "tool",
|
|
38754
38086
|
title: title.slice(0, 240),
|
|
38755
38087
|
operation: operation.slice(0, 80),
|
|
38756
|
-
status:
|
|
38088
|
+
status: resultStatus2(call),
|
|
38757
38089
|
...argumentsSummary,
|
|
38758
38090
|
...output ? { output } : {},
|
|
38759
38091
|
...requestedBy ? { requestedBy } : {},
|
|
@@ -38964,14 +38296,13 @@ var MonolithCornerTurnLoop = class {
|
|
|
38964
38296
|
return await this.currentSessionFingerprint() === this.sessionFingerprint;
|
|
38965
38297
|
}
|
|
38966
38298
|
async currentSessionFingerprint() {
|
|
38967
|
-
const [configuration, roster, grantedHostRoutes
|
|
38299
|
+
const [configuration, roster, grantedHostRoutes] = await Promise.all([
|
|
38968
38300
|
this.options.api.execute("getAgentConfiguration", {
|
|
38969
38301
|
agentId: this.agent.publicKey,
|
|
38970
38302
|
roomId: this.options.cornerId
|
|
38971
38303
|
}),
|
|
38972
38304
|
this.roster(),
|
|
38973
|
-
this.grantedHostRoutes()
|
|
38974
|
-
roomGoogleToolTokens(this.options.api, this.options.cornerId)
|
|
38305
|
+
this.grantedHostRoutes()
|
|
38975
38306
|
]);
|
|
38976
38307
|
const self = roster.members.find((member) => member.identityId === this.agent.publicKey);
|
|
38977
38308
|
const registryRoutes = configuration.registryMcpRoutes ?? [];
|
|
@@ -38991,8 +38322,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
38991
38322
|
...registryRoutes.map((route) => route.routeName)
|
|
38992
38323
|
]
|
|
38993
38324
|
}),
|
|
38994
|
-
...registryRoutes.map((route) => route.routeName)
|
|
38995
|
-
...roomGoogleToolFingerprint(googleTokens)
|
|
38325
|
+
...registryRoutes.map((route) => route.routeName)
|
|
38996
38326
|
], this.sessionCodegraphReady),
|
|
38997
38327
|
reviewerHandle: configuration.reviewerHandle
|
|
38998
38328
|
});
|
|
@@ -39027,14 +38357,13 @@ var MonolithCornerTurnLoop = class {
|
|
|
39027
38357
|
return this.sessionId;
|
|
39028
38358
|
}
|
|
39029
38359
|
trace?.noteActivation("cold");
|
|
39030
|
-
const [configuration, roster, grantedHostRoutes
|
|
38360
|
+
const [configuration, roster, grantedHostRoutes] = await Promise.all([
|
|
39031
38361
|
this.options.api.execute("getAgentConfiguration", {
|
|
39032
38362
|
agentId: this.agent.publicKey,
|
|
39033
38363
|
roomId: this.options.cornerId
|
|
39034
38364
|
}),
|
|
39035
38365
|
this.roster(),
|
|
39036
|
-
this.grantedHostRoutes()
|
|
39037
|
-
roomGoogleToolTokens(this.options.api, this.options.cornerId)
|
|
38366
|
+
this.grantedHostRoutes()
|
|
39038
38367
|
]);
|
|
39039
38368
|
const self = roster.members.find((member) => member.identityId === this.agent.publicKey);
|
|
39040
38369
|
this.yoloMode = configuration.yoloMode;
|
|
@@ -39074,7 +38403,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
39074
38403
|
}) ? { relay: await this.squireRelay.listen() } : {}
|
|
39075
38404
|
};
|
|
39076
38405
|
const resourceAuthFile = `${this.commandContext.path}.resource-auth.json`;
|
|
39077
|
-
await mkdir18(
|
|
38406
|
+
await mkdir18(dirname16(resourceAuthFile), { recursive: true, mode: 448 });
|
|
39078
38407
|
await writeFile14(resourceAuthFile, JSON.stringify({
|
|
39079
38408
|
...this.options.api.connection(),
|
|
39080
38409
|
turnContextPath: this.commandContext.path
|
|
@@ -39141,7 +38470,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
39141
38470
|
args: this.options.config.agentArgs ?? []
|
|
39142
38471
|
}, selection);
|
|
39143
38472
|
const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
|
|
39144
|
-
this.attachmentDir = tmpDir ?
|
|
38473
|
+
this.attachmentDir = tmpDir ? join13(tmpDir, "beeline-attachments") : void 0;
|
|
39145
38474
|
this.sessionScratchDir = tmpDir;
|
|
39146
38475
|
const homeStateDirs = harnessHomeStateDirs(harnessLabel, agentEnv.HOME ?? operatorHome);
|
|
39147
38476
|
await Promise.all(homeStateDirs.map((dir) => mkdir18(dir, { recursive: true })));
|
|
@@ -39210,8 +38539,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
39210
38539
|
agentKind: this.options.config.agentKind,
|
|
39211
38540
|
grantedHostRoutes: mountedHostRoutes
|
|
39212
38541
|
}),
|
|
39213
|
-
...Object.keys(registryHostDeclarations)
|
|
39214
|
-
...roomGoogleToolFingerprint(googleTokens)
|
|
38542
|
+
...Object.keys(registryHostDeclarations)
|
|
39215
38543
|
], codegraphReady),
|
|
39216
38544
|
reviewerHandle: configuration.reviewerHandle
|
|
39217
38545
|
});
|
|
@@ -39259,12 +38587,6 @@ var MonolithCornerTurnLoop = class {
|
|
|
39259
38587
|
if (codegraph)
|
|
39260
38588
|
servers.push(codegraph);
|
|
39261
38589
|
}
|
|
39262
|
-
const youtube = youtubeMcpServer(this.options.config, googleTokens.youtube, resourceAuthFile);
|
|
39263
|
-
if (youtube)
|
|
39264
|
-
servers.push(youtube);
|
|
39265
|
-
const drive = googleDriveMcpServer(this.options.config, googleTokens.drive, resourceAuthFile);
|
|
39266
|
-
if (drive)
|
|
39267
|
-
servers.push(drive);
|
|
39268
38590
|
const grantedRouteServers = grantedHostRouteWires(mountedHostRoutes, operatorHome, { ...hostDeclarations, ...registryHostDeclarations }, resourceAuthFile, squireScope);
|
|
39269
38591
|
await installPiMcpBridge({
|
|
39270
38592
|
agentCommand: harnessLabel,
|
|
@@ -39484,10 +38806,10 @@ var MonolithCornerTurnLoop = class {
|
|
|
39484
38806
|
size: file.size
|
|
39485
38807
|
}));
|
|
39486
38808
|
const allAttachments = [...attachments, ...briefAttachments];
|
|
39487
|
-
const delivered = this.attachmentDir && allAttachments.length ? await deliverAttachments(allAttachments,
|
|
38809
|
+
const delivered = this.attachmentDir && allAttachments.length ? await deliverAttachments(allAttachments, join13(this.attachmentDir, requestId.replace(/[^\w-]/g, "_")), this.options.fetchImpl) : [];
|
|
39488
38810
|
const briefFileLines = await Promise.all((restored.brief?.attachments ?? []).map(async (file, index) => {
|
|
39489
38811
|
const entry = delivered.find((item) => item.attachment === briefAttachments[index]);
|
|
39490
|
-
const verified = entry?.path &&
|
|
38812
|
+
const verified = entry?.path && createHash9("sha256").update(await readFile19(entry.path)).digest("hex") === file.sha256;
|
|
39491
38813
|
return `- ${file.title} (${file.purpose}; ${file.required ? "required" : "optional"}; sha256 ${file.sha256}): ${verified ? entry.path : "UNAVAILABLE OR CONTENT MISMATCH"}`;
|
|
39492
38814
|
}));
|
|
39493
38815
|
const missingRequiredBriefFile = (restored.brief?.attachments ?? []).some((file, index) => file.required && briefFileLines[index]?.includes("UNAVAILABLE OR CONTENT MISMATCH"));
|
|
@@ -39763,9 +39085,9 @@ var MonolithCornerTurnLoop = class {
|
|
|
39763
39085
|
answer = durableReplyText(stream.remainderOf(result.agentText));
|
|
39764
39086
|
const reply = withNudgeReply(answer);
|
|
39765
39087
|
for (const call of result.toolCalls) {
|
|
39766
|
-
const
|
|
39767
|
-
if (
|
|
39768
|
-
console.warn(`[thin-core] corner ${cornerId} ${
|
|
39088
|
+
const failure = toolCallFailureLine(call);
|
|
39089
|
+
if (failure)
|
|
39090
|
+
console.warn(`[thin-core] corner ${cornerId} ${failure}`);
|
|
39769
39091
|
}
|
|
39770
39092
|
stream.close();
|
|
39771
39093
|
if (!reply && explained) {
|
|
@@ -39958,12 +39280,34 @@ var MonolithCornerTurnLoop = class {
|
|
|
39958
39280
|
// apps/body/dist/monolith-room-turn.js
|
|
39959
39281
|
import { mkdir as mkdir19, writeFile as writeFile15 } from "node:fs/promises";
|
|
39960
39282
|
import { homedir as homedir15, hostname as hostname2 } from "node:os";
|
|
39961
|
-
import { dirname as
|
|
39283
|
+
import { dirname as dirname17, join as join15 } from "node:path";
|
|
39962
39284
|
|
|
39963
39285
|
// packages/api-contract/dist/scheduled-prompts.js
|
|
39964
39286
|
var SCHEDULE_SCHEDULER_NAME = "Beeline Scheduler";
|
|
39965
39287
|
var SCHEDULE_RAN_VERB = "ran a schedule for";
|
|
39966
39288
|
|
|
39289
|
+
// apps/body/dist/model-context-window.js
|
|
39290
|
+
import { readFile as readFile20 } from "node:fs/promises";
|
|
39291
|
+
import { join as join14 } from "node:path";
|
|
39292
|
+
async function modelContextWindowTokens(model, piHome) {
|
|
39293
|
+
if (!model || !piHome)
|
|
39294
|
+
return void 0;
|
|
39295
|
+
try {
|
|
39296
|
+
const catalog = JSON.parse(await readFile20(join14(piHome, "models.json"), "utf8"));
|
|
39297
|
+
const parts = model.split("/");
|
|
39298
|
+
const preferredProvider = parts.length > 2 ? parts.shift() : void 0;
|
|
39299
|
+
const modelId = parts.join("/");
|
|
39300
|
+
const providers = preferredProvider ? [catalog.providers?.[preferredProvider]].filter(Boolean) : Object.values(catalog.providers ?? {});
|
|
39301
|
+
for (const provider of providers) {
|
|
39302
|
+
const window = provider?.models?.find((entry) => entry.id === modelId)?.contextWindow;
|
|
39303
|
+
if (window && Number.isFinite(window) && window > 0)
|
|
39304
|
+
return Math.floor(window);
|
|
39305
|
+
}
|
|
39306
|
+
} catch {
|
|
39307
|
+
}
|
|
39308
|
+
return void 0;
|
|
39309
|
+
}
|
|
39310
|
+
|
|
39967
39311
|
// apps/body/dist/monolith-room-turn.js
|
|
39968
39312
|
init_cursor_acp_bridge();
|
|
39969
39313
|
init_runtime();
|
|
@@ -40005,10 +39349,11 @@ function inboxItemAuthorName(item, names) {
|
|
|
40005
39349
|
function inboxItemPromptBody(item) {
|
|
40006
39350
|
return isScheduledPrompt(item) ? item.systemEvent?.consequence ?? item.body : item.body;
|
|
40007
39351
|
}
|
|
40008
|
-
function
|
|
40009
|
-
|
|
40010
|
-
|
|
40011
|
-
|
|
39352
|
+
function pendingCardKind(call) {
|
|
39353
|
+
const kind = /(?:^|[._:/-])(request_grant|offer_connector)$/i.exec(call.title ?? "")?.[1];
|
|
39354
|
+
if (!kind || !/(?:pending|already offered), card (?:posted|still open)/i.test(typeof call.content === "string" ? call.content : JSON.stringify(call.content ?? "")))
|
|
39355
|
+
return void 0;
|
|
39356
|
+
return kind.toLowerCase() === "request_grant" ? "grant" : "connector";
|
|
40012
39357
|
}
|
|
40013
39358
|
function resumePrompt(item) {
|
|
40014
39359
|
if (item.systemEvent?.kind === "connector-offer-decided") {
|
|
@@ -40071,6 +39416,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
40071
39416
|
queuedTurns = [];
|
|
40072
39417
|
/** Session scratch directory attachments are downloaded into (`TMPDIR/beeline-attachments`). */
|
|
40073
39418
|
attachmentDir;
|
|
39419
|
+
modelContextTokens;
|
|
40074
39420
|
/** Whether the pinned model takes images; `undefined` when the pin did not say. */
|
|
40075
39421
|
modelTakesImages;
|
|
40076
39422
|
/** The session's TMPDIR: writable to a granted command in a Room, as it is to the harness (C94). */
|
|
@@ -40085,6 +39431,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
40085
39431
|
memberNames = /* @__PURE__ */ new Map();
|
|
40086
39432
|
/** The request id of the turn that paused on a grant card, until its decision arrives. */
|
|
40087
39433
|
pausedOnGrantRequestId;
|
|
39434
|
+
pausedOnGrantKind;
|
|
40088
39435
|
/** Operator-local turn traces; built once when the daemon configured a directory. */
|
|
40089
39436
|
turnTraceSink;
|
|
40090
39437
|
constructor(options) {
|
|
@@ -40283,14 +39630,13 @@ var MonolithRoomTurnLoop = class {
|
|
|
40283
39630
|
});
|
|
40284
39631
|
}
|
|
40285
39632
|
async currentSessionFingerprint() {
|
|
40286
|
-
const [configuration, roster, grantedHostRoutes
|
|
39633
|
+
const [configuration, roster, grantedHostRoutes] = await Promise.all([
|
|
40287
39634
|
this.options.api.execute("getAgentConfiguration", {
|
|
40288
39635
|
agentId: this.agent.publicKey,
|
|
40289
39636
|
roomId: this.options.roomId
|
|
40290
39637
|
}),
|
|
40291
39638
|
this.roster(),
|
|
40292
|
-
this.grantedHostRoutes()
|
|
40293
|
-
roomGoogleToolTokens(this.options.api, this.options.roomId)
|
|
39639
|
+
this.grantedHostRoutes()
|
|
40294
39640
|
]);
|
|
40295
39641
|
const self = roster.members.find((member) => member.identityId === this.agent.publicKey);
|
|
40296
39642
|
const registryRoutes = configuration.registryMcpRoutes ?? [];
|
|
@@ -40309,8 +39655,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
40309
39655
|
...registryRoutes.map((route) => route.routeName)
|
|
40310
39656
|
]
|
|
40311
39657
|
}),
|
|
40312
|
-
...registryRoutes.map((route) => route.routeName)
|
|
40313
|
-
...roomGoogleToolFingerprint(googleTokens)
|
|
39658
|
+
...registryRoutes.map((route) => route.routeName)
|
|
40314
39659
|
], this.sessionCodegraphReady)
|
|
40315
39660
|
});
|
|
40316
39661
|
}
|
|
@@ -40352,15 +39697,14 @@ var MonolithRoomTurnLoop = class {
|
|
|
40352
39697
|
return this.sessionId;
|
|
40353
39698
|
}
|
|
40354
39699
|
trace?.noteActivation("cold");
|
|
40355
|
-
const [configuration, roster, repositoryState, grantedHostRoutes
|
|
39700
|
+
const [configuration, roster, repositoryState, grantedHostRoutes] = await Promise.all([
|
|
40356
39701
|
this.options.api.execute("getAgentConfiguration", {
|
|
40357
39702
|
agentId: this.agent.publicKey,
|
|
40358
39703
|
roomId: this.options.roomId
|
|
40359
39704
|
}),
|
|
40360
39705
|
this.roster(),
|
|
40361
39706
|
this.repositoryState(),
|
|
40362
|
-
this.grantedHostRoutes()
|
|
40363
|
-
roomGoogleToolTokens(this.options.api, this.options.roomId)
|
|
39707
|
+
this.grantedHostRoutes()
|
|
40364
39708
|
]);
|
|
40365
39709
|
const self = roster.members.find((member) => member.identityId === this.agent.publicKey);
|
|
40366
39710
|
const directMessage = Array.isArray(repositoryState.directParticipants) && repositoryState.directParticipants.length === 2;
|
|
@@ -40384,7 +39728,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
40384
39728
|
}) ? { relay: await this.squireRelay.listen() } : {}
|
|
40385
39729
|
};
|
|
40386
39730
|
const resourceAuthFile = `${this.commandContext.path}.resource-auth.json`;
|
|
40387
|
-
await mkdir19(
|
|
39731
|
+
await mkdir19(dirname17(resourceAuthFile), { recursive: true, mode: 448 });
|
|
40388
39732
|
await writeFile15(resourceAuthFile, JSON.stringify({
|
|
40389
39733
|
...this.options.api.connection(),
|
|
40390
39734
|
turnContextPath: this.commandContext.path
|
|
@@ -40415,6 +39759,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
40415
39759
|
});
|
|
40416
39760
|
const agentEnv = { ...this.options.config.agentEnv, ...homeOverlay };
|
|
40417
39761
|
this.agentEnv = agentEnv;
|
|
39762
|
+
this.modelContextTokens = await modelContextWindowTokens(selectionModel, agentEnv.PI_CODING_AGENT_DIR);
|
|
40418
39763
|
const agentArgs = agentArgsWithModelSelection({
|
|
40419
39764
|
kind: this.options.config.agentKind,
|
|
40420
39765
|
command,
|
|
@@ -40442,8 +39787,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
40442
39787
|
agentKind: this.options.config.agentKind,
|
|
40443
39788
|
grantedHostRoutes: mountedHostRoutes
|
|
40444
39789
|
}),
|
|
40445
|
-
...Object.keys(registryHostDeclarations)
|
|
40446
|
-
...roomGoogleToolFingerprint(googleTokens)
|
|
39790
|
+
...Object.keys(registryHostDeclarations)
|
|
40447
39791
|
], codegraphReady)
|
|
40448
39792
|
});
|
|
40449
39793
|
const spawnCommand = wrapAgentCommand({
|
|
@@ -40487,12 +39831,6 @@ var MonolithRoomTurnLoop = class {
|
|
|
40487
39831
|
if (codegraph)
|
|
40488
39832
|
servers.push(codegraph);
|
|
40489
39833
|
}
|
|
40490
|
-
const youtube = youtubeMcpServer(this.options.config, googleTokens.youtube, resourceAuthFile);
|
|
40491
|
-
if (youtube)
|
|
40492
|
-
servers.push(youtube);
|
|
40493
|
-
const drive = googleDriveMcpServer(this.options.config, googleTokens.drive, resourceAuthFile);
|
|
40494
|
-
if (drive)
|
|
40495
|
-
servers.push(drive);
|
|
40496
39834
|
const hostDeclarations = hostImportedMcpDeclarations({
|
|
40497
39835
|
operatorHome,
|
|
40498
39836
|
agentKind: this.options.config.agentKind
|
|
@@ -40672,6 +40010,10 @@ var MonolithRoomTurnLoop = class {
|
|
|
40672
40010
|
* the press and the delivery, and the server's own receipt already said so.
|
|
40673
40011
|
*/
|
|
40674
40012
|
stopTurn(requestId) {
|
|
40013
|
+
if (this.pausedOnGrantRequestId === requestId) {
|
|
40014
|
+
this.pausedOnGrantRequestId = void 0;
|
|
40015
|
+
this.pausedOnGrantKind = void 0;
|
|
40016
|
+
}
|
|
40675
40017
|
this.squireRelay.cancel(requestId);
|
|
40676
40018
|
for (let index = this.queuedTurns.length - 1; index >= 0; index -= 1)
|
|
40677
40019
|
if (this.queuedTurns[index].id === requestId)
|
|
@@ -40736,10 +40078,15 @@ var MonolithRoomTurnLoop = class {
|
|
|
40736
40078
|
authorId: message.authorId,
|
|
40737
40079
|
line: roomMessagePrompt(names.get(message.authorId) ?? message.authorId.slice(0, 12), message.body, message.attachments, this.deliveredAttachments.get(message.id), this.acceptsImages(), message.id)
|
|
40738
40080
|
}));
|
|
40739
|
-
const
|
|
40740
|
-
const
|
|
40741
|
-
|
|
40081
|
+
const command = this.commandContext.current;
|
|
40082
|
+
const grantDecision = command?.action === "resume";
|
|
40083
|
+
const decisionKind = command?.source.systemEvent?.kind;
|
|
40084
|
+
const decisionResume = grantDecision && command.turnRequestId === this.pausedOnGrantRequestId && (decisionKind === "grant-decided" && this.pausedOnGrantKind === "grant" || decisionKind === "connector-offer-decided" && this.pausedOnGrantKind === "connector");
|
|
40085
|
+
const resumedRequestId = decisionResume ? this.pausedOnGrantRequestId : void 0;
|
|
40086
|
+
if (decisionResume) {
|
|
40742
40087
|
this.pausedOnGrantRequestId = void 0;
|
|
40088
|
+
this.pausedOnGrantKind = void 0;
|
|
40089
|
+
}
|
|
40743
40090
|
const openCorners = (corners.corners ?? []).filter((corner) => !corner.archived);
|
|
40744
40091
|
const closedSince = Math.floor(Date.now() / 1e3) - 24 * 60 * 60;
|
|
40745
40092
|
const closedCorners = (corners.corners ?? []).filter((corner) => corner.archived && corner.closedAt !== void 0 && corner.closedAt >= closedSince).sort((a2, b) => (b.closedAt ?? 0) - (a2.closedAt ?? 0));
|
|
@@ -40747,6 +40094,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
40747
40094
|
const transcript = this.warmTranscript.select(this.sessionId, transcriptRows, this.agent.publicKey);
|
|
40748
40095
|
const assembled = assembleTurnPrompt({
|
|
40749
40096
|
surface: this.sessionSurface,
|
|
40097
|
+
modelContextTokens: this.modelContextTokens,
|
|
40750
40098
|
sessionPrefix: this.turnInstructionPrefix,
|
|
40751
40099
|
...institutionalContext.standingPreference ? {
|
|
40752
40100
|
standingPreference: {
|
|
@@ -40860,8 +40208,10 @@ var MonolithRoomTurnLoop = class {
|
|
|
40860
40208
|
throw new TurnStoppedError("turn stopped by the requester");
|
|
40861
40209
|
}
|
|
40862
40210
|
active.phase = "finishing";
|
|
40863
|
-
|
|
40211
|
+
const pendingCard = result.toolCalls.map((call) => pendingCardKind(call)).find(Boolean);
|
|
40212
|
+
if (pendingCard) {
|
|
40864
40213
|
this.pausedOnGrantRequestId = item.id;
|
|
40214
|
+
this.pausedOnGrantKind = pendingCard;
|
|
40865
40215
|
console.log(`[thin-core] monolith Room ${this.options.roomId} turn ${item.id} paused on a grant card`);
|
|
40866
40216
|
} else if (resumedRequestId) {
|
|
40867
40217
|
console.log(`[thin-core] monolith Room ${this.options.roomId} turn ${resumedRequestId} resumed by card decision ${item.id}`);
|
|
@@ -40872,9 +40222,9 @@ var MonolithRoomTurnLoop = class {
|
|
|
40872
40222
|
this.options.onCornerOpened?.();
|
|
40873
40223
|
}
|
|
40874
40224
|
for (const call of result?.toolCalls ?? []) {
|
|
40875
|
-
const
|
|
40876
|
-
if (
|
|
40877
|
-
console.warn(`[thin-core] monolith Room ${this.options.roomId} ${
|
|
40225
|
+
const failure = toolCallFailureLine(call);
|
|
40226
|
+
if (failure) {
|
|
40227
|
+
console.warn(`[thin-core] monolith Room ${this.options.roomId} ${failure}`);
|
|
40878
40228
|
}
|
|
40879
40229
|
}
|
|
40880
40230
|
stream.close();
|
|
@@ -40978,7 +40328,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
40978
40328
|
console.error("[thin-core] Room command failed", error);
|
|
40979
40329
|
},
|
|
40980
40330
|
onEnter: (command) => this.squireRelay.activate(command, this.commandContext.generationId),
|
|
40981
|
-
onLeave: (command) => this.squireRelay.deactivate(command.turnRequestId, this.pausedOnGrantRequestId
|
|
40331
|
+
onLeave: (command) => this.squireRelay.deactivate(command.turnRequestId, this.pausedOnGrantRequestId),
|
|
40982
40332
|
stop: (requestId) => this.stopTurn(requestId),
|
|
40983
40333
|
restart: () => this.options.onRestartRequested?.(),
|
|
40984
40334
|
canStartTurn: this.options.canStartTurn,
|
|
@@ -41535,8 +40885,8 @@ var DiscoveryWakes = class {
|
|
|
41535
40885
|
this.served = Math.max(this.served, covered);
|
|
41536
40886
|
}
|
|
41537
40887
|
};
|
|
41538
|
-
function shouldPostInitialCornerWorkingState(restore
|
|
41539
|
-
return
|
|
40888
|
+
function shouldPostInitialCornerWorkingState(restore) {
|
|
40889
|
+
return !restore.lifecycle?.branch && !restore.lifecycle?.pr;
|
|
41540
40890
|
}
|
|
41541
40891
|
function cornerBranchIsSafeToDelete(lifecycle) {
|
|
41542
40892
|
const pr = lifecycle?.pr;
|
|
@@ -41552,7 +40902,7 @@ function cornerStartConfigKey(repository, objective) {
|
|
|
41552
40902
|
}
|
|
41553
40903
|
function cornerRepositoryCacheDir(supervisorRoot, remote) {
|
|
41554
40904
|
const normalizedRemote = roomCheckoutRemote(remote);
|
|
41555
|
-
const repositoryHash =
|
|
40905
|
+
const repositoryHash = createHash10("sha256").update(normalizedRemote).digest("hex").slice(0, 24);
|
|
41556
40906
|
return resolve29(supervisorRoot, "beeline", "repositories", `${repositoryHash}.git`);
|
|
41557
40907
|
}
|
|
41558
40908
|
function isStandingCornerStartFault(error) {
|
|
@@ -41563,8 +40913,8 @@ async function materializeCornerWorktree(input) {
|
|
|
41563
40913
|
const remote = roomCheckoutRemote(input.remote);
|
|
41564
40914
|
const gitCommonDir = cornerRepositoryCacheDir(input.supervisorRoot, remote);
|
|
41565
40915
|
const path = resolve29(input.supervisorRoot, "beeline", "corners", input.cornerId);
|
|
41566
|
-
await mkdir20(
|
|
41567
|
-
await mkdir20(
|
|
40916
|
+
await mkdir20(dirname18(gitCommonDir), { recursive: true, mode: 448 });
|
|
40917
|
+
await mkdir20(dirname18(path), { recursive: true, mode: 448 });
|
|
41568
40918
|
const authEnv = githubGitEnv(input.token);
|
|
41569
40919
|
if (!existsSync8(resolve29(gitCommonDir, "HEAD"))) {
|
|
41570
40920
|
await execFileAsync8("git", ["clone", "--bare", remote, gitCommonDir], {
|
|
@@ -41645,6 +40995,34 @@ async function materializeCornerWorktree(input) {
|
|
|
41645
40995
|
}
|
|
41646
40996
|
return { path, gitCommonDir };
|
|
41647
40997
|
}
|
|
40998
|
+
async function cornerScratchFiles(root) {
|
|
40999
|
+
const files = [];
|
|
41000
|
+
const visit = async (directory, prefix) => {
|
|
41001
|
+
for (const entry of await readdir8(directory, { withFileTypes: true })) {
|
|
41002
|
+
const name = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
41003
|
+
if (entry.isDirectory())
|
|
41004
|
+
await visit(resolve29(directory, entry.name), name);
|
|
41005
|
+
else
|
|
41006
|
+
files.push(name);
|
|
41007
|
+
}
|
|
41008
|
+
};
|
|
41009
|
+
await visit(root, "");
|
|
41010
|
+
return files;
|
|
41011
|
+
}
|
|
41012
|
+
async function ignoredGitPaths(worktree, paths) {
|
|
41013
|
+
if (!paths.length)
|
|
41014
|
+
return /* @__PURE__ */ new Set();
|
|
41015
|
+
return new Promise((resolve40, reject) => {
|
|
41016
|
+
const child = execFile12("git", ["-C", worktree, "check-ignore", "-z", "--stdin"], { maxBuffer: 16 * 1024 * 1024 }, (error, stdout6) => {
|
|
41017
|
+
if (error && error.code !== 1)
|
|
41018
|
+
reject(error);
|
|
41019
|
+
else
|
|
41020
|
+
resolve40(new Set(stdout6.split("\0").filter(Boolean)));
|
|
41021
|
+
});
|
|
41022
|
+
child.stdin?.on("error", reject);
|
|
41023
|
+
child.stdin?.end(`${paths.join("\0")}\0`);
|
|
41024
|
+
});
|
|
41025
|
+
}
|
|
41648
41026
|
async function mapWithConcurrency(values, limit, visit) {
|
|
41649
41027
|
let cursor3 = 0;
|
|
41650
41028
|
await Promise.all(Array.from({ length: Math.min(limit, values.length) }, async () => {
|
|
@@ -41657,7 +41035,7 @@ async function mapWithConcurrency(values, limit, visit) {
|
|
|
41657
41035
|
async function discoverCornerWorktree(supervisorRoot, cornerId) {
|
|
41658
41036
|
const cornersRoot = resolve29(supervisorRoot, "beeline", "corners");
|
|
41659
41037
|
const path = resolve29(cornersRoot, cornerId);
|
|
41660
|
-
if (
|
|
41038
|
+
if (dirname18(path) !== cornersRoot || !existsSync8(resolve29(path, ".git")))
|
|
41661
41039
|
return void 0;
|
|
41662
41040
|
const [canonicalRoot, canonicalPath] = await Promise.all([
|
|
41663
41041
|
realpath2(cornersRoot),
|
|
@@ -41790,6 +41168,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
41790
41168
|
localWorktreeIds;
|
|
41791
41169
|
/** Event-driven cleanup retries stay scoped to the failed local corner. */
|
|
41792
41170
|
archiveCleanupFaults = /* @__PURE__ */ new Map();
|
|
41171
|
+
/** A refused local checkout is kept until a later Room listing proves membership again. */
|
|
41172
|
+
archiveCleanupAccessDenied = /* @__PURE__ */ new Set();
|
|
41793
41173
|
startingCorners = /* @__PURE__ */ new Set();
|
|
41794
41174
|
/**
|
|
41795
41175
|
* Rooms whose start is in flight. `running` is not set until the checkout
|
|
@@ -41986,12 +41366,16 @@ var RoomRuntimeCoordinator = class {
|
|
|
41986
41366
|
return turns;
|
|
41987
41367
|
}
|
|
41988
41368
|
async reconcile() {
|
|
41369
|
+
if (this.stopped)
|
|
41370
|
+
return "member";
|
|
41989
41371
|
this.confirmationPending = false;
|
|
41990
41372
|
const existingRooms = new Set(this.running.keys());
|
|
41991
41373
|
const coveredWakes = this.discoveryWakes.beginReconcile();
|
|
41992
41374
|
const bootstrap = await this.options.daemonApi.execute("getDaemonBootstrap", {
|
|
41993
41375
|
agentId: this.agent.publicKey
|
|
41994
41376
|
});
|
|
41377
|
+
if (this.stopped)
|
|
41378
|
+
return "member";
|
|
41995
41379
|
if (!bootstrap.workspaceIds.includes(this.runtime.communityId)) {
|
|
41996
41380
|
this.workspaceRemovalConfirmations += 1;
|
|
41997
41381
|
if (this.workspaceRemovalConfirmations < REMOVAL_CONFIRMATION_READS) {
|
|
@@ -42027,6 +41411,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
42027
41411
|
const desiredCorners = /* @__PURE__ */ new Map();
|
|
42028
41412
|
const archivedCorners = /* @__PURE__ */ new Map();
|
|
42029
41413
|
await mapWithConcurrency(topLevelRooms, ROOM_JOIN_CONCURRENCY, async (room) => {
|
|
41414
|
+
if (this.stopped)
|
|
41415
|
+
return;
|
|
42030
41416
|
try {
|
|
42031
41417
|
const result = await this.options.daemonApi.execute("listRoomCorners", {
|
|
42032
41418
|
roomId: room.roomId
|
|
@@ -42057,6 +41443,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
42057
41443
|
console.error(`[thin-core] monolith Room ${room.roomId} corner listing failed; keeping known corners:`, error);
|
|
42058
41444
|
}
|
|
42059
41445
|
});
|
|
41446
|
+
if (this.stopped)
|
|
41447
|
+
return "member";
|
|
42060
41448
|
for (const roomId of desiredTopRooms)
|
|
42061
41449
|
this.surfaceHealth.discover(roomId, "room");
|
|
42062
41450
|
for (const cornerId of desiredCorners.keys())
|
|
@@ -42064,7 +41452,11 @@ var RoomRuntimeCoordinator = class {
|
|
|
42064
41452
|
for (const channelId of desired)
|
|
42065
41453
|
this.roomRemovalConfirmations.delete(channelId);
|
|
42066
41454
|
await this.retryPendingCornerReaps(desired);
|
|
41455
|
+
if (this.stopped)
|
|
41456
|
+
return "member";
|
|
42067
41457
|
await this.sweepArchivedCornerWorktrees(archivedCorners, desired);
|
|
41458
|
+
if (this.stopped)
|
|
41459
|
+
return "member";
|
|
42068
41460
|
for (const cornerId of this.idleCornerSubscriptions.keys()) {
|
|
42069
41461
|
if (desired.has(cornerId))
|
|
42070
41462
|
continue;
|
|
@@ -42084,6 +41476,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
42084
41476
|
}
|
|
42085
41477
|
this.surfaceHealth.retain(/* @__PURE__ */ new Set([...desired, ...this.running.keys()]));
|
|
42086
41478
|
await mapWithConcurrency(desiredTopRooms, ROOM_JOIN_CONCURRENCY, async (roomId) => {
|
|
41479
|
+
if (this.stopped)
|
|
41480
|
+
return;
|
|
42087
41481
|
if (this.running.has(roomId))
|
|
42088
41482
|
return;
|
|
42089
41483
|
try {
|
|
@@ -42093,6 +41487,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
42093
41487
|
}
|
|
42094
41488
|
});
|
|
42095
41489
|
await mapWithConcurrency([...desiredCorners.values()], ROOM_JOIN_CONCURRENCY, async (corner) => {
|
|
41490
|
+
if (this.stopped)
|
|
41491
|
+
return;
|
|
42096
41492
|
if (!this.running.has(corner.cornerId))
|
|
42097
41493
|
await this.watchCorner(corner);
|
|
42098
41494
|
});
|
|
@@ -42134,6 +41530,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
42134
41530
|
* An unscoped wake still uses the slow reconcile as recovery.
|
|
42135
41531
|
*/
|
|
42136
41532
|
async applyMembershipEvent(event) {
|
|
41533
|
+
if (this.stopped)
|
|
41534
|
+
return;
|
|
42137
41535
|
const roomId = event.roomId;
|
|
42138
41536
|
if (!roomId) {
|
|
42139
41537
|
this.wakeDiscovery();
|
|
@@ -42179,22 +41577,24 @@ var RoomRuntimeCoordinator = class {
|
|
|
42179
41577
|
/** Retire the scratch runtime. Ordinary desired-state reconciliation starts
|
|
42180
41578
|
* the same corner id again and re-reads its now-code lane. */
|
|
42181
41579
|
async applyCornerRestart(cornerId) {
|
|
41580
|
+
if (this.stopped)
|
|
41581
|
+
return;
|
|
42182
41582
|
const running = this.running.get(cornerId);
|
|
42183
41583
|
if (!running) {
|
|
42184
41584
|
this.wakeDiscovery();
|
|
42185
41585
|
return;
|
|
42186
41586
|
}
|
|
42187
|
-
await this.stopRunning(cornerId, running);
|
|
41587
|
+
await this.stopRunning(cornerId, running, true);
|
|
42188
41588
|
this.wakeDiscovery();
|
|
42189
41589
|
}
|
|
42190
|
-
async stopRunning(channelId, running) {
|
|
41590
|
+
async stopRunning(channelId, running, preserveScratch = false) {
|
|
42191
41591
|
this.deferredRepositoryRestarts.delete(channelId);
|
|
42192
41592
|
running.controller.abort();
|
|
42193
41593
|
await running.promise.catch(() => void 0);
|
|
42194
41594
|
try {
|
|
42195
41595
|
if (running.worktree)
|
|
42196
41596
|
await this.reapCornerWorktree(running.worktree);
|
|
42197
|
-
else if (running.scratch)
|
|
41597
|
+
else if (running.scratch && !preserveScratch)
|
|
42198
41598
|
await this.reapCornerScratch(running.scratch);
|
|
42199
41599
|
} catch (error) {
|
|
42200
41600
|
console.error(`[thin-core] corner ${channelId} cleanup failed; will retry:`, error);
|
|
@@ -42205,7 +41605,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
42205
41605
|
return this.runtime.rooms.find((room) => room.channelId === roomId);
|
|
42206
41606
|
}
|
|
42207
41607
|
roomRoot(roomId) {
|
|
42208
|
-
return this.roomRecord(roomId)?.root ?? resolve29(
|
|
41608
|
+
return this.roomRecord(roomId)?.root ?? resolve29(dirname18(this.configPath), "rooms", roomId);
|
|
42209
41609
|
}
|
|
42210
41610
|
roomAgentHomeRoot(workspaceRoot, required = false) {
|
|
42211
41611
|
const flag = process.env.BUZZY_BODY_ROOM_HOME;
|
|
@@ -42215,7 +41615,7 @@ var RoomRuntimeCoordinator = class {
|
|
|
42215
41615
|
if (!required && flag !== "1" && !existsSync8(home) && existsSync8(workspaceRoot))
|
|
42216
41616
|
return void 0;
|
|
42217
41617
|
try {
|
|
42218
|
-
|
|
41618
|
+
mkdirSync3(home, { recursive: true, mode: 448 });
|
|
42219
41619
|
return home;
|
|
42220
41620
|
} catch (error) {
|
|
42221
41621
|
console.error(`[thin-core] per-room agent home unavailable at ${home}:`, error);
|
|
@@ -42228,9 +41628,9 @@ var RoomRuntimeCoordinator = class {
|
|
|
42228
41628
|
...this.baseConfig,
|
|
42229
41629
|
workspaceRoot,
|
|
42230
41630
|
agentPrivateRoot: resolve29(workspaceRoot, "agent-private"),
|
|
42231
|
-
agentMemoryRoot: resolve29(
|
|
42232
|
-
openRouterRoutingCacheDir: openRouterRoutingCacheDir(
|
|
42233
|
-
turnTraceDir: turnTraceDirectory(
|
|
41631
|
+
agentMemoryRoot: resolve29(dirname18(this.configPath), "memory"),
|
|
41632
|
+
openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname18(this.configPath)),
|
|
41633
|
+
turnTraceDir: turnTraceDirectory(dirname18(this.configPath)),
|
|
42234
41634
|
...agentHomeRoot ? { agentHomeRoot } : {}
|
|
42235
41635
|
};
|
|
42236
41636
|
}
|
|
@@ -42242,6 +41642,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
42242
41642
|
});
|
|
42243
41643
|
}
|
|
42244
41644
|
async startRoom(roomId) {
|
|
41645
|
+
if (this.stopped)
|
|
41646
|
+
return;
|
|
42245
41647
|
if (this.running.has(roomId) || this.startingRooms.has(roomId))
|
|
42246
41648
|
return;
|
|
42247
41649
|
this.surfaceHealth.discover(roomId, "room");
|
|
@@ -42322,9 +41724,9 @@ var RoomRuntimeCoordinator = class {
|
|
|
42322
41724
|
return this.roomRoot(roomId);
|
|
42323
41725
|
const remote = roomCheckoutRemote(repository.remote);
|
|
42324
41726
|
const targetBranch = repository.targetBranch || "main";
|
|
42325
|
-
const checkoutId =
|
|
41727
|
+
const checkoutId = createHash10("sha256").update(`${roomId}\0${remote}\0${targetBranch}`).digest("hex").slice(0, 24);
|
|
42326
41728
|
const path = resolve29(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
|
|
42327
|
-
await mkdir20(
|
|
41729
|
+
await mkdir20(dirname18(path), { recursive: true, mode: 448 });
|
|
42328
41730
|
const token = remote.startsWith("https://github.com/") ? await this.parentRepositoryToken(roomId) : void 0;
|
|
42329
41731
|
const env = token ? githubGitEnv(token.token) : process.env;
|
|
42330
41732
|
if (!existsSync8(resolve29(path, ".git"))) {
|
|
@@ -42372,6 +41774,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
42372
41774
|
}
|
|
42373
41775
|
}
|
|
42374
41776
|
async startCorner(corner) {
|
|
41777
|
+
if (this.stopped)
|
|
41778
|
+
return;
|
|
42375
41779
|
if (this.running.has(corner.cornerId) || this.startingCorners.has(corner.cornerId))
|
|
42376
41780
|
return;
|
|
42377
41781
|
this.surfaceHealth.discover(corner.cornerId, "corner");
|
|
@@ -42400,6 +41804,9 @@ var RoomRuntimeCoordinator = class {
|
|
|
42400
41804
|
if (!objective)
|
|
42401
41805
|
throw new Error("corner has no authoritative objective fact");
|
|
42402
41806
|
const repositoryBacked = repository.resolution === "repository" && restore.lane !== "no_code";
|
|
41807
|
+
const scratchPath = resolve29(this.roomRoot(corner.cornerId), "scratch");
|
|
41808
|
+
if (repositoryBacked && existsSync8(scratchPath) && !restore.featureBranch)
|
|
41809
|
+
throw new Error("promoted corner has no server-assigned feature branch");
|
|
42403
41810
|
const targetBranch = repositoryBacked ? repository.targetBranch || "main" : void 0;
|
|
42404
41811
|
const featureBranch = repositoryBacked ? restore.featureBranch ?? `feature/corner-${corner.cornerId.replaceAll("-", "").slice(0, 12)}` : void 0;
|
|
42405
41812
|
const granted = repositoryBacked ? await this.cornerRepositoryToken(corner.parentRoomId) : void 0;
|
|
@@ -42410,11 +41817,51 @@ var RoomRuntimeCoordinator = class {
|
|
|
42410
41817
|
featureBranch,
|
|
42411
41818
|
token: granted.token
|
|
42412
41819
|
}) : void 0;
|
|
41820
|
+
if (worktree) {
|
|
41821
|
+
if (existsSync8(scratchPath)) {
|
|
41822
|
+
const entries = await readdir8(scratchPath);
|
|
41823
|
+
if (entries.includes(".git"))
|
|
41824
|
+
throw new Error("corner scratch contains a Git repository");
|
|
41825
|
+
const files = await cornerScratchFiles(scratchPath);
|
|
41826
|
+
const baselineIgnored = await ignoredGitPaths(worktree.path, files);
|
|
41827
|
+
for (const entry of entries)
|
|
41828
|
+
await cp(resolve29(scratchPath, entry), resolve29(worktree.path, entry), {
|
|
41829
|
+
recursive: true,
|
|
41830
|
+
force: true
|
|
41831
|
+
});
|
|
41832
|
+
if (entries.length) {
|
|
41833
|
+
const scratchIgnored = await ignoredGitPaths(worktree.path, files);
|
|
41834
|
+
const stageable = files.filter((file) => !baselineIgnored.has(file) && !scratchIgnored.has(file));
|
|
41835
|
+
for (let offset = 0; offset < stageable.length; offset += 256)
|
|
41836
|
+
await execFileAsync8("git", [
|
|
41837
|
+
"-C",
|
|
41838
|
+
worktree.path,
|
|
41839
|
+
"add",
|
|
41840
|
+
"-A",
|
|
41841
|
+
"--",
|
|
41842
|
+
...stageable.slice(offset, offset + 256)
|
|
41843
|
+
]);
|
|
41844
|
+
const changed = await execFileAsync8("git", ["-C", worktree.path, "diff", "--cached", "--quiet"]).then(() => false, (error) => {
|
|
41845
|
+
if (error.code === 1)
|
|
41846
|
+
return true;
|
|
41847
|
+
throw error;
|
|
41848
|
+
});
|
|
41849
|
+
if (changed)
|
|
41850
|
+
await execFileAsync8("git", [
|
|
41851
|
+
"-C",
|
|
41852
|
+
worktree.path,
|
|
41853
|
+
"commit",
|
|
41854
|
+
"-m",
|
|
41855
|
+
"Carry no-code corner files into code branch"
|
|
41856
|
+
]);
|
|
41857
|
+
}
|
|
41858
|
+
await this.reapCornerScratch({ path: scratchPath, cornerId: corner.cornerId });
|
|
41859
|
+
}
|
|
41860
|
+
}
|
|
42413
41861
|
const workspacePath = worktree?.path ?? resolve29(this.roomRoot(corner.cornerId), "scratch");
|
|
42414
41862
|
if (!worktree)
|
|
42415
41863
|
await mkdir20(workspacePath, { recursive: true, mode: 448 });
|
|
42416
|
-
|
|
42417
|
-
if (worktree && shouldPostInitialCornerWorkingState(restore, isOpener)) {
|
|
41864
|
+
if (worktree && shouldPostInitialCornerWorkingState(restore)) {
|
|
42418
41865
|
await this.options.daemonApi.execute("postCornerRemoteState", {
|
|
42419
41866
|
cornerId: corner.cornerId,
|
|
42420
41867
|
branch: featureBranch,
|
|
@@ -42516,6 +41963,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
42516
41963
|
}
|
|
42517
41964
|
}
|
|
42518
41965
|
async watchCorner(corner) {
|
|
41966
|
+
if (this.stopped)
|
|
41967
|
+
return;
|
|
42519
41968
|
const cornerId = corner.cornerId;
|
|
42520
41969
|
if (this.running.has(cornerId))
|
|
42521
41970
|
return;
|
|
@@ -42700,6 +42149,9 @@ var RoomRuntimeCoordinator = class {
|
|
|
42700
42149
|
continue;
|
|
42701
42150
|
if (!this.archiveCleanupDue(cornerId))
|
|
42702
42151
|
continue;
|
|
42152
|
+
if (this.archiveCleanupAccessDenied.has(cornerId) && !corners.has(cornerId))
|
|
42153
|
+
continue;
|
|
42154
|
+
this.archiveCleanupAccessDenied.delete(cornerId);
|
|
42703
42155
|
let corner = corners.get(cornerId);
|
|
42704
42156
|
let discovered;
|
|
42705
42157
|
try {
|
|
@@ -42743,7 +42195,10 @@ var RoomRuntimeCoordinator = class {
|
|
|
42743
42195
|
});
|
|
42744
42196
|
console.log(`[thin-core] swept archived corner worktree ${cornerId}`);
|
|
42745
42197
|
} catch (error) {
|
|
42746
|
-
|
|
42198
|
+
if (error instanceof DaemonApiError && error.status === 403)
|
|
42199
|
+
this.archiveCleanupAccessDenied.add(cornerId);
|
|
42200
|
+
else
|
|
42201
|
+
this.deferArchiveCleanup(cornerId);
|
|
42747
42202
|
console.error(`[thin-core] archived corner ${cornerId} cleanup deferred:`, error);
|
|
42748
42203
|
}
|
|
42749
42204
|
}
|
|
@@ -42819,6 +42274,8 @@ var RoomRuntimeCoordinator = class {
|
|
|
42819
42274
|
room.backoffUntil = Math.max(room.backoffUntil, this.now() + retryInMs);
|
|
42820
42275
|
}
|
|
42821
42276
|
async watchdogTick() {
|
|
42277
|
+
if (this.stopped)
|
|
42278
|
+
return;
|
|
42822
42279
|
for (const [roomId, room] of [...this.running]) {
|
|
42823
42280
|
if (room.recovering || room.body.isBusy())
|
|
42824
42281
|
continue;
|
|
@@ -42829,17 +42286,25 @@ var RoomRuntimeCoordinator = class {
|
|
|
42829
42286
|
await room.promise.catch(() => void 0);
|
|
42830
42287
|
if (room.worktree) {
|
|
42831
42288
|
this.confirmationPending = true;
|
|
42832
|
-
} else if (!this.running.has(roomId)) {
|
|
42289
|
+
} else if (!this.stopped && !this.running.has(roomId)) {
|
|
42833
42290
|
this.startRoom(roomId);
|
|
42834
42291
|
}
|
|
42835
42292
|
}
|
|
42836
42293
|
}
|
|
42837
|
-
|
|
42294
|
+
beginShutdown() {
|
|
42295
|
+
if (this.stopped)
|
|
42296
|
+
return;
|
|
42838
42297
|
this.stopped = true;
|
|
42298
|
+
this.restartRequested = true;
|
|
42839
42299
|
for (const cornerId of this.idleCornerSubscriptions.keys())
|
|
42840
42300
|
this.unwatchCorner(cornerId);
|
|
42841
42301
|
this.options.daemonApi.closeLive?.();
|
|
42842
42302
|
this.pendingMembershipEvents.clear();
|
|
42303
|
+
for (const room of this.running.values())
|
|
42304
|
+
room.controller.abort();
|
|
42305
|
+
}
|
|
42306
|
+
async shutdown() {
|
|
42307
|
+
this.beginShutdown();
|
|
42843
42308
|
const deadlineAt = Math.min(this.now() + this.drainDeadlineMs, this.drainDeadlineAt ?? Number.POSITIVE_INFINITY);
|
|
42844
42309
|
const untilDeadline = async (work) => {
|
|
42845
42310
|
let timer;
|
|
@@ -43024,8 +42489,16 @@ var ThinDaemonCore = class {
|
|
|
43024
42489
|
this.roomRuntime.setDrainDeadlineAt(deadlineAt);
|
|
43025
42490
|
}
|
|
43026
42491
|
async run(opts = {}) {
|
|
43027
|
-
|
|
42492
|
+
const stop = () => {
|
|
42493
|
+
this.roomRuntime.setDrainDeadlineAt(Date.now() + 45e3);
|
|
42494
|
+
this.roomRuntime.beginShutdown();
|
|
42495
|
+
};
|
|
42496
|
+
opts.signal?.addEventListener("abort", stop, { once: true });
|
|
42497
|
+
if (opts.signal?.aborted)
|
|
42498
|
+
stop();
|
|
43028
42499
|
try {
|
|
42500
|
+
if (!opts.signal?.aborted)
|
|
42501
|
+
await opts.onEstablished?.();
|
|
43029
42502
|
while (!opts.signal?.aborted) {
|
|
43030
42503
|
this.pendingDiscovery = false;
|
|
43031
42504
|
try {
|
|
@@ -43040,19 +42513,46 @@ var ThinDaemonCore = class {
|
|
|
43040
42513
|
this.discoveryStatus = `monolith discovery degraded: ${error instanceof Error ? error.message : String(error)}`;
|
|
43041
42514
|
this.roomRuntime.reconnectAfterFailure();
|
|
43042
42515
|
}
|
|
42516
|
+
if (opts.signal?.aborted)
|
|
42517
|
+
break;
|
|
43043
42518
|
await opts.onProgress?.(this.healthStatus());
|
|
43044
42519
|
if (!this.pendingDiscovery)
|
|
43045
42520
|
await this.waitForDiscovery(opts.signal);
|
|
43046
42521
|
}
|
|
43047
42522
|
return "aborted";
|
|
43048
42523
|
} finally {
|
|
42524
|
+
opts.signal?.removeEventListener("abort", stop);
|
|
43049
42525
|
await this.roomRuntime.shutdown();
|
|
43050
42526
|
}
|
|
43051
42527
|
}
|
|
43052
42528
|
};
|
|
43053
42529
|
|
|
42530
|
+
// apps/body/dist/daemon-shutdown.js
|
|
42531
|
+
var DAEMON_HARD_STOP_MS = 75e3;
|
|
42532
|
+
function installDaemonStopSignals(controller, options = {}) {
|
|
42533
|
+
const emitter = options.emitter ?? process;
|
|
42534
|
+
let timer;
|
|
42535
|
+
const stop = () => {
|
|
42536
|
+
if (controller.signal.aborted)
|
|
42537
|
+
return;
|
|
42538
|
+
timer = setTimeout(() => {
|
|
42539
|
+
console.error("[thin-core] shutdown deadline reached; exiting old helper");
|
|
42540
|
+
(options.hardExit ?? (() => process.exit(0)))();
|
|
42541
|
+
}, options.timeoutMs ?? DAEMON_HARD_STOP_MS);
|
|
42542
|
+
controller.abort();
|
|
42543
|
+
};
|
|
42544
|
+
emitter.once("SIGINT", stop);
|
|
42545
|
+
emitter.once("SIGTERM", stop);
|
|
42546
|
+
return () => {
|
|
42547
|
+
if (timer)
|
|
42548
|
+
clearTimeout(timer);
|
|
42549
|
+
emitter.removeListener("SIGINT", stop);
|
|
42550
|
+
emitter.removeListener("SIGTERM", stop);
|
|
42551
|
+
};
|
|
42552
|
+
}
|
|
42553
|
+
|
|
43054
42554
|
// apps/body/dist/force-update-journal.js
|
|
43055
|
-
import { mkdirSync as
|
|
42555
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync8, renameSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
43056
42556
|
import { resolve as resolve30 } from "node:path";
|
|
43057
42557
|
var NAME = "force-update-interruptions.json";
|
|
43058
42558
|
function pathFor(runtimeDir) {
|
|
@@ -43060,7 +42560,7 @@ function pathFor(runtimeDir) {
|
|
|
43060
42560
|
}
|
|
43061
42561
|
function read(runtimeDir) {
|
|
43062
42562
|
try {
|
|
43063
|
-
const rows = JSON.parse(
|
|
42563
|
+
const rows = JSON.parse(readFileSync8(pathFor(runtimeDir), "utf8"));
|
|
43064
42564
|
if (!Array.isArray(rows))
|
|
43065
42565
|
throw new Error("invalid force-update interruption journal");
|
|
43066
42566
|
return rows.map((row) => {
|
|
@@ -43078,10 +42578,10 @@ function read(runtimeDir) {
|
|
|
43078
42578
|
}
|
|
43079
42579
|
}
|
|
43080
42580
|
function write(runtimeDir, rows) {
|
|
43081
|
-
|
|
42581
|
+
mkdirSync4(runtimeDir, { recursive: true, mode: 448 });
|
|
43082
42582
|
const target = pathFor(runtimeDir);
|
|
43083
42583
|
const temporary = `${target}.${process.pid}.tmp`;
|
|
43084
|
-
|
|
42584
|
+
writeFileSync3(temporary, `${JSON.stringify(rows)}
|
|
43085
42585
|
`, { mode: 384 });
|
|
43086
42586
|
renameSync(temporary, target);
|
|
43087
42587
|
}
|
|
@@ -43136,9 +42636,9 @@ init_runtime();
|
|
|
43136
42636
|
init_launchd();
|
|
43137
42637
|
init_systemd();
|
|
43138
42638
|
import { spawn as spawn11 } from "node:child_process";
|
|
43139
|
-
import { createHash as
|
|
42639
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
43140
42640
|
import { mkdir as mkdir23, rm as rm11, stat as stat7, writeFile as writeFile17 } from "node:fs/promises";
|
|
43141
|
-
import { dirname as
|
|
42641
|
+
import { dirname as dirname20, resolve as resolve33 } from "node:path";
|
|
43142
42642
|
|
|
43143
42643
|
// apps/body/dist/update-functional-probe.js
|
|
43144
42644
|
import { mkdir as mkdir21, rm as rm10 } from "node:fs/promises";
|
|
@@ -43406,8 +42906,8 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
43406
42906
|
}
|
|
43407
42907
|
let error = initialError;
|
|
43408
42908
|
let detail = error instanceof Error ? error.message : String(error);
|
|
43409
|
-
let
|
|
43410
|
-
if (
|
|
42909
|
+
let failure = classifyAcpTurnFailure(error);
|
|
42910
|
+
if (failure) {
|
|
43411
42911
|
await new Promise((resolveWait) => setTimeout(resolveWait, input.retryDelayMs ?? UPDATE_PROBE_RETRY_DELAY_MS));
|
|
43412
42912
|
try {
|
|
43413
42913
|
const retried = await openSessionAndPrompt();
|
|
@@ -43420,27 +42920,27 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
43420
42920
|
} catch (retryError) {
|
|
43421
42921
|
const retryDetail = retryError instanceof Error ? retryError.message : String(retryError);
|
|
43422
42922
|
const retryFailure = classifyAcpTurnFailure(retryError);
|
|
43423
|
-
if (!retryFailure || !sameAcpTurnFailure(
|
|
42923
|
+
if (!retryFailure || !sameAcpTurnFailure(failure, retryFailure)) {
|
|
43424
42924
|
throw new UpdateFunctionalProbeError("turn-failed", retryDetail, {
|
|
43425
42925
|
cause: retryError
|
|
43426
42926
|
});
|
|
43427
42927
|
}
|
|
43428
42928
|
error = retryError;
|
|
43429
42929
|
detail = retryDetail;
|
|
43430
|
-
|
|
42930
|
+
failure = retryFailure;
|
|
43431
42931
|
}
|
|
43432
42932
|
}
|
|
43433
42933
|
if (error === void 0) {
|
|
43434
|
-
} else if (!
|
|
42934
|
+
} else if (!failure || !input.compareWithCurrentRelease) {
|
|
43435
42935
|
throw new UpdateFunctionalProbeError("turn-failed", detail, { cause: error });
|
|
43436
42936
|
} else {
|
|
43437
42937
|
const current = await input.compareWithCurrentRelease({
|
|
43438
42938
|
kind: "acp-turn-failure",
|
|
43439
42939
|
reason: detail,
|
|
43440
|
-
failure
|
|
42940
|
+
failure
|
|
43441
42941
|
});
|
|
43442
42942
|
const currentFailure = current.kind === "unavailable" ? classifyAcpTurnFailure(current.reason) : void 0;
|
|
43443
|
-
if (!currentFailure || !sameAcpTurnFailure(
|
|
42943
|
+
if (!currentFailure || !sameAcpTurnFailure(failure, currentFailure)) {
|
|
43444
42944
|
throw new UpdateFunctionalProbeError("turn-failed", `${detail}; ${describeCurrentReleaseOutcome(current)}`, { cause: error });
|
|
43445
42945
|
}
|
|
43446
42946
|
console.warn(`[body] update probe: the probe turn failed the same way on this release and the current release (${detail}); that failure is not this bundle's doing, so the probe passes as inconclusive`);
|
|
@@ -43471,8 +42971,8 @@ async function runUpdateFunctionalProbe(input) {
|
|
|
43471
42971
|
}
|
|
43472
42972
|
|
|
43473
42973
|
// apps/body/dist/update-rollback-alert.js
|
|
43474
|
-
import { mkdir as mkdir22, readFile as
|
|
43475
|
-
import { dirname as
|
|
42974
|
+
import { mkdir as mkdir22, readFile as readFile21, rename as rename7, unlink as unlink6, writeFile as writeFile16 } from "node:fs/promises";
|
|
42975
|
+
import { dirname as dirname19, resolve as resolve32 } from "node:path";
|
|
43476
42976
|
var REPORT_INTERVAL_MS = 60 * 60 * 1e3;
|
|
43477
42977
|
var lastLogged = /* @__PURE__ */ new Map();
|
|
43478
42978
|
function updateRollbackAlertPath(runtimeDir) {
|
|
@@ -43481,7 +42981,7 @@ function updateRollbackAlertPath(runtimeDir) {
|
|
|
43481
42981
|
async function writeAlert(runtimeDir, alert) {
|
|
43482
42982
|
const path = updateRollbackAlertPath(runtimeDir);
|
|
43483
42983
|
const staged = `${path}.${process.pid}.tmp`;
|
|
43484
|
-
await mkdir22(
|
|
42984
|
+
await mkdir22(dirname19(path), { recursive: true });
|
|
43485
42985
|
await writeFile16(staged, `${JSON.stringify(alert, null, 2)}
|
|
43486
42986
|
`, { mode: 384 });
|
|
43487
42987
|
await rename7(staged, path);
|
|
@@ -43494,7 +42994,7 @@ async function queueUpdateRollbackAlert(runtimeDir, releaseId, now2 = Date.now()
|
|
|
43494
42994
|
}
|
|
43495
42995
|
async function readUpdateRollbackAlert(runtimeDir) {
|
|
43496
42996
|
try {
|
|
43497
|
-
const value = JSON.parse(await
|
|
42997
|
+
const value = JSON.parse(await readFile21(updateRollbackAlertPath(runtimeDir), "utf8"));
|
|
43498
42998
|
if (value.version !== 1 || typeof value.releaseId !== "string")
|
|
43499
42999
|
return void 0;
|
|
43500
43000
|
return value;
|
|
@@ -43540,21 +43040,21 @@ async function reportUpdateRollback(input) {
|
|
|
43540
43040
|
init_adapter_install_lock();
|
|
43541
43041
|
var UPDATE_CONVERGENCE_SLO_MS = 10 * 6e4;
|
|
43542
43042
|
var DEFAULT_UPDATE_INTERVAL_MS = 3e4;
|
|
43543
|
-
var UPDATE_DRAIN_DEADLINE_MS = UPDATE_CONVERGENCE_SLO_MS -
|
|
43043
|
+
var UPDATE_DRAIN_DEADLINE_MS = UPDATE_CONVERGENCE_SLO_MS - 15e4;
|
|
43544
43044
|
var MAX_HOST_RESTART_STAGGER_MS = 15e3;
|
|
43545
43045
|
function managedRestartStaggerMs(agentId, desiredRelease, drainDeadlineAt, now2 = Date.now()) {
|
|
43546
|
-
const digest =
|
|
43046
|
+
const digest = createHash11("sha256").update(agentId).update("\0").update(desiredRelease).digest();
|
|
43547
43047
|
const spread = digest.readUInt32BE(0) % (MAX_HOST_RESTART_STAGGER_MS + 1);
|
|
43548
43048
|
return Math.min(spread, Math.max(0, drainDeadlineAt - now2));
|
|
43549
43049
|
}
|
|
43550
|
-
var UPDATE_WORKER_DEADLINE_MS =
|
|
43050
|
+
var UPDATE_WORKER_DEADLINE_MS = UPDATE_CONVERGENCE_SLO_MS - 6e4;
|
|
43551
43051
|
var LOCK_STALE_MS = UPDATE_WORKER_DEADLINE_MS + 5 * 6e4;
|
|
43552
43052
|
var DEFAULT_UPDATE_INITIAL_DELAY_MS = 0;
|
|
43553
43053
|
async function withInstallLock(layout, work, options = {}) {
|
|
43554
43054
|
const now2 = options.now ?? Date.now;
|
|
43555
43055
|
const lock = resolve33(layout.releasesRoot, ".state", "install.lock");
|
|
43556
43056
|
const deadline = now2() + (options.waitMs ?? 1e4);
|
|
43557
|
-
await mkdir23(
|
|
43057
|
+
await mkdir23(dirname20(lock), { recursive: true });
|
|
43558
43058
|
for (; ; ) {
|
|
43559
43059
|
try {
|
|
43560
43060
|
await mkdir23(lock);
|
|
@@ -44028,12 +43528,12 @@ async function proveLoadedReleaseReady(layout, runtimeDir, loadedRelease, option
|
|
|
44028
43528
|
if (!current || current.releaseId !== loadedRelease || current.status !== "pending")
|
|
44029
43529
|
return false;
|
|
44030
43530
|
const confirmed = [.../* @__PURE__ */ new Set([...current.confirmedProbeIds ?? [], probeId])].sort();
|
|
44031
|
-
const required = current.requiredProbeIds ?? [probeId];
|
|
44032
|
-
const satisfied = [...confirmed, ...current.unavailableProbeIds ?? []];
|
|
44033
43531
|
await replaceUpdateAttempt(layout, {
|
|
44034
43532
|
...current,
|
|
44035
43533
|
confirmedProbeIds: confirmed,
|
|
44036
|
-
|
|
43534
|
+
// One verified successor is sufficient to validate the shared bundle.
|
|
43535
|
+
// A peer still running the old release cannot hold this journal pending.
|
|
43536
|
+
status: "confirmed"
|
|
44037
43537
|
});
|
|
44038
43538
|
return true;
|
|
44039
43539
|
});
|
|
@@ -44180,7 +43680,7 @@ init_launchd();
|
|
|
44180
43680
|
init_systemd();
|
|
44181
43681
|
init_runtime();
|
|
44182
43682
|
import { mkdir as mkdir24, rename as rename8 } from "node:fs/promises";
|
|
44183
|
-
import { dirname as
|
|
43683
|
+
import { dirname as dirname21, resolve as resolve34 } from "node:path";
|
|
44184
43684
|
async function retireRemovedAgent(runtime, options = {}) {
|
|
44185
43685
|
const deletedRoot = resolve34(runtime.supervisorRoot, "beeline", "deleted-runtimes");
|
|
44186
43686
|
const target = resolve34(deletedRoot, `${runtime.agent.publicKey}-${Date.now()}`);
|
|
@@ -44203,13 +43703,13 @@ async function relocateAgentRuntime(runtime, target, options = {}) {
|
|
|
44203
43703
|
...options.run ? { run: options.run } : {}
|
|
44204
43704
|
});
|
|
44205
43705
|
}
|
|
44206
|
-
await mkdir24(
|
|
43706
|
+
await mkdir24(dirname21(destination), { recursive: true, mode: 448 });
|
|
44207
43707
|
await rename8(source, destination);
|
|
44208
43708
|
return destination;
|
|
44209
43709
|
}
|
|
44210
43710
|
|
|
44211
43711
|
// apps/body/dist/start-command.js
|
|
44212
|
-
import { basename as basename6, dirname as
|
|
43712
|
+
import { basename as basename6, dirname as dirname22 } from "node:path";
|
|
44213
43713
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
44214
43714
|
init_agent_command();
|
|
44215
43715
|
init_runtime();
|
|
@@ -44424,7 +43924,7 @@ async function startStoredRuntime(configPath, opts = {}, dependencyOverrides = {
|
|
|
44424
43924
|
return { status: "started", pid };
|
|
44425
43925
|
}
|
|
44426
43926
|
function agentStartId(configPath) {
|
|
44427
|
-
return basename6(
|
|
43927
|
+
return basename6(dirname22(configPath));
|
|
44428
43928
|
}
|
|
44429
43929
|
async function startRuntime(configPath, spinnerHandle) {
|
|
44430
43930
|
const report = (text2) => spinnerHandle ? spinnerHandle.message(text2) : console.log(text2);
|
|
@@ -44505,7 +44005,7 @@ async function runStartCommand(args, interactiveUi, dependencyOverrides = {}) {
|
|
|
44505
44005
|
for (const path of unique) {
|
|
44506
44006
|
const id = agentStartId(path);
|
|
44507
44007
|
const spinnerHandle = interactiveUi ? spinner() : void 0;
|
|
44508
|
-
spinnerHandle?.start(`Starting ${
|
|
44008
|
+
spinnerHandle?.start(`Starting ${dirname22(path)}\u2026`);
|
|
44509
44009
|
try {
|
|
44510
44010
|
const outcome = await deps.startOne(path, spinnerHandle);
|
|
44511
44011
|
const report = { id, path, ...outcome };
|
|
@@ -44538,10 +44038,10 @@ async function runStartCommand(args, interactiveUi, dependencyOverrides = {}) {
|
|
|
44538
44038
|
|
|
44539
44039
|
// apps/body/dist/connect-command.js
|
|
44540
44040
|
import { spawn as spawn12 } from "node:child_process";
|
|
44541
|
-
import { createHash as
|
|
44542
|
-
import { chmod as chmod8, mkdir as mkdir25, readFile as
|
|
44041
|
+
import { createHash as createHash12, randomUUID as randomUUID10 } from "node:crypto";
|
|
44042
|
+
import { chmod as chmod8, mkdir as mkdir25, readFile as readFile22, unlink as unlink7, writeFile as writeFile18 } from "node:fs/promises";
|
|
44543
44043
|
import { homedir as homedir17, hostname as hostname3 } from "node:os";
|
|
44544
|
-
import { dirname as
|
|
44044
|
+
import { dirname as dirname23, resolve as resolve35 } from "node:path";
|
|
44545
44045
|
import { stdin as stdin3, stdout as stdout4 } from "node:process";
|
|
44546
44046
|
init_access_policy();
|
|
44547
44047
|
init_agent_command();
|
|
@@ -45213,18 +44713,18 @@ async function readMachineId(env = process.env) {
|
|
|
45213
44713
|
let machineId;
|
|
45214
44714
|
let machineName = hostname3();
|
|
45215
44715
|
try {
|
|
45216
|
-
const existing = await
|
|
44716
|
+
const existing = await readFile22(machineIdPath, "utf8");
|
|
45217
44717
|
machineId = existing.trim();
|
|
45218
44718
|
if (!/^[0-9a-f-]{32,}$/.test(machineId))
|
|
45219
44719
|
throw new Error("invalid persisted machine id");
|
|
45220
44720
|
} catch {
|
|
45221
|
-
machineId =
|
|
44721
|
+
machineId = randomUUID10();
|
|
45222
44722
|
try {
|
|
45223
44723
|
await mkdir25(configDir, { recursive: true, mode: 448 });
|
|
45224
44724
|
await writeFile18(machineIdPath, `${machineId}
|
|
45225
44725
|
`, { mode: 384 });
|
|
45226
44726
|
} catch {
|
|
45227
|
-
machineId =
|
|
44727
|
+
machineId = createHash12("sha256").update(machineName).digest("hex").slice(0, 36);
|
|
45228
44728
|
}
|
|
45229
44729
|
}
|
|
45230
44730
|
return { machineId, machineName };
|
|
@@ -45233,7 +44733,7 @@ function requestConnectGrant(baseUrl, pairingCode, selection, fetchImpl, machine
|
|
|
45233
44733
|
const normalizedPairingCode = normalizeAgentPairingCode(pairingCode);
|
|
45234
44734
|
if (!normalizedPairingCode)
|
|
45235
44735
|
throw new Error("invalid pairing code");
|
|
45236
|
-
const avatarSeed =
|
|
44736
|
+
const avatarSeed = createHash12("sha256").update(normalizedPairingCode.toUpperCase()).digest("hex").slice(0, 32);
|
|
45237
44737
|
return jsonRequest(`${baseUrl}/auth/agent/connect`, {
|
|
45238
44738
|
pairing_code: normalizedPairingCode,
|
|
45239
44739
|
harness: selection.harness,
|
|
@@ -45305,7 +44805,7 @@ function providerEnvironment(selection) {
|
|
|
45305
44805
|
};
|
|
45306
44806
|
}
|
|
45307
44807
|
async function writePrivateJson(path, value) {
|
|
45308
|
-
await mkdir25(
|
|
44808
|
+
await mkdir25(dirname23(path), { recursive: true, mode: 448 });
|
|
45309
44809
|
await writeFile18(path, `${JSON.stringify(value, null, 2)}
|
|
45310
44810
|
`, { mode: 384 });
|
|
45311
44811
|
await chmod8(path, 384);
|
|
@@ -45315,7 +44815,7 @@ async function writeProviderEnv(selection, agentPubkey) {
|
|
|
45315
44815
|
if (Object.keys(values).length === 0)
|
|
45316
44816
|
return void 0;
|
|
45317
44817
|
const path = resolve35(defaultSupervisorRoot(process.env), "beeline", "connect", `${agentPubkey}.env`);
|
|
45318
|
-
await mkdir25(
|
|
44818
|
+
await mkdir25(dirname23(path), { recursive: true, mode: 448 });
|
|
45319
44819
|
const contents = Object.entries(values).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join("\n");
|
|
45320
44820
|
await writeFile18(path, `${contents}
|
|
45321
44821
|
`, { mode: 384 });
|
|
@@ -45469,18 +44969,18 @@ async function runConnectFinishCommand(path) {
|
|
|
45469
44969
|
throw new Error("connect-finish may run only from the canonical installed Beeline launcher");
|
|
45470
44970
|
}
|
|
45471
44971
|
try {
|
|
45472
|
-
const grant = JSON.parse(await
|
|
44972
|
+
const grant = JSON.parse(await readFile22(resolve35(path), "utf8"));
|
|
45473
44973
|
if (!isDevicePairingGrant(grant))
|
|
45474
44974
|
throw new Error("device connection grant is invalid");
|
|
45475
44975
|
const connected = await completeDevicePairing(grant);
|
|
45476
44976
|
await unlink7(resolve35(path));
|
|
45477
|
-
const providerEnv = grant.llmEnvFile ? await
|
|
44977
|
+
const providerEnv = grant.llmEnvFile ? await readFile22(grant.llmEnvFile, "utf8").catch(() => "") : "";
|
|
45478
44978
|
const apiKey = (/^OPENROUTER_API_KEY=(\S+)/m.exec(providerEnv)?.[1] ?? "").replace(/^["']|["']$/g, "");
|
|
45479
44979
|
const model = openRouterModelId(grant.model, { OPENROUTER_API_KEY: apiKey });
|
|
45480
44980
|
if (model) {
|
|
45481
44981
|
const decision2 = await resolveOpenRouterRouting({
|
|
45482
44982
|
model,
|
|
45483
|
-
cacheDir: openRouterRoutingCacheDir(
|
|
44983
|
+
cacheDir: openRouterRoutingCacheDir(dirname23(connected.configPath)),
|
|
45484
44984
|
...apiKey ? { apiKey } : {},
|
|
45485
44985
|
probeTimeoutMs: 1e4
|
|
45486
44986
|
});
|
|
@@ -45498,8 +44998,8 @@ async function runConnectFinishCommand(path) {
|
|
|
45498
44998
|
init_self_update();
|
|
45499
44999
|
|
|
45500
45000
|
// apps/body/dist/daemon-failure.js
|
|
45501
|
-
import { mkdir as mkdir26, readFile as
|
|
45502
|
-
import { dirname as
|
|
45001
|
+
import { mkdir as mkdir26, readFile as readFile23, rename as rename9, rm as rm12, writeFile as writeFile19 } from "node:fs/promises";
|
|
45002
|
+
import { dirname as dirname24, resolve as resolve36 } from "node:path";
|
|
45503
45003
|
var DAEMON_FAILURE_LIMIT = 3;
|
|
45504
45004
|
var DAEMON_FAILURE_WINDOW_MS = 5 * 6e4;
|
|
45505
45005
|
function daemonFailurePath(runtimeDir) {
|
|
@@ -45507,8 +45007,8 @@ function daemonFailurePath(runtimeDir) {
|
|
|
45507
45007
|
}
|
|
45508
45008
|
async function readFailureRecord(runtimeDir) {
|
|
45509
45009
|
try {
|
|
45510
|
-
const value = JSON.parse(await
|
|
45511
|
-
if (value.version !== 1 || !Array.isArray(value.failures) || value.failures.some((
|
|
45010
|
+
const value = JSON.parse(await readFile23(daemonFailurePath(runtimeDir), "utf8"));
|
|
45011
|
+
if (value.version !== 1 || !Array.isArray(value.failures) || value.failures.some((failure) => typeof failure !== "number") || typeof value.lastError !== "string") {
|
|
45512
45012
|
return void 0;
|
|
45513
45013
|
}
|
|
45514
45014
|
return value;
|
|
@@ -45519,14 +45019,14 @@ async function readFailureRecord(runtimeDir) {
|
|
|
45519
45019
|
async function writeFailureRecord(runtimeDir, record6) {
|
|
45520
45020
|
const path = daemonFailurePath(runtimeDir);
|
|
45521
45021
|
const staged = `${path}.${process.pid}.tmp`;
|
|
45522
|
-
await mkdir26(
|
|
45022
|
+
await mkdir26(dirname24(path), { recursive: true, mode: 448 });
|
|
45523
45023
|
await writeFile19(staged, `${JSON.stringify(record6, null, 2)}
|
|
45524
45024
|
`, { mode: 384 });
|
|
45525
45025
|
await rename9(staged, path);
|
|
45526
45026
|
}
|
|
45527
45027
|
async function recordDaemonStartFailure(runtimeDir, error, now2 = Date.now()) {
|
|
45528
45028
|
const prior = await readFailureRecord(runtimeDir);
|
|
45529
|
-
const failures = [...prior?.failures ?? [], now2].filter((
|
|
45029
|
+
const failures = [...prior?.failures ?? [], now2].filter((failure) => now2 - failure <= DAEMON_FAILURE_WINDOW_MS);
|
|
45530
45030
|
const distressed = failures.length >= DAEMON_FAILURE_LIMIT;
|
|
45531
45031
|
const record6 = {
|
|
45532
45032
|
version: 1,
|
|
@@ -45546,7 +45046,7 @@ init_systemd();
|
|
|
45546
45046
|
|
|
45547
45047
|
// apps/body/dist/current-release-probe.js
|
|
45548
45048
|
import { spawn as spawn13 } from "node:child_process";
|
|
45549
|
-
import { dirname as
|
|
45049
|
+
import { dirname as dirname25, join as join16 } from "node:path";
|
|
45550
45050
|
init_runtime();
|
|
45551
45051
|
init_self_update();
|
|
45552
45052
|
var CURRENT_RELEASE_PROBE_TIMEOUT_MS = 12e4;
|
|
@@ -45653,7 +45153,7 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
45653
45153
|
const runtime = await readRuntimeRecord(configPath);
|
|
45654
45154
|
const agent = runtimeAgentCommand(runtime);
|
|
45655
45155
|
const config = loadBodyConfig({
|
|
45656
|
-
workspaceRoot: join16(
|
|
45156
|
+
workspaceRoot: join16(dirname25(configPath), "workspace"),
|
|
45657
45157
|
llmEnvFile: runtime.llmEnvFile,
|
|
45658
45158
|
env: { ...env, BUZZ_AGENT_BIN: agent.command, BUZZ_DEV_MCP_BIN: runtime.mcpBinary },
|
|
45659
45159
|
agent
|
|
@@ -45671,7 +45171,7 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
45671
45171
|
}
|
|
45672
45172
|
const layout = beelineInstallLayout(env);
|
|
45673
45173
|
const releaseId = (layout && await activeReleaseId(layout).catch(() => void 0)) ?? "unknown";
|
|
45674
|
-
const runtimeDir =
|
|
45174
|
+
const runtimeDir = dirname25(configPath);
|
|
45675
45175
|
const outcome = await probeOutcome(() => (options.probe ?? runUpdateFunctionalProbe)({
|
|
45676
45176
|
config,
|
|
45677
45177
|
runtimeDir,
|
|
@@ -45686,7 +45186,7 @@ async function runUpdateProbeCommand(args, options = {}) {
|
|
|
45686
45186
|
}
|
|
45687
45187
|
|
|
45688
45188
|
// apps/body/dist/release-status.js
|
|
45689
|
-
import { readFile as
|
|
45189
|
+
import { readFile as readFile24, readdir as readdir9, rename as rename10, writeFile as writeFile20 } from "node:fs/promises";
|
|
45690
45190
|
import { resolve as resolve37 } from "node:path";
|
|
45691
45191
|
var DAEMON_RELEASE_STATUS_FILE = "release-status.json";
|
|
45692
45192
|
var RELEASE_VERSION = /^v\d+\.\d+\.\d+$/;
|
|
@@ -45842,7 +45342,7 @@ var DaemonExitError = class extends Error {
|
|
|
45842
45342
|
};
|
|
45843
45343
|
async function runStoredDaemon(pathOrPointer) {
|
|
45844
45344
|
const configPath = await resolveRuntimeConfigPath(pathOrPointer);
|
|
45845
|
-
daemonFailureRuntimeDir =
|
|
45345
|
+
daemonFailureRuntimeDir = dirname26(configPath);
|
|
45846
45346
|
const accessMigration = await migrateRuntimeRecordAccessPolicy(configPath);
|
|
45847
45347
|
let runtime = accessMigration.runtime;
|
|
45848
45348
|
if (!runtime.transport) {
|
|
@@ -45876,7 +45376,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
45876
45376
|
BUZZ_DEV_MCP_BIN: runtime.mcpBinary
|
|
45877
45377
|
};
|
|
45878
45378
|
const config = loadBodyConfig({
|
|
45879
|
-
workspaceRoot: resolve39(
|
|
45379
|
+
workspaceRoot: resolve39(dirname26(configPath), "workspace"),
|
|
45880
45380
|
llmEnvFile: runtime.llmEnvFile,
|
|
45881
45381
|
env,
|
|
45882
45382
|
agent
|
|
@@ -45903,7 +45403,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
45903
45403
|
config.runtimeConfigPath = configPath;
|
|
45904
45404
|
const sandbox = await ensureBwrapSandbox({
|
|
45905
45405
|
...runtime.sandbox ? { policy: runtime.sandbox } : {},
|
|
45906
|
-
stateDir:
|
|
45406
|
+
stateDir: dirname26(configPath),
|
|
45907
45407
|
beforeInstall: () => extendSystemdStartTimeout(BUBBLEWRAP_INSTALL_BUDGET_MS)
|
|
45908
45408
|
});
|
|
45909
45409
|
if (sandbox.path)
|
|
@@ -45914,10 +45414,8 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
45914
45414
|
config.sandboxMaskPaths = [...config.sandboxMaskPaths ?? [], ...runtime.sandboxMaskPaths];
|
|
45915
45415
|
}
|
|
45916
45416
|
const controller = new AbortController();
|
|
45917
|
-
const
|
|
45918
|
-
|
|
45919
|
-
process.once("SIGTERM", stop);
|
|
45920
|
-
const runtimeDir = dirname27(configPath);
|
|
45417
|
+
const disposeStopSignals = installDaemonStopSignals(controller);
|
|
45418
|
+
const runtimeDir = dirname26(configPath);
|
|
45921
45419
|
const layout = beelineInstallLayout(process.env);
|
|
45922
45420
|
const notifier = new SystemdNotifier();
|
|
45923
45421
|
let rollbackAlertDrain;
|
|
@@ -46259,6 +45757,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
46259
45757
|
institutionalMemoryWorker?.stop();
|
|
46260
45758
|
await notifier.stopping(stoppingStatus).catch(() => void 0);
|
|
46261
45759
|
await clearDaemonPidRecordIfPid(configPath, process.pid);
|
|
45760
|
+
disposeStopSignals();
|
|
46262
45761
|
}
|
|
46263
45762
|
}
|
|
46264
45763
|
async function main() {
|
|
@@ -46282,7 +45781,7 @@ async function main() {
|
|
|
46282
45781
|
if (process.env.BEELINE_SQUIRE_RELAY_URL)
|
|
46283
45782
|
runSquireTaskProxy();
|
|
46284
45783
|
else
|
|
46285
|
-
runSquireFacade();
|
|
45784
|
+
await runSquireFacade();
|
|
46286
45785
|
return;
|
|
46287
45786
|
}
|
|
46288
45787
|
if (command === SQUIRE_BROKER_FLAG) {
|
|
@@ -46363,7 +45862,7 @@ async function main() {
|
|
|
46363
45862
|
}
|
|
46364
45863
|
if (!configPath && agentPubkey) {
|
|
46365
45864
|
const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
|
|
46366
|
-
configPath = configs.find((candidate) =>
|
|
45865
|
+
configPath = configs.find((candidate) => dirname26(candidate).endsWith(agentPubkey));
|
|
46367
45866
|
}
|
|
46368
45867
|
if (!configPath && agentPubkey) {
|
|
46369
45868
|
throw new DaemonExitError(`unknown agent ${agentPubkey}: no durable runtime exists; refusing service restart loop`, UNKNOWN_AGENT_EXIT_STATUS);
|
|
@@ -46391,7 +45890,7 @@ async function main() {
|
|
|
46391
45890
|
if (!agentPubkey)
|
|
46392
45891
|
throw new Error("stop requires --agent <pubkey>");
|
|
46393
45892
|
const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
|
|
46394
|
-
const configPath = configs.find((candidate) =>
|
|
45893
|
+
const configPath = configs.find((candidate) => dirname26(candidate).endsWith(agentPubkey));
|
|
46395
45894
|
if (!configPath)
|
|
46396
45895
|
throw new Error(`no stored runtime found for agent ${agentPubkey}`);
|
|
46397
45896
|
const runtime = await readRuntimeRecord(configPath);
|
|
@@ -46425,10 +45924,10 @@ main().catch(async (err) => {
|
|
|
46425
45924
|
let exitStatus = err instanceof DaemonExitError ? err.exitStatus : 1;
|
|
46426
45925
|
if (process.argv[2] === "daemon" && daemonFailureRuntimeDir && exitStatus === 1) {
|
|
46427
45926
|
try {
|
|
46428
|
-
const
|
|
46429
|
-
if (
|
|
45927
|
+
const failure = await recordDaemonStartFailure(daemonFailureRuntimeDir, err);
|
|
45928
|
+
if (failure.distressed) {
|
|
46430
45929
|
exitStatus = DAEMON_DISTRESS_EXIT_STATUS;
|
|
46431
|
-
console.error(`[thin-core] daemon start failed ${
|
|
45930
|
+
console.error(`[thin-core] daemon start failed ${failure.count} times; service restart stopped. operator record: ${failure.path}`);
|
|
46432
45931
|
}
|
|
46433
45932
|
} catch (recordError) {
|
|
46434
45933
|
console.error("[thin-core] could not persist daemon distress record:", recordError);
|