usebeeline 0.1.173 → 0.1.175

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 +114 -156
  2. package/package.json +1 -1
@@ -91,15 +91,10 @@ async function withKernelLock(key, work, waitMs = 6e5) {
91
91
  const remaining = deadline - Date.now();
92
92
  if (remaining <= 0)
93
93
  throw new KernelLockBusyError();
94
- await new Promise((done, reject) => {
94
+ await new Promise((done) => {
95
95
  const peer = createConnection2(address);
96
96
  peer.resume();
97
- const timer = setTimeout(() => {
98
- peer.destroy();
99
- reject(new KernelLockBusyError());
100
- }, remaining);
101
97
  const finish = () => {
102
- clearTimeout(timer);
103
98
  peer.destroy();
104
99
  done();
105
100
  };
@@ -671,12 +666,12 @@ function archiveUrlFor(manifestUrl, file) {
671
666
  return `${withoutTrailingSlash.slice(0, index)}/${file}`;
672
667
  }
673
668
  async function fetchText(url, fetchImpl) {
674
- const response = await fetchImpl(url, { signal: AbortSignal.timeout(3e4) });
669
+ const response = await fetchImpl(url, { signal: void 0 });
675
670
  if (!response.ok)
676
671
  throw new Error(`fetching ${url} failed: HTTP ${response.status}`);
677
672
  return response.text();
678
673
  }
679
- function run(command2, args, timeoutMs) {
674
+ function run(command2, args, _timeoutMs) {
680
675
  return new Promise((resolveRun) => {
681
676
  const child = spawn2(command2, args, { stdio: ["ignore", "ignore", "pipe"] });
682
677
  let stderr = "";
@@ -684,13 +679,10 @@ function run(command2, args, timeoutMs) {
684
679
  child.stderr?.on("data", (chunk) => {
685
680
  stderr = `${stderr}${chunk}`.slice(-4e3);
686
681
  });
687
- const timer = setTimeout(() => child.kill("SIGKILL"), timeoutMs);
688
682
  child.once("error", () => {
689
- clearTimeout(timer);
690
683
  resolveRun({ status: -1, stderr });
691
684
  });
692
685
  child.once("exit", (status) => {
693
- clearTimeout(timer);
694
686
  resolveRun({ status, stderr });
695
687
  });
696
688
  });
@@ -721,11 +713,7 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
721
713
  return ms;
722
714
  };
723
715
  const fetchImpl = (input, init) => (opts.fetchImpl ?? fetch)(input, {
724
- ...init,
725
- signal: AbortSignal.any([
726
- ...init?.signal ? [init.signal] : [],
727
- AbortSignal.timeout(remaining())
728
- ])
716
+ ...init
729
717
  });
730
718
  const log2 = opts.logger ?? ((line) => console.log(`[body] self-update: ${line}`));
731
719
  let releaseId = sanitizeReleaseId((published.commit ?? published.version ?? `release-${Date.now()}`) + (opts.force ? `-repair-${Date.now()}` : ""));
@@ -756,7 +744,7 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
756
744
  try {
757
745
  log2(`downloading ${published.file}`);
758
746
  const response = await fetchImpl(archiveUrlFor(manifestUrl, published.file), {
759
- signal: AbortSignal.timeout(10 * 6e4)
747
+ signal: void 0
760
748
  });
761
749
  if (!response.ok || !response.body) {
762
750
  throw new Error(`downloading ${published.file} failed: HTTP ${response.status}`);
@@ -775,17 +763,14 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
775
763
  await writeFile2(tempArchive, Buffer.concat(chunks), { mode: 384 });
776
764
  const entries = (await new Promise((resolveList, rejectList) => {
777
765
  const child = spawn2("tar", ["-tzf", tempArchive], { stdio: ["ignore", "pipe", "inherit"] });
778
- const timer = setTimeout(() => child.kill("SIGKILL"), Math.min(3e4, remaining()));
779
766
  let out = "";
780
767
  child.stdout?.on("data", (chunk) => {
781
768
  out += chunk.toString("utf8");
782
769
  });
783
770
  child.once("error", (error) => {
784
- clearTimeout(timer);
785
771
  rejectList(error);
786
772
  });
787
773
  child.once("exit", (status) => {
788
- clearTimeout(timer);
789
774
  status === 0 ? resolveList(out) : rejectList(new Error("tar -tzf failed"));
790
775
  });
791
776
  })).split("\n").filter(Boolean);
@@ -1171,24 +1156,10 @@ async function prepareReleaseInWorker(env, deadlineAt, entrypoint) {
1171
1156
  child.stderr.on("data", (chunk) => {
1172
1157
  stderr = (stderr + chunk).slice(-16e3);
1173
1158
  });
1174
- const kill = (signal) => {
1175
- try {
1176
- process.kill(-child.pid, signal);
1177
- } catch {
1178
- child.kill(signal);
1179
- }
1180
- };
1181
- const timer = setTimeout(() => {
1182
- kill("SIGTERM");
1183
- setTimeout(() => kill("SIGKILL"), 1e3).unref();
1184
- reject(new Error("release prepare deadline exceeded"));
1185
- }, Math.max(0, deadlineAt - Date.now()));
1186
1159
  child.once("error", (error) => {
1187
- clearTimeout(timer);
1188
1160
  reject(error);
1189
1161
  });
1190
1162
  child.once("exit", (code) => {
1191
- clearTimeout(timer);
1192
1163
  if (code !== 0)
1193
1164
  return reject(new Error(`release preparation failed (${code}): ${stderr.trim()}`));
1194
1165
  try {
@@ -1221,7 +1192,6 @@ var init_managed_update = __esm({
1221
1192
  #handoffAt;
1222
1193
  #interruptAt;
1223
1194
  #deadlineAt;
1224
- #timer;
1225
1195
  #handingOff;
1226
1196
  #notice;
1227
1197
  #completed = false;
@@ -1261,7 +1231,6 @@ var init_managed_update = __esm({
1261
1231
  });
1262
1232
  if (!identity?.version || !versionAtLeast(identity.version, this.#minimum)) {
1263
1233
  this.#prepared = void 0;
1264
- clearTimeout(this.#timer);
1265
1234
  throw new Error(`published helper ${identity?.version ?? "unknown"} is below required ${this.#minimum}`);
1266
1235
  }
1267
1236
  }
@@ -1271,8 +1240,6 @@ var init_managed_update = __esm({
1271
1240
  this.#handoffAt = void 0;
1272
1241
  this.#interruptAt = void 0;
1273
1242
  this.#draining = false;
1274
- clearTimeout(this.#timer);
1275
- this.#timer = void 0;
1276
1243
  this.options.changed(void 0);
1277
1244
  return;
1278
1245
  }
@@ -1281,11 +1248,6 @@ var init_managed_update = __esm({
1281
1248
  this.#handoffAt ??= Math.min(this.now() + (this.options.drainMs ?? UPDATE_DRAIN_DEADLINE_MS), this.#deadlineAt - 12e4);
1282
1249
  this.#interruptAt ??= this.now() + UPDATE_INTERRUPT_DEADLINE_MS;
1283
1250
  this.options.changed(releaseId);
1284
- if (!this.#timer)
1285
- this.#timer = setTimeout(() => {
1286
- this.#timer = void 0;
1287
- void this.idleChanged();
1288
- }, Math.max(0, this.#handoffAt - this.now()));
1289
1251
  await this.idleChanged();
1290
1252
  }
1291
1253
  async idleChanged() {
@@ -1302,14 +1264,8 @@ var init_managed_update = __esm({
1302
1264
  this.options.failed(error, this.#minimum);
1303
1265
  }
1304
1266
  }
1305
- if (!this.#timer && this.now() >= this.#handoffAt)
1306
- this.#timer = setTimeout(() => {
1307
- this.#timer = void 0;
1308
- void this.idleChanged();
1309
- }, Math.max(0, this.#interruptAt - this.now()));
1310
1267
  return;
1311
1268
  }
1312
- clearTimeout(this.#timer);
1313
1269
  const target = this.#prepared;
1314
1270
  this.#handingOff = this.options.handoff(target, interrupted).then(() => {
1315
1271
  this.#completed = true;
@@ -1322,7 +1278,6 @@ var init_managed_update = __esm({
1322
1278
  await this.#handingOff;
1323
1279
  }
1324
1280
  dispose() {
1325
- clearTimeout(this.#timer);
1326
1281
  }
1327
1282
  now() {
1328
1283
  return (this.options.now ?? Date.now)();
@@ -1532,8 +1487,8 @@ function fromProcessName(command2) {
1532
1487
  const name = basename2(command2.split(/\s+/)[0] ?? "").toLowerCase().replace(/\.(exe|js|mjs|cjs)$/, "");
1533
1488
  return AGENTS.find((agent) => SESSION_AGENT_BEHAVIORS[agent].processNames?.includes(name));
1534
1489
  }
1535
- function statParent(stat3) {
1536
- const rest = stat3.slice(stat3.lastIndexOf(")") + 1).trim().split(/\s+/);
1490
+ function statParent(stat4) {
1491
+ const rest = stat4.slice(stat4.lastIndexOf(")") + 1).trim().split(/\s+/);
1537
1492
  const parent = Number(rest[1]);
1538
1493
  return Number.isInteger(parent) && parent > 0 ? parent : void 0;
1539
1494
  }
@@ -20189,6 +20144,60 @@ var require_undici = __commonJS({
20189
20144
  }
20190
20145
  });
20191
20146
 
20147
+ // apps/body/dist/filesystem-change.js
20148
+ import { watch as watch2 } from "node:fs";
20149
+ import { stat as stat2 } from "node:fs/promises";
20150
+ import { dirname as dirname5 } from "node:path";
20151
+ function waitForPathRemoval(path) {
20152
+ return new Promise((resolve11, reject) => {
20153
+ let reading = false, dirty = false, ended = false;
20154
+ const finish = (error) => {
20155
+ if (ended)
20156
+ return;
20157
+ ended = true;
20158
+ watcher.close();
20159
+ if (error)
20160
+ reject(error);
20161
+ else
20162
+ resolve11();
20163
+ };
20164
+ const inspect = async () => {
20165
+ dirty = true;
20166
+ if (reading || ended)
20167
+ return;
20168
+ reading = true;
20169
+ try {
20170
+ do {
20171
+ dirty = false;
20172
+ const present = await stat2(path).then(() => true, (error) => {
20173
+ if (error.code === "ENOENT")
20174
+ return false;
20175
+ throw error;
20176
+ });
20177
+ if (!present) {
20178
+ finish();
20179
+ return;
20180
+ }
20181
+ } while (dirty && !ended);
20182
+ } catch (error) {
20183
+ finish(error);
20184
+ } finally {
20185
+ reading = false;
20186
+ }
20187
+ };
20188
+ const watcher = watch2(dirname5(path), () => {
20189
+ void inspect();
20190
+ });
20191
+ watcher.once("error", finish);
20192
+ void inspect();
20193
+ });
20194
+ }
20195
+ var init_filesystem_change = __esm({
20196
+ "apps/body/dist/filesystem-change.js"() {
20197
+ "use strict";
20198
+ }
20199
+ });
20200
+
20192
20201
  // apps/body/dist/session-join/store.js
20193
20202
  var store_exports = {};
20194
20203
  __export(store_exports, {
@@ -20259,7 +20268,7 @@ async function withLock(dir, run2) {
20259
20268
  }
20260
20269
  if (attempt > 400)
20261
20270
  throw new Error("Beeline session state is locked");
20262
- await new Promise((resolve11) => setTimeout(resolve11, 25));
20271
+ await waitForPathRemoval(lock);
20263
20272
  }
20264
20273
  }
20265
20274
  try {
@@ -20382,6 +20391,7 @@ var HOOK_TTL_MS, lastInboxOrder;
20382
20391
  var init_store = __esm({
20383
20392
  "apps/body/dist/session-join/store.js"() {
20384
20393
  "use strict";
20394
+ init_filesystem_change();
20385
20395
  HOOK_TTL_MS = 6 * 36e5;
20386
20396
  lastInboxOrder = 0;
20387
20397
  }
@@ -20410,12 +20420,11 @@ async function request(url, body, headers, stream, cancellation, held = false) {
20410
20420
  headers: { "content-type": "application/json", ...headers },
20411
20421
  ...stream || held ? { dispatcher: memberStreamAgent } : {},
20412
20422
  ...!stream ? { body: JSON.stringify(body) } : {},
20413
- signal: stream ?? cancellation ?? AbortSignal.timeout(6e4)
20423
+ signal: stream ?? cancellation ?? void 0
20414
20424
  });
20415
20425
  }
20416
- async function postJson(url, body, headers = {}, signal, timeoutMs = 6e4, held = false) {
20417
- const timeout = AbortSignal.timeout(Math.max(1, timeoutMs));
20418
- const response = await request(url, body, headers, void 0, signal ? AbortSignal.any([signal, timeout]) : timeout, held);
20426
+ async function postJson(url, body, headers = {}, signal, _timeoutMs = 6e4, held = false) {
20427
+ const response = await request(url, body, headers, void 0, signal, held);
20419
20428
  const text = await response.text();
20420
20429
  let value = {};
20421
20430
  try {
@@ -20574,12 +20583,9 @@ async function* memberStream(session2, token, signal, opened = () => {
20574
20583
  signal.addEventListener("abort", abort, { once: true });
20575
20584
  if (signal.aborted)
20576
20585
  abort();
20577
- const handshake = setTimeout(abort, 6e4);
20578
- handshake.unref?.();
20579
20586
  let cancel;
20580
20587
  try {
20581
20588
  const response = await request(url.toString(), void 0, { authorization: `Bearer ${token}`, accept: "application/x-ndjson" }, controller.signal);
20582
- clearTimeout(handshake);
20583
20589
  if (!response.ok || !response.body || !response.headers.get("content-type")?.startsWith("application/x-ndjson"))
20584
20590
  throw new Error(`Beeline member stream unavailable (HTTP ${response.status})`);
20585
20591
  opened();
@@ -20603,7 +20609,6 @@ async function* memberStream(session2, token, signal, opened = () => {
20603
20609
  if (buffered.trim())
20604
20610
  throw new Error("Beeline stream ended inside a delivery");
20605
20611
  } finally {
20606
- clearTimeout(handshake);
20607
20612
  signal.removeEventListener("abort", abort);
20608
20613
  await cancel?.().catch(() => void 0);
20609
20614
  }
@@ -23835,22 +23840,16 @@ function scanClaude(env = process.env, alive = pidAlive) {
23835
23840
  function chosenName(session2) {
23836
23841
  return ["user", "peer", "hook"].includes(session2.nameSource ?? "") ? session2.name : void 0;
23837
23842
  }
23838
- function postToClaude(socket, text, timeoutMs = 5e3) {
23843
+ function postToClaude(socket, text, _timeoutMs = 5e3) {
23839
23844
  return new Promise((resolve11, reject) => {
23840
23845
  const connection = createConnection3(socket.path);
23841
- const timer = setTimeout(() => {
23842
- connection.destroy();
23843
- reject(new Error("Claude Code inbox did not answer"));
23844
- }, timeoutMs);
23845
23846
  connection.once("error", (error) => {
23846
- clearTimeout(timer);
23847
23847
  reject(error);
23848
23848
  });
23849
23849
  connection.once("connect", () => {
23850
23850
  if (socket.token)
23851
23851
  connection.write(JSON.stringify({ type: "auth", token: socket.token }) + "\n");
23852
23852
  connection.end(JSON.stringify({ type: "user", message: { role: "user", content: text } }) + "\n", () => {
23853
- clearTimeout(timer);
23854
23853
  resolve11();
23855
23854
  });
23856
23855
  });
@@ -23918,7 +23917,7 @@ var init_claude = __esm({
23918
23917
  });
23919
23918
 
23920
23919
  // apps/body/dist/session-join/claude-mcp.js
23921
- import { mkdirSync as mkdirSync2, readFileSync as readFileSync5, readdirSync as readdirSync4, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
23920
+ import { watch as watch3, mkdirSync as mkdirSync2, readFileSync as readFileSync5, readdirSync as readdirSync4, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
23922
23921
  import { join as join5 } from "node:path";
23923
23922
  import { createInterface } from "node:readline";
23924
23923
  function hasClaudeMcp(dir, claudePid) {
@@ -23985,9 +23984,10 @@ async function runClaudeMcp(dir, env, rulesFor) {
23985
23984
  flushing = false;
23986
23985
  }
23987
23986
  };
23988
- const timer = setInterval(() => {
23989
- void flush2().catch(() => void 0);
23990
- }, 500);
23987
+ const watcher = watch3(dir, { recursive: true }, (_event, name) => {
23988
+ if (String(name ?? "").startsWith("inbox/"))
23989
+ void flush2().catch(() => void 0);
23990
+ });
23991
23991
  try {
23992
23992
  await flush2();
23993
23993
  for await (const line of createInterface({ input: process.stdin })) {
@@ -24009,7 +24009,7 @@ async function runClaudeMcp(dir, env, rulesFor) {
24009
24009
  process.stdout.write(JSON.stringify({ jsonrpc: "2.0", id: request2.id, ...result ? { result } : { error: { code: -32601, message: "Method not found" } } }) + "\n");
24010
24010
  }
24011
24011
  } finally {
24012
- clearInterval(timer);
24012
+ watcher.close();
24013
24013
  if (registration)
24014
24014
  rmSync2(registration, { force: true });
24015
24015
  }
@@ -24075,7 +24075,7 @@ var init_sessions = __esm({
24075
24075
 
24076
24076
  // apps/body/dist/session-join/bridge.js
24077
24077
  import { spawn as spawn5 } from "node:child_process";
24078
- import { chmodSync as chmodSync2, closeSync as closeSync3, existsSync as existsSync2, mkdirSync as mkdirSync3, openSync as openSync3, readFileSync as readFileSync6, readdirSync as readdirSync5, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync3, watch as watch2 } from "node:fs";
24078
+ import { chmodSync as chmodSync2, closeSync as closeSync3, existsSync as existsSync2, mkdirSync as mkdirSync3, openSync as openSync3, readFileSync as readFileSync6, readdirSync as readdirSync5, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync3, watch as watch4 } from "node:fs";
24079
24079
  import { createConnection as createConnection4, createServer as createServer3 } from "node:net";
24080
24080
  import { join as join6 } from "node:path";
24081
24081
  import { createHash as createHash6 } from "node:crypto";
@@ -24159,14 +24159,13 @@ async function acceptMemberDelivery(dir, key, runner2, raw) {
24159
24159
  return 0;
24160
24160
  let queued = 0;
24161
24161
  if (frame.type === "delivery") {
24162
- const wakeKey = (wake) => wake.deliveryVersion === void 0 ? wake.id : `${wake.id}:${wake.deliveryVersion}`;
24163
24162
  const parts = [
24164
24163
  ...frame.mentions.map((mention) => renderMention(mention, joined2, runner2)),
24165
- ...frame.wakes.filter((wake) => !joined2.deliveredWakes.includes(wakeKey(wake)) && !(wake.deliveryVersion === 0 && joined2.deliveredWakes.includes(wake.id))).map((wake) => renderWake(wake, joined2, runner2))
24164
+ ...frame.wakes.filter((wake) => !joined2.deliveredWakes.includes(wake.id)).map((wake) => renderWake(wake, joined2, runner2))
24166
24165
  ];
24167
24166
  if (parts.length && queueInboxOnce(dir, key, frame.deliveryId, parts.join("\n\n")))
24168
24167
  queued = parts.length;
24169
- joined2.deliveredWakes = [.../* @__PURE__ */ new Set([...joined2.deliveredWakes, ...frame.wakes.map(wakeKey)])];
24168
+ joined2.deliveredWakes = [.../* @__PURE__ */ new Set([...joined2.deliveredWakes, ...frame.wakes.map((wake) => wake.id)])];
24170
24169
  } else {
24171
24170
  const old = joined2.streamCursor;
24172
24171
  if (old?.epoch === frame.cursor.epoch && old.through > frame.cursor.through)
@@ -24269,7 +24268,7 @@ async function serveOutboxes(dir) {
24269
24268
  }
24270
24269
  return served;
24271
24270
  }
24272
- async function toolViaOutbox(cwd, name, args, timeoutMs = 9e4) {
24271
+ async function toolViaOutbox(cwd, name, args) {
24273
24272
  const dirPath = outboxDir(cwd);
24274
24273
  mkdirSync3(dirPath, { recursive: true });
24275
24274
  writeFileSync3(join6(cwd, ".beeline", ".gitignore"), "*\n");
@@ -24283,7 +24282,6 @@ async function toolViaOutbox(cwd, name, args, timeoutMs = 9e4) {
24283
24282
  if (settled)
24284
24283
  return;
24285
24284
  settled = true;
24286
- clearTimeout(deadline);
24287
24285
  watcher.close();
24288
24286
  resolve11(answer);
24289
24287
  };
@@ -24295,23 +24293,10 @@ async function toolViaOutbox(cwd, name, args, timeoutMs = 9e4) {
24295
24293
  } catch {
24296
24294
  }
24297
24295
  };
24298
- const watcher = watch2(dirPath, (_event, file) => {
24296
+ const watcher = watch4(dirPath, (_event, file) => {
24299
24297
  if (String(file ?? "") === `${id}.result.json`)
24300
24298
  inspect();
24301
24299
  });
24302
- const deadline = setTimeout(() => {
24303
- inspect();
24304
- if (settled)
24305
- return;
24306
- const abandoned = request2 + ".abandoned";
24307
- try {
24308
- renameSync2(request2, abandoned);
24309
- rmSync3(abandoned, { force: true });
24310
- finish(void 0);
24311
- } catch {
24312
- finish({ ok: false, error: "Beeline tool result is awaiting confirmation" });
24313
- }
24314
- }, timeoutMs);
24315
24300
  inspect();
24316
24301
  });
24317
24302
  }
@@ -24343,7 +24328,6 @@ function toolViaBridge(dir, key, name, args) {
24343
24328
  finish(sent ? unknown : void 0);
24344
24329
  }
24345
24330
  });
24346
- connection.setTimeout(9e4, () => finish(sent ? unknown : void 0));
24347
24331
  });
24348
24332
  }
24349
24333
  async function runBridge(dir, runner2) {
@@ -24367,7 +24351,7 @@ async function runBridge(dir, runner2) {
24367
24351
  wake?.();
24368
24352
  };
24369
24353
  serveTools(dir);
24370
- const localWatch = watch2(dir, { recursive: true }, (_event, name) => {
24354
+ const localWatch = watch4(dir, { recursive: true }, (_event, name) => {
24371
24355
  const path = String(name ?? "");
24372
24356
  if (path === "state.json" || path.startsWith("hooks/") || path.startsWith("inbox/") || path.startsWith("deliveries/"))
24373
24357
  changed();
@@ -24375,8 +24359,6 @@ async function runBridge(dir, runner2) {
24375
24359
  const stop = () => {
24376
24360
  for (const stream of streams.values()) {
24377
24361
  stream.controller.abort();
24378
- if (stream.expiry)
24379
- clearTimeout(stream.expiry);
24380
24362
  }
24381
24363
  localWatch.close();
24382
24364
  for (const watcher of outboxWatches.values())
@@ -24399,14 +24381,6 @@ async function runBridge(dir, runner2) {
24399
24381
  const start = (joined2) => {
24400
24382
  const controller = new AbortController(), entry = { fingerprint: fingerprint(joined2), controller };
24401
24383
  streams.set(joined2.key, entry);
24402
- const remaining = (joined2.accessExpiresAt ?? 0) - Date.now();
24403
- if (remaining > 0) {
24404
- entry.expiry = setTimeout(() => {
24405
- controller.abort();
24406
- void accessToken(dir, joined2.key).then(changed, (error) => log(dir, `${joined2.key}: credential renewal ended: ${String(error)}`));
24407
- }, remaining);
24408
- entry.expiry.unref?.();
24409
- }
24410
24384
  void (async () => {
24411
24385
  let recovered = false;
24412
24386
  while (!controller.signal.aborted) {
@@ -24450,16 +24424,12 @@ async function runBridge(dir, runner2) {
24450
24424
  for (const [key, stream] of streams)
24451
24425
  if (!sessions.some((session2) => session2.key === key)) {
24452
24426
  stream.controller.abort();
24453
- if (stream.expiry)
24454
- clearTimeout(stream.expiry);
24455
24427
  streams.delete(key);
24456
24428
  }
24457
24429
  for (const joined2 of sessions) {
24458
24430
  const old = streams.get(joined2.key);
24459
24431
  if (!old || old.fingerprint !== fingerprint(joined2)) {
24460
24432
  old?.controller.abort();
24461
- if (old?.expiry)
24462
- clearTimeout(old.expiry);
24463
24433
  start(joined2);
24464
24434
  }
24465
24435
  const path = outboxDir(joined2.cwd);
@@ -24468,7 +24438,7 @@ async function runBridge(dir, runner2) {
24468
24438
  const ignore = join6(joined2.cwd, ".beeline", ".gitignore");
24469
24439
  if (!existsSync2(ignore))
24470
24440
  writeFileSync3(ignore, "*\n", { mode: 384 });
24471
- outboxWatches.set(path, watch2(path, (_event, name) => {
24441
+ outboxWatches.set(path, watch4(path, (_event, name) => {
24472
24442
  if (String(name ?? "").endsWith(".request.json"))
24473
24443
  changed();
24474
24444
  }));
@@ -24488,8 +24458,6 @@ async function runBridge(dir, runner2) {
24488
24458
  watcher.close();
24489
24459
  for (const stream of streams.values()) {
24490
24460
  stream.controller.abort();
24491
- if (stream.expiry)
24492
- clearTimeout(stream.expiry);
24493
24461
  }
24494
24462
  }
24495
24463
  log(dir, `bridge ${process.pid} stopped: no joined sessions`);
@@ -24544,6 +24512,9 @@ var init_templates = __esm({
24544
24512
  "use strict";
24545
24513
  OPENCODE_PLUGIN = `// Beeline for opencode: written by \`usebeeline join\`, removed by \`usebeeline session leave\`.
24546
24514
  import { execFile } from "node:child_process"
24515
+ import { watch, mkdirSync } from "node:fs"
24516
+ import { join } from "node:path"
24517
+ import { homedir } from "node:os"
24547
24518
 
24548
24519
  const NODE = "__NODE__"
24549
24520
  const BUNDLE = "__BUNDLE__"
@@ -24572,7 +24543,9 @@ const network = (prompt: (id: string, text: string) => Promise<unknown>) => {
24572
24543
  delivering.delete(id)
24573
24544
  }
24574
24545
  }
24575
- const timer = setInterval(() => idle.forEach((id) => void deliver(id)), 5_000)
24546
+ const inbox=join(process.env.XDG_STATE_HOME||join(process.env.HOME||homedir(),".local/state"),"beeline-sessions","inbox")
24547
+ mkdirSync(inbox,{recursive:true})
24548
+ const watcher=watch(inbox,()=>idle.forEach((id)=>void deliver(id)))
24576
24549
  return {
24577
24550
  subagent: (id: string) => subagents.add(id),
24578
24551
  status: async (id: string, state: string, dir: string) => {
@@ -24584,7 +24557,7 @@ const network = (prompt: (id: string, text: string) => Promise<unknown>) => {
24584
24557
  await deliver(id)
24585
24558
  } else idle.delete(id)
24586
24559
  },
24587
- stop: () => clearInterval(timer),
24560
+ stop: () => watcher.close(),
24588
24561
  end: (id?: string) => {
24589
24562
  for (const [s, dir] of [...dirs]) {
24590
24563
  if (id && s !== id) continue
@@ -24649,6 +24622,9 @@ export default {
24649
24622
  PI_EXTENSION = `// Beeline for pi: written by \`usebeeline join\`, removed by \`usebeeline session leave\`.
24650
24623
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"
24651
24624
  import { execFile } from "node:child_process"
24625
+ import { watch, mkdirSync } from "node:fs"
24626
+ import { join } from "node:path"
24627
+ import { homedir } from "node:os"
24652
24628
 
24653
24629
  const NODE = "__NODE__"
24654
24630
  const BUNDLE = "__BUNDLE__"
@@ -24658,7 +24634,7 @@ export default function (pi: ExtensionAPI) {
24658
24634
  let cwd = process.cwd()
24659
24635
  let busy = false
24660
24636
  let delivering = false
24661
- let timer: ReturnType<typeof setInterval> | undefined
24637
+ let watcher: ReturnType<typeof watch> | undefined
24662
24638
  const hook = (args: string[]) =>
24663
24639
  new Promise<string>((resolve) =>
24664
24640
  execFile(NODE, [BUNDLE, "session", "hook", "pi", ...args, "--session", id], { cwd, timeout: 10_000, windowsHide: true },
@@ -24678,9 +24654,9 @@ export default function (pi: ExtensionAPI) {
24678
24654
  id = ctx.sessionManager.getSessionId()
24679
24655
  cwd = ctx.cwd
24680
24656
  await hook(["status", "--state", "idle"])
24681
- timer ??= setInterval(() => {
24682
- if (!busy) void deliver("poll")
24683
- }, 5_000)
24657
+ const inbox=join(process.env.XDG_STATE_HOME||join(process.env.HOME||homedir(),".local/state"),"beeline-sessions","inbox")
24658
+ mkdirSync(inbox,{recursive:true})
24659
+ watcher??=watch(inbox,()=>{void deliver("poll")})
24684
24660
  })
24685
24661
  pi.on("agent_start", async () => {
24686
24662
  busy = true
@@ -24695,8 +24671,8 @@ export default function (pi: ExtensionAPI) {
24695
24671
  await deliver("poll")
24696
24672
  })
24697
24673
  pi.on("session_shutdown", async () => {
24698
- if (timer) clearInterval(timer)
24699
- timer = undefined
24674
+ watcher?.close()
24675
+ watcher = undefined
24700
24676
  await hook(["session-end"])
24701
24677
  })
24702
24678
  }
@@ -24759,7 +24735,7 @@ def register(ctx):
24759
24735
  import { spawnSync } from "node:child_process";
24760
24736
  import { copyFileSync, existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync7, renameSync as renameSync3, rmSync as rmSync4, statSync as statSync4, writeFileSync as writeFileSync4, chmodSync as chmodSync3 } from "node:fs";
24761
24737
  import { homedir as homedir7 } from "node:os";
24762
- import { dirname as dirname5, join as join7 } from "node:path";
24738
+ import { dirname as dirname6, join as join7 } from "node:path";
24763
24739
  function home(env) {
24764
24740
  return env.HOME || homedir7();
24765
24741
  }
@@ -24795,7 +24771,7 @@ function writeFile3(path, content, expected) {
24795
24771
  }
24796
24772
  if (before === content)
24797
24773
  return false;
24798
- mkdirSync4(dirname5(path), { recursive: true });
24774
+ mkdirSync4(dirname6(path), { recursive: true });
24799
24775
  const backup = `${path}.bak-${NAME}`;
24800
24776
  if (before !== void 0 && !existsSync3(backup) && !before.includes(" session hook "))
24801
24777
  copyFileSync(path, backup);
@@ -24958,7 +24934,7 @@ function antigravity(context) {
24958
24934
  const sidecars = object2(config, "sidecars");
24959
24935
  if (context.remove) {
24960
24936
  delete sidecars[NAME];
24961
- rmSync4(dirname5(sidecar), { recursive: true, force: true });
24937
+ rmSync4(dirname6(sidecar), { recursive: true, force: true });
24962
24938
  } else {
24963
24939
  if (writeJson(sidecar, {
24964
24940
  command: context.node,
@@ -25185,10 +25161,6 @@ async function trustCodexHook(context, bin, cwd) {
25185
25161
  pending.set(key, { resolve: resolve11, reject: () => reject(new Error("Codex hook trust unavailable")) });
25186
25162
  child.stdin.write(JSON.stringify({ id: key, method, params }) + "\n");
25187
25163
  });
25188
- const timer = setTimeout(() => {
25189
- fail();
25190
- child.kill();
25191
- }, 15e3);
25192
25164
  try {
25193
25165
  await request2("initialize", { clientInfo: { name: "beeline-session-join", version: "1" }, capabilities: { experimentalApi: true } });
25194
25166
  const list = await request2("hooks/list", { cwds: [cwd] });
@@ -25201,9 +25173,6 @@ async function trustCodexHook(context, bin, cwd) {
25201
25173
  return result.status === "ok";
25202
25174
  } catch {
25203
25175
  return false;
25204
- } finally {
25205
- clearTimeout(timer);
25206
- child.kill();
25207
25176
  }
25208
25177
  }
25209
25178
  var init_codex_trust = __esm({
@@ -25292,6 +25261,7 @@ var init_hook = __esm({
25292
25261
  });
25293
25262
 
25294
25263
  // apps/body/dist/session-join/pull-apps.js
25264
+ import { watch as watch5 } from "node:fs/promises";
25295
25265
  import { execFile as execFile4 } from "node:child_process";
25296
25266
  import { createInterface as createInterface2 } from "node:readline";
25297
25267
  function zcodeKey(dir, cwd) {
@@ -25356,10 +25326,12 @@ async function antigravityOnce(dir, live, send = agentapi) {
25356
25326
  return handed;
25357
25327
  }
25358
25328
  async function runAntigravitySidecar(dir) {
25359
- for (; ; ) {
25360
- await antigravityOnce(dir, hookSessions(dir)).catch(() => 0);
25361
- await new Promise((resolve11) => setTimeout(resolve11, 3e3));
25329
+ await antigravityOnce(dir, hookSessions(dir)).catch(() => 0);
25330
+ for await (const event of watch5(dir, { recursive: true })) {
25331
+ if (event.filename?.startsWith("inbox/"))
25332
+ await antigravityOnce(dir, hookSessions(dir)).catch(() => 0);
25362
25333
  }
25334
+ throw new Error("session inbox watcher closed");
25363
25335
  }
25364
25336
  var agentapi;
25365
25337
  var init_pull_apps = __esm({
@@ -25379,7 +25351,7 @@ __export(command_exports, {
25379
25351
  });
25380
25352
  import { spawn as spawn7, spawnSync as spawnSync2 } from "node:child_process";
25381
25353
  import { closeSync as closeSync4, copyFileSync as copyFileSync2, existsSync as existsSync5, fsyncSync, mkdirSync as mkdirSync5, openSync as openSync4, readFileSync as readFileSync9, readdirSync as readdirSync6, renameSync as renameSync4, rmSync as rmSync6, writeFileSync as writeFileSync5 } from "node:fs";
25382
- import { delimiter, dirname as dirname6, join as join10, resolve as resolve9 } from "node:path";
25354
+ import { delimiter, dirname as dirname7, join as join10, resolve as resolve9 } from "node:path";
25383
25355
  import { createHash as createHash7, randomUUID as randomUUID2 } from "node:crypto";
25384
25356
  function writePending(file, pending) {
25385
25357
  const temporary = file + "." + randomUUID2() + ".tmp";
@@ -25393,7 +25365,7 @@ function writePending(file, pending) {
25393
25365
  }
25394
25366
  renameSync4(temporary, file);
25395
25367
  if (process.platform !== "win32") {
25396
- const directory = openSync4(dirname6(file), "r");
25368
+ const directory = openSync4(dirname7(file), "r");
25397
25369
  try {
25398
25370
  fsyncSync(directory);
25399
25371
  } finally {
@@ -25607,7 +25579,6 @@ async function finishJoinOwned(file, env) {
25607
25579
  const transcript = pending.sessionId ? claudeTranscript(pending.sessionId, env) : void 0;
25608
25580
  if (transcript && permissionMode(transcript) === "bypassPermissions") {
25609
25581
  await acceptClaudeInbound(env);
25610
- await new Promise((resolve11) => setTimeout(resolve11, 1e3));
25611
25582
  }
25612
25583
  }
25613
25584
  await updateState(dir, (state) => {
@@ -25766,7 +25737,7 @@ async function session(args, env) {
25766
25737
  method: "POST",
25767
25738
  headers: { "content-type": "application/json" },
25768
25739
  body: JSON.stringify({ client_id: joined2.clientId, token: joined2.refreshToken }),
25769
- signal: AbortSignal.timeout(15e3)
25740
+ signal: void 0
25770
25741
  }).catch(() => void 0);
25771
25742
  const left = await updateState(dir, (state) => {
25772
25743
  state.sessions = state.sessions.filter((s) => s.key !== joined2.key);
@@ -25780,16 +25751,14 @@ async function session(args, env) {
25780
25751
  }
25781
25752
  throw new Error("Usage: usebeeline join | usebeeline session reply|read|tool|status|leave");
25782
25753
  }
25783
- function readStdin(limitMs) {
25754
+ function readStdin(_limitMs) {
25784
25755
  return new Promise((resolve11) => {
25785
25756
  let text = "";
25786
- const timer = setTimeout(() => resolve11(text), limitMs);
25787
25757
  process.stdin.setEncoding("utf8");
25788
25758
  process.stdin.on("data", (chunk) => {
25789
25759
  text += chunk;
25790
25760
  });
25791
25761
  process.stdin.on("end", () => {
25792
- clearTimeout(timer);
25793
25762
  resolve11(text);
25794
25763
  });
25795
25764
  });
@@ -25835,7 +25804,7 @@ var init_command = __esm({
25835
25804
 
25836
25805
  // apps/body/dist/recovery-cli.js
25837
25806
  import { spawn as spawn8 } from "node:child_process";
25838
- import { readFile as readFile4, readdir as readdir5, stat as stat2, unlink } from "node:fs/promises";
25807
+ import { readFile as readFile4, readdir as readdir5, stat as stat3, unlink } from "node:fs/promises";
25839
25808
  import { resolve as resolve10 } from "node:path";
25840
25809
 
25841
25810
  // apps/body/dist/recovery.js
@@ -25867,7 +25836,7 @@ async function preparePrivateSocketDirectory(path) {
25867
25836
  function machineControlPath(stateRoot) {
25868
25837
  return privateSocketPath(resolve(stateRoot));
25869
25838
  }
25870
- async function requestMachine(stateRoot, request2, accept, timeoutMs = 6e5) {
25839
+ async function requestMachine(stateRoot, request2, accept, _timeoutMs = 6e5) {
25871
25840
  const path = machineControlPath(stateRoot);
25872
25841
  await preparePrivateSocketDirectory(path);
25873
25842
  return new Promise((done, reject) => {
@@ -25875,7 +25844,6 @@ async function requestMachine(stateRoot, request2, accept, timeoutMs = 6e5) {
25875
25844
  let connecting = false;
25876
25845
  let reconnectNeeded = false;
25877
25846
  let settled = false;
25878
- let lastStatus;
25879
25847
  const watcher = watch(dirname2(path), (_event, filename) => {
25880
25848
  if (filename === basename(path)) {
25881
25849
  reconnectNeeded = true;
@@ -25883,12 +25851,10 @@ async function requestMachine(stateRoot, request2, accept, timeoutMs = 6e5) {
25883
25851
  connect();
25884
25852
  }
25885
25853
  });
25886
- const timer = setTimeout(() => finish(new Error(`helper convergence timed out${lastStatus ? `: ${Object.entries(lastStatus.agents).filter(([, agent]) => agent.state !== "serving" && agent.state !== "stopped").map(([id, agent]) => `${id}: ${agent.state} (${agent.status})`).join("; ")}` : "; no live helper acknowledgment"}`)), timeoutMs);
25887
25854
  function finish(error, status) {
25888
25855
  if (settled)
25889
25856
  return;
25890
25857
  settled = true;
25891
- clearTimeout(timer);
25892
25858
  watcher.close();
25893
25859
  socket?.destroy();
25894
25860
  if (error)
@@ -25924,7 +25890,6 @@ async function requestMachine(stateRoot, request2, accept, timeoutMs = 6e5) {
25924
25890
  throw new Error(status.error);
25925
25891
  if (typeof status.generation !== "string" || !status.generation || !Number.isSafeInteger(status.pid) || status.pid <= 0 || !["starting", "serving", "stopping"].includes(status.processState) || !status.agents || typeof status.agents !== "object" || Array.isArray(status.agents))
25926
25892
  throw new Error("invalid helper acknowledgment");
25927
- lastStatus = status;
25928
25893
  if (accept(status))
25929
25894
  finish(void 0, status);
25930
25895
  } catch (error) {
@@ -25975,7 +25940,6 @@ ExecStart=%h/.local/bin/beeline helper-bootstrap
25975
25940
  ExecReload=/bin/kill -HUP $MAINPID
25976
25941
  Restart=always
25977
25942
  RestartSec=1s
25978
- WatchdogSec=180s
25979
25943
  CPUWeight=1000
25980
25944
  IOWeight=1000
25981
25945
  Nice=-5
@@ -26367,7 +26331,7 @@ async function main() {
26367
26331
  const root = resolve10(stateRoot2, "beeline/agents");
26368
26332
  const agents = await Promise.all((await readdir5(root).catch(() => [])).filter((id) => /^[0-9a-f]{64}$/.test(id)).map(async (id) => ({
26369
26333
  agentId: id,
26370
- enabled: !await stat2(resolve10(root, id, "stopped")).then(() => true, () => false),
26334
+ enabled: !await stat3(resolve10(root, id, "stopped")).then(() => true, () => false),
26371
26335
  ...helper?.agents[id] ?? { state: "not hosted" },
26372
26336
  validRecord: await readFile4(resolve10(root, id, "runtime.json"), "utf8").then((raw) => Boolean(JSON.parse(raw).agent)).catch(() => false)
26373
26337
  })));
@@ -26384,7 +26348,7 @@ async function main() {
26384
26348
  const index = args.indexOf("--manifest-url");
26385
26349
  const url = index >= 0 ? args[index + 1] : resolveManifestUrl();
26386
26350
  if (args.includes("--check")) {
26387
- const response = await fetch(url, { signal: AbortSignal.timeout(3e4) });
26351
+ const response = await fetch(url, { signal: void 0 });
26388
26352
  if (!response.ok)
26389
26353
  throw new Error(`manifest fetch failed: HTTP ${response.status}`);
26390
26354
  const bundle = parseUpdateManifest(await response.text(), hostPlatformKey()).bundle;
@@ -26476,7 +26440,7 @@ async function main() {
26476
26440
  child.once("exit", (code) => done(code ?? 1));
26477
26441
  });
26478
26442
  }
26479
- async function convergeDependencies(layout, deadlineAt) {
26443
+ async function convergeDependencies(layout, _deadlineAt) {
26480
26444
  const entry = await resolveBundleEntrypoint(layout.libDir);
26481
26445
  if (!entry)
26482
26446
  throw new Error("dependency phase has no selected body");
@@ -26485,16 +26449,10 @@ async function convergeDependencies(layout, deadlineAt) {
26485
26449
  env: { ...process.env, BEELINE_LIB_DIR: layout.libDir, BEELINE_INTERNAL_RECOVERY: "1" },
26486
26450
  stdio: "inherit"
26487
26451
  });
26488
- const timer = setTimeout(() => {
26489
- child.kill("SIGKILL");
26490
- reject(new Error("dependency convergence exceeded the command deadline; helper remains supervised"));
26491
- }, Math.max(1, deadlineAt - Date.now()));
26492
26452
  child.once("error", (error) => {
26493
- clearTimeout(timer);
26494
26453
  reject(error);
26495
26454
  });
26496
26455
  child.once("exit", (code) => {
26497
- clearTimeout(timer);
26498
26456
  code === 0 ? done() : reject(new Error(`dependency convergence exited ${code}; helper remains supervised`));
26499
26457
  });
26500
26458
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usebeeline",
3
- "version": "0.1.173",
3
+ "version": "0.1.175",
4
4
  "description": "Connect an AI coding agent to Beeline with one command.",
5
5
  "homepage": "https://usebeeline.app",
6
6
  "bugs": {