@buildautomaton/cli 0.1.27 → 0.1.28
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 +138 -6
- package/dist/cli.js.map +4 -4
- package/dist/index.js +138 -6
- 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.28".length > 0 ? "0.1.28" : "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";
|
|
@@ -25638,6 +25638,12 @@ function sendWsMessage(ws, payload) {
|
|
|
25638
25638
|
}
|
|
25639
25639
|
}
|
|
25640
25640
|
|
|
25641
|
+
// src/connection/heartbeat/constants.ts
|
|
25642
|
+
var BRIDGE_APP_HEARTBEAT_INTERVAL_MS = 1e4;
|
|
25643
|
+
var BRIDGE_HEARTBEAT_SEQ_MAX = 2147483646;
|
|
25644
|
+
var BRIDGE_HEARTBEAT_MISSED_ACKS_BEFORE_RECONNECT = 4;
|
|
25645
|
+
var BRIDGE_HEARTBEAT_RTT_SAMPLE_MAX = 5;
|
|
25646
|
+
|
|
25641
25647
|
// ../../node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
|
|
25642
25648
|
import process7 from "node:process";
|
|
25643
25649
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
@@ -26616,14 +26622,18 @@ function runPendingAuth(options) {
|
|
|
26616
26622
|
}
|
|
26617
26623
|
function connect() {
|
|
26618
26624
|
const url2 = buildPendingBridgeUrl(apiUrl, connectionId);
|
|
26625
|
+
let pendingHbSeq = -1;
|
|
26619
26626
|
ws = createWsBridge({
|
|
26620
26627
|
url: url2,
|
|
26621
26628
|
onOpen: () => {
|
|
26622
26629
|
clearQuietOnOpen();
|
|
26630
|
+
pendingHbSeq = -1;
|
|
26623
26631
|
sendWsMessage(ws, { type: "identify", role: "cli", cliVersion: CLI_VERSION });
|
|
26624
26632
|
keepaliveInterval = setInterval(() => {
|
|
26625
26633
|
if (resolved || !ws || ws.readyState !== 1) return;
|
|
26626
|
-
|
|
26634
|
+
pendingHbSeq = pendingHbSeq >= BRIDGE_HEARTBEAT_SEQ_MAX ? 0 : pendingHbSeq + 1;
|
|
26635
|
+
const hb = { t: "h", s: pendingHbSeq };
|
|
26636
|
+
sendWsMessage(ws, hb);
|
|
26627
26637
|
}, PENDING_KEEPALIVE_MS);
|
|
26628
26638
|
if (browserFallback) {
|
|
26629
26639
|
clearTimeout(browserFallback);
|
|
@@ -37782,6 +37792,7 @@ function reportGitRepos(getWs, log2) {
|
|
|
37782
37792
|
var API_TO_BRIDGE_MESSAGE_TYPES = [
|
|
37783
37793
|
"auth_token",
|
|
37784
37794
|
"bridge_identified",
|
|
37795
|
+
"ha",
|
|
37785
37796
|
"dev_servers_config",
|
|
37786
37797
|
"server_control",
|
|
37787
37798
|
"agent_config",
|
|
@@ -37810,6 +37821,10 @@ function parseApiToBridgeMessage(data, log2) {
|
|
|
37810
37821
|
}
|
|
37811
37822
|
return null;
|
|
37812
37823
|
}
|
|
37824
|
+
if (t === "ha") {
|
|
37825
|
+
const s = data.s;
|
|
37826
|
+
if (typeof s !== "number" || !Number.isFinite(s)) return null;
|
|
37827
|
+
}
|
|
37813
37828
|
return data;
|
|
37814
37829
|
}
|
|
37815
37830
|
|
|
@@ -37850,6 +37865,13 @@ var handleBridgeIdentified = (msg, deps) => {
|
|
|
37850
37865
|
});
|
|
37851
37866
|
};
|
|
37852
37867
|
|
|
37868
|
+
// src/connection/heartbeat/ack.ts
|
|
37869
|
+
var handleBridgeHeartbeatAck = (msg, deps) => {
|
|
37870
|
+
const raw = msg.s;
|
|
37871
|
+
if (typeof raw !== "number" || !Number.isFinite(raw)) return;
|
|
37872
|
+
deps.onBridgeHeartbeatAck?.(Math.trunc(raw));
|
|
37873
|
+
};
|
|
37874
|
+
|
|
37853
37875
|
// src/agents/acp/from-bridge/handle-bridge-agent-config.ts
|
|
37854
37876
|
function handleBridgeAgentConfig(msg, { acpManager }) {
|
|
37855
37877
|
if (!Array.isArray(msg.agents) || msg.agents.length === 0) return;
|
|
@@ -39193,6 +39215,9 @@ function dispatchBridgeMessage(msg, deps) {
|
|
|
39193
39215
|
case "bridge_identified":
|
|
39194
39216
|
handleBridgeIdentified(msg, deps);
|
|
39195
39217
|
break;
|
|
39218
|
+
case "ha":
|
|
39219
|
+
handleBridgeHeartbeatAck(msg, deps);
|
|
39220
|
+
break;
|
|
39196
39221
|
case "dev_servers_config":
|
|
39197
39222
|
handleDevServersConfig(msg, deps);
|
|
39198
39223
|
break;
|
|
@@ -39248,9 +39273,17 @@ function dispatchBridgeMessage(msg, deps) {
|
|
|
39248
39273
|
}
|
|
39249
39274
|
|
|
39250
39275
|
// src/routing/handle-bridge-message.ts
|
|
39276
|
+
function normalizeInboundBridgeWebSocketJson(data) {
|
|
39277
|
+
if (data === null || typeof data !== "object" || Array.isArray(data)) return data;
|
|
39278
|
+
const o = data;
|
|
39279
|
+
if (o.t === "ha" && typeof o.s === "number" && Number.isFinite(o.s)) {
|
|
39280
|
+
return { type: "ha", s: Math.trunc(o.s) };
|
|
39281
|
+
}
|
|
39282
|
+
return data;
|
|
39283
|
+
}
|
|
39251
39284
|
function handleBridgeMessage(data, deps) {
|
|
39252
39285
|
if (!deps.getWs()) return;
|
|
39253
|
-
const msg = parseApiToBridgeMessage(data, deps.log);
|
|
39286
|
+
const msg = parseApiToBridgeMessage(normalizeInboundBridgeWebSocketJson(data), deps.log);
|
|
39254
39287
|
if (!msg) return;
|
|
39255
39288
|
setImmediate(() => {
|
|
39256
39289
|
dispatchBridgeMessage(msg, deps);
|
|
@@ -39298,7 +39331,8 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
39298
39331
|
persistTokens,
|
|
39299
39332
|
onAuthInvalid,
|
|
39300
39333
|
e2ee,
|
|
39301
|
-
identifyReportedPaths
|
|
39334
|
+
identifyReportedPaths,
|
|
39335
|
+
bridgeHeartbeat
|
|
39302
39336
|
} = params;
|
|
39303
39337
|
let authRefreshInFlight = false;
|
|
39304
39338
|
function handleOpen() {
|
|
@@ -39330,6 +39364,7 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
39330
39364
|
}
|
|
39331
39365
|
}
|
|
39332
39366
|
function handleClose(code, reason) {
|
|
39367
|
+
bridgeHeartbeat?.stop();
|
|
39333
39368
|
try {
|
|
39334
39369
|
const was = state.currentWs;
|
|
39335
39370
|
state.currentWs = null;
|
|
@@ -39364,6 +39399,7 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
39364
39399
|
} catch {
|
|
39365
39400
|
}
|
|
39366
39401
|
}
|
|
39402
|
+
bridgeHeartbeat?.stop();
|
|
39367
39403
|
const prev = state.currentWs;
|
|
39368
39404
|
if (prev) {
|
|
39369
39405
|
prev.removeAllListeners();
|
|
@@ -39455,6 +39491,92 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
39455
39491
|
return { connect };
|
|
39456
39492
|
}
|
|
39457
39493
|
|
|
39494
|
+
// src/connection/heartbeat/controller.ts
|
|
39495
|
+
function meanRttMs(samples) {
|
|
39496
|
+
if (samples.length === 0) return void 0;
|
|
39497
|
+
let sum = 0;
|
|
39498
|
+
for (const x of samples) sum += x;
|
|
39499
|
+
return sum / samples.length;
|
|
39500
|
+
}
|
|
39501
|
+
function createBridgeHeartbeatController(params) {
|
|
39502
|
+
const { getWs, log: log2 } = params;
|
|
39503
|
+
let interval = null;
|
|
39504
|
+
let seqCursor = -1;
|
|
39505
|
+
let awaitingSeq = null;
|
|
39506
|
+
let sentAtMs = 0;
|
|
39507
|
+
let missed = 0;
|
|
39508
|
+
const rttSamples = [];
|
|
39509
|
+
function clearTimer() {
|
|
39510
|
+
if (interval != null) {
|
|
39511
|
+
clearInterval(interval);
|
|
39512
|
+
interval = null;
|
|
39513
|
+
}
|
|
39514
|
+
}
|
|
39515
|
+
function nextSeq() {
|
|
39516
|
+
seqCursor = seqCursor >= BRIDGE_HEARTBEAT_SEQ_MAX ? 0 : seqCursor + 1;
|
|
39517
|
+
return seqCursor;
|
|
39518
|
+
}
|
|
39519
|
+
function tick() {
|
|
39520
|
+
const ws = getWs();
|
|
39521
|
+
if (!ws || ws.readyState !== wrapper_default.OPEN) return;
|
|
39522
|
+
if (awaitingSeq !== null) {
|
|
39523
|
+
missed++;
|
|
39524
|
+
if (missed >= BRIDGE_HEARTBEAT_MISSED_ACKS_BEFORE_RECONNECT) {
|
|
39525
|
+
try {
|
|
39526
|
+
log2("[Bridge service] Heartbeat missed repeatedly; reconnecting\u2026");
|
|
39527
|
+
} catch {
|
|
39528
|
+
}
|
|
39529
|
+
clearTimer();
|
|
39530
|
+
awaitingSeq = null;
|
|
39531
|
+
missed = 0;
|
|
39532
|
+
rttSamples.length = 0;
|
|
39533
|
+
safeCloseWebSocket(ws);
|
|
39534
|
+
return;
|
|
39535
|
+
}
|
|
39536
|
+
}
|
|
39537
|
+
const seq = nextSeq();
|
|
39538
|
+
const mean = meanRttMs(rttSamples);
|
|
39539
|
+
const payload = mean !== void 0 && Number.isFinite(mean) ? { t: "h", s: seq, m: Math.round(mean) } : { t: "h", s: seq };
|
|
39540
|
+
sendWsMessage(ws, payload);
|
|
39541
|
+
awaitingSeq = seq;
|
|
39542
|
+
sentAtMs = Date.now();
|
|
39543
|
+
}
|
|
39544
|
+
return {
|
|
39545
|
+
start() {
|
|
39546
|
+
clearTimer();
|
|
39547
|
+
awaitingSeq = null;
|
|
39548
|
+
missed = 0;
|
|
39549
|
+
seqCursor = -1;
|
|
39550
|
+
rttSamples.length = 0;
|
|
39551
|
+
interval = setInterval(tick, BRIDGE_APP_HEARTBEAT_INTERVAL_MS);
|
|
39552
|
+
},
|
|
39553
|
+
stop() {
|
|
39554
|
+
clearTimer();
|
|
39555
|
+
awaitingSeq = null;
|
|
39556
|
+
missed = 0;
|
|
39557
|
+
rttSamples.length = 0;
|
|
39558
|
+
},
|
|
39559
|
+
onAck(seq) {
|
|
39560
|
+
if (awaitingSeq === null) return;
|
|
39561
|
+
if (!Number.isFinite(seq)) return;
|
|
39562
|
+
const ack = Math.trunc(seq);
|
|
39563
|
+
const pending = awaitingSeq;
|
|
39564
|
+
if (ack < pending) return;
|
|
39565
|
+
if (ack === pending) {
|
|
39566
|
+
const rtt = Date.now() - sentAtMs;
|
|
39567
|
+
if (Number.isFinite(rtt) && rtt >= 0 && rtt < 6e5) {
|
|
39568
|
+
rttSamples.push(rtt);
|
|
39569
|
+
if (rttSamples.length > BRIDGE_HEARTBEAT_RTT_SAMPLE_MAX) {
|
|
39570
|
+
rttSamples.splice(0, rttSamples.length - BRIDGE_HEARTBEAT_RTT_SAMPLE_MAX);
|
|
39571
|
+
}
|
|
39572
|
+
}
|
|
39573
|
+
}
|
|
39574
|
+
awaitingSeq = null;
|
|
39575
|
+
missed = 0;
|
|
39576
|
+
}
|
|
39577
|
+
};
|
|
39578
|
+
}
|
|
39579
|
+
|
|
39458
39580
|
// src/connection/create-bridge-connection.ts
|
|
39459
39581
|
async function createBridgeConnection(options) {
|
|
39460
39582
|
const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
|
|
@@ -39494,13 +39616,18 @@ async function createBridgeConnection(options) {
|
|
|
39494
39616
|
}
|
|
39495
39617
|
const e2ee = options.e2eCertificate ? createCliE2eeRuntime(options.e2eCertificate) : void 0;
|
|
39496
39618
|
const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeRoot, e2ee });
|
|
39497
|
-
const
|
|
39619
|
+
const bridgeHeartbeat = createBridgeHeartbeatController({ getWs, log: logFn });
|
|
39620
|
+
const baseOnBridgeIdentified = createOnBridgeIdentified({
|
|
39498
39621
|
devServerManager,
|
|
39499
39622
|
firehoseServerUrl,
|
|
39500
39623
|
workspaceId,
|
|
39501
39624
|
state,
|
|
39502
39625
|
logFn
|
|
39503
39626
|
});
|
|
39627
|
+
const onBridgeIdentified = (msg) => {
|
|
39628
|
+
baseOnBridgeIdentified(msg);
|
|
39629
|
+
bridgeHeartbeat.start();
|
|
39630
|
+
};
|
|
39504
39631
|
const sendLocalSkillsReport = createSendLocalSkillsReport(getWs, logFn);
|
|
39505
39632
|
const reportAutoDetectedAgents = createReportAutoDetectedAgents(getWs, logFn);
|
|
39506
39633
|
const messageDeps = {
|
|
@@ -39509,6 +39636,9 @@ async function createBridgeConnection(options) {
|
|
|
39509
39636
|
acpManager,
|
|
39510
39637
|
sessionWorktreeManager,
|
|
39511
39638
|
onBridgeIdentified,
|
|
39639
|
+
onBridgeHeartbeatAck: (seq) => {
|
|
39640
|
+
bridgeHeartbeat.onAck(seq);
|
|
39641
|
+
},
|
|
39512
39642
|
sendLocalSkillsReport,
|
|
39513
39643
|
reportAutoDetectedAgents,
|
|
39514
39644
|
devServerManager,
|
|
@@ -39532,13 +39662,15 @@ async function createBridgeConnection(options) {
|
|
|
39532
39662
|
persistTokens,
|
|
39533
39663
|
onAuthInvalid,
|
|
39534
39664
|
e2ee,
|
|
39535
|
-
identifyReportedPaths
|
|
39665
|
+
identifyReportedPaths,
|
|
39666
|
+
bridgeHeartbeat
|
|
39536
39667
|
});
|
|
39537
39668
|
connect();
|
|
39538
39669
|
const stopFileIndexWatcher = startFileIndexWatcher(getBridgeRoot());
|
|
39539
39670
|
return {
|
|
39540
39671
|
close: async () => {
|
|
39541
39672
|
stopFileIndexWatcher();
|
|
39673
|
+
bridgeHeartbeat.stop();
|
|
39542
39674
|
await closeBridgeConnection(state, acpManager, devServerManager, logFn);
|
|
39543
39675
|
}
|
|
39544
39676
|
};
|