usebeeline 0.1.9 → 0.1.10

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.
@@ -212,8 +212,8 @@ async function runSquireBrokerLink(options) {
212
212
  const pending = /* @__PURE__ */ new Map();
213
213
  const queued = [];
214
214
  let resolveDone;
215
- const done = new Promise((resolve42) => {
216
- resolveDone = resolve42;
215
+ const done = new Promise((resolve43) => {
216
+ resolveDone = resolve43;
217
217
  });
218
218
  const failResponse = (id) => `${JSON.stringify({
219
219
  jsonrpc: "2.0",
@@ -14126,7 +14126,7 @@ function configureNetworkFamilyDefaults(network = net) {
14126
14126
  configureNetworkFamilyDefaults();
14127
14127
 
14128
14128
  // apps/body/dist/cli.js
14129
- import { dirname as dirname30, resolve as resolve41 } from "node:path";
14129
+ import { dirname as dirname30, resolve as resolve42 } from "node:path";
14130
14130
  import { stdin as stdin4, stdout as stdout5 } from "node:process";
14131
14131
 
14132
14132
  // node_modules/@clack/core/dist/index.mjs
@@ -15566,7 +15566,7 @@ function parseCursorModelsOutput(output) {
15566
15566
  };
15567
15567
  }
15568
15568
  async function enumerateCursorModels(env = process.env) {
15569
- return new Promise((resolve42) => {
15569
+ return new Promise((resolve43) => {
15570
15570
  const child = spawn2("cursor-agent", ["models"], {
15571
15571
  env,
15572
15572
  stdio: ["ignore", "pipe", "ignore"]
@@ -15580,11 +15580,11 @@ async function enumerateCursorModels(env = process.env) {
15580
15580
  });
15581
15581
  child.on("error", () => {
15582
15582
  clearTimeout(timer);
15583
- resolve42(void 0);
15583
+ resolve43(void 0);
15584
15584
  });
15585
15585
  child.on("close", (code) => {
15586
15586
  clearTimeout(timer);
15587
- resolve42(code === 0 ? parseCursorModelsOutput(output) : void 0);
15587
+ resolve43(code === 0 ? parseCursorModelsOutput(output) : void 0);
15588
15588
  });
15589
15589
  });
15590
15590
  }
@@ -16011,13 +16011,13 @@ var CursorAcpServer = class {
16011
16011
  consumeLine(line);
16012
16012
  });
16013
16013
  try {
16014
- const { code, signal } = await new Promise((resolve42) => {
16014
+ const { code, signal } = await new Promise((resolve43) => {
16015
16015
  let settled = false;
16016
16016
  const finish = (exitCode, exitSignal) => {
16017
16017
  if (settled)
16018
16018
  return;
16019
16019
  settled = true;
16020
- resolve42({ code: exitCode, signal: exitSignal });
16020
+ resolve43({ code: exitCode, signal: exitSignal });
16021
16021
  };
16022
16022
  child.once("error", (error) => {
16023
16023
  spawnError = error instanceof Error ? error.message : String(error);
@@ -16162,10 +16162,10 @@ function releaseSquireConnectSession(log2, owner = "") {
16162
16162
  function squireChromeProfileDir() {
16163
16163
  return process.env.TRUSTY_SQUIRE_PROFILE_DIR ?? squireHostPaths(homedir2()).profileDir;
16164
16164
  }
16165
- var defaultShellRunner = (command, args) => new Promise((resolve42) => {
16165
+ var defaultShellRunner = (command, args) => new Promise((resolve43) => {
16166
16166
  execFile(command, [...args], { timeout: 12e4, maxBuffer: 4 * 1024 * 1024, encoding: "utf8" }, (error, stdout6, stderr) => {
16167
16167
  const code = error?.code;
16168
- resolve42({
16168
+ resolve43({
16169
16169
  code: typeof code === "number" ? code : error ? 1 : 0,
16170
16170
  stdout: String(stdout6 ?? ""),
16171
16171
  stderr: String(stderr ?? "")
@@ -16190,7 +16190,7 @@ function killConnectTree(child) {
16190
16190
  }
16191
16191
  child.kill();
16192
16192
  }
16193
- var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((resolve42) => {
16193
+ var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((resolve43) => {
16194
16194
  const child = spawn5(command, args, {
16195
16195
  stdio: ["ignore", "pipe", "pipe"],
16196
16196
  env: env ?? squireConnectProcessEnv(),
@@ -16204,7 +16204,7 @@ var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((res
16204
16204
  const safetyTimer = setTimeout(() => {
16205
16205
  if (!resolved) {
16206
16206
  resolved = true;
16207
- resolve42({ stdout: stdout6, stderr, pid: child.pid ?? void 0, report, abort: () => {
16207
+ resolve43({ stdout: stdout6, stderr, pid: child.pid ?? void 0, report, abort: () => {
16208
16208
  } });
16209
16209
  }
16210
16210
  killConnectTree(child);
@@ -16239,7 +16239,7 @@ var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((res
16239
16239
  const finish = (result) => {
16240
16240
  if (!resolved) {
16241
16241
  resolved = true;
16242
- resolve42(result);
16242
+ resolve43(result);
16243
16243
  }
16244
16244
  };
16245
16245
  const settle = (result) => {
@@ -16729,12 +16729,12 @@ var StdioSquireMcpClient = class {
16729
16729
  const child = this.child;
16730
16730
  if (!child)
16731
16731
  return Promise.reject(new Error("Squire MCP session is not running"));
16732
- return new Promise((resolve42, reject) => {
16732
+ return new Promise((resolve43, reject) => {
16733
16733
  const timer = setTimeout(() => {
16734
16734
  this.pending.delete(id);
16735
16735
  reject(new Error(`${method} timed out`));
16736
16736
  }, method === "initialize" ? INITIALIZE_TIMEOUT_MS : CALL_TIMEOUT_MS);
16737
- this.pending.set(id, { resolve: resolve42, reject, timer });
16737
+ this.pending.set(id, { resolve: resolve43, reject, timer });
16738
16738
  child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, params })}
16739
16739
  `);
16740
16740
  });
@@ -16890,9 +16890,9 @@ var SquireTaskRelay = class {
16890
16890
  response.writeHead(400, { "content-type": "application/json" }).end(JSON.stringify({ error: error instanceof Error ? error.message : "Squire relay failed" }));
16891
16891
  }
16892
16892
  });
16893
- await new Promise((resolve42, reject) => {
16893
+ await new Promise((resolve43, reject) => {
16894
16894
  server.once("error", reject);
16895
- server.listen(0, "127.0.0.1", resolve42);
16895
+ server.listen(0, "127.0.0.1", resolve43);
16896
16896
  });
16897
16897
  this.server = server;
16898
16898
  const address = server.address();
@@ -17864,11 +17864,11 @@ var RegistryMcpHostBroker = class {
17864
17864
  })();
17865
17865
  });
17866
17866
  });
