@buildautomaton/cli 0.1.73 → 0.1.74

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.
package/dist/cli.js CHANGED
@@ -11850,8 +11850,8 @@ var init_task_queue_types = __esm({
11850
11850
  });
11851
11851
 
11852
11852
  // src/code-nav/symbol-index/scheduler/task-queue-store.ts
11853
- function setSymbolIndexWorkerRunning(running) {
11854
- symbolIndexWorkerRunning = running;
11853
+ function setSymbolIndexWorkerRunning(running2) {
11854
+ symbolIndexWorkerRunning = running2;
11855
11855
  }
11856
11856
  function taskMatchesCurrentPending(task) {
11857
11857
  const current = pendingSymbolIndexTasks.get(symbolIndexTaskKey(task.parentPath, task.filePath));
@@ -31064,7 +31064,7 @@ var {
31064
31064
  } = import_index.default;
31065
31065
 
31066
31066
  // src/cli-version.ts
31067
- var CLI_VERSION = "0.1.73".length > 0 ? "0.1.73" : "0.0.0-dev";
31067
+ var CLI_VERSION = "0.1.74".length > 0 ? "0.1.74" : "0.0.0-dev";
31068
31068
 
31069
31069
  // src/cli/defaults.ts
31070
31070
  var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
@@ -37505,6 +37505,7 @@ function extractSessionUpdateMessageText(params) {
37505
37505
  }
37506
37506
 
37507
37507
  // src/agents/planning/planning-session-turn-buffer.ts
37508
+ var MAX_PLANNING_BUFFER_CHARS = 512 * 1024;
37508
37509
  var buffersByRunId = /* @__PURE__ */ new Map();
37509
37510
  function registerPlanningSessionTurn(runId) {
37510
37511
  buffersByRunId.set(runId, { messageBuffer: "" });
@@ -37522,7 +37523,10 @@ function capturePlanningSessionUpdate(params) {
37522
37523
  });
37523
37524
  if (bucket !== "message") return false;
37524
37525
  const text = extractSessionUpdateMessageText(params.payload);
37525
- if (text) state.messageBuffer += text;
37526
+ if (text && state.messageBuffer.length < MAX_PLANNING_BUFFER_CHARS) {
37527
+ const room = MAX_PLANNING_BUFFER_CHARS - state.messageBuffer.length;
37528
+ state.messageBuffer += room >= text.length ? text : text.slice(0, room);
37529
+ }
37526
37530
  return true;
37527
37531
  }
37528
37532
  function getPlanningSessionTurnOutput(runId) {
@@ -39416,11 +39420,30 @@ function closeHttpServer(server) {
39416
39420
  }
39417
39421
 
39418
39422
  // src/mcp/bridge-access/read-json-body.ts
39423
+ var MAX_JSON_BODY_BYTES = 1024 * 1024;
39424
+ var RequestBodyTooLargeError = class extends Error {
39425
+ constructor() {
39426
+ super(`Request body exceeds ${MAX_JSON_BODY_BYTES} bytes`);
39427
+ }
39428
+ };
39419
39429
  function readJsonBody(req) {
39420
39430
  return new Promise((resolve37, reject) => {
39421
39431
  const chunks = [];
39422
- req.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
39432
+ let total = 0;
39433
+ let tooLarge = false;
39434
+ req.on("data", (chunk) => {
39435
+ if (tooLarge) return;
39436
+ const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
39437
+ total += buf.length;
39438
+ if (total > MAX_JSON_BODY_BYTES) {
39439
+ tooLarge = true;
39440
+ reject(new RequestBodyTooLargeError());
39441
+ return;
39442
+ }
39443
+ chunks.push(buf);
39444
+ });
39423
39445
  req.on("end", () => {
39446
+ if (tooLarge) return;
39424
39447
  try {
39425
39448
  const raw = Buffer.concat(chunks).toString("utf8").trim();
39426
39449
  if (!raw) {
@@ -39477,7 +39500,7 @@ function createBridgeAccessRequestHandler(registry2) {
39477
39500
  sendJsonResponse(res, 404, { ok: false, error: "Not found" });
39478
39501
  } catch (err) {
39479
39502
  const message = err instanceof Error ? err.message : String(err);
39480
- sendJsonResponse(res, 500, { ok: false, error: message });
39503
+ sendJsonResponse(res, err instanceof RequestBodyTooLargeError ? 413 : 500, { ok: false, error: message });
39481
39504
  }
39482
39505
  })();
39483
39506
  };
@@ -49987,7 +50010,7 @@ init_yield_to_event_loop();
49987
50010
 
49988
50011
  // src/files/read/types.ts
49989
50012
  var LINE_CHUNK_SIZE = 64 * 1024;
49990
- var READ_RANGE_YIELD_EVERY_BYTES = 256 * 1024;
50013
+ var READ_RANGE_YIELD_EVERY_BYTES = 64 * 1024;
49991
50014
 
49992
50015
  // src/files/read/guess-mime-type.ts
49993
50016
  var MIME_BY_EXT = {
@@ -51793,16 +51816,8 @@ var handleAgentConfigMessage = (msg, deps) => {
51793
51816
  handleBridgeAgentConfig(msg, deps);
51794
51817
  };
51795
51818
 
51796
- // src/prompt-turn-queue/client-report.ts
51797
- function sendPromptQueueClientReport(ws, queues) {
51798
- if (!ws) return false;
51799
- const wireQueues = {};
51800
- for (const [queueKey, rows] of Object.entries(queues)) {
51801
- wireQueues[queueKey] = rows.map((r) => ({ turnId: r.turnId, clientState: r.cliState }));
51802
- }
51803
- sendWsMessage(ws, { type: "prompt_queue_client_report", queues: wireQueues });
51804
- return true;
51805
- }
51819
+ // src/prompt-turn-queue/runner/dispatch-started-prompt-queue-runs.ts
51820
+ init_yield_to_event_loop();
51806
51821
 
51807
51822
  // src/prompt-turn-queue/disk-store.ts
51808
51823
  init_cli_database();
@@ -51894,23 +51909,6 @@ function dispatchLocalPrompt(next, deps) {
51894
51909
  handleBridgePrompt(msg, deps);
51895
51910
  }
51896
51911
 
51897
- // src/prompt-turn-queue/runner/queue-selection.ts
51898
- function pickNextRunnableTurn(turns) {
51899
- for (const t of turns) {
51900
- if (t.bridgeServerState === "discarded" || t.bridgeServerState === "stopping") continue;
51901
- if (t.bridgeServerState === "cancel_requested") continue;
51902
- if (!isRunnableBridgePromptTurnServerState(t.bridgeServerState)) continue;
51903
- if (t.lastCliState === "running" || t.lastCliState === "stopped" || t.lastCliState === "failed" || t.lastCliState === "cancelled") {
51904
- continue;
51905
- }
51906
- return t;
51907
- }
51908
- return null;
51909
- }
51910
- function hasRunningTurn(turns) {
51911
- return turns.some((t) => t.lastCliState === "running");
51912
- }
51913
-
51914
51912
  // src/prompt-turn-queue/runner/run-id-queue-key-map.ts
51915
51913
  var runIdToQueueKey = /* @__PURE__ */ new Map();
51916
51914
  function getRunIdQueueKey(runId) {
@@ -51925,9 +51923,121 @@ function deleteRunIdQueueKey(runId) {
51925
51923
  return queueKey;
51926
51924
  }
51927
51925
  function syncRunningTurnQueueKeys(turns, queueKey) {
51928
- for (const running of turns.filter((t) => t.lastCliState === "running")) {
51929
- runIdToQueueKey.set(running.turnId, queueKey);
51926
+ for (const running2 of turns.filter((t) => t.lastCliState === "running")) {
51927
+ runIdToQueueKey.set(running2.turnId, queueKey);
51928
+ }
51929
+ }
51930
+
51931
+ // src/prompt-turn-queue/runner/dispatch-started-prompt-queue-runs.ts
51932
+ async function dispatchStartedPromptQueueRuns(entries, started, deps) {
51933
+ for (const [queueKey] of entries) {
51934
+ const file2 = await readPersistedQueue(queueKey);
51935
+ const running2 = file2?.turns.find((turn) => turn.lastCliState === "running");
51936
+ if (running2 && started.has(running2.turnId) && getRunIdQueueKey(running2.turnId) === queueKey) {
51937
+ dispatchLocalPrompt(running2, deps);
51938
+ }
51939
+ await yieldToEventLoop();
51940
+ }
51941
+ }
51942
+
51943
+ // src/prompt-turn-queue/runner/handle-prompt-queue-cancellations.ts
51944
+ init_yield_to_event_loop();
51945
+
51946
+ // src/prompt-turn-queue/client-report.ts
51947
+ function sendPromptQueueClientReport(ws, queues) {
51948
+ if (!ws) return false;
51949
+ const wireQueues = {};
51950
+ for (const [queueKey, rows] of Object.entries(queues)) {
51951
+ wireQueues[queueKey] = rows.map((r) => ({ turnId: r.turnId, clientState: r.cliState }));
51952
+ }
51953
+ sendWsMessage(ws, { type: "prompt_queue_client_report", queues: wireQueues });
51954
+ return true;
51955
+ }
51956
+
51957
+ // src/prompt-turn-queue/runner/finalize-prompt-turn-on-bridge.ts
51958
+ async function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
51959
+ if (!runId) return false;
51960
+ const queueKey = deleteRunIdQueueKey(runId);
51961
+ if (!queueKey) return false;
51962
+ const f = await readPersistedQueue(queueKey);
51963
+ if (!f) return false;
51964
+ const t = f.turns.find((x) => x.turnId === runId);
51965
+ if (!t) return false;
51966
+ t.lastCliState = opts?.terminalCliState ?? (success2 ? "stopped" : "failed");
51967
+ await writePersistedQueue(f);
51968
+ sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId, cliState: t.lastCliState }] });
51969
+ return true;
51970
+ }
51971
+
51972
+ // src/prompt-turn-queue/runner/handle-prompt-queue-cancellations.ts
51973
+ async function handlePromptQueueCancellations(entries, deps) {
51974
+ for (const [queueKey] of entries) {
51975
+ const file2 = await readPersistedQueue(queueKey);
51976
+ const turn = file2?.turns.find((row) => row.bridgeServerState === "cancel_requested" && row.lastCliState === "running");
51977
+ if (!turn) {
51978
+ await yieldToEventLoop();
51979
+ continue;
51980
+ }
51981
+ deps.log(`[Queue] Cancellation request received for turn ${turn.turnId.slice(0, 8)}\u2026`);
51982
+ if (await deps.acpManager.cancelRun(turn.turnId)) {
51983
+ await yieldToEventLoop();
51984
+ continue;
51985
+ }
51986
+ deps.log(`[Queue] cancel_requested for ${turn.turnId.slice(0, 8)}\u2026 with no local run; marking cancelled.`);
51987
+ await finalizePromptTurnOnBridge(deps.getWs, turn.turnId, false, { terminalCliState: "cancelled" });
51988
+ const ws = deps.getWs();
51989
+ if (ws && turn.sessionId) {
51990
+ sendWsMessage(ws, {
51991
+ type: "prompt_result",
51992
+ sessionId: turn.sessionId,
51993
+ runId: turn.turnId,
51994
+ success: false,
51995
+ error: "Stopped by user",
51996
+ stopReason: "cancelled"
51997
+ });
51998
+ }
51999
+ await yieldToEventLoop();
52000
+ }
52001
+ }
52002
+
52003
+ // src/prompt-turn-queue/runner/persist-prompt-queue-snapshot.ts
52004
+ init_yield_to_event_loop();
52005
+ async function persistPromptQueueSnapshot(entries) {
52006
+ for (const [queueKey, serverTurns] of entries) {
52007
+ const file2 = await mergeBridgeServerQueueSnapshot(queueKey, serverTurns);
52008
+ await writePersistedQueue(file2);
52009
+ await yieldToEventLoop();
52010
+ }
52011
+ for (const [queueKey] of entries) {
52012
+ const file2 = await readPersistedQueue(queueKey);
52013
+ if (file2) syncRunningTurnQueueKeys(file2.turns, queueKey);
52014
+ await yieldToEventLoop();
52015
+ }
52016
+ }
52017
+
52018
+ // src/prompt-turn-queue/runner/prompt-queue-snapshot-types.ts
52019
+ function promptQueueSnapshotEntries(queues) {
52020
+ return Object.entries(queues).filter((entry) => Array.isArray(entry[1]));
52021
+ }
52022
+
52023
+ // src/prompt-turn-queue/runner/start-prompt-queue-runs.ts
52024
+ init_yield_to_event_loop();
52025
+
52026
+ // src/prompt-turn-queue/runner/queue-selection.ts
52027
+ function pickNextRunnableTurn(turns) {
52028
+ for (const t of turns) {
52029
+ if (t.bridgeServerState === "discarded" || t.bridgeServerState === "stopping") continue;
52030
+ if (t.bridgeServerState === "cancel_requested") continue;
52031
+ if (!isRunnableBridgePromptTurnServerState(t.bridgeServerState)) continue;
52032
+ if (t.lastCliState === "running" || t.lastCliState === "stopped" || t.lastCliState === "failed" || t.lastCliState === "cancelled") {
52033
+ continue;
52034
+ }
52035
+ return t;
51930
52036
  }
52037
+ return null;
52038
+ }
52039
+ function hasRunningTurn(turns) {
52040
+ return turns.some((t) => t.lastCliState === "running");
51931
52041
  }
51932
52042
 
51933
52043
  // src/prompt-turn-queue/runner/run-local-revert-before-queued-prompt.ts
@@ -52047,96 +52157,41 @@ async function runLocalRevertBeforeQueuedPrompt(next, deps) {
52047
52157
  return res.ok;
52048
52158
  }
52049
52159
 
52050
- // src/prompt-turn-queue/runner/finalize-prompt-turn-on-bridge.ts
52051
- async function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
52052
- if (!runId) return false;
52053
- const queueKey = deleteRunIdQueueKey(runId);
52054
- if (!queueKey) return false;
52055
- const f = await readPersistedQueue(queueKey);
52056
- if (!f) return false;
52057
- const t = f.turns.find((x) => x.turnId === runId);
52058
- if (!t) return false;
52059
- t.lastCliState = opts?.terminalCliState ?? (success2 ? "stopped" : "failed");
52060
- await writePersistedQueue(f);
52061
- sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId, cliState: t.lastCliState }] });
52062
- return true;
52063
- }
52064
-
52065
- // src/prompt-turn-queue/runner/apply-prompt-queue-state-from-server.ts
52066
- async function applyPromptQueueStateFromServer(msg, deps) {
52067
- const raw = msg.queues;
52068
- if (!raw || typeof raw !== "object") return;
52069
- const getWs = deps.getWs;
52070
- for (const [queueKey, serverTurns] of Object.entries(raw)) {
52071
- if (!Array.isArray(serverTurns)) continue;
52072
- const file2 = await mergeBridgeServerQueueSnapshot(queueKey, serverTurns);
52073
- await writePersistedQueue(file2);
52074
- }
52075
- for (const [queueKey, serverTurns] of Object.entries(raw)) {
52076
- if (!Array.isArray(serverTurns)) continue;
52077
- const file2 = await readPersistedQueue(queueKey);
52078
- if (!file2) continue;
52079
- syncRunningTurnQueueKeys(file2.turns, queueKey);
52080
- }
52081
- for (const [queueKey, serverTurns] of Object.entries(raw)) {
52082
- if (!Array.isArray(serverTurns)) continue;
52083
- const file2 = await readPersistedQueue(queueKey);
52084
- if (!file2) continue;
52085
- const cancelRow = file2.turns.find((t) => t.bridgeServerState === "cancel_requested" && t.lastCliState === "running");
52086
- if (cancelRow) {
52087
- const localCancelHandled = await deps.acpManager.cancelRun(cancelRow.turnId);
52088
- if (!localCancelHandled) {
52089
- deps.log(
52090
- `[Queue] bridge server cancel_requested for ${cancelRow.turnId.slice(0, 8)}\u2026 but no local agent run is active (e.g. after CLI restart); marking cancelled and notifying bridge.`
52091
- );
52092
- await finalizePromptTurnOnBridge(deps.getWs, cancelRow.turnId, false, { terminalCliState: "cancelled" });
52093
- const ws = deps.getWs();
52094
- if (ws && cancelRow.sessionId) {
52095
- sendWsMessage(ws, {
52096
- type: "prompt_result",
52097
- sessionId: cancelRow.sessionId,
52098
- runId: cancelRow.turnId,
52099
- success: false,
52100
- error: "Stopped by user",
52101
- stopReason: "cancelled"
52102
- });
52103
- }
52104
- }
52105
- }
52106
- }
52160
+ // src/prompt-turn-queue/runner/start-prompt-queue-runs.ts
52161
+ async function startPromptQueueRuns(entries, deps) {
52107
52162
  const report = {};
52108
- const startedThisTick = /* @__PURE__ */ new Set();
52109
- for (const [queueKey, serverTurns] of Object.entries(raw)) {
52110
- if (!Array.isArray(serverTurns)) continue;
52163
+ const started = /* @__PURE__ */ new Set();
52164
+ for (const [queueKey] of entries) {
52111
52165
  const file2 = await readPersistedQueue(queueKey);
52112
- if (!file2) continue;
52113
- if (hasRunningTurn(file2.turns)) continue;
52166
+ if (!file2 || hasRunningTurn(file2.turns)) continue;
52114
52167
  const next = pickNextRunnableTurn(file2.turns);
52115
52168
  if (!next) continue;
52116
52169
  if (!await runLocalRevertBeforeQueuedPrompt(next, deps)) {
52117
52170
  next.lastCliState = "failed";
52118
52171
  await writePersistedQueue(file2);
52119
- sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: next.turnId, cliState: "failed" }] });
52172
+ sendPromptQueueClientReport(deps.getWs(), { [queueKey]: [{ turnId: next.turnId, cliState: "failed" }] });
52120
52173
  continue;
52121
52174
  }
