@buildautomaton/cli 0.1.23 → 0.1.24
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 +558 -186
- package/dist/cli.js.map +4 -4
- package/dist/index.js +2604 -2226
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -25064,7 +25064,7 @@ var {
|
|
|
25064
25064
|
} = import_index.default;
|
|
25065
25065
|
|
|
25066
25066
|
// src/cli-version.ts
|
|
25067
|
-
var CLI_VERSION = "0.1.
|
|
25067
|
+
var CLI_VERSION = "0.1.24".length > 0 ? "0.1.24" : "0.0.0-dev";
|
|
25068
25068
|
|
|
25069
25069
|
// src/cli/defaults.ts
|
|
25070
25070
|
var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
|
|
@@ -25074,6 +25074,18 @@ var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
|
|
|
25074
25074
|
import * as fs34 from "node:fs";
|
|
25075
25075
|
import * as path35 from "node:path";
|
|
25076
25076
|
|
|
25077
|
+
// src/cli-log-level.ts
|
|
25078
|
+
var verbosity = "info";
|
|
25079
|
+
function setCliLogVerbosity(level) {
|
|
25080
|
+
verbosity = level;
|
|
25081
|
+
}
|
|
25082
|
+
function getCliLogVerbosity() {
|
|
25083
|
+
return verbosity;
|
|
25084
|
+
}
|
|
25085
|
+
function isCliTrace() {
|
|
25086
|
+
return verbosity === "trace";
|
|
25087
|
+
}
|
|
25088
|
+
|
|
25077
25089
|
// src/config.ts
|
|
25078
25090
|
import fs from "node:fs";
|
|
25079
25091
|
import path from "node:path";
|
|
@@ -25442,15 +25454,21 @@ function getBridgeRoot() {
|
|
|
25442
25454
|
}
|
|
25443
25455
|
|
|
25444
25456
|
// src/log.ts
|
|
25445
|
-
function
|
|
25457
|
+
function timestampPrefix() {
|
|
25446
25458
|
const time3 = (/* @__PURE__ */ new Date()).toISOString().slice(11, 19);
|
|
25447
|
-
|
|
25459
|
+
return `[${time3}]`;
|
|
25460
|
+
}
|
|
25461
|
+
function log(line) {
|
|
25462
|
+
console.log(`${timestampPrefix()} ${line}`);
|
|
25448
25463
|
}
|
|
25449
25464
|
function logImmediate(line) {
|
|
25450
|
-
|
|
25451
|
-
process.stdout.write(`[${time3}] ${line}
|
|
25465
|
+
process.stdout.write(`${timestampPrefix()} ${line}
|
|
25452
25466
|
`);
|
|
25453
25467
|
}
|
|
25468
|
+
function logTrace(line) {
|
|
25469
|
+
if (getCliLogVerbosity() !== "trace") return;
|
|
25470
|
+
console.log(`${timestampPrefix()} [trace] ${line}`);
|
|
25471
|
+
}
|
|
25454
25472
|
|
|
25455
25473
|
// src/process-bridge-resilience.ts
|
|
25456
25474
|
var installed = false;
|
|
@@ -25485,7 +25503,7 @@ function applyCliOutboundNetworkPreferences() {
|
|
|
25485
25503
|
}
|
|
25486
25504
|
}
|
|
25487
25505
|
|
|
25488
|
-
// src/
|
|
25506
|
+
// src/connection/cli-ws-client.ts
|
|
25489
25507
|
import https from "node:https";
|
|
25490
25508
|
var CLI_WEBSOCKET_CLIENT_PING_MS = 25e3;
|
|
25491
25509
|
function attachWebSocketClientPing(ws, intervalMs) {
|
|
@@ -25545,7 +25563,7 @@ function safeSendWebSocketBinary(ws, data) {
|
|
|
25545
25563
|
}
|
|
25546
25564
|
}
|
|
25547
25565
|
|
|
25548
|
-
// src/
|
|
25566
|
+
// src/connection/create-ws-bridge.ts
|
|
25549
25567
|
var BRIDGE_AUTH_ERROR_HEADER = "x-bridge-auth-error";
|
|
25550
25568
|
var BRIDGE_AUTH_ERROR_TOKEN_INVALID = "token_invalid";
|
|
25551
25569
|
function createWsBridge(options) {
|
|
@@ -26156,29 +26174,22 @@ async function openBrowser(connectionId, initialWorkspaceId, preferredBridgeName
|
|
|
26156
26174
|
}
|
|
26157
26175
|
}
|
|
26158
26176
|
|
|
26159
|
-
// src/
|
|
26160
|
-
var RECONNECT_FIRST_MS = 100;
|
|
26161
|
-
var RECONNECT_MAX_MS = 3e4;
|
|
26177
|
+
// src/connection/reconnect/constants.ts
|
|
26162
26178
|
var RECONNECT_QUIET_MS = 2e3;
|
|
26163
|
-
|
|
26164
|
-
|
|
26179
|
+
var PENDING_AUTH_RECONNECT_FIRST_MS = 100;
|
|
26180
|
+
var PENDING_AUTH_RECONNECT_MAX_MS = 3e4;
|
|
26181
|
+
function pendingAuthReconnectDelayMs(attemptBeforeIncrement) {
|
|
26182
|
+
return Math.min(PENDING_AUTH_RECONNECT_FIRST_MS * 2 ** attemptBeforeIncrement, PENDING_AUTH_RECONNECT_MAX_MS);
|
|
26165
26183
|
}
|
|
26166
26184
|
|
|
26167
|
-
// src/
|
|
26185
|
+
// src/connection/reconnect/format-reconnect-delay-for-log.ts
|
|
26168
26186
|
function formatReconnectDelayForLog(delayMs) {
|
|
26169
26187
|
if (delayMs < 1e3) return `${delayMs}ms`;
|
|
26170
26188
|
const s = delayMs / 1e3;
|
|
26171
26189
|
return Number.isInteger(s) ? `${s}s` : `${s.toFixed(1)}s`;
|
|
26172
26190
|
}
|
|
26173
26191
|
|
|
26174
|
-
// src/
|
|
26175
|
-
function logNextReconnectAttempt(log2, serviceLabel, quiet, delayMs, attempt) {
|
|
26176
|
-
if (!quiet.verboseLogs) return;
|
|
26177
|
-
const delayLabel = formatReconnectDelayForLog(delayMs);
|
|
26178
|
-
log2(`${serviceLabel} Next connection attempt in ${delayLabel} (attempt ${attempt}).`);
|
|
26179
|
-
}
|
|
26180
|
-
|
|
26181
|
-
// src/bridge/connection/ws-close-diagnostics.ts
|
|
26192
|
+
// src/connection/ws-close-diagnostics.ts
|
|
26182
26193
|
function describeWebSocketCloseCode(code) {
|
|
26183
26194
|
const known = {
|
|
26184
26195
|
1e3: "normal closure",
|
|
@@ -26209,7 +26220,7 @@ function formatWebSocketClose(label, code, reason, extra) {
|
|
|
26209
26220
|
return `${label} Disconnected: code=${code} (${describeWebSocketCloseCode(code)})${reasonPart}${extraPart}`;
|
|
26210
26221
|
}
|
|
26211
26222
|
|
|
26212
|
-
// src/
|
|
26223
|
+
// src/connection/reconnect/reconnect-quiet-slot.ts
|
|
26213
26224
|
function createEmptyReconnectQuietSlot() {
|
|
26214
26225
|
return { timer: null, verboseLogs: false, pendingCloseLog: null };
|
|
26215
26226
|
}
|
|
@@ -26219,6 +26230,11 @@ function clearReconnectQuietTimer(quiet) {
|
|
|
26219
26230
|
quiet.timer = null;
|
|
26220
26231
|
}
|
|
26221
26232
|
}
|
|
26233
|
+
function abandonReconnectQuietWindow(quiet) {
|
|
26234
|
+
clearReconnectQuietTimer(quiet);
|
|
26235
|
+
quiet.pendingCloseLog = null;
|
|
26236
|
+
quiet.verboseLogs = false;
|
|
26237
|
+
}
|
|
26222
26238
|
function clearReconnectQuietOnSuccessfulConnection(quiet, log2, reconnectedMessage) {
|
|
26223
26239
|
clearReconnectQuietTimer(quiet);
|
|
26224
26240
|
quiet.pendingCloseLog = null;
|
|
@@ -26239,12 +26255,16 @@ function beginDeferredDisconnectForReconnect(options) {
|
|
|
26239
26255
|
shutdownDetail,
|
|
26240
26256
|
reconnectingDetail,
|
|
26241
26257
|
quietMs = RECONNECT_QUIET_MS,
|
|
26242
|
-
shouldAbortQuietWindow
|
|
26258
|
+
shouldAbortQuietWindow,
|
|
26259
|
+
silentWhileReconnect = false
|
|
26243
26260
|
} = options;
|
|
26244
26261
|
if (!willReconnect) {
|
|
26245
26262
|
log2(formatWebSocketClose(serviceLabel, code, reason, shutdownDetail));
|
|
26246
26263
|
return;
|
|
26247
26264
|
}
|
|
26265
|
+
if (silentWhileReconnect) {
|
|
26266
|
+
return;
|
|
26267
|
+
}
|
|
26248
26268
|
quiet.pendingCloseLog = { code, reason };
|
|
26249
26269
|
if (quiet.timer == null) {
|
|
26250
26270
|
quiet.timer = setTimeout(() => {
|
|
@@ -26261,18 +26281,178 @@ function beginDeferredDisconnectForReconnect(options) {
|
|
|
26261
26281
|
}
|
|
26262
26282
|
}
|
|
26263
26283
|
|
|
26264
|
-
// src/
|
|
26265
|
-
function
|
|
26284
|
+
// src/connection/reconnect/reconnect-outage-plan.ts
|
|
26285
|
+
function createEmptyReconnectOutageTracker() {
|
|
26286
|
+
return {
|
|
26287
|
+
startedAt: null,
|
|
26288
|
+
totalFailures: 0,
|
|
26289
|
+
lastLoggedTierIndex: -1,
|
|
26290
|
+
originalCloseCode: null,
|
|
26291
|
+
originalCloseReason: null
|
|
26292
|
+
};
|
|
26293
|
+
}
|
|
26294
|
+
function resetReconnectOutageTracker(tracker) {
|
|
26295
|
+
tracker.startedAt = null;
|
|
26296
|
+
tracker.totalFailures = 0;
|
|
26297
|
+
tracker.lastLoggedTierIndex = -1;
|
|
26298
|
+
tracker.originalCloseCode = null;
|
|
26299
|
+
tracker.originalCloseReason = null;
|
|
26300
|
+
}
|
|
26301
|
+
function reconnectTierIndexForOutageElapsedMs(elapsedMs) {
|
|
26302
|
+
if (elapsedMs < 6e4) return 0;
|
|
26303
|
+
if (elapsedMs < 36e4) return 1;
|
|
26304
|
+
if (elapsedMs < 12e5) return 2;
|
|
26305
|
+
return 3;
|
|
26306
|
+
}
|
|
26307
|
+
function reconnectDelayMsForOutageElapsedMs(elapsedMs) {
|
|
26308
|
+
if (elapsedMs < 6e4) return 3e3;
|
|
26309
|
+
if (elapsedMs < 36e4) return 1e4;
|
|
26310
|
+
if (elapsedMs < 12e5) return 2e4;
|
|
26311
|
+
return 6e4;
|
|
26312
|
+
}
|
|
26313
|
+
function disconnectDetail(code, reason) {
|
|
26314
|
+
const r = reason.trim();
|
|
26315
|
+
const reasonPart = r ? ` reason="${r}"` : "";
|
|
26316
|
+
return `code=${code} (${describeWebSocketCloseCode(code)})${reasonPart}`;
|
|
26317
|
+
}
|
|
26318
|
+
function formatTierPromotionLogLine(parts) {
|
|
26319
|
+
const detail = disconnectDetail(parts.code, parts.reason);
|
|
26320
|
+
return `${parts.serviceLabel} ${parts.disconnectLeadIn}: ${detail}. Trying to re-establish a connection in the background (retry attempts so far: ${parts.totalFailures}).`;
|
|
26321
|
+
}
|
|
26322
|
+
function planReconnectAfterFailure(tracker, nowMs, serviceLabel, disconnectLeadIn, closeCode, closeReason) {
|
|
26323
|
+
if (tracker.startedAt == null) {
|
|
26324
|
+
tracker.startedAt = nowMs;
|
|
26325
|
+
}
|
|
26326
|
+
if (closeCode != null && tracker.originalCloseCode == null) {
|
|
26327
|
+
tracker.originalCloseCode = closeCode;
|
|
26328
|
+
tracker.originalCloseReason = closeReason ?? "";
|
|
26329
|
+
}
|
|
26330
|
+
tracker.totalFailures += 1;
|
|
26331
|
+
const elapsed = nowMs - tracker.startedAt;
|
|
26332
|
+
const tier = reconnectTierIndexForOutageElapsedMs(elapsed);
|
|
26333
|
+
const delayMs = reconnectDelayMsForOutageElapsedMs(elapsed);
|
|
26334
|
+
let logLine = null;
|
|
26335
|
+
if (tier > tracker.lastLoggedTierIndex) {
|
|
26336
|
+
tracker.lastLoggedTierIndex = tier;
|
|
26337
|
+
const code = tracker.originalCloseCode ?? closeCode ?? 0;
|
|
26338
|
+
const reason = tracker.originalCloseReason ?? closeReason ?? "";
|
|
26339
|
+
logLine = formatTierPromotionLogLine({
|
|
26340
|
+
serviceLabel,
|
|
26341
|
+
disconnectLeadIn,
|
|
26342
|
+
code,
|
|
26343
|
+
reason,
|
|
26344
|
+
totalFailures: tracker.totalFailures
|
|
26345
|
+
});
|
|
26346
|
+
}
|
|
26347
|
+
return { delayMs, logLine };
|
|
26348
|
+
}
|
|
26349
|
+
|
|
26350
|
+
// src/connection/reconnect/tiered-channel-reconnect.ts
|
|
26351
|
+
var BRIDGE_SERVICE_LABEL = "[Bridge service]";
|
|
26352
|
+
var BRIDGE_DISCONNECT_LEAD_IN = "Bridge connection was disconnected";
|
|
26353
|
+
var PREVIEW_TUNNEL_SERVICE_LABEL = "[Proxy and log service]";
|
|
26354
|
+
var PREVIEW_TUNNEL_DISCONNECT_LEAD_IN = "Preview tunnel connection was disconnected";
|
|
26355
|
+
var SHUTDOWN_DETAIL = "Not reconnecting (shutting down).";
|
|
26356
|
+
var RECONNECTING_DETAIL = "Reconnecting\u2026";
|
|
26357
|
+
function applyTieredReconnectPlanAndLog(tracker, log2, serviceLabel, disconnectLeadIn, closeCode, closeReason) {
|
|
26358
|
+
try {
|
|
26359
|
+
const { delayMs, logLine } = planReconnectAfterFailure(
|
|
26360
|
+
tracker,
|
|
26361
|
+
Date.now(),
|
|
26362
|
+
serviceLabel,
|
|
26363
|
+
disconnectLeadIn,
|
|
26364
|
+
closeCode,
|
|
26365
|
+
closeReason
|
|
26366
|
+
);
|
|
26367
|
+
if (logLine) {
|
|
26368
|
+
try {
|
|
26369
|
+
log2(logLine);
|
|
26370
|
+
} catch {
|
|
26371
|
+
}
|
|
26372
|
+
}
|
|
26373
|
+
return delayMs;
|
|
26374
|
+
} catch {
|
|
26375
|
+
return 3e3;
|
|
26376
|
+
}
|
|
26377
|
+
}
|
|
26378
|
+
function armReconnectDelayTimer(options) {
|
|
26379
|
+
const {
|
|
26380
|
+
delayMs,
|
|
26381
|
+
bumpAttempt,
|
|
26382
|
+
clearTimer,
|
|
26383
|
+
setTimer,
|
|
26384
|
+
shouldAbortBeforeRun,
|
|
26385
|
+
run,
|
|
26386
|
+
reschedule
|
|
26387
|
+
} = options;
|
|
26388
|
+
clearTimer();
|
|
26389
|
+
bumpAttempt();
|
|
26390
|
+
setTimer(
|
|
26391
|
+
setTimeout(() => {
|
|
26392
|
+
setTimer(null);
|
|
26393
|
+
if (shouldAbortBeforeRun()) return;
|
|
26394
|
+
try {
|
|
26395
|
+
run();
|
|
26396
|
+
} catch {
|
|
26397
|
+
try {
|
|
26398
|
+
if (!shouldAbortBeforeRun()) {
|
|
26399
|
+
reschedule();
|
|
26400
|
+
}
|
|
26401
|
+
} catch {
|
|
26402
|
+
}
|
|
26403
|
+
}
|
|
26404
|
+
}, delayMs)
|
|
26405
|
+
);
|
|
26406
|
+
}
|
|
26407
|
+
function beginTieredSilentReconnectDisconnect(options) {
|
|
26408
|
+
const {
|
|
26409
|
+
isClosedByUser,
|
|
26410
|
+
quiet,
|
|
26411
|
+
code,
|
|
26412
|
+
reason,
|
|
26413
|
+
willReconnect,
|
|
26414
|
+
log: log2,
|
|
26415
|
+
serviceLabel,
|
|
26416
|
+
shouldAbortQuietWindow
|
|
26417
|
+
} = options;
|
|
26266
26418
|
beginDeferredDisconnectForReconnect({
|
|
26419
|
+
isClosedByUser,
|
|
26420
|
+
quiet,
|
|
26421
|
+
code,
|
|
26422
|
+
reason,
|
|
26423
|
+
willReconnect,
|
|
26424
|
+
log: log2,
|
|
26425
|
+
serviceLabel,
|
|
26426
|
+
shutdownDetail: SHUTDOWN_DETAIL,
|
|
26427
|
+
reconnectingDetail: RECONNECTING_DETAIL,
|
|
26428
|
+
shouldAbortQuietWindow,
|
|
26429
|
+
silentWhileReconnect: willReconnect
|
|
26430
|
+
});
|
|
26431
|
+
}
|
|
26432
|
+
function clearTieredReconnectChannelOnOpen(options) {
|
|
26433
|
+
const { quiet, outage, clearLastCloseMeta, log: log2, restoredMessage } = options;
|
|
26434
|
+
const hadOutage = outage.startedAt != null || outage.totalFailures > 0;
|
|
26435
|
+
abandonReconnectQuietWindow(quiet);
|
|
26436
|
+
resetReconnectOutageTracker(outage);
|
|
26437
|
+
clearLastCloseMeta();
|
|
26438
|
+
if (hadOutage) {
|
|
26439
|
+
try {
|
|
26440
|
+
log2(restoredMessage);
|
|
26441
|
+
} catch {
|
|
26442
|
+
}
|
|
26443
|
+
}
|
|
26444
|
+
}
|
|
26445
|
+
|
|
26446
|
+
// src/connection/reconnect/bridge-main-reconnect.ts
|
|
26447
|
+
function beginMainBridgeDeferredDisconnect(state, code, reason, log2, willReconnect) {
|
|
26448
|
+
beginTieredSilentReconnectDisconnect({
|
|
26267
26449
|
isClosedByUser: () => state.closedByUser,
|
|
26268
26450
|
quiet: state.mainQuiet,
|
|
26269
26451
|
code,
|
|
26270
26452
|
reason,
|
|
26271
26453
|
willReconnect,
|
|
26272
26454
|
log: log2,
|
|
26273
|
-
serviceLabel:
|
|
26274
|
-
shutdownDetail: "Not reconnecting (shutting down).",
|
|
26275
|
-
reconnectingDetail: "Reconnecting\u2026",
|
|
26455
|
+
serviceLabel: BRIDGE_SERVICE_LABEL,
|
|
26276
26456
|
shouldAbortQuietWindow: () => {
|
|
26277
26457
|
const w = state.currentWs;
|
|
26278
26458
|
return w != null && w.readyState === wrapper_default.OPEN;
|
|
@@ -26280,32 +26460,59 @@ function beginMainBridgeDeferredDisconnect(state, code, reason, log2, willReconn
|
|
|
26280
26460
|
});
|
|
26281
26461
|
}
|
|
26282
26462
|
function clearMainBridgeReconnectQuietOnOpen(state, log2) {
|
|
26283
|
-
|
|
26463
|
+
clearTieredReconnectChannelOnOpen({
|
|
26464
|
+
quiet: state.mainQuiet,
|
|
26465
|
+
outage: state.mainOutage,
|
|
26466
|
+
clearLastCloseMeta: () => {
|
|
26467
|
+
state.lastReconnectCloseMeta = null;
|
|
26468
|
+
},
|
|
26469
|
+
log: log2,
|
|
26470
|
+
restoredMessage: "Bridge connection restored."
|
|
26471
|
+
});
|
|
26284
26472
|
}
|
|
26285
|
-
function scheduleMainBridgeReconnect(state, connect, log2) {
|
|
26473
|
+
function scheduleMainBridgeReconnect(state, connect, log2, closeMeta) {
|
|
26286
26474
|
if (state.closedByUser || state.currentWs != null) return;
|
|
26287
|
-
const
|
|
26288
|
-
|
|
26289
|
-
|
|
26290
|
-
|
|
26291
|
-
|
|
26292
|
-
|
|
26293
|
-
|
|
26475
|
+
const meta = closeMeta ?? state.lastReconnectCloseMeta ?? void 0;
|
|
26476
|
+
const delay2 = applyTieredReconnectPlanAndLog(
|
|
26477
|
+
state.mainOutage,
|
|
26478
|
+
log2,
|
|
26479
|
+
BRIDGE_SERVICE_LABEL,
|
|
26480
|
+
BRIDGE_DISCONNECT_LEAD_IN,
|
|
26481
|
+
meta?.code,
|
|
26482
|
+
meta?.reason
|
|
26483
|
+
);
|
|
26484
|
+
armReconnectDelayTimer({
|
|
26485
|
+
delayMs: delay2,
|
|
26486
|
+
bumpAttempt: () => {
|
|
26487
|
+
state.reconnectAttempt += 1;
|
|
26488
|
+
},
|
|
26489
|
+
clearTimer: () => {
|
|
26490
|
+
if (state.reconnectTimeout != null) {
|
|
26491
|
+
clearTimeout(state.reconnectTimeout);
|
|
26492
|
+
state.reconnectTimeout = null;
|
|
26493
|
+
}
|
|
26494
|
+
},
|
|
26495
|
+
setTimer: (id) => {
|
|
26496
|
+
state.reconnectTimeout = id;
|
|
26497
|
+
},
|
|
26498
|
+
shouldAbortBeforeRun: () => state.closedByUser || state.currentWs != null,
|
|
26499
|
+
run: connect,
|
|
26500
|
+
reschedule: () => {
|
|
26501
|
+
scheduleMainBridgeReconnect(state, connect, log2);
|
|
26502
|
+
}
|
|
26503
|
+
});
|
|
26294
26504
|
}
|
|
26295
26505
|
|
|
26296
|
-
// src/
|
|
26297
|
-
var PROXY_AND_LOG_SERVICE_LABEL = "[Proxy and log service]";
|
|
26506
|
+
// src/connection/reconnect/firehose-reconnect.ts
|
|
26298
26507
|
function beginFirehoseDeferredDisconnect(ctx, code, reason, log2) {
|
|
26299
|
-
|
|
26508
|
+
beginTieredSilentReconnectDisconnect({
|
|
26300
26509
|
isClosedByUser: () => ctx.closedByUser,
|
|
26301
26510
|
quiet: ctx.firehoseQuiet,
|
|
26302
26511
|
code,
|
|
26303
26512
|
reason,
|
|
26304
26513
|
willReconnect: true,
|
|
26305
26514
|
log: log2,
|
|
26306
|
-
serviceLabel:
|
|
26307
|
-
shutdownDetail: "Not reconnecting (shutting down).",
|
|
26308
|
-
reconnectingDetail: "Reconnecting\u2026",
|
|
26515
|
+
serviceLabel: PREVIEW_TUNNEL_SERVICE_LABEL,
|
|
26309
26516
|
shouldAbortQuietWindow: () => {
|
|
26310
26517
|
const w = ctx.currentWs;
|
|
26311
26518
|
if (!w || w.readyState !== wrapper_default.OPEN) return true;
|
|
@@ -26314,11 +26521,15 @@ function beginFirehoseDeferredDisconnect(ctx, code, reason, log2) {
|
|
|
26314
26521
|
});
|
|
26315
26522
|
}
|
|
26316
26523
|
function clearFirehoseReconnectQuietOnOpen(ctx, log2) {
|
|
26317
|
-
|
|
26318
|
-
ctx.firehoseQuiet,
|
|
26319
|
-
|
|
26320
|
-
|
|
26321
|
-
|
|
26524
|
+
clearTieredReconnectChannelOnOpen({
|
|
26525
|
+
quiet: ctx.firehoseQuiet,
|
|
26526
|
+
outage: ctx.firehoseOutage,
|
|
26527
|
+
clearLastCloseMeta: () => {
|
|
26528
|
+
ctx.lastFirehoseReconnectCloseMeta = null;
|
|
26529
|
+
},
|
|
26530
|
+
log: log2,
|
|
26531
|
+
restoredMessage: "Preview tunnel restored (local HTTP proxy and dev logs)."
|
|
26532
|
+
});
|
|
26322
26533
|
}
|
|
26323
26534
|
|
|
26324
26535
|
// src/auth/run-pending-auth.ts
|
|
@@ -26414,7 +26625,7 @@ function runPendingAuth(options) {
|
|
|
26414
26625
|
}
|
|
26415
26626
|
if (resolved) return;
|
|
26416
26627
|
beginDeferredPendingCloseLog(code, reason);
|
|
26417
|
-
const delay2 =
|
|
26628
|
+
const delay2 = pendingAuthReconnectDelayMs(reconnectAttempt);
|
|
26418
26629
|
reconnectAttempt += 1;
|
|
26419
26630
|
if (signInQuiet.verboseLogs) {
|
|
26420
26631
|
const delayLabel = formatReconnectDelayForLog(delay2);
|
|
@@ -26459,7 +26670,7 @@ function runPendingAuth(options) {
|
|
|
26459
26670
|
};
|
|
26460
26671
|
}
|
|
26461
26672
|
|
|
26462
|
-
// src/
|
|
26673
|
+
// src/connection/close-bridge-connection.ts
|
|
26463
26674
|
async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
|
|
26464
26675
|
const say = log2 ?? logImmediate;
|
|
26465
26676
|
say("Cleaning up connections\u2026");
|
|
@@ -26974,6 +27185,30 @@ var GitRepoMetaSchema = external_exports.object({
|
|
|
26974
27185
|
updatedAt: external_exports.string()
|
|
26975
27186
|
});
|
|
26976
27187
|
|
|
27188
|
+
// ../types/src/claude-code-permission-mode.ts
|
|
27189
|
+
var CLAUDE_CODE_PERMISSION_MODES = [
|
|
27190
|
+
"default",
|
|
27191
|
+
"acceptEdits",
|
|
27192
|
+
"plan",
|
|
27193
|
+
"auto",
|
|
27194
|
+
"dontAsk",
|
|
27195
|
+
"bypassPermissions"
|
|
27196
|
+
];
|
|
27197
|
+
var MODE_SET = new Set(CLAUDE_CODE_PERMISSION_MODES);
|
|
27198
|
+
function isClaudeCodePermissionMode(value) {
|
|
27199
|
+
return MODE_SET.has(value);
|
|
27200
|
+
}
|
|
27201
|
+
|
|
27202
|
+
// ../types/src/agent-config.ts
|
|
27203
|
+
var AGENT_CONFIG_CLAUDE_PERMISSION_MODE_KEY = "claude_permission_mode";
|
|
27204
|
+
function getClaudePermissionModeFromAgentConfig(config2) {
|
|
27205
|
+
if (!config2) return null;
|
|
27206
|
+
const raw = config2[AGENT_CONFIG_CLAUDE_PERMISSION_MODE_KEY];
|
|
27207
|
+
if (typeof raw !== "string") return null;
|
|
27208
|
+
const t = raw.trim();
|
|
27209
|
+
return isClaudeCodePermissionMode(t) ? t : null;
|
|
27210
|
+
}
|
|
27211
|
+
|
|
26977
27212
|
// src/git/session-git-queue.ts
|
|
26978
27213
|
import { execFile as execFile7 } from "node:child_process";
|
|
26979
27214
|
import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
|
|
@@ -31549,10 +31784,28 @@ function gitInstanceFactory(baseDir, options) {
|
|
|
31549
31784
|
init_git_response_error();
|
|
31550
31785
|
var simpleGit = gitInstanceFactory;
|
|
31551
31786
|
|
|
31787
|
+
// src/git/cli-simple-git.ts
|
|
31788
|
+
function cliSimpleGit(baseDir) {
|
|
31789
|
+
const git = simpleGit({ baseDir });
|
|
31790
|
+
git.outputHandler((command, stdout, stderr) => {
|
|
31791
|
+
const trace = isCliTrace();
|
|
31792
|
+
const onChunk = (label) => (chunk) => {
|
|
31793
|
+
const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
31794
|
+
const line = text.replace(/\s+$/, "");
|
|
31795
|
+
if (trace && line) {
|
|
31796
|
+
logTrace(`[git ${command}] ${label}: ${line}`);
|
|
31797
|
+
}
|
|
31798
|
+
};
|
|
31799
|
+
stdout?.on("data", onChunk("stdout"));
|
|
31800
|
+
stderr?.on("data", onChunk("stderr"));
|
|
31801
|
+
});
|
|
31802
|
+
return git;
|
|
31803
|
+
}
|
|
31804
|
+
|
|
31552
31805
|
// src/git/remote-origin-url.ts
|
|
31553
31806
|
async function getRemoteOriginUrl(gitDir) {
|
|
31554
31807
|
try {
|
|
31555
|
-
const git =
|
|
31808
|
+
const git = cliSimpleGit(gitDir);
|
|
31556
31809
|
const remotes = await git.getRemotes(true);
|
|
31557
31810
|
const list = Array.isArray(remotes) ? remotes : [];
|
|
31558
31811
|
const origin = list.find((r) => r.name === "origin");
|
|
@@ -31566,7 +31819,7 @@ async function getRemoteOriginUrl(gitDir) {
|
|
|
31566
31819
|
// src/git/is-git-repo.ts
|
|
31567
31820
|
async function isGitRepoDirectory(dirPath) {
|
|
31568
31821
|
try {
|
|
31569
|
-
return await
|
|
31822
|
+
return await cliSimpleGit(dirPath).checkIsRepo();
|
|
31570
31823
|
} catch {
|
|
31571
31824
|
return false;
|
|
31572
31825
|
}
|
|
@@ -32259,7 +32512,8 @@ async function createSdkStdioAcpClient(options) {
|
|
|
32259
32512
|
onRequest,
|
|
32260
32513
|
onFileChange,
|
|
32261
32514
|
killSubprocessAfterCancelMs,
|
|
32262
|
-
onAgentSubprocessExit
|
|
32515
|
+
onAgentSubprocessExit,
|
|
32516
|
+
agentConfig
|
|
32263
32517
|
} = options;
|
|
32264
32518
|
const isWindows = process.platform === "win32";
|
|
32265
32519
|
const child = spawn2(command[0], command.slice(1), {
|
|
@@ -32374,6 +32628,20 @@ async function createSdkStdioAcpClient(options) {
|
|
|
32374
32628
|
});
|
|
32375
32629
|
const newSessionRes = await connection.newSession({ cwd, mcpServers: [] });
|
|
32376
32630
|
const sessionId = newSessionRes.sessionId;
|
|
32631
|
+
if (backendAgentType === "claude-code") {
|
|
32632
|
+
const cfg = agentConfig != null && typeof agentConfig === "object" && !Array.isArray(agentConfig) ? agentConfig : null;
|
|
32633
|
+
const desiredMode = getClaudePermissionModeFromAgentConfig(cfg);
|
|
32634
|
+
const modes = newSessionRes.modes;
|
|
32635
|
+
if (desiredMode != null && modes?.availableModes?.length) {
|
|
32636
|
+
const allowed = modes.availableModes.some((m) => m.id === desiredMode);
|
|
32637
|
+
if (allowed && desiredMode !== modes.currentModeId) {
|
|
32638
|
+
try {
|
|
32639
|
+
await connection.setSessionMode({ sessionId, modeId: desiredMode });
|
|
32640
|
+
} catch {
|
|
32641
|
+
}
|
|
32642
|
+
}
|
|
32643
|
+
}
|
|
32644
|
+
}
|
|
32377
32645
|
settleResolve({
|
|
32378
32646
|
sessionId,
|
|
32379
32647
|
async sendPrompt(prompt, _options) {
|
|
@@ -32485,10 +32753,7 @@ async function detectLocalAgentPresence() {
|
|
|
32485
32753
|
return false;
|
|
32486
32754
|
}
|
|
32487
32755
|
}
|
|
32488
|
-
function buildClaudeCodeAcpSpawnCommand(base,
|
|
32489
|
-
if (!sessionMode) return [...base];
|
|
32490
|
-
const m = sessionMode.trim();
|
|
32491
|
-
if (m === "plan") return [...base, "--permission-mode", "plan"];
|
|
32756
|
+
function buildClaudeCodeAcpSpawnCommand(base, _sessionMode) {
|
|
32492
32757
|
return [...base];
|
|
32493
32758
|
}
|
|
32494
32759
|
async function createClaudeCodeAcpClient(options) {
|
|
@@ -32951,7 +33216,7 @@ function resolveAgentCommand(preferredAgentType) {
|
|
|
32951
33216
|
command,
|
|
32952
33217
|
label: preferredAgentType,
|
|
32953
33218
|
createClient: createCursorAcpClient,
|
|
32954
|
-
spawnCommandForSession: (sessionMode) => buildCursorAcpSpawnCommand(command, sessionMode)
|
|
33219
|
+
spawnCommandForSession: (sessionMode, _agentConfig) => buildCursorAcpSpawnCommand(command, sessionMode)
|
|
32955
33220
|
};
|
|
32956
33221
|
}
|
|
32957
33222
|
if (useCodexAcp(preferredAgentType, command)) {
|
|
@@ -32959,7 +33224,7 @@ function resolveAgentCommand(preferredAgentType) {
|
|
|
32959
33224
|
command,
|
|
32960
33225
|
label: preferredAgentType,
|
|
32961
33226
|
createClient: createCodexAcpClient,
|
|
32962
|
-
spawnCommandForSession: (sessionMode) => buildCodexAcpSpawnCommand(command, sessionMode)
|
|
33227
|
+
spawnCommandForSession: (sessionMode, _agentConfig) => buildCodexAcpSpawnCommand(command, sessionMode)
|
|
32963
33228
|
};
|
|
32964
33229
|
}
|
|
32965
33230
|
if (useKiroAcp(preferredAgentType, command)) {
|
|
@@ -32967,7 +33232,7 @@ function resolveAgentCommand(preferredAgentType) {
|
|
|
32967
33232
|
command,
|
|
32968
33233
|
label: preferredAgentType,
|
|
32969
33234
|
createClient: createKiroAcpClient,
|
|
32970
|
-
spawnCommandForSession: (sessionMode) => buildKiroAcpSpawnCommand(command, sessionMode)
|
|
33235
|
+
spawnCommandForSession: (sessionMode, _agentConfig) => buildKiroAcpSpawnCommand(command, sessionMode)
|
|
32971
33236
|
};
|
|
32972
33237
|
}
|
|
32973
33238
|
return {
|
|
@@ -33633,7 +33898,7 @@ function buildAcpSessionBridgeHooks(opts) {
|
|
|
33633
33898
|
|
|
33634
33899
|
// src/agents/acp/ensure-acp-client.ts
|
|
33635
33900
|
async function ensureAcpClient(options) {
|
|
33636
|
-
const { state, preferredAgentType, mode, sessionParentPath, routing, sendSessionUpdate, sendRequest, log: log2 } = options;
|
|
33901
|
+
const { state, preferredAgentType, mode, agentConfig, sessionParentPath, routing, sendSessionUpdate, sendRequest, log: log2 } = options;
|
|
33637
33902
|
const targetSessionParentPath = resolveSessionParentPathForAgentProcess(sessionParentPath);
|
|
33638
33903
|
if (state.acpStartPromise && !state.acpHandle) {
|
|
33639
33904
|
await state.acpStartPromise;
|
|
@@ -33655,8 +33920,9 @@ async function ensureAcpClient(options) {
|
|
|
33655
33920
|
state.lastAcpStartError = "No agent type: ensure the app sends agentType on prompts or agent_config for this bridge.";
|
|
33656
33921
|
return null;
|
|
33657
33922
|
}
|
|
33658
|
-
const fullCmd = resolved.spawnCommandForSession(mode);
|
|
33659
|
-
const
|
|
33923
|
+
const fullCmd = resolved.spawnCommandForSession(mode, agentConfig ?? null);
|
|
33924
|
+
const cacheConfig = agentConfig != null && typeof agentConfig === "object" && !Array.isArray(agentConfig) && Object.keys(agentConfig).length > 0 ? `\0${JSON.stringify(agentConfig, Object.keys(agentConfig).sort())}` : "";
|
|
33925
|
+
const agentKey = `${resolved.label}::${fullCmd.join("\0")}${cacheConfig}`;
|
|
33660
33926
|
if (state.acpHandle && state.acpAgentKey !== agentKey) {
|
|
33661
33927
|
try {
|
|
33662
33928
|
state.acpHandle.disconnect();
|
|
@@ -33693,6 +33959,7 @@ async function ensureAcpClient(options) {
|
|
|
33693
33959
|
state.acpStartPromise = resolved.createClient({
|
|
33694
33960
|
command: resolved.command,
|
|
33695
33961
|
sessionMode: mode,
|
|
33962
|
+
agentConfig: agentConfig ?? null,
|
|
33696
33963
|
backendAgentType: preferredAgentType,
|
|
33697
33964
|
onAgentSubprocessExit: () => {
|
|
33698
33965
|
state.acpHandle = null;
|
|
@@ -33754,6 +34021,7 @@ async function createAcpManager(options) {
|
|
|
33754
34021
|
runId,
|
|
33755
34022
|
mode,
|
|
33756
34023
|
agentType,
|
|
34024
|
+
agentConfig,
|
|
33757
34025
|
sessionParentPath,
|
|
33758
34026
|
sendResult: sendResult2,
|
|
33759
34027
|
sendSessionUpdate,
|
|
@@ -33773,6 +34041,7 @@ async function createAcpManager(options) {
|
|
|
33773
34041
|
state,
|
|
33774
34042
|
preferredAgentType: preferredForPrompt,
|
|
33775
34043
|
mode,
|
|
34044
|
+
agentConfig: agentConfig ?? null,
|
|
33776
34045
|
sessionParentPath,
|
|
33777
34046
|
routing: promptRouting,
|
|
33778
34047
|
sendSessionUpdate,
|
|
@@ -33886,7 +34155,7 @@ import * as path14 from "node:path";
|
|
|
33886
34155
|
|
|
33887
34156
|
// src/git/worktree-add.ts
|
|
33888
34157
|
async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
|
|
33889
|
-
const mainGit =
|
|
34158
|
+
const mainGit = cliSimpleGit(mainRepoPath);
|
|
33890
34159
|
await mainGit.raw(["worktree", "add", "-b", branch, worktreePath, "HEAD"]);
|
|
33891
34160
|
}
|
|
33892
34161
|
|
|
@@ -33991,7 +34260,7 @@ async function prepareNewSessionWorktrees(options) {
|
|
|
33991
34260
|
|
|
33992
34261
|
// src/git/rename-branch.ts
|
|
33993
34262
|
async function gitRenameCurrentBranch(repoDir, newName) {
|
|
33994
|
-
const g =
|
|
34263
|
+
const g = cliSimpleGit(repoDir);
|
|
33995
34264
|
await g.raw(["branch", "-m", newName]);
|
|
33996
34265
|
}
|
|
33997
34266
|
|
|
@@ -34034,7 +34303,7 @@ function resolveMainRepoFromWorktreeGitFile(wt) {
|
|
|
34034
34303
|
async function gitWorktreeRemoveForce(worktreePath) {
|
|
34035
34304
|
const mainRepo = resolveMainRepoFromWorktreeGitFile(worktreePath);
|
|
34036
34305
|
if (mainRepo) {
|
|
34037
|
-
await
|
|
34306
|
+
await cliSimpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
|
|
34038
34307
|
} else {
|
|
34039
34308
|
fs14.rmSync(worktreePath, { recursive: true, force: true });
|
|
34040
34309
|
}
|
|
@@ -34164,7 +34433,7 @@ async function gitLogNotReachableFromBase(g, baseSha, headSha) {
|
|
|
34164
34433
|
}
|
|
34165
34434
|
}
|
|
34166
34435
|
async function commitsAheadOfRemoteTracking(repoDir) {
|
|
34167
|
-
const g =
|
|
34436
|
+
const g = cliSimpleGit(repoDir);
|
|
34168
34437
|
const headSha = await revParseSafe(g, "HEAD");
|
|
34169
34438
|
if (!headSha) return 0;
|
|
34170
34439
|
const baseSha = await resolveBaseShaForUnpushedCommits(g);
|
|
@@ -34178,14 +34447,14 @@ async function commitsAheadOfRemoteTracking(repoDir) {
|
|
|
34178
34447
|
}
|
|
34179
34448
|
}
|
|
34180
34449
|
async function getRepoWorkingTreeStatus(repoDir) {
|
|
34181
|
-
const g =
|
|
34450
|
+
const g = cliSimpleGit(repoDir);
|
|
34182
34451
|
const st = await g.status();
|
|
34183
34452
|
const hasUncommittedChanges = (st.files?.length ?? 0) > 0;
|
|
34184
34453
|
const ahead = await commitsAheadOfRemoteTracking(repoDir);
|
|
34185
34454
|
return { hasUncommittedChanges, hasUnpushedCommits: ahead > 0 };
|
|
34186
34455
|
}
|
|
34187
34456
|
async function listUnpushedCommits(repoDir) {
|
|
34188
|
-
const g =
|
|
34457
|
+
const g = cliSimpleGit(repoDir);
|
|
34189
34458
|
const headSha = await revParseSafe(g, "HEAD");
|
|
34190
34459
|
if (!headSha) return [];
|
|
34191
34460
|
const baseSha = await resolveBaseShaForUnpushedCommits(g);
|
|
@@ -34204,7 +34473,7 @@ async function aggregateSessionPathsWorkingTreeStatus(paths) {
|
|
|
34204
34473
|
}
|
|
34205
34474
|
async function pushAheadOfUpstreamForPaths(paths) {
|
|
34206
34475
|
for (const p of paths) {
|
|
34207
|
-
const g =
|
|
34476
|
+
const g = cliSimpleGit(p);
|
|
34208
34477
|
const ahead = await commitsAheadOfRemoteTracking(p);
|
|
34209
34478
|
if (ahead <= 0) continue;
|
|
34210
34479
|
await g.push();
|
|
@@ -34346,7 +34615,7 @@ async function parentForCommitDiff(g, sha) {
|
|
|
34346
34615
|
}
|
|
34347
34616
|
}
|
|
34348
34617
|
async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
|
|
34349
|
-
const g =
|
|
34618
|
+
const g = cliSimpleGit(repoGitCwd);
|
|
34350
34619
|
const parent = await parentForCommitDiff(g, commitSha);
|
|
34351
34620
|
const range = `${parent}..${commitSha}`;
|
|
34352
34621
|
const [nameStatusRaw, numstatRaw] = await Promise.all([
|
|
@@ -34421,7 +34690,7 @@ var MAX_HYDRATE_LINES_PER_FILE = 8e4;
|
|
|
34421
34690
|
async function readGitBlobLines(repoCwd, pathInRepo) {
|
|
34422
34691
|
try {
|
|
34423
34692
|
const rel = pathInRepo.replace(/\\/g, "/");
|
|
34424
|
-
const raw = await
|
|
34693
|
+
const raw = await cliSimpleGit(repoCwd).show([`HEAD:${rel}`]);
|
|
34425
34694
|
return String(raw).split(/\r?\n/);
|
|
34426
34695
|
} catch {
|
|
34427
34696
|
return null;
|
|
@@ -34531,7 +34800,7 @@ async function hydrateUnifiedPatchWithFileContext(patch, filePath, repoGitCwd, p
|
|
|
34531
34800
|
|
|
34532
34801
|
// src/git/working-directory/changes/unified-diff-for-file.ts
|
|
34533
34802
|
async function unifiedDiffForFile(repoCwd, pathInRepo, change) {
|
|
34534
|
-
const g =
|
|
34803
|
+
const g = cliSimpleGit(repoCwd);
|
|
34535
34804
|
try {
|
|
34536
34805
|
let raw;
|
|
34537
34806
|
if (change === "added") {
|
|
@@ -34550,7 +34819,7 @@ async function unifiedDiffForFile(repoCwd, pathInRepo, change) {
|
|
|
34550
34819
|
|
|
34551
34820
|
// src/git/working-directory/changes/list-changed-files-for-repo.ts
|
|
34552
34821
|
async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
34553
|
-
const g =
|
|
34822
|
+
const g = cliSimpleGit(repoGitCwd);
|
|
34554
34823
|
const [nameStatusRaw, numstatRaw, untrackedRaw] = await Promise.all([
|
|
34555
34824
|
g.raw(["diff", "--name-status", "HEAD"]).catch(() => ""),
|
|
34556
34825
|
g.raw(["diff", "HEAD", "--numstat"]).catch(() => ""),
|
|
@@ -34635,7 +34904,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
34635
34904
|
for (const target of options.commitTargetPaths) {
|
|
34636
34905
|
const t = path17.resolve(target);
|
|
34637
34906
|
if (!await isGitRepoDirectory(t)) continue;
|
|
34638
|
-
const g =
|
|
34907
|
+
const g = cliSimpleGit(t);
|
|
34639
34908
|
let branch = "HEAD";
|
|
34640
34909
|
try {
|
|
34641
34910
|
branch = (await g.raw(["rev-parse", "--abbrev-ref", "HEAD"])).trim() || "HEAD";
|
|
@@ -34686,7 +34955,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
34686
34955
|
|
|
34687
34956
|
// src/git/commit-and-push.ts
|
|
34688
34957
|
async function gitCommitAllIfDirty(repoDir, message, options) {
|
|
34689
|
-
const g =
|
|
34958
|
+
const g = cliSimpleGit(repoDir);
|
|
34690
34959
|
const st = await g.status();
|
|
34691
34960
|
if (!st.files?.length) return;
|
|
34692
34961
|
const branch = options.branch.trim();
|
|
@@ -35473,7 +35742,7 @@ function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
|
35473
35742
|
};
|
|
35474
35743
|
}
|
|
35475
35744
|
|
|
35476
|
-
// src/
|
|
35745
|
+
// src/connection/create-bridge-connection.ts
|
|
35477
35746
|
import * as path34 from "node:path";
|
|
35478
35747
|
|
|
35479
35748
|
// src/dev-servers/manager/dev-server-manager.ts
|
|
@@ -36609,7 +36878,17 @@ function tryConsumeBinaryProxyBody(raw, deps) {
|
|
|
36609
36878
|
|
|
36610
36879
|
// src/firehose/connect-firehose.ts
|
|
36611
36880
|
function connectFirehose(options) {
|
|
36612
|
-
const {
|
|
36881
|
+
const {
|
|
36882
|
+
firehoseServerUrl,
|
|
36883
|
+
workspaceId,
|
|
36884
|
+
bridgeName,
|
|
36885
|
+
proxyPorts,
|
|
36886
|
+
log: log2,
|
|
36887
|
+
devServerManager,
|
|
36888
|
+
onOpen,
|
|
36889
|
+
onClose,
|
|
36890
|
+
suppressWebSocketErrors
|
|
36891
|
+
} = options;
|
|
36613
36892
|
const wsUrl = buildFirehoseCliWsUrl(firehoseServerUrl);
|
|
36614
36893
|
applyCliOutboundNetworkPreferences();
|
|
36615
36894
|
const ws = new wrapper_default(wsUrl, buildCliWebSocketClientOptions(wsUrl));
|
|
@@ -36654,7 +36933,9 @@ function connectFirehose(options) {
|
|
|
36654
36933
|
});
|
|
36655
36934
|
ws.on("error", (err) => {
|
|
36656
36935
|
disposeClientPing();
|
|
36657
|
-
|
|
36936
|
+
if (!suppressWebSocketErrors?.()) {
|
|
36937
|
+
logCliWebSocketError(log2, "[Proxy and log service]", err);
|
|
36938
|
+
}
|
|
36658
36939
|
if (ws.readyState === wrapper_default.CONNECTING || ws.readyState === wrapper_default.OPEN) {
|
|
36659
36940
|
safeCloseWebSocket(ws);
|
|
36660
36941
|
}
|
|
@@ -36669,7 +36950,7 @@ function connectFirehose(options) {
|
|
|
36669
36950
|
};
|
|
36670
36951
|
}
|
|
36671
36952
|
|
|
36672
|
-
// src/
|
|
36953
|
+
// src/connection/attach-firehose-after-identified.ts
|
|
36673
36954
|
function attachFirehoseAfterIdentified(ctx, params) {
|
|
36674
36955
|
const { state, devServerManager, logFn } = ctx;
|
|
36675
36956
|
function clearFirehoseReconnectTimer() {
|
|
@@ -36686,10 +36967,44 @@ function attachFirehoseAfterIdentified(ctx, params) {
|
|
|
36686
36967
|
firehoseQuiet: state.firehoseQuiet
|
|
36687
36968
|
};
|
|
36688
36969
|
}
|
|
36970
|
+
function scheduleFirehoseRetryAfterDrop(closeMeta) {
|
|
36971
|
+
if (state.closedByUser) return;
|
|
36972
|
+
const meta = closeMeta ?? state.lastFirehoseReconnectCloseMeta ?? void 0;
|
|
36973
|
+
const delay2 = applyTieredReconnectPlanAndLog(
|
|
36974
|
+
state.firehoseOutage,
|
|
36975
|
+
logFn,
|
|
36976
|
+
PREVIEW_TUNNEL_SERVICE_LABEL,
|
|
36977
|
+
PREVIEW_TUNNEL_DISCONNECT_LEAD_IN,
|
|
36978
|
+
meta?.code,
|
|
36979
|
+
meta?.reason
|
|
36980
|
+
);
|
|
36981
|
+
armReconnectDelayTimer({
|
|
36982
|
+
delayMs: delay2,
|
|
36983
|
+
bumpAttempt: () => {
|
|
36984
|
+
state.firehoseReconnectAttempt += 1;
|
|
36985
|
+
},
|
|
36986
|
+
clearTimer: clearFirehoseReconnectTimer,
|
|
36987
|
+
setTimer: (id) => {
|
|
36988
|
+
state.firehoseReconnectTimeout = id;
|
|
36989
|
+
},
|
|
36990
|
+
shouldAbortBeforeRun: () => state.closedByUser,
|
|
36991
|
+
run: () => {
|
|
36992
|
+
const p = state.lastFirehoseParams;
|
|
36993
|
+
if (!p) return;
|
|
36994
|
+
attachFirehoseAfterIdentified(ctx, p);
|
|
36995
|
+
},
|
|
36996
|
+
reschedule: () => {
|
|
36997
|
+
scheduleFirehoseRetryAfterDrop();
|
|
36998
|
+
}
|
|
36999
|
+
});
|
|
37000
|
+
}
|
|
36689
37001
|
state.lastFirehoseParams = params;
|
|
36690
37002
|
clearFirehoseReconnectTimer();
|
|
36691
37003
|
if (state.firehoseReconnectAttempt === 0) {
|
|
36692
|
-
|
|
37004
|
+
try {
|
|
37005
|
+
logFn("Connecting to preview tunnel (local HTTP proxy and dev logs)\u2026");
|
|
37006
|
+
} catch {
|
|
37007
|
+
}
|
|
36693
37008
|
}
|
|
36694
37009
|
state.firehoseGeneration += 1;
|
|
36695
37010
|
const myGen = state.firehoseGeneration;
|
|
@@ -36704,47 +37019,47 @@ function attachFirehoseAfterIdentified(ctx, params) {
|
|
|
36704
37019
|
proxyPorts: params.proxyPorts,
|
|
36705
37020
|
log: logFn,
|
|
36706
37021
|
devServerManager,
|
|
37022
|
+
suppressWebSocketErrors: () => !state.closedByUser && state.firehoseOutage.startedAt != null,
|
|
36707
37023
|
onOpen: () => {
|
|
36708
37024
|
if (myGen !== state.firehoseGeneration) return;
|
|
36709
|
-
|
|
37025
|
+
try {
|
|
37026
|
+
clearFirehoseReconnectQuietOnOpen(
|
|
37027
|
+
{
|
|
37028
|
+
firehoseQuiet: state.firehoseQuiet,
|
|
37029
|
+
firehoseOutage: state.firehoseOutage,
|
|
37030
|
+
lastFirehoseReconnectCloseMeta: state.lastFirehoseReconnectCloseMeta
|
|
37031
|
+
},
|
|
37032
|
+
logFn
|
|
37033
|
+
);
|
|
37034
|
+
} catch {
|
|
37035
|
+
}
|
|
36710
37036
|
const logOpenAsFirehoseReconnect = state.firehoseReconnectAttempt > 0;
|
|
36711
37037
|
state.firehoseReconnectAttempt = 0;
|
|
36712
37038
|
if (!logOpenAsFirehoseReconnect) {
|
|
36713
|
-
|
|
37039
|
+
try {
|
|
37040
|
+
logFn("Connected to preview tunnel (local HTTP proxy and dev logs).");
|
|
37041
|
+
} catch {
|
|
37042
|
+
}
|
|
36714
37043
|
}
|
|
36715
37044
|
},
|
|
36716
37045
|
onClose: (code, reason) => {
|
|
36717
37046
|
if (myGen !== state.firehoseGeneration) return;
|
|
36718
37047
|
state.firehoseHandle = null;
|
|
36719
37048
|
if (state.closedByUser) return;
|
|
36720
|
-
|
|
36721
|
-
|
|
36722
|
-
|
|
36723
|
-
|
|
36724
|
-
|
|
36725
|
-
|
|
36726
|
-
|
|
36727
|
-
|
|
36728
|
-
|
|
36729
|
-
state.firehoseReconnectAttempt
|
|
36730
|
-
);
|
|
36731
|
-
state.firehoseReconnectTimeout = setTimeout(() => {
|
|
36732
|
-
state.firehoseReconnectTimeout = null;
|
|
36733
|
-
if (state.closedByUser) return;
|
|
36734
|
-
const p = state.lastFirehoseParams;
|
|
36735
|
-
if (!p) {
|
|
36736
|
-
if (state.firehoseQuiet.verboseLogs) {
|
|
36737
|
-
logFn(`${PROXY_AND_LOG_SERVICE_LABEL} Reconnect skipped: no stored connection parameters.`);
|
|
36738
|
-
}
|
|
36739
|
-
return;
|
|
36740
|
-
}
|
|
36741
|
-
attachFirehoseAfterIdentified(ctx, p);
|
|
36742
|
-
}, delay2);
|
|
37049
|
+
state.lastFirehoseReconnectCloseMeta = { code, reason };
|
|
37050
|
+
try {
|
|
37051
|
+
beginFirehoseDeferredDisconnect(firehoseCtx(), code, reason, logFn);
|
|
37052
|
+
} catch {
|
|
37053
|
+
}
|
|
37054
|
+
try {
|
|
37055
|
+
scheduleFirehoseRetryAfterDrop({ code, reason });
|
|
37056
|
+
} catch {
|
|
37057
|
+
}
|
|
36743
37058
|
}
|
|
36744
37059
|
});
|
|
36745
37060
|
}
|
|
36746
37061
|
|
|
36747
|
-
// src/
|
|
37062
|
+
// src/connection/create-bridge-identified-handler.ts
|
|
36748
37063
|
function createOnBridgeIdentified(opts) {
|
|
36749
37064
|
const { devServerManager, firehoseServerUrl, workspaceId, state, logFn } = opts;
|
|
36750
37065
|
const firehoseCtx = { state, devServerManager, logFn };
|
|
@@ -36855,7 +37170,7 @@ async function detectLocalAgentTypes() {
|
|
|
36855
37170
|
}
|
|
36856
37171
|
}
|
|
36857
37172
|
|
|
36858
|
-
// src/
|
|
37173
|
+
// src/connection/create-bridge-local-reports.ts
|
|
36859
37174
|
function createSendLocalSkillsReport(getWs, logFn) {
|
|
36860
37175
|
return () => {
|
|
36861
37176
|
setImmediate(() => {
|
|
@@ -36888,14 +37203,14 @@ function createReportAutoDetectedAgents(getWs, logFn) {
|
|
|
36888
37203
|
};
|
|
36889
37204
|
}
|
|
36890
37205
|
|
|
36891
|
-
// src/
|
|
37206
|
+
// src/connection/build-bridge-url.ts
|
|
36892
37207
|
function buildBridgeUrl(apiUrl, workspaceId, authToken) {
|
|
36893
37208
|
const base = apiUrl.startsWith("https") ? apiUrl.replace(/^https/, "wss") : apiUrl.replace(/^http/, "ws");
|
|
36894
37209
|
const params = new URLSearchParams({ workspaceId, token: authToken });
|
|
36895
37210
|
return `${base}/ws/bridge?${params.toString()}`;
|
|
36896
37211
|
}
|
|
36897
37212
|
|
|
36898
|
-
// src/
|
|
37213
|
+
// src/connection/report-git-repos.ts
|
|
36899
37214
|
function reportGitRepos(getWs, log2) {
|
|
36900
37215
|
setImmediate(() => {
|
|
36901
37216
|
discoverGitRepos().then((repos) => {
|
|
@@ -36951,14 +37266,14 @@ function parseApiToBridgeMessage(data, log2) {
|
|
|
36951
37266
|
return data;
|
|
36952
37267
|
}
|
|
36953
37268
|
|
|
36954
|
-
// src/
|
|
37269
|
+
// src/routing/handlers/auth-token.ts
|
|
36955
37270
|
var handleAuthToken = (msg, { log: log2 }) => {
|
|
36956
37271
|
if (typeof msg.token !== "string") return;
|
|
36957
37272
|
log2("Received auth token. Save it for future runs:");
|
|
36958
37273
|
log2(` export BUILDAUTOMATON_AUTH_TOKEN="${msg.token}"`);
|
|
36959
37274
|
};
|
|
36960
37275
|
|
|
36961
|
-
// src/
|
|
37276
|
+
// src/routing/handlers/bridge-identified.ts
|
|
36962
37277
|
var handleBridgeIdentified = (msg, deps) => {
|
|
36963
37278
|
if (typeof msg.bridgeName !== "string") return;
|
|
36964
37279
|
deps.onBridgeIdentified({
|
|
@@ -36994,7 +37309,7 @@ function handleBridgeAgentConfig(msg, { acpManager }) {
|
|
|
36994
37309
|
acpManager.setPreferredAgentType(msg.agents[0].type);
|
|
36995
37310
|
}
|
|
36996
37311
|
|
|
36997
|
-
// src/
|
|
37312
|
+
// src/routing/handlers/agent-config.ts
|
|
36998
37313
|
var handleAgentConfigMessage = (msg, deps) => {
|
|
36999
37314
|
handleBridgeAgentConfig(msg, deps);
|
|
37000
37315
|
};
|
|
@@ -37153,7 +37468,8 @@ function dispatchLocalPrompt(next, deps) {
|
|
|
37153
37468
|
...typeof pl.followUpCatalogPromptId === "string" ? { followUpCatalogPromptId: pl.followUpCatalogPromptId } : {},
|
|
37154
37469
|
...Array.isArray(pl.sessionChangeSummaryFilePaths) ? { sessionChangeSummaryFilePaths: pl.sessionChangeSummaryFilePaths } : {},
|
|
37155
37470
|
...Array.isArray(pl.sessionChangeSummaryFileSnapshots) ? { sessionChangeSummaryFileSnapshots: pl.sessionChangeSummaryFileSnapshots } : {},
|
|
37156
|
-
...typeof pl.agentType === "string" && pl.agentType.trim() ? { agentType: pl.agentType.trim() } : {}
|
|
37471
|
+
...typeof pl.agentType === "string" && pl.agentType.trim() ? { agentType: pl.agentType.trim() } : {},
|
|
37472
|
+
...pl.agentConfig != null && typeof pl.agentConfig === "object" && !Array.isArray(pl.agentConfig) && Object.keys(pl.agentConfig).length > 0 ? { agentConfig: pl.agentConfig } : {}
|
|
37157
37473
|
};
|
|
37158
37474
|
handleBridgePrompt(msg, deps);
|
|
37159
37475
|
}
|
|
@@ -37451,6 +37767,7 @@ function handleBridgePrompt(msg, deps) {
|
|
|
37451
37767
|
const sessionParentPath = typeof msg.sessionParentPath === "string" && msg.sessionParentPath.trim() ? msg.sessionParentPath.trim() : null;
|
|
37452
37768
|
const agentType = typeof msg.agentType === "string" && msg.agentType.trim() ? msg.agentType.trim() : void 0;
|
|
37453
37769
|
const mode = typeof msg.mode === "string" && msg.mode.trim() ? msg.mode.trim() : void 0;
|
|
37770
|
+
const agentConfig = msg.agentConfig != null && typeof msg.agentConfig === "object" && !Array.isArray(msg.agentConfig) ? msg.agentConfig : void 0;
|
|
37454
37771
|
acpManager.logPromptReceivedFromBridge({ agentType, mode });
|
|
37455
37772
|
async function preambleAndPrompt(resolvedCwd) {
|
|
37456
37773
|
const effectiveCwd = resolveSessionParentPathForAgentProcess(resolvedCwd);
|
|
@@ -37486,6 +37803,7 @@ function handleBridgePrompt(msg, deps) {
|
|
|
37486
37803
|
runId,
|
|
37487
37804
|
mode,
|
|
37488
37805
|
agentType,
|
|
37806
|
+
agentConfig,
|
|
37489
37807
|
sessionParentPath: effectiveCwd,
|
|
37490
37808
|
sendResult: sendResult2,
|
|
37491
37809
|
sendSessionUpdate,
|
|
@@ -37502,27 +37820,27 @@ function handleBridgePrompt(msg, deps) {
|
|
|
37502
37820
|
});
|
|
37503
37821
|
}
|
|
37504
37822
|
|
|
37505
|
-
// src/
|
|
37823
|
+
// src/routing/handlers/prompt.ts
|
|
37506
37824
|
var handlePromptMessage = (msg, deps) => {
|
|
37507
37825
|
handleBridgePrompt(msg, deps);
|
|
37508
37826
|
};
|
|
37509
37827
|
|
|
37510
|
-
// src/
|
|
37828
|
+
// src/routing/handlers/prompt-queue-state.ts
|
|
37511
37829
|
var handlePromptQueueStateMessage = (msg, deps) => {
|
|
37512
37830
|
void applyPromptQueueStateFromServer(msg, deps).catch((err) => {
|
|
37513
37831
|
deps.log(`[Queue] applyPromptQueueStateFromServer failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
37514
37832
|
});
|
|
37515
37833
|
};
|
|
37516
37834
|
|
|
37517
|
-
// src/agents/acp/from-bridge/handle-bridge-
|
|
37518
|
-
function
|
|
37835
|
+
// src/agents/acp/from-bridge/handle-bridge-session-request-response.ts
|
|
37836
|
+
function handleBridgeSessionRequestResponse(msg, { acpManager }) {
|
|
37519
37837
|
if (typeof msg.requestId !== "string") return;
|
|
37520
37838
|
acpManager.resolveRequest(msg.requestId, msg.result ?? {});
|
|
37521
37839
|
}
|
|
37522
37840
|
|
|
37523
|
-
// src/
|
|
37524
|
-
var
|
|
37525
|
-
|
|
37841
|
+
// src/routing/handlers/session-request-response.ts
|
|
37842
|
+
var handleSessionRequestResponseMessage = (msg, deps) => {
|
|
37843
|
+
handleBridgeSessionRequestResponse(msg, deps);
|
|
37526
37844
|
};
|
|
37527
37845
|
|
|
37528
37846
|
// src/skills/preview.ts
|
|
@@ -37709,7 +38027,7 @@ function handleSkillCall(msg, socket, log2) {
|
|
|
37709
38027
|
});
|
|
37710
38028
|
}
|
|
37711
38029
|
|
|
37712
|
-
// src/
|
|
38030
|
+
// src/routing/handlers/skill-call.ts
|
|
37713
38031
|
var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
37714
38032
|
const skillId = typeof msg.skillId === "string" ? msg.skillId : "";
|
|
37715
38033
|
const operationId = typeof msg.operationId === "string" ? msg.operationId : "";
|
|
@@ -38051,7 +38369,7 @@ function handleFileBrowserRequest(msg, socket, e2ee) {
|
|
|
38051
38369
|
})();
|
|
38052
38370
|
}
|
|
38053
38371
|
|
|
38054
|
-
// src/
|
|
38372
|
+
// src/routing/handlers/file-browser-messages.ts
|
|
38055
38373
|
function handleFileBrowserRequestMessage(msg, { getWs, e2ee }) {
|
|
38056
38374
|
if (typeof msg.id !== "string" || typeof msg.path !== "string") return;
|
|
38057
38375
|
const socket = getWs();
|
|
@@ -38069,7 +38387,7 @@ function handleFileBrowserSearchMessage(msg, { getWs, e2ee }) {
|
|
|
38069
38387
|
handleFileBrowserSearch(msg, socket, e2ee);
|
|
38070
38388
|
}
|
|
38071
38389
|
|
|
38072
|
-
// src/
|
|
38390
|
+
// src/routing/handlers/skill-layout-request.ts
|
|
38073
38391
|
function handleSkillLayoutRequest(msg, deps) {
|
|
38074
38392
|
const socket = deps.getWs();
|
|
38075
38393
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
@@ -38115,7 +38433,7 @@ function installRemoteSkills(cwd, targetDir, items) {
|
|
|
38115
38433
|
}
|
|
38116
38434
|
}
|
|
38117
38435
|
|
|
38118
|
-
// src/
|
|
38436
|
+
// src/routing/handlers/install-skills.ts
|
|
38119
38437
|
var handleInstallSkillsMessage = (msg, deps) => {
|
|
38120
38438
|
const socket = deps.getWs();
|
|
38121
38439
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
@@ -38136,12 +38454,12 @@ var handleInstallSkillsMessage = (msg, deps) => {
|
|
|
38136
38454
|
}
|
|
38137
38455
|
};
|
|
38138
38456
|
|
|
38139
|
-
// src/
|
|
38457
|
+
// src/routing/handlers/refresh-local-skills.ts
|
|
38140
38458
|
var handleRefreshLocalSkills = (_msg, deps) => {
|
|
38141
38459
|
deps.sendLocalSkillsReport?.();
|
|
38142
38460
|
};
|
|
38143
38461
|
|
|
38144
|
-
// src/
|
|
38462
|
+
// src/routing/handlers/session-git-request.ts
|
|
38145
38463
|
function sendResult(ws, id, payload, e2ee, encryptedFields = []) {
|
|
38146
38464
|
if (!ws) return;
|
|
38147
38465
|
const message = { type: "session_git_result", id, ...payload };
|
|
@@ -38227,7 +38545,7 @@ var handleSessionGitRequestMessage = (msg, deps) => {
|
|
|
38227
38545
|
})();
|
|
38228
38546
|
};
|
|
38229
38547
|
|
|
38230
|
-
// src/
|
|
38548
|
+
// src/routing/handlers/rename-session-branch.ts
|
|
38231
38549
|
var handleRenameSessionBranchMessage = (msg, deps) => {
|
|
38232
38550
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
38233
38551
|
const newBranch = typeof msg.newBranch === "string" ? msg.newBranch : "";
|
|
@@ -38235,21 +38553,21 @@ var handleRenameSessionBranchMessage = (msg, deps) => {
|
|
|
38235
38553
|
void deps.sessionWorktreeManager.renameSessionBranch(sessionId, newBranch);
|
|
38236
38554
|
};
|
|
38237
38555
|
|
|
38238
|
-
// src/
|
|
38556
|
+
// src/routing/handlers/session-archived.ts
|
|
38239
38557
|
var handleSessionArchivedMessage = (msg, deps) => {
|
|
38240
38558
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
38241
38559
|
if (!sessionId) return;
|
|
38242
38560
|
void deps.sessionWorktreeManager.removeSessionWorktrees(sessionId);
|
|
38243
38561
|
};
|
|
38244
38562
|
|
|
38245
|
-
// src/
|
|
38563
|
+
// src/routing/handlers/session-discarded.ts
|
|
38246
38564
|
var handleSessionDiscardedMessage = (msg, deps) => {
|
|
38247
38565
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
38248
38566
|
if (!sessionId) return;
|
|
38249
38567
|
void deps.sessionWorktreeManager.removeSessionWorktrees(sessionId);
|
|
38250
38568
|
};
|
|
38251
38569
|
|
|
38252
|
-
// src/
|
|
38570
|
+
// src/routing/handlers/revert-turn-snapshot.ts
|
|
38253
38571
|
import * as fs33 from "node:fs";
|
|
38254
38572
|
var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
38255
38573
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
@@ -38281,7 +38599,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
38281
38599
|
})();
|
|
38282
38600
|
};
|
|
38283
38601
|
|
|
38284
|
-
// src/
|
|
38602
|
+
// src/routing/handlers/dev-server-control.ts
|
|
38285
38603
|
var handleDevServerControl = (msg, deps) => {
|
|
38286
38604
|
let wire;
|
|
38287
38605
|
try {
|
|
@@ -38296,13 +38614,13 @@ var handleDevServerControl = (msg, deps) => {
|
|
|
38296
38614
|
deps.devServerManager?.handleControl(serverId, action);
|
|
38297
38615
|
};
|
|
38298
38616
|
|
|
38299
|
-
// src/
|
|
38617
|
+
// src/routing/handlers/dev-servers-config.ts
|
|
38300
38618
|
var handleDevServersConfig = (msg, deps) => {
|
|
38301
38619
|
const devServers = msg.devServers;
|
|
38302
38620
|
deps.devServerManager?.applyConfig(devServers ?? []);
|
|
38303
38621
|
};
|
|
38304
38622
|
|
|
38305
|
-
// src/
|
|
38623
|
+
// src/routing/dispatch-bridge-message.ts
|
|
38306
38624
|
function dispatchBridgeMessage(msg, deps) {
|
|
38307
38625
|
switch (msg.type) {
|
|
38308
38626
|
case "auth_token":
|
|
@@ -38342,7 +38660,7 @@ function dispatchBridgeMessage(msg, deps) {
|
|
|
38342
38660
|
handleRevertTurnSnapshotMessage(msg, deps);
|
|
38343
38661
|
break;
|
|
38344
38662
|
case "cursor_request_response":
|
|
38345
|
-
|
|
38663
|
+
handleSessionRequestResponseMessage(msg, deps);
|
|
38346
38664
|
break;
|
|
38347
38665
|
case "skill_call":
|
|
38348
38666
|
handleSkillCallMessage(msg, deps);
|
|
@@ -38365,7 +38683,7 @@ function dispatchBridgeMessage(msg, deps) {
|
|
|
38365
38683
|
}
|
|
38366
38684
|
}
|
|
38367
38685
|
|
|
38368
|
-
// src/
|
|
38686
|
+
// src/routing/handle-bridge-message.ts
|
|
38369
38687
|
function handleBridgeMessage(data, deps) {
|
|
38370
38688
|
if (!deps.getWs()) return;
|
|
38371
38689
|
const msg = parseApiToBridgeMessage(data, deps.log);
|
|
@@ -38402,7 +38720,7 @@ async function refreshBridgeTokens(params) {
|
|
|
38402
38720
|
}
|
|
38403
38721
|
}
|
|
38404
38722
|
|
|
38405
|
-
// src/
|
|
38723
|
+
// src/connection/main-bridge-ws-lifecycle.ts
|
|
38406
38724
|
function createMainBridgeWebSocketLifecycle(params) {
|
|
38407
38725
|
const {
|
|
38408
38726
|
state,
|
|
@@ -38448,13 +38766,26 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
38448
38766
|
}
|
|
38449
38767
|
}
|
|
38450
38768
|
function handleClose(code, reason) {
|
|
38451
|
-
|
|
38452
|
-
|
|
38453
|
-
|
|
38454
|
-
|
|
38455
|
-
|
|
38456
|
-
|
|
38457
|
-
|
|
38769
|
+
try {
|
|
38770
|
+
const was = state.currentWs;
|
|
38771
|
+
state.currentWs = null;
|
|
38772
|
+
if (was) was.removeAllListeners();
|
|
38773
|
+
const willReconnect = !state.closedByUser;
|
|
38774
|
+
beginMainBridgeDeferredDisconnect(state, code, reason, logFn, willReconnect);
|
|
38775
|
+
if (willReconnect) {
|
|
38776
|
+
state.lastReconnectCloseMeta = { code, reason };
|
|
38777
|
+
try {
|
|
38778
|
+
scheduleMainBridgeReconnect(state, connect, logFn, { code, reason });
|
|
38779
|
+
} catch {
|
|
38780
|
+
}
|
|
38781
|
+
}
|
|
38782
|
+
} catch {
|
|
38783
|
+
if (!state.closedByUser) {
|
|
38784
|
+
try {
|
|
38785
|
+
scheduleMainBridgeReconnect(state, connect, logFn);
|
|
38786
|
+
} catch {
|
|
38787
|
+
}
|
|
38788
|
+
}
|
|
38458
38789
|
}
|
|
38459
38790
|
}
|
|
38460
38791
|
function connect() {
|
|
@@ -38464,7 +38795,10 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
38464
38795
|
state.reconnectTimeout = null;
|
|
38465
38796
|
}
|
|
38466
38797
|
if (state.reconnectAttempt === 0) {
|
|
38467
|
-
|
|
38798
|
+
try {
|
|
38799
|
+
logFn("Connecting to bridge service\u2026");
|
|
38800
|
+
} catch {
|
|
38801
|
+
}
|
|
38468
38802
|
}
|
|
38469
38803
|
const prev = state.currentWs;
|
|
38470
38804
|
if (prev) {
|
|
@@ -38480,53 +38814,84 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
38480
38814
|
}
|
|
38481
38815
|
state.currentWs = null;
|
|
38482
38816
|
}
|
|
38483
|
-
|
|
38484
|
-
|
|
38485
|
-
|
|
38486
|
-
|
|
38487
|
-
|
|
38488
|
-
|
|
38489
|
-
|
|
38490
|
-
|
|
38491
|
-
|
|
38492
|
-
|
|
38493
|
-
|
|
38494
|
-
|
|
38495
|
-
|
|
38496
|
-
|
|
38497
|
-
|
|
38498
|
-
|
|
38499
|
-
|
|
38500
|
-
|
|
38501
|
-
|
|
38502
|
-
|
|
38503
|
-
|
|
38504
|
-
|
|
38505
|
-
|
|
38506
|
-
|
|
38507
|
-
|
|
38817
|
+
try {
|
|
38818
|
+
const url2 = buildBridgeUrl(apiUrl, workspaceId, tokens.accessToken);
|
|
38819
|
+
state.currentWs = createWsBridge({
|
|
38820
|
+
url: url2,
|
|
38821
|
+
clientPingIntervalMs: CLI_WEBSOCKET_CLIENT_PING_MS,
|
|
38822
|
+
onAuthInvalid: () => {
|
|
38823
|
+
if (authRefreshInFlight) return;
|
|
38824
|
+
void (async () => {
|
|
38825
|
+
authRefreshInFlight = true;
|
|
38826
|
+
try {
|
|
38827
|
+
if (tokens.refreshToken) {
|
|
38828
|
+
const next = await refreshBridgeTokens({
|
|
38829
|
+
apiUrl,
|
|
38830
|
+
workspaceId,
|
|
38831
|
+
refreshToken: tokens.refreshToken
|
|
38832
|
+
});
|
|
38833
|
+
if (next?.token && next.refreshToken) {
|
|
38834
|
+
tokens.accessToken = next.token;
|
|
38835
|
+
tokens.refreshToken = next.refreshToken;
|
|
38836
|
+
persistTokens?.({ token: tokens.accessToken, refreshToken: tokens.refreshToken });
|
|
38837
|
+
try {
|
|
38838
|
+
logFn("[Bridge service] Access token refreshed; reconnecting\u2026");
|
|
38839
|
+
} catch {
|
|
38840
|
+
}
|
|
38841
|
+
state.reconnectAttempt = 0;
|
|
38842
|
+
resetReconnectOutageTracker(state.mainOutage);
|
|
38843
|
+
state.lastReconnectCloseMeta = null;
|
|
38844
|
+
state.logBridgeOpenAsReconnect = true;
|
|
38845
|
+
authRefreshInFlight = false;
|
|
38846
|
+
connect();
|
|
38847
|
+
return;
|
|
38848
|
+
}
|
|
38508
38849
|
}
|
|
38850
|
+
authRefreshInFlight = false;
|
|
38851
|
+
state.reconnectAttempt = 0;
|
|
38852
|
+
resetReconnectOutageTracker(state.mainOutage);
|
|
38853
|
+
state.lastReconnectCloseMeta = null;
|
|
38854
|
+
onAuthInvalid();
|
|
38855
|
+
} catch {
|
|
38856
|
+
authRefreshInFlight = false;
|
|
38857
|
+
state.reconnectAttempt = 0;
|
|
38858
|
+
resetReconnectOutageTracker(state.mainOutage);
|
|
38859
|
+
state.lastReconnectCloseMeta = null;
|
|
38860
|
+
onAuthInvalid();
|
|
38509
38861
|
}
|
|
38510
|
-
|
|
38511
|
-
|
|
38512
|
-
|
|
38862
|
+
})();
|
|
38863
|
+
},
|
|
38864
|
+
onOpen: handleOpen,
|
|
38865
|
+
onClose: handleClose,
|
|
38866
|
+
onError: (err) => {
|
|
38867
|
+
if (state.mainOutage.startedAt != null) {
|
|
38868
|
+
return;
|
|
38869
|
+
}
|
|
38870
|
+
try {
|
|
38871
|
+
logCliWebSocketError(logFn, "[Bridge service]", err);
|
|
38513
38872
|
} catch {
|
|
38514
|
-
authRefreshInFlight = false;
|
|
38515
|
-
state.reconnectAttempt = 0;
|
|
38516
|
-
onAuthInvalid();
|
|
38517
38873
|
}
|
|
38518
|
-
}
|
|
38519
|
-
|
|
38520
|
-
|
|
38521
|
-
|
|
38522
|
-
|
|
38523
|
-
|
|
38524
|
-
|
|
38874
|
+
},
|
|
38875
|
+
onMessage: (data) => {
|
|
38876
|
+
try {
|
|
38877
|
+
handleBridgeMessage(data, messageDeps);
|
|
38878
|
+
} catch {
|
|
38879
|
+
}
|
|
38880
|
+
}
|
|
38881
|
+
});
|
|
38882
|
+
} catch {
|
|
38883
|
+
if (!state.closedByUser && state.currentWs == null) {
|
|
38884
|
+
try {
|
|
38885
|
+
scheduleMainBridgeReconnect(state, connect, logFn);
|
|
38886
|
+
} catch {
|
|
38887
|
+
}
|
|
38888
|
+
}
|
|
38889
|
+
}
|
|
38525
38890
|
}
|
|
38526
38891
|
return { connect };
|
|
38527
38892
|
}
|
|
38528
38893
|
|
|
38529
|
-
// src/
|
|
38894
|
+
// src/connection/create-bridge-connection.ts
|
|
38530
38895
|
async function createBridgeConnection(options) {
|
|
38531
38896
|
const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
|
|
38532
38897
|
const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
|
|
@@ -38538,16 +38903,20 @@ async function createBridgeConnection(options) {
|
|
|
38538
38903
|
const state = {
|
|
38539
38904
|
closedByUser: false,
|
|
38540
38905
|
reconnectAttempt: 0,
|
|
38906
|
+
lastReconnectCloseMeta: null,
|
|
38541
38907
|
logBridgeOpenAsReconnect: false,
|
|
38542
38908
|
reconnectTimeout: null,
|
|
38543
38909
|
currentWs: null,
|
|
38544
38910
|
mainQuiet: createEmptyReconnectQuietSlot(),
|
|
38911
|
+
mainOutage: createEmptyReconnectOutageTracker(),
|
|
38545
38912
|
firehoseHandle: null,
|
|
38546
38913
|
lastFirehoseParams: null,
|
|
38547
38914
|
firehoseReconnectTimeout: null,
|
|
38548
38915
|
firehoseReconnectAttempt: 0,
|
|
38549
38916
|
firehoseGeneration: 0,
|
|
38550
|
-
firehoseQuiet: createEmptyReconnectQuietSlot()
|
|
38917
|
+
firehoseQuiet: createEmptyReconnectQuietSlot(),
|
|
38918
|
+
firehoseOutage: createEmptyReconnectOutageTracker(),
|
|
38919
|
+
lastFirehoseReconnectCloseMeta: null
|
|
38551
38920
|
};
|
|
38552
38921
|
const worktreesRootPath = options.worktreesRootPath ?? defaultWorktreesRootPath();
|
|
38553
38922
|
const sessionWorktreeManager = new SessionWorktreeManager({
|
|
@@ -38809,6 +39178,9 @@ function colorize(color, message) {
|
|
|
38809
39178
|
return `${color}${message}${RESET}`;
|
|
38810
39179
|
}
|
|
38811
39180
|
async function runCliAction(program2, opts) {
|
|
39181
|
+
const trace = opts.trace === true;
|
|
39182
|
+
const debug2 = opts.debug === true || trace;
|
|
39183
|
+
setCliLogVerbosity(trace ? "trace" : debug2 ? "debug" : "info");
|
|
38812
39184
|
const positionalUrl = program2.args?.[0];
|
|
38813
39185
|
const urlFromPositional = typeof positionalUrl === "string" && /^https?:\/\//i.test(positionalUrl) ? positionalUrl : void 0;
|
|
38814
39186
|
const apiUrlFromCli = opts.apiUrl ?? urlFromPositional;
|
|
@@ -38900,7 +39272,7 @@ async function main() {
|
|
|
38900
39272
|
"--e2ee-certificates-dir <path>",
|
|
38901
39273
|
"Directory to load or generate E2EE keys for sessions, files, and logs",
|
|
38902
39274
|
process.env.BUILDAUTOMATON_E2EE_CERTIFICATES_DIR
|
|
38903
|
-
).option("--no-config", "Ignore saved config at ~/.buildautomaton/config.json").action(async (opts) => runCliAction(program2, opts));
|
|
39275
|
+
).option("--no-config", "Ignore saved config at ~/.buildautomaton/config.json").option("--debug", "Print debug-level messages from the CLI").option("--trace", "Print trace-level messages (e.g. git subprocess output); implies --debug").action(async (opts) => runCliAction(program2, opts));
|
|
38904
39276
|
await program2.parseAsync(process.argv);
|
|
38905
39277
|
}
|
|
38906
39278
|
main().catch((err) => {
|