usebeeline 0.1.171 → 0.1.174

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 -153
  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";
@@ -24269,7 +24269,7 @@ async function serveOutboxes(dir) {
24269
24269
  }
24270
24270
  return served;
24271
24271
  }
24272
- async function toolViaOutbox(cwd, name, args, timeoutMs = 9e4) {
24272
+ async function toolViaOutbox(cwd, name, args) {
24273
24273
  const dirPath = outboxDir(cwd);
24274
24274
  mkdirSync3(dirPath, { recursive: true });
24275
24275
  writeFileSync3(join6(cwd, ".beeline", ".gitignore"), "*\n");
@@ -24283,7 +24283,6 @@ async function toolViaOutbox(cwd, name, args, timeoutMs = 9e4) {
24283
24283
  if (settled)
24284
24284
  return;
24285
24285
  settled = true;
24286
- clearTimeout(deadline);
24287
24286
  watcher.close();
24288
24287
  resolve11(answer);
24289
24288
  };
@@ -24295,23 +24294,10 @@ async function toolViaOutbox(cwd, name, args, timeoutMs = 9e4) {
24295
24294
  } catch {
24296
24295
  }
24297
24296
  };
24298
- const watcher = watch2(dirPath, (_event, file) => {
24297
+ const watcher = watch4(dirPath, (_event, file) => {
24299
24298
  if (String(file ?? "") === `${id}.result.json`)
24300
24299
  inspect();
24301
24300
  });
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
24301
  inspect();
24316
24302
  });
24317
24303
  }
@@ -24343,7 +24329,6 @@ function toolViaBridge(dir, key, name, args) {
24343
24329
  finish(sent ? unknown : void 0);
24344
24330
  }
24345
24331
  });
24346
- connection.setTimeout(9e4, () => finish(sent ? unknown : void 0));
24347
24332
  });
24348
24333
  }