52122
52175
  next.lastCliState = "running";
52123
52176
  await writePersistedQueue(file2);
52124
52177
  setRunIdQueueKey(next.turnId, queueKey);
52125
- startedThisTick.add(next.turnId);
52178
+ started.add(next.turnId);
52126
52179
  report[queueKey] = [{ turnId: next.turnId, cliState: "running" }];
52180
+ await yieldToEventLoop();
52127
52181
  }
52128
- if (Object.keys(report).length > 0) {
52129
- sendPromptQueueClientReport(getWs(), report);
52130
- }
52131
- for (const [queueKey, serverTurns] of Object.entries(raw)) {
52132
- if (!Array.isArray(serverTurns)) continue;
52133
- const file2 = await readPersistedQueue(queueKey);
52134
- if (!file2) continue;
52135
- const running = file2.turns.find((t) => t.lastCliState === "running");
52136
- if (!running || !startedThisTick.has(running.turnId)) continue;
52137
- if (getRunIdQueueKey(running.turnId) !== queueKey) continue;
52138
- dispatchLocalPrompt(running, deps);
52139
- }
52182
+ if (Object.keys(report).length) sendPromptQueueClientReport(deps.getWs(), report);
52183
+ return started;
52184
+ }
52185
+
52186
+ // src/prompt-turn-queue/runner/apply-prompt-queue-state-from-server.ts
52187
+ async function applyPromptQueueStateFromServer(msg, deps) {
52188
+ const raw = msg.queues;
52189
+ if (!raw || typeof raw !== "object") return;
52190
+ const entries = promptQueueSnapshotEntries(raw);
52191
+ await persistPromptQueueSnapshot(entries);
52192
+ await handlePromptQueueCancellations(entries, deps);
52193
+ const started = await startPromptQueueRuns(entries, deps);
52194
+ await dispatchStartedPromptQueueRuns(entries, started, deps);
52140
52195
  }
