usebeeline 0.1.181 → 0.1.184-rc.2

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 +228 -130
  2. package/package.json +1 -1
@@ -176,7 +176,12 @@ var init_lifecycle_test_guard = __esm({
176
176
  // apps/body/dist/self-update-manifest.js
177
177
  function resolveManifestUrl(env = process.env) {
178
178
  const override = env.BEELINE_UPDATE_MANIFEST_URL?.trim();
179
- return override && override.length > 0 ? override : DEFAULT_UPDATE_MANIFEST_URL;
179
+ if (override)
180
+ return override;
181
+ const channel = env.BEELINE_RELEASE_CHANNEL?.trim() || "latest";
182
+ if (!["latest", "next"].includes(channel))
183
+ throw new Error(`invalid helper release channel: ${channel}`);
184
+ return channel === "next" ? "https://usebeeline.app/dl/next/manifest.json" : DEFAULT_UPDATE_MANIFEST_URL;
180
185
  }
181
186
  function parseUpdateManifest(raw, platform) {
182
187
  let parsed;
@@ -1231,7 +1236,6 @@ var init_managed_update = __esm({
1231
1236
  #interruptAt;
1232
1237
  #deadlineAt;
1233
1238
  #handingOff;
1234
- #notice;
1235
1239
  #completed = false;
1236
1240
  #draining = false;
1237
1241
  constructor(options) {
@@ -1243,10 +1247,7 @@ var init_managed_update = __esm({
1243
1247
  get pending() {
1244
1248
  return this.#preparing ?? this.#handingOff;
1245
1249
  }
1246
- notify(releaseKey, minimum) {
1247
- if (releaseKey && releaseKey === this.#notice)
1248
- return;
1249
- this.#notice = releaseKey;
1250
+ notify(_releaseKey, minimum) {
1250
1251
  if (minimum && (!this.#minimum || !versionAtLeast(this.#minimum, minimum))) {
1251
1252
  this.#minimum = minimum;
1252
1253
  this.#handoffAt = this.now();
@@ -3445,9 +3446,9 @@ var require_dispatcher_base = __commonJS({
3445
3446
  }
3446
3447
  close(callback) {
3447
3448
  if (callback === void 0) {
3448
- return new Promise((resolve12, reject) => {
3449
+ return new Promise((resolve13, reject) => {
3449
3450
  this.close((err, data) => {
3450
- return err ? reject(err) : resolve12(data);
3451
+ return err ? reject(err) : resolve13(data);
3451
3452
  });
3452
3453
  });
3453
3454
  }
@@ -3485,12 +3486,12 @@ var require_dispatcher_base = __commonJS({
3485
3486
  err = null;
3486
3487
  }
3487
3488
  if (callback === void 0) {
3488
- return new Promise((resolve12, reject) => {
3489
+ return new Promise((resolve13, reject) => {
3489
3490
  this.destroy(err, (err2, data) => {
3490
3491
  return err2 ? (
3491
3492
  /* istanbul ignore next: should never error */
3492
3493
  reject(err2)
3493
- ) : resolve12(data);
3494
+ ) : resolve13(data);
3494
3495
  });
3495
3496
  });
3496
3497
  }
@@ -5757,8 +5758,8 @@ var require_util2 = __commonJS({
5757
5758
  function createDeferredPromise() {
5758
5759
  let res;
5759
5760
  let rej;
5760
- const promise = new Promise((resolve12, reject) => {
5761
- res = resolve12;
5761
+ const promise = new Promise((resolve13, reject) => {
5762
+ res = resolve13;
5762
5763
  rej = reject;
5763
5764
  });
5764
5765
  return { promise, resolve: res, reject: rej };
@@ -8004,12 +8005,12 @@ upgrade: ${upgrade}\r
8004
8005
  cb();
8005
8006
  }
8006
8007
  }
8007
- const waitForDrain = () => new Promise((resolve12, reject) => {
8008
+ const waitForDrain = () => new Promise((resolve13, reject) => {
8008
8009
  assert(callback === null);
8009
8010
  if (socket[kError]) {
8010
8011
  reject(socket[kError]);
8011
8012
  } else {
8012
- callback = resolve12;
8013
+ callback = resolve13;
8013
8014
  }
8014
8015
  });
8015
8016
  socket.on("close", onDrain).on("drain", onDrain);
@@ -8646,12 +8647,12 @@ var require_client_h2 = __commonJS({
8646
8647
  cb();
8647
8648
  }
8648
8649
  }
8649
- const waitForDrain = () => new Promise((resolve12, reject) => {
8650
+ const waitForDrain = () => new Promise((resolve13, reject) => {
8650
8651
  assert(callback === null);
8651
8652
  if (socket[kError]) {
8652
8653
  reject(socket[kError]);
8653
8654
  } else {
8654
- callback = resolve12;
8655
+ callback = resolve13;
8655
8656
  }
8656
8657
  });
8657
8658
  h2stream.on("close", onDrain).on("drain", onDrain);
@@ -9129,16 +9130,16 @@ var require_client = __commonJS({
9129
9130
  return this[kNeedDrain] < 2;
9130
9131
  }
9131
9132
  async [kClose]() {
9132
- return new Promise((resolve12) => {
9133
+ return new Promise((resolve13) => {
9133
9134
  if (this[kSize]) {
9134
- this[kClosedResolve] = resolve12;
9135
+ this[kClosedResolve] = resolve13;
9135
9136
  } else {
9136
- resolve12(null);
9137
+ resolve13(null);
9137
9138
  }
9138
9139
  });
9139
9140
  }
9140
9141
  async [kDestroy](err) {
9141
- return new Promise((resolve12) => {
9142
+ return new Promise((resolve13) => {
9142
9143
  const requests = this[kQueue].splice(this[kPendingIdx]);
9143
9144
  for (let i = 0; i < requests.length; i++) {
9144
9145
  const request2 = requests[i];
@@ -9149,7 +9150,7 @@ var require_client = __commonJS({
9149
9150
  this[kClosedResolve]();
9150
9151
  this[kClosedResolve] = null;
9151
9152
  }
9152
- resolve12(null);
9153
+ resolve13(null);
9153
9154
  };
9154
9155
  if (this[kHTTPContext]) {
9155
9156
  this[kHTTPContext].destroy(err, callback);
@@ -9200,7 +9201,7 @@ var require_client = __commonJS({
9200
9201
  });
9201
9202
  }
9202
9203
  try {
9203
- const socket = await new Promise((resolve12, reject) => {
9204
+ const socket = await new Promise((resolve13, reject) => {
9204
9205
  client[kConnector]({
9205
9206
  host,
9206
9207
  hostname,
@@ -9212,7 +9213,7 @@ var require_client = __commonJS({
9212
9213
  if (err) {
9213
9214
  reject(err);
9214
9215
  } else {
9215
- resolve12(socket2);
9216
+ resolve13(socket2);
9216
9217
  }
9217
9218
  });
9218
9219
  });
@@ -9548,8 +9549,8 @@ var require_pool_base = __commonJS({
9548
9549
  if (this[kQueue].isEmpty()) {
9549
9550
  await Promise.all(this[kClients].map((c) => c.close()));
9550
9551
  } else {
9551
- await new Promise((resolve12) => {
9552
- this[kClosedResolve] = resolve12;
9552
+ await new Promise((resolve13) => {
9553
+ this[kClosedResolve] = resolve13;
9553
9554
  });
9554
9555
  }
9555
9556
  }
@@ -10792,7 +10793,7 @@ var require_readable = __commonJS({
10792
10793
  if (this._readableState.closeEmitted) {
10793
10794
  return null;
10794
10795
  }
10795
- return await new Promise((resolve12, reject) => {
10796
+ return await new Promise((resolve13, reject) => {
10796
10797
  if (this[kContentLength] > limit) {
10797
10798
  this.destroy(new AbortError());
10798
10799
  }
@@ -10805,7 +10806,7 @@ var require_readable = __commonJS({
10805
10806
  if (signal?.aborted) {
10806
10807
  reject(signal.reason ?? new AbortError());
10807
10808
  } else {
10808
- resolve12(null);
10809
+ resolve13(null);
10809
10810
  }
10810
10811
  }).on("error", noop).on("data", function(chunk) {
10811
10812
  limit -= chunk.length;
@@ -10824,7 +10825,7 @@ var require_readable = __commonJS({
10824
10825
  }
10825
10826
  async function consume(stream, type) {
10826
10827
  assert(!stream[kConsume]);
10827
- return new Promise((resolve12, reject) => {
10828
+ return new Promise((resolve13, reject) => {
10828
10829
  if (isUnusable(stream)) {
10829
10830
  const rState = stream._readableState;
10830
10831
  if (rState.destroyed && rState.closeEmitted === false) {
@@ -10841,7 +10842,7 @@ var require_readable = __commonJS({
10841
10842
  stream[kConsume] = {
10842
10843
  type,
10843
10844
  stream,
10844
- resolve: resolve12,
10845
+ resolve: resolve13,
10845
10846
  reject,
10846
10847
  length: 0,
10847
10848
  body: []
@@ -10911,18 +10912,18 @@ var require_readable = __commonJS({
10911
10912
  return buffer;
10912
10913
  }
10913
10914
  function consumeEnd(consume2) {
10914
- const { type, body, resolve: resolve12, stream, length } = consume2;
10915
+ const { type, body, resolve: resolve13, stream, length } = consume2;
10915
10916
  try {
10916
10917
  if (type === "text") {
10917
- resolve12(chunksDecode(body, length));
10918
+ resolve13(chunksDecode(body, length));
10918
10919
  } else if (type === "json") {
10919
- resolve12(JSON.parse(chunksDecode(body, length)));
10920
+ resolve13(JSON.parse(chunksDecode(body, length)));
10920
10921
  } else if (type === "arrayBuffer") {
10921
- resolve12(chunksConcat(body, length).buffer);
10922
+ resolve13(chunksConcat(body, length).buffer);
10922
10923
  } else if (type === "blob") {
10923
- resolve12(new Blob(body, { type: stream[kContentType] }));
10924
+ resolve13(new Blob(body, { type: stream[kContentType] }));
10924
10925
  } else if (type === "bytes") {
10925
- resolve12(chunksConcat(body, length));
10926
+ resolve13(chunksConcat(body, length));
10926
10927
  }
10927
10928
  consumeFinish(consume2);
10928
10929
  } catch (err) {
@@ -11179,9 +11180,9 @@ var require_api_request = __commonJS({
11179
11180
  };
11180
11181
  function request2(opts, callback) {
11181
11182
  if (callback === void 0) {
11182
- return new Promise((resolve12, reject) => {
11183
+ return new Promise((resolve13, reject) => {
11183
11184
  request2.call(this, opts, (err, data) => {
11184
- return err ? reject(err) : resolve12(data);
11185
+ return err ? reject(err) : resolve13(data);
11185
11186
  });
11186
11187
  });
11187
11188
  }
@@ -11404,9 +11405,9 @@ var require_api_stream = __commonJS({
11404
11405
  };
11405
11406
  function stream(opts, factory, callback) {
11406
11407
  if (callback === void 0) {
11407
- return new Promise((resolve12, reject) => {
11408
+ return new Promise((resolve13, reject) => {
11408
11409
  stream.call(this, opts, factory, (err, data) => {
11409
- return err ? reject(err) : resolve12(data);
11410
+ return err ? reject(err) : resolve13(data);
11410
11411
  });
11411
11412
  });
11412
11413
  }
@@ -11691,9 +11692,9 @@ var require_api_upgrade = __commonJS({
11691
11692
  };
11692
11693
  function upgrade(opts, callback) {
11693
11694
  if (callback === void 0) {
11694
- return new Promise((resolve12, reject) => {
11695
+ return new Promise((resolve13, reject) => {
11695
11696
  upgrade.call(this, opts, (err, data) => {
11696
- return err ? reject(err) : resolve12(data);
11697
+ return err ? reject(err) : resolve13(data);
11697
11698
  });
11698
11699
  });
11699
11700
  }
@@ -11785,9 +11786,9 @@ var require_api_connect = __commonJS({
11785
11786
  };
11786
11787
  function connect(opts, callback) {
11787
11788
  if (callback === void 0) {
11788
- return new Promise((resolve12, reject) => {
11789
+ return new Promise((resolve13, reject) => {
11789
11790
  connect.call(this, opts, (err, data) => {
11790
- return err ? reject(err) : resolve12(data);
11791
+ return err ? reject(err) : resolve13(data);
11791
11792
  });
11792
11793
  });
11793
11794
  }
@@ -15649,7 +15650,7 @@ var require_fetch = __commonJS({
15649
15650
  function dispatch({ body }) {
15650
15651
  const url = requestCurrentURL(request2);
15651
15652
  const agent = fetchParams.controller.dispatcher;
15652
- return new Promise((resolve12, reject) => agent.dispatch(
15653
+ return new Promise((resolve13, reject) => agent.dispatch(
15653
15654
  {
15654
15655
  path: url.pathname + url.search,
15655
15656
  origin: url.origin,
@@ -15725,7 +15726,7 @@ var require_fetch = __commonJS({
15725
15726
  }
15726
15727
  }
15727
15728
  const onError = this.onError.bind(this);
15728
- resolve12({
15729
+ resolve13({
15729
15730
  status,
15730
15731
  statusText,
15731
15732
  headersList,
@@ -15771,7 +15772,7 @@ var require_fetch = __commonJS({
15771
15772
  for (let i = 0; i < rawHeaders.length; i += 2) {
15772
15773
  headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString("latin1"), true);
15773
15774
  }
15774
- resolve12({
15775
+ resolve13({
15775
15776
  status,
15776
15777
  statusText: STATUS_CODES[status],
15777
15778
  headersList,
@@ -19501,8 +19502,8 @@ var require_util8 = __commonJS({
19501
19502
  return true;
19502
19503
  }
19503
19504
  function delay(ms) {
19504
- return new Promise((resolve12) => {
19505
- setTimeout(resolve12, ms).unref();
19505
+ return new Promise((resolve13) => {
19506
+ setTimeout(resolve13, ms).unref();
19506
19507
  });
19507
19508
  }
19508
19509
  module.exports = {
@@ -20187,7 +20188,7 @@ import { watch as watch2 } from "node:fs";
20187
20188
  import { stat as stat2 } from "node:fs/promises";
20188
20189
  import { dirname as dirname6 } from "node:path";
20189
20190
  function waitForPathRemoval(path) {
20190
- return new Promise((resolve12, reject) => {
20191
+ return new Promise((resolve13, reject) => {
20191
20192
  let reading = false, dirty = false, ended = false;
20192
20193
  const finish = (error) => {
20193
20194
  if (ended)
@@ -20197,7 +20198,7 @@ function waitForPathRemoval(path) {
20197
20198
  if (error)
20198
20199
  reject(error);
20199
20200
  else
20200
- resolve12();
20201
+ resolve13();
20201
20202
  };
20202
20203
  const inspect = async () => {
20203
20204
  dirty = true;
@@ -20674,6 +20675,35 @@ var init_beeline_api = __esm({
20674
20675
  }
20675
20676
  });
20676
20677
 
20678
+ // apps/body/dist/process-exit.js
20679
+ import { spawn as spawn5 } from "node:child_process";
20680
+ function waitForProcessExit(pid, signal) {
20681
+ return new Promise((resolve13, reject) => {
20682
+ const child = spawn5("/usr/bin/python3", ["-c", WAIT, String(pid)], { stdio: "ignore", signal });
20683
+ child.once("error", reject);
20684
+ child.once("close", (code) => code === 0 ? resolve13() : reject(new Error(`process exit observer failed (${code})`)));
20685
+ });
20686
+ }
20687
+ var WAIT;
20688
+ var init_process_exit = __esm({
20689
+ "apps/body/dist/process-exit.js"() {
20690
+ "use strict";
20691
+ WAIT = `import os,sys,select
20692
+ pid=int(sys.argv[1])
20693
+ try:
20694
+ if hasattr(os,'pidfd_open'):
20695
+ fd=os.pidfd_open(pid)
20696
+ try: select.select([fd],[],[])
20697
+ finally: os.close(fd)
20698
+ else:
20699
+ queue=select.kqueue()
20700
+ try: queue.control([select.kevent(pid,filter=select.KQ_FILTER_PROC,flags=select.KQ_EV_ADD|select.KQ_EV_ONESHOT,fflags=select.KQ_NOTE_EXIT)],1)
20701
+ finally: queue.close()
20702
+ except ProcessLookupError: pass
20703
+ `;
20704
+ }
20705
+ });
20706
+
20677
20707
  // packages/api-contract/dist/phone-types-room-live-delta.js
20678
20708
  var init_phone_types_room_live_delta = __esm({
20679
20709
  "packages/api-contract/dist/phone-types-room-live-delta.js"() {
@@ -21584,22 +21614,6 @@ var init_system_message_catalog_daemon_service = __esm({
21584
21614
  parts: [", "],
21585
21615
  variables: []
21586
21616
  },
21587
- "grant-policy-upgrade.system": {
21588
- parts: ["@system"],
21589
- variables: []
21590
- },
21591
- "grant-policy-upgrade.revoked-a-legacy-grant-for": {
21592
- parts: ["revoked a legacy grant for"],
21593
- variables: []
21594
- },
21595
- "grant-policy-upgrade.grant-target": {
21596
- parts: ["", " ", ""],
21597
- variables: ["grant_kind", "grant_target"]
21598
- },
21599
- "grant-policy-upgrade.permission-policy-upgraded": {
21600
- parts: ["permission policy upgraded"],
21601
- variables: []
21602
- },
21603
21617
  "membership-join.joined": {
21604
21618
  parts: ["joined"],
21605
21619
  variables: []
@@ -23706,8 +23720,8 @@ var init_external_agent_rules = __esm({
23706
23720
  },
23707
23721
  {
23708
23722
  id: "commander",
23709
- mcp: "When you finish, are blocked, fail, or need a decision on a chat request, tag the agent or person who asked you (your commander) with the result. A report returns to whoever ordered the work, one step up. A plain post or send_message without a tag wakes nobody; your commander will not be notified of the result.",
23710
- session: "When you finish, are blocked, fail, or need a decision on a chat request, tag the agent or person who asked you (your commander) with the result. A report returns to whoever ordered the work, one step up. A post without a tag wakes nobody."
23723
+ mcp: "When you finish, are blocked, fail, or need a decision on a chat request, tag the agent or person who asked you with the result. Corner reports go one step up to the opener at the opening surface; later chat requests do not change the commander. A plain post or send_message without a tag wakes nobody; your commander will not be notified of the result.",
23724
+ session: "When you finish, are blocked, fail, or need a decision on a chat request, tag the agent or person who asked you with the result. Corner reports go one step up to the opener at the opening surface; later chat requests do not change the commander. A post without a tag wakes nobody."
23711
23725
  },
23712
23726
  {
23713
23727
  id: "tagging",
@@ -23915,12 +23929,12 @@ function scanCodex(proc = "/proc") {
23915
23929
  return found;
23916
23930
  }
23917
23931
  function codexQueue(threadId, text, bin = "codex", timeoutMs = 3e4) {
23918
- return new Promise((resolve12, reject) => {
23932
+ return new Promise((resolve13, reject) => {
23919
23933
  execFile3(bin, ["queue", "--thread", threadId, "--message", text], { timeout: timeoutMs }, (error, _stdout, stderr) => {
23920
23934
  if (error)
23921
23935
  reject(new Error(String(stderr).trim() || error.message));
23922
23936
  else
23923
- resolve12();
23937
+ resolve13();
23924
23938
  });
23925
23939
  });
23926
23940
  }
@@ -23967,7 +23981,7 @@ function chosenName(session2) {
23967
23981
  return ["user", "peer", "hook"].includes(session2.nameSource ?? "") ? session2.name : void 0;
23968
23982
  }
23969
23983
  function postToClaude(socket, text, _timeoutMs = 5e3) {
23970
- return new Promise((resolve12, reject) => {
23984
+ return new Promise((resolve13, reject) => {
23971
23985
  const connection = createConnection3(socket.path);
23972
23986
  connection.once("error", (error) => {
23973
23987
  reject(error);
@@ -23976,7 +23990,7 @@ function postToClaude(socket, text, _timeoutMs = 5e3) {
23976
23990
  if (socket.token)
23977
23991
  connection.write(JSON.stringify({ type: "auth", token: socket.token }) + "\n");
23978
23992
  connection.end(JSON.stringify({ type: "user", message: { role: "user", content: text } }) + "\n", () => {
23979
- resolve12();
23993
+ resolve13();
23980
23994
  });
23981
23995
  });
23982
23996
  });
@@ -24066,17 +24080,19 @@ function hasClaudeMcp(dir, claudePid) {
24066
24080
  }
24067
24081
  async function flushClaudeMcp(dir, session2, token, post = postToClaude) {
24068
24082
  if (!session2.messagingSocketPath)
24069
- return;
24083
+ return false;
24070
24084
  const joined2 = readState(dir).sessions.find((s) => s.agent === "claude-code" && (s.pid === session2.pid || s.sessionId === session2.sessionId));
24071
24085
  if (!joined2)
24072
- return;
24086
+ return false;
24073
24087
  const text = takeInbox(dir, joined2.key);
24074
24088
  if (!text)
24075
- return;
24089
+ return false;
24076
24090
  try {
24077
24091
  await post({ path: session2.messagingSocketPath, token }, text);
24092
+ return true;
24078
24093
  } catch {
24079
24094
  queueInbox(dir, joined2.key, text);
24095
+ return false;
24080
24096
  }
24081
24097
  }
24082
24098
  function joinedClaude(dir, env, chain) {
@@ -24086,32 +24102,38 @@ function joinedClaude(dir, env, chain) {
24086
24102
  return void 0;
24087
24103
  return readState(dir).sessions.find((s) => s.agent === "claude-code" && (s.pid === session2.pid || s.sessionId === session2.sessionId));
24088
24104
  }
24089
- async function runClaudeMcp(dir, env, rulesFor) {
24105
+ async function runClaudeMcp(dir, env, rulesFor, post = postToClaude) {
24090
24106
  const chain = ancestors(process.pid);
24091
24107
  let registration;
24092
- let flushing = false;
24108
+ let flushing = false, dirty = false;
24093
24109
  const flush2 = async () => {
24110
+ dirty = true;
24094
24111
  if (flushing || !env.CLAUDE_CODE_MESSAGING_TOKEN)
24095
24112
  return;
24096
24113
  flushing = true;
24097
24114
  try {
24098
- const live = scanClaude(env);
24099
- const session2 = chain.map((pid) => live.find((s) => s.pid === pid)).find(Boolean);
24100
- if (!session2)
24101
- return;
24102
- if (!registration) {
24103
- const folder = join6(dir, "claude-mcp");
24104
- mkdirSync2(folder, { recursive: true, mode: 448 });
24105
- registration = join6(folder, `${process.pid}.json`);
24106
- writeFileSync2(registration, JSON.stringify({ pid: process.pid, claudePid: session2.pid }), { mode: 384 });
24115
+ while (dirty) {
24116
+ dirty = false;
24117
+ const live = scanClaude(env);
24118
+ const session2 = chain.map((pid) => live.find((s) => s.pid === pid)).find(Boolean);
24119
+ if (!session2)
24120
+ return;
24121
+ if (!registration) {
24122
+ const folder = join6(dir, "claude-mcp");
24123
+ mkdirSync2(folder, { recursive: true, mode: 448 });
24124
+ registration = join6(folder, `${process.pid}.json`);
24125
+ writeFileSync2(registration, JSON.stringify({ pid: process.pid, claudePid: session2.pid }), { mode: 384 });
24126
+ }
24127
+ if (!await flushClaudeMcp(dir, session2, env.CLAUDE_CODE_MESSAGING_TOKEN, post))
24128
+ break;
24107
24129
  }
24108
- await flushClaudeMcp(dir, session2, env.CLAUDE_CODE_MESSAGING_TOKEN);
24109
24130
  } finally {
24110
24131
  flushing = false;
24111
24132
  }
24112
24133
  };
24113
24134
  const watcher = watch3(dir, { recursive: true }, (_event, name) => {
24114
- if (String(name ?? "").startsWith("inbox/"))
24135
+ const path = String(name ?? "");
24136
+ if (path === "state.json" || path.startsWith("inbox/"))
24115
24137
  void flush2().catch(() => void 0);
24116
24138
  });
24117
24139
  try {
@@ -24200,10 +24222,10 @@ var init_sessions = __esm({
24200
24222
  });
24201
24223
 
24202
24224
  // apps/body/dist/session-join/bridge.js
24203
- import { spawn as spawn5 } from "node:child_process";
24225
+ import { execFileSync, spawn as spawn6 } from "node:child_process";
24204
24226
  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";
24205
24227
  import { createConnection as createConnection4, createServer as createServer3 } from "node:net";
24206
- import { join as join7 } from "node:path";
24228
+ import { basename as basename4, join as join7, resolve as resolve10 } from "node:path";
24207
24229
  import { createHash as createHash6 } from "node:crypto";
24208
24230
  function command(runner2, joined2, args) {
24209
24231
  const q = (v) => /^[A-Za-z0-9_./:@=-]+$/.test(v) ? v : `"${v.replace(/(["\\$`])/g, "\\$1")}"`;
@@ -24402,14 +24424,14 @@ async function toolViaOutbox(cwd, name, args) {
24402
24424
  const request2 = join7(dirPath, `${id}.request.json`), result = join7(dirPath, `${id}.result.json`);
24403
24425
  writeFileSync3(`${request2}.tmp`, JSON.stringify({ name, args }));
24404
24426
  renameSync2(`${request2}.tmp`, request2);
24405
- return new Promise((resolve12) => {
24427
+ return new Promise((resolve13) => {
24406
24428
  let settled = false;
24407
24429
  const finish = (answer) => {
24408
24430
  if (settled)
24409
24431
  return;
24410
24432
  settled = true;
24411
24433
  watcher.close();
24412
- resolve12(answer);
24434
+ resolve13(answer);
24413
24435
  };
24414
24436
  const inspect = () => {
24415
24437
  try {
@@ -24427,7 +24449,7 @@ async function toolViaOutbox(cwd, name, args) {
24427
24449
  });
24428
24450
  }
24429
24451
  function toolViaBridge(dir, key, name, args) {
24430
- return new Promise((resolve12) => {
24452
+ return new Promise((resolve13) => {
24431
24453
  const connection = createConnection4(join7(dir, "bridge.sock"));
24432
24454
  let text = "", sent = false, settled = false;
24433
24455
  const unknown = { ok: false, error: "Beeline tool result is awaiting confirmation" };
@@ -24435,7 +24457,7 @@ function toolViaBridge(dir, key, name, args) {
24435
24457
  if (settled)
24436
24458
  return;
24437
24459
  settled = true;
24438
- resolve12(answer);
24460
+ resolve13(answer);
24439
24461
  connection.destroy();
24440
24462
  };
24441
24463
  connection.setEncoding("utf8");
@@ -24477,6 +24499,7 @@ async function runBridge(dir, runner2) {
24477
24499
  wake?.();
24478
24500
  };
24479
24501
  serveTools(dir);
24502
+ writeFileSync3(join7(dir, "bridge-owner.json"), JSON.stringify({ pid: process.pid, digest: bundleDigest(runner2) }), { mode: 384 });
24480
24503
  const localWatch = watch4(dir, { recursive: true }, (_event, name) => {
24481
24504
  const path = String(name ?? "");
24482
24505
  if (path === "state.json" || path.startsWith("hooks/") || path.startsWith("inbox/") || path.startsWith("deliveries/"))
@@ -24573,8 +24596,8 @@ async function runBridge(dir, runner2) {
24573
24596
  await serveOutboxes(dir).catch((error) => log(dir, `outbox: ${String(error)}`));
24574
24597
  await flush(dir, sources).catch((error) => log(dir, `flush: ${String(error)}`));
24575
24598
  if (!localDirty)
24576
- await new Promise((resolve12) => {
24577
- wake = resolve12;
24599
+ await new Promise((resolve13) => {
24600
+ wake = resolve13;
24578
24601
  });
24579
24602
  wake = void 0;
24580
24603
  }
@@ -24599,19 +24622,90 @@ function bridgeRunning(dir) {
24599
24622
  return false;
24600
24623
  }
24601
24624
  }
24602
- function ensureBridge(dir, runner2, env = process.env) {
24603
- if (bridgeRunning(dir))
24604
- return;
24605
- const out = openSync3(join7(dir, "bridge.log"), "a", 384);
24606
- const child = spawn5(runner2.node, [runner2.bundle, "session", "bridge"], { detached: true, stdio: ["ignore", out, out], env });
24607
- child.unref();
24608
- closeSync3(out);
24625
+ function bundleDigest(runner2) {
24626
+ return createHash6("sha256").update(readFileSync6(runner2.bundle)).digest("hex");
24627
+ }
24628
+ function bridgeOwner(dir) {
24629
+ try {
24630
+ return JSON.parse(readFileSync6(join7(dir, "bridge-owner.json"), "utf8"));
24631
+ } catch {
24632
+ return void 0;
24633
+ }
24634
+ }
24635
+ function isBridgeProcess(pid) {
24636
+ try {
24637
+ if (process.platform === "linux") {
24638
+ const args2 = readFileSync6(`/proc/${pid}/cmdline`, "utf8").split("\0").filter(Boolean);
24639
+ return args2.length === 4 && /^node(?:\.exe)?$/.test(basename4(args2[0])) && /^(?:beeline|usebeeline\.mjs|recovery-cli\.mjs)$/.test(basename4(args2[1])) && args2[2] === "session" && args2[3] === "bridge";
24640
+ }
24641
+ const args = execFileSync("ps", ["-ww", "-p", String(pid), "-o", "args="], { encoding: "utf8" }).trim();
24642
+ return /(?:^|\/)node\s+.*\/(?:beeline|usebeeline\.mjs|recovery-cli\.mjs) session bridge$/.test(args);
24643
+ } catch {
24644
+ return false;
24645
+ }
24646
+ }
24647
+ async function ensureBridge(dir, runner2, env = process.env) {
24648
+ await withKernelLock(`beeline-session-bridge:${resolve10(dir)}`, async () => {
24649
+ const digest = bundleDigest(runner2);
24650
+ const pidFile = join7(dir, "bridge.pid");
24651
+ if (bridgeRunning(dir)) {
24652
+ const pid = Number(readFileSync6(pidFile, "utf8"));
24653
+ if (!isBridgeProcess(pid))
24654
+ throw new Error("Beeline bridge PID belongs to an unrecognized process; refusing takeover");
24655
+ const owner = bridgeOwner(dir);
24656
+ if (owner?.pid === pid && owner.digest === digest)
24657
+ return;
24658
+ log(dir, `replacing stale bridge ${pid}`);
24659
+ await withLock(dir, async () => {
24660
+ try {
24661
+ process.kill(pid, "SIGTERM");
24662
+ } catch (error) {
24663
+ if (error.code !== "ESRCH")
24664
+ throw error;
24665
+ }
24666
+ await waitForProcessExit(pid);
24667
+ });
24668
+ if (existsSync2(pidFile) && Number(readFileSync6(pidFile, "utf8")) === pid)
24669
+ rmSync3(pidFile);
24670
+ }
24671
+ const out = openSync3(join7(dir, "bridge.log"), "a", 384);
24672
+ const child = spawn6(runner2.node, [runner2.bundle, "session", "bridge"], { detached: true, stdio: ["ignore", out, out], env });
24673
+ closeSync3(out);
24674
+ child.unref();
24675
+ await new Promise((done, fail) => {
24676
+ const finish = (error) => {
24677
+ watcher.close();
24678
+ child.removeListener("error", failed);
24679
+ child.removeListener("exit", exited);
24680
+ if (error)
24681
+ fail(error);
24682
+ else
24683
+ done();
24684
+ };
24685
+ const inspect = () => {
24686
+ const owner = bridgeOwner(dir);
24687
+ if (owner && owner.pid === child.pid && owner.digest === digest)
24688
+ finish();
24689
+ };
24690
+ const failed = (error) => finish(error);
24691
+ const exited = () => finish(new Error("Beeline bridge exited before readiness; see bridge.log"));
24692
+ const watcher = watch4(dir, (_event, name) => {
24693
+ if (String(name) === "bridge-owner.json")
24694
+ inspect();
24695
+ });
24696
+ child.once("error", failed);
24697
+ child.once("exit", exited);
24698
+ inspect();
24699
+ });
24700
+ });
24609
24701
  }
24610
24702
  var realDeps;
24611
24703
  var init_bridge = __esm({
24612
24704
  "apps/body/dist/session-join/bridge.js"() {
24613
24705
  "use strict";
24614
24706
  init_agent_command();
24707
+ init_kernel_lock();
24708
+ init_process_exit();
24615
24709
  init_phone();
24616
24710
  init_beeline_api();
24617
24711
  init_stream_frame();
@@ -25232,7 +25326,7 @@ var init_claude_inbound = __esm({
25232
25326
  });
25233
25327
 
25234
25328
  // apps/body/dist/session-join/codex-trust.js
25235
- import { spawn as spawn6 } from "node:child_process";
25329
+ import { spawn as spawn7 } from "node:child_process";
25236
25330
  import { join as join10 } from "node:path";
25237
25331
  function beelineTrustEdits(hooks, context) {
25238
25332
  const path = join10(codexHome(context.env), "hooks.json");
@@ -25244,7 +25338,7 @@ function beelineTrustEdits(hooks, context) {
25244
25338
  return [{ keyPath: `hooks.state.${JSON.stringify(hook.key)}.trusted_hash`, value: hook.currentHash, mergeStrategy: "replace" }];
25245
25339
  }
25246
25340
  async function trustCodexHook(context, bin, cwd) {
25247
- const child = spawn6(bin, ["app-server", "--stdio"], { env: context.env, cwd, stdio: ["pipe", "pipe", "ignore"] });
25341
+ const child = spawn7(bin, ["app-server", "--stdio"], { env: context.env, cwd, stdio: ["pipe", "pipe", "ignore"] });
25248
25342
  let id = 0, buffer = "";
25249
25343
  const pending = /* @__PURE__ */ new Map();
25250
25344
  const fail = () => {
@@ -25282,9 +25376,9 @@ async function trustCodexHook(context, bin, cwd) {
25282
25376
  }
25283
25377
  }
25284
25378
  });
25285
- const request2 = (method, params) => new Promise((resolve12, reject) => {
25379
+ const request2 = (method, params) => new Promise((resolve13, reject) => {
25286
25380
  const key = ++id;
25287
- pending.set(key, { resolve: resolve12, reject: () => reject(new Error("Codex hook trust unavailable")) });
25381
+ pending.set(key, { resolve: resolve13, reject: () => reject(new Error("Codex hook trust unavailable")) });
25288
25382
  child.stdin.write(JSON.stringify({ id: key, method, params }) + "\n");
25289
25383
  });
25290
25384
  try {
@@ -25465,7 +25559,7 @@ var init_pull_apps = __esm({
25465
25559
  "use strict";
25466
25560
  init_store();
25467
25561
  init_beeline_api();
25468
- agentapi = (sessionId, text) => new Promise((resolve12, reject) => execFile4("agentapi", ["send-message", sessionId, text], { timeout: 3e4 }, (error) => error ? reject(error) : resolve12()));
25562
+ agentapi = (sessionId, text) => new Promise((resolve13, reject) => execFile4("agentapi", ["send-message", sessionId, text], { timeout: 3e4 }, (error) => error ? reject(error) : resolve13()));
25469
25563
  }
25470
25564
  });
25471
25565
 
@@ -25475,9 +25569,9 @@ __export(command_exports, {
25475
25569
  findOwnSession: () => findOwnSession,
25476
25570
  runSessionCommand: () => runSessionCommand
25477
25571
  });
25478
- import { spawn as spawn7, spawnSync as spawnSync2 } from "node:child_process";
25572
+ import { spawn as spawn8, spawnSync as spawnSync2 } from "node:child_process";
25479
25573
  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";
25480
- import { delimiter, dirname as dirname8, join as join11, resolve as resolve10 } from "node:path";
25574
+ import { delimiter, dirname as dirname8, join as join11, resolve as resolve11 } from "node:path";
25481
25575
  import { createHash as createHash7, randomUUID as randomUUID2 } from "node:crypto";
25482
25576
  function writePending(file, pending) {
25483
25577
  const temporary = file + "." + randomUUID2() + ".tmp";
@@ -25547,7 +25641,7 @@ function runner(dir, env) {
25547
25641
  if (env.BEELINE_SESSION_BUNDLE)
25548
25642
  return { node: process.execPath, bundle: env.BEELINE_SESSION_BUNDLE };
25549
25643
  const bundle = join11(dir, "usebeeline.mjs");
25550
- const running = resolve10(process.argv[1] ?? "");
25644
+ const running = resolve11(process.argv[1] ?? "");
25551
25645
  if (running !== bundle && running.endsWith(".mjs")) {
25552
25646
  mkdirSync5(dir, { recursive: true, mode: 448 });
25553
25647
  copyFileSync2(running, bundle);
@@ -25600,6 +25694,7 @@ async function joinCommand(args, env) {
25600
25694
  const server = serverUrl(args, env);
25601
25695
  const existing = readState(dir).sessions.find((s) => s.key === key && s.server === server);
25602
25696
  if (existing) {
25697
+ let connected = false;
25603
25698
  try {
25604
25699
  await accessToken(dir, key);
25605
25700
  await updateState(dir, (state) => {
@@ -25609,10 +25704,13 @@ async function joinCommand(args, env) {
25609
25704
  s.pid = own2.pid ?? s.pid;
25610
25705
  }
25611
25706
  });
25612
- ensureBridge(dir, run2, env);
25707
+ connected = true;
25708
+ } catch {
25709
+ }
25710
+ if (connected) {
25711
+ await ensureBridge(dir, run2, env);
25613
25712
  console.log(`This ${agentLabel(own2.agent)} session is on Beeline as @${existing.handle ?? existing.name}. Tags in its Rooms arrive here.`);
25614
25713
  return;
25615
- } catch {
25616
25714
  }
25617
25715
  }
25618
25716
  const taken = new Set(readState(dir).sessions.filter((s) => s.key !== key).map((s) => s.name));
@@ -25644,7 +25742,7 @@ async function joinCommand(args, env) {
25644
25742
  if (!resume && previous && previous.file !== file)
25645
25743
  rmSync6(previous.file, { force: true });
25646
25744
  const out = join11(dir, "bridge.log");
25647
- const child = spawn7(run2.node, [run2.bundle, "session", "finish-join", file], { detached: true, stdio: "ignore", env: { ...env, BEELINE_SESSION_BUNDLE: run2.bundle } });
25745
+ const child = spawn8(run2.node, [run2.bundle, "session", "finish-join", file], { detached: true, stdio: "ignore", env: { ...env, BEELINE_SESSION_BUNDLE: run2.bundle } });
25648
25746
  child.unref();
25649
25747
  console.log([
25650
25748
  `Show your person this link. They open it on any device (a phone works) and sign in with GitHub or Google:`,
@@ -25721,7 +25819,7 @@ async function finishJoinOwned(file, env) {
25721
25819
  changes.splice(prompt, 1);
25722
25820
  changes.push("Trusted only Beeline\u2019s SessionStart hook, pinned to its current Codex hash.");
25723
25821
  }
25724
- ensureBridge(dir, run2, env);
25822
+ await ensureBridge(dir, run2, env);
25725
25823
  const rooms = me.rooms.map((r) => r.name).slice(0, 5).join(", ");
25726
25824
  await announce(joined2, `Beeline: you joined as @${joined2.handle ?? joined2.name}${rooms ? ` in ${rooms}` : ""}. When someone tags you there, the message arrives here with the command that answers it.${changes.length ? `
25727
25825
  (${changes.join("; ")})` : ""}
@@ -25815,7 +25913,7 @@ async function session(args, env) {
25815
25913
  if (out)
25816
25914
  process.stdout.write(out + "\n");
25817
25915
  if (event === "session-start" && readState(dir).sessions.length)
25818
- ensureBridge(dir, runner(dir, env), env);
25916
+ await ensureBridge(dir, runner(dir, env), env);
25819
25917
  } catch {
25820
25918
  }
25821
25919
  return;
@@ -25878,14 +25976,14 @@ async function session(args, env) {
25878
25976
  throw new Error("Usage: usebeeline join | usebeeline session reply|read|tool|status|leave");
25879
25977
  }
25880
25978
  function readStdin(_limitMs) {
25881
- return new Promise((resolve12) => {
25979
+ return new Promise((resolve13) => {
25882
25980
  let text = "";
25883
25981
  process.stdin.setEncoding("utf8");
25884
25982
  process.stdin.on("data", (chunk) => {
25885
25983
  text += chunk;
25886
25984
  });
25887
25985
  process.stdin.on("end", () => {
25888
- resolve12(text);
25986
+ resolve13(text);
25889
25987
  });
25890
25988
  });
25891
25989
  }
@@ -25923,15 +26021,15 @@ var init_command = __esm({
25923
26021
  init_setup();
25924
26022
  init_store();
25925
26023
  init_kernel_lock();
25926
- finisherKey = (file) => "beeline-session-sign-in:" + resolve10(file);
26024
+ finisherKey = (file) => "beeline-session-sign-in:" + resolve11(file);
25927
26025
  VALUED = ["--as", "--room", "--reply-to", "--server", "--name", "--session", "--state", "--limit"];
25928
26026
  }
25929
26027
  });
25930
26028
 
25931
26029
  // apps/body/dist/recovery-cli.js
25932
- import { spawn as spawn8 } from "node:child_process";
26030
+ import { spawn as spawn9 } from "node:child_process";
25933
26031
  import { readFile as readFile5, readdir as readdir5, stat as stat3, unlink } from "node:fs/promises";
25934
- import { resolve as resolve11 } from "node:path";
26032
+ import { resolve as resolve12 } from "node:path";
25935
26033
 
25936
26034
  // apps/body/dist/recovery.js
25937
26035
  import { readFile as readFile4, readdir as readdir4, stat } from "node:fs/promises";
@@ -26448,18 +26546,18 @@ async function main() {
26448
26546
  if (args[i] === "--manifest-url" && !args[++i])
26449
26547
  throw new Error("--manifest-url requires a URL");
26450
26548
  }
26451
- const stateRoot2 = process.env.XDG_STATE_HOME || resolve11(process.env.HOME || "", ".local/state");
26549
+ const stateRoot2 = process.env.XDG_STATE_HOME || resolve12(process.env.HOME || "", ".local/state");
26452
26550
  if (args.includes("--status")) {
26453
26551
  const [native, helper] = await Promise.all([
26454
26552
  nativeHelperStatus(),
26455
26553
  requestMachine(stateRoot2, { operation: "status" }, () => true, 2e3).catch(() => void 0)
26456
26554
  ]);
26457
- const root = resolve11(stateRoot2, "beeline/agents");
26555
+ const root = resolve12(stateRoot2, "beeline/agents");
26458
26556
  const agents = await Promise.all((await readdir5(root).catch(() => [])).filter((id) => /^[0-9a-f]{64}$/.test(id)).map(async (id) => ({
26459
26557
  agentId: id,
26460
- enabled: !await stat3(resolve11(root, id, "stopped")).then(() => true, () => false),
26558
+ enabled: !await stat3(resolve12(root, id, "stopped")).then(() => true, () => false),
26461
26559
  ...helper?.agents[id] ?? { state: "not hosted" },
26462
- validRecord: await readFile5(resolve11(root, id, "runtime.json"), "utf8").then((raw) => Boolean(JSON.parse(raw).agent)).catch(() => false)
26560
+ validRecord: await readFile5(resolve12(root, id, "runtime.json"), "utf8").then((raw) => Boolean(JSON.parse(raw).agent)).catch(() => false)
26463
26561
  })));
26464
26562
  console.log(JSON.stringify({
26465
26563
  native,
@@ -26508,7 +26606,7 @@ async function main() {
26508
26606
  console.log(`[beeline] executing release ${status.loadedRelease}; helper ${status.pid}; every enabled agent serving`);
26509
26607
  return;
26510
26608
  }
26511
- const stateRoot = process.env.XDG_STATE_HOME || resolve11(process.env.HOME || "", ".local/state");
26609
+ const stateRoot = process.env.XDG_STATE_HOME || resolve12(process.env.HOME || "", ".local/state");
26512
26610
  let selectedRelease;
26513
26611
  if (command2 === "start") {
26514
26612
  for (let i = 1; i < args.length; i++) {
@@ -26523,13 +26621,13 @@ async function main() {
26523
26621
  const requested = agentFlag >= 0 ? args[agentFlag + 1] : args[1] && !args[1].startsWith("--") ? args[1] : void 0;
26524
26622
  if (agentFlag >= 0 && !requested)
26525
26623
  throw new Error("--agent requires an agent public key");
26526
- const agentRoot = resolve11(stateRoot, "beeline/agents");
26624
+ const agentRoot = resolve12(stateRoot, "beeline/agents");
26527
26625
  const ids = (await readdir5(agentRoot).catch(() => [])).filter((id) => /^[0-9a-f]{64}$/.test(id));
26528
26626
  const selected = requested ? ids.filter((id) => id.startsWith(requested)) : args.includes("--all") ? ids : [];
26529
26627
  if (requested && selected.length !== 1)
26530
26628
  throw new Error(`no unique paired agent matches ${requested}`);
26531
26629
  for (const id of selected)
26532
- await unlink(resolve11(agentRoot, id, "stopped")).catch((error) => {
26630
+ await unlink(resolve12(agentRoot, id, "stopped")).catch((error) => {
26533
26631
  if (error.code !== "ENOENT")
26534
26632
  throw error;
26535
26633
  });
@@ -26553,7 +26651,7 @@ async function main() {
26553
26651
  const entry = await resolveBundleEntrypoint(layout.libDir);
26554
26652
  if (!entry)
26555
26653
  throw new Error("no installed Beeline body; run npx usebeeline connect");
26556
- const child = spawn8(process.execPath, [entry, ...args], {
26654
+ const child = spawn9(process.execPath, [entry, ...args], {
26557
26655
  env: {
26558
26656
  ...process.env,
26559
26657
  BEELINE_LIB_DIR: layout.libDir,
@@ -26571,7 +26669,7 @@ async function convergeDependencies(layout, _deadlineAt) {
26571
26669
  if (!entry)
26572
26670
  throw new Error("dependency phase has no selected body");
26573
26671
  await new Promise((done, reject) => {
26574
- const child = spawn8(process.execPath, [entry, "converge-dependencies"], {
26672
+ const child = spawn9(process.execPath, [entry, "converge-dependencies"], {
26575
26673
  env: { ...process.env, BEELINE_LIB_DIR: layout.libDir, BEELINE_INTERNAL_RECOVERY: "1" },
26576
26674
  stdio: "inherit"
26577
26675
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usebeeline",
3
- "version": "0.1.181",
3
+ "version": "0.1.184-rc.2",
4
4
  "description": "Connect an AI coding agent to Beeline with one command.",
5
5
  "homepage": "https://usebeeline.app",
6
6
  "bugs": {