@buildautomaton/cli 0.1.18 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +679 -346
- package/dist/cli.js.map +4 -4
- package/dist/index.js +656 -323
- package/dist/index.js.map +4 -4
- package/package.json +4 -3
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 path36 = __require("node:path");
|
|
977
|
+
var fs34 = __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 = path36.resolve(baseDir, baseName);
|
|
1910
|
+
if (fs34.existsSync(localBin)) return localBin;
|
|
1911
|
+
if (sourceExt.includes(path36.extname(baseName))) return void 0;
|
|
1912
1912
|
const foundExt = sourceExt.find(
|
|
1913
|
-
(ext) =>
|
|
1913
|
+
(ext) => fs34.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 = fs34.realpathSync(this._scriptPath);
|
|
1926
1926
|
} catch (err) {
|
|
1927
1927
|
resolvedScriptPath = this._scriptPath;
|
|
1928
1928
|
}
|
|
1929
|
-
executableDir =
|
|
1930
|
-
|
|
1929
|
+
executableDir = path36.resolve(
|
|
1930
|
+
path36.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 = path36.basename(
|
|
1938
1938
|
this._scriptPath,
|
|
1939
|
-
|
|
1939
|
+
path36.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(path36.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 = path36.basename(filename, path36.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(path37) {
|
|
2805
|
+
if (path37 === void 0) return this._executableDir;
|
|
2806
|
+
this._executableDir = path37;
|
|
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: randomBytes3, createHash:
|
|
5239
|
+
var { randomBytes: randomBytes3, createHash: createHash2 } = __require("crypto");
|
|
5240
5240
|
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
5241
5241
|
var { URL: URL2 } = __require("url");
|
|
5242
5242
|
var PerMessageDeflate = require_permessage_deflate();
|
|
@@ -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 = createHash2("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: createHash2 } = __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 = createHash2("sha1").update(key + GUID).digest("base64");
|
|
6568
6568
|
const headers = [
|
|
6569
6569
|
"HTTP/1.1 101 Switching Protocols",
|
|
6570
6570
|
"Upgrade: websocket",
|
|
@@ -7129,7 +7129,7 @@ var require_has_flag = __commonJS({
|
|
|
7129
7129
|
var require_supports_color = __commonJS({
|
|
7130
7130
|
"../../node_modules/.pnpm/supports-color@7.2.0/node_modules/supports-color/index.js"(exports, module) {
|
|
7131
7131
|
"use strict";
|
|
7132
|
-
var
|
|
7132
|
+
var os7 = __require("os");
|
|
7133
7133
|
var tty = __require("tty");
|
|
7134
7134
|
var hasFlag = require_has_flag();
|
|
7135
7135
|
var { env } = process;
|
|
@@ -7177,7 +7177,7 @@ var require_supports_color = __commonJS({
|
|
|
7177
7177
|
return min;
|
|
7178
7178
|
}
|
|
7179
7179
|
if (process.platform === "win32") {
|
|
7180
|
-
const osRelease =
|
|
7180
|
+
const osRelease = os7.release().split(".");
|
|
7181
7181
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
7182
7182
|
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
7183
7183
|
}
|
|
@@ -7423,10 +7423,10 @@ 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(path36, isFile, isDirectory) {
|
|
7427
|
+
log2(`checking %s`, path36);
|
|
7428
7428
|
try {
|
|
7429
|
-
const stat3 = fs_1.statSync(
|
|
7429
|
+
const stat3 = fs_1.statSync(path36);
|
|
7430
7430
|
if (stat3.isFile() && isFile) {
|
|
7431
7431
|
log2(`[OK] path represents a file`);
|
|
7432
7432
|
return true;
|
|
@@ -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(path36, type = exports.READABLE) {
|
|
7450
|
+
return check2(path36, (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: path36, errorMaps, issueData } = params;
|
|
7926
|
+
const fullPath = [...path36, ...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, path36, key) {
|
|
8235
8235
|
this._cachedPath = [];
|
|
8236
8236
|
this.parent = parent;
|
|
8237
8237
|
this.data = value;
|
|
8238
|
-
this._path =
|
|
8238
|
+
this._path = path36;
|
|
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, path36) {
|
|
11854
|
+
if (!path36)
|
|
11855
11855
|
return obj;
|
|
11856
|
-
return
|
|
11856
|
+
return path36.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(path36, 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(path36);
|
|
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, path36 = []) => {
|
|
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 = [...path36, ...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(path36) {
|
|
12339
12339
|
const segs = [];
|
|
12340
|
-
for (const seg of
|
|
12340
|
+
for (const seg of path36) {
|
|
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((resolve18) => {
|
|
24804
|
+
this.#abortController.signal.addEventListener("abort", () => resolve18());
|
|
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((resolve18, reject) => {
|
|
24954
|
+
this.#pendingResponses.set(id, { resolve: resolve18, reject });
|
|
24955
24955
|
});
|
|
24956
24956
|
await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
|
|
24957
24957
|
return responsePromise;
|
|
@@ -25063,13 +25063,16 @@ var {
|
|
|
25063
25063
|
Help
|
|
25064
25064
|
} = import_index.default;
|
|
25065
25065
|
|
|
25066
|
+
// src/cli-version.ts
|
|
25067
|
+
var CLI_VERSION = "0.1.20".length > 0 ? "0.1.20" : "0.0.0-dev";
|
|
25068
|
+
|
|
25066
25069
|
// src/cli/defaults.ts
|
|
25067
25070
|
var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
|
|
25068
25071
|
var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
|
|
25069
25072
|
|
|
25070
25073
|
// src/cli/run-cli-action.ts
|
|
25071
|
-
import * as
|
|
25072
|
-
import * as
|
|
25074
|
+
import * as fs33 from "node:fs";
|
|
25075
|
+
import * as path35 from "node:path";
|
|
25073
25076
|
|
|
25074
25077
|
// src/config.ts
|
|
25075
25078
|
import fs from "node:fs";
|
|
@@ -26034,14 +26037,14 @@ var baseOpen = async (options) => {
|
|
|
26034
26037
|
}
|
|
26035
26038
|
const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
|
|
26036
26039
|
if (options.wait) {
|
|
26037
|
-
return new Promise((
|
|
26040
|
+
return new Promise((resolve18, reject) => {
|
|
26038
26041
|
subprocess.once("error", reject);
|
|
26039
26042
|
subprocess.once("close", (exitCode) => {
|
|
26040
26043
|
if (!options.allowNonzeroExitCode && exitCode > 0) {
|
|
26041
26044
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
26042
26045
|
return;
|
|
26043
26046
|
}
|
|
26044
|
-
|
|
26047
|
+
resolve18(subprocess);
|
|
26045
26048
|
});
|
|
26046
26049
|
});
|
|
26047
26050
|
}
|
|
@@ -26337,8 +26340,8 @@ function runPendingAuth(options) {
|
|
|
26337
26340
|
let hasOpenedBrowser = false;
|
|
26338
26341
|
let resolved = false;
|
|
26339
26342
|
let resolveAuth;
|
|
26340
|
-
const authPromise = new Promise((
|
|
26341
|
-
resolveAuth =
|
|
26343
|
+
const authPromise = new Promise((resolve18) => {
|
|
26344
|
+
resolveAuth = resolve18;
|
|
26342
26345
|
});
|
|
26343
26346
|
let reconnectAttempt = 0;
|
|
26344
26347
|
const signInQuiet = createEmptyReconnectQuietSlot();
|
|
@@ -26390,7 +26393,7 @@ function runPendingAuth(options) {
|
|
|
26390
26393
|
url: url2,
|
|
26391
26394
|
onOpen: () => {
|
|
26392
26395
|
clearQuietOnOpen();
|
|
26393
|
-
sendWsMessage(ws, { type: "identify", role: "cli" });
|
|
26396
|
+
sendWsMessage(ws, { type: "identify", role: "cli", cliVersion: CLI_VERSION });
|
|
26394
26397
|
keepaliveInterval = setInterval(() => {
|
|
26395
26398
|
if (resolved || !ws || ws.readyState !== 1) return;
|
|
26396
26399
|
sendWsMessage(ws, { type: "ping", timestamp: Date.now() });
|
|
@@ -26460,7 +26463,7 @@ function runPendingAuth(options) {
|
|
|
26460
26463
|
async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
|
|
26461
26464
|
const say = log2 ?? logImmediate;
|
|
26462
26465
|
say("Cleaning up connections\u2026");
|
|
26463
|
-
await new Promise((
|
|
26466
|
+
await new Promise((resolve18) => setImmediate(resolve18));
|
|
26464
26467
|
state.closedByUser = true;
|
|
26465
26468
|
clearReconnectQuietTimer(state.mainQuiet);
|
|
26466
26469
|
clearReconnectQuietTimer(state.firehoseQuiet);
|
|
@@ -26582,8 +26585,8 @@ function pathspec(...paths) {
|
|
|
26582
26585
|
cache.set(key, paths);
|
|
26583
26586
|
return key;
|
|
26584
26587
|
}
|
|
26585
|
-
function isPathSpec(
|
|
26586
|
-
return
|
|
26588
|
+
function isPathSpec(path36) {
|
|
26589
|
+
return path36 instanceof String && cache.has(path36);
|
|
26587
26590
|
}
|
|
26588
26591
|
function toPaths(pathSpec) {
|
|
26589
26592
|
return cache.get(pathSpec) || [];
|
|
@@ -26672,8 +26675,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
26672
26675
|
function forEachLineWithContent(input, callback) {
|
|
26673
26676
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
26674
26677
|
}
|
|
26675
|
-
function folderExists(
|
|
26676
|
-
return (0, import_file_exists.exists)(
|
|
26678
|
+
function folderExists(path36) {
|
|
26679
|
+
return (0, import_file_exists.exists)(path36, import_file_exists.FOLDER);
|
|
26677
26680
|
}
|
|
26678
26681
|
function append(target, item) {
|
|
26679
26682
|
if (Array.isArray(target)) {
|
|
@@ -27077,8 +27080,8 @@ function checkIsRepoRootTask() {
|
|
|
27077
27080
|
commands,
|
|
27078
27081
|
format: "utf-8",
|
|
27079
27082
|
onError,
|
|
27080
|
-
parser(
|
|
27081
|
-
return /^\.(git)?$/.test(
|
|
27083
|
+
parser(path36) {
|
|
27084
|
+
return /^\.(git)?$/.test(path36.trim());
|
|
27082
27085
|
}
|
|
27083
27086
|
};
|
|
27084
27087
|
}
|
|
@@ -27512,11 +27515,11 @@ function parseGrep(grep) {
|
|
|
27512
27515
|
const paths = /* @__PURE__ */ new Set();
|
|
27513
27516
|
const results = {};
|
|
27514
27517
|
forEachLineWithContent(grep, (input) => {
|
|
27515
|
-
const [
|
|
27516
|
-
paths.add(
|
|
27517
|
-
(results[
|
|
27518
|
+
const [path36, line, preview] = input.split(NULL);
|
|
27519
|
+
paths.add(path36);
|
|
27520
|
+
(results[path36] = results[path36] || []).push({
|
|
27518
27521
|
line: asNumber(line),
|
|
27519
|
-
path:
|
|
27522
|
+
path: path36,
|
|
27520
27523
|
preview
|
|
27521
27524
|
});
|
|
27522
27525
|
});
|
|
@@ -28281,14 +28284,14 @@ var init_hash_object = __esm2({
|
|
|
28281
28284
|
init_task();
|
|
28282
28285
|
}
|
|
28283
28286
|
});
|
|
28284
|
-
function parseInit(bare,
|
|
28287
|
+
function parseInit(bare, path36, text) {
|
|
28285
28288
|
const response = String(text).trim();
|
|
28286
28289
|
let result;
|
|
28287
28290
|
if (result = initResponseRegex.exec(response)) {
|
|
28288
|
-
return new InitSummary(bare,
|
|
28291
|
+
return new InitSummary(bare, path36, false, result[1]);
|
|
28289
28292
|
}
|
|
28290
28293
|
if (result = reInitResponseRegex.exec(response)) {
|
|
28291
|
-
return new InitSummary(bare,
|
|
28294
|
+
return new InitSummary(bare, path36, true, result[1]);
|
|
28292
28295
|
}
|
|
28293
28296
|
let gitDir = "";
|
|
28294
28297
|
const tokens = response.split(" ");
|
|
@@ -28299,7 +28302,7 @@ function parseInit(bare, path34, text) {
|
|
|
28299
28302
|
break;
|
|
28300
28303
|
}
|
|
28301
28304
|
}
|
|
28302
|
-
return new InitSummary(bare,
|
|
28305
|
+
return new InitSummary(bare, path36, /^re/i.test(response), gitDir);
|
|
28303
28306
|
}
|
|
28304
28307
|
var InitSummary;
|
|
28305
28308
|
var initResponseRegex;
|
|
@@ -28308,9 +28311,9 @@ var init_InitSummary = __esm2({
|
|
|
28308
28311
|
"src/lib/responses/InitSummary.ts"() {
|
|
28309
28312
|
"use strict";
|
|
28310
28313
|
InitSummary = class {
|
|
28311
|
-
constructor(bare,
|
|
28314
|
+
constructor(bare, path36, existing, gitDir) {
|
|
28312
28315
|
this.bare = bare;
|
|
28313
|
-
this.path =
|
|
28316
|
+
this.path = path36;
|
|
28314
28317
|
this.existing = existing;
|
|
28315
28318
|
this.gitDir = gitDir;
|
|
28316
28319
|
}
|
|
@@ -28322,7 +28325,7 @@ var init_InitSummary = __esm2({
|
|
|
28322
28325
|
function hasBareCommand(command) {
|
|
28323
28326
|
return command.includes(bareCommand);
|
|
28324
28327
|
}
|
|
28325
|
-
function initTask(bare = false,
|
|
28328
|
+
function initTask(bare = false, path36, customArgs) {
|
|
28326
28329
|
const commands = ["init", ...customArgs];
|
|
28327
28330
|
if (bare && !hasBareCommand(commands)) {
|
|
28328
28331
|
commands.splice(1, 0, bareCommand);
|
|
@@ -28331,7 +28334,7 @@ function initTask(bare = false, path34, customArgs) {
|
|
|
28331
28334
|
commands,
|
|
28332
28335
|
format: "utf-8",
|
|
28333
28336
|
parser(text) {
|
|
28334
|
-
return parseInit(commands.includes("--bare"),
|
|
28337
|
+
return parseInit(commands.includes("--bare"), path36, text);
|
|
28335
28338
|
}
|
|
28336
28339
|
};
|
|
28337
28340
|
}
|
|
@@ -29147,12 +29150,12 @@ var init_FileStatusSummary = __esm2({
|
|
|
29147
29150
|
"use strict";
|
|
29148
29151
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
29149
29152
|
FileStatusSummary = class {
|
|
29150
|
-
constructor(
|
|
29151
|
-
this.path =
|
|
29153
|
+
constructor(path36, index, working_dir) {
|
|
29154
|
+
this.path = path36;
|
|
29152
29155
|
this.index = index;
|
|
29153
29156
|
this.working_dir = working_dir;
|
|
29154
29157
|
if (index === "R" || working_dir === "R") {
|
|
29155
|
-
const detail = fromPathRegex.exec(
|
|
29158
|
+
const detail = fromPathRegex.exec(path36) || [null, path36, path36];
|
|
29156
29159
|
this.from = detail[2] || "";
|
|
29157
29160
|
this.path = detail[1] || "";
|
|
29158
29161
|
}
|
|
@@ -29183,14 +29186,14 @@ function splitLine(result, lineStr) {
|
|
|
29183
29186
|
default:
|
|
29184
29187
|
return;
|
|
29185
29188
|
}
|
|
29186
|
-
function data(index, workingDir,
|
|
29189
|
+
function data(index, workingDir, path36) {
|
|
29187
29190
|
const raw = `${index}${workingDir}`;
|
|
29188
29191
|
const handler = parsers6.get(raw);
|
|
29189
29192
|
if (handler) {
|
|
29190
|
-
handler(result,
|
|
29193
|
+
handler(result, path36);
|
|
29191
29194
|
}
|
|
29192
29195
|
if (raw !== "##" && raw !== "!!") {
|
|
29193
|
-
result.files.push(new FileStatusSummary(
|
|
29196
|
+
result.files.push(new FileStatusSummary(path36, index, workingDir));
|
|
29194
29197
|
}
|
|
29195
29198
|
}
|
|
29196
29199
|
}
|
|
@@ -29499,9 +29502,9 @@ var init_simple_git_api = __esm2({
|
|
|
29499
29502
|
next
|
|
29500
29503
|
);
|
|
29501
29504
|
}
|
|
29502
|
-
hashObject(
|
|
29505
|
+
hashObject(path36, write) {
|
|
29503
29506
|
return this._runTask(
|
|
29504
|
-
hashObjectTask(
|
|
29507
|
+
hashObjectTask(path36, write === true),
|
|
29505
29508
|
trailingFunctionArgument(arguments)
|
|
29506
29509
|
);
|
|
29507
29510
|
}
|
|
@@ -29854,8 +29857,8 @@ var init_branch = __esm2({
|
|
|
29854
29857
|
}
|
|
29855
29858
|
});
|
|
29856
29859
|
function toPath(input) {
|
|
29857
|
-
const
|
|
29858
|
-
return
|
|
29860
|
+
const path36 = input.trim().replace(/^["']|["']$/g, "");
|
|
29861
|
+
return path36 && normalize(path36);
|
|
29859
29862
|
}
|
|
29860
29863
|
var parseCheckIgnore;
|
|
29861
29864
|
var init_CheckIgnore = __esm2({
|
|
@@ -30169,8 +30172,8 @@ __export2(sub_module_exports, {
|
|
|
30169
30172
|
subModuleTask: () => subModuleTask,
|
|
30170
30173
|
updateSubModuleTask: () => updateSubModuleTask
|
|
30171
30174
|
});
|
|
30172
|
-
function addSubModuleTask(repo,
|
|
30173
|
-
return subModuleTask(["add", repo,
|
|
30175
|
+
function addSubModuleTask(repo, path36) {
|
|
30176
|
+
return subModuleTask(["add", repo, path36]);
|
|
30174
30177
|
}
|
|
30175
30178
|
function initSubModuleTask(customArgs) {
|
|
30176
30179
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -30503,8 +30506,8 @@ var require_git = __commonJS2({
|
|
|
30503
30506
|
}
|
|
30504
30507
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
30505
30508
|
};
|
|
30506
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
30507
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
30509
|
+
Git2.prototype.submoduleAdd = function(repo, path36, then) {
|
|
30510
|
+
return this._runTask(addSubModuleTask2(repo, path36), trailingFunctionArgument2(arguments));
|
|
30508
30511
|
};
|
|
30509
30512
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
30510
30513
|
return this._runTask(
|
|
@@ -31364,18 +31367,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
31364
31367
|
}
|
|
31365
31368
|
}
|
|
31366
31369
|
|
|
31367
|
-
// ../types/
|
|
31368
|
-
init_zod();
|
|
31369
|
-
init_zod();
|
|
31370
|
-
init_zod();
|
|
31371
|
-
init_zod();
|
|
31372
|
-
init_zod();
|
|
31373
|
-
init_zod();
|
|
31374
|
-
init_zod();
|
|
31375
|
-
init_zod();
|
|
31376
|
-
init_zod();
|
|
31377
|
-
init_zod();
|
|
31378
|
-
init_zod();
|
|
31370
|
+
// ../types/src/work-items.ts
|
|
31379
31371
|
init_zod();
|
|
31380
31372
|
var WorkItemStatusSchema = external_exports.enum(["backlog", "in-progress", "completed"]);
|
|
31381
31373
|
var WorkItemProgressSchema = external_exports.object({
|
|
@@ -31416,6 +31408,9 @@ var WorkItemSchema = external_exports.object({
|
|
|
31416
31408
|
dependencies: external_exports.array(WorkItemDependencySchema).default([]),
|
|
31417
31409
|
assignedToUserId: external_exports.string().optional()
|
|
31418
31410
|
});
|
|
31411
|
+
|
|
31412
|
+
// ../types/src/user-profiles.ts
|
|
31413
|
+
init_zod();
|
|
31419
31414
|
var UserWorkspaceProfileSchema = external_exports.object({
|
|
31420
31415
|
id: external_exports.string(),
|
|
31421
31416
|
workspaceId: external_exports.string(),
|
|
@@ -31425,6 +31420,9 @@ var UserWorkspaceProfileSchema = external_exports.object({
|
|
|
31425
31420
|
preferences: external_exports.record(external_exports.unknown()).optional(),
|
|
31426
31421
|
learnings: external_exports.array(external_exports.string())
|
|
31427
31422
|
});
|
|
31423
|
+
|
|
31424
|
+
// ../types/src/runtime.ts
|
|
31425
|
+
init_zod();
|
|
31428
31426
|
var WorkspaceOwnerInfoSchema = external_exports.object({
|
|
31429
31427
|
ownerId: external_exports.string(),
|
|
31430
31428
|
ownerName: external_exports.string().optional(),
|
|
@@ -31438,6 +31436,9 @@ var WorkspaceRuntimeEntrySchema = external_exports.object({
|
|
|
31438
31436
|
owner: WorkspaceOwnerInfoSchema.optional(),
|
|
31439
31437
|
isOwner: external_exports.boolean().optional()
|
|
31440
31438
|
});
|
|
31439
|
+
|
|
31440
|
+
// ../types/src/agent.ts
|
|
31441
|
+
init_zod();
|
|
31441
31442
|
var ProjectContextSchema = external_exports.object({
|
|
31442
31443
|
projectId: external_exports.string(),
|
|
31443
31444
|
context: external_exports.record(external_exports.unknown()).default({}),
|
|
@@ -31462,6 +31463,9 @@ var WebSocketMessageSchema = external_exports.object({
|
|
|
31462
31463
|
data: external_exports.any().optional(),
|
|
31463
31464
|
error: external_exports.string().optional()
|
|
31464
31465
|
});
|
|
31466
|
+
|
|
31467
|
+
// ../types/src/checkpoints.ts
|
|
31468
|
+
init_zod();
|
|
31465
31469
|
var CheckpointKindSchema = external_exports.enum(["daily", "weekly", "overall"]);
|
|
31466
31470
|
var CheckpointSummarySchema = external_exports.object({
|
|
31467
31471
|
id: external_exports.string(),
|
|
@@ -31472,6 +31476,9 @@ var CheckpointSummarySchema = external_exports.object({
|
|
|
31472
31476
|
createdAt: external_exports.string(),
|
|
31473
31477
|
updatedAt: external_exports.string()
|
|
31474
31478
|
});
|
|
31479
|
+
|
|
31480
|
+
// ../types/src/threads.ts
|
|
31481
|
+
init_zod();
|
|
31475
31482
|
var ThreadMetaSchema = external_exports.object({
|
|
31476
31483
|
threadId: external_exports.string(),
|
|
31477
31484
|
workspaceId: external_exports.string(),
|
|
@@ -31499,6 +31506,9 @@ var ThreadMessageSchema = external_exports.object({
|
|
|
31499
31506
|
var ThreadCheckpointSummarySchema = CheckpointSummarySchema.extend({
|
|
31500
31507
|
threadId: external_exports.string()
|
|
31501
31508
|
});
|
|
31509
|
+
|
|
31510
|
+
// ../types/src/content-items.ts
|
|
31511
|
+
init_zod();
|
|
31502
31512
|
var ContentSourceSchema = external_exports.enum(["notion", "doc", "slack_thread", "other"]);
|
|
31503
31513
|
var ContentItemMetaSchema = external_exports.object({
|
|
31504
31514
|
contentId: external_exports.string(),
|
|
@@ -31520,6 +31530,9 @@ var ContentStorageRefSchema = external_exports.object({
|
|
|
31520
31530
|
var ContentCheckpointSummarySchema = CheckpointSummarySchema.extend({
|
|
31521
31531
|
contentId: external_exports.string()
|
|
31522
31532
|
});
|
|
31533
|
+
|
|
31534
|
+
// ../types/src/stories.ts
|
|
31535
|
+
init_zod();
|
|
31523
31536
|
var StoryMetaSchema = external_exports.object({
|
|
31524
31537
|
storyId: external_exports.string(),
|
|
31525
31538
|
workspaceId: external_exports.string(),
|
|
@@ -31542,6 +31555,9 @@ var StoryContentItemRefSchema = external_exports.object({
|
|
|
31542
31555
|
var StoryCheckpointSummarySchema = CheckpointSummarySchema.extend({
|
|
31543
31556
|
storyId: external_exports.string()
|
|
31544
31557
|
});
|
|
31558
|
+
|
|
31559
|
+
// ../types/src/sessions.ts
|
|
31560
|
+
init_zod();
|
|
31545
31561
|
var BUILTIN_SESSION_CHANGE_SUMMARY_FOLLOW_UP_CATALOG_PROMPT_ID = "__builtin_change_summary__";
|
|
31546
31562
|
var SessionMetaSchema = external_exports.object({
|
|
31547
31563
|
sessionId: external_exports.string(),
|
|
@@ -31584,6 +31600,8 @@ var SessionThreadRefSchema = external_exports.object({
|
|
|
31584
31600
|
threadId: external_exports.string(),
|
|
31585
31601
|
addedAt: external_exports.string()
|
|
31586
31602
|
});
|
|
31603
|
+
|
|
31604
|
+
// ../types/src/change-summary-path.ts
|
|
31587
31605
|
function normalizeRepoRelativePath(p) {
|
|
31588
31606
|
let t = p.trim().replace(/\\/g, "/");
|
|
31589
31607
|
while (t.startsWith("./")) t = t.slice(2);
|
|
@@ -31600,6 +31618,8 @@ function resolveChangeSummaryPathAgainstAllowed(rawPath, allowed) {
|
|
|
31600
31618
|
}
|
|
31601
31619
|
return null;
|
|
31602
31620
|
}
|
|
31621
|
+
|
|
31622
|
+
// ../types/src/parse-change-summary-json.ts
|
|
31603
31623
|
function clampSummaryToAtMostTwoLines(summary) {
|
|
31604
31624
|
const lines = summary.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0);
|
|
31605
31625
|
return lines.slice(0, 2).join("\n");
|
|
@@ -31636,12 +31656,14 @@ function parseChangeSummaryJson(raw, allowedPaths, options) {
|
|
|
31636
31656
|
const rawPath = typeof o.path === "string" ? o.path.trim() : "";
|
|
31637
31657
|
const summary = typeof o.summary === "string" ? o.summary.trim() : "";
|
|
31638
31658
|
if (!rawPath || !summary) continue;
|
|
31639
|
-
const
|
|
31640
|
-
if (!
|
|
31641
|
-
rows.push({ path:
|
|
31659
|
+
const path36 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
|
|
31660
|
+
if (!path36) continue;
|
|
31661
|
+
rows.push({ path: path36, summary: clampSummaryToAtMostTwoLines(summary) });
|
|
31642
31662
|
}
|
|
31643
31663
|
return rows;
|
|
31644
31664
|
}
|
|
31665
|
+
|
|
31666
|
+
// ../types/src/build-change-summary-prompt.ts
|
|
31645
31667
|
var PATCH_PREVIEW_MAX = 12e3;
|
|
31646
31668
|
function clip(s, max) {
|
|
31647
31669
|
if (s.length <= max) return s;
|
|
@@ -31699,6 +31721,8 @@ function buildSessionChangeSummaryPrompt(files) {
|
|
|
31699
31721
|
}
|
|
31700
31722
|
return lines.join("\n");
|
|
31701
31723
|
}
|
|
31724
|
+
|
|
31725
|
+
// ../types/src/dedupe-session-file-changes-by-path.ts
|
|
31702
31726
|
function defaultRichness(c) {
|
|
31703
31727
|
const patch = typeof c.patchContent === "string" ? c.patchContent.length : 0;
|
|
31704
31728
|
const nt = typeof c.newText === "string" ? c.newText.length : 0;
|
|
@@ -31716,6 +31740,9 @@ function dedupeSessionFileChangesByPath(items, richness = (item) => defaultRichn
|
|
|
31716
31740
|
}
|
|
31717
31741
|
return Array.from(byPath.entries()).sort(([a], [b]) => a.localeCompare(b)).map(([, v]) => v);
|
|
31718
31742
|
}
|
|
31743
|
+
|
|
31744
|
+
// ../types/src/artifacts.ts
|
|
31745
|
+
init_zod();
|
|
31719
31746
|
var ArtifactMetaSchema = external_exports.object({
|
|
31720
31747
|
artifactId: external_exports.string(),
|
|
31721
31748
|
workspaceId: external_exports.string(),
|
|
@@ -31729,6 +31756,9 @@ var ArtifactMetaSchema = external_exports.object({
|
|
|
31729
31756
|
createdAt: external_exports.string(),
|
|
31730
31757
|
updatedAt: external_exports.string()
|
|
31731
31758
|
});
|
|
31759
|
+
|
|
31760
|
+
// ../types/src/templates.ts
|
|
31761
|
+
init_zod();
|
|
31732
31762
|
var TemplateMetaSchema = external_exports.object({
|
|
31733
31763
|
templateId: external_exports.string(),
|
|
31734
31764
|
workspaceId: external_exports.string(),
|
|
@@ -31738,6 +31768,9 @@ var TemplateMetaSchema = external_exports.object({
|
|
|
31738
31768
|
createdAt: external_exports.string(),
|
|
31739
31769
|
updatedAt: external_exports.string()
|
|
31740
31770
|
});
|
|
31771
|
+
|
|
31772
|
+
// ../types/src/git-repos.ts
|
|
31773
|
+
init_zod();
|
|
31741
31774
|
var GitRepoMetaSchema = external_exports.object({
|
|
31742
31775
|
/** Stable id for the repo (e.g. hash of normalized canonical URL). Used for DO idFromName. */
|
|
31743
31776
|
repoId: external_exports.string(),
|
|
@@ -31753,9 +31786,9 @@ var GitRepoMetaSchema = external_exports.object({
|
|
|
31753
31786
|
// src/agents/acp/put-summarize-change-summaries.ts
|
|
31754
31787
|
async function putEncryptedChangeSummaryRows(params) {
|
|
31755
31788
|
const base = params.apiBaseUrl.replace(/\/+$/, "");
|
|
31756
|
-
const entries = params.rows.map(({ path:
|
|
31789
|
+
const entries = params.rows.map(({ path: path36, summary }) => {
|
|
31757
31790
|
const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
|
|
31758
|
-
return { path:
|
|
31791
|
+
return { path: path36, summary: JSON.stringify(enc) };
|
|
31759
31792
|
});
|
|
31760
31793
|
const res = await fetch(
|
|
31761
31794
|
`${base}/api/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
|
|
@@ -32154,7 +32187,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
32154
32187
|
child.once("close", (code, signal) => {
|
|
32155
32188
|
onAgentSubprocessExit?.({ code, signal });
|
|
32156
32189
|
});
|
|
32157
|
-
return new Promise((
|
|
32190
|
+
return new Promise((resolve18, reject) => {
|
|
32158
32191
|
let initSettled = false;
|
|
32159
32192
|
const settleReject = (err) => {
|
|
32160
32193
|
if (initSettled) return;
|
|
@@ -32168,7 +32201,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
32168
32201
|
const settleResolve = (handle) => {
|
|
32169
32202
|
if (initSettled) return;
|
|
32170
32203
|
initSettled = true;
|
|
32171
|
-
|
|
32204
|
+
resolve18(handle);
|
|
32172
32205
|
};
|
|
32173
32206
|
child.on("error", (err) => {
|
|
32174
32207
|
settleReject(new Error(formatSpawnError(err, command[0])));
|
|
@@ -32204,8 +32237,8 @@ async function createSdkStdioAcpClient(options) {
|
|
|
32204
32237
|
});
|
|
32205
32238
|
} catch {
|
|
32206
32239
|
}
|
|
32207
|
-
return await new Promise((
|
|
32208
|
-
pendingPermissionResolvers.set(requestId,
|
|
32240
|
+
return await new Promise((resolve19) => {
|
|
32241
|
+
pendingPermissionResolvers.set(requestId, resolve19);
|
|
32209
32242
|
});
|
|
32210
32243
|
},
|
|
32211
32244
|
async readTextFile(params) {
|
|
@@ -32313,9 +32346,9 @@ async function createSdkStdioAcpClient(options) {
|
|
|
32313
32346
|
}
|
|
32314
32347
|
},
|
|
32315
32348
|
async cancel() {
|
|
32316
|
-
for (const [id,
|
|
32349
|
+
for (const [id, resolve19] of [...pendingPermissionResolvers.entries()]) {
|
|
32317
32350
|
pendingPermissionResolvers.delete(id);
|
|
32318
|
-
|
|
32351
|
+
resolve19({ outcome: { outcome: "cancelled" } });
|
|
32319
32352
|
}
|
|
32320
32353
|
try {
|
|
32321
32354
|
await connection.cancel({ sessionId });
|
|
@@ -32331,10 +32364,10 @@ async function createSdkStdioAcpClient(options) {
|
|
|
32331
32364
|
}
|
|
32332
32365
|
},
|
|
32333
32366
|
resolveRequest(requestId, result) {
|
|
32334
|
-
const
|
|
32335
|
-
if (!
|
|
32367
|
+
const resolve19 = pendingPermissionResolvers.get(requestId);
|
|
32368
|
+
if (!resolve19) return;
|
|
32336
32369
|
pendingPermissionResolvers.delete(requestId);
|
|
32337
|
-
|
|
32370
|
+
resolve19(result);
|
|
32338
32371
|
},
|
|
32339
32372
|
disconnect() {
|
|
32340
32373
|
child.kill();
|
|
@@ -32485,7 +32518,7 @@ async function createCursorAcpClient(options) {
|
|
|
32485
32518
|
});
|
|
32486
32519
|
const stderrCapture = createStderrCapture(child);
|
|
32487
32520
|
child.stderr?.on("data", (chunk) => stderrCapture.append(chunk));
|
|
32488
|
-
return new Promise((
|
|
32521
|
+
return new Promise((resolve18, reject) => {
|
|
32489
32522
|
child.on("error", (err) => {
|
|
32490
32523
|
child.kill();
|
|
32491
32524
|
reject(new Error(formatSpawnError2(err, command[0])));
|
|
@@ -32672,7 +32705,7 @@ async function createCursorAcpClient(options) {
|
|
|
32672
32705
|
const newResult = await send("session/new", { cwd, mcpServers: [] });
|
|
32673
32706
|
const sessionId = newResult?.sessionId ?? "";
|
|
32674
32707
|
if (!sessionId) throw new Error("Cursor ACP session/new did not return sessionId");
|
|
32675
|
-
|
|
32708
|
+
resolve18({
|
|
32676
32709
|
sessionId,
|
|
32677
32710
|
async sendPrompt(prompt, _options) {
|
|
32678
32711
|
promptOutputBuffer = "";
|
|
@@ -33740,7 +33773,7 @@ async function createAcpManager(options) {
|
|
|
33740
33773
|
}
|
|
33741
33774
|
|
|
33742
33775
|
// src/worktrees/session-worktree-manager.ts
|
|
33743
|
-
import * as
|
|
33776
|
+
import * as path18 from "node:path";
|
|
33744
33777
|
import os4 from "node:os";
|
|
33745
33778
|
|
|
33746
33779
|
// src/worktrees/prepare-new-session-worktrees.ts
|
|
@@ -33789,10 +33822,15 @@ function saveWorktreeLayout(layout) {
|
|
|
33789
33822
|
function baseNameSafe(abs) {
|
|
33790
33823
|
return path12.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
|
|
33791
33824
|
}
|
|
33792
|
-
function
|
|
33825
|
+
function getLauncherDirNameIfPresent(layout, launcherCwdAbs) {
|
|
33793
33826
|
const norm = path12.resolve(launcherCwdAbs);
|
|
33794
33827
|
const existing = layout.launcherCwds.find((e) => path12.resolve(e.absolutePath) === norm);
|
|
33795
|
-
|
|
33828
|
+
return existing?.dirName;
|
|
33829
|
+
}
|
|
33830
|
+
function allocateDirNameForLauncherCwd(layout, launcherCwdAbs) {
|
|
33831
|
+
const existing = getLauncherDirNameIfPresent(layout, launcherCwdAbs);
|
|
33832
|
+
if (existing) return existing;
|
|
33833
|
+
const norm = path12.resolve(launcherCwdAbs);
|
|
33796
33834
|
const base = baseNameSafe(norm);
|
|
33797
33835
|
const used = new Set(layout.launcherCwds.map((e) => e.dirName));
|
|
33798
33836
|
let name = base;
|
|
@@ -34570,11 +34608,88 @@ async function commitSessionWorktrees(options) {
|
|
|
34570
34608
|
}
|
|
34571
34609
|
}
|
|
34572
34610
|
|
|
34611
|
+
// src/worktrees/discover-session-worktree-on-disk.ts
|
|
34612
|
+
import * as fs18 from "node:fs";
|
|
34613
|
+
import * as path17 from "node:path";
|
|
34614
|
+
function isGitDir(abs) {
|
|
34615
|
+
try {
|
|
34616
|
+
return fs18.existsSync(path17.join(abs, ".git"));
|
|
34617
|
+
} catch {
|
|
34618
|
+
return false;
|
|
34619
|
+
}
|
|
34620
|
+
}
|
|
34621
|
+
function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
34622
|
+
const out = [];
|
|
34623
|
+
const walk = (dir, depth) => {
|
|
34624
|
+
if (depth > maxDepth) return;
|
|
34625
|
+
let entries;
|
|
34626
|
+
try {
|
|
34627
|
+
entries = fs18.readdirSync(dir, { withFileTypes: true });
|
|
34628
|
+
} catch {
|
|
34629
|
+
return;
|
|
34630
|
+
}
|
|
34631
|
+
for (const e of entries) {
|
|
34632
|
+
if (e.name.startsWith(".")) continue;
|
|
34633
|
+
const full = path17.join(dir, e.name);
|
|
34634
|
+
if (!e.isDirectory()) continue;
|
|
34635
|
+
if (e.name === sessionId) {
|
|
34636
|
+
if (isGitDir(full)) out.push(path17.resolve(full));
|
|
34637
|
+
} else {
|
|
34638
|
+
walk(full, depth + 1);
|
|
34639
|
+
}
|
|
34640
|
+
}
|
|
34641
|
+
};
|
|
34642
|
+
walk(root, 0);
|
|
34643
|
+
return out;
|
|
34644
|
+
}
|
|
34645
|
+
function discoverSessionWorktreeOnDisk(options) {
|
|
34646
|
+
const { sessionId, worktreesRootAbs, layout, launcherCwd } = options;
|
|
34647
|
+
if (!sessionId.trim() || !fs18.existsSync(worktreesRootAbs)) return null;
|
|
34648
|
+
const preferredKey = getLauncherDirNameIfPresent(layout, launcherCwd);
|
|
34649
|
+
const keys = [];
|
|
34650
|
+
if (preferredKey) keys.push(preferredKey);
|
|
34651
|
+
try {
|
|
34652
|
+
for (const name of fs18.readdirSync(worktreesRootAbs)) {
|
|
34653
|
+
if (name.startsWith(".")) continue;
|
|
34654
|
+
const p = path17.join(worktreesRootAbs, name);
|
|
34655
|
+
if (!fs18.statSync(p).isDirectory()) continue;
|
|
34656
|
+
if (name !== preferredKey) keys.push(name);
|
|
34657
|
+
}
|
|
34658
|
+
} catch {
|
|
34659
|
+
return null;
|
|
34660
|
+
}
|
|
34661
|
+
for (const key of keys) {
|
|
34662
|
+
const mirrorRoot = path17.join(worktreesRootAbs, key);
|
|
34663
|
+
if (!fs18.existsSync(mirrorRoot) || !fs18.statSync(mirrorRoot).isDirectory()) continue;
|
|
34664
|
+
const worktreePaths = collectWorktreeRootsNamed(mirrorRoot, sessionId, 24);
|
|
34665
|
+
if (worktreePaths.length > 0) {
|
|
34666
|
+
return { agentCwd: path17.resolve(mirrorRoot), worktreePaths };
|
|
34667
|
+
}
|
|
34668
|
+
}
|
|
34669
|
+
return null;
|
|
34670
|
+
}
|
|
34671
|
+
function discoverSessionWorktreesUnderMirrorRoot(mirrorRootAbs, sessionId) {
|
|
34672
|
+
const mirrorRoot = path17.resolve(mirrorRootAbs);
|
|
34673
|
+
if (!sessionId.trim() || !fs18.existsSync(mirrorRoot)) return null;
|
|
34674
|
+
try {
|
|
34675
|
+
if (!fs18.statSync(mirrorRoot).isDirectory()) return null;
|
|
34676
|
+
} catch {
|
|
34677
|
+
return null;
|
|
34678
|
+
}
|
|
34679
|
+
const worktreePaths = collectWorktreeRootsNamed(mirrorRoot, sessionId, 24);
|
|
34680
|
+
if (worktreePaths.length === 0) return null;
|
|
34681
|
+
return { agentCwd: mirrorRoot, worktreePaths };
|
|
34682
|
+
}
|
|
34683
|
+
|
|
34573
34684
|
// src/worktrees/session-worktree-manager.ts
|
|
34685
|
+
function parseSessionParent(v) {
|
|
34686
|
+
if (v === "bridge_root" || v === "worktrees_root") return v;
|
|
34687
|
+
if (v === "session_worktrees_root") return "worktrees_root";
|
|
34688
|
+
return null;
|
|
34689
|
+
}
|
|
34574
34690
|
var SessionWorktreeManager = class {
|
|
34575
34691
|
rootAbs;
|
|
34576
34692
|
log;
|
|
34577
|
-
bridgeWantsWorktrees = false;
|
|
34578
34693
|
sessionPaths = /* @__PURE__ */ new Map();
|
|
34579
34694
|
sessionAgentCwd = /* @__PURE__ */ new Map();
|
|
34580
34695
|
layout;
|
|
@@ -34583,22 +34698,67 @@ var SessionWorktreeManager = class {
|
|
|
34583
34698
|
this.log = options.log;
|
|
34584
34699
|
this.layout = loadWorktreeLayout();
|
|
34585
34700
|
}
|
|
34586
|
-
|
|
34587
|
-
this.
|
|
34701
|
+
rememberWorktrees(sessionId, agentCwd, worktreePaths) {
|
|
34702
|
+
this.sessionPaths.set(sessionId, worktreePaths);
|
|
34703
|
+
this.sessionAgentCwd.set(sessionId, path18.resolve(agentCwd));
|
|
34588
34704
|
}
|
|
34589
|
-
|
|
34590
|
-
return
|
|
34705
|
+
tryDiscoverFromDisk(sessionId) {
|
|
34706
|
+
return discoverSessionWorktreeOnDisk({
|
|
34707
|
+
sessionId,
|
|
34708
|
+
worktreesRootAbs: this.rootAbs,
|
|
34709
|
+
layout: this.layout,
|
|
34710
|
+
launcherCwd: getBridgeWorkspaceDirectory()
|
|
34711
|
+
});
|
|
34591
34712
|
}
|
|
34592
34713
|
/**
|
|
34593
34714
|
* Returns cwd for the agent (mirror of launcher tree), or undefined to use the bridge workspace directory.
|
|
34594
34715
|
*/
|
|
34595
34716
|
async resolveCwdForPrompt(sessionId, opts) {
|
|
34596
|
-
if (!sessionId
|
|
34717
|
+
if (!sessionId) return void 0;
|
|
34718
|
+
const parentPathRaw = opts.sessionParentPath?.trim();
|
|
34719
|
+
if (parentPathRaw) {
|
|
34720
|
+
const agentCwd = path18.resolve(parentPathRaw);
|
|
34721
|
+
const sid = sessionId?.trim();
|
|
34722
|
+
if (sid && parseSessionParent(opts.sessionParent) === "worktrees_root") {
|
|
34723
|
+
const fromMirror = discoverSessionWorktreesUnderMirrorRoot(agentCwd, sid);
|
|
34724
|
+
if (fromMirror) this.rememberWorktrees(sid, fromMirror.agentCwd, fromMirror.worktreePaths);
|
|
34725
|
+
}
|
|
34726
|
+
return agentCwd;
|
|
34727
|
+
}
|
|
34728
|
+
const parentKind = parseSessionParent(opts.sessionParent);
|
|
34729
|
+
if (parentKind === "bridge_root") {
|
|
34597
34730
|
return void 0;
|
|
34598
34731
|
}
|
|
34732
|
+
if (parentKind === "worktrees_root") {
|
|
34733
|
+
if (!opts.isNewSession) {
|
|
34734
|
+
const cached2 = this.sessionAgentCwd.get(sessionId);
|
|
34735
|
+
if (cached2) return path18.resolve(cached2);
|
|
34736
|
+
const disc = this.tryDiscoverFromDisk(sessionId);
|
|
34737
|
+
if (disc) {
|
|
34738
|
+
this.rememberWorktrees(sessionId, disc.agentCwd, disc.worktreePaths);
|
|
34739
|
+
return path18.resolve(disc.agentCwd);
|
|
34740
|
+
}
|
|
34741
|
+
return void 0;
|
|
34742
|
+
}
|
|
34743
|
+
const prep2 = await prepareNewSessionWorktrees({
|
|
34744
|
+
rootAbs: this.rootAbs,
|
|
34745
|
+
launcherCwd: getBridgeWorkspaceDirectory(),
|
|
34746
|
+
sessionId,
|
|
34747
|
+
layout: this.layout,
|
|
34748
|
+
log: this.log
|
|
34749
|
+
});
|
|
34750
|
+
if (!prep2) return void 0;
|
|
34751
|
+
this.rememberWorktrees(sessionId, prep2.agentCwd, prep2.worktreePaths);
|
|
34752
|
+
return path18.resolve(prep2.agentCwd);
|
|
34753
|
+
}
|
|
34599
34754
|
if (!opts.isNewSession) {
|
|
34600
|
-
const
|
|
34601
|
-
if (
|
|
34755
|
+
const cached2 = this.sessionAgentCwd.get(sessionId);
|
|
34756
|
+
if (cached2) return path18.resolve(cached2);
|
|
34757
|
+
const disc = this.tryDiscoverFromDisk(sessionId);
|
|
34758
|
+
if (disc) {
|
|
34759
|
+
this.rememberWorktrees(sessionId, disc.agentCwd, disc.worktreePaths);
|
|
34760
|
+
return path18.resolve(disc.agentCwd);
|
|
34761
|
+
}
|
|
34602
34762
|
return void 0;
|
|
34603
34763
|
}
|
|
34604
34764
|
const prep = await prepareNewSessionWorktrees({
|
|
@@ -34609,9 +34769,8 @@ var SessionWorktreeManager = class {
|
|
|
34609
34769
|
log: this.log
|
|
34610
34770
|
});
|
|
34611
34771
|
if (!prep) return void 0;
|
|
34612
|
-
this.
|
|
34613
|
-
|
|
34614
|
-
return path17.resolve(prep.agentCwd);
|
|
34772
|
+
this.rememberWorktrees(sessionId, prep.agentCwd, prep.worktreePaths);
|
|
34773
|
+
return path18.resolve(prep.agentCwd);
|
|
34615
34774
|
}
|
|
34616
34775
|
async renameSessionBranch(sessionId, newBranch) {
|
|
34617
34776
|
const paths = this.sessionPaths.get(sessionId);
|
|
@@ -34632,7 +34791,7 @@ var SessionWorktreeManager = class {
|
|
|
34632
34791
|
getAgentCwdForSession(sessionId) {
|
|
34633
34792
|
if (!sessionId) return null;
|
|
34634
34793
|
const c = this.sessionAgentCwd.get(sessionId);
|
|
34635
|
-
return c ?
|
|
34794
|
+
return c ? path18.resolve(c) : null;
|
|
34636
34795
|
}
|
|
34637
34796
|
async removeSessionWorktrees(sessionId) {
|
|
34638
34797
|
const paths = this.sessionPaths.get(sessionId);
|
|
@@ -34653,7 +34812,13 @@ var SessionWorktreeManager = class {
|
|
|
34653
34812
|
}
|
|
34654
34813
|
resolveCommitTargets(sessionId) {
|
|
34655
34814
|
const paths = this.sessionPaths.get(sessionId);
|
|
34656
|
-
|
|
34815
|
+
if (paths?.length) return paths;
|
|
34816
|
+
const disc = this.tryDiscoverFromDisk(sessionId);
|
|
34817
|
+
if (disc?.worktreePaths.length) {
|
|
34818
|
+
this.rememberWorktrees(sessionId, disc.agentCwd, disc.worktreePaths);
|
|
34819
|
+
return disc.worktreePaths;
|
|
34820
|
+
}
|
|
34821
|
+
return [getBridgeWorkspaceDirectory()];
|
|
34657
34822
|
}
|
|
34658
34823
|
async getSessionWorkingTreeStatus(sessionId) {
|
|
34659
34824
|
return aggregateSessionPathsWorkingTreeStatus(this.resolveCommitTargets(sessionId));
|
|
@@ -34680,30 +34845,30 @@ var SessionWorktreeManager = class {
|
|
|
34680
34845
|
}
|
|
34681
34846
|
};
|
|
34682
34847
|
function defaultWorktreesRootAbs() {
|
|
34683
|
-
return
|
|
34848
|
+
return path18.join(os4.homedir(), ".buildautomaton", "worktrees");
|
|
34684
34849
|
}
|
|
34685
34850
|
|
|
34686
34851
|
// src/files/watch-file-index.ts
|
|
34687
34852
|
import { watch } from "node:fs";
|
|
34688
|
-
import
|
|
34853
|
+
import path25 from "node:path";
|
|
34689
34854
|
|
|
34690
34855
|
// src/files/index/build-file-index.ts
|
|
34691
|
-
import
|
|
34856
|
+
import path22 from "node:path";
|
|
34692
34857
|
|
|
34693
34858
|
// src/runtime/yield-to-event-loop.ts
|
|
34694
34859
|
function yieldToEventLoop() {
|
|
34695
|
-
return new Promise((
|
|
34860
|
+
return new Promise((resolve18) => setImmediate(resolve18));
|
|
34696
34861
|
}
|
|
34697
34862
|
|
|
34698
34863
|
// src/files/index/walk-workspace-tree.ts
|
|
34699
|
-
import
|
|
34700
|
-
import
|
|
34864
|
+
import fs19 from "node:fs";
|
|
34865
|
+
import path20 from "node:path";
|
|
34701
34866
|
|
|
34702
34867
|
// src/files/index/constants.ts
|
|
34703
|
-
import
|
|
34868
|
+
import path19 from "node:path";
|
|
34704
34869
|
import os5 from "node:os";
|
|
34705
34870
|
var INDEX_WORK_YIELD_EVERY = 256;
|
|
34706
|
-
var INDEX_DIR =
|
|
34871
|
+
var INDEX_DIR = path19.join(os5.homedir(), ".buildautomaton");
|
|
34707
34872
|
var INDEX_HASH_LEN = 16;
|
|
34708
34873
|
var INDEX_VERSION = 2;
|
|
34709
34874
|
var INDEX_LOG_PREFIX = "[file-index]";
|
|
@@ -34712,20 +34877,20 @@ var INDEX_LOG_PREFIX = "[file-index]";
|
|
|
34712
34877
|
function walkWorkspaceTreeSync(dir, baseDir, out) {
|
|
34713
34878
|
let names;
|
|
34714
34879
|
try {
|
|
34715
|
-
names =
|
|
34880
|
+
names = fs19.readdirSync(dir);
|
|
34716
34881
|
} catch {
|
|
34717
34882
|
return;
|
|
34718
34883
|
}
|
|
34719
34884
|
for (const name of names) {
|
|
34720
34885
|
if (name.startsWith(".")) continue;
|
|
34721
|
-
const full =
|
|
34886
|
+
const full = path20.join(dir, name);
|
|
34722
34887
|
let stat3;
|
|
34723
34888
|
try {
|
|
34724
|
-
stat3 =
|
|
34889
|
+
stat3 = fs19.statSync(full);
|
|
34725
34890
|
} catch {
|
|
34726
34891
|
continue;
|
|
34727
34892
|
}
|
|
34728
|
-
const relative5 =
|
|
34893
|
+
const relative5 = path20.relative(baseDir, full).replace(/\\/g, "/");
|
|
34729
34894
|
if (stat3.isDirectory()) {
|
|
34730
34895
|
walkWorkspaceTreeSync(full, baseDir, out);
|
|
34731
34896
|
} else if (stat3.isFile()) {
|
|
@@ -34736,7 +34901,7 @@ function walkWorkspaceTreeSync(dir, baseDir, out) {
|
|
|
34736
34901
|
async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
|
|
34737
34902
|
let names;
|
|
34738
34903
|
try {
|
|
34739
|
-
names = await
|
|
34904
|
+
names = await fs19.promises.readdir(dir);
|
|
34740
34905
|
} catch {
|
|
34741
34906
|
return;
|
|
34742
34907
|
}
|
|
@@ -34746,14 +34911,14 @@ async function walkWorkspaceTreeAsync(dir, baseDir, out, state) {
|
|
|
34746
34911
|
await yieldToEventLoop();
|
|
34747
34912
|
}
|
|
34748
34913
|
state.n++;
|
|
34749
|
-
const full =
|
|
34914
|
+
const full = path20.join(dir, name);
|
|
34750
34915
|
let stat3;
|
|
34751
34916
|
try {
|
|
34752
|
-
stat3 = await
|
|
34917
|
+
stat3 = await fs19.promises.stat(full);
|
|
34753
34918
|
} catch {
|
|
34754
34919
|
continue;
|
|
34755
34920
|
}
|
|
34756
|
-
const relative5 =
|
|
34921
|
+
const relative5 = path20.relative(baseDir, full).replace(/\\/g, "/");
|
|
34757
34922
|
if (stat3.isDirectory()) {
|
|
34758
34923
|
await walkWorkspaceTreeAsync(full, baseDir, out, state);
|
|
34759
34924
|
} else if (stat3.isFile()) {
|
|
@@ -34834,22 +34999,22 @@ async function buildTrigramMapForPathsAsync(paths) {
|
|
|
34834
34999
|
}
|
|
34835
35000
|
|
|
34836
35001
|
// src/files/index/write-index-file.ts
|
|
34837
|
-
import
|
|
35002
|
+
import fs20 from "node:fs";
|
|
34838
35003
|
|
|
34839
35004
|
// src/files/index/paths.ts
|
|
34840
|
-
import
|
|
35005
|
+
import path21 from "node:path";
|
|
34841
35006
|
import crypto2 from "node:crypto";
|
|
34842
35007
|
function getIndexPathForCwd(resolvedCwd) {
|
|
34843
35008
|
const hash = crypto2.createHash("sha256").update(resolvedCwd).digest("hex").slice(0, INDEX_HASH_LEN);
|
|
34844
|
-
return
|
|
35009
|
+
return path21.join(INDEX_DIR, `.file-index-${hash}.json`);
|
|
34845
35010
|
}
|
|
34846
35011
|
|
|
34847
35012
|
// src/files/index/write-index-file.ts
|
|
34848
35013
|
function writeIndexFileSync(resolvedCwd, data) {
|
|
34849
35014
|
const indexPath = getIndexPathForCwd(resolvedCwd);
|
|
34850
35015
|
try {
|
|
34851
|
-
if (!
|
|
34852
|
-
|
|
35016
|
+
if (!fs20.existsSync(INDEX_DIR)) fs20.mkdirSync(INDEX_DIR, { recursive: true });
|
|
35017
|
+
fs20.writeFileSync(indexPath, JSON.stringify(data), "utf8");
|
|
34853
35018
|
} catch (e) {
|
|
34854
35019
|
console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
|
|
34855
35020
|
}
|
|
@@ -34857,8 +35022,8 @@ function writeIndexFileSync(resolvedCwd, data) {
|
|
|
34857
35022
|
async function writeIndexFileAsync(resolvedCwd, data) {
|
|
34858
35023
|
const indexPath = getIndexPathForCwd(resolvedCwd);
|
|
34859
35024
|
try {
|
|
34860
|
-
await
|
|
34861
|
-
await
|
|
35025
|
+
await fs20.promises.mkdir(INDEX_DIR, { recursive: true });
|
|
35026
|
+
await fs20.promises.writeFile(indexPath, JSON.stringify(data), "utf8");
|
|
34862
35027
|
} catch (e) {
|
|
34863
35028
|
console.error(`${INDEX_LOG_PREFIX} Failed to write index:`, e);
|
|
34864
35029
|
}
|
|
@@ -34872,7 +35037,7 @@ function sortPaths(paths) {
|
|
|
34872
35037
|
paths.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
|
|
34873
35038
|
}
|
|
34874
35039
|
function buildFileIndex(cwd) {
|
|
34875
|
-
const resolved =
|
|
35040
|
+
const resolved = path22.resolve(cwd);
|
|
34876
35041
|
const paths = [];
|
|
34877
35042
|
walkWorkspaceTreeSync(resolved, resolved, paths);
|
|
34878
35043
|
sortPaths(paths);
|
|
@@ -34882,7 +35047,7 @@ function buildFileIndex(cwd) {
|
|
|
34882
35047
|
return data;
|
|
34883
35048
|
}
|
|
34884
35049
|
async function buildFileIndexAsync(cwd) {
|
|
34885
|
-
const resolved =
|
|
35050
|
+
const resolved = path22.resolve(cwd);
|
|
34886
35051
|
const paths = [];
|
|
34887
35052
|
await walkWorkspaceTreeAsync(resolved, resolved, paths, createWalkYieldState());
|
|
34888
35053
|
await yieldToEventLoop();
|
|
@@ -34894,13 +35059,13 @@ async function buildFileIndexAsync(cwd) {
|
|
|
34894
35059
|
}
|
|
34895
35060
|
|
|
34896
35061
|
// src/files/index/load-file-index.ts
|
|
34897
|
-
import
|
|
34898
|
-
import
|
|
35062
|
+
import fs21 from "node:fs";
|
|
35063
|
+
import path23 from "node:path";
|
|
34899
35064
|
function loadFileIndex(cwd) {
|
|
34900
|
-
const resolved =
|
|
35065
|
+
const resolved = path23.resolve(cwd);
|
|
34901
35066
|
const indexPath = getIndexPathForCwd(resolved);
|
|
34902
35067
|
try {
|
|
34903
|
-
const raw =
|
|
35068
|
+
const raw = fs21.readFileSync(indexPath, "utf8");
|
|
34904
35069
|
const parsed = JSON.parse(raw);
|
|
34905
35070
|
if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.paths)) {
|
|
34906
35071
|
const obj = parsed;
|
|
@@ -34919,9 +35084,9 @@ function loadFileIndex(cwd) {
|
|
|
34919
35084
|
}
|
|
34920
35085
|
|
|
34921
35086
|
// src/files/index/ensure-file-index.ts
|
|
34922
|
-
import
|
|
35087
|
+
import path24 from "node:path";
|
|
34923
35088
|
async function ensureFileIndexAsync(cwd) {
|
|
34924
|
-
const resolved =
|
|
35089
|
+
const resolved = path24.resolve(cwd);
|
|
34925
35090
|
const cached2 = loadFileIndex(resolved);
|
|
34926
35091
|
if (cached2 !== null) return { data: cached2, fromCache: true };
|
|
34927
35092
|
const data = await buildFileIndexAsync(resolved);
|
|
@@ -35004,7 +35169,7 @@ function createFsWatcher(resolved, schedule) {
|
|
|
35004
35169
|
}
|
|
35005
35170
|
}
|
|
35006
35171
|
function startFileIndexWatcher(cwd = getBridgeWorkspaceDirectory()) {
|
|
35007
|
-
const resolved =
|
|
35172
|
+
const resolved = path25.resolve(cwd);
|
|
35008
35173
|
void buildFileIndexAsync(resolved).catch((e) => {
|
|
35009
35174
|
console.error("[file-index] Initial index build failed:", e);
|
|
35010
35175
|
});
|
|
@@ -35031,6 +35196,9 @@ function startFileIndexWatcher(cwd = getBridgeWorkspaceDirectory()) {
|
|
|
35031
35196
|
};
|
|
35032
35197
|
}
|
|
35033
35198
|
|
|
35199
|
+
// src/bridge/connection/create-bridge-connection.ts
|
|
35200
|
+
import * as path34 from "node:path";
|
|
35201
|
+
|
|
35034
35202
|
// src/dev-servers/manager/dev-server-manager.ts
|
|
35035
35203
|
import { rm as rm2 } from "node:fs/promises";
|
|
35036
35204
|
|
|
@@ -35051,15 +35219,15 @@ function sendDevServerStatus(getWs, serverId, status, options) {
|
|
|
35051
35219
|
|
|
35052
35220
|
// src/dev-servers/process/terminate-child-process.ts
|
|
35053
35221
|
async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
|
|
35054
|
-
const exited = new Promise((
|
|
35055
|
-
proc.once("exit", () =>
|
|
35222
|
+
const exited = new Promise((resolve18) => {
|
|
35223
|
+
proc.once("exit", () => resolve18());
|
|
35056
35224
|
});
|
|
35057
35225
|
log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
|
|
35058
35226
|
try {
|
|
35059
35227
|
proc.kill("SIGTERM");
|
|
35060
35228
|
} catch {
|
|
35061
35229
|
}
|
|
35062
|
-
await Promise.race([exited, new Promise((
|
|
35230
|
+
await Promise.race([exited, new Promise((resolve18) => setTimeout(resolve18, graceMs))]);
|
|
35063
35231
|
}
|
|
35064
35232
|
function forceKillChild(proc, log2, shortId, graceMs) {
|
|
35065
35233
|
log2(
|
|
@@ -35073,7 +35241,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
|
|
|
35073
35241
|
}
|
|
35074
35242
|
|
|
35075
35243
|
// src/dev-servers/process/wire-dev-server-child-process.ts
|
|
35076
|
-
import
|
|
35244
|
+
import fs22 from "node:fs";
|
|
35077
35245
|
|
|
35078
35246
|
// src/dev-servers/manager/forward-pipe.ts
|
|
35079
35247
|
function forwardChildPipe(childReadable, terminal, onData) {
|
|
@@ -35109,7 +35277,7 @@ function wireDevServerChildProcess(d) {
|
|
|
35109
35277
|
d.setPollInterval(void 0);
|
|
35110
35278
|
return;
|
|
35111
35279
|
}
|
|
35112
|
-
|
|
35280
|
+
fs22.readFile(d.mergedLogPath, (err, buf) => {
|
|
35113
35281
|
if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
|
|
35114
35282
|
if (buf.length <= d.mergedReadPos.value) return;
|
|
35115
35283
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
@@ -35147,7 +35315,7 @@ ${errTail}` : ""}`);
|
|
|
35147
35315
|
d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
|
|
35148
35316
|
};
|
|
35149
35317
|
if (mergedPath) {
|
|
35150
|
-
|
|
35318
|
+
fs22.readFile(mergedPath, (err, buf) => {
|
|
35151
35319
|
if (!err && buf.length > d.mergedReadPos.value) {
|
|
35152
35320
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
35153
35321
|
if (chunk.length > 0) {
|
|
@@ -35249,13 +35417,13 @@ function parseDevServerDefs(servers) {
|
|
|
35249
35417
|
}
|
|
35250
35418
|
|
|
35251
35419
|
// src/dev-servers/manager/shell-spawn/utils.ts
|
|
35252
|
-
import
|
|
35420
|
+
import fs23 from "node:fs";
|
|
35253
35421
|
function isSpawnEbadf(e) {
|
|
35254
35422
|
return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
|
|
35255
35423
|
}
|
|
35256
35424
|
function rmDirQuiet(dir) {
|
|
35257
35425
|
try {
|
|
35258
|
-
|
|
35426
|
+
fs23.rmSync(dir, { recursive: true, force: true });
|
|
35259
35427
|
} catch {
|
|
35260
35428
|
}
|
|
35261
35429
|
}
|
|
@@ -35263,7 +35431,7 @@ var cachedDevNullReadFd;
|
|
|
35263
35431
|
function devNullReadFd() {
|
|
35264
35432
|
if (cachedDevNullReadFd === void 0) {
|
|
35265
35433
|
const devPath = process.platform === "win32" ? "nul" : "/dev/null";
|
|
35266
|
-
cachedDevNullReadFd =
|
|
35434
|
+
cachedDevNullReadFd = fs23.openSync(devPath, "r");
|
|
35267
35435
|
}
|
|
35268
35436
|
return cachedDevNullReadFd;
|
|
35269
35437
|
}
|
|
@@ -35337,15 +35505,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
|
35337
35505
|
|
|
35338
35506
|
// src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
|
|
35339
35507
|
import { spawn as spawn6 } from "node:child_process";
|
|
35340
|
-
import
|
|
35508
|
+
import fs24 from "node:fs";
|
|
35341
35509
|
import { tmpdir } from "node:os";
|
|
35342
|
-
import
|
|
35510
|
+
import path26 from "node:path";
|
|
35343
35511
|
function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
35344
|
-
const tmpRoot =
|
|
35345
|
-
const logPath =
|
|
35512
|
+
const tmpRoot = fs24.mkdtempSync(path26.join(tmpdir(), "ba-devsrv-log-"));
|
|
35513
|
+
const logPath = path26.join(tmpRoot, "combined.log");
|
|
35346
35514
|
let logFd;
|
|
35347
35515
|
try {
|
|
35348
|
-
logFd =
|
|
35516
|
+
logFd = fs24.openSync(logPath, "a");
|
|
35349
35517
|
} catch {
|
|
35350
35518
|
rmDirQuiet(tmpRoot);
|
|
35351
35519
|
return null;
|
|
@@ -35364,7 +35532,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
35364
35532
|
} else {
|
|
35365
35533
|
proc = spawn6("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
|
|
35366
35534
|
}
|
|
35367
|
-
|
|
35535
|
+
fs24.closeSync(logFd);
|
|
35368
35536
|
return {
|
|
35369
35537
|
proc,
|
|
35370
35538
|
pipedStdoutStderr: true,
|
|
@@ -35373,7 +35541,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
35373
35541
|
};
|
|
35374
35542
|
} catch (e) {
|
|
35375
35543
|
try {
|
|
35376
|
-
|
|
35544
|
+
fs24.closeSync(logFd);
|
|
35377
35545
|
} catch {
|
|
35378
35546
|
}
|
|
35379
35547
|
rmDirQuiet(tmpRoot);
|
|
@@ -35384,22 +35552,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
35384
35552
|
|
|
35385
35553
|
// src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
|
|
35386
35554
|
import { spawn as spawn7 } from "node:child_process";
|
|
35387
|
-
import
|
|
35555
|
+
import fs25 from "node:fs";
|
|
35388
35556
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
35389
|
-
import
|
|
35557
|
+
import path27 from "node:path";
|
|
35390
35558
|
function shSingleQuote(s) {
|
|
35391
35559
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
35392
35560
|
}
|
|
35393
35561
|
function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
|
|
35394
|
-
const tmpRoot =
|
|
35395
|
-
const logPath =
|
|
35396
|
-
const innerPath =
|
|
35397
|
-
const runnerPath =
|
|
35562
|
+
const tmpRoot = fs25.mkdtempSync(path27.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
35563
|
+
const logPath = path27.join(tmpRoot, "combined.log");
|
|
35564
|
+
const innerPath = path27.join(tmpRoot, "_cmd.sh");
|
|
35565
|
+
const runnerPath = path27.join(tmpRoot, "_run.sh");
|
|
35398
35566
|
try {
|
|
35399
|
-
|
|
35567
|
+
fs25.writeFileSync(innerPath, `#!/bin/sh
|
|
35400
35568
|
${command}
|
|
35401
35569
|
`);
|
|
35402
|
-
|
|
35570
|
+
fs25.writeFileSync(
|
|
35403
35571
|
runnerPath,
|
|
35404
35572
|
`#!/bin/sh
|
|
35405
35573
|
cd ${shSingleQuote(cwd)}
|
|
@@ -35425,13 +35593,13 @@ cd ${shSingleQuote(cwd)}
|
|
|
35425
35593
|
}
|
|
35426
35594
|
}
|
|
35427
35595
|
function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
|
|
35428
|
-
const tmpRoot =
|
|
35429
|
-
const logPath =
|
|
35430
|
-
const runnerPath =
|
|
35596
|
+
const tmpRoot = fs25.mkdtempSync(path27.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
35597
|
+
const logPath = path27.join(tmpRoot, "combined.log");
|
|
35598
|
+
const runnerPath = path27.join(tmpRoot, "_run.bat");
|
|
35431
35599
|
const q = (p) => `"${p.replace(/"/g, '""')}"`;
|
|
35432
35600
|
const com = process.env.ComSpec || "cmd.exe";
|
|
35433
35601
|
try {
|
|
35434
|
-
|
|
35602
|
+
fs25.writeFileSync(
|
|
35435
35603
|
runnerPath,
|
|
35436
35604
|
`@ECHO OFF\r
|
|
35437
35605
|
CD /D ${q(cwd)}\r
|
|
@@ -35942,7 +36110,7 @@ async function proxyToLocal(request) {
|
|
|
35942
36110
|
};
|
|
35943
36111
|
const maxAttempts = isIdempotentProxyMethod(request.method) ? LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS.length + 1 : 1;
|
|
35944
36112
|
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
35945
|
-
const once = await new Promise((
|
|
36113
|
+
const once = await new Promise((resolve18) => {
|
|
35946
36114
|
const req = mod.request(opts, (res) => {
|
|
35947
36115
|
const chunks = [];
|
|
35948
36116
|
res.on("data", (c) => chunks.push(c));
|
|
@@ -35953,7 +36121,7 @@ async function proxyToLocal(request) {
|
|
|
35953
36121
|
if (typeof v === "string") headers[k] = v;
|
|
35954
36122
|
else if (Array.isArray(v) && v[0]) headers[k] = v[0];
|
|
35955
36123
|
}
|
|
35956
|
-
|
|
36124
|
+
resolve18({
|
|
35957
36125
|
id: request.id,
|
|
35958
36126
|
statusCode: res.statusCode ?? 0,
|
|
35959
36127
|
headers,
|
|
@@ -35962,7 +36130,7 @@ async function proxyToLocal(request) {
|
|
|
35962
36130
|
});
|
|
35963
36131
|
});
|
|
35964
36132
|
req.on("error", (err) => {
|
|
35965
|
-
|
|
36133
|
+
resolve18({
|
|
35966
36134
|
id: request.id,
|
|
35967
36135
|
statusCode: 0,
|
|
35968
36136
|
headers: {},
|
|
@@ -36301,10 +36469,9 @@ function attachFirehoseAfterIdentified(ctx, params) {
|
|
|
36301
36469
|
|
|
36302
36470
|
// src/bridge/connection/create-bridge-identified-handler.ts
|
|
36303
36471
|
function createOnBridgeIdentified(opts) {
|
|
36304
|
-
const {
|
|
36472
|
+
const { devServerManager, firehoseServerUrl, workspaceId, state, logFn } = opts;
|
|
36305
36473
|
const firehoseCtx = { state, devServerManager, logFn };
|
|
36306
36474
|
return (msg) => {
|
|
36307
|
-
sessionWorktreeManager.setBridgeSessionWorktrees(msg.sessionWorktreesEnabled === true);
|
|
36308
36475
|
const bridgeName = msg.bridgeName;
|
|
36309
36476
|
const proxyPorts = Array.isArray(msg.proxyPorts) ? msg.proxyPorts : [];
|
|
36310
36477
|
const devServers = msg.devServers ?? [];
|
|
@@ -36323,30 +36490,30 @@ function createOnBridgeIdentified(opts) {
|
|
|
36323
36490
|
}
|
|
36324
36491
|
|
|
36325
36492
|
// src/skills/discover-local-agent-skills.ts
|
|
36326
|
-
import
|
|
36327
|
-
import
|
|
36493
|
+
import fs26 from "node:fs";
|
|
36494
|
+
import path28 from "node:path";
|
|
36328
36495
|
var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
|
|
36329
36496
|
function discoverLocalSkills(cwd) {
|
|
36330
36497
|
const out = [];
|
|
36331
36498
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
36332
36499
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
36333
|
-
const base =
|
|
36334
|
-
if (!
|
|
36500
|
+
const base = path28.join(cwd, rel);
|
|
36501
|
+
if (!fs26.existsSync(base) || !fs26.statSync(base).isDirectory()) continue;
|
|
36335
36502
|
let entries = [];
|
|
36336
36503
|
try {
|
|
36337
|
-
entries =
|
|
36504
|
+
entries = fs26.readdirSync(base);
|
|
36338
36505
|
} catch {
|
|
36339
36506
|
continue;
|
|
36340
36507
|
}
|
|
36341
36508
|
for (const name of entries) {
|
|
36342
|
-
const dir =
|
|
36509
|
+
const dir = path28.join(base, name);
|
|
36343
36510
|
try {
|
|
36344
|
-
if (!
|
|
36511
|
+
if (!fs26.statSync(dir).isDirectory()) continue;
|
|
36345
36512
|
} catch {
|
|
36346
36513
|
continue;
|
|
36347
36514
|
}
|
|
36348
|
-
const skillMd =
|
|
36349
|
-
if (!
|
|
36515
|
+
const skillMd = path28.join(dir, "SKILL.md");
|
|
36516
|
+
if (!fs26.existsSync(skillMd)) continue;
|
|
36350
36517
|
const key = `${rel}/${name}`;
|
|
36351
36518
|
if (seenKeys.has(key)) continue;
|
|
36352
36519
|
seenKeys.add(key);
|
|
@@ -36358,23 +36525,23 @@ function discoverLocalSkills(cwd) {
|
|
|
36358
36525
|
function discoverSkillLayoutRoots(cwd) {
|
|
36359
36526
|
const roots = [];
|
|
36360
36527
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
36361
|
-
const base =
|
|
36362
|
-
if (!
|
|
36528
|
+
const base = path28.join(cwd, rel);
|
|
36529
|
+
if (!fs26.existsSync(base) || !fs26.statSync(base).isDirectory()) continue;
|
|
36363
36530
|
let entries = [];
|
|
36364
36531
|
try {
|
|
36365
|
-
entries =
|
|
36532
|
+
entries = fs26.readdirSync(base);
|
|
36366
36533
|
} catch {
|
|
36367
36534
|
continue;
|
|
36368
36535
|
}
|
|
36369
36536
|
const skills2 = [];
|
|
36370
36537
|
for (const name of entries) {
|
|
36371
|
-
const dir =
|
|
36538
|
+
const dir = path28.join(base, name);
|
|
36372
36539
|
try {
|
|
36373
|
-
if (!
|
|
36540
|
+
if (!fs26.statSync(dir).isDirectory()) continue;
|
|
36374
36541
|
} catch {
|
|
36375
36542
|
continue;
|
|
36376
36543
|
}
|
|
36377
|
-
if (!
|
|
36544
|
+
if (!fs26.existsSync(path28.join(dir, "SKILL.md"))) continue;
|
|
36378
36545
|
const relPath = `${rel}/${name}`.replace(/\\/g, "/");
|
|
36379
36546
|
skills2.push({ name, relPath });
|
|
36380
36547
|
}
|
|
@@ -36419,7 +36586,7 @@ function createSendLocalSkillsReport(getWs, logFn) {
|
|
|
36419
36586
|
const socket = getWs();
|
|
36420
36587
|
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
36421
36588
|
const skills2 = discoverLocalSkills(getBridgeWorkspaceDirectory());
|
|
36422
|
-
socket
|
|
36589
|
+
sendWsMessage(socket, { type: "local_skills", skills: skills2 });
|
|
36423
36590
|
} catch (e) {
|
|
36424
36591
|
logFn(
|
|
36425
36592
|
`[Bridge service] Local skills report failed: ${e instanceof Error ? e.message : String(e)}`
|
|
@@ -36472,6 +36639,42 @@ function reportGitRepos(getWs, log2) {
|
|
|
36472
36639
|
});
|
|
36473
36640
|
}
|
|
36474
36641
|
|
|
36642
|
+
// src/types/api-to-bridge-messages.ts
|
|
36643
|
+
var API_TO_BRIDGE_MESSAGE_TYPES = [
|
|
36644
|
+
"auth_token",
|
|
36645
|
+
"bridge_identified",
|
|
36646
|
+
"dev_servers_config",
|
|
36647
|
+
"server_control",
|
|
36648
|
+
"agent_config",
|
|
36649
|
+
"prompt_queue_state",
|
|
36650
|
+
"prompt",
|
|
36651
|
+
"session_git_request",
|
|
36652
|
+
"rename_session_branch",
|
|
36653
|
+
"session_archived",
|
|
36654
|
+
"session_discarded",
|
|
36655
|
+
"revert_turn_snapshot",
|
|
36656
|
+
"cancel_run",
|
|
36657
|
+
"cursor_request_response",
|
|
36658
|
+
"skill_call",
|
|
36659
|
+
"file_browser_request",
|
|
36660
|
+
"file_browser_search",
|
|
36661
|
+
"skill_layout_request",
|
|
36662
|
+
"install_skills",
|
|
36663
|
+
"refresh_local_skills"
|
|
36664
|
+
];
|
|
36665
|
+
var API_TO_BRIDGE_TYPE_SET = new Set(API_TO_BRIDGE_MESSAGE_TYPES);
|
|
36666
|
+
function parseApiToBridgeMessage(data, log2) {
|
|
36667
|
+
if (data === null || typeof data !== "object" || Array.isArray(data)) return null;
|
|
36668
|
+
const t = data.type;
|
|
36669
|
+
if (typeof t !== "string" || !API_TO_BRIDGE_TYPE_SET.has(t)) {
|
|
36670
|
+
if (typeof t === "string") {
|
|
36671
|
+
log2?.(`[Bridge service] unhandled message type: ${t}`);
|
|
36672
|
+
}
|
|
36673
|
+
return null;
|
|
36674
|
+
}
|
|
36675
|
+
return data;
|
|
36676
|
+
}
|
|
36677
|
+
|
|
36475
36678
|
// src/bridge/routing/handlers/auth-token.ts
|
|
36476
36679
|
var handleAuthToken = (msg, { log: log2 }) => {
|
|
36477
36680
|
if (typeof msg.token !== "string") return;
|
|
@@ -36482,9 +36685,11 @@ var handleAuthToken = (msg, { log: log2 }) => {
|
|
|
36482
36685
|
// src/bridge/routing/handlers/bridge-identified.ts
|
|
36483
36686
|
var handleBridgeIdentified = (msg, deps) => {
|
|
36484
36687
|
if (typeof msg.bridgeName !== "string") return;
|
|
36485
|
-
deps.onBridgeIdentified(
|
|
36486
|
-
msg
|
|
36487
|
-
|
|
36688
|
+
deps.onBridgeIdentified({
|
|
36689
|
+
bridgeName: msg.bridgeName,
|
|
36690
|
+
proxyPorts: msg.proxyPorts,
|
|
36691
|
+
devServers: msg.devServers
|
|
36692
|
+
});
|
|
36488
36693
|
setImmediate(() => {
|
|
36489
36694
|
void (async () => {
|
|
36490
36695
|
try {
|
|
@@ -36519,7 +36724,174 @@ var handleAgentConfigMessage = (msg, deps) => {
|
|
|
36519
36724
|
};
|
|
36520
36725
|
|
|
36521
36726
|
// src/agents/acp/from-bridge/handle-bridge-prompt.ts
|
|
36522
|
-
import * as
|
|
36727
|
+
import * as path30 from "node:path";
|
|
36728
|
+
|
|
36729
|
+
// src/prompt-turn-queue/client-report.ts
|
|
36730
|
+
function sendPromptQueueClientReport(ws, queues) {
|
|
36731
|
+
if (!ws) return false;
|
|
36732
|
+
sendWsMessage(ws, { type: "prompt_queue_client_report", queues });
|
|
36733
|
+
return true;
|
|
36734
|
+
}
|
|
36735
|
+
|
|
36736
|
+
// src/prompt-turn-queue/disk-store.ts
|
|
36737
|
+
import fs28 from "node:fs";
|
|
36738
|
+
|
|
36739
|
+
// src/prompt-turn-queue/paths.ts
|
|
36740
|
+
import crypto3 from "node:crypto";
|
|
36741
|
+
import fs27 from "node:fs";
|
|
36742
|
+
import path29 from "node:path";
|
|
36743
|
+
import os6 from "node:os";
|
|
36744
|
+
var QUEUE_KEY_HEX_64 = /^[a-f0-9]{64}$/i;
|
|
36745
|
+
function queueStateFileSlug(queueKey) {
|
|
36746
|
+
if (QUEUE_KEY_HEX_64.test(queueKey)) return queueKey.toLowerCase();
|
|
36747
|
+
return crypto3.createHash("sha256").update(queueKey, "utf8").digest("hex");
|
|
36748
|
+
}
|
|
36749
|
+
function getPromptQueuesDirectory() {
|
|
36750
|
+
const override = process.env.BUILDAMATON_PROMPT_QUEUES_DIR?.trim();
|
|
36751
|
+
if (override) return path29.resolve(override);
|
|
36752
|
+
return path29.join(os6.homedir(), ".buildautomaton", "queues");
|
|
36753
|
+
}
|
|
36754
|
+
function ensurePromptQueuesDirectory() {
|
|
36755
|
+
const dir = getPromptQueuesDirectory();
|
|
36756
|
+
if (!fs27.existsSync(dir)) fs27.mkdirSync(dir, { recursive: true });
|
|
36757
|
+
}
|
|
36758
|
+
function queueStateFilePath(queueKey) {
|
|
36759
|
+
return path29.join(getPromptQueuesDirectory(), `${queueStateFileSlug(queueKey)}.json`);
|
|
36760
|
+
}
|
|
36761
|
+
|
|
36762
|
+
// src/prompt-turn-queue/disk-store.ts
|
|
36763
|
+
function parsePersistedQueueFile(raw) {
|
|
36764
|
+
try {
|
|
36765
|
+
const o = JSON.parse(raw);
|
|
36766
|
+
const queueKey = typeof o.queueKey === "string" ? o.queueKey : typeof o.queueKeyHash === "string" ? o.queueKeyHash : null;
|
|
36767
|
+
if (!queueKey || typeof o.updatedAt !== "string" || !Array.isArray(o.turns)) return null;
|
|
36768
|
+
return { queueKey, updatedAt: o.updatedAt, turns: o.turns };
|
|
36769
|
+
} catch {
|
|
36770
|
+
return null;
|
|
36771
|
+
}
|
|
36772
|
+
}
|
|
36773
|
+
function readPersistedQueue(queueKey) {
|
|
36774
|
+
const p = queueStateFilePath(queueKey);
|
|
36775
|
+
try {
|
|
36776
|
+
return parsePersistedQueueFile(fs28.readFileSync(p, "utf8"));
|
|
36777
|
+
} catch {
|
|
36778
|
+
return null;
|
|
36779
|
+
}
|
|
36780
|
+
}
|
|
36781
|
+
function writePersistedQueue(file2) {
|
|
36782
|
+
ensurePromptQueuesDirectory();
|
|
36783
|
+
const p = queueStateFilePath(file2.queueKey);
|
|
36784
|
+
fs28.writeFileSync(p, JSON.stringify(file2, null, 2), "utf8");
|
|
36785
|
+
}
|
|
36786
|
+
function mergeServerQueueSnapshot(queueKey, serverTurns) {
|
|
36787
|
+
const prev = readPersistedQueue(queueKey);
|
|
36788
|
+
const turns = [];
|
|
36789
|
+
for (const raw of serverTurns) {
|
|
36790
|
+
if (!raw || typeof raw !== "object") continue;
|
|
36791
|
+
const o = raw;
|
|
36792
|
+
const turnId = typeof o.turnId === "string" ? o.turnId : "";
|
|
36793
|
+
const sessionId = typeof o.sessionId === "string" ? o.sessionId : "";
|
|
36794
|
+
const turnOrd = typeof o.turnOrd === "number" ? o.turnOrd : Number(o.turnOrd) || 0;
|
|
36795
|
+
const serverState = o.serverState;
|
|
36796
|
+
const lastClientState = o.lastClientState ?? null;
|
|
36797
|
+
const payload = o.payload && typeof o.payload === "object" ? o.payload : {};
|
|
36798
|
+
if (!turnId || !sessionId) continue;
|
|
36799
|
+
if (serverState !== "queued" && serverState !== "stopping" && serverState !== "discarded") continue;
|
|
36800
|
+
const old = prev?.turns.find((t) => t.turnId === turnId);
|
|
36801
|
+
const mergedClient = old?.lastClientState === "running" && lastClientState == null ? "running" : lastClientState;
|
|
36802
|
+
turns.push({
|
|
36803
|
+
turnId,
|
|
36804
|
+
sessionId,
|
|
36805
|
+
turnOrd,
|
|
36806
|
+
serverState,
|
|
36807
|
+
lastClientState: mergedClient,
|
|
36808
|
+
payload
|
|
36809
|
+
});
|
|
36810
|
+
}
|
|
36811
|
+
turns.sort((a, b) => a.turnOrd - b.turnOrd);
|
|
36812
|
+
return { queueKey, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), turns };
|
|
36813
|
+
}
|
|
36814
|
+
|
|
36815
|
+
// src/prompt-turn-queue/runner.ts
|
|
36816
|
+
var runIdToQueueKey = /* @__PURE__ */ new Map();
|
|
36817
|
+
function pickNextRunnableTurn(turns) {
|
|
36818
|
+
for (const t of turns) {
|
|
36819
|
+
if (t.serverState === "discarded" || t.serverState === "stopping") continue;
|
|
36820
|
+
if (t.serverState !== "queued") continue;
|
|
36821
|
+
if (t.lastClientState === "running" || t.lastClientState === "stopped" || t.lastClientState === "failed") continue;
|
|
36822
|
+
return t;
|
|
36823
|
+
}
|
|
36824
|
+
return null;
|
|
36825
|
+
}
|
|
36826
|
+
function hasRunningTurn(turns) {
|
|
36827
|
+
return turns.some((t) => t.lastClientState === "running");
|
|
36828
|
+
}
|
|
36829
|
+
function dispatchLocalPrompt(next, deps) {
|
|
36830
|
+
const pl = next.payload;
|
|
36831
|
+
const msg = {
|
|
36832
|
+
type: "prompt",
|
|
36833
|
+
sessionId: next.sessionId,
|
|
36834
|
+
runId: next.turnId,
|
|
36835
|
+
prompt: pl.prompt,
|
|
36836
|
+
mode: typeof pl.mode === "string" ? pl.mode : "agent",
|
|
36837
|
+
isNewSession: pl.isNewSession === true,
|
|
36838
|
+
...typeof pl.followUpCatalogPromptId === "string" ? { followUpCatalogPromptId: pl.followUpCatalogPromptId } : {},
|
|
36839
|
+
...Array.isArray(pl.sessionChangeSummaryFilePaths) ? { sessionChangeSummaryFilePaths: pl.sessionChangeSummaryFilePaths } : {},
|
|
36840
|
+
...Array.isArray(pl.sessionChangeSummaryFileSnapshots) ? { sessionChangeSummaryFileSnapshots: pl.sessionChangeSummaryFileSnapshots } : {},
|
|
36841
|
+
...typeof pl.agentType === "string" && pl.agentType.trim() ? { agentType: pl.agentType.trim() } : {}
|
|
36842
|
+
};
|
|
36843
|
+
handleBridgePrompt(msg, deps);
|
|
36844
|
+
}
|
|
36845
|
+
function applyPromptQueueStateFromServer(msg, deps) {
|
|
36846
|
+
const raw = msg.queues;
|
|
36847
|
+
if (!raw || typeof raw !== "object") return;
|
|
36848
|
+
const getWs = deps.getWs;
|
|
36849
|
+
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
36850
|
+
if (!Array.isArray(serverTurns)) continue;
|
|
36851
|
+
const file2 = mergeServerQueueSnapshot(queueKey, serverTurns);
|
|
36852
|
+
writePersistedQueue(file2);
|
|
36853
|
+
}
|
|
36854
|
+
const report = {};
|
|
36855
|
+
const startedThisTick = /* @__PURE__ */ new Set();
|
|
36856
|
+
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
36857
|
+
if (!Array.isArray(serverTurns)) continue;
|
|
36858
|
+
const file2 = readPersistedQueue(queueKey);
|
|
36859
|
+
if (!file2) continue;
|
|
36860
|
+
if (hasRunningTurn(file2.turns)) continue;
|
|
36861
|
+
const next = pickNextRunnableTurn(file2.turns);
|
|
36862
|
+
if (!next) continue;
|
|
36863
|
+
next.lastClientState = "running";
|
|
36864
|
+
writePersistedQueue(file2);
|
|
36865
|
+
runIdToQueueKey.set(next.turnId, queueKey);
|
|
36866
|
+
startedThisTick.add(next.turnId);
|
|
36867
|
+
report[queueKey] = [{ turnId: next.turnId, clientState: "running" }];
|
|
36868
|
+
}
|
|
36869
|
+
if (Object.keys(report).length > 0) {
|
|
36870
|
+
sendPromptQueueClientReport(getWs(), report);
|
|
36871
|
+
}
|
|
36872
|
+
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
36873
|
+
if (!Array.isArray(serverTurns)) continue;
|
|
36874
|
+
const file2 = readPersistedQueue(queueKey);
|
|
36875
|
+
if (!file2) continue;
|
|
36876
|
+
const running = file2.turns.find((t) => t.lastClientState === "running");
|
|
36877
|
+
if (!running || !startedThisTick.has(running.turnId)) continue;
|
|
36878
|
+
if (runIdToQueueKey.get(running.turnId) !== queueKey) continue;
|
|
36879
|
+
dispatchLocalPrompt(running, deps);
|
|
36880
|
+
}
|
|
36881
|
+
}
|
|
36882
|
+
function finalizePromptTurnOnBridge(getWs, runId, success2) {
|
|
36883
|
+
if (!runId) return;
|
|
36884
|
+
const queueKey = runIdToQueueKey.get(runId);
|
|
36885
|
+
runIdToQueueKey.delete(runId);
|
|
36886
|
+
if (!queueKey) return;
|
|
36887
|
+
const f = readPersistedQueue(queueKey);
|
|
36888
|
+
if (!f) return;
|
|
36889
|
+
const t = f.turns.find((x) => x.turnId === runId);
|
|
36890
|
+
if (!t) return;
|
|
36891
|
+
t.lastClientState = success2 ? "stopped" : "failed";
|
|
36892
|
+
writePersistedQueue(f);
|
|
36893
|
+
sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId, clientState: t.lastClientState }] });
|
|
36894
|
+
}
|
|
36523
36895
|
|
|
36524
36896
|
// src/agents/acp/from-bridge/bridge-prompt-wiring.ts
|
|
36525
36897
|
function createBridgePromptSenders(deps, getWs) {
|
|
@@ -36534,6 +36906,9 @@ function createBridgePromptSenders(deps, getWs) {
|
|
|
36534
36906
|
const skipEncryptForChangeSummaryFollowUp = result.type === "prompt_result" && result.followUpCatalogPromptId === BUILTIN_SESSION_CHANGE_SUMMARY_FOLLOW_UP_CATALOG_PROMPT_ID;
|
|
36535
36907
|
const encryptedFields = result.type === "prompt_result" && !skipEncryptForChangeSummaryFollowUp ? ["output", "error"] : [];
|
|
36536
36908
|
sendBridgeMessage(result, encryptedFields);
|
|
36909
|
+
if (result.type === "prompt_result") {
|
|
36910
|
+
finalizePromptTurnOnBridge(getWs, typeof result.runId === "string" ? result.runId : void 0, result.success === true);
|
|
36911
|
+
}
|
|
36537
36912
|
};
|
|
36538
36913
|
const sendSessionUpdate = (payload) => {
|
|
36539
36914
|
const s = getWs();
|
|
@@ -36558,63 +36933,6 @@ function createBridgePromptSenders(deps, getWs) {
|
|
|
36558
36933
|
// src/agents/acp/from-bridge/bridge-prompt-preamble.ts
|
|
36559
36934
|
import { execFile as execFile10 } from "node:child_process";
|
|
36560
36935
|
import { promisify as promisify10 } from "node:util";
|
|
36561
|
-
|
|
36562
|
-
// src/git/bridge-queue-key.ts
|
|
36563
|
-
import * as path28 from "node:path";
|
|
36564
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
36565
|
-
function normalizeCanonicalGitUrl(url2) {
|
|
36566
|
-
let s = url2.trim();
|
|
36567
|
-
if (!s) return s;
|
|
36568
|
-
if (s.toLowerCase().endsWith(".git")) {
|
|
36569
|
-
s = s.slice(0, -4);
|
|
36570
|
-
}
|
|
36571
|
-
s = s.replace(/\/+$/, "");
|
|
36572
|
-
const httpsMatch = /^(https?):\/\/([^/]+)(\/.*)?$/i.exec(s);
|
|
36573
|
-
if (httpsMatch) {
|
|
36574
|
-
const host = httpsMatch[2].toLowerCase();
|
|
36575
|
-
const p = httpsMatch[3] ?? "";
|
|
36576
|
-
s = `${httpsMatch[1].toLowerCase()}://${host}${p}`;
|
|
36577
|
-
} else {
|
|
36578
|
-
const sshMatch = /^git@([^:]+):(.+)$/i.exec(s);
|
|
36579
|
-
if (sshMatch) {
|
|
36580
|
-
const host = sshMatch[1].toLowerCase();
|
|
36581
|
-
s = `git@${host}:${sshMatch[2]}`;
|
|
36582
|
-
}
|
|
36583
|
-
}
|
|
36584
|
-
return s;
|
|
36585
|
-
}
|
|
36586
|
-
function canonicalUrlToRepoIdSync(url2) {
|
|
36587
|
-
const normalized = normalizeCanonicalGitUrl(url2);
|
|
36588
|
-
return createHash2("sha256").update(normalized).digest("hex").slice(0, 32);
|
|
36589
|
-
}
|
|
36590
|
-
function fallbackRepoIdFromPath(absPath) {
|
|
36591
|
-
return createHash2("sha256").update(path28.resolve(absPath)).digest("hex").slice(0, 32);
|
|
36592
|
-
}
|
|
36593
|
-
async function resolveBridgeQueueBindFields(options) {
|
|
36594
|
-
const { effectiveCwd, worktreePaths, primaryRepoRoots, log: log2 } = options;
|
|
36595
|
-
const cwdAbs = worktreePaths.length > 0 ? path28.resolve(worktreePaths[0]) : path28.resolve(effectiveCwd);
|
|
36596
|
-
if (!primaryRepoRoots.length) {
|
|
36597
|
-
log2("[Bridge service] Prompt queue bind skipped: no Git repository roots under the working directory.");
|
|
36598
|
-
return null;
|
|
36599
|
-
}
|
|
36600
|
-
let primaryRoot = primaryRepoRoots[0];
|
|
36601
|
-
let remote = await getRemoteOriginUrl(primaryRoot);
|
|
36602
|
-
if (!remote) {
|
|
36603
|
-
for (const r of primaryRepoRoots.slice(1)) {
|
|
36604
|
-
const u = await getRemoteOriginUrl(r);
|
|
36605
|
-
if (u) {
|
|
36606
|
-
primaryRoot = r;
|
|
36607
|
-
remote = u;
|
|
36608
|
-
break;
|
|
36609
|
-
}
|
|
36610
|
-
}
|
|
36611
|
-
}
|
|
36612
|
-
const repoId = remote ? canonicalUrlToRepoIdSync(remote) : fallbackRepoIdFromPath(primaryRoot);
|
|
36613
|
-
const canonicalQueueKey = `repo:${repoId}::cwd:${cwdAbs}`;
|
|
36614
|
-
return { canonicalQueueKey, repoId, cwdAbs };
|
|
36615
|
-
}
|
|
36616
|
-
|
|
36617
|
-
// src/agents/acp/from-bridge/bridge-prompt-preamble.ts
|
|
36618
36936
|
var execFileAsync9 = promisify10(execFile10);
|
|
36619
36937
|
async function readGitBranch(cwd) {
|
|
36620
36938
|
try {
|
|
@@ -36634,30 +36952,17 @@ async function runBridgePromptPreamble(params) {
|
|
|
36634
36952
|
fallbackCwd: effectiveCwd,
|
|
36635
36953
|
log: log2
|
|
36636
36954
|
});
|
|
36637
|
-
if (s && sessionId) {
|
|
36638
|
-
const bind = await resolveBridgeQueueBindFields({
|
|
36639
|
-
effectiveCwd,
|
|
36640
|
-
worktreePaths,
|
|
36641
|
-
primaryRepoRoots: repoRoots,
|
|
36642
|
-
log: log2
|
|
36643
|
-
});
|
|
36644
|
-
if (bind) {
|
|
36645
|
-
sendWsMessage(s, {
|
|
36646
|
-
type: "bridge_queue_bind",
|
|
36647
|
-
sessionId,
|
|
36648
|
-
canonicalQueueKey: bind.canonicalQueueKey,
|
|
36649
|
-
repoId: bind.repoId,
|
|
36650
|
-
cwdAbs: bind.cwdAbs
|
|
36651
|
-
});
|
|
36652
|
-
}
|
|
36653
|
-
}
|
|
36654
36955
|
if (s && sessionId) {
|
|
36655
36956
|
const cliGitBranch = await readGitBranch(effectiveCwd);
|
|
36957
|
+
const usesWt = sessionWorktreeManager.usesWorktreeSession(sessionId);
|
|
36958
|
+
const mirrorAbs = sessionWorktreeManager.getAgentCwdForSession(sessionId);
|
|
36656
36959
|
sendWsMessage(s, {
|
|
36657
36960
|
type: "session_git_context_report",
|
|
36658
36961
|
sessionId,
|
|
36659
36962
|
cliGitBranch,
|
|
36660
|
-
agentUsesWorktree:
|
|
36963
|
+
agentUsesWorktree: usesWt,
|
|
36964
|
+
sessionParent: usesWt ? "worktrees_root" : "bridge_root",
|
|
36965
|
+
sessionParentPath: usesWt ? mirrorAbs : getBridgeWorkspaceDirectory()
|
|
36661
36966
|
});
|
|
36662
36967
|
}
|
|
36663
36968
|
if (s && sessionId && runId) {
|
|
@@ -36676,9 +36981,9 @@ function parseChangeSummarySnapshots(raw) {
|
|
|
36676
36981
|
for (const item of raw) {
|
|
36677
36982
|
if (!item || typeof item !== "object") continue;
|
|
36678
36983
|
const o = item;
|
|
36679
|
-
const
|
|
36680
|
-
if (!
|
|
36681
|
-
const row = { path:
|
|
36984
|
+
const path36 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
|
|
36985
|
+
if (!path36) continue;
|
|
36986
|
+
const row = { path: path36 };
|
|
36682
36987
|
if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
|
|
36683
36988
|
if (typeof o.oldText === "string") row.oldText = o.oldText;
|
|
36684
36989
|
if (typeof o.newText === "string") row.newText = o.newText;
|
|
@@ -36777,12 +37082,14 @@ function handleBridgePrompt(msg, deps) {
|
|
|
36777
37082
|
return;
|
|
36778
37083
|
}
|
|
36779
37084
|
const isNewSession = msg.isNewSession === true;
|
|
36780
|
-
const
|
|
37085
|
+
const rawParent = msg.sessionParent;
|
|
37086
|
+
const sessionParent = rawParent === "bridge_root" || rawParent === "worktrees_root" ? rawParent : rawParent === "session_worktrees_root" ? "worktrees_root" : null;
|
|
37087
|
+
const sessionParentPath = typeof msg.sessionParentPath === "string" && msg.sessionParentPath.trim() ? msg.sessionParentPath.trim() : null;
|
|
36781
37088
|
const agentType = typeof msg.agentType === "string" && msg.agentType.trim() ? msg.agentType.trim() : void 0;
|
|
36782
37089
|
const mode = typeof msg.mode === "string" && msg.mode.trim() ? msg.mode.trim() : void 0;
|
|
36783
37090
|
acpManager.logPromptReceivedFromBridge({ agentType, mode });
|
|
36784
37091
|
async function preambleAndPrompt(resolvedCwd) {
|
|
36785
|
-
const effectiveCwd =
|
|
37092
|
+
const effectiveCwd = path30.resolve(resolvedCwd ?? getBridgeWorkspaceDirectory());
|
|
36786
37093
|
await runBridgePromptPreamble({
|
|
36787
37094
|
getWs,
|
|
36788
37095
|
log: log2,
|
|
@@ -36825,7 +37132,7 @@ function handleBridgePrompt(msg, deps) {
|
|
|
36825
37132
|
e2ee: deps.e2ee
|
|
36826
37133
|
});
|
|
36827
37134
|
}
|
|
36828
|
-
void sessionWorktreeManager.resolveCwdForPrompt(sessionId, { isNewSession,
|
|
37135
|
+
void sessionWorktreeManager.resolveCwdForPrompt(sessionId, { isNewSession, sessionParent, sessionParentPath }).then((cwd) => preambleAndPrompt(cwd)).catch((err) => {
|
|
36829
37136
|
log2(`[Agent] Worktree resolve failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
36830
37137
|
void preambleAndPrompt(void 0);
|
|
36831
37138
|
});
|
|
@@ -36836,6 +37143,11 @@ var handlePromptMessage = (msg, deps) => {
|
|
|
36836
37143
|
handleBridgePrompt(msg, deps);
|
|
36837
37144
|
};
|
|
36838
37145
|
|
|
37146
|
+
// src/bridge/routing/handlers/prompt-queue-state.ts
|
|
37147
|
+
var handlePromptQueueStateMessage = (msg, deps) => {
|
|
37148
|
+
applyPromptQueueStateFromServer(msg, deps);
|
|
37149
|
+
};
|
|
37150
|
+
|
|
36839
37151
|
// src/agents/acp/from-bridge/handle-bridge-cancel-run.ts
|
|
36840
37152
|
async function handleBridgeCancelRun(msg, { log: log2, acpManager, getWs }) {
|
|
36841
37153
|
const runId = msg.runId;
|
|
@@ -36855,6 +37167,7 @@ async function handleBridgeCancelRun(msg, { log: log2, acpManager, getWs }) {
|
|
|
36855
37167
|
error: "Stopped by user",
|
|
36856
37168
|
stopReason: "no_local_run"
|
|
36857
37169
|
});
|
|
37170
|
+
finalizePromptTurnOnBridge(getWs, runId, false);
|
|
36858
37171
|
}
|
|
36859
37172
|
|
|
36860
37173
|
// src/bridge/routing/handlers/cancel-run.ts
|
|
@@ -36894,8 +37207,8 @@ function randomSecret() {
|
|
|
36894
37207
|
}
|
|
36895
37208
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
36896
37209
|
}
|
|
36897
|
-
async function requestPreviewApi(port, secret, method,
|
|
36898
|
-
const url2 = `http://127.0.0.1:${port}${
|
|
37210
|
+
async function requestPreviewApi(port, secret, method, path36, body) {
|
|
37211
|
+
const url2 = `http://127.0.0.1:${port}${path36}`;
|
|
36899
37212
|
const headers = {
|
|
36900
37213
|
[PREVIEW_SECRET_HEADER]: secret,
|
|
36901
37214
|
"Content-Type": "application/json"
|
|
@@ -36907,7 +37220,7 @@ async function requestPreviewApi(port, secret, method, path34, body) {
|
|
|
36907
37220
|
});
|
|
36908
37221
|
const data = await res.json().catch(() => ({}));
|
|
36909
37222
|
if (!res.ok) {
|
|
36910
|
-
throw new Error(data?.error ?? `Preview API ${method} ${
|
|
37223
|
+
throw new Error(data?.error ?? `Preview API ${method} ${path36}: ${res.status}`);
|
|
36911
37224
|
}
|
|
36912
37225
|
return data;
|
|
36913
37226
|
}
|
|
@@ -37059,26 +37372,28 @@ function handleSkillCall(msg, socket, log2) {
|
|
|
37059
37372
|
|
|
37060
37373
|
// src/bridge/routing/handlers/skill-call.ts
|
|
37061
37374
|
var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
37062
|
-
|
|
37375
|
+
const skillId = typeof msg.skillId === "string" ? msg.skillId : "";
|
|
37376
|
+
const operationId = typeof msg.operationId === "string" ? msg.operationId : "";
|
|
37377
|
+
if (!skillId || !operationId) return;
|
|
37063
37378
|
const socket = getWs();
|
|
37064
37379
|
if (!socket) return;
|
|
37065
37380
|
handleSkillCall(
|
|
37066
|
-
msg,
|
|
37381
|
+
{ id: msg.id, skillId, operationId, params: msg.params },
|
|
37067
37382
|
socket,
|
|
37068
37383
|
log2
|
|
37069
37384
|
);
|
|
37070
37385
|
};
|
|
37071
37386
|
|
|
37072
37387
|
// src/files/list-dir.ts
|
|
37073
|
-
import
|
|
37074
|
-
import
|
|
37388
|
+
import fs29 from "node:fs";
|
|
37389
|
+
import path32 from "node:path";
|
|
37075
37390
|
|
|
37076
37391
|
// src/files/ensure-under-cwd.ts
|
|
37077
|
-
import
|
|
37392
|
+
import path31 from "node:path";
|
|
37078
37393
|
function ensureUnderCwd(relativePath, cwd = getBridgeWorkspaceDirectory()) {
|
|
37079
|
-
const normalized =
|
|
37080
|
-
const resolved =
|
|
37081
|
-
if (!resolved.startsWith(cwd +
|
|
37394
|
+
const normalized = path31.normalize(relativePath).replace(/^(\.\/)+/, "");
|
|
37395
|
+
const resolved = path31.resolve(cwd, normalized);
|
|
37396
|
+
if (!resolved.startsWith(cwd + path31.sep) && resolved !== cwd) {
|
|
37082
37397
|
return null;
|
|
37083
37398
|
}
|
|
37084
37399
|
return resolved;
|
|
@@ -37092,7 +37407,7 @@ async function listDirAsync(relativePath) {
|
|
|
37092
37407
|
return { error: "Path is outside working directory" };
|
|
37093
37408
|
}
|
|
37094
37409
|
try {
|
|
37095
|
-
const names = await
|
|
37410
|
+
const names = await fs29.promises.readdir(resolved, { withFileTypes: true });
|
|
37096
37411
|
const visible = names.filter((d) => !d.name.startsWith("."));
|
|
37097
37412
|
const entries = [];
|
|
37098
37413
|
for (let i = 0; i < visible.length; i++) {
|
|
@@ -37100,12 +37415,12 @@ async function listDirAsync(relativePath) {
|
|
|
37100
37415
|
await yieldToEventLoop();
|
|
37101
37416
|
}
|
|
37102
37417
|
const d = visible[i];
|
|
37103
|
-
const entryPath =
|
|
37104
|
-
const fullPath =
|
|
37418
|
+
const entryPath = path32.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
37419
|
+
const fullPath = path32.join(resolved, d.name);
|
|
37105
37420
|
let isDir = d.isDirectory();
|
|
37106
37421
|
if (d.isSymbolicLink()) {
|
|
37107
37422
|
try {
|
|
37108
|
-
const targetStat = await
|
|
37423
|
+
const targetStat = await fs29.promises.stat(fullPath);
|
|
37109
37424
|
isDir = targetStat.isDirectory();
|
|
37110
37425
|
} catch {
|
|
37111
37426
|
isDir = false;
|
|
@@ -37130,25 +37445,25 @@ async function listDirAsync(relativePath) {
|
|
|
37130
37445
|
}
|
|
37131
37446
|
|
|
37132
37447
|
// src/files/read-file.ts
|
|
37133
|
-
import
|
|
37448
|
+
import fs30 from "node:fs";
|
|
37134
37449
|
import { StringDecoder } from "node:string_decoder";
|
|
37135
37450
|
function resolveFilePath(relativePath) {
|
|
37136
37451
|
const resolved = ensureUnderCwd(relativePath, getBridgeWorkspaceDirectory());
|
|
37137
37452
|
if (!resolved) return { error: "Path is outside working directory" };
|
|
37138
37453
|
let real;
|
|
37139
37454
|
try {
|
|
37140
|
-
real =
|
|
37455
|
+
real = fs30.realpathSync(resolved);
|
|
37141
37456
|
} catch {
|
|
37142
37457
|
real = resolved;
|
|
37143
37458
|
}
|
|
37144
|
-
const stat3 =
|
|
37459
|
+
const stat3 = fs30.statSync(real);
|
|
37145
37460
|
if (!stat3.isFile()) return { error: "Not a file" };
|
|
37146
37461
|
return real;
|
|
37147
37462
|
}
|
|
37148
37463
|
var LINE_CHUNK_SIZE = 64 * 1024;
|
|
37149
37464
|
function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
37150
|
-
const fileSize =
|
|
37151
|
-
const fd =
|
|
37465
|
+
const fileSize = fs30.statSync(filePath).size;
|
|
37466
|
+
const fd = fs30.openSync(filePath, "r");
|
|
37152
37467
|
const bufSize = 64 * 1024;
|
|
37153
37468
|
const buf = Buffer.alloc(bufSize);
|
|
37154
37469
|
const decoder = new StringDecoder("utf8");
|
|
@@ -37161,7 +37476,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
37161
37476
|
let line0Accum = "";
|
|
37162
37477
|
try {
|
|
37163
37478
|
let bytesRead;
|
|
37164
|
-
while (!done && (bytesRead =
|
|
37479
|
+
while (!done && (bytesRead = fs30.readSync(fd, buf, 0, bufSize, null)) > 0) {
|
|
37165
37480
|
const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
|
|
37166
37481
|
partial2 = "";
|
|
37167
37482
|
let lineStart = 0;
|
|
@@ -37296,7 +37611,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
37296
37611
|
}
|
|
37297
37612
|
return { content: resultLines.join("\n"), size: fileSize };
|
|
37298
37613
|
} finally {
|
|
37299
|
-
|
|
37614
|
+
fs30.closeSync(fd);
|
|
37300
37615
|
}
|
|
37301
37616
|
}
|
|
37302
37617
|
function readFile3(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
@@ -37307,8 +37622,8 @@ function readFile3(relativePath, startLine, endLine, lineOffset, lineChunkSize =
|
|
|
37307
37622
|
if (hasRange) {
|
|
37308
37623
|
return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
|
|
37309
37624
|
}
|
|
37310
|
-
const stat3 =
|
|
37311
|
-
const raw =
|
|
37625
|
+
const stat3 = fs30.statSync(result);
|
|
37626
|
+
const raw = fs30.readFileSync(result, "utf8");
|
|
37312
37627
|
const lines = raw.split(/\r?\n/);
|
|
37313
37628
|
return { content: raw, totalLines: lines.length, size: stat3.size };
|
|
37314
37629
|
} catch (err) {
|
|
@@ -37420,12 +37735,14 @@ function handleSkillLayoutRequest(msg, deps) {
|
|
|
37420
37735
|
const socket = deps.getWs();
|
|
37421
37736
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
37422
37737
|
const roots = discoverSkillLayoutRoots(getBridgeWorkspaceDirectory());
|
|
37423
|
-
socket
|
|
37738
|
+
if (socket) {
|
|
37739
|
+
sendWsMessage(socket, { type: "skill_layout_response", id, roots });
|
|
37740
|
+
}
|
|
37424
37741
|
}
|
|
37425
37742
|
|
|
37426
37743
|
// src/skills/install-remote-skills.ts
|
|
37427
|
-
import
|
|
37428
|
-
import
|
|
37744
|
+
import fs31 from "node:fs";
|
|
37745
|
+
import path33 from "node:path";
|
|
37429
37746
|
function installRemoteSkills(cwd, targetDir, items) {
|
|
37430
37747
|
const installed2 = [];
|
|
37431
37748
|
if (!Array.isArray(items)) {
|
|
@@ -37436,15 +37753,15 @@ function installRemoteSkills(cwd, targetDir, items) {
|
|
|
37436
37753
|
if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
|
|
37437
37754
|
continue;
|
|
37438
37755
|
}
|
|
37439
|
-
const skillDir =
|
|
37756
|
+
const skillDir = path33.join(cwd, targetDir, item.skillName);
|
|
37440
37757
|
for (const f of item.files) {
|
|
37441
37758
|
if (typeof f.path !== "string" || !f.text && !f.base64) continue;
|
|
37442
|
-
const dest =
|
|
37443
|
-
|
|
37759
|
+
const dest = path33.join(skillDir, f.path);
|
|
37760
|
+
fs31.mkdirSync(path33.dirname(dest), { recursive: true });
|
|
37444
37761
|
if (f.text !== void 0) {
|
|
37445
|
-
|
|
37762
|
+
fs31.writeFileSync(dest, f.text, "utf8");
|
|
37446
37763
|
} else if (f.base64) {
|
|
37447
|
-
|
|
37764
|
+
fs31.writeFileSync(dest, Buffer.from(f.base64, "base64"));
|
|
37448
37765
|
}
|
|
37449
37766
|
}
|
|
37450
37767
|
installed2.push({
|
|
@@ -37470,10 +37787,14 @@ var handleInstallSkillsMessage = (msg, deps) => {
|
|
|
37470
37787
|
if (!result.success) {
|
|
37471
37788
|
const err = result.error ?? "Invalid items";
|
|
37472
37789
|
deps.log(`[Bridge service] Install skills failed: ${err}`);
|
|
37473
|
-
socket
|
|
37790
|
+
if (socket) {
|
|
37791
|
+
sendWsMessage(socket, { type: "install_skills_result", id, success: false, error: err });
|
|
37792
|
+
}
|
|
37474
37793
|
return;
|
|
37475
37794
|
}
|
|
37476
|
-
socket
|
|
37795
|
+
if (socket) {
|
|
37796
|
+
sendWsMessage(socket, { type: "install_skills_result", id, success: true, installed: result.installed });
|
|
37797
|
+
}
|
|
37477
37798
|
};
|
|
37478
37799
|
|
|
37479
37800
|
// src/bridge/routing/handlers/refresh-local-skills.ts
|
|
@@ -37590,7 +37911,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
|
|
|
37590
37911
|
};
|
|
37591
37912
|
|
|
37592
37913
|
// src/bridge/routing/handlers/revert-turn-snapshot.ts
|
|
37593
|
-
import * as
|
|
37914
|
+
import * as fs32 from "node:fs";
|
|
37594
37915
|
var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
37595
37916
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
37596
37917
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
@@ -37602,7 +37923,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
37602
37923
|
if (!s) return;
|
|
37603
37924
|
const agentBase = sessionWorktreeManager.getAgentCwdForSession(sessionId) ?? getBridgeWorkspaceDirectory();
|
|
37604
37925
|
const file2 = snapshotFilePath(agentBase, turnId);
|
|
37605
|
-
if (!
|
|
37926
|
+
if (!fs32.existsSync(file2)) {
|
|
37606
37927
|
sendWsMessage(s, {
|
|
37607
37928
|
type: "revert_turn_snapshot_result",
|
|
37608
37929
|
id,
|
|
@@ -37623,7 +37944,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
37623
37944
|
|
|
37624
37945
|
// src/bridge/routing/handlers/dev-server-control.ts
|
|
37625
37946
|
var handleDevServerControl = (msg, deps) => {
|
|
37626
|
-
let wire
|
|
37947
|
+
let wire;
|
|
37627
37948
|
try {
|
|
37628
37949
|
wire = deps.e2ee ? deps.e2ee.decryptMessage(msg) : msg;
|
|
37629
37950
|
} catch (e) {
|
|
@@ -37644,9 +37965,7 @@ var handleDevServersConfig = (msg, deps) => {
|
|
|
37644
37965
|
|
|
37645
37966
|
// src/bridge/routing/dispatch-bridge-message.ts
|
|
37646
37967
|
function dispatchBridgeMessage(msg, deps) {
|
|
37647
|
-
|
|
37648
|
-
if (typeof type !== "string") return;
|
|
37649
|
-
switch (type) {
|
|
37968
|
+
switch (msg.type) {
|
|
37650
37969
|
case "auth_token":
|
|
37651
37970
|
handleAuthToken(msg, deps);
|
|
37652
37971
|
break;
|
|
@@ -37662,6 +37981,9 @@ function dispatchBridgeMessage(msg, deps) {
|
|
|
37662
37981
|
case "agent_config":
|
|
37663
37982
|
handleAgentConfigMessage(msg, deps);
|
|
37664
37983
|
break;
|
|
37984
|
+
case "prompt_queue_state":
|
|
37985
|
+
handlePromptQueueStateMessage(msg, deps);
|
|
37986
|
+
break;
|
|
37665
37987
|
case "prompt":
|
|
37666
37988
|
handlePromptMessage(msg, deps);
|
|
37667
37989
|
break;
|
|
@@ -37704,15 +38026,14 @@ function dispatchBridgeMessage(msg, deps) {
|
|
|
37704
38026
|
case "refresh_local_skills":
|
|
37705
38027
|
handleRefreshLocalSkills(msg, deps);
|
|
37706
38028
|
break;
|
|
37707
|
-
default:
|
|
37708
|
-
deps.log?.(`[Bridge service] unhandled message type: ${type}`);
|
|
37709
38029
|
}
|
|
37710
38030
|
}
|
|
37711
38031
|
|
|
37712
38032
|
// src/bridge/routing/handle-bridge-message.ts
|
|
37713
38033
|
function handleBridgeMessage(data, deps) {
|
|
37714
|
-
const msg = data;
|
|
37715
38034
|
if (!deps.getWs()) return;
|
|
38035
|
+
const msg = parseApiToBridgeMessage(data, deps.log);
|
|
38036
|
+
if (!msg) return;
|
|
37716
38037
|
setImmediate(() => {
|
|
37717
38038
|
dispatchBridgeMessage(msg, deps);
|
|
37718
38039
|
});
|
|
@@ -37758,7 +38079,8 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
37758
38079
|
tokens,
|
|
37759
38080
|
persistTokens,
|
|
37760
38081
|
onAuthInvalid,
|
|
37761
|
-
e2ee
|
|
38082
|
+
e2ee,
|
|
38083
|
+
identifyReportedPaths
|
|
37762
38084
|
} = params;
|
|
37763
38085
|
let authRefreshInFlight = false;
|
|
37764
38086
|
function handleOpen() {
|
|
@@ -37771,7 +38093,14 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
37771
38093
|
}
|
|
37772
38094
|
const socket = getWs();
|
|
37773
38095
|
if (socket) {
|
|
37774
|
-
sendWsMessage(socket, {
|
|
38096
|
+
sendWsMessage(socket, {
|
|
38097
|
+
type: "identify",
|
|
38098
|
+
role: "cli",
|
|
38099
|
+
cliVersion: CLI_VERSION,
|
|
38100
|
+
bridgeRootPath: identifyReportedPaths.bridgeRootPath,
|
|
38101
|
+
worktreesRootPath: identifyReportedPaths.worktreesRootPath,
|
|
38102
|
+
...e2ee ? { e: e2ee.handshake } : {}
|
|
38103
|
+
});
|
|
37775
38104
|
reportGitRepos(getWs, logFn);
|
|
37776
38105
|
}
|
|
37777
38106
|
if (justAuthenticated && socket) {
|
|
@@ -37897,7 +38226,6 @@ async function createBridgeConnection(options) {
|
|
|
37897
38226
|
const e2ee = options.e2eCertificate ? createCliE2eeRuntime(options.e2eCertificate) : void 0;
|
|
37898
38227
|
const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeCwd: getBridgeWorkspaceDirectory, e2ee });
|
|
37899
38228
|
const onBridgeIdentified = createOnBridgeIdentified({
|
|
37900
|
-
sessionWorktreeManager,
|
|
37901
38229
|
devServerManager,
|
|
37902
38230
|
firehoseServerUrl,
|
|
37903
38231
|
workspaceId,
|
|
@@ -37919,6 +38247,10 @@ async function createBridgeConnection(options) {
|
|
|
37919
38247
|
cloudApiBaseUrl: apiUrl,
|
|
37920
38248
|
getCloudAccessToken: () => tokens.accessToken
|
|
37921
38249
|
};
|
|
38250
|
+
const identifyReportedPaths = {
|
|
38251
|
+
bridgeRootPath: path34.resolve(getBridgeWorkspaceDirectory()),
|
|
38252
|
+
worktreesRootPath: path34.resolve(worktreesRootAbs)
|
|
38253
|
+
};
|
|
37922
38254
|
const { connect } = createMainBridgeWebSocketLifecycle({
|
|
37923
38255
|
state,
|
|
37924
38256
|
getWs,
|
|
@@ -37930,7 +38262,8 @@ async function createBridgeConnection(options) {
|
|
|
37930
38262
|
tokens,
|
|
37931
38263
|
persistTokens,
|
|
37932
38264
|
onAuthInvalid,
|
|
37933
|
-
e2ee
|
|
38265
|
+
e2ee,
|
|
38266
|
+
identifyReportedPaths
|
|
37934
38267
|
});
|
|
37935
38268
|
connect();
|
|
37936
38269
|
const stopFileIndexWatcher = startFileIndexWatcher(getBridgeWorkspaceDirectory());
|
|
@@ -38148,9 +38481,9 @@ async function runCliAction(program2, opts) {
|
|
|
38148
38481
|
let authToken = opts.token;
|
|
38149
38482
|
const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
|
|
38150
38483
|
if (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim()) {
|
|
38151
|
-
const resolvedCwd =
|
|
38484
|
+
const resolvedCwd = path35.resolve(process.cwd(), opts.cwd.trim());
|
|
38152
38485
|
try {
|
|
38153
|
-
const st =
|
|
38486
|
+
const st = fs33.statSync(resolvedCwd);
|
|
38154
38487
|
if (!st.isDirectory()) {
|
|
38155
38488
|
console.error(`--cwd is not a directory: ${resolvedCwd}`);
|
|
38156
38489
|
process.exit(1);
|
|
@@ -38170,7 +38503,7 @@ async function runCliAction(program2, opts) {
|
|
|
38170
38503
|
);
|
|
38171
38504
|
let worktreesRootAbs;
|
|
38172
38505
|
if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
|
|
38173
|
-
worktreesRootAbs =
|
|
38506
|
+
worktreesRootAbs = path35.resolve(opts.worktreesRoot.trim());
|
|
38174
38507
|
}
|
|
38175
38508
|
const e2eCertificates = opts.e2eeCertificatesDir?.trim() ? await loadOrCreateE2eCertificates(opts.e2eeCertificatesDir.trim()) : void 0;
|
|
38176
38509
|
if (e2eCertificates) {
|
|
@@ -38213,7 +38546,7 @@ async function runCliAction(program2, opts) {
|
|
|
38213
38546
|
// src/cli.ts
|
|
38214
38547
|
async function main() {
|
|
38215
38548
|
const program2 = new Command();
|
|
38216
|
-
program2.name("buildautomaton").description("CLI for BuildAutomaton: ACP client, WebSocket bridge to backend, and skills (e.g. preview)").version(
|
|
38549
|
+
program2.name("buildautomaton").description("CLI for BuildAutomaton: ACP client, WebSocket bridge to backend, and skills (e.g. preview)").version(CLI_VERSION).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(
|
|
38217
38550
|
"--firehose-url <url>",
|
|
38218
38551
|
"Firehose server URL (default: Fly app; or BUILDAUTOMATON_FIREHOSE_URL / legacy BUILDAUTOMATON_PROXY_URL)",
|
|
38219
38552
|
process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL
|
|
@@ -38222,7 +38555,7 @@ async function main() {
|
|
|
38222
38555
|
"Working directory for the bridge (absolute or relative to the current directory); affects skills, git, file index, and agent cwd"
|
|
38223
38556
|
).option("-n, --name <name>", "Bridge name when creating via browser (alphanumeric and underscores only)").option(
|
|
38224
38557
|
"--worktrees-root <path>",
|
|
38225
|
-
"Root directory for per-session git worktrees (default: ~/.buildautomaton/worktrees).
|
|
38558
|
+
"Root directory for per-session git worktrees (default: ~/.buildautomaton/worktrees)."
|
|
38226
38559
|
).option(
|
|
38227
38560
|
"--e2ee-certificates-dir <path>",
|
|
38228
38561
|
"Directory to load or generate E2EE keys for sessions, files, and logs",
|