@buildautomaton/cli 0.1.9 → 0.1.11

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
@@ -5232,7 +5232,7 @@ var require_websocket = __commonJS({
5232
5232
  "../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket.js"(exports, module) {
5233
5233
  "use strict";
5234
5234
  var EventEmitter2 = __require("events");
5235
- var https3 = __require("https");
5235
+ var https2 = __require("https");
5236
5236
  var http = __require("http");
5237
5237
  var net = __require("net");
5238
5238
  var tls = __require("tls");
@@ -5767,7 +5767,7 @@ var require_websocket = __commonJS({
5767
5767
  }
5768
5768
  const defaultPort = isSecure ? 443 : 80;
5769
5769
  const key = randomBytes(16).toString("base64");
5770
- const request = isSecure ? https3.request : http.request;
5770
+ const request = isSecure ? https2.request : http.request;
5771
5771
  const protocolSet = /* @__PURE__ */ new Set();
5772
5772
  let perMessageDeflate;
5773
5773
  opts.createConnection = opts.createConnection || (isSecure ? tlsConnect : netConnect);
@@ -25177,9 +25177,6 @@ var import_websocket = __toESM(require_websocket(), 1);
25177
25177
  var import_websocket_server = __toESM(require_websocket_server(), 1);
25178
25178
  var wrapper_default = import_websocket.default;
25179
25179
 
25180
- // src/bridge/connection/create-ws-bridge.ts
25181
- import https from "node:https";
25182
-
25183
25180
  // src/net/apply-cli-outbound-network-prefs.ts
25184
25181
  import dns from "node:dns";
25185
25182
  var applied = false;
@@ -25192,26 +25189,77 @@ function applyCliOutboundNetworkPreferences() {
25192
25189
  }
25193
25190
  }
25194
25191
 
25192
+ // src/bridge/connection/cli-ws-client.ts
25193
+ import https from "node:https";
25194
+ var CLI_WEBSOCKET_CLIENT_PING_MS = 25e3;
25195
+ function attachWebSocketClientPing(ws, intervalMs) {
25196
+ let timer = null;
25197
+ function clear() {
25198
+ if (timer != null) {
25199
+ clearInterval(timer);
25200
+ timer = null;
25201
+ }
25202
+ }
25203
+ clear();
25204
+ timer = setInterval(() => {
25205
+ if (ws.readyState === wrapper_default.OPEN) {
25206
+ try {
25207
+ ws.ping();
25208
+ } catch {
25209
+ }
25210
+ }
25211
+ }, intervalMs);
25212
+ return clear;
25213
+ }
25214
+ function buildCliWebSocketClientOptions(wsUrl) {
25215
+ const wsOptions = { perMessageDeflate: false, family: 4 };
25216
+ if (wsUrl.startsWith("wss://")) {
25217
+ wsOptions.agent = new https.Agent({ rejectUnauthorized: false, family: 4 });
25218
+ }
25219
+ return wsOptions;
25220
+ }
25221
+ function logCliWebSocketError(log2, serviceLabel, err, detail) {
25222
+ const mid = detail ? ` ${detail}` : "";
25223
+ log2(`${serviceLabel} WebSocket error${mid}: ${err.message}`);
25224
+ }
25225
+ function safeCloseWebSocket(ws) {
25226
+ try {
25227
+ if (ws.readyState === wrapper_default.CLOSED) {
25228
+ ws.removeAllListeners();
25229
+ return;
25230
+ }
25231
+ ws.once("close", () => {
25232
+ ws.removeAllListeners();
25233
+ });
25234
+ ws.close();
25235
+ } catch {
25236
+ try {
25237
+ ws.removeAllListeners();
25238
+ } catch {
25239
+ }
25240
+ }
25241
+ }
25242
+ function safeSendWebSocketBinary(ws, data) {
25243
+ if (ws.readyState !== wrapper_default.OPEN) return false;
25244
+ try {
25245
+ ws.send(data, { binary: true });
25246
+ return true;
25247
+ } catch {
25248
+ return false;
25249
+ }
25250
+ }
25251
+
25195
25252
  // src/bridge/connection/create-ws-bridge.ts
25196
25253
  var BRIDGE_AUTH_ERROR_HEADER = "x-bridge-auth-error";
25197
25254
  var BRIDGE_AUTH_ERROR_TOKEN_INVALID = "token_invalid";
25198
25255
  function createWsBridge(options) {
25199
25256
  const { url: url2, onMessage, onOpen, onClose, onError: onError2, onAuthInvalid, clientPingIntervalMs } = options;
25200
25257
  applyCliOutboundNetworkPreferences();
25201
- const wsOptions = {
25202
- perMessageDeflate: false,
25203
- family: 4
25204
- };
25205
- if (url2.startsWith("wss://")) {
25206
- wsOptions.agent = new https.Agent({ rejectUnauthorized: false, family: 4 });
25207
- }
25208
- const ws = new wrapper_default(url2, wsOptions);
25209
- let clientPingTimer = null;
25210
- function clearClientPing() {
25211
- if (clientPingTimer != null) {
25212
- clearInterval(clientPingTimer);
25213
- clientPingTimer = null;
25214
- }
25258
+ const ws = new wrapper_default(url2, buildCliWebSocketClientOptions(url2));
25259
+ let clearClientPing = null;
25260
+ function disposeClientPing() {
25261
+ clearClientPing?.();
25262
+ clearClientPing = null;
25215
25263
  }
25216
25264
  ws.on("unexpected-response", (request, response) => {
25217
25265
  const status = response?.statusCode ?? 0;
@@ -25222,16 +25270,9 @@ function createWsBridge(options) {
25222
25270
  }
25223
25271
  });
25224
25272
  ws.on("open", () => {
25225
- clearClientPing();
25273
+ disposeClientPing();
25226
25274
  if (clientPingIntervalMs != null && clientPingIntervalMs > 0) {
25227
- clientPingTimer = setInterval(() => {
25228
- if (ws.readyState === wrapper_default.OPEN) {
25229
- try {
25230
- ws.ping();
25231
- } catch {
25232
- }
25233
- }
25234
- }, clientPingIntervalMs);
25275
+ clearClientPing = attachWebSocketClientPing(ws, clientPingIntervalMs);
25235
25276
  }
25236
25277
  onOpen?.();
25237
25278
  });
@@ -25252,11 +25293,11 @@ function createWsBridge(options) {
25252
25293
  }
25253
25294
  });
25254
25295
  ws.on("close", (code, reason) => {
25255
- clearClientPing();
25296
+ disposeClientPing();
25256
25297
  onClose?.(code, reason.toString());
25257
25298
  });
25258
25299
  ws.on("error", (err) => {
25259
- clearClientPing();
25300
+ disposeClientPing();
25260
25301
  onError2?.(err);
25261
25302
  });
25262
25303
  return ws;
@@ -25528,9 +25569,9 @@ function runPendingAuth(options) {
25528
25569
  keepaliveInterval = null;
25529
25570
  }
25530
25571
  if (ws) {
25531
- ws.removeAllListeners();
25532
- ws.close();
25572
+ const w = ws;
25533
25573
  ws = null;
25574
+ safeCloseWebSocket(w);
25534
25575
  }
25535
25576
  }
25536
25577
  function connect() {
@@ -25573,7 +25614,7 @@ function runPendingAuth(options) {
25573
25614
  connect();
25574
25615
  }, delay2);
25575
25616
  },
25576
- onError: (err) => logFn(`[Bridge service] WebSocket error while waiting for sign-in: ${err.message}`),
25617
+ onError: (err) => logCliWebSocketError(logFn, "[Bridge service]", err, "while waiting for sign-in"),
25577
25618
  onMessage: (data) => {
25578
25619
  const msg = data;
25579
25620
  if (msg.type === "auth_token" && typeof msg.token === "string") {
@@ -32793,14 +32834,50 @@ async function removeSessionWorktrees(paths, log2) {
32793
32834
  }
32794
32835
 
32795
32836
  // src/git/working-tree-status.ts
32796
- async function commitsAheadOfUpstream(repoDir) {
32797
- const g = simpleGit(repoDir);
32837
+ async function tryConfigGet(g, key) {
32838
+ try {
32839
+ const out = await g.raw(["config", "--get", key]);
32840
+ const v = String(out).trim();
32841
+ return v || null;
32842
+ } catch {
32843
+ return null;
32844
+ }
32845
+ }
32846
+ async function resolveRemoteTrackingRefForAhead(g) {
32798
32847
  try {
32799
32848
  await g.raw(["rev-parse", "--verify", "@{u}"]);
32849
+ return "@{u}";
32850
+ } catch {
32851
+ }
32852
+ const branch = (await g.raw(["rev-parse", "--abbrev-ref", "HEAD"])).trim();
32853
+ if (!branch || branch === "HEAD") return null;
32854
+ const remote = await tryConfigGet(g, `branch.${branch}.remote`) ?? "origin";
32855
+ const merge2 = await tryConfigGet(g, `branch.${branch}.merge`);
32856
+ if (merge2) {
32857
+ const upstreamBranch = merge2.replace(/^refs\/heads\//, "");
32858
+ const ref = `refs/remotes/${remote}/${upstreamBranch}`;
32859
+ try {
32860
+ await g.raw(["rev-parse", "--verify", ref]);
32861
+ return ref;
32862
+ } catch {
32863
+ }
32864
+ }
32865
+ const fallbackRef = `refs/remotes/${remote}/${branch}`;
32866
+ try {
32867
+ await g.raw(["rev-parse", "--verify", fallbackRef]);
32868
+ return fallbackRef;
32800
32869
  } catch {
32801
- return 0;
32870
+ return null;
32802
32871
  }
32803
- const out = await g.raw(["rev-list", "--count", "@{u}..HEAD"]);
32872
+ }
32873
+ async function commitsAheadOfRemoteTracking(repoDir) {
32874
+ const g = simpleGit(repoDir);
32875
+ const trackingRef = await resolveRemoteTrackingRefForAhead(g);
32876
+ if (!trackingRef) return 0;
32877
+ const localSha = (await g.raw(["rev-parse", "HEAD"])).trim();
32878
+ const remoteSha = (await g.raw(["rev-parse", trackingRef])).trim();
32879
+ if (localSha === remoteSha) return 0;
32880
+ const out = await g.raw(["rev-list", "--count", `${trackingRef}..HEAD`]);
32804
32881
  const n = parseInt(String(out).trim(), 10);
32805
32882
  return Number.isNaN(n) ? 0 : n;
32806
32883
  }
@@ -32808,7 +32885,7 @@ async function getRepoWorkingTreeStatus(repoDir) {
32808
32885
  const g = simpleGit(repoDir);
32809
32886
  const st = await g.status();
32810
32887
  const hasUncommittedChanges = (st.files?.length ?? 0) > 0;
32811
- const ahead = await commitsAheadOfUpstream(repoDir);
32888
+ const ahead = await commitsAheadOfRemoteTracking(repoDir);
32812
32889
  return { hasUncommittedChanges, hasUnpushedCommits: ahead > 0 };
32813
32890
  }
32814
32891
  async function aggregateSessionPathsWorkingTreeStatus(paths) {
@@ -32824,7 +32901,7 @@ async function aggregateSessionPathsWorkingTreeStatus(paths) {
32824
32901
  async function pushAheadOfUpstreamForPaths(paths) {
32825
32902
  for (const p of paths) {
32826
32903
  const g = simpleGit(p);
32827
- const ahead = await commitsAheadOfUpstream(p);
32904
+ const ahead = await commitsAheadOfRemoteTracking(p);
32828
32905
  if (ahead <= 0) continue;
32829
32906
  await g.push();
32830
32907
  }
@@ -34099,8 +34176,53 @@ var DevServerManager = class {
34099
34176
  }
34100
34177
  };
34101
34178
 
34102
- // src/firehose/connect-firehose.ts
34103
- import https2 from "node:https";
34179
+ // src/net/transient-local-fetch-retry.ts
34180
+ var LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS = [30, 100, 200, 400];
34181
+ function sleepMs(ms) {
34182
+ return new Promise((r) => setTimeout(r, ms));
34183
+ }
34184
+ function collectErrorText(err) {
34185
+ const parts = [];
34186
+ let e = err;
34187
+ for (let depth = 0; depth < 6 && e != null; depth += 1) {
34188
+ if (e instanceof Error) {
34189
+ parts.push(e.message);
34190
+ e = e.cause;
34191
+ } else {
34192
+ parts.push(String(e));
34193
+ break;
34194
+ }
34195
+ }
34196
+ return parts.join(" ").toLowerCase();
34197
+ }
34198
+ function isTransientLocalServiceError(err) {
34199
+ const text = collectErrorText(err);
34200
+ if (!text) return false;
34201
+ return text.includes("fetch failed") || text.includes("econnrefused") || text.includes("econnreset") || text.includes("epipe") || text.includes("etimedout") || text.includes("socket hang up") || text.includes("network connection lost") || text.includes("ecanceled") || text.includes("aborted") || text.includes("und_err_socket") || text.includes("other side closed") || text.includes("eai_again");
34202
+ }
34203
+ function isIdempotentHttpMethod(method) {
34204
+ const m = method.toUpperCase();
34205
+ return m === "GET" || m === "HEAD" || m === "OPTIONS";
34206
+ }
34207
+ async function fetchWithLocalTransientRetries(url2, init, options) {
34208
+ const method = (init?.method ?? "GET").toUpperCase();
34209
+ const allowRetry = isIdempotentHttpMethod(method);
34210
+ const delays = options?.delaysMs ?? LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS;
34211
+ const maxAttempts = options?.maxAttempts ?? (allowRetry ? Math.max(1, delays.length + 1) : 1);
34212
+ let lastErr;
34213
+ for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
34214
+ try {
34215
+ return await fetch(url2, init);
34216
+ } catch (e) {
34217
+ lastErr = e;
34218
+ const canRetry = allowRetry && attempt < maxAttempts - 1 && isTransientLocalServiceError(e);
34219
+ if (!canRetry) throw e;
34220
+ const waitMs = delays[Math.min(attempt, delays.length - 1)] ?? 100;
34221
+ await sleepMs(waitMs);
34222
+ }
34223
+ }
34224
+ throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
34225
+ }
34104
34226
 
34105
34227
  // src/firehose/proxy/local-proxy.ts
34106
34228
  var ALLOWED_HOSTS = ["localhost", "127.0.0.1", "::1"];
@@ -34108,6 +34230,10 @@ function isAllowedHost(host) {
34108
34230
  const h = host.replace(/^\[|\]$/g, "");
34109
34231
  return ALLOWED_HOSTS.includes(host) || ALLOWED_HOSTS.includes(h);
34110
34232
  }
34233
+ function isIdempotentProxyMethod(method) {
34234
+ const m = method.toUpperCase();
34235
+ return m === "GET" || m === "HEAD" || m === "OPTIONS";
34236
+ }
34111
34237
  function checkUrlAndHost(request) {
34112
34238
  let url2;
34113
34239
  try {
@@ -34135,38 +34261,47 @@ async function proxyToLocal(request) {
34135
34261
  path: url2.pathname + url2.search,
34136
34262
  headers: request.headers
34137
34263
  };
34138
- return new Promise((resolve15) => {
34139
- const req = mod.request(opts, (res) => {
34140
- const chunks = [];
34141
- res.on("data", (c) => chunks.push(c));
34142
- res.on("end", () => {
34143
- const body = Buffer.concat(chunks).toString("utf8");
34144
- const headers = {};
34145
- for (const [k, v] of Object.entries(res.headers)) {
34146
- if (typeof v === "string") headers[k] = v;
34147
- else if (Array.isArray(v) && v[0]) headers[k] = v[0];
34148
- }
34264
+ const maxAttempts = isIdempotentProxyMethod(request.method) ? LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS.length + 1 : 1;
34265
+ for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
34266
+ const once = await new Promise((resolve15) => {
34267
+ const req = mod.request(opts, (res) => {
34268
+ const chunks = [];
34269
+ res.on("data", (c) => chunks.push(c));
34270
+ res.on("end", () => {
34271
+ const body = Buffer.concat(chunks).toString("utf8");
34272
+ const headers = {};
34273
+ for (const [k, v] of Object.entries(res.headers)) {
34274
+ if (typeof v === "string") headers[k] = v;
34275
+ else if (Array.isArray(v) && v[0]) headers[k] = v[0];
34276
+ }
34277
+ resolve15({
34278
+ id: request.id,
34279
+ statusCode: res.statusCode ?? 0,
34280
+ headers,
34281
+ body
34282
+ });
34283
+ });
34284
+ });
34285
+ req.on("error", (err) => {
34149
34286
  resolve15({
34150
34287
  id: request.id,
34151
- statusCode: res.statusCode ?? 0,
34152
- headers,
34153
- body
34288
+ statusCode: 0,
34289
+ headers: {},
34290
+ body: "",
34291
+ error: err.message
34154
34292
  });
34155
34293
  });
34294
+ const method = request.method.toUpperCase();
34295
+ if (request.body && method !== "GET" && method !== "HEAD") req.write(request.body);
34296
+ req.end();
34156
34297
  });
34157
- req.on("error", (err) => {
34158
- resolve15({
34159
- id: request.id,
34160
- statusCode: 0,
34161
- headers: {},
34162
- body: "",
34163
- error: err.message
34164
- });
34165
- });
34166
- const method = request.method.toUpperCase();
34167
- if (request.body && method !== "GET" && method !== "HEAD") req.write(request.body);
34168
- req.end();
34169
- });
34298
+ const errMsg = once.error ?? "";
34299
+ const canRetry = attempt < maxAttempts - 1 && errMsg !== "" && isTransientLocalServiceError(new Error(errMsg));
34300
+ if (!canRetry) return once;
34301
+ const waitMs = LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS[Math.min(attempt, LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS.length - 1)] ?? 100;
34302
+ await sleepMs(waitMs);
34303
+ }
34304
+ throw new Error("Local proxy retry loop exited unexpectedly");
34170
34305
  }
34171
34306
  async function proxyToLocalStreaming(request, callbacks) {
34172
34307
  const checked = checkUrlAndHost(request);
@@ -34183,7 +34318,7 @@ async function proxyToLocalStreaming(request, callbacks) {
34183
34318
  if (request.body !== void 0 && request.body !== null && method !== "GET" && method !== "HEAD") {
34184
34319
  init.body = request.body;
34185
34320
  }
34186
- const res = await fetch(request.url, init);
34321
+ const res = await fetchWithLocalTransientRetries(request.url, init);
34187
34322
  const headers = {};
34188
34323
  res.headers.forEach((value, key) => {
34189
34324
  headers[key] = value;
@@ -34213,6 +34348,9 @@ async function proxyToLocalStreaming(request, callbacks) {
34213
34348
  function startStreamingProxy(ws, log2, pr) {
34214
34349
  proxyToLocalStreaming(pr, {
34215
34350
  onStart: (statusCode, headers) => {
34351
+ if (ws.readyState !== wrapper_default.OPEN) {
34352
+ throw new Error("Preview stream interrupted (firehose connection closed)");
34353
+ }
34216
34354
  const forwardedHeaders = { ...headers };
34217
34355
  const ce = "content-encoding";
34218
34356
  const cl = "content-length";
@@ -34225,7 +34363,10 @@ function startStreamingProxy(ws, log2, pr) {
34225
34363
  },
34226
34364
  onChunk: (chunk) => {
34227
34365
  const idBuf = Buffer.from(pr.id, "utf8");
34228
- ws.send(Buffer.concat([idBuf, Buffer.from(chunk)]), { binary: true });
34366
+ const buf = Buffer.concat([idBuf, Buffer.from(chunk)]);
34367
+ if (!safeSendWebSocketBinary(ws, buf)) {
34368
+ throw new Error("Preview stream interrupted (firehose connection closed)");
34369
+ }
34229
34370
  },
34230
34371
  onEnd: () => sendWsMessage(ws, { type: "proxy_result_end", id: pr.id }),
34231
34372
  onError: (error40) => {
@@ -34343,22 +34484,15 @@ function tryConsumeBinaryProxyBody(raw, deps) {
34343
34484
  }
34344
34485
 
34345
34486
  // src/firehose/connect-firehose.ts
34346
- var FIREHOSE_CLIENT_PING_MS = 25e3;
34347
34487
  function connectFirehose(options) {
34348
34488
  const { firehoseServerUrl, workspaceId, bridgeName, proxyPorts, log: log2, devServerManager, onOpen, onClose } = options;
34349
34489
  const wsUrl = buildFirehoseCliWsUrl(firehoseServerUrl);
34350
34490
  applyCliOutboundNetworkPreferences();
34351
- const wsOptions = { perMessageDeflate: false, family: 4 };
34352
- if (wsUrl.startsWith("wss://")) {
34353
- wsOptions.agent = new https2.Agent({ rejectUnauthorized: false, family: 4 });
34354
- }
34355
- const ws = new wrapper_default(wsUrl, wsOptions);
34356
- let clientPingTimer = null;
34357
- function clearClientPing() {
34358
- if (clientPingTimer != null) {
34359
- clearInterval(clientPingTimer);
34360
- clientPingTimer = null;
34361
- }
34491
+ const ws = new wrapper_default(wsUrl, buildCliWebSocketClientOptions(wsUrl));
34492
+ let clearClientPing = null;
34493
+ function disposeClientPing() {
34494
+ clearClientPing?.();
34495
+ clearClientPing = null;
34362
34496
  }
34363
34497
  const firehoseSend = (payload) => {
34364
34498
  sendWsMessage(ws, payload);
@@ -34372,15 +34506,8 @@ function connectFirehose(options) {
34372
34506
  startStreamingProxy: (pr) => startStreamingProxy(ws, log2, pr)
34373
34507
  };
34374
34508
  ws.on("open", () => {
34375
- clearClientPing();
34376
- clientPingTimer = setInterval(() => {
34377
- if (ws.readyState === wrapper_default.OPEN) {
34378
- try {
34379
- ws.ping();
34380
- } catch {
34381
- }
34382
- }
34383
- }, FIREHOSE_CLIENT_PING_MS);
34509
+ disposeClientPing();
34510
+ clearClientPing = attachWebSocketClientPing(ws, CLI_WEBSOCKET_CLIENT_PING_MS);
34384
34511
  onOpen?.();
34385
34512
  devServerManager.attachFirehose(firehoseSend);
34386
34513
  sendWsMessage(ws, { type: "identify", workspaceId, bridgeName, proxyPorts });
@@ -34396,24 +34523,23 @@ function connectFirehose(options) {
34396
34523
  }
34397
34524
  });
34398
34525
  ws.on("close", (code, reason) => {
34399
- clearClientPing();
34526
+ disposeClientPing();
34400
34527
  devServerManager.detachFirehose();
34401
34528
  const reasonStr = typeof reason === "string" ? reason : reason.toString();
34402
34529
  onClose?.(code, reasonStr);
34403
34530
  });
34404
34531
  ws.on("error", (err) => {
34405
- clearClientPing();
34406
- log2(`[Proxy and log service] WebSocket error: ${err.message}`);
34532
+ disposeClientPing();
34533
+ logCliWebSocketError(log2, "[Proxy and log service]", err);
34534
+ if (ws.readyState === wrapper_default.CONNECTING || ws.readyState === wrapper_default.OPEN) {
34535
+ safeCloseWebSocket(ws);
34536
+ }
34407
34537
  });
34408
34538
  return {
34409
34539
  close() {
34410
- clearClientPing();
34540
+ disposeClientPing();
34411
34541
  devServerManager.detachFirehose();
34412
- try {
34413
- ws.removeAllListeners();
34414
- ws.close();
34415
- } catch {
34416
- }
34542
+ safeCloseWebSocket(ws);
34417
34543
  },
34418
34544
  isConnected: () => ws.readyState === wrapper_default.OPEN
34419
34545
  };
@@ -35766,7 +35892,6 @@ async function refreshBridgeTokens(params) {
35766
35892
  }
35767
35893
 
35768
35894
  // src/bridge/connection/main-bridge-ws-lifecycle.ts
35769
- var BRIDGE_CLIENT_PING_MS = 25e3;
35770
35895
  function createMainBridgeWebSocketLifecycle(params) {
35771
35896
  const {
35772
35897
  state,
@@ -35824,6 +35949,11 @@ function createMainBridgeWebSocketLifecycle(params) {
35824
35949
  const prev = state.currentWs;
35825
35950
  if (prev) {
35826
35951
  prev.removeAllListeners();
35952
+ prev.once("error", () => {
35953
+ });
35954
+ prev.once("close", () => {
35955
+ prev.removeAllListeners();
35956
+ });
35827
35957
  try {
35828
35958
  prev.close();
35829
35959
  } catch {
@@ -35833,7 +35963,7 @@ function createMainBridgeWebSocketLifecycle(params) {
35833
35963
  const url2 = buildBridgeUrl(apiUrl, workspaceId, tokens.accessToken);
35834
35964
  state.currentWs = createWsBridge({
35835
35965
  url: url2,
35836
- clientPingIntervalMs: BRIDGE_CLIENT_PING_MS,
35966
+ clientPingIntervalMs: CLI_WEBSOCKET_CLIENT_PING_MS,
35837
35967
  onAuthInvalid: () => {
35838
35968
  if (authRefreshInFlight) return;
35839
35969
  void (async () => {
@@ -35869,7 +35999,7 @@ function createMainBridgeWebSocketLifecycle(params) {
35869
35999
  },
35870
36000
  onOpen: handleOpen,
35871
36001
  onClose: handleClose,
35872
- onError: (err) => logFn(`[Bridge service] WebSocket error: ${err.message}`),
36002
+ onError: (err) => logCliWebSocketError(logFn, "[Bridge service]", err),
35873
36003
  onMessage: (data) => handleBridgeMessage(data, messageDeps)
35874
36004
  });
35875
36005
  }