@buildautomaton/cli 0.1.15 → 0.1.16
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/README.md +4 -4
- package/dist/cli.js +1013 -541
- package/dist/cli.js.map +4 -4
- package/dist/index.js +418 -148
- package/dist/index.js.map +4 -4
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -973,8 +973,8 @@ var require_command = __commonJS({
|
|
|
973
973
|
"../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/lib/command.js"(exports) {
|
|
974
974
|
var EventEmitter2 = __require("node:events").EventEmitter;
|
|
975
975
|
var childProcess2 = __require("node:child_process");
|
|
976
|
-
var
|
|
977
|
-
var
|
|
976
|
+
var path34 = __require("node:path");
|
|
977
|
+
var fs31 = __require("node:fs");
|
|
978
978
|
var process8 = __require("node:process");
|
|
979
979
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
980
980
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1906,11 +1906,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1906
1906
|
let launchWithNode = false;
|
|
1907
1907
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1908
1908
|
function findFile(baseDir, baseName) {
|
|
1909
|
-
const localBin =
|
|
1910
|
-
if (
|
|
1911
|
-
if (sourceExt.includes(
|
|
1909
|
+
const localBin = path34.resolve(baseDir, baseName);
|
|
1910
|
+
if (fs31.existsSync(localBin)) return localBin;
|
|
1911
|
+
if (sourceExt.includes(path34.extname(baseName))) return void 0;
|
|
1912
1912
|
const foundExt = sourceExt.find(
|
|
1913
|
-
(ext) =>
|
|
1913
|
+
(ext) => fs31.existsSync(`${localBin}${ext}`)
|
|
1914
1914
|
);
|
|
1915
1915
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1916
1916
|
return void 0;
|
|
@@ -1922,21 +1922,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1922
1922
|
if (this._scriptPath) {
|
|
1923
1923
|
let resolvedScriptPath;
|
|
1924
1924
|
try {
|
|
1925
|
-
resolvedScriptPath =
|
|
1925
|
+
resolvedScriptPath = fs31.realpathSync(this._scriptPath);
|
|
1926
1926
|
} catch (err) {
|
|
1927
1927
|
resolvedScriptPath = this._scriptPath;
|
|
1928
1928
|
}
|
|
1929
|
-
executableDir =
|
|
1930
|
-
|
|
1929
|
+
executableDir = path34.resolve(
|
|
1930
|
+
path34.dirname(resolvedScriptPath),
|
|
1931
1931
|
executableDir
|
|
1932
1932
|
);
|
|
1933
1933
|
}
|
|
1934
1934
|
if (executableDir) {
|
|
1935
1935
|
let localFile = findFile(executableDir, executableFile);
|
|
1936
1936
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
1937
|
-
const legacyName =
|
|
1937
|
+
const legacyName = path34.basename(
|
|
1938
1938
|
this._scriptPath,
|
|
1939
|
-
|
|
1939
|
+
path34.extname(this._scriptPath)
|
|
1940
1940
|
);
|
|
1941
1941
|
if (legacyName !== this._name) {
|
|
1942
1942
|
localFile = findFile(
|
|
@@ -1947,7 +1947,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1947
1947
|
}
|
|
1948
1948
|
executableFile = localFile || executableFile;
|
|
1949
1949
|
}
|
|
1950
|
-
launchWithNode = sourceExt.includes(
|
|
1950
|
+
launchWithNode = sourceExt.includes(path34.extname(executableFile));
|
|
1951
1951
|
let proc;
|
|
1952
1952
|
if (process8.platform !== "win32") {
|
|
1953
1953
|
if (launchWithNode) {
|
|
@@ -2787,7 +2787,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2787
2787
|
* @return {Command}
|
|
2788
2788
|
*/
|
|
2789
2789
|
nameFromFilename(filename) {
|
|
2790
|
-
this._name =
|
|
2790
|
+
this._name = path34.basename(filename, path34.extname(filename));
|
|
2791
2791
|
return this;
|
|
2792
2792
|
}
|
|
2793
2793
|
/**
|
|
@@ -2801,9 +2801,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2801
2801
|
* @param {string} [path]
|
|
2802
2802
|
* @return {(string|null|Command)}
|
|
2803
2803
|
*/
|
|
2804
|
-
executableDir(
|
|
2805
|
-
if (
|
|
2806
|
-
this._executableDir =
|
|
2804
|
+
executableDir(path35) {
|
|
2805
|
+
if (path35 === void 0) return this._executableDir;
|
|
2806
|
+
this._executableDir = path35;
|
|
2807
2807
|
return this;
|
|
2808
2808
|
}
|
|
2809
2809
|
/**
|
|
@@ -5236,7 +5236,7 @@ var require_websocket = __commonJS({
|
|
|
5236
5236
|
var http = __require("http");
|
|
5237
5237
|
var net = __require("net");
|
|
5238
5238
|
var tls = __require("tls");
|
|
5239
|
-
var { randomBytes, createHash:
|
|
5239
|
+
var { randomBytes: randomBytes3, createHash: createHash3 } = __require("crypto");
|
|
5240
5240
|
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
5241
5241
|
var { URL: URL2 } = __require("url");
|
|
5242
5242
|
var PerMessageDeflate = require_permessage_deflate();
|
|
@@ -5766,7 +5766,7 @@ var require_websocket = __commonJS({
|
|
|
5766
5766
|
}
|
|
5767
5767
|
}
|
|
5768
5768
|
const defaultPort = isSecure ? 443 : 80;
|
|
5769
|
-
const key =
|
|
5769
|
+
const key = randomBytes3(16).toString("base64");
|
|
5770
5770
|
const request = isSecure ? https2.request : http.request;
|
|
5771
5771
|
const protocolSet = /* @__PURE__ */ new Set();
|
|
5772
5772
|
let perMessageDeflate;
|
|
@@ -5896,7 +5896,7 @@ var require_websocket = __commonJS({
|
|
|
5896
5896
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
5897
5897
|
return;
|
|
5898
5898
|
}
|
|
5899
|
-
const digest =
|
|
5899
|
+
const digest = createHash3("sha1").update(key + GUID).digest("base64");
|
|
5900
5900
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
5901
5901
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
5902
5902
|
return;
|
|
@@ -6263,7 +6263,7 @@ var require_websocket_server = __commonJS({
|
|
|
6263
6263
|
var EventEmitter2 = __require("events");
|
|
6264
6264
|
var http = __require("http");
|
|
6265
6265
|
var { Duplex } = __require("stream");
|
|
6266
|
-
var { createHash:
|
|
6266
|
+
var { createHash: createHash3 } = __require("crypto");
|
|
6267
6267
|
var extension = require_extension();
|
|
6268
6268
|
var PerMessageDeflate = require_permessage_deflate();
|
|
6269
6269
|
var subprotocol = require_subprotocol();
|
|
@@ -6564,7 +6564,7 @@ var require_websocket_server = __commonJS({
|
|
|
6564
6564
|
);
|
|
6565
6565
|
}
|
|
6566
6566
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
6567
|
-
const digest =
|
|
6567
|
+
const digest = createHash3("sha1").update(key + GUID).digest("base64");
|
|
6568
6568
|
const headers = [
|
|
6569
6569
|
"HTTP/1.1 101 Switching Protocols",
|
|
6570
6570
|
"Upgrade: websocket",
|
|
@@ -7423,15 +7423,15 @@ var require_src2 = __commonJS({
|
|
|
7423
7423
|
var fs_1 = __require("fs");
|
|
7424
7424
|
var debug_1 = __importDefault(require_src());
|
|
7425
7425
|
var log2 = debug_1.default("@kwsites/file-exists");
|
|
7426
|
-
function check2(
|
|
7427
|
-
log2(`checking %s`,
|
|
7426
|
+
function check2(path34, isFile, isDirectory) {
|
|
7427
|
+
log2(`checking %s`, path34);
|
|
7428
7428
|
try {
|
|
7429
|
-
const
|
|
7430
|
-
if (
|
|
7429
|
+
const stat3 = fs_1.statSync(path34);
|
|
7430
|
+
if (stat3.isFile() && isFile) {
|
|
7431
7431
|
log2(`[OK] path represents a file`);
|
|
7432
7432
|
return true;
|
|
7433
7433
|
}
|
|
7434
|
-
if (
|
|
7434
|
+
if (stat3.isDirectory() && isDirectory) {
|
|
7435
7435
|
log2(`[OK] path represents a directory`);
|
|
7436
7436
|
return true;
|
|
7437
7437
|
}
|
|
@@ -7446,8 +7446,8 @@ var require_src2 = __commonJS({
|
|
|
7446
7446
|
throw e;
|
|
7447
7447
|
}
|
|
7448
7448
|
}
|
|
7449
|
-
function exists2(
|
|
7450
|
-
return check2(
|
|
7449
|
+
function exists2(path34, type = exports.READABLE) {
|
|
7450
|
+
return check2(path34, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
|
|
7451
7451
|
}
|
|
7452
7452
|
exports.exists = exists2;
|
|
7453
7453
|
exports.FILE = 1;
|
|
@@ -7922,8 +7922,8 @@ var init_parseUtil = __esm({
|
|
|
7922
7922
|
init_errors();
|
|
7923
7923
|
init_en();
|
|
7924
7924
|
makeIssue = (params) => {
|
|
7925
|
-
const { data, path:
|
|
7926
|
-
const fullPath = [...
|
|
7925
|
+
const { data, path: path34, errorMaps, issueData } = params;
|
|
7926
|
+
const fullPath = [...path34, ...issueData.path || []];
|
|
7927
7927
|
const fullIssue = {
|
|
7928
7928
|
...issueData,
|
|
7929
7929
|
path: fullPath
|
|
@@ -8231,11 +8231,11 @@ var init_types = __esm({
|
|
|
8231
8231
|
init_parseUtil();
|
|
8232
8232
|
init_util2();
|
|
8233
8233
|
ParseInputLazyPath = class {
|
|
8234
|
-
constructor(parent, value,
|
|
8234
|
+
constructor(parent, value, path34, key) {
|
|
8235
8235
|
this._cachedPath = [];
|
|
8236
8236
|
this.parent = parent;
|
|
8237
8237
|
this.data = value;
|
|
8238
|
-
this._path =
|
|
8238
|
+
this._path = path34;
|
|
8239
8239
|
this._key = key;
|
|
8240
8240
|
}
|
|
8241
8241
|
get path() {
|
|
@@ -11850,10 +11850,10 @@ function assignProp(target, prop, value) {
|
|
|
11850
11850
|
configurable: true
|
|
11851
11851
|
});
|
|
11852
11852
|
}
|
|
11853
|
-
function getElementAtPath(obj,
|
|
11854
|
-
if (!
|
|
11853
|
+
function getElementAtPath(obj, path34) {
|
|
11854
|
+
if (!path34)
|
|
11855
11855
|
return obj;
|
|
11856
|
-
return
|
|
11856
|
+
return path34.reduce((acc, key) => acc?.[key], obj);
|
|
11857
11857
|
}
|
|
11858
11858
|
function promiseAllObject(promisesObj) {
|
|
11859
11859
|
const keys = Object.keys(promisesObj);
|
|
@@ -12102,11 +12102,11 @@ function aborted(x, startIndex = 0) {
|
|
|
12102
12102
|
}
|
|
12103
12103
|
return false;
|
|
12104
12104
|
}
|
|
12105
|
-
function prefixIssues(
|
|
12105
|
+
function prefixIssues(path34, issues) {
|
|
12106
12106
|
return issues.map((iss) => {
|
|
12107
12107
|
var _a2;
|
|
12108
12108
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
12109
|
-
iss.path.unshift(
|
|
12109
|
+
iss.path.unshift(path34);
|
|
12110
12110
|
return iss;
|
|
12111
12111
|
});
|
|
12112
12112
|
}
|
|
@@ -12295,7 +12295,7 @@ function treeifyError(error40, _mapper) {
|
|
|
12295
12295
|
return issue2.message;
|
|
12296
12296
|
};
|
|
12297
12297
|
const result = { errors: [] };
|
|
12298
|
-
const processError = (error41,
|
|
12298
|
+
const processError = (error41, path34 = []) => {
|
|
12299
12299
|
var _a2, _b;
|
|
12300
12300
|
for (const issue2 of error41.issues) {
|
|
12301
12301
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -12305,7 +12305,7 @@ function treeifyError(error40, _mapper) {
|
|
|
12305
12305
|
} else if (issue2.code === "invalid_element") {
|
|
12306
12306
|
processError({ issues: issue2.issues }, issue2.path);
|
|
12307
12307
|
} else {
|
|
12308
|
-
const fullpath = [...
|
|
12308
|
+
const fullpath = [...path34, ...issue2.path];
|
|
12309
12309
|
if (fullpath.length === 0) {
|
|
12310
12310
|
result.errors.push(mapper(issue2));
|
|
12311
12311
|
continue;
|
|
@@ -12335,9 +12335,9 @@ function treeifyError(error40, _mapper) {
|
|
|
12335
12335
|
processError(error40);
|
|
12336
12336
|
return result;
|
|
12337
12337
|
}
|
|
12338
|
-
function toDotPath(
|
|
12338
|
+
function toDotPath(path34) {
|
|
12339
12339
|
const segs = [];
|
|
12340
|
-
for (const seg of
|
|
12340
|
+
for (const seg of path34) {
|
|
12341
12341
|
if (typeof seg === "number")
|
|
12342
12342
|
segs.push(`[${seg}]`);
|
|
12343
12343
|
else if (typeof seg === "symbol")
|
|
@@ -24800,8 +24800,8 @@ var init_acp = __esm({
|
|
|
24800
24800
|
this.#requestHandler = requestHandler;
|
|
24801
24801
|
this.#notificationHandler = notificationHandler;
|
|
24802
24802
|
this.#stream = stream;
|
|
24803
|
-
this.#closedPromise = new Promise((
|
|
24804
|
-
this.#abortController.signal.addEventListener("abort", () =>
|
|
24803
|
+
this.#closedPromise = new Promise((resolve17) => {
|
|
24804
|
+
this.#abortController.signal.addEventListener("abort", () => resolve17());
|
|
24805
24805
|
});
|
|
24806
24806
|
this.#receive();
|
|
24807
24807
|
}
|
|
@@ -24950,8 +24950,8 @@ var init_acp = __esm({
|
|
|
24950
24950
|
}
|
|
24951
24951
|
async sendRequest(method, params) {
|
|
24952
24952
|
const id = this.#nextRequestId++;
|
|
24953
|
-
const responsePromise = new Promise((
|
|
24954
|
-
this.#pendingResponses.set(id, { resolve:
|
|
24953
|
+
const responsePromise = new Promise((resolve17, reject) => {
|
|
24954
|
+
this.#pendingResponses.set(id, { resolve: resolve17, reject });
|
|
24955
24955
|
});
|
|
24956
24956
|
await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
|
|
24957
24957
|
return responsePromise;
|
|
@@ -25046,10 +25046,6 @@ var init_acp = __esm({
|
|
|
25046
25046
|
}
|
|
25047
25047
|
});
|
|
25048
25048
|
|
|
25049
|
-
// src/cli.ts
|
|
25050
|
-
import * as fs29 from "node:fs";
|
|
25051
|
-
import * as path32 from "node:path";
|
|
25052
|
-
|
|
25053
25049
|
// ../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/esm.mjs
|
|
25054
25050
|
var import_index = __toESM(require_commander(), 1);
|
|
25055
25051
|
var {
|
|
@@ -25067,6 +25063,14 @@ var {
|
|
|
25067
25063
|
Help
|
|
25068
25064
|
} = import_index.default;
|
|
25069
25065
|
|
|
25066
|
+
// src/cli/defaults.ts
|
|
25067
|
+
var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
|
|
25068
|
+
var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
|
|
25069
|
+
|
|
25070
|
+
// src/cli/run-cli-action.ts
|
|
25071
|
+
import * as fs30 from "node:fs";
|
|
25072
|
+
import * as path33 from "node:path";
|
|
25073
|
+
|
|
25070
25074
|
// src/config.ts
|
|
25071
25075
|
import fs from "node:fs";
|
|
25072
25076
|
import path from "node:path";
|
|
@@ -25145,15 +25149,291 @@ function clearConfigForApi(apiUrl) {
|
|
|
25145
25149
|
}
|
|
25146
25150
|
}
|
|
25147
25151
|
|
|
25148
|
-
// src/
|
|
25152
|
+
// src/e2e-certificates/certificates.ts
|
|
25153
|
+
import * as fs2 from "node:fs/promises";
|
|
25149
25154
|
import * as path2 from "node:path";
|
|
25155
|
+
|
|
25156
|
+
// ../e2ee/src/constants.ts
|
|
25157
|
+
var E2EE_ALG = "A1";
|
|
25158
|
+
var E2EE_KEY_BYTES = 32;
|
|
25159
|
+
var E2EE_NONCE_BYTES = 12;
|
|
25160
|
+
|
|
25161
|
+
// ../e2ee/src/types.ts
|
|
25162
|
+
function isE2eeEnvelope(value) {
|
|
25163
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
25164
|
+
const o = value;
|
|
25165
|
+
return typeof o.k === "string" && typeof o.n === "string" && typeof o.c === "string";
|
|
25166
|
+
}
|
|
25167
|
+
function isE2eeKeyRecord(value) {
|
|
25168
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
25169
|
+
const o = value;
|
|
25170
|
+
return typeof o.id === "string" && o.id.length > 0 && typeof o.name === "string" && o.name.length > 0 && o.a === E2EE_ALG && typeof o.k === "string" && o.k.length > 0 && typeof o.createdAt === "string" && o.createdAt.length > 0;
|
|
25171
|
+
}
|
|
25172
|
+
|
|
25173
|
+
// ../e2ee/src/encoding.ts
|
|
25174
|
+
function base64UrlEncode(bytes) {
|
|
25175
|
+
let binary = "";
|
|
25176
|
+
for (let i = 0; i < bytes.length; i += 1) binary += String.fromCharCode(bytes[i]);
|
|
25177
|
+
const b64 = btoa(binary);
|
|
25178
|
+
return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
25179
|
+
}
|
|
25180
|
+
function base64UrlDecode(value) {
|
|
25181
|
+
const b64 = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
25182
|
+
const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
|
|
25183
|
+
const binary = atob(padded);
|
|
25184
|
+
const out = new Uint8Array(binary.length);
|
|
25185
|
+
for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i);
|
|
25186
|
+
return out;
|
|
25187
|
+
}
|
|
25188
|
+
|
|
25189
|
+
// ../e2ee/src/pem.ts
|
|
25190
|
+
var E2EE_PEM_LABEL = "BUILD AUTOMATON E2EE KEY";
|
|
25191
|
+
function pemHeaderValue(headers, name) {
|
|
25192
|
+
return headers[name.toLowerCase()];
|
|
25193
|
+
}
|
|
25194
|
+
function encodePemBase64(bytes) {
|
|
25195
|
+
const raw = base64UrlEncode(bytes).replace(/-/g, "+").replace(/_/g, "/");
|
|
25196
|
+
const padded = raw + "=".repeat((4 - raw.length % 4) % 4);
|
|
25197
|
+
return padded.replace(/.{1,64}/g, "$&\n").trimEnd();
|
|
25198
|
+
}
|
|
25199
|
+
function decodePemBase64(value) {
|
|
25200
|
+
const compact = value.replace(/\s+/g, "");
|
|
25201
|
+
const binary = atob(compact);
|
|
25202
|
+
const out = new Uint8Array(binary.length);
|
|
25203
|
+
for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i);
|
|
25204
|
+
return out;
|
|
25205
|
+
}
|
|
25206
|
+
function parseE2eeKeyRecordPem(raw, fallbackName) {
|
|
25207
|
+
const lines = raw.trim().split(/\r?\n/);
|
|
25208
|
+
if (lines[0]?.trim() !== `-----BEGIN ${E2EE_PEM_LABEL}-----`) {
|
|
25209
|
+
throw new Error("The E2EE key file is not a BuildAutomaton PEM key.");
|
|
25210
|
+
}
|
|
25211
|
+
const endIndex = lines.findIndex((line) => line.trim() === `-----END ${E2EE_PEM_LABEL}-----`);
|
|
25212
|
+
if (endIndex < 0) throw new Error("The E2EE key PEM is missing its end marker.");
|
|
25213
|
+
const headers = {};
|
|
25214
|
+
const bodyLines = [];
|
|
25215
|
+
let readingBody = false;
|
|
25216
|
+
for (const line of lines.slice(1, endIndex)) {
|
|
25217
|
+
const trimmed2 = line.trim();
|
|
25218
|
+
if (!trimmed2) {
|
|
25219
|
+
readingBody = true;
|
|
25220
|
+
continue;
|
|
25221
|
+
}
|
|
25222
|
+
const headerMatch = /^([A-Za-z0-9-]+):\s*(.*)$/.exec(trimmed2);
|
|
25223
|
+
if (!readingBody && headerMatch) {
|
|
25224
|
+
headers[headerMatch[1].toLowerCase()] = headerMatch[2].trim();
|
|
25225
|
+
continue;
|
|
25226
|
+
}
|
|
25227
|
+
readingBody = true;
|
|
25228
|
+
bodyLines.push(trimmed2);
|
|
25229
|
+
}
|
|
25230
|
+
const keyBytes = decodePemBase64(bodyLines.join(""));
|
|
25231
|
+
if (keyBytes.byteLength !== E2EE_KEY_BYTES) throw new Error("The E2EE key PEM does not contain a 256-bit key.");
|
|
25232
|
+
const key = {
|
|
25233
|
+
id: pemHeaderValue(headers, "Key-Id") ?? "",
|
|
25234
|
+
name: pemHeaderValue(headers, "Name") ?? fallbackName,
|
|
25235
|
+
a: pemHeaderValue(headers, "Algorithm") ?? E2EE_ALG,
|
|
25236
|
+
k: base64UrlEncode(keyBytes),
|
|
25237
|
+
createdAt: pemHeaderValue(headers, "Created-At") ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
25238
|
+
};
|
|
25239
|
+
if (!isE2eeKeyRecord(key)) throw new Error("The E2EE key PEM has invalid metadata.");
|
|
25240
|
+
return {
|
|
25241
|
+
...key,
|
|
25242
|
+
name: key.name.trim() || fallbackName
|
|
25243
|
+
};
|
|
25244
|
+
}
|
|
25245
|
+
function parseE2eeKeyRecord(raw, fallbackName) {
|
|
25246
|
+
return parseE2eeKeyRecordPem(raw.trim(), fallbackName);
|
|
25247
|
+
}
|
|
25248
|
+
function serializeE2eeKeyRecord(key) {
|
|
25249
|
+
return [
|
|
25250
|
+
`-----BEGIN ${E2EE_PEM_LABEL}-----`,
|
|
25251
|
+
`Key-Id: ${key.id}`,
|
|
25252
|
+
`Name: ${key.name}`,
|
|
25253
|
+
`Algorithm: ${key.a}`,
|
|
25254
|
+
`Created-At: ${key.createdAt}`,
|
|
25255
|
+
"",
|
|
25256
|
+
encodePemBase64(base64UrlDecode(key.k)),
|
|
25257
|
+
`-----END ${E2EE_PEM_LABEL}-----`,
|
|
25258
|
+
""
|
|
25259
|
+
].join("\n");
|
|
25260
|
+
}
|
|
25261
|
+
|
|
25262
|
+
// src/lib/e2ee/cli-e2ee-key.ts
|
|
25263
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
25264
|
+
function createE2eeKeyRecord(name) {
|
|
25265
|
+
const raw = randomBytes(E2EE_KEY_BYTES);
|
|
25266
|
+
const digest = createHash("sha256").update(raw).digest();
|
|
25267
|
+
return {
|
|
25268
|
+
id: base64UrlEncode(digest.subarray(0, 16)),
|
|
25269
|
+
name: name.trim() || "BuildAutomaton E2EE key",
|
|
25270
|
+
a: E2EE_ALG,
|
|
25271
|
+
k: base64UrlEncode(raw),
|
|
25272
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
25273
|
+
};
|
|
25274
|
+
}
|
|
25275
|
+
|
|
25276
|
+
// src/lib/e2ee/cli-e2ee-runtime.ts
|
|
25277
|
+
import { createCipheriv, createDecipheriv, randomBytes as randomBytes2 } from "node:crypto";
|
|
25278
|
+
function nonceFromCounter(prefix, counter) {
|
|
25279
|
+
const nonce = Buffer.alloc(E2EE_NONCE_BYTES);
|
|
25280
|
+
prefix.copy(nonce, 0);
|
|
25281
|
+
nonce.writeBigUInt64BE(counter, 4);
|
|
25282
|
+
return nonce;
|
|
25283
|
+
}
|
|
25284
|
+
function createCliE2eeRuntime(key) {
|
|
25285
|
+
const rawKey = Buffer.from(base64UrlDecode(key.k));
|
|
25286
|
+
const prefix = randomBytes2(4);
|
|
25287
|
+
let counter = 0n;
|
|
25288
|
+
function nextNonce() {
|
|
25289
|
+
counter += 1n;
|
|
25290
|
+
return nonceFromCounter(prefix, counter);
|
|
25291
|
+
}
|
|
25292
|
+
function encryptObject(messageWithoutSensitiveFields, plaintext) {
|
|
25293
|
+
const nonce = nextNonce();
|
|
25294
|
+
const cipher = createCipheriv("aes-256-gcm", rawKey, nonce);
|
|
25295
|
+
const ciphertext = Buffer.concat([cipher.update(JSON.stringify(plaintext), "utf8"), cipher.final()]);
|
|
25296
|
+
const tag = cipher.getAuthTag();
|
|
25297
|
+
return {
|
|
25298
|
+
k: key.id,
|
|
25299
|
+
n: base64UrlEncode(nonce),
|
|
25300
|
+
c: base64UrlEncode(Buffer.concat([ciphertext, tag]))
|
|
25301
|
+
};
|
|
25302
|
+
}
|
|
25303
|
+
return {
|
|
25304
|
+
keyId: key.id,
|
|
25305
|
+
handshake: { k: key.id, a: key.a },
|
|
25306
|
+
encryptFields(message, fields) {
|
|
25307
|
+
const plaintext = {};
|
|
25308
|
+
const stripped = { ...message };
|
|
25309
|
+
let hasPlaintext = false;
|
|
25310
|
+
for (const field of fields) {
|
|
25311
|
+
if (Object.prototype.hasOwnProperty.call(stripped, field) && stripped[field] !== void 0) {
|
|
25312
|
+
plaintext[field] = stripped[field];
|
|
25313
|
+
delete stripped[field];
|
|
25314
|
+
hasPlaintext = true;
|
|
25315
|
+
}
|
|
25316
|
+
}
|
|
25317
|
+
if (!hasPlaintext) return message;
|
|
25318
|
+
stripped.ee = encryptObject(stripped, plaintext);
|
|
25319
|
+
return stripped;
|
|
25320
|
+
},
|
|
25321
|
+
decryptMessage(message) {
|
|
25322
|
+
const envelope = message.ee;
|
|
25323
|
+
if (!isE2eeEnvelope(envelope)) return message;
|
|
25324
|
+
if (envelope.k !== key.id) throw new Error(`E2EE key mismatch: ${envelope.k}`);
|
|
25325
|
+
const sealed = Buffer.from(base64UrlDecode(envelope.c));
|
|
25326
|
+
if (sealed.length < 16) throw new Error("Invalid E2EE payload.");
|
|
25327
|
+
const ciphertext = sealed.subarray(0, sealed.length - 16);
|
|
25328
|
+
const tag = sealed.subarray(sealed.length - 16);
|
|
25329
|
+
const nonce = Buffer.from(base64UrlDecode(envelope.n));
|
|
25330
|
+
const decipher = createDecipheriv("aes-256-gcm", rawKey, nonce);
|
|
25331
|
+
decipher.setAuthTag(tag);
|
|
25332
|
+
const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
25333
|
+
const parsed = JSON.parse(decrypted);
|
|
25334
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
25335
|
+
throw new Error("E2EE payload did not decode to an object.");
|
|
25336
|
+
}
|
|
25337
|
+
const merged = { ...message, ...parsed };
|
|
25338
|
+
delete merged.ee;
|
|
25339
|
+
return merged;
|
|
25340
|
+
}
|
|
25341
|
+
};
|
|
25342
|
+
}
|
|
25343
|
+
|
|
25344
|
+
// src/e2e-certificates/certificates.ts
|
|
25345
|
+
var E2E_CERTIFICATE_ALGORITHM = "A1";
|
|
25346
|
+
var CERTIFICATE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".pem", ".key", ".crt"]);
|
|
25347
|
+
function certificateFromKey({
|
|
25348
|
+
raw,
|
|
25349
|
+
name,
|
|
25350
|
+
createdAt
|
|
25351
|
+
}) {
|
|
25352
|
+
try {
|
|
25353
|
+
const key = parseE2eeKeyRecord(raw, name);
|
|
25354
|
+
return {
|
|
25355
|
+
...key,
|
|
25356
|
+
name: key.name || name,
|
|
25357
|
+
algorithm: E2E_CERTIFICATE_ALGORITHM,
|
|
25358
|
+
pemBundle: serializeE2eeKeyRecord({ ...key, createdAt: key.createdAt || createdAt })
|
|
25359
|
+
};
|
|
25360
|
+
} catch {
|
|
25361
|
+
return void 0;
|
|
25362
|
+
}
|
|
25363
|
+
}
|
|
25364
|
+
function baseNameForCertificate(fileName) {
|
|
25365
|
+
return path2.basename(fileName, path2.extname(fileName)) || "BuildAutomaton E2EE certificate";
|
|
25366
|
+
}
|
|
25367
|
+
async function readCertificateFiles(directory) {
|
|
25368
|
+
let entries;
|
|
25369
|
+
try {
|
|
25370
|
+
entries = await fs2.readdir(directory, { withFileTypes: true });
|
|
25371
|
+
} catch (err) {
|
|
25372
|
+
const nodeErr = err;
|
|
25373
|
+
if (nodeErr.code === "ENOENT") return [];
|
|
25374
|
+
throw err;
|
|
25375
|
+
}
|
|
25376
|
+
const certificates = [];
|
|
25377
|
+
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
25378
|
+
if (!entry.isFile() || !CERTIFICATE_FILE_EXTENSIONS.has(path2.extname(entry.name).toLowerCase())) continue;
|
|
25379
|
+
const filePath = path2.join(directory, entry.name);
|
|
25380
|
+
const raw = await fs2.readFile(filePath, "utf8").catch(() => void 0);
|
|
25381
|
+
if (!raw) continue;
|
|
25382
|
+
const stat3 = await fs2.stat(filePath).catch(() => void 0);
|
|
25383
|
+
const certificate = certificateFromKey({
|
|
25384
|
+
raw,
|
|
25385
|
+
name: baseNameForCertificate(entry.name),
|
|
25386
|
+
createdAt: stat3?.mtime?.toISOString() ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
25387
|
+
});
|
|
25388
|
+
if (certificate) {
|
|
25389
|
+
certificates.push(certificate);
|
|
25390
|
+
}
|
|
25391
|
+
}
|
|
25392
|
+
return certificates;
|
|
25393
|
+
}
|
|
25394
|
+
function createCertificate(directory) {
|
|
25395
|
+
const baseName = path2.basename(directory) || "BuildAutomaton E2EE certificate";
|
|
25396
|
+
const key = createE2eeKeyRecord(baseName);
|
|
25397
|
+
return {
|
|
25398
|
+
...key,
|
|
25399
|
+
algorithm: E2E_CERTIFICATE_ALGORITHM,
|
|
25400
|
+
pemBundle: serializeE2eeKeyRecord(key)
|
|
25401
|
+
};
|
|
25402
|
+
}
|
|
25403
|
+
async function loadOrCreateE2eCertificates(directory) {
|
|
25404
|
+
const resolved = path2.resolve(directory);
|
|
25405
|
+
await fs2.mkdir(resolved, { recursive: true, mode: 448 });
|
|
25406
|
+
const existing = await readCertificateFiles(resolved);
|
|
25407
|
+
if (existing.length > 0) {
|
|
25408
|
+
return {
|
|
25409
|
+
directory: resolved,
|
|
25410
|
+
certificates: existing,
|
|
25411
|
+
activeCertificate: existing[0],
|
|
25412
|
+
generated: false
|
|
25413
|
+
};
|
|
25414
|
+
}
|
|
25415
|
+
const certificate = createCertificate(resolved);
|
|
25416
|
+
const fileName = `buildautomaton-e2ee-key-${certificate.id.slice(0, 12)}.pem`;
|
|
25417
|
+
await fs2.writeFile(path2.join(resolved, fileName), certificate.pemBundle, {
|
|
25418
|
+
mode: 384
|
|
25419
|
+
});
|
|
25420
|
+
return {
|
|
25421
|
+
directory: resolved,
|
|
25422
|
+
certificates: [certificate],
|
|
25423
|
+
activeCertificate: certificate,
|
|
25424
|
+
generated: true
|
|
25425
|
+
};
|
|
25426
|
+
}
|
|
25427
|
+
|
|
25428
|
+
// src/files/cwd/bridge-workspace-directory.ts
|
|
25429
|
+
import * as path3 from "node:path";
|
|
25150
25430
|
var bridgeWorkspaceDirectory = null;
|
|
25151
25431
|
function initBridgeWorkspaceDirectory() {
|
|
25152
|
-
bridgeWorkspaceDirectory =
|
|
25432
|
+
bridgeWorkspaceDirectory = path3.resolve(process.cwd());
|
|
25153
25433
|
}
|
|
25154
25434
|
function getBridgeWorkspaceDirectory() {
|
|
25155
25435
|
if (bridgeWorkspaceDirectory == null) {
|
|
25156
|
-
bridgeWorkspaceDirectory =
|
|
25436
|
+
bridgeWorkspaceDirectory = path3.resolve(process.cwd());
|
|
25157
25437
|
}
|
|
25158
25438
|
return bridgeWorkspaceDirectory;
|
|
25159
25439
|
}
|
|
@@ -25324,30 +25604,30 @@ function sendWsMessage(ws, payload) {
|
|
|
25324
25604
|
// ../../node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
|
|
25325
25605
|
import process7 from "node:process";
|
|
25326
25606
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
25327
|
-
import
|
|
25607
|
+
import path4 from "node:path";
|
|
25328
25608
|
import { fileURLToPath } from "node:url";
|
|
25329
25609
|
import { promisify as promisify5 } from "node:util";
|
|
25330
25610
|
import childProcess from "node:child_process";
|
|
25331
|
-
import
|
|
25611
|
+
import fs7, { constants as fsConstants2 } from "node:fs/promises";
|
|
25332
25612
|
|
|
25333
25613
|
// ../../node_modules/.pnpm/wsl-utils@0.1.0/node_modules/wsl-utils/index.js
|
|
25334
25614
|
import process3 from "node:process";
|
|
25335
|
-
import
|
|
25615
|
+
import fs6, { constants as fsConstants } from "node:fs/promises";
|
|
25336
25616
|
|
|
25337
25617
|
// ../../node_modules/.pnpm/is-wsl@3.1.1/node_modules/is-wsl/index.js
|
|
25338
25618
|
import process2 from "node:process";
|
|
25339
25619
|
import os2 from "node:os";
|
|
25340
|
-
import
|
|
25620
|
+
import fs5 from "node:fs";
|
|
25341
25621
|
|
|
25342
25622
|
// ../../node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
|
|
25343
|
-
import
|
|
25623
|
+
import fs4 from "node:fs";
|
|
25344
25624
|
|
|
25345
25625
|
// ../../node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.js
|
|
25346
|
-
import
|
|
25626
|
+
import fs3 from "node:fs";
|
|
25347
25627
|
var isDockerCached;
|
|
25348
25628
|
function hasDockerEnv() {
|
|
25349
25629
|
try {
|
|
25350
|
-
|
|
25630
|
+
fs3.statSync("/.dockerenv");
|
|
25351
25631
|
return true;
|
|
25352
25632
|
} catch {
|
|
25353
25633
|
return false;
|
|
@@ -25355,7 +25635,7 @@ function hasDockerEnv() {
|
|
|
25355
25635
|
}
|
|
25356
25636
|
function hasDockerCGroup() {
|
|
25357
25637
|
try {
|
|
25358
|
-
return
|
|
25638
|
+
return fs3.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
|
|
25359
25639
|
} catch {
|
|
25360
25640
|
return false;
|
|
25361
25641
|
}
|
|
@@ -25371,7 +25651,7 @@ function isDocker() {
|
|
|
25371
25651
|
var cachedResult;
|
|
25372
25652
|
var hasContainerEnv = () => {
|
|
25373
25653
|
try {
|
|
25374
|
-
|
|
25654
|
+
fs4.statSync("/run/.containerenv");
|
|
25375
25655
|
return true;
|
|
25376
25656
|
} catch {
|
|
25377
25657
|
return false;
|
|
@@ -25396,12 +25676,12 @@ var isWsl = () => {
|
|
|
25396
25676
|
return true;
|
|
25397
25677
|
}
|
|
25398
25678
|
try {
|
|
25399
|
-
if (
|
|
25679
|
+
if (fs5.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft")) {
|
|
25400
25680
|
return !isInsideContainer();
|
|
25401
25681
|
}
|
|
25402
25682
|
} catch {
|
|
25403
25683
|
}
|
|
25404
|
-
if (
|
|
25684
|
+
if (fs5.existsSync("/proc/sys/fs/binfmt_misc/WSLInterop") || fs5.existsSync("/run/WSL")) {
|
|
25405
25685
|
return !isInsideContainer();
|
|
25406
25686
|
}
|
|
25407
25687
|
return false;
|
|
@@ -25419,14 +25699,14 @@ var wslDrivesMountPoint = /* @__PURE__ */ (() => {
|
|
|
25419
25699
|
const configFilePath2 = "/etc/wsl.conf";
|
|
25420
25700
|
let isConfigFileExists = false;
|
|
25421
25701
|
try {
|
|
25422
|
-
await
|
|
25702
|
+
await fs6.access(configFilePath2, fsConstants.F_OK);
|
|
25423
25703
|
isConfigFileExists = true;
|
|
25424
25704
|
} catch {
|
|
25425
25705
|
}
|
|
25426
25706
|
if (!isConfigFileExists) {
|
|
25427
25707
|
return defaultMountPoint;
|
|
25428
25708
|
}
|
|
25429
|
-
const configContent = await
|
|
25709
|
+
const configContent = await fs6.readFile(configFilePath2, { encoding: "utf8" });
|
|
25430
25710
|
const configMountPoint = /(?<!#.*)root\s*=\s*(?<mountPoint>.*)/g.exec(configContent);
|
|
25431
25711
|
if (!configMountPoint) {
|
|
25432
25712
|
return defaultMountPoint;
|
|
@@ -25580,8 +25860,8 @@ async function defaultBrowser2() {
|
|
|
25580
25860
|
|
|
25581
25861
|
// ../../node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
|
|
25582
25862
|
var execFile5 = promisify5(childProcess.execFile);
|
|
25583
|
-
var __dirname =
|
|
25584
|
-
var localXdgOpenPath =
|
|
25863
|
+
var __dirname = path4.dirname(fileURLToPath(import.meta.url));
|
|
25864
|
+
var localXdgOpenPath = path4.join(__dirname, "xdg-open");
|
|
25585
25865
|
var { platform, arch } = process7;
|
|
25586
25866
|
async function getWindowsDefaultBrowserFromWsl() {
|
|
25587
25867
|
const powershellPath = await powerShellPath();
|
|
@@ -25731,7 +26011,7 @@ var baseOpen = async (options) => {
|
|
|
25731
26011
|
const isBundled = !__dirname || __dirname === "/";
|
|
25732
26012
|
let exeLocalXdgOpen = false;
|
|
25733
26013
|
try {
|
|
25734
|
-
await
|
|
26014
|
+
await fs7.access(localXdgOpenPath, fsConstants2.X_OK);
|
|
25735
26015
|
exeLocalXdgOpen = true;
|
|
25736
26016
|
} catch {
|
|
25737
26017
|
}
|
|
@@ -25754,14 +26034,14 @@ var baseOpen = async (options) => {
|
|
|
25754
26034
|
}
|
|
25755
26035
|
const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
|
|
25756
26036
|
if (options.wait) {
|
|
25757
|
-
return new Promise((
|
|
26037
|
+
return new Promise((resolve17, reject) => {
|
|
25758
26038
|
subprocess.once("error", reject);
|
|
25759
26039
|
subprocess.once("close", (exitCode) => {
|
|
25760
26040
|
if (!options.allowNonzeroExitCode && exitCode > 0) {
|
|
25761
26041
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
25762
26042
|
return;
|
|
25763
26043
|
}
|
|
25764
|
-
|
|
26044
|
+
resolve17(subprocess);
|
|
25765
26045
|
});
|
|
25766
26046
|
});
|
|
25767
26047
|
}
|
|
@@ -25845,8 +26125,11 @@ function isLocalApiUrl(apiUrl) {
|
|
|
25845
26125
|
return false;
|
|
25846
26126
|
}
|
|
25847
26127
|
}
|
|
26128
|
+
function appUrlForApiUrl(apiUrl) {
|
|
26129
|
+
return apiUrl && isLocalApiUrl(apiUrl) ? process.env.BUILDAUTOMATON_APP_URL ?? "http://localhost:3000" : process.env.BUILDAUTOMATON_APP_URL ?? "https://app.buildautomaton.com";
|
|
26130
|
+
}
|
|
25848
26131
|
async function openBrowser(connectionId, initialWorkspaceId, preferredBridgeName, apiUrl, logFn = log) {
|
|
25849
|
-
const appUrl =
|
|
26132
|
+
const appUrl = appUrlForApiUrl(apiUrl);
|
|
25850
26133
|
let connectCliUrl = `${appUrl.replace(/\/$/, "")}/bridges/connect?connectionId=${connectionId}`;
|
|
25851
26134
|
if (initialWorkspaceId) {
|
|
25852
26135
|
try {
|
|
@@ -26054,8 +26337,8 @@ function runPendingAuth(options) {
|
|
|
26054
26337
|
let hasOpenedBrowser = false;
|
|
26055
26338
|
let resolved = false;
|
|
26056
26339
|
let resolveAuth;
|
|
26057
|
-
const authPromise = new Promise((
|
|
26058
|
-
resolveAuth =
|
|
26340
|
+
const authPromise = new Promise((resolve17) => {
|
|
26341
|
+
resolveAuth = resolve17;
|
|
26059
26342
|
});
|
|
26060
26343
|
let reconnectAttempt = 0;
|
|
26061
26344
|
const signInQuiet = createEmptyReconnectQuietSlot();
|
|
@@ -26177,7 +26460,7 @@ function runPendingAuth(options) {
|
|
|
26177
26460
|
async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
|
|
26178
26461
|
const say = log2 ?? logImmediate;
|
|
26179
26462
|
say("Cleaning up connections\u2026");
|
|
26180
|
-
await new Promise((
|
|
26463
|
+
await new Promise((resolve17) => setImmediate(resolve17));
|
|
26181
26464
|
state.closedByUser = true;
|
|
26182
26465
|
clearReconnectQuietTimer(state.mainQuiet);
|
|
26183
26466
|
clearReconnectQuietTimer(state.firehoseQuiet);
|
|
@@ -26248,19 +26531,19 @@ function localAgentErrorSuggestsAuth(agentType, errorText) {
|
|
|
26248
26531
|
|
|
26249
26532
|
// src/git/session-git-queue.ts
|
|
26250
26533
|
import { execFile as execFile7 } from "node:child_process";
|
|
26251
|
-
import { readFile, stat } from "node:fs/promises";
|
|
26534
|
+
import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
|
|
26252
26535
|
import { promisify as promisify7 } from "node:util";
|
|
26253
|
-
import * as
|
|
26536
|
+
import * as path7 from "node:path";
|
|
26254
26537
|
|
|
26255
26538
|
// src/git/pre-turn-snapshot.ts
|
|
26256
|
-
import * as
|
|
26257
|
-
import * as
|
|
26539
|
+
import * as fs9 from "node:fs";
|
|
26540
|
+
import * as path6 from "node:path";
|
|
26258
26541
|
import { execFile as execFile6 } from "node:child_process";
|
|
26259
26542
|
import { promisify as promisify6 } from "node:util";
|
|
26260
26543
|
|
|
26261
26544
|
// src/git/discover-repos.ts
|
|
26262
|
-
import * as
|
|
26263
|
-
import * as
|
|
26545
|
+
import * as fs8 from "node:fs";
|
|
26546
|
+
import * as path5 from "node:path";
|
|
26264
26547
|
|
|
26265
26548
|
// ../../node_modules/.pnpm/simple-git@3.32.3/node_modules/simple-git/dist/esm/index.js
|
|
26266
26549
|
var import_file_exists = __toESM(require_dist(), 1);
|
|
@@ -26299,8 +26582,8 @@ function pathspec(...paths) {
|
|
|
26299
26582
|
cache.set(key, paths);
|
|
26300
26583
|
return key;
|
|
26301
26584
|
}
|
|
26302
|
-
function isPathSpec(
|
|
26303
|
-
return
|
|
26585
|
+
function isPathSpec(path34) {
|
|
26586
|
+
return path34 instanceof String && cache.has(path34);
|
|
26304
26587
|
}
|
|
26305
26588
|
function toPaths(pathSpec) {
|
|
26306
26589
|
return cache.get(pathSpec) || [];
|
|
@@ -26389,8 +26672,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
26389
26672
|
function forEachLineWithContent(input, callback) {
|
|
26390
26673
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
26391
26674
|
}
|
|
26392
|
-
function folderExists(
|
|
26393
|
-
return (0, import_file_exists.exists)(
|
|
26675
|
+
function folderExists(path34) {
|
|
26676
|
+
return (0, import_file_exists.exists)(path34, import_file_exists.FOLDER);
|
|
26394
26677
|
}
|
|
26395
26678
|
function append(target, item) {
|
|
26396
26679
|
if (Array.isArray(target)) {
|
|
@@ -26794,8 +27077,8 @@ function checkIsRepoRootTask() {
|
|
|
26794
27077
|
commands,
|
|
26795
27078
|
format: "utf-8",
|
|
26796
27079
|
onError,
|
|
26797
|
-
parser(
|
|
26798
|
-
return /^\.(git)?$/.test(
|
|
27080
|
+
parser(path34) {
|
|
27081
|
+
return /^\.(git)?$/.test(path34.trim());
|
|
26799
27082
|
}
|
|
26800
27083
|
};
|
|
26801
27084
|
}
|
|
@@ -27229,11 +27512,11 @@ function parseGrep(grep) {
|
|
|
27229
27512
|
const paths = /* @__PURE__ */ new Set();
|
|
27230
27513
|
const results = {};
|
|
27231
27514
|
forEachLineWithContent(grep, (input) => {
|
|
27232
|
-
const [
|
|
27233
|
-
paths.add(
|
|
27234
|
-
(results[
|
|
27515
|
+
const [path34, line, preview] = input.split(NULL);
|
|
27516
|
+
paths.add(path34);
|
|
27517
|
+
(results[path34] = results[path34] || []).push({
|
|
27235
27518
|
line: asNumber(line),
|
|
27236
|
-
path:
|
|
27519
|
+
path: path34,
|
|
27237
27520
|
preview
|
|
27238
27521
|
});
|
|
27239
27522
|
});
|
|
@@ -27998,14 +28281,14 @@ var init_hash_object = __esm2({
|
|
|
27998
28281
|
init_task();
|
|
27999
28282
|
}
|
|
28000
28283
|
});
|
|
28001
|
-
function parseInit(bare,
|
|
28284
|
+
function parseInit(bare, path34, text) {
|
|
28002
28285
|
const response = String(text).trim();
|
|
28003
28286
|
let result;
|
|
28004
28287
|
if (result = initResponseRegex.exec(response)) {
|
|
28005
|
-
return new InitSummary(bare,
|
|
28288
|
+
return new InitSummary(bare, path34, false, result[1]);
|
|
28006
28289
|
}
|
|
28007
28290
|
if (result = reInitResponseRegex.exec(response)) {
|
|
28008
|
-
return new InitSummary(bare,
|
|
28291
|
+
return new InitSummary(bare, path34, true, result[1]);
|
|
28009
28292
|
}
|
|
28010
28293
|
let gitDir = "";
|
|
28011
28294
|
const tokens = response.split(" ");
|
|
@@ -28016,7 +28299,7 @@ function parseInit(bare, path33, text) {
|
|
|
28016
28299
|
break;
|
|
28017
28300
|
}
|
|
28018
28301
|
}
|
|
28019
|
-
return new InitSummary(bare,
|
|
28302
|
+
return new InitSummary(bare, path34, /^re/i.test(response), gitDir);
|
|
28020
28303
|
}
|
|
28021
28304
|
var InitSummary;
|
|
28022
28305
|
var initResponseRegex;
|
|
@@ -28025,9 +28308,9 @@ var init_InitSummary = __esm2({
|
|
|
28025
28308
|
"src/lib/responses/InitSummary.ts"() {
|
|
28026
28309
|
"use strict";
|
|
28027
28310
|
InitSummary = class {
|
|
28028
|
-
constructor(bare,
|
|
28311
|
+
constructor(bare, path34, existing, gitDir) {
|
|
28029
28312
|
this.bare = bare;
|
|
28030
|
-
this.path =
|
|
28313
|
+
this.path = path34;
|
|
28031
28314
|
this.existing = existing;
|
|
28032
28315
|
this.gitDir = gitDir;
|
|
28033
28316
|
}
|
|
@@ -28039,7 +28322,7 @@ var init_InitSummary = __esm2({
|
|
|
28039
28322
|
function hasBareCommand(command) {
|
|
28040
28323
|
return command.includes(bareCommand);
|
|
28041
28324
|
}
|
|
28042
|
-
function initTask(bare = false,
|
|
28325
|
+
function initTask(bare = false, path34, customArgs) {
|
|
28043
28326
|
const commands = ["init", ...customArgs];
|
|
28044
28327
|
if (bare && !hasBareCommand(commands)) {
|
|
28045
28328
|
commands.splice(1, 0, bareCommand);
|
|
@@ -28048,7 +28331,7 @@ function initTask(bare = false, path33, customArgs) {
|
|
|
28048
28331
|
commands,
|
|
28049
28332
|
format: "utf-8",
|
|
28050
28333
|
parser(text) {
|
|
28051
|
-
return parseInit(commands.includes("--bare"),
|
|
28334
|
+
return parseInit(commands.includes("--bare"), path34, text);
|
|
28052
28335
|
}
|
|
28053
28336
|
};
|
|
28054
28337
|
}
|
|
@@ -28864,12 +29147,12 @@ var init_FileStatusSummary = __esm2({
|
|
|
28864
29147
|
"use strict";
|
|
28865
29148
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
28866
29149
|
FileStatusSummary = class {
|
|
28867
|
-
constructor(
|
|
28868
|
-
this.path =
|
|
29150
|
+
constructor(path34, index, working_dir) {
|
|
29151
|
+
this.path = path34;
|
|
28869
29152
|
this.index = index;
|
|
28870
29153
|
this.working_dir = working_dir;
|
|
28871
29154
|
if (index === "R" || working_dir === "R") {
|
|
28872
|
-
const detail = fromPathRegex.exec(
|
|
29155
|
+
const detail = fromPathRegex.exec(path34) || [null, path34, path34];
|
|
28873
29156
|
this.from = detail[2] || "";
|
|
28874
29157
|
this.path = detail[1] || "";
|
|
28875
29158
|
}
|
|
@@ -28900,14 +29183,14 @@ function splitLine(result, lineStr) {
|
|
|
28900
29183
|
default:
|
|
28901
29184
|
return;
|
|
28902
29185
|
}
|
|
28903
|
-
function data(index, workingDir,
|
|
29186
|
+
function data(index, workingDir, path34) {
|
|
28904
29187
|
const raw = `${index}${workingDir}`;
|
|
28905
29188
|
const handler = parsers6.get(raw);
|
|
28906
29189
|
if (handler) {
|
|
28907
|
-
handler(result,
|
|
29190
|
+
handler(result, path34);
|
|
28908
29191
|
}
|
|
28909
29192
|
if (raw !== "##" && raw !== "!!") {
|
|
28910
|
-
result.files.push(new FileStatusSummary(
|
|
29193
|
+
result.files.push(new FileStatusSummary(path34, index, workingDir));
|
|
28911
29194
|
}
|
|
28912
29195
|
}
|
|
28913
29196
|
}
|
|
@@ -29216,9 +29499,9 @@ var init_simple_git_api = __esm2({
|
|
|
29216
29499
|
next
|
|
29217
29500
|
);
|
|
29218
29501
|
}
|
|
29219
|
-
hashObject(
|
|
29502
|
+
hashObject(path34, write) {
|
|
29220
29503
|
return this._runTask(
|
|
29221
|
-
hashObjectTask(
|
|
29504
|
+
hashObjectTask(path34, write === true),
|
|
29222
29505
|
trailingFunctionArgument(arguments)
|
|
29223
29506
|
);
|
|
29224
29507
|
}
|
|
@@ -29571,8 +29854,8 @@ var init_branch = __esm2({
|
|
|
29571
29854
|
}
|
|
29572
29855
|
});
|
|
29573
29856
|
function toPath(input) {
|
|
29574
|
-
const
|
|
29575
|
-
return
|
|
29857
|
+
const path34 = input.trim().replace(/^["']|["']$/g, "");
|
|
29858
|
+
return path34 && normalize(path34);
|
|
29576
29859
|
}
|
|
29577
29860
|
var parseCheckIgnore;
|
|
29578
29861
|
var init_CheckIgnore = __esm2({
|
|
@@ -29886,8 +30169,8 @@ __export2(sub_module_exports, {
|
|
|
29886
30169
|
subModuleTask: () => subModuleTask,
|
|
29887
30170
|
updateSubModuleTask: () => updateSubModuleTask
|
|
29888
30171
|
});
|
|
29889
|
-
function addSubModuleTask(repo,
|
|
29890
|
-
return subModuleTask(["add", repo,
|
|
30172
|
+
function addSubModuleTask(repo, path34) {
|
|
30173
|
+
return subModuleTask(["add", repo, path34]);
|
|
29891
30174
|
}
|
|
29892
30175
|
function initSubModuleTask(customArgs) {
|
|
29893
30176
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -30220,8 +30503,8 @@ var require_git = __commonJS2({
|
|
|
30220
30503
|
}
|
|
30221
30504
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
30222
30505
|
};
|
|
30223
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
30224
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
30506
|
+
Git2.prototype.submoduleAdd = function(repo, path34, then) {
|
|
30507
|
+
return this._runTask(addSubModuleTask2(repo, path34), trailingFunctionArgument2(arguments));
|
|
30225
30508
|
};
|
|
30226
30509
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
30227
30510
|
return this._runTask(
|
|
@@ -30847,20 +31130,20 @@ async function isGitRepoDirectory(dirPath) {
|
|
|
30847
31130
|
// src/git/discover-repos.ts
|
|
30848
31131
|
async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
|
|
30849
31132
|
const result = [];
|
|
30850
|
-
const cwdResolved =
|
|
31133
|
+
const cwdResolved = path5.resolve(cwd);
|
|
30851
31134
|
if (await isGitRepoDirectory(cwdResolved)) {
|
|
30852
31135
|
const remoteUrl = await getRemoteOriginUrl(cwdResolved);
|
|
30853
31136
|
result.push({ absolutePath: cwdResolved, remoteUrl });
|
|
30854
31137
|
}
|
|
30855
31138
|
let entries;
|
|
30856
31139
|
try {
|
|
30857
|
-
entries =
|
|
31140
|
+
entries = fs8.readdirSync(cwdResolved, { withFileTypes: true });
|
|
30858
31141
|
} catch {
|
|
30859
31142
|
return result;
|
|
30860
31143
|
}
|
|
30861
31144
|
for (const ent of entries) {
|
|
30862
31145
|
if (!ent.isDirectory()) continue;
|
|
30863
|
-
const childPath =
|
|
31146
|
+
const childPath = path5.join(cwdResolved, ent.name);
|
|
30864
31147
|
if (await isGitRepoDirectory(childPath)) {
|
|
30865
31148
|
const remoteUrl = await getRemoteOriginUrl(childPath);
|
|
30866
31149
|
result.push({ absolutePath: childPath, remoteUrl });
|
|
@@ -30869,22 +31152,22 @@ async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
|
|
|
30869
31152
|
return result;
|
|
30870
31153
|
}
|
|
30871
31154
|
async function discoverGitReposUnderRoot(rootAbs) {
|
|
30872
|
-
const root =
|
|
31155
|
+
const root = path5.resolve(rootAbs);
|
|
30873
31156
|
const roots = [];
|
|
30874
31157
|
async function walk(dir) {
|
|
30875
31158
|
if (await isGitRepoDirectory(dir)) {
|
|
30876
|
-
roots.push(
|
|
31159
|
+
roots.push(path5.resolve(dir));
|
|
30877
31160
|
return;
|
|
30878
31161
|
}
|
|
30879
31162
|
let entries;
|
|
30880
31163
|
try {
|
|
30881
|
-
entries =
|
|
31164
|
+
entries = fs8.readdirSync(dir, { withFileTypes: true });
|
|
30882
31165
|
} catch {
|
|
30883
31166
|
return;
|
|
30884
31167
|
}
|
|
30885
31168
|
for (const ent of entries) {
|
|
30886
31169
|
if (!ent.isDirectory() || ent.name === ".git") continue;
|
|
30887
|
-
await walk(
|
|
31170
|
+
await walk(path5.join(dir, ent.name));
|
|
30888
31171
|
}
|
|
30889
31172
|
}
|
|
30890
31173
|
await walk(root);
|
|
@@ -30900,7 +31183,7 @@ async function discoverGitReposUnderRoot(rootAbs) {
|
|
|
30900
31183
|
// src/git/pre-turn-snapshot.ts
|
|
30901
31184
|
var execFileAsync5 = promisify6(execFile6);
|
|
30902
31185
|
function snapshotsDirForCwd(agentCwd) {
|
|
30903
|
-
return
|
|
31186
|
+
return path6.join(agentCwd, ".buildautomaton", "snapshots");
|
|
30904
31187
|
}
|
|
30905
31188
|
async function gitStashCreate(repoRoot, log2) {
|
|
30906
31189
|
try {
|
|
@@ -30929,7 +31212,7 @@ async function gitRun(repoRoot, args, log2, label) {
|
|
|
30929
31212
|
async function resolveSnapshotRepoRoots(options) {
|
|
30930
31213
|
const { worktreePaths, fallbackCwd, log: log2 } = options;
|
|
30931
31214
|
if (worktreePaths?.length) {
|
|
30932
|
-
const uniq = [...new Set(worktreePaths.map((p) =>
|
|
31215
|
+
const uniq = [...new Set(worktreePaths.map((p) => path6.resolve(p)))];
|
|
30933
31216
|
return uniq;
|
|
30934
31217
|
}
|
|
30935
31218
|
try {
|
|
@@ -30952,7 +31235,7 @@ async function capturePreTurnSnapshot(options) {
|
|
|
30952
31235
|
}
|
|
30953
31236
|
const dir = snapshotsDirForCwd(agentCwd);
|
|
30954
31237
|
try {
|
|
30955
|
-
|
|
31238
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
30956
31239
|
} catch (e) {
|
|
30957
31240
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
30958
31241
|
}
|
|
@@ -30961,9 +31244,9 @@ async function capturePreTurnSnapshot(options) {
|
|
|
30961
31244
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
30962
31245
|
repos
|
|
30963
31246
|
};
|
|
30964
|
-
const filePath =
|
|
31247
|
+
const filePath = path6.join(dir, `${runId}.json`);
|
|
30965
31248
|
try {
|
|
30966
|
-
|
|
31249
|
+
fs9.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
|
|
30967
31250
|
} catch (e) {
|
|
30968
31251
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
30969
31252
|
}
|
|
@@ -30976,7 +31259,7 @@ async function capturePreTurnSnapshot(options) {
|
|
|
30976
31259
|
async function applyPreTurnSnapshot(filePath, log2) {
|
|
30977
31260
|
let data;
|
|
30978
31261
|
try {
|
|
30979
|
-
const raw =
|
|
31262
|
+
const raw = fs9.readFileSync(filePath, "utf8");
|
|
30980
31263
|
data = JSON.parse(raw);
|
|
30981
31264
|
} catch (e) {
|
|
30982
31265
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
@@ -30999,7 +31282,7 @@ async function applyPreTurnSnapshot(filePath, log2) {
|
|
|
30999
31282
|
return { ok: true };
|
|
31000
31283
|
}
|
|
31001
31284
|
function snapshotFilePath(agentCwd, runId) {
|
|
31002
|
-
return
|
|
31285
|
+
return path6.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
|
|
31003
31286
|
}
|
|
31004
31287
|
|
|
31005
31288
|
// src/git/session-git-queue.ts
|
|
@@ -31007,9 +31290,9 @@ var execFileAsync6 = promisify7(execFile7);
|
|
|
31007
31290
|
var MAX_FULL_FILE_TEXT_BYTES = 512 * 1024;
|
|
31008
31291
|
async function readWorkspaceFileAsUtf8(absPath) {
|
|
31009
31292
|
try {
|
|
31010
|
-
const st = await
|
|
31293
|
+
const st = await stat2(absPath);
|
|
31011
31294
|
if (!st.isFile() || st.size > MAX_FULL_FILE_TEXT_BYTES) return void 0;
|
|
31012
|
-
return await
|
|
31295
|
+
return await readFile2(absPath, "utf8");
|
|
31013
31296
|
} catch {
|
|
31014
31297
|
return void 0;
|
|
31015
31298
|
}
|
|
@@ -31019,7 +31302,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
31019
31302
|
const filePath = snapshotFilePath(agentCwd, runId);
|
|
31020
31303
|
let data;
|
|
31021
31304
|
try {
|
|
31022
|
-
const raw = await
|
|
31305
|
+
const raw = await readFile2(filePath, "utf8");
|
|
31023
31306
|
data = JSON.parse(raw);
|
|
31024
31307
|
} catch (e) {
|
|
31025
31308
|
log2(
|
|
@@ -31048,7 +31331,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
31048
31331
|
continue;
|
|
31049
31332
|
}
|
|
31050
31333
|
const lines = namesRaw.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
31051
|
-
const slug =
|
|
31334
|
+
const slug = path7.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
|
|
31052
31335
|
for (const rel of lines) {
|
|
31053
31336
|
if (rel.includes("..")) continue;
|
|
31054
31337
|
try {
|
|
@@ -31062,7 +31345,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
31062
31345
|
);
|
|
31063
31346
|
if (!patchContent.trim()) continue;
|
|
31064
31347
|
const displayPath = multiRepo ? `${slug}/${rel}` : rel;
|
|
31065
|
-
const absFile =
|
|
31348
|
+
const absFile = path7.join(repo.path, rel);
|
|
31066
31349
|
const newText = await readWorkspaceFileAsUtf8(absFile);
|
|
31067
31350
|
sendSessionUpdate({
|
|
31068
31351
|
type: "session_file_change",
|
|
@@ -31144,8 +31427,8 @@ async function sendPromptToAgent(options) {
|
|
|
31144
31427
|
}
|
|
31145
31428
|
|
|
31146
31429
|
// src/agents/acp/ensure-acp-client.ts
|
|
31147
|
-
import * as
|
|
31148
|
-
import * as
|
|
31430
|
+
import * as fs10 from "node:fs";
|
|
31431
|
+
import * as path11 from "node:path";
|
|
31149
31432
|
|
|
31150
31433
|
// src/error-message.ts
|
|
31151
31434
|
function errorMessage(err) {
|
|
@@ -31234,21 +31517,21 @@ function editSnippetToUnifiedDiff(filePath, oldText, newText) {
|
|
|
31234
31517
|
}
|
|
31235
31518
|
|
|
31236
31519
|
// src/agents/acp/safe-fs-path.ts
|
|
31237
|
-
import * as
|
|
31520
|
+
import * as path8 from "node:path";
|
|
31238
31521
|
function resolveSafePathUnderCwd(cwd, filePath) {
|
|
31239
31522
|
const trimmed2 = filePath.trim();
|
|
31240
31523
|
if (!trimmed2) return null;
|
|
31241
|
-
const normalizedCwd =
|
|
31242
|
-
const resolved =
|
|
31243
|
-
const rel =
|
|
31244
|
-
if (rel.startsWith("..") ||
|
|
31524
|
+
const normalizedCwd = path8.resolve(cwd);
|
|
31525
|
+
const resolved = path8.isAbsolute(trimmed2) ? path8.normalize(trimmed2) : path8.resolve(normalizedCwd, trimmed2);
|
|
31526
|
+
const rel = path8.relative(normalizedCwd, resolved);
|
|
31527
|
+
if (rel.startsWith("..") || path8.isAbsolute(rel)) return null;
|
|
31245
31528
|
return resolved;
|
|
31246
31529
|
}
|
|
31247
31530
|
function toDisplayPathRelativeToCwd(cwd, absolutePath) {
|
|
31248
|
-
const normalizedCwd =
|
|
31249
|
-
const rel =
|
|
31250
|
-
if (!rel || rel === "") return
|
|
31251
|
-
return rel.split(
|
|
31531
|
+
const normalizedCwd = path8.resolve(cwd);
|
|
31532
|
+
const rel = path8.relative(normalizedCwd, path8.resolve(absolutePath));
|
|
31533
|
+
if (!rel || rel === "") return path8.basename(absolutePath);
|
|
31534
|
+
return rel.split(path8.sep).join("/");
|
|
31252
31535
|
}
|
|
31253
31536
|
|
|
31254
31537
|
// src/agents/acp/clients/agent-stderr-capture.ts
|
|
@@ -31368,7 +31651,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
31368
31651
|
child.once("close", (code, signal) => {
|
|
31369
31652
|
onAgentSubprocessExit?.({ code, signal });
|
|
31370
31653
|
});
|
|
31371
|
-
return new Promise((
|
|
31654
|
+
return new Promise((resolve17, reject) => {
|
|
31372
31655
|
let initSettled = false;
|
|
31373
31656
|
const settleReject = (err) => {
|
|
31374
31657
|
if (initSettled) return;
|
|
@@ -31382,7 +31665,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
31382
31665
|
const settleResolve = (handle) => {
|
|
31383
31666
|
if (initSettled) return;
|
|
31384
31667
|
initSettled = true;
|
|
31385
|
-
|
|
31668
|
+
resolve17(handle);
|
|
31386
31669
|
};
|
|
31387
31670
|
child.on("error", (err) => {
|
|
31388
31671
|
settleReject(new Error(formatSpawnError(err, command[0])));
|
|
@@ -31418,8 +31701,8 @@ async function createSdkStdioAcpClient(options) {
|
|
|
31418
31701
|
});
|
|
31419
31702
|
} catch {
|
|
31420
31703
|
}
|
|
31421
|
-
return await new Promise((
|
|
31422
|
-
pendingPermissionResolvers.set(requestId,
|
|
31704
|
+
return await new Promise((resolve18) => {
|
|
31705
|
+
pendingPermissionResolvers.set(requestId, resolve18);
|
|
31423
31706
|
});
|
|
31424
31707
|
},
|
|
31425
31708
|
async readTextFile(params) {
|
|
@@ -31527,9 +31810,9 @@ async function createSdkStdioAcpClient(options) {
|
|
|
31527
31810
|
}
|
|
31528
31811
|
},
|
|
31529
31812
|
async cancel() {
|
|
31530
|
-
for (const [id,
|
|
31813
|
+
for (const [id, resolve18] of [...pendingPermissionResolvers.entries()]) {
|
|
31531
31814
|
pendingPermissionResolvers.delete(id);
|
|
31532
|
-
|
|
31815
|
+
resolve18({ outcome: { outcome: "cancelled" } });
|
|
31533
31816
|
}
|
|
31534
31817
|
try {
|
|
31535
31818
|
await connection.cancel({ sessionId });
|
|
@@ -31545,10 +31828,10 @@ async function createSdkStdioAcpClient(options) {
|
|
|
31545
31828
|
}
|
|
31546
31829
|
},
|
|
31547
31830
|
resolveRequest(requestId, result) {
|
|
31548
|
-
const
|
|
31549
|
-
if (!
|
|
31831
|
+
const resolve18 = pendingPermissionResolvers.get(requestId);
|
|
31832
|
+
if (!resolve18) return;
|
|
31550
31833
|
pendingPermissionResolvers.delete(requestId);
|
|
31551
|
-
|
|
31834
|
+
resolve18(result);
|
|
31552
31835
|
},
|
|
31553
31836
|
disconnect() {
|
|
31554
31837
|
child.kill();
|
|
@@ -31689,7 +31972,7 @@ async function createCursorAcpClient(options) {
|
|
|
31689
31972
|
onRequest,
|
|
31690
31973
|
onFileChange
|
|
31691
31974
|
} = options;
|
|
31692
|
-
const dbgFs = process.env.
|
|
31975
|
+
const dbgFs = process.env.BUILDAUTOMATON_DEBUG_ACP_FS === "1";
|
|
31693
31976
|
const isWindows = process.platform === "win32";
|
|
31694
31977
|
const child = spawn3(command[0], command.slice(1), {
|
|
31695
31978
|
cwd,
|
|
@@ -31699,7 +31982,7 @@ async function createCursorAcpClient(options) {
|
|
|
31699
31982
|
});
|
|
31700
31983
|
const stderrCapture = createStderrCapture(child);
|
|
31701
31984
|
child.stderr?.on("data", (chunk) => stderrCapture.append(chunk));
|
|
31702
|
-
return new Promise((
|
|
31985
|
+
return new Promise((resolve17, reject) => {
|
|
31703
31986
|
child.on("error", (err) => {
|
|
31704
31987
|
child.kill();
|
|
31705
31988
|
reject(new Error(formatSpawnError2(err, command[0])));
|
|
@@ -31886,7 +32169,7 @@ async function createCursorAcpClient(options) {
|
|
|
31886
32169
|
const newResult = await send("session/new", { cwd, mcpServers: [] });
|
|
31887
32170
|
const sessionId = newResult?.sessionId ?? "";
|
|
31888
32171
|
if (!sessionId) throw new Error("Cursor ACP session/new did not return sessionId");
|
|
31889
|
-
|
|
32172
|
+
resolve17({
|
|
31890
32173
|
sessionId,
|
|
31891
32174
|
async sendPrompt(prompt, _options) {
|
|
31892
32175
|
promptOutputBuffer = "";
|
|
@@ -32077,16 +32360,16 @@ import { existsSync, statSync } from "node:fs";
|
|
|
32077
32360
|
|
|
32078
32361
|
// src/git/get-git-repo-root-sync.ts
|
|
32079
32362
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
32080
|
-
import * as
|
|
32363
|
+
import * as path9 from "node:path";
|
|
32081
32364
|
function getGitRepoRootSync(startDir) {
|
|
32082
32365
|
try {
|
|
32083
32366
|
const out = execFileSync2("git", ["rev-parse", "--show-toplevel"], {
|
|
32084
|
-
cwd:
|
|
32367
|
+
cwd: path9.resolve(startDir),
|
|
32085
32368
|
encoding: "utf8",
|
|
32086
32369
|
stdio: ["ignore", "pipe", "ignore"],
|
|
32087
32370
|
maxBuffer: 1024 * 1024
|
|
32088
32371
|
}).trim();
|
|
32089
|
-
return out ?
|
|
32372
|
+
return out ? path9.resolve(out) : null;
|
|
32090
32373
|
} catch {
|
|
32091
32374
|
return null;
|
|
32092
32375
|
}
|
|
@@ -32095,25 +32378,25 @@ function getGitRepoRootSync(startDir) {
|
|
|
32095
32378
|
// src/agents/acp/workspace-files.ts
|
|
32096
32379
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
32097
32380
|
import { readFileSync as readFileSync4 } from "node:fs";
|
|
32098
|
-
import * as
|
|
32381
|
+
import * as path10 from "node:path";
|
|
32099
32382
|
function resolveWorkspaceFilePath(cwd, rawPath) {
|
|
32100
32383
|
const trimmed2 = rawPath.trim();
|
|
32101
32384
|
if (!trimmed2) return null;
|
|
32102
|
-
const normalizedCwd =
|
|
32385
|
+
const normalizedCwd = path10.resolve(cwd);
|
|
32103
32386
|
let abs = resolveSafePathUnderCwd(cwd, trimmed2);
|
|
32104
32387
|
if (!abs) {
|
|
32105
|
-
const candidate =
|
|
32388
|
+
const candidate = path10.isAbsolute(trimmed2) ? path10.normalize(trimmed2) : path10.normalize(path10.resolve(normalizedCwd, trimmed2));
|
|
32106
32389
|
const gitRoot2 = getGitRepoRootSync(cwd);
|
|
32107
32390
|
if (!gitRoot2) return null;
|
|
32108
|
-
const rel =
|
|
32109
|
-
if (rel.startsWith("..") ||
|
|
32391
|
+
const rel = path10.relative(gitRoot2, candidate);
|
|
32392
|
+
if (rel.startsWith("..") || path10.isAbsolute(rel)) return null;
|
|
32110
32393
|
abs = candidate;
|
|
32111
32394
|
}
|
|
32112
32395
|
const gitRoot = getGitRepoRootSync(cwd);
|
|
32113
32396
|
if (gitRoot) {
|
|
32114
|
-
const relFromRoot =
|
|
32115
|
-
if (!relFromRoot.startsWith("..") && !
|
|
32116
|
-
return { abs, display: relFromRoot.split(
|
|
32397
|
+
const relFromRoot = path10.relative(gitRoot, abs);
|
|
32398
|
+
if (!relFromRoot.startsWith("..") && !path10.isAbsolute(relFromRoot)) {
|
|
32399
|
+
return { abs, display: relFromRoot.split(path10.sep).join("/") };
|
|
32117
32400
|
}
|
|
32118
32401
|
}
|
|
32119
32402
|
return { abs, display: toDisplayPathRelativeToCwd(cwd, abs) };
|
|
@@ -32122,9 +32405,9 @@ function readUtf8WorkspaceFile(cwd, displayPath) {
|
|
|
32122
32405
|
if (!displayPath || displayPath.includes("..")) return "";
|
|
32123
32406
|
const gitRoot = getGitRepoRootSync(cwd);
|
|
32124
32407
|
if (gitRoot) {
|
|
32125
|
-
const abs2 =
|
|
32126
|
-
const rel =
|
|
32127
|
-
if (!rel.startsWith("..") && !
|
|
32408
|
+
const abs2 = path10.resolve(gitRoot, displayPath);
|
|
32409
|
+
const rel = path10.relative(gitRoot, abs2);
|
|
32410
|
+
if (!rel.startsWith("..") && !path10.isAbsolute(rel)) {
|
|
32128
32411
|
try {
|
|
32129
32412
|
return readFileSync4(abs2, "utf8");
|
|
32130
32413
|
} catch {
|
|
@@ -32143,9 +32426,9 @@ function tryWorkspaceDisplayToAbs(cwd, displayPath) {
|
|
|
32143
32426
|
if (!displayPath || displayPath.includes("..")) return null;
|
|
32144
32427
|
const gitRoot = getGitRepoRootSync(cwd);
|
|
32145
32428
|
if (gitRoot) {
|
|
32146
|
-
const abs =
|
|
32147
|
-
const rel =
|
|
32148
|
-
if (!rel.startsWith("..") && !
|
|
32429
|
+
const abs = path10.resolve(gitRoot, displayPath);
|
|
32430
|
+
const rel = path10.relative(gitRoot, abs);
|
|
32431
|
+
if (!rel.startsWith("..") && !path10.isAbsolute(rel)) return abs;
|
|
32149
32432
|
}
|
|
32150
32433
|
return resolveSafePathUnderCwd(cwd, displayPath);
|
|
32151
32434
|
}
|
|
@@ -32713,10 +32996,10 @@ function buildAcpSessionBridgeHooks(opts) {
|
|
|
32713
32996
|
// src/agents/acp/ensure-acp-client.ts
|
|
32714
32997
|
async function ensureAcpClient(options) {
|
|
32715
32998
|
const { state, preferredAgentType, mode, cwd, routing, sendSessionUpdate, sendRequest, log: log2 } = options;
|
|
32716
|
-
const targetCwd =
|
|
32999
|
+
const targetCwd = path11.resolve(
|
|
32717
33000
|
cwd != null && String(cwd).trim() !== "" ? String(cwd).trim() : getBridgeWorkspaceDirectory()
|
|
32718
33001
|
);
|
|
32719
|
-
if (state.acpHandle && state.lastAcpCwd != null &&
|
|
33002
|
+
if (state.acpHandle && state.lastAcpCwd != null && path11.resolve(state.lastAcpCwd) !== path11.resolve(targetCwd)) {
|
|
32720
33003
|
try {
|
|
32721
33004
|
state.acpHandle.disconnect();
|
|
32722
33005
|
} catch {
|
|
@@ -32748,7 +33031,7 @@ async function ensureAcpClient(options) {
|
|
|
32748
33031
|
if (!state.acpStartPromise) {
|
|
32749
33032
|
let statOk = false;
|
|
32750
33033
|
try {
|
|
32751
|
-
const st =
|
|
33034
|
+
const st = fs10.statSync(targetCwd);
|
|
32752
33035
|
statOk = st.isDirectory();
|
|
32753
33036
|
if (!statOk) {
|
|
32754
33037
|
state.lastAcpStartError = `Agent cwd is not a directory: ${targetCwd}`;
|
|
@@ -32944,12 +33227,12 @@ async function createAcpManager(options) {
|
|
|
32944
33227
|
}
|
|
32945
33228
|
|
|
32946
33229
|
// src/worktrees/session-worktree-manager.ts
|
|
32947
|
-
import * as
|
|
33230
|
+
import * as path17 from "node:path";
|
|
32948
33231
|
import os4 from "node:os";
|
|
32949
33232
|
|
|
32950
33233
|
// src/worktrees/prepare-new-session-worktrees.ts
|
|
32951
|
-
import * as
|
|
32952
|
-
import * as
|
|
33234
|
+
import * as fs12 from "node:fs";
|
|
33235
|
+
import * as path13 from "node:path";
|
|
32953
33236
|
|
|
32954
33237
|
// src/git/worktree-add.ts
|
|
32955
33238
|
async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
|
|
@@ -32958,12 +33241,12 @@ async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
|
|
|
32958
33241
|
}
|
|
32959
33242
|
|
|
32960
33243
|
// src/worktrees/worktree-layout-file.ts
|
|
32961
|
-
import * as
|
|
32962
|
-
import * as
|
|
33244
|
+
import * as fs11 from "node:fs";
|
|
33245
|
+
import * as path12 from "node:path";
|
|
32963
33246
|
import os3 from "node:os";
|
|
32964
33247
|
var LAYOUT_FILENAME = "worktree-launcher-layout.json";
|
|
32965
33248
|
function defaultWorktreeLayoutPath() {
|
|
32966
|
-
return
|
|
33249
|
+
return path12.join(os3.homedir(), ".buildautomaton", LAYOUT_FILENAME);
|
|
32967
33250
|
}
|
|
32968
33251
|
function normalizeLoadedLayout(raw) {
|
|
32969
33252
|
if (raw && typeof raw === "object" && "launcherCwds" in raw) {
|
|
@@ -32975,8 +33258,8 @@ function normalizeLoadedLayout(raw) {
|
|
|
32975
33258
|
function loadWorktreeLayout() {
|
|
32976
33259
|
try {
|
|
32977
33260
|
const p = defaultWorktreeLayoutPath();
|
|
32978
|
-
if (!
|
|
32979
|
-
const raw = JSON.parse(
|
|
33261
|
+
if (!fs11.existsSync(p)) return { launcherCwds: [] };
|
|
33262
|
+
const raw = JSON.parse(fs11.readFileSync(p, "utf8"));
|
|
32980
33263
|
return normalizeLoadedLayout(raw);
|
|
32981
33264
|
} catch {
|
|
32982
33265
|
return { launcherCwds: [] };
|
|
@@ -32984,18 +33267,18 @@ function loadWorktreeLayout() {
|
|
|
32984
33267
|
}
|
|
32985
33268
|
function saveWorktreeLayout(layout) {
|
|
32986
33269
|
try {
|
|
32987
|
-
const dir =
|
|
32988
|
-
|
|
32989
|
-
|
|
33270
|
+
const dir = path12.dirname(defaultWorktreeLayoutPath());
|
|
33271
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
33272
|
+
fs11.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
|
|
32990
33273
|
} catch {
|
|
32991
33274
|
}
|
|
32992
33275
|
}
|
|
32993
33276
|
function baseNameSafe(abs) {
|
|
32994
|
-
return
|
|
33277
|
+
return path12.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
|
|
32995
33278
|
}
|
|
32996
33279
|
function allocateDirNameForLauncherCwd(layout, launcherCwdAbs) {
|
|
32997
|
-
const norm =
|
|
32998
|
-
const existing = layout.launcherCwds.find((e) =>
|
|
33280
|
+
const norm = path12.resolve(launcherCwdAbs);
|
|
33281
|
+
const existing = layout.launcherCwds.find((e) => path12.resolve(e.absolutePath) === norm);
|
|
32999
33282
|
if (existing) return existing.dirName;
|
|
33000
33283
|
const base = baseNameSafe(norm);
|
|
33001
33284
|
const used = new Set(layout.launcherCwds.map((e) => e.dirName));
|
|
@@ -33013,9 +33296,9 @@ function allocateDirNameForLauncherCwd(layout, launcherCwdAbs) {
|
|
|
33013
33296
|
// src/worktrees/prepare-new-session-worktrees.ts
|
|
33014
33297
|
async function prepareNewSessionWorktrees(options) {
|
|
33015
33298
|
const { rootAbs, launcherCwd, sessionId, layout, log: log2 } = options;
|
|
33016
|
-
const launcherResolved =
|
|
33299
|
+
const launcherResolved = path13.resolve(launcherCwd);
|
|
33017
33300
|
const cwdKey = allocateDirNameForLauncherCwd(layout, launcherResolved);
|
|
33018
|
-
const agentMirrorRoot =
|
|
33301
|
+
const agentMirrorRoot = path13.join(rootAbs, cwdKey);
|
|
33019
33302
|
const repos = await discoverGitReposUnderRoot(launcherResolved);
|
|
33020
33303
|
if (repos.length === 0) {
|
|
33021
33304
|
log2("[worktrees] No Git repositories under launcher working directory; skipping worktree creation.");
|
|
@@ -33023,13 +33306,13 @@ async function prepareNewSessionWorktrees(options) {
|
|
|
33023
33306
|
}
|
|
33024
33307
|
const branch = `session-${sessionId}`;
|
|
33025
33308
|
const worktreePaths = [];
|
|
33026
|
-
|
|
33309
|
+
fs12.mkdirSync(agentMirrorRoot, { recursive: true });
|
|
33027
33310
|
for (const repo of repos) {
|
|
33028
|
-
let rel =
|
|
33029
|
-
if (rel.startsWith("..") ||
|
|
33311
|
+
let rel = path13.relative(launcherResolved, repo.absolutePath);
|
|
33312
|
+
if (rel.startsWith("..") || path13.isAbsolute(rel)) continue;
|
|
33030
33313
|
const relNorm = rel === "" ? "." : rel;
|
|
33031
|
-
const wtPath =
|
|
33032
|
-
|
|
33314
|
+
const wtPath = path13.join(agentMirrorRoot, relNorm, sessionId);
|
|
33315
|
+
fs12.mkdirSync(path13.dirname(wtPath), { recursive: true });
|
|
33033
33316
|
try {
|
|
33034
33317
|
await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch);
|
|
33035
33318
|
log2(`[worktrees] Added worktree ${wtPath} (branch ${branch}).`);
|
|
@@ -33066,23 +33349,23 @@ async function renameSessionWorktreeBranches(paths, newBranch, log2) {
|
|
|
33066
33349
|
}
|
|
33067
33350
|
|
|
33068
33351
|
// src/worktrees/remove-session-worktrees.ts
|
|
33069
|
-
import * as
|
|
33352
|
+
import * as fs15 from "node:fs";
|
|
33070
33353
|
|
|
33071
33354
|
// src/git/worktree-remove.ts
|
|
33072
|
-
import * as
|
|
33355
|
+
import * as fs14 from "node:fs";
|
|
33073
33356
|
|
|
33074
33357
|
// src/git/resolve-main-repo-from-git-file.ts
|
|
33075
|
-
import * as
|
|
33076
|
-
import * as
|
|
33358
|
+
import * as fs13 from "node:fs";
|
|
33359
|
+
import * as path14 from "node:path";
|
|
33077
33360
|
function resolveMainRepoFromWorktreeGitFile(wt) {
|
|
33078
|
-
const gitDirFile =
|
|
33079
|
-
if (!
|
|
33080
|
-
const first2 =
|
|
33361
|
+
const gitDirFile = path14.join(wt, ".git");
|
|
33362
|
+
if (!fs13.existsSync(gitDirFile) || !fs13.statSync(gitDirFile).isFile()) return "";
|
|
33363
|
+
const first2 = fs13.readFileSync(gitDirFile, "utf8").trim();
|
|
33081
33364
|
const m = first2.match(/^gitdir:\s*(.+)$/im);
|
|
33082
33365
|
if (!m) return "";
|
|
33083
|
-
const gitWorktreePath =
|
|
33084
|
-
const gitDir =
|
|
33085
|
-
return
|
|
33366
|
+
const gitWorktreePath = path14.resolve(wt, m[1].trim());
|
|
33367
|
+
const gitDir = path14.dirname(path14.dirname(gitWorktreePath));
|
|
33368
|
+
return path14.dirname(gitDir);
|
|
33086
33369
|
}
|
|
33087
33370
|
|
|
33088
33371
|
// src/git/worktree-remove.ts
|
|
@@ -33091,7 +33374,7 @@ async function gitWorktreeRemoveForce(worktreePath) {
|
|
|
33091
33374
|
if (mainRepo) {
|
|
33092
33375
|
await simpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
|
|
33093
33376
|
} else {
|
|
33094
|
-
|
|
33377
|
+
fs14.rmSync(worktreePath, { recursive: true, force: true });
|
|
33095
33378
|
}
|
|
33096
33379
|
}
|
|
33097
33380
|
|
|
@@ -33104,7 +33387,7 @@ async function removeSessionWorktrees(paths, log2) {
|
|
|
33104
33387
|
} catch (e) {
|
|
33105
33388
|
log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
|
|
33106
33389
|
try {
|
|
33107
|
-
|
|
33390
|
+
fs15.rmSync(wt, { recursive: true, force: true });
|
|
33108
33391
|
} catch {
|
|
33109
33392
|
}
|
|
33110
33393
|
}
|
|
@@ -33324,7 +33607,7 @@ function formatRemoteDisplayLabel(remoteUrl) {
|
|
|
33324
33607
|
}
|
|
33325
33608
|
|
|
33326
33609
|
// src/git/working-directory/changes/get-working-tree-change-repo-details.ts
|
|
33327
|
-
import * as
|
|
33610
|
+
import * as path16 from "node:path";
|
|
33328
33611
|
|
|
33329
33612
|
// src/git/working-directory/changes/parse-git-status.ts
|
|
33330
33613
|
function parseNameStatusLines(lines) {
|
|
@@ -33444,8 +33727,8 @@ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
|
|
|
33444
33727
|
}
|
|
33445
33728
|
|
|
33446
33729
|
// src/git/working-directory/changes/list-changed-files-for-repo.ts
|
|
33447
|
-
import * as
|
|
33448
|
-
import * as
|
|
33730
|
+
import * as fs17 from "node:fs";
|
|
33731
|
+
import * as path15 from "node:path";
|
|
33449
33732
|
|
|
33450
33733
|
// src/git/working-directory/changes/count-lines.ts
|
|
33451
33734
|
import { createReadStream } from "node:fs";
|
|
@@ -33469,7 +33752,7 @@ async function countTextFileLines(absFile) {
|
|
|
33469
33752
|
}
|
|
33470
33753
|
|
|
33471
33754
|
// src/git/working-directory/changes/hydrate-patch.ts
|
|
33472
|
-
import * as
|
|
33755
|
+
import * as fs16 from "node:fs";
|
|
33473
33756
|
var UNIFIED_HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
|
|
33474
33757
|
var MAX_HYDRATE_LINES_PER_GAP = 8e3;
|
|
33475
33758
|
var MAX_HYDRATE_LINES_PER_FILE = 8e4;
|
|
@@ -33484,7 +33767,7 @@ async function readGitBlobLines(repoCwd, pathInRepo) {
|
|
|
33484
33767
|
}
|
|
33485
33768
|
async function readWorktreeFileLines(abs) {
|
|
33486
33769
|
try {
|
|
33487
|
-
const raw = await
|
|
33770
|
+
const raw = await fs16.promises.readFile(abs, "utf8");
|
|
33488
33771
|
return raw.split(/\r?\n/);
|
|
33489
33772
|
} catch {
|
|
33490
33773
|
return null;
|
|
@@ -33619,7 +33902,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
33619
33902
|
const rows = [];
|
|
33620
33903
|
for (const pathInRepo of paths) {
|
|
33621
33904
|
const relLauncher = posixJoinDirFile(repoRelPath, pathInRepo.replace(/\\/g, "/"));
|
|
33622
|
-
const abs =
|
|
33905
|
+
const abs = path15.join(repoGitCwd, pathInRepo);
|
|
33623
33906
|
const nums = numByPath.get(pathInRepo);
|
|
33624
33907
|
let additions = nums?.additions ?? 0;
|
|
33625
33908
|
let deletions = nums?.deletions ?? 0;
|
|
@@ -33632,7 +33915,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
33632
33915
|
deletions = fromGit.deletions;
|
|
33633
33916
|
} else {
|
|
33634
33917
|
try {
|
|
33635
|
-
const st = await
|
|
33918
|
+
const st = await fs17.promises.stat(abs);
|
|
33636
33919
|
if (st.isFile()) additions = await countTextFileLines(abs);
|
|
33637
33920
|
else additions = 0;
|
|
33638
33921
|
} catch {
|
|
@@ -33658,7 +33941,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
33658
33941
|
} else {
|
|
33659
33942
|
pathInRepo = row.pathRelLauncher;
|
|
33660
33943
|
}
|
|
33661
|
-
const absFile =
|
|
33944
|
+
const absFile = path15.join(repoGitCwd, pathInRepo);
|
|
33662
33945
|
let patch = await unifiedDiffForFile(repoGitCwd, pathInRepo, row.change);
|
|
33663
33946
|
if (patch) {
|
|
33664
33947
|
patch = await hydrateUnifiedPatchWithFileContext(patch, absFile, repoGitCwd, pathInRepo, row.change);
|
|
@@ -33674,8 +33957,8 @@ function normRepoRel(p) {
|
|
|
33674
33957
|
return x === "" ? "." : x;
|
|
33675
33958
|
}
|
|
33676
33959
|
async function getWorkingTreeChangeRepoDetails(options) {
|
|
33677
|
-
const launcher =
|
|
33678
|
-
const mirror = options.agentMirrorRootAbs ?
|
|
33960
|
+
const launcher = path16.resolve(getBridgeWorkspaceDirectory());
|
|
33961
|
+
const mirror = options.agentMirrorRootAbs ? path16.resolve(options.agentMirrorRootAbs) : null;
|
|
33679
33962
|
const out = [];
|
|
33680
33963
|
const filter = options.repoFilterRelPath != null ? normRepoRel(options.repoFilterRelPath) : null;
|
|
33681
33964
|
const basisInput = options.basis ?? { kind: "working" };
|
|
@@ -33687,7 +33970,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
33687
33970
|
}
|
|
33688
33971
|
const basis = filter == null && basisInput.kind === "commit" ? { kind: "working" } : basisInput;
|
|
33689
33972
|
for (const target of options.commitTargetAbsDirs) {
|
|
33690
|
-
const t =
|
|
33973
|
+
const t = path16.resolve(target);
|
|
33691
33974
|
if (!await isGitRepoDirectory(t)) continue;
|
|
33692
33975
|
const g = simpleGit(t);
|
|
33693
33976
|
let branch = "HEAD";
|
|
@@ -33700,7 +33983,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
33700
33983
|
const remoteDisplay = formatRemoteDisplayLabel(remoteUrl);
|
|
33701
33984
|
let repoRelPath;
|
|
33702
33985
|
if (mirror) {
|
|
33703
|
-
const relNorm =
|
|
33986
|
+
const relNorm = path16.relative(mirror, path16.dirname(t));
|
|
33704
33987
|
repoRelPath = relNorm === "" ? "." : relNorm.replace(/\\/g, "/");
|
|
33705
33988
|
} else {
|
|
33706
33989
|
let top = t;
|
|
@@ -33709,8 +33992,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
33709
33992
|
} catch {
|
|
33710
33993
|
top = t;
|
|
33711
33994
|
}
|
|
33712
|
-
const rel =
|
|
33713
|
-
repoRelPath = rel.startsWith("..") ?
|
|
33995
|
+
const rel = path16.relative(launcher, path16.resolve(top)).replace(/\\/g, "/") || ".";
|
|
33996
|
+
repoRelPath = rel.startsWith("..") ? path16.basename(path16.resolve(top)) : rel;
|
|
33714
33997
|
}
|
|
33715
33998
|
const norm = normRepoRel(repoRelPath === "" ? "." : repoRelPath);
|
|
33716
33999
|
if (filter && norm !== filter) continue;
|
|
@@ -33802,7 +34085,7 @@ var SessionWorktreeManager = class {
|
|
|
33802
34085
|
}
|
|
33803
34086
|
if (!opts.isNewSession) {
|
|
33804
34087
|
const agentCwd = this.sessionAgentCwd.get(sessionId);
|
|
33805
|
-
if (agentCwd) return
|
|
34088
|
+
if (agentCwd) return path17.resolve(agentCwd);
|
|
33806
34089
|
return void 0;
|
|
33807
34090
|
}
|
|
33808
34091
|
const prep = await prepareNewSessionWorktrees({
|
|
@@ -33815,7 +34098,7 @@ var SessionWorktreeManager = class {
|
|
|
33815
34098
|
if (!prep) return void 0;
|
|
33816
34099
|
this.sessionPaths.set(sessionId, prep.worktreePaths);
|
|
33817
34100
|
this.sessionAgentCwd.set(sessionId, prep.agentCwd);
|
|
33818
|
-
return
|
|
34101
|
+
return path17.resolve(prep.agentCwd);
|
|
33819
34102
|
}
|
|
33820
34103
|
async renameSessionBranch(sessionId, newBranch) {
|
|
33821
34104
|
const paths = this.sessionPaths.get(sessionId);
|
|
@@ -33836,7 +34119,7 @@ var SessionWorktreeManager = class {
|
|
|
33836
34119
|
getAgentCwdForSession(sessionId) {
|
|
33837
34120
|
if (!sessionId) return null;
|
|
33838
34121
|
const c = this.sessionAgentCwd.get(sessionId);
|
|
33839
|
-
return c ?
|
|
34122
|
+
return c ? path17.resolve(c) : null;
|
|
33840
34123
|
}
|
|
33841
34124
|
async removeSessionWorktrees(sessionId) {
|
|
33842
34125
|
const paths = this.sessionPaths.get(sessionId);
|
|
@@ -33884,30 +34167,30 @@ var SessionWorktreeManager = class {
|
|
|
33884
34167
|
}
|
|
33885
34168
|
};
|
|
33886
34169
|
function defaultWorktreesRootAbs() {
|
|
33887
|
-
return
|
|
34170
|
+
return path17.join(os4.homedir(), ".buildautomaton", "worktrees");
|
|
33888
34171
|
}
|
|
33889
34172
|
|
|
33890
34173
|
// src/files/watch-file-index.ts
|
|
33891
34174
|
import { watch } from "node:fs";
|
|
33892
|
-
import
|
|
34175
|
+
import path24 from "node:path";
|
|
33893
34176
|
|
|
33894
34177
|
// src/files/index/build-file-index.ts
|
|
33895
|
-
import
|
|
34178
|
+
import path21 from "node:path";
|
|
33896
34179
|
|
|
33897
34180
|
// src/runtime/yield-to-event-loop.ts
|
|
33898
34181
|
function yieldToEventLoop() {
|
|
33899
|
-
return new Promise((
|
|
34182
|
+
return new Promise((resolve17) => setImmediate(resolve17));
|
|
33900
34183
|
}
|
|
33901
34184
|
|
|
33902
34185
|
// src/files/index/walk-workspace-tree.ts
|
|
33903
|
-
import
|
|
33904
|
-
import
|
|
34186
|
+
import fs18 from "node:fs";
|
|
34187
|
+
import path19 from "node:path";
|
|
33905
34188
|
|
|
33906
34189
|
// src/files/index/constants.ts
|
|
33907
|
-
import
|
|
34190
|
+
import path18 from "node:path";
|
|
33908
34191
|
import os5 from "node:os";
|
|
33909
34192
|
var INDEX_WORK_YIELD_EVERY = 256;
|
|
33910
|
-
var INDEX_DIR =
|
|
34193
|
+
var INDEX_DIR = path18.join(os5.homedir(), ".buildautomaton");
|
|
33911
34194
|
var INDEX_HASH_LEN = 16;
|
|
33912
34195
|
var INDEX_VERSION = 2;
|
|
33913
34196
|
var INDEX_LOG_PREFIX = "[file-index]";
|
|
@@ -33916,23 +34199,23 @@ var INDEX_LOG_PREFIX = "[file-index]";
|
|
|
33916
34199
|
function walkWorkspaceTreeSync(dir, baseDir, out) {
|
|
33917
34200
|
let names;
|
|
33918
34201
|
try {
|
|
33919
|
-
names =
|
|
34202
|
+
names = fs18.readdirSync(dir);
|
|
33920
34203
|
} catch {
|
|
33921
34204
|
return;
|
|
33922
34205
|
}
|
|
33923
34206
|
for (const name of names) {
|
|
33924
34207
|
if (name.startsWith(".")) continue;
|
|
33925
|
-
const full =
|
|
33926
|
-
let
|
|
34208
|
+
const full = path19.join(dir, name);
|
|
34209
|
+
let stat3;
|
|
33927
34210
|
try {
|
|
33928
|
-
|
|
34211
|
+
stat3 = fs18.statSync(full);
|
|
33929
34212
|
} catch {
|
|
33930
34213
|
continue;
|
|
33931
34214
|
}
|
|
33932
|
-
const relative5 =
|
|
33933
|
-
if (
|
|
34215
|
+
const relative5 = path19.relative(baseDir, full).replace(/\\/g, "/");
|
|
34216
|
+
if (stat3.isDirectory()) {
|
|
33934
34217
|
walkWorkspaceTreeSync(full, baseDir, out);
|
|
33935
|
-
} else if (
|
|
34218
|
+
} else if (stat3.isFile()) {
|
|
33936
34219
|
out.push(relative5);
|
|
33937
34220
|
}
|
|
33938
34221
|
}
|
|
@@ -33940,7 +34223,7 @@ function walkWorkspaceTreeSync(dir, baseDir, out) {
|
|
|
33940
34223
|
async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
|
|
33941
34224
|
let names;
|
|
33942
34225
|
try {
|
|
33943
|
-
names = await
|
|
34226
|
+
names = await fs18.promises.readdir(dir);
|
|
33944
34227
|
} catch {
|
|
33945
34228
|
return;
|
|
33946
34229
|
}
|
|
@@ -33950,17 +34233,17 @@ async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
|
|
|
33950
34233
|
await yieldToEventLoop();
|
|
33951
34234
|
}
|
|
33952
34235
|
state.n++;
|
|
33953
|
-
const full =
|
|
33954
|
-
let
|
|
34236
|
+
const full = path19.join(dir, name);
|
|
34237
|
+
let stat3;
|
|
33955
34238
|
try {
|
|
33956
|
-
|
|
34239
|
+
stat3 = await fs18.promises.stat(full);
|
|
33957
34240
|
} catch {
|
|
33958
34241
|
continue;
|
|
33959
34242
|
}
|
|
33960
|
-
const relative5 =
|
|
33961
|
-
if (
|
|
34243
|
+
const relative5 = path19.relative(baseDir, full).replace(/\\/g, "/");
|
|
34244
|
+
if (stat3.isDirectory()) {
|
|
33962
34245
|
await walkWorkspaceTreeAsync(full, baseDir, out, state);
|
|
33963
|
-
} else if (
|
|
34246
|
+
} else if (stat3.isFile()) {
|
|
33964
34247
|
out.push(relative5);
|
|
33965
34248
|
}
|
|
33966
34249
|
}
|
|
@@ -34038,22 +34321,22 @@ async function buildTrigramMapForPathsAsync(paths) {
|
|
|
34038
34321
|
}
|
|
34039
34322
|
|
|
34040
34323
|
// src/files/index/write-index-file.ts
|
|
34041
|
-
import
|
|
34324
|
+
import fs19 from "node:fs";
|
|
34042
34325
|
|
|
34043
34326
|
// src/files/index/paths.ts
|
|
34044
|
-
import
|
|
34327
|
+
import path20 from "node:path";
|
|
34045
34328
|
import crypto2 from "node:crypto";
|
|
34046
34329
|
function getIndexPathForCwd(resolvedCwd) {
|
|
34047
34330
|
const hash = crypto2.createHash("sha256").update(resolvedCwd).digest("hex").slice(0, INDEX_HASH_LEN);
|
|
34048
|
-
return
|
|
34331
|
+
return path20.join(INDEX_DIR, `.file-index-${hash}.json`);
|
|
34049
34332
|
}
|
|
34050
34333
|
|
|
34051
34334
|
// src/files/index/write-index-file.ts
|
|
34052
34335
|
function writeIndexFileSync(resolvedCwd, data) {
|
|
34053
34336
|
const indexPath = getIndexPathForCwd(resolvedCwd);
|
|
34054
34337
|
try {
|
|
34055
|
-
if (!
|
|
34056
|
-
|
|
34338
|
+
if (!fs19.existsSync(INDEX_DIR)) fs19.mkdirSync(INDEX_DIR, { recursive: true });
|
|
34339
|
+
fs19.writeFileSync(indexPath, JSON.stringify(data), "utf8");
|
|
34057
34340
|
} catch (e) {
|
|
34058
34341
|
console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
|
|
34059
34342
|
}
|
|
@@ -34061,8 +34344,8 @@ function writeIndexFileSync(resolvedCwd, data) {
|
|
|
34061
34344
|
async function writeIndexFileAsync(resolvedCwd, data) {
|
|
34062
34345
|
const indexPath = getIndexPathForCwd(resolvedCwd);
|
|
34063
34346
|
try {
|
|
34064
|
-
await
|
|
34065
|
-
await
|
|
34347
|
+
await fs19.promises.mkdir(INDEX_DIR, { recursive: true });
|
|
34348
|
+
await fs19.promises.writeFile(indexPath, JSON.stringify(data), "utf8");
|
|
34066
34349
|
} catch (e) {
|
|
34067
34350
|
console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
|
|
34068
34351
|
}
|
|
@@ -34076,7 +34359,7 @@ function sortPaths(paths) {
|
|
|
34076
34359
|
paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
|
|
34077
34360
|
}
|
|
34078
34361
|
function buildFileIndex(cwd) {
|
|
34079
|
-
const resolved =
|
|
34362
|
+
const resolved = path21.resolve(cwd);
|
|
34080
34363
|
const paths = [];
|
|
34081
34364
|
walkWorkspaceTreeSync(resolved, resolved, paths);
|
|
34082
34365
|
sortPaths(paths);
|
|
@@ -34086,7 +34369,7 @@ function buildFileIndex(cwd) {
|
|
|
34086
34369
|
return data;
|
|
34087
34370
|
}
|
|
34088
34371
|
async function buildFileIndexAsync(cwd) {
|
|
34089
|
-
const resolved =
|
|
34372
|
+
const resolved = path21.resolve(cwd);
|
|
34090
34373
|
const paths = [];
|
|
34091
34374
|
await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
|
|
34092
34375
|
await yieldToEventLoop();
|
|
@@ -34098,13 +34381,13 @@ async function buildFileIndexAsync(cwd) {
|
|
|
34098
34381
|
}
|
|
34099
34382
|
|
|
34100
34383
|
// src/files/index/load-file-index.ts
|
|
34101
|
-
import
|
|
34102
|
-
import
|
|
34384
|
+
import fs20 from "node:fs";
|
|
34385
|
+
import path22 from "node:path";
|
|
34103
34386
|
function loadFileIndex(cwd) {
|
|
34104
|
-
const resolved =
|
|
34387
|
+
const resolved = path22.resolve(cwd);
|
|
34105
34388
|
const indexPath = getIndexPathForCwd(resolved);
|
|
34106
34389
|
try {
|
|
34107
|
-
const raw =
|
|
34390
|
+
const raw = fs20.readFileSync(indexPath, "utf8");
|
|
34108
34391
|
const parsed = JSON.parse(raw);
|
|
34109
34392
|
if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.paths)) {
|
|
34110
34393
|
const obj = parsed;
|
|
@@ -34123,9 +34406,9 @@ function loadFileIndex(cwd) {
|
|
|
34123
34406
|
}
|
|
34124
34407
|
|
|
34125
34408
|
// src/files/index/ensure-file-index.ts
|
|
34126
|
-
import
|
|
34409
|
+
import path23 from "node:path";
|
|
34127
34410
|
async function ensureFileIndexAsync(cwd) {
|
|
34128
|
-
const resolved =
|
|
34411
|
+
const resolved = path23.resolve(cwd);
|
|
34129
34412
|
const cached2 = loadFileIndex(resolved);
|
|
34130
34413
|
if (cached2 !== null) return { data: cached2, fromCache: true };
|
|
34131
34414
|
const data = await buildFileIndexAsync(resolved);
|
|
@@ -34208,7 +34491,7 @@ function createFsWatcher(resolved, schedule) {
|
|
|
34208
34491
|
}
|
|
34209
34492
|
}
|
|
34210
34493
|
function startFileIndexWatcher(cwd = getBridgeWorkspaceDirectory()) {
|
|
34211
|
-
const resolved =
|
|
34494
|
+
const resolved = path24.resolve(cwd);
|
|
34212
34495
|
void buildFileIndexAsync(resolved).catch((e) => {
|
|
34213
34496
|
console.error("[file-index] Initial index build failed:", e);
|
|
34214
34497
|
});
|
|
@@ -34236,7 +34519,7 @@ function startFileIndexWatcher(cwd = getBridgeWorkspaceDirectory()) {
|
|
|
34236
34519
|
}
|
|
34237
34520
|
|
|
34238
34521
|
// src/dev-servers/manager/dev-server-manager.ts
|
|
34239
|
-
import { rm } from "node:fs/promises";
|
|
34522
|
+
import { rm as rm2 } from "node:fs/promises";
|
|
34240
34523
|
|
|
34241
34524
|
// src/dev-servers/process/send-server-status.ts
|
|
34242
34525
|
function sendDevServerStatus(getWs, serverId, status, options) {
|
|
@@ -34255,15 +34538,15 @@ function sendDevServerStatus(getWs, serverId, status, options) {
|
|
|
34255
34538
|
|
|
34256
34539
|
// src/dev-servers/process/terminate-child-process.ts
|
|
34257
34540
|
async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
|
|
34258
|
-
const exited = new Promise((
|
|
34259
|
-
proc.once("exit", () =>
|
|
34541
|
+
const exited = new Promise((resolve17) => {
|
|
34542
|
+
proc.once("exit", () => resolve17());
|
|
34260
34543
|
});
|
|
34261
34544
|
log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
|
|
34262
34545
|
try {
|
|
34263
34546
|
proc.kill("SIGTERM");
|
|
34264
34547
|
} catch {
|
|
34265
34548
|
}
|
|
34266
|
-
await Promise.race([exited, new Promise((
|
|
34549
|
+
await Promise.race([exited, new Promise((resolve17) => setTimeout(resolve17, graceMs))]);
|
|
34267
34550
|
}
|
|
34268
34551
|
function forceKillChild(proc, log2, shortId, graceMs) {
|
|
34269
34552
|
log2(
|
|
@@ -34277,7 +34560,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
|
|
|
34277
34560
|
}
|
|
34278
34561
|
|
|
34279
34562
|
// src/dev-servers/process/wire-dev-server-child-process.ts
|
|
34280
|
-
import
|
|
34563
|
+
import fs21 from "node:fs";
|
|
34281
34564
|
|
|
34282
34565
|
// src/dev-servers/manager/forward-pipe.ts
|
|
34283
34566
|
function forwardChildPipe(childReadable, terminal, onData) {
|
|
@@ -34313,7 +34596,7 @@ function wireDevServerChildProcess(d) {
|
|
|
34313
34596
|
d.setPollInterval(void 0);
|
|
34314
34597
|
return;
|
|
34315
34598
|
}
|
|
34316
|
-
|
|
34599
|
+
fs21.readFile(d.mergedLogPath, (err, buf) => {
|
|
34317
34600
|
if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
|
|
34318
34601
|
if (buf.length <= d.mergedReadPos.value) return;
|
|
34319
34602
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
@@ -34351,7 +34634,7 @@ ${errTail}` : ""}`);
|
|
|
34351
34634
|
d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
|
|
34352
34635
|
};
|
|
34353
34636
|
if (mergedPath) {
|
|
34354
|
-
|
|
34637
|
+
fs21.readFile(mergedPath, (err, buf) => {
|
|
34355
34638
|
if (!err && buf.length > d.mergedReadPos.value) {
|
|
34356
34639
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
34357
34640
|
if (chunk.length > 0) {
|
|
@@ -34453,13 +34736,13 @@ function parseDevServerDefs(servers) {
|
|
|
34453
34736
|
}
|
|
34454
34737
|
|
|
34455
34738
|
// src/dev-servers/manager/shell-spawn/utils.ts
|
|
34456
|
-
import
|
|
34739
|
+
import fs22 from "node:fs";
|
|
34457
34740
|
function isSpawnEbadf(e) {
|
|
34458
34741
|
return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
|
|
34459
34742
|
}
|
|
34460
34743
|
function rmDirQuiet(dir) {
|
|
34461
34744
|
try {
|
|
34462
|
-
|
|
34745
|
+
fs22.rmSync(dir, { recursive: true, force: true });
|
|
34463
34746
|
} catch {
|
|
34464
34747
|
}
|
|
34465
34748
|
}
|
|
@@ -34467,7 +34750,7 @@ var cachedDevNullReadFd;
|
|
|
34467
34750
|
function devNullReadFd() {
|
|
34468
34751
|
if (cachedDevNullReadFd === void 0) {
|
|
34469
34752
|
const devPath = process.platform === "win32" ? "nul" : "/dev/null";
|
|
34470
|
-
cachedDevNullReadFd =
|
|
34753
|
+
cachedDevNullReadFd = fs22.openSync(devPath, "r");
|
|
34471
34754
|
}
|
|
34472
34755
|
return cachedDevNullReadFd;
|
|
34473
34756
|
}
|
|
@@ -34541,15 +34824,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
|
34541
34824
|
|
|
34542
34825
|
// src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
|
|
34543
34826
|
import { spawn as spawn6 } from "node:child_process";
|
|
34544
|
-
import
|
|
34827
|
+
import fs23 from "node:fs";
|
|
34545
34828
|
import { tmpdir } from "node:os";
|
|
34546
|
-
import
|
|
34829
|
+
import path25 from "node:path";
|
|
34547
34830
|
function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
34548
|
-
const tmpRoot =
|
|
34549
|
-
const logPath =
|
|
34831
|
+
const tmpRoot = fs23.mkdtempSync(path25.join(tmpdir(), "ba-devsrv-log-"));
|
|
34832
|
+
const logPath = path25.join(tmpRoot, "combined.log");
|
|
34550
34833
|
let logFd;
|
|
34551
34834
|
try {
|
|
34552
|
-
logFd =
|
|
34835
|
+
logFd = fs23.openSync(logPath, "a");
|
|
34553
34836
|
} catch {
|
|
34554
34837
|
rmDirQuiet(tmpRoot);
|
|
34555
34838
|
return null;
|
|
@@ -34568,7 +34851,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
34568
34851
|
} else {
|
|
34569
34852
|
proc = spawn6("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
|
|
34570
34853
|
}
|
|
34571
|
-
|
|
34854
|
+
fs23.closeSync(logFd);
|
|
34572
34855
|
return {
|
|
34573
34856
|
proc,
|
|
34574
34857
|
pipedStdoutStderr: true,
|
|
@@ -34577,7 +34860,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
34577
34860
|
};
|
|
34578
34861
|
} catch (e) {
|
|
34579
34862
|
try {
|
|
34580
|
-
|
|
34863
|
+
fs23.closeSync(logFd);
|
|
34581
34864
|
} catch {
|
|
34582
34865
|
}
|
|
34583
34866
|
rmDirQuiet(tmpRoot);
|
|
@@ -34588,22 +34871,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
34588
34871
|
|
|
34589
34872
|
// src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
|
|
34590
34873
|
import { spawn as spawn7 } from "node:child_process";
|
|
34591
|
-
import
|
|
34874
|
+
import fs24 from "node:fs";
|
|
34592
34875
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
34593
|
-
import
|
|
34876
|
+
import path26 from "node:path";
|
|
34594
34877
|
function shSingleQuote(s) {
|
|
34595
34878
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
34596
34879
|
}
|
|
34597
34880
|
function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
|
|
34598
|
-
const tmpRoot =
|
|
34599
|
-
const logPath =
|
|
34600
|
-
const innerPath =
|
|
34601
|
-
const runnerPath =
|
|
34881
|
+
const tmpRoot = fs24.mkdtempSync(path26.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
34882
|
+
const logPath = path26.join(tmpRoot, "combined.log");
|
|
34883
|
+
const innerPath = path26.join(tmpRoot, "_cmd.sh");
|
|
34884
|
+
const runnerPath = path26.join(tmpRoot, "_run.sh");
|
|
34602
34885
|
try {
|
|
34603
|
-
|
|
34886
|
+
fs24.writeFileSync(innerPath, `#!/bin/sh
|
|
34604
34887
|
${command}
|
|
34605
34888
|
`);
|
|
34606
|
-
|
|
34889
|
+
fs24.writeFileSync(
|
|
34607
34890
|
runnerPath,
|
|
34608
34891
|
`#!/bin/sh
|
|
34609
34892
|
cd ${shSingleQuote(cwd)}
|
|
@@ -34629,13 +34912,13 @@ cd ${shSingleQuote(cwd)}
|
|
|
34629
34912
|
}
|
|
34630
34913
|
}
|
|
34631
34914
|
function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
|
|
34632
|
-
const tmpRoot =
|
|
34633
|
-
const logPath =
|
|
34634
|
-
const runnerPath =
|
|
34915
|
+
const tmpRoot = fs24.mkdtempSync(path26.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
34916
|
+
const logPath = path26.join(tmpRoot, "combined.log");
|
|
34917
|
+
const runnerPath = path26.join(tmpRoot, "_run.bat");
|
|
34635
34918
|
const q = (p) => `"${p.replace(/"/g, '""')}"`;
|
|
34636
34919
|
const com = process.env.ComSpec || "cmd.exe";
|
|
34637
34920
|
try {
|
|
34638
|
-
|
|
34921
|
+
fs24.writeFileSync(
|
|
34639
34922
|
runnerPath,
|
|
34640
34923
|
`@ECHO OFF\r
|
|
34641
34924
|
CD /D ${q(cwd)}\r
|
|
@@ -34745,8 +35028,90 @@ var StreamTail = class {
|
|
|
34745
35028
|
}
|
|
34746
35029
|
};
|
|
34747
35030
|
|
|
34748
|
-
// src/dev-servers/manager/dev-server-
|
|
35031
|
+
// src/dev-servers/manager/dev-server-constants.ts
|
|
34749
35032
|
var BRIDGE_SHUTDOWN_GRACE_MS = 8e3;
|
|
35033
|
+
|
|
35034
|
+
// src/dev-servers/manager/dev-server-firehose-messages.ts
|
|
35035
|
+
function buildFirehoseSnapshotMessage(params) {
|
|
35036
|
+
const payload = {
|
|
35037
|
+
type: "log_snapshot",
|
|
35038
|
+
serverId: params.serverId,
|
|
35039
|
+
viewerId: params.viewerId,
|
|
35040
|
+
stdoutTail: params.tails.stdout,
|
|
35041
|
+
stderrTail: params.tails.stderr
|
|
35042
|
+
};
|
|
35043
|
+
return params.e2ee ? params.e2ee.encryptFields(payload, ["stdoutTail", "stderrTail"]) : payload;
|
|
35044
|
+
}
|
|
35045
|
+
function buildFirehoseLogChunkMessage(params) {
|
|
35046
|
+
const payload = {
|
|
35047
|
+
type: "log_chunk",
|
|
35048
|
+
serverId: params.serverId,
|
|
35049
|
+
stream: params.stream,
|
|
35050
|
+
text: params.text
|
|
35051
|
+
};
|
|
35052
|
+
return params.e2ee ? params.e2ee.encryptFields(payload, ["text"]) : payload;
|
|
35053
|
+
}
|
|
35054
|
+
|
|
35055
|
+
// src/dev-servers/manager/dev-server-firehose-sink.ts
|
|
35056
|
+
var DevServerFirehoseSink = class {
|
|
35057
|
+
constructor(options) {
|
|
35058
|
+
this.options = options;
|
|
35059
|
+
}
|
|
35060
|
+
logViewerRefCountByServerId = /* @__PURE__ */ new Map();
|
|
35061
|
+
firehoseSend = null;
|
|
35062
|
+
attach(send) {
|
|
35063
|
+
this.firehoseSend = send;
|
|
35064
|
+
}
|
|
35065
|
+
detach() {
|
|
35066
|
+
this.firehoseSend = null;
|
|
35067
|
+
this.logViewerRefCountByServerId.clear();
|
|
35068
|
+
}
|
|
35069
|
+
openLogViewer(serverId, viewerId) {
|
|
35070
|
+
const next = (this.logViewerRefCountByServerId.get(serverId) ?? 0) + 1;
|
|
35071
|
+
this.logViewerRefCountByServerId.set(serverId, next);
|
|
35072
|
+
this.sendSnapshot(serverId, viewerId);
|
|
35073
|
+
}
|
|
35074
|
+
closeLogViewer(serverId) {
|
|
35075
|
+
const n = (this.logViewerRefCountByServerId.get(serverId) ?? 0) - 1;
|
|
35076
|
+
if (n <= 0) this.logViewerRefCountByServerId.delete(serverId);
|
|
35077
|
+
else this.logViewerRefCountByServerId.set(serverId, n);
|
|
35078
|
+
}
|
|
35079
|
+
pushLogChunk(serverId, stream, chunk) {
|
|
35080
|
+
if ((this.logViewerRefCountByServerId.get(serverId) ?? 0) <= 0) return;
|
|
35081
|
+
if (!this.options.isPipedCaptureEnabled(serverId)) return;
|
|
35082
|
+
if (!this.firehoseSend) return;
|
|
35083
|
+
const text = chunk.toString("utf8");
|
|
35084
|
+
setImmediate(() => {
|
|
35085
|
+
if (!this.firehoseSend) return;
|
|
35086
|
+
this.firehoseSend(buildFirehoseLogChunkMessage({ serverId, stream, text, e2ee: this.options.e2ee }));
|
|
35087
|
+
});
|
|
35088
|
+
}
|
|
35089
|
+
sendSnapshot(serverId, viewerId) {
|
|
35090
|
+
const payload = buildFirehoseSnapshotMessage({
|
|
35091
|
+
serverId,
|
|
35092
|
+
viewerId,
|
|
35093
|
+
tails: this.options.getTails(serverId),
|
|
35094
|
+
e2ee: this.options.e2ee
|
|
35095
|
+
});
|
|
35096
|
+
setImmediate(() => {
|
|
35097
|
+
const send = this.firehoseSend;
|
|
35098
|
+
if (!send) return;
|
|
35099
|
+
send(payload);
|
|
35100
|
+
});
|
|
35101
|
+
}
|
|
35102
|
+
};
|
|
35103
|
+
|
|
35104
|
+
// src/dev-servers/manager/cleanup-merged-log-dir.ts
|
|
35105
|
+
import { rm } from "node:fs/promises";
|
|
35106
|
+
function cleanupMergedLogDirForServer(map2, serverId) {
|
|
35107
|
+
const mergedDir = map2.get(serverId);
|
|
35108
|
+
if (!mergedDir) return;
|
|
35109
|
+
map2.delete(serverId);
|
|
35110
|
+
void rm(mergedDir, { recursive: true, force: true }).catch(() => {
|
|
35111
|
+
});
|
|
35112
|
+
}
|
|
35113
|
+
|
|
35114
|
+
// src/dev-servers/manager/dev-server-manager.ts
|
|
34750
35115
|
var emptyTails = () => ({ stdout: [], stderr: [] });
|
|
34751
35116
|
var DevServerManager = class {
|
|
34752
35117
|
defsById = /* @__PURE__ */ new Map();
|
|
@@ -34754,66 +35119,36 @@ var DevServerManager = class {
|
|
|
34754
35119
|
streamTailsByServerId = /* @__PURE__ */ new Map();
|
|
34755
35120
|
spawnGenerationByServerId = /* @__PURE__ */ new Map();
|
|
34756
35121
|
pipedCaptureByServerId = /* @__PURE__ */ new Map();
|
|
34757
|
-
logViewerRefCountByServerId = /* @__PURE__ */ new Map();
|
|
34758
|
-
firehoseSend = null;
|
|
34759
35122
|
mergedLogPollByServerId = /* @__PURE__ */ new Map();
|
|
34760
35123
|
mergedLogCleanupDirByServerId = /* @__PURE__ */ new Map();
|
|
34761
35124
|
abortControllersByServerId = /* @__PURE__ */ new Map();
|
|
34762
35125
|
getWs;
|
|
34763
35126
|
log;
|
|
34764
35127
|
getBridgeCwd;
|
|
35128
|
+
e2ee;
|
|
35129
|
+
firehoseSink;
|
|
34765
35130
|
constructor(options) {
|
|
34766
35131
|
this.getWs = options.getWs;
|
|
34767
35132
|
this.log = options.log;
|
|
34768
35133
|
this.getBridgeCwd = options.getBridgeCwd ?? (() => process.cwd());
|
|
35134
|
+
this.e2ee = options.e2ee;
|
|
35135
|
+
this.firehoseSink = new DevServerFirehoseSink({
|
|
35136
|
+
getTails: (serverId) => this.snapshotTails(serverId),
|
|
35137
|
+
isPipedCaptureEnabled: (serverId) => this.pipedCaptureByServerId.get(serverId) === true,
|
|
35138
|
+
e2ee: this.e2ee
|
|
35139
|
+
});
|
|
34769
35140
|
}
|
|
34770
35141
|
attachFirehose(send) {
|
|
34771
|
-
this.
|
|
35142
|
+
this.firehoseSink.attach(send);
|
|
34772
35143
|
}
|
|
34773
35144
|
detachFirehose() {
|
|
34774
|
-
this.
|
|
34775
|
-
this.logViewerRefCountByServerId.clear();
|
|
35145
|
+
this.firehoseSink.detach();
|
|
34776
35146
|
}
|
|
34777
35147
|
handleFirehoseLogViewerOpen(serverId, _viewerId) {
|
|
34778
|
-
|
|
34779
|
-
this.logViewerRefCountByServerId.set(serverId, next);
|
|
34780
|
-
this.sendSnapshotToFirehose(serverId, _viewerId);
|
|
35148
|
+
this.firehoseSink.openLogViewer(serverId, _viewerId);
|
|
34781
35149
|
}
|
|
34782
35150
|
handleFirehoseLogViewerClose(serverId, _viewerId) {
|
|
34783
|
-
|
|
34784
|
-
if (n <= 0) this.logViewerRefCountByServerId.delete(serverId);
|
|
34785
|
-
else this.logViewerRefCountByServerId.set(serverId, n);
|
|
34786
|
-
}
|
|
34787
|
-
sendSnapshotToFirehose(serverId, viewerId) {
|
|
34788
|
-
const tails = this.streamTailsByServerId.get(serverId);
|
|
34789
|
-
const payload = {
|
|
34790
|
-
type: "log_snapshot",
|
|
34791
|
-
serverId,
|
|
34792
|
-
viewerId,
|
|
34793
|
-
stdoutTail: tails?.stdout.getTail() ?? [],
|
|
34794
|
-
stderrTail: tails?.stderr.getTail() ?? []
|
|
34795
|
-
};
|
|
34796
|
-
setImmediate(() => {
|
|
34797
|
-
const send = this.firehoseSend;
|
|
34798
|
-
if (!send) return;
|
|
34799
|
-
send(payload);
|
|
34800
|
-
});
|
|
34801
|
-
}
|
|
34802
|
-
pushRemoteLogChunk(serverId, stream, chunk) {
|
|
34803
|
-
if ((this.logViewerRefCountByServerId.get(serverId) ?? 0) <= 0) return;
|
|
34804
|
-
if (!this.pipedCaptureByServerId.get(serverId)) return;
|
|
34805
|
-
const send = this.firehoseSend;
|
|
34806
|
-
if (!send) return;
|
|
34807
|
-
const text = chunk.toString("utf8");
|
|
34808
|
-
setImmediate(() => {
|
|
34809
|
-
if (!this.firehoseSend) return;
|
|
34810
|
-
this.firehoseSend({
|
|
34811
|
-
type: "log_chunk",
|
|
34812
|
-
serverId,
|
|
34813
|
-
stream,
|
|
34814
|
-
text
|
|
34815
|
-
});
|
|
34816
|
-
});
|
|
35151
|
+
this.firehoseSink.closeLogViewer(serverId);
|
|
34817
35152
|
}
|
|
34818
35153
|
applyConfig(servers) {
|
|
34819
35154
|
this.defsById.clear();
|
|
@@ -34866,12 +35201,7 @@ var DevServerManager = class {
|
|
|
34866
35201
|
}
|
|
34867
35202
|
this.clearTails(serverId);
|
|
34868
35203
|
this.pipedCaptureByServerId.delete(serverId);
|
|
34869
|
-
|
|
34870
|
-
if (mergedDir) {
|
|
34871
|
-
this.mergedLogCleanupDirByServerId.delete(serverId);
|
|
34872
|
-
void rm(mergedDir, { recursive: true, force: true }).catch(() => {
|
|
34873
|
-
});
|
|
34874
|
-
}
|
|
35204
|
+
cleanupMergedLogDirForServer(this.mergedLogCleanupDirByServerId, serverId);
|
|
34875
35205
|
this.sendStatus(serverId, "stopped", void 0, tails);
|
|
34876
35206
|
}
|
|
34877
35207
|
start(serverId) {
|
|
@@ -34954,7 +35284,7 @@ var DevServerManager = class {
|
|
|
34954
35284
|
log: this.log,
|
|
34955
35285
|
stdoutTail,
|
|
34956
35286
|
stderrTail,
|
|
34957
|
-
pushRemoteLogChunk: (sid, stream, chunk) => this.
|
|
35287
|
+
pushRemoteLogChunk: (sid, stream, chunk) => this.firehoseSink.pushLogChunk(sid, stream, chunk),
|
|
34958
35288
|
sendStatus: (status, detail, tails) => this.sendStatus(serverId, status, detail, tails),
|
|
34959
35289
|
setPollInterval: (iv) => {
|
|
34960
35290
|
if (iv) this.mergedLogPollByServerId.set(serverId, iv);
|
|
@@ -34968,7 +35298,7 @@ var DevServerManager = class {
|
|
|
34968
35298
|
this.mergedLogCleanupDirByServerId.delete(serverId);
|
|
34969
35299
|
},
|
|
34970
35300
|
rmMergedCleanupDir: (dir) => {
|
|
34971
|
-
void
|
|
35301
|
+
void rm2(dir, { recursive: true, force: true }).catch(() => {
|
|
34972
35302
|
});
|
|
34973
35303
|
},
|
|
34974
35304
|
clearTailBuffers: () => this.clearTails(serverId)
|
|
@@ -35005,12 +35335,7 @@ var DevServerManager = class {
|
|
|
35005
35335
|
this.processes.delete(serverId);
|
|
35006
35336
|
this.clearPoll(serverId);
|
|
35007
35337
|
this.pipedCaptureByServerId.delete(serverId);
|
|
35008
|
-
|
|
35009
|
-
if (mergedDir) {
|
|
35010
|
-
this.mergedLogCleanupDirByServerId.delete(serverId);
|
|
35011
|
-
void rm(mergedDir, { recursive: true, force: true }).catch(() => {
|
|
35012
|
-
});
|
|
35013
|
-
}
|
|
35338
|
+
cleanupMergedLogDirForServer(this.mergedLogCleanupDirByServerId, serverId);
|
|
35014
35339
|
const tails = this.snapshotTails(serverId);
|
|
35015
35340
|
this.clearTails(serverId);
|
|
35016
35341
|
this.sendStatus(serverId, "unknown", "Bridge closed before process exited", tails);
|
|
@@ -35104,7 +35429,7 @@ async function proxyToLocal(request) {
|
|
|
35104
35429
|
};
|
|
35105
35430
|
const maxAttempts = isIdempotentProxyMethod(request.method) ? LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS.length + 1 : 1;
|
|
35106
35431
|
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
35107
|
-
const once = await new Promise((
|
|
35432
|
+
const once = await new Promise((resolve17) => {
|
|
35108
35433
|
const req = mod.request(opts, (res) => {
|
|
35109
35434
|
const chunks = [];
|
|
35110
35435
|
res.on("data", (c) => chunks.push(c));
|
|
@@ -35115,7 +35440,7 @@ async function proxyToLocal(request) {
|
|
|
35115
35440
|
if (typeof v === "string") headers[k] = v;
|
|
35116
35441
|
else if (Array.isArray(v) && v[0]) headers[k] = v[0];
|
|
35117
35442
|
}
|
|
35118
|
-
|
|
35443
|
+
resolve17({
|
|
35119
35444
|
id: request.id,
|
|
35120
35445
|
statusCode: res.statusCode ?? 0,
|
|
35121
35446
|
headers,
|
|
@@ -35124,7 +35449,7 @@ async function proxyToLocal(request) {
|
|
|
35124
35449
|
});
|
|
35125
35450
|
});
|
|
35126
35451
|
req.on("error", (err) => {
|
|
35127
|
-
|
|
35452
|
+
resolve17({
|
|
35128
35453
|
id: request.id,
|
|
35129
35454
|
statusCode: 0,
|
|
35130
35455
|
headers: {},
|
|
@@ -35485,30 +35810,30 @@ function createOnBridgeIdentified(opts) {
|
|
|
35485
35810
|
}
|
|
35486
35811
|
|
|
35487
35812
|
// src/skills/discover-local-agent-skills.ts
|
|
35488
|
-
import
|
|
35489
|
-
import
|
|
35813
|
+
import fs25 from "node:fs";
|
|
35814
|
+
import path27 from "node:path";
|
|
35490
35815
|
var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
|
|
35491
35816
|
function discoverLocalSkills(cwd) {
|
|
35492
35817
|
const out = [];
|
|
35493
35818
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
35494
35819
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
35495
|
-
const base =
|
|
35496
|
-
if (!
|
|
35820
|
+
const base = path27.join(cwd, rel);
|
|
35821
|
+
if (!fs25.existsSync(base) || !fs25.statSync(base).isDirectory()) continue;
|
|
35497
35822
|
let entries = [];
|
|
35498
35823
|
try {
|
|
35499
|
-
entries =
|
|
35824
|
+
entries = fs25.readdirSync(base);
|
|
35500
35825
|
} catch {
|
|
35501
35826
|
continue;
|
|
35502
35827
|
}
|
|
35503
35828
|
for (const name of entries) {
|
|
35504
|
-
const dir =
|
|
35829
|
+
const dir = path27.join(base, name);
|
|
35505
35830
|
try {
|
|
35506
|
-
if (!
|
|
35831
|
+
if (!fs25.statSync(dir).isDirectory()) continue;
|
|
35507
35832
|
} catch {
|
|
35508
35833
|
continue;
|
|
35509
35834
|
}
|
|
35510
|
-
const skillMd =
|
|
35511
|
-
if (!
|
|
35835
|
+
const skillMd = path27.join(dir, "SKILL.md");
|
|
35836
|
+
if (!fs25.existsSync(skillMd)) continue;
|
|
35512
35837
|
const key = `${rel}/${name}`;
|
|
35513
35838
|
if (seenKeys.has(key)) continue;
|
|
35514
35839
|
seenKeys.add(key);
|
|
@@ -35520,23 +35845,23 @@ function discoverLocalSkills(cwd) {
|
|
|
35520
35845
|
function discoverSkillLayoutRoots(cwd) {
|
|
35521
35846
|
const roots = [];
|
|
35522
35847
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
35523
|
-
const base =
|
|
35524
|
-
if (!
|
|
35848
|
+
const base = path27.join(cwd, rel);
|
|
35849
|
+
if (!fs25.existsSync(base) || !fs25.statSync(base).isDirectory()) continue;
|
|
35525
35850
|
let entries = [];
|
|
35526
35851
|
try {
|
|
35527
|
-
entries =
|
|
35852
|
+
entries = fs25.readdirSync(base);
|
|
35528
35853
|
} catch {
|
|
35529
35854
|
continue;
|
|
35530
35855
|
}
|
|
35531
35856
|
const skills2 = [];
|
|
35532
35857
|
for (const name of entries) {
|
|
35533
|
-
const dir =
|
|
35858
|
+
const dir = path27.join(base, name);
|
|
35534
35859
|
try {
|
|
35535
|
-
if (!
|
|
35860
|
+
if (!fs25.statSync(dir).isDirectory()) continue;
|
|
35536
35861
|
} catch {
|
|
35537
35862
|
continue;
|
|
35538
35863
|
}
|
|
35539
|
-
if (!
|
|
35864
|
+
if (!fs25.existsSync(path27.join(dir, "SKILL.md"))) continue;
|
|
35540
35865
|
const relPath = `${rel}/${name}`.replace(/\\/g, "/");
|
|
35541
35866
|
skills2.push({ name, relPath });
|
|
35542
35867
|
}
|
|
@@ -35638,7 +35963,7 @@ function reportGitRepos(getWs, log2) {
|
|
|
35638
35963
|
var handleAuthToken = (msg, { log: log2 }) => {
|
|
35639
35964
|
if (typeof msg.token !== "string") return;
|
|
35640
35965
|
log2("Received auth token. Save it for future runs:");
|
|
35641
|
-
log2(` export
|
|
35966
|
+
log2(` export BUILDAUTOMATON_AUTH_TOKEN="${msg.token}"`);
|
|
35642
35967
|
};
|
|
35643
35968
|
|
|
35644
35969
|
// src/bridge/routing/handlers/bridge-identified.ts
|
|
@@ -35681,13 +36006,13 @@ var handleAgentConfigMessage = (msg, deps) => {
|
|
|
35681
36006
|
};
|
|
35682
36007
|
|
|
35683
36008
|
// src/agents/acp/from-bridge/handle-bridge-prompt.ts
|
|
35684
|
-
import * as
|
|
36009
|
+
import * as path29 from "node:path";
|
|
35685
36010
|
import { execFile as execFile10 } from "node:child_process";
|
|
35686
36011
|
import { promisify as promisify10 } from "node:util";
|
|
35687
36012
|
|
|
35688
36013
|
// src/git/bridge-queue-key.ts
|
|
35689
|
-
import * as
|
|
35690
|
-
import { createHash } from "node:crypto";
|
|
36014
|
+
import * as path28 from "node:path";
|
|
36015
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
35691
36016
|
function normalizeCanonicalGitUrl(url2) {
|
|
35692
36017
|
let s = url2.trim();
|
|
35693
36018
|
if (!s) return s;
|
|
@@ -35711,14 +36036,14 @@ function normalizeCanonicalGitUrl(url2) {
|
|
|
35711
36036
|
}
|
|
35712
36037
|
function canonicalUrlToRepoIdSync(url2) {
|
|
35713
36038
|
const normalized = normalizeCanonicalGitUrl(url2);
|
|
35714
|
-
return
|
|
36039
|
+
return createHash2("sha256").update(normalized).digest("hex").slice(0, 32);
|
|
35715
36040
|
}
|
|
35716
36041
|
function fallbackRepoIdFromPath(absPath) {
|
|
35717
|
-
return
|
|
36042
|
+
return createHash2("sha256").update(path28.resolve(absPath)).digest("hex").slice(0, 32);
|
|
35718
36043
|
}
|
|
35719
36044
|
async function resolveBridgeQueueBindFields(options) {
|
|
35720
36045
|
const { effectiveCwd, worktreePaths, primaryRepoRoots, log: log2 } = options;
|
|
35721
|
-
const cwdAbs = worktreePaths.length > 0 ?
|
|
36046
|
+
const cwdAbs = worktreePaths.length > 0 ? path28.resolve(worktreePaths[0]) : path28.resolve(effectiveCwd);
|
|
35722
36047
|
if (!primaryRepoRoots.length) {
|
|
35723
36048
|
log2("[Bridge service] Prompt queue bind skipped: no Git repository roots under the working directory.");
|
|
35724
36049
|
return null;
|
|
@@ -35758,21 +36083,28 @@ function handleBridgePrompt(msg, deps) {
|
|
|
35758
36083
|
const sessionId = msg.sessionId;
|
|
35759
36084
|
const runId = typeof msg.runId === "string" ? msg.runId : void 0;
|
|
35760
36085
|
const promptId = typeof msg.id === "string" ? msg.id : void 0;
|
|
36086
|
+
const sendBridgeMessage = (message, encryptedFields = []) => {
|
|
36087
|
+
const s = getWs();
|
|
36088
|
+
if (!s) return false;
|
|
36089
|
+
const wire = deps.e2ee && encryptedFields.length > 0 ? deps.e2ee.encryptFields(message, encryptedFields) : message;
|
|
36090
|
+
sendWsMessage(s, wire);
|
|
36091
|
+
return true;
|
|
36092
|
+
};
|
|
35761
36093
|
if (!promptText.trim()) {
|
|
35762
36094
|
log2(
|
|
35763
36095
|
`[Bridge service] Prompt ignored: empty or missing prompt text (session ${typeof msg.sessionId === "string" ? msg.sessionId.slice(0, 8) : "\u2014"}\u2026, run ${typeof msg.runId === "string" ? msg.runId.slice(0, 8) : "\u2014"}\u2026).`
|
|
35764
36096
|
);
|
|
35765
|
-
|
|
35766
|
-
|
|
35767
|
-
sendWsMessage(s, {
|
|
36097
|
+
sendBridgeMessage(
|
|
36098
|
+
{
|
|
35768
36099
|
type: "prompt_result",
|
|
35769
36100
|
...promptId ? { id: promptId } : {},
|
|
35770
36101
|
...sessionId ? { sessionId } : {},
|
|
35771
36102
|
...runId ? { runId } : {},
|
|
35772
36103
|
success: false,
|
|
35773
36104
|
error: "Empty or missing prompt text from the bridge; this turn was not sent to the agent."
|
|
35774
|
-
}
|
|
35775
|
-
|
|
36105
|
+
},
|
|
36106
|
+
["error"]
|
|
36107
|
+
);
|
|
35776
36108
|
return;
|
|
35777
36109
|
}
|
|
35778
36110
|
const isNewSession = msg.isNewSession === true;
|
|
@@ -35781,8 +36113,7 @@ function handleBridgePrompt(msg, deps) {
|
|
|
35781
36113
|
const mode = typeof msg.mode === "string" && msg.mode.trim() ? msg.mode.trim() : void 0;
|
|
35782
36114
|
acpManager.logPromptReceivedFromBridge({ agentType, mode });
|
|
35783
36115
|
const sendResult2 = (result) => {
|
|
35784
|
-
|
|
35785
|
-
if (s) sendWsMessage(s, result);
|
|
36116
|
+
sendBridgeMessage(result, result.type === "prompt_result" ? ["output", "error"] : []);
|
|
35786
36117
|
};
|
|
35787
36118
|
const sendSessionUpdate = (payload) => {
|
|
35788
36119
|
const s = getWs();
|
|
@@ -35791,11 +36122,19 @@ function handleBridgePrompt(msg, deps) {
|
|
|
35791
36122
|
return;
|
|
35792
36123
|
}
|
|
35793
36124
|
const p = payload;
|
|
35794
|
-
|
|
36125
|
+
const wire = p.type === "session_update" && deps.e2ee ? deps.e2ee.encryptFields(payload, ["payload"]) : p.type === "session_file_change" && deps.e2ee ? deps.e2ee.encryptFields(payload, [
|
|
36126
|
+
"path",
|
|
36127
|
+
"oldText",
|
|
36128
|
+
"newText",
|
|
36129
|
+
"patchContent",
|
|
36130
|
+
"isDirectory",
|
|
36131
|
+
"directoryRemoved"
|
|
36132
|
+
]) : payload;
|
|
36133
|
+
sendWsMessage(s, wire);
|
|
35795
36134
|
};
|
|
35796
36135
|
async function preambleAndPrompt(resolvedCwd) {
|
|
35797
36136
|
const s = getWs();
|
|
35798
|
-
const effectiveCwd =
|
|
36137
|
+
const effectiveCwd = path29.resolve(resolvedCwd ?? getBridgeWorkspaceDirectory());
|
|
35799
36138
|
const worktreePaths = sessionWorktreeManager.getWorktreePathsForSession(sessionId) ?? [];
|
|
35800
36139
|
const repoRoots = await resolveSnapshotRepoRoots({
|
|
35801
36140
|
worktreePaths,
|
|
@@ -35903,8 +36242,8 @@ var PREVIEW_API_BASE_PATH = "/__preview";
|
|
|
35903
36242
|
var PREVIEW_SECRET_HEADER = "X-Preview-Secret";
|
|
35904
36243
|
var DEFAULT_PORT = 3e3;
|
|
35905
36244
|
var DEFAULT_COMMAND = "npm run preview";
|
|
35906
|
-
var PREVIEW_COMMAND_ENV = "
|
|
35907
|
-
var PREVIEW_PORT_ENV = "
|
|
36245
|
+
var PREVIEW_COMMAND_ENV = "BUILDAUTOMATON_PREVIEW_COMMAND";
|
|
36246
|
+
var PREVIEW_PORT_ENV = "BUILDAUTOMATON_PREVIEW_PORT";
|
|
35908
36247
|
var previewProcess = null;
|
|
35909
36248
|
var previewPort = DEFAULT_PORT;
|
|
35910
36249
|
var previewSecret = "";
|
|
@@ -35918,8 +36257,8 @@ function randomSecret() {
|
|
|
35918
36257
|
}
|
|
35919
36258
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
35920
36259
|
}
|
|
35921
|
-
async function requestPreviewApi(port, secret, method,
|
|
35922
|
-
const url2 = `http://127.0.0.1:${port}${
|
|
36260
|
+
async function requestPreviewApi(port, secret, method, path34, body) {
|
|
36261
|
+
const url2 = `http://127.0.0.1:${port}${path34}`;
|
|
35923
36262
|
const headers = {
|
|
35924
36263
|
[PREVIEW_SECRET_HEADER]: secret,
|
|
35925
36264
|
"Content-Type": "application/json"
|
|
@@ -35931,7 +36270,7 @@ async function requestPreviewApi(port, secret, method, path33, body) {
|
|
|
35931
36270
|
});
|
|
35932
36271
|
const data = await res.json().catch(() => ({}));
|
|
35933
36272
|
if (!res.ok) {
|
|
35934
|
-
throw new Error(data?.error ?? `Preview API ${method} ${
|
|
36273
|
+
throw new Error(data?.error ?? `Preview API ${method} ${path34}: ${res.status}`);
|
|
35935
36274
|
}
|
|
35936
36275
|
return data;
|
|
35937
36276
|
}
|
|
@@ -35957,7 +36296,7 @@ var OPERATIONS = [
|
|
|
35957
36296
|
var previewSkill = {
|
|
35958
36297
|
id: "preview",
|
|
35959
36298
|
name: "Preview",
|
|
35960
|
-
description: "Start and manage a local preview server that implements the BuildAutomaton Preview Server API. Configure the command with
|
|
36299
|
+
description: "Start and manage a local preview server that implements the BuildAutomaton Preview Server API. Configure the command with BUILDAUTOMATON_PREVIEW_COMMAND (default: npm run preview). The server receives PORT and PREVIEW_SECRET and must expose /__preview/status and /__preview/stop.",
|
|
35961
36300
|
operations: OPERATIONS,
|
|
35962
36301
|
async execute(operationId, params) {
|
|
35963
36302
|
const command = getPreviewCommand();
|
|
@@ -36094,15 +36433,15 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
|
36094
36433
|
};
|
|
36095
36434
|
|
|
36096
36435
|
// src/files/list-dir.ts
|
|
36097
|
-
import
|
|
36098
|
-
import
|
|
36436
|
+
import fs26 from "node:fs";
|
|
36437
|
+
import path31 from "node:path";
|
|
36099
36438
|
|
|
36100
36439
|
// src/files/ensure-under-cwd.ts
|
|
36101
|
-
import
|
|
36440
|
+
import path30 from "node:path";
|
|
36102
36441
|
function ensureUnderCwd(relativePath, cwd = getBridgeWorkspaceDirectory()) {
|
|
36103
|
-
const normalized =
|
|
36104
|
-
const resolved =
|
|
36105
|
-
if (!resolved.startsWith(cwd +
|
|
36442
|
+
const normalized = path30.normalize(relativePath).replace(/^(\.\/)+/, "");
|
|
36443
|
+
const resolved = path30.resolve(cwd, normalized);
|
|
36444
|
+
if (!resolved.startsWith(cwd + path30.sep) && resolved !== cwd) {
|
|
36106
36445
|
return null;
|
|
36107
36446
|
}
|
|
36108
36447
|
return resolved;
|
|
@@ -36116,7 +36455,7 @@ async function listDirAsync(relativePath) {
|
|
|
36116
36455
|
return { error: "Path is outside working directory" };
|
|
36117
36456
|
}
|
|
36118
36457
|
try {
|
|
36119
|
-
const names = await
|
|
36458
|
+
const names = await fs26.promises.readdir(resolved, { withFileTypes: true });
|
|
36120
36459
|
const visible = names.filter((d) => !d.name.startsWith("."));
|
|
36121
36460
|
const entries = [];
|
|
36122
36461
|
for (let i = 0; i < visible.length; i++) {
|
|
@@ -36124,12 +36463,12 @@ async function listDirAsync(relativePath) {
|
|
|
36124
36463
|
await yieldToEventLoop();
|
|
36125
36464
|
}
|
|
36126
36465
|
const d = visible[i];
|
|
36127
|
-
const entryPath =
|
|
36128
|
-
const fullPath =
|
|
36466
|
+
const entryPath = path31.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
36467
|
+
const fullPath = path31.join(resolved, d.name);
|
|
36129
36468
|
let isDir = d.isDirectory();
|
|
36130
36469
|
if (d.isSymbolicLink()) {
|
|
36131
36470
|
try {
|
|
36132
|
-
const targetStat = await
|
|
36471
|
+
const targetStat = await fs26.promises.stat(fullPath);
|
|
36133
36472
|
isDir = targetStat.isDirectory();
|
|
36134
36473
|
} catch {
|
|
36135
36474
|
isDir = false;
|
|
@@ -36154,25 +36493,25 @@ async function listDirAsync(relativePath) {
|
|
|
36154
36493
|
}
|
|
36155
36494
|
|
|
36156
36495
|
// src/files/read-file.ts
|
|
36157
|
-
import
|
|
36496
|
+
import fs27 from "node:fs";
|
|
36158
36497
|
import { StringDecoder } from "node:string_decoder";
|
|
36159
36498
|
function resolveFilePath(relativePath) {
|
|
36160
36499
|
const resolved = ensureUnderCwd(relativePath, getBridgeWorkspaceDirectory());
|
|
36161
36500
|
if (!resolved) return { error: "Path is outside working directory" };
|
|
36162
36501
|
let real;
|
|
36163
36502
|
try {
|
|
36164
|
-
real =
|
|
36503
|
+
real = fs27.realpathSync(resolved);
|
|
36165
36504
|
} catch {
|
|
36166
36505
|
real = resolved;
|
|
36167
36506
|
}
|
|
36168
|
-
const
|
|
36169
|
-
if (!
|
|
36507
|
+
const stat3 = fs27.statSync(real);
|
|
36508
|
+
if (!stat3.isFile()) return { error: "Not a file" };
|
|
36170
36509
|
return real;
|
|
36171
36510
|
}
|
|
36172
36511
|
var LINE_CHUNK_SIZE = 64 * 1024;
|
|
36173
36512
|
function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
36174
|
-
const fileSize =
|
|
36175
|
-
const fd =
|
|
36513
|
+
const fileSize = fs27.statSync(filePath).size;
|
|
36514
|
+
const fd = fs27.openSync(filePath, "r");
|
|
36176
36515
|
const bufSize = 64 * 1024;
|
|
36177
36516
|
const buf = Buffer.alloc(bufSize);
|
|
36178
36517
|
const decoder = new StringDecoder("utf8");
|
|
@@ -36185,7 +36524,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
36185
36524
|
let line0Accum = "";
|
|
36186
36525
|
try {
|
|
36187
36526
|
let bytesRead;
|
|
36188
|
-
while (!done && (bytesRead =
|
|
36527
|
+
while (!done && (bytesRead = fs27.readSync(fd, buf, 0, bufSize, null)) > 0) {
|
|
36189
36528
|
const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
|
|
36190
36529
|
partial2 = "";
|
|
36191
36530
|
let lineStart = 0;
|
|
@@ -36320,10 +36659,10 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
36320
36659
|
}
|
|
36321
36660
|
return { content: resultLines.join("\n"), size: fileSize };
|
|
36322
36661
|
} finally {
|
|
36323
|
-
|
|
36662
|
+
fs27.closeSync(fd);
|
|
36324
36663
|
}
|
|
36325
36664
|
}
|
|
36326
|
-
function
|
|
36665
|
+
function readFile3(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
36327
36666
|
try {
|
|
36328
36667
|
const result = resolveFilePath(relativePath);
|
|
36329
36668
|
if (typeof result === "object") return result;
|
|
@@ -36331,43 +36670,45 @@ function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize =
|
|
|
36331
36670
|
if (hasRange) {
|
|
36332
36671
|
return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
|
|
36333
36672
|
}
|
|
36334
|
-
const
|
|
36335
|
-
const raw =
|
|
36673
|
+
const stat3 = fs27.statSync(result);
|
|
36674
|
+
const raw = fs27.readFileSync(result, "utf8");
|
|
36336
36675
|
const lines = raw.split(/\r?\n/);
|
|
36337
|
-
return { content: raw, totalLines: lines.length, size:
|
|
36676
|
+
return { content: raw, totalLines: lines.length, size: stat3.size };
|
|
36338
36677
|
} catch (err) {
|
|
36339
36678
|
return { error: err instanceof Error ? err.message : String(err) };
|
|
36340
36679
|
}
|
|
36341
36680
|
}
|
|
36342
36681
|
async function readFileAsync(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
36343
36682
|
await yieldToEventLoop();
|
|
36344
|
-
return
|
|
36683
|
+
return readFile3(relativePath, startLine, endLine, lineOffset, lineChunkSize);
|
|
36345
36684
|
}
|
|
36346
36685
|
|
|
36347
36686
|
// src/files/handle-file-browser-search.ts
|
|
36348
36687
|
var SEARCH_LIMIT = 100;
|
|
36349
|
-
function handleFileBrowserSearch(msg, socket) {
|
|
36688
|
+
function handleFileBrowserSearch(msg, socket, e2ee) {
|
|
36350
36689
|
void (async () => {
|
|
36351
36690
|
await yieldToEventLoop();
|
|
36352
36691
|
const q = typeof msg.q === "string" ? msg.q : "";
|
|
36353
36692
|
const cwd = getBridgeWorkspaceDirectory();
|
|
36354
36693
|
const index = loadFileIndex(cwd);
|
|
36355
36694
|
if (index === null) {
|
|
36356
|
-
|
|
36695
|
+
const payload2 = {
|
|
36357
36696
|
type: "file_browser_search_response",
|
|
36358
36697
|
id: msg.id,
|
|
36359
36698
|
paths: [],
|
|
36360
36699
|
indexReady: false
|
|
36361
|
-
}
|
|
36700
|
+
};
|
|
36701
|
+
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload2, ["paths"]) : payload2);
|
|
36362
36702
|
return;
|
|
36363
36703
|
}
|
|
36364
36704
|
const results = await searchFileIndexAsync(index, q, SEARCH_LIMIT);
|
|
36365
|
-
|
|
36705
|
+
const payload = {
|
|
36366
36706
|
type: "file_browser_search_response",
|
|
36367
36707
|
id: msg.id,
|
|
36368
36708
|
paths: results,
|
|
36369
36709
|
indexReady: true
|
|
36370
|
-
}
|
|
36710
|
+
};
|
|
36711
|
+
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["paths"]) : payload);
|
|
36371
36712
|
})();
|
|
36372
36713
|
}
|
|
36373
36714
|
function triggerFileIndexBuild() {
|
|
@@ -36379,7 +36720,10 @@ function triggerFileIndexBuild() {
|
|
|
36379
36720
|
}
|
|
36380
36721
|
|
|
36381
36722
|
// src/files/handle-file-browser-request.ts
|
|
36382
|
-
function
|
|
36723
|
+
function sendFileBrowserMessage(socket, e2ee, payload) {
|
|
36724
|
+
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["entries", "content", "totalLines", "size", "lineOffset"]) : payload);
|
|
36725
|
+
}
|
|
36726
|
+
function handleFileBrowserRequest(msg, socket, e2ee) {
|
|
36383
36727
|
void (async () => {
|
|
36384
36728
|
const reqPath = msg.path.replace(/^\/+/, "") || ".";
|
|
36385
36729
|
const op = msg.op === "read" ? "read" : "list";
|
|
@@ -36388,7 +36732,7 @@ function handleFileBrowserRequest(msg, socket) {
|
|
|
36388
36732
|
if ("error" in result) {
|
|
36389
36733
|
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
|
|
36390
36734
|
} else {
|
|
36391
|
-
|
|
36735
|
+
sendFileBrowserMessage(socket, e2ee, { type: "file_browser_response", id: msg.id, entries: result.entries });
|
|
36392
36736
|
if (reqPath === "." || reqPath === "") {
|
|
36393
36737
|
triggerFileIndexBuild();
|
|
36394
36738
|
}
|
|
@@ -36410,27 +36754,28 @@ function handleFileBrowserRequest(msg, socket) {
|
|
|
36410
36754
|
size: result.size
|
|
36411
36755
|
};
|
|
36412
36756
|
if (result.lineOffset != null) payload.lineOffset = result.lineOffset;
|
|
36413
|
-
|
|
36757
|
+
sendFileBrowserMessage(socket, e2ee, payload);
|
|
36414
36758
|
}
|
|
36415
36759
|
}
|
|
36416
36760
|
})();
|
|
36417
36761
|
}
|
|
36418
36762
|
|
|
36419
36763
|
// src/bridge/routing/handlers/file-browser-messages.ts
|
|
36420
|
-
function handleFileBrowserRequestMessage(msg, { getWs }) {
|
|
36764
|
+
function handleFileBrowserRequestMessage(msg, { getWs, e2ee }) {
|
|
36421
36765
|
if (typeof msg.id !== "string" || typeof msg.path !== "string") return;
|
|
36422
36766
|
const socket = getWs();
|
|
36423
36767
|
if (!socket) return;
|
|
36424
36768
|
handleFileBrowserRequest(
|
|
36425
36769
|
msg,
|
|
36426
|
-
socket
|
|
36770
|
+
socket,
|
|
36771
|
+
e2ee
|
|
36427
36772
|
);
|
|
36428
36773
|
}
|
|
36429
|
-
function handleFileBrowserSearchMessage(msg, { getWs }) {
|
|
36774
|
+
function handleFileBrowserSearchMessage(msg, { getWs, e2ee }) {
|
|
36430
36775
|
if (typeof msg.id !== "string") return;
|
|
36431
36776
|
const socket = getWs();
|
|
36432
36777
|
if (!socket) return;
|
|
36433
|
-
handleFileBrowserSearch(msg, socket);
|
|
36778
|
+
handleFileBrowserSearch(msg, socket, e2ee);
|
|
36434
36779
|
}
|
|
36435
36780
|
|
|
36436
36781
|
// src/bridge/routing/handlers/skill-layout-request.ts
|
|
@@ -36442,8 +36787,8 @@ function handleSkillLayoutRequest(msg, deps) {
|
|
|
36442
36787
|
}
|
|
36443
36788
|
|
|
36444
36789
|
// src/skills/install-remote-skills.ts
|
|
36445
|
-
import
|
|
36446
|
-
import
|
|
36790
|
+
import fs28 from "node:fs";
|
|
36791
|
+
import path32 from "node:path";
|
|
36447
36792
|
function installRemoteSkills(cwd, targetDir, items) {
|
|
36448
36793
|
const installed2 = [];
|
|
36449
36794
|
if (!Array.isArray(items)) {
|
|
@@ -36454,15 +36799,15 @@ function installRemoteSkills(cwd, targetDir, items) {
|
|
|
36454
36799
|
if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
|
|
36455
36800
|
continue;
|
|
36456
36801
|
}
|
|
36457
|
-
const skillDir =
|
|
36802
|
+
const skillDir = path32.join(cwd, targetDir, item.skillName);
|
|
36458
36803
|
for (const f of item.files) {
|
|
36459
36804
|
if (typeof f.path !== "string" || !f.text && !f.base64) continue;
|
|
36460
|
-
const dest =
|
|
36461
|
-
|
|
36805
|
+
const dest = path32.join(skillDir, f.path);
|
|
36806
|
+
fs28.mkdirSync(path32.dirname(dest), { recursive: true });
|
|
36462
36807
|
if (f.text !== void 0) {
|
|
36463
|
-
|
|
36808
|
+
fs28.writeFileSync(dest, f.text, "utf8");
|
|
36464
36809
|
} else if (f.base64) {
|
|
36465
|
-
|
|
36810
|
+
fs28.writeFileSync(dest, Buffer.from(f.base64, "base64"));
|
|
36466
36811
|
}
|
|
36467
36812
|
}
|
|
36468
36813
|
installed2.push({
|
|
@@ -36500,9 +36845,10 @@ var handleRefreshLocalSkills = (_msg, deps) => {
|
|
|
36500
36845
|
};
|
|
36501
36846
|
|
|
36502
36847
|
// src/bridge/routing/handlers/session-git-request.ts
|
|
36503
|
-
function sendResult(ws, id, payload) {
|
|
36848
|
+
function sendResult(ws, id, payload, e2ee, encryptedFields = []) {
|
|
36504
36849
|
if (!ws) return;
|
|
36505
|
-
|
|
36850
|
+
const message = { type: "session_git_result", id, ...payload };
|
|
36851
|
+
sendWsMessage(ws, e2ee && encryptedFields.length > 0 ? e2ee.encryptFields(message, encryptedFields) : message);
|
|
36506
36852
|
}
|
|
36507
36853
|
var handleSessionGitRequestMessage = (msg, deps) => {
|
|
36508
36854
|
if (typeof msg.id !== "string") return;
|
|
@@ -36512,7 +36858,7 @@ var handleSessionGitRequestMessage = (msg, deps) => {
|
|
|
36512
36858
|
return;
|
|
36513
36859
|
void (async () => {
|
|
36514
36860
|
const ws = deps.getWs();
|
|
36515
|
-
const reply = (payload) => sendResult(ws, msg.id, payload);
|
|
36861
|
+
const reply = (payload, encryptedFields = []) => sendResult(ws, msg.id, payload, deps.e2ee, encryptedFields);
|
|
36516
36862
|
try {
|
|
36517
36863
|
if (action === "status") {
|
|
36518
36864
|
const r = await deps.sessionWorktreeManager.getSessionWorkingTreeStatus(sessionId);
|
|
@@ -36538,7 +36884,7 @@ var handleSessionGitRequestMessage = (msg, deps) => {
|
|
|
36538
36884
|
reply({
|
|
36539
36885
|
ok: true,
|
|
36540
36886
|
repos
|
|
36541
|
-
});
|
|
36887
|
+
}, ["repos"]);
|
|
36542
36888
|
return;
|
|
36543
36889
|
}
|
|
36544
36890
|
if (action === "push") {
|
|
@@ -36607,7 +36953,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
|
|
|
36607
36953
|
};
|
|
36608
36954
|
|
|
36609
36955
|
// src/bridge/routing/handlers/revert-turn-snapshot.ts
|
|
36610
|
-
import * as
|
|
36956
|
+
import * as fs29 from "node:fs";
|
|
36611
36957
|
var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
36612
36958
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
36613
36959
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
@@ -36619,7 +36965,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
36619
36965
|
if (!s) return;
|
|
36620
36966
|
const agentBase = sessionWorktreeManager.getAgentCwdForSession(sessionId) ?? getBridgeWorkspaceDirectory();
|
|
36621
36967
|
const file2 = snapshotFilePath(agentBase, turnId);
|
|
36622
|
-
if (!
|
|
36968
|
+
if (!fs29.existsSync(file2)) {
|
|
36623
36969
|
sendWsMessage(s, {
|
|
36624
36970
|
type: "revert_turn_snapshot_result",
|
|
36625
36971
|
id,
|
|
@@ -36640,8 +36986,15 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
36640
36986
|
|
|
36641
36987
|
// src/bridge/routing/handlers/dev-server-control.ts
|
|
36642
36988
|
var handleDevServerControl = (msg, deps) => {
|
|
36643
|
-
|
|
36644
|
-
|
|
36989
|
+
let wire = msg;
|
|
36990
|
+
try {
|
|
36991
|
+
wire = deps.e2ee ? deps.e2ee.decryptMessage(msg) : msg;
|
|
36992
|
+
} catch (e) {
|
|
36993
|
+
deps.log(`[E2EE] Could not decrypt dev server command: ${e instanceof Error ? e.message : String(e)}`);
|
|
36994
|
+
return;
|
|
36995
|
+
}
|
|
36996
|
+
const serverId = typeof wire.serverId === "string" ? wire.serverId : "";
|
|
36997
|
+
const action = wire.action === "start" || wire.action === "stop" ? wire.action : null;
|
|
36645
36998
|
if (!serverId || !action) return;
|
|
36646
36999
|
deps.devServerManager?.handleControl(serverId, action);
|
|
36647
37000
|
};
|
|
@@ -36767,7 +37120,8 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
36767
37120
|
messageDeps,
|
|
36768
37121
|
tokens,
|
|
36769
37122
|
persistTokens,
|
|
36770
|
-
onAuthInvalid
|
|
37123
|
+
onAuthInvalid,
|
|
37124
|
+
e2ee
|
|
36771
37125
|
} = params;
|
|
36772
37126
|
let authRefreshInFlight = false;
|
|
36773
37127
|
function handleOpen() {
|
|
@@ -36780,15 +37134,15 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
36780
37134
|
}
|
|
36781
37135
|
const socket = getWs();
|
|
36782
37136
|
if (socket) {
|
|
36783
|
-
sendWsMessage(socket, { type: "identify", role: "cli" });
|
|
37137
|
+
sendWsMessage(socket, { type: "identify", role: "cli", ...e2ee ? { e: e2ee.handshake } : {} });
|
|
36784
37138
|
reportGitRepos(getWs, logFn);
|
|
36785
37139
|
}
|
|
36786
37140
|
if (justAuthenticated && socket) {
|
|
36787
37141
|
logFn(
|
|
36788
37142
|
"Save these for future runs (access token may rotate; refresh token is stored in ~/.buildautomaton/config.json when you use browser auth):"
|
|
36789
37143
|
);
|
|
36790
|
-
logFn(` export
|
|
36791
|
-
logFn(` export
|
|
37144
|
+
logFn(` export BUILDAUTOMATON_AUTH_TOKEN="${tokens.accessToken}"`);
|
|
37145
|
+
logFn(` export BUILDAUTOMATON_WORKSPACE_ID="${workspaceId}"`);
|
|
36792
37146
|
}
|
|
36793
37147
|
}
|
|
36794
37148
|
function handleClose(code, reason) {
|
|
@@ -36903,7 +37257,8 @@ async function createBridgeConnection(options) {
|
|
|
36903
37257
|
function getWs() {
|
|
36904
37258
|
return state.currentWs;
|
|
36905
37259
|
}
|
|
36906
|
-
const
|
|
37260
|
+
const e2ee = options.e2eCertificate ? createCliE2eeRuntime(options.e2eCertificate) : void 0;
|
|
37261
|
+
const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeCwd: getBridgeWorkspaceDirectory, e2ee });
|
|
36907
37262
|
const onBridgeIdentified = createOnBridgeIdentified({
|
|
36908
37263
|
sessionWorktreeManager,
|
|
36909
37264
|
devServerManager,
|
|
@@ -36922,7 +37277,8 @@ async function createBridgeConnection(options) {
|
|
|
36922
37277
|
onBridgeIdentified,
|
|
36923
37278
|
sendLocalSkillsReport,
|
|
36924
37279
|
reportAutoDetectedAgents,
|
|
36925
|
-
devServerManager
|
|
37280
|
+
devServerManager,
|
|
37281
|
+
e2ee
|
|
36926
37282
|
};
|
|
36927
37283
|
const { connect } = createMainBridgeWebSocketLifecycle({
|
|
36928
37284
|
state,
|
|
@@ -36934,7 +37290,8 @@ async function createBridgeConnection(options) {
|
|
|
36934
37290
|
messageDeps,
|
|
36935
37291
|
tokens,
|
|
36936
37292
|
persistTokens,
|
|
36937
|
-
onAuthInvalid
|
|
37293
|
+
onAuthInvalid,
|
|
37294
|
+
e2ee
|
|
36938
37295
|
});
|
|
36939
37296
|
connect();
|
|
36940
37297
|
const stopFileIndexWatcher = startFileIndexWatcher(getBridgeWorkspaceDirectory());
|
|
@@ -36946,14 +37303,149 @@ async function createBridgeConnection(options) {
|
|
|
36946
37303
|
};
|
|
36947
37304
|
}
|
|
36948
37305
|
|
|
37306
|
+
// src/e2e-certificates/key-command.ts
|
|
37307
|
+
import * as readline3 from "node:readline";
|
|
37308
|
+
function installE2eCertificateKeyCommand({
|
|
37309
|
+
log: log2,
|
|
37310
|
+
onOpenCertificate,
|
|
37311
|
+
onInterrupt
|
|
37312
|
+
}) {
|
|
37313
|
+
if (!process.stdin.isTTY || typeof process.stdin.setRawMode !== "function") {
|
|
37314
|
+
log2("[E2EE] Press c to import the E2EE key in a browser when running in an interactive terminal.");
|
|
37315
|
+
return () => {
|
|
37316
|
+
};
|
|
37317
|
+
}
|
|
37318
|
+
readline3.emitKeypressEvents(process.stdin);
|
|
37319
|
+
process.stdin.setRawMode(true);
|
|
37320
|
+
process.stdin.resume();
|
|
37321
|
+
const onKeypress = (str, key) => {
|
|
37322
|
+
if (key?.ctrl && key.name === "c") {
|
|
37323
|
+
onInterrupt();
|
|
37324
|
+
return;
|
|
37325
|
+
}
|
|
37326
|
+
if (!key?.ctrl && !key?.meta && (key?.name === "c" || str === "c")) {
|
|
37327
|
+
onOpenCertificate();
|
|
37328
|
+
}
|
|
37329
|
+
};
|
|
37330
|
+
process.stdin.on("keypress", onKeypress);
|
|
37331
|
+
log2("[E2EE] Press c to import the active E2EE key into the browser.");
|
|
37332
|
+
return () => {
|
|
37333
|
+
process.stdin.off("keypress", onKeypress);
|
|
37334
|
+
if (process.stdin.isTTY && typeof process.stdin.setRawMode === "function") {
|
|
37335
|
+
process.stdin.setRawMode(false);
|
|
37336
|
+
}
|
|
37337
|
+
};
|
|
37338
|
+
}
|
|
37339
|
+
|
|
37340
|
+
// src/e2e-certificates/open-import-url.ts
|
|
37341
|
+
async function openE2eCertificateImportUrl({
|
|
37342
|
+
apiUrl,
|
|
37343
|
+
workspaceId,
|
|
37344
|
+
certificate,
|
|
37345
|
+
log: log2
|
|
37346
|
+
}) {
|
|
37347
|
+
const appUrl = appUrlForApiUrl(apiUrl);
|
|
37348
|
+
const payload = encodeURIComponent(certificate.pemBundle);
|
|
37349
|
+
const url2 = `${appUrl.replace(/\/$/, "")}/w/${encodeURIComponent(workspaceId)}/settings/e2e-encryption?certificate=${payload}`;
|
|
37350
|
+
log2(`[E2EE] Opening browser to import key "${certificate.name}" (${certificate.id})...`);
|
|
37351
|
+
try {
|
|
37352
|
+
await open_default(url2, { wait: false });
|
|
37353
|
+
} catch {
|
|
37354
|
+
log2("[E2EE] Could not open browser. Open this URL manually:");
|
|
37355
|
+
log2(url2);
|
|
37356
|
+
}
|
|
37357
|
+
}
|
|
37358
|
+
|
|
37359
|
+
// src/run-bridge-connected.ts
|
|
37360
|
+
async function runConnectedBridge(options, restartWithoutAuth) {
|
|
37361
|
+
const {
|
|
37362
|
+
apiUrl,
|
|
37363
|
+
workspaceId,
|
|
37364
|
+
authToken,
|
|
37365
|
+
refreshToken,
|
|
37366
|
+
justAuthenticated,
|
|
37367
|
+
worktreesRootAbs,
|
|
37368
|
+
e2eCertificate
|
|
37369
|
+
} = options;
|
|
37370
|
+
const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
|
|
37371
|
+
let cleanupKeyCommand;
|
|
37372
|
+
const handle = await createBridgeConnection({
|
|
37373
|
+
apiUrl,
|
|
37374
|
+
workspaceId,
|
|
37375
|
+
authToken,
|
|
37376
|
+
refreshToken,
|
|
37377
|
+
firehoseServerUrl,
|
|
37378
|
+
justAuthenticated,
|
|
37379
|
+
worktreesRootAbs,
|
|
37380
|
+
e2eCertificate,
|
|
37381
|
+
log,
|
|
37382
|
+
persistTokens: (t) => {
|
|
37383
|
+
writeConfigForApi(apiUrl, {
|
|
37384
|
+
workspaceId,
|
|
37385
|
+
token: t.token,
|
|
37386
|
+
refreshToken: t.refreshToken
|
|
37387
|
+
});
|
|
37388
|
+
},
|
|
37389
|
+
onAuthInvalid: () => {
|
|
37390
|
+
cleanupKeyCommand?.();
|
|
37391
|
+
log("[Bridge service] Access token invalid or revoked; re-authenticating\u2026");
|
|
37392
|
+
clearConfigForApi(apiUrl);
|
|
37393
|
+
void handle.close().then(() => {
|
|
37394
|
+
void restartWithoutAuth({ apiUrl, firehoseServerUrl, worktreesRootAbs, e2eCertificate });
|
|
37395
|
+
});
|
|
37396
|
+
}
|
|
37397
|
+
});
|
|
37398
|
+
const onSignal = (kind) => {
|
|
37399
|
+
cleanupKeyCommand?.();
|
|
37400
|
+
logImmediate(
|
|
37401
|
+
kind === "interrupt" ? "Keyboard interrupt (Ctrl+C) \u2014 stopping\u2026" : "Stop requested \u2014 shutting down\u2026"
|
|
37402
|
+
);
|
|
37403
|
+
setImmediate(() => {
|
|
37404
|
+
void handle.close().then(() => {
|
|
37405
|
+
process.exit(0);
|
|
37406
|
+
});
|
|
37407
|
+
});
|
|
37408
|
+
};
|
|
37409
|
+
const onSigInt = () => onSignal("interrupt");
|
|
37410
|
+
const onSigTerm = () => onSignal("stop");
|
|
37411
|
+
process.on("SIGINT", onSigInt);
|
|
37412
|
+
process.on("SIGTERM", onSigTerm);
|
|
37413
|
+
if (e2eCertificate) {
|
|
37414
|
+
let openingCertificate = false;
|
|
37415
|
+
cleanupKeyCommand = installE2eCertificateKeyCommand({
|
|
37416
|
+
log,
|
|
37417
|
+
onInterrupt: onSigInt,
|
|
37418
|
+
onOpenCertificate: () => {
|
|
37419
|
+
if (openingCertificate) return;
|
|
37420
|
+
openingCertificate = true;
|
|
37421
|
+
void openE2eCertificateImportUrl({
|
|
37422
|
+
apiUrl,
|
|
37423
|
+
workspaceId,
|
|
37424
|
+
certificate: e2eCertificate,
|
|
37425
|
+
log
|
|
37426
|
+
}).finally(() => {
|
|
37427
|
+
openingCertificate = false;
|
|
37428
|
+
});
|
|
37429
|
+
}
|
|
37430
|
+
});
|
|
37431
|
+
}
|
|
37432
|
+
}
|
|
37433
|
+
|
|
36949
37434
|
// src/run-bridge.ts
|
|
36950
37435
|
async function runBridge(options) {
|
|
36951
37436
|
installBridgeProcessResilience();
|
|
36952
|
-
const {
|
|
37437
|
+
const {
|
|
37438
|
+
apiUrl,
|
|
37439
|
+
workspaceId,
|
|
37440
|
+
authToken,
|
|
37441
|
+
bridgeName,
|
|
37442
|
+
worktreesRootAbs,
|
|
37443
|
+
e2eCertificate
|
|
37444
|
+
} = options;
|
|
36953
37445
|
const firehoseServerUrl = options.firehoseServerUrl ?? options.proxyServerUrl;
|
|
36954
37446
|
const hasAuth = workspaceId && authToken;
|
|
36955
37447
|
if (!hasAuth) {
|
|
36956
|
-
const
|
|
37448
|
+
const handle = runPendingAuth({
|
|
36957
37449
|
apiUrl,
|
|
36958
37450
|
initialWorkspaceId: workspaceId,
|
|
36959
37451
|
preferredBridgeName: bridgeName,
|
|
@@ -36961,23 +37453,23 @@ async function runBridge(options) {
|
|
|
36961
37453
|
onAuth: (_auth) => {
|
|
36962
37454
|
}
|
|
36963
37455
|
});
|
|
36964
|
-
const
|
|
37456
|
+
const onSignal = (kind) => {
|
|
36965
37457
|
logImmediate(
|
|
36966
37458
|
kind === "interrupt" ? "Keyboard interrupt (Ctrl+C) \u2014 stopping\u2026" : "Stop requested \u2014 shutting down\u2026"
|
|
36967
37459
|
);
|
|
36968
37460
|
setImmediate(() => {
|
|
36969
|
-
|
|
37461
|
+
handle.close();
|
|
36970
37462
|
process.exit(0);
|
|
36971
37463
|
});
|
|
36972
37464
|
};
|
|
36973
|
-
const
|
|
36974
|
-
const
|
|
36975
|
-
process.on("SIGINT",
|
|
36976
|
-
process.on("SIGTERM",
|
|
36977
|
-
const auth = await
|
|
36978
|
-
process.off("SIGINT",
|
|
36979
|
-
process.off("SIGTERM",
|
|
36980
|
-
|
|
37465
|
+
const onSigInt = () => onSignal("interrupt");
|
|
37466
|
+
const onSigTerm = () => onSignal("stop");
|
|
37467
|
+
process.on("SIGINT", onSigInt);
|
|
37468
|
+
process.on("SIGTERM", onSigTerm);
|
|
37469
|
+
const auth = await handle.authPromise;
|
|
37470
|
+
process.off("SIGINT", onSigInt);
|
|
37471
|
+
process.off("SIGTERM", onSigTerm);
|
|
37472
|
+
handle.close();
|
|
36981
37473
|
if (!auth) return;
|
|
36982
37474
|
writeConfigForApi(apiUrl, {
|
|
36983
37475
|
workspaceId: auth.workspaceId,
|
|
@@ -36992,111 +37484,91 @@ async function runBridge(options) {
|
|
|
36992
37484
|
firehoseServerUrl,
|
|
36993
37485
|
bridgeName,
|
|
36994
37486
|
justAuthenticated: true,
|
|
36995
|
-
worktreesRootAbs
|
|
37487
|
+
worktreesRootAbs,
|
|
37488
|
+
e2eCertificate
|
|
36996
37489
|
});
|
|
36997
37490
|
return;
|
|
36998
37491
|
}
|
|
36999
|
-
|
|
37492
|
+
await runConnectedBridge(options, runBridge);
|
|
37493
|
+
}
|
|
37494
|
+
|
|
37495
|
+
// src/cli/run-cli-action.ts
|
|
37496
|
+
async function runCliAction(program2, opts) {
|
|
37497
|
+
const positionalUrl = program2.args?.[0];
|
|
37498
|
+
const urlFromPositional = typeof positionalUrl === "string" && /^https?:\/\//i.test(positionalUrl) ? positionalUrl : void 0;
|
|
37499
|
+
const apiUrlFromCli = opts.apiUrl ?? urlFromPositional;
|
|
37500
|
+
const apiUrl = apiUrlFromCli ?? DEFAULT_API_URL;
|
|
37501
|
+
let workspaceId = opts.workspaceId ?? "";
|
|
37502
|
+
let authToken = opts.token;
|
|
37503
|
+
const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
|
|
37504
|
+
if (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim()) {
|
|
37505
|
+
const resolvedCwd = path33.resolve(process.cwd(), opts.cwd.trim());
|
|
37506
|
+
try {
|
|
37507
|
+
const st = fs30.statSync(resolvedCwd);
|
|
37508
|
+
if (!st.isDirectory()) {
|
|
37509
|
+
console.error(`--cwd is not a directory: ${resolvedCwd}`);
|
|
37510
|
+
process.exit(1);
|
|
37511
|
+
}
|
|
37512
|
+
} catch {
|
|
37513
|
+
console.error(`--cwd path does not exist or is not accessible: ${resolvedCwd}`);
|
|
37514
|
+
process.exit(1);
|
|
37515
|
+
}
|
|
37516
|
+
process.chdir(resolvedCwd);
|
|
37517
|
+
}
|
|
37518
|
+
initBridgeWorkspaceDirectory();
|
|
37519
|
+
let worktreesRootAbs;
|
|
37520
|
+
if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
|
|
37521
|
+
worktreesRootAbs = path33.resolve(opts.worktreesRoot.trim());
|
|
37522
|
+
}
|
|
37523
|
+
const e2eCertificates = opts.e2eeCertificatesDir?.trim() ? await loadOrCreateE2eCertificates(opts.e2eeCertificatesDir.trim()) : void 0;
|
|
37524
|
+
if (e2eCertificates) {
|
|
37525
|
+
const action = e2eCertificates.generated ? "Generated" : "Loaded";
|
|
37526
|
+
console.log(
|
|
37527
|
+
`[E2EE] ${action} ${e2eCertificates.certificates.length} key${e2eCertificates.certificates.length === 1 ? "" : "s"} from ${e2eCertificates.directory}`
|
|
37528
|
+
);
|
|
37529
|
+
console.log(
|
|
37530
|
+
`[E2EE] Active key: ${e2eCertificates.activeCertificate.name} (${e2eCertificates.activeCertificate.id})`
|
|
37531
|
+
);
|
|
37532
|
+
}
|
|
37533
|
+
let refreshToken;
|
|
37534
|
+
if ((!workspaceId || !authToken) && opts.config !== false) {
|
|
37535
|
+
const saved = readConfigForApi(apiUrl);
|
|
37536
|
+
if (saved?.workspaceId && saved?.token) {
|
|
37537
|
+
if (!workspaceId) workspaceId = saved.workspaceId;
|
|
37538
|
+
if (!authToken) authToken = saved.token;
|
|
37539
|
+
refreshToken = saved.refreshToken;
|
|
37540
|
+
}
|
|
37541
|
+
}
|
|
37542
|
+
await runBridge({
|
|
37000
37543
|
apiUrl,
|
|
37001
|
-
workspaceId,
|
|
37544
|
+
workspaceId: workspaceId || void 0,
|
|
37002
37545
|
authToken,
|
|
37003
37546
|
refreshToken,
|
|
37004
37547
|
firehoseServerUrl,
|
|
37005
|
-
|
|
37548
|
+
bridgeName: opts.name?.trim() || void 0,
|
|
37006
37549
|
worktreesRootAbs,
|
|
37007
|
-
|
|
37008
|
-
persistTokens: (t) => {
|
|
37009
|
-
writeConfigForApi(apiUrl, {
|
|
37010
|
-
workspaceId,
|
|
37011
|
-
token: t.token,
|
|
37012
|
-
refreshToken: t.refreshToken
|
|
37013
|
-
});
|
|
37014
|
-
},
|
|
37015
|
-
onAuthInvalid: () => {
|
|
37016
|
-
log("[Bridge service] Access token invalid or revoked; re-authenticating\u2026");
|
|
37017
|
-
clearConfigForApi(apiUrl);
|
|
37018
|
-
void handle.close().then(() => {
|
|
37019
|
-
void runBridge({ apiUrl, firehoseServerUrl, worktreesRootAbs });
|
|
37020
|
-
});
|
|
37021
|
-
}
|
|
37550
|
+
e2eCertificate: e2eCertificates?.activeCertificate
|
|
37022
37551
|
});
|
|
37023
|
-
const onSignal = (kind) => {
|
|
37024
|
-
logImmediate(
|
|
37025
|
-
kind === "interrupt" ? "Keyboard interrupt (Ctrl+C) \u2014 stopping\u2026" : "Stop requested \u2014 shutting down\u2026"
|
|
37026
|
-
);
|
|
37027
|
-
setImmediate(() => {
|
|
37028
|
-
void handle.close().then(() => {
|
|
37029
|
-
process.exit(0);
|
|
37030
|
-
});
|
|
37031
|
-
});
|
|
37032
|
-
};
|
|
37033
|
-
const onSigInt = () => onSignal("interrupt");
|
|
37034
|
-
const onSigTerm = () => onSignal("stop");
|
|
37035
|
-
process.on("SIGINT", onSigInt);
|
|
37036
|
-
process.on("SIGTERM", onSigTerm);
|
|
37037
37552
|
}
|
|
37038
37553
|
|
|
37039
37554
|
// src/cli.ts
|
|
37040
|
-
var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
|
|
37041
|
-
var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
|
|
37042
37555
|
async function main() {
|
|
37043
37556
|
const program2 = new Command();
|
|
37044
|
-
program2.name("buildautomaton").description("CLI for BuildAutomaton: ACP client, WebSocket bridge to backend, and skills (e.g. preview)").version("0.1.0").option("-u, --api-url <url>", "Backend API URL", process.env.BUILDAUTOMATON_API_URL ?? DEFAULT_API_URL).option("-w, --workspace-id <id>", "Workspace ID (or set
|
|
37557
|
+
program2.name("buildautomaton").description("CLI for BuildAutomaton: ACP client, WebSocket bridge to backend, and skills (e.g. preview)").version("0.1.0").option("-u, --api-url <url>", "Backend API URL", process.env.BUILDAUTOMATON_API_URL ?? DEFAULT_API_URL).option("-w, --workspace-id <id>", "Workspace ID (or set BUILDAUTOMATON_WORKSPACE_ID)", process.env.BUILDAUTOMATON_WORKSPACE_ID).option("-t, --token <token>", "Auth token (or set BUILDAUTOMATON_AUTH_TOKEN)", process.env.BUILDAUTOMATON_AUTH_TOKEN).option(
|
|
37045
37558
|
"--firehose-url <url>",
|
|
37046
|
-
"Firehose server URL (default: Fly app; or
|
|
37047
|
-
process.env.
|
|
37559
|
+
"Firehose server URL (default: Fly app; or BUILDAUTOMATON_FIREHOSE_URL / legacy BUILDAUTOMATON_PROXY_URL)",
|
|
37560
|
+
process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL
|
|
37048
37561
|
).option("--proxy-url <url>", "Deprecated alias for --firehose-url", void 0).option(
|
|
37049
37562
|
"--cwd <path>",
|
|
37050
37563
|
"Working directory for the bridge (absolute or relative to the current directory); affects skills, git, file index, and agent cwd"
|
|
37051
37564
|
).option("-n, --name <name>", "Bridge name when creating via browser (alphanumeric and underscores only)").option(
|
|
37052
37565
|
"--worktrees-root <path>",
|
|
37053
37566
|
"Root directory for per-session git worktrees (default: ~/.buildautomaton/worktrees). Whether worktrees are used is controlled in the cloud for each bridge token."
|
|
37054
|
-
).option(
|
|
37055
|
-
|
|
37056
|
-
|
|
37057
|
-
|
|
37058
|
-
|
|
37059
|
-
let workspaceId = opts.workspaceId ?? "";
|
|
37060
|
-
let authToken = opts.token;
|
|
37061
|
-
const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAMATON_FIREHOSE_URL ?? process.env.BUILDAMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
|
|
37062
|
-
if (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim()) {
|
|
37063
|
-
const resolvedCwd = path32.resolve(process.cwd(), opts.cwd.trim());
|
|
37064
|
-
try {
|
|
37065
|
-
const st = fs29.statSync(resolvedCwd);
|
|
37066
|
-
if (!st.isDirectory()) {
|
|
37067
|
-
console.error(`--cwd is not a directory: ${resolvedCwd}`);
|
|
37068
|
-
process.exit(1);
|
|
37069
|
-
}
|
|
37070
|
-
} catch {
|
|
37071
|
-
console.error(`--cwd path does not exist or is not accessible: ${resolvedCwd}`);
|
|
37072
|
-
process.exit(1);
|
|
37073
|
-
}
|
|
37074
|
-
process.chdir(resolvedCwd);
|
|
37075
|
-
}
|
|
37076
|
-
initBridgeWorkspaceDirectory();
|
|
37077
|
-
let worktreesRootAbs;
|
|
37078
|
-
if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
|
|
37079
|
-
worktreesRootAbs = path32.resolve(opts.worktreesRoot.trim());
|
|
37080
|
-
}
|
|
37081
|
-
let refreshToken;
|
|
37082
|
-
if ((!workspaceId || !authToken) && opts.config !== false) {
|
|
37083
|
-
const saved = readConfigForApi(apiUrl);
|
|
37084
|
-
if (saved?.workspaceId && saved?.token) {
|
|
37085
|
-
if (!workspaceId) workspaceId = saved.workspaceId;
|
|
37086
|
-
if (!authToken) authToken = saved.token;
|
|
37087
|
-
refreshToken = saved.refreshToken;
|
|
37088
|
-
}
|
|
37089
|
-
}
|
|
37090
|
-
await runBridge({
|
|
37091
|
-
apiUrl,
|
|
37092
|
-
workspaceId: workspaceId || void 0,
|
|
37093
|
-
authToken,
|
|
37094
|
-
refreshToken,
|
|
37095
|
-
firehoseServerUrl,
|
|
37096
|
-
bridgeName: opts.name?.trim() || void 0,
|
|
37097
|
-
worktreesRootAbs
|
|
37098
|
-
});
|
|
37099
|
-
});
|
|
37567
|
+
).option(
|
|
37568
|
+
"--e2ee-certificates-dir <path>",
|
|
37569
|
+
"Directory to load or generate E2EE keys for sessions, files, and logs",
|
|
37570
|
+
process.env.BUILDAUTOMATON_E2EE_CERTIFICATES_DIR
|
|
37571
|
+
).option("--no-config", "Ignore saved config at ~/.buildautomaton/config.json").action(async (opts) => runCliAction(program2, opts));
|
|
37100
37572
|
await program2.parseAsync(process.argv);
|
|
37101
37573
|
}
|
|
37102
37574
|
main().catch((err) => {
|