@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/cli.js CHANGED
@@ -7262,31 +7262,31 @@ function handleWorkerOutMessage(message) {
7262
7262
  return;
7263
7263
  }
7264
7264
  if (message.type === "error") {
7265
- const pending2 = message.requestId != null ? pendingRequests.get(message.requestId) : void 0;
7265
+ const pending3 = message.requestId != null ? pendingRequests.get(message.requestId) : void 0;
7266
7266
  maybeLogCodeNavCacheWorkerError(message.message);
7267
- if (pending2 != null) {
7267
+ if (pending3 != null) {
7268
7268
  pendingRequests.delete(message.requestId);
7269
7269
  if (isCliImmediateShutdownRequested()) {
7270
- pending2.reject(new CliSqliteInterrupted());
7270
+ pending3.reject(new CliSqliteInterrupted());
7271
7271
  } else {
7272
- pending2.reject(new Error(message.message));
7272
+ pending3.reject(new Error(message.message));
7273
7273
  }
7274
7274
  }
7275
7275
  return;
7276
7276
  }
7277
7277
  if (!("requestId" in message)) return;
7278
- const pending = pendingRequests.get(message.requestId);
7279
- if (pending == null) return;
7278
+ const pending2 = pendingRequests.get(message.requestId);
7279
+ if (pending2 == null) return;
7280
7280
  pendingRequests.delete(message.requestId);
7281
- pending.resolve(message);
7281
+ pending2.resolve(message);
7282
7282
  }
7283
7283
  function resetWorkerReadyState() {
7284
7284
  workerReady = false;
7285
7285
  workerReadyWaiters = [];
7286
7286
  }
