@buildautomaton/cli 0.1.72 → 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/index.js CHANGED
@@ -26497,8 +26497,8 @@ var init_task_queue_types = __esm({
26497
26497
  });
26498
26498
 
26499
26499
  // src/code-nav/symbol-index/scheduler/task-queue-store.ts
26500
- function setSymbolIndexWorkerRunning(running) {
26501
- symbolIndexWorkerRunning = running;
26500
+ function setSymbolIndexWorkerRunning(running2) {
26501
+ symbolIndexWorkerRunning = running2;
26502
26502
  }
26503
26503
  function taskMatchesCurrentPending(task) {
26504
26504
  const current = pendingSymbolIndexTasks.get(symbolIndexTaskKey(task.parentPath, task.filePath));
@@ -29997,12 +29997,32 @@ function attachSdkStdioStderrAuthWatch(options) {
29997
29997
 
29998
29998
  // src/agents/acp/clients/sdk/spawn-sdk-stdio-process.ts
29999
29999
  import { spawn } from "node:child_process";
30000
+
30001
+ // src/agents/acp/clients/bridge-installed-agent-auth-env.ts
30002
+ var authEnv = /* @__PURE__ */ new Map();
30003
+ function setBridgeInstalledAgentAuthEnv(entries) {
30004
+ authEnv.clear();
30005
+ for (const entry of entries) {
30006
+ const envVar = typeof entry.envVar === "string" ? entry.envVar.trim() : "";
30007
+ const token = typeof entry.token === "string" ? entry.token.trim() : "";
30008
+ if (envVar && token) authEnv.set(envVar, token);
30009
+ }
30010
+ }
30011
+ function bridgeInstalledAgentAuthProcessEnv(base = process.env) {
30012
+ if (authEnv.size === 0) return base;
30013
+ return { ...base, ...Object.fromEntries(authEnv) };
30014
+ }
30015
+ function cursorAgentUsesApiKeyAuth(env = process.env) {
30016
+ return Boolean(env.CURSOR_API_KEY?.trim() || env.CURSOR_AUTH_TOKEN?.trim());
30017
+ }
30018
+
30019
+ // src/agents/acp/clients/sdk/spawn-sdk-stdio-process.ts
30000
30020
  function spawnSdkStdioProcess(options) {
30001
30021
  const isWindows = process.platform === "win32";
30002
30022
  const child = spawn(options.command[0], options.command.slice(1), {
30003
30023
  cwd: options.cwd,
30004
30024
  stdio: ["pipe", "pipe", "pipe"],
30005
- env: process.env,
30025
+ env: bridgeInstalledAgentAuthProcessEnv(process.env),
30006
30026
  shell: isWindows
30007
30027
  });
30008
30028
  const stderrCapture = createStderrCapture(child);
@@ -30586,7 +30606,7 @@ function installBridgeProcessResilience() {
30586
30606
  }
30587
30607
 
30588
30608
  // src/cli-version.ts
30589
- var CLI_VERSION = "0.1.72".length > 0 ? "0.1.72" : "0.0.0-dev";
30609
+ var CLI_VERSION = "0.1.74".length > 0 ? "0.1.74" : "0.0.0-dev";
30590
30610
 
30591
30611
  // src/connection/heartbeat/constants.ts
30592
30612
  var BRIDGE_APP_HEARTBEAT_INTERVAL_MS = 1e4;
@@ -33469,10 +33489,11 @@ function createCursorAcpIncomingLineHandler(deps) {
33469
33489
 
33470
33490
  // src/agents/acp/clients/cursor/cursor-json-rpc-acp-transport.ts
33471
33491
  function createCursorJsonRpcAcpTransport(deps) {
33472
- const { send, cancelSessionNotification } = deps;
33492
+ const { send, cancelSessionNotification, skipBrowserAuthenticate } = deps;
33473
33493
  return {
33474
33494
  initialize: (request) => send("initialize", request),
33475
33495
  afterInitialize: async () => {
33496
+ if (skipBrowserAuthenticate) return;
33476
33497
  await send("authenticate", { methodId: "cursor_login" });
33477
33498
  },
33478
33499
  resumeSession: (p) => send("session/resume", p),
@@ -33581,7 +33602,8 @@ async function initCursorAcpWire(options) {
33581
33602
  rl.on("line", (line) => incoming.handleLine(line));
33582
33603
  const transport = createCursorJsonRpcAcpTransport({
33583
33604
  send: wire.send,
33584
- cancelSessionNotification: wire.cancelSessionNotification
33605
+ cancelSessionNotification: wire.cancelSessionNotification,
33606
+ skipBrowserAuthenticate: options.skipBrowserAuthenticate
33585
33607
  });
33586
33608
  const established = await bootstrapAcpWireSession(transport, options.sessionCtx, CURSOR_ACP_CLIENT_INFO);
33587
33609
  return { wire, transport, established, incoming, pendingRequests: pendingRequests2 };
@@ -33594,7 +33616,7 @@ function spawnCursorAcpProcess(options) {
33594
33616
  const child = spawn3(options.command[0], options.command.slice(1), {
33595
33617
  cwd: options.cwd,
33596
33618
  stdio: ["pipe", "pipe", "pipe"],
33597
- env: process.env,
33619
+ env: bridgeInstalledAgentAuthProcessEnv(process.env),
33598
33620
  shell: isWindows
33599
33621
  });
33600
33622
  const stderrCapture = createStderrCapture(child);
@@ -33626,11 +33648,13 @@ async function createCursorAcpClient(options) {
33626
33648
  onAgentSubprocessExit
33627
33649
  } = options;
33628
33650
  const dbgFs = process.env.BUILDAUTOMATON_DEBUG_ACP_FS === "1";
33651
+ const spawnEnv = bridgeInstalledAgentAuthProcessEnv(process.env);
33629
33652
  const { child, stderrCapture } = spawnCursorAcpProcess({
33630
33653
  command,
33631
33654
  cwd,
33632
33655
  onAgentSubprocessExit
33633
33656
  });
33657
+ const skipBrowserAuthenticate = cursorAgentUsesApiKeyAuth(spawnEnv);
33634
33658
  const sessionCtx = createCursorAcpSessionContext({
33635
33659
  cwd,
33636
33660
  mcpServers: options.mcpServers,
@@ -33653,6 +33677,7 @@ async function createCursorAcpClient(options) {
33653
33677
  const { wire, transport, established, incoming, pendingRequests: pendingRequests2 } = await initCursorAcpWire({
33654
33678
  child,
33655
33679
  sessionCtx,
33680
+ skipBrowserAuthenticate,
33656
33681
  incomingDeps: { dbgFs, sessionCtx, onSessionUpdate, onRequest }
33657
33682
  });
33658
33683
  resolve35(
@@ -34499,6 +34524,7 @@ function extractSessionUpdateMessageText(params) {
34499
34524
  }
34500
34525
 
34501
34526
  // src/agents/planning/planning-session-turn-buffer.ts
34527
+ var MAX_PLANNING_BUFFER_CHARS = 512 * 1024;
34502
34528
  var buffersByRunId = /* @__PURE__ */ new Map();
34503
34529
  function registerPlanningSessionTurn(runId) {
34504
34530
  buffersByRunId.set(runId, { messageBuffer: "" });
@@ -34516,7 +34542,10 @@ function capturePlanningSessionUpdate(params) {
34516
34542
  });
34517
34543
  if (bucket !== "message") return false;
34518
34544
  const text = extractSessionUpdateMessageText(params.payload);
34519
- if (text) state.messageBuffer += text;
34545
+ if (text && state.messageBuffer.length < MAX_PLANNING_BUFFER_CHARS) {
34546
+ const room = MAX_PLANNING_BUFFER_CHARS - state.messageBuffer.length;
34547
+ state.messageBuffer += room >= text.length ? text : text.slice(0, room);
34548
+ }
34520
34549
  return true;
34521
34550
  }
34522
34551
  function getPlanningSessionTurnOutput(runId) {
@@ -36581,11 +36610,30 @@ function closeHttpServer(server) {
36581
36610
  }
36582
36611
 
36583
36612
  // src/mcp/bridge-access/read-json-body.ts
36613
+ var MAX_JSON_BODY_BYTES = 1024 * 1024;
36614
+ var RequestBodyTooLargeError = class extends Error {
36615
+ constructor() {
36616
+ super(`Request body exceeds ${MAX_JSON_BODY_BYTES} bytes`);
36617
+ }
36618
+ };
36584
36619
  function readJsonBody(req) {
36585
36620
  return new Promise((resolve35, reject) => {
36586
36621
  const chunks = [];
36587
- req.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
36622
+ let total = 0;
36623
+ let tooLarge = false;
36624
+ req.on("data", (chunk) => {
36625
+ if (tooLarge) return;
36626
+ const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
36627
+ total += buf.length;
36628
+ if (total > MAX_JSON_BODY_BYTES) {
36629
+ tooLarge = true;
36630
+ reject(new RequestBodyTooLargeError());
36631
+ return;
36632
+ }
36633
+ chunks.push(buf);
36634
+ });
36588
36635
  req.on("end", () => {
36636
+ if (tooLarge) return;
36589
36637
  try {
36590
36638
  const raw = Buffer.concat(chunks).toString("utf8").trim();
36591
36639
  if (!raw) {
@@ -36642,7 +36690,7 @@ function createBridgeAccessRequestHandler(registry2) {
36642
36690
  sendJsonResponse(res, 404, { ok: false, error: "Not found" });
36643
36691
  } catch (err) {
36644
36692
  const message = err instanceof Error ? err.message : String(err);
36645
- sendJsonResponse(res, 500, { ok: false, error: message });
36693
+ sendJsonResponse(res, err instanceof RequestBodyTooLargeError ? 413 : 500, { ok: false, error: message });
36646
36694
  }
36647
36695
  })();
36648
36696
  };
@@ -46916,7 +46964,7 @@ init_yield_to_event_loop();
46916
46964
 
46917
46965
  // src/files/read/types.ts
46918
46966
  var LINE_CHUNK_SIZE = 64 * 1024;
46919
- var READ_RANGE_YIELD_EVERY_BYTES = 256 * 1024;
46967
+ var READ_RANGE_YIELD_EVERY_BYTES = 64 * 1024;
46920
46968
 
46921
46969
  // src/files/read/guess-mime-type.ts
46922
46970
  var MIME_BY_EXT = {
@@ -48508,6 +48556,7 @@ function buildBridgeUrl(apiUrl, workspaceId, authToken) {
48508
48556
  var API_TO_BRIDGE_MESSAGE_TYPES = [
48509
48557
  "auth_token",
48510
48558
  "bridge_identified",
48559
+ "installed_agent_auth_sync",
48511
48560
  "ha",
48512
48561
  "preview_environments_config",
48513
48562
  "preview_environment_control",
@@ -48596,6 +48645,16 @@ var handleBridgeIdentified = (msg, deps) => {
48596
48645
  });
48597
48646
  };
48598
48647
 
48648
+ // src/routing/handlers/installed-agent-auth-sync.ts
48649
+ var handleInstalledAgentAuthSync = (msg) => {
48650
+ const entries = Array.isArray(msg.entries) ? msg.entries : [];
48651
+ setBridgeInstalledAgentAuthEnv(
48652
+ entries.filter(
48653
+ (e) => e != null && typeof e === "object" && typeof e.envVar === "string" && typeof e.token === "string"
48654
+ )
48655
+ );
48656
+ };
48657
+
48599
48658
  // src/connection/heartbeat/ack.ts
48600
48659
  var handleBridgeHeartbeatAck = (msg, deps) => {
48601
48660
  const raw = msg.s;
@@ -48612,6 +48671,9 @@ function dispatchBridgeConnectionMessage(msg, deps) {
48612
48671
  case "bridge_identified":
48613
48672
  handleBridgeIdentified(msg, deps);
48614
48673
  break;
48674
+ case "installed_agent_auth_sync":
48675
+ handleInstalledAgentAuthSync(msg, deps);
48676
+ break;
48615
48677
  case "ha":
48616
48678
  handleBridgeHeartbeatAck(msg, deps);
48617
48679
  break;
@@ -48708,16 +48770,8 @@ var handleAgentConfigMessage = (msg, deps) => {
48708
48770
  handleBridgeAgentConfig(msg, deps);
48709
48771
  };
48710
48772
 
48711
- // src/prompt-turn-queue/client-report.ts
48712
- function sendPromptQueueClientReport(ws, queues) {
48713
- if (!ws) return false;
48714
- const wireQueues = {};
48715
- for (const [queueKey, rows] of Object.entries(queues)) {
48716
- wireQueues[queueKey] = rows.map((r) => ({ turnId: r.turnId, clientState: r.cliState }));
48717
- }
48718
- sendWsMessage(ws, { type: "prompt_queue_client_report", queues: wireQueues });
48719
- return true;
48720
- }
48773
+ // src/prompt-turn-queue/runner/dispatch-started-prompt-queue-runs.ts
48774
+ init_yield_to_event_loop();
48721
48775
 
48722
48776
  // src/prompt-turn-queue/disk-store.ts
48723
48777
  init_cli_database();
@@ -48809,23 +48863,6 @@ function dispatchLocalPrompt(next, deps) {
48809
48863
  handleBridgePrompt(msg, deps);
48810
48864
  }
48811
48865
 
48812
- // src/prompt-turn-queue/runner/queue-selection.ts
48813
- function pickNextRunnableTurn(turns) {
48814
- for (const t of turns) {
48815
- if (t.bridgeServerState === "discarded" || t.bridgeServerState === "stopping") continue;
48816
- if (t.bridgeServerState === "cancel_requested") continue;
48817
- if (!isRunnableBridgePromptTurnServerState(t.bridgeServerState)) continue;
48818
- if (t.lastCliState === "running" || t.lastCliState === "stopped" || t.lastCliState === "failed" || t.lastCliState === "cancelled") {
48819
- continue;
48820
- }
48821
- return t;
48822
- }
48823
- return null;
48824
- }
48825
- function hasRunningTurn(turns) {
48826
- return turns.some((t) => t.lastCliState === "running");
48827
- }
48828
-
48829
48866
  // src/prompt-turn-queue/runner/run-id-queue-key-map.ts
48830
48867
  var runIdToQueueKey = /* @__PURE__ */ new Map();
48831
48868
  function getRunIdQueueKey(runId) {
@@ -48840,11 +48877,123 @@ function deleteRunIdQueueKey(runId) {
48840
48877
  return queueKey;
48841
48878
  }
48842
48879
  function syncRunningTurnQueueKeys(turns, queueKey) {
48843
- for (const running of turns.filter((t) => t.lastCliState === "running")) {
48844
- runIdToQueueKey.set(running.turnId, queueKey);
48880
+ for (const running2 of turns.filter((t) => t.lastCliState === "running")) {
48881
+ runIdToQueueKey.set(running2.turnId, queueKey);
48882
+ }
48883
+ }
48884
+
48885
+ // src/prompt-turn-queue/runner/dispatch-started-prompt-queue-runs.ts
48886
+ async function dispatchStartedPromptQueueRuns(entries, started, deps) {
48887
+ for (const [queueKey] of entries) {
48888
+ const file2 = await readPersistedQueue(queueKey);
48889
+ const running2 = file2?.turns.find((turn) => turn.lastCliState === "running");
48890
+ if (running2 && started.has(running2.turnId) && getRunIdQueueKey(running2.turnId) === queueKey) {
48891
+ dispatchLocalPrompt(running2, deps);
48892
+ }
48893
+ await yieldToEventLoop();
48894
+ }
48895
+ }
48896
+
48897
+ // src/prompt-turn-queue/runner/handle-prompt-queue-cancellations.ts
48898
+ init_yield_to_event_loop();
48899
+
48900
+ // src/prompt-turn-queue/client-report.ts
48901
+ function sendPromptQueueClientReport(ws, queues) {
48902
+ if (!ws) return false;
48903
+ const wireQueues = {};
48904
+ for (const [queueKey, rows] of Object.entries(queues)) {
48905
+ wireQueues[queueKey] = rows.map((r) => ({ turnId: r.turnId, clientState: r.cliState }));
48906
+ }
48907
+ sendWsMessage(ws, { type: "prompt_queue_client_report", queues: wireQueues });
48908
+ return true;
48909
+ }
48910
+
48911
+ // src/prompt-turn-queue/runner/finalize-prompt-turn-on-bridge.ts
48912
+ async function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
48913
+ if (!runId) return false;
48914
+ const queueKey = deleteRunIdQueueKey(runId);
48915
+ if (!queueKey) return false;
48916
+ const f = await readPersistedQueue(queueKey);
48917
+ if (!f) return false;
48918
+ const t = f.turns.find((x) => x.turnId === runId);
48919
+ if (!t) return false;
48920
+ t.lastCliState = opts?.terminalCliState ?? (success2 ? "stopped" : "failed");
48921
+ await writePersistedQueue(f);
48922
+ sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId, cliState: t.lastCliState }] });
48923
+ return true;
48924
+ }
48925
+
48926
+ // src/prompt-turn-queue/runner/handle-prompt-queue-cancellations.ts
48927
+ async function handlePromptQueueCancellations(entries, deps) {
48928
+ for (const [queueKey] of entries) {
48929
+ const file2 = await readPersistedQueue(queueKey);
48930
+ const turn = file2?.turns.find((row) => row.bridgeServerState === "cancel_requested" && row.lastCliState === "running");
48931
+ if (!turn) {
48932
+ await yieldToEventLoop();
48933
+ continue;
48934
+ }
48935
+ deps.log(`[Queue] Cancellation request received for turn ${turn.turnId.slice(0, 8)}\u2026`);
48936
+ if (await deps.acpManager.cancelRun(turn.turnId)) {
48937
+ await yieldToEventLoop();
48938
+ continue;
48939
+ }
48940
+ deps.log(`[Queue] cancel_requested for ${turn.turnId.slice(0, 8)}\u2026 with no local run; marking cancelled.`);
48941
+ await finalizePromptTurnOnBridge(deps.getWs, turn.turnId, false, { terminalCliState: "cancelled" });
48942
+ const ws = deps.getWs();
48943
+ if (ws && turn.sessionId) {
48944
+ sendWsMessage(ws, {
48945
+ type: "prompt_result",
48946
+ sessionId: turn.sessionId,
48947
+ runId: turn.turnId,
48948
+ success: false,
48949
+ error: "Stopped by user",
48950
+ stopReason: "cancelled"
48951
+ });
48952
+ }
48953
+ await yieldToEventLoop();
48845
48954
  }
48846
48955
  }
48847
48956
 
48957
+ // src/prompt-turn-queue/runner/persist-prompt-queue-snapshot.ts
48958
+ init_yield_to_event_loop();
48959
+ async function persistPromptQueueSnapshot(entries) {
48960
+ for (const [queueKey, serverTurns] of entries) {
48961
+ const file2 = await mergeBridgeServerQueueSnapshot(queueKey, serverTurns);
48962
+ await writePersistedQueue(file2);
48963
+ await yieldToEventLoop();
48964
+ }
48965
+ for (const [queueKey] of entries) {
48966
+ const file2 = await readPersistedQueue(queueKey);
48967
+ if (file2) syncRunningTurnQueueKeys(file2.turns, queueKey);
48968
+ await yieldToEventLoop();
48969
+ }
48970
+ }
48971
+
48972
+ // src/prompt-turn-queue/runner/prompt-queue-snapshot-types.ts
48973
+ function promptQueueSnapshotEntries(queues) {
48974
+ return Object.entries(queues).filter((entry) => Array.isArray(entry[1]));
48975
+ }
48976
+
48977
+ // src/prompt-turn-queue/runner/start-prompt-queue-runs.ts
48978
+ init_yield_to_event_loop();
48979
+
48980
+ // src/prompt-turn-queue/runner/queue-selection.ts
48981
+ function pickNextRunnableTurn(turns) {
48982
+ for (const t of turns) {
48983
+ if (t.bridgeServerState === "discarded" || t.bridgeServerState === "stopping") continue;
48984
+ if (t.bridgeServerState === "cancel_requested") continue;
48985
+ if (!isRunnableBridgePromptTurnServerState(t.bridgeServerState)) continue;
48986
+ if (t.lastCliState === "running" || t.lastCliState === "stopped" || t.lastCliState === "failed" || t.lastCliState === "cancelled") {
48987
+ continue;
48988
+ }
48989
+ return t;
48990
+ }
48991
+ return null;
48992
+ }
48993
+ function hasRunningTurn(turns) {
48994
+ return turns.some((t) => t.lastCliState === "running");
48995
+ }
48996
+
48848
48997
  // src/prompt-turn-queue/runner/run-local-revert-before-queued-prompt.ts
48849
48998
  import fs58 from "node:fs";
48850
48999
 
@@ -48962,96 +49111,41 @@ async function runLocalRevertBeforeQueuedPrompt(next, deps) {
48962
49111
  return res.ok;
48963
49112
  }
48964
49113
 
48965
- // src/prompt-turn-queue/runner/finalize-prompt-turn-on-bridge.ts
48966
- async function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
48967
- if (!runId) return false;
48968
- const queueKey = deleteRunIdQueueKey(runId);
48969
- if (!queueKey) return false;
48970
- const f = await readPersistedQueue(queueKey);
48971
- if (!f) return false;
48972
- const t = f.turns.find((x) => x.turnId === runId);
48973
- if (!t) return false;
48974
- t.lastCliState = opts?.terminalCliState ?? (success2 ? "stopped" : "failed");
48975
- await writePersistedQueue(f);
48976
- sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId, cliState: t.lastCliState }] });
48977
- return true;
48978
- }
48979
-
48980
- // src/prompt-turn-queue/runner/apply-prompt-queue-state-from-server.ts
48981
- async function applyPromptQueueStateFromServer(msg, deps) {
48982
- const raw = msg.queues;
48983
- if (!raw || typeof raw !== "object") return;
48984
- const getWs = deps.getWs;
48985
- for (const [queueKey, serverTurns] of Object.entries(raw)) {
48986
- if (!Array.isArray(serverTurns)) continue;
48987
- const file2 = await mergeBridgeServerQueueSnapshot(queueKey, serverTurns);
48988
- await writePersistedQueue(file2);
48989
- }
48990
- for (const [queueKey, serverTurns] of Object.entries(raw)) {
48991
- if (!Array.isArray(serverTurns)) continue;
48992
- const file2 = await readPersistedQueue(queueKey);
48993
- if (!file2) continue;
48994
- syncRunningTurnQueueKeys(file2.turns, queueKey);
48995
- }
48996
- for (const [queueKey, serverTurns] of Object.entries(raw)) {
48997
- if (!Array.isArray(serverTurns)) continue;
48998
- const file2 = await readPersistedQueue(queueKey);
48999
- if (!file2) continue;
49000
- const cancelRow = file2.turns.find((t) => t.bridgeServerState === "cancel_requested" && t.lastCliState === "running");
49001
- if (cancelRow) {
49002
- const localCancelHandled = await deps.acpManager.cancelRun(cancelRow.turnId);
49003
- if (!localCancelHandled) {
49004
- deps.log(
49005
- `[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.`
49006
- );
49007
- await finalizePromptTurnOnBridge(deps.getWs, cancelRow.turnId, false, { terminalCliState: "cancelled" });
49008
- const ws = deps.getWs();
49009
- if (ws && cancelRow.sessionId) {
49010
- sendWsMessage(ws, {
49011
- type: "prompt_result",
49012
- sessionId: cancelRow.sessionId,
49013
- runId: cancelRow.turnId,
49014
- success: false,
49015
- error: "Stopped by user",
49016
- stopReason: "cancelled"
49017
- });
49018
- }
49019
- }
49020
- }
49021
- }
49114
+ // src/prompt-turn-queue/runner/start-prompt-queue-runs.ts
49115
+ async function startPromptQueueRuns(entries, deps) {
49022
49116
  const report = {};
49023
- const startedThisTick = /* @__PURE__ */ new Set();
49024
- for (const [queueKey, serverTurns] of Object.entries(raw)) {
49025
- if (!Array.isArray(serverTurns)) continue;
49117
+ const started = /* @__PURE__ */ new Set();
49118
+ for (const [queueKey] of entries) {
49026
49119
  const file2 = await readPersistedQueue(queueKey);
49027
- if (!file2) continue;
49028
- if (hasRunningTurn(file2.turns)) continue;
49120
+ if (!file2 || hasRunningTurn(file2.turns)) continue;
49029
49121
  const next = pickNextRunnableTurn(file2.turns);
49030
49122
  if (!next) continue;
49031
49123
  if (!await runLocalRevertBeforeQueuedPrompt(next, deps)) {
49032
49124
  next.lastCliState = "failed";
49033
49125
  await writePersistedQueue(file2);
49034
- sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: next.turnId, cliState: "failed" }] });
49126
+ sendPromptQueueClientReport(deps.getWs(), { [queueKey]: [{ turnId: next.turnId, cliState: "failed" }] });
49035
49127
  continue;
49036
49128
  }
49037
49129
  next.lastCliState = "running";
49038
49130
  await writePersistedQueue(file2);
49039
49131
  setRunIdQueueKey(next.turnId, queueKey);
49040
- startedThisTick.add(next.turnId);
49132
+ started.add(next.turnId);
49041
49133
  report[queueKey] = [{ turnId: next.turnId, cliState: "running" }];
49134
+ await yieldToEventLoop();
49042
49135
  }
49043
- if (Object.keys(report).length > 0) {
49044
- sendPromptQueueClientReport(getWs(), report);
49045
- }
49046
- for (const [queueKey, serverTurns] of Object.entries(raw)) {
49047
- if (!Array.isArray(serverTurns)) continue;
49048
- const file2 = await readPersistedQueue(queueKey);
49049
- if (!file2) continue;
49050
- const running = file2.turns.find((t) => t.lastCliState === "running");
49051
- if (!running || !startedThisTick.has(running.turnId)) continue;
49052
- if (getRunIdQueueKey(running.turnId) !== queueKey) continue;
49053
- dispatchLocalPrompt(running, deps);
49054
- }
49136
+ if (Object.keys(report).length) sendPromptQueueClientReport(deps.getWs(), report);
49137
+ return started;
49138
+ }
49139
+
49140
+ // src/prompt-turn-queue/runner/apply-prompt-queue-state-from-server.ts
49141
+ async function applyPromptQueueStateFromServer(msg, deps) {
49142
+ const raw = msg.queues;
49143
+ if (!raw || typeof raw !== "object") return;
49144
+ const entries = promptQueueSnapshotEntries(raw);
49145
+ await persistPromptQueueSnapshot(entries);
49146
+ await handlePromptQueueCancellations(entries, deps);
49147
+ const started = await startPromptQueueRuns(entries, deps);
49148
+ await dispatchStartedPromptQueueRuns(entries, started, deps);
49055
49149
  }
49056
49150
 
49057
49151
  // src/agents/acp/from-bridge/bridge-prompt-wiring.ts
@@ -49317,10 +49411,34 @@ var handlePromptMessage = (msg, deps) => {
49317
49411
  handleBridgePrompt(msg, deps);
49318
49412
  };
49319
49413
 
49414
+ // src/prompt-turn-queue/runner/serial-prompt-queue-work.ts
49415
+ var running = false;
49416
+ var latestWork = null;
49417
+ async function drain() {
49418
+ while (latestWork) {
49419
+ const work = latestWork;
49420
+ latestWork = null;
49421
+ await work();
49422
+ }
49423
+ }
49424
+ function enqueueLatestPromptQueueStateWork(work) {
49425
+ latestWork = work;
49426
+ if (running) return;
49427
+ running = true;
49428
+ void drain().finally(() => {
49429
+ running = false;
49430
+ if (latestWork) enqueueLatestPromptQueueStateWork(latestWork);
49431
+ });
49432
+ }
49433
+
49320
49434
  // src/routing/handlers/prompt-queue-state.ts
49321
49435
  var handlePromptQueueStateMessage = (msg, deps) => {
49322
- void applyPromptQueueStateFromServer(msg, deps).catch((err) => {
49323
- deps.log(`[Queue] applyPromptQueueStateFromServer failed: ${err instanceof Error ? err.message : String(err)}`);
49436
+ enqueueLatestPromptQueueStateWork(async () => {
49437
+ try {
49438
+ await applyPromptQueueStateFromServer(msg, deps);
49439
+ } catch (err) {
49440
+ deps.log(`[Queue] applyPromptQueueStateFromServer failed: ${err instanceof Error ? err.message : String(err)}`);
49441
+ }
49324
49442
  });
49325
49443
  };
49326
49444
 
@@ -50292,6 +50410,7 @@ function dispatchBridgeMessage(msg, deps) {
50292
50410
  switch (msg.type) {
50293
50411
  case "auth_token":
50294
50412
  case "bridge_identified":
50413
+ case "installed_agent_auth_sync":
50295
50414
  case "ha":
50296
50415
  dispatchBridgeConnectionMessage(msg, deps);
50297
50416
  break;