@buildautomaton/cli 0.1.37 → 0.1.39
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 +1201 -868
- package/dist/cli.js.map +4 -4
- package/dist/index.js +1186 -853
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -973,7 +973,7 @@ 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
|
|
976
|
+
var path46 = __require("node:path");
|
|
977
977
|
var fs41 = __require("node:fs");
|
|
978
978
|
var process8 = __require("node:process");
|
|
979
979
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
@@ -1906,9 +1906,9 @@ 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 =
|
|
1909
|
+
const localBin = path46.resolve(baseDir, baseName);
|
|
1910
1910
|
if (fs41.existsSync(localBin)) return localBin;
|
|
1911
|
-
if (sourceExt.includes(
|
|
1911
|
+
if (sourceExt.includes(path46.extname(baseName))) return void 0;
|
|
1912
1912
|
const foundExt = sourceExt.find(
|
|
1913
1913
|
(ext) => fs41.existsSync(`${localBin}${ext}`)
|
|
1914
1914
|
);
|
|
@@ -1926,17 +1926,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1926
1926
|
} catch (err) {
|
|
1927
1927
|
resolvedScriptPath = this._scriptPath;
|
|
1928
1928
|
}
|
|
1929
|
-
executableDir =
|
|
1930
|
-
|
|
1929
|
+
executableDir = path46.resolve(
|
|
1930
|
+
path46.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 = path46.basename(
|
|
1938
1938
|
this._scriptPath,
|
|
1939
|
-
|
|
1939
|
+
path46.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(path46.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 = path46.basename(filename, path46.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(path47) {
|
|
2805
|
+
if (path47 === void 0) return this._executableDir;
|
|
2806
|
+
this._executableDir = path47;
|
|
2807
2807
|
return this;
|
|
2808
2808
|
}
|
|
2809
2809
|
/**
|
|
@@ -7061,8 +7061,8 @@ var init_parseUtil = __esm({
|
|
|
7061
7061
|
init_errors();
|
|
7062
7062
|
init_en();
|
|
7063
7063
|
makeIssue = (params) => {
|
|
7064
|
-
const { data, path:
|
|
7065
|
-
const fullPath = [...
|
|
7064
|
+
const { data, path: path46, errorMaps, issueData } = params;
|
|
7065
|
+
const fullPath = [...path46, ...issueData.path || []];
|
|
7066
7066
|
const fullIssue = {
|
|
7067
7067
|
...issueData,
|
|
7068
7068
|
path: fullPath
|
|
@@ -7370,11 +7370,11 @@ var init_types = __esm({
|
|
|
7370
7370
|
init_parseUtil();
|
|
7371
7371
|
init_util();
|
|
7372
7372
|
ParseInputLazyPath = class {
|
|
7373
|
-
constructor(parent, value,
|
|
7373
|
+
constructor(parent, value, path46, key) {
|
|
7374
7374
|
this._cachedPath = [];
|
|
7375
7375
|
this.parent = parent;
|
|
7376
7376
|
this.data = value;
|
|
7377
|
-
this._path =
|
|
7377
|
+
this._path = path46;
|
|
7378
7378
|
this._key = key;
|
|
7379
7379
|
}
|
|
7380
7380
|
get path() {
|
|
@@ -11529,10 +11529,10 @@ var require_src2 = __commonJS({
|
|
|
11529
11529
|
var fs_1 = __require("fs");
|
|
11530
11530
|
var debug_1 = __importDefault(require_src());
|
|
11531
11531
|
var log2 = debug_1.default("@kwsites/file-exists");
|
|
11532
|
-
function check2(
|
|
11533
|
-
log2(`checking %s`,
|
|
11532
|
+
function check2(path46, isFile, isDirectory) {
|
|
11533
|
+
log2(`checking %s`, path46);
|
|
11534
11534
|
try {
|
|
11535
|
-
const stat3 = fs_1.statSync(
|
|
11535
|
+
const stat3 = fs_1.statSync(path46);
|
|
11536
11536
|
if (stat3.isFile() && isFile) {
|
|
11537
11537
|
log2(`[OK] path represents a file`);
|
|
11538
11538
|
return true;
|
|
@@ -11552,8 +11552,8 @@ var require_src2 = __commonJS({
|
|
|
11552
11552
|
throw e;
|
|
11553
11553
|
}
|
|
11554
11554
|
}
|
|
11555
|
-
function exists2(
|
|
11556
|
-
return check2(
|
|
11555
|
+
function exists2(path46, type = exports.READABLE) {
|
|
11556
|
+
return check2(path46, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
|
|
11557
11557
|
}
|
|
11558
11558
|
exports.exists = exists2;
|
|
11559
11559
|
exports.FILE = 1;
|
|
@@ -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, path46) {
|
|
11854
|
+
if (!path46)
|
|
11855
11855
|
return obj;
|
|
11856
|
-
return
|
|
11856
|
+
return path46.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(path46, 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(path46);
|
|
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, path46 = []) => {
|
|
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 = [...path46, ...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(path46) {
|
|
12339
12339
|
const segs = [];
|
|
12340
|
-
for (const seg of
|
|
12340
|
+
for (const seg of path46) {
|
|
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((resolve22) => {
|
|
24804
|
+
this.#abortController.signal.addEventListener("abort", () => resolve22());
|
|
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((resolve22, reject) => {
|
|
24954
|
+
this.#pendingResponses.set(id, { resolve: resolve22, reject });
|
|
24955
24955
|
});
|
|
24956
24956
|
await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
|
|
24957
24957
|
return responsePromise;
|
|
@@ -25064,7 +25064,7 @@ var {
|
|
|
25064
25064
|
} = import_index.default;
|
|
25065
25065
|
|
|
25066
25066
|
// src/cli-version.ts
|
|
25067
|
-
var CLI_VERSION = "0.1.
|
|
25067
|
+
var CLI_VERSION = "0.1.39".length > 0 ? "0.1.39" : "0.0.0-dev";
|
|
25068
25068
|
|
|
25069
25069
|
// src/cli/defaults.ts
|
|
25070
25070
|
var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
|
|
@@ -25072,7 +25072,7 @@ var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
|
|
|
25072
25072
|
|
|
25073
25073
|
// src/cli/run-cli-action.ts
|
|
25074
25074
|
import * as fs40 from "node:fs";
|
|
25075
|
-
import * as
|
|
25075
|
+
import * as path45 from "node:path";
|
|
25076
25076
|
|
|
25077
25077
|
// src/cli-log-level.ts
|
|
25078
25078
|
var verbosity = "info";
|
|
@@ -26079,14 +26079,14 @@ var baseOpen = async (options) => {
|
|
|
26079
26079
|
}
|
|
26080
26080
|
const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
|
|
26081
26081
|
if (options.wait) {
|
|
26082
|
-
return new Promise((
|
|
26082
|
+
return new Promise((resolve22, reject) => {
|
|
26083
26083
|
subprocess.once("error", reject);
|
|
26084
26084
|
subprocess.once("close", (exitCode) => {
|
|
26085
26085
|
if (!options.allowNonzeroExitCode && exitCode > 0) {
|
|
26086
26086
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
26087
26087
|
return;
|
|
26088
26088
|
}
|
|
26089
|
-
|
|
26089
|
+
resolve22(subprocess);
|
|
26090
26090
|
});
|
|
26091
26091
|
});
|
|
26092
26092
|
}
|
|
@@ -26575,8 +26575,8 @@ function runPendingAuth(options) {
|
|
|
26575
26575
|
let hasOpenedBrowser = false;
|
|
26576
26576
|
let resolved = false;
|
|
26577
26577
|
let resolveAuth;
|
|
26578
|
-
const authPromise = new Promise((
|
|
26579
|
-
resolveAuth =
|
|
26578
|
+
const authPromise = new Promise((resolve22) => {
|
|
26579
|
+
resolveAuth = resolve22;
|
|
26580
26580
|
});
|
|
26581
26581
|
let reconnectAttempt = 0;
|
|
26582
26582
|
const signInQuiet = createEmptyReconnectQuietSlot();
|
|
@@ -26727,7 +26727,7 @@ import sqliteWasm from "node-sqlite3-wasm";
|
|
|
26727
26727
|
|
|
26728
26728
|
// src/runtime/yield-to-event-loop.ts
|
|
26729
26729
|
function yieldToEventLoop() {
|
|
26730
|
-
return new Promise((
|
|
26730
|
+
return new Promise((resolve22) => setImmediate(resolve22));
|
|
26731
26731
|
}
|
|
26732
26732
|
|
|
26733
26733
|
// src/sqlite/cli-sqlite-paths.ts
|
|
@@ -27570,9 +27570,9 @@ function parseChangeSummaryJson(raw, allowedPaths, options) {
|
|
|
27570
27570
|
const rawPath = typeof o.path === "string" ? o.path.trim() : "";
|
|
27571
27571
|
const summary = typeof o.summary === "string" ? o.summary.trim() : "";
|
|
27572
27572
|
if (!rawPath || !summary) continue;
|
|
27573
|
-
const
|
|
27574
|
-
if (!
|
|
27575
|
-
rows.push({ path:
|
|
27573
|
+
const path46 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
|
|
27574
|
+
if (!path46) continue;
|
|
27575
|
+
rows.push({ path: path46, summary: clampSummaryToAtMostTwoLines(summary) });
|
|
27576
27576
|
}
|
|
27577
27577
|
return rows;
|
|
27578
27578
|
}
|
|
@@ -27866,8 +27866,8 @@ function pathspec(...paths) {
|
|
|
27866
27866
|
cache.set(key, paths);
|
|
27867
27867
|
return key;
|
|
27868
27868
|
}
|
|
27869
|
-
function isPathSpec(
|
|
27870
|
-
return
|
|
27869
|
+
function isPathSpec(path46) {
|
|
27870
|
+
return path46 instanceof String && cache.has(path46);
|
|
27871
27871
|
}
|
|
27872
27872
|
function toPaths(pathSpec) {
|
|
27873
27873
|
return cache.get(pathSpec) || [];
|
|
@@ -27956,8 +27956,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
27956
27956
|
function forEachLineWithContent(input, callback) {
|
|
27957
27957
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
27958
27958
|
}
|
|
27959
|
-
function folderExists(
|
|
27960
|
-
return (0, import_file_exists.exists)(
|
|
27959
|
+
function folderExists(path46) {
|
|
27960
|
+
return (0, import_file_exists.exists)(path46, import_file_exists.FOLDER);
|
|
27961
27961
|
}
|
|
27962
27962
|
function append(target, item) {
|
|
27963
27963
|
if (Array.isArray(target)) {
|
|
@@ -28361,8 +28361,8 @@ function checkIsRepoRootTask() {
|
|
|
28361
28361
|
commands,
|
|
28362
28362
|
format: "utf-8",
|
|
28363
28363
|
onError,
|
|
28364
|
-
parser(
|
|
28365
|
-
return /^\.(git)?$/.test(
|
|
28364
|
+
parser(path46) {
|
|
28365
|
+
return /^\.(git)?$/.test(path46.trim());
|
|
28366
28366
|
}
|
|
28367
28367
|
};
|
|
28368
28368
|
}
|
|
@@ -28796,11 +28796,11 @@ function parseGrep(grep) {
|
|
|
28796
28796
|
const paths = /* @__PURE__ */ new Set();
|
|
28797
28797
|
const results = {};
|
|
28798
28798
|
forEachLineWithContent(grep, (input) => {
|
|
28799
|
-
const [
|
|
28800
|
-
paths.add(
|
|
28801
|
-
(results[
|
|
28799
|
+
const [path46, line, preview] = input.split(NULL);
|
|
28800
|
+
paths.add(path46);
|
|
28801
|
+
(results[path46] = results[path46] || []).push({
|
|
28802
28802
|
line: asNumber(line),
|
|
28803
|
-
path:
|
|
28803
|
+
path: path46,
|
|
28804
28804
|
preview
|
|
28805
28805
|
});
|
|
28806
28806
|
});
|
|
@@ -29565,14 +29565,14 @@ var init_hash_object = __esm2({
|
|
|
29565
29565
|
init_task();
|
|
29566
29566
|
}
|
|
29567
29567
|
});
|
|
29568
|
-
function parseInit(bare,
|
|
29568
|
+
function parseInit(bare, path46, text) {
|
|
29569
29569
|
const response = String(text).trim();
|
|
29570
29570
|
let result;
|
|
29571
29571
|
if (result = initResponseRegex.exec(response)) {
|
|
29572
|
-
return new InitSummary(bare,
|
|
29572
|
+
return new InitSummary(bare, path46, false, result[1]);
|
|
29573
29573
|
}
|
|
29574
29574
|
if (result = reInitResponseRegex.exec(response)) {
|
|
29575
|
-
return new InitSummary(bare,
|
|
29575
|
+
return new InitSummary(bare, path46, true, result[1]);
|
|
29576
29576
|
}
|
|
29577
29577
|
let gitDir = "";
|
|
29578
29578
|
const tokens = response.split(" ");
|
|
@@ -29583,7 +29583,7 @@ function parseInit(bare, path43, text) {
|
|
|
29583
29583
|
break;
|
|
29584
29584
|
}
|
|
29585
29585
|
}
|
|
29586
|
-
return new InitSummary(bare,
|
|
29586
|
+
return new InitSummary(bare, path46, /^re/i.test(response), gitDir);
|
|
29587
29587
|
}
|
|
29588
29588
|
var InitSummary;
|
|
29589
29589
|
var initResponseRegex;
|
|
@@ -29592,9 +29592,9 @@ var init_InitSummary = __esm2({
|
|
|
29592
29592
|
"src/lib/responses/InitSummary.ts"() {
|
|
29593
29593
|
"use strict";
|
|
29594
29594
|
InitSummary = class {
|
|
29595
|
-
constructor(bare,
|
|
29595
|
+
constructor(bare, path46, existing, gitDir) {
|
|
29596
29596
|
this.bare = bare;
|
|
29597
|
-
this.path =
|
|
29597
|
+
this.path = path46;
|
|
29598
29598
|
this.existing = existing;
|
|
29599
29599
|
this.gitDir = gitDir;
|
|
29600
29600
|
}
|
|
@@ -29606,7 +29606,7 @@ var init_InitSummary = __esm2({
|
|
|
29606
29606
|
function hasBareCommand(command) {
|
|
29607
29607
|
return command.includes(bareCommand);
|
|
29608
29608
|
}
|
|
29609
|
-
function initTask(bare = false,
|
|
29609
|
+
function initTask(bare = false, path46, customArgs) {
|
|
29610
29610
|
const commands = ["init", ...customArgs];
|
|
29611
29611
|
if (bare && !hasBareCommand(commands)) {
|
|
29612
29612
|
commands.splice(1, 0, bareCommand);
|
|
@@ -29615,7 +29615,7 @@ function initTask(bare = false, path43, customArgs) {
|
|
|
29615
29615
|
commands,
|
|
29616
29616
|
format: "utf-8",
|
|
29617
29617
|
parser(text) {
|
|
29618
|
-
return parseInit(commands.includes("--bare"),
|
|
29618
|
+
return parseInit(commands.includes("--bare"), path46, text);
|
|
29619
29619
|
}
|
|
29620
29620
|
};
|
|
29621
29621
|
}
|
|
@@ -30431,12 +30431,12 @@ var init_FileStatusSummary = __esm2({
|
|
|
30431
30431
|
"use strict";
|
|
30432
30432
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
30433
30433
|
FileStatusSummary = class {
|
|
30434
|
-
constructor(
|
|
30435
|
-
this.path =
|
|
30434
|
+
constructor(path46, index, working_dir) {
|
|
30435
|
+
this.path = path46;
|
|
30436
30436
|
this.index = index;
|
|
30437
30437
|
this.working_dir = working_dir;
|
|
30438
30438
|
if (index === "R" || working_dir === "R") {
|
|
30439
|
-
const detail = fromPathRegex.exec(
|
|
30439
|
+
const detail = fromPathRegex.exec(path46) || [null, path46, path46];
|
|
30440
30440
|
this.from = detail[2] || "";
|
|
30441
30441
|
this.path = detail[1] || "";
|
|
30442
30442
|
}
|
|
@@ -30467,14 +30467,14 @@ function splitLine(result, lineStr) {
|
|
|
30467
30467
|
default:
|
|
30468
30468
|
return;
|
|
30469
30469
|
}
|
|
30470
|
-
function data(index, workingDir,
|
|
30470
|
+
function data(index, workingDir, path46) {
|
|
30471
30471
|
const raw = `${index}${workingDir}`;
|
|
30472
30472
|
const handler = parsers6.get(raw);
|
|
30473
30473
|
if (handler) {
|
|
30474
|
-
handler(result,
|
|
30474
|
+
handler(result, path46);
|
|
30475
30475
|
}
|
|
30476
30476
|
if (raw !== "##" && raw !== "!!") {
|
|
30477
|
-
result.files.push(new FileStatusSummary(
|
|
30477
|
+
result.files.push(new FileStatusSummary(path46, index, workingDir));
|
|
30478
30478
|
}
|
|
30479
30479
|
}
|
|
30480
30480
|
}
|
|
@@ -30783,9 +30783,9 @@ var init_simple_git_api = __esm2({
|
|
|
30783
30783
|
next
|
|
30784
30784
|
);
|
|
30785
30785
|
}
|
|
30786
|
-
hashObject(
|
|
30786
|
+
hashObject(path46, write) {
|
|
30787
30787
|
return this._runTask(
|
|
30788
|
-
hashObjectTask(
|
|
30788
|
+
hashObjectTask(path46, write === true),
|
|
30789
30789
|
trailingFunctionArgument(arguments)
|
|
30790
30790
|
);
|
|
30791
30791
|
}
|
|
@@ -31138,8 +31138,8 @@ var init_branch = __esm2({
|
|
|
31138
31138
|
}
|
|
31139
31139
|
});
|
|
31140
31140
|
function toPath(input) {
|
|
31141
|
-
const
|
|
31142
|
-
return
|
|
31141
|
+
const path46 = input.trim().replace(/^["']|["']$/g, "");
|
|
31142
|
+
return path46 && normalize(path46);
|
|
31143
31143
|
}
|
|
31144
31144
|
var parseCheckIgnore;
|
|
31145
31145
|
var init_CheckIgnore = __esm2({
|
|
@@ -31453,8 +31453,8 @@ __export2(sub_module_exports, {
|
|
|
31453
31453
|
subModuleTask: () => subModuleTask,
|
|
31454
31454
|
updateSubModuleTask: () => updateSubModuleTask
|
|
31455
31455
|
});
|
|
31456
|
-
function addSubModuleTask(repo,
|
|
31457
|
-
return subModuleTask(["add", repo,
|
|
31456
|
+
function addSubModuleTask(repo, path46) {
|
|
31457
|
+
return subModuleTask(["add", repo, path46]);
|
|
31458
31458
|
}
|
|
31459
31459
|
function initSubModuleTask(customArgs) {
|
|
31460
31460
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -31787,8 +31787,8 @@ var require_git = __commonJS2({
|
|
|
31787
31787
|
}
|
|
31788
31788
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
31789
31789
|
};
|
|
31790
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
31791
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
31790
|
+
Git2.prototype.submoduleAdd = function(repo, path46, then) {
|
|
31791
|
+
return this._runTask(addSubModuleTask2(repo, path46), trailingFunctionArgument2(arguments));
|
|
31792
31792
|
};
|
|
31793
31793
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
31794
31794
|
return this._runTask(
|
|
@@ -32425,8 +32425,8 @@ async function runGitTask(fn) {
|
|
|
32425
32425
|
}
|
|
32426
32426
|
async function yieldToEventLoop2() {
|
|
32427
32427
|
throwIfGitShutdownRequested();
|
|
32428
|
-
await new Promise((
|
|
32429
|
-
setImmediate(
|
|
32428
|
+
await new Promise((resolve22) => {
|
|
32429
|
+
setImmediate(resolve22);
|
|
32430
32430
|
});
|
|
32431
32431
|
throwIfGitShutdownRequested();
|
|
32432
32432
|
}
|
|
@@ -32751,9 +32751,9 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
32751
32751
|
// src/agents/acp/put-summarize-change-summaries.ts
|
|
32752
32752
|
async function putEncryptedChangeSummaryRows(params) {
|
|
32753
32753
|
const base = params.apiBaseUrl.replace(/\/+$/, "");
|
|
32754
|
-
const entries = params.rows.map(({ path:
|
|
32754
|
+
const entries = params.rows.map(({ path: path46, summary }) => {
|
|
32755
32755
|
const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
|
|
32756
|
-
return { path:
|
|
32756
|
+
return { path: path46, summary: JSON.stringify(enc) };
|
|
32757
32757
|
});
|
|
32758
32758
|
const res = await fetch(
|
|
32759
32759
|
`${base}/api/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
|
|
@@ -33756,11 +33756,11 @@ async function sendAcpPromptViaTransport(transport, ctx, sessionId, promptText,
|
|
|
33756
33756
|
// src/agents/acp/clients/sdk/sdk-stdio-permission-request-handshake.ts
|
|
33757
33757
|
function awaitSdkStdioPermissionRequestHandshake(params) {
|
|
33758
33758
|
const { requestId, paramsRecord, pending, onRequest } = params;
|
|
33759
|
-
return new Promise((
|
|
33760
|
-
pending.set(requestId, { resolve:
|
|
33759
|
+
return new Promise((resolve22) => {
|
|
33760
|
+
pending.set(requestId, { resolve: resolve22, params: paramsRecord });
|
|
33761
33761
|
if (onRequest == null) {
|
|
33762
33762
|
pending.delete(requestId);
|
|
33763
|
-
|
|
33763
|
+
resolve22({ outcome: { outcome: "denied" } });
|
|
33764
33764
|
return;
|
|
33765
33765
|
}
|
|
33766
33766
|
try {
|
|
@@ -33826,7 +33826,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
33826
33826
|
child.once("close", (code, signal) => {
|
|
33827
33827
|
onAgentSubprocessExit?.({ code, signal });
|
|
33828
33828
|
});
|
|
33829
|
-
return new Promise((
|
|
33829
|
+
return new Promise((resolve22, reject) => {
|
|
33830
33830
|
let initSettled = false;
|
|
33831
33831
|
const settleReject = (err) => {
|
|
33832
33832
|
if (initSettled) return;
|
|
@@ -33840,7 +33840,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
33840
33840
|
const settleResolve = (handle) => {
|
|
33841
33841
|
if (initSettled) return;
|
|
33842
33842
|
initSettled = true;
|
|
33843
|
-
|
|
33843
|
+
resolve22(handle);
|
|
33844
33844
|
};
|
|
33845
33845
|
child.on("error", (err) => {
|
|
33846
33846
|
settleReject(new Error(formatSpawnError(err, command[0])));
|
|
@@ -34131,7 +34131,7 @@ async function createCursorAcpClient(options) {
|
|
|
34131
34131
|
logDebug,
|
|
34132
34132
|
getStderrText: () => stderrCapture.getText()
|
|
34133
34133
|
};
|
|
34134
|
-
return new Promise((
|
|
34134
|
+
return new Promise((resolve22, reject) => {
|
|
34135
34135
|
child.on("error", (err) => {
|
|
34136
34136
|
child.kill();
|
|
34137
34137
|
reject(new Error(formatSpawnError2(err, command[0])));
|
|
@@ -34307,7 +34307,7 @@ async function createCursorAcpClient(options) {
|
|
|
34307
34307
|
clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
|
|
34308
34308
|
});
|
|
34309
34309
|
const sessionId = established.sessionId;
|
|
34310
|
-
|
|
34310
|
+
resolve22({
|
|
34311
34311
|
sessionId,
|
|
34312
34312
|
async sendPrompt(prompt, options2) {
|
|
34313
34313
|
const imgs = options2?.images?.map((im) => ({ type: "image", mimeType: im.mimeType, data: im.dataBase64 }));
|
|
@@ -34599,7 +34599,7 @@ function createBridgeOnFileChange(opts) {
|
|
|
34599
34599
|
|
|
34600
34600
|
// src/agents/acp/hooks/bridge-on-request.ts
|
|
34601
34601
|
function createBridgeOnRequest(opts) {
|
|
34602
|
-
const { routing, getSendRequest, log: log2, getAutoApproveAcpPermissions, resolveAcpPermissionRequest } = opts;
|
|
34602
|
+
const { routing, getSendRequest, log: log2, getAutoApproveAcpPermissions, resolveAcpPermissionRequest, nextTranscriptStreamSeq } = opts;
|
|
34603
34603
|
return (request) => {
|
|
34604
34604
|
const runId = routing.runId;
|
|
34605
34605
|
const sessionId = routing.sessionId;
|
|
@@ -34628,6 +34628,7 @@ function createBridgeOnRequest(opts) {
|
|
|
34628
34628
|
);
|
|
34629
34629
|
}
|
|
34630
34630
|
try {
|
|
34631
|
+
const transcriptStreamSeq = nextTranscriptStreamSeq?.(runId);
|
|
34631
34632
|
sendReq({
|
|
34632
34633
|
type: "session_update",
|
|
34633
34634
|
...sessionId ? { sessionId } : {},
|
|
@@ -34638,7 +34639,8 @@ function createBridgeOnRequest(opts) {
|
|
|
34638
34639
|
requestId: request.requestId,
|
|
34639
34640
|
method: request.method,
|
|
34640
34641
|
params: request.params
|
|
34641
|
-
}
|
|
34642
|
+
},
|
|
34643
|
+
...transcriptStreamSeq != null ? { transcriptStreamSeq } : {}
|
|
34642
34644
|
});
|
|
34643
34645
|
} catch (err) {
|
|
34644
34646
|
log2(
|
|
@@ -35039,7 +35041,7 @@ function sendSessionInfoTitleUpdate(params) {
|
|
|
35039
35041
|
|
|
35040
35042
|
// src/agents/acp/hooks/bridge-on-session-update/create-bridge-on-session-update.ts
|
|
35041
35043
|
function createBridgeOnSessionUpdate(opts) {
|
|
35042
|
-
const { routing, getSendSessionUpdate, log: log2, sessionParentPath } = opts;
|
|
35044
|
+
const { routing, getSendSessionUpdate, log: log2, sessionParentPath, nextTranscriptStreamSeq } = opts;
|
|
35043
35045
|
const pathTracker = new PathSnapshotTracker();
|
|
35044
35046
|
return (params) => {
|
|
35045
35047
|
const runId = routing.runId;
|
|
@@ -35117,12 +35119,14 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
35117
35119
|
return;
|
|
35118
35120
|
}
|
|
35119
35121
|
try {
|
|
35122
|
+
const transcriptStreamSeq = nextTranscriptStreamSeq?.(runId);
|
|
35120
35123
|
send({
|
|
35121
35124
|
type: "session_update",
|
|
35122
35125
|
...sessionId ? { sessionId } : {},
|
|
35123
35126
|
runId,
|
|
35124
35127
|
kind: updateKind,
|
|
35125
|
-
payload: params
|
|
35128
|
+
payload: params,
|
|
35129
|
+
...transcriptStreamSeq != null ? { transcriptStreamSeq } : {}
|
|
35126
35130
|
});
|
|
35127
35131
|
} catch (err) {
|
|
35128
35132
|
log2(
|
|
@@ -35135,10 +35139,17 @@ function createBridgeOnSessionUpdate(opts) {
|
|
|
35135
35139
|
|
|
35136
35140
|
// src/agents/acp/hooks/build-acp-session-bridge-hooks.ts
|
|
35137
35141
|
function buildAcpSessionBridgeHooks(opts) {
|
|
35142
|
+
const transcriptStreamSeqByRunId = /* @__PURE__ */ new Map();
|
|
35143
|
+
const nextTranscriptStreamSeq = (runId) => {
|
|
35144
|
+
const n = (transcriptStreamSeqByRunId.get(runId) ?? 0) + 1;
|
|
35145
|
+
transcriptStreamSeqByRunId.set(runId, n);
|
|
35146
|
+
return n;
|
|
35147
|
+
};
|
|
35148
|
+
const optsWithSeq = { ...opts, nextTranscriptStreamSeq };
|
|
35138
35149
|
return {
|
|
35139
|
-
onFileChange: createBridgeOnFileChange(
|
|
35140
|
-
onSessionUpdate: createBridgeOnSessionUpdate(
|
|
35141
|
-
onRequest: createBridgeOnRequest(
|
|
35150
|
+
onFileChange: createBridgeOnFileChange(optsWithSeq),
|
|
35151
|
+
onSessionUpdate: createBridgeOnSessionUpdate(optsWithSeq),
|
|
35152
|
+
onRequest: createBridgeOnRequest(optsWithSeq)
|
|
35142
35153
|
};
|
|
35143
35154
|
}
|
|
35144
35155
|
|
|
@@ -35542,266 +35553,65 @@ async function createAcpManager(options) {
|
|
|
35542
35553
|
};
|
|
35543
35554
|
}
|
|
35544
35555
|
|
|
35545
|
-
// src/
|
|
35546
|
-
|
|
35547
|
-
import os8 from "node:os";
|
|
35548
|
-
|
|
35549
|
-
// src/worktrees/prepare-new-session-worktrees.ts
|
|
35550
|
-
import * as fs18 from "node:fs";
|
|
35551
|
-
import * as path21 from "node:path";
|
|
35552
|
-
|
|
35553
|
-
// src/git/worktrees/worktree-add.ts
|
|
35554
|
-
async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
|
|
35555
|
-
const mainGit = cliSimpleGit(mainRepoPath);
|
|
35556
|
-
await mainGit.raw(["worktree", "add", "-b", branch, worktreePath, "HEAD"]);
|
|
35557
|
-
}
|
|
35558
|
-
|
|
35559
|
-
// src/worktrees/worktree-layout-file.ts
|
|
35560
|
-
import * as fs17 from "node:fs";
|
|
35561
|
-
import * as path20 from "node:path";
|
|
35562
|
-
import os7 from "node:os";
|
|
35563
|
-
var LAYOUT_FILENAME = "worktree-launcher-layout.json";
|
|
35564
|
-
function defaultWorktreeLayoutPath() {
|
|
35565
|
-
return path20.join(os7.homedir(), ".buildautomaton", LAYOUT_FILENAME);
|
|
35566
|
-
}
|
|
35567
|
-
function normalizeLoadedLayout(raw) {
|
|
35568
|
-
if (raw && typeof raw === "object" && "launcherCwds" in raw) {
|
|
35569
|
-
const j = raw;
|
|
35570
|
-
if (Array.isArray(j.launcherCwds)) return { launcherCwds: j.launcherCwds };
|
|
35571
|
-
}
|
|
35572
|
-
return { launcherCwds: [] };
|
|
35573
|
-
}
|
|
35574
|
-
function loadWorktreeLayout() {
|
|
35575
|
-
try {
|
|
35576
|
-
const p = defaultWorktreeLayoutPath();
|
|
35577
|
-
if (!fs17.existsSync(p)) return { launcherCwds: [] };
|
|
35578
|
-
const raw = JSON.parse(fs17.readFileSync(p, "utf8"));
|
|
35579
|
-
return normalizeLoadedLayout(raw);
|
|
35580
|
-
} catch {
|
|
35581
|
-
return { launcherCwds: [] };
|
|
35582
|
-
}
|
|
35583
|
-
}
|
|
35584
|
-
function saveWorktreeLayout(layout) {
|
|
35585
|
-
try {
|
|
35586
|
-
const dir = path20.dirname(defaultWorktreeLayoutPath());
|
|
35587
|
-
fs17.mkdirSync(dir, { recursive: true });
|
|
35588
|
-
fs17.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
|
|
35589
|
-
} catch {
|
|
35590
|
-
}
|
|
35591
|
-
}
|
|
35592
|
-
function baseNameSafe(pathString) {
|
|
35593
|
-
return path20.basename(pathString).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
|
|
35594
|
-
}
|
|
35595
|
-
function getLauncherDirNameIfPresent(layout, bridgeRootPath2) {
|
|
35596
|
-
const norm = path20.resolve(bridgeRootPath2);
|
|
35597
|
-
const existing = layout.launcherCwds.find((e) => path20.resolve(e.absolutePath) === norm);
|
|
35598
|
-
return existing?.dirName;
|
|
35599
|
-
}
|
|
35600
|
-
function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
|
|
35601
|
-
const existing = getLauncherDirNameIfPresent(layout, bridgeRootPath2);
|
|
35602
|
-
if (existing) return existing;
|
|
35603
|
-
const norm = path20.resolve(bridgeRootPath2);
|
|
35604
|
-
const base = baseNameSafe(norm);
|
|
35605
|
-
const used = new Set(layout.launcherCwds.map((e) => e.dirName));
|
|
35606
|
-
let name = base;
|
|
35607
|
-
let n = 2;
|
|
35608
|
-
while (used.has(name)) {
|
|
35609
|
-
name = `${base}-${n}`;
|
|
35610
|
-
n += 1;
|
|
35611
|
-
}
|
|
35612
|
-
layout.launcherCwds.push({ absolutePath: norm, dirName: name });
|
|
35613
|
-
saveWorktreeLayout(layout);
|
|
35614
|
-
return name;
|
|
35615
|
-
}
|
|
35616
|
-
|
|
35617
|
-
// src/worktrees/prepare-new-session-worktrees.ts
|
|
35618
|
-
async function prepareNewSessionWorktrees(options) {
|
|
35619
|
-
const { worktreesRootPath, bridgeRoot, sessionId, layout, log: log2 } = options;
|
|
35620
|
-
const bridgeResolved = path21.resolve(bridgeRoot);
|
|
35621
|
-
const cwdKey = allocateDirNameForLauncherCwd(layout, bridgeResolved);
|
|
35622
|
-
const bridgeKeyDir = path21.join(worktreesRootPath, cwdKey);
|
|
35623
|
-
const sessionDir = path21.join(bridgeKeyDir, sessionId);
|
|
35624
|
-
const repos = await discoverGitReposUnderRoot(bridgeResolved);
|
|
35625
|
-
if (repos.length === 0) {
|
|
35626
|
-
log2("[worktrees] No Git repositories under bridge root; skipping worktree creation.");
|
|
35627
|
-
return null;
|
|
35628
|
-
}
|
|
35629
|
-
const branch = `session-${sessionId}`;
|
|
35630
|
-
const worktreePaths = [];
|
|
35631
|
-
fs18.mkdirSync(sessionDir, { recursive: true });
|
|
35632
|
-
for (const repo of repos) {
|
|
35633
|
-
let rel = path21.relative(bridgeResolved, repo.absolutePath);
|
|
35634
|
-
if (rel.startsWith("..") || path21.isAbsolute(rel)) continue;
|
|
35635
|
-
const relNorm = rel === "" ? "." : rel;
|
|
35636
|
-
const wtPath = relNorm === "." ? sessionDir : path21.join(sessionDir, relNorm);
|
|
35637
|
-
if (relNorm !== ".") {
|
|
35638
|
-
fs18.mkdirSync(path21.dirname(wtPath), { recursive: true });
|
|
35639
|
-
}
|
|
35640
|
-
try {
|
|
35641
|
-
await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch);
|
|
35642
|
-
log2(`[worktrees] Added worktree ${wtPath} (branch ${branch}).`);
|
|
35643
|
-
worktreePaths.push(wtPath);
|
|
35644
|
-
} catch (e) {
|
|
35645
|
-
log2(
|
|
35646
|
-
`[worktrees] Worktree add failed for ${repo.absolutePath}: ${e instanceof Error ? e.message : String(e)}`
|
|
35647
|
-
);
|
|
35648
|
-
}
|
|
35649
|
-
}
|
|
35650
|
-
if (worktreePaths.length === 0) return null;
|
|
35651
|
-
return {
|
|
35652
|
-
worktreePaths,
|
|
35653
|
-
sessionParentPath: sessionDir,
|
|
35654
|
-
workingTreeRelRoot: sessionDir
|
|
35655
|
-
};
|
|
35656
|
-
}
|
|
35657
|
-
|
|
35658
|
-
// src/git/branches/rename-branch.ts
|
|
35659
|
-
async function gitRenameCurrentBranch(repoDir, newName) {
|
|
35660
|
-
const g = cliSimpleGit(repoDir);
|
|
35661
|
-
await g.raw(["branch", "-m", newName]);
|
|
35662
|
-
}
|
|
35663
|
-
|
|
35664
|
-
// src/worktrees/rename-session-worktree-branches.ts
|
|
35665
|
-
async function renameSessionWorktreeBranches(paths, newBranch, log2) {
|
|
35666
|
-
const safe = newBranch.replace(/[^a-zA-Z0-9/_-]+/g, "-").slice(0, 80) || "session-branch";
|
|
35667
|
-
for (const wt of paths) {
|
|
35668
|
-
try {
|
|
35669
|
-
await gitRenameCurrentBranch(wt, safe);
|
|
35670
|
-
log2(`[worktrees] Renamed branch in ${wt} \u2192 ${safe}`);
|
|
35671
|
-
} catch (e) {
|
|
35672
|
-
log2(
|
|
35673
|
-
`[worktrees] Branch rename failed in ${wt}: ${e instanceof Error ? e.message : String(e)}`
|
|
35674
|
-
);
|
|
35675
|
-
}
|
|
35676
|
-
}
|
|
35677
|
-
}
|
|
35678
|
-
|
|
35679
|
-
// src/worktrees/remove-session-worktrees.ts
|
|
35680
|
-
import * as fs21 from "node:fs";
|
|
35681
|
-
|
|
35682
|
-
// src/git/worktrees/worktree-remove.ts
|
|
35683
|
-
import * as fs20 from "node:fs";
|
|
35684
|
-
|
|
35685
|
-
// src/git/worktrees/resolve-main-repo-from-git-file.ts
|
|
35686
|
-
import * as fs19 from "node:fs";
|
|
35687
|
-
import * as path22 from "node:path";
|
|
35688
|
-
function resolveMainRepoFromWorktreeGitFile(wt) {
|
|
35689
|
-
const gitDirFile = path22.join(wt, ".git");
|
|
35690
|
-
if (!fs19.existsSync(gitDirFile) || !fs19.statSync(gitDirFile).isFile()) return "";
|
|
35691
|
-
const first2 = fs19.readFileSync(gitDirFile, "utf8").trim();
|
|
35692
|
-
const m = first2.match(/^gitdir:\s*(.+)$/im);
|
|
35693
|
-
if (!m) return "";
|
|
35694
|
-
const gitWorktreePath = path22.resolve(wt, m[1].trim());
|
|
35695
|
-
const gitDir = path22.dirname(path22.dirname(gitWorktreePath));
|
|
35696
|
-
return path22.dirname(gitDir);
|
|
35697
|
-
}
|
|
35556
|
+
// src/git/changes/types.ts
|
|
35557
|
+
var MAX_PATCH_CHARS = 35e4;
|
|
35698
35558
|
|
|
35699
|
-
// src/git/
|
|
35700
|
-
|
|
35701
|
-
const
|
|
35702
|
-
|
|
35703
|
-
|
|
35704
|
-
} else {
|
|
35705
|
-
fs20.rmSync(worktreePath, { recursive: true, force: true });
|
|
35706
|
-
}
|
|
35559
|
+
// src/git/changes/lib/repo-format.ts
|
|
35560
|
+
function posixJoinDirFile(dir, file2) {
|
|
35561
|
+
const d = dir === "." || dir === "" ? "" : dir.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
35562
|
+
const f = file2.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
35563
|
+
return d ? `${d}/${f}` : f;
|
|
35707
35564
|
}
|
|
35708
|
-
|
|
35709
|
-
|
|
35710
|
-
|
|
35711
|
-
for (const wt of paths) {
|
|
35565
|
+
function formatRepoShortTitle(remoteUrl, repoRelPath) {
|
|
35566
|
+
const u = remoteUrl.trim();
|
|
35567
|
+
if (u) {
|
|
35712
35568
|
try {
|
|
35713
|
-
|
|
35714
|
-
|
|
35715
|
-
|
|
35716
|
-
|
|
35717
|
-
|
|
35718
|
-
|
|
35719
|
-
}
|
|
35569
|
+
if (u.startsWith("git@")) {
|
|
35570
|
+
const colon = u.indexOf(":");
|
|
35571
|
+
if (colon > 0) {
|
|
35572
|
+
const pathPart = u.slice(colon + 1).replace(/\.git$/i, "").replace(/\/+$/, "");
|
|
35573
|
+
if (pathPart.includes("/")) return pathPart;
|
|
35574
|
+
}
|
|
35575
|
+
} else {
|
|
35576
|
+
const parsed = new URL(u);
|
|
35577
|
+
const p = parsed.pathname.replace(/^\//, "").replace(/\.git$/i, "");
|
|
35578
|
+
const parts = p.split("/").filter(Boolean);
|
|
35579
|
+
if (parts.length >= 2) {
|
|
35580
|
+
return `${parts[parts.length - 2]}/${parts[parts.length - 1]}`;
|
|
35581
|
+
}
|
|
35582
|
+
if (parts.length === 1) return parts[0];
|
|
35720
35583
|
}
|
|
35584
|
+
} catch {
|
|
35721
35585
|
}
|
|
35722
35586
|
}
|
|
35723
|
-
|
|
35724
|
-
|
|
35725
|
-
|
|
35726
|
-
|
|
35727
|
-
const m = /* @__PURE__ */ new Map();
|
|
35728
|
-
for (const line of lines) {
|
|
35729
|
-
if (!line.trim()) continue;
|
|
35730
|
-
const tabParts = line.split(" ");
|
|
35731
|
-
if (tabParts.length < 2) continue;
|
|
35732
|
-
const status = tabParts[0].trim();
|
|
35733
|
-
const code = status[0];
|
|
35734
|
-
if (code === "A") {
|
|
35735
|
-
m.set(tabParts[tabParts.length - 1], "added");
|
|
35736
|
-
} else if (code === "D") {
|
|
35737
|
-
m.set(tabParts[tabParts.length - 1], "removed");
|
|
35738
|
-
} else if (code === "R" || code === "C") {
|
|
35739
|
-
if (tabParts.length >= 3) m.set(tabParts[tabParts.length - 1], "modified");
|
|
35740
|
-
} else if (code === "M" || code === "U" || code === "T") {
|
|
35741
|
-
m.set(tabParts[tabParts.length - 1], "modified");
|
|
35742
|
-
}
|
|
35743
|
-
}
|
|
35744
|
-
return m;
|
|
35745
|
-
}
|
|
35746
|
-
function parseNumstatFirstLine(line) {
|
|
35747
|
-
const parts = line.split(" ");
|
|
35748
|
-
if (parts.length < 3) return null;
|
|
35749
|
-
const [a, d] = parts;
|
|
35750
|
-
const additions = a === "-" ? 0 : parseInt(String(a), 10) || 0;
|
|
35751
|
-
const deletions = d === "-" ? 0 : parseInt(String(d), 10) || 0;
|
|
35752
|
-
return { additions, deletions };
|
|
35753
|
-
}
|
|
35754
|
-
function parseNumstat(lines) {
|
|
35755
|
-
const m = /* @__PURE__ */ new Map();
|
|
35756
|
-
for (const line of lines) {
|
|
35757
|
-
if (!line.trim()) continue;
|
|
35758
|
-
const parts = line.split(" ");
|
|
35759
|
-
if (parts.length < 3) continue;
|
|
35760
|
-
const [a, d, p] = parts;
|
|
35761
|
-
const additions = a === "-" ? 0 : parseInt(String(a), 10) || 0;
|
|
35762
|
-
const deletions = d === "-" ? 0 : parseInt(String(d), 10) || 0;
|
|
35763
|
-
m.set(p, { additions, deletions });
|
|
35587
|
+
if (repoRelPath && repoRelPath !== ".") {
|
|
35588
|
+
const segments = repoRelPath.split("/").filter(Boolean);
|
|
35589
|
+
const last2 = segments[segments.length - 1];
|
|
35590
|
+
if (last2) return last2;
|
|
35764
35591
|
}
|
|
35765
|
-
return
|
|
35592
|
+
return "Repository";
|
|
35766
35593
|
}
|
|
35767
|
-
|
|
35768
|
-
const
|
|
35594
|
+
function formatRemoteDisplayLabel(remoteUrl) {
|
|
35595
|
+
const u = remoteUrl.trim();
|
|
35596
|
+
if (!u) return "";
|
|
35597
|
+
let hostPath = u;
|
|
35769
35598
|
try {
|
|
35770
|
-
|
|
35771
|
-
|
|
35772
|
-
|
|
35599
|
+
if (u.startsWith("git@")) {
|
|
35600
|
+
const rest = u.slice("git@".length);
|
|
35601
|
+
const slash = rest.indexOf(":");
|
|
35602
|
+
if (slash > 0) hostPath = `${rest.slice(0, slash)}/${rest.slice(slash + 1)}`;
|
|
35603
|
+
} else {
|
|
35604
|
+
const parsed = new URL(u);
|
|
35605
|
+
hostPath = `${parsed.hostname}${parsed.pathname}`.replace(/\/\.git$/i, "").replace(/\.git$/i, "");
|
|
35606
|
+
}
|
|
35773
35607
|
} catch {
|
|
35774
|
-
|
|
35775
|
-
}
|
|
35776
|
-
}
|
|
35777
|
-
|
|
35778
|
-
// src/git/changes/lib/working-tree-changed-path-count.ts
|
|
35779
|
-
function workingTreeChangedPathCount(nameStatusLines, numstatLines, untrackedLines) {
|
|
35780
|
-
const kindByPath = parseNameStatusLines(nameStatusLines);
|
|
35781
|
-
const numByPath = parseNumstat(numstatLines);
|
|
35782
|
-
const paths = /* @__PURE__ */ new Set([...kindByPath.keys(), ...numByPath.keys()]);
|
|
35783
|
-
for (const p of untrackedLines.map((s) => s.trim()).filter(Boolean)) {
|
|
35784
|
-
paths.add(p);
|
|
35608
|
+
hostPath = u.replace(/^https?:\/\//i, "").replace(/\.git$/i, "");
|
|
35785
35609
|
}
|
|
35786
|
-
return
|
|
35610
|
+
return `origin \xB7 ${hostPath}`;
|
|
35787
35611
|
}
|
|
35788
35612
|
|
|
35789
|
-
// src/git/changes/
|
|
35790
|
-
|
|
35791
|
-
return runGitTask(async () => {
|
|
35792
|
-
const g = cliSimpleGit(repoGitCwd);
|
|
35793
|
-
const [nameStatusRaw, numstatRaw, untrackedRaw] = await Promise.all([
|
|
35794
|
-
g.raw(["diff", "--name-status", "HEAD"]).catch(() => ""),
|
|
35795
|
-
g.raw(["diff", "HEAD", "--numstat"]).catch(() => ""),
|
|
35796
|
-
g.raw(["ls-files", "--others", "--exclude-standard"]).catch(() => "")
|
|
35797
|
-
]);
|
|
35798
|
-
return workingTreeChangedPathCount(
|
|
35799
|
-
String(nameStatusRaw).split("\n"),
|
|
35800
|
-
String(numstatRaw).split("\n"),
|
|
35801
|
-
String(untrackedRaw).split("\n")
|
|
35802
|
-
);
|
|
35803
|
-
});
|
|
35804
|
-
}
|
|
35613
|
+
// src/git/changes/get-working-tree-change-repo-details.ts
|
|
35614
|
+
import * as path21 from "node:path";
|
|
35805
35615
|
|
|
35806
35616
|
// src/git/commits/resolve-remote-tracking.ts
|
|
35807
35617
|
async function tryConfigGet(g, key) {
|
|
@@ -35901,96 +35711,6 @@ async function commitsAheadOfRemoteTracking(repoDir) {
|
|
|
35901
35711
|
}
|
|
35902
35712
|
}
|
|
35903
35713
|
|
|
35904
|
-
// src/git/status/working-tree-status.ts
|
|
35905
|
-
async function getRepoWorkingTreeStatus(repoDir) {
|
|
35906
|
-
return runGitTask(async () => {
|
|
35907
|
-
const uncommittedFileCount = await countWorkingTreeChangedFilesForRepo(repoDir);
|
|
35908
|
-
const hasUncommittedChanges = uncommittedFileCount > 0;
|
|
35909
|
-
const ahead = await commitsAheadOfRemoteTracking(repoDir);
|
|
35910
|
-
return { hasUncommittedChanges, hasUnpushedCommits: ahead > 0, uncommittedFileCount };
|
|
35911
|
-
});
|
|
35912
|
-
}
|
|
35913
|
-
async function aggregateSessionPathsWorkingTreeStatus(paths) {
|
|
35914
|
-
let hasUncommittedChanges = false;
|
|
35915
|
-
let hasUnpushedCommits = false;
|
|
35916
|
-
let uncommittedFileCount = 0;
|
|
35917
|
-
await forEachWithGitYield(paths, async (p) => {
|
|
35918
|
-
const s = await getRepoWorkingTreeStatus(p);
|
|
35919
|
-
uncommittedFileCount += s.uncommittedFileCount;
|
|
35920
|
-
if (s.hasUncommittedChanges) hasUncommittedChanges = true;
|
|
35921
|
-
if (s.hasUnpushedCommits) hasUnpushedCommits = true;
|
|
35922
|
-
});
|
|
35923
|
-
return { hasUncommittedChanges, hasUnpushedCommits, uncommittedFileCount };
|
|
35924
|
-
}
|
|
35925
|
-
async function pushAheadOfUpstreamForPaths(paths) {
|
|
35926
|
-
await forEachWithGitYield(paths, async (p) => {
|
|
35927
|
-
const g = cliSimpleGit(p);
|
|
35928
|
-
const ahead = await commitsAheadOfRemoteTracking(p);
|
|
35929
|
-
if (ahead <= 0) return;
|
|
35930
|
-
await g.push();
|
|
35931
|
-
});
|
|
35932
|
-
}
|
|
35933
|
-
|
|
35934
|
-
// src/git/changes/types.ts
|
|
35935
|
-
var MAX_PATCH_CHARS = 35e4;
|
|
35936
|
-
|
|
35937
|
-
// src/git/changes/lib/repo-format.ts
|
|
35938
|
-
function posixJoinDirFile(dir, file2) {
|
|
35939
|
-
const d = dir === "." || dir === "" ? "" : dir.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
35940
|
-
const f = file2.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
35941
|
-
return d ? `${d}/${f}` : f;
|
|
35942
|
-
}
|
|
35943
|
-
function formatRepoShortTitle(remoteUrl, repoRelPath) {
|
|
35944
|
-
const u = remoteUrl.trim();
|
|
35945
|
-
if (u) {
|
|
35946
|
-
try {
|
|
35947
|
-
if (u.startsWith("git@")) {
|
|
35948
|
-
const colon = u.indexOf(":");
|
|
35949
|
-
if (colon > 0) {
|
|
35950
|
-
const pathPart = u.slice(colon + 1).replace(/\.git$/i, "").replace(/\/+$/, "");
|
|
35951
|
-
if (pathPart.includes("/")) return pathPart;
|
|
35952
|
-
}
|
|
35953
|
-
} else {
|
|
35954
|
-
const parsed = new URL(u);
|
|
35955
|
-
const p = parsed.pathname.replace(/^\//, "").replace(/\.git$/i, "");
|
|
35956
|
-
const parts = p.split("/").filter(Boolean);
|
|
35957
|
-
if (parts.length >= 2) {
|
|
35958
|
-
return `${parts[parts.length - 2]}/${parts[parts.length - 1]}`;
|
|
35959
|
-
}
|
|
35960
|
-
if (parts.length === 1) return parts[0];
|
|
35961
|
-
}
|
|
35962
|
-
} catch {
|
|
35963
|
-
}
|
|
35964
|
-
}
|
|
35965
|
-
if (repoRelPath && repoRelPath !== ".") {
|
|
35966
|
-
const segments = repoRelPath.split("/").filter(Boolean);
|
|
35967
|
-
const last2 = segments[segments.length - 1];
|
|
35968
|
-
if (last2) return last2;
|
|
35969
|
-
}
|
|
35970
|
-
return "Repository";
|
|
35971
|
-
}
|
|
35972
|
-
function formatRemoteDisplayLabel(remoteUrl) {
|
|
35973
|
-
const u = remoteUrl.trim();
|
|
35974
|
-
if (!u) return "";
|
|
35975
|
-
let hostPath = u;
|
|
35976
|
-
try {
|
|
35977
|
-
if (u.startsWith("git@")) {
|
|
35978
|
-
const rest = u.slice("git@".length);
|
|
35979
|
-
const slash = rest.indexOf(":");
|
|
35980
|
-
if (slash > 0) hostPath = `${rest.slice(0, slash)}/${rest.slice(slash + 1)}`;
|
|
35981
|
-
} else {
|
|
35982
|
-
const parsed = new URL(u);
|
|
35983
|
-
hostPath = `${parsed.hostname}${parsed.pathname}`.replace(/\/\.git$/i, "").replace(/\.git$/i, "");
|
|
35984
|
-
}
|
|
35985
|
-
} catch {
|
|
35986
|
-
hostPath = u.replace(/^https?:\/\//i, "").replace(/\.git$/i, "");
|
|
35987
|
-
}
|
|
35988
|
-
return `origin \xB7 ${hostPath}`;
|
|
35989
|
-
}
|
|
35990
|
-
|
|
35991
|
-
// src/git/changes/get-working-tree-change-repo-details.ts
|
|
35992
|
-
import * as path24 from "node:path";
|
|
35993
|
-
|
|
35994
35714
|
// src/git/commits/lib/parse-log-lines.ts
|
|
35995
35715
|
function parseLogShaDateSubjectLines(raw) {
|
|
35996
35716
|
const out = [];
|
|
@@ -36061,6 +35781,59 @@ async function listRecentCommits(repoDir, limitInput) {
|
|
|
36061
35781
|
}
|
|
36062
35782
|
}
|
|
36063
35783
|
|
|
35784
|
+
// src/git/changes/lib/parse-git-status.ts
|
|
35785
|
+
function parseNameStatusLines(lines) {
|
|
35786
|
+
const m = /* @__PURE__ */ new Map();
|
|
35787
|
+
for (const line of lines) {
|
|
35788
|
+
if (!line.trim()) continue;
|
|
35789
|
+
const tabParts = line.split(" ");
|
|
35790
|
+
if (tabParts.length < 2) continue;
|
|
35791
|
+
const status = tabParts[0].trim();
|
|
35792
|
+
const code = status[0];
|
|
35793
|
+
if (code === "A") {
|
|
35794
|
+
m.set(tabParts[tabParts.length - 1], "added");
|
|
35795
|
+
} else if (code === "D") {
|
|
35796
|
+
m.set(tabParts[tabParts.length - 1], "removed");
|
|
35797
|
+
} else if (code === "R" || code === "C") {
|
|
35798
|
+
if (tabParts.length >= 3) m.set(tabParts[tabParts.length - 1], "modified");
|
|
35799
|
+
} else if (code === "M" || code === "U" || code === "T") {
|
|
35800
|
+
m.set(tabParts[tabParts.length - 1], "modified");
|
|
35801
|
+
}
|
|
35802
|
+
}
|
|
35803
|
+
return m;
|
|
35804
|
+
}
|
|
35805
|
+
function parseNumstatFirstLine(line) {
|
|
35806
|
+
const parts = line.split(" ");
|
|
35807
|
+
if (parts.length < 3) return null;
|
|
35808
|
+
const [a, d] = parts;
|
|
35809
|
+
const additions = a === "-" ? 0 : parseInt(String(a), 10) || 0;
|
|
35810
|
+
const deletions = d === "-" ? 0 : parseInt(String(d), 10) || 0;
|
|
35811
|
+
return { additions, deletions };
|
|
35812
|
+
}
|
|
35813
|
+
function parseNumstat(lines) {
|
|
35814
|
+
const m = /* @__PURE__ */ new Map();
|
|
35815
|
+
for (const line of lines) {
|
|
35816
|
+
if (!line.trim()) continue;
|
|
35817
|
+
const parts = line.split(" ");
|
|
35818
|
+
if (parts.length < 3) continue;
|
|
35819
|
+
const [a, d, p] = parts;
|
|
35820
|
+
const additions = a === "-" ? 0 : parseInt(String(a), 10) || 0;
|
|
35821
|
+
const deletions = d === "-" ? 0 : parseInt(String(d), 10) || 0;
|
|
35822
|
+
m.set(p, { additions, deletions });
|
|
35823
|
+
}
|
|
35824
|
+
return m;
|
|
35825
|
+
}
|
|
35826
|
+
async function numstatFromGitNoIndex(g, pathInRepo) {
|
|
35827
|
+
const devNull = process.platform === "win32" ? "NUL" : "/dev/null";
|
|
35828
|
+
try {
|
|
35829
|
+
const out = await g.raw(["diff", "--numstat", "--no-index", "--", devNull, pathInRepo]);
|
|
35830
|
+
const first2 = String(out).split("\n").find((l) => l.trim()) ?? "";
|
|
35831
|
+
return parseNumstatFirstLine(first2);
|
|
35832
|
+
} catch {
|
|
35833
|
+
return null;
|
|
35834
|
+
}
|
|
35835
|
+
}
|
|
35836
|
+
|
|
36064
35837
|
// src/git/changes/lib/patch-truncate.ts
|
|
36065
35838
|
function truncatePatch(s) {
|
|
36066
35839
|
if (s.length <= MAX_PATCH_CHARS) return s;
|
|
@@ -36126,8 +35899,8 @@ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha) {
|
|
|
36126
35899
|
}
|
|
36127
35900
|
|
|
36128
35901
|
// src/git/changes/list-changed-files-for-repo.ts
|
|
36129
|
-
import * as
|
|
36130
|
-
import * as
|
|
35902
|
+
import * as fs18 from "node:fs";
|
|
35903
|
+
import * as path20 from "node:path";
|
|
36131
35904
|
|
|
36132
35905
|
// src/git/changes/lib/count-lines.ts
|
|
36133
35906
|
import { createReadStream } from "node:fs";
|
|
@@ -36151,7 +35924,7 @@ async function countTextFileLines(filePath) {
|
|
|
36151
35924
|
}
|
|
36152
35925
|
|
|
36153
35926
|
// src/git/changes/hydrate-patch.ts
|
|
36154
|
-
import * as
|
|
35927
|
+
import * as fs17 from "node:fs";
|
|
36155
35928
|
var UNIFIED_HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
|
|
36156
35929
|
var MAX_HYDRATE_LINES_PER_GAP = 8e3;
|
|
36157
35930
|
var MAX_HYDRATE_LINES_PER_FILE = 8e4;
|
|
@@ -36166,7 +35939,7 @@ async function readGitBlobLines(repoCwd, pathInRepo) {
|
|
|
36166
35939
|
}
|
|
36167
35940
|
async function readWorktreeFileLines(filePath) {
|
|
36168
35941
|
try {
|
|
36169
|
-
const raw = await
|
|
35942
|
+
const raw = await fs17.promises.readFile(filePath, "utf8");
|
|
36170
35943
|
return raw.split(/\r?\n/);
|
|
36171
35944
|
} catch {
|
|
36172
35945
|
return null;
|
|
@@ -36291,7 +36064,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
36291
36064
|
const rows = [];
|
|
36292
36065
|
await forEachWithGitYield([...paths], async (pathInRepo) => {
|
|
36293
36066
|
const relLauncher = posixJoinDirFile(repoRelPath, pathInRepo.replace(/\\/g, "/"));
|
|
36294
|
-
const repoFilePath =
|
|
36067
|
+
const repoFilePath = path20.join(repoGitCwd, pathInRepo);
|
|
36295
36068
|
const nums = numByPath.get(pathInRepo);
|
|
36296
36069
|
let additions = nums?.additions ?? 0;
|
|
36297
36070
|
let deletions = nums?.deletions ?? 0;
|
|
@@ -36304,7 +36077,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
36304
36077
|
deletions = fromGit.deletions;
|
|
36305
36078
|
} else {
|
|
36306
36079
|
try {
|
|
36307
|
-
const st = await
|
|
36080
|
+
const st = await fs18.promises.stat(repoFilePath);
|
|
36308
36081
|
if (st.isFile()) additions = await countTextFileLines(repoFilePath);
|
|
36309
36082
|
else additions = 0;
|
|
36310
36083
|
} catch {
|
|
@@ -36330,7 +36103,7 @@ async function listChangedFilesForRepo(repoGitCwd, repoRelPath) {
|
|
|
36330
36103
|
} else {
|
|
36331
36104
|
pathInRepo = row.pathRelLauncher;
|
|
36332
36105
|
}
|
|
36333
|
-
const filePath =
|
|
36106
|
+
const filePath = path20.join(repoGitCwd, pathInRepo);
|
|
36334
36107
|
let patch = await unifiedDiffForFile(repoGitCwd, pathInRepo, row.change);
|
|
36335
36108
|
if (patch) {
|
|
36336
36109
|
patch = await hydrateUnifiedPatchWithFileContext(patch, filePath, repoGitCwd, pathInRepo, row.change);
|
|
@@ -36346,8 +36119,8 @@ function normRepoRel(p) {
|
|
|
36346
36119
|
return x === "" ? "." : x;
|
|
36347
36120
|
}
|
|
36348
36121
|
async function getWorkingTreeChangeRepoDetails(options) {
|
|
36349
|
-
const bridgeRoot =
|
|
36350
|
-
const sessionWtRoot = options.sessionWorktreeRootPath ?
|
|
36122
|
+
const bridgeRoot = path21.resolve(getBridgeRoot());
|
|
36123
|
+
const sessionWtRoot = options.sessionWorktreeRootPath ? path21.resolve(options.sessionWorktreeRootPath) : null;
|
|
36351
36124
|
const legacyNested = options.legacyRepoNestedSessionLayout === true;
|
|
36352
36125
|
const out = [];
|
|
36353
36126
|
const filter = options.repoFilterRelPath != null ? normRepoRel(options.repoFilterRelPath) : null;
|
|
@@ -36362,7 +36135,7 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
36362
36135
|
for (let i = 0; i < options.commitTargetPaths.length; i++) {
|
|
36363
36136
|
if (i > 0) await yieldToEventLoop2();
|
|
36364
36137
|
const target = options.commitTargetPaths[i];
|
|
36365
|
-
const t =
|
|
36138
|
+
const t = path21.resolve(target);
|
|
36366
36139
|
if (!await isGitRepoDirectory(t)) continue;
|
|
36367
36140
|
const g = cliSimpleGit(t);
|
|
36368
36141
|
let branch = "HEAD";
|
|
@@ -36375,8 +36148,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
36375
36148
|
const remoteDisplay = formatRemoteDisplayLabel(remoteUrl);
|
|
36376
36149
|
let repoRelPath;
|
|
36377
36150
|
if (sessionWtRoot) {
|
|
36378
|
-
const anchor = legacyNested ?
|
|
36379
|
-
const relNorm =
|
|
36151
|
+
const anchor = legacyNested ? path21.dirname(t) : t;
|
|
36152
|
+
const relNorm = path21.relative(sessionWtRoot, anchor);
|
|
36380
36153
|
repoRelPath = relNorm === "" ? "." : relNorm.replace(/\\/g, "/");
|
|
36381
36154
|
} else {
|
|
36382
36155
|
let top = t;
|
|
@@ -36385,8 +36158,8 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
36385
36158
|
} catch {
|
|
36386
36159
|
top = t;
|
|
36387
36160
|
}
|
|
36388
|
-
const rel =
|
|
36389
|
-
repoRelPath = rel.startsWith("..") ?
|
|
36161
|
+
const rel = path21.relative(bridgeRoot, path21.resolve(top)).replace(/\\/g, "/") || ".";
|
|
36162
|
+
repoRelPath = rel.startsWith("..") ? path21.basename(path21.resolve(top)) : rel;
|
|
36390
36163
|
}
|
|
36391
36164
|
const norm = normRepoRel(repoRelPath === "" ? "." : repoRelPath);
|
|
36392
36165
|
if (filter && norm !== filter) continue;
|
|
@@ -36418,6 +36191,64 @@ async function getWorkingTreeChangeRepoDetails(options) {
|
|
|
36418
36191
|
return out;
|
|
36419
36192
|
}
|
|
36420
36193
|
|
|
36194
|
+
// src/git/changes/lib/working-tree-changed-path-count.ts
|
|
36195
|
+
function workingTreeChangedPathCount(nameStatusLines, numstatLines, untrackedLines) {
|
|
36196
|
+
const kindByPath = parseNameStatusLines(nameStatusLines);
|
|
36197
|
+
const numByPath = parseNumstat(numstatLines);
|
|
36198
|
+
const paths = /* @__PURE__ */ new Set([...kindByPath.keys(), ...numByPath.keys()]);
|
|
36199
|
+
for (const p of untrackedLines.map((s) => s.trim()).filter(Boolean)) {
|
|
36200
|
+
paths.add(p);
|
|
36201
|
+
}
|
|
36202
|
+
return paths.size;
|
|
36203
|
+
}
|
|
36204
|
+
|
|
36205
|
+
// src/git/changes/count-working-tree-changed-files.ts
|
|
36206
|
+
async function countWorkingTreeChangedFilesForRepo(repoGitCwd) {
|
|
36207
|
+
return runGitTask(async () => {
|
|
36208
|
+
const g = cliSimpleGit(repoGitCwd);
|
|
36209
|
+
const [nameStatusRaw, numstatRaw, untrackedRaw] = await Promise.all([
|
|
36210
|
+
g.raw(["diff", "--name-status", "HEAD"]).catch(() => ""),
|
|
36211
|
+
g.raw(["diff", "HEAD", "--numstat"]).catch(() => ""),
|
|
36212
|
+
g.raw(["ls-files", "--others", "--exclude-standard"]).catch(() => "")
|
|
36213
|
+
]);
|
|
36214
|
+
return workingTreeChangedPathCount(
|
|
36215
|
+
String(nameStatusRaw).split("\n"),
|
|
36216
|
+
String(numstatRaw).split("\n"),
|
|
36217
|
+
String(untrackedRaw).split("\n")
|
|
36218
|
+
);
|
|
36219
|
+
});
|
|
36220
|
+
}
|
|
36221
|
+
|
|
36222
|
+
// src/git/status/working-tree-status.ts
|
|
36223
|
+
async function getRepoWorkingTreeStatus(repoDir) {
|
|
36224
|
+
return runGitTask(async () => {
|
|
36225
|
+
const uncommittedFileCount = await countWorkingTreeChangedFilesForRepo(repoDir);
|
|
36226
|
+
const hasUncommittedChanges = uncommittedFileCount > 0;
|
|
36227
|
+
const ahead = await commitsAheadOfRemoteTracking(repoDir);
|
|
36228
|
+
return { hasUncommittedChanges, hasUnpushedCommits: ahead > 0, uncommittedFileCount };
|
|
36229
|
+
});
|
|
36230
|
+
}
|
|
36231
|
+
async function aggregateSessionPathsWorkingTreeStatus(paths) {
|
|
36232
|
+
let hasUncommittedChanges = false;
|
|
36233
|
+
let hasUnpushedCommits = false;
|
|
36234
|
+
let uncommittedFileCount = 0;
|
|
36235
|
+
await forEachWithGitYield(paths, async (p) => {
|
|
36236
|
+
const s = await getRepoWorkingTreeStatus(p);
|
|
36237
|
+
uncommittedFileCount += s.uncommittedFileCount;
|
|
36238
|
+
if (s.hasUncommittedChanges) hasUncommittedChanges = true;
|
|
36239
|
+
if (s.hasUnpushedCommits) hasUnpushedCommits = true;
|
|
36240
|
+
});
|
|
36241
|
+
return { hasUncommittedChanges, hasUnpushedCommits, uncommittedFileCount };
|
|
36242
|
+
}
|
|
36243
|
+
async function pushAheadOfUpstreamForPaths(paths) {
|
|
36244
|
+
await forEachWithGitYield(paths, async (p) => {
|
|
36245
|
+
const g = cliSimpleGit(p);
|
|
36246
|
+
const ahead = await commitsAheadOfRemoteTracking(p);
|
|
36247
|
+
if (ahead <= 0) return;
|
|
36248
|
+
await g.push();
|
|
36249
|
+
});
|
|
36250
|
+
}
|
|
36251
|
+
|
|
36421
36252
|
// src/git/branches/commit-and-push.ts
|
|
36422
36253
|
async function gitCommitAllIfDirty(repoDir, message, options) {
|
|
36423
36254
|
const g = cliSimpleGit(repoDir);
|
|
@@ -36455,12 +36286,137 @@ async function commitSessionWorktrees(options) {
|
|
|
36455
36286
|
}
|
|
36456
36287
|
}
|
|
36457
36288
|
|
|
36289
|
+
// src/worktrees/remove-session-worktrees.ts
|
|
36290
|
+
import * as fs21 from "node:fs";
|
|
36291
|
+
|
|
36292
|
+
// src/git/worktrees/worktree-remove.ts
|
|
36293
|
+
import * as fs20 from "node:fs";
|
|
36294
|
+
|
|
36295
|
+
// src/git/worktrees/resolve-main-repo-from-git-file.ts
|
|
36296
|
+
import * as fs19 from "node:fs";
|
|
36297
|
+
import * as path22 from "node:path";
|
|
36298
|
+
function resolveMainRepoFromWorktreeGitFile(wt) {
|
|
36299
|
+
const gitDirFile = path22.join(wt, ".git");
|
|
36300
|
+
if (!fs19.existsSync(gitDirFile) || !fs19.statSync(gitDirFile).isFile()) return "";
|
|
36301
|
+
const first2 = fs19.readFileSync(gitDirFile, "utf8").trim();
|
|
36302
|
+
const m = first2.match(/^gitdir:\s*(.+)$/im);
|
|
36303
|
+
if (!m) return "";
|
|
36304
|
+
const gitWorktreePath = path22.resolve(wt, m[1].trim());
|
|
36305
|
+
const gitDir = path22.dirname(path22.dirname(gitWorktreePath));
|
|
36306
|
+
return path22.dirname(gitDir);
|
|
36307
|
+
}
|
|
36308
|
+
|
|
36309
|
+
// src/git/worktrees/worktree-remove.ts
|
|
36310
|
+
async function gitWorktreeRemoveForce(worktreePath) {
|
|
36311
|
+
const mainRepo = resolveMainRepoFromWorktreeGitFile(worktreePath);
|
|
36312
|
+
if (mainRepo) {
|
|
36313
|
+
await cliSimpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
|
|
36314
|
+
} else {
|
|
36315
|
+
fs20.rmSync(worktreePath, { recursive: true, force: true });
|
|
36316
|
+
}
|
|
36317
|
+
}
|
|
36318
|
+
|
|
36319
|
+
// src/worktrees/remove-session-worktrees.ts
|
|
36320
|
+
async function removeSessionWorktrees(paths, log2) {
|
|
36321
|
+
for (const wt of paths) {
|
|
36322
|
+
try {
|
|
36323
|
+
await gitWorktreeRemoveForce(wt);
|
|
36324
|
+
log2(`[worktrees] Removed worktree ${wt}`);
|
|
36325
|
+
} catch (e) {
|
|
36326
|
+
log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
|
|
36327
|
+
try {
|
|
36328
|
+
fs21.rmSync(wt, { recursive: true, force: true });
|
|
36329
|
+
} catch {
|
|
36330
|
+
}
|
|
36331
|
+
}
|
|
36332
|
+
}
|
|
36333
|
+
}
|
|
36334
|
+
|
|
36335
|
+
// src/git/branches/rename-branch.ts
|
|
36336
|
+
async function gitRenameCurrentBranch(repoDir, newName) {
|
|
36337
|
+
const g = cliSimpleGit(repoDir);
|
|
36338
|
+
await g.raw(["branch", "-m", newName]);
|
|
36339
|
+
}
|
|
36340
|
+
|
|
36341
|
+
// src/worktrees/rename-session-worktree-branches.ts
|
|
36342
|
+
async function renameSessionWorktreeBranches(paths, newBranch, log2) {
|
|
36343
|
+
const safe = newBranch.replace(/[^a-zA-Z0-9/_-]+/g, "-").slice(0, 80) || "session-branch";
|
|
36344
|
+
for (const wt of paths) {
|
|
36345
|
+
try {
|
|
36346
|
+
await gitRenameCurrentBranch(wt, safe);
|
|
36347
|
+
log2(`[worktrees] Renamed branch in ${wt} \u2192 ${safe}`);
|
|
36348
|
+
} catch (e) {
|
|
36349
|
+
log2(
|
|
36350
|
+
`[worktrees] Branch rename failed in ${wt}: ${e instanceof Error ? e.message : String(e)}`
|
|
36351
|
+
);
|
|
36352
|
+
}
|
|
36353
|
+
}
|
|
36354
|
+
}
|
|
36355
|
+
|
|
36356
|
+
// src/worktrees/worktree-layout-file.ts
|
|
36357
|
+
import * as fs22 from "node:fs";
|
|
36358
|
+
import * as path23 from "node:path";
|
|
36359
|
+
import os7 from "node:os";
|
|
36360
|
+
var LAYOUT_FILENAME = "worktree-launcher-layout.json";
|
|
36361
|
+
function defaultWorktreeLayoutPath() {
|
|
36362
|
+
return path23.join(os7.homedir(), ".buildautomaton", LAYOUT_FILENAME);
|
|
36363
|
+
}
|
|
36364
|
+
function normalizeLoadedLayout(raw) {
|
|
36365
|
+
if (raw && typeof raw === "object" && "launcherCwds" in raw) {
|
|
36366
|
+
const j = raw;
|
|
36367
|
+
if (Array.isArray(j.launcherCwds)) return { launcherCwds: j.launcherCwds };
|
|
36368
|
+
}
|
|
36369
|
+
return { launcherCwds: [] };
|
|
36370
|
+
}
|
|
36371
|
+
function loadWorktreeLayout() {
|
|
36372
|
+
try {
|
|
36373
|
+
const p = defaultWorktreeLayoutPath();
|
|
36374
|
+
if (!fs22.existsSync(p)) return { launcherCwds: [] };
|
|
36375
|
+
const raw = JSON.parse(fs22.readFileSync(p, "utf8"));
|
|
36376
|
+
return normalizeLoadedLayout(raw);
|
|
36377
|
+
} catch {
|
|
36378
|
+
return { launcherCwds: [] };
|
|
36379
|
+
}
|
|
36380
|
+
}
|
|
36381
|
+
function saveWorktreeLayout(layout) {
|
|
36382
|
+
try {
|
|
36383
|
+
const dir = path23.dirname(defaultWorktreeLayoutPath());
|
|
36384
|
+
fs22.mkdirSync(dir, { recursive: true });
|
|
36385
|
+
fs22.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
|
|
36386
|
+
} catch {
|
|
36387
|
+
}
|
|
36388
|
+
}
|
|
36389
|
+
function baseNameSafe(pathString) {
|
|
36390
|
+
return path23.basename(pathString).replace(/[^a-zA-Z0-9._-]+/g, "-") || "cwd";
|
|
36391
|
+
}
|
|
36392
|
+
function getLauncherDirNameIfPresent(layout, bridgeRootPath2) {
|
|
36393
|
+
const norm = path23.resolve(bridgeRootPath2);
|
|
36394
|
+
const existing = layout.launcherCwds.find((e) => path23.resolve(e.absolutePath) === norm);
|
|
36395
|
+
return existing?.dirName;
|
|
36396
|
+
}
|
|
36397
|
+
function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
|
|
36398
|
+
const existing = getLauncherDirNameIfPresent(layout, bridgeRootPath2);
|
|
36399
|
+
if (existing) return existing;
|
|
36400
|
+
const norm = path23.resolve(bridgeRootPath2);
|
|
36401
|
+
const base = baseNameSafe(norm);
|
|
36402
|
+
const used = new Set(layout.launcherCwds.map((e) => e.dirName));
|
|
36403
|
+
let name = base;
|
|
36404
|
+
let n = 2;
|
|
36405
|
+
while (used.has(name)) {
|
|
36406
|
+
name = `${base}-${n}`;
|
|
36407
|
+
n += 1;
|
|
36408
|
+
}
|
|
36409
|
+
layout.launcherCwds.push({ absolutePath: norm, dirName: name });
|
|
36410
|
+
saveWorktreeLayout(layout);
|
|
36411
|
+
return name;
|
|
36412
|
+
}
|
|
36413
|
+
|
|
36458
36414
|
// src/worktrees/discover-session-worktree-on-disk.ts
|
|
36459
|
-
import * as
|
|
36460
|
-
import * as
|
|
36415
|
+
import * as fs23 from "node:fs";
|
|
36416
|
+
import * as path24 from "node:path";
|
|
36461
36417
|
function isGitDir(dirPath) {
|
|
36462
36418
|
try {
|
|
36463
|
-
return
|
|
36419
|
+
return fs23.existsSync(path24.join(dirPath, ".git"));
|
|
36464
36420
|
} catch {
|
|
36465
36421
|
return false;
|
|
36466
36422
|
}
|
|
@@ -36469,23 +36425,23 @@ function collectGitRepoRootsUnderDirectory(rootPath) {
|
|
|
36469
36425
|
const out = [];
|
|
36470
36426
|
const walk = (dir) => {
|
|
36471
36427
|
if (isGitDir(dir)) {
|
|
36472
|
-
out.push(
|
|
36428
|
+
out.push(path24.resolve(dir));
|
|
36473
36429
|
return;
|
|
36474
36430
|
}
|
|
36475
36431
|
let entries;
|
|
36476
36432
|
try {
|
|
36477
|
-
entries =
|
|
36433
|
+
entries = fs23.readdirSync(dir, { withFileTypes: true });
|
|
36478
36434
|
} catch {
|
|
36479
36435
|
return;
|
|
36480
36436
|
}
|
|
36481
36437
|
for (const e of entries) {
|
|
36482
36438
|
if (e.name.startsWith(".")) continue;
|
|
36483
|
-
const full =
|
|
36439
|
+
const full = path24.join(dir, e.name);
|
|
36484
36440
|
if (!e.isDirectory()) continue;
|
|
36485
36441
|
walk(full);
|
|
36486
36442
|
}
|
|
36487
36443
|
};
|
|
36488
|
-
walk(
|
|
36444
|
+
walk(path24.resolve(rootPath));
|
|
36489
36445
|
return [...new Set(out)];
|
|
36490
36446
|
}
|
|
36491
36447
|
function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
@@ -36494,16 +36450,16 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
|
36494
36450
|
if (depth > maxDepth) return;
|
|
36495
36451
|
let entries;
|
|
36496
36452
|
try {
|
|
36497
|
-
entries =
|
|
36453
|
+
entries = fs23.readdirSync(dir, { withFileTypes: true });
|
|
36498
36454
|
} catch {
|
|
36499
36455
|
return;
|
|
36500
36456
|
}
|
|
36501
36457
|
for (const e of entries) {
|
|
36502
36458
|
if (e.name.startsWith(".")) continue;
|
|
36503
|
-
const full =
|
|
36459
|
+
const full = path24.join(dir, e.name);
|
|
36504
36460
|
if (!e.isDirectory()) continue;
|
|
36505
36461
|
if (e.name === sessionId) {
|
|
36506
|
-
if (isGitDir(full)) out.push(
|
|
36462
|
+
if (isGitDir(full)) out.push(path24.resolve(full));
|
|
36507
36463
|
} else {
|
|
36508
36464
|
walk(full, depth + 1);
|
|
36509
36465
|
}
|
|
@@ -36515,14 +36471,14 @@ function collectWorktreeRootsNamed(root, sessionId, maxDepth) {
|
|
|
36515
36471
|
function tryBindingFromSessionDirectory(sessionDir) {
|
|
36516
36472
|
let st;
|
|
36517
36473
|
try {
|
|
36518
|
-
st =
|
|
36474
|
+
st = fs23.statSync(sessionDir);
|
|
36519
36475
|
} catch {
|
|
36520
36476
|
return null;
|
|
36521
36477
|
}
|
|
36522
36478
|
if (!st.isDirectory()) return null;
|
|
36523
36479
|
const worktreePaths = collectGitRepoRootsUnderDirectory(sessionDir);
|
|
36524
36480
|
if (worktreePaths.length === 0) return null;
|
|
36525
|
-
const abs =
|
|
36481
|
+
const abs = path24.resolve(sessionDir);
|
|
36526
36482
|
return {
|
|
36527
36483
|
sessionParentPath: abs,
|
|
36528
36484
|
workingTreeRelRoot: abs,
|
|
@@ -36532,20 +36488,20 @@ function tryBindingFromSessionDirectory(sessionDir) {
|
|
|
36532
36488
|
function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
|
|
36533
36489
|
const sid = sessionId.trim();
|
|
36534
36490
|
if (!sid) return null;
|
|
36535
|
-
const hintR =
|
|
36491
|
+
const hintR = path24.resolve(checkoutPath);
|
|
36536
36492
|
let best = null;
|
|
36537
|
-
let cur =
|
|
36493
|
+
let cur = path24.dirname(hintR);
|
|
36538
36494
|
for (let i = 0; i < 40; i++) {
|
|
36539
36495
|
const paths = collectWorktreeRootsNamed(cur, sid, 24);
|
|
36540
|
-
if (paths.some((p) =>
|
|
36541
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ??
|
|
36496
|
+
if (paths.some((p) => path24.resolve(p) === hintR)) {
|
|
36497
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(paths) ?? path24.resolve(paths[0]);
|
|
36542
36498
|
best = {
|
|
36543
|
-
sessionParentPath:
|
|
36544
|
-
workingTreeRelRoot:
|
|
36545
|
-
repoCheckoutPaths: paths.map((p) =>
|
|
36499
|
+
sessionParentPath: path24.resolve(isolated),
|
|
36500
|
+
workingTreeRelRoot: path24.resolve(cur),
|
|
36501
|
+
repoCheckoutPaths: paths.map((p) => path24.resolve(p))
|
|
36546
36502
|
};
|
|
36547
36503
|
}
|
|
36548
|
-
const next =
|
|
36504
|
+
const next = path24.dirname(cur);
|
|
36549
36505
|
if (next === cur) break;
|
|
36550
36506
|
cur = next;
|
|
36551
36507
|
}
|
|
@@ -36553,33 +36509,33 @@ function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
|
|
|
36553
36509
|
}
|
|
36554
36510
|
function discoverSessionWorktreeOnDisk(options) {
|
|
36555
36511
|
const { sessionId, worktreesRootPath, layout, bridgeRoot } = options;
|
|
36556
|
-
if (!sessionId.trim() || !
|
|
36512
|
+
if (!sessionId.trim() || !fs23.existsSync(worktreesRootPath)) return null;
|
|
36557
36513
|
const preferredKey = getLauncherDirNameIfPresent(layout, bridgeRoot);
|
|
36558
36514
|
const keys = [];
|
|
36559
36515
|
if (preferredKey) keys.push(preferredKey);
|
|
36560
36516
|
try {
|
|
36561
|
-
for (const name of
|
|
36517
|
+
for (const name of fs23.readdirSync(worktreesRootPath)) {
|
|
36562
36518
|
if (name.startsWith(".")) continue;
|
|
36563
|
-
const p =
|
|
36564
|
-
if (!
|
|
36519
|
+
const p = path24.join(worktreesRootPath, name);
|
|
36520
|
+
if (!fs23.statSync(p).isDirectory()) continue;
|
|
36565
36521
|
if (name !== preferredKey) keys.push(name);
|
|
36566
36522
|
}
|
|
36567
36523
|
} catch {
|
|
36568
36524
|
return null;
|
|
36569
36525
|
}
|
|
36570
36526
|
for (const key of keys) {
|
|
36571
|
-
const layoutRoot =
|
|
36572
|
-
if (!
|
|
36573
|
-
const sessionDir =
|
|
36527
|
+
const layoutRoot = path24.join(worktreesRootPath, key);
|
|
36528
|
+
if (!fs23.existsSync(layoutRoot) || !fs23.statSync(layoutRoot).isDirectory()) continue;
|
|
36529
|
+
const sessionDir = path24.join(layoutRoot, sessionId);
|
|
36574
36530
|
const nested = tryBindingFromSessionDirectory(sessionDir);
|
|
36575
36531
|
if (nested) return nested;
|
|
36576
36532
|
const legacyPaths = collectWorktreeRootsNamed(layoutRoot, sessionId, 24);
|
|
36577
36533
|
if (legacyPaths.length > 0) {
|
|
36578
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ??
|
|
36534
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path24.resolve(legacyPaths[0]);
|
|
36579
36535
|
return {
|
|
36580
|
-
sessionParentPath:
|
|
36581
|
-
workingTreeRelRoot:
|
|
36582
|
-
repoCheckoutPaths: legacyPaths.map((p) =>
|
|
36536
|
+
sessionParentPath: path24.resolve(isolated),
|
|
36537
|
+
workingTreeRelRoot: path24.resolve(layoutRoot),
|
|
36538
|
+
repoCheckoutPaths: legacyPaths.map((p) => path24.resolve(p))
|
|
36583
36539
|
};
|
|
36584
36540
|
}
|
|
36585
36541
|
}
|
|
@@ -36588,12 +36544,12 @@ function discoverSessionWorktreeOnDisk(options) {
|
|
|
36588
36544
|
function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPathOrHint, sessionId) {
|
|
36589
36545
|
const sid = sessionId.trim();
|
|
36590
36546
|
if (!sid) return null;
|
|
36591
|
-
const hint =
|
|
36592
|
-
const underHint = tryBindingFromSessionDirectory(
|
|
36547
|
+
const hint = path24.resolve(sessionWorktreeRootPathOrHint);
|
|
36548
|
+
const underHint = tryBindingFromSessionDirectory(path24.join(hint, sid));
|
|
36593
36549
|
if (underHint) return underHint;
|
|
36594
36550
|
const direct = tryBindingFromSessionDirectory(hint);
|
|
36595
36551
|
if (direct) {
|
|
36596
|
-
if (
|
|
36552
|
+
if (path24.basename(hint) === sid && isGitDir(hint)) {
|
|
36597
36553
|
const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
|
|
36598
36554
|
if (legacyFromCheckout && legacyFromCheckout.repoCheckoutPaths.length > direct.repoCheckoutPaths.length) {
|
|
36599
36555
|
return legacyFromCheckout;
|
|
@@ -36601,216 +36557,349 @@ function discoverSessionWorktreesUnderSessionWorktreeRoot(sessionWorktreeRootPat
|
|
|
36601
36557
|
}
|
|
36602
36558
|
return direct;
|
|
36603
36559
|
}
|
|
36604
|
-
if (
|
|
36560
|
+
if (path24.basename(hint) === sid && isGitDir(hint)) {
|
|
36605
36561
|
const legacyFromCheckout = discoverLegacyBindingAscendingFromCheckout(sid, hint);
|
|
36606
36562
|
if (legacyFromCheckout) return legacyFromCheckout;
|
|
36607
36563
|
}
|
|
36608
36564
|
let st;
|
|
36609
36565
|
try {
|
|
36610
|
-
st =
|
|
36566
|
+
st = fs23.statSync(hint);
|
|
36611
36567
|
} catch {
|
|
36612
36568
|
return null;
|
|
36613
36569
|
}
|
|
36614
36570
|
if (!st.isDirectory()) return null;
|
|
36615
36571
|
const legacyPaths = collectWorktreeRootsNamed(hint, sid, 24);
|
|
36616
36572
|
if (legacyPaths.length === 0) return null;
|
|
36617
|
-
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ??
|
|
36573
|
+
const isolated = resolveIsolatedSessionParentPathFromCheckouts(legacyPaths) ?? path24.resolve(legacyPaths[0]);
|
|
36618
36574
|
return {
|
|
36619
|
-
sessionParentPath:
|
|
36575
|
+
sessionParentPath: path24.resolve(isolated),
|
|
36620
36576
|
workingTreeRelRoot: hint,
|
|
36621
|
-
repoCheckoutPaths: legacyPaths.map((p) =>
|
|
36577
|
+
repoCheckoutPaths: legacyPaths.map((p) => path24.resolve(p))
|
|
36622
36578
|
};
|
|
36623
36579
|
}
|
|
36624
36580
|
|
|
36625
|
-
// src/worktrees/session-
|
|
36581
|
+
// src/worktrees/manager/discover-session-binding.ts
|
|
36582
|
+
function discoverSessionBinding(params) {
|
|
36583
|
+
return discoverSessionWorktreeOnDisk({
|
|
36584
|
+
sessionId: params.sessionId,
|
|
36585
|
+
worktreesRootPath: params.worktreesRootPath,
|
|
36586
|
+
layout: params.layout,
|
|
36587
|
+
bridgeRoot: getBridgeRoot()
|
|
36588
|
+
});
|
|
36589
|
+
}
|
|
36590
|
+
|
|
36591
|
+
// src/worktrees/manager/resolve-isolated-session-parent-path.ts
|
|
36592
|
+
function resolveIsolatedSessionParentPath(sessionId, cache2, ensureRepoCheckoutPaths) {
|
|
36593
|
+
if (!sessionId) return null;
|
|
36594
|
+
const sid = sessionId.trim();
|
|
36595
|
+
const cached2 = cache2.getSessionParentPath(sid);
|
|
36596
|
+
if (cached2) return cached2;
|
|
36597
|
+
const paths = ensureRepoCheckoutPaths(sid);
|
|
36598
|
+
if (!paths?.length) return null;
|
|
36599
|
+
return resolveIsolatedSessionParentPathFromCheckouts(paths);
|
|
36600
|
+
}
|
|
36601
|
+
function ensureRepoCheckoutPathsForSession(sessionId, cache2, discover) {
|
|
36602
|
+
if (!sessionId?.trim()) return void 0;
|
|
36603
|
+
const sid = sessionId.trim();
|
|
36604
|
+
const cached2 = cache2.getRepoCheckoutPaths(sid);
|
|
36605
|
+
if (cached2?.length) return cached2;
|
|
36606
|
+
const disc = discover(sid);
|
|
36607
|
+
if (disc?.repoCheckoutPaths.length) {
|
|
36608
|
+
cache2.remember(sid, disc);
|
|
36609
|
+
return [...disc.repoCheckoutPaths];
|
|
36610
|
+
}
|
|
36611
|
+
return void 0;
|
|
36612
|
+
}
|
|
36613
|
+
|
|
36614
|
+
// src/worktrees/manager/resolve-commit-targets.ts
|
|
36615
|
+
function resolveCommitTargets(sessionId, cache2, discover) {
|
|
36616
|
+
const paths = cache2.getRepoCheckoutPathsRef(sessionId);
|
|
36617
|
+
if (paths?.length) return paths;
|
|
36618
|
+
const disc = discover(sessionId);
|
|
36619
|
+
if (disc?.repoCheckoutPaths.length) {
|
|
36620
|
+
cache2.remember(sessionId, disc);
|
|
36621
|
+
return disc.repoCheckoutPaths;
|
|
36622
|
+
}
|
|
36623
|
+
return [getBridgeRoot()];
|
|
36624
|
+
}
|
|
36625
|
+
|
|
36626
|
+
// src/worktrees/manager/parse-session-parent.ts
|
|
36626
36627
|
function parseSessionParent(v) {
|
|
36627
36628
|
if (v === "bridge_root" || v === "worktrees_root") return v;
|
|
36628
36629
|
if (v === "session_worktrees_root") return "worktrees_root";
|
|
36629
36630
|
return null;
|
|
36630
36631
|
}
|
|
36631
|
-
|
|
36632
|
-
|
|
36633
|
-
|
|
36632
|
+
|
|
36633
|
+
// src/worktrees/prepare-new-session-worktrees.ts
|
|
36634
|
+
import * as fs24 from "node:fs";
|
|
36635
|
+
import * as path25 from "node:path";
|
|
36636
|
+
|
|
36637
|
+
// src/git/worktrees/worktree-add.ts
|
|
36638
|
+
async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch, baseRef = "HEAD") {
|
|
36639
|
+
const mainGit = cliSimpleGit(mainRepoPath);
|
|
36640
|
+
const base = baseRef.trim() || "HEAD";
|
|
36641
|
+
await mainGit.raw(["worktree", "add", "-b", branch, worktreePath, base]);
|
|
36642
|
+
}
|
|
36643
|
+
|
|
36644
|
+
// src/worktrees/prepare-new-session-worktrees.ts
|
|
36645
|
+
function normalizeRepoRelPath(rel) {
|
|
36646
|
+
return rel === "" ? "." : rel.replace(/\\/g, "/");
|
|
36647
|
+
}
|
|
36648
|
+
function resolveBaseRefForRepo(relNorm, baseBranches) {
|
|
36649
|
+
if (!baseBranches) return "HEAD";
|
|
36650
|
+
const direct = baseBranches[relNorm]?.trim();
|
|
36651
|
+
if (direct) return direct;
|
|
36652
|
+
if (relNorm !== "." && baseBranches["."]?.trim()) return baseBranches["."].trim();
|
|
36653
|
+
return "HEAD";
|
|
36654
|
+
}
|
|
36655
|
+
async function prepareNewSessionWorktrees(options) {
|
|
36656
|
+
const { worktreesRootPath, bridgeRoot, sessionId, layout, log: log2, worktreeBaseBranches } = options;
|
|
36657
|
+
const bridgeResolved = path25.resolve(bridgeRoot);
|
|
36658
|
+
const cwdKey = allocateDirNameForLauncherCwd(layout, bridgeResolved);
|
|
36659
|
+
const bridgeKeyDir = path25.join(worktreesRootPath, cwdKey);
|
|
36660
|
+
const sessionDir = path25.join(bridgeKeyDir, sessionId);
|
|
36661
|
+
const repos = await discoverGitReposUnderRoot(bridgeResolved);
|
|
36662
|
+
if (repos.length === 0) {
|
|
36663
|
+
log2("[worktrees] No Git repositories under bridge root; skipping worktree creation.");
|
|
36664
|
+
return null;
|
|
36665
|
+
}
|
|
36666
|
+
const branch = `session-${sessionId}`;
|
|
36667
|
+
const worktreePaths = [];
|
|
36668
|
+
fs24.mkdirSync(sessionDir, { recursive: true });
|
|
36669
|
+
for (const repo of repos) {
|
|
36670
|
+
let rel = path25.relative(bridgeResolved, repo.absolutePath);
|
|
36671
|
+
if (rel.startsWith("..") || path25.isAbsolute(rel)) continue;
|
|
36672
|
+
const relNorm = normalizeRepoRelPath(rel === "" ? "." : rel);
|
|
36673
|
+
const wtPath = relNorm === "." ? sessionDir : path25.join(sessionDir, relNorm);
|
|
36674
|
+
if (relNorm !== ".") {
|
|
36675
|
+
fs24.mkdirSync(path25.dirname(wtPath), { recursive: true });
|
|
36676
|
+
}
|
|
36677
|
+
const baseRef = resolveBaseRefForRepo(relNorm, worktreeBaseBranches);
|
|
36678
|
+
try {
|
|
36679
|
+
await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch, baseRef);
|
|
36680
|
+
log2(`[worktrees] Added worktree ${wtPath} (branch ${branch}, base ${baseRef}).`);
|
|
36681
|
+
worktreePaths.push(wtPath);
|
|
36682
|
+
} catch (e) {
|
|
36683
|
+
log2(
|
|
36684
|
+
`[worktrees] Worktree add failed for ${repo.absolutePath}: ${e instanceof Error ? e.message : String(e)}`
|
|
36685
|
+
);
|
|
36686
|
+
}
|
|
36687
|
+
}
|
|
36688
|
+
if (worktreePaths.length === 0) return null;
|
|
36689
|
+
return {
|
|
36690
|
+
worktreePaths,
|
|
36691
|
+
sessionParentPath: sessionDir,
|
|
36692
|
+
workingTreeRelRoot: sessionDir
|
|
36693
|
+
};
|
|
36694
|
+
}
|
|
36695
|
+
|
|
36696
|
+
// src/worktrees/manager/prepare-and-remember-session-worktrees.ts
|
|
36697
|
+
async function prepareAndRememberSessionWorktrees(params) {
|
|
36698
|
+
const prep = await prepareNewSessionWorktrees({
|
|
36699
|
+
worktreesRootPath: params.worktreesRootPath,
|
|
36700
|
+
bridgeRoot: getBridgeRoot(),
|
|
36701
|
+
sessionId: params.sessionId,
|
|
36702
|
+
layout: params.layout,
|
|
36703
|
+
log: params.log,
|
|
36704
|
+
...params.worktreeBaseBranches && Object.keys(params.worktreeBaseBranches).length > 0 ? { worktreeBaseBranches: params.worktreeBaseBranches } : {}
|
|
36705
|
+
});
|
|
36706
|
+
if (!prep) return void 0;
|
|
36707
|
+
params.cache.remember(params.sessionId, {
|
|
36708
|
+
sessionParentPath: prep.sessionParentPath,
|
|
36709
|
+
workingTreeRelRoot: prep.workingTreeRelRoot,
|
|
36710
|
+
repoCheckoutPaths: prep.worktreePaths
|
|
36711
|
+
});
|
|
36712
|
+
return params.cache.getSessionParentPath(params.sessionId);
|
|
36713
|
+
}
|
|
36714
|
+
|
|
36715
|
+
// src/worktrees/manager/resolve-existing-session-parent-path.ts
|
|
36716
|
+
function resolveExistingSessionParentPath(sessionId, cache2, discover) {
|
|
36717
|
+
const cached2 = cache2.getSessionParentPath(sessionId);
|
|
36718
|
+
if (cached2) return cached2;
|
|
36719
|
+
const disc = discover();
|
|
36720
|
+
if (disc) {
|
|
36721
|
+
cache2.remember(sessionId, disc);
|
|
36722
|
+
return cache2.getSessionParentPath(sessionId);
|
|
36723
|
+
}
|
|
36724
|
+
return void 0;
|
|
36725
|
+
}
|
|
36726
|
+
|
|
36727
|
+
// src/worktrees/manager/resolve-explicit-session-parent-path.ts
|
|
36728
|
+
import * as path26 from "node:path";
|
|
36729
|
+
function resolveExplicitSessionParentPath(params) {
|
|
36730
|
+
const resolved = path26.resolve(params.parentPathRaw);
|
|
36731
|
+
if (parseSessionParent(params.sessionParent) !== "worktrees_root") {
|
|
36732
|
+
return resolved;
|
|
36733
|
+
}
|
|
36734
|
+
const rememberAndReturn = (binding) => {
|
|
36735
|
+
params.cache.remember(params.sessionId, binding);
|
|
36736
|
+
return params.cache.getSessionParentPath(params.sessionId) ?? resolved;
|
|
36737
|
+
};
|
|
36738
|
+
const diskFirst = params.discover();
|
|
36739
|
+
if (diskFirst) return rememberAndReturn(diskFirst);
|
|
36740
|
+
const fromRoot = discoverSessionWorktreesUnderSessionWorktreeRoot(resolved, params.sessionId);
|
|
36741
|
+
if (fromRoot) return rememberAndReturn(fromRoot);
|
|
36742
|
+
let cur = resolved;
|
|
36743
|
+
for (let i = 0; i < 16; i++) {
|
|
36744
|
+
const tryRoot = discoverSessionWorktreesUnderSessionWorktreeRoot(cur, params.sessionId);
|
|
36745
|
+
if (tryRoot) return rememberAndReturn(tryRoot);
|
|
36746
|
+
const next = path26.dirname(cur);
|
|
36747
|
+
if (next === cur) break;
|
|
36748
|
+
cur = next;
|
|
36749
|
+
}
|
|
36750
|
+
return resolved;
|
|
36751
|
+
}
|
|
36752
|
+
|
|
36753
|
+
// src/worktrees/manager/resolve-session-parent-path-for-prompt.ts
|
|
36754
|
+
async function resolveSessionParentPathForPrompt(params) {
|
|
36755
|
+
const { sessionId, cache: cache2, worktreesRootPath, layout, log: log2, discover, opts } = params;
|
|
36756
|
+
if (!sessionId) return void 0;
|
|
36757
|
+
const sid = sessionId.trim();
|
|
36758
|
+
const parentPathRaw = opts.sessionParentPath?.trim();
|
|
36759
|
+
if (parentPathRaw) {
|
|
36760
|
+
return resolveExplicitSessionParentPath({
|
|
36761
|
+
sessionId: sid,
|
|
36762
|
+
sessionParent: opts.sessionParent,
|
|
36763
|
+
parentPathRaw,
|
|
36764
|
+
cache: cache2,
|
|
36765
|
+
discover: () => discover(sid)
|
|
36766
|
+
});
|
|
36767
|
+
}
|
|
36768
|
+
const parentKind = parseSessionParent(opts.sessionParent);
|
|
36769
|
+
if (parentKind === "bridge_root") {
|
|
36770
|
+
return void 0;
|
|
36771
|
+
}
|
|
36772
|
+
if (parentKind === "worktrees_root") {
|
|
36773
|
+
if (!opts.isNewSession) {
|
|
36774
|
+
return resolveExistingSessionParentPath(sid, cache2, () => discover(sid));
|
|
36775
|
+
}
|
|
36776
|
+
return prepareAndRememberSessionWorktrees({
|
|
36777
|
+
cache: cache2,
|
|
36778
|
+
sessionId: sid,
|
|
36779
|
+
worktreesRootPath,
|
|
36780
|
+
layout,
|
|
36781
|
+
log: log2,
|
|
36782
|
+
...opts.worktreeBaseBranches ? { worktreeBaseBranches: opts.worktreeBaseBranches } : {}
|
|
36783
|
+
});
|
|
36784
|
+
}
|
|
36785
|
+
if (!opts.isNewSession) {
|
|
36786
|
+
return resolveExistingSessionParentPath(sid, cache2, () => discover(sid));
|
|
36787
|
+
}
|
|
36788
|
+
return prepareAndRememberSessionWorktrees({
|
|
36789
|
+
cache: cache2,
|
|
36790
|
+
sessionId: sid,
|
|
36791
|
+
worktreesRootPath,
|
|
36792
|
+
layout,
|
|
36793
|
+
log: log2
|
|
36794
|
+
});
|
|
36795
|
+
}
|
|
36796
|
+
|
|
36797
|
+
// src/worktrees/manager/session-worktree-cache.ts
|
|
36798
|
+
import * as path27 from "node:path";
|
|
36799
|
+
var SessionWorktreeCache = class {
|
|
36634
36800
|
sessionRepoCheckoutPaths = /* @__PURE__ */ new Map();
|
|
36635
36801
|
sessionParentPathBySession = /* @__PURE__ */ new Map();
|
|
36636
36802
|
sessionWorkingTreeRelRootBySession = /* @__PURE__ */ new Map();
|
|
36637
|
-
|
|
36638
|
-
|
|
36639
|
-
this.worktreesRootPath = options.worktreesRootPath;
|
|
36640
|
-
this.log = options.log;
|
|
36641
|
-
this.layout = loadWorktreeLayout();
|
|
36642
|
-
}
|
|
36643
|
-
rememberSessionWorktrees(sessionId, binding) {
|
|
36644
|
-
const paths = binding.repoCheckoutPaths.map((p) => path26.resolve(p));
|
|
36803
|
+
remember(sessionId, binding) {
|
|
36804
|
+
const paths = binding.repoCheckoutPaths.map((p) => path27.resolve(p));
|
|
36645
36805
|
this.sessionRepoCheckoutPaths.set(sessionId, paths);
|
|
36646
|
-
this.sessionParentPathBySession.set(sessionId,
|
|
36647
|
-
this.sessionWorkingTreeRelRootBySession.set(sessionId,
|
|
36806
|
+
this.sessionParentPathBySession.set(sessionId, path27.resolve(binding.sessionParentPath));
|
|
36807
|
+
this.sessionWorkingTreeRelRootBySession.set(sessionId, path27.resolve(binding.workingTreeRelRoot));
|
|
36808
|
+
}
|
|
36809
|
+
clearSession(sessionId) {
|
|
36810
|
+
const paths = this.sessionRepoCheckoutPaths.get(sessionId);
|
|
36811
|
+
this.sessionRepoCheckoutPaths.delete(sessionId);
|
|
36812
|
+
this.sessionParentPathBySession.delete(sessionId);
|
|
36813
|
+
this.sessionWorkingTreeRelRootBySession.delete(sessionId);
|
|
36814
|
+
return paths;
|
|
36648
36815
|
}
|
|
36649
|
-
|
|
36816
|
+
getSessionParentPath(sessionId) {
|
|
36650
36817
|
return this.sessionParentPathBySession.get(sessionId);
|
|
36651
36818
|
}
|
|
36652
|
-
|
|
36653
|
-
return
|
|
36654
|
-
|
|
36655
|
-
|
|
36656
|
-
|
|
36657
|
-
|
|
36658
|
-
|
|
36819
|
+
getWorkingTreeRelRoot(sessionId) {
|
|
36820
|
+
return this.sessionWorkingTreeRelRootBySession.get(sessionId) ?? null;
|
|
36821
|
+
}
|
|
36822
|
+
hasSession(sessionId) {
|
|
36823
|
+
return this.sessionParentPathBySession.has(sessionId);
|
|
36824
|
+
}
|
|
36825
|
+
getRepoCheckoutPaths(sessionId) {
|
|
36826
|
+
const paths = this.sessionRepoCheckoutPaths.get(sessionId);
|
|
36827
|
+
return paths?.length ? [...paths] : void 0;
|
|
36828
|
+
}
|
|
36829
|
+
getRepoCheckoutPathsRef(sessionId) {
|
|
36830
|
+
const paths = this.sessionRepoCheckoutPaths.get(sessionId);
|
|
36831
|
+
return paths?.length ? paths : void 0;
|
|
36659
36832
|
}
|
|
36660
36833
|
isLegacyNestedLayout(sessionId) {
|
|
36661
36834
|
const parent = this.sessionParentPathBySession.get(sessionId);
|
|
36662
36835
|
const relRoot = this.sessionWorkingTreeRelRootBySession.get(sessionId);
|
|
36663
36836
|
if (!parent || !relRoot) return false;
|
|
36664
|
-
return
|
|
36837
|
+
return path27.resolve(parent) !== path27.resolve(relRoot);
|
|
36838
|
+
}
|
|
36839
|
+
};
|
|
36840
|
+
|
|
36841
|
+
// src/worktrees/manager/manager.ts
|
|
36842
|
+
var SessionWorktreeManager = class {
|
|
36843
|
+
worktreesRootPath;
|
|
36844
|
+
log;
|
|
36845
|
+
cache = new SessionWorktreeCache();
|
|
36846
|
+
layout;
|
|
36847
|
+
constructor(options) {
|
|
36848
|
+
this.worktreesRootPath = options.worktreesRootPath;
|
|
36849
|
+
this.log = options.log;
|
|
36850
|
+
this.layout = loadWorktreeLayout();
|
|
36851
|
+
}
|
|
36852
|
+
discover(sessionId) {
|
|
36853
|
+
return discoverSessionBinding({
|
|
36854
|
+
sessionId,
|
|
36855
|
+
worktreesRootPath: this.worktreesRootPath,
|
|
36856
|
+
layout: this.layout
|
|
36857
|
+
});
|
|
36665
36858
|
}
|
|
36666
|
-
/**
|
|
36667
|
-
* Session parent path for `worktrees_root`: the per-session directory (new layout) or primary checkout (legacy).
|
|
36668
|
-
*/
|
|
36669
36859
|
getIsolatedSessionParentPathForSession(sessionId) {
|
|
36670
|
-
|
|
36671
|
-
|
|
36672
|
-
|
|
36673
|
-
|
|
36674
|
-
|
|
36675
|
-
|
|
36676
|
-
|
|
36677
|
-
|
|
36678
|
-
|
|
36679
|
-
|
|
36680
|
-
* or `undefined` meaning use {@link getBridgeRoot}.
|
|
36681
|
-
*/
|
|
36682
|
-
async resolveSessionParentPathForPrompt(sessionId, opts) {
|
|
36683
|
-
if (!sessionId) return void 0;
|
|
36684
|
-
const sid = sessionId.trim();
|
|
36685
|
-
const parentPathRaw = opts.sessionParentPath?.trim();
|
|
36686
|
-
if (parentPathRaw) {
|
|
36687
|
-
const resolved = path26.resolve(parentPathRaw);
|
|
36688
|
-
if (sid && parseSessionParent(opts.sessionParent) === "worktrees_root") {
|
|
36689
|
-
const diskFirst = this.tryDiscoverFromDisk(sid);
|
|
36690
|
-
if (diskFirst) {
|
|
36691
|
-
this.rememberSessionWorktrees(sid, diskFirst);
|
|
36692
|
-
return this.sessionParentPathAfterRemember(sid);
|
|
36693
|
-
}
|
|
36694
|
-
const fromRoot = discoverSessionWorktreesUnderSessionWorktreeRoot(resolved, sid);
|
|
36695
|
-
if (fromRoot) {
|
|
36696
|
-
this.rememberSessionWorktrees(sid, fromRoot);
|
|
36697
|
-
return this.sessionParentPathAfterRemember(sid);
|
|
36698
|
-
}
|
|
36699
|
-
let cur = resolved;
|
|
36700
|
-
for (let i = 0; i < 16; i++) {
|
|
36701
|
-
const tryRoot = discoverSessionWorktreesUnderSessionWorktreeRoot(cur, sid);
|
|
36702
|
-
if (tryRoot) {
|
|
36703
|
-
this.rememberSessionWorktrees(sid, tryRoot);
|
|
36704
|
-
return this.sessionParentPathAfterRemember(sid);
|
|
36705
|
-
}
|
|
36706
|
-
const next = path26.dirname(cur);
|
|
36707
|
-
if (next === cur) break;
|
|
36708
|
-
cur = next;
|
|
36709
|
-
}
|
|
36710
|
-
}
|
|
36711
|
-
return resolved;
|
|
36712
|
-
}
|
|
36713
|
-
const parentKind = parseSessionParent(opts.sessionParent);
|
|
36714
|
-
if (parentKind === "bridge_root") {
|
|
36715
|
-
return void 0;
|
|
36716
|
-
}
|
|
36717
|
-
if (parentKind === "worktrees_root") {
|
|
36718
|
-
if (!opts.isNewSession) {
|
|
36719
|
-
const cached2 = this.sessionParentPathAfterRemember(sid);
|
|
36720
|
-
if (cached2) return cached2;
|
|
36721
|
-
const disc = this.tryDiscoverFromDisk(sid);
|
|
36722
|
-
if (disc) {
|
|
36723
|
-
this.rememberSessionWorktrees(sid, disc);
|
|
36724
|
-
return this.sessionParentPathAfterRemember(sid);
|
|
36725
|
-
}
|
|
36726
|
-
return void 0;
|
|
36727
|
-
}
|
|
36728
|
-
const prep2 = await prepareNewSessionWorktrees({
|
|
36729
|
-
worktreesRootPath: this.worktreesRootPath,
|
|
36730
|
-
bridgeRoot: getBridgeRoot(),
|
|
36731
|
-
sessionId: sid,
|
|
36732
|
-
layout: this.layout,
|
|
36733
|
-
log: this.log
|
|
36734
|
-
});
|
|
36735
|
-
if (!prep2) return void 0;
|
|
36736
|
-
this.rememberSessionWorktrees(sid, {
|
|
36737
|
-
sessionParentPath: prep2.sessionParentPath,
|
|
36738
|
-
workingTreeRelRoot: prep2.workingTreeRelRoot,
|
|
36739
|
-
repoCheckoutPaths: prep2.worktreePaths
|
|
36740
|
-
});
|
|
36741
|
-
return this.sessionParentPathAfterRemember(sid);
|
|
36742
|
-
}
|
|
36743
|
-
if (!opts.isNewSession) {
|
|
36744
|
-
const cached2 = this.sessionParentPathAfterRemember(sid);
|
|
36745
|
-
if (cached2) return cached2;
|
|
36746
|
-
const disc = this.tryDiscoverFromDisk(sid);
|
|
36747
|
-
if (disc) {
|
|
36748
|
-
this.rememberSessionWorktrees(sid, disc);
|
|
36749
|
-
return this.sessionParentPathAfterRemember(sid);
|
|
36750
|
-
}
|
|
36751
|
-
return void 0;
|
|
36752
|
-
}
|
|
36753
|
-
const prep = await prepareNewSessionWorktrees({
|
|
36860
|
+
return resolveIsolatedSessionParentPath(
|
|
36861
|
+
sessionId,
|
|
36862
|
+
this.cache,
|
|
36863
|
+
(sid) => this.ensureRepoCheckoutPathsForSession(sid)
|
|
36864
|
+
);
|
|
36865
|
+
}
|
|
36866
|
+
resolveSessionParentPathForPrompt(sessionId, opts) {
|
|
36867
|
+
return resolveSessionParentPathForPrompt({
|
|
36868
|
+
sessionId,
|
|
36869
|
+
cache: this.cache,
|
|
36754
36870
|
worktreesRootPath: this.worktreesRootPath,
|
|
36755
|
-
bridgeRoot: getBridgeRoot(),
|
|
36756
|
-
sessionId: sid,
|
|
36757
36871
|
layout: this.layout,
|
|
36758
|
-
log: this.log
|
|
36759
|
-
|
|
36760
|
-
|
|
36761
|
-
this.rememberSessionWorktrees(sid, {
|
|
36762
|
-
sessionParentPath: prep.sessionParentPath,
|
|
36763
|
-
workingTreeRelRoot: prep.workingTreeRelRoot,
|
|
36764
|
-
repoCheckoutPaths: prep.worktreePaths
|
|
36872
|
+
log: this.log,
|
|
36873
|
+
discover: (sid) => this.discover(sid),
|
|
36874
|
+
opts
|
|
36765
36875
|
});
|
|
36766
|
-
return this.sessionParentPathAfterRemember(sid);
|
|
36767
36876
|
}
|
|
36768
36877
|
async renameSessionBranch(sessionId, newBranch) {
|
|
36769
|
-
const paths = this.
|
|
36878
|
+
const paths = this.cache.getRepoCheckoutPathsRef(sessionId);
|
|
36770
36879
|
if (!paths?.length) return;
|
|
36771
36880
|
await renameSessionWorktreeBranches(paths, newBranch, this.log);
|
|
36772
36881
|
}
|
|
36773
|
-
/** True when this session uses an isolated worktree layout (not the bridge root). */
|
|
36774
36882
|
usesWorktreeSession(sessionId) {
|
|
36775
36883
|
if (!sessionId) return false;
|
|
36776
|
-
return this.
|
|
36884
|
+
return this.cache.hasSession(sessionId);
|
|
36777
36885
|
}
|
|
36778
|
-
/** Per-repo git checkout directories for this session (for snapshots, commits, change lists). */
|
|
36779
36886
|
getRepoCheckoutPathsForSession(sessionId) {
|
|
36780
36887
|
if (!sessionId) return void 0;
|
|
36781
|
-
|
|
36782
|
-
return paths?.length ? [...paths] : void 0;
|
|
36888
|
+
return this.cache.getRepoCheckoutPaths(sessionId);
|
|
36783
36889
|
}
|
|
36784
|
-
/**
|
|
36785
|
-
* Same paths as {@link getRepoCheckoutPathsForSession}, but loads from disk into memory when the CLI
|
|
36786
|
-
* restarted or maps were not yet populated (avoids discovering every repo under the worktrees root).
|
|
36787
|
-
*/
|
|
36788
36890
|
ensureRepoCheckoutPathsForSession(sessionId) {
|
|
36789
|
-
|
|
36790
|
-
const sid = sessionId.trim();
|
|
36791
|
-
const cached2 = this.sessionRepoCheckoutPaths.get(sid);
|
|
36792
|
-
if (cached2?.length) return [...cached2];
|
|
36793
|
-
const disc = this.tryDiscoverFromDisk(sid);
|
|
36794
|
-
if (disc?.repoCheckoutPaths.length) {
|
|
36795
|
-
this.rememberSessionWorktrees(sid, disc);
|
|
36796
|
-
return [...disc.repoCheckoutPaths];
|
|
36797
|
-
}
|
|
36798
|
-
return void 0;
|
|
36891
|
+
return ensureRepoCheckoutPathsForSession(sessionId, this.cache, (sid) => this.discover(sid));
|
|
36799
36892
|
}
|
|
36800
|
-
/** Session parent directory when in worktrees mode; null otherwise (same as {@link getIsolatedSessionParentPathForSession} path). */
|
|
36801
36893
|
getSessionWorktreeRootForSession(sessionId) {
|
|
36802
36894
|
return this.getIsolatedSessionParentPathForSession(sessionId);
|
|
36803
36895
|
}
|
|
36804
36896
|
async removeSessionWorktrees(sessionId) {
|
|
36805
|
-
const paths = this.
|
|
36806
|
-
this.sessionRepoCheckoutPaths.delete(sessionId);
|
|
36807
|
-
this.sessionParentPathBySession.delete(sessionId);
|
|
36808
|
-
this.sessionWorkingTreeRelRootBySession.delete(sessionId);
|
|
36897
|
+
const paths = this.cache.clearSession(sessionId);
|
|
36809
36898
|
if (!paths?.length) return;
|
|
36810
36899
|
await removeSessionWorktrees(paths, this.log);
|
|
36811
36900
|
}
|
|
36812
36901
|
async commitSession(params) {
|
|
36813
|
-
const paths = this.
|
|
36902
|
+
const paths = this.cache.getRepoCheckoutPathsRef(params.sessionId);
|
|
36814
36903
|
const targets = paths?.length ? paths : [getBridgeRoot()];
|
|
36815
36904
|
return commitSessionWorktrees({
|
|
36816
36905
|
paths: targets,
|
|
@@ -36819,28 +36908,17 @@ var SessionWorktreeManager = class {
|
|
|
36819
36908
|
push: params.push
|
|
36820
36909
|
});
|
|
36821
36910
|
}
|
|
36822
|
-
resolveCommitTargets(sessionId) {
|
|
36823
|
-
const paths = this.sessionRepoCheckoutPaths.get(sessionId);
|
|
36824
|
-
if (paths?.length) return paths;
|
|
36825
|
-
const disc = this.tryDiscoverFromDisk(sessionId);
|
|
36826
|
-
if (disc?.repoCheckoutPaths.length) {
|
|
36827
|
-
this.rememberSessionWorktrees(sessionId, disc);
|
|
36828
|
-
return disc.repoCheckoutPaths;
|
|
36829
|
-
}
|
|
36830
|
-
return [getBridgeRoot()];
|
|
36831
|
-
}
|
|
36832
36911
|
async getSessionWorkingTreeStatus(sessionId) {
|
|
36833
|
-
return aggregateSessionPathsWorkingTreeStatus(
|
|
36912
|
+
return aggregateSessionPathsWorkingTreeStatus(
|
|
36913
|
+
resolveCommitTargets(sessionId, this.cache, (sid) => this.discover(sid))
|
|
36914
|
+
);
|
|
36834
36915
|
}
|
|
36835
|
-
/** Per-repo changed files vs HEAD (or a single commit vs parent) for the same git roots used for commit/push. */
|
|
36836
36916
|
async getSessionWorkingTreeChangeDetails(sessionId, opts) {
|
|
36837
|
-
const targets = this.
|
|
36838
|
-
const sessionWorkingTreeRelRoot = this.sessionWorkingTreeRelRootBySession.get(sessionId) ?? null;
|
|
36839
|
-
const legacyNested = this.isLegacyNestedLayout(sessionId);
|
|
36917
|
+
const targets = resolveCommitTargets(sessionId, this.cache, (sid) => this.discover(sid));
|
|
36840
36918
|
return getWorkingTreeChangeRepoDetails({
|
|
36841
36919
|
commitTargetPaths: targets,
|
|
36842
|
-
sessionWorktreeRootPath:
|
|
36843
|
-
legacyRepoNestedSessionLayout:
|
|
36920
|
+
sessionWorktreeRootPath: this.cache.getWorkingTreeRelRoot(sessionId),
|
|
36921
|
+
legacyRepoNestedSessionLayout: this.cache.isLegacyNestedLayout(sessionId),
|
|
36844
36922
|
repoFilterRelPath: opts?.repoRelPath?.trim() ? opts.repoRelPath.trim() : null,
|
|
36845
36923
|
basis: opts?.basis,
|
|
36846
36924
|
recentCommitsLimit: opts?.recentCommitsLimit
|
|
@@ -36848,7 +36926,9 @@ var SessionWorktreeManager = class {
|
|
|
36848
36926
|
}
|
|
36849
36927
|
async pushSessionUpstream(sessionId) {
|
|
36850
36928
|
try {
|
|
36851
|
-
await pushAheadOfUpstreamForPaths(
|
|
36929
|
+
await pushAheadOfUpstreamForPaths(
|
|
36930
|
+
resolveCommitTargets(sessionId, this.cache, (sid) => this.discover(sid))
|
|
36931
|
+
);
|
|
36852
36932
|
return { ok: true };
|
|
36853
36933
|
} catch (e) {
|
|
36854
36934
|
const err = e instanceof Error ? e.message : String(e);
|
|
@@ -36856,27 +36936,31 @@ var SessionWorktreeManager = class {
|
|
|
36856
36936
|
}
|
|
36857
36937
|
}
|
|
36858
36938
|
};
|
|
36939
|
+
|
|
36940
|
+
// src/worktrees/manager/default-worktrees-root-path.ts
|
|
36941
|
+
import * as path28 from "node:path";
|
|
36942
|
+
import os8 from "node:os";
|
|
36859
36943
|
function defaultWorktreesRootPath() {
|
|
36860
|
-
return
|
|
36944
|
+
return path28.join(os8.homedir(), ".buildautomaton", "worktrees");
|
|
36861
36945
|
}
|
|
36862
36946
|
|
|
36863
36947
|
// src/files/watch-file-index.ts
|
|
36864
36948
|
import { watch } from "node:fs";
|
|
36865
|
-
import
|
|
36949
|
+
import path33 from "node:path";
|
|
36866
36950
|
|
|
36867
36951
|
// src/files/index/paths.ts
|
|
36868
|
-
import
|
|
36952
|
+
import path29 from "node:path";
|
|
36869
36953
|
import crypto2 from "node:crypto";
|
|
36870
36954
|
function getCwdHashForFileIndex(resolvedCwd) {
|
|
36871
|
-
return crypto2.createHash("sha256").update(
|
|
36955
|
+
return crypto2.createHash("sha256").update(path29.resolve(resolvedCwd)).digest("hex").slice(0, INDEX_HASH_LEN);
|
|
36872
36956
|
}
|
|
36873
36957
|
|
|
36874
36958
|
// src/files/index/build-file-index.ts
|
|
36875
|
-
import
|
|
36959
|
+
import path31 from "node:path";
|
|
36876
36960
|
|
|
36877
36961
|
// src/files/index/walk-workspace-tree.ts
|
|
36878
36962
|
import fs25 from "node:fs";
|
|
36879
|
-
import
|
|
36963
|
+
import path30 from "node:path";
|
|
36880
36964
|
var DEPENDENCY_INSTALL_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
36881
36965
|
"node_modules",
|
|
36882
36966
|
"bower_components",
|
|
@@ -36905,18 +36989,18 @@ async function walkWorkspaceTreeAsync(dir, baseDir, onFile, state) {
|
|
|
36905
36989
|
if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();
|
|
36906
36990
|
}
|
|
36907
36991
|
state.n++;
|
|
36908
|
-
const full =
|
|
36992
|
+
const full = path30.join(dir, name);
|
|
36909
36993
|
let stat3;
|
|
36910
36994
|
try {
|
|
36911
36995
|
stat3 = await fs25.promises.stat(full);
|
|
36912
36996
|
} catch {
|
|
36913
36997
|
continue;
|
|
36914
36998
|
}
|
|
36915
|
-
const
|
|
36999
|
+
const relative6 = path30.relative(baseDir, full).replace(/\\/g, "/");
|
|
36916
37000
|
if (stat3.isDirectory()) {
|
|
36917
37001
|
await walkWorkspaceTreeAsync(full, baseDir, onFile, state);
|
|
36918
37002
|
} else if (stat3.isFile()) {
|
|
36919
|
-
onFile(
|
|
37003
|
+
onFile(relative6);
|
|
36920
37004
|
}
|
|
36921
37005
|
}
|
|
36922
37006
|
}
|
|
@@ -37014,7 +37098,7 @@ async function collectWorkspacePathsAsync(resolved) {
|
|
|
37014
37098
|
}
|
|
37015
37099
|
async function buildFileIndexAsync(cwd) {
|
|
37016
37100
|
return withFileIndexSqliteLock(async () => {
|
|
37017
|
-
const resolved =
|
|
37101
|
+
const resolved = path31.resolve(cwd);
|
|
37018
37102
|
await yieldToEventLoop();
|
|
37019
37103
|
assertNotShutdown();
|
|
37020
37104
|
const paths = await collectWorkspacePathsAsync(resolved);
|
|
@@ -37026,7 +37110,7 @@ async function buildFileIndexAsync(cwd) {
|
|
|
37026
37110
|
}
|
|
37027
37111
|
|
|
37028
37112
|
// src/files/index/ensure-file-index.ts
|
|
37029
|
-
import
|
|
37113
|
+
import path32 from "node:path";
|
|
37030
37114
|
|
|
37031
37115
|
// src/files/index/search-file-index.ts
|
|
37032
37116
|
function escapeLikePattern(fragment) {
|
|
@@ -37078,7 +37162,7 @@ async function searchBridgeFilePathsAsync(resolvedCwd, query, limit = 100) {
|
|
|
37078
37162
|
|
|
37079
37163
|
// src/files/index/ensure-file-index.ts
|
|
37080
37164
|
async function ensureFileIndexAsync(cwd) {
|
|
37081
|
-
const resolved =
|
|
37165
|
+
const resolved = path32.resolve(cwd);
|
|
37082
37166
|
if (await bridgeFileIndexIsPopulated(resolved)) {
|
|
37083
37167
|
return { fromCache: true, pathCount: await bridgeFileIndexPathCount(resolved) };
|
|
37084
37168
|
}
|
|
@@ -37122,7 +37206,7 @@ function createFsWatcher(resolved, schedule) {
|
|
|
37122
37206
|
}
|
|
37123
37207
|
}
|
|
37124
37208
|
function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
37125
|
-
const resolved =
|
|
37209
|
+
const resolved = path33.resolve(cwd);
|
|
37126
37210
|
void buildFileIndexAsync(resolved).catch((e) => {
|
|
37127
37211
|
if (e instanceof CliSqliteInterrupted) return;
|
|
37128
37212
|
console.error("[file-index] Initial index build failed:", e);
|
|
@@ -37152,7 +37236,7 @@ function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
|
37152
37236
|
}
|
|
37153
37237
|
|
|
37154
37238
|
// src/connection/create-bridge-connection.ts
|
|
37155
|
-
import * as
|
|
37239
|
+
import * as path44 from "node:path";
|
|
37156
37240
|
|
|
37157
37241
|
// src/dev-servers/manager/dev-server-manager.ts
|
|
37158
37242
|
import { rm as rm2 } from "node:fs/promises";
|
|
@@ -37174,15 +37258,15 @@ function sendDevServerStatus(getWs, serverId, status, options) {
|
|
|
37174
37258
|
|
|
37175
37259
|
// src/dev-servers/process/terminate-child-process.ts
|
|
37176
37260
|
async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
|
|
37177
|
-
const exited = new Promise((
|
|
37178
|
-
proc.once("exit", () =>
|
|
37261
|
+
const exited = new Promise((resolve22) => {
|
|
37262
|
+
proc.once("exit", () => resolve22());
|
|
37179
37263
|
});
|
|
37180
37264
|
log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
|
|
37181
37265
|
try {
|
|
37182
37266
|
proc.kill("SIGTERM");
|
|
37183
37267
|
} catch {
|
|
37184
37268
|
}
|
|
37185
|
-
await Promise.race([exited, new Promise((
|
|
37269
|
+
await Promise.race([exited, new Promise((resolve22) => setTimeout(resolve22, graceMs))]);
|
|
37186
37270
|
}
|
|
37187
37271
|
function forceKillChild(proc, log2, shortId, graceMs) {
|
|
37188
37272
|
log2(
|
|
@@ -37462,10 +37546,10 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
|
37462
37546
|
import { spawn as spawn7 } from "node:child_process";
|
|
37463
37547
|
import fs29 from "node:fs";
|
|
37464
37548
|
import { tmpdir } from "node:os";
|
|
37465
|
-
import
|
|
37549
|
+
import path34 from "node:path";
|
|
37466
37550
|
function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
37467
|
-
const tmpRoot = fs29.mkdtempSync(
|
|
37468
|
-
const logPath =
|
|
37551
|
+
const tmpRoot = fs29.mkdtempSync(path34.join(tmpdir(), "ba-devsrv-log-"));
|
|
37552
|
+
const logPath = path34.join(tmpRoot, "combined.log");
|
|
37469
37553
|
let logFd;
|
|
37470
37554
|
try {
|
|
37471
37555
|
logFd = fs29.openSync(logPath, "a");
|
|
@@ -37509,15 +37593,15 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
37509
37593
|
import { spawn as spawn8 } from "node:child_process";
|
|
37510
37594
|
import fs30 from "node:fs";
|
|
37511
37595
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
37512
|
-
import
|
|
37596
|
+
import path35 from "node:path";
|
|
37513
37597
|
function shSingleQuote(s) {
|
|
37514
37598
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
37515
37599
|
}
|
|
37516
37600
|
function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
|
|
37517
|
-
const tmpRoot = fs30.mkdtempSync(
|
|
37518
|
-
const logPath =
|
|
37519
|
-
const innerPath =
|
|
37520
|
-
const runnerPath =
|
|
37601
|
+
const tmpRoot = fs30.mkdtempSync(path35.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
37602
|
+
const logPath = path35.join(tmpRoot, "combined.log");
|
|
37603
|
+
const innerPath = path35.join(tmpRoot, "_cmd.sh");
|
|
37604
|
+
const runnerPath = path35.join(tmpRoot, "_run.sh");
|
|
37521
37605
|
try {
|
|
37522
37606
|
fs30.writeFileSync(innerPath, `#!/bin/sh
|
|
37523
37607
|
${command}
|
|
@@ -37548,9 +37632,9 @@ cd ${shSingleQuote(cwd)}
|
|
|
37548
37632
|
}
|
|
37549
37633
|
}
|
|
37550
37634
|
function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
|
|
37551
|
-
const tmpRoot = fs30.mkdtempSync(
|
|
37552
|
-
const logPath =
|
|
37553
|
-
const runnerPath =
|
|
37635
|
+
const tmpRoot = fs30.mkdtempSync(path35.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
37636
|
+
const logPath = path35.join(tmpRoot, "combined.log");
|
|
37637
|
+
const runnerPath = path35.join(tmpRoot, "_run.bat");
|
|
37554
37638
|
const q = (p) => `"${p.replace(/"/g, '""')}"`;
|
|
37555
37639
|
const com = process.env.ComSpec || "cmd.exe";
|
|
37556
37640
|
try {
|
|
@@ -38063,7 +38147,7 @@ async function proxyToLocal(request) {
|
|
|
38063
38147
|
};
|
|
38064
38148
|
const maxAttempts = isIdempotentProxyMethod(request.method) ? LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS.length + 1 : 1;
|
|
38065
38149
|
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
38066
|
-
const once = await new Promise((
|
|
38150
|
+
const once = await new Promise((resolve22) => {
|
|
38067
38151
|
const req = mod.request(opts, (res) => {
|
|
38068
38152
|
const chunks = [];
|
|
38069
38153
|
res.on("data", (c) => chunks.push(c));
|
|
@@ -38074,7 +38158,7 @@ async function proxyToLocal(request) {
|
|
|
38074
38158
|
if (typeof v === "string") headers[k] = v;
|
|
38075
38159
|
else if (Array.isArray(v) && v[0]) headers[k] = v[0];
|
|
38076
38160
|
}
|
|
38077
|
-
|
|
38161
|
+
resolve22({
|
|
38078
38162
|
id: request.id,
|
|
38079
38163
|
statusCode: res.statusCode ?? 0,
|
|
38080
38164
|
headers,
|
|
@@ -38083,7 +38167,7 @@ async function proxyToLocal(request) {
|
|
|
38083
38167
|
});
|
|
38084
38168
|
});
|
|
38085
38169
|
req.on("error", (err) => {
|
|
38086
|
-
|
|
38170
|
+
resolve22({
|
|
38087
38171
|
id: request.id,
|
|
38088
38172
|
statusCode: 0,
|
|
38089
38173
|
headers: {},
|
|
@@ -38492,13 +38576,13 @@ function createOnBridgeIdentified(opts) {
|
|
|
38492
38576
|
|
|
38493
38577
|
// src/skills/discover-local-agent-skills.ts
|
|
38494
38578
|
import fs31 from "node:fs";
|
|
38495
|
-
import
|
|
38579
|
+
import path36 from "node:path";
|
|
38496
38580
|
var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
|
|
38497
38581
|
function discoverLocalSkills(cwd) {
|
|
38498
38582
|
const out = [];
|
|
38499
38583
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
38500
38584
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
38501
|
-
const base =
|
|
38585
|
+
const base = path36.join(cwd, rel);
|
|
38502
38586
|
if (!fs31.existsSync(base) || !fs31.statSync(base).isDirectory()) continue;
|
|
38503
38587
|
let entries = [];
|
|
38504
38588
|
try {
|
|
@@ -38507,13 +38591,13 @@ function discoverLocalSkills(cwd) {
|
|
|
38507
38591
|
continue;
|
|
38508
38592
|
}
|
|
38509
38593
|
for (const name of entries) {
|
|
38510
|
-
const dir =
|
|
38594
|
+
const dir = path36.join(base, name);
|
|
38511
38595
|
try {
|
|
38512
38596
|
if (!fs31.statSync(dir).isDirectory()) continue;
|
|
38513
38597
|
} catch {
|
|
38514
38598
|
continue;
|
|
38515
38599
|
}
|
|
38516
|
-
const skillMd =
|
|
38600
|
+
const skillMd = path36.join(dir, "SKILL.md");
|
|
38517
38601
|
if (!fs31.existsSync(skillMd)) continue;
|
|
38518
38602
|
const key = `${rel}/${name}`;
|
|
38519
38603
|
if (seenKeys.has(key)) continue;
|
|
@@ -38526,7 +38610,7 @@ function discoverLocalSkills(cwd) {
|
|
|
38526
38610
|
function discoverSkillLayoutRoots(cwd) {
|
|
38527
38611
|
const roots = [];
|
|
38528
38612
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
38529
|
-
const base =
|
|
38613
|
+
const base = path36.join(cwd, rel);
|
|
38530
38614
|
if (!fs31.existsSync(base) || !fs31.statSync(base).isDirectory()) continue;
|
|
38531
38615
|
let entries = [];
|
|
38532
38616
|
try {
|
|
@@ -38536,13 +38620,13 @@ function discoverSkillLayoutRoots(cwd) {
|
|
|
38536
38620
|
}
|
|
38537
38621
|
const skills2 = [];
|
|
38538
38622
|
for (const name of entries) {
|
|
38539
|
-
const dir =
|
|
38623
|
+
const dir = path36.join(base, name);
|
|
38540
38624
|
try {
|
|
38541
38625
|
if (!fs31.statSync(dir).isDirectory()) continue;
|
|
38542
38626
|
} catch {
|
|
38543
38627
|
continue;
|
|
38544
38628
|
}
|
|
38545
|
-
if (!fs31.existsSync(
|
|
38629
|
+
if (!fs31.existsSync(path36.join(dir, "SKILL.md"))) continue;
|
|
38546
38630
|
const relPath = `${rel}/${name}`.replace(/\\/g, "/");
|
|
38547
38631
|
skills2.push({ name, relPath });
|
|
38548
38632
|
}
|
|
@@ -38665,7 +38749,9 @@ var API_TO_BRIDGE_MESSAGE_TYPES = [
|
|
|
38665
38749
|
"file_browser_search",
|
|
38666
38750
|
"skill_layout_request",
|
|
38667
38751
|
"install_skills",
|
|
38668
|
-
"refresh_local_skills"
|
|
38752
|
+
"refresh_local_skills",
|
|
38753
|
+
"bridge_git_context_request",
|
|
38754
|
+
"list_repo_branches_request"
|
|
38669
38755
|
];
|
|
38670
38756
|
var API_TO_BRIDGE_TYPE_SET = new Set(API_TO_BRIDGE_MESSAGE_TYPES);
|
|
38671
38757
|
function parseApiToBridgeMessage(data, log2) {
|
|
@@ -38749,9 +38835,6 @@ var handleAgentConfigMessage = (msg, deps) => {
|
|
|
38749
38835
|
handleBridgeAgentConfig(msg, deps);
|
|
38750
38836
|
};
|
|
38751
38837
|
|
|
38752
|
-
// src/prompt-turn-queue/runner.ts
|
|
38753
|
-
import fs32 from "node:fs";
|
|
38754
|
-
|
|
38755
38838
|
// src/prompt-turn-queue/client-report.ts
|
|
38756
38839
|
function sendPromptQueueClientReport(ws, queues) {
|
|
38757
38840
|
if (!ws) return false;
|
|
@@ -38821,8 +38904,36 @@ async function mergeServerQueueSnapshot(queueKey, serverTurns) {
|
|
|
38821
38904
|
return { queueKey, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), turns };
|
|
38822
38905
|
}
|
|
38823
38906
|
|
|
38824
|
-
// src/prompt-turn-queue/runner.ts
|
|
38825
|
-
|
|
38907
|
+
// src/prompt-turn-queue/runner/dispatch-local-prompt.ts
|
|
38908
|
+
function dispatchLocalPrompt(next, deps) {
|
|
38909
|
+
const pl = next.payload;
|
|
38910
|
+
const rawParent = pl["sessionParent"];
|
|
38911
|
+
const sessionParent = rawParent === "bridge_root" || rawParent === "worktrees_root" ? rawParent : void 0;
|
|
38912
|
+
const rawParentPath = pl["sessionParentPath"];
|
|
38913
|
+
const sessionParentPath = typeof rawParentPath === "string" && rawParentPath.trim() !== "" ? rawParentPath.trim() : void 0;
|
|
38914
|
+
const rawBaseBranches = pl["worktreeBaseBranches"];
|
|
38915
|
+
const worktreeBaseBranches = rawBaseBranches != null && typeof rawBaseBranches === "object" && !Array.isArray(rawBaseBranches) ? rawBaseBranches : void 0;
|
|
38916
|
+
const msg = {
|
|
38917
|
+
type: "prompt",
|
|
38918
|
+
sessionId: next.sessionId,
|
|
38919
|
+
runId: next.turnId,
|
|
38920
|
+
prompt: pl.prompt,
|
|
38921
|
+
mode: typeof pl.mode === "string" ? pl.mode : "agent",
|
|
38922
|
+
isNewSession: pl.isNewSession === true,
|
|
38923
|
+
...sessionParent ? { sessionParent } : {},
|
|
38924
|
+
...sessionParentPath ? { sessionParentPath } : {},
|
|
38925
|
+
...worktreeBaseBranches && Object.keys(worktreeBaseBranches).length > 0 ? { worktreeBaseBranches } : {},
|
|
38926
|
+
...typeof pl.followUpCatalogPromptId === "string" ? { followUpCatalogPromptId: pl.followUpCatalogPromptId } : {},
|
|
38927
|
+
...Array.isArray(pl.sessionChangeSummaryFilePaths) ? { sessionChangeSummaryFilePaths: pl.sessionChangeSummaryFilePaths } : {},
|
|
38928
|
+
...Array.isArray(pl.sessionChangeSummaryFileSnapshots) ? { sessionChangeSummaryFileSnapshots: pl.sessionChangeSummaryFileSnapshots } : {},
|
|
38929
|
+
...typeof pl.agentType === "string" && pl.agentType.trim() ? { agentType: pl.agentType.trim() } : {},
|
|
38930
|
+
...pl.agentConfig != null && typeof pl.agentConfig === "object" && !Array.isArray(pl.agentConfig) && Object.keys(pl.agentConfig).length > 0 ? { agentConfig: pl.agentConfig } : {},
|
|
38931
|
+
...Array.isArray(pl.attachments) && pl.attachments.length > 0 ? { attachments: pl.attachments } : {}
|
|
38932
|
+
};
|
|
38933
|
+
handleBridgePrompt(msg, deps);
|
|
38934
|
+
}
|
|
38935
|
+
|
|
38936
|
+
// src/prompt-turn-queue/runner/queue-selection.ts
|
|
38826
38937
|
function isRunnableServerState(s) {
|
|
38827
38938
|
return s === "queued" || s === "requeued" || s === "requeued_with_revert";
|
|
38828
38939
|
}
|
|
@@ -38841,6 +38952,28 @@ function pickNextRunnableTurn(turns) {
|
|
|
38841
38952
|
function hasRunningTurn(turns) {
|
|
38842
38953
|
return turns.some((t) => t.lastClientState === "running");
|
|
38843
38954
|
}
|
|
38955
|
+
|
|
38956
|
+
// src/prompt-turn-queue/runner/run-id-queue-key-map.ts
|
|
38957
|
+
var runIdToQueueKey = /* @__PURE__ */ new Map();
|
|
38958
|
+
function getRunIdQueueKey(runId) {
|
|
38959
|
+
return runIdToQueueKey.get(runId);
|
|
38960
|
+
}
|
|
38961
|
+
function setRunIdQueueKey(runId, queueKey) {
|
|
38962
|
+
runIdToQueueKey.set(runId, queueKey);
|
|
38963
|
+
}
|
|
38964
|
+
function deleteRunIdQueueKey(runId) {
|
|
38965
|
+
const queueKey = runIdToQueueKey.get(runId);
|
|
38966
|
+
runIdToQueueKey.delete(runId);
|
|
38967
|
+
return queueKey;
|
|
38968
|
+
}
|
|
38969
|
+
function syncRunningTurnQueueKeys(turns, queueKey) {
|
|
38970
|
+
for (const running of turns.filter((t) => t.lastClientState === "running")) {
|
|
38971
|
+
runIdToQueueKey.set(running.turnId, queueKey);
|
|
38972
|
+
}
|
|
38973
|
+
}
|
|
38974
|
+
|
|
38975
|
+
// src/prompt-turn-queue/runner/run-local-revert-before-queued-prompt.ts
|
|
38976
|
+
import fs32 from "node:fs";
|
|
38844
38977
|
async function runLocalRevertBeforeQueuedPrompt(next, deps) {
|
|
38845
38978
|
if (next.serverState !== "requeued_with_revert") return true;
|
|
38846
38979
|
const sid = next.sessionId;
|
|
@@ -38862,30 +38995,23 @@ async function runLocalRevertBeforeQueuedPrompt(next, deps) {
|
|
|
38862
38995
|
}
|
|
38863
38996
|
return res.ok;
|
|
38864
38997
|
}
|
|
38865
|
-
|
|
38866
|
-
|
|
38867
|
-
|
|
38868
|
-
|
|
38869
|
-
const
|
|
38870
|
-
|
|
38871
|
-
const
|
|
38872
|
-
|
|
38873
|
-
|
|
38874
|
-
|
|
38875
|
-
|
|
38876
|
-
|
|
38877
|
-
|
|
38878
|
-
|
|
38879
|
-
...sessionParentPath ? { sessionParentPath } : {},
|
|
38880
|
-
...typeof pl.followUpCatalogPromptId === "string" ? { followUpCatalogPromptId: pl.followUpCatalogPromptId } : {},
|
|
38881
|
-
...Array.isArray(pl.sessionChangeSummaryFilePaths) ? { sessionChangeSummaryFilePaths: pl.sessionChangeSummaryFilePaths } : {},
|
|
38882
|
-
...Array.isArray(pl.sessionChangeSummaryFileSnapshots) ? { sessionChangeSummaryFileSnapshots: pl.sessionChangeSummaryFileSnapshots } : {},
|
|
38883
|
-
...typeof pl.agentType === "string" && pl.agentType.trim() ? { agentType: pl.agentType.trim() } : {},
|
|
38884
|
-
...pl.agentConfig != null && typeof pl.agentConfig === "object" && !Array.isArray(pl.agentConfig) && Object.keys(pl.agentConfig).length > 0 ? { agentConfig: pl.agentConfig } : {},
|
|
38885
|
-
...Array.isArray(pl.attachments) && pl.attachments.length > 0 ? { attachments: pl.attachments } : {}
|
|
38886
|
-
};
|
|
38887
|
-
handleBridgePrompt(msg, deps);
|
|
38998
|
+
|
|
38999
|
+
// src/prompt-turn-queue/runner/finalize-prompt-turn-on-bridge.ts
|
|
39000
|
+
async function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
|
|
39001
|
+
if (!runId) return false;
|
|
39002
|
+
const queueKey = deleteRunIdQueueKey(runId);
|
|
39003
|
+
if (!queueKey) return false;
|
|
39004
|
+
const f = await readPersistedQueue(queueKey);
|
|
39005
|
+
if (!f) return false;
|
|
39006
|
+
const t = f.turns.find((x) => x.turnId === runId);
|
|
39007
|
+
if (!t) return false;
|
|
39008
|
+
t.lastClientState = opts?.terminalClientState ?? (success2 ? "stopped" : "failed");
|
|
39009
|
+
await writePersistedQueue(f);
|
|
39010
|
+
sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId, clientState: t.lastClientState }] });
|
|
39011
|
+
return true;
|
|
38888
39012
|
}
|
|
39013
|
+
|
|
39014
|
+
// src/prompt-turn-queue/runner/apply-prompt-queue-state-from-server.ts
|
|
38889
39015
|
async function applyPromptQueueStateFromServer(msg, deps) {
|
|
38890
39016
|
const raw = msg.queues;
|
|
38891
39017
|
if (!raw || typeof raw !== "object") return;
|
|
@@ -38899,9 +39025,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38899
39025
|
if (!Array.isArray(serverTurns)) continue;
|
|
38900
39026
|
const file2 = await readPersistedQueue(queueKey);
|
|
38901
39027
|
if (!file2) continue;
|
|
38902
|
-
|
|
38903
|
-
runIdToQueueKey.set(running.turnId, queueKey);
|
|
38904
|
-
}
|
|
39028
|
+
syncRunningTurnQueueKeys(file2.turns, queueKey);
|
|
38905
39029
|
}
|
|
38906
39030
|
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
38907
39031
|
if (!Array.isArray(serverTurns)) continue;
|
|
@@ -38946,7 +39070,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38946
39070
|
}
|
|
38947
39071
|
next.lastClientState = "running";
|
|
38948
39072
|
await writePersistedQueue(file2);
|
|
38949
|
-
|
|
39073
|
+
setRunIdQueueKey(next.turnId, queueKey);
|
|
38950
39074
|
startedThisTick.add(next.turnId);
|
|
38951
39075
|
report[queueKey] = [{ turnId: next.turnId, clientState: "running" }];
|
|
38952
39076
|
}
|
|
@@ -38959,24 +39083,10 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
38959
39083
|
if (!file2) continue;
|
|
38960
39084
|
const running = file2.turns.find((t) => t.lastClientState === "running");
|
|
38961
39085
|
if (!running || !startedThisTick.has(running.turnId)) continue;
|
|
38962
|
-
if (
|
|
39086
|
+
if (getRunIdQueueKey(running.turnId) !== queueKey) continue;
|
|
38963
39087
|
dispatchLocalPrompt(running, deps);
|
|
38964
39088
|
}
|
|
38965
39089
|
}
|
|
38966
|
-
async function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
|
|
38967
|
-
if (!runId) return false;
|
|
38968
|
-
const queueKey = runIdToQueueKey.get(runId);
|
|
38969
|
-
runIdToQueueKey.delete(runId);
|
|
38970
|
-
if (!queueKey) return false;
|
|
38971
|
-
const f = await readPersistedQueue(queueKey);
|
|
38972
|
-
if (!f) return false;
|
|
38973
|
-
const t = f.turns.find((x) => x.turnId === runId);
|
|
38974
|
-
if (!t) return false;
|
|
38975
|
-
t.lastClientState = opts?.terminalClientState ?? (success2 ? "stopped" : "failed");
|
|
38976
|
-
await writePersistedQueue(f);
|
|
38977
|
-
sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId, clientState: t.lastClientState }] });
|
|
38978
|
-
return true;
|
|
38979
|
-
}
|
|
38980
39090
|
|
|
38981
39091
|
// src/agents/acp/from-bridge/bridge-prompt-wiring.ts
|
|
38982
39092
|
function createBridgePromptSenders(deps, getWs) {
|
|
@@ -39023,6 +39133,91 @@ function createBridgePromptSenders(deps, getWs) {
|
|
|
39023
39133
|
return { sendBridgeMessage, sendResult: sendResult2, sendSessionUpdate };
|
|
39024
39134
|
}
|
|
39025
39135
|
|
|
39136
|
+
// src/agents/acp/from-bridge/handle-bridge-prompt/parse-bridge-attachments.ts
|
|
39137
|
+
function parseBridgeAttachments(msg) {
|
|
39138
|
+
const raw = msg.attachments;
|
|
39139
|
+
if (!Array.isArray(raw)) return [];
|
|
39140
|
+
const out = [];
|
|
39141
|
+
for (const x of raw) {
|
|
39142
|
+
if (x === null || typeof x !== "object" || Array.isArray(x)) continue;
|
|
39143
|
+
const o = x;
|
|
39144
|
+
const id = typeof o.attachmentId === "string" ? o.attachmentId.trim() : "";
|
|
39145
|
+
if (!id) continue;
|
|
39146
|
+
const mt = typeof o.mimeType === "string" && o.mimeType.trim() ? o.mimeType.trim() : "application/octet-stream";
|
|
39147
|
+
out.push({ attachmentId: id, mimeType: mt });
|
|
39148
|
+
}
|
|
39149
|
+
return out;
|
|
39150
|
+
}
|
|
39151
|
+
|
|
39152
|
+
// src/agents/acp/from-bridge/handle-bridge-prompt/parse-worktree-base-branches.ts
|
|
39153
|
+
function parseWorktreeBaseBranches(msg) {
|
|
39154
|
+
const raw = msg.worktreeBaseBranches;
|
|
39155
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
39156
|
+
const out = {};
|
|
39157
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
39158
|
+
if (typeof k !== "string" || typeof v !== "string") continue;
|
|
39159
|
+
const rel = k.trim();
|
|
39160
|
+
const branch = v.trim();
|
|
39161
|
+
if (rel && branch) out[rel] = branch;
|
|
39162
|
+
}
|
|
39163
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
39164
|
+
}
|
|
39165
|
+
|
|
39166
|
+
// src/agents/acp/change-summary/decrypt-change-summary-file-input.ts
|
|
39167
|
+
function decryptChangeSummaryFileInput(row, e2ee) {
|
|
39168
|
+
if (!e2ee) return row;
|
|
39169
|
+
for (const field of ["path", "patchContent", "oldText", "newText"]) {
|
|
39170
|
+
const raw = row[field];
|
|
39171
|
+
if (typeof raw !== "string" || raw.trim() === "") continue;
|
|
39172
|
+
let o;
|
|
39173
|
+
try {
|
|
39174
|
+
o = JSON.parse(raw);
|
|
39175
|
+
} catch {
|
|
39176
|
+
continue;
|
|
39177
|
+
}
|
|
39178
|
+
if (!isE2eeEnvelope(o.ee)) continue;
|
|
39179
|
+
try {
|
|
39180
|
+
const d = e2ee.decryptMessage(o);
|
|
39181
|
+
const out = {
|
|
39182
|
+
path: typeof d.path === "string" ? d.path : row.path
|
|
39183
|
+
};
|
|
39184
|
+
if (d.directoryRemoved === true) out.directoryRemoved = true;
|
|
39185
|
+
else if (row.directoryRemoved === true) out.directoryRemoved = true;
|
|
39186
|
+
if (typeof d.patchContent === "string") out.patchContent = d.patchContent;
|
|
39187
|
+
else if (typeof row.patchContent === "string" && row.patchContent !== raw) out.patchContent = row.patchContent;
|
|
39188
|
+
if (typeof d.oldText === "string") out.oldText = d.oldText;
|
|
39189
|
+
else if (typeof row.oldText === "string") out.oldText = row.oldText;
|
|
39190
|
+
if (typeof d.newText === "string") out.newText = d.newText;
|
|
39191
|
+
else if (typeof row.newText === "string") out.newText = row.newText;
|
|
39192
|
+
return out;
|
|
39193
|
+
} catch {
|
|
39194
|
+
return row;
|
|
39195
|
+
}
|
|
39196
|
+
}
|
|
39197
|
+
return row;
|
|
39198
|
+
}
|
|
39199
|
+
|
|
39200
|
+
// src/agents/acp/change-summary/resolve-change-summary-prompt-for-agent.ts
|
|
39201
|
+
function hasSummarizePayload(f) {
|
|
39202
|
+
return f.directoryRemoved === true || f.patchContent != null && f.patchContent.trim() !== "" || f.oldText != null && f.oldText.trim() !== "" || f.newText != null && f.newText.trim() !== "";
|
|
39203
|
+
}
|
|
39204
|
+
function resolveChangeSummaryPromptForAgent(params) {
|
|
39205
|
+
const isBuiltin = params.followUpCatalogPromptId === BUILTIN_SESSION_CHANGE_SUMMARY_FOLLOW_UP_CATALOG_PROMPT_ID;
|
|
39206
|
+
const snaps = params.sessionChangeSummaryFileSnapshots;
|
|
39207
|
+
if (!isBuiltin || !snaps || snaps.length === 0) {
|
|
39208
|
+
return { promptText: params.bridgePromptText, sessionChangeSummaryFilePaths: void 0 };
|
|
39209
|
+
}
|
|
39210
|
+
const decrypted = dedupeSessionFileChangesByPath(snaps.map((row) => decryptChangeSummaryFileInput(row, params.e2ee)));
|
|
39211
|
+
const withPayload = decrypted.filter(hasSummarizePayload);
|
|
39212
|
+
if (withPayload.length === 0) {
|
|
39213
|
+
return { promptText: params.bridgePromptText, sessionChangeSummaryFilePaths: void 0 };
|
|
39214
|
+
}
|
|
39215
|
+
return {
|
|
39216
|
+
promptText: buildSessionChangeSummaryPrompt(withPayload),
|
|
39217
|
+
sessionChangeSummaryFilePaths: withPayload.map((f) => f.path)
|
|
39218
|
+
};
|
|
39219
|
+
}
|
|
39220
|
+
|
|
39026
39221
|
// src/agents/acp/from-bridge/bridge-prompt-preamble.ts
|
|
39027
39222
|
import { execFile as execFile8 } from "node:child_process";
|
|
39028
39223
|
import { promisify as promisify8 } from "node:util";
|
|
@@ -39075,9 +39270,9 @@ function parseChangeSummarySnapshots(raw) {
|
|
|
39075
39270
|
for (const item of raw) {
|
|
39076
39271
|
if (!item || typeof item !== "object") continue;
|
|
39077
39272
|
const o = item;
|
|
39078
|
-
const
|
|
39079
|
-
if (!
|
|
39080
|
-
const row = { path:
|
|
39273
|
+
const path46 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
|
|
39274
|
+
if (!path46) continue;
|
|
39275
|
+
const row = { path: path46 };
|
|
39081
39276
|
if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
|
|
39082
39277
|
if (typeof o.oldText === "string") row.oldText = o.oldText;
|
|
39083
39278
|
if (typeof o.newText === "string") row.newText = o.newText;
|
|
@@ -39094,76 +39289,73 @@ function parseFollowUpFieldsFromPromptMessage(msg) {
|
|
|
39094
39289
|
return { followUpCatalogPromptId, sessionChangeSummaryFilePaths, sessionChangeSummaryFileSnapshots };
|
|
39095
39290
|
}
|
|
39096
39291
|
|
|
39097
|
-
// src/agents/acp/
|
|
39098
|
-
function
|
|
39099
|
-
|
|
39100
|
-
|
|
39101
|
-
|
|
39102
|
-
|
|
39103
|
-
|
|
39104
|
-
|
|
39105
|
-
|
|
39106
|
-
|
|
39107
|
-
|
|
39108
|
-
|
|
39109
|
-
|
|
39110
|
-
|
|
39111
|
-
|
|
39112
|
-
|
|
39113
|
-
|
|
39114
|
-
|
|
39115
|
-
|
|
39116
|
-
|
|
39117
|
-
|
|
39118
|
-
|
|
39119
|
-
|
|
39120
|
-
|
|
39121
|
-
|
|
39122
|
-
|
|
39123
|
-
|
|
39124
|
-
|
|
39125
|
-
|
|
39126
|
-
|
|
39127
|
-
|
|
39128
|
-
|
|
39129
|
-
}
|
|
39130
|
-
|
|
39131
|
-
|
|
39132
|
-
|
|
39133
|
-
|
|
39134
|
-
|
|
39135
|
-
|
|
39136
|
-
|
|
39137
|
-
|
|
39138
|
-
|
|
39139
|
-
|
|
39140
|
-
}
|
|
39141
|
-
const decrypted = dedupeSessionFileChangesByPath(snaps.map((row) => decryptChangeSummaryFileInput(row, params.e2ee)));
|
|
39142
|
-
const withPayload = decrypted.filter(hasSummarizePayload);
|
|
39143
|
-
if (withPayload.length === 0) {
|
|
39144
|
-
return { promptText: params.bridgePromptText, sessionChangeSummaryFilePaths: void 0 };
|
|
39292
|
+
// src/agents/acp/from-bridge/handle-bridge-prompt/run-preamble-and-prompt.ts
|
|
39293
|
+
async function runPreambleAndPrompt(params) {
|
|
39294
|
+
const {
|
|
39295
|
+
deps,
|
|
39296
|
+
msg,
|
|
39297
|
+
getWs,
|
|
39298
|
+
log: log2,
|
|
39299
|
+
sessionWorktreeManager,
|
|
39300
|
+
sessionId,
|
|
39301
|
+
runId,
|
|
39302
|
+
promptText,
|
|
39303
|
+
attachments,
|
|
39304
|
+
mode,
|
|
39305
|
+
agentType,
|
|
39306
|
+
agentId,
|
|
39307
|
+
agentConfig,
|
|
39308
|
+
resolvedCwd,
|
|
39309
|
+
senders: { sendResult: sendResult2, sendSessionUpdate }
|
|
39310
|
+
} = params;
|
|
39311
|
+
const effectiveCwd = resolveSessionParentPathForAgentProcess(resolvedCwd);
|
|
39312
|
+
await runBridgePromptPreamble({
|
|
39313
|
+
getWs,
|
|
39314
|
+
log: log2,
|
|
39315
|
+
sessionWorktreeManager,
|
|
39316
|
+
sessionId,
|
|
39317
|
+
runId,
|
|
39318
|
+
effectiveCwd
|
|
39319
|
+
});
|
|
39320
|
+
const {
|
|
39321
|
+
followUpCatalogPromptId,
|
|
39322
|
+
sessionChangeSummaryFilePaths: pathsFromBridge,
|
|
39323
|
+
sessionChangeSummaryFileSnapshots
|
|
39324
|
+
} = parseFollowUpFieldsFromPromptMessage(msg);
|
|
39325
|
+
const { promptText: resolvedPromptText, sessionChangeSummaryFilePaths } = resolveChangeSummaryPromptForAgent({
|
|
39326
|
+
followUpCatalogPromptId,
|
|
39327
|
+
sessionChangeSummaryFileSnapshots,
|
|
39328
|
+
bridgePromptText: promptText,
|
|
39329
|
+
e2ee: deps.e2ee
|
|
39330
|
+
});
|
|
39331
|
+
if (sessionChangeSummaryFileSnapshots && sessionChangeSummaryFileSnapshots.length > 0 && resolvedPromptText === promptText) {
|
|
39332
|
+
deps.log(
|
|
39333
|
+
"[Agent] Change-summary snapshots were present but the prompt was not rebuilt (decrypt failed or empty payloads); sending the bridge prompt as-is."
|
|
39334
|
+
);
|
|
39145
39335
|
}
|
|
39146
|
-
|
|
39147
|
-
|
|
39148
|
-
|
|
39149
|
-
|
|
39336
|
+
const pathsForUpload = sessionChangeSummaryFilePaths ?? pathsFromBridge;
|
|
39337
|
+
deps.acpManager.handlePrompt({
|
|
39338
|
+
promptText: resolvedPromptText,
|
|
39339
|
+
promptId: msg.id,
|
|
39340
|
+
sessionId,
|
|
39341
|
+
runId,
|
|
39342
|
+
mode,
|
|
39343
|
+
agentType,
|
|
39344
|
+
agentId,
|
|
39345
|
+
agentConfig,
|
|
39346
|
+
sessionParentPath: effectiveCwd,
|
|
39347
|
+
sendResult: sendResult2,
|
|
39348
|
+
sendSessionUpdate,
|
|
39349
|
+
followUpCatalogPromptId,
|
|
39350
|
+
sessionChangeSummaryFilePaths: pathsForUpload,
|
|
39351
|
+
cloudApiBaseUrl: deps.cloudApiBaseUrl,
|
|
39352
|
+
getCloudAccessToken: deps.getCloudAccessToken,
|
|
39353
|
+
e2ee: deps.e2ee,
|
|
39354
|
+
...attachments.length > 0 ? { attachments } : {}
|
|
39355
|
+
});
|
|
39150
39356
|
}
|
|
39151
39357
|
|
|
39152
|
-
// src/agents/acp/from-bridge/handle-bridge-prompt.ts
|
|
39153
|
-
function parseBridgeAttachments(msg) {
|
|
39154
|
-
const raw = msg.attachments;
|
|
39155
|
-
if (!Array.isArray(raw)) return [];
|
|
39156
|
-
const out = [];
|
|
39157
|
-
for (const x of raw) {
|
|
39158
|
-
if (x === null || typeof x !== "object" || Array.isArray(x)) continue;
|
|
39159
|
-
const o = x;
|
|
39160
|
-
const id = typeof o.attachmentId === "string" ? o.attachmentId.trim() : "";
|
|
39161
|
-
if (!id) continue;
|
|
39162
|
-
const mt = typeof o.mimeType === "string" && o.mimeType.trim() ? o.mimeType.trim() : "application/octet-stream";
|
|
39163
|
-
out.push({ attachmentId: id, mimeType: mt });
|
|
39164
|
-
}
|
|
39165
|
-
return out;
|
|
39166
|
-
}
|
|
39358
|
+
// src/agents/acp/from-bridge/handle-bridge-prompt/handle-bridge-prompt.ts
|
|
39167
39359
|
function handleBridgePrompt(msg, deps) {
|
|
39168
39360
|
const { getWs, log: log2, acpManager, sessionWorktreeManager } = deps;
|
|
39169
39361
|
const rawPrompt = msg.prompt;
|
|
@@ -39172,12 +39364,12 @@ function handleBridgePrompt(msg, deps) {
|
|
|
39172
39364
|
const sessionId = msg.sessionId;
|
|
39173
39365
|
const runId = typeof msg.runId === "string" ? msg.runId : void 0;
|
|
39174
39366
|
const promptId = typeof msg.id === "string" ? msg.id : void 0;
|
|
39175
|
-
const
|
|
39367
|
+
const senders = createBridgePromptSenders(deps, getWs);
|
|
39176
39368
|
if (!promptText.trim() && attachments.length === 0) {
|
|
39177
39369
|
log2(
|
|
39178
39370
|
`[Bridge service] Prompt ignored: empty or missing prompt text (session ${typeof msg.sessionId === "string" ? msg.sessionId.slice(0, 8) : "\u2014"}\u2026, run ${typeof msg.runId === "string" ? msg.runId.slice(0, 8) : "\u2014"}\u2026).`
|
|
39179
39371
|
);
|
|
39180
|
-
sendBridgeMessage(
|
|
39372
|
+
senders.sendBridgeMessage(
|
|
39181
39373
|
{
|
|
39182
39374
|
type: "prompt_result",
|
|
39183
39375
|
...promptId ? { id: promptId } : {},
|
|
@@ -39199,57 +39391,50 @@ function handleBridgePrompt(msg, deps) {
|
|
|
39199
39391
|
const agentId = typeof rawAgentId === "string" && rawAgentId.trim() !== "" ? rawAgentId.trim() : null;
|
|
39200
39392
|
const mode = typeof msg.mode === "string" && msg.mode.trim() ? msg.mode.trim() : void 0;
|
|
39201
39393
|
const agentConfig = msg.agentConfig != null && typeof msg.agentConfig === "object" && !Array.isArray(msg.agentConfig) ? msg.agentConfig : void 0;
|
|
39394
|
+
const worktreeBaseBranches = parseWorktreeBaseBranches(msg);
|
|
39202
39395
|
acpManager.logPromptReceivedFromBridge({ agentType, mode });
|
|
39203
|
-
|
|
39204
|
-
|
|
39205
|
-
|
|
39396
|
+
void sessionWorktreeManager.resolveSessionParentPathForPrompt(sessionId, {
|
|
39397
|
+
isNewSession,
|
|
39398
|
+
sessionParent,
|
|
39399
|
+
sessionParentPath,
|
|
39400
|
+
...worktreeBaseBranches ? { worktreeBaseBranches } : {}
|
|
39401
|
+
}).then(
|
|
39402
|
+
(cwd) => runPreambleAndPrompt({
|
|
39403
|
+
deps,
|
|
39404
|
+
msg,
|
|
39206
39405
|
getWs,
|
|
39207
39406
|
log: log2,
|
|
39208
39407
|
sessionWorktreeManager,
|
|
39209
39408
|
sessionId,
|
|
39210
39409
|
runId,
|
|
39211
|
-
|
|
39212
|
-
|
|
39213
|
-
|
|
39214
|
-
|
|
39215
|
-
|
|
39216
|
-
|
|
39217
|
-
|
|
39218
|
-
|
|
39219
|
-
|
|
39220
|
-
|
|
39221
|
-
|
|
39222
|
-
|
|
39223
|
-
|
|
39224
|
-
|
|
39225
|
-
|
|
39226
|
-
|
|
39227
|
-
|
|
39228
|
-
}
|
|
39229
|
-
const pathsForUpload = sessionChangeSummaryFilePaths ?? pathsFromBridge;
|
|
39230
|
-
acpManager.handlePrompt({
|
|
39231
|
-
promptText: resolvedPromptText,
|
|
39232
|
-
promptId: msg.id,
|
|
39410
|
+
promptText,
|
|
39411
|
+
attachments,
|
|
39412
|
+
mode,
|
|
39413
|
+
agentType,
|
|
39414
|
+
agentId,
|
|
39415
|
+
agentConfig,
|
|
39416
|
+
resolvedCwd: cwd,
|
|
39417
|
+
senders
|
|
39418
|
+
})
|
|
39419
|
+
).catch((err) => {
|
|
39420
|
+
log2(`[Agent] Session parent path resolve failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
39421
|
+
void runPreambleAndPrompt({
|
|
39422
|
+
deps,
|
|
39423
|
+
msg,
|
|
39424
|
+
getWs,
|
|
39425
|
+
log: log2,
|
|
39426
|
+
sessionWorktreeManager,
|
|
39233
39427
|
sessionId,
|
|
39234
39428
|
runId,
|
|
39429
|
+
promptText,
|
|
39430
|
+
attachments,
|
|
39235
39431
|
mode,
|
|
39236
39432
|
agentType,
|
|
39237
39433
|
agentId,
|
|
39238
39434
|
agentConfig,
|
|
39239
|
-
|
|
39240
|
-
|
|
39241
|
-
sendSessionUpdate,
|
|
39242
|
-
followUpCatalogPromptId,
|
|
39243
|
-
sessionChangeSummaryFilePaths: pathsForUpload,
|
|
39244
|
-
cloudApiBaseUrl: deps.cloudApiBaseUrl,
|
|
39245
|
-
getCloudAccessToken: deps.getCloudAccessToken,
|
|
39246
|
-
e2ee: deps.e2ee,
|
|
39247
|
-
...attachments.length > 0 ? { attachments } : {}
|
|
39435
|
+
resolvedCwd: void 0,
|
|
39436
|
+
senders
|
|
39248
39437
|
});
|
|
39249
|
-
}
|
|
39250
|
-
void sessionWorktreeManager.resolveSessionParentPathForPrompt(sessionId, { isNewSession, sessionParent, sessionParentPath }).then((cwd) => preambleAndPrompt(cwd)).catch((err) => {
|
|
39251
|
-
log2(`[Agent] Session parent path resolve failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
39252
|
-
void preambleAndPrompt(void 0);
|
|
39253
39438
|
});
|
|
39254
39439
|
}
|
|
39255
39440
|
|
|
@@ -39297,8 +39482,8 @@ function randomSecret() {
|
|
|
39297
39482
|
}
|
|
39298
39483
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
39299
39484
|
}
|
|
39300
|
-
async function requestPreviewApi(port, secret, method,
|
|
39301
|
-
const url2 = `http://127.0.0.1:${port}${
|
|
39485
|
+
async function requestPreviewApi(port, secret, method, path46, body) {
|
|
39486
|
+
const url2 = `http://127.0.0.1:${port}${path46}`;
|
|
39302
39487
|
const headers = {
|
|
39303
39488
|
[PREVIEW_SECRET_HEADER]: secret,
|
|
39304
39489
|
"Content-Type": "application/json"
|
|
@@ -39310,7 +39495,7 @@ async function requestPreviewApi(port, secret, method, path43, body) {
|
|
|
39310
39495
|
});
|
|
39311
39496
|
const data = await res.json().catch(() => ({}));
|
|
39312
39497
|
if (!res.ok) {
|
|
39313
|
-
throw new Error(data?.error ?? `Preview API ${method} ${
|
|
39498
|
+
throw new Error(data?.error ?? `Preview API ${method} ${path46}: ${res.status}`);
|
|
39314
39499
|
}
|
|
39315
39500
|
return data;
|
|
39316
39501
|
}
|
|
@@ -39478,11 +39663,11 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
|
39478
39663
|
import fs34 from "node:fs";
|
|
39479
39664
|
|
|
39480
39665
|
// src/files/ensure-under-cwd.ts
|
|
39481
|
-
import
|
|
39666
|
+
import path37 from "node:path";
|
|
39482
39667
|
function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
|
|
39483
|
-
const normalized =
|
|
39484
|
-
const resolved =
|
|
39485
|
-
if (!resolved.startsWith(cwd +
|
|
39668
|
+
const normalized = path37.normalize(relativePath).replace(/^(\.\/)+/, "");
|
|
39669
|
+
const resolved = path37.resolve(cwd, normalized);
|
|
39670
|
+
if (!resolved.startsWith(cwd + path37.sep) && resolved !== cwd) {
|
|
39486
39671
|
return null;
|
|
39487
39672
|
}
|
|
39488
39673
|
return resolved;
|
|
@@ -39492,11 +39677,11 @@ function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
|
|
|
39492
39677
|
var LIST_DIR_YIELD_EVERY = 256;
|
|
39493
39678
|
|
|
39494
39679
|
// src/files/list-dir/map-dir-entry.ts
|
|
39495
|
-
import
|
|
39680
|
+
import path38 from "node:path";
|
|
39496
39681
|
import fs33 from "node:fs";
|
|
39497
39682
|
async function mapDirEntry(d, relativePath, resolved) {
|
|
39498
|
-
const entryPath =
|
|
39499
|
-
const fullPath =
|
|
39683
|
+
const entryPath = path38.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
39684
|
+
const fullPath = path38.join(resolved, d.name);
|
|
39500
39685
|
let isDir = d.isDirectory();
|
|
39501
39686
|
if (d.isSymbolicLink()) {
|
|
39502
39687
|
try {
|
|
@@ -39847,13 +40032,13 @@ function resolveFileBrowserSessionParent(sessionWorktreeManager, sessionId) {
|
|
|
39847
40032
|
}
|
|
39848
40033
|
|
|
39849
40034
|
// src/files/handle-file-browser-search.ts
|
|
39850
|
-
import
|
|
40035
|
+
import path39 from "node:path";
|
|
39851
40036
|
var SEARCH_LIMIT = 100;
|
|
39852
40037
|
function handleFileBrowserSearch(msg, socket, e2ee, sessionWorktreeManager) {
|
|
39853
40038
|
void (async () => {
|
|
39854
40039
|
await yieldToEventLoop();
|
|
39855
40040
|
const q = typeof msg.q === "string" ? msg.q : "";
|
|
39856
|
-
const sessionParentPath =
|
|
40041
|
+
const sessionParentPath = path39.resolve(
|
|
39857
40042
|
sessionWorktreeManager != null ? resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : getBridgeRoot()
|
|
39858
40043
|
);
|
|
39859
40044
|
if (!await bridgeFileIndexIsPopulated(sessionParentPath)) {
|
|
@@ -39973,7 +40158,7 @@ function handleSkillLayoutRequest(msg, deps) {
|
|
|
39973
40158
|
|
|
39974
40159
|
// src/skills/install-remote-skills.ts
|
|
39975
40160
|
import fs38 from "node:fs";
|
|
39976
|
-
import
|
|
40161
|
+
import path40 from "node:path";
|
|
39977
40162
|
function installRemoteSkills(cwd, targetDir, items) {
|
|
39978
40163
|
const installed2 = [];
|
|
39979
40164
|
if (!Array.isArray(items)) {
|
|
@@ -39984,11 +40169,11 @@ function installRemoteSkills(cwd, targetDir, items) {
|
|
|
39984
40169
|
if (typeof item.sourceId !== "string" || typeof item.skillName !== "string" || typeof item.versionHash !== "string" || !Array.isArray(item.files)) {
|
|
39985
40170
|
continue;
|
|
39986
40171
|
}
|
|
39987
|
-
const skillDir =
|
|
40172
|
+
const skillDir = path40.join(cwd, targetDir, item.skillName);
|
|
39988
40173
|
for (const f of item.files) {
|
|
39989
40174
|
if (typeof f.path !== "string" || !f.text && !f.base64) continue;
|
|
39990
|
-
const dest =
|
|
39991
|
-
fs38.mkdirSync(
|
|
40175
|
+
const dest = path40.join(skillDir, f.path);
|
|
40176
|
+
fs38.mkdirSync(path40.dirname(dest), { recursive: true });
|
|
39992
40177
|
if (f.text !== void 0) {
|
|
39993
40178
|
fs38.writeFileSync(dest, f.text, "utf8");
|
|
39994
40179
|
} else if (f.base64) {
|
|
@@ -40204,6 +40389,148 @@ var handleDevServersConfig = (msg, deps) => {
|
|
|
40204
40389
|
deps.devServerManager?.applyConfig(devServers ?? []);
|
|
40205
40390
|
};
|
|
40206
40391
|
|
|
40392
|
+
// src/git/bridge-git-context.ts
|
|
40393
|
+
import * as path41 from "node:path";
|
|
40394
|
+
|
|
40395
|
+
// src/git/branches/get-current-branch.ts
|
|
40396
|
+
async function getCurrentBranch(repoPath) {
|
|
40397
|
+
try {
|
|
40398
|
+
const git = cliSimpleGit(repoPath);
|
|
40399
|
+
const branch = await git.revparse(["--abbrev-ref", "HEAD"]);
|
|
40400
|
+
const trimmed2 = typeof branch === "string" ? branch.trim() : "";
|
|
40401
|
+
if (!trimmed2 || trimmed2 === "HEAD") return null;
|
|
40402
|
+
return trimmed2;
|
|
40403
|
+
} catch {
|
|
40404
|
+
return null;
|
|
40405
|
+
}
|
|
40406
|
+
}
|
|
40407
|
+
|
|
40408
|
+
// src/git/branches/list-repo-branch-refs.ts
|
|
40409
|
+
function normalizeBranchRef(raw) {
|
|
40410
|
+
const trimmed2 = raw.trim();
|
|
40411
|
+
if (!trimmed2 || trimmed2 === "HEAD") return null;
|
|
40412
|
+
if (trimmed2.startsWith("refs/heads/")) return trimmed2.slice("refs/heads/".length);
|
|
40413
|
+
if (trimmed2.startsWith("refs/remotes/")) return trimmed2.slice("refs/remotes/".length);
|
|
40414
|
+
return trimmed2;
|
|
40415
|
+
}
|
|
40416
|
+
async function listRepoBranchRefs(repoPath) {
|
|
40417
|
+
try {
|
|
40418
|
+
const git = cliSimpleGit(repoPath);
|
|
40419
|
+
const out = await git.raw([
|
|
40420
|
+
"for-each-ref",
|
|
40421
|
+
"--sort=-committerdate",
|
|
40422
|
+
"--format=%(refname:short)",
|
|
40423
|
+
"refs/heads",
|
|
40424
|
+
"refs/remotes"
|
|
40425
|
+
]);
|
|
40426
|
+
const lines = out.split("\n").map((line) => normalizeBranchRef(line)).filter((line) => Boolean(line));
|
|
40427
|
+
const seen = /* @__PURE__ */ new Set();
|
|
40428
|
+
const ordered = [];
|
|
40429
|
+
for (const name of lines) {
|
|
40430
|
+
if (seen.has(name)) continue;
|
|
40431
|
+
seen.add(name);
|
|
40432
|
+
ordered.push(name);
|
|
40433
|
+
}
|
|
40434
|
+
return ordered;
|
|
40435
|
+
} catch {
|
|
40436
|
+
return [];
|
|
40437
|
+
}
|
|
40438
|
+
}
|
|
40439
|
+
|
|
40440
|
+
// src/git/bridge-git-context.ts
|
|
40441
|
+
function folderNameForRelPath(relPath, bridgeRoot) {
|
|
40442
|
+
if (relPath === "." || relPath === "") {
|
|
40443
|
+
return path41.basename(path41.resolve(bridgeRoot)) || "repo";
|
|
40444
|
+
}
|
|
40445
|
+
return path41.basename(relPath) || relPath;
|
|
40446
|
+
}
|
|
40447
|
+
async function discoverGitReposForBridgeContext(bridgeRoot) {
|
|
40448
|
+
const root = path41.resolve(bridgeRoot);
|
|
40449
|
+
if (await isGitRepoDirectory(root)) {
|
|
40450
|
+
const remoteUrl = await getRemoteOriginUrl(root);
|
|
40451
|
+
return [{ absolutePath: root, remoteUrl }];
|
|
40452
|
+
}
|
|
40453
|
+
const [deep, shallow] = await Promise.all([discoverGitReposUnderRoot(root), discoverGitRepos(root)]);
|
|
40454
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
40455
|
+
for (const repo of [...deep, ...shallow]) {
|
|
40456
|
+
byPath.set(path41.resolve(repo.absolutePath), repo);
|
|
40457
|
+
}
|
|
40458
|
+
return [...byPath.values()];
|
|
40459
|
+
}
|
|
40460
|
+
async function getBridgeGitContext(bridgeRoot = getBridgeRoot()) {
|
|
40461
|
+
const bridgeResolved = path41.resolve(bridgeRoot);
|
|
40462
|
+
const repos = await discoverGitReposForBridgeContext(bridgeResolved);
|
|
40463
|
+
const rows = [];
|
|
40464
|
+
for (const repo of repos) {
|
|
40465
|
+
let rel = path41.relative(bridgeResolved, repo.absolutePath);
|
|
40466
|
+
if (rel.startsWith("..") || path41.isAbsolute(rel)) continue;
|
|
40467
|
+
const relPath = rel === "" ? "." : rel.replace(/\\/g, "/");
|
|
40468
|
+
const currentBranch = await getCurrentBranch(repo.absolutePath);
|
|
40469
|
+
const remoteUrl = repo.remoteUrl.trim() || null;
|
|
40470
|
+
rows.push({
|
|
40471
|
+
relPath,
|
|
40472
|
+
folderName: folderNameForRelPath(relPath, bridgeResolved),
|
|
40473
|
+
currentBranch,
|
|
40474
|
+
remoteUrl
|
|
40475
|
+
});
|
|
40476
|
+
}
|
|
40477
|
+
rows.sort((a, b) => a.relPath.localeCompare(b.relPath));
|
|
40478
|
+
return rows;
|
|
40479
|
+
}
|
|
40480
|
+
async function listRepoBranchesForBridge(repoRelPath, bridgeRoot = getBridgeRoot()) {
|
|
40481
|
+
const bridgeResolved = path41.resolve(bridgeRoot);
|
|
40482
|
+
const rel = repoRelPath.trim() === "." ? "" : repoRelPath.trim().replace(/\\/g, "/");
|
|
40483
|
+
const repoPath = rel === "" ? bridgeResolved : path41.join(bridgeResolved, rel);
|
|
40484
|
+
const resolved = path41.resolve(repoPath);
|
|
40485
|
+
if (!resolved.startsWith(bridgeResolved + path41.sep) && resolved !== bridgeResolved) {
|
|
40486
|
+
return [];
|
|
40487
|
+
}
|
|
40488
|
+
return listRepoBranchRefs(resolved);
|
|
40489
|
+
}
|
|
40490
|
+
|
|
40491
|
+
// src/routing/handlers/bridge-git-context-messages.ts
|
|
40492
|
+
function handleBridgeGitContextRequestMessage(msg, getWs) {
|
|
40493
|
+
void (async () => {
|
|
40494
|
+
const socket = getWs();
|
|
40495
|
+
if (!socket) return;
|
|
40496
|
+
try {
|
|
40497
|
+
const repos = await getBridgeGitContext();
|
|
40498
|
+
sendWsMessage(socket, { type: "bridge_git_context_response", id: msg.id, repos });
|
|
40499
|
+
} catch (e) {
|
|
40500
|
+
sendWsMessage(socket, {
|
|
40501
|
+
type: "bridge_git_context_response",
|
|
40502
|
+
id: msg.id,
|
|
40503
|
+
error: e instanceof Error ? e.message : String(e)
|
|
40504
|
+
});
|
|
40505
|
+
}
|
|
40506
|
+
})();
|
|
40507
|
+
}
|
|
40508
|
+
function handleListRepoBranchesRequestMessage(msg, getWs) {
|
|
40509
|
+
void (async () => {
|
|
40510
|
+
const socket = getWs();
|
|
40511
|
+
if (!socket) return;
|
|
40512
|
+
const repoRelPath = typeof msg.repoRelPath === "string" ? msg.repoRelPath.trim() : "";
|
|
40513
|
+
if (!repoRelPath) {
|
|
40514
|
+
sendWsMessage(socket, {
|
|
40515
|
+
type: "list_repo_branches_response",
|
|
40516
|
+
id: msg.id,
|
|
40517
|
+
error: "repoRelPath required"
|
|
40518
|
+
});
|
|
40519
|
+
return;
|
|
40520
|
+
}
|
|
40521
|
+
try {
|
|
40522
|
+
const branches = await listRepoBranchesForBridge(repoRelPath);
|
|
40523
|
+
sendWsMessage(socket, { type: "list_repo_branches_response", id: msg.id, branches });
|
|
40524
|
+
} catch (e) {
|
|
40525
|
+
sendWsMessage(socket, {
|
|
40526
|
+
type: "list_repo_branches_response",
|
|
40527
|
+
id: msg.id,
|
|
40528
|
+
error: e instanceof Error ? e.message : String(e)
|
|
40529
|
+
});
|
|
40530
|
+
}
|
|
40531
|
+
})();
|
|
40532
|
+
}
|
|
40533
|
+
|
|
40207
40534
|
// src/routing/dispatch-bridge-message.ts
|
|
40208
40535
|
function dispatchBridgeMessage(msg, deps) {
|
|
40209
40536
|
switch (msg.type) {
|
|
@@ -40267,6 +40594,12 @@ function dispatchBridgeMessage(msg, deps) {
|
|
|
40267
40594
|
case "refresh_local_skills":
|
|
40268
40595
|
handleRefreshLocalSkills(msg, deps);
|
|
40269
40596
|
break;
|
|
40597
|
+
case "bridge_git_context_request":
|
|
40598
|
+
handleBridgeGitContextRequestMessage(msg, deps.getWs);
|
|
40599
|
+
break;
|
|
40600
|
+
case "list_repo_branches_request":
|
|
40601
|
+
handleListRepoBranchesRequestMessage(msg, deps.getWs);
|
|
40602
|
+
break;
|
|
40270
40603
|
}
|
|
40271
40604
|
}
|
|
40272
40605
|
|
|
@@ -40638,10 +40971,10 @@ function listCliAgentCapabilityCacheForWorkspace(db, workspaceId) {
|
|
|
40638
40971
|
}
|
|
40639
40972
|
|
|
40640
40973
|
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
40641
|
-
import * as
|
|
40974
|
+
import * as path43 from "node:path";
|
|
40642
40975
|
|
|
40643
40976
|
// src/agents/capabilities/probe-one-agent-type-for-capabilities.ts
|
|
40644
|
-
import * as
|
|
40977
|
+
import * as path42 from "node:path";
|
|
40645
40978
|
async function probeOneAgentTypeForCapabilities(params) {
|
|
40646
40979
|
const { agentType, cwd, workspaceId, log: log2, reportAgentCapabilities, bridgeReport = true } = params;
|
|
40647
40980
|
if (isCliImmediateShutdownRequested()) return false;
|
|
@@ -40681,7 +41014,7 @@ async function probeOneAgentTypeForCapabilities(params) {
|
|
|
40681
41014
|
if (isCliImmediateShutdownRequested()) return false;
|
|
40682
41015
|
handle = await resolved.createClient({
|
|
40683
41016
|
command: resolved.command,
|
|
40684
|
-
cwd:
|
|
41017
|
+
cwd: path42.resolve(cwd),
|
|
40685
41018
|
backendAgentType: agentType,
|
|
40686
41019
|
sessionMode: "agent",
|
|
40687
41020
|
persistedAcpSessionId: null,
|
|
@@ -40755,7 +41088,7 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
|
|
|
40755
41088
|
async function warmupAgentCapabilitiesOnConnect(params) {
|
|
40756
41089
|
const { workspaceId, log: log2, getWs } = params;
|
|
40757
41090
|
if (isCliImmediateShutdownRequested()) return;
|
|
40758
|
-
const cwd =
|
|
41091
|
+
const cwd = path43.resolve(getBridgeRoot());
|
|
40759
41092
|
async function sendBatchFromCache() {
|
|
40760
41093
|
const socket = getWs();
|
|
40761
41094
|
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
@@ -40922,8 +41255,8 @@ async function createBridgeConnection(options) {
|
|
|
40922
41255
|
getCloudAccessToken: () => tokens.accessToken
|
|
40923
41256
|
};
|
|
40924
41257
|
const identifyReportedPaths = {
|
|
40925
|
-
bridgeRootPath:
|
|
40926
|
-
worktreesRootPath:
|
|
41258
|
+
bridgeRootPath: path44.resolve(getBridgeRoot()),
|
|
41259
|
+
worktreesRootPath: path44.resolve(worktreesRootPath)
|
|
40927
41260
|
};
|
|
40928
41261
|
const { connect } = createMainBridgeWebSocketLifecycle({
|
|
40929
41262
|
state,
|
|
@@ -41177,7 +41510,7 @@ async function runCliAction(program2, opts) {
|
|
|
41177
41510
|
const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
|
|
41178
41511
|
const bridgeRootOpt = (opts.bridgeRoot && typeof opts.bridgeRoot === "string" && opts.bridgeRoot.trim() ? opts.bridgeRoot.trim() : null) ?? (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim() ? opts.cwd.trim() : null);
|
|
41179
41512
|
if (bridgeRootOpt) {
|
|
41180
|
-
const resolvedBridgeRoot =
|
|
41513
|
+
const resolvedBridgeRoot = path45.resolve(process.cwd(), bridgeRootOpt);
|
|
41181
41514
|
try {
|
|
41182
41515
|
const st = fs40.statSync(resolvedBridgeRoot);
|
|
41183
41516
|
if (!st.isDirectory()) {
|
|
@@ -41199,7 +41532,7 @@ async function runCliAction(program2, opts) {
|
|
|
41199
41532
|
);
|
|
41200
41533
|
let worktreesRootPath;
|
|
41201
41534
|
if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
|
|
41202
|
-
worktreesRootPath =
|
|
41535
|
+
worktreesRootPath = path45.resolve(opts.worktreesRoot.trim());
|
|
41203
41536
|
}
|
|
41204
41537
|
const e2eCertificates = opts.e2eeCertificatesDir?.trim() ? await loadOrCreateE2eCertificates(opts.e2eeCertificatesDir.trim()) : void 0;
|
|
41205
41538
|
if (e2eCertificates) {
|