@buildautomaton/cli 0.1.51 → 0.1.53
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 +719 -312
- package/dist/cli.js.map +4 -4
- package/dist/index.js +704 -297
- 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 path63 = __require("node:path");
|
|
977
977
|
var fs47 = __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 = path63.resolve(baseDir, baseName);
|
|
1910
1910
|
if (fs47.existsSync(localBin)) return localBin;
|
|
1911
|
-
if (sourceExt.includes(
|
|
1911
|
+
if (sourceExt.includes(path63.extname(baseName))) return void 0;
|
|
1912
1912
|
const foundExt = sourceExt.find(
|
|
1913
1913
|
(ext) => fs47.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 = path63.resolve(
|
|
1930
|
+
path63.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 = path63.basename(
|
|
1938
1938
|
this._scriptPath,
|
|
1939
|
-
|
|
1939
|
+
path63.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(path63.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 = path63.basename(filename, path63.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(path64) {
|
|
2805
|
+
if (path64 === void 0) return this._executableDir;
|
|
2806
|
+
this._executableDir = path64;
|
|
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: path63, errorMaps, issueData } = params;
|
|
7065
|
+
const fullPath = [...path63, ...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, path63, key) {
|
|
7374
7374
|
this._cachedPath = [];
|
|
7375
7375
|
this.parent = parent;
|
|
7376
7376
|
this.data = value;
|
|
7377
|
-
this._path =
|
|
7377
|
+
this._path = path63;
|
|
7378
7378
|
this._key = key;
|
|
7379
7379
|
}
|
|
7380
7380
|
get path() {
|
|
@@ -11099,10 +11099,10 @@ function assignProp(target, prop, value) {
|
|
|
11099
11099
|
configurable: true
|
|
11100
11100
|
});
|
|
11101
11101
|
}
|
|
11102
|
-
function getElementAtPath(obj,
|
|
11103
|
-
if (!
|
|
11102
|
+
function getElementAtPath(obj, path63) {
|
|
11103
|
+
if (!path63)
|
|
11104
11104
|
return obj;
|
|
11105
|
-
return
|
|
11105
|
+
return path63.reduce((acc, key) => acc?.[key], obj);
|
|
11106
11106
|
}
|
|
11107
11107
|
function promiseAllObject(promisesObj) {
|
|
11108
11108
|
const keys = Object.keys(promisesObj);
|
|
@@ -11351,11 +11351,11 @@ function aborted(x, startIndex = 0) {
|
|
|
11351
11351
|
}
|
|
11352
11352
|
return false;
|
|
11353
11353
|
}
|
|
11354
|
-
function prefixIssues(
|
|
11354
|
+
function prefixIssues(path63, issues) {
|
|
11355
11355
|
return issues.map((iss) => {
|
|
11356
11356
|
var _a2;
|
|
11357
11357
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
11358
|
-
iss.path.unshift(
|
|
11358
|
+
iss.path.unshift(path63);
|
|
11359
11359
|
return iss;
|
|
11360
11360
|
});
|
|
11361
11361
|
}
|
|
@@ -11544,7 +11544,7 @@ function treeifyError(error40, _mapper) {
|
|
|
11544
11544
|
return issue2.message;
|
|
11545
11545
|
};
|
|
11546
11546
|
const result = { errors: [] };
|
|
11547
|
-
const processError = (error41,
|
|
11547
|
+
const processError = (error41, path63 = []) => {
|
|
11548
11548
|
var _a2, _b;
|
|
11549
11549
|
for (const issue2 of error41.issues) {
|
|
11550
11550
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -11554,7 +11554,7 @@ function treeifyError(error40, _mapper) {
|
|
|
11554
11554
|
} else if (issue2.code === "invalid_element") {
|
|
11555
11555
|
processError({ issues: issue2.issues }, issue2.path);
|
|
11556
11556
|
} else {
|
|
11557
|
-
const fullpath = [...
|
|
11557
|
+
const fullpath = [...path63, ...issue2.path];
|
|
11558
11558
|
if (fullpath.length === 0) {
|
|
11559
11559
|
result.errors.push(mapper(issue2));
|
|
11560
11560
|
continue;
|
|
@@ -11584,9 +11584,9 @@ function treeifyError(error40, _mapper) {
|
|
|
11584
11584
|
processError(error40);
|
|
11585
11585
|
return result;
|
|
11586
11586
|
}
|
|
11587
|
-
function toDotPath(
|
|
11587
|
+
function toDotPath(path63) {
|
|
11588
11588
|
const segs = [];
|
|
11589
|
-
for (const seg of
|
|
11589
|
+
for (const seg of path63) {
|
|
11590
11590
|
if (typeof seg === "number")
|
|
11591
11591
|
segs.push(`[${seg}]`);
|
|
11592
11592
|
else if (typeof seg === "symbol")
|
|
@@ -24049,8 +24049,8 @@ var init_acp = __esm({
|
|
|
24049
24049
|
this.#requestHandler = requestHandler;
|
|
24050
24050
|
this.#notificationHandler = notificationHandler;
|
|
24051
24051
|
this.#stream = stream;
|
|
24052
|
-
this.#closedPromise = new Promise((
|
|
24053
|
-
this.#abortController.signal.addEventListener("abort", () =>
|
|
24052
|
+
this.#closedPromise = new Promise((resolve35) => {
|
|
24053
|
+
this.#abortController.signal.addEventListener("abort", () => resolve35());
|
|
24054
24054
|
});
|
|
24055
24055
|
this.#receive();
|
|
24056
24056
|
}
|
|
@@ -24199,8 +24199,8 @@ var init_acp = __esm({
|
|
|
24199
24199
|
}
|
|
24200
24200
|
async sendRequest(method, params) {
|
|
24201
24201
|
const id = this.#nextRequestId++;
|
|
24202
|
-
const responsePromise = new Promise((
|
|
24203
|
-
this.#pendingResponses.set(id, { resolve:
|
|
24202
|
+
const responsePromise = new Promise((resolve35, reject) => {
|
|
24203
|
+
this.#pendingResponses.set(id, { resolve: resolve35, reject });
|
|
24204
24204
|
});
|
|
24205
24205
|
await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
|
|
24206
24206
|
return responsePromise;
|
|
@@ -25069,10 +25069,10 @@ var require_src2 = __commonJS({
|
|
|
25069
25069
|
var fs_1 = __require("fs");
|
|
25070
25070
|
var debug_1 = __importDefault(require_src());
|
|
25071
25071
|
var log2 = debug_1.default("@kwsites/file-exists");
|
|
25072
|
-
function check2(
|
|
25073
|
-
log2(`checking %s`,
|
|
25072
|
+
function check2(path63, isFile, isDirectory) {
|
|
25073
|
+
log2(`checking %s`, path63);
|
|
25074
25074
|
try {
|
|
25075
|
-
const stat3 = fs_1.statSync(
|
|
25075
|
+
const stat3 = fs_1.statSync(path63);
|
|
25076
25076
|
if (stat3.isFile() && isFile) {
|
|
25077
25077
|
log2(`[OK] path represents a file`);
|
|
25078
25078
|
return true;
|
|
@@ -25092,8 +25092,8 @@ var require_src2 = __commonJS({
|
|
|
25092
25092
|
throw e;
|
|
25093
25093
|
}
|
|
25094
25094
|
}
|
|
25095
|
-
function exists2(
|
|
25096
|
-
return check2(
|
|
25095
|
+
function exists2(path63, type = exports.READABLE) {
|
|
25096
|
+
return check2(path63, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
|
|
25097
25097
|
}
|
|
25098
25098
|
exports.exists = exists2;
|
|
25099
25099
|
exports.FILE = 1;
|
|
@@ -25174,7 +25174,7 @@ var {
|
|
|
25174
25174
|
} = import_index.default;
|
|
25175
25175
|
|
|
25176
25176
|
// src/cli-version.ts
|
|
25177
|
-
var CLI_VERSION = "0.1.
|
|
25177
|
+
var CLI_VERSION = "0.1.53".length > 0 ? "0.1.53" : "0.0.0-dev";
|
|
25178
25178
|
|
|
25179
25179
|
// src/cli/defaults.ts
|
|
25180
25180
|
var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
|
|
@@ -25182,7 +25182,7 @@ var DEFAULT_FIREHOSE_URL = "https://buildautomaton-firehose.fly.dev";
|
|
|
25182
25182
|
|
|
25183
25183
|
// src/cli/run-cli-action.ts
|
|
25184
25184
|
import * as fs46 from "node:fs";
|
|
25185
|
-
import * as
|
|
25185
|
+
import * as path62 from "node:path";
|
|
25186
25186
|
|
|
25187
25187
|
// src/cli-log-level.ts
|
|
25188
25188
|
var verbosity = "info";
|
|
@@ -26297,14 +26297,14 @@ var baseOpen = async (options) => {
|
|
|
26297
26297
|
}
|
|
26298
26298
|
const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
|
|
26299
26299
|
if (options.wait) {
|
|
26300
|
-
return new Promise((
|
|
26300
|
+
return new Promise((resolve35, reject) => {
|
|
26301
26301
|
subprocess.once("error", reject);
|
|
26302
26302
|
subprocess.once("close", (exitCode) => {
|
|
26303
26303
|
if (!options.allowNonzeroExitCode && exitCode > 0) {
|
|
26304
26304
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
26305
26305
|
return;
|
|
26306
26306
|
}
|
|
26307
|
-
|
|
26307
|
+
resolve35(subprocess);
|
|
26308
26308
|
});
|
|
26309
26309
|
});
|
|
26310
26310
|
}
|
|
@@ -26848,8 +26848,8 @@ function runPendingAuth(options) {
|
|
|
26848
26848
|
let hasOpenedBrowser = false;
|
|
26849
26849
|
let resolved = false;
|
|
26850
26850
|
let resolveAuth;
|
|
26851
|
-
const authPromise = new Promise((
|
|
26852
|
-
resolveAuth =
|
|
26851
|
+
const authPromise = new Promise((resolve35) => {
|
|
26852
|
+
resolveAuth = resolve35;
|
|
26853
26853
|
});
|
|
26854
26854
|
let reconnectAttempt = 0;
|
|
26855
26855
|
const signInQuiet = createEmptyReconnectQuietSlot();
|
|
@@ -27000,7 +27000,7 @@ import sqliteWasm from "node-sqlite3-wasm";
|
|
|
27000
27000
|
|
|
27001
27001
|
// src/runtime/yield-to-event-loop.ts
|
|
27002
27002
|
function yieldToEventLoop() {
|
|
27003
|
-
return new Promise((
|
|
27003
|
+
return new Promise((resolve35) => setImmediate(resolve35));
|
|
27004
27004
|
}
|
|
27005
27005
|
|
|
27006
27006
|
// src/sqlite/cli-sqlite-paths.ts
|
|
@@ -28117,9 +28117,9 @@ function parseChangeSummaryJson(raw, allowedPaths, options) {
|
|
|
28117
28117
|
const rawPath = typeof o.path === "string" ? o.path.trim() : "";
|
|
28118
28118
|
const summary = typeof o.summary === "string" ? o.summary.trim() : "";
|
|
28119
28119
|
if (!rawPath || !summary) continue;
|
|
28120
|
-
const
|
|
28121
|
-
if (!
|
|
28122
|
-
rows.push({ path:
|
|
28120
|
+
const path63 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
|
|
28121
|
+
if (!path63) continue;
|
|
28122
|
+
rows.push({ path: path63, summary: clampSummaryToAtMostTwoLines(summary) });
|
|
28123
28123
|
}
|
|
28124
28124
|
return rows;
|
|
28125
28125
|
}
|
|
@@ -28347,6 +28347,11 @@ var BRIDGE_MCP_TOOL_LABELS = {
|
|
|
28347
28347
|
[GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL]: "Read parent session transcript"
|
|
28348
28348
|
};
|
|
28349
28349
|
|
|
28350
|
+
// ../types/src/prompts/server.ts
|
|
28351
|
+
function isRunnableBridgePromptTurnServerState(state) {
|
|
28352
|
+
return state === "queued" || state === "requeued" || state === "requeued_with_revert";
|
|
28353
|
+
}
|
|
28354
|
+
|
|
28350
28355
|
// ../types/src/claude-code-permission-mode.ts
|
|
28351
28356
|
var CLAUDE_CODE_PERMISSION_MODES = [
|
|
28352
28357
|
"default",
|
|
@@ -28631,10 +28636,10 @@ async function killChildProcessTreeGracefully(child, graceMs = ACP_PROCESS_TREE_
|
|
|
28631
28636
|
}
|
|
28632
28637
|
await killProcessTree(pid, "SIGTERM");
|
|
28633
28638
|
if (graceMs <= 0) return;
|
|
28634
|
-
const exited = new Promise((
|
|
28635
|
-
child.once("exit", () =>
|
|
28639
|
+
const exited = new Promise((resolve35) => {
|
|
28640
|
+
child.once("exit", () => resolve35());
|
|
28636
28641
|
});
|
|
28637
|
-
await Promise.race([exited, new Promise((
|
|
28642
|
+
await Promise.race([exited, new Promise((resolve35) => setTimeout(resolve35, graceMs))]);
|
|
28638
28643
|
if (child.exitCode == null && child.signalCode == null) {
|
|
28639
28644
|
await killProcessTree(pid, "SIGKILL");
|
|
28640
28645
|
}
|
|
@@ -28651,8 +28656,8 @@ async function gracefulAcpSubprocessDisconnect(params) {
|
|
|
28651
28656
|
await transport.closeSession?.(sessionId);
|
|
28652
28657
|
} catch {
|
|
28653
28658
|
}
|
|
28654
|
-
await new Promise((
|
|
28655
|
-
const timer = setTimeout(
|
|
28659
|
+
await new Promise((resolve35) => {
|
|
28660
|
+
const timer = setTimeout(resolve35, ACP_GRACEFUL_SESSION_CLOSE_WAIT_MS);
|
|
28656
28661
|
timer.unref?.();
|
|
28657
28662
|
});
|
|
28658
28663
|
}
|
|
@@ -28927,11 +28932,11 @@ function createSdkStdioExtNotificationHandler(options) {
|
|
|
28927
28932
|
// src/agents/acp/clients/sdk/sdk-stdio-permission-request-handshake.ts
|
|
28928
28933
|
function awaitSdkStdioPermissionRequestHandshake(params) {
|
|
28929
28934
|
const { requestId, paramsRecord, pending, onRequest } = params;
|
|
28930
|
-
return new Promise((
|
|
28931
|
-
pending.set(requestId, { resolve:
|
|
28935
|
+
return new Promise((resolve35) => {
|
|
28936
|
+
pending.set(requestId, { resolve: resolve35, params: paramsRecord });
|
|
28932
28937
|
if (onRequest == null) {
|
|
28933
28938
|
pending.delete(requestId);
|
|
28934
|
-
|
|
28939
|
+
resolve35({ outcome: { outcome: "denied" } });
|
|
28935
28940
|
return;
|
|
28936
28941
|
}
|
|
28937
28942
|
try {
|
|
@@ -29441,10 +29446,10 @@ function createSdkStdioInitSettle(child) {
|
|
|
29441
29446
|
forceAcpSubprocessDisconnect(child);
|
|
29442
29447
|
reject(err);
|
|
29443
29448
|
},
|
|
29444
|
-
settleResolve(
|
|
29449
|
+
settleResolve(resolve35, handle) {
|
|
29445
29450
|
if (initSettled) return;
|
|
29446
29451
|
initSettled = true;
|
|
29447
|
-
|
|
29452
|
+
resolve35(handle);
|
|
29448
29453
|
}
|
|
29449
29454
|
};
|
|
29450
29455
|
}
|
|
@@ -29513,7 +29518,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
29513
29518
|
onFileChange,
|
|
29514
29519
|
stderrCapture
|
|
29515
29520
|
});
|
|
29516
|
-
return new Promise((
|
|
29521
|
+
return new Promise((resolve35, reject) => {
|
|
29517
29522
|
const init = createSdkStdioInitSettle(child);
|
|
29518
29523
|
child.on("error", (err) => {
|
|
29519
29524
|
init.settleReject(reject, new Error(formatSpawnError(err, command[0])));
|
|
@@ -29538,7 +29543,7 @@ async function createSdkStdioAcpClient(options) {
|
|
|
29538
29543
|
protocolVersion: PROTOCOL_VERSION2
|
|
29539
29544
|
});
|
|
29540
29545
|
init.settleResolve(
|
|
29541
|
-
|
|
29546
|
+
resolve35,
|
|
29542
29547
|
createSdkStdioHandle({
|
|
29543
29548
|
child,
|
|
29544
29549
|
sessionId: established.sessionId,
|
|
@@ -30071,7 +30076,7 @@ async function createCursorAcpClient(options) {
|
|
|
30071
30076
|
onFileChange,
|
|
30072
30077
|
stderrCapture
|
|
30073
30078
|
});
|
|
30074
|
-
return new Promise((
|
|
30079
|
+
return new Promise((resolve35, reject) => {
|
|
30075
30080
|
child.on("error", (err) => {
|
|
30076
30081
|
killChildProcessTree(child, "SIGKILL");
|
|
30077
30082
|
reject(new Error(formatSpawnError(err, command[0])));
|
|
@@ -30083,7 +30088,7 @@ async function createCursorAcpClient(options) {
|
|
|
30083
30088
|
sessionCtx,
|
|
30084
30089
|
incomingDeps: { dbgFs, sessionCtx, onSessionUpdate, onRequest }
|
|
30085
30090
|
});
|
|
30086
|
-
|
|
30091
|
+
resolve35(
|
|
30087
30092
|
createCursorAcpHandle({
|
|
30088
30093
|
child,
|
|
30089
30094
|
sessionId: established.sessionId,
|
|
@@ -31289,8 +31294,8 @@ function pathspec(...paths) {
|
|
|
31289
31294
|
cache.set(key, paths);
|
|
31290
31295
|
return key;
|
|
31291
31296
|
}
|
|
31292
|
-
function isPathSpec(
|
|
31293
|
-
return
|
|
31297
|
+
function isPathSpec(path63) {
|
|
31298
|
+
return path63 instanceof String && cache.has(path63);
|
|
31294
31299
|
}
|
|
31295
31300
|
function toPaths(pathSpec) {
|
|
31296
31301
|
return cache.get(pathSpec) || [];
|
|
@@ -31379,8 +31384,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
31379
31384
|
function forEachLineWithContent(input, callback) {
|
|
31380
31385
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
31381
31386
|
}
|
|
31382
|
-
function folderExists(
|
|
31383
|
-
return (0, import_file_exists.exists)(
|
|
31387
|
+
function folderExists(path63) {
|
|
31388
|
+
return (0, import_file_exists.exists)(path63, import_file_exists.FOLDER);
|
|
31384
31389
|
}
|
|
31385
31390
|
function append(target, item) {
|
|
31386
31391
|
if (Array.isArray(target)) {
|
|
@@ -31784,8 +31789,8 @@ function checkIsRepoRootTask() {
|
|
|
31784
31789
|
commands,
|
|
31785
31790
|
format: "utf-8",
|
|
31786
31791
|
onError,
|
|
31787
|
-
parser(
|
|
31788
|
-
return /^\.(git)?$/.test(
|
|
31792
|
+
parser(path63) {
|
|
31793
|
+
return /^\.(git)?$/.test(path63.trim());
|
|
31789
31794
|
}
|
|
31790
31795
|
};
|
|
31791
31796
|
}
|
|
@@ -32219,11 +32224,11 @@ function parseGrep(grep) {
|
|
|
32219
32224
|
const paths = /* @__PURE__ */ new Set();
|
|
32220
32225
|
const results = {};
|
|
32221
32226
|
forEachLineWithContent(grep, (input) => {
|
|
32222
|
-
const [
|
|
32223
|
-
paths.add(
|
|
32224
|
-
(results[
|
|
32227
|
+
const [path63, line, preview] = input.split(NULL);
|
|
32228
|
+
paths.add(path63);
|
|
32229
|
+
(results[path63] = results[path63] || []).push({
|
|
32225
32230
|
line: asNumber(line),
|
|
32226
|
-
path:
|
|
32231
|
+
path: path63,
|
|
32227
32232
|
preview
|
|
32228
32233
|
});
|
|
32229
32234
|
});
|
|
@@ -32988,14 +32993,14 @@ var init_hash_object = __esm2({
|
|
|
32988
32993
|
init_task();
|
|
32989
32994
|
}
|
|
32990
32995
|
});
|
|
32991
|
-
function parseInit(bare,
|
|
32996
|
+
function parseInit(bare, path63, text) {
|
|
32992
32997
|
const response = String(text).trim();
|
|
32993
32998
|
let result;
|
|
32994
32999
|
if (result = initResponseRegex.exec(response)) {
|
|
32995
|
-
return new InitSummary(bare,
|
|
33000
|
+
return new InitSummary(bare, path63, false, result[1]);
|
|
32996
33001
|
}
|
|
32997
33002
|
if (result = reInitResponseRegex.exec(response)) {
|
|
32998
|
-
return new InitSummary(bare,
|
|
33003
|
+
return new InitSummary(bare, path63, true, result[1]);
|
|
32999
33004
|
}
|
|
33000
33005
|
let gitDir = "";
|
|
33001
33006
|
const tokens = response.split(" ");
|
|
@@ -33006,7 +33011,7 @@ function parseInit(bare, path62, text) {
|
|
|
33006
33011
|
break;
|
|
33007
33012
|
}
|
|
33008
33013
|
}
|
|
33009
|
-
return new InitSummary(bare,
|
|
33014
|
+
return new InitSummary(bare, path63, /^re/i.test(response), gitDir);
|
|
33010
33015
|
}
|
|
33011
33016
|
var InitSummary;
|
|
33012
33017
|
var initResponseRegex;
|
|
@@ -33015,9 +33020,9 @@ var init_InitSummary = __esm2({
|
|
|
33015
33020
|
"src/lib/responses/InitSummary.ts"() {
|
|
33016
33021
|
"use strict";
|
|
33017
33022
|
InitSummary = class {
|
|
33018
|
-
constructor(bare,
|
|
33023
|
+
constructor(bare, path63, existing, gitDir) {
|
|
33019
33024
|
this.bare = bare;
|
|
33020
|
-
this.path =
|
|
33025
|
+
this.path = path63;
|
|
33021
33026
|
this.existing = existing;
|
|
33022
33027
|
this.gitDir = gitDir;
|
|
33023
33028
|
}
|
|
@@ -33029,7 +33034,7 @@ var init_InitSummary = __esm2({
|
|
|
33029
33034
|
function hasBareCommand(command) {
|
|
33030
33035
|
return command.includes(bareCommand);
|
|
33031
33036
|
}
|
|
33032
|
-
function initTask(bare = false,
|
|
33037
|
+
function initTask(bare = false, path63, customArgs) {
|
|
33033
33038
|
const commands = ["init", ...customArgs];
|
|
33034
33039
|
if (bare && !hasBareCommand(commands)) {
|
|
33035
33040
|
commands.splice(1, 0, bareCommand);
|
|
@@ -33038,7 +33043,7 @@ function initTask(bare = false, path62, customArgs) {
|
|
|
33038
33043
|
commands,
|
|
33039
33044
|
format: "utf-8",
|
|
33040
33045
|
parser(text) {
|
|
33041
|
-
return parseInit(commands.includes("--bare"),
|
|
33046
|
+
return parseInit(commands.includes("--bare"), path63, text);
|
|
33042
33047
|
}
|
|
33043
33048
|
};
|
|
33044
33049
|
}
|
|
@@ -33854,12 +33859,12 @@ var init_FileStatusSummary = __esm2({
|
|
|
33854
33859
|
"use strict";
|
|
33855
33860
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
33856
33861
|
FileStatusSummary = class {
|
|
33857
|
-
constructor(
|
|
33858
|
-
this.path =
|
|
33862
|
+
constructor(path63, index, working_dir) {
|
|
33863
|
+
this.path = path63;
|
|
33859
33864
|
this.index = index;
|
|
33860
33865
|
this.working_dir = working_dir;
|
|
33861
33866
|
if (index === "R" || working_dir === "R") {
|
|
33862
|
-
const detail = fromPathRegex.exec(
|
|
33867
|
+
const detail = fromPathRegex.exec(path63) || [null, path63, path63];
|
|
33863
33868
|
this.from = detail[2] || "";
|
|
33864
33869
|
this.path = detail[1] || "";
|
|
33865
33870
|
}
|
|
@@ -33890,14 +33895,14 @@ function splitLine(result, lineStr) {
|
|
|
33890
33895
|
default:
|
|
33891
33896
|
return;
|
|
33892
33897
|
}
|
|
33893
|
-
function data(index, workingDir,
|
|
33898
|
+
function data(index, workingDir, path63) {
|
|
33894
33899
|
const raw = `${index}${workingDir}`;
|
|
33895
33900
|
const handler = parsers6.get(raw);
|
|
33896
33901
|
if (handler) {
|
|
33897
|
-
handler(result,
|
|
33902
|
+
handler(result, path63);
|
|
33898
33903
|
}
|
|
33899
33904
|
if (raw !== "##" && raw !== "!!") {
|
|
33900
|
-
result.files.push(new FileStatusSummary(
|
|
33905
|
+
result.files.push(new FileStatusSummary(path63, index, workingDir));
|
|
33901
33906
|
}
|
|
33902
33907
|
}
|
|
33903
33908
|
}
|
|
@@ -34206,9 +34211,9 @@ var init_simple_git_api = __esm2({
|
|
|
34206
34211
|
next
|
|
34207
34212
|
);
|
|
34208
34213
|
}
|
|
34209
|
-
hashObject(
|
|
34214
|
+
hashObject(path63, write) {
|
|
34210
34215
|
return this._runTask(
|
|
34211
|
-
hashObjectTask(
|
|
34216
|
+
hashObjectTask(path63, write === true),
|
|
34212
34217
|
trailingFunctionArgument(arguments)
|
|
34213
34218
|
);
|
|
34214
34219
|
}
|
|
@@ -34561,8 +34566,8 @@ var init_branch = __esm2({
|
|
|
34561
34566
|
}
|
|
34562
34567
|
});
|
|
34563
34568
|
function toPath(input) {
|
|
34564
|
-
const
|
|
34565
|
-
return
|
|
34569
|
+
const path63 = input.trim().replace(/^["']|["']$/g, "");
|
|
34570
|
+
return path63 && normalize3(path63);
|
|
34566
34571
|
}
|
|
34567
34572
|
var parseCheckIgnore;
|
|
34568
34573
|
var init_CheckIgnore = __esm2({
|
|
@@ -34876,8 +34881,8 @@ __export2(sub_module_exports, {
|
|
|
34876
34881
|
subModuleTask: () => subModuleTask,
|
|
34877
34882
|
updateSubModuleTask: () => updateSubModuleTask
|
|
34878
34883
|
});
|
|
34879
|
-
function addSubModuleTask(repo,
|
|
34880
|
-
return subModuleTask(["add", repo,
|
|
34884
|
+
function addSubModuleTask(repo, path63) {
|
|
34885
|
+
return subModuleTask(["add", repo, path63]);
|
|
34881
34886
|
}
|
|
34882
34887
|
function initSubModuleTask(customArgs) {
|
|
34883
34888
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -35210,8 +35215,8 @@ var require_git = __commonJS2({
|
|
|
35210
35215
|
}
|
|
35211
35216
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
35212
35217
|
};
|
|
35213
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
35214
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
35218
|
+
Git2.prototype.submoduleAdd = function(repo, path63, then) {
|
|
35219
|
+
return this._runTask(addSubModuleTask2(repo, path63), trailingFunctionArgument2(arguments));
|
|
35215
35220
|
};
|
|
35216
35221
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
35217
35222
|
return this._runTask(
|
|
@@ -35848,8 +35853,8 @@ async function runGitTask(fn) {
|
|
|
35848
35853
|
}
|
|
35849
35854
|
async function yieldToEventLoop2() {
|
|
35850
35855
|
throwIfGitShutdownRequested();
|
|
35851
|
-
await new Promise((
|
|
35852
|
-
setImmediate(
|
|
35856
|
+
await new Promise((resolve35) => {
|
|
35857
|
+
setImmediate(resolve35);
|
|
35853
35858
|
});
|
|
35854
35859
|
throwIfGitShutdownRequested();
|
|
35855
35860
|
}
|
|
@@ -35929,10 +35934,10 @@ async function discoverGitRepos(cwd = getBridgeRoot()) {
|
|
|
35929
35934
|
await yieldGitDiscoverWork(i + 1);
|
|
35930
35935
|
const ent = entries[i];
|
|
35931
35936
|
if (!ent.isDirectory()) continue;
|
|
35932
|
-
const
|
|
35933
|
-
if (await isGitRepoDirectory(
|
|
35934
|
-
const remoteUrl = await getRemoteOriginUrl(
|
|
35935
|
-
result.push({ absolutePath:
|
|
35937
|
+
const childPath2 = path17.join(cwdResolved, ent.name);
|
|
35938
|
+
if (await isGitRepoDirectory(childPath2)) {
|
|
35939
|
+
const remoteUrl = await getRemoteOriginUrl(childPath2);
|
|
35940
|
+
result.push({ absolutePath: childPath2, remoteUrl });
|
|
35936
35941
|
}
|
|
35937
35942
|
}
|
|
35938
35943
|
return result;
|
|
@@ -36184,9 +36189,9 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
36184
36189
|
// src/agents/acp/put-summarize-change-summaries.ts
|
|
36185
36190
|
async function putEncryptedChangeSummaryRows(params) {
|
|
36186
36191
|
const base = params.apiBaseUrl.replace(/\/+$/, "");
|
|
36187
|
-
const entries = params.rows.map(({ path:
|
|
36192
|
+
const entries = params.rows.map(({ path: path63, summary }) => {
|
|
36188
36193
|
const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
|
|
36189
|
-
return { path:
|
|
36194
|
+
return { path: path63, summary: JSON.stringify(enc) };
|
|
36190
36195
|
});
|
|
36191
36196
|
const res = await fetch(
|
|
36192
36197
|
`${base}/internal/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
|
|
@@ -37034,8 +37039,8 @@ async function commitSessionWorktree(cache2, params) {
|
|
|
37034
37039
|
}
|
|
37035
37040
|
|
|
37036
37041
|
// src/git/changes/parse/normalize-git-diff-path.ts
|
|
37037
|
-
function normalizeGitDiffPath(
|
|
37038
|
-
return
|
|
37042
|
+
function normalizeGitDiffPath(path63) {
|
|
37043
|
+
return path63.replace(/\\/g, "/").replace(/\/ +/g, "/").trim();
|
|
37039
37044
|
}
|
|
37040
37045
|
|
|
37041
37046
|
// src/git/changes/parse/expand-git-rename-numstat-path.ts
|
|
@@ -37135,8 +37140,8 @@ function parseNumstatEntries(lines) {
|
|
|
37135
37140
|
}
|
|
37136
37141
|
function parseNumstat(lines) {
|
|
37137
37142
|
const m = /* @__PURE__ */ new Map();
|
|
37138
|
-
for (const [
|
|
37139
|
-
m.set(
|
|
37143
|
+
for (const [path63, entry] of parseNumstatEntries(lines)) {
|
|
37144
|
+
m.set(path63, { additions: entry.additions, deletions: entry.deletions });
|
|
37140
37145
|
}
|
|
37141
37146
|
return m;
|
|
37142
37147
|
}
|
|
@@ -37574,24 +37579,45 @@ function truncatePatch(s) {
|
|
|
37574
37579
|
}
|
|
37575
37580
|
|
|
37576
37581
|
// src/git/changes/patch/unified-diff-for-file.ts
|
|
37582
|
+
var RENAME_DIFF_ARGS = ["-M", "--find-renames"];
|
|
37583
|
+
function devNullPath() {
|
|
37584
|
+
return process.platform === "win32" ? "NUL" : "/dev/null";
|
|
37585
|
+
}
|
|
37577
37586
|
function patchTextFromGitDiffOutput(raw) {
|
|
37578
37587
|
if (raw.trim() === "") return void 0;
|
|
37579
37588
|
return normalizePatchContent(raw);
|
|
37580
37589
|
}
|
|
37590
|
+
async function rawGitDiff(g, args) {
|
|
37591
|
+
return String(await g.raw([...args]).catch(() => ""));
|
|
37592
|
+
}
|
|
37593
|
+
async function unifiedDiffAgainstHead(g, pathInRepo, change, movedFromPathInRepo) {
|
|
37594
|
+
const args = change === "moved" && movedFromPathInRepo ? ["diff", "--no-color", ...RENAME_DIFF_ARGS, "HEAD", "--", movedFromPathInRepo, pathInRepo] : change === "removed" ? ["diff", "--no-color", ...RENAME_DIFF_ARGS, "HEAD", "--", pathInRepo] : ["diff", "--no-color", ...RENAME_DIFF_ARGS, "HEAD", "--", pathInRepo];
|
|
37595
|
+
return patchTextFromGitDiffOutput(await rawGitDiff(g, args));
|
|
37596
|
+
}
|
|
37597
|
+
async function unifiedDiffForAddedUntrackedFile(g, pathInRepo) {
|
|
37598
|
+
const raw = await rawGitDiff(g, [
|
|
37599
|
+
"diff",
|
|
37600
|
+
"--no-color",
|
|
37601
|
+
...RENAME_DIFF_ARGS,
|
|
37602
|
+
"--no-index",
|
|
37603
|
+
"--",
|
|
37604
|
+
devNullPath(),
|
|
37605
|
+
pathInRepo
|
|
37606
|
+
]);
|
|
37607
|
+
return patchTextFromGitDiffOutput(raw);
|
|
37608
|
+
}
|
|
37581
37609
|
async function unifiedDiffForFile(repoCwd, pathInRepo, change, movedFromPathInRepo) {
|
|
37582
37610
|
const g = cliSimpleGit(repoCwd);
|
|
37583
|
-
|
|
37584
|
-
|
|
37585
|
-
|
|
37586
|
-
|
|
37611
|
+
let patch = await unifiedDiffAgainstHead(g, pathInRepo, change, movedFromPathInRepo);
|
|
37612
|
+
if (!patch && change === "added") {
|
|
37613
|
+
patch = await unifiedDiffForAddedUntrackedFile(g, pathInRepo);
|
|
37614
|
+
}
|
|
37587
37615
|
return patch ? truncatePatch(patch) : void 0;
|
|
37588
37616
|
}
|
|
37589
37617
|
async function unifiedDiffForFileInRange(repoCwd, range, pathInRepo, change, movedFromPathInRepo) {
|
|
37590
37618
|
const g = cliSimpleGit(repoCwd);
|
|
37591
|
-
const
|
|
37592
|
-
const
|
|
37593
|
-
const raw = await g.raw([...args]).catch(() => "");
|
|
37594
|
-
const patch = patchTextFromGitDiffOutput(String(raw));
|
|
37619
|
+
const args = change === "moved" && movedFromPathInRepo ? ["diff", "--no-color", ...RENAME_DIFF_ARGS, "-U20000", range, "--", movedFromPathInRepo, pathInRepo] : ["diff", "--no-color", ...RENAME_DIFF_ARGS, "-U20000", range, "--", pathInRepo];
|
|
37620
|
+
const patch = patchTextFromGitDiffOutput(await rawGitDiff(g, args));
|
|
37595
37621
|
return patch ? truncatePatch(patch) : void 0;
|
|
37596
37622
|
}
|
|
37597
37623
|
|
|
@@ -37769,7 +37795,7 @@ async function parentForCommitDiff(g, sha) {
|
|
|
37769
37795
|
}
|
|
37770
37796
|
|
|
37771
37797
|
// src/git/changes/listing/rename-diff-args.ts
|
|
37772
|
-
var
|
|
37798
|
+
var RENAME_DIFF_ARGS2 = ["-M", "--find-renames"];
|
|
37773
37799
|
|
|
37774
37800
|
// src/git/changes/rows/pick-preferred-changed-file-row.ts
|
|
37775
37801
|
function rowRank(row) {
|
|
@@ -37822,7 +37848,7 @@ async function listChangedFilesForCommit(repoGitCwd, repoRelPath, commitSha, opt
|
|
|
37822
37848
|
const g = cliSimpleGit(repoGitCwd);
|
|
37823
37849
|
const normRel = normalizeRepoRelPath(repoRelPath);
|
|
37824
37850
|
const [nameStatusRaw, numstatRaw] = await Promise.all([
|
|
37825
|
-
g.raw(["diff-tree", "--no-commit-id", "--name-status", "-r", ...
|
|
37851
|
+
g.raw(["diff-tree", "--no-commit-id", "--name-status", "-r", ...RENAME_DIFF_ARGS2, commitSha]).catch(() => ""),
|
|
37826
37852
|
g.raw(["show", "--numstat", "--format=format:", commitSha]).catch(() => "")
|
|
37827
37853
|
]);
|
|
37828
37854
|
const parsed = parseDiffOutput(String(nameStatusRaw), String(numstatRaw));
|
|
@@ -38094,8 +38120,8 @@ async function enrichWorkingTreeFileRows(options) {
|
|
|
38094
38120
|
async function listChangedFilesForRepo(repoGitCwd, repoRelPath, options = {}) {
|
|
38095
38121
|
const g = cliSimpleGit(repoGitCwd);
|
|
38096
38122
|
const [nameStatusRaw, numstatRaw, untrackedRaw] = await Promise.all([
|
|
38097
|
-
g.raw(["diff", ...
|
|
38098
|
-
g.raw(["diff", ...
|
|
38123
|
+
g.raw(["diff", ...RENAME_DIFF_ARGS2, "--name-status", "HEAD"]).catch(() => ""),
|
|
38124
|
+
g.raw(["diff", ...RENAME_DIFF_ARGS2, "HEAD", "--numstat"]).catch(() => ""),
|
|
38099
38125
|
g.raw(["ls-files", "--others", "--exclude-standard"]).catch(() => "")
|
|
38100
38126
|
]);
|
|
38101
38127
|
const parsed = parseDiffOutput(String(nameStatusRaw), String(numstatRaw));
|
|
@@ -39362,7 +39388,7 @@ function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
|
39362
39388
|
}
|
|
39363
39389
|
|
|
39364
39390
|
// src/connection/create-bridge-connection.ts
|
|
39365
|
-
import * as
|
|
39391
|
+
import * as path61 from "node:path";
|
|
39366
39392
|
|
|
39367
39393
|
// src/dev-servers/manager/dev-server-manager.ts
|
|
39368
39394
|
import { rm as rm2 } from "node:fs/promises";
|
|
@@ -39384,15 +39410,15 @@ function sendDevServerStatus(getWs, serverId, status, options) {
|
|
|
39384
39410
|
|
|
39385
39411
|
// src/dev-servers/process/terminate-child-process.ts
|
|
39386
39412
|
async function sigtermAndWaitForExit(proc, graceMs, log2, shortId) {
|
|
39387
|
-
const exited = new Promise((
|
|
39388
|
-
proc.once("exit", () =>
|
|
39413
|
+
const exited = new Promise((resolve35) => {
|
|
39414
|
+
proc.once("exit", () => resolve35());
|
|
39389
39415
|
});
|
|
39390
39416
|
log2(`[dev-server] Sending SIGTERM to ${shortId} (pid=${proc.pid ?? "?"}).`);
|
|
39391
39417
|
try {
|
|
39392
39418
|
proc.kill("SIGTERM");
|
|
39393
39419
|
} catch {
|
|
39394
39420
|
}
|
|
39395
|
-
await Promise.race([exited, new Promise((
|
|
39421
|
+
await Promise.race([exited, new Promise((resolve35) => setTimeout(resolve35, graceMs))]);
|
|
39396
39422
|
}
|
|
39397
39423
|
function forceKillChild(proc, log2, shortId, graceMs) {
|
|
39398
39424
|
log2(
|
|
@@ -40273,7 +40299,7 @@ async function proxyToLocal(request) {
|
|
|
40273
40299
|
};
|
|
40274
40300
|
const maxAttempts = isIdempotentProxyMethod(request.method) ? LOCAL_PREVIEW_FETCH_RETRY_DELAYS_MS.length + 1 : 1;
|
|
40275
40301
|
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
40276
|
-
const once = await new Promise((
|
|
40302
|
+
const once = await new Promise((resolve35) => {
|
|
40277
40303
|
const req = mod.request(opts, (res) => {
|
|
40278
40304
|
const chunks = [];
|
|
40279
40305
|
res.on("data", (c) => chunks.push(c));
|
|
@@ -40284,7 +40310,7 @@ async function proxyToLocal(request) {
|
|
|
40284
40310
|
if (typeof v === "string") headers[k] = v;
|
|
40285
40311
|
else if (Array.isArray(v) && v[0]) headers[k] = v[0];
|
|
40286
40312
|
}
|
|
40287
|
-
|
|
40313
|
+
resolve35({
|
|
40288
40314
|
id: request.id,
|
|
40289
40315
|
statusCode: res.statusCode ?? 0,
|
|
40290
40316
|
headers,
|
|
@@ -40293,7 +40319,7 @@ async function proxyToLocal(request) {
|
|
|
40293
40319
|
});
|
|
40294
40320
|
});
|
|
40295
40321
|
req.on("error", (err) => {
|
|
40296
|
-
|
|
40322
|
+
resolve35({
|
|
40297
40323
|
id: request.id,
|
|
40298
40324
|
statusCode: 0,
|
|
40299
40325
|
headers: {},
|
|
@@ -40998,12 +41024,16 @@ var handleAgentConfigMessage = (msg, deps) => {
|
|
|
40998
41024
|
// src/prompt-turn-queue/client-report.ts
|
|
40999
41025
|
function sendPromptQueueClientReport(ws, queues) {
|
|
41000
41026
|
if (!ws) return false;
|
|
41001
|
-
|
|
41027
|
+
const wireQueues = {};
|
|
41028
|
+
for (const [queueKey, rows] of Object.entries(queues)) {
|
|
41029
|
+
wireQueues[queueKey] = rows.map((r) => ({ turnId: r.turnId, clientState: r.cliState }));
|
|
41030
|
+
}
|
|
41031
|
+
sendWsMessage(ws, { type: "prompt_queue_client_report", queues: wireQueues });
|
|
41002
41032
|
return true;
|
|
41003
41033
|
}
|
|
41004
41034
|
|
|
41005
41035
|
// src/prompt-turn-queue/disk-store.ts
|
|
41006
|
-
var
|
|
41036
|
+
var MERGEABLE_BRIDGE_SERVER_STATES = /* @__PURE__ */ new Set([
|
|
41007
41037
|
"queued",
|
|
41008
41038
|
"requeued",
|
|
41009
41039
|
"requeued_with_revert",
|
|
@@ -41035,7 +41065,7 @@ async function writePersistedQueue(file2) {
|
|
|
41035
41065
|
);
|
|
41036
41066
|
});
|
|
41037
41067
|
}
|
|
41038
|
-
async function
|
|
41068
|
+
async function mergeBridgeServerQueueSnapshot(queueKey, serverTurns) {
|
|
41039
41069
|
const prev = await readPersistedQueue(queueKey);
|
|
41040
41070
|
const turns = [];
|
|
41041
41071
|
for (const raw of serverTurns) {
|
|
@@ -41044,19 +41074,19 @@ async function mergeServerQueueSnapshot(queueKey, serverTurns) {
|
|
|
41044
41074
|
const turnId = typeof o.turnId === "string" ? o.turnId : "";
|
|
41045
41075
|
const sessionId = typeof o.sessionId === "string" ? o.sessionId : "";
|
|
41046
41076
|
const turnOrd = typeof o.turnOrd === "number" ? o.turnOrd : Number(o.turnOrd) || 0;
|
|
41047
|
-
const
|
|
41048
|
-
const
|
|
41077
|
+
const bridgeServerState = o.serverState ?? o.bridgeServerState;
|
|
41078
|
+
const lastCliState = o.lastClientState ?? o.lastCliState ?? null;
|
|
41049
41079
|
const payload = o.payload && typeof o.payload === "object" ? o.payload : {};
|
|
41050
41080
|
if (!turnId || !sessionId) continue;
|
|
41051
|
-
if (!
|
|
41081
|
+
if (!MERGEABLE_BRIDGE_SERVER_STATES.has(String(bridgeServerState))) continue;
|
|
41052
41082
|
const old = prev?.turns.find((t) => t.turnId === turnId);
|
|
41053
|
-
const
|
|
41083
|
+
const mergedCli = old?.lastCliState === "running" && lastCliState == null ? "running" : lastCliState;
|
|
41054
41084
|
turns.push({
|
|
41055
41085
|
turnId,
|
|
41056
41086
|
sessionId,
|
|
41057
41087
|
turnOrd,
|
|
41058
|
-
|
|
41059
|
-
|
|
41088
|
+
bridgeServerState,
|
|
41089
|
+
lastCliState: mergedCli,
|
|
41060
41090
|
payload
|
|
41061
41091
|
});
|
|
41062
41092
|
}
|
|
@@ -41094,15 +41124,12 @@ function dispatchLocalPrompt(next, deps) {
|
|
|
41094
41124
|
}
|
|
41095
41125
|
|
|
41096
41126
|
// src/prompt-turn-queue/runner/queue-selection.ts
|
|
41097
|
-
function isRunnableServerState(s) {
|
|
41098
|
-
return s === "queued" || s === "requeued" || s === "requeued_with_revert";
|
|
41099
|
-
}
|
|
41100
41127
|
function pickNextRunnableTurn(turns) {
|
|
41101
41128
|
for (const t of turns) {
|
|
41102
|
-
if (t.
|
|
41103
|
-
if (t.
|
|
41104
|
-
if (!
|
|
41105
|
-
if (t.
|
|
41129
|
+
if (t.bridgeServerState === "discarded" || t.bridgeServerState === "stopping") continue;
|
|
41130
|
+
if (t.bridgeServerState === "cancel_requested") continue;
|
|
41131
|
+
if (!isRunnableBridgePromptTurnServerState(t.bridgeServerState)) continue;
|
|
41132
|
+
if (t.lastCliState === "running" || t.lastCliState === "stopped" || t.lastCliState === "failed" || t.lastCliState === "cancelled") {
|
|
41106
41133
|
continue;
|
|
41107
41134
|
}
|
|
41108
41135
|
return t;
|
|
@@ -41110,7 +41137,7 @@ function pickNextRunnableTurn(turns) {
|
|
|
41110
41137
|
return null;
|
|
41111
41138
|
}
|
|
41112
41139
|
function hasRunningTurn(turns) {
|
|
41113
|
-
return turns.some((t) => t.
|
|
41140
|
+
return turns.some((t) => t.lastCliState === "running");
|
|
41114
41141
|
}
|
|
41115
41142
|
|
|
41116
41143
|
// src/prompt-turn-queue/runner/run-id-queue-key-map.ts
|
|
@@ -41127,7 +41154,7 @@ function deleteRunIdQueueKey(runId) {
|
|
|
41127
41154
|
return queueKey;
|
|
41128
41155
|
}
|
|
41129
41156
|
function syncRunningTurnQueueKeys(turns, queueKey) {
|
|
41130
|
-
for (const running of turns.filter((t) => t.
|
|
41157
|
+
for (const running of turns.filter((t) => t.lastCliState === "running")) {
|
|
41131
41158
|
runIdToQueueKey.set(running.turnId, queueKey);
|
|
41132
41159
|
}
|
|
41133
41160
|
}
|
|
@@ -41135,7 +41162,7 @@ function syncRunningTurnQueueKeys(turns, queueKey) {
|
|
|
41135
41162
|
// src/prompt-turn-queue/runner/run-local-revert-before-queued-prompt.ts
|
|
41136
41163
|
import fs38 from "node:fs";
|
|
41137
41164
|
async function runLocalRevertBeforeQueuedPrompt(next, deps) {
|
|
41138
|
-
if (next.
|
|
41165
|
+
if (next.bridgeServerState !== "requeued_with_revert") return true;
|
|
41139
41166
|
const sid = next.sessionId;
|
|
41140
41167
|
const pl = next.payload;
|
|
41141
41168
|
const tid = typeof pl.snapshotRevertTurnId === "string" && pl.snapshotRevertTurnId.trim() !== "" ? pl.snapshotRevertTurnId.trim() : next.turnId;
|
|
@@ -41165,9 +41192,9 @@ async function finalizePromptTurnOnBridge(getWs, runId, success2, opts) {
|
|
|
41165
41192
|
if (!f) return false;
|
|
41166
41193
|
const t = f.turns.find((x) => x.turnId === runId);
|
|
41167
41194
|
if (!t) return false;
|
|
41168
|
-
t.
|
|
41195
|
+
t.lastCliState = opts?.terminalCliState ?? (success2 ? "stopped" : "failed");
|
|
41169
41196
|
await writePersistedQueue(f);
|
|
41170
|
-
sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId,
|
|
41197
|
+
sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: runId, cliState: t.lastCliState }] });
|
|
41171
41198
|
return true;
|
|
41172
41199
|
}
|
|
41173
41200
|
|
|
@@ -41178,7 +41205,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
41178
41205
|
const getWs = deps.getWs;
|
|
41179
41206
|
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
41180
41207
|
if (!Array.isArray(serverTurns)) continue;
|
|
41181
|
-
const file2 = await
|
|
41208
|
+
const file2 = await mergeBridgeServerQueueSnapshot(queueKey, serverTurns);
|
|
41182
41209
|
await writePersistedQueue(file2);
|
|
41183
41210
|
}
|
|
41184
41211
|
for (const [queueKey, serverTurns] of Object.entries(raw)) {
|
|
@@ -41191,14 +41218,14 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
41191
41218
|
if (!Array.isArray(serverTurns)) continue;
|
|
41192
41219
|
const file2 = await readPersistedQueue(queueKey);
|
|
41193
41220
|
if (!file2) continue;
|
|
41194
|
-
const cancelRow = file2.turns.find((t) => t.
|
|
41221
|
+
const cancelRow = file2.turns.find((t) => t.bridgeServerState === "cancel_requested" && t.lastCliState === "running");
|
|
41195
41222
|
if (cancelRow) {
|
|
41196
41223
|
const localCancelHandled = await deps.acpManager.cancelRun(cancelRow.turnId);
|
|
41197
41224
|
if (!localCancelHandled) {
|
|
41198
41225
|
deps.log(
|
|
41199
|
-
`[Queue] server cancel_requested for ${cancelRow.turnId.slice(0, 8)}\u2026 but no local agent run is active (e.g. after CLI restart); marking cancelled and notifying bridge.`
|
|
41226
|
+
`[Queue] bridge server cancel_requested for ${cancelRow.turnId.slice(0, 8)}\u2026 but no local agent run is active (e.g. after CLI restart); marking cancelled and notifying bridge.`
|
|
41200
41227
|
);
|
|
41201
|
-
await finalizePromptTurnOnBridge(deps.getWs, cancelRow.turnId, false, {
|
|
41228
|
+
await finalizePromptTurnOnBridge(deps.getWs, cancelRow.turnId, false, { terminalCliState: "cancelled" });
|
|
41202
41229
|
const ws = deps.getWs();
|
|
41203
41230
|
if (ws && cancelRow.sessionId) {
|
|
41204
41231
|
sendWsMessage(ws, {
|
|
@@ -41223,16 +41250,16 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
41223
41250
|
const next = pickNextRunnableTurn(file2.turns);
|
|
41224
41251
|
if (!next) continue;
|
|
41225
41252
|
if (!await runLocalRevertBeforeQueuedPrompt(next, deps)) {
|
|
41226
|
-
next.
|
|
41253
|
+
next.lastCliState = "failed";
|
|
41227
41254
|
await writePersistedQueue(file2);
|
|
41228
|
-
sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: next.turnId,
|
|
41255
|
+
sendPromptQueueClientReport(getWs(), { [queueKey]: [{ turnId: next.turnId, cliState: "failed" }] });
|
|
41229
41256
|
continue;
|
|
41230
41257
|
}
|
|
41231
|
-
next.
|
|
41258
|
+
next.lastCliState = "running";
|
|
41232
41259
|
await writePersistedQueue(file2);
|
|
41233
41260
|
setRunIdQueueKey(next.turnId, queueKey);
|
|
41234
41261
|
startedThisTick.add(next.turnId);
|
|
41235
|
-
report[queueKey] = [{ turnId: next.turnId,
|
|
41262
|
+
report[queueKey] = [{ turnId: next.turnId, cliState: "running" }];
|
|
41236
41263
|
}
|
|
41237
41264
|
if (Object.keys(report).length > 0) {
|
|
41238
41265
|
sendPromptQueueClientReport(getWs(), report);
|
|
@@ -41241,7 +41268,7 @@ async function applyPromptQueueStateFromServer(msg, deps) {
|
|
|
41241
41268
|
if (!Array.isArray(serverTurns)) continue;
|
|
41242
41269
|
const file2 = await readPersistedQueue(queueKey);
|
|
41243
41270
|
if (!file2) continue;
|
|
41244
|
-
const running = file2.turns.find((t) => t.
|
|
41271
|
+
const running = file2.turns.find((t) => t.lastCliState === "running");
|
|
41245
41272
|
if (!running || !startedThisTick.has(running.turnId)) continue;
|
|
41246
41273
|
if (getRunIdQueueKey(running.turnId) !== queueKey) continue;
|
|
41247
41274
|
dispatchLocalPrompt(running, deps);
|
|
@@ -41268,7 +41295,7 @@ function createBridgePromptSenders(deps, getWs) {
|
|
|
41268
41295
|
getWs,
|
|
41269
41296
|
typeof pr.runId === "string" ? pr.runId : void 0,
|
|
41270
41297
|
pr.success === true,
|
|
41271
|
-
cancelled ? {
|
|
41298
|
+
cancelled ? { terminalCliState: "cancelled" } : void 0
|
|
41272
41299
|
).catch(() => {
|
|
41273
41300
|
});
|
|
41274
41301
|
}
|
|
@@ -41430,9 +41457,9 @@ function parseChangeSummarySnapshots(raw) {
|
|
|
41430
41457
|
for (const item of raw) {
|
|
41431
41458
|
if (!item || typeof item !== "object") continue;
|
|
41432
41459
|
const o = item;
|
|
41433
|
-
const
|
|
41434
|
-
if (!
|
|
41435
|
-
const row = { path:
|
|
41460
|
+
const path63 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
|
|
41461
|
+
if (!path63) continue;
|
|
41462
|
+
const row = { path: path63 };
|
|
41436
41463
|
if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
|
|
41437
41464
|
if (typeof o.oldText === "string") row.oldText = o.oldText;
|
|
41438
41465
|
if (typeof o.newText === "string") row.newText = o.newText;
|
|
@@ -41642,8 +41669,8 @@ function randomSecret() {
|
|
|
41642
41669
|
}
|
|
41643
41670
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
41644
41671
|
}
|
|
41645
|
-
async function requestPreviewApi(port, secret, method,
|
|
41646
|
-
const url2 = `http://127.0.0.1:${port}${
|
|
41672
|
+
async function requestPreviewApi(port, secret, method, path63, body) {
|
|
41673
|
+
const url2 = `http://127.0.0.1:${port}${path63}`;
|
|
41647
41674
|
const headers = {
|
|
41648
41675
|
[PREVIEW_SECRET_HEADER]: secret,
|
|
41649
41676
|
"Content-Type": "application/json"
|
|
@@ -41655,7 +41682,7 @@ async function requestPreviewApi(port, secret, method, path62, body) {
|
|
|
41655
41682
|
});
|
|
41656
41683
|
const data = await res.json().catch(() => ({}));
|
|
41657
41684
|
if (!res.ok) {
|
|
41658
|
-
throw new Error(data?.error ?? `Preview API ${method} ${
|
|
41685
|
+
throw new Error(data?.error ?? `Preview API ${method} ${path63}: ${res.status}`);
|
|
41659
41686
|
}
|
|
41660
41687
|
return data;
|
|
41661
41688
|
}
|
|
@@ -41819,6 +41846,17 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
|
41819
41846
|
);
|
|
41820
41847
|
};
|
|
41821
41848
|
|
|
41849
|
+
// src/files/resolve-file-browser-session-parent.ts
|
|
41850
|
+
async function resolveFileBrowserSessionParent(sessionWorktreeManager, sessionId) {
|
|
41851
|
+
const sid = sessionId?.trim();
|
|
41852
|
+
if (sid) {
|
|
41853
|
+
await sessionWorktreeManager.ensureRepoCheckoutPathsForSessionAsync(sid);
|
|
41854
|
+
const worktreeRoot = sessionWorktreeManager.getSessionWorktreeRootForSession(sid);
|
|
41855
|
+
if (worktreeRoot) return worktreeRoot;
|
|
41856
|
+
}
|
|
41857
|
+
return getBridgeRoot();
|
|
41858
|
+
}
|
|
41859
|
+
|
|
41822
41860
|
// src/files/list-dir/index.ts
|
|
41823
41861
|
import fs40 from "node:fs";
|
|
41824
41862
|
|
|
@@ -41890,10 +41928,447 @@ async function listDirAsync(relativePath, sessionParentPath = getBridgeRoot()) {
|
|
|
41890
41928
|
}
|
|
41891
41929
|
}
|
|
41892
41930
|
|
|
41931
|
+
// src/files/handle-file-browser-search.ts
|
|
41932
|
+
import path55 from "node:path";
|
|
41933
|
+
var SEARCH_LIMIT = 100;
|
|
41934
|
+
function handleFileBrowserSearch(msg, socket, e2ee, sessionWorktreeManager) {
|
|
41935
|
+
void (async () => {
|
|
41936
|
+
await yieldToEventLoop();
|
|
41937
|
+
const q = typeof msg.q === "string" ? msg.q : "";
|
|
41938
|
+
const sessionParentPath = path55.resolve(
|
|
41939
|
+
sessionWorktreeManager != null ? await resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : getBridgeRoot()
|
|
41940
|
+
);
|
|
41941
|
+
if (!await bridgeFileIndexIsPopulated(sessionParentPath)) {
|
|
41942
|
+
const payload2 = {
|
|
41943
|
+
type: "file_browser_search_response",
|
|
41944
|
+
id: msg.id,
|
|
41945
|
+
paths: [],
|
|
41946
|
+
indexReady: false
|
|
41947
|
+
};
|
|
41948
|
+
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload2, ["paths"]) : payload2);
|
|
41949
|
+
return;
|
|
41950
|
+
}
|
|
41951
|
+
const results = await searchBridgeFilePathsAsync(sessionParentPath, q, SEARCH_LIMIT);
|
|
41952
|
+
const payload = {
|
|
41953
|
+
type: "file_browser_search_response",
|
|
41954
|
+
id: msg.id,
|
|
41955
|
+
paths: results,
|
|
41956
|
+
indexReady: true
|
|
41957
|
+
};
|
|
41958
|
+
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["paths"]) : payload);
|
|
41959
|
+
})();
|
|
41960
|
+
}
|
|
41961
|
+
function triggerFileIndexBuild(sessionParentPath = getBridgeRoot()) {
|
|
41962
|
+
setImmediate(() => {
|
|
41963
|
+
void ensureFileIndexAsync(sessionParentPath).catch((e) => {
|
|
41964
|
+
console.error("[file-index] Background build failed:", e);
|
|
41965
|
+
});
|
|
41966
|
+
});
|
|
41967
|
+
}
|
|
41968
|
+
|
|
41969
|
+
// src/git/tree/resolve-repo-abs-path.ts
|
|
41970
|
+
import * as path56 from "node:path";
|
|
41971
|
+
function resolveRepoAbsPathFromBridge(repoRelPath, bridgeRoot = getBridgeRoot()) {
|
|
41972
|
+
const bridgeResolved = path56.resolve(bridgeRoot);
|
|
41973
|
+
const rel = repoRelPath.trim() === "." ? "" : repoRelPath.trim().replace(/\\/g, "/");
|
|
41974
|
+
const repoPath = rel === "" ? bridgeResolved : path56.join(bridgeResolved, rel);
|
|
41975
|
+
const resolved = path56.resolve(repoPath);
|
|
41976
|
+
if (!resolved.startsWith(bridgeResolved + path56.sep) && resolved !== bridgeResolved) {
|
|
41977
|
+
return null;
|
|
41978
|
+
}
|
|
41979
|
+
return resolved;
|
|
41980
|
+
}
|
|
41981
|
+
|
|
41982
|
+
// src/git/tree/resolve-branch-commit.ts
|
|
41983
|
+
async function resolveBranchCommit(repoAbsPath, branch) {
|
|
41984
|
+
const branchRef = branch.trim();
|
|
41985
|
+
if (!branchRef) return null;
|
|
41986
|
+
try {
|
|
41987
|
+
return (await cliSimpleGit(repoAbsPath).revparse([`${branchRef}^{commit}`])).trim();
|
|
41988
|
+
} catch {
|
|
41989
|
+
return null;
|
|
41990
|
+
}
|
|
41991
|
+
}
|
|
41992
|
+
|
|
41993
|
+
// src/git/tree/list-git-tree-dir.ts
|
|
41994
|
+
function parseLsTreeLine(line) {
|
|
41995
|
+
const tab = line.indexOf(" ");
|
|
41996
|
+
if (tab < 0) return null;
|
|
41997
|
+
const meta = line.slice(0, tab).trim().split(/\s+/);
|
|
41998
|
+
if (meta.length < 3) return null;
|
|
41999
|
+
const mode = meta[0];
|
|
42000
|
+
const objectType2 = meta[1];
|
|
42001
|
+
let name = line.slice(tab + 1);
|
|
42002
|
+
if (name.startsWith('"') && name.endsWith('"')) {
|
|
42003
|
+
name = name.slice(1, -1).replace(/\\n/g, "\n").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
42004
|
+
}
|
|
42005
|
+
return { mode, objectType: objectType2, name };
|
|
42006
|
+
}
|
|
42007
|
+
function childPath(relativePath, name) {
|
|
42008
|
+
const base = relativePath.replace(/^\/+/, "").replace(/\\/g, "/");
|
|
42009
|
+
if (!base || base === ".") return name;
|
|
42010
|
+
return `${base}/${name}`.replace(/\\/g, "/");
|
|
42011
|
+
}
|
|
42012
|
+
function lsTreeArgs(commit, relativePath) {
|
|
42013
|
+
const rel = relativePath.replace(/^\/+/, "").replace(/\\/g, "/");
|
|
42014
|
+
if (!rel || rel === ".") return ["ls-tree", commit];
|
|
42015
|
+
return ["ls-tree", `${commit}:${rel}`];
|
|
42016
|
+
}
|
|
42017
|
+
async function listGitTreeDirAsync(repoAbsPath, branch, relativePath) {
|
|
42018
|
+
await yieldToEventLoop();
|
|
42019
|
+
const commit = await resolveBranchCommit(repoAbsPath, branch);
|
|
42020
|
+
if (!commit) return { error: "Branch not found" };
|
|
42021
|
+
try {
|
|
42022
|
+
const raw = await cliSimpleGit(repoAbsPath).raw(lsTreeArgs(commit, relativePath));
|
|
42023
|
+
await yieldToEventLoop();
|
|
42024
|
+
const lines = String(raw ?? "").split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
42025
|
+
const entries = [];
|
|
42026
|
+
for (let i = 0; i < lines.length; i++) {
|
|
42027
|
+
if (i > 0 && i % LIST_DIR_YIELD_EVERY === 0) {
|
|
42028
|
+
await yieldToEventLoop();
|
|
42029
|
+
}
|
|
42030
|
+
const parsed = parseLsTreeLine(lines[i]);
|
|
42031
|
+
if (!parsed) continue;
|
|
42032
|
+
const { mode, objectType: objectType2, name } = parsed;
|
|
42033
|
+
if (!name || name === "." || name === "..") continue;
|
|
42034
|
+
const isSymlink = mode === "120000";
|
|
42035
|
+
const isDir = objectType2 === "tree";
|
|
42036
|
+
entries.push({
|
|
42037
|
+
name,
|
|
42038
|
+
path: childPath(relativePath, name),
|
|
42039
|
+
isDir,
|
|
42040
|
+
...isSymlink ? { isSymlink: true } : {}
|
|
42041
|
+
});
|
|
42042
|
+
}
|
|
42043
|
+
if (entries.length >= LIST_DIR_YIELD_EVERY) {
|
|
42044
|
+
await yieldToEventLoop();
|
|
42045
|
+
}
|
|
42046
|
+
return { entries: sortListEntries(entries) };
|
|
42047
|
+
} catch (err) {
|
|
42048
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
42049
|
+
if (/not a tree object|does not exist|bad revision/i.test(message)) {
|
|
42050
|
+
return { error: "Path not found in branch" };
|
|
42051
|
+
}
|
|
42052
|
+
return { error: message };
|
|
42053
|
+
}
|
|
42054
|
+
}
|
|
42055
|
+
|
|
41893
42056
|
// src/files/read-file/types.ts
|
|
41894
42057
|
var LINE_CHUNK_SIZE = 64 * 1024;
|
|
41895
42058
|
var READ_RANGE_YIELD_EVERY_BYTES = 256 * 1024;
|
|
41896
42059
|
|
|
42060
|
+
// src/files/read-file/guess-mime-type.ts
|
|
42061
|
+
var MIME_BY_EXT = {
|
|
42062
|
+
png: "image/png",
|
|
42063
|
+
jpg: "image/jpeg",
|
|
42064
|
+
jpeg: "image/jpeg",
|
|
42065
|
+
gif: "image/gif",
|
|
42066
|
+
bmp: "image/bmp",
|
|
42067
|
+
ico: "image/x-icon",
|
|
42068
|
+
webp: "image/webp",
|
|
42069
|
+
avif: "image/avif",
|
|
42070
|
+
svg: "image/svg+xml",
|
|
42071
|
+
pdf: "application/pdf",
|
|
42072
|
+
json: "application/json",
|
|
42073
|
+
html: "text/html",
|
|
42074
|
+
htm: "text/html",
|
|
42075
|
+
css: "text/css",
|
|
42076
|
+
js: "text/javascript",
|
|
42077
|
+
mjs: "text/javascript",
|
|
42078
|
+
ts: "text/typescript",
|
|
42079
|
+
txt: "text/plain",
|
|
42080
|
+
md: "text/markdown",
|
|
42081
|
+
xml: "application/xml",
|
|
42082
|
+
zip: "application/zip",
|
|
42083
|
+
gz: "application/gzip",
|
|
42084
|
+
wasm: "application/wasm"
|
|
42085
|
+
};
|
|
42086
|
+
function guessMimeType(filePath) {
|
|
42087
|
+
const ext = filePath.split(".").pop()?.toLowerCase() ?? "";
|
|
42088
|
+
return MIME_BY_EXT[ext] ?? "application/octet-stream";
|
|
42089
|
+
}
|
|
42090
|
+
|
|
42091
|
+
// src/git/tree/file/git-blob-ref.ts
|
|
42092
|
+
async function gitBlobRef(repoAbsPath, branch, relativePath) {
|
|
42093
|
+
const commit = await resolveBranchCommit(repoAbsPath, branch);
|
|
42094
|
+
await yieldToEventLoop();
|
|
42095
|
+
if (!commit) return null;
|
|
42096
|
+
const rel = relativePath.replace(/^\/+/, "").replace(/\\/g, "/");
|
|
42097
|
+
if (!rel || rel === ".") return null;
|
|
42098
|
+
return `${commit}:${rel}`;
|
|
42099
|
+
}
|
|
42100
|
+
|
|
42101
|
+
// src/git/tree/file/is-binary-buffer.ts
|
|
42102
|
+
function isBinaryBuffer(buf) {
|
|
42103
|
+
const sample = buf.subarray(0, Math.min(buf.length, 8192));
|
|
42104
|
+
for (let i = 0; i < sample.length; i++) {
|
|
42105
|
+
if (sample[i] === 0) return true;
|
|
42106
|
+
}
|
|
42107
|
+
return false;
|
|
42108
|
+
}
|
|
42109
|
+
|
|
42110
|
+
// src/git/tree/file/read-git-blob-text-async.ts
|
|
42111
|
+
import { StringDecoder } from "node:string_decoder";
|
|
42112
|
+
async function countGitBlobLinesAsync(buf) {
|
|
42113
|
+
if (buf.length === 0) return 1;
|
|
42114
|
+
let lines = 1;
|
|
42115
|
+
let bytesSinceYield = 0;
|
|
42116
|
+
for (let i = 0; i < buf.length; i++) {
|
|
42117
|
+
const b = buf[i];
|
|
42118
|
+
if (b === 10) {
|
|
42119
|
+
lines++;
|
|
42120
|
+
} else if (b === 13) {
|
|
42121
|
+
if (i + 1 < buf.length && buf[i + 1] === 10) {
|
|
42122
|
+
lines++;
|
|
42123
|
+
i++;
|
|
42124
|
+
} else {
|
|
42125
|
+
lines++;
|
|
42126
|
+
}
|
|
42127
|
+
}
|
|
42128
|
+
bytesSinceYield++;
|
|
42129
|
+
if (bytesSinceYield >= READ_RANGE_YIELD_EVERY_BYTES) {
|
|
42130
|
+
await yieldToEventLoop();
|
|
42131
|
+
bytesSinceYield = 0;
|
|
42132
|
+
}
|
|
42133
|
+
}
|
|
42134
|
+
return lines;
|
|
42135
|
+
}
|
|
42136
|
+
async function readGitBlobLineRangeAsync(buf, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
42137
|
+
const bufSize = 64 * 1024;
|
|
42138
|
+
const decoder = new StringDecoder("utf8");
|
|
42139
|
+
let currentLine = 0;
|
|
42140
|
+
const resultLines = [];
|
|
42141
|
+
let partial2 = "";
|
|
42142
|
+
let done = false;
|
|
42143
|
+
let skipLine0Chars = typeof lineOffsetIn === "number" ? lineOffsetIn : 0;
|
|
42144
|
+
let line0CharsReturned = 0;
|
|
42145
|
+
let line0Accum = "";
|
|
42146
|
+
let bytesSinceYield = 0;
|
|
42147
|
+
let position = 0;
|
|
42148
|
+
const finish = async () => {
|
|
42149
|
+
const totalLines = await countGitBlobLinesAsync(buf);
|
|
42150
|
+
return { content: resultLines.join("\n"), totalLines };
|
|
42151
|
+
};
|
|
42152
|
+
while (!done && position < buf.length) {
|
|
42153
|
+
const chunkEnd = Math.min(position + bufSize, buf.length);
|
|
42154
|
+
const bytesRead = chunkEnd - position;
|
|
42155
|
+
position = chunkEnd;
|
|
42156
|
+
bytesSinceYield += bytesRead;
|
|
42157
|
+
if (bytesSinceYield >= READ_RANGE_YIELD_EVERY_BYTES) {
|
|
42158
|
+
await yieldToEventLoop();
|
|
42159
|
+
bytesSinceYield = 0;
|
|
42160
|
+
}
|
|
42161
|
+
const text = partial2 + decoder.write(buf.subarray(position - bytesRead, position));
|
|
42162
|
+
partial2 = "";
|
|
42163
|
+
let lineStart = 0;
|
|
42164
|
+
for (let i = 0; i < text.length; i++) {
|
|
42165
|
+
if (text[i] === "\n") {
|
|
42166
|
+
const lineContent = (() => {
|
|
42167
|
+
let lineEnd = i;
|
|
42168
|
+
if (lineEnd > lineStart && text[lineEnd - 1] === "\r") lineEnd--;
|
|
42169
|
+
return text.slice(lineStart, lineEnd);
|
|
42170
|
+
})();
|
|
42171
|
+
if (currentLine === 0 && (startLine === 0 || lineOffsetIn !== void 0)) {
|
|
42172
|
+
line0Accum += lineContent;
|
|
42173
|
+
const totalLine0 = line0Accum.length;
|
|
42174
|
+
if (skipLine0Chars > 0) {
|
|
42175
|
+
if (totalLine0 <= skipLine0Chars) {
|
|
42176
|
+
skipLine0Chars -= totalLine0;
|
|
42177
|
+
line0Accum = "";
|
|
42178
|
+
currentLine++;
|
|
42179
|
+
lineStart = i + 1;
|
|
42180
|
+
if (currentLine > endLine) {
|
|
42181
|
+
done = true;
|
|
42182
|
+
break;
|
|
42183
|
+
}
|
|
42184
|
+
continue;
|
|
42185
|
+
}
|
|
42186
|
+
const from = skipLine0Chars;
|
|
42187
|
+
const take = Math.min(lineChunkSize, totalLine0 - from);
|
|
42188
|
+
resultLines.push(line0Accum.slice(from, from + take));
|
|
42189
|
+
line0CharsReturned += take;
|
|
42190
|
+
if (from + take < totalLine0) {
|
|
42191
|
+
const totalLines = await countGitBlobLinesAsync(buf);
|
|
42192
|
+
return {
|
|
42193
|
+
content: resultLines.join("\n"),
|
|
42194
|
+
totalLines,
|
|
42195
|
+
lineOffset: lineOffsetIn + line0CharsReturned
|
|
42196
|
+
};
|
|
42197
|
+
}
|
|
42198
|
+
line0Accum = "";
|
|
42199
|
+
skipLine0Chars = 0;
|
|
42200
|
+
line0CharsReturned = 0;
|
|
42201
|
+
} else if (totalLine0 > lineChunkSize) {
|
|
42202
|
+
resultLines.push(line0Accum.slice(0, lineChunkSize));
|
|
42203
|
+
const totalLines = await countGitBlobLinesAsync(buf);
|
|
42204
|
+
return {
|
|
42205
|
+
content: resultLines.join("\n"),
|
|
42206
|
+
totalLines,
|
|
42207
|
+
lineOffset: lineChunkSize
|
|
42208
|
+
};
|
|
42209
|
+
} else {
|
|
42210
|
+
resultLines.push(line0Accum);
|
|
42211
|
+
line0Accum = "";
|
|
42212
|
+
}
|
|
42213
|
+
} else if (currentLine >= startLine && currentLine <= endLine) {
|
|
42214
|
+
resultLines.push(lineContent);
|
|
42215
|
+
}
|
|
42216
|
+
currentLine++;
|
|
42217
|
+
lineStart = i + 1;
|
|
42218
|
+
if (currentLine > endLine) {
|
|
42219
|
+
done = true;
|
|
42220
|
+
break;
|
|
42221
|
+
}
|
|
42222
|
+
}
|
|
42223
|
+
}
|
|
42224
|
+
if (!done) {
|
|
42225
|
+
const lineContent = text.slice(lineStart);
|
|
42226
|
+
if (currentLine === 0 && (startLine === 0 || lineOffsetIn !== void 0)) {
|
|
42227
|
+
line0Accum += lineContent;
|
|
42228
|
+
const totalLine0 = line0Accum.length;
|
|
42229
|
+
if (skipLine0Chars > 0) {
|
|
42230
|
+
if (totalLine0 <= skipLine0Chars) {
|
|
42231
|
+
skipLine0Chars -= totalLine0;
|
|
42232
|
+
line0Accum = "";
|
|
42233
|
+
} else {
|
|
42234
|
+
const from = skipLine0Chars;
|
|
42235
|
+
const take = Math.min(lineChunkSize, totalLine0 - from);
|
|
42236
|
+
resultLines.push(line0Accum.slice(from, from + take));
|
|
42237
|
+
const totalLines = await countGitBlobLinesAsync(buf);
|
|
42238
|
+
return {
|
|
42239
|
+
content: resultLines.join("\n"),
|
|
42240
|
+
totalLines,
|
|
42241
|
+
lineOffset: (lineOffsetIn ?? 0) + take
|
|
42242
|
+
};
|
|
42243
|
+
}
|
|
42244
|
+
} else if (totalLine0 > lineChunkSize) {
|
|
42245
|
+
resultLines.push(line0Accum.slice(0, lineChunkSize));
|
|
42246
|
+
const totalLines = await countGitBlobLinesAsync(buf);
|
|
42247
|
+
return {
|
|
42248
|
+
content: resultLines.join("\n"),
|
|
42249
|
+
totalLines,
|
|
42250
|
+
lineOffset: lineChunkSize
|
|
42251
|
+
};
|
|
42252
|
+
}
|
|
42253
|
+
}
|
|
42254
|
+
partial2 = text.slice(lineStart);
|
|
42255
|
+
}
|
|
42256
|
+
}
|
|
42257
|
+
if (!done) {
|
|
42258
|
+
const tail = partial2 + decoder.end();
|
|
42259
|
+
if (currentLine === 0 && (startLine === 0 || lineOffsetIn !== void 0) && tail.length > 0) {
|
|
42260
|
+
line0Accum += tail.endsWith("\r") ? tail.slice(0, -1) : tail;
|
|
42261
|
+
const totalLine0 = line0Accum.length;
|
|
42262
|
+
if (skipLine0Chars > 0) {
|
|
42263
|
+
if (totalLine0 <= skipLine0Chars) {
|
|
42264
|
+
return finish();
|
|
42265
|
+
}
|
|
42266
|
+
const from = skipLine0Chars;
|
|
42267
|
+
const take = Math.min(lineChunkSize, totalLine0 - from);
|
|
42268
|
+
resultLines.push(line0Accum.slice(from, from + take));
|
|
42269
|
+
line0CharsReturned += take;
|
|
42270
|
+
if (from + take < totalLine0) {
|
|
42271
|
+
const totalLines = await countGitBlobLinesAsync(buf);
|
|
42272
|
+
return {
|
|
42273
|
+
content: resultLines.join("\n"),
|
|
42274
|
+
totalLines,
|
|
42275
|
+
lineOffset: (lineOffsetIn ?? 0) + line0CharsReturned
|
|
42276
|
+
};
|
|
42277
|
+
}
|
|
42278
|
+
} else if (totalLine0 > lineChunkSize) {
|
|
42279
|
+
resultLines.push(line0Accum.slice(0, lineChunkSize));
|
|
42280
|
+
const totalLines = await countGitBlobLinesAsync(buf);
|
|
42281
|
+
return {
|
|
42282
|
+
content: resultLines.join("\n"),
|
|
42283
|
+
totalLines,
|
|
42284
|
+
lineOffset: lineChunkSize
|
|
42285
|
+
};
|
|
42286
|
+
} else {
|
|
42287
|
+
resultLines.push(line0Accum);
|
|
42288
|
+
}
|
|
42289
|
+
} else if (tail.length > 0 && currentLine >= startLine && currentLine <= endLine) {
|
|
42290
|
+
resultLines.push(tail.endsWith("\r") ? tail.slice(0, -1) : tail);
|
|
42291
|
+
}
|
|
42292
|
+
}
|
|
42293
|
+
return finish();
|
|
42294
|
+
}
|
|
42295
|
+
async function decodeGitBlobUtf8Async(buf) {
|
|
42296
|
+
await yieldToEventLoop();
|
|
42297
|
+
const text = buf.toString("utf8");
|
|
42298
|
+
await yieldToEventLoop();
|
|
42299
|
+
return text;
|
|
42300
|
+
}
|
|
42301
|
+
async function readGitBlobUtf8FullAsync(buf) {
|
|
42302
|
+
const text = await decodeGitBlobUtf8Async(buf);
|
|
42303
|
+
const totalLines = await countGitBlobLinesAsync(buf);
|
|
42304
|
+
return { content: text, totalLines };
|
|
42305
|
+
}
|
|
42306
|
+
|
|
42307
|
+
// src/git/tree/file/index.ts
|
|
42308
|
+
async function readGitTreeFileAsync(repoAbsPath, branch, relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE, encoding = "utf8") {
|
|
42309
|
+
await yieldToEventLoop();
|
|
42310
|
+
const branchRef = branch.trim();
|
|
42311
|
+
if (!branchRef) return { error: "branch required" };
|
|
42312
|
+
const rel = relativePath.replace(/^\/+/, "").replace(/\\/g, "/");
|
|
42313
|
+
if (!rel || rel === ".") return { error: "file path required" };
|
|
42314
|
+
const blobRef = await gitBlobRef(repoAbsPath, branchRef, rel);
|
|
42315
|
+
if (!blobRef) return { error: "Branch not found" };
|
|
42316
|
+
const hasRange = typeof startLine === "number" && typeof endLine === "number";
|
|
42317
|
+
try {
|
|
42318
|
+
if (encoding === "base64") {
|
|
42319
|
+
if (hasRange) return { error: "base64 encoding requires a full file read (no line range)" };
|
|
42320
|
+
const buf2 = await cliSimpleGit(repoAbsPath).showBuffer([blobRef]);
|
|
42321
|
+
await yieldToEventLoop();
|
|
42322
|
+
return {
|
|
42323
|
+
content: buf2.toString("base64"),
|
|
42324
|
+
size: buf2.length,
|
|
42325
|
+
mimeType: guessMimeType(rel)
|
|
42326
|
+
};
|
|
42327
|
+
}
|
|
42328
|
+
const buf = await cliSimpleGit(repoAbsPath).showBuffer([blobRef]);
|
|
42329
|
+
await yieldToEventLoop();
|
|
42330
|
+
const size = buf.length;
|
|
42331
|
+
if (isBinaryBuffer(buf)) {
|
|
42332
|
+
return { error: "Binary file cannot be displayed as text" };
|
|
42333
|
+
}
|
|
42334
|
+
if (hasRange) {
|
|
42335
|
+
const ranged = await readGitBlobLineRangeAsync(buf, startLine, endLine, lineOffset, lineChunkSize);
|
|
42336
|
+
return {
|
|
42337
|
+
content: ranged.content,
|
|
42338
|
+
totalLines: ranged.totalLines,
|
|
42339
|
+
size,
|
|
42340
|
+
...ranged.lineOffset != null ? { lineOffset: ranged.lineOffset } : {}
|
|
42341
|
+
};
|
|
42342
|
+
}
|
|
42343
|
+
const full = await readGitBlobUtf8FullAsync(buf);
|
|
42344
|
+
return { content: full.content, totalLines: full.totalLines, size, mimeType: guessMimeType(rel) };
|
|
42345
|
+
} catch (err) {
|
|
42346
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
42347
|
+
if (/does not exist|bad revision|exists on disk, but not in/i.test(message)) {
|
|
42348
|
+
return { error: "File not found in branch" };
|
|
42349
|
+
}
|
|
42350
|
+
return { error: message };
|
|
42351
|
+
}
|
|
42352
|
+
}
|
|
42353
|
+
|
|
42354
|
+
// src/files/browser/send-file-browser-message.ts
|
|
42355
|
+
function sendFileBrowserMessage(socket, e2ee, payload) {
|
|
42356
|
+
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["entries", "content", "totalLines", "size", "lineOffset"]) : payload);
|
|
42357
|
+
}
|
|
42358
|
+
|
|
42359
|
+
// src/files/browser/handle-file-browser-list.ts
|
|
42360
|
+
async function handleFileBrowserList(socket, e2ee, id, reqPath, sessionParentPath, gitScope) {
|
|
42361
|
+
const result = gitScope ? await listGitTreeDirAsync(gitScope.repoAbsPath, gitScope.branch, reqPath) : await listDirAsync(reqPath, sessionParentPath);
|
|
42362
|
+
if ("error" in result) {
|
|
42363
|
+
sendWsMessage(socket, { type: "file_browser_response", id, error: result.error });
|
|
42364
|
+
return;
|
|
42365
|
+
}
|
|
42366
|
+
sendFileBrowserMessage(socket, e2ee, { type: "file_browser_response", id, entries: result.entries });
|
|
42367
|
+
if (!gitScope && (reqPath === "." || reqPath === "")) {
|
|
42368
|
+
triggerFileIndexBuild(sessionParentPath);
|
|
42369
|
+
}
|
|
42370
|
+
}
|
|
42371
|
+
|
|
41897
42372
|
// src/files/read-file/resolve-file-path.ts
|
|
41898
42373
|
import fs41 from "node:fs";
|
|
41899
42374
|
async function resolveFilePathAsync(relativePath, sessionParentPath = getBridgeRoot()) {
|
|
@@ -41916,13 +42391,13 @@ async function resolveFilePathAsync(relativePath, sessionParentPath = getBridgeR
|
|
|
41916
42391
|
|
|
41917
42392
|
// src/files/read-file/read-file-range-async.ts
|
|
41918
42393
|
import fs42 from "node:fs";
|
|
41919
|
-
import { StringDecoder } from "node:string_decoder";
|
|
42394
|
+
import { StringDecoder as StringDecoder2 } from "node:string_decoder";
|
|
41920
42395
|
async function readFileRangeAsync(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
41921
42396
|
const fileSize = (await fs42.promises.stat(filePath)).size;
|
|
41922
42397
|
const fd = await fs42.promises.open(filePath, "r");
|
|
41923
42398
|
const bufSize = 64 * 1024;
|
|
41924
42399
|
const buf = Buffer.alloc(bufSize);
|
|
41925
|
-
const decoder = new
|
|
42400
|
+
const decoder = new StringDecoder2("utf8");
|
|
41926
42401
|
let currentLine = 0;
|
|
41927
42402
|
const resultLines = [];
|
|
41928
42403
|
let partial2 = "";
|
|
@@ -42116,37 +42591,6 @@ async function readFileFullAsync(filePath) {
|
|
|
42116
42591
|
return { content: raw, totalLines: lines.length, size };
|
|
42117
42592
|
}
|
|
42118
42593
|
|
|
42119
|
-
// src/files/read-file/guess-mime-type.ts
|
|
42120
|
-
var MIME_BY_EXT = {
|
|
42121
|
-
png: "image/png",
|
|
42122
|
-
jpg: "image/jpeg",
|
|
42123
|
-
jpeg: "image/jpeg",
|
|
42124
|
-
gif: "image/gif",
|
|
42125
|
-
bmp: "image/bmp",
|
|
42126
|
-
ico: "image/x-icon",
|
|
42127
|
-
webp: "image/webp",
|
|
42128
|
-
avif: "image/avif",
|
|
42129
|
-
svg: "image/svg+xml",
|
|
42130
|
-
pdf: "application/pdf",
|
|
42131
|
-
json: "application/json",
|
|
42132
|
-
html: "text/html",
|
|
42133
|
-
htm: "text/html",
|
|
42134
|
-
css: "text/css",
|
|
42135
|
-
js: "text/javascript",
|
|
42136
|
-
mjs: "text/javascript",
|
|
42137
|
-
ts: "text/typescript",
|
|
42138
|
-
txt: "text/plain",
|
|
42139
|
-
md: "text/markdown",
|
|
42140
|
-
xml: "application/xml",
|
|
42141
|
-
zip: "application/zip",
|
|
42142
|
-
gz: "application/gzip",
|
|
42143
|
-
wasm: "application/wasm"
|
|
42144
|
-
};
|
|
42145
|
-
function guessMimeType(filePath) {
|
|
42146
|
-
const ext = filePath.split(".").pop()?.toLowerCase() ?? "";
|
|
42147
|
-
return MIME_BY_EXT[ext] ?? "application/octet-stream";
|
|
42148
|
-
}
|
|
42149
|
-
|
|
42150
42594
|
// src/files/read-file/read-file-binary-full-async.ts
|
|
42151
42595
|
async function readFileBinaryFullAsync(filePath) {
|
|
42152
42596
|
const { buffer, size } = await readFileBufferFullAsync(filePath);
|
|
@@ -42180,104 +42624,72 @@ async function readFileAsync(relativePath, startLine, endLine, lineOffset, lineC
|
|
|
42180
42624
|
}
|
|
42181
42625
|
}
|
|
42182
42626
|
|
|
42183
|
-
// src/files/
|
|
42184
|
-
async function
|
|
42185
|
-
const
|
|
42186
|
-
|
|
42187
|
-
|
|
42188
|
-
|
|
42189
|
-
|
|
42627
|
+
// src/files/browser/handle-file-browser-read.ts
|
|
42628
|
+
async function handleFileBrowserRead(socket, e2ee, msg, reqPath, sessionParentPath, gitScope) {
|
|
42629
|
+
const startLine = typeof msg.startLine === "number" ? msg.startLine : void 0;
|
|
42630
|
+
const endLine = typeof msg.endLine === "number" ? msg.endLine : void 0;
|
|
42631
|
+
const lineOffset = typeof msg.lineOffset === "number" ? msg.lineOffset : void 0;
|
|
42632
|
+
const lineChunkSize = typeof msg.lineChunkSize === "number" ? msg.lineChunkSize : void 0;
|
|
42633
|
+
const encoding = msg.encoding === "base64" ? "base64" : "utf8";
|
|
42634
|
+
const result = gitScope ? await readGitTreeFileAsync(
|
|
42635
|
+
gitScope.repoAbsPath,
|
|
42636
|
+
gitScope.branch,
|
|
42637
|
+
reqPath,
|
|
42638
|
+
startLine,
|
|
42639
|
+
endLine,
|
|
42640
|
+
lineOffset,
|
|
42641
|
+
lineChunkSize,
|
|
42642
|
+
encoding
|
|
42643
|
+
) : await readFileAsync(
|
|
42644
|
+
reqPath,
|
|
42645
|
+
startLine,
|
|
42646
|
+
endLine,
|
|
42647
|
+
lineOffset,
|
|
42648
|
+
lineChunkSize,
|
|
42649
|
+
sessionParentPath,
|
|
42650
|
+
encoding
|
|
42651
|
+
);
|
|
42652
|
+
if ("error" in result) {
|
|
42653
|
+
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
|
|
42654
|
+
return;
|
|
42190
42655
|
}
|
|
42191
|
-
|
|
42656
|
+
const payload = {
|
|
42657
|
+
type: "file_browser_response",
|
|
42658
|
+
id: msg.id,
|
|
42659
|
+
content: result.content,
|
|
42660
|
+
totalLines: result.totalLines,
|
|
42661
|
+
size: result.size
|
|
42662
|
+
};
|
|
42663
|
+
if (result.lineOffset != null) payload.lineOffset = result.lineOffset;
|
|
42664
|
+
if (result.mimeType != null) payload.mimeType = result.mimeType;
|
|
42665
|
+
if (result.resolvedPath != null) payload.resolvedPath = result.resolvedPath;
|
|
42666
|
+
sendFileBrowserMessage(socket, e2ee, payload);
|
|
42192
42667
|
}
|
|
42193
42668
|
|
|
42194
|
-
// src/files/
|
|
42195
|
-
|
|
42196
|
-
|
|
42197
|
-
|
|
42198
|
-
|
|
42199
|
-
|
|
42200
|
-
|
|
42201
|
-
const sessionParentPath = path55.resolve(
|
|
42202
|
-
sessionWorktreeManager != null ? await resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : getBridgeRoot()
|
|
42203
|
-
);
|
|
42204
|
-
if (!await bridgeFileIndexIsPopulated(sessionParentPath)) {
|
|
42205
|
-
const payload2 = {
|
|
42206
|
-
type: "file_browser_search_response",
|
|
42207
|
-
id: msg.id,
|
|
42208
|
-
paths: [],
|
|
42209
|
-
indexReady: false
|
|
42210
|
-
};
|
|
42211
|
-
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload2, ["paths"]) : payload2);
|
|
42212
|
-
return;
|
|
42213
|
-
}
|
|
42214
|
-
const results = await searchBridgeFilePathsAsync(sessionParentPath, q, SEARCH_LIMIT);
|
|
42215
|
-
const payload = {
|
|
42216
|
-
type: "file_browser_search_response",
|
|
42217
|
-
id: msg.id,
|
|
42218
|
-
paths: results,
|
|
42219
|
-
indexReady: true
|
|
42220
|
-
};
|
|
42221
|
-
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["paths"]) : payload);
|
|
42222
|
-
})();
|
|
42223
|
-
}
|
|
42224
|
-
function triggerFileIndexBuild(sessionParentPath = getBridgeRoot()) {
|
|
42225
|
-
setImmediate(() => {
|
|
42226
|
-
void ensureFileIndexAsync(sessionParentPath).catch((e) => {
|
|
42227
|
-
console.error("[file-index] Background build failed:", e);
|
|
42228
|
-
});
|
|
42229
|
-
});
|
|
42669
|
+
// src/files/browser/resolve-git-branch-scope.ts
|
|
42670
|
+
function resolveGitBranchScope(msg) {
|
|
42671
|
+
const gitBranchScope = msg.source === "git_branch" && typeof msg.repoRelPath === "string" && typeof msg.branch === "string" && msg.branch.trim().length > 0;
|
|
42672
|
+
if (!gitBranchScope) return null;
|
|
42673
|
+
const repoAbsPath = resolveRepoAbsPathFromBridge(msg.repoRelPath);
|
|
42674
|
+
if (!repoAbsPath) return null;
|
|
42675
|
+
return { repoAbsPath, branch: msg.branch.trim() };
|
|
42230
42676
|
}
|
|
42231
42677
|
|
|
42232
|
-
// src/files/
|
|
42233
|
-
function sendFileBrowserMessage(socket, e2ee, payload) {
|
|
42234
|
-
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["entries", "content", "totalLines", "size", "lineOffset"]) : payload);
|
|
42235
|
-
}
|
|
42678
|
+
// src/files/browser/index.ts
|
|
42236
42679
|
function handleFileBrowserRequest(msg, socket, e2ee, sessionWorktreeManager) {
|
|
42237
42680
|
void (async () => {
|
|
42238
42681
|
const reqPath = msg.path.replace(/^\/+/, "") || ".";
|
|
42239
42682
|
const op = msg.op === "read" ? "read" : "list";
|
|
42240
42683
|
const sessionParentPath = sessionWorktreeManager != null ? await resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : void 0;
|
|
42684
|
+
const gitScope = resolveGitBranchScope(msg);
|
|
42685
|
+
if (msg.source === "git_branch" && typeof msg.repoRelPath === "string" && typeof msg.branch === "string" && msg.branch.trim().length > 0 && !gitScope) {
|
|
42686
|
+
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: "Invalid repository path" });
|
|
42687
|
+
return;
|
|
42688
|
+
}
|
|
42241
42689
|
if (op === "list") {
|
|
42242
|
-
|
|
42243
|
-
if ("error" in result) {
|
|
42244
|
-
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
|
|
42245
|
-
} else {
|
|
42246
|
-
sendFileBrowserMessage(socket, e2ee, { type: "file_browser_response", id: msg.id, entries: result.entries });
|
|
42247
|
-
if (reqPath === "." || reqPath === "") {
|
|
42248
|
-
triggerFileIndexBuild(sessionParentPath);
|
|
42249
|
-
}
|
|
42250
|
-
}
|
|
42690
|
+
await handleFileBrowserList(socket, e2ee, msg.id, reqPath, sessionParentPath, gitScope);
|
|
42251
42691
|
} else {
|
|
42252
|
-
|
|
42253
|
-
const endLine = typeof msg.endLine === "number" ? msg.endLine : void 0;
|
|
42254
|
-
const lineOffset = typeof msg.lineOffset === "number" ? msg.lineOffset : void 0;
|
|
42255
|
-
const lineChunkSize = typeof msg.lineChunkSize === "number" ? msg.lineChunkSize : void 0;
|
|
42256
|
-
const encoding = msg.encoding === "base64" ? "base64" : "utf8";
|
|
42257
|
-
const result = await readFileAsync(
|
|
42258
|
-
reqPath,
|
|
42259
|
-
startLine,
|
|
42260
|
-
endLine,
|
|
42261
|
-
lineOffset,
|
|
42262
|
-
lineChunkSize,
|
|
42263
|
-
sessionParentPath,
|
|
42264
|
-
encoding
|
|
42265
|
-
);
|
|
42266
|
-
if ("error" in result) {
|
|
42267
|
-
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
|
|
42268
|
-
} else {
|
|
42269
|
-
const payload = {
|
|
42270
|
-
type: "file_browser_response",
|
|
42271
|
-
id: msg.id,
|
|
42272
|
-
content: result.content,
|
|
42273
|
-
totalLines: result.totalLines,
|
|
42274
|
-
size: result.size
|
|
42275
|
-
};
|
|
42276
|
-
if (result.lineOffset != null) payload.lineOffset = result.lineOffset;
|
|
42277
|
-
if (result.mimeType != null) payload.mimeType = result.mimeType;
|
|
42278
|
-
if (result.resolvedPath != null) payload.resolvedPath = result.resolvedPath;
|
|
42279
|
-
sendFileBrowserMessage(socket, e2ee, payload);
|
|
42280
|
-
}
|
|
42692
|
+
await handleFileBrowserRead(socket, e2ee, msg, reqPath, sessionParentPath, gitScope);
|
|
42281
42693
|
}
|
|
42282
42694
|
})();
|
|
42283
42695
|
}
|
|
@@ -42287,12 +42699,7 @@ function handleFileBrowserRequestMessage(msg, { getWs, e2ee, sessionWorktreeMana
|
|
|
42287
42699
|
if (typeof msg.id !== "string" || typeof msg.path !== "string") return;
|
|
42288
42700
|
const socket = getWs();
|
|
42289
42701
|
if (!socket) return;
|
|
42290
|
-
handleFileBrowserRequest(
|
|
42291
|
-
msg,
|
|
42292
|
-
socket,
|
|
42293
|
-
e2ee,
|
|
42294
|
-
sessionWorktreeManager
|
|
42295
|
-
);
|
|
42702
|
+
handleFileBrowserRequest(msg, socket, e2ee, sessionWorktreeManager);
|
|
42296
42703
|
}
|
|
42297
42704
|
function handleFileBrowserSearchMessage(msg, { getWs, e2ee, sessionWorktreeManager }) {
|
|
42298
42705
|
if (typeof msg.id !== "string") return;
|
|
@@ -42327,7 +42734,7 @@ function isValidRemoteSkillInstallItem(item) {
|
|
|
42327
42734
|
|
|
42328
42735
|
// src/skills/install/install-remote-skills-async.ts
|
|
42329
42736
|
import fs44 from "node:fs";
|
|
42330
|
-
import
|
|
42737
|
+
import path57 from "node:path";
|
|
42331
42738
|
|
|
42332
42739
|
// src/skills/install/constants.ts
|
|
42333
42740
|
var INSTALL_SKILLS_YIELD_EVERY = 16;
|
|
@@ -42338,8 +42745,8 @@ async function writeInstallFileAsync(skillDir, f, filesWritten) {
|
|
|
42338
42745
|
if (++filesWritten.count % INSTALL_SKILLS_YIELD_EVERY === 0) {
|
|
42339
42746
|
await yieldToEventLoop();
|
|
42340
42747
|
}
|
|
42341
|
-
const dest =
|
|
42342
|
-
await fs44.promises.mkdir(
|
|
42748
|
+
const dest = path57.join(skillDir, f.path);
|
|
42749
|
+
await fs44.promises.mkdir(path57.dirname(dest), { recursive: true });
|
|
42343
42750
|
if (f.text !== void 0) {
|
|
42344
42751
|
await fs44.promises.writeFile(dest, f.text, "utf8");
|
|
42345
42752
|
} else if (f.base64) {
|
|
@@ -42355,7 +42762,7 @@ async function installRemoteSkillsAsync(cwd, targetDir, items) {
|
|
|
42355
42762
|
try {
|
|
42356
42763
|
for (const item of items) {
|
|
42357
42764
|
if (!isValidRemoteSkillInstallItem(item)) continue;
|
|
42358
|
-
const skillDir =
|
|
42765
|
+
const skillDir = path57.join(cwd, targetDir, item.skillName);
|
|
42359
42766
|
for (const f of item.files) {
|
|
42360
42767
|
await writeInstallFileAsync(skillDir, f, filesWritten);
|
|
42361
42768
|
}
|
|
@@ -42694,7 +43101,7 @@ var handleDevServersConfig = (msg, deps) => {
|
|
|
42694
43101
|
};
|
|
42695
43102
|
|
|
42696
43103
|
// src/git/bridge-git-context.ts
|
|
42697
|
-
import * as
|
|
43104
|
+
import * as path58 from "node:path";
|
|
42698
43105
|
|
|
42699
43106
|
// src/git/branches/get-current-branch.ts
|
|
42700
43107
|
async function getCurrentBranch(repoPath) {
|
|
@@ -42744,12 +43151,12 @@ async function listRepoBranchRefs(repoPath) {
|
|
|
42744
43151
|
// src/git/bridge-git-context.ts
|
|
42745
43152
|
function folderNameForRelPath(relPath, bridgeRoot) {
|
|
42746
43153
|
if (relPath === "." || relPath === "") {
|
|
42747
|
-
return
|
|
43154
|
+
return path58.basename(path58.resolve(bridgeRoot)) || "repo";
|
|
42748
43155
|
}
|
|
42749
|
-
return
|
|
43156
|
+
return path58.basename(relPath) || relPath;
|
|
42750
43157
|
}
|
|
42751
43158
|
async function discoverGitReposForBridgeContext(bridgeRoot) {
|
|
42752
|
-
const root =
|
|
43159
|
+
const root = path58.resolve(bridgeRoot);
|
|
42753
43160
|
if (await isGitRepoDirectory(root)) {
|
|
42754
43161
|
const remoteUrl = await getRemoteOriginUrl(root);
|
|
42755
43162
|
return [{ absolutePath: root, remoteUrl }];
|
|
@@ -42757,19 +43164,19 @@ async function discoverGitReposForBridgeContext(bridgeRoot) {
|
|
|
42757
43164
|
const [deep, shallow] = await Promise.all([discoverGitReposUnderRoot(root), discoverGitRepos(root)]);
|
|
42758
43165
|
const byPath = /* @__PURE__ */ new Map();
|
|
42759
43166
|
for (const repo of [...deep, ...shallow]) {
|
|
42760
|
-
byPath.set(
|
|
43167
|
+
byPath.set(path58.resolve(repo.absolutePath), repo);
|
|
42761
43168
|
}
|
|
42762
43169
|
return [...byPath.values()];
|
|
42763
43170
|
}
|
|
42764
43171
|
async function getBridgeGitContext(bridgeRoot = getBridgeRoot()) {
|
|
42765
|
-
const bridgeResolved =
|
|
43172
|
+
const bridgeResolved = path58.resolve(bridgeRoot);
|
|
42766
43173
|
const repos = await discoverGitReposForBridgeContext(bridgeResolved);
|
|
42767
43174
|
const rows = [];
|
|
42768
43175
|
for (let i = 0; i < repos.length; i++) {
|
|
42769
43176
|
if (i > 0) await yieldToEventLoop();
|
|
42770
43177
|
const repo = repos[i];
|
|
42771
|
-
let rel =
|
|
42772
|
-
if (rel.startsWith("..") ||
|
|
43178
|
+
let rel = path58.relative(bridgeResolved, repo.absolutePath);
|
|
43179
|
+
if (rel.startsWith("..") || path58.isAbsolute(rel)) continue;
|
|
42773
43180
|
const relPath = rel === "" ? "." : rel.replace(/\\/g, "/");
|
|
42774
43181
|
const currentBranch = await getCurrentBranch(repo.absolutePath);
|
|
42775
43182
|
const remoteUrl = repo.remoteUrl.trim() || null;
|
|
@@ -42784,11 +43191,11 @@ async function getBridgeGitContext(bridgeRoot = getBridgeRoot()) {
|
|
|
42784
43191
|
return rows;
|
|
42785
43192
|
}
|
|
42786
43193
|
async function listRepoBranchesForBridge(repoRelPath, bridgeRoot = getBridgeRoot()) {
|
|
42787
|
-
const bridgeResolved =
|
|
43194
|
+
const bridgeResolved = path58.resolve(bridgeRoot);
|
|
42788
43195
|
const rel = repoRelPath.trim() === "." ? "" : repoRelPath.trim().replace(/\\/g, "/");
|
|
42789
|
-
const repoPath = rel === "" ? bridgeResolved :
|
|
42790
|
-
const resolved =
|
|
42791
|
-
if (!resolved.startsWith(bridgeResolved +
|
|
43196
|
+
const repoPath = rel === "" ? bridgeResolved : path58.join(bridgeResolved, rel);
|
|
43197
|
+
const resolved = path58.resolve(repoPath);
|
|
43198
|
+
if (!resolved.startsWith(bridgeResolved + path58.sep) && resolved !== bridgeResolved) {
|
|
42792
43199
|
return [];
|
|
42793
43200
|
}
|
|
42794
43201
|
return listRepoBranchRefs(resolved);
|
|
@@ -43293,10 +43700,10 @@ function listCliAgentCapabilityCacheForWorkspace(db, workspaceId) {
|
|
|
43293
43700
|
}
|
|
43294
43701
|
|
|
43295
43702
|
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
43296
|
-
import * as
|
|
43703
|
+
import * as path60 from "node:path";
|
|
43297
43704
|
|
|
43298
43705
|
// src/agents/capabilities/probe-one-agent-type-for-capabilities.ts
|
|
43299
|
-
import * as
|
|
43706
|
+
import * as path59 from "node:path";
|
|
43300
43707
|
async function probeOneAgentTypeForCapabilities(params) {
|
|
43301
43708
|
const { agentType, cwd, workspaceId, log: log2, reportAgentCapabilities, bridgeReport = true, shouldContinue } = params;
|
|
43302
43709
|
const canContinue = () => shouldContinue?.() !== false;
|
|
@@ -43334,7 +43741,7 @@ async function probeOneAgentTypeForCapabilities(params) {
|
|
|
43334
43741
|
if (!canContinue()) return false;
|
|
43335
43742
|
handle = await resolved.createClient({
|
|
43336
43743
|
command: resolved.command,
|
|
43337
|
-
cwd:
|
|
43744
|
+
cwd: path59.resolve(cwd),
|
|
43338
43745
|
backendAgentType: agentType,
|
|
43339
43746
|
sessionMode: "agent",
|
|
43340
43747
|
persistedAcpSessionId: null,
|
|
@@ -43412,7 +43819,7 @@ async function warmupAgentCapabilitiesOnConnect(params) {
|
|
|
43412
43819
|
const { workspaceId, log: log2, getWs } = params;
|
|
43413
43820
|
const isCurrent = beginAgentCapabilityWarmupRun();
|
|
43414
43821
|
if (!isCurrent()) return;
|
|
43415
|
-
const cwd =
|
|
43822
|
+
const cwd = path60.resolve(getBridgeRoot());
|
|
43416
43823
|
async function sendBatchFromCache() {
|
|
43417
43824
|
if (!isCurrent()) return;
|
|
43418
43825
|
const socket = getWs();
|
|
@@ -43758,18 +44165,18 @@ import * as http from "node:http";
|
|
|
43758
44165
|
|
|
43759
44166
|
// src/mcp/bridge-access/read-json-body.ts
|
|
43760
44167
|
function readJsonBody(req) {
|
|
43761
|
-
return new Promise((
|
|
44168
|
+
return new Promise((resolve35, reject) => {
|
|
43762
44169
|
const chunks = [];
|
|
43763
44170
|
req.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
|
43764
44171
|
req.on("end", () => {
|
|
43765
44172
|
try {
|
|
43766
44173
|
const raw = Buffer.concat(chunks).toString("utf8").trim();
|
|
43767
44174
|
if (!raw) {
|
|
43768
|
-
|
|
44175
|
+
resolve35({});
|
|
43769
44176
|
return;
|
|
43770
44177
|
}
|
|
43771
44178
|
const parsed = JSON.parse(raw);
|
|
43772
|
-
|
|
44179
|
+
resolve35(parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {});
|
|
43773
44180
|
} catch (e) {
|
|
43774
44181
|
reject(e);
|
|
43775
44182
|
}
|
|
@@ -43827,7 +44234,7 @@ function createBridgeAccessRequestHandler(registry2) {
|
|
|
43827
44234
|
// src/mcp/bridge-access/start-server.ts
|
|
43828
44235
|
function startBridgeAccessServer(registry2) {
|
|
43829
44236
|
const server = http.createServer(createBridgeAccessRequestHandler(registry2));
|
|
43830
|
-
return new Promise((
|
|
44237
|
+
return new Promise((resolve35, reject) => {
|
|
43831
44238
|
server.once("error", reject);
|
|
43832
44239
|
server.listen(0, "127.0.0.1", () => {
|
|
43833
44240
|
const addr = server.address();
|
|
@@ -43835,7 +44242,7 @@ function startBridgeAccessServer(registry2) {
|
|
|
43835
44242
|
reject(new Error("Bridge access server did not bind"));
|
|
43836
44243
|
return;
|
|
43837
44244
|
}
|
|
43838
|
-
|
|
44245
|
+
resolve35({
|
|
43839
44246
|
port: addr.port,
|
|
43840
44247
|
close: () => new Promise((closeResolve, closeReject) => {
|
|
43841
44248
|
server.close((err) => err ? closeReject(err) : closeResolve());
|
|
@@ -43975,8 +44382,8 @@ async function createBridgeConnection(options) {
|
|
|
43975
44382
|
getCloudAccessToken: () => tokens.accessToken
|
|
43976
44383
|
};
|
|
43977
44384
|
const identifyReportedPaths = {
|
|
43978
|
-
bridgeRootPath:
|
|
43979
|
-
worktreesRootPath:
|
|
44385
|
+
bridgeRootPath: path61.resolve(getBridgeRoot()),
|
|
44386
|
+
worktreesRootPath: path61.resolve(worktreesRootPath)
|
|
43980
44387
|
};
|
|
43981
44388
|
const { connect } = createMainBridgeWebSocketLifecycle({
|
|
43982
44389
|
state,
|
|
@@ -44231,7 +44638,7 @@ async function runCliAction(program2, opts) {
|
|
|
44231
44638
|
const firehoseServerUrl = opts.firehoseUrl ?? opts.proxyUrl ?? process.env.BUILDAUTOMATON_FIREHOSE_URL ?? process.env.BUILDAUTOMATON_PROXY_URL ?? DEFAULT_FIREHOSE_URL;
|
|
44232
44639
|
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);
|
|
44233
44640
|
if (bridgeRootOpt) {
|
|
44234
|
-
const resolvedBridgeRoot =
|
|
44641
|
+
const resolvedBridgeRoot = path62.resolve(process.cwd(), bridgeRootOpt);
|
|
44235
44642
|
try {
|
|
44236
44643
|
const st = fs46.statSync(resolvedBridgeRoot);
|
|
44237
44644
|
if (!st.isDirectory()) {
|
|
@@ -44253,7 +44660,7 @@ async function runCliAction(program2, opts) {
|
|
|
44253
44660
|
);
|
|
44254
44661
|
let worktreesRootPath;
|
|
44255
44662
|
if (opts.worktreesRoot && opts.worktreesRoot.trim()) {
|
|
44256
|
-
worktreesRootPath =
|
|
44663
|
+
worktreesRootPath = path62.resolve(opts.worktreesRoot.trim());
|
|
44257
44664
|
}
|
|
44258
44665
|
const e2eCertificates = opts.e2eeCertificatesDir?.trim() ? await loadOrCreateE2eCertificates(opts.e2eeCertificatesDir.trim()) : void 0;
|
|
44259
44666
|
if (e2eCertificates) {
|