usebeeline 0.0.53 → 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.
Files changed (2) hide show
  1. package/dist/usebeeline.mjs +112 -14
  2. package/package.json +1 -1
@@ -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 resolve28 } from "node:path";
959
- import { readFile as readFile14, unlink as unlink3, writeFile as writeFile15 } from "node:fs/promises";
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((resolve29, reject) => {
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
- resolve29(runId);
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((resolve29, reject) => {
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: resolve29,
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);
@@ -21403,7 +21409,7 @@ async function probeReleaseInSubprocess(input) {
21403
21409
  return { kind: "unavailable", reason: `release ${input.releaseId} has no runnable CLI entrypoint` };
21404
21410
  }
21405
21411
  const timeoutMs = input.timeoutMs ?? CURRENT_RELEASE_PROBE_TIMEOUT_MS;
21406
- return new Promise((resolve29) => {
21412
+ return new Promise((resolve30) => {
21407
21413
  const child = spawn7(input.execPath ?? process.execPath, [entrypoint, UPDATE_PROBE_COMMAND, "--config", input.runtimeConfigPath], { env: input.env ?? process.env, stdio: ["ignore", "pipe", "pipe"] });
21408
21414
  let stdout6 = "";
21409
21415
  let stderr = "";
@@ -21413,7 +21419,7 @@ async function probeReleaseInSubprocess(input) {
21413
21419
  return;
21414
21420
  settled = true;
21415
21421
  clearTimeout(timer);
21416
- resolve29(outcome);
21422
+ resolve30(outcome);
21417
21423
  };
21418
21424
  const timer = setTimeout(() => {
21419
21425
  child.kill("SIGKILL");
@@ -21518,6 +21524,90 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
21518
21524
  return status;
21519
21525
  }
21520
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
+
21521
21611
  // apps/body/dist/cli.js
21522
21612
  function usage(exitCode = 1) {
21523
21613
  console.error(`
@@ -21548,6 +21638,10 @@ All other config via env vars (see config.ts).
21548
21638
  process.exit(exitCode);
21549
21639
  }
21550
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
+ }
21551
21645
  var DaemonExitError = class extends Error {
21552
21646
  exitStatus;
21553
21647
  constructor(message, exitStatus) {
@@ -21570,7 +21664,7 @@ async function runStoredDaemon(pathOrPointer) {
21570
21664
  runtime = activated.runtime;
21571
21665
  const daemonApi = activated.client;
21572
21666
  const agent = runtimeAgentCommand(runtime);
21573
- await writeFile15(resolve28(dirname15(configPath), "daemon.pid"), `${process.pid}
21667
+ await writeFile15(resolve29(dirname15(configPath), "daemon.pid"), `${process.pid}
21574
21668
  `, { mode: 384 });
21575
21669
  const env = {
21576
21670
  ...process.env,
@@ -21578,7 +21672,7 @@ async function runStoredDaemon(pathOrPointer) {
21578
21672
  BUZZ_DEV_MCP_BIN: runtime.mcpBinary
21579
21673
  };
21580
21674
  const config = loadBodyConfig({
21581
- workspaceRoot: resolve28(dirname15(configPath), "workspace"),
21675
+ workspaceRoot: resolve29(dirname15(configPath), "workspace"),
21582
21676
  llmEnvFile: runtime.llmEnvFile,
21583
21677
  env,
21584
21678
  agent
@@ -21655,6 +21749,9 @@ async function runStoredDaemon(pathOrPointer) {
21655
21749
  console.log(`[beeline] thin daemon core ${runtime.communityId} starting with ${runtime.rooms.length} Room binding(s)`);
21656
21750
  console.log(`[body] agent binary: ${formatAgentCommand(agent)}`);
21657
21751
  console.log(`[body] ${sandbox.advisory}`);
21752
+ runScratchSweepLogged(runtimeDir);
21753
+ const scratchSweepTimer = setInterval(() => runScratchSweepLogged(runtimeDir), SCRATCH_SWEEP_INTERVAL_MS);
21754
+ scratchSweepTimer.unref();
21658
21755
  let ready = false;
21659
21756
  let stoppingStatus = "daemon stopped";
21660
21757
  try {
@@ -21752,11 +21849,12 @@ async function runStoredDaemon(pathOrPointer) {
21752
21849
  }
21753
21850
  throw error;
21754
21851
  } finally {
21852
+ clearInterval(scratchSweepTimer);
21755
21853
  await notifier.stopping(stoppingStatus).catch(() => void 0);
21756
- const pidPath = resolve28(dirname15(configPath), "daemon.pid");
21854
+ const pidPath = resolve29(dirname15(configPath), "daemon.pid");
21757
21855
  const recorded = Number((await readFile14(pidPath, "utf8").catch(() => "")).trim());
21758
21856
  if (recorded === process.pid) {
21759
- await unlink3(pidPath).catch(() => void 0);
21857
+ await unlink4(pidPath).catch(() => void 0);
21760
21858
  }
21761
21859
  }
21762
21860
  }
@@ -21781,7 +21879,7 @@ async function main() {
21781
21879
  const roomId = roomFlag >= 0 ? args[roomFlag + 1] : void 0;
21782
21880
  if (!configPath || !roomId)
21783
21881
  throw new Error("corner-read-token requires --config and --room");
21784
- const activated = await activateDaemonTransport(resolve28(configPath));
21882
+ const activated = await activateDaemonTransport(resolve29(configPath));
21785
21883
  if (!activated)
21786
21884
  throw new Error("corner-read-token requires monolith transport");
21787
21885
  const credential = await activated.client.execute("getRoomGitHubToken", { roomId });
@@ -21843,7 +21941,7 @@ async function main() {
21843
21941
  }
21844
21942
  if (!configPath)
21845
21943
  throw new Error("daemon requires --config <runtime.json> or --agent <pubkey>");
21846
- await runStoredDaemon(resolve28(configPath));
21944
+ await runStoredDaemon(resolve29(configPath));
21847
21945
  return;
21848
21946
  }
21849
21947
  if (command === "update") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usebeeline",
3
- "version": "0.0.53",
3
+ "version": "0.0.54",
4
4
  "description": "Connect an AI coding agent to Beeline with one command.",
5
5
  "homepage": "https://usebeeline.app",
6
6
  "bugs": {