7287
7287
  function rejectAllPendingRequests(error40) {
7288
- for (const [, pending] of pendingRequests) {
7289
- pending.reject(error40);
7288
+ for (const [, pending2] of pendingRequests) {
7289
+ pending2.reject(error40);
7290
7290
  }
7291
7291
  pendingRequests.clear();
7292
7292
  }
@@ -8319,14 +8319,14 @@ function legacyCliDiskMigrationIsPending() {
8319
8319
  return false;
8320
8320
  }
8321
8321
  function importCliSqliteLegacyDiskData(db, log2) {
8322
- const pending = legacyCliDiskMigrationIsPending();
8323
- if (pending && log2) {
8322
+ const pending2 = legacyCliDiskMigrationIsPending();
8323
+ if (pending2 && log2) {
8324
8324
  log2("Migrating legacy on-disk CLI data to SQLite\u2026");
8325
8325
  }
8326
8326
  archiveLegacyFileIndexJsonFiles();
8327
8327
  importLegacyAgentSessionsFromDisk(db);
8328
8328
  importLegacyPromptQueuesFromDisk(db);
8329
- if (pending && log2) {
8329
+ if (pending2 && log2) {
8330
8330
  log2("Legacy on-disk CLI data migration finished.");
8331
8331
  }
8332
8332
  }
@@ -16657,7 +16657,7 @@ var require_tree_kill = __commonJS({
16657
16657
  "../../node_modules/.pnpm/tree-kill@1.2.2/node_modules/tree-kill/index.js"(exports, module) {
16658
16658
  "use strict";
16659
16659
  var childProcess2 = __require("child_process");
16660
- var spawn11 = childProcess2.spawn;
16660
+ var spawn12 = childProcess2.spawn;
16661
16661
  var exec = childProcess2.exec;
16662
16662
  module.exports = function(pid, signal, callback) {
16663
16663
  if (typeof signal === "function" && callback === void 0) {
@@ -16682,7 +16682,7 @@ var require_tree_kill = __commonJS({
16682
16682
  break;
16683
16683
  case "darwin":
16684
16684
  buildProcessTree(pid, tree, pidsToProcess, function(parentPid) {
16685
- return spawn11("pgrep", ["-P", parentPid]);
16685
+ return spawn12("pgrep", ["-P", parentPid]);
16686
16686
  }, function() {
16687
16687
  killAll(tree, signal, callback);
16688
16688
  });
@@ -16694,7 +16694,7 @@ var require_tree_kill = __commonJS({
16694
16694
  // break;
16695
16695
  default:
16696
16696
  buildProcessTree(pid, tree, pidsToProcess, function(parentPid) {
16697
- return spawn11("ps", ["-o", "pid", "--no-headers", "--ppid", parentPid]);
16697
+ return spawn12("ps", ["-o", "pid", "--no-headers", "--ppid", parentPid]);
16698
16698
  }, function() {
16699
16699
  killAll(tree, signal, callback);
16700
16700
  });
@@ -31071,7 +31071,7 @@ var {
31071
31071
  } = import_index.default;
31072
31072
 
31073
31073
  // src/cli-version.ts
31074
- var CLI_VERSION = "0.1.78".length > 0 ? "0.1.78" : "0.0.0-dev";
31074
+ var CLI_VERSION = "0.1.79".length > 0 ? "0.1.79" : "0.0.0-dev";
31075
31075
 
31076
31076
  // src/cli/defaults.ts
31077
31077
  var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
@@ -31698,9 +31698,9 @@ function createWsBridge(options) {
31698
31698
  return ws;
31699
31699
  }
31700
31700
  function sendWsMessage(ws, payload) {
31701
- if (ws.readyState === wrapper_default.OPEN) {
31702
- ws.send(JSON.stringify(payload));
31703
- }
31701
+ if (ws.readyState !== wrapper_default.OPEN) return false;
31702
+ ws.send(JSON.stringify(payload));
31703
+ return true;
31704
31704
  }
31705
31705
 
31706
31706
  // src/connection/heartbeat/constants.ts
@@ -34953,6 +34953,31 @@ function getAgentModelFromAgentConfig(config2) {
34953
34953
  var HOUR_MS = 36e5;
34954
34954
  var DAY_MS = 24 * HOUR_MS;
34955
34955
 
34956
+ // ../types/src/hosts/skus.ts
34957
+ function defineHostSku(params) {
34958
+ return structuredClone(params);
34959
+ }
34960
+ var FLY_LEGACY_HOST_SKU = defineHostSku({
34961
+ id: "fly-shared-1x512-1gb",
34962
+ provider: "fly",
34963
+ compute: { cpus: 1, cpuKind: "shared" },
34964
+ memory: { memoryMb: 512 },
34965
+ storage: { storageGb: 1 },
34966
+ monthlyPriceCents: 750
34967
+ });
34968
+ var FLY_DEFAULT_HOST_SKU = defineHostSku({
34969
+ id: "fly-shared-1x1024-1gb",
34970
+ provider: "fly",
34971
+ compute: { cpus: 1, cpuKind: "shared" },
34972
+ memory: { memoryMb: 1024 },
34973
+ storage: { storageGb: 1 },
34974
+ monthlyPriceCents: 1e3
34975
+ });
34976
+ var HOST_SKUS_BY_ID = {
34977
+ [FLY_LEGACY_HOST_SKU.id]: FLY_LEGACY_HOST_SKU,
34978
+ [FLY_DEFAULT_HOST_SKU.id]: FLY_DEFAULT_HOST_SKU
34979
+ };
34980
+
34956
34981
  // ../types/src/bridges/agents/types.ts
34957
34982
  var INSTALLABLE_BRIDGE_AGENTS = [
34958
34983
  { value: "claude-code", label: "Anthropic Claude Code", tokenLabel: "Anthropic API key", tokenEnvVar: "ANTHROPIC_API_KEY" },
@@ -35453,11 +35478,11 @@ function createSdkStdioExtNotificationHandler(options) {
35453
35478
 
35454
35479
  // src/agents/acp/clients/sdk/sdk-stdio-permission-request-handshake.ts
35455
35480
  function awaitSdkStdioPermissionRequestHandshake(params) {
35456
- const { requestId, paramsRecord, pending, onRequest } = params;
35481
+ const { requestId, paramsRecord, pending: pending2, onRequest } = params;
35457
35482
  return new Promise((resolve37) => {
35458
- pending.set(requestId, { resolve: resolve37, params: paramsRecord });
35483
+ pending2.set(requestId, { resolve: resolve37, params: paramsRecord });
35459
35484
  if (onRequest == null) {
35460
- pending.delete(requestId);
35485
+ pending2.delete(requestId);
35461
35486
  resolve37({ outcome: { outcome: "denied" } });
35462
35487
  return;
35463
35488
  }
@@ -35473,9 +35498,9 @@ function awaitSdkStdioPermissionRequestHandshake(params) {
35473
35498
  }
35474
35499
 
35475
35500
  // src/agents/acp/clients/sdk/sdk-stdio-permission-pending.ts
35476
- function resolvePendingSdkStdioPermissionCancellations(pending) {
35477
- for (const [id, entry] of [...pending.entries()]) {
35478
- pending.delete(id);
35501
+ function resolvePendingSdkStdioPermissionCancellations(pending2) {
35502
+ for (const [id, entry] of [...pending2.entries()]) {
35503
+ pending2.delete(id);
35479
35504
  entry.resolve({ outcome: { outcome: "cancelled" } });
35480
35505
  }
35481
35506
  }
@@ -36201,8 +36226,8 @@ function createCursorAcpSessionContext(options) {
36201
36226
 
36202
36227
  // src/agents/acp/clients/cursor/cancel-pending-cursor-permission-requests.ts
36203
36228
  function cancelPendingCursorPermissionRequests(pendingRequests2, respond) {
36204
- for (const [reqId, pending] of [...pendingRequests2.entries()]) {
36205
- if (pending.method === "session/request_permission") {
36229
+ for (const [reqId, pending2] of [...pendingRequests2.entries()]) {
36230
+ if (pending2.method === "session/request_permission") {
36206
36231
  respond(reqId, { outcome: { outcome: "cancelled" } });
36207
36232
  pendingRequests2.delete(reqId);
36208
36233
  }
@@ -36394,8 +36419,8 @@ function handleCursorIncomingPermissionRequest(id, method, msg, deps) {
36394
36419
 
36395
36420
  // src/agents/acp/clients/cursor/cursor-incoming-resolve-request.ts
36396
36421
  function resolveCursorIncomingRequest(pendingRequests2, respond, requestId, result) {
36397
- const pending = pendingRequests2.get(requestId);
36398
- const payload = pending?.method === "session/request_permission" ? enrichAcpPermissionRpcResultFromRequestParams(result, pending.params) : result;
36422
+ const pending2 = pendingRequests2.get(requestId);
36423
+ const payload = pending2?.method === "session/request_permission" ? enrichAcpPermissionRpcResultFromRequestParams(result, pending2.params) : result;
36399
36424
  respond(requestId, payload);
36400
36425
  pendingRequests2.delete(requestId);
36401
36426
  }
@@ -36533,25 +36558,25 @@ function createCursorJsonRpcInboundRespond(stdin) {
36533
36558
 
36534
36559
  // src/agents/acp/clients/cursor/cursor-json-rpc-outbound.ts
36535
36560
  function createCursorJsonRpcOutboundPending() {
36536
- const pending = /* @__PURE__ */ new Map();
36561
+ const pending2 = /* @__PURE__ */ new Map();
36537
36562
  let nextId = 1;
36538
36563
  function allocateId() {
36539
36564
  return nextId++;
36540
36565
  }
36541
36566
  function register(id, waiter) {
36542
- pending.set(id, waiter);
36567
+ pending2.set(id, waiter);
36543
36568
  }
36544
36569
  function settleResponse(id, msg) {
36545
- const waiter = pending.get(id);
36570
+ const waiter = pending2.get(id);
36546
36571
  if (!waiter) return false;
36547
- pending.delete(id);
36572
+ pending2.delete(id);
36548
36573
  if (msg.error) waiter.reject(msg.error);
36549
36574
  else waiter.resolve(msg.result);
36550
36575
  return true;
36551
36576
  }
36552
36577
  function rejectOnWriteError(id, err) {
36553
- const waiter = pending.get(id);
36554
- pending.delete(id);
36578
+ const waiter = pending2.get(id);
36579
+ pending2.delete(id);
36555
36580
  waiter?.reject(err);
36556
36581
  }
36557
36582
  return { allocateId, register, settleResponse, rejectOnWriteError };
@@ -41504,11 +41529,11 @@ function tryConsumeBinaryProxyBody(raw, deps) {
41504
41529
  if (!PROXY_ID_RE.test(id)) return false;
41505
41530
  const body = raw.slice(PROXY_ID_BYTES);
41506
41531
  const bodyBytes = body.length > 0 ? new Uint8Array(body) : new Uint8Array(0);
41507
- const pending = deps.pendingProxyBody.get(id);
41508
- if (pending) {
41532
+ const pending2 = deps.pendingProxyBody.get(id);
41533
+ if (pending2) {
41509
41534
  deps.pendingProxyBody.delete(id);
41510
41535
  deps.startStreamingProxy({
41511
- ...pending.pr,
41536
+ ...pending2.pr,
41512
41537
  body: bodyBytes.length > 0 ? bodyBytes : void 0
41513
41538
  });
41514
41539
  return true;
@@ -41901,9 +41926,9 @@ function processHeartbeatAck(params) {
41901
41926
  if (awaitingSeq === null) return { awaitingSeq, missed: 0 };
41902
41927
  if (!Number.isFinite(seq)) return { awaitingSeq, missed: 0 };
41903
41928
  const ack = Math.trunc(seq);
41904
- const pending = awaitingSeq;
41905
- if (ack < pending) return { awaitingSeq, missed: 0 };
41906
- if (ack === pending) {
41929
+ const pending2 = awaitingSeq;
41930
+ if (ack < pending2) return { awaitingSeq, missed: 0 };
41931
+ if (ack === pending2) {
41907
41932
  recordRtt(Date.now() - sentAtMs);
41908
41933
  }
41909
41934
  return { awaitingSeq: null, missed: 0 };
@@ -52272,18 +52297,62 @@ async function applyPromptQueueStateFromServer(msg, deps) {
52272
52297
  }
52273
52298
  }
52274
52299
 
52300
+ // src/agents/acp/from-bridge/pending-prompt-results.ts
52301
+ var pending = [];
52302
+ function enqueuePendingPromptResult(message) {
52303
+ const runId = typeof message.runId === "string" ? message.runId : "";
52304
+ if (runId) {
52305
+ const idx = pending.findIndex((m) => m.runId === runId);
52306
+ if (idx >= 0) pending.splice(idx, 1);
52307
+ }
52308
+ pending.push(message);
52309
+ }
52310
+ function flushPendingPromptResults(getWs, encrypt) {
52311
+ if (pending.length === 0) return;
52312
+ const ws = getWs();
52313
+ if (!ws || ws.readyState !== wrapper_default.OPEN) return;
52314
+ const still = [];
52315
+ for (const message of pending) {
52316
+ const wire = encrypt ? encrypt(message) : message;
52317
+ if (!sendWsMessage(ws, wire)) still.push(message);
52318
+ }
52319
+ pending.length = 0;
52320
+ pending.push(...still);
52321
+ }
52322
+
52323
+ // src/agents/acp/from-bridge/send-session-update-wire.ts
52324
+ function sendSessionUpdateWire(getWs, payload, opts) {
52325
+ const s = getWs();
52326
+ if (!s || s.readyState !== wrapper_default.OPEN) {
52327
+ opts.log("[Bridge service] Session update not sent: not connected to the bridge.");
52328
+ return;
52329
+ }
52330
+ const p = payload;
52331
+ const wire = p.type === "session_update" && opts.e2ee ? opts.e2ee.encryptFields(payload, ["payload"]) : p.type === "session_file_change" && opts.e2ee ? opts.e2ee.encryptFields(payload, [
52332
+ "path",
52333
+ "oldText",
52334
+ "newText",
52335
+ "patchContent",
52336
+ "isDirectory",
52337
+ "directoryRemoved"
52338
+ ]) : payload;
52339
+ sendWsMessage(s, wire);
52340
+ }
52341
+
52275
52342
  // src/agents/acp/from-bridge/bridge-prompt-wiring.ts
52276
52343
  function createBridgePromptSenders(deps, getWs) {
52277
52344
  const sendBridgeMessage = (message, encryptedFields = []) => {
52278
52345
  const s = getWs();
52279
- if (!s) return false;
52346
+ if (!s || s.readyState !== wrapper_default.OPEN) return false;
52280
52347
  const wire = deps.e2ee && encryptedFields.length > 0 ? deps.e2ee.encryptFields(message, encryptedFields) : message;
52281
- sendWsMessage(s, wire);
52282
- return true;
52348
+ return sendWsMessage(s, wire);
52283
52349
  };
52284
52350
  const sendResult = (result) => {
52285
- const encryptedFields = result.type === "prompt_result" ? ["output", "error"] : [];
52286
- sendBridgeMessage(result, encryptedFields);
52351
+ const sent = sendBridgeMessage(result, result.type === "prompt_result" ? ["output", "error"] : []);
52352
+ if (!sent && result.type === "prompt_result") {
52353
+ enqueuePendingPromptResult(result);
52354
+ deps.log("[Bridge service] prompt_result deferred until bridge reconnect.");
52355
+ }
52287
52356
  if (result.type === "prompt_result") {
52288
52357
  const pr = result;
52289
52358
  const cancelled = pr.stopReason === "cancelled";
@@ -52296,24 +52365,11 @@ function createBridgePromptSenders(deps, getWs) {
52296
52365
  });
52297
52366
  }
52298
52367
  };
52299
- const sendSessionUpdate = (payload) => {
52300
- const s = getWs();
52301
- if (!s) {
52302
- deps.log("[Bridge service] Session update not sent: not connected to the bridge.");
52303
- return;
52304
- }
52305
- const p = payload;
52306
- const wire = p.type === "session_update" && deps.e2ee ? deps.e2ee.encryptFields(payload, ["payload"]) : p.type === "session_file_change" && deps.e2ee ? deps.e2ee.encryptFields(payload, [
52307
- "path",
52308
- "oldText",
52309
- "newText",
52310
- "patchContent",
52311
- "isDirectory",
52312
- "directoryRemoved"
52313
- ]) : payload;
52314
- sendWsMessage(s, wire);
52368
+ return {
52369
+ sendBridgeMessage,
52370
+ sendResult,
52371
+ sendSessionUpdate: (payload) => sendSessionUpdateWire(getWs, payload, { e2ee: deps.e2ee, log: deps.log })
52315
52372
  };
52316
- return { sendBridgeMessage, sendResult, sendSessionUpdate };
52317
52373
  }
52318
52374
 
52319
52375
  // src/agents/acp/from-bridge/handle-bridge-prompt/parse-bridge-attachments.ts
@@ -53197,25 +53253,59 @@ var handleInstallSkillsMessage = (msg, deps) => {
53197
53253
  })();
53198
53254
  };
53199
53255
 
53200
- // src/agents/install/commands/run-npm-global-install.ts
53201
- import { execFile as execFile9 } from "node:child_process";
53202
- import { promisify as promisify10 } from "node:util";
53203
-
53204
- // src/agents/install/format-command-output.ts
53205
- function formatCommandOutput(stdout, stderr) {
53206
- const parts = [String(stdout ?? "").trimEnd(), String(stderr ?? "").trimEnd()].filter(Boolean);
53207
- return parts.join("\n");
53256
+ // src/agents/install/run-streaming-command.ts
53257
+ import { spawn as spawn11 } from "node:child_process";
53258
+ import * as readline3 from "node:readline";
53259
+ function runStreamingCommand(command, args, options) {
53260
+ return new Promise((resolve37, reject) => {
53261
+ const child = spawn11(command, args, {
53262
+ env: options.env,
53263
+ stdio: ["ignore", "pipe", "pipe"]
53264
+ });
53265
+ let settled = false;
53266
+ const timer = options.timeoutMs != null ? setTimeout(() => {
53267
+ child.kill("SIGKILL");
53268
+ if (!settled) {
53269
+ settled = true;
53270
+ reject(new Error(`Command timed out after ${options.timeoutMs}ms`));
53271
+ }
53272
+ }, options.timeoutMs) : null;
53273
+ const onLine = (line) => {
53274
+ if (line.length > 0) options.onLine?.(line);
53275
+ };
53276
+ if (child.stdout) {
53277
+ readline3.createInterface({ input: child.stdout, crlfDelay: Infinity }).on("line", onLine);
53278
+ }
53279
+ if (child.stderr) {
53280
+ readline3.createInterface({ input: child.stderr, crlfDelay: Infinity }).on("line", onLine);
53281
+ }
53282
+ child.on("error", (err) => {
53283
+ if (timer) clearTimeout(timer);
53284
+ if (!settled) {
53285
+ settled = true;
53286
+ reject(err);
53287
+ }
53288
+ });
53289
+ child.on("close", (code, signal) => {
53290
+ if (timer) clearTimeout(timer);
53291
+ if (!settled) {
53292
+ settled = true;
53293
+ resolve37({ code, signal });
53294
+ }
53295
+ });
53296
+ });
53208
53297
  }
53209
53298
 
53210
53299
  // src/agents/install/commands/run-npm-global-install.ts
53211
- var execFileAsync8 = promisify10(execFile9);
53212
- async function runNpmGlobalInstall(packageName, env, timeoutMs = 3e5) {
53213
- const { stdout, stderr } = await execFileAsync8("npm", ["install", "-g", packageName], {
53214
- timeout: timeoutMs,
53300
+ async function runNpmGlobalInstall(packageName, env, options) {
53301
+ const result = await runStreamingCommand("npm", ["install", "-g", packageName], {
53215
53302
  env: bridgeAgentPathEnv(env),
53216
- maxBuffer: 10 * 1024 * 1024
53303
+ timeoutMs: options?.timeoutMs ?? 3e5,
53304
+ onLine: options?.onLine
53217
53305
  });
53218
- return formatCommandOutput(stdout, stderr);
53306
+ if (result.code !== 0) {
53307
+ throw new Error(`npm install -g ${packageName} failed (exit ${result.code ?? "signal"})`);
53308
+ }
53219
53309
  }
53220
53310
 
53221
53311
  // src/agents/install/commands/claude-code.ts
@@ -53223,11 +53313,12 @@ var claudeCodeInstallCommand = {
53223
53313
  agentType: "claude-code",
53224
53314
  detectCommand: "claude",
53225
53315
  async install(ctx) {
53226
- const logOutput = await runNpmGlobalInstall("@anthropic-ai/claude-code", {
53227
- ...ctx.env,
53228
- ANTHROPIC_API_KEY: ctx.authToken
53229
- });
53230
- ctx.onProgress?.("Installing Anthropic Claude Code", logOutput || void 0);
53316
+ ctx.onProgress?.("Installing Anthropic Claude Code");
53317
+ await runNpmGlobalInstall(
53318
+ "@anthropic-ai/claude-code",
53319
+ { ...ctx.env, ANTHROPIC_API_KEY: ctx.authToken },
53320
+ { onLine: (line) => ctx.onProgress?.("Installing Anthropic Claude Code", line) }
53321
+ );
53231
53322
  }
53232
53323
  };
53233
53324
 
@@ -53236,34 +53327,34 @@ var codexAcpInstallCommand = {
53236
53327
  agentType: "codex-acp",
53237
53328
  detectCommand: "codex",
53238
53329
  async install(ctx) {
53239
- const logOutput = await runNpmGlobalInstall("@openai/codex", {
53240
- ...ctx.env,
53241
- OPENAI_API_KEY: ctx.authToken
53242
- });
53243
- ctx.onProgress?.("Installing Codex", logOutput || void 0);
53330
+ ctx.onProgress?.("Installing Codex");
53331
+ await runNpmGlobalInstall(
53332
+ "@openai/codex",
53333
+ { ...ctx.env, OPENAI_API_KEY: ctx.authToken },
53334
+ { onLine: (line) => ctx.onProgress?.("Installing Codex", line) }
53335
+ );
53244
53336
  }
53245
53337
  };
53246
53338
 
53247
53339
  // src/agents/install/commands/cursor-cli.ts
53248
- import { execFile as execFile10 } from "node:child_process";
53249
- import { promisify as promisify11 } from "node:util";
53250
- var execFileAsync9 = promisify11(execFile10);
53251
53340
  var cursorCliInstallCommand = {
53252
53341
  agentType: "cursor-cli",
53253
53342
  detectCommand: "agent",
53254
53343
  alternateDetectCommands: ["cursor-agent"],
53255
53344
  async install(ctx) {
53256
- const { stdout, stderr } = await execFileAsync9(
53345
+ ctx.onProgress?.("Installing Cursor CLI");
53346
+ const result = await runStreamingCommand(
53257
53347
  "bash",
53258
53348
  ["-lc", "curl -fsSL https://cursor.com/install | bash"],
53259
53349
  {
53260
- timeout: 3e5,
53350
+ timeoutMs: 3e5,
53261
53351
  env: { ...bridgeAgentPathEnv(ctx.env), CURSOR_API_KEY: ctx.authToken },
53262
- maxBuffer: 10 * 1024 * 1024
53352
+ onLine: (line) => ctx.onProgress?.("Installing Cursor CLI", line)
53263
53353
  }
53264
53354
  );
53265
- const logOutput = formatCommandOutput(stdout, stderr);
53266
- ctx.onProgress?.("Installing Cursor CLI", logOutput || void 0);
53355
+ if (result.code !== 0) {
53356
+ throw new Error(`Cursor CLI install failed (exit ${result.code ?? "signal"})`);
53357
+ }
53267
53358
  }
53268
53359
  };
53269
53360
 
@@ -53272,11 +53363,12 @@ var opencodeInstallCommand = {
53272
53363
  agentType: "opencode",
53273
53364
  detectCommand: "opencode",
53274
53365
  async install(ctx) {
53275
- const logOutput = await runNpmGlobalInstall("opencode-ai", {
53276
- ...ctx.env,
53277
- OPENCODE_API_KEY: ctx.authToken
53278
- });
53279
- ctx.onProgress?.("Installing OpenCode", logOutput || void 0);
53366
+ ctx.onProgress?.("Installing OpenCode");
53367
+ await runNpmGlobalInstall(
53368
+ "opencode-ai",
53369
+ { ...ctx.env, OPENCODE_API_KEY: ctx.authToken },
53370
+ { onLine: (line) => ctx.onProgress?.("Installing OpenCode", line) }
53371
+ );
53280
53372
  }
53281
53373
  };
53282
53374
 
@@ -53337,25 +53429,47 @@ var handleInstallAgentMessage = (msg, deps) => {
53337
53429
  if (!processId || !agentId || !tokenId || !agentType || !authToken) return;
53338
53430
  void (async () => {
53339
53431
  const socket = deps.getWs();
53340
- const report = (step, message, logOutput) => {
53341
- if (socket) {
53342
- sendWsMessage(socket, {
53343
- type: "install_agent_progress",
53344
- processId,
53345
- agentId,
53346
- tokenId,
53347
- agentType,
53348
- step,
53349
- message,
53350
- ...logOutput ? { logOutput } : {}
53351
- });
53432
+ let pendingLines = [];
53433
+ let flushTimer = null;
53434
+ const sendProgress = (message, logOutput) => {
53435
+ if (!socket) return;
53436
+ sendWsMessage(socket, {
53437
+ type: "install_agent_progress",
53438
+ processId,
53439
+ agentId,
53440
+ tokenId,
53441
+ agentType,
53442
+ step: "agent_install_package",
53443
+ message,
53444
+ ...logOutput ? { logOutput } : {}
53445
+ });
53446
+ };
53447
+ const flushLines = (message) => {
53448
+ if (flushTimer) {
53449
+ clearTimeout(flushTimer);
53450
+ flushTimer = null;
53352
53451
  }
53452
+ if (pendingLines.length === 0) return;
53453
+ const logOutput = pendingLines.join("\n");
53454
+ pendingLines = [];
53455
+ sendProgress(message, logOutput);
53353
53456
  };
53354
53457
  const result = await installLocalAgentOnBridge({
53355
53458
  agentType,
53356
53459
  authToken,
53357
- onProgress: (message, logOutput) => report("agent_install_package", message, logOutput)
53460
+ onProgress: (message, logOutput) => {
53461
+ if (logOutput == null) {
53462
+ flushLines(message);
53463
+ sendProgress(message);
53464
+ return;
53465
+ }
53466
+ pendingLines.push(logOutput);
53467
+ if (!flushTimer) {
53468
+ flushTimer = setTimeout(() => flushLines(message), 100);
53469
+ }
53470
+ }
53358
53471
  });
53472
+ flushLines("Installing agent packages on the bridge machine.");
53359
53473
  if (socket) {
53360
53474
  sendWsMessage(socket, {
53361
53475
  type: "install_agent_result",
@@ -53367,9 +53481,7 @@ var handleInstallAgentMessage = (msg, deps) => {
53367
53481
  error: result.error
53368
53482
  });
53369
53483
  }
53370
- if (result.success) {
53371
- await deps.reportAutoDetectedAgents?.();
53372
- }
53484
+ if (result.success) await deps.reportAutoDetectedAgents?.();
53373
53485
  if (!result.success) {
53374
53486
  deps.log(`[Bridge service] Install agent failed: ${result.error ?? "unknown"}`);
53375
53487
  }
@@ -53954,6 +54066,10 @@ function createMainBridgeOpenHandler(params) {
53954
54066
  if (socket) {
53955
54067
  sendBridgeIdentify(socket, { identifyReportedPaths, e2ee });
53956
54068
  reportGitRepos(getWs, logFn);
54069
+ flushPendingPromptResults(
54070
+ getWs,
54071
+ (message) => e2ee ? e2ee.encryptFields(message, ["output", "error"]) : message
54072
+ );
53957
54073
  try {
53958
54074
  onBridgeSocketOpen?.();
53959
54075
  } catch {
@@ -54098,7 +54214,7 @@ async function createBridgeConnection(options) {
54098
54214
  }
54099
54215
 
54100
54216
  // src/e2e-certificates/key-command.ts
54101
- import * as readline3 from "node:readline";
54217
+ import * as readline4 from "node:readline";
54102
54218
  function installE2eCertificateKeyCommand({
54103
54219
  log: log2,
54104
54220
  onOpenCertificate,
@@ -54109,7 +54225,7 @@ function installE2eCertificateKeyCommand({
54109
54225
  return () => {
54110
54226
  };
54111
54227
  }
54112
- readline3.emitKeypressEvents(process.stdin);
54228
+ readline4.emitKeypressEvents(process.stdin);
54113
54229
  process.stdin.setRawMode(true);
54114
54230
  process.stdin.resume();
54115
54231
  const onKeypress = (str, key) => {