usebeeline 0.0.52 → 0.0.54
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 +122 -16
- package/package.json +1 -1
package/dist/usebeeline.mjs
CHANGED
|
@@ -955,8 +955,8 @@ var init_self_update = __esm({
|
|
|
955
955
|
});
|
|
956
956
|
|
|
957
957
|
// apps/body/dist/cli.js
|
|
958
|
-
import { dirname as dirname15, resolve as
|
|
959
|
-
import { readFile as readFile14, unlink as
|
|
958
|
+
import { dirname as dirname15, resolve as resolve29 } from "node:path";
|
|
959
|
+
import { readFile as readFile14, unlink as unlink4, writeFile as writeFile15 } from "node:fs/promises";
|
|
960
960
|
import { stdin as stdin4, stdout as stdout5 } from "node:process";
|
|
961
961
|
|
|
962
962
|
// node_modules/@clack/core/dist/index.mjs
|
|
@@ -3832,7 +3832,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
3832
3832
|
const current = this.activeRunIds.get(sessionId);
|
|
3833
3833
|
if (current)
|
|
3834
3834
|
return Promise.resolve(current);
|
|
3835
|
-
return new Promise((
|
|
3835
|
+
return new Promise((resolve30, reject) => {
|
|
3836
3836
|
const onUpdate = (update) => {
|
|
3837
3837
|
if (update.sessionId !== sessionId)
|
|
3838
3838
|
return;
|
|
@@ -3840,7 +3840,7 @@ var AcpClient = class extends EventEmitter {
|
|
|
3840
3840
|
if (!runId)
|
|
3841
3841
|
return;
|
|
3842
3842
|
cleanup();
|
|
3843
|
-
|
|
3843
|
+
resolve30(runId);
|
|
3844
3844
|
};
|
|
3845
3845
|
const timer = setTimeout(() => {
|
|
3846
3846
|
cleanup();
|
|
@@ -3924,13 +3924,13 @@ var AcpClient = class extends EventEmitter {
|
|
|
3924
3924
|
}
|
|
3925
3925
|
const id = this.nextId++;
|
|
3926
3926
|
const payload = { jsonrpc: "2.0", id, method, params };
|
|
3927
|
-
return new Promise((
|
|
3927
|
+
return new Promise((resolve30, reject) => {
|
|
3928
3928
|
const timer = setTimeout(() => {
|
|
3929
3929
|
this.pending.delete(id);
|
|
3930
3930
|
reject(new AcpRequestTimeoutError(method, timeoutMs, this.stderrTail, Boolean(onStart), detail));
|
|
3931
3931
|
}, timeoutMs);
|
|
3932
3932
|
this.pending.set(id, {
|
|
3933
|
-
resolve:
|
|
3933
|
+
resolve: resolve30,
|
|
3934
3934
|
reject,
|
|
3935
3935
|
timer,
|
|
3936
3936
|
method,
|
|
@@ -15355,6 +15355,8 @@ function harnessStateDirsFromEnv(env) {
|
|
|
15355
15355
|
import { mkdir as mkdir5, writeFile as writeFile6 } from "node:fs/promises";
|
|
15356
15356
|
import { basename as basename4, extname, join as join4 } from "node:path";
|
|
15357
15357
|
var MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024;
|
|
15358
|
+
var MEDIA_TTL_HOURS = 24;
|
|
15359
|
+
var EXPIRED_REASON = `expired: attachments are kept for ${MEDIA_TTL_HOURS} hours and these bytes are past that window`;
|
|
15358
15360
|
var FETCH_TIMEOUT_MS = 3e4;
|
|
15359
15361
|
var MAX_INLINE_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
15360
15362
|
function safeFileName(attachment, index, taken) {
|
|
@@ -15379,10 +15381,14 @@ async function deliverAttachments(attachments, dir, fetchImpl = fetch) {
|
|
|
15379
15381
|
});
|
|
15380
15382
|
if (attachment.size && attachment.size > MAX_ATTACHMENT_BYTES)
|
|
15381
15383
|
return tooLarge(attachment.size);
|
|
15384
|
+
if (attachment.expired)
|
|
15385
|
+
return { attachment, reason: EXPIRED_REASON };
|
|
15382
15386
|
try {
|
|
15383
15387
|
const response = await fetchImpl(attachment.url, {
|
|
15384
15388
|
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
|
|
15385
15389
|
});
|
|
15390
|
+
if (response.status === 410)
|
|
15391
|
+
return { attachment, reason: EXPIRED_REASON };
|
|
15386
15392
|
if (!response.ok)
|
|
15387
15393
|
throw new Error(`HTTP ${response.status}`);
|
|
15388
15394
|
const declared = Number(response.headers.get("content-length") ?? 0);
|
|
@@ -17040,6 +17046,9 @@ var MonolithCornerTurnLoop = class {
|
|
|
17040
17046
|
this.sessionScratchDir = tmpDir;
|
|
17041
17047
|
const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
|
|
17042
17048
|
await Promise.all(homeStateDirs.map((dir) => mkdir9(dir, { recursive: true })));
|
|
17049
|
+
const attachScratchRoot = this.options.config.agentHomeRoot ?? tmpDir;
|
|
17050
|
+
if (attachScratchRoot)
|
|
17051
|
+
await mkdir9(attachScratchRoot, { recursive: true });
|
|
17043
17052
|
const spawnCommand = wrapAgentCommand({
|
|
17044
17053
|
bwrapPath: this.options.config.bwrapPath,
|
|
17045
17054
|
spec: {
|
|
@@ -17051,6 +17060,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
17051
17060
|
harnessStateDirs: stateDirs,
|
|
17052
17061
|
harnessHomeStateDirs: homeStateDirs,
|
|
17053
17062
|
...tmpDir ? { tmpDir } : {},
|
|
17063
|
+
...attachScratchRoot ? { additionalWritablePaths: [attachScratchRoot] } : {},
|
|
17054
17064
|
maskPaths: credentialMaskPaths(this.options.config.sandboxMaskPaths, operatorHome)
|
|
17055
17065
|
},
|
|
17056
17066
|
command,
|
|
@@ -17088,7 +17098,7 @@ var MonolithCornerTurnLoop = class {
|
|
|
17088
17098
|
attachRoot: this.options.worktreePath,
|
|
17089
17099
|
// The whole per-session overlay, not an enumerated subset: see
|
|
17090
17100
|
// `monolith-room-turn.ts`'s matching comment.
|
|
17091
|
-
attachScratchRoot
|
|
17101
|
+
attachScratchRoot,
|
|
17092
17102
|
...this.options.grantRunnerEndpoint ? { grantRunner: this.options.grantRunnerEndpoint } : {}
|
|
17093
17103
|
})
|
|
17094
17104
|
];
|
|
@@ -17812,6 +17822,9 @@ var MonolithRoomTurnLoop = class {
|
|
|
17812
17822
|
this.sessionStateDirs = stateDirs;
|
|
17813
17823
|
const homeStateDirs = harnessHomeStateDirs(command, agentEnv.HOME ?? operatorHome);
|
|
17814
17824
|
await Promise.all(homeStateDirs.map((dir) => mkdir10(dir, { recursive: true })));
|
|
17825
|
+
const attachScratchRoot = this.options.config.agentHomeRoot ?? tmpDir;
|
|
17826
|
+
if (attachScratchRoot)
|
|
17827
|
+
await mkdir10(attachScratchRoot, { recursive: true });
|
|
17815
17828
|
const spawnCommand = wrapAgentCommand({
|
|
17816
17829
|
bwrapPath: this.options.config.bwrapPath,
|
|
17817
17830
|
spec: {
|
|
@@ -17820,6 +17833,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
17820
17833
|
harnessStateDirs: stateDirs,
|
|
17821
17834
|
harnessHomeStateDirs: homeStateDirs,
|
|
17822
17835
|
...tmpDir ? { tmpDir } : {},
|
|
17836
|
+
...attachScratchRoot ? { additionalWritablePaths: [attachScratchRoot] } : {},
|
|
17823
17837
|
maskPaths: credentialMaskPaths(this.options.config.sandboxMaskPaths, operatorHome)
|
|
17824
17838
|
},
|
|
17825
17839
|
command,
|
|
@@ -17835,7 +17849,7 @@ var MonolithRoomTurnLoop = class {
|
|
|
17835
17849
|
// never picks where a harness writes a file it generates (grok's own
|
|
17836
17850
|
// images dir, say), so anything inside the overlay it could possibly
|
|
17837
17851
|
// have written must be attachable, whatever subdirectory that is.
|
|
17838
|
-
attachScratchRoot
|
|
17852
|
+
attachScratchRoot,
|
|
17839
17853
|
directMessage,
|
|
17840
17854
|
...this.options.grantRunnerEndpoint ? { grantRunner: this.options.grantRunnerEndpoint } : {}
|
|
17841
17855
|
})
|
|
@@ -21395,7 +21409,7 @@ async function probeReleaseInSubprocess(input) {
|
|
|
21395
21409
|
return { kind: "unavailable", reason: `release ${input.releaseId} has no runnable CLI entrypoint` };
|
|
21396
21410
|
}
|
|
21397
21411
|
const timeoutMs = input.timeoutMs ?? CURRENT_RELEASE_PROBE_TIMEOUT_MS;
|
|
21398
|
-
return new Promise((
|
|
21412
|
+
return new Promise((resolve30) => {
|
|
21399
21413
|
const child = spawn7(input.execPath ?? process.execPath, [entrypoint, UPDATE_PROBE_COMMAND, "--config", input.runtimeConfigPath], { env: input.env ?? process.env, stdio: ["ignore", "pipe", "pipe"] });
|
|
21400
21414
|
let stdout6 = "";
|
|
21401
21415
|
let stderr = "";
|
|
@@ -21405,7 +21419,7 @@ async function probeReleaseInSubprocess(input) {
|
|
|
21405
21419
|
return;
|
|
21406
21420
|
settled = true;
|
|
21407
21421
|
clearTimeout(timer);
|
|
21408
|
-
|
|
21422
|
+
resolve30(outcome);
|
|
21409
21423
|
};
|
|
21410
21424
|
const timer = setTimeout(() => {
|
|
21411
21425
|
child.kill("SIGKILL");
|
|
@@ -21510,6 +21524,90 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
|
|
|
21510
21524
|
return status;
|
|
21511
21525
|
}
|
|
21512
21526
|
|
|
21527
|
+
// apps/body/dist/scratch-sweep.js
|
|
21528
|
+
import { lstat as lstat3, readdir as readdir6, rmdir, unlink as unlink3 } from "node:fs/promises";
|
|
21529
|
+
import { resolve as resolve28 } from "node:path";
|
|
21530
|
+
var DEFAULT_SCRATCH_TTL_HOURS = 72;
|
|
21531
|
+
var NEVER_SWEEP_SUBDIR_NAMES = new Set(HOME_SUBDIRS.filter((name) => name !== "tmp"));
|
|
21532
|
+
function scratchTtlMs(env = process.env) {
|
|
21533
|
+
const raw = env.BEELINE_SCRATCH_TTL_HOURS?.trim();
|
|
21534
|
+
const hours = raw ? Number(raw) : DEFAULT_SCRATCH_TTL_HOURS;
|
|
21535
|
+
return (Number.isFinite(hours) && hours > 0 ? hours : DEFAULT_SCRATCH_TTL_HOURS) * 60 * 60 * 1e3;
|
|
21536
|
+
}
|
|
21537
|
+
async function discoverAttachScratchRoots(runtimeDir) {
|
|
21538
|
+
const roomsDir = resolve28(runtimeDir, "rooms");
|
|
21539
|
+
let entries;
|
|
21540
|
+
try {
|
|
21541
|
+
entries = await readdir6(roomsDir, { withFileTypes: true });
|
|
21542
|
+
} catch {
|
|
21543
|
+
return [];
|
|
21544
|
+
}
|
|
21545
|
+
const roots = [];
|
|
21546
|
+
for (const entry of entries) {
|
|
21547
|
+
if (!entry.isDirectory())
|
|
21548
|
+
continue;
|
|
21549
|
+
const home = resolve28(roomsDir, entry.name, "agent-home");
|
|
21550
|
+
const stats = await lstat3(home).catch(() => void 0);
|
|
21551
|
+
if (stats?.isDirectory())
|
|
21552
|
+
roots.push(home);
|
|
21553
|
+
}
|
|
21554
|
+
return roots;
|
|
21555
|
+
}
|
|
21556
|
+
async function removeStaleFiles(dir, cutoffMs, protectNamesHere) {
|
|
21557
|
+
let entries;
|
|
21558
|
+
try {
|
|
21559
|
+
entries = await readdir6(dir, { withFileTypes: true });
|
|
21560
|
+
} catch {
|
|
21561
|
+
return { removedFiles: 0, removedBytes: 0 };
|
|
21562
|
+
}
|
|
21563
|
+
let removedFiles = 0;
|
|
21564
|
+
let removedBytes = 0;
|
|
21565
|
+
for (const entry of entries) {
|
|
21566
|
+
if (protectNamesHere && NEVER_SWEEP_SUBDIR_NAMES.has(entry.name))
|
|
21567
|
+
continue;
|
|
21568
|
+
const path = resolve28(dir, entry.name);
|
|
21569
|
+
const stats = await lstat3(path).catch(() => void 0);
|
|
21570
|
+
if (!stats || stats.isSymbolicLink())
|
|
21571
|
+
continue;
|
|
21572
|
+
if (stats.isDirectory()) {
|
|
21573
|
+
const nested = await removeStaleFiles(path, cutoffMs, false);
|
|
21574
|
+
removedFiles += nested.removedFiles;
|
|
21575
|
+
removedBytes += nested.removedBytes;
|
|
21576
|
+
const remaining = await readdir6(path).catch(() => void 0);
|
|
21577
|
+
if (remaining && remaining.length === 0)
|
|
21578
|
+
await rmdir(path).catch(() => void 0);
|
|
21579
|
+
continue;
|
|
21580
|
+
}
|
|
21581
|
+
if (!stats.isFile() || stats.mtimeMs >= cutoffMs)
|
|
21582
|
+
continue;
|
|
21583
|
+
await unlink3(path).catch(() => void 0);
|
|
21584
|
+
removedFiles += 1;
|
|
21585
|
+
removedBytes += stats.size;
|
|
21586
|
+
}
|
|
21587
|
+
return { removedFiles, removedBytes };
|
|
21588
|
+
}
|
|
21589
|
+
async function sweepAttachScratchRoots(roots, ttlMs, now2 = Date.now()) {
|
|
21590
|
+
const cutoffMs = now2 - ttlMs;
|
|
21591
|
+
let removedFiles = 0;
|
|
21592
|
+
let removedBytes = 0;
|
|
21593
|
+
for (const root of roots) {
|
|
21594
|
+
const stats = await lstat3(root).catch(() => void 0);
|
|
21595
|
+
if (!stats?.isDirectory())
|
|
21596
|
+
continue;
|
|
21597
|
+
const result = await removeStaleFiles(root, cutoffMs, true);
|
|
21598
|
+
removedFiles += result.removedFiles;
|
|
21599
|
+
removedBytes += result.removedBytes;
|
|
21600
|
+
}
|
|
21601
|
+
return { removedFiles, removedBytes, roots: roots.length };
|
|
21602
|
+
}
|
|
21603
|
+
async function runScratchSweep(runtimeDir, env = process.env) {
|
|
21604
|
+
const roots = await discoverAttachScratchRoots(runtimeDir);
|
|
21605
|
+
const ttlMs = scratchTtlMs(env);
|
|
21606
|
+
const summary = await sweepAttachScratchRoots(roots, ttlMs);
|
|
21607
|
+
console.log(`[body] scratch sweep: removed ${summary.removedFiles} files (${summary.removedBytes} bytes) older than ${Math.round(ttlMs / (60 * 60 * 1e3))}h under ${summary.roots} roots`);
|
|
21608
|
+
return summary;
|
|
21609
|
+
}
|
|
21610
|
+
|
|
21513
21611
|
// apps/body/dist/cli.js
|
|
21514
21612
|
function usage(exitCode = 1) {
|
|
21515
21613
|
console.error(`
|
|
@@ -21540,6 +21638,10 @@ All other config via env vars (see config.ts).
|
|
|
21540
21638
|
process.exit(exitCode);
|
|
21541
21639
|
}
|
|
21542
21640
|
var daemonFailureRuntimeDir;
|
|
21641
|
+
var SCRATCH_SWEEP_INTERVAL_MS = 6 * 60 * 6e4;
|
|
21642
|
+
function runScratchSweepLogged(runtimeDir) {
|
|
21643
|
+
void runScratchSweep(runtimeDir).catch((error) => console.error("[body] scratch sweep failed:", error));
|
|
21644
|
+
}
|
|
21543
21645
|
var DaemonExitError = class extends Error {
|
|
21544
21646
|
exitStatus;
|
|
21545
21647
|
constructor(message, exitStatus) {
|
|
@@ -21562,7 +21664,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
21562
21664
|
runtime = activated.runtime;
|
|
21563
21665
|
const daemonApi = activated.client;
|
|
21564
21666
|
const agent = runtimeAgentCommand(runtime);
|
|
21565
|
-
await writeFile15(
|
|
21667
|
+
await writeFile15(resolve29(dirname15(configPath), "daemon.pid"), `${process.pid}
|
|
21566
21668
|
`, { mode: 384 });
|
|
21567
21669
|
const env = {
|
|
21568
21670
|
...process.env,
|
|
@@ -21570,7 +21672,7 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
21570
21672
|
BUZZ_DEV_MCP_BIN: runtime.mcpBinary
|
|
21571
21673
|
};
|
|
21572
21674
|
const config = loadBodyConfig({
|
|
21573
|
-
workspaceRoot:
|
|
21675
|
+
workspaceRoot: resolve29(dirname15(configPath), "workspace"),
|
|
21574
21676
|
llmEnvFile: runtime.llmEnvFile,
|
|
21575
21677
|
env,
|
|
21576
21678
|
agent
|
|
@@ -21647,6 +21749,9 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
21647
21749
|
console.log(`[beeline] thin daemon core ${runtime.communityId} starting with ${runtime.rooms.length} Room binding(s)`);
|
|
21648
21750
|
console.log(`[body] agent binary: ${formatAgentCommand(agent)}`);
|
|
21649
21751
|
console.log(`[body] ${sandbox.advisory}`);
|
|
21752
|
+
runScratchSweepLogged(runtimeDir);
|
|
21753
|
+
const scratchSweepTimer = setInterval(() => runScratchSweepLogged(runtimeDir), SCRATCH_SWEEP_INTERVAL_MS);
|
|
21754
|
+
scratchSweepTimer.unref();
|
|
21650
21755
|
let ready = false;
|
|
21651
21756
|
let stoppingStatus = "daemon stopped";
|
|
21652
21757
|
try {
|
|
@@ -21744,11 +21849,12 @@ async function runStoredDaemon(pathOrPointer) {
|
|
|
21744
21849
|
}
|
|
21745
21850
|
throw error;
|
|
21746
21851
|
} finally {
|
|
21852
|
+
clearInterval(scratchSweepTimer);
|
|
21747
21853
|
await notifier.stopping(stoppingStatus).catch(() => void 0);
|
|
21748
|
-
const pidPath =
|
|
21854
|
+
const pidPath = resolve29(dirname15(configPath), "daemon.pid");
|
|
21749
21855
|
const recorded = Number((await readFile14(pidPath, "utf8").catch(() => "")).trim());
|
|
21750
21856
|
if (recorded === process.pid) {
|
|
21751
|
-
await
|
|
21857
|
+
await unlink4(pidPath).catch(() => void 0);
|
|
21752
21858
|
}
|
|
21753
21859
|
}
|
|
21754
21860
|
}
|
|
@@ -21773,7 +21879,7 @@ async function main() {
|
|
|
21773
21879
|
const roomId = roomFlag >= 0 ? args[roomFlag + 1] : void 0;
|
|
21774
21880
|
if (!configPath || !roomId)
|
|
21775
21881
|
throw new Error("corner-read-token requires --config and --room");
|
|
21776
|
-
const activated = await activateDaemonTransport(
|
|
21882
|
+
const activated = await activateDaemonTransport(resolve29(configPath));
|
|
21777
21883
|
if (!activated)
|
|
21778
21884
|
throw new Error("corner-read-token requires monolith transport");
|
|
21779
21885
|
const credential = await activated.client.execute("getRoomGitHubToken", { roomId });
|
|
@@ -21835,7 +21941,7 @@ async function main() {
|
|
|
21835
21941
|
}
|
|
21836
21942
|
if (!configPath)
|
|
21837
21943
|
throw new Error("daemon requires --config <runtime.json> or --agent <pubkey>");
|
|
21838
|
-
await runStoredDaemon(
|
|
21944
|
+
await runStoredDaemon(resolve29(configPath));
|
|
21839
21945
|
return;
|
|
21840
21946
|
}
|
|
21841
21947
|
if (command === "update") {
|