@buildautomaton/cli 0.1.78 → 0.1.79

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
@@ -3691,7 +3691,7 @@ var require_tree_kill = __commonJS({
3691
3691
  "../../node_modules/.pnpm/tree-kill@1.2.2/node_modules/tree-kill/index.js"(exports, module) {
3692
3692
  "use strict";
3693
3693
  var childProcess2 = __require("child_process");
3694
- var spawn11 = childProcess2.spawn;
3694
+ var spawn12 = childProcess2.spawn;
3695
3695
  var exec = childProcess2.exec;
3696
3696
  module.exports = function(pid, signal, callback) {
3697
3697
  if (typeof signal === "function" && callback === void 0) {
@@ -3716,7 +3716,7 @@ var require_tree_kill = __commonJS({
3716
3716
  break;
3717
3717
  case "darwin":
3718
3718
  buildProcessTree(pid, tree, pidsToProcess, function(parentPid) {
3719
- return spawn11("pgrep", ["-P", parentPid]);
3719
+ return spawn12("pgrep", ["-P", parentPid]);
3720
3720
  }, function() {
3721
3721
  killAll(tree, signal, callback);
3722
3722
  });
@@ -3728,7 +3728,7 @@ var require_tree_kill = __commonJS({
3728
3728
  // break;
3729
3729
  default:
3730
3730
  buildProcessTree(pid, tree, pidsToProcess, function(parentPid) {
3731
- return spawn11("ps", ["-o", "pid", "--no-headers", "--ppid", parentPid]);
3731
+ return spawn12("ps", ["-o", "pid", "--no-headers", "--ppid", parentPid]);
3732
3732
  }, function() {
3733
3733
  killAll(tree, signal, callback);
3734
3734
  });
@@ -21909,31 +21909,31 @@ function handleWorkerOutMessage(message) {
21909
21909
  return;
21910
21910
  }
21911
21911
  if (message.type === "error") {
21912
- const pending2 = message.requestId != null ? pendingRequests.get(message.requestId) : void 0;
21912
+ const pending3 = message.requestId != null ? pendingRequests.get(message.requestId) : void 0;
21913
21913
  maybeLogCodeNavCacheWorkerError(message.message);
21914
- if (pending2 != null) {
21914
+ if (pending3 != null) {
21915
21915
  pendingRequests.delete(message.requestId);
21916
21916
  if (isCliImmediateShutdownRequested()) {
21917
- pending2.reject(new CliSqliteInterrupted());
21917
+ pending3.reject(new CliSqliteInterrupted());
21918
21918
  } else {
21919
- pending2.reject(new Error(message.message));
21919
+ pending3.reject(new Error(message.message));
21920
21920
  }
21921
21921
  }
21922
21922
  return;
21923
21923
  }
21924
21924
  if (!("requestId" in message)) return;
21925
- const pending = pendingRequests.get(message.requestId);
21926
- if (pending == null) return;
21925
+ const pending2 = pendingRequests.get(message.requestId);
21926
+ if (pending2 == null) return;
21927
21927
  pendingRequests.delete(message.requestId);
21928
- pending.resolve(message);
21928
+ pending2.resolve(message);
21929
21929
  }
21930
21930
  function resetWorkerReadyState() {
21931
21931
  workerReady = false;
21932
21932
  workerReadyWaiters = [];
21933
21933
  }
21934
21934
  function rejectAllPendingRequests(error40) {
21935
- for (const [, pending] of pendingRequests) {
21936
- pending.reject(error40);
21935
+ for (const [, pending2] of pendingRequests) {
21936
+ pending2.reject(error40);
21937
21937
  }
21938
21938
  pendingRequests.clear();
21939
21939
  }
@@ -22966,14 +22966,14 @@ function legacyCliDiskMigrationIsPending() {
22966
22966
  return false;
22967
22967
  }
22968
22968
  function importCliSqliteLegacyDiskData(db, log2) {
22969
- const pending = legacyCliDiskMigrationIsPending();
22970
- if (pending && log2) {
22969
+ const pending2 = legacyCliDiskMigrationIsPending();
22970
+ if (pending2 && log2) {
22971
22971
  log2("Migrating legacy on-disk CLI data to SQLite\u2026");
22972
22972
  }
22973
22973
  archiveLegacyFileIndexJsonFiles();
22974
22974
  importLegacyAgentSessionsFromDisk(db);
22975
22975
  importLegacyPromptQueuesFromDisk(db);
22976
- if (pending && log2) {
22976
+ if (pending2 && log2) {
22977
22977
  log2("Legacy on-disk CLI data migration finished.");
22978
22978
  }
22979
22979
  }
@@ -28219,9 +28219,9 @@ function createWsBridge(options) {
28219
28219
  return ws;
28220
28220
  }
28221
28221
  function sendWsMessage(ws, payload) {
28222
- if (ws.readyState === wrapper_default.OPEN) {
28223
- ws.send(JSON.stringify(payload));
28224
- }
28222
+ if (ws.readyState !== wrapper_default.OPEN) return false;
28223
+ ws.send(JSON.stringify(payload));
28224
+ return true;
28225
28225
  }
28226
28226
 
28227
28227
  // src/files/cwd/index.ts
@@ -29352,6 +29352,31 @@ function getAgentModelFromAgentConfig(config2) {
29352
29352
  var HOUR_MS = 36e5;
29353
29353
  var DAY_MS = 24 * HOUR_MS;
29354
29354
 
29355
+ // ../types/src/hosts/skus.ts
29356
+ function defineHostSku(params) {
29357
+ return structuredClone(params);
29358
+ }
29359
+ var FLY_LEGACY_HOST_SKU = defineHostSku({
29360
+ id: "fly-shared-1x512-1gb",
29361
+ provider: "fly",
29362
+ compute: { cpus: 1, cpuKind: "shared" },
29363
+ memory: { memoryMb: 512 },
29364
+ storage: { storageGb: 1 },
29365
+ monthlyPriceCents: 750
29366
+ });
29367
+ var FLY_DEFAULT_HOST_SKU = defineHostSku({
29368
+ id: "fly-shared-1x1024-1gb",
29369
+ provider: "fly",
29370
+ compute: { cpus: 1, cpuKind: "shared" },
29371
+ memory: { memoryMb: 1024 },
29372
+ storage: { storageGb: 1 },
29373
+ monthlyPriceCents: 1e3
29374
+ });
29375
+ var HOST_SKUS_BY_ID = {
29376
+ [FLY_LEGACY_HOST_SKU.id]: FLY_LEGACY_HOST_SKU,
29377
+ [FLY_DEFAULT_HOST_SKU.id]: FLY_DEFAULT_HOST_SKU
29378
+ };
29379
+
29355
29380
  // ../types/src/bridges/agents/types.ts
29356
29381
  var INSTALLABLE_BRIDGE_AGENTS = [
29357
29382
  { value: "claude-code", label: "Anthropic Claude Code", tokenLabel: "Anthropic API key", tokenEnvVar: "ANTHROPIC_API_KEY" },
@@ -29465,11 +29490,11 @@ function createSdkStdioExtNotificationHandler(options) {
29465
29490
 
29466
29491
  // src/agents/acp/clients/sdk/sdk-stdio-permission-request-handshake.ts
29467
29492
  function awaitSdkStdioPermissionRequestHandshake(params) {
29468
- const { requestId, paramsRecord, pending, onRequest } = params;
29493
+ const { requestId, paramsRecord, pending: pending2, onRequest } = params;
29469
29494
  return new Promise((resolve35) => {
29470
- pending.set(requestId, { resolve: resolve35, params: paramsRecord });
29495
+ pending2.set(requestId, { resolve: resolve35, params: paramsRecord });
29471
29496
  if (onRequest == null) {
29472
- pending.delete(requestId);
29497
+ pending2.delete(requestId);
29473
29498
  resolve35({ outcome: { outcome: "denied" } });
29474
29499
  return;
29475
29500
  }
@@ -29485,9 +29510,9 @@ function awaitSdkStdioPermissionRequestHandshake(params) {
29485
29510
  }
29486
29511
 
29487
29512
  // src/agents/acp/clients/sdk/sdk-stdio-permission-pending.ts
29488
- function resolvePendingSdkStdioPermissionCancellations(pending) {
29489
- for (const [id, entry] of [...pending.entries()]) {
29490
- pending.delete(id);
29513
+ function resolvePendingSdkStdioPermissionCancellations(pending2) {
29514
+ for (const [id, entry] of [...pending2.entries()]) {
29515
+ pending2.delete(id);
29491
29516
  entry.resolve({ outcome: { outcome: "cancelled" } });
29492
29517
  }
29493
29518
  }
@@ -30613,7 +30638,7 @@ function installBridgeProcessResilience() {
30613
30638
  }
30614
30639
 
30615
30640
  // src/cli-version.ts
30616
- var CLI_VERSION = "0.1.78".length > 0 ? "0.1.78" : "0.0.0-dev";
30641
+ var CLI_VERSION = "0.1.79".length > 0 ? "0.1.79" : "0.0.0-dev";
30617
30642
 
30618
30643
  // src/connection/heartbeat/constants.ts
30619
30644
  var BRIDGE_APP_HEARTBEAT_INTERVAL_MS = 1e4;
@@ -33220,8 +33245,8 @@ function createCursorAcpSessionContext(options) {
33220
33245
 
33221
33246
  // src/agents/acp/clients/cursor/cancel-pending-cursor-permission-requests.ts
33222
33247
  function cancelPendingCursorPermissionRequests(pendingRequests2, respond) {
33223
- for (const [reqId, pending] of [...pendingRequests2.entries()]) {
33224
- if (pending.method === "session/request_permission") {
33248
+ for (const [reqId, pending2] of [...pendingRequests2.entries()]) {
33249
+ if (pending2.method === "session/request_permission") {
33225
33250
  respond(reqId, { outcome: { outcome: "cancelled" } });
33226
33251
  pendingRequests2.delete(reqId);
33227
33252
  }
@@ -33413,8 +33438,8 @@ function handleCursorIncomingPermissionRequest(id, method, msg, deps) {
33413
33438
 
33414
33439
  // src/agents/acp/clients/cursor/cursor-incoming-resolve-request.ts
33415
33440
  function resolveCursorIncomingRequest(pendingRequests2, respond, requestId, result) {
33416
- const pending = pendingRequests2.get(requestId);
33417
- const payload = pending?.method === "session/request_permission" ? enrichAcpPermissionRpcResultFromRequestParams(result, pending.params) : result;
33441
+ const pending2 = pendingRequests2.get(requestId);
33442
+ const payload = pending2?.method === "session/request_permission" ? enrichAcpPermissionRpcResultFromRequestParams(result, pending2.params) : result;
33418
33443
  respond(requestId, payload);
33419
33444
  pendingRequests2.delete(requestId);
33420
33445
  }
@@ -33552,25 +33577,25 @@ function createCursorJsonRpcInboundRespond(stdin) {
33552
33577
 
33553
33578
  // src/agents/acp/clients/cursor/cursor-json-rpc-outbound.ts
33554
33579
  function createCursorJsonRpcOutboundPending() {
33555
- const pending = /* @__PURE__ */ new Map();
33580
+ const pending2 = /* @__PURE__ */ new Map();
33556
33581
  let nextId = 1;
33557
33582
  function allocateId() {
33558
33583
  return nextId++;
33559
33584
  }
33560
33585
  function register(id, waiter) {
33561
- pending.set(id, waiter);
33586
+ pending2.set(id, waiter);
33562
33587
  }
33563
33588
  function settleResponse(id, msg) {
33564
- const waiter = pending.get(id);
33589
+ const waiter = pending2.get(id);
33565
33590
  if (!waiter) return false;
33566
- pending.delete(id);
33591
+ pending2.delete(id);
33567
33592
  if (msg.error) waiter.reject(msg.error);
33568
33593
  else waiter.resolve(msg.result);
33569
33594
  return true;
33570
33595
  }
33571
33596
  function rejectOnWriteError(id, err) {
33572
- const waiter = pending.get(id);
33573
- pending.delete(id);
33597
+ const waiter = pending2.get(id);
33598
+ pending2.delete(id);
33574
33599
  waiter?.reject(err);
33575
33600
  }
33576
33601
  return { allocateId, register, settleResponse, rejectOnWriteError };
@@ -38458,11 +38483,11 @@ function tryConsumeBinaryProxyBody(raw, deps) {
38458
38483
  if (!PROXY_ID_RE.test(id)) return false;
38459
38484
  const body = raw.slice(PROXY_ID_BYTES);
38460
38485
  const bodyBytes = body.length > 0 ? new Uint8Array(body) : new Uint8Array(0);
38461
- const pending = deps.pendingProxyBody.get(id);
38462
- if (pending) {
38486
+ const pending2 = deps.pendingProxyBody.get(id);
38487
+ if (pending2) {
38463
38488
  deps.pendingProxyBody.delete(id);
38464
38489
  deps.startStreamingProxy({
38465
- ...pending.pr,
38490
+ ...pending2.pr,
38466
38491
  body: bodyBytes.length > 0 ? bodyBytes : void 0
38467
38492
  });
38468
38493
  return true;
@@ -38855,9 +38880,9 @@ function processHeartbeatAck(params) {
38855
38880
  if (awaitingSeq === null) return { awaitingSeq, missed: 0 };
38856
38881
  if (!Number.isFinite(seq)) return { awaitingSeq, missed: 0 };
38857
38882
  const ack = Math.trunc(seq);
38858
- const pending = awaitingSeq;
38859
- if (ack < pending) return { awaitingSeq, missed: 0 };
38860
- if (ack === pending) {
38883
+ const pending2 = awaitingSeq;
38884
+ if (ack < pending2) return { awaitingSeq, missed: 0 };
38885
+ if (ack === pending2) {
38861
38886
  recordRtt(Date.now() - sentAtMs);
38862
38887
  }
38863
38888
  return { awaitingSeq: null, missed: 0 };
@@ -49226,18 +49251,62 @@ async function applyPromptQueueStateFromServer(msg, deps) {
49226
49251
  }
49227
49252
  }
49228
49253
 
49254
+ // src/agents/acp/from-bridge/pending-prompt-results.ts
49255
+ var pending = [];
49256
+ function enqueuePendingPromptResult(message) {
49257
+ const runId = typeof message.runId === "string" ? message.runId : "";
49258
+ if (runId) {
49259
+ const idx = pending.findIndex((m) => m.runId === runId);
49260
+ if (idx >= 0) pending.splice(idx, 1);
49261
+ }
49262
+ pending.push(message);
49263
+ }
49264
+ function flushPendingPromptResults(getWs, encrypt) {
49265
+ if (pending.length === 0) return;
49266
+ const ws = getWs();
49267
+ if (!ws || ws.readyState !== wrapper_default.OPEN) return;
49268
+ const still = [];
49269
+ for (const message of pending) {
49270
+ const wire = encrypt ? encrypt(message) : message;
49271
+ if (!sendWsMessage(ws, wire)) still.push(message);
49272
+ }
49273
+ pending.length = 0;
49274
+ pending.push(...still);
49275
+ }
49276
+
49277
+ // src/agents/acp/from-bridge/send-session-update-wire.ts
49278
+ function sendSessionUpdateWire(getWs, payload, opts) {
49279
+ const s = getWs();
49280
+ if (!s || s.readyState !== wrapper_default.OPEN) {
49281
+ opts.log("[Bridge service] Session update not sent: not connected to the bridge.");
49282
+ return;
49283
+ }
49284
+ const p = payload;
49285
+ const wire = p.type === "session_update" && opts.e2ee ? opts.e2ee.encryptFields(payload, ["payload"]) : p.type === "session_file_change" && opts.e2ee ? opts.e2ee.encryptFields(payload, [
49286
+ "path",
49287
+ "oldText",
49288
+ "newText",
49289
+ "patchContent",
49290
+ "isDirectory",
49291
+ "directoryRemoved"
49292
+ ]) : payload;
49293
+ sendWsMessage(s, wire);
49294
+ }
49295
+
49229
49296
  // src/agents/acp/from-bridge/bridge-prompt-wiring.ts
49230
49297
  function createBridgePromptSenders(deps, getWs) {
49231
49298
  const sendBridgeMessage = (message, encryptedFields = []) => {
49232
49299
  const s = getWs();
49233
- if (!s) return false;
49300
+ if (!s || s.readyState !== wrapper_default.OPEN) return false;
49234
49301
  const wire = deps.e2ee && encryptedFields.length > 0 ? deps.e2ee.encryptFields(message, encryptedFields) : message;
49235
- sendWsMessage(s, wire);
49236
- return true;
49302
+ return sendWsMessage(s, wire);
49237
49303
  };
49238
49304
  const sendResult = (result) => {
49239
- const encryptedFields = result.type === "prompt_result" ? ["output", "error"] : [];
49240
- sendBridgeMessage(result, encryptedFields);
49305
+ const sent = sendBridgeMessage(result, result.type === "prompt_result" ? ["output", "error"] : []);
49306
+ if (!sent && result.type === "prompt_result") {
49307
+ enqueuePendingPromptResult(result);
49308
+ deps.log("[Bridge service] prompt_result deferred until bridge reconnect.");
49309
+ }
49241
49310
  if (result.type === "prompt_result") {
49242
49311
  const pr = result;
49243
49312
  const cancelled = pr.stopReason === "cancelled";
@@ -49250,24 +49319,11 @@ function createBridgePromptSenders(deps, getWs) {
49250
49319
  });
49251
49320
  }
49252
49321
  };
49253
- const sendSessionUpdate = (payload) => {
49254
- const s = getWs();
49255
- if (!s) {
49256
- deps.log("[Bridge service] Session update not sent: not connected to the bridge.");
49257
- return;
49258
- }
49259
- const p = payload;
49260
- const wire = p.type === "session_update" && deps.e2ee ? deps.e2ee.encryptFields(payload, ["payload"]) : p.type === "session_file_change" && deps.e2ee ? deps.e2ee.encryptFields(payload, [
49261
- "path",
49262
- "oldText",
49263
- "newText",
49264
- "patchContent",
49265
- "isDirectory",
49266
- "directoryRemoved"
49267
- ]) : payload;
49268
- sendWsMessage(s, wire);
49322
+ return {
49323
+ sendBridgeMessage,
49324
+ sendResult,
49325
+ sendSessionUpdate: (payload) => sendSessionUpdateWire(getWs, payload, { e2ee: deps.e2ee, log: deps.log })
49269
49326
  };
49270
- return { sendBridgeMessage, sendResult, sendSessionUpdate };
49271
49327
  }
49272
49328
 
49273
49329
  // src/agents/acp/from-bridge/handle-bridge-prompt/parse-bridge-attachments.ts
@@ -49977,25 +50033,59 @@ var handleInstallSkillsMessage = (msg, deps) => {
49977
50033
  })();
49978
50034
  };
49979
50035
 
49980
- // src/agents/install/commands/run-npm-global-install.ts
49981
- import { execFile as execFile9 } from "node:child_process";
49982
- import { promisify as promisify10 } from "node:util";
49983
-
49984
- // src/agents/install/format-command-output.ts
49985
- function formatCommandOutput(stdout, stderr) {
49986
- const parts = [String(stdout ?? "").trimEnd(), String(stderr ?? "").trimEnd()].filter(Boolean);
49987
- return parts.join("\n");
50036
+ // src/agents/install/run-streaming-command.ts
50037
+ import { spawn as spawn11 } from "node:child_process";
50038
+ import * as readline3 from "node:readline";
50039
+ function runStreamingCommand(command, args, options) {
50040
+ return new Promise((resolve35, reject) => {
50041
+ const child = spawn11(command, args, {
50042
+ env: options.env,
50043
+ stdio: ["ignore", "pipe", "pipe"]
50044
+ });
50045
+ let settled = false;
50046
+ const timer = options.timeoutMs != null ? setTimeout(() => {
50047
+ child.kill("SIGKILL");
50048
+ if (!settled) {
50049
+ settled = true;
50050
+ reject(new Error(`Command timed out after ${options.timeoutMs}ms`));
50051
+ }
50052
+ }, options.timeoutMs) : null;
50053
+ const onLine = (line) => {
50054
+ if (line.length > 0) options.onLine?.(line);
50055
+ };
50056
+ if (child.stdout) {
50057
+ readline3.createInterface({ input: child.stdout, crlfDelay: Infinity }).on("line", onLine);
50058
+ }
50059
+ if (child.stderr) {
50060
+ readline3.createInterface({ input: child.stderr, crlfDelay: Infinity }).on("line", onLine);
50061
+ }
50062
+ child.on("error", (err) => {
50063
+ if (timer) clearTimeout(timer);
50064
+ if (!settled) {
50065
+ settled = true;
50066
+ reject(err);
50067
+ }
50068
+ });
50069
+ child.on("close", (code, signal) => {
50070
+ if (timer) clearTimeout(timer);
50071
+ if (!settled) {
50072
+ settled = true;
50073
+ resolve35({ code, signal });
50074
+ }
50075
+ });
50076
+ });
49988
50077
  }
49989
50078
 
49990
50079
  // src/agents/install/commands/run-npm-global-install.ts
49991
- var execFileAsync8 = promisify10(execFile9);
49992
- async function runNpmGlobalInstall(packageName, env, timeoutMs = 3e5) {
49993
- const { stdout, stderr } = await execFileAsync8("npm", ["install", "-g", packageName], {
49994
- timeout: timeoutMs,
50080
+ async function runNpmGlobalInstall(packageName, env, options) {
50081
+ const result = await runStreamingCommand("npm", ["install", "-g", packageName], {
49995
50082
  env: bridgeAgentPathEnv(env),
49996
- maxBuffer: 10 * 1024 * 1024
50083
+ timeoutMs: options?.timeoutMs ?? 3e5,
50084
+ onLine: options?.onLine
49997
50085
  });
49998
- return formatCommandOutput(stdout, stderr);
50086
+ if (result.code !== 0) {
50087
+ throw new Error(`npm install -g ${packageName} failed (exit ${result.code ?? "signal"})`);
50088
+ }
49999
50089
  }
50000
50090
 
50001
50091
  // src/agents/install/commands/claude-code.ts
@@ -50003,11 +50093,12 @@ var claudeCodeInstallCommand = {
50003
50093
  agentType: "claude-code",
50004
50094
  detectCommand: "claude",
50005
50095
  async install(ctx) {
50006
- const logOutput = await runNpmGlobalInstall("@anthropic-ai/claude-code", {
50007
- ...ctx.env,
50008
- ANTHROPIC_API_KEY: ctx.authToken
50009
- });
50010
- ctx.onProgress?.("Installing Anthropic Claude Code", logOutput || void 0);
50096
+ ctx.onProgress?.("Installing Anthropic Claude Code");
50097
+ await runNpmGlobalInstall(
50098
+ "@anthropic-ai/claude-code",
50099
+ { ...ctx.env, ANTHROPIC_API_KEY: ctx.authToken },
50100
+ { onLine: (line) => ctx.onProgress?.("Installing Anthropic Claude Code", line) }
50101
+ );
50011
50102
  }
50012
50103
  };
50013
50104
 
@@ -50016,34 +50107,34 @@ var codexAcpInstallCommand = {
50016
50107
  agentType: "codex-acp",
50017
50108
  detectCommand: "codex",
50018
50109
  async install(ctx) {
50019
- const logOutput = await runNpmGlobalInstall("@openai/codex", {
50020
- ...ctx.env,
50021
- OPENAI_API_KEY: ctx.authToken
50022
- });
50023
- ctx.onProgress?.("Installing Codex", logOutput || void 0);
50110
+ ctx.onProgress?.("Installing Codex");
50111
+ await runNpmGlobalInstall(
50112
+ "@openai/codex",
50113
+ { ...ctx.env, OPENAI_API_KEY: ctx.authToken },
50114
+ { onLine: (line) => ctx.onProgress?.("Installing Codex", line) }
50115
+ );
50024
50116
  }
50025
50117
  };
50026
50118
 
50027
50119
  // src/agents/install/commands/cursor-cli.ts
50028
- import { execFile as execFile10 } from "node:child_process";
50029
- import { promisify as promisify11 } from "node:util";
50030
- var execFileAsync9 = promisify11(execFile10);
50031
50120
  var cursorCliInstallCommand = {
50032
50121
  agentType: "cursor-cli",
50033
50122
  detectCommand: "agent",
50034
50123
  alternateDetectCommands: ["cursor-agent"],
50035
50124
  async install(ctx) {
50036
- const { stdout, stderr } = await execFileAsync9(
50125
+ ctx.onProgress?.("Installing Cursor CLI");
50126
+ const result = await runStreamingCommand(
50037
50127
  "bash",
50038
50128
  ["-lc", "curl -fsSL https://cursor.com/install | bash"],
50039
50129
  {
50040
- timeout: 3e5,
50130
+ timeoutMs: 3e5,
50041
50131
  env: { ...bridgeAgentPathEnv(ctx.env), CURSOR_API_KEY: ctx.authToken },
50042
- maxBuffer: 10 * 1024 * 1024
50132
+ onLine: (line) => ctx.onProgress?.("Installing Cursor CLI", line)
50043
50133
  }
50044
50134
  );
50045
- const logOutput = formatCommandOutput(stdout, stderr);
50046
- ctx.onProgress?.("Installing Cursor CLI", logOutput || void 0);
50135
+ if (result.code !== 0) {
50136
+ throw new Error(`Cursor CLI install failed (exit ${result.code ?? "signal"})`);
50137
+ }
50047
50138
  }
50048
50139
  };
50049
50140
 
@@ -50052,11 +50143,12 @@ var opencodeInstallCommand = {
50052
50143
  agentType: "opencode",
50053
50144
  detectCommand: "opencode",
50054
50145
  async install(ctx) {
50055
- const logOutput = await runNpmGlobalInstall("opencode-ai", {
50056
- ...ctx.env,
50057
- OPENCODE_API_KEY: ctx.authToken
50058
- });
50059
- ctx.onProgress?.("Installing OpenCode", logOutput || void 0);
50146
+ ctx.onProgress?.("Installing OpenCode");
50147
+ await runNpmGlobalInstall(
50148
+ "opencode-ai",
50149
+ { ...ctx.env, OPENCODE_API_KEY: ctx.authToken },
50150
+ { onLine: (line) => ctx.onProgress?.("Installing OpenCode", line) }
50151
+ );
50060
50152
  }
50061
50153
  };
50062
50154
 
@@ -50117,25 +50209,47 @@ var handleInstallAgentMessage = (msg, deps) => {
50117
50209
  if (!processId || !agentId || !tokenId || !agentType || !authToken) return;
50118
50210
  void (async () => {
50119
50211
  const socket = deps.getWs();
50120
- const report = (step, message, logOutput) => {
50121
- if (socket) {
50122
- sendWsMessage(socket, {
50123
- type: "install_agent_progress",
50124
- processId,
50125
- agentId,
50126
- tokenId,
50127
- agentType,
50128
- step,
50129
- message,
50130
- ...logOutput ? { logOutput } : {}
50131
- });
50212
+ let pendingLines = [];
50213
+ let flushTimer = null;
50214
+ const sendProgress = (message, logOutput) => {
50215
+ if (!socket) return;
50216
+ sendWsMessage(socket, {
50217
+ type: "install_agent_progress",
50218
+ processId,
50219
+ agentId,
50220
+ tokenId,
50221
+ agentType,
50222
+ step: "agent_install_package",
50223
+ message,
50224
+ ...logOutput ? { logOutput } : {}
50225
+ });
50226
+ };
50227
+ const flushLines = (message) => {
50228
+ if (flushTimer) {
50229
+ clearTimeout(flushTimer);
50230
+ flushTimer = null;
50132
50231
  }
50232
+ if (pendingLines.length === 0) return;
50233
+ const logOutput = pendingLines.join("\n");
50234
+ pendingLines = [];
50235
+ sendProgress(message, logOutput);
50133
50236
  };
50134
50237
  const result = await installLocalAgentOnBridge({
50135
50238
  agentType,
50136
50239
  authToken,
50137
- onProgress: (message, logOutput) => report("agent_install_package", message, logOutput)
50240
+ onProgress: (message, logOutput) => {
50241
+ if (logOutput == null) {
50242
+ flushLines(message);
50243
+ sendProgress(message);
50244
+ return;
50245
+ }
50246
+ pendingLines.push(logOutput);
50247
+ if (!flushTimer) {
50248
+ flushTimer = setTimeout(() => flushLines(message), 100);
50249
+ }
50250
+ }
50138
50251
  });
50252
+ flushLines("Installing agent packages on the bridge machine.");
50139
50253
  if (socket) {
50140
50254
  sendWsMessage(socket, {
50141
50255
  type: "install_agent_result",
@@ -50147,9 +50261,7 @@ var handleInstallAgentMessage = (msg, deps) => {
50147
50261
  error: result.error
50148
50262
  });
50149
50263
  }
50150
- if (result.success) {
50151
- await deps.reportAutoDetectedAgents?.();
50152
- }
50264
+ if (result.success) await deps.reportAutoDetectedAgents?.();
50153
50265
  if (!result.success) {
50154
50266
  deps.log(`[Bridge service] Install agent failed: ${result.error ?? "unknown"}`);
50155
50267
  }
@@ -50734,6 +50846,10 @@ function createMainBridgeOpenHandler(params) {
50734
50846
  if (socket) {
50735
50847
  sendBridgeIdentify(socket, { identifyReportedPaths, e2ee });
50736
50848
  reportGitRepos(getWs, logFn);
50849
+ flushPendingPromptResults(
50850
+ getWs,
50851
+ (message) => e2ee ? e2ee.encryptFields(message, ["output", "error"]) : message
50852
+ );
50737
50853
  try {
50738
50854
  onBridgeSocketOpen?.();
50739
50855
  } catch {
@@ -50878,7 +50994,7 @@ async function createBridgeConnection(options) {
50878
50994
  }
50879
50995
 
50880
50996
  // src/e2e-certificates/key-command.ts
50881
- import * as readline3 from "node:readline";
50997
+ import * as readline4 from "node:readline";
50882
50998
  function installE2eCertificateKeyCommand({
50883
50999
  log: log2,
50884
51000
  onOpenCertificate,
@@ -50889,7 +51005,7 @@ function installE2eCertificateKeyCommand({
50889
51005
  return () => {
50890
51006
  };
50891
51007
  }
50892
- readline3.emitKeypressEvents(process.stdin);
51008
+ readline4.emitKeypressEvents(process.stdin);
50893
51009
  process.stdin.setRawMode(true);
50894
51010
  process.stdin.resume();
50895
51011
  const onKeypress = (str, key) => {