usebeeline 0.0.0 → 0.0.1

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 +797 -253
  2. package/package.json +2 -2
@@ -9515,9 +9515,9 @@ var require_permessage_deflate = __commonJS({
9515
9515
  * @private
9516
9516
  */
9517
9517
  _decompress(data, fin, callback) {
9518
- const endpoint = this._isServer ? "client" : "server";
9518
+ const endpoint2 = this._isServer ? "client" : "server";
9519
9519
  if (!this._inflate) {
9520
- const key = `${endpoint}_max_window_bits`;
9520
+ const key = `${endpoint2}_max_window_bits`;
9521
9521
  const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key];
9522
9522
  this._inflate = zlib.createInflateRaw({
9523
9523
  ...this._options.zlibInflateOptions,
@@ -9550,7 +9550,7 @@ var require_permessage_deflate = __commonJS({
9550
9550
  } else {
9551
9551
  this._inflate[kTotalLength] = 0;
9552
9552
  this._inflate[kBuffers] = [];
9553
- if (fin && this.params[`${endpoint}_no_context_takeover`]) {
9553
+ if (fin && this.params[`${endpoint2}_no_context_takeover`]) {
9554
9554
  this._inflate.reset();
9555
9555
  }
9556
9556
  }
@@ -9566,9 +9566,9 @@ var require_permessage_deflate = __commonJS({
9566
9566
  * @private
9567
9567
  */
9568
9568
  _compress(data, fin, callback) {
9569
- const endpoint = this._isServer ? "server" : "client";
9569
+ const endpoint2 = this._isServer ? "server" : "client";
9570
9570
  if (!this._deflate) {
9571
- const key = `${endpoint}_max_window_bits`;
9571
+ const key = `${endpoint2}_max_window_bits`;
9572
9572
  const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key];
9573
9573
  this._deflate = zlib.createDeflateRaw({
9574
9574
  ...this._options.zlibDeflateOptions,
@@ -9594,7 +9594,7 @@ var require_permessage_deflate = __commonJS({
9594
9594
  this._deflate[kCallback] = null;
9595
9595
  this._deflate[kTotalLength] = 0;
9596
9596
  this._deflate[kBuffers] = [];
9597
- if (fin && this.params[`${endpoint}_no_context_takeover`]) {
9597
+ if (fin && this.params[`${endpoint2}_no_context_takeover`]) {
9598
9598
  this._deflate.reset();
9599
9599
  }
9600
9600
  callback(null, data2);
@@ -22145,9 +22145,9 @@ import { constants as fsConstants2 } from "node:fs";
22145
22145
  import { access as access2, chmod as chmod6, lstat as lstat5, mkdir as mkdir17, open as open2, readFile as readFile12, rename as rename7, rm as rm9, symlink as symlink4, writeFile as writeFile11 } from "node:fs/promises";
22146
22146
  import { spawn as spawn11 } from "node:child_process";
22147
22147
  import { homedir as homedir10 } from "node:os";
22148
- import { dirname as dirname15, join as join2, resolve as resolve35 } from "node:path";
22148
+ import { dirname as dirname15, join as join2, resolve as resolve36 } from "node:path";
22149
22149
  function anchorLayout(rawLibDir) {
22150
- const libDir = resolve35(rawLibDir);
22150
+ const libDir = resolve36(rawLibDir);
22151
22151
  const segments = libDir.split(/[/\\]/);
22152
22152
  const idx = segments.lastIndexOf(RELEASES_SEGMENT);
22153
22153
  if (idx >= 2 && segments[idx - 1] === "lib") {
@@ -22163,9 +22163,9 @@ function anchorLayout(rawLibDir) {
22163
22163
  // prefix's bin, NOT <prefix>/lib/bin — deriving it one level up was the
22164
22164
  // defect that made activateRelease write its stable forwarders where
22165
22165
  // nothing executed them, leaving stale raw wrappers in <prefix>/bin.
22166
- binDir: resolve35(libDir, "../../bin"),
22166
+ binDir: resolve36(libDir, "../../bin"),
22167
22167
  libDir,
22168
- releasesRoot: resolve35(libDir, `../${RELEASES_SEGMENT}`)
22168
+ releasesRoot: resolve36(libDir, `../${RELEASES_SEGMENT}`)
22169
22169
  };
22170
22170
  }
22171
22171
  function beelineInstallLayout(env = process.env) {
@@ -22176,7 +22176,7 @@ function beelineInstallLayout(env = process.env) {
22176
22176
  }
22177
22177
  function defaultBeelineInstallLayout(env = process.env) {
22178
22178
  const home = env.HOME?.trim() || homedir10();
22179
- return anchorLayout(resolve35(home, ".local", "lib", "beeline"));
22179
+ return anchorLayout(resolve36(home, ".local", "lib", "beeline"));
22180
22180
  }
22181
22181
  function hostPlatformKey() {
22182
22182
  const os = process.platform === "linux" ? "linux" : process.platform === "darwin" ? "darwin" : "";
@@ -22781,7 +22781,7 @@ var init_self_update = __esm({
22781
22781
  });
22782
22782
 
22783
22783
  // apps/body/dist/cli.js
22784
- import { dirname as dirname20, resolve as resolve43 } from "node:path";
22784
+ import { dirname as dirname20, resolve as resolve44 } from "node:path";
22785
22785
  import { existsSync as existsSync16 } from "node:fs";
22786
22786
  import { readdir as readdir9, readFile as readFile17, unlink as unlink6, writeFile as writeFile18 } from "node:fs/promises";
22787
22787
  import { stdin as stdin5, stdout as stdout6 } from "node:process";
@@ -25576,14 +25576,14 @@ function isNonRetryableQueryError(error) {
25576
25576
  return typeof error === "object" && error !== null && "nonRetryable" in error && error.nonRetryable === true;
25577
25577
  }
25578
25578
  function withQueryAttemptTimeout(operation, controller) {
25579
- return new Promise((resolve44, reject) => {
25579
+ return new Promise((resolve45, reject) => {
25580
25580
  const timer = setTimeout(() => {
25581
25581
  controller.abort();
25582
25582
  reject(new Error(`queryEvents timed out after ${QUERY_ATTEMPT_TIMEOUT_MS}ms`));
25583
25583
  }, QUERY_ATTEMPT_TIMEOUT_MS);
25584
25584
  operation.then((value) => {
25585
25585
  clearTimeout(timer);
25586
- resolve44(value);
25586
+ resolve45(value);
25587
25587
  }, (error) => {
25588
25588
  clearTimeout(timer);
25589
25589
  reject(error);
@@ -25646,10 +25646,10 @@ async function flushQueryBatch(batchKey, batch) {
25646
25646
  function enqueueQueryEvents(opts, filters, queryPubkey) {
25647
25647
  const scope = `${queryCachePrefix(opts, queryPubkey)}${currentFetchId()}\0${opts.identity ? "auth" : "anon"}`;
25648
25648
  const batchKey = filters.every(canPartitionFilter) ? scope : `${scope}\0unpartitioned\0${JSON.stringify(filters)}`;
25649
- return new Promise((resolve44, reject) => {
25649
+ return new Promise((resolve45, reject) => {
25650
25650
  const existing = pendingQueryBatches.get(batchKey);
25651
25651
  const batch = existing ?? [];
25652
- batch.push({ opts, filters, queryPubkey, resolve: resolve44, reject });
25652
+ batch.push({ opts, filters, queryPubkey, resolve: resolve45, reject });
25653
25653
  if (existing)
25654
25654
  return;
25655
25655
  pendingQueryBatches.set(batchKey, batch);
@@ -25702,7 +25702,7 @@ function publishRetryDelayMs(failedAttempt) {
25702
25702
  return Math.round(exponential * (1 + Math.random() * 0.25));
25703
25703
  }
25704
25704
  function sleep(ms) {
25705
- return new Promise((resolve44) => setTimeout(resolve44, ms));
25705
+ return new Promise((resolve45) => setTimeout(resolve45, ms));
25706
25706
  }
25707
25707
  function errorMessage(error) {
25708
25708
  return error instanceof Error ? error.message : String(error);
@@ -25939,7 +25939,7 @@ var RelayWs = class {
25939
25939
  return pending;
25940
25940
  }
25941
25941
  doConnect() {
25942
- return new Promise((resolve44, reject) => {
25942
+ return new Promise((resolve45, reject) => {
25943
25943
  const WS = this.opts.WebSocketImpl ?? defaultWebSocket();
25944
25944
  const timeoutMs = this.opts.connectTimeoutMs ?? 15e3;
25945
25945
  let settled = false;
@@ -25966,7 +25966,7 @@ var RelayWs = class {
25966
25966
  const reconnected = this.successfulConnections > 0;
25967
25967
  this.successfulConnections += 1;
25968
25968
  this.startKeepalive();
25969
- resolve44();
25969
+ resolve45();
25970
25970
  if (reconnected)
25971
25971
  this.resubscribeLiveRequests();
25972
25972
  }
@@ -26076,14 +26076,14 @@ var RelayWs = class {
26076
26076
  ],
26077
26077
  content: ""
26078
26078
  }, this.opts.identity.secretKey);
26079
- return new Promise((resolve44, reject) => {
26080
- this.pendingAuth.set(event.id, { resolve: resolve44, reject });
26079
+ return new Promise((resolve45, reject) => {
26080
+ this.pendingAuth.set(event.id, { resolve: resolve45, reject });
26081
26081
  this.send(["AUTH", event]);
26082
26082
  setTimeout(() => {
26083
26083
  if (this.pendingAuth.has(event.id)) {
26084
26084
  this.pendingAuth.delete(event.id);
26085
26085
  if (this.ws && this.ws.readyState === 1)
26086
- resolve44();
26086
+ resolve45();
26087
26087
  else
26088
26088
  reject(new Error("NIP-42 AUTH timed out"));
26089
26089
  }
@@ -26108,7 +26108,7 @@ var RelayWs = class {
26108
26108
  }
26109
26109
  /** Publish an event over WS (`["EVENT", event]`). Resolves on OK true. */
26110
26110
  publish(event, timeoutMs = 1e4) {
26111
- return new Promise((resolve44, reject) => {
26111
+ return new Promise((resolve45, reject) => {
26112
26112
  const timer = setTimeout(() => {
26113
26113
  off();
26114
26114
  reject(new Error(`WS publish timeout for ${event.id}`));
@@ -26118,7 +26118,7 @@ var RelayWs = class {
26118
26118
  clearTimeout(timer);
26119
26119
  off();
26120
26120
  if (msg[2] === true)
26121
- resolve44();
26121
+ resolve45();
26122
26122
  else
26123
26123
  reject(new Error(`WS publish rejected: ${String(msg[3] ?? "")}`));
26124
26124
  }
@@ -26232,7 +26232,7 @@ var RelayWs = class {
26232
26232
  }
26233
26233
  };
26234
26234
  function wsQueryEvents(ws, filters, timeoutMs = 1e4) {
26235
- return new Promise((resolve44, reject) => {
26235
+ return new Promise((resolve45, reject) => {
26236
26236
  const events = [];
26237
26237
  let settled = false;
26238
26238
  let unsubscribe;
@@ -26249,7 +26249,7 @@ function wsQueryEvents(ws, filters, timeoutMs = 1e4) {
26249
26249
  const timer = setTimeout(() => finish(() => reject(new Error(`wsQueryEvents timeout after ${timeoutMs}ms`))), timeoutMs);
26250
26250
  offClose = ws.onClose(() => finish(() => reject(new Error("wsQueryEvents: socket closed"))));
26251
26251
  unsubscribe = ws.subscribe(filters, (event) => events.push(event), {
26252
- onEose: () => finish(() => resolve44(events))
26252
+ onEose: () => finish(() => resolve45(events))
26253
26253
  });
26254
26254
  });
26255
26255
  }
@@ -26311,13 +26311,13 @@ async function flushWsQueryBatch(batchKey) {
26311
26311
  }
26312
26312
  function enqueueWsQueryEvents(ws, filters, timeoutMs) {
26313
26313
  const batchKey = wsBatchKey(ws, filters);
26314
- return new Promise((resolve44, reject) => {
26314
+ return new Promise((resolve45, reject) => {
26315
26315
  const existing = pendingWsBatches.get(batchKey);
26316
26316
  if (existing) {
26317
- existing.queries.push({ filters, resolve: resolve44, reject });
26317
+ existing.queries.push({ filters, resolve: resolve45, reject });
26318
26318
  return;
26319
26319
  }
26320
- pendingWsBatches.set(batchKey, { ws, timeoutMs, queries: [{ filters, resolve: resolve44, reject }] });
26320
+ pendingWsBatches.set(batchKey, { ws, timeoutMs, queries: [{ filters, resolve: resolve45, reject }] });
26321
26321
  queueMicrotask(() => void flushWsQueryBatch(batchKey));
26322
26322
  });
26323
26323
  }
@@ -29126,14 +29126,14 @@ async function getGitHubRoomInstallationToken(baseUrl, identity2, roomId) {
29126
29126
  var HEX_KEY_RE = /^[0-9a-f]{64}$/;
29127
29127
  var IDENTITY_PREDECESSORS_TIMEOUT_MS = 5e3;
29128
29128
  function withIdentityPredecessorTimeout(operation, controller) {
29129
- return new Promise((resolve44, reject) => {
29129
+ return new Promise((resolve45, reject) => {
29130
29130
  const timer = setTimeout(() => {
29131
29131
  controller.abort();
29132
29132
  reject(new OidcBindError("offline", "identity succession lookup timed out"));
29133
29133
  }, IDENTITY_PREDECESSORS_TIMEOUT_MS);
29134
29134
  operation.then((value) => {
29135
29135
  clearTimeout(timer);
29136
- resolve44(value);
29136
+ resolve45(value);
29137
29137
  }, (error) => {
29138
29138
  clearTimeout(timer);
29139
29139
  reject(error);
@@ -30543,7 +30543,7 @@ var BuzzClient = class {
30543
30543
  return this.successionPredecessors;
30544
30544
  this.successionPredecessors = await Promise.race([
30545
30545
  fetchIdentityPredecessors(this.baseUrl, this.identity).catch(() => []),
30546
- new Promise((resolve44) => setTimeout(() => resolve44([]), SUCCESSION_LOAD_TIMEOUT_MS))
30546
+ new Promise((resolve45) => setTimeout(() => resolve45([]), SUCCESSION_LOAD_TIMEOUT_MS))
30547
30547
  ]);
30548
30548
  return this.successionPredecessors;
30549
30549
  }
@@ -30849,7 +30849,7 @@ var BuzzClient = class {
30849
30849
  return values.length > 1 ? expanded.flatMap((candidate) => values.map((value) => ({ ...candidate, [tag]: [value] }))) : expanded;
30850
30850
  }, [{ ...filter }]));
30851
30851
  const seenIds = /* @__PURE__ */ new Set();
30852
- const unsubscribes = await Promise.all(installedFilters.map((filter) => new Promise((resolve44) => {
30852
+ const unsubscribes = await Promise.all(installedFilters.map((filter) => new Promise((resolve45) => {
30853
30853
  let settled = false;
30854
30854
  let newestCreatedAt = 0;
30855
30855
  let unsubscribe = () => void 0;
@@ -30858,7 +30858,7 @@ var BuzzClient = class {
30858
30858
  return;
30859
30859
  settled = true;
30860
30860
  clearTimeout(timer);
30861
- resolve44(unsubscribe);
30861
+ resolve45(unsubscribe);
30862
30862
  };
30863
30863
  const timer = setTimeout(finish, 3e3);
30864
30864
  timer.unref?.();
@@ -32870,7 +32870,7 @@ var AcpClient = class extends EventEmitter {
32870
32870
  const current = this.activeRunIds.get(sessionId);
32871
32871
  if (current)
32872
32872
  return Promise.resolve(current);
32873
- return new Promise((resolve44, reject) => {
32873
+ return new Promise((resolve45, reject) => {
32874
32874
  const onUpdate = (update) => {
32875
32875
  if (update.sessionId !== sessionId)
32876
32876
  return;
@@ -32878,7 +32878,7 @@ var AcpClient = class extends EventEmitter {
32878
32878
  if (!runId)
32879
32879
  return;
32880
32880
  cleanup();
32881
- resolve44(runId);
32881
+ resolve45(runId);
32882
32882
  };
32883
32883
  const timer = setTimeout(() => {
32884
32884
  cleanup();
@@ -32955,13 +32955,13 @@ var AcpClient = class extends EventEmitter {
32955
32955
  }
32956
32956
  const id = this.nextId++;
32957
32957
  const payload = { jsonrpc: "2.0", id, method, params };
32958
- return new Promise((resolve44, reject) => {
32958
+ return new Promise((resolve45, reject) => {
32959
32959
  const timer = setTimeout(() => {
32960
32960
  this.pending.delete(id);
32961
32961
  reject(new AcpRequestTimeoutError(method, timeoutMs, this.stderrTail, Boolean(onStart)));
32962
32962
  }, timeoutMs);
32963
32963
  this.pending.set(id, {
32964
- resolve: resolve44,
32964
+ resolve: resolve45,
32965
32965
  reject,
32966
32966
  timer,
32967
32967
  method,
@@ -34610,7 +34610,7 @@ function compactActivityUpdate(update) {
34610
34610
  const text2 = stripAgentReplyPreamble(compactText(update.content ?? update.message ?? update.output, 2e3) ?? "").trim();
34611
34611
  return text2 ? { sessionUpdate: "progress_update", text: text2 } : void 0;
34612
34612
  }
34613
- function projectActivity(client, channelId, channelOwner, sessionId) {
34613
+ function projectActivity(client, channelId, channelOwner, sessionId, publishActivity) {
34614
34614
  let pending = [];
34615
34615
  let timer;
34616
34616
  const toolCallKinds = /* @__PURE__ */ new Map();
@@ -34620,7 +34620,7 @@ function projectActivity(client, channelId, channelOwner, sessionId) {
34620
34620
  let publishedPlanKey = "";
34621
34621
  let publishTail = Promise.resolve();
34622
34622
  const publishBatch = (events) => {
34623
- const publish = () => emitActivityEvent(channelId, channelOwner, { sessionId, channelId, events });
34623
+ const publish = () => publishActivity ? publishActivity({ sessionId, channelId, events }) : emitActivityEvent(channelId, channelOwner, { sessionId, channelId, events });
34624
34624
  publishTail = publishTail.then(publish, publish);
34625
34625
  return publishTail;
34626
34626
  };
@@ -34740,7 +34740,13 @@ function projectActivity(client, channelId, channelOwner, sessionId) {
34740
34740
  currentPlan = compactAuthoredPlan?.items.length ? {
34741
34741
  ...pinnedObjective ? { objective: pinnedObjective } : compactAuthoredPlan.objective ? { objective: compactAuthoredPlan.objective } : {},
34742
34742
  items: compactAuthoredPlan.items
34743
- } : currentPlan?.items.length ? { ...currentPlan, ...pinnedObjective ? { objective: pinnedObjective } : {} } : fallbackPlan(pinnedObjective ?? objective);
34743
+ } : currentPlan?.items.length ? (
34744
+ // A later turn (a follow-up, a nudge, a completion-ladder check) that
34745
+ // brings no fresh plan of its own must not blank a checklist an
34746
+ // earlier turn already published — that is the finished corner
34747
+ // losing its sub-goals, not an honest "no plan yet" state.
34748
+ { ...currentPlan, ...pinnedObjective ? { objective: pinnedObjective } : {} }
34749
+ ) : fallbackPlan(pinnedObjective ?? objective);
34744
34750
  await publishPlan(currentPlan);
34745
34751
  };
34746
34752
  controller.completePlan = async () => {
@@ -34831,7 +34837,7 @@ function nextMonotonicSecond(lastRef) {
34831
34837
  lastRef.value = createdAt;
34832
34838
  return createdAt;
34833
34839
  }
34834
- function createDraftStreamer(channelId, owner, sessionId, requestId, flushMs = AGENT_DRAFT_FLUSH_MS) {
34840
+ function createDraftStreamer(channelId, owner, sessionId, requestId, flushMs = AGENT_DRAFT_FLUSH_MS, publishLive, retractLive) {
34835
34841
  let latest2 = "";
34836
34842
  let published = "";
34837
34843
  let finished = false;
@@ -34851,7 +34857,7 @@ function createDraftStreamer(channelId, owner, sessionId, requestId, flushMs = A
34851
34857
  publishedSnapshots.add(stripped);
34852
34858
  const snapshot = stripped;
34853
34859
  const createdAt = nextMonotonicSecond(lastCreatedAt);
34854
- inflight = inflight.then(() => postAgentDraft(channelId, owner, sessionId, requestId, snapshot, createdAt)).catch((error) => console.error("[body] agent draft publish failed:", error));
34860
+ inflight = inflight.then(() => publishLive ? publishLive(snapshot) : postAgentDraft(channelId, owner, sessionId, requestId, snapshot, createdAt)).catch((error) => console.error("[body] agent draft publish failed:", error));
34855
34861
  };
34856
34862
  return {
34857
34863
  onChunk(fullTextSoFar) {
@@ -34871,13 +34877,13 @@ function createDraftStreamer(channelId, owner, sessionId, requestId, flushMs = A
34871
34877
  flush();
34872
34878
  if (publishedSnapshots.size > 0) {
34873
34879
  const createdAt = nextMonotonicSecond(lastCreatedAt);
34874
- inflight = inflight.then(() => retractAgentDraft(channelId, channelId, owner, createdAt)).catch((error) => console.error("[body] agent draft retract failed:", error));
34880
+ inflight = inflight.then(() => retractLive ? retractLive() : retractAgentDraft(channelId, channelId, owner, createdAt)).catch((error) => console.error("[body] agent draft retract failed:", error));
34875
34881
  }
34876
34882
  await inflight;
34877
34883
  }
34878
34884
  };
34879
34885
  }
34880
- function createThoughtStreamer(channelId, owner, sessionId, flushMs = AGENT_DRAFT_FLUSH_MS) {
34886
+ function createThoughtStreamer(channelId, owner, sessionId, flushMs = AGENT_DRAFT_FLUSH_MS, publishLive, retractLive) {
34881
34887
  let latest2 = "";
34882
34888
  let published = "";
34883
34889
  let finished = false;
@@ -34892,7 +34898,7 @@ function createThoughtStreamer(channelId, owner, sessionId, flushMs = AGENT_DRAF
34892
34898
  published = text2;
34893
34899
  const snapshot = text2;
34894
34900
  const createdAt = nextMonotonicSecond(lastCreatedAt);
34895
- inflight = inflight.then(() => postAgentThought(channelId, owner, sessionId, snapshot, createdAt)).catch((error) => console.error("[body] agent thought publish failed:", error));
34901
+ inflight = inflight.then(() => publishLive ? publishLive(snapshot) : postAgentThought(channelId, owner, sessionId, snapshot, createdAt)).catch((error) => console.error("[body] agent thought publish failed:", error));
34896
34902
  };
34897
34903
  return {
34898
34904
  onChunk(text2) {
@@ -34910,7 +34916,7 @@ function createThoughtStreamer(channelId, owner, sessionId, flushMs = AGENT_DRAF
34910
34916
  flush();
34911
34917
  if (published) {
34912
34918
  const createdAt = nextMonotonicSecond(lastCreatedAt);
34913
- inflight = inflight.then(() => retractAgentThought(channelId, channelId, owner, sessionId, createdAt)).catch((error) => console.error("[body] agent thought retract failed:", error));
34919
+ inflight = inflight.then(() => retractLive ? retractLive() : retractAgentThought(channelId, channelId, owner, sessionId, createdAt)).catch((error) => console.error("[body] agent thought retract failed:", error));
34914
34920
  }
34915
34921
  await inflight;
34916
34922
  }
@@ -34984,7 +34990,7 @@ function startAgentPresence(channelId, owner, intervalMs = AGENT_PRESENCE_HEARTB
34984
34990
  const generationId = randomUUID2();
34985
34991
  const backoff = async (delayMs) => {
34986
34992
  for (let remaining = delayMs; remaining > 0 && !stopped; remaining -= 250) {
34987
- await new Promise((resolve44) => setTimeout(resolve44, Math.min(250, remaining)));
34993
+ await new Promise((resolve45) => setTimeout(resolve45, Math.min(250, remaining)));
34988
34994
  }
34989
34995
  };
34990
34996
  const publishWithRetry = async (nextStatus) => {
@@ -35132,7 +35138,7 @@ function delayWithJitter(attempt) {
35132
35138
  const spread = exponential * 0.25;
35133
35139
  return Math.max(250, Math.round(exponential - spread + Math.random() * spread * 2));
35134
35140
  }
35135
- var sleep2 = (ms) => new Promise((resolve44) => setTimeout(resolve44, ms));
35141
+ var sleep2 = (ms) => new Promise((resolve45) => setTimeout(resolve45, ms));
35136
35142
  async function publishCritical(publish, options) {
35137
35143
  const maxAttempts = options.maxAttempts ?? CRITICAL_PUBLISH_MAX_ATTEMPTS;
35138
35144
  let lastError;
@@ -35179,6 +35185,7 @@ function migrateDurableBodyData(candidate, path) {
35179
35185
  modelTurns: legacy.modelTurns,
35180
35186
  sessionReprimes: legacy.sessionReprimes,
35181
35187
  githubEventCursors: legacy.githubEventCursors,
35188
+ daemonInboxCursors: legacy.daemonInboxCursors,
35182
35189
  factory: legacy.factory
35183
35190
  };
35184
35191
  }
@@ -35220,6 +35227,7 @@ var DurableBodyState = class {
35220
35227
  this.data.modelTurns ??= [];
35221
35228
  this.data.sessionReprimes ??= [];
35222
35229
  this.data.githubEventCursors ??= {};
35230
+ this.data.daemonInboxCursors ??= {};
35223
35231
  } catch (error) {
35224
35232
  if (error.code !== "ENOENT")
35225
35233
  throw error;
@@ -35288,6 +35296,18 @@ var DurableBodyState = class {
35288
35296
  await this.load();
35289
35297
  return { ...this.inbox(channelId).cursor };
35290
35298
  }
35299
+ async daemonInboxCursor(channelId) {
35300
+ await this.load();
35301
+ return this.data.daemonInboxCursors?.[channelId];
35302
+ }
35303
+ async setDaemonInboxCursor(channelId, cursor3) {
35304
+ await this.load();
35305
+ const cursors = this.data.daemonInboxCursors ??= {};
35306
+ if (cursors[channelId] === cursor3)
35307
+ return;
35308
+ cursors[channelId] = cursor3;
35309
+ await this.save();
35310
+ }
35291
35311
  /** Persist one inspectable model invocation, including the human event that authorized it. */
35292
35312
  async recordModelTurn(turn) {
35293
35313
  await this.load();
@@ -37683,7 +37703,7 @@ var WorkCalendar = class {
37683
37703
  if (!found) {
37684
37704
  const delay = this.dependencies.runNowVisibilityRetryMs ?? RUN_NOW_VISIBILITY_RETRY_MS;
37685
37705
  if (delay > 0)
37686
- await new Promise((resolve44) => setTimeout(resolve44, delay));
37706
+ await new Promise((resolve45) => setTimeout(resolve45, delay));
37687
37707
  await this.refresh();
37688
37708
  found = this.scheduleById(scheduleId);
37689
37709
  }
@@ -38577,8 +38597,8 @@ function trustySquireIpcPaths(env = process.env) {
38577
38597
  for (const address of [env.DBUS_SESSION_BUS_ADDRESS, env.DBUS_STARTER_ADDRESS]) {
38578
38598
  if (!address?.trim())
38579
38599
  continue;
38580
- for (const endpoint of address.split(";")) {
38581
- const match = /(?:^unix:|,)path=([^,]+)/.exec(endpoint);
38600
+ for (const endpoint2 of address.split(";")) {
38601
+ const match = /(?:^unix:|,)path=([^,]+)/.exec(endpoint2);
38582
38602
  if (match?.[1] && isAbsolute5(match[1]))
38583
38603
  paths.add(resolve13(match[1]));
38584
38604
  }
@@ -38592,8 +38612,8 @@ function trustySquireIpcPaths(env = process.env) {
38592
38612
  return [...paths];
38593
38613
  }
38594
38614
  function hasUnmaskableTrustySquireIpc(env = process.env) {
38595
- return [env.DBUS_SESSION_BUS_ADDRESS, env.DBUS_STARTER_ADDRESS].some((address) => address?.split(";").filter(Boolean).some((endpoint) => {
38596
- const match = /(?:^unix:|,)path=([^,]+)/.exec(endpoint);
38615
+ return [env.DBUS_SESSION_BUS_ADDRESS, env.DBUS_STARTER_ADDRESS].some((address) => address?.split(";").filter(Boolean).some((endpoint2) => {
38616
+ const match = /(?:^unix:|,)path=([^,]+)/.exec(endpoint2);
38597
38617
  return !match?.[1] || !isAbsolute5(match[1]);
38598
38618
  }));
38599
38619
  }
@@ -39972,15 +39992,15 @@ var SquireHostBroker = class {
39972
39992
  allowedTools: new Set(allowedTools)
39973
39993
  };
39974
39994
  channel.allowedTools = new Set(allowedTools);
39975
- const endpoint = {
39995
+ const endpoint2 = {
39976
39996
  name: "squire",
39977
39997
  command: process.execPath,
39978
39998
  args: [this.proxyEntrypoint, "127.0.0.1", String(address.port), channel.token],
39979
39999
  env: []
39980
40000
  };
39981
- channel.endpoint = endpoint;
40001
+ channel.endpoint = endpoint2;
39982
40002
  this.channels.set(channelId, channel);
39983
- return endpoint;
40003
+ return endpoint2;
39984
40004
  }
39985
40005
  accept(socket) {
39986
40006
  socket.setEncoding("utf8");
@@ -40205,14 +40225,14 @@ var AgentToolHostBroker = class {
40205
40225
  previous?.connection?.destroy();
40206
40226
  const token2 = randomBytes6(32).toString("hex");
40207
40227
  const proxyArgs = [this.proxyEntrypoint, "127.0.0.1", String(address.port), token2];
40208
- const endpoint = {
40228
+ const endpoint2 = {
40209
40229
  name: BEELINE_AGENT_TOOL_SERVER_NAME,
40210
40230
  command: process.execPath,
40211
40231
  args: this.proxyEntrypoint.endsWith(".ts") ? ["--import", "tsx", ...proxyArgs] : proxyArgs,
40212
40232
  env: []
40213
40233
  };
40214
- this.sessions.set(binding.channelId, { token: token2, binding, endpoint });
40215
- return endpoint;
40234
+ this.sessions.set(binding.channelId, { token: token2, binding, endpoint: endpoint2 });
40235
+ return endpoint2;
40216
40236
  }
40217
40237
  revoke(channelId) {
40218
40238
  const session = this.sessions.get(channelId);
@@ -40537,8 +40557,8 @@ async function inspectMcpServer(spec, timeoutMs = 15e3) {
40537
40557
  const request = (method, params) => {
40538
40558
  const id = nextId++;
40539
40559
  const payload = JSON.stringify({ jsonrpc: "2.0", id, method, params });
40540
- return new Promise((resolve44, reject) => {
40541
- pending.set(id, { resolve: resolve44, reject });
40560
+ return new Promise((resolve45, reject) => {
40561
+ pending.set(id, { resolve: resolve45, reject });
40542
40562
  child.stdin.write(payload + "\n");
40543
40563
  });
40544
40564
  };
@@ -41760,8 +41780,8 @@ var AgentMentionTurnQueue = class {
41760
41780
  run(cornerId, task) {
41761
41781
  const prior = this.tails.get(cornerId) ?? Promise.resolve();
41762
41782
  let release;
41763
- const gate = new Promise((resolve44) => {
41764
- release = resolve44;
41783
+ const gate = new Promise((resolve45) => {
41784
+ release = resolve45;
41765
41785
  });
41766
41786
  const tail = prior.catch(() => void 0).then(() => gate);
41767
41787
  this.tails.set(cornerId, tail);
@@ -43628,6 +43648,10 @@ function isChannelAddressedMessage(event, agentPubkey, roomParticipants = [], in
43628
43648
  return false;
43629
43649
  if (event.tags.some((tag) => tag[0] === "p" && tag[1] === agentPubkey))
43630
43650
  return true;
43651
+ const replyParentId = event.tags.find((tag) => tag[0] === "e" && tag[1] && tag[3] === "reply")?.[1];
43652
+ const replyParent = replyParentId ? indexedMessages.find((message2) => message2.id === replyParentId) : void 0;
43653
+ if (replyParent?.author.kind === "agent" && replyParent.author.pubkey === agentPubkey)
43654
+ return true;
43631
43655
  if (event.tags.some((tag) => tag[0] === "p" && tag[1] && roomParticipants.includes(tag[1]))) {
43632
43656
  return false;
43633
43657
  }
@@ -43635,21 +43659,7 @@ function isChannelAddressedMessage(event, agentPubkey, roomParticipants = [], in
43635
43659
  participants.delete(agentPubkey);
43636
43660
  if (participants.size === 1 && participants.has(event.pubkey))
43637
43661
  return true;
43638
- const indexedCurrent = indexedMessages.find((message2) => message2.id === event.id);
43639
- if (indexedCurrent && indexedCurrent.presentation !== "message")
43640
- return false;
43641
- const conversation = indexedMessages.filter((message2) => message2.presentation === "message");
43642
- const currentIndex = conversation.findIndex((message2) => message2.id === event.id);
43643
- const latestIndexed = conversation.at(-1);
43644
- const followsIndexedTail = latestIndexed && (latestIndexed.createdAt < event.created_at || latestIndexed.createdAt === event.created_at && latestIndexed.id.localeCompare(event.id) < 0);
43645
- const preceding = currentIndex >= 0 ? conversation[currentIndex - 1] : followsIndexedTail ? latestIndexed : void 0;
43646
- if (preceding?.author.kind !== "agent" || preceding.author.pubkey !== agentPubkey)
43647
- return false;
43648
- const repliedTo = preceding.reply?.eventId;
43649
- if (!repliedTo)
43650
- return false;
43651
- const triggeringMessage = conversation.find((message2) => message2.id === repliedTo);
43652
- return triggeringMessage?.author.kind === "human" && triggeringMessage.author.pubkey === event.pubkey;
43662
+ return false;
43653
43663
  }
43654
43664
  function isChannelWorkIntent(event, agentPubkey, roomParticipants = [], indexedMessages = []) {
43655
43665
  if (!isChannelAddressedMessage(event, agentPubkey, roomParticipants, indexedMessages))
@@ -43821,6 +43831,8 @@ var Body = class {
43821
43831
  * disposes its own sockets exactly as before.
43822
43832
  */
43823
43833
  sharedSocket;
43834
+ /** Present only after the one-way monolith transport switch is activated. */
43835
+ daemonApi;
43824
43836
  disposed = false;
43825
43837
  /**
43826
43838
  * Set only after the managed update's absolute drain deadline expires.
@@ -43888,6 +43900,7 @@ var Body = class {
43888
43900
  this.onRoomPresence = services.onRoomPresence;
43889
43901
  this.runScheduleNow = services.runScheduleNow;
43890
43902
  this.sharedSocket = services.relaySocket;
43903
+ this.daemonApi = services.daemonApi;
43891
43904
  this.durableState = new DurableBodyState(services.statePath ?? resolve27(config.workspaceRoot, ".beeline-body-state.json"));
43892
43905
  this.permissionReader = {
43893
43906
  readEvent: async (eventId) => {
@@ -44639,7 +44652,8 @@ var Body = class {
44639
44652
  this.agentIdentity,
44640
44653
  // Transcript correlation follows the durable logical turn, not a
44641
44654
  // physical ACP process id that changes after suspension/restart.
44642
- session.logicalSessionId ?? opened.sessionId
44655
+ session.logicalSessionId ?? opened.sessionId,
44656
+ this.daemonApi ? (batch) => this.publishMonolithActivity(input.channelId, batch) : void 0
44643
44657
  );
44644
44658
  session.activityProjection = activityProjection;
44645
44659
  session.unsubscribeActivity = activityProjection;
@@ -44681,7 +44695,16 @@ var Body = class {
44681
44695
  async applyModelConfigForSession(client, sessionId, communityId, sessionNewRaw, session) {
44682
44696
  let selection = null;
44683
44697
  try {
44684
- selection = await getAgentModelConfig(this.agentClientContext(), communityId, this.agentIdentity.publicKey);
44698
+ if (this.daemonApi) {
44699
+ const configured = await this.daemonApi.execute("getAgentConfiguration", {
44700
+ agentId: this.agentIdentity.publicKey,
44701
+ roomId: session.channelId
44702
+ });
44703
+ selection = configured.model || configured.effort ? { model: configured.model, effort: configured.effort } : null;
44704
+ } else {
44705
+ const persisted = await getAgentModelConfig(this.agentClientContext(), communityId, this.agentIdentity.publicKey);
44706
+ selection = persisted ? { model: persisted.model, effort: persisted.effort } : null;
44707
+ }
44685
44708
  } catch (error) {
44686
44709
  console.error("[body] failed to read persisted agent model config:", error);
44687
44710
  }
@@ -44695,7 +44718,21 @@ var Body = class {
44695
44718
  session.modelConfigOptions = catalogOptions;
44696
44719
  if (catalogOptions.length) {
44697
44720
  try {
44698
- await publishAgentModelCatalog(this.agentClientContext(), communityId, withEffectiveCurrentValues(catalogOptions, applied), applied ?? void 0);
44721
+ if (this.daemonApi) {
44722
+ await this.daemonApi.execute("postAgentModelCatalog", {
44723
+ agentId: this.agentIdentity.publicKey,
44724
+ workspaceId: communityId,
44725
+ options: withEffectiveCurrentValues(catalogOptions, applied).flatMap((option) => ["model", "thought_level", "effort", "reasoning_effort"].includes(option.category) ? [
44726
+ {
44727
+ ...option,
44728
+ category: option.category
44729
+ }
44730
+ ] : []),
44731
+ ...applied ? { selection: applied } : {}
44732
+ });
44733
+ } else {
44734
+ await publishAgentModelCatalog(this.agentClientContext(), communityId, withEffectiveCurrentValues(catalogOptions, applied), applied ?? void 0);
44735
+ }
44699
44736
  } catch (error) {
44700
44737
  console.error("[body] failed to publish agent model catalog:", error);
44701
44738
  }
@@ -44726,7 +44763,15 @@ var Body = class {
44726
44763
  attachAgentCommandPublisher(client, communityId, sessionId) {
44727
44764
  const publisher = createAgentCommandPublisher({
44728
44765
  publish: async (commands) => {
44729
- await publishAgentCommands(this.agentClientContext(), communityId, commands);
44766
+ if (this.daemonApi) {
44767
+ await this.daemonApi.execute("postAgentCommands", {
44768
+ agentId: this.agentIdentity.publicKey,
44769
+ workspaceId: communityId,
44770
+ commands
44771
+ });
44772
+ } else {
44773
+ await publishAgentCommands(this.agentClientContext(), communityId, commands);
44774
+ }
44730
44775
  },
44731
44776
  publishedSignatures: PUBLISHED_COMMAND_SIGNATURES,
44732
44777
  dedupeKeyPrefix: communityId
@@ -44930,6 +44975,43 @@ var Body = class {
44930
44975
  console.error("[body] failed to publish queued-steer acknowledgement:", error);
44931
44976
  });
44932
44977
  }
44978
+ async publishMonolithActivity(channelId, batch) {
44979
+ if (!this.daemonApi)
44980
+ return;
44981
+ const activity2 = batch.events.map((event) => {
44982
+ const plan = event.plan && typeof event.plan === "object" ? event.plan : void 0;
44983
+ return {
44984
+ kind: event.sessionUpdate === "tool_activity" ? "tool" : "summary",
44985
+ title: typeof event.title === "string" ? event.title : typeof event.text === "string" ? event.text : "Agent activity",
44986
+ ...typeof event.command === "string" ? { operation: event.command } : {},
44987
+ ...typeof event.status === "string" ? { status: event.status } : {},
44988
+ ...plan?.items ? {
44989
+ plan: {
44990
+ ...plan.objective ? { objective: plan.objective } : {},
44991
+ items: plan.items
44992
+ }
44993
+ } : {}
44994
+ };
44995
+ });
44996
+ await this.daemonApi.execute("postAgentActivity", {
44997
+ agentId: this.agentIdentity.publicKey,
44998
+ roomId: channelId,
44999
+ requestId: batch.sessionId,
45000
+ activity: activity2
45001
+ });
45002
+ }
45003
+ postTurnStatus(roomId, requestId, sessionId, status) {
45004
+ if (!this.daemonApi) {
45005
+ return postAgentTurnStatus(roomId, this.agentIdentity, requestId, sessionId, status, this.presenceGenerations.get(roomId));
45006
+ }
45007
+ return this.daemonApi.execute("postAgentTurnReceipt", {
45008
+ agentId: this.agentIdentity.publicKey,
45009
+ roomId,
45010
+ requestId,
45011
+ status,
45012
+ generationId: sessionId
45013
+ }).then(() => void 0);
45014
+ }
44933
45015
  /**
44934
45016
  * Prompt deadlines are process-health boundaries, not merely UI timeouts.
44935
45017
  * Retire a non-returning ACP generation so the next Room turn gets a fresh
@@ -44943,8 +45025,28 @@ var Body = class {
44943
45025
  * the caller publishes exactly one final agent message after this resolves.
44944
45026
  */
44945
45027
  async promptAgent(session, prompt, turn, activeRoomTurn) {
44946
- const draft = !turn.silent ? createDraftStreamer(turn.channelId, this.agentIdentity, session.logicalSessionId ?? session.sessionId, turn.requestId) : void 0;
44947
- const thought = !turn.silent ? createThoughtStreamer(turn.channelId, this.agentIdentity, session.logicalSessionId ?? session.sessionId) : void 0;
45028
+ const draft = !turn.silent ? createDraftStreamer(turn.channelId, this.agentIdentity, session.logicalSessionId ?? session.sessionId, turn.requestId, void 0, this.daemonApi ? (text2) => this.daemonApi.execute("postAgentDraft", {
45029
+ agentId: this.agentIdentity.publicKey,
45030
+ roomId: turn.channelId,
45031
+ turnId: session.logicalSessionId ?? session.sessionId,
45032
+ text: text2
45033
+ }).then(() => void 0) : void 0, this.daemonApi ? () => this.daemonApi.execute("retractAgentLiveOutput", {
45034
+ agentId: this.agentIdentity.publicKey,
45035
+ roomId: turn.channelId,
45036
+ turnId: session.logicalSessionId ?? session.sessionId,
45037
+ kind: "draft"
45038
+ }).then(() => void 0) : void 0) : void 0;
45039
+ const thought = !turn.silent ? createThoughtStreamer(turn.channelId, this.agentIdentity, session.logicalSessionId ?? session.sessionId, void 0, this.daemonApi ? (text2) => this.daemonApi.execute("postAgentThought", {
45040
+ agentId: this.agentIdentity.publicKey,
45041
+ roomId: turn.channelId,
45042
+ turnId: session.logicalSessionId ?? session.sessionId,
45043
+ text: text2
45044
+ }).then(() => void 0) : void 0, this.daemonApi ? () => this.daemonApi.execute("retractAgentLiveOutput", {
45045
+ agentId: this.agentIdentity.publicKey,
45046
+ roomId: turn.channelId,
45047
+ turnId: session.logicalSessionId ?? session.sessionId,
45048
+ kind: "thought"
45049
+ }).then(() => void 0) : void 0) : void 0;
44948
45050
  const permissionTurn = {
44949
45051
  requestId: turn.requestId,
44950
45052
  ...turn.originalRequestId ? { originalRequestId: turn.originalRequestId } : {},
@@ -45200,7 +45302,7 @@ var Body = class {
45200
45302
  return { attachments, failed };
45201
45303
  }
45202
45304
  async publishAgentResult(channelId, session, result, fallback = "", options = {}) {
45203
- const uploaded = await this.uploadAgentOutputs(session, result);
45305
+ const uploaded = this.daemonApi ? { attachments: [], failed: false } : await this.uploadAgentOutputs(session, result);
45204
45306
  let reply = stripAttachmentDirectives(stripAgentReplyPreamble(result.agentText)).trim();
45205
45307
  if (reply && isPureRetryNarration(reply)) {
45206
45308
  console.log(`[body] discarded harness retry narration instead of publishing it as a reply`);
@@ -45219,6 +45321,16 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
45219
45321
  return "";
45220
45322
  }
45221
45323
  const extraTags = options.prepareTags ? await options.prepareTags(reply) : options.extraTags ?? [];
45324
+ if (this.daemonApi) {
45325
+ await this.daemonApi.execute("postRoomMessage", {
45326
+ roomId: channelId,
45327
+ ...options.replyTo ? { requestId: options.replyTo } : {},
45328
+ text: reply,
45329
+ presentation: "message",
45330
+ ...extraTags.length ? { tags: Object.fromEntries(extraTags.filter((tag) => tag[0] && tag[1])) } : {}
45331
+ });
45332
+ return reply;
45333
+ }
45222
45334
  let event;
45223
45335
  if (options.replyTo) {
45224
45336
  event = await this.durableState.reserveReply(channelId, options.replyTo, buildAgentMessage(channelId, this.agentIdentity, reply, options.replyTo, uploaded.attachments, [["request", options.replyTo], ...extraTags], options.replyRootId));
@@ -45534,8 +45646,10 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
45534
45646
  console.warn(`[body] ${scopeWarning}`);
45535
45647
  const readonlyServerWithoutMemory = readOnlyMcpServer(this.config, readonlyCwd);
45536
45648
  const agentId = this.agentIdentity;
45537
- await this.ensureAgentInChannel(tlcChannelId, agentId);
45538
- await this.ensureAgentEntity(tlcChannelId);
45649
+ if (!this.daemonApi) {
45650
+ await this.ensureAgentInChannel(tlcChannelId, agentId);
45651
+ await this.ensureAgentEntity(tlcChannelId);
45652
+ }
45539
45653
  const communityId = await this.channelCommunityId(tlcChannelId);
45540
45654
  const workspaceId = communityId ?? tlcChannelId;
45541
45655
  const roomMemory = await this.sessionMemory(communityId);
@@ -45591,6 +45705,16 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
45591
45705
  if (boundRepo)
45592
45706
  this.agentToolRoomRepositories.set(tlcChannelId, boundRepo);
45593
45707
  const mandateGeneration2 = Date.now();
45708
+ if (this.daemonApi) {
45709
+ this.agentTools.bindMandate(tlcChannelId, {
45710
+ schema_version: BEELINE_AGENT_TOOL_SCHEMA_VERSION,
45711
+ generation: { event_id: `monolith:${mandateGeneration2}`, generation: mandateGeneration2 },
45712
+ grants: [],
45713
+ defaults: BEELINE_MANDATE_DEFAULTS.map((entry) => ({ ...entry })),
45714
+ blockers: []
45715
+ });
45716
+ return session;
45717
+ }
45594
45718
  const started = buildControlMessage("permission-status", tlcChannelId, agentId, `\u{1F916} Agent session started (read-only) \u2014 session=${session.logicalSessionId}`, [
45595
45719
  ["session", session.logicalSessionId],
45596
45720
  ["mode", "readonly"],
@@ -45660,7 +45784,11 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
45660
45784
  }
45661
45785
  }).catch(async (error) => {
45662
45786
  if (attempt.cornerId && !this.subchannels.has(attempt.cornerId)) {
45663
- await archiveChannel(this.agentIdentity, attempt.cornerId).catch(() => void 0);
45787
+ if (this.daemonApi) {
45788
+ await this.daemonApi.execute("archiveCorner", { cornerId: attempt.cornerId }).catch(() => void 0);
45789
+ } else {
45790
+ await archiveChannel(this.agentIdentity, attempt.cornerId).catch(() => void 0);
45791
+ }
45664
45792
  await this.postFailureFactOnce(tlcChannelId, `Corner for ${attempt.objective || "the requested task"} could not start and was closed.`, [
45665
45793
  ["subchannel", attempt.cornerId],
45666
45794
  ["request", request.eventId],
@@ -45689,7 +45817,8 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
45689
45817
  const freshRoomRepo = roomRepo && this.refreshRepositoryTruth ? await this.refreshRepositoryTruth(roomRepo, "corner-open") : roomRepo;
45690
45818
  const boundRepo = freshRoomRepo ? await this.cornerBoundRepo(tlcChannelId, freshRoomRepo) : void 0;
45691
45819
  const agentId = this.agentIdentity;
45692
- await this.ensureAgentInChannel(tlcChannelId, agentId);
45820
+ if (!this.daemonApi)
45821
+ await this.ensureAgentInChannel(tlcChannelId, agentId);
45693
45822
  const communityId = await this.channelCommunityId(tlcChannelId);
45694
45823
  const conversation = await this.agentHistory(tlcChannelId);
45695
45824
  const statedTask = intent ? taskDescriptionFromCornerRequest(intent).slice(0, 320) : "";
@@ -45699,7 +45828,14 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
45699
45828
  const cornerName = cornerTitleFromTask(taskDescription);
45700
45829
  const taskSlug = slugifyCornerTask(cornerName);
45701
45830
  const openingHumanPubkey = request?.authorPubkey ?? this.bodyIdentity.publicKey;
45702
- const subchannelId = await createAgentSubchannel(agentId, tlcChannelId, cornerName, openingHumanPubkey, communityId ?? void 0, taskDescription || void 0, [
45831
+ const subchannelId = this.daemonApi ? (await this.daemonApi.execute("createCorner", {
45832
+ roomId: tlcChannelId,
45833
+ requestId: request?.eventId ?? randomUUID5().replaceAll("-", ""),
45834
+ name: cornerName,
45835
+ task: taskDescription,
45836
+ ...boundRepo ? { repository: this.repoId(boundRepo) } : {},
45837
+ ...boundRepo?.targetBranch ? { targetBranch: shortBranchName(boundRepo.targetBranch) } : {}
45838
+ })).cornerId : await createAgentSubchannel(agentId, tlcChannelId, cornerName, openingHumanPubkey, communityId ?? void 0, taskDescription || void 0, [
45703
45839
  ...request ? [
45704
45840
  ["request", request.eventId],
45705
45841
  ["requester", request.authorPubkey]
@@ -45720,30 +45856,50 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
45720
45856
  if (request) {
45721
45857
  const requesterAttribution = request.delegation ? (await this.roomAuthorAttributions(tlcChannelId, [request.authorPubkey])).get(request.authorPubkey) : request.authorAttribution;
45722
45858
  const requester = requesterAttribution?.handle ?? fallbackPersonName(request.authorPubkey);
45723
- await postControlMessage("corner-created", tlcChannelId, agentId, `Corner requested by @${requester.replace(/^@/, "")}: ${taskDescription || request.content.trim() || "untitled task"}`, [
45724
- ["subchannel", subchannelId],
45725
- ["request", request.eventId],
45726
- ["requester", request.authorPubkey],
45727
- ["status", "open"],
45728
- ["display-status", "starting"],
45729
- ["task", taskDescription]
45730
- ]);
45731
- if (!options?.suppressOpenCard) {
45732
- await postControlMessage("corner-open-fact", tlcChannelId, agentId, `Corner opened: ${cornerName}`, [
45733
- ["t", "corner-open"],
45859
+ const createdText = `Corner requested by @${requester.replace(/^@/, "")}: ${taskDescription || request.content.trim() || "untitled task"}`;
45860
+ if (this.daemonApi) {
45861
+ await this.daemonApi.execute("postRoomMessage", {
45862
+ roomId: tlcChannelId,
45863
+ requestId: request.eventId,
45864
+ text: createdText,
45865
+ presentation: "card",
45866
+ tags: { type: "corner-created", subchannel: subchannelId, status: "open" }
45867
+ });
45868
+ } else
45869
+ await postControlMessage("corner-created", tlcChannelId, agentId, createdText, [
45734
45870
  ["subchannel", subchannelId],
45735
- ["objective", taskDescription || request.content.trim() || cornerName],
45736
- ["name", cornerName]
45871
+ ["request", request.eventId],
45872
+ ["requester", request.authorPubkey],
45873
+ ["status", "open"],
45874
+ ["display-status", "starting"],
45875
+ ["task", taskDescription]
45737
45876
  ]);
45877
+ if (!options?.suppressOpenCard) {
45878
+ if (this.daemonApi) {
45879
+ await this.daemonApi.execute("postRoomMessage", {
45880
+ roomId: tlcChannelId,
45881
+ requestId: request.eventId,
45882
+ text: `Corner opened: ${cornerName}`,
45883
+ presentation: "card",
45884
+ tags: { type: "corner-open", subchannel: subchannelId, objective: taskDescription }
45885
+ });
45886
+ } else
45887
+ await postControlMessage("corner-open-fact", tlcChannelId, agentId, `Corner opened: ${cornerName}`, [
45888
+ ["t", "corner-open"],
45889
+ ["subchannel", subchannelId],
45890
+ ["objective", taskDescription || request.content.trim() || cornerName],
45891
+ ["name", cornerName]
45892
+ ]);
45738
45893
  }
45739
45894
  }
45740
- try {
45741
- await waitUntilMember(this.agentClientContext(), subchannelId, openingHumanPubkey);
45742
- } catch (error) {
45743
- await archiveChannel(agentId, subchannelId).catch((archiveError) => console.error(`[body] failed to archive corner ${subchannelId} after its opening human was not projected:`, archiveError));
45744
- throw error;
45745
- }
45746
- const mirroredParticipantPubkeys = await this.mirrorMembers(tlcChannelId, subchannelId);
45895
+ if (!this.daemonApi)
45896
+ try {
45897
+ await waitUntilMember(this.agentClientContext(), subchannelId, openingHumanPubkey);
45898
+ } catch (error) {
45899
+ await archiveChannel(agentId, subchannelId).catch((archiveError) => console.error(`[body] failed to archive corner ${subchannelId} after its opening human was not projected:`, archiveError));
45900
+ throw error;
45901
+ }
45902
+ const mirroredParticipantPubkeys = this.daemonApi ? [agentId.publicKey, openingHumanPubkey] : await this.mirrorMembers(tlcChannelId, subchannelId);
45747
45903
  const participantPubkeys = [.../* @__PURE__ */ new Set([...mirroredParticipantPubkeys, openingHumanPubkey])];
45748
45904
  const worktreePath = boundRepo ? this.cornerWorktreePath(boundRepo, subchannelId) : resolve27(this.config.workspaceRoot, "repoless-corners", subchannelId);
45749
45905
  const featureBranch = taskSlug ? `feature/${taskSlug}-${subchannelId.slice(0, 8)}` : `feature/${subchannelId.slice(0, 8)}`;
@@ -45770,7 +45926,8 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
45770
45926
  if (cornerMemory) {
45771
45927
  mcpServers.push(readOnlyMcpServer(this.config, worktreePath, cornerMemory.dir));
45772
45928
  }
45773
- mcpServers.push(...await this.authorizedExternalServers(subchannelId));
45929
+ if (!this.daemonApi)
45930
+ mcpServers.push(...await this.authorizedExternalServers(subchannelId));
45774
45931
  mcpServers.push(...operatorMcpServersForCorners(this.config.accessPolicy, this.config.operatorMcpServers));
45775
45932
  if (boundRepo) {
45776
45933
  const codegraphServer = codegraphMcpServer(this.config);
@@ -45859,32 +46016,42 @@ ${AGENT_ATTACHMENT_FAILURE_REPLY}`;
45859
46016
  ["request", request.eventId],
45860
46017
  ["requester", request.authorPubkey]
45861
46018
  ] : [];
45862
- await postControlMessage("corner-session-live", subchannelId, agentId, boundRepo ? `\u{1F916} Agent edit session started \u2014 members mirrored from parent TLC.
46019
+ const liveText = boundRepo ? `\u{1F916} Agent edit session started \u2014 members mirrored from parent TLC.
45863
46020
  Worktree: ${worktreePath}
45864
46021
  Branch: ${featureBranch}` : `\u{1F916} Agent repo-less corner started \u2014 members mirrored from parent TLC.
45865
46022
  Workspace: ${worktreePath}
45866
- Deliver artifacts from this corner; there is no branch to land.`, [
45867
- ["session", session.logicalSessionId],
45868
- ["parent", tlcChannelId],
45869
- ["mode", "edit"],
45870
- ["agent", agentId.publicKey],
45871
- ...repoId ? [["repo", repoId]] : [],
45872
- ...boundRepo ? [["feature", featureBranch]] : [],
45873
- ...boundRepo ? [["branch", targetBranch2]] : [],
45874
- ["status", "live"],
45875
- ...options?.mission ? [
45876
- ["mission", options.mission.missionId],
45877
- ["grant", options.mission.grantEventId],
45878
- ["controller-agent", options.mission.controllerAgentPubkey],
45879
- ["principal", options.mission.principalPubkey],
45880
- ["target-agent", options.mission.targetAgentPubkey],
45881
- ["mission-workspace", options.mission.workspaceId],
45882
- ["mission-room", options.mission.roomId],
45883
- ["mission-repo", options.mission.repository.key],
45884
- ["mission-ref", options.mission.repository.targetBranch]
45885
- ] : [],
45886
- ...requestTags
45887
- ]);
46023
+ Deliver artifacts from this corner; there is no branch to land.`;
46024
+ if (this.daemonApi) {
46025
+ await this.daemonApi.execute("postRoomMessage", {
46026
+ roomId: subchannelId,
46027
+ ...request ? { requestId: request.eventId } : {},
46028
+ text: liveText,
46029
+ presentation: "system",
46030
+ tags: { type: "corner-session-live", parent: tlcChannelId, status: "live" }
46031
+ });
46032
+ } else
46033
+ await postControlMessage("corner-session-live", subchannelId, agentId, liveText, [
46034
+ ["session", session.logicalSessionId],
46035
+ ["parent", tlcChannelId],
46036
+ ["mode", "edit"],
46037
+ ["agent", agentId.publicKey],
46038
+ ...repoId ? [["repo", repoId]] : [],
46039
+ ...boundRepo ? [["feature", featureBranch]] : [],
46040
+ ...boundRepo ? [["branch", targetBranch2]] : [],
46041
+ ["status", "live"],
46042
+ ...options?.mission ? [
46043
+ ["mission", options.mission.missionId],
46044
+ ["grant", options.mission.grantEventId],
46045
+ ["controller-agent", options.mission.controllerAgentPubkey],
46046
+ ["principal", options.mission.principalPubkey],
46047
+ ["target-agent", options.mission.targetAgentPubkey],
46048
+ ["mission-workspace", options.mission.workspaceId],
46049
+ ["mission-room", options.mission.roomId],
46050
+ ["mission-repo", options.mission.repository.key],
46051
+ ["mission-ref", options.mission.repository.targetBranch]
46052
+ ] : [],
46053
+ ...requestTags
46054
+ ]);
45888
46055
  return info;
45889
46056
  }
45890
46057
  /** Resolve display-only Room speaker labels. These labels never grant authority. */
@@ -45963,6 +46130,32 @@ Deliver artifacts from this corner; there is no branch to land.`, [
45963
46130
  }).room(channelId)).messages;
45964
46131
  }
45965
46132
  async agentHistory(channelId) {
46133
+ if (this.daemonApi) {
46134
+ const history = await this.daemonApi.execute("getRoomConversation", {
46135
+ roomId: channelId,
46136
+ limit: 200
46137
+ });
46138
+ return history.items.filter((item) => item.type === "message").map((item) => ({
46139
+ type: item.authorId === this.agentIdentity.publicKey ? "agent-message" : "human-message",
46140
+ eventId: item.id,
46141
+ channelId,
46142
+ author: {
46143
+ pubkey: item.authorId,
46144
+ kind: item.authorId === this.agentIdentity.publicKey ? "agent" : "human",
46145
+ label: item.authorId === this.agentIdentity.publicKey ? this.agentIdentity.name : fallbackPersonName(item.authorId)
46146
+ },
46147
+ body: item.body,
46148
+ attachments: item.attachments.map((attachment2) => ({
46149
+ url: attachment2.url,
46150
+ name: attachment2.name ?? "attachment",
46151
+ mimeType: attachment2.mimeType ?? "application/octet-stream",
46152
+ size: attachment2.size ?? 0,
46153
+ ...attachment2.thumbnailUrl ? { thumbnailUrl: attachment2.thumbnailUrl } : {}
46154
+ })),
46155
+ createdAt: item.createdAt,
46156
+ provenance: "monolith-verified"
46157
+ }));
46158
+ }
45966
46159
  return roomViewConversationHistory(channelId, await this.indexedRoomMessages(channelId));
45967
46160
  }
45968
46161
  ensureChannelPresenceCache(channelId) {
@@ -46586,7 +46779,7 @@ Deliver artifacts from this corner; there is no branch to land.`, [
46586
46779
  let addressed = isChannelAddressedMessage(event, this.agentIdentity.publicKey, roomParticipants);
46587
46780
  const otherParticipants = new Set(roomParticipants);
46588
46781
  otherParticipants.delete(this.agentIdentity.publicKey);
46589
- if (!addressed && event.kind === 9 && event.pubkey !== this.agentIdentity.publicKey && otherParticipants.size > 1) {
46782
+ if (!addressed && event.kind === 9 && event.pubkey !== this.agentIdentity.publicKey && otherParticipants.size > 1 && event.tags.some((tag) => tag[0] === "e" && tag[1] && tag[3] === "reply")) {
46590
46783
  if (!indexedMessagesLoaded) {
46591
46784
  indexedMessages = await this.indexedRoomMessages(tlcChannelId);
46592
46785
  indexedMessagesLoaded = true;
@@ -47008,20 +47201,24 @@ Deliver artifacts from this corner; there is no branch to land.`, [
47008
47201
  const delegatedReplyTags = this.delegatedReplyTags(request);
47009
47202
  if (this.config.modelUnavailable) {
47010
47203
  const receiptSessionId = this.sessions.get(tlcChannelId)?.logicalSessionId ?? `${this.agentIdentity.publicKey}:${tlcChannelId}`;
47011
- await postControlMessage("turn-receipt", tlcChannelId, this.agentIdentity, "", [
47012
- ["t", "agent-turn"],
47013
- ["request", request.eventId],
47014
- ["session", receiptSessionId],
47015
- ["agent", this.agentIdentity.publicKey],
47016
- ["mode", "readonly"],
47017
- ["status", "failed"],
47018
- ...this.presenceGenerations.get(tlcChannelId) ? [["generation", this.presenceGenerations.get(tlcChannelId)]] : []
47019
- ]);
47204
+ if (this.daemonApi) {
47205
+ await this.postTurnStatus(tlcChannelId, request.eventId, receiptSessionId, "failed");
47206
+ } else {
47207
+ await postControlMessage("turn-receipt", tlcChannelId, this.agentIdentity, "", [
47208
+ ["t", "agent-turn"],
47209
+ ["request", request.eventId],
47210
+ ["session", receiptSessionId],
47211
+ ["agent", this.agentIdentity.publicKey],
47212
+ ["mode", "readonly"],
47213
+ ["status", "failed"],
47214
+ ...this.presenceGenerations.get(tlcChannelId) ? [["generation", this.presenceGenerations.get(tlcChannelId)]] : []
47215
+ ]);
47216
+ }
47020
47217
  return { status: "handled", outcome: { openedCorner: false, producedReply: true } };
47021
47218
  }
47022
- if (!scheduled)
47219
+ if (!scheduled && !this.daemonApi)
47023
47220
  await this.markSlashCommandVocabulary(tlcChannelId, request.content);
47024
- const releaseIntent = boundRepo && editPolicy === "repository" && !explicitCornerWork && !scheduled && releaseRoomIntent(request.content);
47221
+ const releaseIntent = !this.daemonApi && boundRepo && editPolicy === "repository" && !explicitCornerWork && !scheduled && releaseRoomIntent(request.content);
47025
47222
  const informationOnly = scheduled !== void 0 || agentExchange !== void 0 || releaseIntent !== void 0 || isReadOnlyInformationRequest(request.content);
47026
47223
  const requestAuthor = request.authorAttribution ?? (() => {
47027
47224
  const name = fallbackPersonName(request.authorPubkey);
@@ -47093,7 +47290,7 @@ Deliver artifacts from this corner; there is no branch to land.`, [
47093
47290
  async acquireRoomReplySession(tlcChannelId, turn) {
47094
47291
  const { request, boundRepo, editPolicy } = turn;
47095
47292
  const receiptSessionId = this.sessions.get(tlcChannelId)?.logicalSessionId ?? `${this.agentIdentity.publicKey}:${tlcChannelId}`;
47096
- await postAgentTurnStatus(tlcChannelId, this.agentIdentity, request.eventId, receiptSessionId, "working", this.presenceGenerations.get(tlcChannelId));
47293
+ await this.postTurnStatus(tlcChannelId, request.eventId, receiptSessionId, "working");
47097
47294
  try {
47098
47295
  const session = this.sessions.get(tlcChannelId) ?? await this.provision(tlcChannelId, boundRepo, editPolicy);
47099
47296
  if (session.mode !== "readonly") {
@@ -47101,7 +47298,7 @@ Deliver artifacts from this corner; there is no branch to land.`, [
47101
47298
  }
47102
47299
  return { status: "ready", receiptSessionId, session };
47103
47300
  } catch (error) {
47104
- await postAgentTurnStatus(tlcChannelId, this.agentIdentity, request.eventId, receiptSessionId, "failed", this.presenceGenerations.get(tlcChannelId)).catch((statusError) => console.error("[body] failed to replace Room receipt after session start failure:", statusError));
47301
+ await this.postTurnStatus(tlcChannelId, request.eventId, receiptSessionId, "failed").catch((statusError) => console.error("[body] failed to replace Room receipt after session start failure:", statusError));
47105
47302
  if (!(error instanceof ReadOnlyToolsUnavailableError))
47106
47303
  throw error;
47107
47304
  console.error(`[body] read-only tools unavailable for Room ${tlcChannelId}:`, error);
@@ -47197,7 +47394,7 @@ Deliver artifacts from this corner; there is no branch to land.`, [
47197
47394
  } catch (publishError) {
47198
47395
  console.error("[body] failed to publish Room reply after corner transition:", publishError);
47199
47396
  }
47200
- await postAgentTurnStatus(tlcChannelId, this.agentIdentity, request.eventId, session.logicalSessionId ?? session.sessionId, "complete", this.presenceGenerations.get(tlcChannelId));
47397
+ await this.postTurnStatus(tlcChannelId, request.eventId, session.logicalSessionId ?? session.sessionId, "complete");
47201
47398
  return { openedCorner: true, producedReply: true };
47202
47399
  }
47203
47400
  if (!scheduled && !agentExchange && usesTextTargetBranchFallback(this.config.agentCommand ?? this.config.agentBinary)) {
@@ -47207,7 +47404,7 @@ Deliver artifacts from this corner; there is no branch to land.`, [
47207
47404
  }
47208
47405
  if (turn.targetBranchProposalFailed) {
47209
47406
  console.log(`[body] room ${tlcChannelId} request ${request.eventId}: target-branch proposal publication failed; leaving the request retryable`);
47210
- await postAgentTurnStatus(tlcChannelId, this.agentIdentity, request.eventId, session.logicalSessionId ?? session.sessionId, "failed", this.presenceGenerations.get(tlcChannelId)).catch((statusError) => console.error("[body] failed to publish Room turn failure status:", statusError));
47407
+ await this.postTurnStatus(tlcChannelId, request.eventId, session.logicalSessionId ?? session.sessionId, "failed").catch((statusError) => console.error("[body] failed to publish Room turn failure status:", statusError));
47211
47408
  return { openedCorner: false, producedReply: false };
47212
47409
  }
47213
47410
  }
@@ -47233,17 +47430,17 @@ Deliver artifacts from this corner; there is no branch to land.`, [
47233
47430
  }
47234
47431
  this.processedRequestIds.add(request.eventId);
47235
47432
  await this.durableState.delivered(tlcChannelId, request.eventId);
47236
- await postAgentTurnStatus(tlcChannelId, this.agentIdentity, request.eventId, session.logicalSessionId ?? session.sessionId, "complete", this.presenceGenerations.get(tlcChannelId)).catch((statusError) => console.error("[body] failed to publish Room turn completion status:", statusError));
47433
+ await this.postTurnStatus(tlcChannelId, request.eventId, session.logicalSessionId ?? session.sessionId, "complete").catch((statusError) => console.error("[body] failed to publish Room turn completion status:", statusError));
47237
47434
  return { openedCorner: false, producedReply: Boolean(reply) };
47238
47435
  } catch (error) {
47239
47436
  if (this.forcedUpdateRestart && promptAttempted && !scheduled) {
47240
47437
  return { openedCorner: false, producedReply: false };
47241
47438
  }
47242
47439
  if (scheduled && error instanceof ScheduleActivationRefusedError) {
47243
- await postAgentTurnStatus(tlcChannelId, this.agentIdentity, request.eventId, session.logicalSessionId ?? session.sessionId, "failed", this.presenceGenerations.get(tlcChannelId)).catch(() => void 0);
47440
+ await this.postTurnStatus(tlcChannelId, request.eventId, session.logicalSessionId ?? session.sessionId, "failed").catch(() => void 0);
47244
47441
  throw error;
47245
47442
  }
47246
- await postAgentTurnStatus(tlcChannelId, this.agentIdentity, request.eventId, session.logicalSessionId ?? session.sessionId, "failed", this.presenceGenerations.get(tlcChannelId)).catch((statusError) => console.error("[body] failed to publish Room turn failure status:", statusError));
47443
+ await this.postTurnStatus(tlcChannelId, request.eventId, session.logicalSessionId ?? session.sessionId, "failed").catch((statusError) => console.error("[body] failed to publish Room turn failure status:", statusError));
47247
47444
  if (promptAttempted) {
47248
47445
  console.error(`[body] Room turn ${request.eventId} failed:`, error);
47249
47446
  this.processedRequestIds.add(request.eventId);
@@ -47530,6 +47727,13 @@ Deliver artifacts from this corner; there is no branch to land.`, [
47530
47727
  return [...new Set(checked.filter((item) => item.human).map((item) => item.pubkey))];
47531
47728
  }
47532
47729
  async requesterCanOpenCornerDirectly(roomId, requesterPubkey) {
47730
+ if (this.daemonApi) {
47731
+ const authority = await this.daemonApi.execute("getRoomAuthority", {
47732
+ roomId,
47733
+ principalId: requesterPubkey
47734
+ });
47735
+ return authority.member && authority.principalKind === "human" && (authority.role === "owner" || authority.role === "admin");
47736
+ }
47533
47737
  const member2 = (await listMembers(this.agentClientContext(), roomId)).find((candidate) => candidate.pubkey === requesterPubkey);
47534
47738
  return Boolean(member2 && (member2.role === "owner" || member2.role === "admin") && !await isRegisteredAgentIdentity2(requesterPubkey, this.agentRelay));
47535
47739
  }
@@ -48179,7 +48383,7 @@ Deliver artifacts from this corner; there is no branch to land.`, [
48179
48383
  let preparedMention;
48180
48384
  let publishedMentionEvent;
48181
48385
  const parentRoomId = info.session.parentChannelId;
48182
- await this.finishCornerTurn(info, result, "", parentRoomId ? {
48386
+ await this.finishCornerTurn(info, result, "", parentRoomId && !this.daemonApi ? {
48183
48387
  extraTagsForText: async (text2) => {
48184
48388
  preparedMention = await this.prepareCornerAgentMention({
48185
48389
  roomId: parentRoomId,
@@ -48195,14 +48399,14 @@ Deliver artifacts from this corner; there is no branch to land.`, [
48195
48399
  }
48196
48400
  } : {});
48197
48401
  await this.completeCornerPlan(info.session);
48198
- await postAgentTurnStatus(info.subchannelId, this.agentIdentity, requestId, sessionId, "complete", this.presenceGenerations.get(info.subchannelId));
48402
+ await this.postTurnStatus(info.subchannelId, requestId, sessionId, "complete");
48199
48403
  if (preparedMention && publishedMentionEvent) {
48200
48404
  await this.finishCornerAgentMention(preparedMention, publishedMentionEvent);
48201
48405
  }
48202
48406
  } catch (error) {
48203
48407
  if (info.archived)
48204
48408
  return;
48205
- await postAgentTurnStatus(info.subchannelId, this.agentIdentity, requestId, sessionId, "failed", this.presenceGenerations.get(info.subchannelId)).catch(() => void 0);
48409
+ await this.postTurnStatus(info.subchannelId, requestId, sessionId, "failed").catch(() => void 0);
48206
48410
  } finally {
48207
48411
  this.runningAgentTasks.delete(info.subchannelId);
48208
48412
  await this.observeOneCornerRemote(info).catch((error) => console.error(`[body] corner ${info.subchannelId} completion observation failed:`, error));
@@ -48219,6 +48423,15 @@ Deliver artifacts from this corner; there is no branch to land.`, [
48219
48423
  return false;
48220
48424
  this.publishingFailureFacts.add(coordinate);
48221
48425
  try {
48426
+ if (this.daemonApi) {
48427
+ await this.daemonApi.execute("postRoomMessage", {
48428
+ roomId: channelId,
48429
+ text: content,
48430
+ presentation: "system",
48431
+ tags: Object.fromEntries(tags.filter((tag) => tag[0] && tag[1]))
48432
+ });
48433
+ return true;
48434
+ }
48222
48435
  const existing = await this.agentRelay.queryEvents([
48223
48436
  {
48224
48437
  kinds: [9],
@@ -48521,8 +48734,8 @@ Deliver artifacts from this corner; there is no branch to land.`, [
48521
48734
  release = lease.release;
48522
48735
  this.roomSockets.set(channelId, client);
48523
48736
  let finishWait = () => void 0;
48524
- const socketClosed = new Promise((resolve44) => {
48525
- finishWait = resolve44;
48737
+ const socketClosed = new Promise((resolve45) => {
48738
+ finishWait = resolve45;
48526
48739
  });
48527
48740
  offClose = client.onSocketClose(finishWait);
48528
48741
  const onAbort = () => finishWait();
@@ -48603,6 +48816,77 @@ Deliver artifacts from this corner; there is no branch to land.`, [
48603
48816
  }
48604
48817
  }
48605
48818
  }
48819
+ async runMonolithRoomLoop(channelId, boundRepo, editPolicy, opts) {
48820
+ const api = this.daemonApi;
48821
+ let cursor3 = await this.durableState.daemonInboxCursor(channelId);
48822
+ await api.execute("postAgentPresence", {
48823
+ agentId: this.agentIdentity.publicKey,
48824
+ roomId: channelId,
48825
+ status: this.config.modelUnavailable ? "offline" : "online"
48826
+ });
48827
+ if (!cursor3) {
48828
+ const activation = await api.execute("getRoomInbox", {
48829
+ roomId: channelId,
48830
+ startAtLatest: true
48831
+ });
48832
+ if (activation.cursor) {
48833
+ cursor3 = activation.cursor;
48834
+ await this.durableState.setDaemonInboxCursor(channelId, cursor3);
48835
+ }
48836
+ }
48837
+ while (!opts.signal?.aborted && !this.disposed) {
48838
+ try {
48839
+ const inbox = await api.execute("getRoomInbox", {
48840
+ roomId: channelId,
48841
+ ...cursor3 ? { after: cursor3 } : {},
48842
+ limit: 200
48843
+ });
48844
+ for (const item of inbox.items) {
48845
+ if (item.authorId === this.agentIdentity.publicKey || item.type !== "message" || item.mentionIds.length > 0 && !item.mentionIds.includes(this.agentIdentity.publicKey) || this.processedRequestIds.has(item.id))
48846
+ continue;
48847
+ const authority = await api.execute("getRoomAuthority", {
48848
+ roomId: channelId,
48849
+ principalId: item.authorId
48850
+ });
48851
+ if (!authority.member || authority.principalKind !== "human")
48852
+ continue;
48853
+ if (!this.senderAccessAllowed(item.authorId))
48854
+ continue;
48855
+ const attachments = item.attachments.map((attachment2) => ({
48856
+ url: attachment2.url,
48857
+ name: attachment2.name ?? "attachment",
48858
+ mimeType: attachment2.mimeType ?? "application/octet-stream",
48859
+ size: attachment2.size ?? 0,
48860
+ ...attachment2.thumbnailUrl ? { thumbnailUrl: attachment2.thumbnailUrl } : {}
48861
+ }));
48862
+ const request = {
48863
+ eventId: item.id,
48864
+ authorPubkey: item.authorId,
48865
+ content: item.body.trim(),
48866
+ attachments,
48867
+ createdAt: item.createdAt,
48868
+ ...item.rootMessageId ? { replyRootId: item.rootMessageId } : {}
48869
+ };
48870
+ const workIntent = !isReadOnlyInformationRequest(item.body);
48871
+ const outcome = await this.replyInRoom(channelId, boundRepo, request, editPolicy === "repository" && workIntent, editPolicy, void 0, workIntent);
48872
+ if (outcome.producedReply)
48873
+ this.processedRequestIds.add(item.id);
48874
+ }
48875
+ if (inbox.cursor) {
48876
+ cursor3 = inbox.cursor;
48877
+ await this.durableState.setDaemonInboxCursor(channelId, cursor3);
48878
+ }
48879
+ this.onRoomPollSuccess?.(channelId);
48880
+ await this.waitForPoll(opts.pollMs ?? 1e3, opts.signal);
48881
+ } catch (error) {
48882
+ if (opts.signal?.aborted || this.disposed)
48883
+ break;
48884
+ this.onRoomPollFailure?.(channelId, 1e3);
48885
+ console.error(`[body] monolith Room ${channelId} poll failed:`, error);
48886
+ await this.waitForPoll(1e3, opts.signal);
48887
+ }
48888
+ }
48889
+ }
48606
48890
  /** One long-running body loop owns request discovery, steering, and merge closure. */
48607
48891
  async runChannelLoop(tlcChannelId, boundRepo, opts = {}) {
48608
48892
  await this.channelCommunityId(tlcChannelId).then((communityId) => communityId ? this.syncModelSelectionToRelay(communityId) : void 0).catch((error) => console.error("[body] model catalog sync failed:", error));
@@ -48628,6 +48912,10 @@ Deliver artifacts from this corner; there is no branch to land.`, [
48628
48912
  }
48629
48913
  /** Durable loop for DMs and ordinary Rooms that have no repository binding. */
48630
48914
  async runConversationRoomLoop(channelId, editPolicy, opts = {}) {
48915
+ if (this.daemonApi) {
48916
+ await this.runMonolithRoomLoop(channelId, void 0, editPolicy, opts);
48917
+ return;
48918
+ }
48631
48919
  await this.channelCommunityId(channelId).then((communityId) => communityId ? this.syncModelSelectionToRelay(communityId) : void 0).catch((error) => console.error("[body] model selection sync failed:", error));
48632
48920
  const stopPresence = startAgentPresence(channelId, this.agentIdentity, void 0, (status) => this.onRoomPresence?.(channelId, status), this.config.modelUnavailable ? "offline" : "online", {
48633
48921
  policy: this.config.accessPolicy ?? LEGACY_ACCESS_POLICY,
@@ -48649,6 +48937,11 @@ Deliver artifacts from this corner; there is no branch to land.`, [
48649
48937
  }
48650
48938
  /** Durable paired-agent loop for the repository's single Workspace Room. */
48651
48939
  async runRepositoryRoomLoop(communityId, channelId, boundRepo, opts = {}) {
48940
+ if (this.daemonApi) {
48941
+ await this.assertRepositorySafety(channelId, boundRepo);
48942
+ await this.runMonolithRoomLoop(channelId, boundRepo, "repository", opts);
48943
+ return;
48944
+ }
48652
48945
  if (!boundRepo.repositoryKey)
48653
48946
  throw new Error("paired Room is missing its repository key");
48654
48947
  await this.syncModelSelectionToRelay(communityId).catch((error) => console.error("[body] model selection sync failed:", error));
@@ -49035,6 +49328,8 @@ Deliver artifacts from this corner; there is no branch to land.`, [
49035
49328
  }
49036
49329
  }
49037
49330
  async observeOneCornerRemote(info, githubEventId) {
49331
+ if (this.daemonApi)
49332
+ return;
49038
49333
  if (info.archived || !info.boundRepo || !info.featureBranch || !info.boundRepo.truth?.binding.remote?.startsWith("git://github.com/"))
49039
49334
  return;
49040
49335
  if (this.observingCornerRemotes.has(info.subchannelId))
@@ -49805,6 +50100,14 @@ Deliver artifacts from this corner; there is no branch to land.`, [
49805
50100
  const fallback = shortBranchName(boundRepo.targetBranch);
49806
50101
  const confirmed = this.confirmedRoomTargetBranches.get(channelId);
49807
50102
  try {
50103
+ if (this.daemonApi) {
50104
+ const config2 = await this.daemonApi.execute("getRoomTargetBranch", {
50105
+ roomId: channelId
50106
+ });
50107
+ const branch2 = shortBranchName(config2.targetBranch);
50108
+ this.confirmedRoomTargetBranches.set(channelId, branch2);
50109
+ return branch2;
50110
+ }
49808
50111
  const config = await getRoomRepository(this.agentClientContext(), channelId);
49809
50112
  if (!config?.targetBranch)
49810
50113
  return confirmed ?? fallback;
@@ -49845,15 +50148,24 @@ Deliver artifacts from this corner; there is no branch to land.`, [
49845
50148
  void announceNoop;
49846
50149
  return false;
49847
50150
  }
49848
- await postControlMessage("target-branch-proposal", tlcChannelId, this.agentIdentity, targetBranchProposalText(from, branch), [
49849
- ["t", TARGET_BRANCH_PROPOSAL_TAG],
49850
- ["from", from],
49851
- ["to", branch],
49852
- ["repo", this.repoId(boundRepo)],
49853
- ["agent", this.agentIdentity.publicKey],
49854
- ["request", request.eventId],
49855
- ["requester", request.authorPubkey]
49856
- ]);
50151
+ if (this.daemonApi) {
50152
+ await this.daemonApi.execute("postTargetBranchProposal", {
50153
+ roomId: tlcChannelId,
50154
+ requestId: request.eventId,
50155
+ from,
50156
+ to: branch,
50157
+ repository: this.repoId(boundRepo)
50158
+ });
50159
+ } else
50160
+ await postControlMessage("target-branch-proposal", tlcChannelId, this.agentIdentity, targetBranchProposalText(from, branch), [
50161
+ ["t", TARGET_BRANCH_PROPOSAL_TAG],
50162
+ ["from", from],
50163
+ ["to", branch],
50164
+ ["repo", this.repoId(boundRepo)],
50165
+ ["agent", this.agentIdentity.publicKey],
50166
+ ["request", request.eventId],
50167
+ ["requester", request.authorPubkey]
50168
+ ]);
49857
50169
  return true;
49858
50170
  }
49859
50171
  agentClientContext() {
@@ -49868,6 +50180,13 @@ Deliver artifacts from this corner; there is no branch to land.`, [
49868
50180
  }
49869
50181
  /** Resolve the parent channel's optional community linkage. */
49870
50182
  async channelCommunityId(channelId) {
50183
+ if (this.daemonApi) {
50184
+ const authority = await this.daemonApi.execute("getRoomAuthority", {
50185
+ roomId: channelId,
50186
+ principalId: this.agentIdentity.publicKey
50187
+ });
50188
+ return authority.member ? authority.workspaceId : null;
50189
+ }
49871
50190
  const creates = await this.agentRelay.queryEvents([
49872
50191
  { kinds: [9007], "#h": [channelId], limit: 5 }
49873
50192
  ]);
@@ -50571,6 +50890,24 @@ import { basename as basename9, dirname as dirname11, isAbsolute as isAbsolute10
50571
50890
  import { spawn as spawn8, spawnSync as spawnSync2, execFile } from "node:child_process";
50572
50891
  import { promisify } from "node:util";
50573
50892
  var execFileAsync = promisify(execFile);
50893
+ function isMonolithTransport(value) {
50894
+ if (typeof value !== "object" || value === null)
50895
+ return false;
50896
+ const candidate = value;
50897
+ if (candidate.kind !== "monolith" || typeof candidate.baseUrl !== "string")
50898
+ return false;
50899
+ let origin;
50900
+ try {
50901
+ origin = new URL(candidate.baseUrl);
50902
+ } catch {
50903
+ return false;
50904
+ }
50905
+ if (origin.protocol !== "https:" && origin.protocol !== "http:" || origin.username || origin.password || origin.pathname && origin.pathname !== "/" || origin.search || origin.hash || origin.origin !== candidate.baseUrl)
50906
+ return false;
50907
+ const exchange = candidate.exchangeToken;
50908
+ const daemon = candidate.daemonToken;
50909
+ return typeof exchange === "string" && /^bde_[A-Za-z0-9_-]{43}$/.test(exchange) && daemon === void 0 || typeof daemon === "string" && /^bdt_[A-Za-z0-9_-]{43}$/.test(daemon) && exchange === void 0;
50910
+ }
50574
50911
  function runtimeAgentCommand(runtime) {
50575
50912
  const command = runtime.agentCommand ?? runtime.agentBinary;
50576
50913
  const inferredKind = command.endsWith("/buzz-agent") || command === "buzz-agent" ? "reference" : "custom";
@@ -50906,7 +51243,7 @@ async function readRuntimeRecord(path) {
50906
51243
  createdAt: parsed.createdAt
50907
51244
  };
50908
51245
  }
50909
- if (parsed.version !== 2 || !parsed.communityId || !parsed.supervisorRoot || !Array.isArray(parsed.rooms) || parsed.rooms.some((room) => !room.channelId || !room.repo?.root || room.root !== void 0 && (typeof room.root !== "string" || !room.root)) || parsed.agentKind !== void 0 && !AGENT_KINDS.includes(parsed.agentKind) || parsed.accessPolicy !== void 0 && !isAgentAccessPolicy(parsed.accessPolicy) || parsed.accessAllowlist !== void 0 && !isAgentAccessAllowlist(parsed.accessAllowlist) || parsed.accessPolicy === "allowlist" && !isAgentAccessAllowlist(parsed.accessAllowlist) || parsed.accessPolicy !== "allowlist" && parsed.accessAllowlist !== void 0 || parsed.accessAutoResponse !== void 0 && typeof parsed.accessAutoResponse !== "string" || parsed.externalMcpCapabilities !== void 0 && (!Array.isArray(parsed.externalMcpCapabilities) || parsed.externalMcpCapabilities.some((capability) => !isExternalMcpCapability(capability)) || parsed.accessPolicy !== "creator") || parsed.sandbox !== void 0 && !isSandboxPolicy(parsed.sandbox) || parsed.sandboxMaskPaths !== void 0 && (!Array.isArray(parsed.sandboxMaskPaths) || parsed.sandboxMaskPaths.some((path2) => typeof path2 !== "string" || !path2.trim())) || parsed.sharedSkills !== void 0 && (!Array.isArray(parsed.sharedSkills) || parsed.sharedSkills.some((name) => !isSharedSkillName(name)) || new Set(parsed.sharedSkills).size !== parsed.sharedSkills.length) || parsed.modelSelection !== void 0 && (typeof parsed.modelSelection !== "object" || parsed.modelSelection === null || parsed.modelSelection.model !== void 0 && typeof parsed.modelSelection.model !== "string" || parsed.modelSelection.effort !== void 0 && typeof parsed.modelSelection.effort !== "string") || parsed.agentCommand !== void 0 && !parsed.agentCommand || parsed.agentArgs !== void 0 && (!Array.isArray(parsed.agentArgs) || parsed.agentArgs.some((argument) => typeof argument !== "string"))) {
51246
+ if (parsed.version !== 2 || !parsed.communityId || !parsed.supervisorRoot || !Array.isArray(parsed.rooms) || parsed.rooms.some((room) => !room.channelId || !room.repo?.root || room.root !== void 0 && (typeof room.root !== "string" || !room.root)) || parsed.agentKind !== void 0 && !AGENT_KINDS.includes(parsed.agentKind) || parsed.accessPolicy !== void 0 && !isAgentAccessPolicy(parsed.accessPolicy) || parsed.accessAllowlist !== void 0 && !isAgentAccessAllowlist(parsed.accessAllowlist) || parsed.accessPolicy === "allowlist" && !isAgentAccessAllowlist(parsed.accessAllowlist) || parsed.accessPolicy !== "allowlist" && parsed.accessAllowlist !== void 0 || parsed.accessAutoResponse !== void 0 && typeof parsed.accessAutoResponse !== "string" || parsed.externalMcpCapabilities !== void 0 && (!Array.isArray(parsed.externalMcpCapabilities) || parsed.externalMcpCapabilities.some((capability) => !isExternalMcpCapability(capability)) || parsed.accessPolicy !== "creator") || parsed.sandbox !== void 0 && !isSandboxPolicy(parsed.sandbox) || parsed.sandboxMaskPaths !== void 0 && (!Array.isArray(parsed.sandboxMaskPaths) || parsed.sandboxMaskPaths.some((path2) => typeof path2 !== "string" || !path2.trim())) || parsed.sharedSkills !== void 0 && (!Array.isArray(parsed.sharedSkills) || parsed.sharedSkills.some((name) => !isSharedSkillName(name)) || new Set(parsed.sharedSkills).size !== parsed.sharedSkills.length) || parsed.modelSelection !== void 0 && (typeof parsed.modelSelection !== "object" || parsed.modelSelection === null || parsed.modelSelection.model !== void 0 && typeof parsed.modelSelection.model !== "string" || parsed.modelSelection.effort !== void 0 && typeof parsed.modelSelection.effort !== "string") || parsed.transport !== void 0 && !isMonolithTransport(parsed.transport) || parsed.agentCommand !== void 0 && !parsed.agentCommand || parsed.agentArgs !== void 0 && (!Array.isArray(parsed.agentArgs) || parsed.agentArgs.some((argument) => typeof argument !== "string"))) {
50910
51247
  throw new Error(`invalid agent runtime config: ${configPath}`);
50911
51248
  }
50912
51249
  runtimeIdentity(parsed.agent);
@@ -52832,6 +53169,7 @@ var RoomRuntimeCoordinator = class {
52832
53169
  * NIP-01 subId onto it, instead of opening ~N+1 sockets on one agent pubkey.
52833
53170
  */
52834
53171
  relaySocket;
53172
+ daemonApi;
52835
53173
  repositoryTruth;
52836
53174
  githubApp;
52837
53175
  namedRepositoryResolutions = /* @__PURE__ */ new Map();
@@ -52878,13 +53216,16 @@ var RoomRuntimeCoordinator = class {
52878
53216
  idleMs: Number(process.env.BUZZY_BODY_SESSION_IDLE_MS ?? String(5 * 6e4)),
52879
53217
  reserveInteractiveSlot: true
52880
53218
  });
52881
- this.relaySocket = options.relaySocket ?? new SharedRelaySocket({
52882
- baseUrl: runtime.relayBaseUrl,
52883
- ...runtime.relayHost ? { host: runtime.relayHost } : {},
52884
- ...baseConfig.relayWsUrl ? { wsUrl: baseConfig.relayWsUrl } : {},
52885
- identity: this.agent,
52886
- WebSocketImpl: wrapper_default
52887
- });
53219
+ this.daemonApi = options.daemonApi;
53220
+ if (!this.daemonApi) {
53221
+ this.relaySocket = options.relaySocket ?? new SharedRelaySocket({
53222
+ baseUrl: runtime.relayBaseUrl,
53223
+ ...runtime.relayHost ? { host: runtime.relayHost } : {},
53224
+ ...baseConfig.relayWsUrl ? { wsUrl: baseConfig.relayWsUrl } : {},
53225
+ identity: this.agent,
53226
+ WebSocketImpl: wrapper_default
53227
+ });
53228
+ }
52888
53229
  this.githubApp = GitHubAppRuntime.fromEnvironment(process.env, {
52889
53230
  baseUrl: runtime.relayBaseUrl,
52890
53231
  identity: this.agent
@@ -53046,6 +53387,8 @@ var RoomRuntimeCoordinator = class {
53046
53387
  await client.syncAgentDeclaration(this.runtime.communityId, { displayName });
53047
53388
  }
53048
53389
  async reconcile() {
53390
+ if (this.daemonApi)
53391
+ return this.reconcileMonolith();
53049
53392
  const client = createBuzzClient({
53050
53393
  baseUrl: this.runtime.relayBaseUrl,
53051
53394
  ...this.runtime.relayHost ? { host: this.runtime.relayHost } : {},
@@ -53227,6 +53570,45 @@ var RoomRuntimeCoordinator = class {
53227
53570
  client.disconnect();
53228
53571
  }
53229
53572
  }
53573
+ async reconcileMonolith() {
53574
+ const bootstrap = await this.daemonApi.execute("getDaemonBootstrap", {
53575
+ agentId: this.agent.publicKey
53576
+ });
53577
+ if (!bootstrap.workspaceIds.includes(this.runtime.communityId)) {
53578
+ this.workspaceRemovalConfirmations += 1;
53579
+ if (this.workspaceRemovalConfirmations < REMOVAL_CONFIRMATION_READS) {
53580
+ this.confirmationPending = true;
53581
+ return "unknown";
53582
+ }
53583
+ return "not-member";
53584
+ }
53585
+ this.workspaceRemovalConfirmations = 0;
53586
+ const desired = new Map(bootstrap.rooms.filter((room) => !room.archived).map((room) => [room.roomId, room]));
53587
+ for (const channelId of desired.keys())
53588
+ this.roomRemovalConfirmations.delete(channelId);
53589
+ for (const [channelId, running] of [...this.running]) {
53590
+ if (desired.has(channelId))
53591
+ continue;
53592
+ const confirmations = (this.roomRemovalConfirmations.get(channelId) ?? 0) + 1;
53593
+ this.roomRemovalConfirmations.set(channelId, confirmations);
53594
+ if (confirmations < REMOVAL_CONFIRMATION_READS) {
53595
+ this.confirmationPending = true;
53596
+ continue;
53597
+ }
53598
+ running.controller.abort();
53599
+ await running.promise.catch(() => void 0);
53600
+ }
53601
+ await mapWithConcurrency([...desired.keys()], ROOM_JOIN_CONCURRENCY, async (channelId) => {
53602
+ if (this.running.has(channelId))
53603
+ return;
53604
+ const known = this.runtime.rooms.find((room) => room.channelId === channelId);
53605
+ if (known)
53606
+ await this.startRepositoryRoom(known, channelId);
53607
+ else
53608
+ this.startConversationRoom(channelId, "named-repository");
53609
+ });
53610
+ return "member";
53611
+ }
53230
53612
  /**
53231
53613
  * Record the relay's terminal `channel is archived` verdict for one Room:
53232
53614
  * logged once, then the Room is held inert — dropped from serving for the
@@ -53333,7 +53715,8 @@ var RoomRuntimeCoordinator = class {
53333
53715
  };
53334
53716
  const body = new Body(config, runtimeIdentity(this.runtime.body), this.agent, {
53335
53717
  scheduler: this.scheduler,
53336
- relaySocket: this.relaySocket,
53718
+ ...this.relaySocket ? { relaySocket: this.relaySocket } : {},
53719
+ ...this.daemonApi ? { daemonApi: this.daemonApi } : {},
53337
53720
  statePath: resolve30(workspaceRoot, "body-state.json"),
53338
53721
  resolveNamedRepository: (target) => this.resolveNamedRepository(channelId, target),
53339
53722
  refreshRepositoryTruth: (repo, checkpoint) => this.refreshBoundRepo(repo, checkpoint),
@@ -53379,7 +53762,8 @@ var RoomRuntimeCoordinator = class {
53379
53762
  const startedAt = this.now();
53380
53763
  const body = new Body(config, runtimeIdentity(this.runtime.body), this.agent, {
53381
53764
  scheduler: this.scheduler,
53382
- relaySocket: this.relaySocket,
53765
+ ...this.relaySocket ? { relaySocket: this.relaySocket } : {},
53766
+ ...this.daemonApi ? { daemonApi: this.daemonApi } : {},
53383
53767
  statePath: resolve30(workspaceRoot, "body-state.json"),
53384
53768
  resolveNamedRepository: (target) => this.resolveNamedRepository(channelId, target),
53385
53769
  onRoomPollSuccess: () => this.notePoll(channelId),
@@ -54156,29 +54540,41 @@ async function waitForNextTick(ms, signal) {
54156
54540
  var ThinDaemonCore = class {
54157
54541
  agent;
54158
54542
  relaySocket;
54543
+ daemonApi;
54159
54544
  roomRuntime;
54160
54545
  workCalendar;
54161
54546
  now;
54162
54547
  constructor(runtime, configPath, baseConfig, options = {}) {
54163
54548
  this.agent = runtimeIdentity(runtime.agent);
54164
54549
  this.now = options.now ?? Date.now;
54165
- this.relaySocket = new SharedRelaySocket({
54166
- baseUrl: runtime.relayBaseUrl,
54167
- ...runtime.relayHost ? { host: runtime.relayHost } : {},
54168
- ...baseConfig.relayWsUrl ? { wsUrl: baseConfig.relayWsUrl } : {},
54169
- identity: this.agent,
54170
- WebSocketImpl: wrapper_default
54171
- });
54550
+ this.daemonApi = options.daemonApi;
54551
+ if (runtime.transport && !this.daemonApi) {
54552
+ throw new Error("monolith runtime requires an activated daemon API client");
54553
+ }
54554
+ if (!runtime.transport) {
54555
+ this.relaySocket = new SharedRelaySocket({
54556
+ baseUrl: runtime.relayBaseUrl,
54557
+ ...runtime.relayHost ? { host: runtime.relayHost } : {},
54558
+ ...baseConfig.relayWsUrl ? { wsUrl: baseConfig.relayWsUrl } : {},
54559
+ identity: this.agent,
54560
+ WebSocketImpl: wrapper_default
54561
+ });
54562
+ }
54172
54563
  this.roomRuntime = new RoomRuntimeCoordinator(runtime, configPath, baseConfig, {
54173
54564
  ...options,
54174
- relaySocket: this.relaySocket
54565
+ ...this.relaySocket ? { relaySocket: this.relaySocket } : {},
54566
+ ...this.daemonApi ? { daemonApi: this.daemonApi } : {}
54175
54567
  });
54176
- this.workCalendar = options.workCalendar ?? createDaemonWorkCalendar({
54568
+ this.workCalendar = options.workCalendar ?? (this.daemonApi ? {
54569
+ start: async () => void 0,
54570
+ dispose: async () => void 0,
54571
+ refreshNow: async () => void 0
54572
+ } : createDaemonWorkCalendar({
54177
54573
  runtime,
54178
54574
  configPath,
54179
54575
  roomRuntime: this.roomRuntime,
54180
54576
  nowMs: this.now
54181
- });
54577
+ }));
54182
54578
  if (this.workCalendar.runNow) {
54183
54579
  this.roomRuntime.setScheduleRunNow((scheduleId) => this.workCalendar.runNow(scheduleId));
54184
54580
  }
@@ -54215,20 +54611,24 @@ var ThinDaemonCore = class {
54215
54611
  let calendarState = "idle";
54216
54612
  await opts.onEstablished?.();
54217
54613
  try {
54218
- const client = await this.relaySocket.connected();
54219
- const socket = client.socket;
54220
- if (!socket)
54221
- throw new Error("control-plane WS connected but exposed no socket");
54222
- unsubscribeControl = socket.subscribe([
54223
- {
54224
- kinds: [KIND_PUT_USER, KIND_REMOVE_USER],
54225
- "#p": [this.agent.publicKey],
54226
- since: Math.floor(this.now() / 1e3)
54227
- }
54228
- ], () => {
54229
- wake = true;
54230
- });
54231
- degraded = "";
54614
+ if (!this.relaySocket) {
54615
+ degraded = "";
54616
+ } else {
54617
+ const client = await this.relaySocket.connected();
54618
+ const socket = client.socket;
54619
+ if (!socket)
54620
+ throw new Error("control-plane WS connected but exposed no socket");
54621
+ unsubscribeControl = socket.subscribe([
54622
+ {
54623
+ kinds: [KIND_PUT_USER, KIND_REMOVE_USER],
54624
+ "#p": [this.agent.publicKey],
54625
+ since: Math.floor(this.now() / 1e3)
54626
+ }
54627
+ ], () => {
54628
+ wake = true;
54629
+ });
54630
+ degraded = "";
54631
+ }
54232
54632
  } catch (error) {
54233
54633
  degraded = `relay control socket degraded: ${error instanceof Error ? error.message : String(error)}`;
54234
54634
  console.error(`[thin-core] control-plane WS unavailable; relying on the ${this.roomRuntime.reconcileHeartbeatIntervalMs()}ms heartbeat poll:`, error);
@@ -54271,11 +54671,106 @@ var ThinDaemonCore = class {
54271
54671
  unsubscribeControl?.();
54272
54672
  await this.workCalendar.dispose();
54273
54673
  await this.roomRuntime.shutdown();
54274
- this.relaySocket.disconnect();
54674
+ this.relaySocket?.disconnect();
54275
54675
  }
54276
54676
  }
54277
54677
  };
54278
54678
 
54679
+ // apps/body/dist/daemon-api-client.js
54680
+ import { resolve as resolve32 } from "node:path";
54681
+ var DaemonApiError = class extends Error {
54682
+ status;
54683
+ retryable;
54684
+ constructor(message2, status, retryable) {
54685
+ super(message2);
54686
+ this.status = status;
54687
+ this.retryable = retryable;
54688
+ this.name = "DaemonApiError";
54689
+ }
54690
+ };
54691
+ function endpoint(origin, path) {
54692
+ return new URL(path, `${origin}/`).toString();
54693
+ }
54694
+ async function responseError(response) {
54695
+ let code = "request_failed";
54696
+ try {
54697
+ const value = await response.json();
54698
+ if (typeof value.error === "string" && value.error)
54699
+ code = value.error;
54700
+ } catch {
54701
+ }
54702
+ return new DaemonApiError(`monolith daemon request failed (${response.status}: ${code})`, response.status, response.status === 408 || response.status === 429 || response.status >= 500);
54703
+ }
54704
+ var DaemonApiClient = class {
54705
+ baseUrl;
54706
+ daemonToken;
54707
+ agentId;
54708
+ fetchImpl;
54709
+ constructor(baseUrl, daemonToken, agentId, fetchImpl = fetch) {
54710
+ this.baseUrl = baseUrl;
54711
+ this.daemonToken = daemonToken;
54712
+ this.agentId = agentId;
54713
+ this.fetchImpl = fetchImpl;
54714
+ }
54715
+ async execute(name, input) {
54716
+ const candidate = input;
54717
+ if (typeof candidate.agentId === "string" && candidate.agentId !== this.agentId) {
54718
+ throw new Error("daemon operation agentId does not match the runtime identity");
54719
+ }
54720
+ const response = await this.fetchImpl(endpoint(this.baseUrl, `/v1/daemon/operations/${String(name)}`), {
54721
+ method: "POST",
54722
+ headers: {
54723
+ authorization: `Bearer ${this.daemonToken}`,
54724
+ "content-type": "application/json"
54725
+ },
54726
+ body: JSON.stringify(input)
54727
+ });
54728
+ if (!response.ok)
54729
+ throw await responseError(response);
54730
+ return await response.json();
54731
+ }
54732
+ };
54733
+ async function activateDaemonTransport(path, fetchImpl = fetch) {
54734
+ const runtime = await readRuntimeRecord(path);
54735
+ const expectedPath = resolve32(runtimeDirectory(runtime.supervisorRoot, runtime.agent.publicKey), "runtime.json");
54736
+ if (resolve32(path) !== expectedPath) {
54737
+ throw new Error(`refusing daemon token exchange outside canonical runtime path: ${path}`);
54738
+ }
54739
+ const transport = runtime.transport;
54740
+ if (!transport)
54741
+ return void 0;
54742
+ if ("daemonToken" in transport && transport.daemonToken) {
54743
+ return {
54744
+ runtime,
54745
+ client: new DaemonApiClient(transport.baseUrl, transport.daemonToken, runtime.agent.publicKey, fetchImpl)
54746
+ };
54747
+ }
54748
+ const response = await fetchImpl(endpoint(transport.baseUrl, "/v1/auth/daemon/exchange"), {
54749
+ method: "POST",
54750
+ headers: { "content-type": "application/json" },
54751
+ body: JSON.stringify({ exchangeToken: transport.exchangeToken })
54752
+ });
54753
+ if (!response.ok)
54754
+ throw await responseError(response);
54755
+ const result = await response.json();
54756
+ if (typeof result.daemonToken !== "string" || !/^bdt_[A-Za-z0-9_-]{43}$/.test(result.daemonToken) || result.agentId !== runtime.agent.publicKey) {
54757
+ throw new Error("daemon token exchange returned an invalid runtime identity");
54758
+ }
54759
+ const promoted = {
54760
+ ...runtime,
54761
+ transport: {
54762
+ kind: "monolith",
54763
+ baseUrl: transport.baseUrl,
54764
+ daemonToken: result.daemonToken
54765
+ }
54766
+ };
54767
+ await writeRuntimeRecord(promoted);
54768
+ return {
54769
+ runtime: promoted,
54770
+ client: new DaemonApiClient(transport.baseUrl, result.daemonToken, runtime.agent.publicKey, fetchImpl)
54771
+ };
54772
+ }
54773
+
54279
54774
  // apps/body/dist/relay-command.js
54280
54775
  var defaults = {
54281
54776
  cwd: () => process.cwd(),
@@ -54356,7 +54851,7 @@ var import_picocolors2 = __toESM(require_picocolors(), 1);
54356
54851
  import { execFile as execFile2 } from "node:child_process";
54357
54852
  import { mkdir as mkdir15, readFile as readFile11, writeFile as writeFile9 } from "node:fs/promises";
54358
54853
  import { homedir as homedir7 } from "node:os";
54359
- import { dirname as dirname13, resolve as resolve32 } from "node:path";
54854
+ import { dirname as dirname13, resolve as resolve33 } from "node:path";
54360
54855
  import { setTimeout as sleep3 } from "node:timers/promises";
54361
54856
  import { promisify as promisify3 } from "node:util";
54362
54857
  var execFileAsync2 = promisify3(execFile2);
@@ -54398,9 +54893,9 @@ WantedBy=default.target
54398
54893
  }
54399
54894
  function isCanonicalInstalledLauncher(env = process.env, invocationPath = process.argv[1]) {
54400
54895
  const home = env.HOME?.trim() || homedir7();
54401
- const expectedLibDir = resolve32(home, ".local", "lib", "beeline");
54896
+ const expectedLibDir = resolve33(home, ".local", "lib", "beeline");
54402
54897
  const expectedPrefix = `${expectedLibDir}/`;
54403
- return resolve32(env.BEELINE_LIB_DIR?.trim() || "/") === expectedLibDir && Boolean(invocationPath) && resolve32(invocationPath).startsWith(expectedPrefix);
54898
+ return resolve33(env.BEELINE_LIB_DIR?.trim() || "/") === expectedLibDir && Boolean(invocationPath) && resolve33(invocationPath).startsWith(expectedPrefix);
54404
54899
  }
54405
54900
  function assertCanonicalInstalledLauncher(env, invocationPath) {
54406
54901
  if (isCanonicalInstalledLauncher(env, invocationPath))
@@ -54408,8 +54903,8 @@ function assertCanonicalInstalledLauncher(env, invocationPath) {
54408
54903
  throw new Error("refusing to modify the shared Beeline systemd unit outside the canonical ~/.local/bin/beeline launcher");
54409
54904
  }
54410
54905
  function systemdUserUnitPath(env = process.env) {
54411
- const configRoot = env.XDG_CONFIG_HOME?.trim() || resolve32(homedir7(), ".config");
54412
- return resolve32(configRoot, "systemd", "user", SYSTEMD_UNIT_NAME);
54906
+ const configRoot = env.XDG_CONFIG_HOME?.trim() || resolve33(homedir7(), ".config");
54907
+ return resolve33(configRoot, "systemd", "user", SYSTEMD_UNIT_NAME);
54413
54908
  }
54414
54909
  var runSystemctl = async (args) => {
54415
54910
  const result = await execFileAsync2("systemctl", ["--user", ...args], {
@@ -54583,7 +55078,7 @@ async function runStartCommand(args, interactiveUi) {
54583
55078
  // apps/body/dist/pair-command.js
54584
55079
  import { existsSync as existsSync15 } from "node:fs";
54585
55080
  import { homedir as homedir9 } from "node:os";
54586
- import { resolve as resolve34 } from "node:path";
55081
+ import { resolve as resolve35 } from "node:path";
54587
55082
  import { stdin as stdin3, stdout as stdout4 } from "node:process";
54588
55083
  var import_picocolors3 = __toESM(require_picocolors(), 1);
54589
55084
 
@@ -54856,7 +55351,7 @@ import { spawn as spawn10 } from "node:child_process";
54856
55351
  import { constants as constants4 } from "node:fs";
54857
55352
  import { access, chmod as chmod5, mkdir as mkdir16, writeFile as writeFile10 } from "node:fs/promises";
54858
55353
  import { homedir as homedir8 } from "node:os";
54859
- import { resolve as resolve33 } from "node:path";
55354
+ import { resolve as resolve34 } from "node:path";
54860
55355
  var CONNECT_TIMEOUT_MS = 30 * 6e4;
54861
55356
  var TRUSTY_SQUIRE_SKILL = `---
54862
55357
  name: trusty-squire
@@ -54932,7 +55427,7 @@ async function ensureSkillAt(path) {
54932
55427
  return path;
54933
55428
  } catch {
54934
55429
  }
54935
- await mkdir16(resolve33(path, ".."), { recursive: true, mode: 448 });
55430
+ await mkdir16(resolve34(path, ".."), { recursive: true, mode: 448 });
54936
55431
  try {
54937
55432
  await writeFile10(path, TRUSTY_SQUIRE_SKILL, { mode: 384, flag: "wx" });
54938
55433
  } catch (error) {
@@ -54943,11 +55438,11 @@ async function ensureSkillAt(path) {
54943
55438
  return path;
54944
55439
  }
54945
55440
  async function ensureTrustySquireSkill(operatorHome = homedir8()) {
54946
- return ensureSkillAt(resolve33(operatorHome, ".agents", "skills", "trusty-squire", "SKILL.md"));
55441
+ return ensureSkillAt(resolve34(operatorHome, ".agents", "skills", "trusty-squire", "SKILL.md"));
54947
55442
  }
54948
55443
  async function ensureHarnessSkill(kind, operatorHome) {
54949
55444
  const harnessDir = kind === "codex" ? ".codex" : ".claude";
54950
- return ensureSkillAt(resolve33(operatorHome, harnessDir, "skills", "trusty-squire", "SKILL.md"));
55445
+ return ensureSkillAt(resolve34(operatorHome, harnessDir, "skills", "trusty-squire", "SKILL.md"));
54951
55446
  }
54952
55447
  async function connectTrustySquireForPair(input) {
54953
55448
  const target = assertTrustySquireConnectSupported(input.agentKind);
@@ -55102,7 +55597,7 @@ function resolvePairRepository(repoFlag) {
55102
55597
  if (!repoFlag) {
55103
55598
  return { cwd: process.cwd(), repo: null };
55104
55599
  }
55105
- const resolved = resolve34(repoFlag);
55600
+ const resolved = resolve35(repoFlag);
55106
55601
  if (!existsSync15(resolved)) {
55107
55602
  throw new Error(`--repo path does not exist: ${resolved}`);
55108
55603
  }
@@ -55364,7 +55859,7 @@ async function runPairCommand(args, llmEnvFile, agentPrivateKey) {
55364
55859
  import { spawn as spawn12 } from "node:child_process";
55365
55860
  import { createHash as createHash15, randomBytes as randomBytes7 } from "node:crypto";
55366
55861
  import { chmod as chmod7, mkdir as mkdir18, readFile as readFile13, unlink as unlink5, writeFile as writeFile12 } from "node:fs/promises";
55367
- import { dirname as dirname16, resolve as resolve36 } from "node:path";
55862
+ import { dirname as dirname16, resolve as resolve37 } from "node:path";
55368
55863
  import { stdin as stdin4, stdout as stdout5 } from "node:process";
55369
55864
  init_self_update();
55370
55865
  init_self_update_manifest();
@@ -55409,6 +55904,10 @@ var clackPrompts = {
55409
55904
  clackPromptOutput();
55410
55905
  return unwrapPrompt(await select(input), "Connection cancelled.");
55411
55906
  },
55907
+ async autocomplete(input) {
55908
+ clackPromptOutput();
55909
+ return unwrapPrompt(await autocomplete({ ...input, output: clackPromptOutput() }), "Connection cancelled.");
55910
+ },
55412
55911
  async text(input) {
55413
55912
  clackPromptOutput();
55414
55913
  return unwrapPrompt(await text({
@@ -55424,7 +55923,21 @@ var clackPrompts = {
55424
55923
  }), "Connection cancelled.");
55425
55924
  }
55426
55925
  };
55427
- async function collectConnectWizard(prompts = clackPrompts) {
55926
+ async function loadConnectModelCatalog(input) {
55927
+ const agent = resolveAgentCommand({ kind: input.harness });
55928
+ const catalog = await fetchAgentModelCatalog(agent, providerEnvironment({
55929
+ harness: input.harness,
55930
+ ...input.provider ? { provider: input.provider } : {},
55931
+ ...input.apiKey ? { apiKey: input.apiKey } : {},
55932
+ model: defaultConnectModel(input.harness, input.provider)
55933
+ }));
55934
+ const modelAxis = catalog.catalog.find((axis) => axis.category === "model");
55935
+ if (!modelAxis?.options.length) {
55936
+ throw new Error(`${input.harness} did not advertise any available models`);
55937
+ }
55938
+ return { currentValue: modelAxis.currentValue, options: modelAxis.options };
55939
+ }
55940
+ async function collectConnectWizard(prompts = clackPrompts, loadModels = loadConnectModelCatalog) {
55428
55941
  const harness = await prompts.select({
55429
55942
  message: brass("Choose harness"),
55430
55943
  options: CONNECT_HARNESSES.map((value) => ({
@@ -55449,16 +55962,36 @@ async function collectConnectWizard(prompts = clackPrompts) {
55449
55962
  validate: (value) => value.trim() ? void 0 : "API key is required"
55450
55963
  });
55451
55964
  }
55452
- const model = await prompts.text({
55965
+ const catalog = await loadModels({
55966
+ harness,
55967
+ ...provider ? { provider } : {},
55968
+ ...apiKey ? { apiKey: apiKey.trim() } : {}
55969
+ });
55970
+ const initialModel = catalog.currentValue ?? defaultConnectModel(harness, provider);
55971
+ const model = await prompts.autocomplete({
55453
55972
  message: brass("Choose model"),
55454
- initialValue: defaultConnectModel(harness, provider),
55455
- validate: (value) => value.trim() ? void 0 : "Model is required"
55973
+ options: catalog.options.map((choice) => ({
55974
+ value: choice.id,
55975
+ label: choice.name ? `${choice.name} (${choice.id})` : choice.id
55976
+ })),
55977
+ ...catalog.options.some((choice) => choice.id === initialModel) ? { initialValue: initialModel } : {},
55978
+ placeholder: "Type to filter available models\u2026",
55979
+ maxItems: 12
55980
+ });
55981
+ const name = await prompts.text({
55982
+ message: brass("Agent name"),
55983
+ validate: (value) => {
55984
+ if (!value.trim())
55985
+ return "Agent name is required";
55986
+ return isReasonableAgentName(value) ? void 0 : `Use letters, spaces, hyphens, or apostrophes (${AGENT_NAME_MAX_LENGTH} characters max)`;
55987
+ }
55456
55988
  });
55457
55989
  const soul = await prompts.text({
55458
55990
  message: brass("Input soul"),
55459
55991
  validate: (value) => value.trim() ? void 0 : "Soul is required"
55460
55992
  });
55461
55993
  return {
55994
+ name: name.trim().replace(/\s+/g, " "),
55462
55995
  harness,
55463
55996
  ...provider ? { provider } : {},
55464
55997
  ...apiKey ? { apiKey: apiKey.trim() } : {},
@@ -55531,7 +56064,7 @@ async function installCurrentRelease(fetchImpl) {
55531
56064
  }
55532
56065
  });
55533
56066
  await activateRelease(layout, releaseId);
55534
- return resolve36(layout.binDir, "beeline");
56067
+ return resolve37(layout.binDir, "beeline");
55535
56068
  }
55536
56069
  function providerEnvironment(selection) {
55537
56070
  if (!selection.provider || !selection.apiKey)
@@ -55561,7 +56094,7 @@ async function writeProviderEnv(selection, agentPubkey) {
55561
56094
  const values = providerEnvironment(selection);
55562
56095
  if (Object.keys(values).length === 0)
55563
56096
  return void 0;
55564
- const path = resolve36(defaultSupervisorRoot(process.env), "beeline", "connect", `${agentPubkey}.env`);
56097
+ const path = resolve37(defaultSupervisorRoot(process.env), "beeline", "connect", `${agentPubkey}.env`);
55565
56098
  await mkdir18(dirname16(path), { recursive: true, mode: 448 });
55566
56099
  const contents = Object.entries(values).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join("\n");
55567
56100
  await writeFile12(path, `${contents}
@@ -55610,13 +56143,14 @@ async function runConnectCommand(options = {}) {
55610
56143
  intro(brass("Beeline connect"));
55611
56144
  const selection = await collectConnectWizard();
55612
56145
  const fetchImpl = options.fetchImpl ?? fetch;
55613
- const baseUrl = (process.env.BEELINE_AUTH_URL ?? "https://usebeeline.app").replace(/\/$/, "");
56146
+ const baseUrl = (process.env.BEELINE_AUTH_URL ?? "https://server.usebeeline.app").replace(/\/$/, "");
55614
56147
  const verifier = randomBytes7(32).toString("base64url");
55615
- const start = await brassSpinner("Preparing secure browser approval\u2026", () => jsonRequest(`${baseUrl}/auth/device/connect`, {
56148
+ const start = await brassSpinner("Preparing secure sign-in\u2026", () => jsonRequest(`${baseUrl}/auth/device/connect`, {
55616
56149
  harness: selection.harness,
55617
56150
  ...selection.provider ? { provider: selection.provider } : {},
55618
56151
  model: selection.model,
55619
56152
  soul: selection.soul,
56153
+ agent_name: selection.name,
55620
56154
  code_challenge: sha2564(verifier)
55621
56155
  }, fetchImpl));
55622
56156
  try {
@@ -55624,10 +56158,10 @@ async function runConnectCommand(options = {}) {
55624
56158
  } catch {
55625
56159
  console.log(`Open this link to connect: ${start.verification_uri_complete}`);
55626
56160
  }
55627
- const grant = await brassSpinner("Waiting for browser approval\u2026", () => pollDeviceGrant({ baseUrl, start, verifier, fetchImpl }));
56161
+ const grant = await brassSpinner("Connecting to your Beeline Workspace\u2026", () => pollDeviceGrant({ baseUrl, start, verifier, fetchImpl }));
55628
56162
  const installedBinary = await brassSpinner("Installing the Beeline daemon\u2026", () => installCurrentRelease(fetchImpl));
55629
56163
  const llmEnvFile = await writeProviderEnv(selection, grant.agent_pubkey);
55630
- const grantPath = resolve36(defaultSupervisorRoot(process.env), "beeline", "connect", `grant-${process.pid}-${Date.now()}.json`);
56164
+ const grantPath = resolve37(defaultSupervisorRoot(process.env), "beeline", "connect", `grant-${process.pid}-${Date.now()}.json`);
55631
56165
  await writePrivateJson(grantPath, {
55632
56166
  pairingCode: grant.pairing_code,
55633
56167
  agentSecretKey: grant.agent_secret_key,
@@ -55658,11 +56192,11 @@ async function runConnectFinishCommand(path) {
55658
56192
  if (!isCanonicalInstalledLauncher(process.env, process.argv[1])) {
55659
56193
  throw new Error("connect-finish may run only from the canonical installed Beeline launcher");
55660
56194
  }
55661
- const grant = JSON.parse(await readFile13(resolve36(path), "utf8"));
56195
+ const grant = JSON.parse(await readFile13(resolve37(path), "utf8"));
55662
56196
  if (!isDevicePairingGrant(grant))
55663
56197
  throw new Error("device connection grant is invalid");
55664
56198
  await completeDevicePairing(grant);
55665
- await unlink5(resolve36(path));
56199
+ await unlink5(resolve37(path));
55666
56200
  }
55667
56201
 
55668
56202
  // apps/body/dist/mission-scaffold-command.js
@@ -55670,7 +56204,7 @@ var import_picocolors4 = __toESM(require_picocolors(), 1);
55670
56204
 
55671
56205
  // apps/body/dist/mission-scaffold.js
55672
56206
  import { readdir as readdir7, writeFile as writeFile13 } from "node:fs/promises";
55673
- import { isAbsolute as isAbsolute11, join as join3, relative as relative8, resolve as resolve37 } from "node:path";
56207
+ import { isAbsolute as isAbsolute11, join as join3, relative as relative8, resolve as resolve38 } from "node:path";
55674
56208
  var DEFAULT_MISSION_NAME = "Mission";
55675
56209
  var UNKNOWN = "(capture during the bootstrap interview)";
55676
56210
  function line(value, fallback = UNKNOWN) {
@@ -55787,7 +56321,7 @@ function orgChartMarkdown(input) {
55787
56321
  `;
55788
56322
  }
55789
56323
  async function planMissionScaffold(dir, input = {}) {
55790
- const root = resolve37(dir);
56324
+ const root = resolve38(dir);
55791
56325
  let existing;
55792
56326
  try {
55793
56327
  existing = new Set(await readdir7(root));
@@ -55884,13 +56418,13 @@ init_self_update_manifest();
55884
56418
  init_self_update();
55885
56419
  import { spawn as spawn13 } from "node:child_process";
55886
56420
  import { mkdir as mkdir20, rm as rm10, stat as stat4, writeFile as writeFile15 } from "node:fs/promises";
55887
- import { dirname as dirname18, resolve as resolve39 } from "node:path";
56421
+ import { dirname as dirname18, resolve as resolve40 } from "node:path";
55888
56422
 
55889
56423
  // apps/body/dist/update-rollback-alert.js
55890
56424
  import { mkdir as mkdir19, readFile as readFile14, rename as rename8, writeFile as writeFile14 } from "node:fs/promises";
55891
- import { dirname as dirname17, resolve as resolve38 } from "node:path";
56425
+ import { dirname as dirname17, resolve as resolve39 } from "node:path";
55892
56426
  function updateRollbackAlertPath(runtimeDir) {
55893
- return resolve38(runtimeDir, "update-rollback-alert.json");
56427
+ return resolve39(runtimeDir, "update-rollback-alert.json");
55894
56428
  }
55895
56429
  async function writeAlert(runtimeDir, alert) {
55896
56430
  const path = updateRollbackAlertPath(runtimeDir);
@@ -55933,13 +56467,13 @@ var LOCK_STALE_MS = UPDATE_WORKER_DEADLINE_MS + 5 * 6e4;
55933
56467
  var DEFAULT_UPDATE_INITIAL_DELAY_MS = 0;
55934
56468
  async function withInstallLock(layout, work, options = {}) {
55935
56469
  const now7 = options.now ?? Date.now;
55936
- const lock = resolve39(layout.releasesRoot, ".state", "install.lock");
56470
+ const lock = resolve40(layout.releasesRoot, ".state", "install.lock");
55937
56471
  const deadline = now7() + (options.waitMs ?? 1e4);
55938
56472
  await mkdir20(dirname18(lock), { recursive: true });
55939
56473
  for (; ; ) {
55940
56474
  try {
55941
56475
  await mkdir20(lock);
55942
- await writeFile15(resolve39(lock, "owner"), `${process.pid}
56476
+ await writeFile15(resolve40(lock, "owner"), `${process.pid}
55943
56477
  ${now7()}
55944
56478
  `, "utf8");
55945
56479
  break;
@@ -56047,7 +56581,7 @@ var ManagedUpdateHandoff = class _ManagedUpdateHandoff {
56047
56581
  if (!attempt || attempt.releaseId !== desiredRelease || attempt.status !== "pending") {
56048
56582
  const from = await readInstalledBundleIdentity({
56049
56583
  ...this.#layout,
56050
- libDir: resolve39(this.#layout.releasesRoot, this.#loadedRelease)
56584
+ libDir: resolve40(this.#layout.releasesRoot, this.#loadedRelease)
56051
56585
  }).catch(() => void 0) ?? {};
56052
56586
  const to = await readInstalledBundleIdentity(this.#layout).catch(() => void 0) ?? {};
56053
56587
  const record2 = {
@@ -56231,7 +56765,7 @@ async function proveLoadedReleaseReady(layout, runtimeDir, loadedRelease, option
56231
56765
  });
56232
56766
  if (!accepted)
56233
56767
  return false;
56234
- await writeFile15(resolve39(runtimeDir, "daemon-ready.json"), `${JSON.stringify({
56768
+ await writeFile15(resolve40(runtimeDir, "daemon-ready.json"), `${JSON.stringify({
56235
56769
  readyAt: (options.now ?? Date.now)(),
56236
56770
  loadedRelease,
56237
56771
  functionalProof: options.functionalProof
@@ -56437,11 +56971,11 @@ init_self_update();
56437
56971
 
56438
56972
  // apps/body/dist/daemon-failure.js
56439
56973
  import { mkdir as mkdir21, readFile as readFile15, rename as rename9, rm as rm11, writeFile as writeFile16 } from "node:fs/promises";
56440
- import { dirname as dirname19, resolve as resolve40 } from "node:path";
56974
+ import { dirname as dirname19, resolve as resolve41 } from "node:path";
56441
56975
  var DAEMON_FAILURE_LIMIT = 3;
56442
56976
  var DAEMON_FAILURE_WINDOW_MS = 5 * 6e4;
56443
56977
  function daemonFailurePath(runtimeDir) {
56444
- return resolve40(runtimeDir, "daemon-distress.json");
56978
+ return resolve41(runtimeDir, "daemon-distress.json");
56445
56979
  }
56446
56980
  async function readFailureRecord(runtimeDir) {
56447
56981
  try {
@@ -56482,7 +57016,7 @@ async function clearDaemonStartFailures(runtimeDir) {
56482
57016
  // apps/body/dist/update-functional-probe.js
56483
57017
  import { mkdir as mkdir22, rm as rm12 } from "node:fs/promises";
56484
57018
  import { homedir as homedir11 } from "node:os";
56485
- import { resolve as resolve41 } from "node:path";
57019
+ import { resolve as resolve42 } from "node:path";
56486
57020
  var UPDATE_PROBE_SESSION_TIMEOUT_MS = 1e4;
56487
57021
  var UPDATE_PROBE_SESSION_OPEN_TIMEOUT_MS = 2e4;
56488
57022
  var UPDATE_PROBE_TURN_TIMEOUT_MS = 45e3;
@@ -56504,9 +57038,9 @@ async function runUpdateFunctionalProbe(input) {
56504
57038
  if (input.sandboxRequired && !input.config.bwrapPath) {
56505
57039
  throw new UpdateFunctionalProbeError("sandbox-unavailable", "the configured bubblewrap boundary did not pass its startup self-test");
56506
57040
  }
56507
- const root = resolve41(input.runtimeDir, "update-functional-probe");
56508
- const cwd = resolve41(root, "checkout");
56509
- const homeRoot = resolve41(root, "agent-home");
57041
+ const root = resolve42(input.runtimeDir, "update-functional-probe");
57042
+ const cwd = resolve42(root, "checkout");
57043
+ const homeRoot = resolve42(root, "agent-home");
56510
57044
  await rm12(root, { recursive: true, force: true });
56511
57045
  await mkdir22(cwd, { recursive: true, mode: 448 });
56512
57046
  const calls = [];
@@ -56629,7 +57163,7 @@ async function runUpdateFunctionalProbe(input) {
56629
57163
 
56630
57164
  // apps/body/dist/release-status.js
56631
57165
  import { readFile as readFile16, readdir as readdir8, rename as rename10, writeFile as writeFile17 } from "node:fs/promises";
56632
- import { resolve as resolve42 } from "node:path";
57166
+ import { resolve as resolve43 } from "node:path";
56633
57167
  var DAEMON_RELEASE_STATUS_FILE = "release-status.json";
56634
57168
  var RELEASE_VERSION = /^v\d+\.\d+\.\d+$/;
56635
57169
  var SOURCE_SHA = /^[0-9a-f]{7,64}$/;
@@ -56646,7 +57180,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity2, opti
56646
57180
  pid: options.pid ?? process.pid,
56647
57181
  readyAt: (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString()
56648
57182
  };
56649
- const target = resolve42(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
57183
+ const target = resolve43(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
56650
57184
  const temporary = `${target}.${status.pid}.tmp`;
56651
57185
  await writeFile17(temporary, `${JSON.stringify(status, null, 2)}
56652
57186
  `, { mode: 384 });
@@ -56808,11 +57342,19 @@ async function runStoredDaemon(pathOrPointer) {
56808
57342
  const configPath = await resolveRuntimeConfigPath(pathOrPointer);
56809
57343
  daemonFailureRuntimeDir = dirname20(configPath);
56810
57344
  const accessMigration = await migrateRuntimeRecordAccessPolicy(configPath);
56811
- const { runtime } = await migrateLegacyRepositoryPaths(accessMigration.runtime, {
57345
+ let { runtime } = await migrateLegacyRepositoryPaths(accessMigration.runtime, {
56812
57346
  log: console.log
56813
57347
  });
57348
+ let daemonApi;
57349
+ if (runtime.transport) {
57350
+ const activated = await activateDaemonTransport(configPath);
57351
+ if (!activated)
57352
+ throw new Error("monolith daemon transport activation failed");
57353
+ runtime = activated.runtime;
57354
+ daemonApi = activated.client;
57355
+ }
56814
57356
  const agent = runtimeAgentCommand(runtime);
56815
- await writeFile18(resolve43(dirname20(configPath), "daemon.pid"), `${process.pid}
57357
+ await writeFile18(resolve44(dirname20(configPath), "daemon.pid"), `${process.pid}
56816
57358
  `, { mode: 384 });
56817
57359
  const env = {
56818
57360
  ...process.env,
@@ -56822,7 +57364,7 @@ async function runStoredDaemon(pathOrPointer) {
56822
57364
  ...runtime.relayHost ? { BUZZY_RELAY_HOST: runtime.relayHost } : {}
56823
57365
  };
56824
57366
  const config = loadBodyConfig({
56825
- workspaceRoot: resolve43(dirname20(configPath), "workspace"),
57367
+ workspaceRoot: resolve44(dirname20(configPath), "workspace"),
56826
57368
  llmEnvFile: runtime.llmEnvFile,
56827
57369
  env,
56828
57370
  agent
@@ -56902,7 +57444,9 @@ async function runStoredDaemon(pathOrPointer) {
56902
57444
  let ready = false;
56903
57445
  let stoppingStatus = "daemon stopped";
56904
57446
  try {
56905
- const core = new ThinDaemonCore(runtime, configPath, config);
57447
+ const core = new ThinDaemonCore(runtime, configPath, config, {
57448
+ ...daemonApi ? { daemonApi } : {}
57449
+ });
56906
57450
  const result = await core.run({
56907
57451
  signal: controller.signal,
56908
57452
  onEstablished: async () => {
@@ -56969,7 +57513,7 @@ async function runStoredDaemon(pathOrPointer) {
56969
57513
  throw error;
56970
57514
  } finally {
56971
57515
  await notifier.stopping(stoppingStatus).catch(() => void 0);
56972
- const pidPath = resolve43(dirname20(configPath), "daemon.pid");
57516
+ const pidPath = resolve44(dirname20(configPath), "daemon.pid");
56973
57517
  const recorded = Number((await readFile17(pidPath, "utf8").catch(() => "")).trim());
56974
57518
  if (recorded === process.pid) {
56975
57519
  await unlink6(pidPath).catch(() => void 0);
@@ -56980,13 +57524,13 @@ async function runtimeSpendStatePaths(configPath, runtime) {
56980
57524
  const paths = /* @__PURE__ */ new Set();
56981
57525
  const runtimeRoot = dirname20(configPath);
56982
57526
  for (const room of runtime.rooms) {
56983
- paths.add(resolve43(room.root ?? resolve43(runtimeRoot, "rooms", room.channelId), "body-state.json"));
57527
+ paths.add(resolve44(room.root ?? resolve44(runtimeRoot, "rooms", room.channelId), "body-state.json"));
56984
57528
  }
56985
- const roomsRoot = resolve43(runtimeRoot, "rooms");
57529
+ const roomsRoot = resolve44(runtimeRoot, "rooms");
56986
57530
  const entries = await readdir9(roomsRoot, { withFileTypes: true }).catch(() => []);
56987
57531
  for (const entry of entries) {
56988
57532
  if (entry.isDirectory())
56989
- paths.add(resolve43(roomsRoot, entry.name, "body-state.json"));
57533
+ paths.add(resolve44(roomsRoot, entry.name, "body-state.json"));
56990
57534
  }
56991
57535
  return [...paths];
56992
57536
  }
@@ -57089,7 +57633,7 @@ async function main2() {
57089
57633
  }
57090
57634
  if (!configPath)
57091
57635
  throw new Error("daemon requires --config <runtime.json> or --agent <pubkey>");
57092
- await runStoredDaemon(resolve43(configPath));
57636
+ await runStoredDaemon(resolve44(configPath));
57093
57637
  return;
57094
57638
  }
57095
57639
  if (command === "update") {