52141
52196
 
52142
52197
  // src/agents/acp/from-bridge/bridge-prompt-wiring.ts
@@ -52402,10 +52457,34 @@ var handlePromptMessage = (msg, deps) => {
52402
52457
  handleBridgePrompt(msg, deps);
52403
52458
  };
52404
52459
 
52460
+ // src/prompt-turn-queue/runner/serial-prompt-queue-work.ts
52461
+ var running = false;
52462
+ var latestWork = null;
52463
+ async function drain() {
52464
+ while (latestWork) {
52465
+ const work = latestWork;
52466
+ latestWork = null;
52467
+ await work();
52468
+ }
52469
+ }
52470
+ function enqueueLatestPromptQueueStateWork(work) {
52471
+ latestWork = work;
52472
+ if (running) return;
52473
+ running = true;
52474
+ void drain().finally(() => {
52475
+ running = false;
52476
+ if (latestWork) enqueueLatestPromptQueueStateWork(latestWork);
52477
+ });
52478
+ }
52479
+
52405
52480
  // src/routing/handlers/prompt-queue-state.ts
52406
52481
  var handlePromptQueueStateMessage = (msg, deps) => {
52407
- void applyPromptQueueStateFromServer(msg, deps).catch((err) => {
52408
- deps.log(`[Queue] applyPromptQueueStateFromServer failed: ${err instanceof Error ? err.message : String(err)}`);
52482
+ enqueueLatestPromptQueueStateWork(async () => {
52483
+ try {
52484
+ await applyPromptQueueStateFromServer(msg, deps);
52485
+ } catch (err) {
52486
+ deps.log(`[Queue] applyPromptQueueStateFromServer failed: ${err instanceof Error ? err.message : String(err)}`);
52487
+ }
52409
52488
  });
52410
52489
  };
52411
52490