17867
- await new Promise((resolve42, reject) => {
17867
+ await new Promise((resolve43, reject) => {
17868
17868
  this.server.once("error", reject);
17869
17869
  this.server.listen(this.socketPath, () => {
17870
17870
  this.server.off("error", reject);
17871
- resolve42();
17871
+ resolve43();
17872
17872
  });
17873
17873
  });
17874
17874
  chmodSync(this.socketPath, 384);
@@ -17877,12 +17877,12 @@ var RegistryMcpHostBroker = class {
17877
17877
  const server = this.server;
17878
17878
  this.server = void 0;
17879
17879
  if (server)
17880
- await new Promise((resolve42) => server.close(() => resolve42()));
17880
+ await new Promise((resolve43) => server.close(() => resolve43()));
17881
17881
  rmSync(this.socketPath, { force: true });
17882
17882
  }
17883
17883
  };
17884
17884
  async function brokerRequest(socketPath, request) {
17885
- return new Promise((resolve42, reject) => {
17885
+ return new Promise((resolve43, reject) => {
17886
17886
  const socket = createConnection3(socketPath);
17887
17887
  let output = "";
17888
17888
  socket.setEncoding("utf8");
@@ -17899,7 +17899,7 @@ async function brokerRequest(socketPath, request) {
17899
17899
  throw new Error(parsed.error);
17900
17900
  if (!Array.isArray(parsed.messages) || !parsed.messages.every((entry) => typeof entry === "string"))
17901
17901
  throw new Error("Registry MCP broker returned an invalid response");
17902
- resolve42(parsed.messages);
17902
+ resolve43(parsed.messages);
17903
17903
  } catch (error) {
17904
17904
  reject(error);
17905
17905
  }
@@ -28531,13 +28531,13 @@ var RoomSupervisor = class {
28531
28531
  */
28532
28532
  retryDelay(failures, signal, since = this.#wakes) {
28533
28533
  const delay = this.delaysMs[failures - 1];
28534
- return new Promise((resolve42) => {
28534
+ return new Promise((resolve43) => {
28535
28535
  let timer;
28536
28536
  const done = () => {
28537
28537
  clearTimeout(timer);
28538
28538
  this.#parked.delete(done);
28539
28539
  signal?.removeEventListener("abort", done);
28540
- resolve42();
28540
+ resolve43();
28541
28541
  };
28542
28542
  this.#parked.add(done);
28543
28543
  signal?.addEventListener("abort", done, { once: true });
@@ -28729,12 +28729,12 @@ async function retryBeforeReady(work, options) {
28729
28729
  if (wait2 <= 0)
28730
28730
  break;
28731
28731
  await options.extendStartTimeout(wait2 + 15e3);
28732
- await new Promise((resolve42) => {
28732
+ await new Promise((resolve43) => {
28733
28733
  const timer = setTimeout(done, wait2);
28734
28734
  function done() {
28735
28735
  clearTimeout(timer);
28736
28736
  options.signal?.removeEventListener("abort", done);
28737
- resolve42();
28737
+ resolve43();
28738
28738
  }
28739
28739
  wake = done;
28740
28740
  options.signal?.addEventListener("abort", done, { once: true });
@@ -29195,9 +29195,26 @@ var AcpRequestTimeoutError = class extends Error {
29195
29195
  this.name = "AcpRequestTimeoutError";
29196
29196
  }
29197
29197
  };
29198
- function isSilentPromptTimeout(error) {
29199
- return error instanceof AcpRequestTimeoutError && error.inactivity && error.method === "session/prompt";
29200
- }
29198
+ var TURN_BACKSTOP_MS = 30 * 6e4;
29199
+ var AcpTurnBackstopError = class extends Error {
29200
+ timeoutMs;
29201
+ lastActivity;
29202
+ cause = "turn_backstop";
29203
+ constructor(timeoutMs, lastActivity, stderrTail = "", detail = "") {
29204
+ const meaningful = flattenHarnessCause(stderrTail);
29205
+ super(`turn_backstop: no ACP traffic for ${timeoutMs / 6e4} minutes; last activity: ${lastActivity}${detail ? ` (${detail})` : ""}${meaningful ? `; harness stderr: ${meaningful}` : ""}`);
29206
+ this.timeoutMs = timeoutMs;
29207
+ this.lastActivity = lastActivity;
29208
+ this.name = "AcpTurnBackstopError";
29209
+ }
29210
+ };
29211
+ var AcpRuntimeExitedError = class extends Error {
29212
+ cause = "runtime_exited";
29213
+ constructor(detail) {
29214
+ super(`runtime_exited: ${detail}`);
29215
+ this.name = "AcpRuntimeExitedError";
29216
+ }
29217
+ };
29201
29218
  function killChildProcessGroup(child, signal) {
29202
29219
  if (!child.pid)
29203
29220
  return;
@@ -29521,16 +29538,26 @@ var AcpClient = class extends EventEmitter {
29521
29538
  });
29522
29539
  this.child.stdout.setEncoding("utf8");
29523
29540
  this.child.stdout.on("data", (chunk) => this.onData(chunk));
29541
+ const child = this.child;
29542
+ const pipeClosed = (pipe) => {
29543
+ setTimeout(() => {
29544
+ if (this.child === child && this.alive) {
29545
+ const stderr = flattenHarnessCause(this.stderrTail);
29546
+ this.failRuntime(`ACP agent ${this.agentLabel} ${pipe} pipe closed${stderr ? `: ${stderr}` : ""}`);
29547
+ }
29548
+ }, 25);
29549
+ };
29550
+ this.child.stdout.on("end", () => pipeClosed("stdout"));
29551
+ this.child.stdout.on("close", () => pipeClosed("stdout"));
29552
+ this.child.stdout.on("error", (error) => this.failRuntime(`stdout: ${error.message}`));
29553
+ this.child.stdin.on("close", () => pipeClosed("stdin"));
29554
+ this.child.stdin.on("error", (error) => this.failRuntime(`stdin: ${error.message}`));
29524
29555
  this.child.on("exit", (code, signal) => {
29525
- void this.handleChildExit(code, signal);
29556
+ if (this.child === child)
29557
+ void this.handleChildExit(code, signal);
29526
29558
  });
29527
29559
  this.child.on("error", (err) => {
29528
- this.alive = false;
29529
- for (const [, p] of this.pending) {
29530
- clearTimeout(p.timer);
29531
- p.reject(err);
29532
- }
29533
- this.pending.clear();
29560
+ this.failRuntime(`ACP agent ${this.agentLabel}: ${err.message}`);
29534
29561
  if (this.listenerCount("error") > 0)
29535
29562
  this.emit("error", err);
29536
29563
  });
@@ -29556,13 +29583,28 @@ var AcpClient = class extends EventEmitter {
29556
29583
  */
29557
29584
  async handleChildExit(code, signal) {
29558
29585
  this.alive = false;
29559
- const oomKilled = signal === "SIGKILL" && !this.stopping && await this.oomKills.consume().catch(() => false);
29586
+ for (const p of this.pending.values())
29587
+ this.clearTimer(p);
29588
+ let oomKilled = false;
29589
+ if (signal === "SIGKILL" && !this.stopping) {
29590
+ let diagnosticTimer;
29591
+ try {
29592
+ oomKilled = await Promise.race([
29593
+ this.oomKills.consume().catch(() => false),
29594
+ new Promise((resolve43) => {
29595
+ diagnosticTimer = setTimeout(() => resolve43(false), 100);
29596
+ })
29597
+ ]);
29598
+ } finally {
29599
+ clearTimeout(diagnosticTimer);
29600
+ }
29601
+ }
29560
29602
  const exitText = oomKilled ? `ACP agent ${this.agentLabel} was killed by the kernel OOM killer (signal=SIGKILL)` : `ACP agent ${this.agentLabel} exited code=${code} signal=${signal}`;
29561
29603
  const meaningful = flattenHarnessCause(this.stderrTail);
29562
29604
  const stderrSuffix = meaningful ? `: ${meaningful}` : "";
29563
29605
  for (const [, p] of this.pending) {
29564
29606
  this.clearTimer(p);
29565
- p.reject(new Error(`${exitText}${stderrSuffix}`));
29607
+ p.reject(new AcpRuntimeExitedError(`${exitText}${stderrSuffix}`));
29566
29608
  }
29567
29609
  this.pending.clear();
29568
29610
  this.activeRunIds.clear();
@@ -29571,9 +29613,15 @@ var AcpClient = class extends EventEmitter {
29571
29613
  this.sessionCommands.clear();
29572
29614
  this.emit("exit", { code, signal });
29573
29615
  }
29616
+ failRuntime(detail) {
29617
+ this.alive = false;
29618
+ for (const p of this.pending.values()) {
29619
+ this.clearTimer(p);
29620
+ p.reject(new AcpRuntimeExitedError(detail));
29621
+ }
29622
+ this.pending.clear();
29623
+ }
29574
29624
  async stop() {
29575
- if (!this.alive)
29576
- return;
29577
29625
  const child = this.child;
29578
29626
  if (!child)
29579
29627
  return;
@@ -29705,10 +29753,10 @@ var AcpClient = class extends EventEmitter {
29705
29753
  }
29706
29754
  /**
29707
29755
  * Run one prompt turn. `timeoutMs` is an idle window, not a hard cap on
29708
- * turn length: every `session/update` for this session (message chunk,
29709
- * tool call, or otherwise) re-arms it, so an actively-working agent can
29710
- * run indefinitely while a genuinely wedged one (zero activity for
29711
- * `timeoutMs`) still gets cancelled. `onChunk` is the ACP-boundary
29756
+ * turn length: every inbound ACP message for this session re-arms it.
29757
+ * Open tool calls suspend the backstop until completion. A silent session
29758
+ * with no open tool is cancelled without stopping the runtime.
29759
+ * `onChunk` is the ACP-boundary
29712
29760
  * streaming hook: called for every incremental `agent_message_chunk`
29713
29761
  * delta as it arrives, so a caller can project live text without waiting
29714
29762
  * for the turn to finish. A harness that only emits a final message
@@ -29723,18 +29771,15 @@ var AcpClient = class extends EventEmitter {
29723
29771
  get lastPromptBytes() {
29724
29772
  return this.lastPromptByteCount;
29725
29773
  }
29726
- async sessionPrompt(sessionId, text2, timeoutMs = 12e4, onChunk, onActivity, onToolCalls) {
29774
+ async sessionPrompt(sessionId, text2, timeoutMs = TURN_BACKSTOP_MS, onChunk, onActivity, onToolCalls) {
29727
29775
  this.lastPromptByteCount = typeof text2 === "string" ? Buffer.byteLength(text2, "utf8") : void 0;
29728
29776
  const updates = [];
29729
29777
  let promptRunId;
29730
- let requestId;
29731
29778
  const onUpdate = (u4) => {
29732
29779
  if (u4.sessionId !== sessionId)
29733
29780
  return;
29734
29781
  updates.push(u4);
29735
29782
  promptRunId ??= this.activeRunIdFromUpdate(u4.update);
29736
- if (requestId !== void 0)
29737
- this.resetPendingIdleTimeout(requestId);
29738
29783
  onActivity?.(agentStreamSnapshot(updates, this.agentLabel));
29739
29784
  onToolCalls?.(toolCallEntries(updates));
29740
29785
  if (onChunk) {
@@ -29751,9 +29796,7 @@ var AcpClient = class extends EventEmitter {
29751
29796
  const result = await this.request("session/prompt", {
29752
29797
  sessionId,
29753
29798
  prompt: typeof text2 === "string" ? [{ type: "text", text: text2 }] : [...text2]
29754
- }, timeoutMs, (id) => {
29755
- requestId = id;
29756
- }, promptPayloadNote(text2));
29799
+ }, timeoutMs, true, promptPayloadNote(text2));
29757
29800
  const agentText = finalAgentMessageText(updates, this.agentLabel);
29758
29801
  const toolCalls = toolCallEntries(updates);
29759
29802
  return {
@@ -29836,22 +29879,22 @@ var AcpClient = class extends EventEmitter {
29836
29879
  }
29837
29880
  }
29838
29881
  /**
29839
- * Re-arm a pending request's idle timer from its full `idleTimeoutMs`,
29840
- * called on every ACP activity signal for that request (streamed text
29841
- * delta, session/update, tool call). A request only times out after this
29842
- * much wall-clock time with zero activity, not after a fixed deadline —
29843
- * so an actively-working turn can run indefinitely while a genuinely
29844
- * wedged one still gets caught.
29882
+ * A tool owns its deadline. Silence while it is open is never a turn failure.
29883
+ * After the last tool closes, start a full backstop window for this session.
29845
29884
  */
29846
29885
  resetPendingIdleTimeout(id) {
29847
29886
  const p = this.pending.get(id);
29848
29887
  if (!p || p.idleTimeoutMs === void 0)
29849
29888
  return;
29850
29889
  this.clearTimer(p);
29851
- const { idleTimeoutMs, method, reject, detail } = p;
29890
+ if (p.openToolCalls?.size)
29891
+ return;
29892
+ const { idleTimeoutMs, reject, detail, sessionId, lastActivity } = p;
29852
29893
  p.timer = setTimeout(() => {
29853
29894
  this.pending.delete(id);
29854
- reject(new AcpRequestTimeoutError(method ?? "request", idleTimeoutMs, this.stderrTail, true, detail ?? ""));
29895
+ if (sessionId)
29896
+ this.sessionCancel(sessionId);
29897
+ reject(new AcpTurnBackstopError(idleTimeoutMs, lastActivity ?? "session/prompt", this.stderrTail, detail));
29855
29898
  }, idleTimeoutMs);
29856
29899
  }
29857
29900
  onData(chunk) {
@@ -29874,6 +29917,25 @@ var AcpClient = class extends EventEmitter {
29874
29917
  handleMessage(msg) {
29875
29918
  const id = msg.id;
29876
29919
  const method = msg.method;
29920
+ const params = msg.params;
29921
+ const response = !method && id !== void 0 ? this.pending.get(Number(id)) : void 0;
29922
+ const sessionId = params?.sessionId ?? response?.sessionId;
29923
+ if (sessionId) {
29924
+ for (const [requestId, pending] of this.pending) {
29925
+ if (pending.method !== "session/prompt" || pending.sessionId !== sessionId)
29926
+ continue;
29927
+ const update = params?.update;
29928
+ pending.lastActivity = typeof update?.sessionUpdate === "string" ? update.sessionUpdate : method ?? `response:${response?.method ?? "request"}`;
29929
+ if (typeof update?.toolCallId === "string" && (update.sessionUpdate === "tool_call" || update.sessionUpdate === "tool_call_update")) {
29930
+ if (update.status === "pending" || update.status === "in_progress") {
29931
+ pending.openToolCalls?.add(update.toolCallId);
29932
+ } else if (update.status === "completed" || update.status === "failed") {
29933
+ pending.openToolCalls?.delete(update.toolCallId);
29934
+ }
29935
+ }
29936
+ this.resetPendingIdleTimeout(requestId);
29937
+ }
29938
+ }
29877
29939
  if (id !== void 0 && !method) {
29878
29940
  const n3 = Number(id);
29879
29941
  const p = this.pending.get(n3);
@@ -29901,19 +29963,19 @@ var AcpClient = class extends EventEmitter {
29901
29963
  return;
29902
29964
  }
29903
29965
  if (method === "session/update") {
29904
- const params = msg.params;
29905
- if (params?.sessionId && params.update) {
29906
- if (params.update.sessionUpdate === "available_commands_update") {
29907
- const commands = parseAvailableCommands(params.update.availableCommands);
29908
- this.sessionCommands.set(params.sessionId, commands);
29966
+ const params2 = msg.params;
29967
+ if (params2?.sessionId && params2.update) {
29968
+ if (params2.update.sessionUpdate === "available_commands_update") {
29969
+ const commands = parseAvailableCommands(params2.update.availableCommands);
29970
+ this.sessionCommands.set(params2.sessionId, commands);
29909
29971
  this.commandsHandler?.(commands);
29910
- this.emit("commands", { sessionId: params.sessionId, commands });
29972
+ this.emit("commands", { sessionId: params2.sessionId, commands });
29911
29973
  }
29912
- const toolCallId = params.update.toolCallId;
29913
- const sessionUpdate = params.update.sessionUpdate;
29974
+ const toolCallId = params2.update.toolCallId;
29975
+ const sessionUpdate = params2.update.sessionUpdate;
29914
29976
  if (typeof toolCallId === "string" && (sessionUpdate === "tool_call" || sessionUpdate === "tool_call_update")) {
29915
- const metadataKey = `${params.sessionId}\0${toolCallId}`;
29916
- const status = params.update.status;
29977
+ const metadataKey = `${params2.sessionId}\0${toolCallId}`;
29978
+ const status = params2.update.status;
29917
29979
  if (status === "completed" || status === "failed") {
29918
29980
  this.toolCallMetadata.delete(metadataKey);
29919
29981
  } else {
@@ -29921,25 +29983,25 @@ var AcpClient = class extends EventEmitter {
29921
29983
  this.toolCallMetadata.set(metadataKey, {
29922
29984
  ...existing,
29923
29985
  toolCallId,
29924
- ...typeof params.update.title === "string" ? { title: params.update.title } : {},
29925
- ...typeof params.update.kind === "string" ? { kind: params.update.kind } : {},
29926
- ..."rawInput" in params.update ? { rawInput: params.update.rawInput } : {},
29986
+ ...typeof params2.update.title === "string" ? { title: params2.update.title } : {},
29987
+ ...typeof params2.update.kind === "string" ? { kind: params2.update.kind } : {},
29988
+ ..."rawInput" in params2.update ? { rawInput: params2.update.rawInput } : {},
29927
29989
  // `content`/`locations` carry the touched file paths for adapters
29928
29990
  // whose permission request omits them (codex-acp's file-change
29929
29991
  // request has no rawInput at all) — the corner worktree guard in
29930
29992
  // `session-sandbox.ts` reads them.
29931
- ..."content" in params.update ? { content: params.update.content } : {},
29932
- ..."locations" in params.update ? { locations: params.update.locations } : {}
29993
+ ..."content" in params2.update ? { content: params2.update.content } : {},
29994
+ ..."locations" in params2.update ? { locations: params2.update.locations } : {}
29933
29995
  });
29934
29996
  }
29935
29997
  }
29936
29998
  const u4 = {
29937
- sessionId: params.sessionId,
29938
- update: params.update
29999
+ sessionId: params2.sessionId,
30000
+ update: params2.update
29939
30001
  };
29940
- const activeRunId = this.activeRunIdFromUpdate(params.update);
30002
+ const activeRunId = this.activeRunIdFromUpdate(params2.update);
29941
30003
  if (activeRunId)
29942
- this.activeRunIds.set(params.sessionId, activeRunId);
30004
+ this.activeRunIds.set(params2.sessionId, activeRunId);
29943
30005
  this.emit("session/update", u4);
29944
30006
  }
29945
30007
  return;
@@ -29954,7 +30016,7 @@ var AcpClient = class extends EventEmitter {
29954
30016
  const current = this.activeRunIds.get(sessionId);
29955
30017
  if (current)
29956
30018
  return Promise.resolve(current);
29957
- return new Promise((resolve42, reject) => {
30019
+ return new Promise((resolve43, reject) => {
29958
30020
  const onUpdate = (update) => {
29959
30021
  if (update.sessionId !== sessionId)
29960
30022
  return;
@@ -29962,7 +30024,7 @@ var AcpClient = class extends EventEmitter {
29962
30024
  if (!runId)
29963
30025
  return;
29964
30026
  cleanup();
29965
- resolve42(runId);
30027
+ resolve43(runId);
29966
30028
  };
29967
30029
  const timer = setTimeout(() => {
29968
30030
  cleanup();
@@ -30034,32 +30096,30 @@ var AcpClient = class extends EventEmitter {
30034
30096
  result: { outcome: { outcome: "cancelled" } }
30035
30097
  });
30036
30098
  }
30037
- /**
30038
- * `onStart`, when given, receives the assigned request id synchronously
30039
- * and marks the request as idle-resettable at `timeoutMs`: callers can
30040
- * then call `resetPendingIdleTimeout(id)` on activity to defer the
30041
- * timeout instead of it firing at a fixed deadline.
30042
- */
30043
- request(method, params, timeoutMs = 6e4, onStart, detail = "") {
30099
+ /** Prompt backstops reset on session traffic; other requests use a fixed deadline. */
30100
+ request(method, params, timeoutMs = 6e4, backstop = false, detail = "") {
30044
30101
  if (!this.child || !this.alive) {
30045
30102
  return Promise.reject(new Error("AcpClient not started"));
30046
30103
  }
30047
30104
  const id = this.nextId++;
30048
30105
  const payload = { jsonrpc: "2.0", id, method, params };
30049
- return new Promise((resolve42, reject) => {
30050
- const timer = setTimeout(() => {
30106
+ return new Promise((resolve43, reject) => {
30107
+ const timer = backstop ? void 0 : setTimeout(() => {
30051
30108
  this.pending.delete(id);
30052
- reject(new AcpRequestTimeoutError(method, timeoutMs, this.stderrTail, Boolean(onStart), detail));
30109
+ reject(new AcpRequestTimeoutError(method, timeoutMs, this.stderrTail, false, detail));
30053
30110
  }, timeoutMs);
30111
+ const sessionId = params?.sessionId;
30054
30112
  this.pending.set(id, {
30055
- resolve: resolve42,
30113
+ resolve: resolve43,
30056
30114
  reject,
30057
30115
  timer,
30058
30116
  method,
30117
+ ...sessionId ? { sessionId } : {},
30059
30118
  ...detail ? { detail } : {},
30060
- ...onStart ? { idleTimeoutMs: timeoutMs } : {}
30119
+ ...backstop ? { idleTimeoutMs: timeoutMs, lastActivity: method, openToolCalls: /* @__PURE__ */ new Set() } : {}
30061
30120
  });
30062
- onStart?.(id);
30121
+ if (backstop)
30122
+ this.resetPendingIdleTimeout(id);
30063
30123
  this.write(payload);
30064
30124
  });
30065
30125
  }
@@ -30067,9 +30127,15 @@ var AcpClient = class extends EventEmitter {
30067
30127
  this.write({ jsonrpc: "2.0", method, params });
30068
30128
  }
30069
30129
  write(obj) {
30070
- if (!this.child?.stdin.writable)
30130
+ if (!this.child?.stdin.writable) {
30131
+ if (this.child)
30132
+ this.failRuntime(`ACP agent ${this.agentLabel} stdin pipe closed`);
30071
30133
  return;
30072
- this.child.stdin.write(JSON.stringify(obj) + "\n");
30134
+ }
30135
+ this.child.stdin.write(JSON.stringify(obj) + "\n", (error) => {
30136
+ if (error)
30137
+ this.failRuntime(`stdin: ${error.message}`);
30138
+ });
30073
30139
  }
30074
30140
  };
30075
30141
 
@@ -31187,7 +31253,10 @@ function interpreterScriptArgument(argv) {
31187
31253
 
31188
31254
  // packages/api-contract/dist/connector-offers.js
31189
31255
  var CONNECTOR_OFFER_WINDOW_MS = 2 * 6e4;
31190
- var OFFERABLE_CONNECTOR_KINDS = CONNECTABLE_CONNECTOR_KINDS.filter((kind) => kind !== "wallet");
31256
+ var OFFERABLE_CONNECTOR_KINDS = [
31257
+ ...CONNECTABLE_CONNECTOR_KINDS,
31258
+ "wallet"
31259
+ ];
31191
31260
 
31192
31261
  // packages/api-contract/dist/phone-guards.js
31193
31262
  var CLOSED_VIEWER = {
@@ -31648,11 +31717,11 @@ The soul is not authority and never changes your tools, permissions, roles, or m
31648
31717
  {
31649
31718
  id: "core.files",
31650
31719
  topic: "files",
31651
- why: "Agents fetched the reference URL of a shared file instead of the copy already downloaded for them.",
31720
+ why: "Files on earlier messages are shown only as markers and never pre-downloaded; agents fetched media URLs instead.",
31652
31721
  budgetBytes: 160,
31653
31722
  layer: "core",
31654
31723
  surfaces: EVERYWHERE,
31655
- render: () => "Files people share are downloaded for you: read the local path in the prompt and never fetch the reference URL."
31724
+ render: () => "For a \u{1F4CE} file, call download_attachment and read its path. Never fetch media URLs; on failure, say you couldn't open it."
31656
31725
  },
31657
31726
  {
31658
31727
  id: "surface.tools",
@@ -32016,7 +32085,7 @@ var BEELINE_TRIAGE_SKILL_NAME = "beeline-triage";
32016
32085
  var BEELINE_REVIEW_SKILL_NAME = "beeline-review";
32017
32086
  var BEELINE_SPEC_SKILL_NAME = "beeline-spec";
32018
32087
  var BEELINE_ROOM_MECHANICS = [
32019
- "Files and photos people share are downloaded for you: read them at the local path named in the prompt (photos may also arrive inline); never fetch the reference URL.",
32088
+ "Files and photos on the message you are answering are downloaded for you: read them at the local path named in the prompt (photos may also arrive inline). A file on an earlier message shows only as a \u{1F4CE} marker with an id; call beeline-agent download_attachment with that message id and attachment id, then read the returned path. Never fetch a media URL; if the download fails, tell the requester you could not open the file.",
32020
32089
  "To create a file you can send, call beeline-agent write_scratch_file with a relative path and content - text by default, or base64 for bytes you computed; it returns a path in your writable session home. To send a file, call beeline-agent post_artifact with a path inside your checkout or anywhere in your writable session home (wherever a file you or your harness generated actually landed, including one you just wrote), or with html/bytes content directly; it is uploaded and attached to your reply, and title and mime default from the file when you post by path. write_scratch_file produces the file, not a picture. To put a real photograph in an artifact, call beeline-agent fetch_image with the photo URL; it writes the bytes to your session scratch and returns the path, mime, and size \u2014 read them, base64-encode, and embed as a data: URL. The validator still refuses every http(s) image reference, and drawing an SVG stand-in is not a photograph.",
32021
32090
  "To run something later or repeatedly, call beeline-agent create_schedule (interval in minutes or a 5-field cron, optional maxRuns); list_schedules / update_schedule / delete_schedule manage them, including schedules other agents created for themselves.",
32022
32091
  `To react to a message in this Room, call beeline-agent react_to_message with its message id and one supported emoji (${MESSAGE_REACTION_EMOJIS.join(" ")}).`,
@@ -32135,6 +32204,15 @@ The record informs the verdict but never replaces approve_merge or pr_checks_sta
32135
32204
  - Record every command and exit code.
32136
32205
  - A review with no executed command is invalid and must FAIL.
32137
32206
 
32207
+ ### Design rules
32208
+
32209
+ When the diff touches UI and the repository has a DESIGN.md, check every changed style against its rules: colours from theme tokens only, the type roles, the spacing scale, the allowed radii, elevation, the shared components, and touch targets.
32210
+
32211
+ - Run the repository's design lints. In Beeline, from \`apps/mobile\`: \`npx vitest run sources/buzz/calm-lint sources/buzz/design-lint\`.
32212
+ - FAIL when a design baseline count grows, or when an allowlist entry is added without naming the design decision behind it.
32213
+ - Require a screenshot or rendered proof of every visual change in each theme the app ships (in Beeline, Obsidian and Bone).
32214
+ - A design-rule violation is an engineering finding and blocks PASS.
32215
+
32138
32216
  ## 4. Adversarial pass
32139
32217
 
32140
32218
  - For every changed function, name one concrete input or sequence that breaks it.
@@ -33409,6 +33487,14 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
33409
33487
  }
33410
33488
  await applyGrantedHostRoutes(root, operatorHome, grantedHostRoutes, agentKind, failClosed, resourceAuthFile, extraHostRoutes, squireScope);
33411
33489
  await provisionPiCustomModelConfig(root, operatorHome, failClosed, openRouterRouting);
33490
+ if (appliesToHarness(agentKind, "pi")) {
33491
+ const settings2 = {
33492
+ httpIdleTimeoutMs: 3e5,
33493
+ retry: { enabled: true, maxRetries: 3, baseDelayMs: 2e3 }
33494
+ };
33495
+ await writeIsolatedHarnessFile(resolve15(root, "pi", "settings.json"), `${JSON.stringify(settings2, null, 2)}
33496
+ `);
33497
+ }
33412
33498
  }
33413
33499
  function appliesToHarness(selected, harness) {
33414
33500
  return !selected || selected === harness;
@@ -34390,7 +34476,7 @@ function clearInstallFailure(stateDir) {
34390
34476
  } catch {
34391
34477
  }
34392
34478
  }
34393
- var runSandboxInstallCommand = (command, args) => new Promise((resolve42) => {
34479
+ var runSandboxInstallCommand = (command, args) => new Promise((resolve43) => {
34394
34480
  execFile6(command, [...args], {
34395
34481
  timeout: INSTALL_TIMEOUT_MS,
34396
34482
  maxBuffer: INSTALL_OUTPUT_LIMIT * 2,
@@ -34400,7 +34486,7 @@ var runSandboxInstallCommand = (command, args) => new Promise((resolve42) => {
34400
34486
  }, (error, stdout6, stderr) => {
34401
34487
  const code = error && "code" in error && typeof error.code === "number" ? error.code : error ? null : 0;
34402
34488
  const output = [stdout6, stderr].join("").trim();
34403
- resolve42({ code, output: output || (error ? error.message : "") });
34489
+ resolve43({ code, output: output || (error ? error.message : "") });
34404
34490
  });
34405
34491
  });
34406
34492
  function lastLine(output, fallback) {
@@ -35073,6 +35159,7 @@ var UPDATE_PROBE_TURN_TIMEOUT_MS = 45e3;
35073
35159
  var UPDATE_PROBE_RETRY_DELAY_MS = 2e3;
35074
35160
  var ACP_ERROR_CODE = /\bACP error (-\d+):/;
35075
35161
  var ACP_PROMPT_INACTIVITY = /\bACP session\/prompt timed out after \d+ms of inactivity\b/;
35162
+ var ACP_TURN_BACKSTOP = /\bturn_backstop: no ACP traffic for [\d.]+ minutes; last activity:/;
35076
35163
  function isServerInternalCode(code) {
35077
35164
  return code === -32603 || code <= -32e3 && code >= -32099;
35078
35165
  }
@@ -35080,8 +35167,9 @@ function classifyAcpTurnFailure(error) {
35080
35167
  const message = error instanceof Error ? error.message : typeof error === "string" ? error : void 0;
35081
35168
  if (!message)
35082
35169
  return void 0;
35083
- if (ACP_PROMPT_INACTIVITY.test(message))
35170
+ if (ACP_TURN_BACKSTOP.test(message) || ACP_PROMPT_INACTIVITY.test(message)) {
35084
35171
  return { kind: "prompt-inactivity" };
35172
+ }
35085
35173
  const code = Number(ACP_ERROR_CODE.exec(message)?.[1]);
35086
35174
  if (Number.isFinite(code) && isServerInternalCode(code))
35087
35175
  return { kind: "server-internal", code };
@@ -35136,7 +35224,7 @@ function describeCurrentReleaseOutcome(outcome) {
35136
35224
  async function retryWhileAdapterReinstalls(run2, options = {}) {
35137
35225
  const attempts = options.attempts ?? 12;
35138
35226
  const delayMs = options.delayMs ?? 5e3;
35139
- const sleep4 = options.sleep ?? ((ms) => new Promise((resolve42) => setTimeout(resolve42, ms)));
35227
+ const sleep4 = options.sleep ?? ((ms) => new Promise((resolve43) => setTimeout(resolve43, ms)));
35140
35228
  for (let attempt = 1; ; attempt += 1) {
35141
35229
  try {
35142
35230
  return await run2();
@@ -37809,7 +37897,7 @@ async function probeReleaseInSubprocess(input) {
37809
37897
  return { kind: "unavailable", reason: `release ${input.releaseId} has no runnable CLI entrypoint` };
37810
37898
  }
37811
37899
  const timeoutMs = input.timeoutMs ?? CURRENT_RELEASE_PROBE_TIMEOUT_MS;
37812
- return new Promise((resolve42) => {
37900
+ return new Promise((resolve43) => {
37813
37901
  const child = spawn13(input.execPath ?? process.execPath, [entrypoint, UPDATE_PROBE_COMMAND, "--config", input.runtimeConfigPath], { env: input.env ?? process.env, stdio: ["ignore", "pipe", "pipe"] });
37814
37902
  let stdout6 = "";
37815
37903
  let stderr = "";
@@ -37819,7 +37907,7 @@ async function probeReleaseInSubprocess(input) {
37819
37907
  return;
37820
37908
  settled = true;
37821
37909
  clearTimeout(timer);
37822
- resolve42(outcome);
37910
+ resolve43(outcome);
37823
37911
  };
37824
37912
  const timer = setTimeout(() => {
37825
37913
  child.kill("SIGKILL");
@@ -37904,7 +37992,7 @@ import { dirname as dirname29 } from "node:path";
37904
37992
 
37905
37993
  // apps/body/dist/agent-runtime.js
37906
37994
  import { homedir as homedir18 } from "node:os";
37907
- import { dirname as dirname28, join as join19, resolve as resolve40 } from "node:path";
37995
+ import { dirname as dirname28, join as join19, resolve as resolve41 } from "node:path";
37908
37996
 
37909
37997
  // apps/body/dist/model-availability.js
37910
37998
  var SECRET_VALUE = /(?:token|key|secret|password)=?[^\s,;]*/gi;
@@ -38038,10 +38126,10 @@ var LOGIN_URL = /https:\/\/login\.tailscale\.com\/[A-Za-z0-9_/-]+/u;
38038
38126
  function clipped(value) {
38039
38127
  return value.length <= OUTPUT_LIMIT ? value : value.slice(value.length - OUTPUT_LIMIT);
38040
38128
  }
38041
- var runTailscaleCommand = (command, args) => new Promise((resolve42) => {
38129
+ var runTailscaleCommand = (command, args) => new Promise((resolve43) => {
38042
38130
  execFile7(command, [...args], { timeout: COMMAND_TIMEOUT_MS, maxBuffer: OUTPUT_LIMIT * 2 }, (error, stdout6, stderr) => {
38043
38131
  const code = error && "code" in error && typeof error.code === "number" ? error.code : error ? null : 0;
38044
- resolve42({ code, stdout: clipped(stdout6), stderr: clipped(stderr) });
38132
+ resolve43({ code, stdout: clipped(stdout6), stderr: clipped(stderr) });
38045
38133
  });
38046
38134
  });
38047
38135
  function loginUrlFrom(status, output) {
@@ -38605,7 +38693,7 @@ import { execFile as execFile13 } from "node:child_process";
38605
38693
  import { createHash as createHash13 } from "node:crypto";
38606
38694
  import { existsSync as existsSync8, mkdirSync as mkdirSync3 } from "node:fs";
38607
38695
  import { mkdir as mkdir26, readdir as readdir9, realpath as realpath2, rm as rm14 } from "node:fs/promises";
38608
- import { dirname as dirname26, relative as relative3, resolve as resolve35, sep as sep2 } from "node:path";
38696
+ import { dirname as dirname26, relative as relative3, resolve as resolve36, sep as sep2 } from "node:path";
38609
38697
  import { promisify as promisify8 } from "node:util";
38610
38698
 
38611
38699
  // apps/body/dist/grant-runner.js
@@ -39066,8 +39154,30 @@ function captureConnectionUsage(recorder, turn, calls) {
39066
39154
  }
39067
39155
  }
39068
39156
 
39069
- // apps/body/dist/turn-usage.js
39157
+ // apps/body/dist/model-context-window.js
39070
39158
  import { readFile as readFile21 } from "node:fs/promises";
39159
+ import { join as join13 } from "node:path";
39160
+ async function modelContextWindowTokens(model, piHome) {
39161
+ if (!model || !piHome)
39162
+ return void 0;
39163
+ try {
39164
+ const catalog = JSON.parse(await readFile21(join13(piHome, "models.json"), "utf8"));
39165
+ const parts = model.split("/");
39166
+ const preferredProvider = parts.length > 2 ? parts.shift() : void 0;
39167
+ const modelId = parts.join("/");
39168
+ const providers = preferredProvider ? [catalog.providers?.[preferredProvider]].filter(Boolean) : Object.values(catalog.providers ?? {});
39169
+ for (const provider of providers) {
39170
+ const window = provider?.models?.find((entry) => entry.id === modelId)?.contextWindow;
39171
+ if (window && Number.isFinite(window) && window > 0)
39172
+ return Math.floor(window);
39173
+ }
39174
+ } catch {
39175
+ }
39176
+ return void 0;
39177
+ }
39178
+
39179
+ // apps/body/dist/turn-usage.js
39180
+ import { readFile as readFile22 } from "node:fs/promises";
39071
39181
  function tokenCount(value) {
39072
39182
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
39073
39183
  }
@@ -39079,61 +39189,77 @@ function promptTokens(usage2) {
39079
39189
  const cacheWrite = tokenCount(usage2.cacheWrite) ?? tokenCount(usage2.cache_write) ?? 0;
39080
39190
  return input + cacheRead + cacheWrite;
39081
39191
  }
39082
- async function readHarnessTurnUsage(input) {
39192
+ async function readUsageCalls(input, latestTurn) {
39083
39193
  const file = await piSessionFilePath(input.agentEnv, input.sessionId);
39084
39194
  if (!file)
39195
+ return latestTurn ? void 0 : [];
39196
+ const raw = await readFile22(file, "utf8").catch(() => void 0);
39197
+ if (raw === void 0)
39085
39198
  return void 0;
39086
- let raw;
39087
- try {
39088
- raw = await readFile21(file, "utf8");
39089
- } catch {
39090
- return void 0;
39091
- }
39092
- let latest;
39199
+ const calls = [];
39093
39200
  for (const line of raw.split(/\r?\n/)) {
39094
- if (!line.trim())
39095
- continue;
39096
39201
  let entry;
39097
39202
  try {
39098
39203
  entry = JSON.parse(line);
39099
39204
  } catch {
39100
39205
  continue;
39101
39206
  }
39102
- if (entry.type !== "message" || !entry.message)
39207
+ if (!entry || entry.type !== "message" || !entry.message)
39103
39208
  continue;
39104
- if (entry.message.role === "user") {
39105
- latest = void 0;
39106
- continue;
39107
- }
39209
+ if (entry.message.role === "user" && latestTurn)
39210
+ calls.length = 0;
39108
39211
  if (entry.message.role !== "assistant")
39109
39212
  continue;
39110
39213
  const usage2 = entry.message.usage;
39111
- if (!usage2 || typeof usage2 !== "object" || Array.isArray(usage2))
39112
- continue;
39113
- const tokens = promptTokens(usage2);
39114
- if (tokens === void 0)
39115
- continue;
39214
+ const tokens = usage2 && typeof usage2 === "object" && !Array.isArray(usage2) ? promptTokens(usage2) : void 0;
39116
39215
  const model = entry.message.model;
39117
- latest = {
39118
- inputTokens: tokens,
39216
+ calls.push({
39217
+ ...tokens !== void 0 ? { inputTokens: tokens } : {},
39119
39218
  ...typeof model === "string" && model ? { model } : {}
39120
- };
39219
+ });
39121
39220
  }
39122
- return latest;
39221
+ return calls;
39222
+ }
39223
+ function summarize(calls) {
39224
+ if (!calls.length)
39225
+ return void 0;
39226
+ const measured = calls.filter((call) => call.inputTokens !== void 0);
39227
+ return {
39228
+ ...calls[calls.length - 1],
39229
+ ...measured.length ? { totalInputTokens: measured.reduce((sum, call) => sum + call.inputTokens, 0) } : {},
39230
+ modelCalls: measured.length,
39231
+ modelCallsWithoutUsage: calls.length - measured.length
39232
+ };
39123
39233
  }
39234
+ var TurnUsageAccumulator = class {
39235
+ calls = [];
39236
+ async measure(input, run2) {
39237
+ const before = await readUsageCalls(input, false);
39238
+ try {
39239
+ return await run2();
39240
+ } finally {
39241
+ const after = await readUsageCalls(input, false);
39242
+ if (before && after)
39243
+ this.calls.push(...after.slice(before.length));
39244
+ }
39245
+ }
39246
+ get usage() {
39247
+ return summarize(this.calls);
39248
+ }
39249
+ };
39124
39250
 
39125
39251
  // apps/body/dist/server-command-intake.js
39126
39252
  import { randomUUID as randomUUID10 } from "node:crypto";
39127
39253
  import { mkdir as mkdir17, writeFile as writeFile16 } from "node:fs/promises";
39128
39254
  import { writeFileSync as writeFileSync4 } from "node:fs";
39129
39255
  import { tmpdir as tmpdir4 } from "node:os";
39130
- import { dirname as dirname21, join as join13 } from "node:path";
39256
+ import { dirname as dirname21, join as join14 } from "node:path";
39131
39257
  var CommandExecutionContext = class {
39132
39258
  generationId = randomUUID10();
39133
39259
  path;
39134
39260
  current;
39135
39261
  constructor(root) {
39136
- this.path = join13(root ?? tmpdir4(), `beeline-command-${this.generationId}.json`);
39262
+ this.path = join14(root ?? tmpdir4(), `beeline-command-${this.generationId}.json`);
39137
39263
  }
39138
39264
  async enter(command) {
39139
39265
  this.current = command;
@@ -39281,11 +39407,11 @@ async function runServerCommandIntake(options) {
39281
39407
  if (attempt === 3)
39282
39408
  throw error;
39283
39409
  const waitMs = Math.max(250 * 2 ** attempt, error instanceof DaemonApiError ? error.retryAfterMs ?? 0 : 0);
39284
- await new Promise((resolve42) => {
39410
+ await new Promise((resolve43) => {
39285
39411
  const done = () => {
39286
39412
  clearTimeout(timer);
39287
39413
  signal?.removeEventListener("abort", done);
39288
- resolve42();
39414
+ resolve43();
39289
39415
  };
39290
39416
  const timer = setTimeout(done, waitMs);
39291
39417
  signal?.addEventListener("abort", done, { once: true });
@@ -39376,11 +39502,11 @@ async function runServerCommandIntake(options) {
39376
39502
  }
39377
39503
  }
39378
39504
  options.onPoll?.();
39379
- const reconcile = await new Promise((resolve42) => {
39505
+ const reconcile = await new Promise((resolve43) => {
39380
39506
  const done = (needed) => {
39381
39507
  signal?.removeEventListener("abort", aborted);
39382
39508
  wake = void 0;
39383
- resolve42(needed);
39509
+ resolve43(needed);
39384
39510
  };
39385
39511
  const aborted = () => done(false);
39386
39512
  wake = done;
@@ -39422,9 +39548,9 @@ async function runServerCommandIntake(options) {
39422
39548
  // apps/body/dist/monolith-corner-turn.js
39423
39549
  import { execFile as execFile12 } from "node:child_process";
39424
39550
  import { createHash as createHash12 } from "node:crypto";
39425
- import { mkdir as mkdir25, readFile as readFile26, writeFile as writeFile20 } from "node:fs/promises";
39551
+ import { mkdir as mkdir25, readFile as readFile27, writeFile as writeFile20 } from "node:fs/promises";
39426
39552
  import { homedir as homedir17, hostname as hostname3 } from "node:os";
39427
- import { dirname as dirname25, join as join18, resolve as resolve34 } from "node:path";
39553
+ import { dirname as dirname25, join as join18, resolve as resolve35 } from "node:path";
39428
39554
  import { promisify as promisify7 } from "node:util";
39429
39555
 
39430
39556
  // apps/body/dist/agent-command-catalog.js
@@ -39443,7 +39569,7 @@ function agentCommandCatalogPublisher(input) {
39443
39569
 
39444
39570
  // apps/body/dist/attachment-delivery.js
39445
39571
  import { mkdir as mkdir18, writeFile as writeFile17 } from "node:fs/promises";
39446
- import { basename as basename8, extname, join as join14 } from "node:path";
39572
+ import { basename as basename8, extname, join as join15 } from "node:path";
39447
39573
  var MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024;
39448
39574
  var EXPIRED_REASON = "expired: these attachment bytes are past their retention window";
39449
39575
  var FETCH_TIMEOUT_MS = 3e4;
@@ -39493,6 +39619,10 @@ async function fetchBoundedBytes(url, fetchImpl = fetch) {
39493
39619
  return { status: response.status, ok: true, bytes, mimeType };
39494
39620
  }
39495
39621
  var MAX_INLINE_IMAGE_BYTES = 5 * 1024 * 1024;
39622
+ function safeAttachmentNames(attachments) {
39623
+ const taken = /* @__PURE__ */ new Set();
39624
+ return attachments.map((attachment, index) => safeFileName(attachment, index, taken));
39625
+ }
39496
39626
  function safeFileName(attachment, index, taken) {
39497
39627
  const raw = basename8(attachment.name ?? "").replace(/[^\w.-]+/g, "_").replace(/^\.+/, "");
39498
39628
  let name = raw || `attachment-${index + 1}`;
@@ -39506,8 +39636,7 @@ function safeFileName(attachment, index, taken) {
39506
39636
  async function deliverAttachments(attachments, dir, fetchImpl = fetch, cached = []) {
39507
39637
  if (!attachments.length)
39508
39638
  return [];
39509
- const taken = /* @__PURE__ */ new Set();
39510
- const names = attachments.map((attachment, index) => safeFileName(attachment, index, taken));
39639
+ const names = safeAttachmentNames(attachments);
39511
39640
  return Promise.all(attachments.map(async (attachment, index) => {
39512
39641
  const tooLarge = (bytes) => ({
39513
39642
  attachment,
@@ -39540,7 +39669,7 @@ async function deliverAttachments(attachments, dir, fetchImpl = fetch, cached =
39540
39669
  return { attachment, reason: EXPIRED_REASON };
39541
39670
  if (!fetched.ok)
39542
39671
  throw new Error(`HTTP ${fetched.status}`);
39543
- const path = join14(dir, names[index]);
39672
+ const path = join15(dir, names[index]);
39544
39673
  await writeFile17(path, fetched.bytes);
39545
39674
  const bytes = fetched.bytes;
39546
39675
  const mimeType = attachment.mimeType ?? fetched.mimeType;
@@ -39564,6 +39693,24 @@ async function deliverAttachments(attachments, dir, fetchImpl = fetch, cached =
39564
39693
  }
39565
39694
  }));
39566
39695
  }
39696
+ var MEDIA_ID = /\/v1\/media\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:[?#]|$)/i;
39697
+ function attachmentId(attachment) {
39698
+ return MEDIA_ID.exec(attachment.url)?.[1]?.toLowerCase();
39699
+ }
39700
+ function readableSize(bytes) {
39701
+ if (bytes < 1024)
39702
+ return `${bytes} B`;
39703
+ if (bytes < 1024 * 1024)
39704
+ return `${Math.round(bytes / 1024)} KB`;
39705
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
39706
+ }
39707
+ function attachmentMarkerLines(attachments) {
39708
+ return attachments.map((attachment) => {
39709
+ const metadata = [attachment.mimeType, attachment.size ? readableSize(attachment.size) : ""].filter(Boolean).join(", ");
39710
+ const id = attachmentId(attachment);
39711
+ return `\u{1F4CE} ${attachment.name ?? "attachment"}${metadata ? ` (${metadata})` : ""} ${id ? `id=${id}` : "id unavailable"}${attachment.expired ? " (expired)" : ""}`;
39712
+ });
39713
+ }
39567
39714
  function withoutImageData(delivered) {
39568
39715
  return delivered.map(({ image: _image, ...rest }) => rest);
39569
39716
  }
@@ -40034,7 +40181,7 @@ function mountedMcpSet(servers) {
40034
40181
 
40035
40182
  // apps/body/dist/pi-mcp-bridge.js
40036
40183
  import { execFile as execFile9 } from "node:child_process";
40037
- import { mkdtemp as mkdtemp2, mkdir as mkdir19, readFile as readFile22, rm as rm11, unlink as unlink8 } from "node:fs/promises";
40184
+ import { mkdtemp as mkdtemp2, mkdir as mkdir19, readFile as readFile23, rm as rm11, unlink as unlink8 } from "node:fs/promises";
40038
40185
  import { tmpdir as tmpdir5 } from "node:os";
40039
40186
  import { resolve as resolve28 } from "node:path";
40040
40187
  import { promisify as promisify5 } from "node:util";
@@ -40066,7 +40213,7 @@ async function piHasNativeMcp(command) {
40066
40213
  }
40067
40214
  async function isolatedPiConfig(piHome) {
40068
40215
  try {
40069
- const parsed = JSON.parse(await readFile22(resolve28(piHome, "mcp.json"), "utf8"));
40216
+ const parsed = JSON.parse(await readFile23(resolve28(piHome, "mcp.json"), "utf8"));
40070
40217
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
40071
40218
  } catch (error) {
40072
40219
  if (error.code !== "ENOENT")
@@ -40345,20 +40492,22 @@ export default async function (pi) {
40345
40492
 
40346
40493
  // apps/body/dist/corner-branch-sync.js
40347
40494
  import { execFile as execFile10 } from "node:child_process";
40495
+ import { access as access2, readFile as readFile24 } from "node:fs/promises";
40496
+ import { resolve as resolve29 } from "node:path";
40348
40497
  var CORNER_GIT_SYNC_TIMEOUT_MS = 12e4;
40349
40498
  var CORNER_GIT_SYNC_KILL_GRACE_MS = 1e3;
40350
40499
  var CornerGitSyncInterruptedError = class extends Error {
40351
40500
  };
40352
40501
  async function syncCornerBranch(input) {
40353
- const git = async (args) => {
40502
+ const git = async (args, cleanup = false) => {
40354
40503
  const controller = new AbortController();
40355
- const signal = input.signal ? AbortSignal.any([input.signal, controller.signal]) : controller.signal;
40504
+ const signal = input.signal && !cleanup ? AbortSignal.any([input.signal, controller.signal]) : controller.signal;
40356
40505
  const timer = setTimeout(() => controller.abort(), CORNER_GIT_SYNC_TIMEOUT_MS);
40357
40506
  const interrupted = () => new CornerGitSyncInterruptedError(`corner git sync ${args[0]} ${controller.signal.aborted ? `timed out after ${CORNER_GIT_SYNC_TIMEOUT_MS}ms` : "stopped"}`);
40358
40507
  try {
40359
40508
  if (signal.aborted)
40360
40509
  throw interrupted();
40361
- return await new Promise((resolve42, reject) => {
40510
+ return await new Promise((resolve43, reject) => {
40362
40511
  let killTimer;
40363
40512
  let stdout6 = "";
40364
40513
  let failure = null;
@@ -40372,35 +40521,41 @@ async function syncCornerBranch(input) {
40372
40521
  });
40373
40522
  const abort = () => {
40374
40523
  if (!child) {
40375
- cleanup();
40524
+ cleanup2();
40376
40525
  reject(interrupted());
40377
40526
  } else {
40378
40527
  killTimer = setTimeout(() => child.kill("SIGKILL"), CORNER_GIT_SYNC_KILL_GRACE_MS);
40379
40528
  }
40380
40529
  };
40381
40530
  signal.addEventListener("abort", abort, { once: true });
40382
- const cleanup = () => {
40531
+ const cleanup2 = () => {
40383
40532
  signal.removeEventListener("abort", abort);
40384
40533
  if (killTimer)
40385
40534
  clearTimeout(killTimer);
40386
40535
  };
40387
40536
  if (child)
40388
40537
  child.once("close", () => {
40389
- cleanup();
40538
+ cleanup2();
40390
40539
  if (signal.aborted)
40391
40540
  reject(interrupted());
40392
40541
  else if (failure)
40393
40542
  reject(failure);
40394
40543
  else
40395
- resolve42(stdout6);
40544
+ resolve43(stdout6);
40396
40545
  });
40397
40546
  else
40398
- input.git(args).then(resolve42, reject).finally(cleanup);
40547
+ input.git(args).then(resolve43, reject).finally(cleanup2);
40399
40548
  });
40400
40549
  } finally {
40401
40550
  clearTimeout(timer);
40402
40551
  }
40403
40552
  };
40553
+ const marker = await readFile24(resolve29(input.worktreePath, ".git"), "utf8").catch(() => "");
40554
+ const gitDir = resolve29(input.worktreePath, marker.startsWith("gitdir: ") ? marker.slice(8).trim() : ".git");
40555
+ for (const directory of ["rebase-merge", "rebase-apply"]) {
40556
+ if (await access2(resolve29(gitDir, directory)).then(() => true, () => false))
40557
+ await git(["rebase", "--abort"], true);
40558
+ }
40404
40559
  const remoteRef = `refs/remotes/origin/${input.featureBranch}`;
40405
40560
  const fetched = await git([
40406
40561
  "fetch",
@@ -40427,12 +40582,12 @@ async function syncCornerBranch(input) {
40427
40582
  await git(behind ? ["merge", "--ff-only", remote] : ["rebase", remote]);
40428
40583
  return behind ? "fast-forwarded" : "rebased";
40429
40584
  } catch (error) {
40430
- if (error instanceof CornerGitSyncInterruptedError)
40431
- throw error;
40432
- await git(["rebase", "--abort"]).catch((error2) => {
40585
+ await git(["rebase", "--abort"], true).catch((error2) => {
40433
40586
  if (error2 instanceof CornerGitSyncInterruptedError)
40434
40587
  throw error2;
40435
40588
  });
40589
+ if (error instanceof CornerGitSyncInterruptedError)
40590
+ throw error;
40436
40591
  await git(["reset", "--hard", remote]);
40437
40592
  return "realigned";
40438
40593
  }
@@ -40446,7 +40601,7 @@ async function contains(git, head, ancestor) {
40446
40601
  }
40447
40602
 
40448
40603
  // apps/body/dist/room-session.js
40449
- import { resolve as resolve29 } from "node:path";
40604
+ import { resolve as resolve30 } from "node:path";
40450
40605
 
40451
40606
  // apps/body/dist/read-only-policy.js
40452
40607
  var READ_ONLY_MCP_SERVER_NAME = "beeline-readonly-mcp";
@@ -40681,21 +40836,21 @@ function readOnlyMcpServer(config, cwd, agentMemoryDir) {
40681
40836
  command: config.readonlyMcpCommand,
40682
40837
  args: [...config.readonlyMcpArgs ?? []],
40683
40838
  env: [
40684
- { name: "BEELINE_READONLY_ROOT", value: resolve29(cwd) },
40839
+ { name: "BEELINE_READONLY_ROOT", value: resolve30(cwd) },
40685
40840
  ...config.agentHomeRoot ? [
40686
40841
  {
40687
40842
  name: "BEELINE_READONLY_AGENT_SKILLS_ROOT",
40688
- value: resolve29(config.agentHomeRoot, skillDir, "skills")
40843
+ value: resolve30(config.agentHomeRoot, skillDir, "skills")
40689
40844
  }
40690
40845
  ] : [],
40691
- ...agentMemoryDir ? [{ name: "BEELINE_READONLY_AGENT_MEMORY_ROOT", value: resolve29(agentMemoryDir) }] : []
40846
+ ...agentMemoryDir ? [{ name: "BEELINE_READONLY_AGENT_MEMORY_ROOT", value: resolve30(agentMemoryDir) }] : []
40692
40847
  ]
40693
40848
  };
40694
40849
  }
40695
40850
 
40696
40851
  // apps/body/dist/institutional-context.js
40697
40852
  import { performance as performance2 } from "node:perf_hooks";
40698
- var INSTITUTIONAL_CONTEXT_TIMEOUT_MS = 200;
40853
+ var INSTITUTIONAL_CONTEXT_TIMEOUT_MS = 500;
40699
40854
  var INSTITUTIONAL_MEMORY_LIVE_FLAG = "BEELINE_INSTITUTIONAL_MEMORY_ENABLED";
40700
40855
  function institutionalMemoryFlagEnabled(env, flag) {
40701
40856
  return env[flag] !== "false";
@@ -40742,15 +40897,15 @@ async function awaitInstitutionalContext(fetch2, log2 = console.warn, budgetMs =
40742
40897
 
40743
40898
  // apps/body/dist/codegraph.js
40744
40899
  import { execFile as execFile11 } from "node:child_process";
40745
- import { access as access2, appendFile, mkdir as mkdir20, readFile as readFile23 } from "node:fs/promises";
40746
- import { dirname as dirname22, isAbsolute as isAbsolute3, resolve as resolve30 } from "node:path";
40900
+ import { access as access3, appendFile, mkdir as mkdir20, readFile as readFile25 } from "node:fs/promises";
40901
+ import { dirname as dirname22, isAbsolute as isAbsolute3, resolve as resolve31 } from "node:path";
40747
40902
  import { promisify as promisify6 } from "node:util";
40748
40903
  var execFileAsync6 = promisify6(execFile11);
40749
40904
  var CODEGRAPH_MCP_SERVER_NAME = "codegraph";
40750
40905
  var CODEGRAPH_INDEX_PATH = ".codegraph/codegraph.db";
40751
40906
  var CODEGRAPH_PREPARE_TIMEOUT_MS = 12e4;
40752
40907
  function codegraphIndexDirectory(cwd) {
40753
- return resolve30(cwd, dirname22(CODEGRAPH_INDEX_PATH));
40908
+ return resolve31(cwd, dirname22(CODEGRAPH_INDEX_PATH));
40754
40909
  }
40755
40910
  function codegraphMcpServer(config, cwd, options) {
40756
40911
  if (!config.codegraphCommand)
@@ -40758,7 +40913,7 @@ function codegraphMcpServer(config, cwd, options) {
40758
40913
  return {
40759
40914
  name: CODEGRAPH_MCP_SERVER_NAME,
40760
40915
  command: config.codegraphCommand,
40761
- args: ["serve", "--mcp", "--path", resolve30(cwd), ...options.readonly ? ["--no-watch"] : []],
40916
+ args: ["serve", "--mcp", "--path", resolve31(cwd), ...options.readonly ? ["--no-watch"] : []],
40762
40917
  env: [
40763
40918
  { name: "CODEGRAPH_TELEMETRY", value: "0" },
40764
40919
  // One MCP child per harness session is easier to contain than a daemon
@@ -40776,7 +40931,7 @@ async function isGitWorktree(cwd) {
40776
40931
  cwd,
40777
40932
  timeout: 1e4
40778
40933
  });
40779
- return resolve30(stdout6.trim()) === resolve30(cwd);
40934
+ return resolve31(stdout6.trim()) === resolve31(cwd);
40780
40935
  } catch {
40781
40936
  return false;
40782
40937
  }
@@ -40790,9 +40945,9 @@ async function excludeIndexFromGitStatus(cwd) {
40790
40945
  const gitPath = stdout6.trim();
40791
40946
  if (!gitPath)
40792
40947
  return;
40793
- const path = isAbsolute3(gitPath) ? gitPath : resolve30(cwd, gitPath);
40948
+ const path = isAbsolute3(gitPath) ? gitPath : resolve31(cwd, gitPath);
40794
40949
  await mkdir20(dirname22(path), { recursive: true });
40795
- const existing = await readFile23(path, "utf8").catch(() => "");
40950
+ const existing = await readFile25(path, "utf8").catch(() => "");
40796
40951
  if (existing.split("\n").includes(".codegraph/"))
40797
40952
  return;
40798
40953
  await appendFile(path, `${existing && !existing.endsWith("\n") ? "\n" : ""}.codegraph/
@@ -40805,8 +40960,8 @@ async function prepareCodegraphIndex(config, cwd) {
40805
40960
  if (!command || !await isGitWorktree(cwd))
40806
40961
  return false;
40807
40962
  await excludeIndexFromGitStatus(cwd);
40808
- const indexPath = resolve30(cwd, CODEGRAPH_INDEX_PATH);
40809
- const indexed = await access2(indexPath).then(() => true, () => false);
40963
+ const indexPath = resolve31(cwd, CODEGRAPH_INDEX_PATH);
40964
+ const indexed = await access3(indexPath).then(() => true, () => false);
40810
40965
  const args = indexed ? ["sync", "--quiet", cwd] : ["init", "--yes", cwd];
40811
40966
  try {
40812
40967
  await execFileAsync6(command, args, {
@@ -40831,31 +40986,9 @@ import { dirname as dirname23, join as join16 } from "node:path";
40831
40986
  var SCHEDULE_SCHEDULER_NAME = "Beeline Scheduler";
40832
40987
  var SCHEDULE_RAN_VERB = "ran a schedule for";
40833
40988
 
40834
- // apps/body/dist/model-context-window.js
40835
- import { readFile as readFile24 } from "node:fs/promises";
40836
- import { join as join15 } from "node:path";
40837
- async function modelContextWindowTokens(model, piHome) {
40838
- if (!model || !piHome)
40839
- return void 0;
40840
- try {
40841
- const catalog = JSON.parse(await readFile24(join15(piHome, "models.json"), "utf8"));
40842
- const parts = model.split("/");
40843
- const preferredProvider = parts.length > 2 ? parts.shift() : void 0;
40844
- const modelId = parts.join("/");
40845
- const providers = preferredProvider ? [catalog.providers?.[preferredProvider]].filter(Boolean) : Object.values(catalog.providers ?? {});
40846
- for (const provider of providers) {
40847
- const window = provider?.models?.find((entry) => entry.id === modelId)?.contextWindow;
40848
- if (window && Number.isFinite(window) && window > 0)
40849
- return Math.floor(window);
40850
- }
40851
- } catch {
40852
- }
40853
- return void 0;
40854
- }
40855
-
40856
40989
  // apps/body/dist/turn-trace.js
40857
40990
  import { appendFile as appendFile2, mkdir as mkdir21, readdir as readdir7, rm as rm12 } from "node:fs/promises";
40858
- import { resolve as resolve31 } from "node:path";
40991
+ import { resolve as resolve32 } from "node:path";
40859
40992
  import { performance as performance3 } from "node:perf_hooks";
40860
40993
  var TURN_PHASES = [
40861
40994
  /** Enqueued on `SessionScheduler` until this turn holds a slot. A capacity wait lives here. */
@@ -40891,6 +41024,7 @@ var TurnTrace = class {
40891
41024
  atAdmission;
40892
41025
  finished = false;
40893
41026
  promptSections;
41027
+ promptWindow;
40894
41028
  searchMemoryCalls;
40895
41029
  searchMemoryMisses;
40896
41030
  /** Every distinct tool call id this turn has seen, across retries. */
@@ -40972,6 +41106,10 @@ var TurnTrace = class {
40972
41106
  notePromptSections(report) {
40973
41107
  this.promptSections = Object.fromEntries(report.map((entry) => [entry.id, entry.bytes]));
40974
41108
  }
41109
+ /** Assembled text only; the harness's tool schema is outside this measurement. */
41110
+ notePromptWindow(prompt, modelContextTokens) {
41111
+ this.promptWindow = modelContextTokens === void 0 ? void 0 : { promptBytes: Buffer.byteLength(prompt), modelContextTokens };
41112
+ }
40975
41113
  /** The prompt left for the harness. Idempotent: a steer resume is the same attempt. */
40976
41114
  promptSent() {
40977
41115
  this.current.promptSentAt ??= this.now();
@@ -41081,6 +41219,7 @@ var TurnTrace = class {
41081
41219
  ...this.atAdmission ? { atAdmission: this.atAdmission } : {}
41082
41220
  },
41083
41221
  ...this.promptSections ? { promptSections: this.promptSections } : {},
41222
+ ...this.promptWindow ? { promptWindow: this.promptWindow } : {},
41084
41223
  ...this.searchMemoryCalls !== void 0 ? { searchMemoryCalls: this.searchMemoryCalls, searchMemoryMisses: this.searchMemoryMisses ?? 0 } : {}
41085
41224
  };
41086
41225
  }
@@ -41135,7 +41274,7 @@ function formatTurnTraceLine(record5) {
41135
41274
  return [head, ...record5.attempts.map((attempt) => formatTurnAttempt(attempt))].join("\n ");
41136
41275
  }
41137
41276
  function turnTraceDirectory(runtimeDir) {
41138
- return resolve31(runtimeDir, "turn-traces");
41277
+ return resolve32(runtimeDir, "turn-traces");
41139
41278
  }
41140
41279
  var TURN_TRACE_RETENTION_DAYS = 7;
41141
41280
  function traceFileName(date) {
@@ -41152,7 +41291,7 @@ var TurnTraceFile = class {
41152
41291
  this.options = options;
41153
41292
  }
41154
41293
  path(now2 = (this.options.clock ?? (() => /* @__PURE__ */ new Date()))()) {
41155
- return resolve31(this.directory, traceFileName(now2));
41294
+ return resolve32(this.directory, traceFileName(now2));
41156
41295
  }
41157
41296
  write(record5) {
41158
41297
  this.tail = this.tail.catch(() => void 0).then(async () => {
@@ -41176,7 +41315,7 @@ var TurnTraceFile = class {
41176
41315
  this.prunedDay = day;
41177
41316
  const cutoff = traceFileName(new Date(now2.getTime() - TURN_TRACE_RETENTION_DAYS * 864e5));
41178
41317
  const names = await readdir7(this.directory).catch(() => []);
41179
- await Promise.all(names.filter((name) => /^turns-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name) && name < cutoff).map((name) => rm12(resolve31(this.directory, name), { force: true })));
41318
+ await Promise.all(names.filter((name) => /^turns-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name) && name < cutoff).map((name) => rm12(resolve32(this.directory, name), { force: true })));
41180
41319
  }
41181
41320
  };
41182
41321
 
@@ -41224,7 +41363,7 @@ var WarmTranscript = class {
41224
41363
  };
41225
41364
 
41226
41365
  // apps/body/dist/monolith-room-turn.js
41227
- var ROOM_PROMPT_INACTIVITY_TIMEOUT_MS = 18e4;
41366
+ var ROOM_PROMPT_BACKSTOP_MS = TURN_BACKSTOP_MS;
41228
41367
  function isRoomMcpPermissionRequest(request, mountedServers = ROOM_MOUNTED_MCP_SERVERS, hostServers = CODE_OWNED_HOST_MCP_NAMES) {
41229
41368
  if (isHostMcpPermissionRequest(request, hostServers))
41230
41369
  return false;
@@ -41344,6 +41483,7 @@ var MonolithRoomTurnLoop = class {
41344
41483
  * and the terminal receipt is posted on a path that may run after it.
41345
41484
  */
41346
41485
  turnMetrics = {};
41486
+ turnUsage = new TurnUsageAccumulator();
41347
41487
  /** OpenRouter providers this activation pinned, in order (C92). */
41348
41488
  pinnedProviders = [];
41349
41489
  /** The one provider re-pinned after an empty completion, until the session ends. */
@@ -41523,10 +41663,10 @@ var MonolithRoomTurnLoop = class {
41523
41663
  * Missing numbers are omitted rather than zeroed.
41524
41664
  */
41525
41665
  async captureTurnMetrics() {
41526
- const usage2 = this.sessionId ? await readHarnessTurnUsage({ agentEnv: this.agentEnv, sessionId: this.sessionId }) : void 0;
41666
+ const { model: _model, ...usage2 } = this.turnUsage.usage ?? {};
41527
41667
  const promptBytes = this.client?.lastPromptBytes;
41528
41668
  return {
41529
- ...usage2 ? { inputTokens: usage2.inputTokens } : {},
41669
+ ...usage2,
41530
41670
  ...promptBytes ? { promptBytes } : {}
41531
41671
  };
41532
41672
  }
@@ -42013,6 +42153,7 @@ var MonolithRoomTurnLoop = class {
42013
42153
  const api = this.options.api;
42014
42154
  this.busy = true;
42015
42155
  this.turnMetrics = {};
42156
+ this.turnUsage = new TurnUsageAccumulator();
42016
42157
  const trace = this.beginTurnTrace(item.id);
42017
42158
  const institutionalContextFetch = startInstitutionalContextFetch(api, this.options.roomId);
42018
42159
  let statsStartedAt = 0;
@@ -42033,8 +42174,8 @@ var MonolithRoomTurnLoop = class {
42033
42174
  let timer;
42034
42175
  const stats = statsPromise && remaining > 0 ? await Promise.race([
42035
42176
  statsPromise,
42036
- new Promise((resolve42) => {
42037
- timer = setTimeout(() => resolve42(void 0), remaining);
42177
+ new Promise((resolve43) => {
42178
+ timer = setTimeout(() => resolve43(void 0), remaining);
42038
42179
  })
42039
42180
  ]).finally(() => {
42040
42181
  if (timer)
@@ -42095,7 +42236,7 @@ var MonolithRoomTurnLoop = class {
42095
42236
  const transcriptRows = conversation.items.filter((message) => message.type === "message" && message.id !== item.id && !active.steers.some((steerItem) => steerItem.id === message.id)).slice(-80).map((message) => ({
42096
42237
  id: message.id,
42097
42238
  authorId: message.authorId,
42098
- line: roomMessagePrompt(names.get(message.authorId) ?? message.authorId.slice(0, 12), message.body, message.attachments, this.deliveredAttachments.get(message.id), this.acceptsImages(), message.id)
42239
+ line: transcriptMessagePrompt(names.get(message.authorId) ?? message.authorId.slice(0, 12), message.body, message.attachments, message.id)
42099
42240
  }));
42100
42241
  const command = this.commandContext.current;
42101
42242
  const grantDecision = command?.action === "resume";
@@ -42133,6 +42274,7 @@ var MonolithRoomTurnLoop = class {
42133
42274
  }
42134
42275
  });
42135
42276
  trace.notePromptSections(assembled.report);
42277
+ trace.notePromptWindow(assembled.text, this.modelContextTokens);
42136
42278
  this.commandContext.notePromptSections([
42137
42279
  ...this.sessionPromptSectionIds,
42138
42280
  ...assembled.report.map((section) => section.id)
@@ -42156,14 +42298,14 @@ var MonolithRoomTurnLoop = class {
42156
42298
  try {
42157
42299
  stream.beginRun();
42158
42300
  trace.promptSent();
42159
- result2 = await this.client.sessionPrompt(this.sessionId, nextPrompt, ROOM_PROMPT_INACTIVITY_TIMEOUT_MS, (delta, full, currentRun) => {
42301
+ result2 = await this.turnUsage.measure({ agentEnv: this.agentEnv, sessionId: this.sessionId }, () => this.client.sessionPrompt(this.sessionId, nextPrompt, ROOM_PROMPT_BACKSTOP_MS, (delta, full, currentRun) => {
42160
42302
  trace.firstModelOutput();
42161
42303
  stream.onChunk(delta, full, currentRun);
42162
42304
  }, void 0, (calls) => {
42163
42305
  trace.toolCalls(calls);
42164
42306
  if (openedACorner(openCornerToolCall(calls)))
42165
42307
  liveCornerOpened = true;
42166
- });
42308
+ }));
42167
42309
  } catch (error) {
42168
42310
  promptError = error;
42169
42311
  }
@@ -42306,8 +42448,8 @@ var MonolithRoomTurnLoop = class {
42306
42448
  void finishTrace("cancelled").catch(() => void 0);
42307
42449
  return;
42308
42450
  }
42309
- if (liveCornerOpened && error instanceof AcpRequestTimeoutError && error.inactivity && error.method === "session/prompt") {
42310
- console.log(`[thin-core] monolith Room ${this.options.roomId} turn ${item.id}: inactivity timeout after opening a corner; the work continues in the corner`);
42451
+ if (liveCornerOpened && error instanceof AcpTurnBackstopError) {
42452
+ console.log(`[thin-core] monolith Room ${this.options.roomId} turn ${item.id}: turn_backstop after opening a corner; the work continues in the corner`);
42311
42453
  this.options.onCornerOpened?.();
42312
42454
  const lastRun = liveStream?.lastRunText ?? "";
42313
42455
  const streamed = isPureRetryNarration(lastRun) ? "" : durableReplyText(lastRun);
@@ -42330,8 +42472,6 @@ var MonolithRoomTurnLoop = class {
42330
42472
  void finishTrace("complete").catch(() => void 0);
42331
42473
  return;
42332
42474
  }
42333
- if (isSilentPromptTimeout(error))
42334
- await this.discardSession().catch(() => void 0);
42335
42475
  await liveStream?.retract().catch((retractError) => {
42336
42476
  console.error(`[thin-core] monolith Room ${this.options.roomId} draft retract failed:`, retractError);
42337
42477
  });
@@ -42422,6 +42562,13 @@ function openCornerToolCall(calls) {
42422
42562
  function openedACorner(call) {
42423
42563
  return !!call && isCompletedToolCall(call);
42424
42564
  }
42565
+ function transcriptMessagePrompt(author, body, attachments, messageId) {
42566
+ return [
42567
+ `[message id: ${messageId}]`,
42568
+ `${author}: ${body.trim() || "(shared attachments)"}`,
42569
+ ...attachmentMarkerLines(attachments)
42570
+ ].join("\n");
42571
+ }
42425
42572
  function roomMessagePrompt(author, body, attachments, delivered, harnessAcceptsImages = true, messageId) {
42426
42573
  const message = body.trim() || "(shared attachments)";
42427
42574
  const rendered = author ? `${author}: ${message}` : message;
@@ -42434,9 +42581,9 @@ function roomMessagePrompt(author, body, attachments, delivered, harnessAcceptsI
42434
42581
 
42435
42582
  // apps/body/dist/corner-github-auth.js
42436
42583
  import { chmod as chmod9, mkdir as mkdir23, writeFile as writeFile19 } from "node:fs/promises";
42437
- import { delimiter as delimiter2, resolve as resolve32 } from "node:path";
42584
+ import { delimiter as delimiter2, resolve as resolve33 } from "node:path";
42438
42585
  async function installCornerGitHubWrappers(input) {
42439
- const bin = resolve32(input.root, "beeline-github-bin");
42586
+ const bin = resolve33(input.root, "beeline-github-bin");
42440
42587
  await mkdir23(bin, { recursive: true, mode: 448 });
42441
42588
  const common = {
42442
42589
  node: process.execPath,
@@ -42446,13 +42593,13 @@ async function installCornerGitHubWrappers(input) {
42446
42593
  featureBranch: input.featureBranch,
42447
42594
  targetBranch: input.targetBranch
42448
42595
  };
42449
- await writeLauncher(resolve32(bin, "git"), {
42596
+ await writeLauncher(resolve33(bin, "git"), {
42450
42597
  ...common,
42451
42598
  command: input.gitBinary,
42452
42599
  launcher: "git"
42453
42600
  });
42454
42601
  if (input.ghBinary)
42455
- await writeLauncher(resolve32(bin, "gh"), {
42602
+ await writeLauncher(resolve33(bin, "gh"), {
42456
42603
  ...common,
42457
42604
  command: input.ghBinary,
42458
42605
  launcher: "gh"
@@ -42591,29 +42738,29 @@ process.exit(result.status ?? 1);
42591
42738
  // apps/body/dist/warm-node-modules.js
42592
42739
  import { createHash as createHash11, randomUUID as randomUUID11 } from "node:crypto";
42593
42740
  import { constants as fsConstants3 } from "node:fs";
42594
- import { chmod as chmod10, copyFile as copyFile2, link, lstat as lstat4, mkdir as mkdir24, readdir as readdir8, readFile as readFile25, readlink as readlink2, rename as rename9, rm as rm13, stat as stat8, symlink as symlink3, utimes } from "node:fs/promises";
42595
- import { dirname as dirname24, join as join17, resolve as resolve33 } from "node:path";
42741
+ import { chmod as chmod10, copyFile as copyFile2, link, lstat as lstat4, mkdir as mkdir24, readdir as readdir8, readFile as readFile26, readlink as readlink2, rename as rename9, rm as rm13, stat as stat8, symlink as symlink3, utimes } from "node:fs/promises";
42742
+ import { dirname as dirname24, join as join17, resolve as resolve34 } from "node:path";
42596
42743
  var STORE_FORMAT = "v1";
42597
42744
  var STAGING_PREFIX = ".beeline-warm-";
42598
42745
  var STAGING_SWEEP_MS = 24 * 60 * 60 * 1e3;
42599
42746
  var WARM_STORE_MAX_ENTRIES = 3;
42600
42747
  function sharedNpmCacheDir(supervisorRoot) {
42601
- return resolve33(supervisorRoot, "beeline", "npm-cache");
42748
+ return resolve34(supervisorRoot, "beeline", "npm-cache");
42602
42749
  }
42603
42750
  function sharedPnpmStoreDir(supervisorRoot) {
42604
- return resolve33(supervisorRoot, "beeline", "pnpm-store");
42751
+ return resolve34(supervisorRoot, "beeline", "pnpm-store");
42605
42752
  }
42606
42753
  function sharedCargoTargetDir(supervisorRoot) {
42607
- return resolve33(supervisorRoot, "beeline", "cargo-target");
42754
+ return resolve34(supervisorRoot, "beeline", "cargo-target");
42608
42755
  }
42609
42756
  function warmNodeModulesStoreDir(supervisorRoot) {
42610
- return resolve33(supervisorRoot, "beeline", "node-modules");
42757
+ return resolve34(supervisorRoot, "beeline", "node-modules");
42611
42758
  }
42612
42759
  function isPlanRefusal(value) {
42613
42760
  return "failure" in value;
42614
42761
  }
42615
42762
  async function readWarmPlan(worktreePath) {
42616
- const lockfile = await readFile25(resolve33(worktreePath, "package-lock.json")).catch(() => void 0);
42763
+ const lockfile = await readFile26(resolve34(worktreePath, "package-lock.json")).catch(() => void 0);
42617
42764
  if (!lockfile)
42618
42765
  return { failure: "no-lockfile" };
42619
42766
  const packages = parseLockfilePackages(lockfile);
@@ -42652,11 +42799,11 @@ async function seedWarmNodeModules(input) {
42652
42799
  return { reason: plan.failure, ...plan.detail ? { detail: plan.detail } : {} };
42653
42800
  }
42654
42801
  for (const tree of plan.trees) {
42655
- if (await pathExists(resolve33(input.worktreePath, tree))) {
42802
+ if (await pathExists(resolve34(input.worktreePath, tree))) {
42656
42803
  return { reason: "present", key: plan.key };
42657
42804
  }
42658
42805
  }
42659
- const entry = resolve33(input.storeRoot, plan.key);
42806
+ const entry = resolve34(input.storeRoot, plan.key);
42660
42807
  if (!await isDirectory(entry))
42661
42808
  return { reason: "cold", key: plan.key };
42662
42809
  const [storeDevice, checkoutDevice] = await Promise.all([
@@ -42666,19 +42813,19 @@ async function seedWarmNodeModules(input) {
42666
42813
  if (storeDevice === void 0 || storeDevice !== checkoutDevice) {
42667
42814
  return { reason: "cross-device", key: plan.key };
42668
42815
  }
42669
- const staging = resolve33(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID11()}`);
42816
+ const staging = resolve34(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID11()}`);
42670
42817
  const placed = [];
42671
42818
  const now2 = (input.now ?? Date.now)();
42672
42819
  try {
42673
42820
  await sweepStaleStaging(input.storeRoot, now2);
42674
42821
  await utimes(entry, now2 / 1e3, now2 / 1e3).catch(() => void 0);
42675
42822
  for (const tree of plan.trees) {
42676
- await cloneTree(resolve33(entry, tree), resolve33(staging, tree), seedFile);
42823
+ await cloneTree(resolve34(entry, tree), resolve34(staging, tree), seedFile);
42677
42824
  }
42678
42825
  for (const tree of plan.trees) {
42679
- const target = resolve33(input.worktreePath, tree);
42826
+ const target = resolve34(input.worktreePath, tree);
42680
42827
  await mkdir24(dirname24(target), { recursive: true });
42681
- await rename9(resolve33(staging, tree), target);
42828
+ await rename9(resolve34(staging, tree), target);
42682
42829
  placed.push(target);
42683
42830
  }
42684
42831
  return { reason: "seeded", key: plan.key };
@@ -42696,11 +42843,11 @@ async function harvestWarmNodeModules(input) {
42696
42843
  if (isPlanRefusal(plan)) {
42697
42844
  return { reason: plan.failure, ...plan.detail ? { detail: plan.detail } : {} };
42698
42845
  }
42699
- const entry = resolve33(input.storeRoot, plan.key);
42846
+ const entry = resolve34(input.storeRoot, plan.key);
42700
42847
  if (await pathExists(entry))
42701
42848
  return { reason: "already-warm", key: plan.key };
42702
42849
  for (const tree of plan.trees) {
42703
- if (!await isDirectory(resolve33(input.worktreePath, tree))) {
42850
+ if (!await isDirectory(resolve34(input.worktreePath, tree))) {
42704
42851
  return { reason: "no-node-modules", key: plan.key, detail: tree };
42705
42852
  }
42706
42853
  }
@@ -42712,12 +42859,12 @@ async function harvestWarmNodeModules(input) {
42712
42859
  detail: `${missing.length} absent, e.g. ${missing.slice(0, 3).join(", ")}`
42713
42860
  };
42714
42861
  }
42715
- const staging = resolve33(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID11()}`);
42862
+ const staging = resolve34(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID11()}`);
42716
42863
  try {
42717
42864
  await mkdir24(input.storeRoot, { recursive: true, mode: 493 });
42718
42865
  await sweepStaleStaging(input.storeRoot, (input.now ?? Date.now)());
42719
42866
  for (const tree of plan.trees) {
42720
- await cloneTree(resolve33(input.worktreePath, tree), resolve33(staging, tree), harvestFile);
42867
+ await cloneTree(resolve34(input.worktreePath, tree), resolve34(staging, tree), harvestFile);
42721
42868
  }
42722
42869
  await input.onCopied?.();
42723
42870
  if (!await stagedTreeIsPublishable(input.worktreePath, staging, plan.key)) {
@@ -42740,16 +42887,16 @@ async function stagedTreeIsPublishable(worktreePath, staging, key) {
42740
42887
  return false;
42741
42888
  const hidden = join17("node_modules", ".package-lock.json");
42742
42889
  const [copied, current] = await Promise.all([
42743
- readFile25(resolve33(staging, hidden)).catch(() => void 0),
42744
- readFile25(resolve33(worktreePath, hidden)).catch(() => void 0)
42890
+ readFile26(resolve34(staging, hidden)).catch(() => void 0),
42891
+ readFile26(resolve34(worktreePath, hidden)).catch(() => void 0)
42745
42892
  ]);
42746
42893
  if (!copied || !current || !copied.equals(current))
42747
42894
  return false;
42748
42895
  return (await missingInstalledPackages(worktreePath, staging)).length === 0;
42749
42896
  }
42750
42897
  async function missingInstalledPackages(worktreePath, treeRoot = worktreePath) {
42751
- const wanted = parseLockfilePackages(await readFile25(resolve33(worktreePath, "package-lock.json")).catch(() => void 0));
42752
- const installed = parseLockfilePackages(await readFile25(resolve33(treeRoot, "node_modules", ".package-lock.json")).catch(() => void 0));
42898
+ const wanted = parseLockfilePackages(await readFile26(resolve34(worktreePath, "package-lock.json")).catch(() => void 0));
42899
+ const installed = parseLockfilePackages(await readFile26(resolve34(treeRoot, "node_modules", ".package-lock.json")).catch(() => void 0));
42753
42900
  if (!wanted)
42754
42901
  return ["package-lock.json is unreadable"];
42755
42902
  if (!installed)
@@ -42769,7 +42916,7 @@ async function missingInstalledPackages(worktreePath, treeRoot = worktreePath) {
42769
42916
  required.push(path);
42770
42917
  }
42771
42918
  await mapWithLimit(required, INTEGRITY_READ_CONCURRENCY, async (path) => {
42772
- if (!(path in installed) || !await isInstalledPackage(resolve33(treeRoot, path))) {
42919
+ if (!(path in installed) || !await isInstalledPackage(resolve34(treeRoot, path))) {
42773
42920
  missing.push(path);
42774
42921
  }
42775
42922
  });
@@ -43119,6 +43266,8 @@ var MonolithCornerTurnLoop = class {
43119
43266
  * and the terminal receipt is posted on a path that may run after it.
43120
43267
  */
43121
43268
  turnMetrics = {};
43269
+ turnUsage = new TurnUsageAccumulator();
43270
+ modelContextTokens;
43122
43271
  /** OpenRouter providers this activation pinned, in order (C92). */
43123
43272
  pinnedProviders = [];
43124
43273
  /** Whether the pinned model takes images; `undefined` when the pin did not say. */
@@ -43266,10 +43415,10 @@ var MonolithCornerTurnLoop = class {
43266
43415
  * Missing numbers are omitted rather than zeroed.
43267
43416
  */
43268
43417
  async captureTurnMetrics() {
43269
- const usage2 = this.sessionId ? await readHarnessTurnUsage({ agentEnv: this.agentEnv, sessionId: this.sessionId }) : void 0;
43418
+ const { model: _model, ...usage2 } = this.turnUsage.usage ?? {};
43270
43419
  const promptBytes = this.client?.lastPromptBytes;
43271
43420
  return {
43272
- ...usage2 ? { inputTokens: usage2.inputTokens } : {},
43421
+ ...usage2,
43273
43422
  ...promptBytes ? { promptBytes } : {}
43274
43423
  };
43275
43424
  }
@@ -43466,6 +43615,7 @@ var MonolithCornerTurnLoop = class {
43466
43615
  CARGO_TARGET_DIR: cargoTargetDir
43467
43616
  };
43468
43617
  this.agentEnv = agentEnv;
43618
+ this.modelContextTokens = await modelContextWindowTokens(selection.model, agentEnv.PI_CODING_AGENT_DIR);
43469
43619
  const agentArgs = agentArgsWithModelSelection({
43470
43620
  kind: this.options.config.agentKind,
43471
43621
  command,
@@ -43693,7 +43843,7 @@ var MonolithCornerTurnLoop = class {
43693
43843
  briefRevision: restore.brief?.revision
43694
43844
  }),
43695
43845
  ...this.options.config.agentHomeRoot && this.options.config.agentKind && !AGENT_SKILL_DIRS.includes(this.options.config.agentKind) ? [
43696
- `This harness has no verified native skill discovery. Read the release-managed review procedure at ${resolve34(this.options.config.agentHomeRoot, "codex", "skills", "beeline-review", "SKILL.md")} before the verdict.`
43846
+ `This harness has no verified native skill discovery. Read the release-managed review procedure at ${resolve35(this.options.config.agentHomeRoot, "codex", "skills", "beeline-review", "SKILL.md")} before the verdict.`
43697
43847
  ] : []
43698
43848
  ].join("\n");
43699
43849
  } catch {
@@ -43825,8 +43975,8 @@ var MonolithCornerTurnLoop = class {
43825
43975
  let timer;
43826
43976
  const stats = statsPromise && remaining > 0 ? await Promise.race([
43827
43977
  statsPromise,
43828
- new Promise((resolve42) => {
43829
- timer = setTimeout(() => resolve42(void 0), remaining);
43978
+ new Promise((resolve43) => {
43979
+ timer = setTimeout(() => resolve43(void 0), remaining);
43830
43980
  })
43831
43981
  ]).finally(() => {
43832
43982
  if (timer)
@@ -43856,6 +44006,7 @@ var MonolithCornerTurnLoop = class {
43856
44006
  throw new Error("corner turn stopped for daemon handoff");
43857
44007
  this.busy = true;
43858
44008
  this.turnMetrics = {};
44009
+ this.turnUsage = new TurnUsageAccumulator();
43859
44010
  await this.syncBranch();
43860
44011
  const [conversation, roster, restored, activeReviewerInstruction, institutionalContext, memberCorners] = await trace.measure("context-fetch", () => Promise.all([
43861
44012
  api.execute("getRoomConversation", {
@@ -43883,7 +44034,7 @@ var MonolithCornerTurnLoop = class {
43883
44034
  const delivered = this.attachmentDir && allAttachments.length ? await deliverAttachments(allAttachments, join18(this.attachmentDir, requestId.replace(/[^\w-]/g, "_")), this.options.fetchImpl) : [];
43884
44035
  const briefFileLines = await Promise.all((restored.brief?.attachments ?? []).map(async (file, index) => {
43885
44036
  const entry = delivered.find((item) => item.attachment === briefAttachments[index]);
43886
- const verified = entry?.path && createHash12("sha256").update(await readFile26(entry.path)).digest("hex") === file.sha256;
44037
+ const verified = entry?.path && createHash12("sha256").update(await readFile27(entry.path)).digest("hex") === file.sha256;
43887
44038
  return `- ${file.title} (${file.purpose}; ${file.required ? "required" : "optional"}; sha256 ${file.sha256}): ${verified ? entry.path : "UNAVAILABLE OR CONTENT MISMATCH"}`;
43888
44039
  }));
43889
44040
  const missingRequiredBriefFile = (restored.brief?.attachments ?? []).some((file, index) => file.required && briefFileLines[index]?.includes("UNAVAILABLE OR CONTENT MISMATCH"));
@@ -43891,18 +44042,20 @@ var MonolithCornerTurnLoop = class {
43891
44042
  const requestedBy = requester && !requester.name && names.get(requester.pubkey) ? { ...requester, name: names.get(requester.pubkey) } : requester;
43892
44043
  if (requestedBy)
43893
44044
  this.currentTurn = { requestId, requester: requestedBy };
43894
- const transcriptRows = conversation.items.filter((message) => message.id !== requestId && message.id !== sourceMessageId && message.body.trim()).slice(-120).map((message) => ({
44045
+ const transcriptRows = conversation.items.filter((message) => message.id !== requestId && message.id !== sourceMessageId && (message.body.trim() || message.attachments?.length)).slice(-120).map((message) => ({
43895
44046
  id: message.id,
43896
44047
  authorId: message.authorId,
43897
44048
  line: [
43898
44049
  ...message.type === "message" ? [`[message id: ${message.id}]`] : [],
43899
- `${names.get(message.authorId) ?? "Beeline"} [${message.type}]: ${message.body}`
44050
+ `${names.get(message.authorId) ?? "Beeline"} [${message.type}]: ${message.body.trim() ? message.body : "(shared attachments)"}`,
44051
+ ...attachmentMarkerLines(message.attachments ?? [])
43900
44052
  ].join("\n")
43901
44053
  }));
43902
44054
  const buildPrompt = () => {
43903
44055
  const transcript = this.warmTranscript.select(this.sessionId, transcriptRows, this.agent.publicKey);
43904
44056
  const assembled = assembleTurnPrompt({
43905
44057
  surface: this.sessionSurface,
44058
+ modelContextTokens: this.modelContextTokens,
43906
44059
  sessionPrefix: this.turnSessionPrefix,
43907
44060
  objective: this.options.objective,
43908
44061
  ...restored.titleGenerated && restored.title ? { generatedTitle: restored.title } : {},
@@ -43928,6 +44081,7 @@ var MonolithCornerTurnLoop = class {
43928
44081
  }
43929
44082
  });
43930
44083
  trace.notePromptSections(assembled.report);
44084
+ trace.notePromptWindow(assembled.text, this.modelContextTokens);
43931
44085
  this.commandContext.notePromptSections([
43932
44086
  ...this.sessionPromptSectionIds,
43933
44087
  ...assembled.report.map((section) => section.id)
@@ -44042,7 +44196,7 @@ var MonolithCornerTurnLoop = class {
44042
44196
  narrationRunBoundary = 0;
44043
44197
  currentNarrationRun = "";
44044
44198
  trace.promptSent();
44045
- return this.client.sessionPrompt(this.sessionId, promptWithImages(prompt, attachmentImageBlocks(delivered, this.acceptsImages())), ROOM_PROMPT_INACTIVITY_TIMEOUT_MS, (delta, full, currentRun, runs) => {
44199
+ return this.turnUsage.measure({ agentEnv: this.agentEnv, sessionId: this.sessionId }, () => this.client.sessionPrompt(this.sessionId, promptWithImages(prompt, attachmentImageBlocks(delivered, this.acceptsImages())), ROOM_PROMPT_BACKSTOP_MS, (delta, full, currentRun, runs) => {
44046
44200
  trace.firstModelOutput();
44047
44201
  if (runs) {
44048
44202
  completedNarrationRuns = runs.slice(narrationRunBoundary);
@@ -44059,7 +44213,7 @@ var MonolithCornerTurnLoop = class {
44059
44213
  trace.toolCalls(calls);
44060
44214
  publishToolCalls(calls, true);
44061
44215
  publishToolCalls(calls, false, lastNarratedToolCall);
44062
- });
44216
+ }));
44063
44217
  };
44064
44218
  let loginRetryUsed = false;
44065
44219
  const runPrompt = async (prompt = buildPrompt()) => {
@@ -44205,7 +44359,7 @@ ${deviceGrantResumePrompt(grantedDevice, result.agentText)}`);
44205
44359
  await trace.measure("publish", () => stream.settle(repeatedNarration ? "" : durableReply, durableReply && !repeatedNarration ? {
44206
44360
  ...requestedById ? { triggerMessageId: requestId } : {}
44207
44361
  } : {}));
44208
- }, { priority: "interactive", roomKey: cornerId });
44362
+ }, { priority: "interactive", roomKey: this.options.parentRoomId });
44209
44363
  }, (error) => console.error(`[thin-core] corner ${cornerId} receipt heartbeat failed:`, error));
44210
44364
  if (laneUpgraded) {
44211
44365
  void finishTrace("complete").catch(() => void 0);
@@ -44235,8 +44389,6 @@ ${deviceGrantResumePrompt(grantedDevice, result.agentText)}`);
44235
44389
  void finishTrace("complete").catch(() => void 0);
44236
44390
  return;
44237
44391
  }
44238
- if (isSilentPromptTimeout(error))
44239
- await this.discardSession().catch(() => void 0);
44240
44392
  const reason = distillTurnFailureReason(error);
44241
44393
  startTraceStats();
44242
44394
  await api.execute("postAgentTurnReceipt", {
@@ -44312,7 +44464,7 @@ ${deviceGrantResumePrompt(grantedDevice, result.agentText)}`);
44312
44464
  } catch (error) {
44313
44465
  if (attempt === 2)
44314
44466
  throw error;
44315
- await new Promise((resolve42) => setTimeout(resolve42, 250 * (attempt + 1)));
44467
+ await new Promise((resolve43) => setTimeout(resolve43, 250 * (attempt + 1)));
44316
44468
  }
44317
44469
  }
44318
44470
  if (!token)
@@ -44924,7 +45076,7 @@ function cornerStartConfigKey(repository, objective) {
44924
45076
  function cornerRepositoryCacheDir(supervisorRoot, remote) {
44925
45077
  const normalizedRemote = roomCheckoutRemote(remote);
44926
45078
  const repositoryHash = createHash13("sha256").update(normalizedRemote).digest("hex").slice(0, 24);
44927
- return resolve35(supervisorRoot, "beeline", "repositories", `${repositoryHash}.git`);
45079
+ return resolve36(supervisorRoot, "beeline", "repositories", `${repositoryHash}.git`);
44928
45080
  }
44929
45081
  function isStandingCornerStartFault(error) {
44930
45082
  const text2 = error instanceof Error ? error.message : String(error);
@@ -44933,11 +45085,11 @@ function isStandingCornerStartFault(error) {
44933
45085
  async function materializeCornerWorktree(input) {
44934
45086
  const remote = roomCheckoutRemote(input.remote);
44935
45087
  const gitCommonDir = cornerRepositoryCacheDir(input.supervisorRoot, remote);
44936
- const path = resolve35(input.supervisorRoot, "beeline", "corners", input.cornerId);
45088
+ const path = resolve36(input.supervisorRoot, "beeline", "corners", input.cornerId);
44937
45089
  await mkdir26(dirname26(gitCommonDir), { recursive: true, mode: 448 });
44938
45090
  await mkdir26(dirname26(path), { recursive: true, mode: 448 });
44939
45091
  const authEnv = githubGitEnv(input.token);
44940
- if (!existsSync8(resolve35(gitCommonDir, "HEAD"))) {
45092
+ if (!existsSync8(resolve36(gitCommonDir, "HEAD"))) {
44941
45093
  await execFileAsync8("git", ["clone", "--bare", remote, gitCommonDir], {
44942
45094
  env: authEnv,
44943
45095
  maxBuffer: 4 * 1024 * 1024
@@ -44960,7 +45112,7 @@ async function materializeCornerWorktree(input) {
44960
45112
  return false;
44961
45113
  throw error;
44962
45114
  });
44963
- if (!existsSync8(resolve35(path, ".git"))) {
45115
+ if (!existsSync8(resolve36(path, ".git"))) {
44964
45116
  await rm14(path, { recursive: true, force: true });
44965
45117
  await execFileAsync8("git", [
44966
45118
  `--git-dir=${gitCommonDir}`,
@@ -45026,9 +45178,9 @@ async function mapWithConcurrency(values, limit, visit) {
45026
45178
  }));
45027
45179
  }
45028
45180
  async function discoverCornerWorktree(supervisorRoot, cornerId) {
45029
- const cornersRoot = resolve35(supervisorRoot, "beeline", "corners");
45030
- const path = resolve35(cornersRoot, cornerId);
45031
- if (dirname26(path) !== cornersRoot || !existsSync8(resolve35(path, ".git")))
45181
+ const cornersRoot = resolve36(supervisorRoot, "beeline", "corners");
45182
+ const path = resolve36(cornersRoot, cornerId);
45183
+ if (dirname26(path) !== cornersRoot || !existsSync8(resolve36(path, ".git")))
45032
45184
  return void 0;
45033
45185
  const [canonicalRoot, canonicalPath] = await Promise.all([
45034
45186
  realpath2(cornersRoot),
@@ -45040,8 +45192,8 @@ async function discoverCornerWorktree(supervisorRoot, cornerId) {
45040
45192
  const common = await execFileAsync8("git", ["-C", path, "rev-parse", "--git-common-dir"]).catch(() => void 0);
45041
45193
  if (!common)
45042
45194
  return void 0;
45043
- const gitCommonDir = resolve35(path, common.stdout.trim());
45044
- const repositoriesRoot = resolve35(supervisorRoot, "beeline", "repositories");
45195
+ const gitCommonDir = resolve36(path, common.stdout.trim());
45196
+ const repositoriesRoot = resolve36(supervisorRoot, "beeline", "repositories");
45045
45197
  const commonRelative = relative3(repositoriesRoot, gitCommonDir);
45046
45198
  if (!commonRelative || commonRelative === ".." || commonRelative.startsWith(`..${sep2}`) || commonRelative.startsWith(sep2)) {
45047
45199
  throw new Error(`refusing corner ${cornerId} with git directory outside repository cache`);
@@ -45049,7 +45201,7 @@ async function discoverCornerWorktree(supervisorRoot, cornerId) {
45049
45201
  return { path, gitCommonDir };
45050
45202
  }
45051
45203
  async function localCornerWorktreeIds(supervisorRoot) {
45052
- const root = resolve35(supervisorRoot, "beeline", "corners");
45204
+ const root = resolve36(supervisorRoot, "beeline", "corners");
45053
45205
  const entries = await readdir9(root, { withFileTypes: true }).catch((error) => {
45054
45206
  if (error.code === "ENOENT")
45055
45207
  return [];
@@ -45139,8 +45291,8 @@ async function originContains(gitCommonDir, head) {
45139
45291
  }
45140
45292
  var execFileAsync8 = promisify8(execFile13);
45141
45293
  async function removeCornerScratchWorkspace(input) {
45142
- const expected = resolve35(input.roomRoot, "scratch");
45143
- if (resolve35(input.scratchPath) !== expected) {
45294
+ const expected = resolve36(input.roomRoot, "scratch");
45295
+ if (resolve36(input.scratchPath) !== expected) {
45144
45296
  throw new Error(`refusing to remove scratch outside corner ${input.cornerId}`);
45145
45297
  }
45146
45298
  await rm14(expected, { recursive: true, force: true });
@@ -45252,7 +45404,7 @@ var RoomRuntimeCoordinator = class {
45252
45404
  ...fixedWorkspaceCeiling ? { maxLiveSessions: Number(fixedWorkspaceCeiling) } : {},
45253
45405
  perRoomLiveSessions: resolvePerRoomLiveSessions(process.env),
45254
45406
  workspaceFloor: Number(process.env.BUZZY_BODY_MAX_SESSIONS_FLOOR ?? String(DEFAULT_WORKSPACE_LIVE_SESSIONS_FLOOR)),
45255
- activeRoomCount: () => this.running.size,
45407
+ activeRoomCount: () => this.activeRoomCount(),
45256
45408
  idleMs: resolveSessionIdleMs(process.env),
45257
45409
  maxWarmSessions: resolveMaxWarmSessions(process.env),
45258
45410
  reserveInteractiveSlot: true
@@ -45282,7 +45434,7 @@ var RoomRuntimeCoordinator = class {
45282
45434
  this.discoveryWakeListener?.();
45283
45435
  }
45284
45436
  activeRoomCount() {
45285
- return this.running.size;
45437
+ return new Set([...this.running.keys()].map((id) => this.monolithCornerParents.get(id) ?? id)).size;
45286
45438
  }
45287
45439
  surfaceHealthSnapshot() {
45288
45440
  return this.surfaceHealth.snapshot();
@@ -45589,13 +45741,13 @@ var RoomRuntimeCoordinator = class {
45589
45741
  return this.runtime.rooms.find((room) => room.channelId === roomId);
45590
45742
  }
45591
45743
  roomRoot(roomId) {
45592
- return this.roomRecord(roomId)?.root ?? resolve35(dirname26(this.configPath), "rooms", roomId);
45744
+ return this.roomRecord(roomId)?.root ?? resolve36(dirname26(this.configPath), "rooms", roomId);
45593
45745
  }
45594
45746
  roomAgentHomeRoot(workspaceRoot, required = false) {
45595
45747
  const flag = process.env.BUZZY_BODY_ROOM_HOME;
45596
45748
  if (!required && flag === "0")
45597
45749
  return void 0;
45598
- const home = resolve35(workspaceRoot, "agent-home");
45750
+ const home = resolve36(workspaceRoot, "agent-home");
45599
45751
  if (!required && flag !== "1" && !existsSync8(home) && existsSync8(workspaceRoot))
45600
45752
  return void 0;
45601
45753
  try {
@@ -45611,8 +45763,8 @@ var RoomRuntimeCoordinator = class {
45611
45763
  return {
45612
45764
  ...this.baseConfig,
45613
45765
  workspaceRoot,
45614
- agentPrivateRoot: resolve35(workspaceRoot, "agent-private"),
45615
- agentMemoryRoot: resolve35(dirname26(this.configPath), "memory"),
45766
+ agentPrivateRoot: resolve36(workspaceRoot, "agent-private"),
45767
+ agentMemoryRoot: resolve36(dirname26(this.configPath), "memory"),
45616
45768
  openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname26(this.configPath)),
45617
45769
  turnTraceDir: turnTraceDirectory(dirname26(this.configPath)),
45618
45770
  ...agentHomeRoot ? { agentHomeRoot } : {}
@@ -45695,11 +45847,11 @@ var RoomRuntimeCoordinator = class {
45695
45847
  const remote = roomCheckoutRemote(repository.remote);
45696
45848
  const targetBranch = repository.targetBranch || "main";
45697
45849
  const checkoutId = createHash13("sha256").update(`${roomId}\0${remote}\0${targetBranch}`).digest("hex").slice(0, 24);
45698
- const path = resolve35(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
45850
+ const path = resolve36(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
45699
45851
  await mkdir26(dirname26(path), { recursive: true, mode: 448 });
45700
45852
  const token = remote.startsWith("https://github.com/") ? await this.parentRepositoryToken(roomId) : void 0;
45701
45853
  const env = token ? githubGitEnv(token.token) : process.env;
45702
- if (!existsSync8(resolve35(path, ".git"))) {
45854
+ if (!existsSync8(resolve36(path, ".git"))) {
45703
45855
  await execFileAsync8("git", ["clone", "--no-checkout", remote, path], {
45704
45856
  env,
45705
45857
  maxBuffer: 4 * 1024 * 1024
@@ -45776,7 +45928,7 @@ var RoomRuntimeCoordinator = class {
45776
45928
  if (!objective)
45777
45929
  throw new Error("corner has no authoritative objective fact");
45778
45930
  const repositoryBacked = repository.resolution === "repository" && restore.lane !== "no_code";
45779
- const scratchPath = resolve35(this.roomRoot(corner.cornerId), "scratch");
45931
+ const scratchPath = resolve36(this.roomRoot(corner.cornerId), "scratch");
45780
45932
  if (repositoryBacked && existsSync8(scratchPath) && !restore.featureBranch)
45781
45933
  throw new Error("promoted corner has no server-assigned feature branch");
45782
45934
  const targetBranch = repositoryBacked ? repository.targetBranch || "main" : void 0;
@@ -45791,7 +45943,7 @@ var RoomRuntimeCoordinator = class {
45791
45943
  }) : void 0;
45792
45944
  if (worktree && existsSync8(scratchPath))
45793
45945
  await this.reapCornerScratch({ path: scratchPath, cornerId: corner.cornerId });
45794
- const workspacePath = worktree?.path ?? resolve35(this.roomRoot(corner.cornerId), "scratch");
45946
+ const workspacePath = worktree?.path ?? resolve36(this.roomRoot(corner.cornerId), "scratch");
45795
45947
  if (!worktree)
45796
45948
  await mkdir26(workspacePath, { recursive: true, mode: 448 });
45797
45949
  if (worktree && shouldPostInitialCornerWorkingState(restore)) {
@@ -46114,7 +46266,7 @@ var RoomRuntimeCoordinator = class {
46114
46266
  throw new Error(`archived corner ${corner.cornerId} has no authoritative repository`);
46115
46267
  }
46116
46268
  const expectedCommonDir = cornerRepositoryCacheDir(this.runtime.supervisorRoot, repository.remote);
46117
- if (resolve35(discovered.gitCommonDir) !== expectedCommonDir) {
46269
+ if (resolve36(discovered.gitCommonDir) !== expectedCommonDir) {
46118
46270
  throw new Error(`archived corner ${corner.cornerId} repository cache does not match`);
46119
46271
  }
46120
46272
  if (!restore.featureBranch) {
@@ -46465,10 +46617,10 @@ var ThinDaemonCore = class {
46465
46617
 
46466
46618
  // apps/body/dist/force-update-journal.js
46467
46619
  import { mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync, writeFileSync as writeFileSync5 } from "node:fs";
46468
- import { resolve as resolve36 } from "node:path";
46620
+ import { resolve as resolve37 } from "node:path";
46469
46621
  var NAME = "force-update-interruptions.json";
46470
46622
  function pathFor(runtimeDir) {
46471
- return resolve36(runtimeDir, NAME);
46623
+ return resolve37(runtimeDir, NAME);
46472
46624
  }
46473
46625
  function read(runtimeDir) {
46474
46626
  try {
@@ -46546,17 +46698,17 @@ function staleGeneration(error) {
46546
46698
  init_launchd();
46547
46699
  init_systemd();
46548
46700
  import { mkdir as mkdir27, rename as rename10 } from "node:fs/promises";
46549
- import { dirname as dirname27, resolve as resolve37 } from "node:path";
46701
+ import { dirname as dirname27, resolve as resolve38 } from "node:path";
46550
46702
  async function retireRemovedAgent(runtime, options = {}) {
46551
- const deletedRoot = resolve37(runtime.supervisorRoot, "beeline", "deleted-runtimes");
46552
- const target = resolve37(deletedRoot, `${runtime.agent.publicKey}-${Date.now()}`);
46703
+ const deletedRoot = resolve38(runtime.supervisorRoot, "beeline", "deleted-runtimes");
46704
+ const target = resolve38(deletedRoot, `${runtime.agent.publicKey}-${Date.now()}`);
46553
46705
  return relocateAgentRuntime(runtime, target, {
46554
46706
  ...options.run ? { run: options.run } : {}
46555
46707
  });
46556
46708
  }
46557
46709
  async function relocateAgentRuntime(runtime, target, options = {}) {
46558
46710
  const source = runtimeDirectory(runtime.supervisorRoot, runtime.agent.publicKey);
46559
- const destination = resolve37(target);
46711
+ const destination = resolve38(target);
46560
46712
  if (destination === source || destination.startsWith(`${source}/`)) {
46561
46713
  throw new Error("agent runtime destination must be outside the live runtime");
46562
46714
  }
@@ -46579,8 +46731,8 @@ init_self_update();
46579
46731
  init_systemd();
46580
46732
 
46581
46733
  // apps/body/dist/release-status.js
46582
- import { readFile as readFile27, readdir as readdir10, rename as rename11, writeFile as writeFile21 } from "node:fs/promises";
46583
- import { resolve as resolve38 } from "node:path";
46734
+ import { readFile as readFile28, readdir as readdir10, rename as rename11, writeFile as writeFile21 } from "node:fs/promises";
46735
+ import { resolve as resolve39 } from "node:path";
46584
46736
  var DAEMON_RELEASE_STATUS_FILE = "release-status.json";
46585
46737
  var RELEASE_VERSION = /^v\d+\.\d+\.\d+$/;
46586
46738
  var SOURCE_SHA = /^[0-9a-f]{7,64}$/;
@@ -46597,7 +46749,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
46597
46749
  pid: options.pid ?? process.pid,
46598
46750
  readyAt: (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString()
46599
46751
  };
46600
- const target = resolve38(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
46752
+ const target = resolve39(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
46601
46753
  const temporary = `${target}.${status.pid}.tmp`;
46602
46754
  await writeFile21(temporary, `${JSON.stringify(status, null, 2)}
46603
46755
  `, { mode: 384 });
@@ -46607,7 +46759,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
46607
46759
 
46608
46760
  // apps/body/dist/scratch-sweep.js
46609
46761
  import { lstat as lstat5, readdir as readdir11, rmdir as rmdir2, unlink as unlink9 } from "node:fs/promises";
46610
- import { resolve as resolve39 } from "node:path";
46762
+ import { resolve as resolve40 } from "node:path";
46611
46763
  var DEFAULT_SCRATCH_TTL_HOURS = 72;
46612
46764
  var NEVER_SWEEP_SUBDIR_NAMES = new Set(HOME_SUBDIRS.filter((name) => name !== "tmp"));
46613
46765
  function scratchTtlMs(env = process.env) {
@@ -46616,7 +46768,7 @@ function scratchTtlMs(env = process.env) {
46616
46768
  return (Number.isFinite(hours) && hours > 0 ? hours : DEFAULT_SCRATCH_TTL_HOURS) * 60 * 60 * 1e3;
46617
46769
  }
46618
46770
  async function discoverAttachScratchRoots(runtimeDir) {
46619
- const roomsDir = resolve39(runtimeDir, "rooms");
46771
+ const roomsDir = resolve40(runtimeDir, "rooms");
46620
46772
  let entries;
46621
46773
  try {
46622
46774
  entries = await readdir11(roomsDir, { withFileTypes: true });
@@ -46627,7 +46779,7 @@ async function discoverAttachScratchRoots(runtimeDir) {
46627
46779
  for (const entry of entries) {
46628
46780
  if (!entry.isDirectory())
46629
46781
  continue;
46630
- const home = resolve39(roomsDir, entry.name, "agent-home");
46782
+ const home = resolve40(roomsDir, entry.name, "agent-home");
46631
46783
  const stats = await lstat5(home).catch(() => void 0);
46632
46784
  if (stats?.isDirectory())
46633
46785
  roots.push(home);
@@ -46646,7 +46798,7 @@ async function removeStaleFiles(dir, cutoffMs, protectNamesHere) {
46646
46798
  for (const entry of entries) {
46647
46799
  if (protectNamesHere && NEVER_SWEEP_SUBDIR_NAMES.has(entry.name))
46648
46800
  continue;
46649
- const path = resolve39(dir, entry.name);
46801
+ const path = resolve40(dir, entry.name);
46650
46802
  const stats = await lstat5(path).catch(() => void 0);
46651
46803
  if (!stats || stats.isSymbolicLink())
46652
46804
  continue;
@@ -46731,7 +46883,7 @@ async function runAgentRuntime(configPath, host, signal) {
46731
46883
  BUZZ_DEV_MCP_BIN: runtime.mcpBinary
46732
46884
  };
46733
46885
  const config = loadBodyConfig({
46734
- workspaceRoot: resolve40(runtimeDir, "workspace"),
46886
+ workspaceRoot: resolve41(runtimeDir, "workspace"),
46735
46887
  llmEnvFile: runtime.llmEnvFile,
46736
46888
  env,
46737
46889
  agent
@@ -47591,7 +47743,7 @@ async function main() {
47591
47743
  const roomId = roomFlag >= 0 ? args[roomFlag + 1] : void 0;
47592
47744
  if (!configPath || !roomId)
47593
47745
  throw new Error("corner-read-token requires --config and --room");
47594
- const activated = await activateDaemonTransport(resolve41(configPath));
47746
+ const activated = await activateDaemonTransport(resolve42(configPath));
47595
47747
  if (!activated)
47596
47748
  throw new Error("corner-read-token requires monolith transport");
47597
47749
  const credential = await activated.client.execute("getRoomGitHubToken", { roomId });
@@ -47646,7 +47798,7 @@ async function main() {
47646
47798
  }
47647
47799
  if (!configPath && !args.includes("--machine"))
47648
47800
  throw new Error("daemon requires --machine, or --config <runtime.json> for one agent");
47649
- const { reason, lifecycle } = await runMachineHelper(configPath ? { configPaths: [resolve41(configPath)] } : {});
47801
+ const { reason, lifecycle } = await runMachineHelper(configPath ? { configPaths: [resolve42(configPath)] } : {});
47650
47802
  daemonLifecycle = lifecycle;
47651
47803
  lifecycle.exit(reason);
47652
47804
  return;