24349
24334
  async function runBridge(dir, runner2) {
@@ -24367,7 +24352,7 @@ async function runBridge(dir, runner2) {
24367
24352
  wake?.();
24368
24353
  };
24369
24354
  serveTools(dir);
24370
- const localWatch = watch2(dir, { recursive: true }, (_event, name) => {
24355
+ const localWatch = watch4(dir, { recursive: true }, (_event, name) => {
24371
24356
  const path = String(name ?? "");
24372
24357
  if (path === "state.json" || path.startsWith("hooks/") || path.startsWith("inbox/") || path.startsWith("deliveries/"))
24373
24358
  changed();
@@ -24375,8 +24360,6 @@ async function runBridge(dir, runner2) {
24375
24360
  const stop = () => {
24376
24361
  for (const stream of streams.values()) {
24377
24362
  stream.controller.abort();
24378
- if (stream.expiry)
24379
- clearTimeout(stream.expiry);
24380
24363
  }
24381
24364
  localWatch.close();
24382
24365
  for (const watcher of outboxWatches.values())
@@ -24399,14 +24382,6 @@ async function runBridge(dir, runner2) {
24399
24382
  const start = (joined2) => {
24400
24383
  const controller = new AbortController(), entry = { fingerprint: fingerprint(joined2), controller };
24401
24384
  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
24385
  void (async () => {
24411
24386
  let recovered = false;
24412
24387
  while (!controller.signal.aborted) {
@@ -24450,16 +24425,12 @@ async function runBridge(dir, runner2) {
24450
24425
  for (const [key, stream] of streams)
24451
24426
  if (!sessions.some((session2) => session2.key === key)) {
24452
24427
  stream.controller.abort();
24453
- if (stream.expiry)
24454
- clearTimeout(stream.expiry);
24455
24428
  streams.delete(key);
24456
24429
  }
24457
24430
  for (const joined2 of sessions) {
24458
24431
  const old = streams.get(joined2.key);
24459
24432
  if (!old || old.fingerprint !== fingerprint(joined2)) {
24460
24433
  old?.controller.abort();
24461
- if (old?.expiry)
24462
- clearTimeout(old.expiry);
24463
24434
  start(joined2);
24464
24435
  }
24465
24436
  const path = outboxDir(joined2.cwd);
@@ -24468,7 +24439,7 @@ async function runBridge(dir, runner2) {
24468
24439
  const ignore = join6(joined2.cwd, ".beeline", ".gitignore");
24469
24440
  if (!existsSync2(ignore))
24470
24441
  writeFileSync3(ignore, "*\n", { mode: 384 });
24471
- outboxWatches.set(path, watch2(path, (_event, name) => {
24442
+ outboxWatches.set(path, watch4(path, (_event, name) => {
24472
24443
  if (String(name ?? "").endsWith(".request.json"))
24473
24444
  changed();
24474
24445
  }));
@@ -24488,8 +24459,6 @@ async function runBridge(dir, runner2) {
24488
24459
  watcher.close();
24489
24460
  for (const stream of streams.values()) {
24490
24461
  stream.controller.abort();
24491
- if (stream.expiry)
24492
- clearTimeout(stream.expiry);
24493
24462
  }
24494
24463
  }
24495
24464
  log(dir, `bridge ${process.pid} stopped: no joined sessions`);
@@ -24544,6 +24513,9 @@ var init_templates = __esm({
24544
24513
  "use strict";
24545
24514
  OPENCODE_PLUGIN = `// Beeline for opencode: written by \`usebeeline join\`, removed by \`usebeeline session leave\`.
24546
24515
  import { execFile } from "node:child_process"
24516
+ import { watch, mkdirSync } from "node:fs"
24517
+ import { join } from "node:path"
24518
+ import { homedir } from "node:os"
24547
24519
 
24548
24520
  const NODE = "__NODE__"
24549
24521
  const BUNDLE = "__BUNDLE__"
@@ -24572,7 +24544,9 @@ const network = (prompt: (id: string, text: string) => Promise<unknown>) => {
24572
24544
  delivering.delete(id)
24573
24545
  }
24574
24546
  }
24575
- const timer = setInterval(() => idle.forEach((id) => void deliver(id)), 5_000)
24547
+ const inbox=join(process.env.XDG_STATE_HOME||join(process.env.HOME||homedir(),".local/state"),"beeline-sessions","inbox")
24548
+ mkdirSync(inbox,{recursive:true})
24549
+ const watcher=watch(inbox,()=>idle.forEach((id)=>void deliver(id)))
24576
24550
  return {
24577
24551
  subagent: (id: string) => subagents.add(id),
24578
24552
  status: async (id: string, state: string, dir: string) => {
@@ -24584,7 +24558,7 @@ const network = (prompt: (id: string, text: string) => Promise<unknown>) => {
24584
24558
  await deliver(id)
24585
24559
  } else idle.delete(id)
24586
24560
  },
24587
- stop: () => clearInterval(timer),
24561
+ stop: () => watcher.close(),
24588
24562
  end: (id?: string) => {
24589
24563
  for (const [s, dir] of [...dirs]) {
24590
24564
  if (id && s !== id) continue
@@ -24649,6 +24623,9 @@ export default {
24649
24623
  PI_EXTENSION = `// Beeline for pi: written by \`usebeeline join\`, removed by \`usebeeline session leave\`.
24650
24624
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"
24651
24625
  import { execFile } from "node:child_process"
24626
+ import { watch, mkdirSync } from "node:fs"
24627
+ import { join } from "node:path"
24628
+ import { homedir } from "node:os"
24652
24629
 
24653
24630
  const NODE = "__NODE__"
24654
24631
  const BUNDLE = "__BUNDLE__"
@@ -24658,7 +24635,7 @@ export default function (pi: ExtensionAPI) {
24658
24635
  let cwd = process.cwd()
24659
24636
  let busy = false
24660
24637
  let delivering = false
24661
- let timer: ReturnType<typeof setInterval> | undefined
24638
+ let watcher: ReturnType<typeof watch> | undefined
24662
24639
  const hook = (args: string[]) =>
24663
24640
  new Promise<string>((resolve) =>
24664
24641
  execFile(NODE, [BUNDLE, "session", "hook", "pi", ...args, "--session", id], { cwd, timeout: 10_000, windowsHide: true },
@@ -24678,9 +24655,9 @@ export default function (pi: ExtensionAPI) {
24678
24655
  id = ctx.sessionManager.getSessionId()
24679
24656
  cwd = ctx.cwd
24680
24657
  await hook(["status", "--state", "idle"])
24681
- timer ??= setInterval(() => {
24682
- if (!busy) void deliver("poll")
24683
- }, 5_000)
24658
+ const inbox=join(process.env.XDG_STATE_HOME||join(process.env.HOME||homedir(),".local/state"),"beeline-sessions","inbox")
24659
+ mkdirSync(inbox,{recursive:true})
24660
+ watcher??=watch(inbox,()=>{void deliver("poll")})
24684
24661
  })
24685
24662
  pi.on("agent_start", async () => {
24686
24663
  busy = true
@@ -24695,8 +24672,8 @@ export default function (pi: ExtensionAPI) {
24695
24672
  await deliver("poll")
24696
24673
  })
24697
24674
  pi.on("session_shutdown", async () => {
24698
- if (timer) clearInterval(timer)
24699
- timer = undefined
24675
+ watcher?.close()
24676
+ watcher = undefined
24700
24677
  await hook(["session-end"])
24701
24678
  })
24702
24679
  }
@@ -24759,7 +24736,7 @@ def register(ctx):
24759
24736
  import { spawnSync } from "node:child_process";
24760
24737
  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
24738
  import { homedir as homedir7 } from "node:os";
24762
- import { dirname as dirname5, join as join7 } from "node:path";
24739
+ import { dirname as dirname6, join as join7 } from "node:path";
24763
24740
  function home(env) {
24764
24741
  return env.HOME || homedir7();
24765
24742
  }
@@ -24795,7 +24772,7 @@ function writeFile3(path, content, expected) {
24795
24772
  }
24796
24773
  if (before === content)
24797
24774
  return false;
24798
- mkdirSync4(dirname5(path), { recursive: true });
24775
+ mkdirSync4(dirname6(path), { recursive: true });
24799
24776
  const backup = `${path}.bak-${NAME}`;
24800
24777
  if (before !== void 0 && !existsSync3(backup) && !before.includes(" session hook "))
24801
24778
  copyFileSync(path, backup);
@@ -24958,7 +24935,7 @@ function antigravity(context) {
24958
24935
  const sidecars = object2(config, "sidecars");
24959
24936
  if (context.remove) {
24960
24937
  delete sidecars[NAME];
24961
- rmSync4(dirname5(sidecar), { recursive: true, force: true });
24938
+ rmSync4(dirname6(sidecar), { recursive: true, force: true });
24962
24939
  } else {
24963
24940
  if (writeJson(sidecar, {
24964
24941
  command: context.node,
@@ -25185,10 +25162,6 @@ async function trustCodexHook(context, bin, cwd) {
25185
25162
  pending.set(key, { resolve: resolve11, reject: () => reject(new Error("Codex hook trust unavailable")) });
25186
25163
  child.stdin.write(JSON.stringify({ id: key, method, params }) + "\n");
25187
25164
  });
25188
- const timer = setTimeout(() => {
25189
- fail();
25190
- child.kill();
25191
- }, 15e3);
25192
25165
  try {
25193
25166
  await request2("initialize", { clientInfo: { name: "beeline-session-join", version: "1" }, capabilities: { experimentalApi: true } });
25194
25167
  const list = await request2("hooks/list", { cwds: [cwd] });
@@ -25201,9 +25174,6 @@ async function trustCodexHook(context, bin, cwd) {
25201
25174
  return result.status === "ok";
25202
25175
  } catch {
25203
25176
  return false;
25204
- } finally {
25205
- clearTimeout(timer);
25206
- child.kill();
25207
25177
  }
25208
25178
  }
25209
25179
  var init_codex_trust = __esm({
@@ -25292,6 +25262,7 @@ var init_hook = __esm({
25292
25262
  });
25293
25263
 
25294
25264
  // apps/body/dist/session-join/pull-apps.js
25265
+ import { watch as watch5 } from "node:fs/promises";
25295
25266
  import { execFile as execFile4 } from "node:child_process";
25296
25267
  import { createInterface as createInterface2 } from "node:readline";
25297
25268
  function zcodeKey(dir, cwd) {
@@ -25356,10 +25327,12 @@ async function antigravityOnce(dir, live, send = agentapi) {
25356
25327
  return handed;
25357
25328
  }
25358
25329
  async function runAntigravitySidecar(dir) {
25359
- for (; ; ) {
25360
- await antigravityOnce(dir, hookSessions(dir)).catch(() => 0);
25361
- await new Promise((resolve11) => setTimeout(resolve11, 3e3));
25330
+ await antigravityOnce(dir, hookSessions(dir)).catch(() => 0);
25331
+ for await (const event of watch5(dir, { recursive: true })) {
25332
+ if (event.filename?.startsWith("inbox/"))
25333
+ await antigravityOnce(dir, hookSessions(dir)).catch(() => 0);
25362
25334
  }
25335
+ throw new Error("session inbox watcher closed");
25363
25336
  }
25364
25337
  var agentapi;
25365
25338
  var init_pull_apps = __esm({
@@ -25379,7 +25352,7 @@ __export(command_exports, {
25379
25352
  });
25380
25353
  import { spawn as spawn7, spawnSync as spawnSync2 } from "node:child_process";
25381
25354
  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";
25355
+ import { delimiter, dirname as dirname7, join as join10, resolve as resolve9 } from "node:path";
25383
25356
  import { createHash as createHash7, randomUUID as randomUUID2 } from "node:crypto";
25384
25357
  function writePending(file, pending) {
25385
25358
  const temporary = file + "." + randomUUID2() + ".tmp";
@@ -25393,7 +25366,7 @@ function writePending(file, pending) {
25393
25366
  }
25394
25367
  renameSync4(temporary, file);
25395
25368
  if (process.platform !== "win32") {
25396
- const directory = openSync4(dirname6(file), "r");
25369
+ const directory = openSync4(dirname7(file), "r");
25397
25370
  try {
25398
25371
  fsyncSync(directory);
25399
25372
  } finally {
@@ -25607,7 +25580,6 @@ async function finishJoinOwned(file, env) {
25607
25580
  const transcript = pending.sessionId ? claudeTranscript(pending.sessionId, env) : void 0;
25608
25581
  if (transcript && permissionMode(transcript) === "bypassPermissions") {
25609
25582
  await acceptClaudeInbound(env);
25610
- await new Promise((resolve11) => setTimeout(resolve11, 1e3));
25611
25583
  }
25612
25584
  }
25613
25585
  await updateState(dir, (state) => {
@@ -25766,7 +25738,7 @@ async function session(args, env) {
25766
25738
  method: "POST",
25767
25739
  headers: { "content-type": "application/json" },
25768
25740
  body: JSON.stringify({ client_id: joined2.clientId, token: joined2.refreshToken }),
25769
- signal: AbortSignal.timeout(15e3)
25741
+ signal: void 0
25770
25742
  }).catch(() => void 0);
25771
25743
  const left = await updateState(dir, (state) => {
25772
25744
  state.sessions = state.sessions.filter((s) => s.key !== joined2.key);
@@ -25780,16 +25752,14 @@ async function session(args, env) {
25780
25752
  }
25781
25753
  throw new Error("Usage: usebeeline join | usebeeline session reply|read|tool|status|leave");
25782
25754
  }
25783
- function readStdin(limitMs) {
25755
+ function readStdin(_limitMs) {
25784
25756
  return new Promise((resolve11) => {
25785
25757
  let text = "";
25786
- const timer = setTimeout(() => resolve11(text), limitMs);
25787
25758
  process.stdin.setEncoding("utf8");
25788
25759
  process.stdin.on("data", (chunk) => {
25789
25760
  text += chunk;
25790
25761
  });
25791
25762
  process.stdin.on("end", () => {
25792
- clearTimeout(timer);
25793
25763
  resolve11(text);
25794
25764
  });
25795
25765
  });
@@ -25835,7 +25805,7 @@ var init_command = __esm({
25835
25805
 
25836
25806
  // apps/body/dist/recovery-cli.js
25837
25807
  import { spawn as spawn8 } from "node:child_process";
25838
- import { readFile as readFile4, readdir as readdir5, stat as stat2, unlink } from "node:fs/promises";
25808
+ import { readFile as readFile4, readdir as readdir5, stat as stat3, unlink } from "node:fs/promises";
25839
25809
  import { resolve as resolve10 } from "node:path";
25840
25810
 
25841
25811
  // apps/body/dist/recovery.js
@@ -25867,7 +25837,7 @@ async function preparePrivateSocketDirectory(path) {
25867
25837
  function machineControlPath(stateRoot) {
25868
25838
  return privateSocketPath(resolve(stateRoot));
25869
25839
  }
25870
- async function requestMachine(stateRoot, request2, accept, timeoutMs = 6e5) {
25840
+ async function requestMachine(stateRoot, request2, accept, _timeoutMs = 6e5) {
25871
25841
  const path = machineControlPath(stateRoot);
25872
25842
  await preparePrivateSocketDirectory(path);
25873
25843
  return new Promise((done, reject) => {
@@ -25875,7 +25845,6 @@ async function requestMachine(stateRoot, request2, accept, timeoutMs = 6e5) {
25875
25845
  let connecting = false;
25876
25846
  let reconnectNeeded = false;
25877
25847
  let settled = false;
25878
- let lastStatus;
25879
25848
  const watcher = watch(dirname2(path), (_event, filename) => {
25880
25849
  if (filename === basename(path)) {
25881
25850
  reconnectNeeded = true;
@@ -25883,12 +25852,10 @@ async function requestMachine(stateRoot, request2, accept, timeoutMs = 6e5) {
25883
25852
  connect();
25884
25853
  }
25885
25854
  });
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
25855
  function finish(error, status) {
25888
25856
  if (settled)
25889
25857
  return;
25890
25858
  settled = true;
25891
- clearTimeout(timer);
25892
25859
  watcher.close();
25893
25860
  socket?.destroy();
25894
25861
  if (error)
@@ -25924,7 +25891,6 @@ async function requestMachine(stateRoot, request2, accept, timeoutMs = 6e5) {
25924
25891
  throw new Error(status.error);
25925
25892
  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
25893
  throw new Error("invalid helper acknowledgment");
25927
- lastStatus = status;
25928
25894
  if (accept(status))
25929
25895
  finish(void 0, status);
25930
25896
  } catch (error) {
@@ -25975,7 +25941,6 @@ ExecStart=%h/.local/bin/beeline helper-bootstrap
25975
25941
  ExecReload=/bin/kill -HUP $MAINPID
25976
25942
  Restart=always
25977
25943
  RestartSec=1s
25978
- WatchdogSec=180s
25979
25944
  CPUWeight=1000
25980
25945
  IOWeight=1000
25981
25946
  Nice=-5
@@ -26367,7 +26332,7 @@ async function main() {
26367
26332
  const root = resolve10(stateRoot2, "beeline/agents");
26368
26333
  const agents = await Promise.all((await readdir5(root).catch(() => [])).filter((id) => /^[0-9a-f]{64}$/.test(id)).map(async (id) => ({
26369
26334
  agentId: id,
26370
- enabled: !await stat2(resolve10(root, id, "stopped")).then(() => true, () => false),
26335
+ enabled: !await stat3(resolve10(root, id, "stopped")).then(() => true, () => false),
26371
26336
  ...helper?.agents[id] ?? { state: "not hosted" },
26372
26337
  validRecord: await readFile4(resolve10(root, id, "runtime.json"), "utf8").then((raw) => Boolean(JSON.parse(raw).agent)).catch(() => false)
26373
26338
  })));
@@ -26384,7 +26349,7 @@ async function main() {
26384
26349
  const index = args.indexOf("--manifest-url");
26385
26350
  const url = index >= 0 ? args[index + 1] : resolveManifestUrl();
26386
26351
  if (args.includes("--check")) {
26387
- const response = await fetch(url, { signal: AbortSignal.timeout(3e4) });
26352
+ const response = await fetch(url, { signal: void 0 });
26388
26353
  if (!response.ok)
26389
26354
  throw new Error(`manifest fetch failed: HTTP ${response.status}`);
26390
26355
  const bundle = parseUpdateManifest(await response.text(), hostPlatformKey()).bundle;
@@ -26476,7 +26441,7 @@ async function main() {
26476
26441
  child.once("exit", (code) => done(code ?? 1));
26477
26442
  });
26478
26443
  }
26479
- async function convergeDependencies(layout, deadlineAt) {
26444
+ async function convergeDependencies(layout, _deadlineAt) {
26480
26445
  const entry = await resolveBundleEntrypoint(layout.libDir);
26481
26446
  if (!entry)
26482
26447
  throw new Error("dependency phase has no selected body");
@@ -26485,16 +26450,10 @@ async function convergeDependencies(layout, deadlineAt) {
26485
26450
  env: { ...process.env, BEELINE_LIB_DIR: layout.libDir, BEELINE_INTERNAL_RECOVERY: "1" },
26486
26451
  stdio: "inherit"
26487
26452
  });
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
26453
  child.once("error", (error) => {
26493
- clearTimeout(timer);
26494
26454
  reject(error);
26495
26455
  });
26496
26456
  child.once("exit", (code) => {
26497
- clearTimeout(timer);
26498
26457
  code === 0 ? done() : reject(new Error(`dependency convergence exited ${code}; helper remains supervised`));
26499
26458
  });
26500
26459
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usebeeline",
3
- "version": "0.1.171",
3
+ "version": "0.1.174",
4
4
  "description": "Connect an AI coding agent to Beeline with one command.",
5
5
  "homepage": "https://usebeeline.app",
6
6
  "bugs": {