@buildautomaton/cli 0.1.56 → 0.1.57
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 +1467 -1156
- package/dist/cli.js.map +4 -4
- package/dist/index.js +1437 -1126
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4175,8 +4175,8 @@ var init_parseUtil = __esm({
|
|
|
4175
4175
|
init_errors();
|
|
4176
4176
|
init_en();
|
|
4177
4177
|
makeIssue = (params) => {
|
|
4178
|
-
const { data, path:
|
|
4179
|
-
const fullPath = [...
|
|
4178
|
+
const { data, path: path73, errorMaps, issueData } = params;
|
|
4179
|
+
const fullPath = [...path73, ...issueData.path || []];
|
|
4180
4180
|
const fullIssue = {
|
|
4181
4181
|
...issueData,
|
|
4182
4182
|
path: fullPath
|
|
@@ -4484,11 +4484,11 @@ var init_types = __esm({
|
|
|
4484
4484
|
init_parseUtil();
|
|
4485
4485
|
init_util();
|
|
4486
4486
|
ParseInputLazyPath = class {
|
|
4487
|
-
constructor(parent, value,
|
|
4487
|
+
constructor(parent, value, path73, key) {
|
|
4488
4488
|
this._cachedPath = [];
|
|
4489
4489
|
this.parent = parent;
|
|
4490
4490
|
this.data = value;
|
|
4491
|
-
this._path =
|
|
4491
|
+
this._path = path73;
|
|
4492
4492
|
this._key = key;
|
|
4493
4493
|
}
|
|
4494
4494
|
get path() {
|
|
@@ -8103,10 +8103,10 @@ function assignProp(target, prop, value) {
|
|
|
8103
8103
|
configurable: true
|
|
8104
8104
|
});
|
|
8105
8105
|
}
|
|
8106
|
-
function getElementAtPath(obj,
|
|
8107
|
-
if (!
|
|
8106
|
+
function getElementAtPath(obj, path73) {
|
|
8107
|
+
if (!path73)
|
|
8108
8108
|
return obj;
|
|
8109
|
-
return
|
|
8109
|
+
return path73.reduce((acc, key) => acc?.[key], obj);
|
|
8110
8110
|
}
|
|
8111
8111
|
function promiseAllObject(promisesObj) {
|
|
8112
8112
|
const keys = Object.keys(promisesObj);
|
|
@@ -8355,11 +8355,11 @@ function aborted(x, startIndex = 0) {
|
|
|
8355
8355
|
}
|
|
8356
8356
|
return false;
|
|
8357
8357
|
}
|
|
8358
|
-
function prefixIssues(
|
|
8358
|
+
function prefixIssues(path73, issues) {
|
|
8359
8359
|
return issues.map((iss) => {
|
|
8360
8360
|
var _a2;
|
|
8361
8361
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
8362
|
-
iss.path.unshift(
|
|
8362
|
+
iss.path.unshift(path73);
|
|
8363
8363
|
return iss;
|
|
8364
8364
|
});
|
|
8365
8365
|
}
|
|
@@ -8548,7 +8548,7 @@ function treeifyError(error40, _mapper) {
|
|
|
8548
8548
|
return issue2.message;
|
|
8549
8549
|
};
|
|
8550
8550
|
const result = { errors: [] };
|
|
8551
|
-
const processError = (error41,
|
|
8551
|
+
const processError = (error41, path73 = []) => {
|
|
8552
8552
|
var _a2, _b;
|
|
8553
8553
|
for (const issue2 of error41.issues) {
|
|
8554
8554
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -8558,7 +8558,7 @@ function treeifyError(error40, _mapper) {
|
|
|
8558
8558
|
} else if (issue2.code === "invalid_element") {
|
|
8559
8559
|
processError({ issues: issue2.issues }, issue2.path);
|
|
8560
8560
|
} else {
|
|
8561
|
-
const fullpath = [...
|
|
8561
|
+
const fullpath = [...path73, ...issue2.path];
|
|
8562
8562
|
if (fullpath.length === 0) {
|
|
8563
8563
|
result.errors.push(mapper(issue2));
|
|
8564
8564
|
continue;
|
|
@@ -8588,9 +8588,9 @@ function treeifyError(error40, _mapper) {
|
|
|
8588
8588
|
processError(error40);
|
|
8589
8589
|
return result;
|
|
8590
8590
|
}
|
|
8591
|
-
function toDotPath(
|
|
8591
|
+
function toDotPath(path73) {
|
|
8592
8592
|
const segs = [];
|
|
8593
|
-
for (const seg of
|
|
8593
|
+
for (const seg of path73) {
|
|
8594
8594
|
if (typeof seg === "number")
|
|
8595
8595
|
segs.push(`[${seg}]`);
|
|
8596
8596
|
else if (typeof seg === "symbol")
|
|
@@ -21596,7 +21596,7 @@ var require_ignore = __commonJS({
|
|
|
21596
21596
|
// path matching.
|
|
21597
21597
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
21598
21598
|
// @returns {TestResult} true if a file is ignored
|
|
21599
|
-
test(
|
|
21599
|
+
test(path73, checkUnignored, mode) {
|
|
21600
21600
|
let ignored = false;
|
|
21601
21601
|
let unignored = false;
|
|
21602
21602
|
let matchedRule;
|
|
@@ -21605,7 +21605,7 @@ var require_ignore = __commonJS({
|
|
|
21605
21605
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
21606
21606
|
return;
|
|
21607
21607
|
}
|
|
21608
|
-
const matched = rule[mode].test(
|
|
21608
|
+
const matched = rule[mode].test(path73);
|
|
21609
21609
|
if (!matched) {
|
|
21610
21610
|
return;
|
|
21611
21611
|
}
|
|
@@ -21626,17 +21626,17 @@ var require_ignore = __commonJS({
|
|
|
21626
21626
|
var throwError = (message, Ctor) => {
|
|
21627
21627
|
throw new Ctor(message);
|
|
21628
21628
|
};
|
|
21629
|
-
var checkPath = (
|
|
21630
|
-
if (!isString(
|
|
21629
|
+
var checkPath = (path73, originalPath, doThrow) => {
|
|
21630
|
+
if (!isString(path73)) {
|
|
21631
21631
|
return doThrow(
|
|
21632
21632
|
`path must be a string, but got \`${originalPath}\``,
|
|
21633
21633
|
TypeError
|
|
21634
21634
|
);
|
|
21635
21635
|
}
|
|
21636
|
-
if (!
|
|
21636
|
+
if (!path73) {
|
|
21637
21637
|
return doThrow(`path must not be empty`, TypeError);
|
|
21638
21638
|
}
|
|
21639
|
-
if (checkPath.isNotRelative(
|
|
21639
|
+
if (checkPath.isNotRelative(path73)) {
|
|
21640
21640
|
const r = "`path.relative()`d";
|
|
21641
21641
|
return doThrow(
|
|
21642
21642
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -21645,7 +21645,7 @@ var require_ignore = __commonJS({
|
|
|
21645
21645
|
}
|
|
21646
21646
|
return true;
|
|
21647
21647
|
};
|
|
21648
|
-
var isNotRelative = (
|
|
21648
|
+
var isNotRelative = (path73) => REGEX_TEST_INVALID_PATH.test(path73);
|
|
21649
21649
|
checkPath.isNotRelative = isNotRelative;
|
|
21650
21650
|
checkPath.convert = (p) => p;
|
|
21651
21651
|
var Ignore = class {
|
|
@@ -21675,19 +21675,19 @@ var require_ignore = __commonJS({
|
|
|
21675
21675
|
}
|
|
21676
21676
|
// @returns {TestResult}
|
|
21677
21677
|
_test(originalPath, cache2, checkUnignored, slices) {
|
|
21678
|
-
const
|
|
21678
|
+
const path73 = originalPath && checkPath.convert(originalPath);
|
|
21679
21679
|
checkPath(
|
|
21680
|
-
|
|
21680
|
+
path73,
|
|
21681
21681
|
originalPath,
|
|
21682
21682
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
21683
21683
|
);
|
|
21684
|
-
return this._t(
|
|
21684
|
+
return this._t(path73, cache2, checkUnignored, slices);
|
|
21685
21685
|
}
|
|
21686
|
-
checkIgnore(
|
|
21687
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
21688
|
-
return this.test(
|
|
21686
|
+
checkIgnore(path73) {
|
|
21687
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path73)) {
|
|
21688
|
+
return this.test(path73);
|
|
21689
21689
|
}
|
|
21690
|
-
const slices =
|
|
21690
|
+
const slices = path73.split(SLASH).filter(Boolean);
|
|
21691
21691
|
slices.pop();
|
|
21692
21692
|
if (slices.length) {
|
|
21693
21693
|
const parent = this._t(
|
|
@@ -21700,18 +21700,18 @@ var require_ignore = __commonJS({
|
|
|
21700
21700
|
return parent;
|
|
21701
21701
|
}
|
|
21702
21702
|
}
|
|
21703
|
-
return this._rules.test(
|
|
21703
|
+
return this._rules.test(path73, false, MODE_CHECK_IGNORE);
|
|
21704
21704
|
}
|
|
21705
|
-
_t(
|
|
21706
|
-
if (
|
|
21707
|
-
return cache2[
|
|
21705
|
+
_t(path73, cache2, checkUnignored, slices) {
|
|
21706
|
+
if (path73 in cache2) {
|
|
21707
|
+
return cache2[path73];
|
|
21708
21708
|
}
|
|
21709
21709
|
if (!slices) {
|
|
21710
|
-
slices =
|
|
21710
|
+
slices = path73.split(SLASH).filter(Boolean);
|
|
21711
21711
|
}
|
|
21712
21712
|
slices.pop();
|
|
21713
21713
|
if (!slices.length) {
|
|
21714
|
-
return cache2[
|
|
21714
|
+
return cache2[path73] = this._rules.test(path73, checkUnignored, MODE_IGNORE);
|
|
21715
21715
|
}
|
|
21716
21716
|
const parent = this._t(
|
|
21717
21717
|
slices.join(SLASH) + SLASH,
|
|
@@ -21719,29 +21719,29 @@ var require_ignore = __commonJS({
|
|
|
21719
21719
|
checkUnignored,
|
|
21720
21720
|
slices
|
|
21721
21721
|
);
|
|
21722
|
-
return cache2[
|
|
21722
|
+
return cache2[path73] = parent.ignored ? parent : this._rules.test(path73, checkUnignored, MODE_IGNORE);
|
|
21723
21723
|
}
|
|
21724
|
-
ignores(
|
|
21725
|
-
return this._test(
|
|
21724
|
+
ignores(path73) {
|
|
21725
|
+
return this._test(path73, this._ignoreCache, false).ignored;
|
|
21726
21726
|
}
|
|
21727
21727
|
createFilter() {
|
|
21728
|
-
return (
|
|
21728
|
+
return (path73) => !this.ignores(path73);
|
|
21729
21729
|
}
|
|
21730
21730
|
filter(paths) {
|
|
21731
21731
|
return makeArray(paths).filter(this.createFilter());
|
|
21732
21732
|
}
|
|
21733
21733
|
// @returns {TestResult}
|
|
21734
|
-
test(
|
|
21735
|
-
return this._test(
|
|
21734
|
+
test(path73) {
|
|
21735
|
+
return this._test(path73, this._testCache, true);
|
|
21736
21736
|
}
|
|
21737
21737
|
};
|
|
21738
21738
|
var factory = (options) => new Ignore(options);
|
|
21739
|
-
var isPathValid = (
|
|
21739
|
+
var isPathValid = (path73) => checkPath(path73 && checkPath.convert(path73), path73, RETURN_FALSE);
|
|
21740
21740
|
var setupWindows = () => {
|
|
21741
21741
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
21742
21742
|
checkPath.convert = makePosix;
|
|
21743
21743
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
21744
|
-
checkPath.isNotRelative = (
|
|
21744
|
+
checkPath.isNotRelative = (path73) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path73) || isNotRelative(path73);
|
|
21745
21745
|
};
|
|
21746
21746
|
if (
|
|
21747
21747
|
// Detect `process` so that it can run in browsers.
|
|
@@ -22530,10 +22530,10 @@ var require_src2 = __commonJS({
|
|
|
22530
22530
|
var fs_1 = __require("fs");
|
|
22531
22531
|
var debug_1 = __importDefault(require_src());
|
|
22532
22532
|
var log2 = debug_1.default("@kwsites/file-exists");
|
|
22533
|
-
function check2(
|
|
22534
|
-
log2(`checking %s`,
|
|
22533
|
+
function check2(path73, isFile, isDirectory) {
|
|
22534
|
+
log2(`checking %s`, path73);
|
|
22535
22535
|
try {
|
|
22536
|
-
const stat2 = fs_1.statSync(
|
|
22536
|
+
const stat2 = fs_1.statSync(path73);
|
|
22537
22537
|
if (stat2.isFile() && isFile) {
|
|
22538
22538
|
log2(`[OK] path represents a file`);
|
|
22539
22539
|
return true;
|
|
@@ -22553,8 +22553,8 @@ var require_src2 = __commonJS({
|
|
|
22553
22553
|
throw e;
|
|
22554
22554
|
}
|
|
22555
22555
|
}
|
|
22556
|
-
function exists2(
|
|
22557
|
-
return check2(
|
|
22556
|
+
function exists2(path73, type = exports.READABLE) {
|
|
22557
|
+
return check2(path73, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
|
|
22558
22558
|
}
|
|
22559
22559
|
exports.exists = exists2;
|
|
22560
22560
|
exports.FILE = 1;
|
|
@@ -23640,9 +23640,9 @@ function parseChangeSummaryJson(raw, allowedPaths, options) {
|
|
|
23640
23640
|
const rawPath = typeof o.path === "string" ? o.path.trim() : "";
|
|
23641
23641
|
const summary = typeof o.summary === "string" ? o.summary.trim() : "";
|
|
23642
23642
|
if (!rawPath || !summary) continue;
|
|
23643
|
-
const
|
|
23644
|
-
if (!
|
|
23645
|
-
rows.push({ path:
|
|
23643
|
+
const path73 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
|
|
23644
|
+
if (!path73) continue;
|
|
23645
|
+
rows.push({ path: path73, summary: clampSummaryToAtMostTwoLines(summary) });
|
|
23646
23646
|
}
|
|
23647
23647
|
return rows;
|
|
23648
23648
|
}
|
|
@@ -24956,8 +24956,8 @@ function randomSecret() {
|
|
|
24956
24956
|
}
|
|
24957
24957
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
24958
24958
|
}
|
|
24959
|
-
async function requestPreviewApi(port, secret, method,
|
|
24960
|
-
const url2 = `http://127.0.0.1:${port}${
|
|
24959
|
+
async function requestPreviewApi(port, secret, method, path73, body) {
|
|
24960
|
+
const url2 = `http://127.0.0.1:${port}${path73}`;
|
|
24961
24961
|
const headers = {
|
|
24962
24962
|
[PREVIEW_SECRET_HEADER]: secret,
|
|
24963
24963
|
"Content-Type": "application/json"
|
|
@@ -24969,7 +24969,7 @@ async function requestPreviewApi(port, secret, method, path71, body) {
|
|
|
24969
24969
|
});
|
|
24970
24970
|
const data = await res.json().catch(() => ({}));
|
|
24971
24971
|
if (!res.ok) {
|
|
24972
|
-
throw new Error(data?.error ?? `Preview API ${method} ${
|
|
24972
|
+
throw new Error(data?.error ?? `Preview API ${method} ${path73}: ${res.status}`);
|
|
24973
24973
|
}
|
|
24974
24974
|
return data;
|
|
24975
24975
|
}
|
|
@@ -25184,7 +25184,7 @@ function installBridgeProcessResilience() {
|
|
|
25184
25184
|
}
|
|
25185
25185
|
|
|
25186
25186
|
// src/cli-version.ts
|
|
25187
|
-
var CLI_VERSION = "0.1.
|
|
25187
|
+
var CLI_VERSION = "0.1.57".length > 0 ? "0.1.57" : "0.0.0-dev";
|
|
25188
25188
|
|
|
25189
25189
|
// src/connection/heartbeat/constants.ts
|
|
25190
25190
|
var BRIDGE_APP_HEARTBEAT_INTERVAL_MS = 1e4;
|
|
@@ -26043,7 +26043,7 @@ function clearMainBridgeReconnectQuietOnOpen(state, log2) {
|
|
|
26043
26043
|
function scheduleMainBridgeReconnect(state, connect, log2, closeMeta) {
|
|
26044
26044
|
if (state.closedByUser || state.currentWs != null) return;
|
|
26045
26045
|
const meta = closeMeta ?? state.lastReconnectCloseMeta ?? void 0;
|
|
26046
|
-
const
|
|
26046
|
+
const delay3 = applyTieredReconnectPlanAndLog(
|
|
26047
26047
|
state.mainOutage,
|
|
26048
26048
|
log2,
|
|
26049
26049
|
BRIDGE_SERVICE_LABEL,
|
|
@@ -26052,7 +26052,7 @@ function scheduleMainBridgeReconnect(state, connect, log2, closeMeta) {
|
|
|
26052
26052
|
meta?.reason
|
|
26053
26053
|
);
|
|
26054
26054
|
armReconnectDelayTimer({
|
|
26055
|
-
delayMs:
|
|
26055
|
+
delayMs: delay3,
|
|
26056
26056
|
bumpAttempt: () => {
|
|
26057
26057
|
state.reconnectAttempt += 1;
|
|
26058
26058
|
},
|
|
@@ -26254,10 +26254,10 @@ function runPendingAuth(options) {
|
|
|
26254
26254
|
}
|
|
26255
26255
|
if (resolved) return;
|
|
26256
26256
|
beginDeferredPendingCloseLog(code, reason);
|
|
26257
|
-
const
|
|
26257
|
+
const delay3 = pendingAuthReconnectDelayMs(reconnectAttempt);
|
|
26258
26258
|
reconnectAttempt += 1;
|
|
26259
26259
|
if (signInQuiet.verboseLogs) {
|
|
26260
|
-
const delayLabel = formatReconnectDelayForLog(
|
|
26260
|
+
const delayLabel = formatReconnectDelayForLog(delay3);
|
|
26261
26261
|
logFn(
|
|
26262
26262
|
`[Bridge service] Next sign-in connection attempt in ${delayLabel} (attempt ${reconnectAttempt}).`
|
|
26263
26263
|
);
|
|
@@ -26265,7 +26265,7 @@ function runPendingAuth(options) {
|
|
|
26265
26265
|
reconnectTimeout = setTimeout(() => {
|
|
26266
26266
|
reconnectTimeout = null;
|
|
26267
26267
|
connect();
|
|
26268
|
-
},
|
|
26268
|
+
}, delay3);
|
|
26269
26269
|
},
|
|
26270
26270
|
onError: (err) => logCliWebSocketError(logFn, "[Bridge service]", err, "while waiting for sign-in"),
|
|
26271
26271
|
onMessage: (data) => {
|
|
@@ -26359,11 +26359,7 @@ function isCliSqliteLockError(e) {
|
|
|
26359
26359
|
return lower.includes("database is locked") || lower.includes("sqlite_busy") || lower.includes("sqlite3_busy") || lower.includes("database") && lower.includes("locked");
|
|
26360
26360
|
}
|
|
26361
26361
|
|
|
26362
|
-
// src/sqlite/
|
|
26363
|
-
var { Database: SqliteDatabase } = sqliteWasm;
|
|
26364
|
-
var SYNC_RETRY_MAX = 40;
|
|
26365
|
-
var ASYNC_RETRY_MAX = 60;
|
|
26366
|
-
var ASYNC_BASE_DELAY_MS = 20;
|
|
26362
|
+
// src/sqlite/sqlite-pragmas.ts
|
|
26367
26363
|
function applySqliteConcurrencyPragmas(db) {
|
|
26368
26364
|
try {
|
|
26369
26365
|
db.run("PRAGMA foreign_keys = ON");
|
|
@@ -26389,12 +26385,17 @@ function applySqliteMemoryPragmas(db) {
|
|
|
26389
26385
|
} catch {
|
|
26390
26386
|
}
|
|
26391
26387
|
}
|
|
26388
|
+
|
|
26389
|
+
// src/sqlite/sqlite-lock-retry.ts
|
|
26390
|
+
var SYNC_RETRY_MAX = 40;
|
|
26391
|
+
var ASYNC_RETRY_MAX = 60;
|
|
26392
|
+
var ASYNC_BASE_DELAY_MS = 20;
|
|
26392
26393
|
function syncSleepMs(ms) {
|
|
26393
26394
|
if (ms <= 0) return;
|
|
26394
26395
|
const deadline = Date.now() + ms;
|
|
26395
26396
|
while (Date.now() < deadline) {
|
|
26396
26397
|
if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();
|
|
26397
|
-
const chunk = Math.min(
|
|
26398
|
+
const chunk = Math.min(10, deadline - Date.now());
|
|
26398
26399
|
if (chunk <= 0) break;
|
|
26399
26400
|
try {
|
|
26400
26401
|
const sab = new SharedArrayBuffer(4);
|
|
@@ -26418,7 +26419,22 @@ async function asyncDelayMsInterruptible(ms) {
|
|
|
26418
26419
|
await yieldToEventLoop();
|
|
26419
26420
|
}
|
|
26420
26421
|
}
|
|
26422
|
+
|
|
26423
|
+
// src/sqlite/create-sqlite-database-access.ts
|
|
26424
|
+
var { Database: SqliteDatabase } = sqliteWasm;
|
|
26421
26425
|
function createSqliteDatabaseAccess(config2) {
|
|
26426
|
+
let migrateDoneForPath = null;
|
|
26427
|
+
function shouldSkipMigrate(sqlitePath, db) {
|
|
26428
|
+
if (migrateDoneForPath !== sqlitePath) return false;
|
|
26429
|
+
try {
|
|
26430
|
+
const row = db.get(
|
|
26431
|
+
"SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='__migrations' LIMIT 1"
|
|
26432
|
+
);
|
|
26433
|
+
return row != null;
|
|
26434
|
+
} catch {
|
|
26435
|
+
return false;
|
|
26436
|
+
}
|
|
26437
|
+
}
|
|
26422
26438
|
function safeClose(db) {
|
|
26423
26439
|
if (db == null) return;
|
|
26424
26440
|
try {
|
|
@@ -26434,7 +26450,11 @@ function createSqliteDatabaseAccess(config2) {
|
|
|
26434
26450
|
try {
|
|
26435
26451
|
applySqliteConcurrencyPragmas(db);
|
|
26436
26452
|
applySqliteMemoryPragmas(db);
|
|
26437
|
-
config2.
|
|
26453
|
+
const sqlitePath2 = config2.getPath();
|
|
26454
|
+
if (!shouldSkipMigrate(sqlitePath2, db)) {
|
|
26455
|
+
config2.migrate(db);
|
|
26456
|
+
migrateDoneForPath = sqlitePath2;
|
|
26457
|
+
}
|
|
26438
26458
|
config2.afterOpen?.(db, options);
|
|
26439
26459
|
} catch (e) {
|
|
26440
26460
|
safeClose(db);
|
|
@@ -26490,14 +26510,16 @@ function createSqliteDatabaseAccess(config2) {
|
|
|
26490
26510
|
async function ensureInitialized(options) {
|
|
26491
26511
|
await withAsync(() => void 0, options);
|
|
26492
26512
|
}
|
|
26513
|
+
function closeAllConnections() {
|
|
26514
|
+
migrateDoneForPath = null;
|
|
26515
|
+
}
|
|
26493
26516
|
return {
|
|
26494
26517
|
safeClose,
|
|
26495
26518
|
openConnection,
|
|
26496
26519
|
withSync,
|
|
26497
26520
|
withAsync,
|
|
26498
26521
|
ensureInitialized,
|
|
26499
|
-
closeAllConnections
|
|
26500
|
-
}
|
|
26522
|
+
closeAllConnections
|
|
26501
26523
|
};
|
|
26502
26524
|
}
|
|
26503
26525
|
|
|
@@ -26697,7 +26719,7 @@ function readMigrationSql(filename, ...searchSubdirs) {
|
|
|
26697
26719
|
join(moduleDir, "..", sub, filename),
|
|
26698
26720
|
join(moduleDir, "..", "..", "dist", sub, filename)
|
|
26699
26721
|
]);
|
|
26700
|
-
const resolved = candidates.find((
|
|
26722
|
+
const resolved = candidates.find((path73) => existsSync(path73));
|
|
26701
26723
|
if (!resolved) {
|
|
26702
26724
|
throw new Error(`Missing SQLite migration SQL: ${filename} (searched ${searchSubdirs.join(", ")})`);
|
|
26703
26725
|
}
|
|
@@ -26829,6 +26851,161 @@ var withCliSqliteSync = cliSqlite.withSync;
|
|
|
26829
26851
|
var withCliSqlite = cliSqlite.withAsync;
|
|
26830
26852
|
var ensureCliSqliteInitialized = cliSqlite.ensureInitialized;
|
|
26831
26853
|
|
|
26854
|
+
// src/sqlite/code-nav-cache/code-nav-cache-paths.ts
|
|
26855
|
+
import fs14 from "node:fs";
|
|
26856
|
+
import path12 from "node:path";
|
|
26857
|
+
import os7 from "node:os";
|
|
26858
|
+
function getCodeNavCacheSqlitePath() {
|
|
26859
|
+
const override = process.env.BUILDAMATON_CODE_NAV_CACHE_SQLITE_PATH?.trim();
|
|
26860
|
+
if (override) return path12.resolve(override);
|
|
26861
|
+
return path12.join(os7.homedir(), ".buildautomaton", "code-nav-cache.sqlite");
|
|
26862
|
+
}
|
|
26863
|
+
function ensureCodeNavCacheSqliteParentDir(sqlitePath) {
|
|
26864
|
+
const dir = path12.dirname(sqlitePath);
|
|
26865
|
+
if (!fs14.existsSync(dir)) fs14.mkdirSync(dir, { recursive: true });
|
|
26866
|
+
}
|
|
26867
|
+
|
|
26868
|
+
// src/sqlite/code-nav-cache/migrate-code-nav-cache-sqlite.ts
|
|
26869
|
+
var CHECKPOINT_V12 = "001_code_nav_cache_checkpoint_v1";
|
|
26870
|
+
var CHECKPOINT_V1_SQL2 = readCodeNavCacheMigrationSql("001_code_nav_cache_checkpoint_v1.sql");
|
|
26871
|
+
var MIGRATION_002 = "002_content_hash_symbol_index";
|
|
26872
|
+
var MIGRATION_002_SQL = readCodeNavCacheMigrationSql("002_content_hash_symbol_index.sql");
|
|
26873
|
+
var MIGRATION_003 = "003_content_hash_tag_rows";
|
|
26874
|
+
var MIGRATION_003_SQL = readCodeNavCacheMigrationSql("003_content_hash_tag_rows.sql");
|
|
26875
|
+
var CODE_NAV_CACHE_SQLITE_MIGRATIONS = [
|
|
26876
|
+
{
|
|
26877
|
+
name: CHECKPOINT_V12,
|
|
26878
|
+
checkpoint: true,
|
|
26879
|
+
migrate: (db) => {
|
|
26880
|
+
db.exec(CHECKPOINT_V1_SQL2);
|
|
26881
|
+
},
|
|
26882
|
+
alreadyApplied: (db) => {
|
|
26883
|
+
const row = db.get(
|
|
26884
|
+
`SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='file_index_parent_path' LIMIT 1`
|
|
26885
|
+
);
|
|
26886
|
+
return row != null;
|
|
26887
|
+
}
|
|
26888
|
+
},
|
|
26889
|
+
{
|
|
26890
|
+
name: MIGRATION_002,
|
|
26891
|
+
migrate: (db) => {
|
|
26892
|
+
db.exec(MIGRATION_002_SQL);
|
|
26893
|
+
},
|
|
26894
|
+
alreadyApplied: (db) => {
|
|
26895
|
+
const row = db.get(
|
|
26896
|
+
`SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='symbol_file_blob' LIMIT 1`
|
|
26897
|
+
);
|
|
26898
|
+
return row != null;
|
|
26899
|
+
}
|
|
26900
|
+
},
|
|
26901
|
+
{
|
|
26902
|
+
name: MIGRATION_003,
|
|
26903
|
+
migrate: (db) => {
|
|
26904
|
+
db.exec(MIGRATION_003_SQL);
|
|
26905
|
+
},
|
|
26906
|
+
alreadyApplied: (db) => {
|
|
26907
|
+
const row = db.get(
|
|
26908
|
+
`SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='symbol_index_tag' LIMIT 1`
|
|
26909
|
+
);
|
|
26910
|
+
if (row == null) return false;
|
|
26911
|
+
const blob = db.get(
|
|
26912
|
+
`SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='symbol_file_blob' LIMIT 1`
|
|
26913
|
+
);
|
|
26914
|
+
return blob == null;
|
|
26915
|
+
}
|
|
26916
|
+
}
|
|
26917
|
+
];
|
|
26918
|
+
function migrateCodeNavCacheSqlite(db) {
|
|
26919
|
+
runSqliteMigrations(
|
|
26920
|
+
db,
|
|
26921
|
+
CODE_NAV_CACHE_SQLITE_MIGRATIONS,
|
|
26922
|
+
readCodeNavCacheMigrationSql("000_bootstrap_migrations_table.sql"),
|
|
26923
|
+
"code-nav-cache"
|
|
26924
|
+
);
|
|
26925
|
+
}
|
|
26926
|
+
|
|
26927
|
+
// src/sqlite/code-nav-cache/code-nav-cache-sqlite-work-lock.ts
|
|
26928
|
+
import fs15 from "node:fs";
|
|
26929
|
+
function isSqliteCorruptError(e) {
|
|
26930
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
26931
|
+
return msg.includes("malformed") || msg.includes("database disk image is malformed") || msg.includes("corrupt");
|
|
26932
|
+
}
|
|
26933
|
+
var chain = Promise.resolve();
|
|
26934
|
+
var workLockDepth = 0;
|
|
26935
|
+
function resetCodeNavCacheSqliteWorkLock() {
|
|
26936
|
+
chain = Promise.resolve();
|
|
26937
|
+
workLockDepth = 0;
|
|
26938
|
+
}
|
|
26939
|
+
function withCodeNavCacheSqliteWorkLock(fn) {
|
|
26940
|
+
if (workLockDepth > 0) {
|
|
26941
|
+
return Promise.resolve(fn());
|
|
26942
|
+
}
|
|
26943
|
+
const run = async () => {
|
|
26944
|
+
workLockDepth += 1;
|
|
26945
|
+
try {
|
|
26946
|
+
return await Promise.resolve(fn());
|
|
26947
|
+
} finally {
|
|
26948
|
+
workLockDepth = Math.max(0, workLockDepth - 1);
|
|
26949
|
+
}
|
|
26950
|
+
};
|
|
26951
|
+
const runWithCorruptRecovery = async () => {
|
|
26952
|
+
try {
|
|
26953
|
+
return await run();
|
|
26954
|
+
} catch (e) {
|
|
26955
|
+
if (!isSqliteCorruptError(e)) throw e;
|
|
26956
|
+
try {
|
|
26957
|
+
fs15.unlinkSync(getCodeNavCacheSqlitePath());
|
|
26958
|
+
} catch {
|
|
26959
|
+
}
|
|
26960
|
+
chain = Promise.resolve();
|
|
26961
|
+
return await run();
|
|
26962
|
+
}
|
|
26963
|
+
};
|
|
26964
|
+
const next = chain.then(runWithCorruptRecovery);
|
|
26965
|
+
chain = next.then(
|
|
26966
|
+
() => void 0,
|
|
26967
|
+
() => void 0
|
|
26968
|
+
);
|
|
26969
|
+
return next;
|
|
26970
|
+
}
|
|
26971
|
+
|
|
26972
|
+
// src/sqlite/code-nav-cache/code-nav-cache-database.ts
|
|
26973
|
+
var codeNavCacheSqlite = createSqliteDatabaseAccess({
|
|
26974
|
+
getPath: getCodeNavCacheSqlitePath,
|
|
26975
|
+
ensureParentDir: ensureCodeNavCacheSqliteParentDir,
|
|
26976
|
+
migrate: migrateCodeNavCacheSqlite
|
|
26977
|
+
});
|
|
26978
|
+
var codeNavCacheAccessDepth = 0;
|
|
26979
|
+
async function waitForOuterCodeNavCacheAccessAsync() {
|
|
26980
|
+
while (codeNavCacheAccessDepth > 0) {
|
|
26981
|
+
if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();
|
|
26982
|
+
await new Promise((resolve32) => setTimeout(resolve32, 5));
|
|
26983
|
+
await yieldToEventLoop();
|
|
26984
|
+
}
|
|
26985
|
+
}
|
|
26986
|
+
var safeCloseCodeNavCacheSqliteDatabase = codeNavCacheSqlite.safeClose;
|
|
26987
|
+
function closeAllCodeNavCacheSqliteConnections() {
|
|
26988
|
+
codeNavCacheSqlite.closeAllConnections();
|
|
26989
|
+
resetCodeNavCacheSqliteWorkLock();
|
|
26990
|
+
codeNavCacheAccessDepth = 0;
|
|
26991
|
+
}
|
|
26992
|
+
var openCodeNavCacheSqliteConnection = codeNavCacheSqlite.openConnection;
|
|
26993
|
+
async function withCodeNavCacheSqlite(fn) {
|
|
26994
|
+
return withCodeNavCacheSqliteWorkLock(async () => {
|
|
26995
|
+
const nested = codeNavCacheAccessDepth > 0;
|
|
26996
|
+
if (!nested) await waitForOuterCodeNavCacheAccessAsync();
|
|
26997
|
+
codeNavCacheAccessDepth += 1;
|
|
26998
|
+
try {
|
|
26999
|
+
return await codeNavCacheSqlite.withAsync(fn);
|
|
27000
|
+
} finally {
|
|
27001
|
+
codeNavCacheAccessDepth = Math.max(0, codeNavCacheAccessDepth - 1);
|
|
27002
|
+
}
|
|
27003
|
+
});
|
|
27004
|
+
}
|
|
27005
|
+
async function ensureCodeNavCacheSqliteInitialized() {
|
|
27006
|
+
await withCodeNavCacheSqlite(() => void 0);
|
|
27007
|
+
}
|
|
27008
|
+
|
|
26832
27009
|
// src/connection/close-bridge-connection.ts
|
|
26833
27010
|
async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
|
|
26834
27011
|
requestCliImmediateShutdown();
|
|
@@ -26874,6 +27051,7 @@ async function closeBridgeConnection(state, acpManager, devServerManager, log2)
|
|
|
26874
27051
|
}
|
|
26875
27052
|
try {
|
|
26876
27053
|
closeAllCliSqliteConnections();
|
|
27054
|
+
closeAllCodeNavCacheSqliteConnections();
|
|
26877
27055
|
} catch {
|
|
26878
27056
|
}
|
|
26879
27057
|
say("Shutdown complete.");
|
|
@@ -26960,16 +27138,16 @@ import * as fs20 from "node:fs";
|
|
|
26960
27138
|
import * as path24 from "node:path";
|
|
26961
27139
|
|
|
26962
27140
|
// src/paths/session-layout-paths.ts
|
|
26963
|
-
import * as
|
|
27141
|
+
import * as path13 from "node:path";
|
|
26964
27142
|
function resolveIsolatedSessionParentPathFromCheckouts(worktreePaths) {
|
|
26965
|
-
const resolved = worktreePaths.map((p) =>
|
|
27143
|
+
const resolved = worktreePaths.map((p) => path13.resolve(p)).filter(Boolean);
|
|
26966
27144
|
if (resolved.length === 0) return null;
|
|
26967
27145
|
resolved.sort();
|
|
26968
27146
|
return resolved[0];
|
|
26969
27147
|
}
|
|
26970
27148
|
function resolveSessionParentPathForAgentProcess(resolvedSessionParentPath) {
|
|
26971
27149
|
if (resolvedSessionParentPath != null && String(resolvedSessionParentPath).trim() !== "") {
|
|
26972
|
-
return
|
|
27150
|
+
return path13.resolve(String(resolvedSessionParentPath).trim());
|
|
26973
27151
|
}
|
|
26974
27152
|
return getBridgeRoot();
|
|
26975
27153
|
}
|
|
@@ -27710,16 +27888,16 @@ import { existsSync as existsSync2, statSync } from "node:fs";
|
|
|
27710
27888
|
|
|
27711
27889
|
// src/git/get-git-repo-root-sync.ts
|
|
27712
27890
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
27713
|
-
import * as
|
|
27891
|
+
import * as path14 from "node:path";
|
|
27714
27892
|
function getGitRepoRootSync(startDir) {
|
|
27715
27893
|
try {
|
|
27716
27894
|
const out = execFileSync2("git", ["rev-parse", "--show-toplevel"], {
|
|
27717
|
-
cwd:
|
|
27895
|
+
cwd: path14.resolve(startDir),
|
|
27718
27896
|
encoding: "utf8",
|
|
27719
27897
|
stdio: ["ignore", "pipe", "ignore"],
|
|
27720
27898
|
maxBuffer: 1024 * 1024
|
|
27721
27899
|
}).trim();
|
|
27722
|
-
return out ?
|
|
27900
|
+
return out ? path14.resolve(out) : null;
|
|
27723
27901
|
} catch {
|
|
27724
27902
|
return null;
|
|
27725
27903
|
}
|
|
@@ -27728,25 +27906,25 @@ function getGitRepoRootSync(startDir) {
|
|
|
27728
27906
|
// src/agents/acp/workspace-files.ts
|
|
27729
27907
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
27730
27908
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
27731
|
-
import * as
|
|
27909
|
+
import * as path15 from "node:path";
|
|
27732
27910
|
function resolveWorkspaceFilePath(sessionParentPath, rawPath) {
|
|
27733
27911
|
const trimmed2 = rawPath.trim();
|
|
27734
27912
|
if (!trimmed2) return null;
|
|
27735
|
-
const normalizedSessionParent =
|
|
27913
|
+
const normalizedSessionParent = path15.resolve(sessionParentPath);
|
|
27736
27914
|
let resolvedPath = resolveSafePathUnderCwd(sessionParentPath, trimmed2);
|
|
27737
27915
|
if (!resolvedPath) {
|
|
27738
|
-
const candidate =
|
|
27916
|
+
const candidate = path15.isAbsolute(trimmed2) ? path15.normalize(trimmed2) : path15.normalize(path15.resolve(normalizedSessionParent, trimmed2));
|
|
27739
27917
|
const gitRoot2 = getGitRepoRootSync(sessionParentPath);
|
|
27740
27918
|
if (!gitRoot2) return null;
|
|
27741
|
-
const rel =
|
|
27742
|
-
if (rel.startsWith("..") ||
|
|
27919
|
+
const rel = path15.relative(gitRoot2, candidate);
|
|
27920
|
+
if (rel.startsWith("..") || path15.isAbsolute(rel)) return null;
|
|
27743
27921
|
resolvedPath = candidate;
|
|
27744
27922
|
}
|
|
27745
27923
|
const gitRoot = getGitRepoRootSync(sessionParentPath);
|
|
27746
27924
|
if (gitRoot) {
|
|
27747
|
-
const relFromRoot =
|
|
27748
|
-
if (!relFromRoot.startsWith("..") && !
|
|
27749
|
-
return { resolvedPath, display: relFromRoot.split(
|
|
27925
|
+
const relFromRoot = path15.relative(gitRoot, resolvedPath);
|
|
27926
|
+
if (!relFromRoot.startsWith("..") && !path15.isAbsolute(relFromRoot)) {
|
|
27927
|
+
return { resolvedPath, display: relFromRoot.split(path15.sep).join("/") };
|
|
27750
27928
|
}
|
|
27751
27929
|
}
|
|
27752
27930
|
return { resolvedPath, display: toDisplayPathRelativeToCwd(sessionParentPath, resolvedPath) };
|
|
@@ -27755,9 +27933,9 @@ function readUtf8WorkspaceFile(sessionParentPath, displayPath) {
|
|
|
27755
27933
|
if (!displayPath || displayPath.includes("..")) return "";
|
|
27756
27934
|
const gitRoot = getGitRepoRootSync(sessionParentPath);
|
|
27757
27935
|
if (gitRoot) {
|
|
27758
|
-
const resolvedPath2 =
|
|
27759
|
-
const rel =
|
|
27760
|
-
if (!rel.startsWith("..") && !
|
|
27936
|
+
const resolvedPath2 = path15.resolve(gitRoot, displayPath);
|
|
27937
|
+
const rel = path15.relative(gitRoot, resolvedPath2);
|
|
27938
|
+
if (!rel.startsWith("..") && !path15.isAbsolute(rel)) {
|
|
27761
27939
|
try {
|
|
27762
27940
|
return readFileSync3(resolvedPath2, "utf8");
|
|
27763
27941
|
} catch {
|
|
@@ -27776,9 +27954,9 @@ function tryWorkspaceDisplayToPath(sessionParentPath, displayPath) {
|
|
|
27776
27954
|
if (!displayPath || displayPath.includes("..")) return null;
|
|
27777
27955
|
const gitRoot = getGitRepoRootSync(sessionParentPath);
|
|
27778
27956
|
if (gitRoot) {
|
|
27779
|
-
const resolvedPath =
|
|
27780
|
-
const rel =
|
|
27781
|
-
if (!rel.startsWith("..") && !
|
|
27957
|
+
const resolvedPath = path15.resolve(gitRoot, displayPath);
|
|
27958
|
+
const rel = path15.relative(gitRoot, resolvedPath);
|
|
27959
|
+
if (!rel.startsWith("..") && !path15.isAbsolute(rel)) return resolvedPath;
|
|
27782
27960
|
}
|
|
27783
27961
|
return resolveSafePathUnderCwd(sessionParentPath, displayPath);
|
|
27784
27962
|
}
|
|
@@ -27829,92 +28007,22 @@ function getSessionFileChangeDirectoryFlags(sessionParentPath, displayPath) {
|
|
|
27829
28007
|
return { isDirectory: false, directoryRemoved: false };
|
|
27830
28008
|
}
|
|
27831
28009
|
|
|
27832
|
-
// src/sqlite/code-nav-cache/code-nav-cache-
|
|
27833
|
-
|
|
27834
|
-
|
|
27835
|
-
|
|
27836
|
-
|
|
27837
|
-
|
|
27838
|
-
|
|
27839
|
-
|
|
27840
|
-
|
|
27841
|
-
|
|
27842
|
-
|
|
27843
|
-
if (!fs14.existsSync(dir)) fs14.mkdirSync(dir, { recursive: true });
|
|
27844
|
-
}
|
|
27845
|
-
|
|
27846
|
-
// src/sqlite/code-nav-cache/migrate-code-nav-cache-sqlite.ts
|
|
27847
|
-
var CHECKPOINT_V12 = "001_code_nav_cache_checkpoint_v1";
|
|
27848
|
-
var CHECKPOINT_V1_SQL2 = readCodeNavCacheMigrationSql("001_code_nav_cache_checkpoint_v1.sql");
|
|
27849
|
-
var MIGRATION_002 = "002_content_hash_symbol_index";
|
|
27850
|
-
var MIGRATION_002_SQL = readCodeNavCacheMigrationSql("002_content_hash_symbol_index.sql");
|
|
27851
|
-
var MIGRATION_003 = "003_content_hash_tag_rows";
|
|
27852
|
-
var MIGRATION_003_SQL = readCodeNavCacheMigrationSql("003_content_hash_tag_rows.sql");
|
|
27853
|
-
var CODE_NAV_CACHE_SQLITE_MIGRATIONS = [
|
|
27854
|
-
{
|
|
27855
|
-
name: CHECKPOINT_V12,
|
|
27856
|
-
checkpoint: true,
|
|
27857
|
-
migrate: (db) => {
|
|
27858
|
-
db.exec(CHECKPOINT_V1_SQL2);
|
|
27859
|
-
},
|
|
27860
|
-
alreadyApplied: (db) => {
|
|
27861
|
-
const row = db.get(
|
|
27862
|
-
`SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='file_index_parent_path' LIMIT 1`
|
|
27863
|
-
);
|
|
27864
|
-
return row != null;
|
|
27865
|
-
}
|
|
27866
|
-
},
|
|
27867
|
-
{
|
|
27868
|
-
name: MIGRATION_002,
|
|
27869
|
-
migrate: (db) => {
|
|
27870
|
-
db.exec(MIGRATION_002_SQL);
|
|
27871
|
-
},
|
|
27872
|
-
alreadyApplied: (db) => {
|
|
27873
|
-
const row = db.get(
|
|
27874
|
-
`SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='symbol_file_blob' LIMIT 1`
|
|
27875
|
-
);
|
|
27876
|
-
return row != null;
|
|
27877
|
-
}
|
|
27878
|
-
},
|
|
27879
|
-
{
|
|
27880
|
-
name: MIGRATION_003,
|
|
27881
|
-
migrate: (db) => {
|
|
27882
|
-
db.exec(MIGRATION_003_SQL);
|
|
27883
|
-
},
|
|
27884
|
-
alreadyApplied: (db) => {
|
|
27885
|
-
const row = db.get(
|
|
27886
|
-
`SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='symbol_index_tag' LIMIT 1`
|
|
27887
|
-
);
|
|
27888
|
-
if (row == null) return false;
|
|
27889
|
-
const blob = db.get(
|
|
27890
|
-
`SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='symbol_file_blob' LIMIT 1`
|
|
27891
|
-
);
|
|
27892
|
-
return blob == null;
|
|
28010
|
+
// src/sqlite/code-nav-cache/code-nav-cache-sqlite-transaction.ts
|
|
28011
|
+
function runCodeNavCacheWriteTransaction(db, fn) {
|
|
28012
|
+
db.run("BEGIN IMMEDIATE");
|
|
28013
|
+
try {
|
|
28014
|
+
const result = fn();
|
|
28015
|
+
db.run("COMMIT");
|
|
28016
|
+
return result;
|
|
28017
|
+
} catch (e) {
|
|
28018
|
+
try {
|
|
28019
|
+
db.run("ROLLBACK");
|
|
28020
|
+
} catch {
|
|
27893
28021
|
}
|
|
28022
|
+
throw e;
|
|
27894
28023
|
}
|
|
27895
|
-
];
|
|
27896
|
-
function migrateCodeNavCacheSqlite(db) {
|
|
27897
|
-
runSqliteMigrations(
|
|
27898
|
-
db,
|
|
27899
|
-
CODE_NAV_CACHE_SQLITE_MIGRATIONS,
|
|
27900
|
-
readCodeNavCacheMigrationSql("000_bootstrap_migrations_table.sql"),
|
|
27901
|
-
"code-nav-cache"
|
|
27902
|
-
);
|
|
27903
28024
|
}
|
|
27904
28025
|
|
|
27905
|
-
// src/sqlite/code-nav-cache/code-nav-cache-database.ts
|
|
27906
|
-
var codeNavCacheSqlite = createSqliteDatabaseAccess({
|
|
27907
|
-
getPath: getCodeNavCacheSqlitePath,
|
|
27908
|
-
ensureParentDir: ensureCodeNavCacheSqliteParentDir,
|
|
27909
|
-
migrate: migrateCodeNavCacheSqlite
|
|
27910
|
-
});
|
|
27911
|
-
var safeCloseCodeNavCacheSqliteDatabase = codeNavCacheSqlite.safeClose;
|
|
27912
|
-
var closeAllCodeNavCacheSqliteConnections = codeNavCacheSqlite.closeAllConnections;
|
|
27913
|
-
var openCodeNavCacheSqliteConnection = codeNavCacheSqlite.openConnection;
|
|
27914
|
-
var withCodeNavCacheSqliteSync = codeNavCacheSqlite.withSync;
|
|
27915
|
-
var withCodeNavCacheSqlite = codeNavCacheSqlite.withAsync;
|
|
27916
|
-
var ensureCodeNavCacheSqliteInitialized = codeNavCacheSqlite.ensureInitialized;
|
|
27917
|
-
|
|
27918
28026
|
// src/code-nav/yield-during-work.ts
|
|
27919
28027
|
var CODE_NAV_YIELD_EVERY = INDEX_WORK_YIELD_EVERY;
|
|
27920
28028
|
function createCodeNavYieldState() {
|
|
@@ -27929,11 +28037,11 @@ async function yieldDuringCodeNavWork(state) {
|
|
|
27929
28037
|
}
|
|
27930
28038
|
|
|
27931
28039
|
// src/code-nav/walk-code-nav-files.ts
|
|
27932
|
-
import
|
|
28040
|
+
import fs18 from "node:fs";
|
|
27933
28041
|
import path19 from "node:path";
|
|
27934
28042
|
|
|
27935
28043
|
// src/files/index/walk-workspace-tree.ts
|
|
27936
|
-
import
|
|
28044
|
+
import fs16 from "node:fs";
|
|
27937
28045
|
import path16 from "node:path";
|
|
27938
28046
|
var DEPENDENCY_INSTALL_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
27939
28047
|
"node_modules",
|
|
@@ -27951,7 +28059,7 @@ function shouldSkipWorkspaceWalkEntry(name) {
|
|
|
27951
28059
|
async function walkWorkspaceTreeAsync(dir, baseDir, onFile, state) {
|
|
27952
28060
|
let names;
|
|
27953
28061
|
try {
|
|
27954
|
-
names = await
|
|
28062
|
+
names = await fs16.promises.readdir(dir);
|
|
27955
28063
|
} catch {
|
|
27956
28064
|
return;
|
|
27957
28065
|
}
|
|
@@ -27966,7 +28074,7 @@ async function walkWorkspaceTreeAsync(dir, baseDir, onFile, state) {
|
|
|
27966
28074
|
const full = path16.join(dir, name);
|
|
27967
28075
|
let stat2;
|
|
27968
28076
|
try {
|
|
27969
|
-
stat2 = await
|
|
28077
|
+
stat2 = await fs16.promises.stat(full);
|
|
27970
28078
|
} catch {
|
|
27971
28079
|
continue;
|
|
27972
28080
|
}
|
|
@@ -27984,7 +28092,7 @@ function createWalkYieldState() {
|
|
|
27984
28092
|
|
|
27985
28093
|
// src/code-nav/gitignore-filter.ts
|
|
27986
28094
|
var import_ignore = __toESM(require_ignore(), 1);
|
|
27987
|
-
import
|
|
28095
|
+
import fs17 from "node:fs";
|
|
27988
28096
|
import path17 from "node:path";
|
|
27989
28097
|
var DEFAULT_IGNORED = [".git", ".git/**"];
|
|
27990
28098
|
function normalizeRelPath(relPath) {
|
|
@@ -27995,7 +28103,7 @@ var GitignoreFilter = class {
|
|
|
27995
28103
|
/** Load `.gitignore` in `absDir` and push a layer when the file exists. */
|
|
27996
28104
|
async enterDirectory(absDir, dirRel) {
|
|
27997
28105
|
try {
|
|
27998
|
-
const content = await
|
|
28106
|
+
const content = await fs17.promises.readFile(path17.join(absDir, ".gitignore"), "utf8");
|
|
27999
28107
|
this.layers.push({ dirRel, ig: (0, import_ignore.default)().add(content) });
|
|
28000
28108
|
} catch {
|
|
28001
28109
|
}
|
|
@@ -28098,7 +28206,7 @@ async function walkCodeNavFilesInDirectory(dir, baseDir, relDir, filter, onFile,
|
|
|
28098
28206
|
await filter.enterDirectory(dir, relDir);
|
|
28099
28207
|
let names;
|
|
28100
28208
|
try {
|
|
28101
|
-
names = await
|
|
28209
|
+
names = await fs18.promises.readdir(dir);
|
|
28102
28210
|
} catch {
|
|
28103
28211
|
filter.leaveDirectory(relDir);
|
|
28104
28212
|
return;
|
|
@@ -28115,7 +28223,7 @@ async function walkCodeNavFilesInDirectory(dir, baseDir, relDir, filter, onFile,
|
|
|
28115
28223
|
const full = path19.join(dir, name);
|
|
28116
28224
|
let stat2;
|
|
28117
28225
|
try {
|
|
28118
|
-
stat2 = await
|
|
28226
|
+
stat2 = await fs18.promises.stat(full);
|
|
28119
28227
|
} catch {
|
|
28120
28228
|
continue;
|
|
28121
28229
|
}
|
|
@@ -28322,12 +28430,27 @@ function removeParentFileMapEntry(db, parentId, filePath) {
|
|
|
28322
28430
|
db.run("DELETE FROM symbol_parent_file_map WHERE parent_id = ? AND file_path = ?", [parentId, filePath]);
|
|
28323
28431
|
return previous === void 0 ? null : previous;
|
|
28324
28432
|
}
|
|
28325
|
-
function
|
|
28326
|
-
const rows = db.all(
|
|
28327
|
-
|
|
28328
|
-
|
|
28329
|
-
|
|
28330
|
-
|
|
28433
|
+
function clearParentFileMapBatch(db, parentId, limit) {
|
|
28434
|
+
const rows = db.all(
|
|
28435
|
+
`SELECT file_path, content_hash
|
|
28436
|
+
FROM symbol_parent_file_map
|
|
28437
|
+
WHERE parent_id = ?
|
|
28438
|
+
LIMIT ?`,
|
|
28439
|
+
[parentId, limit]
|
|
28440
|
+
);
|
|
28441
|
+
if (rows.length === 0) return { released: [], remaining: false };
|
|
28442
|
+
const del = db.prepare("DELETE FROM symbol_parent_file_map WHERE parent_id = ? AND file_path = ?");
|
|
28443
|
+
try {
|
|
28444
|
+
for (const row of rows) {
|
|
28445
|
+
del.run([parentId, row.file_path]);
|
|
28446
|
+
}
|
|
28447
|
+
} finally {
|
|
28448
|
+
del.finalize();
|
|
28449
|
+
}
|
|
28450
|
+
return {
|
|
28451
|
+
released: rows.flatMap((row) => row.content_hash == null ? [] : [row.content_hash]),
|
|
28452
|
+
remaining: rows.length >= limit
|
|
28453
|
+
};
|
|
28331
28454
|
}
|
|
28332
28455
|
|
|
28333
28456
|
// src/code-nav/symbol-index/storage/symbol-content-index.ts
|
|
@@ -28416,139 +28539,15 @@ function removeSymbolIndexFileData(db, ctx, filePath) {
|
|
|
28416
28539
|
const released = removeParentFileMapEntry(db, ctx.parentId, filePath);
|
|
28417
28540
|
gcReleasedHashes(db, [released]);
|
|
28418
28541
|
}
|
|
28419
|
-
function
|
|
28420
|
-
const released =
|
|
28542
|
+
function clearSymbolIndexParentDataBatch(db, ctx, limit) {
|
|
28543
|
+
const { released, remaining } = clearParentFileMapBatch(db, ctx.parentId, limit);
|
|
28421
28544
|
gcReleasedHashes(db, released);
|
|
28422
|
-
|
|
28423
|
-
|
|
28424
|
-
// src/code-nav/symbol-index/query/tag-query-shared.ts
|
|
28425
|
-
var TAG_SELECT = `file_path, name, role, kind, start_line, start_column, end_line, end_column,
|
|
28426
|
-
scope_start_line, scope_start_column, parent_scope_start_line, parent_scope_start_column, nav_target_path, scope_chain`;
|
|
28427
|
-
function rowToLocation(row) {
|
|
28428
|
-
return {
|
|
28429
|
-
path: row.file_path,
|
|
28430
|
-
line: row.start_line + 1,
|
|
28431
|
-
column: row.start_column,
|
|
28432
|
-
kind: row.kind,
|
|
28433
|
-
role: row.role === "def" ? "definition" : "reference"
|
|
28434
|
-
};
|
|
28435
|
-
}
|
|
28436
|
-
function modulePathLocation(row) {
|
|
28437
|
-
return {
|
|
28438
|
-
path: row.nav_target_path,
|
|
28439
|
-
line: 1,
|
|
28440
|
-
column: 0,
|
|
28441
|
-
kind: "module",
|
|
28442
|
-
role: "reference"
|
|
28443
|
-
};
|
|
28444
|
-
}
|
|
28445
|
-
function emptyRefRow(filePath) {
|
|
28446
|
-
return {
|
|
28447
|
-
file_path: filePath,
|
|
28448
|
-
name: "",
|
|
28449
|
-
role: "ref",
|
|
28450
|
-
kind: "",
|
|
28451
|
-
start_line: 0,
|
|
28452
|
-
start_column: 0,
|
|
28453
|
-
end_line: 0,
|
|
28454
|
-
end_column: 0,
|
|
28455
|
-
scope_start_line: null,
|
|
28456
|
-
scope_start_column: null,
|
|
28457
|
-
parent_scope_start_line: null,
|
|
28458
|
-
parent_scope_start_column: null,
|
|
28459
|
-
nav_target_path: null,
|
|
28460
|
-
scope_chain: null
|
|
28461
|
-
};
|
|
28462
|
-
}
|
|
28463
|
-
|
|
28464
|
-
// src/code-nav/symbol-index/storage/file-content-load.ts
|
|
28465
|
-
function loadFileTags(db, ctx, filePath) {
|
|
28466
|
-
const contentHash = getEffectiveContentHash(db, ctx, filePath);
|
|
28467
|
-
if (contentHash == null) return [];
|
|
28468
|
-
return db.all(
|
|
28469
|
-
`SELECT ${TAG_SELECT}
|
|
28470
|
-
FROM symbol_index_tag
|
|
28471
|
-
WHERE content_hash = ? AND file_path = ?
|
|
28472
|
-
ORDER BY start_line, start_column`,
|
|
28473
|
-
[contentHash, filePath]
|
|
28474
|
-
);
|
|
28475
|
-
}
|
|
28476
|
-
function loadFileImports(db, ctx, filePath) {
|
|
28477
|
-
const contentHash = getEffectiveContentHash(db, ctx, filePath);
|
|
28478
|
-
if (contentHash == null) return [];
|
|
28479
|
-
return db.all(
|
|
28480
|
-
`SELECT file_path, local_name, source_name, module_specifier, source_file_path, import_kind, start_line, start_column
|
|
28481
|
-
FROM symbol_index_import
|
|
28482
|
-
WHERE content_hash = ? AND file_path = ?
|
|
28483
|
-
ORDER BY start_line, start_column`,
|
|
28484
|
-
[contentHash, filePath]
|
|
28485
|
-
);
|
|
28486
|
-
}
|
|
28487
|
-
function findTagsByName(db, ctx, name) {
|
|
28488
|
-
const filePaths = listEffectiveIndexedFilePaths(db, ctx);
|
|
28489
|
-
const rows = [];
|
|
28490
|
-
for (const filePath of filePaths) {
|
|
28491
|
-
const contentHash = getEffectiveContentHash(db, ctx, filePath);
|
|
28492
|
-
if (contentHash == null) continue;
|
|
28493
|
-
const matches = db.all(
|
|
28494
|
-
`SELECT ${TAG_SELECT}
|
|
28495
|
-
FROM symbol_index_tag
|
|
28496
|
-
WHERE content_hash = ? AND file_path = ? AND name = ?
|
|
28497
|
-
ORDER BY start_line, start_column`,
|
|
28498
|
-
[contentHash, filePath, name]
|
|
28499
|
-
);
|
|
28500
|
-
rows.push(...matches);
|
|
28501
|
-
}
|
|
28502
|
-
rows.sort(
|
|
28503
|
-
(a, b) => a.file_path.localeCompare(b.file_path) || a.start_line - b.start_line || a.start_column - b.start_column
|
|
28504
|
-
);
|
|
28505
|
-
return rows;
|
|
28506
|
-
}
|
|
28507
|
-
|
|
28508
|
-
// src/code-nav/symbol-index/lifecycle/symbol-index-file-ready.ts
|
|
28509
|
-
function symbolIndexFileIsReady(parentPath, filePath) {
|
|
28510
|
-
const normalizedParent = normalizeResolvedPath(parentPath);
|
|
28511
|
-
const normalizedFile = filePath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
28512
|
-
if (!normalizedFile) return false;
|
|
28513
|
-
return withCodeNavCacheSqliteSync((db) => {
|
|
28514
|
-
const ctx = getSymbolIndexParentContext(db, normalizedParent);
|
|
28515
|
-
if (ctx == null) return false;
|
|
28516
|
-
const versionRow = db.get("SELECT index_version FROM symbol_index_parent_path WHERE id = ?", [
|
|
28517
|
-
ctx.parentId
|
|
28518
|
-
]);
|
|
28519
|
-
if (versionRow == null || versionRow.index_version < SYMBOL_INDEX_VERSION) return false;
|
|
28520
|
-
return getEffectiveContentHash(db, ctx, normalizedFile) != null;
|
|
28521
|
-
});
|
|
28545
|
+
return remaining;
|
|
28522
28546
|
}
|
|
28523
28547
|
|
|
28524
28548
|
// src/code-nav/symbol-index/sqlite/symbol-index-sqlite-lock.ts
|
|
28525
|
-
import fs18 from "node:fs";
|
|
28526
|
-
function isSqliteCorruptError(e) {
|
|
28527
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
28528
|
-
return msg.includes("malformed") || msg.includes("database disk image is malformed") || msg.includes("corrupt");
|
|
28529
|
-
}
|
|
28530
|
-
var chain = Promise.resolve();
|
|
28531
28549
|
function withSymbolIndexSqliteLock(fn) {
|
|
28532
|
-
|
|
28533
|
-
try {
|
|
28534
|
-
return await Promise.resolve(fn());
|
|
28535
|
-
} catch (e) {
|
|
28536
|
-
if (!isSqliteCorruptError(e)) throw e;
|
|
28537
|
-
closeAllCodeNavCacheSqliteConnections();
|
|
28538
|
-
try {
|
|
28539
|
-
fs18.unlinkSync(getCodeNavCacheSqlitePath());
|
|
28540
|
-
} catch {
|
|
28541
|
-
}
|
|
28542
|
-
chain = Promise.resolve();
|
|
28543
|
-
return await Promise.resolve(fn());
|
|
28544
|
-
}
|
|
28545
|
-
};
|
|
28546
|
-
const next = chain.then(run);
|
|
28547
|
-
chain = next.then(
|
|
28548
|
-
() => void 0,
|
|
28549
|
-
() => void 0
|
|
28550
|
-
);
|
|
28551
|
-
return next;
|
|
28550
|
+
return withCodeNavCacheSqliteWorkLock(fn);
|
|
28552
28551
|
}
|
|
28553
28552
|
|
|
28554
28553
|
// src/code-nav/symbol-index/imports/star-reexport-names.ts
|
|
@@ -28653,43 +28652,111 @@ function expandStarReexportBindings(collected) {
|
|
|
28653
28652
|
}
|
|
28654
28653
|
|
|
28655
28654
|
// src/code-nav/symbol-index/persistence/persist-single-file.ts
|
|
28656
|
-
function
|
|
28657
|
-
|
|
28658
|
-
db
|
|
28659
|
-
try {
|
|
28655
|
+
async function persistSymbolIndexFileAsync(resolved, relPath, source, tags, imports) {
|
|
28656
|
+
await withCodeNavCacheSqlite(async (db) => {
|
|
28657
|
+
runCodeNavCacheWriteTransaction(db, () => {
|
|
28660
28658
|
upsertSymbolIndexParentPath(db, resolved);
|
|
28661
28659
|
const ctx = getSymbolIndexParentContext(db, resolved);
|
|
28662
28660
|
if (ctx == null) throw new Error(`Failed to resolve symbol index parent: ${resolved}`);
|
|
28663
28661
|
persistSymbolIndexFileData(db, ctx, relPath, source, tags, imports);
|
|
28664
|
-
|
|
28665
|
-
} catch (e) {
|
|
28666
|
-
try {
|
|
28667
|
-
db.run("ROLLBACK");
|
|
28668
|
-
} catch {
|
|
28669
|
-
}
|
|
28670
|
-
throw e;
|
|
28671
|
-
}
|
|
28662
|
+
});
|
|
28672
28663
|
});
|
|
28673
28664
|
}
|
|
28674
|
-
function
|
|
28675
|
-
|
|
28676
|
-
db
|
|
28677
|
-
try {
|
|
28665
|
+
async function removeSymbolIndexFileAsync(resolved, relPath) {
|
|
28666
|
+
await withCodeNavCacheSqlite(async (db) => {
|
|
28667
|
+
runCodeNavCacheWriteTransaction(db, () => {
|
|
28678
28668
|
upsertSymbolIndexParentPath(db, resolved);
|
|
28679
28669
|
const ctx = getSymbolIndexParentContext(db, resolved);
|
|
28680
28670
|
if (ctx == null) throw new Error(`Failed to resolve symbol index parent: ${resolved}`);
|
|
28681
28671
|
removeSymbolIndexFileData(db, ctx, relPath);
|
|
28682
|
-
|
|
28683
|
-
} catch (e) {
|
|
28684
|
-
try {
|
|
28685
|
-
db.run("ROLLBACK");
|
|
28686
|
-
} catch {
|
|
28687
|
-
}
|
|
28688
|
-
throw e;
|
|
28689
|
-
}
|
|
28672
|
+
});
|
|
28690
28673
|
});
|
|
28691
28674
|
}
|
|
28692
28675
|
|
|
28676
|
+
// src/code-nav/symbol-index/query/tag-query-shared.ts
|
|
28677
|
+
var TAG_SELECT = `file_path, name, role, kind, start_line, start_column, end_line, end_column,
|
|
28678
|
+
scope_start_line, scope_start_column, parent_scope_start_line, parent_scope_start_column, nav_target_path, scope_chain`;
|
|
28679
|
+
function rowToLocation(row) {
|
|
28680
|
+
return {
|
|
28681
|
+
path: row.file_path,
|
|
28682
|
+
line: row.start_line + 1,
|
|
28683
|
+
column: row.start_column,
|
|
28684
|
+
kind: row.kind,
|
|
28685
|
+
role: row.role === "def" ? "definition" : "reference"
|
|
28686
|
+
};
|
|
28687
|
+
}
|
|
28688
|
+
function modulePathLocation(row) {
|
|
28689
|
+
return {
|
|
28690
|
+
path: row.nav_target_path,
|
|
28691
|
+
line: 1,
|
|
28692
|
+
column: 0,
|
|
28693
|
+
kind: "module",
|
|
28694
|
+
role: "reference"
|
|
28695
|
+
};
|
|
28696
|
+
}
|
|
28697
|
+
function emptyRefRow(filePath) {
|
|
28698
|
+
return {
|
|
28699
|
+
file_path: filePath,
|
|
28700
|
+
name: "",
|
|
28701
|
+
role: "ref",
|
|
28702
|
+
kind: "",
|
|
28703
|
+
start_line: 0,
|
|
28704
|
+
start_column: 0,
|
|
28705
|
+
end_line: 0,
|
|
28706
|
+
end_column: 0,
|
|
28707
|
+
scope_start_line: null,
|
|
28708
|
+
scope_start_column: null,
|
|
28709
|
+
parent_scope_start_line: null,
|
|
28710
|
+
parent_scope_start_column: null,
|
|
28711
|
+
nav_target_path: null,
|
|
28712
|
+
scope_chain: null
|
|
28713
|
+
};
|
|
28714
|
+
}
|
|
28715
|
+
|
|
28716
|
+
// src/code-nav/symbol-index/storage/file-content-load.ts
|
|
28717
|
+
function loadFileTags(db, ctx, filePath) {
|
|
28718
|
+
const contentHash = getEffectiveContentHash(db, ctx, filePath);
|
|
28719
|
+
if (contentHash == null) return [];
|
|
28720
|
+
return db.all(
|
|
28721
|
+
`SELECT ${TAG_SELECT}
|
|
28722
|
+
FROM symbol_index_tag
|
|
28723
|
+
WHERE content_hash = ? AND file_path = ?
|
|
28724
|
+
ORDER BY start_line, start_column`,
|
|
28725
|
+
[contentHash, filePath]
|
|
28726
|
+
);
|
|
28727
|
+
}
|
|
28728
|
+
function loadFileImports(db, ctx, filePath) {
|
|
28729
|
+
const contentHash = getEffectiveContentHash(db, ctx, filePath);
|
|
28730
|
+
if (contentHash == null) return [];
|
|
28731
|
+
return db.all(
|
|
28732
|
+
`SELECT file_path, local_name, source_name, module_specifier, source_file_path, import_kind, start_line, start_column
|
|
28733
|
+
FROM symbol_index_import
|
|
28734
|
+
WHERE content_hash = ? AND file_path = ?
|
|
28735
|
+
ORDER BY start_line, start_column`,
|
|
28736
|
+
[contentHash, filePath]
|
|
28737
|
+
);
|
|
28738
|
+
}
|
|
28739
|
+
function findTagsByName(db, ctx, name) {
|
|
28740
|
+
const filePaths = listEffectiveIndexedFilePaths(db, ctx);
|
|
28741
|
+
const rows = [];
|
|
28742
|
+
for (const filePath of filePaths) {
|
|
28743
|
+
const contentHash = getEffectiveContentHash(db, ctx, filePath);
|
|
28744
|
+
if (contentHash == null) continue;
|
|
28745
|
+
const matches = db.all(
|
|
28746
|
+
`SELECT ${TAG_SELECT}
|
|
28747
|
+
FROM symbol_index_tag
|
|
28748
|
+
WHERE content_hash = ? AND file_path = ? AND name = ?
|
|
28749
|
+
ORDER BY start_line, start_column`,
|
|
28750
|
+
[contentHash, filePath, name]
|
|
28751
|
+
);
|
|
28752
|
+
rows.push(...matches);
|
|
28753
|
+
}
|
|
28754
|
+
rows.sort(
|
|
28755
|
+
(a, b) => a.file_path.localeCompare(b.file_path) || a.start_line - b.start_line || a.start_column - b.start_column
|
|
28756
|
+
);
|
|
28757
|
+
return rows;
|
|
28758
|
+
}
|
|
28759
|
+
|
|
28693
28760
|
// src/code-nav/symbol-index/build/load-indexed-file-entry.ts
|
|
28694
28761
|
function dbTagToSymbolTag(row) {
|
|
28695
28762
|
return {
|
|
@@ -28735,21 +28802,52 @@ function loadIndexedFileEntry(db, ctx, relPath) {
|
|
|
28735
28802
|
function normalizeRelPath2(filePath) {
|
|
28736
28803
|
return filePath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
28737
28804
|
}
|
|
28738
|
-
function
|
|
28805
|
+
function listDirectImportTargetsWithDb(db, resolved, relPath) {
|
|
28806
|
+
const ctx = getSymbolIndexParentContext(db, resolved);
|
|
28807
|
+
if (ctx == null) return [];
|
|
28808
|
+
const entry = loadIndexedFileEntry(db, ctx, relPath);
|
|
28809
|
+
if (entry == null) return [];
|
|
28810
|
+
const paths = /* @__PURE__ */ new Set();
|
|
28811
|
+
for (const binding of entry.imports) {
|
|
28812
|
+
if (binding.sourceFilePath) paths.add(binding.sourceFilePath);
|
|
28813
|
+
}
|
|
28814
|
+
return Array.from(paths);
|
|
28815
|
+
}
|
|
28816
|
+
async function listDirectImportTargetsForFileAsync(parentPath, filePath) {
|
|
28739
28817
|
const resolved = normalizeResolvedPath(parentPath);
|
|
28740
28818
|
const relPath = normalizeRelPath2(filePath);
|
|
28741
28819
|
if (!relPath) return [];
|
|
28742
|
-
return
|
|
28743
|
-
|
|
28820
|
+
return withCodeNavCacheSqlite((db) => listDirectImportTargetsWithDb(db, resolved, relPath));
|
|
28821
|
+
}
|
|
28822
|
+
|
|
28823
|
+
// src/code-nav/symbol-index/lifecycle/symbol-index-file-ready.ts
|
|
28824
|
+
function symbolIndexFileIsReadyWithDb(db, parentPath, filePath) {
|
|
28825
|
+
const normalizedParent = normalizeResolvedPath(parentPath);
|
|
28826
|
+
const normalizedFile = filePath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
28827
|
+
if (!normalizedFile) return false;
|
|
28828
|
+
const ctx = getSymbolIndexParentContext(db, normalizedParent);
|
|
28829
|
+
if (ctx == null) return false;
|
|
28830
|
+
const versionRow = db.get("SELECT index_version FROM symbol_index_parent_path WHERE id = ?", [
|
|
28831
|
+
ctx.parentId
|
|
28832
|
+
]);
|
|
28833
|
+
if (versionRow == null || versionRow.index_version < SYMBOL_INDEX_VERSION) return false;
|
|
28834
|
+
return getEffectiveContentHash(db, ctx, normalizedFile) != null;
|
|
28835
|
+
}
|
|
28836
|
+
async function symbolIndexFileIsReadyAsync(parentPath, filePath) {
|
|
28837
|
+
return withCodeNavCacheSqlite((db) => symbolIndexFileIsReadyWithDb(db, parentPath, filePath));
|
|
28838
|
+
}
|
|
28839
|
+
async function loadSymbolIndexReadyFileSet(parentPath) {
|
|
28840
|
+
const normalizedParent = normalizeResolvedPath(parentPath);
|
|
28841
|
+
const paths = await withCodeNavCacheSqlite((db) => {
|
|
28842
|
+
const ctx = getSymbolIndexParentContext(db, normalizedParent);
|
|
28744
28843
|
if (ctx == null) return [];
|
|
28745
|
-
const
|
|
28746
|
-
|
|
28747
|
-
|
|
28748
|
-
|
|
28749
|
-
|
|
28750
|
-
}
|
|
28751
|
-
return [...paths];
|
|
28844
|
+
const versionRow = db.get("SELECT index_version FROM symbol_index_parent_path WHERE id = ?", [
|
|
28845
|
+
ctx.parentId
|
|
28846
|
+
]);
|
|
28847
|
+
if (versionRow == null || versionRow.index_version < SYMBOL_INDEX_VERSION) return [];
|
|
28848
|
+
return listEffectiveIndexedFilePaths(db, ctx);
|
|
28752
28849
|
});
|
|
28850
|
+
return new Set(paths);
|
|
28753
28851
|
}
|
|
28754
28852
|
|
|
28755
28853
|
// src/code-nav/symbol-index/build/extract-file-symbol-data.ts
|
|
@@ -29059,9 +29157,9 @@ async function augmentTypeReferenceTags(tags, nameNodes, root) {
|
|
|
29059
29157
|
}
|
|
29060
29158
|
|
|
29061
29159
|
// src/code-nav/scope-chain.ts
|
|
29062
|
-
function serializeScopeChain(
|
|
29063
|
-
if (
|
|
29064
|
-
return
|
|
29160
|
+
function serializeScopeChain(chain2) {
|
|
29161
|
+
if (chain2.length === 0) return null;
|
|
29162
|
+
return chain2.map((anchor) => `${anchor.startLine}:${anchor.startColumn}`).join(",");
|
|
29065
29163
|
}
|
|
29066
29164
|
function parseScopeChain(raw) {
|
|
29067
29165
|
if (!raw) return [];
|
|
@@ -29077,9 +29175,9 @@ function parseScopeChain(raw) {
|
|
|
29077
29175
|
}
|
|
29078
29176
|
return out;
|
|
29079
29177
|
}
|
|
29080
|
-
function anchorInScopeChain(line, column,
|
|
29081
|
-
if (line == null || column == null) return
|
|
29082
|
-
return
|
|
29178
|
+
function anchorInScopeChain(line, column, chain2) {
|
|
29179
|
+
if (line == null || column == null) return chain2.length === 0;
|
|
29180
|
+
return chain2.some((anchor) => anchor.startLine === line && anchor.startColumn === column);
|
|
29083
29181
|
}
|
|
29084
29182
|
|
|
29085
29183
|
// src/code-nav/enrich-tag-scope.ts
|
|
@@ -29116,15 +29214,15 @@ function scopeAnchorFromNode(node) {
|
|
|
29116
29214
|
};
|
|
29117
29215
|
}
|
|
29118
29216
|
function findEnclosingScopeChain(nameNode) {
|
|
29119
|
-
const
|
|
29217
|
+
const chain2 = [];
|
|
29120
29218
|
let current = nameNode.parent;
|
|
29121
29219
|
while (current) {
|
|
29122
29220
|
if (SCOPE_CONTAINER_TYPES.has(current.type)) {
|
|
29123
|
-
|
|
29221
|
+
chain2.push(scopeAnchorFromNode(current));
|
|
29124
29222
|
}
|
|
29125
29223
|
current = current.parent;
|
|
29126
29224
|
}
|
|
29127
|
-
return
|
|
29225
|
+
return chain2;
|
|
29128
29226
|
}
|
|
29129
29227
|
function findEnclosingScopes(nameNode) {
|
|
29130
29228
|
const scopeChain = findEnclosingScopeChain(nameNode);
|
|
@@ -29981,7 +30079,7 @@ async function extractFileSymbolData(resolved, relPath, workspaceFilesOverride)
|
|
|
29981
30079
|
}
|
|
29982
30080
|
}
|
|
29983
30081
|
await yieldToEventLoop();
|
|
29984
|
-
const workspaceFiles = workspaceFilesOverride ??
|
|
30082
|
+
const workspaceFiles = workspaceFilesOverride ?? await withCodeNavCacheSqlite((db) => listWorkspaceFiles(db, resolved, relPath));
|
|
29985
30083
|
const imports = source != null ? await extractImportBindingsFromSource(relPath, source, workspaceFiles) : [];
|
|
29986
30084
|
const yieldState = createCodeNavYieldState();
|
|
29987
30085
|
return {
|
|
@@ -30006,7 +30104,7 @@ async function indexOneSymbolFileForBuild(resolved, relPath, workspaceFiles) {
|
|
|
30006
30104
|
};
|
|
30007
30105
|
if (data.imports.some((binding) => binding.importKind === "star")) {
|
|
30008
30106
|
await yieldToEventLoop();
|
|
30009
|
-
entry =
|
|
30107
|
+
entry = await withCodeNavCacheSqlite((db) => {
|
|
30010
30108
|
const ctx = getSymbolIndexParentContext(db, resolved);
|
|
30011
30109
|
if (ctx == null) return entry;
|
|
30012
30110
|
const resolveEntry = (filePath) => loadIndexedFileEntry(db, ctx, filePath);
|
|
@@ -30016,7 +30114,7 @@ async function indexOneSymbolFileForBuild(resolved, relPath, workspaceFiles) {
|
|
|
30016
30114
|
}
|
|
30017
30115
|
await withSymbolIndexSqliteLock(async () => {
|
|
30018
30116
|
await yieldToEventLoop();
|
|
30019
|
-
|
|
30117
|
+
await persistSymbolIndexFileAsync(resolved, relPath, entry.source, entry.tags, entry.imports);
|
|
30020
30118
|
});
|
|
30021
30119
|
}
|
|
30022
30120
|
async function ensureSymbolIndexFileAsync(parentPath, filePath, opts) {
|
|
@@ -30024,41 +30122,51 @@ async function ensureSymbolIndexFileAsync(parentPath, filePath, opts) {
|
|
|
30024
30122
|
const relPath = normalizeRelPath3(filePath);
|
|
30025
30123
|
if (!relPath) return false;
|
|
30026
30124
|
const importDepth = opts?.importDepth ?? 0;
|
|
30027
|
-
|
|
30125
|
+
await withCodeNavCacheSqlite((db) => {
|
|
30028
30126
|
upsertSymbolIndexParentPath(db, resolved);
|
|
30029
30127
|
});
|
|
30030
|
-
if (!
|
|
30128
|
+
if (!await symbolIndexFileIsReadyAsync(resolved, relPath)) {
|
|
30031
30129
|
await indexOneSymbolFileForBuild(resolved, relPath, void 0);
|
|
30032
30130
|
}
|
|
30033
|
-
if (importDepth > 0 &&
|
|
30034
|
-
const targets =
|
|
30131
|
+
if (importDepth > 0 && await symbolIndexFileIsReadyAsync(resolved, relPath)) {
|
|
30132
|
+
const targets = (await listDirectImportTargetsForFileAsync(resolved, relPath)).slice(
|
|
30133
|
+
0,
|
|
30134
|
+
MAX_IMPORT_PREFETCH_COUNT
|
|
30135
|
+
);
|
|
30035
30136
|
for (const target of targets) {
|
|
30036
30137
|
await yieldToEventLoop();
|
|
30037
|
-
if (!
|
|
30138
|
+
if (!await symbolIndexFileIsReadyAsync(resolved, target)) {
|
|
30038
30139
|
await ensureSymbolIndexFileAsync(resolved, target, { importDepth: importDepth - 1 });
|
|
30039
30140
|
}
|
|
30040
30141
|
}
|
|
30041
30142
|
}
|
|
30042
|
-
return
|
|
30143
|
+
return await symbolIndexFileIsReadyAsync(resolved, relPath);
|
|
30043
30144
|
}
|
|
30044
|
-
function
|
|
30145
|
+
async function registerSymbolIndexParentAsync(parentPath) {
|
|
30045
30146
|
const resolved = normalizeResolvedPath(parentPath);
|
|
30046
|
-
|
|
30147
|
+
await withCodeNavCacheSqlite((db) => {
|
|
30047
30148
|
upsertSymbolIndexParentPath(db, resolved);
|
|
30048
30149
|
});
|
|
30049
30150
|
}
|
|
30050
30151
|
|
|
30051
30152
|
// src/code-nav/symbol-index/build/build-symbol-index.ts
|
|
30153
|
+
var SYMBOL_PARENT_CLEAR_BATCH_SIZE = 256;
|
|
30052
30154
|
async function buildSymbolIndexAsync(parentPath) {
|
|
30053
30155
|
const resolved = normalizeResolvedPath(parentPath);
|
|
30054
30156
|
await yieldToEventLoop();
|
|
30055
|
-
|
|
30056
|
-
|
|
30057
|
-
|
|
30058
|
-
|
|
30059
|
-
|
|
30157
|
+
let clearRemaining = true;
|
|
30158
|
+
while (clearRemaining) {
|
|
30159
|
+
await withSymbolIndexSqliteLock(async () => {
|
|
30160
|
+
clearRemaining = await withCodeNavCacheSqlite(
|
|
30161
|
+
(db) => runCodeNavCacheWriteTransaction(db, () => {
|
|
30162
|
+
upsertSymbolIndexParentPath(db, resolved);
|
|
30163
|
+
const ctx = getSymbolIndexParentContext(db, resolved);
|
|
30164
|
+
return ctx == null ? false : clearSymbolIndexParentDataBatch(db, ctx, SYMBOL_PARENT_CLEAR_BATCH_SIZE);
|
|
30165
|
+
})
|
|
30166
|
+
);
|
|
30060
30167
|
});
|
|
30061
|
-
|
|
30168
|
+
if (clearRemaining) await yieldToEventLoop();
|
|
30169
|
+
}
|
|
30062
30170
|
const workspaceFiles = /* @__PURE__ */ new Set();
|
|
30063
30171
|
const walkState = createWalkYieldState();
|
|
30064
30172
|
const yieldState = createCodeNavYieldState();
|
|
@@ -30075,9 +30183,7 @@ async function buildSymbolIndexAsync(parentPath) {
|
|
|
30075
30183
|
resolved,
|
|
30076
30184
|
async (relPath) => {
|
|
30077
30185
|
await yieldDuringCodeNavWork(yieldState);
|
|
30078
|
-
|
|
30079
|
-
await indexOneSymbolFileForBuild(resolved, relPath, workspaceFiles);
|
|
30080
|
-
}
|
|
30186
|
+
await indexOneSymbolFileForBuild(resolved, relPath, workspaceFiles);
|
|
30081
30187
|
fileCount += 1;
|
|
30082
30188
|
},
|
|
30083
30189
|
walkState
|
|
@@ -30086,18 +30192,79 @@ async function buildSymbolIndexAsync(parentPath) {
|
|
|
30086
30192
|
return { fileCount, tagCount: 0 };
|
|
30087
30193
|
}
|
|
30088
30194
|
|
|
30195
|
+
// src/code-nav/symbol-index/scheduler/task-priority-heap.ts
|
|
30196
|
+
function higherPriority(a, b) {
|
|
30197
|
+
return a.priority > b.priority;
|
|
30198
|
+
}
|
|
30199
|
+
var SymbolIndexTaskPriorityHeap = class {
|
|
30200
|
+
heap = [];
|
|
30201
|
+
clear() {
|
|
30202
|
+
this.heap.length = 0;
|
|
30203
|
+
}
|
|
30204
|
+
push(task) {
|
|
30205
|
+
this.heap.push(task);
|
|
30206
|
+
let i = this.heap.length - 1;
|
|
30207
|
+
while (i > 0) {
|
|
30208
|
+
const parent = Math.floor((i - 1) / 2);
|
|
30209
|
+
if (!higherPriority(this.heap[i], this.heap[parent])) break;
|
|
30210
|
+
this.swap(i, parent);
|
|
30211
|
+
i = parent;
|
|
30212
|
+
}
|
|
30213
|
+
}
|
|
30214
|
+
pop() {
|
|
30215
|
+
if (this.heap.length === 0) return void 0;
|
|
30216
|
+
const top = this.heap[0];
|
|
30217
|
+
const last2 = this.heap.pop();
|
|
30218
|
+
if (this.heap.length > 0) {
|
|
30219
|
+
this.heap[0] = last2;
|
|
30220
|
+
this.sink(0);
|
|
30221
|
+
}
|
|
30222
|
+
return top;
|
|
30223
|
+
}
|
|
30224
|
+
get size() {
|
|
30225
|
+
return this.heap.length;
|
|
30226
|
+
}
|
|
30227
|
+
sink(start) {
|
|
30228
|
+
let i = start;
|
|
30229
|
+
while (true) {
|
|
30230
|
+
const left = i * 2 + 1;
|
|
30231
|
+
const right = left + 1;
|
|
30232
|
+
let best = i;
|
|
30233
|
+
if (left < this.heap.length && higherPriority(this.heap[left], this.heap[best])) best = left;
|
|
30234
|
+
if (right < this.heap.length && higherPriority(this.heap[right], this.heap[best])) best = right;
|
|
30235
|
+
if (best === i) break;
|
|
30236
|
+
this.swap(i, best);
|
|
30237
|
+
i = best;
|
|
30238
|
+
}
|
|
30239
|
+
}
|
|
30240
|
+
swap(i, j) {
|
|
30241
|
+
const tmp = this.heap[i];
|
|
30242
|
+
this.heap[i] = this.heap[j];
|
|
30243
|
+
this.heap[j] = tmp;
|
|
30244
|
+
}
|
|
30245
|
+
};
|
|
30246
|
+
|
|
30247
|
+
// src/code-nav/symbol-index/scheduler/task-queue-types.ts
|
|
30248
|
+
function symbolIndexTaskKey(parentPath, filePath) {
|
|
30249
|
+
return `${parentPath}\0${filePath}`;
|
|
30250
|
+
}
|
|
30251
|
+
|
|
30089
30252
|
// src/code-nav/symbol-index/scheduler/task-queue.ts
|
|
30090
30253
|
var pending = /* @__PURE__ */ new Map();
|
|
30254
|
+
var heap = new SymbolIndexTaskPriorityHeap();
|
|
30255
|
+
var latestActiveSequenceByParent = /* @__PURE__ */ new Map();
|
|
30091
30256
|
var workerRunning = false;
|
|
30092
|
-
function
|
|
30093
|
-
|
|
30257
|
+
function taskMatchesCurrentPending(task) {
|
|
30258
|
+
const current = pending.get(symbolIndexTaskKey(task.parentPath, task.filePath));
|
|
30259
|
+
return current === task;
|
|
30094
30260
|
}
|
|
30095
30261
|
function pickNextTask() {
|
|
30096
|
-
|
|
30097
|
-
|
|
30098
|
-
if (
|
|
30262
|
+
while (heap.size > 0) {
|
|
30263
|
+
const task = heap.pop();
|
|
30264
|
+
if (task == null || !taskMatchesCurrentPending(task)) continue;
|
|
30265
|
+
return task;
|
|
30099
30266
|
}
|
|
30100
|
-
return
|
|
30267
|
+
return void 0;
|
|
30101
30268
|
}
|
|
30102
30269
|
async function runWorker() {
|
|
30103
30270
|
if (workerRunning) return;
|
|
@@ -30107,74 +30274,93 @@ async function runWorker() {
|
|
|
30107
30274
|
while (pending.size > 0) {
|
|
30108
30275
|
const task = pickNextTask();
|
|
30109
30276
|
if (task == null) break;
|
|
30110
|
-
pending.delete(
|
|
30277
|
+
pending.delete(symbolIndexTaskKey(task.parentPath, task.filePath));
|
|
30111
30278
|
await yieldDuringCodeNavWork(yieldState);
|
|
30112
|
-
|
|
30279
|
+
const latestActiveSequence = latestActiveSequenceByParent.get(task.parentPath);
|
|
30280
|
+
if (latestActiveSequence != null && task.sequence != null && task.sequence < latestActiveSequence) {
|
|
30281
|
+
continue;
|
|
30282
|
+
}
|
|
30283
|
+
if (!await symbolIndexFileIsReadyAsync(task.parentPath, task.filePath)) {
|
|
30113
30284
|
await ensureSymbolIndexFileAsync(task.parentPath, task.filePath);
|
|
30114
30285
|
}
|
|
30115
30286
|
await yieldToEventLoop();
|
|
30116
30287
|
}
|
|
30117
30288
|
} finally {
|
|
30289
|
+
if (pending.size === 0) heap.clear();
|
|
30118
30290
|
workerRunning = false;
|
|
30119
30291
|
if (pending.size > 0) void runWorker();
|
|
30120
30292
|
}
|
|
30121
30293
|
}
|
|
30122
|
-
function enqueueSymbolIndexTask(parentPath, filePath, priority) {
|
|
30294
|
+
function enqueueSymbolIndexTask(parentPath, filePath, priority, sequence) {
|
|
30123
30295
|
const normalizedParent = normalizeResolvedPath(parentPath);
|
|
30124
30296
|
const normalizedFile = filePath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
30125
30297
|
if (!normalizedFile) return;
|
|
30126
|
-
|
|
30127
|
-
const key = taskKey(normalizedParent, normalizedFile);
|
|
30298
|
+
const key = symbolIndexTaskKey(normalizedParent, normalizedFile);
|
|
30128
30299
|
const existing = pending.get(key);
|
|
30129
30300
|
if (existing != null && existing.priority >= priority) return;
|
|
30130
|
-
|
|
30301
|
+
const task = { parentPath: normalizedParent, filePath: normalizedFile, priority, sequence };
|
|
30302
|
+
pending.set(key, task);
|
|
30303
|
+
heap.push(task);
|
|
30131
30304
|
void runWorker();
|
|
30132
30305
|
}
|
|
30306
|
+
function markLatestActiveSymbolIndexTask(parentPath, sequence) {
|
|
30307
|
+
const normalizedParent = normalizeResolvedPath(parentPath);
|
|
30308
|
+
const existing = latestActiveSequenceByParent.get(normalizedParent);
|
|
30309
|
+
if (existing != null && existing >= sequence) return;
|
|
30310
|
+
latestActiveSequenceByParent.set(normalizedParent, sequence);
|
|
30311
|
+
for (const [key, task] of pending) {
|
|
30312
|
+
if (task.parentPath === normalizedParent && task.sequence != null && task.sequence < sequence) {
|
|
30313
|
+
pending.delete(key);
|
|
30314
|
+
}
|
|
30315
|
+
}
|
|
30316
|
+
if (pending.size === 0) heap.clear();
|
|
30317
|
+
}
|
|
30133
30318
|
|
|
30134
30319
|
// src/code-nav/symbol-index/scheduler/symbol-index-scheduler.ts
|
|
30135
30320
|
var requestSeq = 0;
|
|
30136
30321
|
var warmupSeq = 0;
|
|
30137
30322
|
var warmupScheduled = /* @__PURE__ */ new Set();
|
|
30323
|
+
var warmupCompleted = /* @__PURE__ */ new Set();
|
|
30138
30324
|
function scheduleSymbolIndexFile(parentPath, filePath) {
|
|
30139
|
-
|
|
30325
|
+
const sequence = ++requestSeq;
|
|
30326
|
+
markLatestActiveSymbolIndexTask(parentPath, sequence);
|
|
30327
|
+
enqueueSymbolIndexTask(parentPath, filePath, 1e6 + sequence, sequence);
|
|
30140
30328
|
}
|
|
30141
30329
|
function scheduleSymbolIndexImportNeighbors(parentPath, filePaths) {
|
|
30142
30330
|
let priority = 5e5 + requestSeq;
|
|
30143
30331
|
for (const filePath of filePaths) {
|
|
30144
|
-
enqueueSymbolIndexTask(parentPath, filePath, priority);
|
|
30332
|
+
enqueueSymbolIndexTask(parentPath, filePath, priority, requestSeq);
|
|
30145
30333
|
priority -= 1;
|
|
30146
30334
|
}
|
|
30147
30335
|
}
|
|
30148
30336
|
function scheduleSymbolIndexWarmup(parentPath) {
|
|
30149
30337
|
const resolved = normalizeResolvedPath(parentPath);
|
|
30338
|
+
if (warmupCompleted.has(resolved)) return;
|
|
30150
30339
|
if (warmupScheduled.has(resolved)) return;
|
|
30151
30340
|
warmupScheduled.add(resolved);
|
|
30152
30341
|
setImmediate(() => {
|
|
30153
30342
|
void (async () => {
|
|
30154
30343
|
try {
|
|
30344
|
+
const readyFiles = await loadSymbolIndexReadyFileSet(resolved);
|
|
30155
30345
|
const walkState = createWalkYieldState();
|
|
30156
30346
|
const yieldState = createCodeNavYieldState();
|
|
30157
30347
|
await walkCodeNavFilesAsync(
|
|
30158
30348
|
resolved,
|
|
30159
30349
|
async (relPath) => {
|
|
30160
30350
|
await yieldDuringCodeNavWork(yieldState);
|
|
30161
|
-
if (!
|
|
30162
|
-
enqueueSymbolIndexTask(resolved, relPath, ++warmupSeq);
|
|
30351
|
+
if (!readyFiles.has(relPath)) {
|
|
30352
|
+
enqueueSymbolIndexTask(resolved, relPath, ++warmupSeq, requestSeq);
|
|
30163
30353
|
}
|
|
30164
30354
|
},
|
|
30165
30355
|
walkState
|
|
30166
30356
|
);
|
|
30357
|
+
warmupCompleted.add(resolved);
|
|
30167
30358
|
} finally {
|
|
30168
30359
|
warmupScheduled.delete(resolved);
|
|
30169
30360
|
}
|
|
30170
30361
|
})();
|
|
30171
30362
|
});
|
|
30172
30363
|
}
|
|
30173
|
-
function scheduleSymbolIndexForRequest(parentPath, reqPath, importTargets) {
|
|
30174
|
-
scheduleSymbolIndexFile(parentPath, reqPath);
|
|
30175
|
-
scheduleSymbolIndexImportNeighbors(parentPath, importTargets);
|
|
30176
|
-
scheduleSymbolIndexWarmup(parentPath);
|
|
30177
|
-
}
|
|
30178
30364
|
|
|
30179
30365
|
// src/code-nav/symbol-index/lifecycle/normalize-symbol-index-path.ts
|
|
30180
30366
|
import path23 from "node:path";
|
|
@@ -30190,27 +30376,23 @@ function normalizeSymbolIndexRelPath(parentPath, changedPath) {
|
|
|
30190
30376
|
async function updateSymbolIndexForFile(parentPath, changedPath) {
|
|
30191
30377
|
const relPath = normalizeSymbolIndexRelPath(parentPath, changedPath);
|
|
30192
30378
|
if (relPath == null) return;
|
|
30379
|
+
const resolved = normalizeResolvedPath(parentPath);
|
|
30380
|
+
const { source, tags, imports } = await extractFileSymbolData(resolved, relPath);
|
|
30381
|
+
await yieldToEventLoop();
|
|
30193
30382
|
await withSymbolIndexSqliteLock(async () => {
|
|
30194
|
-
|
|
30195
|
-
const { source, tags, imports } = await extractFileSymbolData(resolved, relPath);
|
|
30196
|
-
await yieldToEventLoop();
|
|
30197
|
-
persistSymbolIndexFile(resolved, relPath, source, tags, imports);
|
|
30383
|
+
await persistSymbolIndexFileAsync(resolved, relPath, source, tags, imports);
|
|
30198
30384
|
});
|
|
30199
30385
|
}
|
|
30200
30386
|
async function removeSymbolIndexForFile(parentPath, changedPath) {
|
|
30201
30387
|
const relPath = normalizeSymbolIndexRelPath(parentPath, changedPath);
|
|
30202
30388
|
if (relPath == null) return;
|
|
30389
|
+
const resolved = normalizeResolvedPath(parentPath);
|
|
30203
30390
|
await withSymbolIndexSqliteLock(async () => {
|
|
30204
|
-
|
|
30391
|
+
await removeSymbolIndexFileAsync(resolved, relPath);
|
|
30205
30392
|
});
|
|
30206
30393
|
}
|
|
30207
30394
|
|
|
30208
30395
|
// src/code-nav/symbol-index/sqlite/symbol-index-import-sqlite.ts
|
|
30209
|
-
function listImportsForFile(db, parentId, filePath) {
|
|
30210
|
-
const ctx = getSymbolIndexParentContextById(db, parentId);
|
|
30211
|
-
if (ctx == null) return [];
|
|
30212
|
-
return loadFileImports(db, ctx, filePath);
|
|
30213
|
-
}
|
|
30214
30396
|
function prefersTypeImport(refKind) {
|
|
30215
30397
|
return refKind === "type";
|
|
30216
30398
|
}
|
|
@@ -30236,7 +30418,7 @@ function findImportBindingForLocalName(imports, localName, ref) {
|
|
|
30236
30418
|
function defsByFileNameKey(filePath, name) {
|
|
30237
30419
|
return `${filePath}\0${name}`;
|
|
30238
30420
|
}
|
|
30239
|
-
function
|
|
30421
|
+
function createSnapshotNavigationLookups(db, parentId) {
|
|
30240
30422
|
const ctx = getSymbolIndexParentContextById(db, parentId);
|
|
30241
30423
|
if (ctx == null) {
|
|
30242
30424
|
return {
|
|
@@ -30248,29 +30430,24 @@ function createNavigationLookups(db, parentId) {
|
|
|
30248
30430
|
const fileDefsCache = /* @__PURE__ */ new Map();
|
|
30249
30431
|
const defsByFileNameCache = /* @__PURE__ */ new Map();
|
|
30250
30432
|
const importsCache = /* @__PURE__ */ new Map();
|
|
30251
|
-
|
|
30252
|
-
|
|
30253
|
-
|
|
30254
|
-
|
|
30255
|
-
|
|
30256
|
-
|
|
30257
|
-
|
|
30258
|
-
|
|
30259
|
-
|
|
30260
|
-
|
|
30261
|
-
|
|
30262
|
-
if (cached2) return cached2;
|
|
30263
|
-
cached2 = loadFileTags(db, ctx, filePath).filter((row) => row.role === "def" && row.name === name);
|
|
30264
|
-
defsByFileNameCache.set(key, cached2);
|
|
30265
|
-
return cached2;
|
|
30266
|
-
},
|
|
30267
|
-
lookupImportsForFile(filePath) {
|
|
30268
|
-
let cached2 = importsCache.get(filePath);
|
|
30269
|
-
if (cached2) return cached2;
|
|
30270
|
-
cached2 = listImportsForFile(db, parentId, filePath);
|
|
30271
|
-
importsCache.set(filePath, cached2);
|
|
30272
|
-
return cached2;
|
|
30433
|
+
for (const filePath of listEffectiveIndexedFilePaths(db, ctx)) {
|
|
30434
|
+
const defs = loadFileTags(db, ctx, filePath).filter((row) => row.role === "def");
|
|
30435
|
+
fileDefsCache.set(filePath, defs);
|
|
30436
|
+
for (const def of defs) {
|
|
30437
|
+
const key = defsByFileNameKey(filePath, def.name);
|
|
30438
|
+
const existing = defsByFileNameCache.get(key);
|
|
30439
|
+
if (existing) {
|
|
30440
|
+
existing.push(def);
|
|
30441
|
+
} else {
|
|
30442
|
+
defsByFileNameCache.set(key, [def]);
|
|
30443
|
+
}
|
|
30273
30444
|
}
|
|
30445
|
+
importsCache.set(filePath, loadFileImports(db, ctx, filePath));
|
|
30446
|
+
}
|
|
30447
|
+
return {
|
|
30448
|
+
loadFileDefs: (filePath) => fileDefsCache.get(filePath) ?? [],
|
|
30449
|
+
lookupDefsInFileNamed: (filePath, name) => defsByFileNameCache.get(defsByFileNameKey(filePath, name)) ?? [],
|
|
30450
|
+
lookupImportsForFile: (filePath) => importsCache.get(filePath) ?? []
|
|
30274
30451
|
};
|
|
30275
30452
|
}
|
|
30276
30453
|
|
|
@@ -30279,11 +30456,11 @@ function refScopeChain(ref) {
|
|
|
30279
30456
|
const parsed = parseScopeChain(ref.scope_chain);
|
|
30280
30457
|
if (parsed.length > 0) return parsed;
|
|
30281
30458
|
if (ref.scope_start_line != null && ref.scope_start_column != null) {
|
|
30282
|
-
const
|
|
30459
|
+
const chain2 = [{ startLine: ref.scope_start_line, startColumn: ref.scope_start_column }];
|
|
30283
30460
|
if (ref.parent_scope_start_line != null && ref.parent_scope_start_column != null) {
|
|
30284
|
-
|
|
30461
|
+
chain2.push({ startLine: ref.parent_scope_start_line, startColumn: ref.parent_scope_start_column });
|
|
30285
30462
|
}
|
|
30286
|
-
return
|
|
30463
|
+
return chain2;
|
|
30287
30464
|
}
|
|
30288
30465
|
return [];
|
|
30289
30466
|
}
|
|
@@ -30294,17 +30471,17 @@ function defAtScopeAnchor(def, anchor) {
|
|
|
30294
30471
|
return scopesMatch(def.scope_start_line, def.scope_start_column, anchor.startLine, anchor.startColumn) || scopesMatch(def.start_line, def.start_column, anchor.startLine, anchor.startColumn);
|
|
30295
30472
|
}
|
|
30296
30473
|
function defVisibleInRefScopeChain(def, ref) {
|
|
30297
|
-
const
|
|
30298
|
-
if (
|
|
30299
|
-
return anchorInScopeChain(def.scope_start_line, def.scope_start_column,
|
|
30474
|
+
const chain2 = refScopeChain(ref);
|
|
30475
|
+
if (chain2.length === 0) return isModuleLevelDef2(def);
|
|
30476
|
+
return anchorInScopeChain(def.scope_start_line, def.scope_start_column, chain2) || anchorInScopeChain(def.start_line, def.start_column, chain2.slice(1));
|
|
30300
30477
|
}
|
|
30301
30478
|
function scopeDepthInChain(def, ref) {
|
|
30302
|
-
const
|
|
30303
|
-
for (let index = 0; index <
|
|
30304
|
-
const anchor =
|
|
30479
|
+
const chain2 = refScopeChain(ref);
|
|
30480
|
+
for (let index = 0; index < chain2.length; index++) {
|
|
30481
|
+
const anchor = chain2[index];
|
|
30305
30482
|
if (defAtScopeAnchor(def, anchor)) return index;
|
|
30306
30483
|
}
|
|
30307
|
-
return
|
|
30484
|
+
return chain2.length;
|
|
30308
30485
|
}
|
|
30309
30486
|
|
|
30310
30487
|
// src/code-nav/resolution/navigation/confidence.ts
|
|
@@ -30470,9 +30647,9 @@ function resolveScopeLevelCandidates(defs) {
|
|
|
30470
30647
|
function resolveLocalDefinitions(ref, fileDefs) {
|
|
30471
30648
|
const named = fileDefs.filter((def) => def.name === ref.name && declaredBeforeRef(def, ref));
|
|
30472
30649
|
if (named.length === 0) return [];
|
|
30473
|
-
const
|
|
30474
|
-
if (
|
|
30475
|
-
for (const anchor of
|
|
30650
|
+
const chain2 = refScopeChain(ref);
|
|
30651
|
+
if (chain2.length > 0) {
|
|
30652
|
+
for (const anchor of chain2) {
|
|
30476
30653
|
const atLevel = named.filter((def) => defAtScopeAnchor(def, anchor));
|
|
30477
30654
|
if (atLevel.length > 0) return resolveScopeLevelCandidates(atLevel);
|
|
30478
30655
|
}
|
|
@@ -30487,10 +30664,10 @@ function resolveLocalDefinitions(ref, fileDefs) {
|
|
|
30487
30664
|
function resolveLocalDefinitionCandidates(ref, fileDefs) {
|
|
30488
30665
|
const named = fileDefs.filter((def) => def.name === ref.name && declaredBeforeRef(def, ref));
|
|
30489
30666
|
if (named.length === 0) return [];
|
|
30490
|
-
const
|
|
30491
|
-
if (
|
|
30667
|
+
const chain2 = refScopeChain(ref);
|
|
30668
|
+
if (chain2.length === 0) return resolveScopeLevelCandidates(named.filter((def) => isModuleLevelDef2(def)));
|
|
30492
30669
|
const visible = named.filter((def) => {
|
|
30493
|
-
if (
|
|
30670
|
+
if (chain2.some((anchor) => defAtScopeAnchor(def, anchor))) return true;
|
|
30494
30671
|
if (defVisibleInRefScopeChain(def, ref)) return true;
|
|
30495
30672
|
return isModuleLevelDef2(def);
|
|
30496
30673
|
});
|
|
@@ -30671,32 +30848,41 @@ function pickPrimaryTagAtPosition(rows, filePath, line, column) {
|
|
|
30671
30848
|
async function queryDefinitionsNavigation(parentPath, filePath, line, column) {
|
|
30672
30849
|
await yieldToEventLoop();
|
|
30673
30850
|
const resolved = normalizeResolvedPath(parentPath);
|
|
30674
|
-
const
|
|
30851
|
+
const snapshot = await withCodeNavCacheSqlite((db) => {
|
|
30675
30852
|
const ctx = getSymbolIndexParentContext(db, resolved);
|
|
30676
30853
|
if (ctx == null) return null;
|
|
30677
30854
|
const fileRows = loadFileTags(db, ctx, filePath);
|
|
30678
30855
|
const primary = pickPrimaryTagAtPosition(fileRows, filePath, line, column);
|
|
30679
30856
|
if (!primary) return null;
|
|
30680
30857
|
const atPos = findTagsAtPosition(fileRows, filePath, line, column);
|
|
30681
|
-
|
|
30682
|
-
return { definitions: [modulePathLocation(primary)], confidentTarget: true };
|
|
30683
|
-
}
|
|
30684
|
-
const onDefinition = atPos.some((row) => row.role === "def");
|
|
30685
|
-
if (onDefinition) {
|
|
30686
|
-
const defs = atPos.filter((row) => row.role === "def").map(rowToLocation);
|
|
30687
|
-
return { definitions: defs, confidentTarget: defs.length === 1 };
|
|
30688
|
-
}
|
|
30689
|
-
const lookups = createNavigationLookups(db, ctx.parentId);
|
|
30858
|
+
const lookups = createSnapshotNavigationLookups(db, ctx.parentId);
|
|
30690
30859
|
const workspaceFiles = listWorkspaceFiles(db, resolved, filePath);
|
|
30691
|
-
|
|
30692
|
-
const navigation = resolveNavigation(navCtx);
|
|
30693
|
-
return {
|
|
30694
|
-
definitions: navigation.definitions.map(rowToLocation),
|
|
30695
|
-
confidentTarget: navigation.confidentTarget
|
|
30696
|
-
};
|
|
30860
|
+
return { primary, atPos, lookups, workspaceFiles };
|
|
30697
30861
|
});
|
|
30862
|
+
if (snapshot == null) {
|
|
30863
|
+
await yieldToEventLoop();
|
|
30864
|
+
return { definitions: [], confidentTarget: false };
|
|
30865
|
+
}
|
|
30866
|
+
const result = resolveDefinitionsFromSnapshot(filePath, snapshot);
|
|
30698
30867
|
await yieldToEventLoop();
|
|
30699
|
-
return result
|
|
30868
|
+
return result;
|
|
30869
|
+
}
|
|
30870
|
+
function resolveDefinitionsFromSnapshot(filePath, snapshot) {
|
|
30871
|
+
const { primary, atPos, lookups, workspaceFiles } = snapshot;
|
|
30872
|
+
if (primary.kind === "module" && primary.nav_target_path) {
|
|
30873
|
+
return { definitions: [modulePathLocation(primary)], confidentTarget: true };
|
|
30874
|
+
}
|
|
30875
|
+
const onDefinition = atPos.some((row) => row.role === "def");
|
|
30876
|
+
if (onDefinition) {
|
|
30877
|
+
const defs = atPos.filter((row) => row.role === "def").map(rowToLocation);
|
|
30878
|
+
return { definitions: defs, confidentTarget: defs.length === 1 };
|
|
30879
|
+
}
|
|
30880
|
+
const navCtx = buildNavigationContext(filePath, primary, lookups, workspaceFiles);
|
|
30881
|
+
const navigation = resolveNavigation(navCtx);
|
|
30882
|
+
return {
|
|
30883
|
+
definitions: navigation.definitions.map(rowToLocation),
|
|
30884
|
+
confidentTarget: navigation.confidentTarget
|
|
30885
|
+
};
|
|
30700
30886
|
}
|
|
30701
30887
|
async function queryDefinitionsAt(parentPath, filePath, line, column) {
|
|
30702
30888
|
return (await queryDefinitionsNavigation(parentPath, filePath, line, column)).definitions;
|
|
@@ -30709,7 +30895,7 @@ async function queryDefinitionAt(parentPath, filePath, line, column) {
|
|
|
30709
30895
|
async function queryReferencesAt(parentPath, filePath, line, column) {
|
|
30710
30896
|
await yieldToEventLoop();
|
|
30711
30897
|
const resolved = normalizeResolvedPath(parentPath);
|
|
30712
|
-
const rows =
|
|
30898
|
+
const rows = await withCodeNavCacheSqlite((db) => {
|
|
30713
30899
|
const ctx = getSymbolIndexParentContext(db, resolved);
|
|
30714
30900
|
if (ctx == null) return null;
|
|
30715
30901
|
const fileRows = loadFileTags(db, ctx, filePath);
|
|
@@ -30744,23 +30930,28 @@ function rowToSymbolSpan(row, clickable) {
|
|
|
30744
30930
|
async function querySymbolsInFile(parentPath, filePath) {
|
|
30745
30931
|
await yieldToEventLoop();
|
|
30746
30932
|
const resolved = normalizeResolvedPath(parentPath);
|
|
30747
|
-
const
|
|
30933
|
+
const snapshot = await withCodeNavCacheSqlite((db) => {
|
|
30748
30934
|
const ctx = getSymbolIndexParentContext(db, resolved);
|
|
30749
|
-
if (ctx == null) return
|
|
30935
|
+
if (ctx == null) return null;
|
|
30750
30936
|
const rows = loadFileTags(db, ctx, filePath);
|
|
30751
|
-
if (rows.length === 0) return
|
|
30752
|
-
const lookups =
|
|
30937
|
+
if (rows.length === 0) return null;
|
|
30938
|
+
const lookups = createSnapshotNavigationLookups(db, ctx.parentId);
|
|
30753
30939
|
const workspaceFiles = listWorkspaceFiles(db, resolved, filePath);
|
|
30754
|
-
|
|
30755
|
-
|
|
30756
|
-
|
|
30757
|
-
|
|
30758
|
-
|
|
30759
|
-
|
|
30760
|
-
|
|
30761
|
-
|
|
30762
|
-
|
|
30763
|
-
|
|
30940
|
+
return { rows, lookups, workspaceFiles };
|
|
30941
|
+
});
|
|
30942
|
+
if (snapshot == null) {
|
|
30943
|
+
await yieldToEventLoop();
|
|
30944
|
+
return [];
|
|
30945
|
+
}
|
|
30946
|
+
const baseCtx = buildNavigationContext(
|
|
30947
|
+
filePath,
|
|
30948
|
+
snapshot.rows[0] ?? emptyRefRow(filePath),
|
|
30949
|
+
snapshot.lookups,
|
|
30950
|
+
snapshot.workspaceFiles
|
|
30951
|
+
);
|
|
30952
|
+
const spans = snapshot.rows.map((row) => {
|
|
30953
|
+
const navCtx = { ...baseCtx, ref: row };
|
|
30954
|
+
return rowToSymbolSpan(row, refHasResolvableDefinitions(navCtx));
|
|
30764
30955
|
});
|
|
30765
30956
|
await yieldToEventLoop();
|
|
30766
30957
|
return spans;
|
|
@@ -31763,8 +31954,8 @@ async function execGitFile(args, options) {
|
|
|
31763
31954
|
}
|
|
31764
31955
|
|
|
31765
31956
|
// src/git/changes/parse/normalize-git-diff-path.ts
|
|
31766
|
-
function normalizeGitDiffPath(
|
|
31767
|
-
return
|
|
31957
|
+
function normalizeGitDiffPath(path73) {
|
|
31958
|
+
return path73.replace(/\\/g, "/").replace(/\/ +/g, "/").trim();
|
|
31768
31959
|
}
|
|
31769
31960
|
|
|
31770
31961
|
// src/git/changes/parse/parse-name-status-entries.ts
|
|
@@ -32051,9 +32242,9 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
32051
32242
|
// src/agents/acp/put-summarize-change-summaries.ts
|
|
32052
32243
|
async function putEncryptedChangeSummaryRows(params) {
|
|
32053
32244
|
const base = params.apiBaseUrl.replace(/\/+$/, "");
|
|
32054
|
-
const entries = params.rows.map(({ path:
|
|
32245
|
+
const entries = params.rows.map(({ path: path73, summary }) => {
|
|
32055
32246
|
const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
|
|
32056
|
-
return { path:
|
|
32247
|
+
return { path: path73, summary: JSON.stringify(enc) };
|
|
32057
32248
|
});
|
|
32058
32249
|
const res = await fetch(
|
|
32059
32250
|
`${base}/internal/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
|
|
@@ -32980,8 +33171,8 @@ function pathspec(...paths) {
|
|
|
32980
33171
|
cache.set(key, paths);
|
|
32981
33172
|
return key;
|
|
32982
33173
|
}
|
|
32983
|
-
function isPathSpec(
|
|
32984
|
-
return
|
|
33174
|
+
function isPathSpec(path73) {
|
|
33175
|
+
return path73 instanceof String && cache.has(path73);
|
|
32985
33176
|
}
|
|
32986
33177
|
function toPaths(pathSpec) {
|
|
32987
33178
|
return cache.get(pathSpec) || [];
|
|
@@ -33070,8 +33261,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
33070
33261
|
function forEachLineWithContent(input, callback) {
|
|
33071
33262
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
33072
33263
|
}
|
|
33073
|
-
function folderExists(
|
|
33074
|
-
return (0, import_file_exists.exists)(
|
|
33264
|
+
function folderExists(path73) {
|
|
33265
|
+
return (0, import_file_exists.exists)(path73, import_file_exists.FOLDER);
|
|
33075
33266
|
}
|
|
33076
33267
|
function append(target, item) {
|
|
33077
33268
|
if (Array.isArray(target)) {
|
|
@@ -33475,8 +33666,8 @@ function checkIsRepoRootTask() {
|
|
|
33475
33666
|
commands,
|
|
33476
33667
|
format: "utf-8",
|
|
33477
33668
|
onError,
|
|
33478
|
-
parser(
|
|
33479
|
-
return /^\.(git)?$/.test(
|
|
33669
|
+
parser(path73) {
|
|
33670
|
+
return /^\.(git)?$/.test(path73.trim());
|
|
33480
33671
|
}
|
|
33481
33672
|
};
|
|
33482
33673
|
}
|
|
@@ -33910,11 +34101,11 @@ function parseGrep(grep) {
|
|
|
33910
34101
|
const paths = /* @__PURE__ */ new Set();
|
|
33911
34102
|
const results = {};
|
|
33912
34103
|
forEachLineWithContent(grep, (input) => {
|
|
33913
|
-
const [
|
|
33914
|
-
paths.add(
|
|
33915
|
-
(results[
|
|
34104
|
+
const [path73, line, preview] = input.split(NULL);
|
|
34105
|
+
paths.add(path73);
|
|
34106
|
+
(results[path73] = results[path73] || []).push({
|
|
33916
34107
|
line: asNumber(line),
|
|
33917
|
-
path:
|
|
34108
|
+
path: path73,
|
|
33918
34109
|
preview
|
|
33919
34110
|
});
|
|
33920
34111
|
});
|
|
@@ -34679,14 +34870,14 @@ var init_hash_object = __esm2({
|
|
|
34679
34870
|
init_task();
|
|
34680
34871
|
}
|
|
34681
34872
|
});
|
|
34682
|
-
function parseInit(bare,
|
|
34873
|
+
function parseInit(bare, path73, text) {
|
|
34683
34874
|
const response = String(text).trim();
|
|
34684
34875
|
let result;
|
|
34685
34876
|
if (result = initResponseRegex.exec(response)) {
|
|
34686
|
-
return new InitSummary(bare,
|
|
34877
|
+
return new InitSummary(bare, path73, false, result[1]);
|
|
34687
34878
|
}
|
|
34688
34879
|
if (result = reInitResponseRegex.exec(response)) {
|
|
34689
|
-
return new InitSummary(bare,
|
|
34880
|
+
return new InitSummary(bare, path73, true, result[1]);
|
|
34690
34881
|
}
|
|
34691
34882
|
let gitDir = "";
|
|
34692
34883
|
const tokens = response.split(" ");
|
|
@@ -34697,7 +34888,7 @@ function parseInit(bare, path71, text) {
|
|
|
34697
34888
|
break;
|
|
34698
34889
|
}
|
|
34699
34890
|
}
|
|
34700
|
-
return new InitSummary(bare,
|
|
34891
|
+
return new InitSummary(bare, path73, /^re/i.test(response), gitDir);
|
|
34701
34892
|
}
|
|
34702
34893
|
var InitSummary;
|
|
34703
34894
|
var initResponseRegex;
|
|
@@ -34706,9 +34897,9 @@ var init_InitSummary = __esm2({
|
|
|
34706
34897
|
"src/lib/responses/InitSummary.ts"() {
|
|
34707
34898
|
"use strict";
|
|
34708
34899
|
InitSummary = class {
|
|
34709
|
-
constructor(bare,
|
|
34900
|
+
constructor(bare, path73, existing, gitDir) {
|
|
34710
34901
|
this.bare = bare;
|
|
34711
|
-
this.path =
|
|
34902
|
+
this.path = path73;
|
|
34712
34903
|
this.existing = existing;
|
|
34713
34904
|
this.gitDir = gitDir;
|
|
34714
34905
|
}
|
|
@@ -34720,7 +34911,7 @@ var init_InitSummary = __esm2({
|
|
|
34720
34911
|
function hasBareCommand(command) {
|
|
34721
34912
|
return command.includes(bareCommand);
|
|
34722
34913
|
}
|
|
34723
|
-
function initTask(bare = false,
|
|
34914
|
+
function initTask(bare = false, path73, customArgs) {
|
|
34724
34915
|
const commands = ["init", ...customArgs];
|
|
34725
34916
|
if (bare && !hasBareCommand(commands)) {
|
|
34726
34917
|
commands.splice(1, 0, bareCommand);
|
|
@@ -34729,7 +34920,7 @@ function initTask(bare = false, path71, customArgs) {
|
|
|
34729
34920
|
commands,
|
|
34730
34921
|
format: "utf-8",
|
|
34731
34922
|
parser(text) {
|
|
34732
|
-
return parseInit(commands.includes("--bare"),
|
|
34923
|
+
return parseInit(commands.includes("--bare"), path73, text);
|
|
34733
34924
|
}
|
|
34734
34925
|
};
|
|
34735
34926
|
}
|
|
@@ -35545,12 +35736,12 @@ var init_FileStatusSummary = __esm2({
|
|
|
35545
35736
|
"use strict";
|
|
35546
35737
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
35547
35738
|
FileStatusSummary = class {
|
|
35548
|
-
constructor(
|
|
35549
|
-
this.path =
|
|
35739
|
+
constructor(path73, index, working_dir) {
|
|
35740
|
+
this.path = path73;
|
|
35550
35741
|
this.index = index;
|
|
35551
35742
|
this.working_dir = working_dir;
|
|
35552
35743
|
if (index === "R" || working_dir === "R") {
|
|
35553
|
-
const detail = fromPathRegex.exec(
|
|
35744
|
+
const detail = fromPathRegex.exec(path73) || [null, path73, path73];
|
|
35554
35745
|
this.from = detail[2] || "";
|
|
35555
35746
|
this.path = detail[1] || "";
|
|
35556
35747
|
}
|
|
@@ -35581,14 +35772,14 @@ function splitLine(result, lineStr) {
|
|
|
35581
35772
|
default:
|
|
35582
35773
|
return;
|
|
35583
35774
|
}
|
|
35584
|
-
function data(index, workingDir,
|
|
35775
|
+
function data(index, workingDir, path73) {
|
|
35585
35776
|
const raw = `${index}${workingDir}`;
|
|
35586
35777
|
const handler = parsers6.get(raw);
|
|
35587
35778
|
if (handler) {
|
|
35588
|
-
handler(result,
|
|
35779
|
+
handler(result, path73);
|
|
35589
35780
|
}
|
|
35590
35781
|
if (raw !== "##" && raw !== "!!") {
|
|
35591
|
-
result.files.push(new FileStatusSummary(
|
|
35782
|
+
result.files.push(new FileStatusSummary(path73, index, workingDir));
|
|
35592
35783
|
}
|
|
35593
35784
|
}
|
|
35594
35785
|
}
|
|
@@ -35861,15 +36052,15 @@ var init_simple_git_api = __esm2({
|
|
|
35861
36052
|
this._executor = _executor;
|
|
35862
36053
|
}
|
|
35863
36054
|
_runTask(task, then) {
|
|
35864
|
-
const
|
|
35865
|
-
const promise2 =
|
|
36055
|
+
const chain2 = this._executor.chain();
|
|
36056
|
+
const promise2 = chain2.push(task);
|
|
35866
36057
|
if (then) {
|
|
35867
36058
|
taskCallback(task, promise2, then);
|
|
35868
36059
|
}
|
|
35869
36060
|
return Object.create(this, {
|
|
35870
36061
|
then: { value: promise2.then.bind(promise2) },
|
|
35871
36062
|
catch: { value: promise2.catch.bind(promise2) },
|
|
35872
|
-
_executor: { value:
|
|
36063
|
+
_executor: { value: chain2 }
|
|
35873
36064
|
});
|
|
35874
36065
|
}
|
|
35875
36066
|
add(files) {
|
|
@@ -35897,9 +36088,9 @@ var init_simple_git_api = __esm2({
|
|
|
35897
36088
|
next
|
|
35898
36089
|
);
|
|
35899
36090
|
}
|
|
35900
|
-
hashObject(
|
|
36091
|
+
hashObject(path73, write) {
|
|
35901
36092
|
return this._runTask(
|
|
35902
|
-
hashObjectTask(
|
|
36093
|
+
hashObjectTask(path73, write === true),
|
|
35903
36094
|
trailingFunctionArgument(arguments)
|
|
35904
36095
|
);
|
|
35905
36096
|
}
|
|
@@ -36252,8 +36443,8 @@ var init_branch = __esm2({
|
|
|
36252
36443
|
}
|
|
36253
36444
|
});
|
|
36254
36445
|
function toPath(input) {
|
|
36255
|
-
const
|
|
36256
|
-
return
|
|
36446
|
+
const path73 = input.trim().replace(/^["']|["']$/g, "");
|
|
36447
|
+
return path73 && normalize3(path73);
|
|
36257
36448
|
}
|
|
36258
36449
|
var parseCheckIgnore;
|
|
36259
36450
|
var init_CheckIgnore = __esm2({
|
|
@@ -36567,8 +36758,8 @@ __export2(sub_module_exports, {
|
|
|
36567
36758
|
subModuleTask: () => subModuleTask,
|
|
36568
36759
|
updateSubModuleTask: () => updateSubModuleTask
|
|
36569
36760
|
});
|
|
36570
|
-
function addSubModuleTask(repo,
|
|
36571
|
-
return subModuleTask(["add", repo,
|
|
36761
|
+
function addSubModuleTask(repo, path73) {
|
|
36762
|
+
return subModuleTask(["add", repo, path73]);
|
|
36572
36763
|
}
|
|
36573
36764
|
function initSubModuleTask(customArgs) {
|
|
36574
36765
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -36901,8 +37092,8 @@ var require_git = __commonJS2({
|
|
|
36901
37092
|
}
|
|
36902
37093
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
36903
37094
|
};
|
|
36904
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
36905
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
37095
|
+
Git2.prototype.submoduleAdd = function(repo, path73, then) {
|
|
37096
|
+
return this._runTask(addSubModuleTask2(repo, path73), trailingFunctionArgument2(arguments));
|
|
36906
37097
|
};
|
|
36907
37098
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
36908
37099
|
return this._runTask(
|
|
@@ -37638,8 +37829,8 @@ function parseNumstatEntries(lines) {
|
|
|
37638
37829
|
}
|
|
37639
37830
|
function parseNumstat(lines) {
|
|
37640
37831
|
const m = /* @__PURE__ */ new Map();
|
|
37641
|
-
for (const [
|
|
37642
|
-
m.set(
|
|
37832
|
+
for (const [path73, entry] of parseNumstatEntries(lines)) {
|
|
37833
|
+
m.set(path73, { additions: entry.additions, deletions: entry.deletions });
|
|
37643
37834
|
}
|
|
37644
37835
|
return m;
|
|
37645
37836
|
}
|
|
@@ -39683,37 +39874,16 @@ function defaultWorktreesRootPath() {
|
|
|
39683
39874
|
}
|
|
39684
39875
|
|
|
39685
39876
|
// src/files/watch-file-index.ts
|
|
39686
|
-
import
|
|
39687
|
-
import { watch } from "node:fs";
|
|
39688
|
-
import path56 from "node:path";
|
|
39877
|
+
import path58 from "node:path";
|
|
39689
39878
|
|
|
39690
39879
|
// src/files/index/build-file-index.ts
|
|
39691
39880
|
import path54 from "node:path";
|
|
39692
39881
|
|
|
39693
39882
|
// src/files/index/file-index-sqlite-lock.ts
|
|
39694
|
-
|
|
39695
|
-
function isSqliteCorruptError2(e) {
|
|
39696
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
39697
|
-
return msg.includes("malformed") || msg.includes("database disk image is malformed") || msg.includes("corrupt");
|
|
39698
|
-
}
|
|
39699
|
-
var chain2 = Promise.resolve();
|
|
39883
|
+
var fileIndexChain = Promise.resolve();
|
|
39700
39884
|
function withFileIndexSqliteLock(fn) {
|
|
39701
|
-
const
|
|
39702
|
-
|
|
39703
|
-
return await Promise.resolve(fn());
|
|
39704
|
-
} catch (e) {
|
|
39705
|
-
if (!isSqliteCorruptError2(e)) throw e;
|
|
39706
|
-
closeAllCodeNavCacheSqliteConnections();
|
|
39707
|
-
try {
|
|
39708
|
-
fs35.unlinkSync(getCodeNavCacheSqlitePath());
|
|
39709
|
-
} catch {
|
|
39710
|
-
}
|
|
39711
|
-
chain2 = Promise.resolve();
|
|
39712
|
-
return await Promise.resolve(fn());
|
|
39713
|
-
}
|
|
39714
|
-
};
|
|
39715
|
-
const next = chain2.then(run);
|
|
39716
|
-
chain2 = next.then(
|
|
39885
|
+
const next = fileIndexChain.then(() => Promise.resolve(fn()));
|
|
39886
|
+
fileIndexChain = next.then(
|
|
39717
39887
|
() => void 0,
|
|
39718
39888
|
() => void 0
|
|
39719
39889
|
);
|
|
@@ -39734,6 +39904,14 @@ async function collectWorkspacePathsAsync(resolved) {
|
|
|
39734
39904
|
return paths;
|
|
39735
39905
|
}
|
|
39736
39906
|
|
|
39907
|
+
// src/files/index/file-index-persist-constants.ts
|
|
39908
|
+
var FILE_INDEX_INSERT_BUFFER = 2048;
|
|
39909
|
+
|
|
39910
|
+
// src/files/index/file-index-persist-shutdown.ts
|
|
39911
|
+
function assertFileIndexPersistNotShutdown() {
|
|
39912
|
+
if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();
|
|
39913
|
+
}
|
|
39914
|
+
|
|
39737
39915
|
// src/files/index/file-index-parent-path.ts
|
|
39738
39916
|
function upsertFileIndexParentPath(db, resolved) {
|
|
39739
39917
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -39748,57 +39926,56 @@ function upsertFileIndexParentPath(db, resolved) {
|
|
|
39748
39926
|
return Number(row.id);
|
|
39749
39927
|
}
|
|
39750
39928
|
|
|
39751
|
-
// src/files/index/
|
|
39752
|
-
|
|
39753
|
-
|
|
39754
|
-
|
|
39929
|
+
// src/files/index/file-index-persist-transaction.ts
|
|
39930
|
+
function clearFileIndexChildPaths(db, resolved) {
|
|
39931
|
+
runCodeNavCacheWriteTransaction(db, () => {
|
|
39932
|
+
const parentId = upsertFileIndexParentPath(db, resolved);
|
|
39933
|
+
db.run("DELETE FROM file_index_child_path WHERE parent_id = ?", [parentId]);
|
|
39934
|
+
});
|
|
39755
39935
|
}
|
|
39756
|
-
function
|
|
39757
|
-
return
|
|
39758
|
-
|
|
39759
|
-
db.
|
|
39936
|
+
function insertFileIndexChildPathBatch(db, resolved, paths) {
|
|
39937
|
+
return runCodeNavCacheWriteTransaction(db, () => {
|
|
39938
|
+
const parentId = upsertFileIndexParentPath(db, resolved);
|
|
39939
|
+
const ins = db.prepare(
|
|
39940
|
+
"INSERT INTO file_index_child_path (parent_id, path) VALUES (?, ?)"
|
|
39941
|
+
);
|
|
39760
39942
|
try {
|
|
39761
|
-
const
|
|
39762
|
-
|
|
39763
|
-
const ins = db.prepare("INSERT INTO file_index_child_path (parent_id, path) VALUES (?, ?)");
|
|
39764
|
-
try {
|
|
39765
|
-
let batch = 0;
|
|
39766
|
-
for (const rel of paths) {
|
|
39767
|
-
if (++batch >= FILE_INDEX_INTERRUPT_CHECK_EVERY) {
|
|
39768
|
-
batch = 0;
|
|
39769
|
-
assertNotShutdown2();
|
|
39770
|
-
}
|
|
39771
|
-
ins.run([parentId, rel]);
|
|
39772
|
-
pathCount += 1;
|
|
39773
|
-
}
|
|
39774
|
-
} finally {
|
|
39775
|
-
ins.finalize();
|
|
39943
|
+
for (const rel of paths) {
|
|
39944
|
+
ins.run([parentId, rel]);
|
|
39776
39945
|
}
|
|
39777
|
-
|
|
39778
|
-
}
|
|
39779
|
-
|
|
39780
|
-
db.run("ROLLBACK");
|
|
39781
|
-
} catch {
|
|
39782
|
-
}
|
|
39783
|
-
throw e;
|
|
39946
|
+
return paths.length;
|
|
39947
|
+
} finally {
|
|
39948
|
+
ins.finalize();
|
|
39784
39949
|
}
|
|
39785
|
-
return pathCount;
|
|
39786
39950
|
});
|
|
39787
39951
|
}
|
|
39788
39952
|
|
|
39953
|
+
// src/files/index/persist-file-index-paths.ts
|
|
39954
|
+
async function persistFileIndexPathsAsync(resolved, paths) {
|
|
39955
|
+
await withCodeNavCacheSqlite((db) => clearFileIndexChildPaths(db, resolved));
|
|
39956
|
+
let pathCount = 0;
|
|
39957
|
+
for (let offset = 0; offset < paths.length; offset += FILE_INDEX_INSERT_BUFFER) {
|
|
39958
|
+
assertFileIndexPersistNotShutdown();
|
|
39959
|
+
const batch = paths.slice(offset, offset + FILE_INDEX_INSERT_BUFFER);
|
|
39960
|
+
pathCount += await withCodeNavCacheSqlite((db) => insertFileIndexChildPathBatch(db, resolved, batch));
|
|
39961
|
+
await yieldToEventLoop();
|
|
39962
|
+
}
|
|
39963
|
+
return pathCount;
|
|
39964
|
+
}
|
|
39965
|
+
|
|
39789
39966
|
// src/files/index/build-file-index.ts
|
|
39790
|
-
function
|
|
39967
|
+
function assertNotShutdown2() {
|
|
39791
39968
|
if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();
|
|
39792
39969
|
}
|
|
39793
39970
|
async function buildFileIndexAsync(cwd) {
|
|
39794
|
-
|
|
39795
|
-
|
|
39796
|
-
|
|
39797
|
-
|
|
39798
|
-
|
|
39799
|
-
|
|
39800
|
-
|
|
39801
|
-
const pathCount =
|
|
39971
|
+
const resolved = path54.resolve(cwd);
|
|
39972
|
+
await yieldToEventLoop();
|
|
39973
|
+
assertNotShutdown2();
|
|
39974
|
+
const paths = await collectWorkspacePathsAsync(resolved);
|
|
39975
|
+
await yieldToEventLoop();
|
|
39976
|
+
assertNotShutdown2();
|
|
39977
|
+
return await withFileIndexSqliteLock(async () => {
|
|
39978
|
+
const pathCount = await persistFileIndexPathsAsync(resolved, paths);
|
|
39802
39979
|
return { pathCount };
|
|
39803
39980
|
});
|
|
39804
39981
|
}
|
|
@@ -39863,8 +40040,9 @@ async function ensureFileIndexAsync(cwd) {
|
|
|
39863
40040
|
return { ...await buildFileIndexAsync(resolved), fromCache: false };
|
|
39864
40041
|
}
|
|
39865
40042
|
|
|
39866
|
-
// src/files/
|
|
39867
|
-
|
|
40043
|
+
// src/files/index/file-index-fs-watcher.ts
|
|
40044
|
+
import { watch } from "node:fs";
|
|
40045
|
+
var FILE_INDEX_WATCH_DEBOUNCE_MS = 900;
|
|
39868
40046
|
function shouldIgnoreRelative(rel) {
|
|
39869
40047
|
const n = rel.replace(/\\/g, "/");
|
|
39870
40048
|
return n.split("/").some((segment) => shouldSkipWorkspaceWalkEntry(segment));
|
|
@@ -39874,7 +40052,7 @@ function attachWatchErrorLog(w) {
|
|
|
39874
40052
|
console.error("[file-index] File watcher error:", err);
|
|
39875
40053
|
});
|
|
39876
40054
|
}
|
|
39877
|
-
function
|
|
40055
|
+
function createFileIndexFsWatcher(resolved, schedule) {
|
|
39878
40056
|
const onEvent = (_event, filename) => {
|
|
39879
40057
|
if (filename != null) {
|
|
39880
40058
|
const rel = typeof filename === "string" ? filename.replace(/\\/g, "/") : filename.toString("utf8").replace(/\\/g, "/");
|
|
@@ -39901,11 +40079,15 @@ function createFsWatcher(resolved, schedule) {
|
|
|
39901
40079
|
throw e;
|
|
39902
40080
|
}
|
|
39903
40081
|
}
|
|
40082
|
+
|
|
40083
|
+
// src/files/index/file-index-incremental-symbol-updates.ts
|
|
40084
|
+
import fs35 from "node:fs";
|
|
40085
|
+
import path56 from "node:path";
|
|
39904
40086
|
async function applyIncrementalSymbolIndexUpdates(resolved, relPaths) {
|
|
39905
40087
|
for (const rel of relPaths) {
|
|
39906
40088
|
const absPath = path56.join(resolved, rel);
|
|
39907
40089
|
try {
|
|
39908
|
-
const stat2 = await
|
|
40090
|
+
const stat2 = await fs35.promises.stat(absPath);
|
|
39909
40091
|
if (stat2.isFile()) {
|
|
39910
40092
|
await updateSymbolIndexForFile(resolved, absPath);
|
|
39911
40093
|
} else {
|
|
@@ -39921,54 +40103,80 @@ async function applyIncrementalSymbolIndexUpdates(resolved, relPaths) {
|
|
|
39921
40103
|
await yieldToEventLoop();
|
|
39922
40104
|
}
|
|
39923
40105
|
}
|
|
39924
|
-
|
|
39925
|
-
|
|
39926
|
-
|
|
40106
|
+
|
|
40107
|
+
// src/files/index/file-index-initial-builds.ts
|
|
40108
|
+
import path57 from "node:path";
|
|
40109
|
+
async function runInitialIndexBuilds(cwd = getBridgeRoot()) {
|
|
40110
|
+
const resolved = path57.resolve(cwd);
|
|
40111
|
+
try {
|
|
40112
|
+
await buildFileIndexAsync(resolved);
|
|
40113
|
+
await buildSymbolIndexAsync(resolved);
|
|
40114
|
+
} catch (e) {
|
|
39927
40115
|
if (e instanceof CliSqliteInterrupted) return;
|
|
39928
40116
|
console.error("[file-index] Initial index build failed:", e);
|
|
40117
|
+
}
|
|
40118
|
+
}
|
|
40119
|
+
function scheduleInitialIndexBuilds(cwd = getBridgeRoot()) {
|
|
40120
|
+
setImmediate(() => {
|
|
40121
|
+
void runInitialIndexBuilds(cwd);
|
|
39929
40122
|
});
|
|
39930
|
-
|
|
39931
|
-
|
|
39932
|
-
|
|
39933
|
-
|
|
40123
|
+
}
|
|
40124
|
+
|
|
40125
|
+
// src/files/watch-file-index.ts
|
|
40126
|
+
var MAX_INCREMENTAL_SYMBOL_UPDATES = 512;
|
|
40127
|
+
function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
40128
|
+
const resolved = path58.resolve(cwd);
|
|
39934
40129
|
let timer = null;
|
|
39935
40130
|
const pendingSymbolUpdates = /* @__PURE__ */ new Set();
|
|
39936
40131
|
let needsFullSymbolRebuild = false;
|
|
40132
|
+
let rebuildRunning = false;
|
|
40133
|
+
let rebuildQueued = false;
|
|
39937
40134
|
const runRebuild = () => {
|
|
39938
|
-
|
|
39939
|
-
|
|
39940
|
-
console.error("[file-index] Watch rebuild failed:", e);
|
|
39941
|
-
});
|
|
39942
|
-
if (needsFullSymbolRebuild) {
|
|
39943
|
-
needsFullSymbolRebuild = false;
|
|
39944
|
-
pendingSymbolUpdates.clear();
|
|
39945
|
-
void buildSymbolIndexAsync(resolved).catch((e) => {
|
|
39946
|
-
if (e instanceof CliSqliteInterrupted) return;
|
|
39947
|
-
console.error("[code-nav] Watch rebuild failed:", e);
|
|
39948
|
-
});
|
|
40135
|
+
if (rebuildRunning) {
|
|
40136
|
+
rebuildQueued = true;
|
|
39949
40137
|
return;
|
|
39950
40138
|
}
|
|
39951
|
-
|
|
40139
|
+
rebuildRunning = true;
|
|
40140
|
+
const fullSymbol = needsFullSymbolRebuild;
|
|
40141
|
+
needsFullSymbolRebuild = false;
|
|
40142
|
+
const relPaths = fullSymbol ? [] : [...pendingSymbolUpdates];
|
|
39952
40143
|
pendingSymbolUpdates.clear();
|
|
39953
|
-
|
|
39954
|
-
|
|
40144
|
+
void buildFileIndexAsync(resolved).then(async () => {
|
|
40145
|
+
if (fullSymbol) {
|
|
40146
|
+
await buildSymbolIndexAsync(resolved);
|
|
40147
|
+
return;
|
|
40148
|
+
}
|
|
40149
|
+
if (relPaths.length === 0) return;
|
|
40150
|
+
await applyIncrementalSymbolIndexUpdates(resolved, relPaths);
|
|
40151
|
+
}).catch((e) => {
|
|
39955
40152
|
if (e instanceof CliSqliteInterrupted) return;
|
|
39956
|
-
console.error("[
|
|
40153
|
+
console.error("[file-index] Watch rebuild failed:", e);
|
|
40154
|
+
}).finally(() => {
|
|
40155
|
+
rebuildRunning = false;
|
|
40156
|
+
if (rebuildQueued || needsFullSymbolRebuild || pendingSymbolUpdates.size > 0) {
|
|
40157
|
+
rebuildQueued = false;
|
|
40158
|
+
setImmediate(runRebuild);
|
|
40159
|
+
}
|
|
39957
40160
|
});
|
|
39958
40161
|
};
|
|
39959
40162
|
const schedule = (relPath) => {
|
|
39960
|
-
if (relPath != null) {
|
|
40163
|
+
if (relPath != null && !needsFullSymbolRebuild) {
|
|
39961
40164
|
pendingSymbolUpdates.add(relPath);
|
|
40165
|
+
if (pendingSymbolUpdates.size > MAX_INCREMENTAL_SYMBOL_UPDATES) {
|
|
40166
|
+
pendingSymbolUpdates.clear();
|
|
40167
|
+
needsFullSymbolRebuild = true;
|
|
40168
|
+
}
|
|
39962
40169
|
} else {
|
|
40170
|
+
pendingSymbolUpdates.clear();
|
|
39963
40171
|
needsFullSymbolRebuild = true;
|
|
39964
40172
|
}
|
|
39965
40173
|
if (timer) clearTimeout(timer);
|
|
39966
40174
|
timer = setTimeout(() => {
|
|
39967
40175
|
timer = null;
|
|
39968
40176
|
runRebuild();
|
|
39969
|
-
},
|
|
40177
|
+
}, FILE_INDEX_WATCH_DEBOUNCE_MS);
|
|
39970
40178
|
};
|
|
39971
|
-
const watcher =
|
|
40179
|
+
const watcher = createFileIndexFsWatcher(resolved, schedule);
|
|
39972
40180
|
return () => {
|
|
39973
40181
|
if (timer) {
|
|
39974
40182
|
clearTimeout(timer);
|
|
@@ -39979,7 +40187,7 @@ function startFileIndexWatcher(cwd = getBridgeRoot()) {
|
|
|
39979
40187
|
}
|
|
39980
40188
|
|
|
39981
40189
|
// src/connection/create-bridge-connection.ts
|
|
39982
|
-
import * as
|
|
40190
|
+
import * as path72 from "node:path";
|
|
39983
40191
|
|
|
39984
40192
|
// src/dev-servers/manager/dev-server-manager.ts
|
|
39985
40193
|
import { rm as rm2 } from "node:fs/promises";
|
|
@@ -40023,7 +40231,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
|
|
|
40023
40231
|
}
|
|
40024
40232
|
|
|
40025
40233
|
// src/dev-servers/process/wire-dev-server-child-process.ts
|
|
40026
|
-
import
|
|
40234
|
+
import fs36 from "node:fs";
|
|
40027
40235
|
|
|
40028
40236
|
// src/dev-servers/manager/forward-pipe.ts
|
|
40029
40237
|
function forwardChildPipe(childReadable, terminal, onData) {
|
|
@@ -40059,7 +40267,7 @@ function wireDevServerChildProcess(d) {
|
|
|
40059
40267
|
d.setPollInterval(void 0);
|
|
40060
40268
|
return;
|
|
40061
40269
|
}
|
|
40062
|
-
|
|
40270
|
+
fs36.readFile(d.mergedLogPath, (err, buf) => {
|
|
40063
40271
|
if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
|
|
40064
40272
|
if (buf.length <= d.mergedReadPos.value) return;
|
|
40065
40273
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
@@ -40097,7 +40305,7 @@ ${errTail}` : ""}`);
|
|
|
40097
40305
|
d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
|
|
40098
40306
|
};
|
|
40099
40307
|
if (mergedPath) {
|
|
40100
|
-
|
|
40308
|
+
fs36.readFile(mergedPath, (err, buf) => {
|
|
40101
40309
|
if (!err && buf.length > d.mergedReadPos.value) {
|
|
40102
40310
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
40103
40311
|
if (chunk.length > 0) {
|
|
@@ -40199,13 +40407,13 @@ function parseDevServerDefs(servers) {
|
|
|
40199
40407
|
}
|
|
40200
40408
|
|
|
40201
40409
|
// src/dev-servers/manager/shell-spawn/utils.ts
|
|
40202
|
-
import
|
|
40410
|
+
import fs37 from "node:fs";
|
|
40203
40411
|
function isSpawnEbadf(e) {
|
|
40204
40412
|
return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
|
|
40205
40413
|
}
|
|
40206
40414
|
function rmDirQuiet(dir) {
|
|
40207
40415
|
try {
|
|
40208
|
-
|
|
40416
|
+
fs37.rmSync(dir, { recursive: true, force: true });
|
|
40209
40417
|
} catch {
|
|
40210
40418
|
}
|
|
40211
40419
|
}
|
|
@@ -40213,7 +40421,7 @@ var cachedDevNullReadFd;
|
|
|
40213
40421
|
function devNullReadFd() {
|
|
40214
40422
|
if (cachedDevNullReadFd === void 0) {
|
|
40215
40423
|
const devPath = process.platform === "win32" ? "nul" : "/dev/null";
|
|
40216
|
-
cachedDevNullReadFd =
|
|
40424
|
+
cachedDevNullReadFd = fs37.openSync(devPath, "r");
|
|
40217
40425
|
}
|
|
40218
40426
|
return cachedDevNullReadFd;
|
|
40219
40427
|
}
|
|
@@ -40287,15 +40495,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
|
40287
40495
|
|
|
40288
40496
|
// src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
|
|
40289
40497
|
import { spawn as spawn8 } from "node:child_process";
|
|
40290
|
-
import
|
|
40498
|
+
import fs38 from "node:fs";
|
|
40291
40499
|
import { tmpdir } from "node:os";
|
|
40292
|
-
import
|
|
40500
|
+
import path59 from "node:path";
|
|
40293
40501
|
function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
40294
|
-
const tmpRoot =
|
|
40295
|
-
const logPath =
|
|
40502
|
+
const tmpRoot = fs38.mkdtempSync(path59.join(tmpdir(), "ba-devsrv-log-"));
|
|
40503
|
+
const logPath = path59.join(tmpRoot, "combined.log");
|
|
40296
40504
|
let logFd;
|
|
40297
40505
|
try {
|
|
40298
|
-
logFd =
|
|
40506
|
+
logFd = fs38.openSync(logPath, "a");
|
|
40299
40507
|
} catch {
|
|
40300
40508
|
rmDirQuiet(tmpRoot);
|
|
40301
40509
|
return null;
|
|
@@ -40314,7 +40522,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
40314
40522
|
} else {
|
|
40315
40523
|
proc = spawn8("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
|
|
40316
40524
|
}
|
|
40317
|
-
|
|
40525
|
+
fs38.closeSync(logFd);
|
|
40318
40526
|
return {
|
|
40319
40527
|
proc,
|
|
40320
40528
|
pipedStdoutStderr: true,
|
|
@@ -40323,7 +40531,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
40323
40531
|
};
|
|
40324
40532
|
} catch (e) {
|
|
40325
40533
|
try {
|
|
40326
|
-
|
|
40534
|
+
fs38.closeSync(logFd);
|
|
40327
40535
|
} catch {
|
|
40328
40536
|
}
|
|
40329
40537
|
rmDirQuiet(tmpRoot);
|
|
@@ -40334,22 +40542,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
40334
40542
|
|
|
40335
40543
|
// src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
|
|
40336
40544
|
import { spawn as spawn9 } from "node:child_process";
|
|
40337
|
-
import
|
|
40545
|
+
import fs39 from "node:fs";
|
|
40338
40546
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
40339
|
-
import
|
|
40547
|
+
import path60 from "node:path";
|
|
40340
40548
|
function shSingleQuote(s) {
|
|
40341
40549
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
40342
40550
|
}
|
|
40343
40551
|
function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
|
|
40344
|
-
const tmpRoot =
|
|
40345
|
-
const logPath =
|
|
40346
|
-
const innerPath =
|
|
40347
|
-
const runnerPath =
|
|
40552
|
+
const tmpRoot = fs39.mkdtempSync(path60.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
40553
|
+
const logPath = path60.join(tmpRoot, "combined.log");
|
|
40554
|
+
const innerPath = path60.join(tmpRoot, "_cmd.sh");
|
|
40555
|
+
const runnerPath = path60.join(tmpRoot, "_run.sh");
|
|
40348
40556
|
try {
|
|
40349
|
-
|
|
40557
|
+
fs39.writeFileSync(innerPath, `#!/bin/sh
|
|
40350
40558
|
${command}
|
|
40351
40559
|
`);
|
|
40352
|
-
|
|
40560
|
+
fs39.writeFileSync(
|
|
40353
40561
|
runnerPath,
|
|
40354
40562
|
`#!/bin/sh
|
|
40355
40563
|
cd ${shSingleQuote(cwd)}
|
|
@@ -40375,13 +40583,13 @@ cd ${shSingleQuote(cwd)}
|
|
|
40375
40583
|
}
|
|
40376
40584
|
}
|
|
40377
40585
|
function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
|
|
40378
|
-
const tmpRoot =
|
|
40379
|
-
const logPath =
|
|
40380
|
-
const runnerPath =
|
|
40586
|
+
const tmpRoot = fs39.mkdtempSync(path60.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
40587
|
+
const logPath = path60.join(tmpRoot, "combined.log");
|
|
40588
|
+
const runnerPath = path60.join(tmpRoot, "_run.bat");
|
|
40381
40589
|
const q = (p) => `"${p.replace(/"/g, '""')}"`;
|
|
40382
40590
|
const com = process.env.ComSpec || "cmd.exe";
|
|
40383
40591
|
try {
|
|
40384
|
-
|
|
40592
|
+
fs39.writeFileSync(
|
|
40385
40593
|
runnerPath,
|
|
40386
40594
|
`@ECHO OFF\r
|
|
40387
40595
|
CD /D ${q(cwd)}\r
|
|
@@ -41038,7 +41246,7 @@ function attachFirehoseAfterIdentified(ctx, params) {
|
|
|
41038
41246
|
function scheduleFirehoseRetryAfterDrop(closeMeta) {
|
|
41039
41247
|
if (state.closedByUser) return;
|
|
41040
41248
|
const meta = closeMeta ?? state.lastFirehoseReconnectCloseMeta ?? void 0;
|
|
41041
|
-
const
|
|
41249
|
+
const delay3 = applyTieredReconnectPlanAndLog(
|
|
41042
41250
|
state.firehoseOutage,
|
|
41043
41251
|
logFn,
|
|
41044
41252
|
PREVIEW_TUNNEL_SERVICE_LABEL,
|
|
@@ -41047,7 +41255,7 @@ function attachFirehoseAfterIdentified(ctx, params) {
|
|
|
41047
41255
|
meta?.reason
|
|
41048
41256
|
);
|
|
41049
41257
|
armReconnectDelayTimer({
|
|
41050
|
-
delayMs:
|
|
41258
|
+
delayMs: delay3,
|
|
41051
41259
|
bumpAttempt: () => {
|
|
41052
41260
|
state.firehoseReconnectAttempt += 1;
|
|
41053
41261
|
},
|
|
@@ -41158,17 +41366,17 @@ async function yieldSkillDiscoveryWork(entryCount) {
|
|
|
41158
41366
|
}
|
|
41159
41367
|
|
|
41160
41368
|
// src/skills/discovery/discover-local-skills.ts
|
|
41161
|
-
import
|
|
41162
|
-
import
|
|
41369
|
+
import fs40 from "node:fs";
|
|
41370
|
+
import path61 from "node:path";
|
|
41163
41371
|
function collectSkillFromDir(rel, base, name, seenKeys, out) {
|
|
41164
|
-
const dir =
|
|
41372
|
+
const dir = path61.join(base, name);
|
|
41165
41373
|
try {
|
|
41166
|
-
if (!
|
|
41374
|
+
if (!fs40.statSync(dir).isDirectory()) return;
|
|
41167
41375
|
} catch {
|
|
41168
41376
|
return;
|
|
41169
41377
|
}
|
|
41170
|
-
const skillMd =
|
|
41171
|
-
if (!
|
|
41378
|
+
const skillMd = path61.join(dir, "SKILL.md");
|
|
41379
|
+
if (!fs40.existsSync(skillMd)) return;
|
|
41172
41380
|
const key = `${rel}/${name}`;
|
|
41173
41381
|
if (seenKeys.has(key)) return;
|
|
41174
41382
|
seenKeys.add(key);
|
|
@@ -41180,11 +41388,11 @@ async function discoverLocalSkillsAsync(cwd) {
|
|
|
41180
41388
|
let work = 0;
|
|
41181
41389
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
41182
41390
|
await yieldSkillDiscoveryWork(++work);
|
|
41183
|
-
const base =
|
|
41184
|
-
if (!
|
|
41391
|
+
const base = path61.join(cwd, rel);
|
|
41392
|
+
if (!fs40.existsSync(base) || !fs40.statSync(base).isDirectory()) continue;
|
|
41185
41393
|
let entries = [];
|
|
41186
41394
|
try {
|
|
41187
|
-
entries =
|
|
41395
|
+
entries = fs40.readdirSync(base);
|
|
41188
41396
|
} catch {
|
|
41189
41397
|
continue;
|
|
41190
41398
|
}
|
|
@@ -41197,16 +41405,16 @@ async function discoverLocalSkillsAsync(cwd) {
|
|
|
41197
41405
|
}
|
|
41198
41406
|
|
|
41199
41407
|
// src/skills/discovery/discover-skill-layout-roots.ts
|
|
41200
|
-
import
|
|
41201
|
-
import
|
|
41408
|
+
import fs41 from "node:fs";
|
|
41409
|
+
import path62 from "node:path";
|
|
41202
41410
|
function collectLayoutSkill(rel, base, name, skills2) {
|
|
41203
|
-
const dir =
|
|
41411
|
+
const dir = path62.join(base, name);
|
|
41204
41412
|
try {
|
|
41205
|
-
if (!
|
|
41413
|
+
if (!fs41.statSync(dir).isDirectory()) return;
|
|
41206
41414
|
} catch {
|
|
41207
41415
|
return;
|
|
41208
41416
|
}
|
|
41209
|
-
if (!
|
|
41417
|
+
if (!fs41.existsSync(path62.join(dir, "SKILL.md"))) return;
|
|
41210
41418
|
const relPath = `${rel}/${name}`.replace(/\\/g, "/");
|
|
41211
41419
|
skills2.push({ name, relPath });
|
|
41212
41420
|
}
|
|
@@ -41215,11 +41423,11 @@ async function discoverSkillLayoutRootsAsync(cwd) {
|
|
|
41215
41423
|
let work = 0;
|
|
41216
41424
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
41217
41425
|
await yieldSkillDiscoveryWork(++work);
|
|
41218
|
-
const base =
|
|
41219
|
-
if (!
|
|
41426
|
+
const base = path62.join(cwd, rel);
|
|
41427
|
+
if (!fs41.existsSync(base) || !fs41.statSync(base).isDirectory()) continue;
|
|
41220
41428
|
let entries = [];
|
|
41221
41429
|
try {
|
|
41222
|
-
entries =
|
|
41430
|
+
entries = fs41.readdirSync(base);
|
|
41223
41431
|
} catch {
|
|
41224
41432
|
continue;
|
|
41225
41433
|
}
|
|
@@ -41307,27 +41515,6 @@ function buildBridgeUrl(apiUrl, workspaceId, authToken) {
|
|
|
41307
41515
|
return `${base}/ws/bridge?${params.toString()}`;
|
|
41308
41516
|
}
|
|
41309
41517
|
|
|
41310
|
-
// src/connection/report-git-repos.ts
|
|
41311
|
-
function reportGitRepos(getWs, log2) {
|
|
41312
|
-
setImmediate(() => {
|
|
41313
|
-
discoverGitRepos().then((repos) => {
|
|
41314
|
-
if (repos.length > 0) {
|
|
41315
|
-
const socket = getWs();
|
|
41316
|
-
if (socket) {
|
|
41317
|
-
sendWsMessage(socket, {
|
|
41318
|
-
type: "git_repos",
|
|
41319
|
-
repos: repos.map((r) => ({ absolutePath: r.absolutePath, remoteUrl: r.remoteUrl }))
|
|
41320
|
-
});
|
|
41321
|
-
}
|
|
41322
|
-
}
|
|
41323
|
-
}).catch((err) => {
|
|
41324
|
-
log2(
|
|
41325
|
-
`[Bridge service] Git repository discovery failed: ${err instanceof Error ? err.message : String(err)}`
|
|
41326
|
-
);
|
|
41327
|
-
});
|
|
41328
|
-
});
|
|
41329
|
-
}
|
|
41330
|
-
|
|
41331
41518
|
// src/types/api-to-bridge-messages.ts
|
|
41332
41519
|
var API_TO_BRIDGE_MESSAGE_TYPES = [
|
|
41333
41520
|
"auth_token",
|
|
@@ -41584,11 +41771,11 @@ function syncRunningTurnQueueKeys(turns, queueKey) {
|
|
|
41584
41771
|
}
|
|
41585
41772
|
|
|
41586
41773
|
// src/prompt-turn-queue/runner/run-local-revert-before-queued-prompt.ts
|
|
41587
|
-
import
|
|
41774
|
+
import fs43 from "node:fs";
|
|
41588
41775
|
|
|
41589
41776
|
// src/git/snapshot/capture.ts
|
|
41590
|
-
import * as
|
|
41591
|
-
import * as
|
|
41777
|
+
import * as fs42 from "node:fs";
|
|
41778
|
+
import * as path63 from "node:path";
|
|
41592
41779
|
|
|
41593
41780
|
// src/git/snapshot/git.ts
|
|
41594
41781
|
async function gitStashCreate(repoRoot, log2) {
|
|
@@ -41628,7 +41815,7 @@ async function gitRun(repoRoot, args, log2, label) {
|
|
|
41628
41815
|
async function resolveSnapshotRepoRoots(options) {
|
|
41629
41816
|
const { worktreePaths, fallbackCwd, sessionId, log: log2 } = options;
|
|
41630
41817
|
if (worktreePaths?.length) {
|
|
41631
|
-
const uniq = [...new Set(worktreePaths.map((p) =>
|
|
41818
|
+
const uniq = [...new Set(worktreePaths.map((p) => path63.resolve(p)))];
|
|
41632
41819
|
return uniq;
|
|
41633
41820
|
}
|
|
41634
41821
|
try {
|
|
@@ -41636,7 +41823,7 @@ async function resolveSnapshotRepoRoots(options) {
|
|
|
41636
41823
|
const mapped = repos.map((r) => r.absolutePath);
|
|
41637
41824
|
const sid = sessionId?.trim();
|
|
41638
41825
|
if (sid) {
|
|
41639
|
-
const filtered = mapped.filter((root) =>
|
|
41826
|
+
const filtered = mapped.filter((root) => path63.basename(root) === sid);
|
|
41640
41827
|
if (filtered.length > 0) return filtered;
|
|
41641
41828
|
}
|
|
41642
41829
|
return mapped;
|
|
@@ -41658,7 +41845,7 @@ async function capturePreTurnSnapshot(options) {
|
|
|
41658
41845
|
});
|
|
41659
41846
|
const dir = snapshotsDirForCwd(agentCwd);
|
|
41660
41847
|
try {
|
|
41661
|
-
|
|
41848
|
+
fs42.mkdirSync(dir, { recursive: true });
|
|
41662
41849
|
} catch (e) {
|
|
41663
41850
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
41664
41851
|
}
|
|
@@ -41667,9 +41854,9 @@ async function capturePreTurnSnapshot(options) {
|
|
|
41667
41854
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
41668
41855
|
repos
|
|
41669
41856
|
};
|
|
41670
|
-
const filePath =
|
|
41857
|
+
const filePath = path63.join(dir, `${runId}.json`);
|
|
41671
41858
|
try {
|
|
41672
|
-
|
|
41859
|
+
fs42.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
|
|
41673
41860
|
} catch (e) {
|
|
41674
41861
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
41675
41862
|
}
|
|
@@ -41682,7 +41869,7 @@ async function capturePreTurnSnapshot(options) {
|
|
|
41682
41869
|
async function applyPreTurnSnapshot(filePath, log2) {
|
|
41683
41870
|
let data;
|
|
41684
41871
|
try {
|
|
41685
|
-
const raw =
|
|
41872
|
+
const raw = fs42.readFileSync(filePath, "utf8");
|
|
41686
41873
|
data = JSON.parse(raw);
|
|
41687
41874
|
} catch (e) {
|
|
41688
41875
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
@@ -41722,7 +41909,7 @@ async function runLocalRevertBeforeQueuedPrompt(next, deps) {
|
|
|
41722
41909
|
const agentBase = deps.sessionWorktreeManager.getSessionWorktreeRootForSession(sid) ?? getBridgeRoot();
|
|
41723
41910
|
const file2 = snapshotFilePath(agentBase, tid);
|
|
41724
41911
|
try {
|
|
41725
|
-
await
|
|
41912
|
+
await fs43.promises.access(file2, fs43.constants.F_OK);
|
|
41726
41913
|
} catch {
|
|
41727
41914
|
deps.log(
|
|
41728
41915
|
`[Queue] requeued_with_revert: no pre-turn snapshot for ${tid.slice(0, 8)}\u2026; continuing without revert.`
|
|
@@ -42010,9 +42197,9 @@ function parseChangeSummarySnapshots(raw) {
|
|
|
42010
42197
|
for (const item of raw) {
|
|
42011
42198
|
if (!item || typeof item !== "object") continue;
|
|
42012
42199
|
const o = item;
|
|
42013
|
-
const
|
|
42014
|
-
if (!
|
|
42015
|
-
const row = { path:
|
|
42200
|
+
const path73 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
|
|
42201
|
+
if (!path73) continue;
|
|
42202
|
+
const row = { path: path73 };
|
|
42016
42203
|
if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
|
|
42017
42204
|
if (typeof o.oldText === "string") row.oldText = o.oldText;
|
|
42018
42205
|
if (typeof o.newText === "string") row.newText = o.newText;
|
|
@@ -42237,14 +42424,14 @@ async function resolveFileBrowserSessionParent(sessionWorktreeManager, sessionId
|
|
|
42237
42424
|
}
|
|
42238
42425
|
|
|
42239
42426
|
// src/files/list-dir/index.ts
|
|
42240
|
-
import
|
|
42427
|
+
import fs45 from "node:fs";
|
|
42241
42428
|
|
|
42242
42429
|
// src/files/ensure-under-cwd.ts
|
|
42243
|
-
import
|
|
42430
|
+
import path64 from "node:path";
|
|
42244
42431
|
function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
|
|
42245
|
-
const normalized =
|
|
42246
|
-
const resolved =
|
|
42247
|
-
if (!resolved.startsWith(cwd +
|
|
42432
|
+
const normalized = path64.normalize(relativePath).replace(/^(\.\/)+/, "");
|
|
42433
|
+
const resolved = path64.resolve(cwd, normalized);
|
|
42434
|
+
if (!resolved.startsWith(cwd + path64.sep) && resolved !== cwd) {
|
|
42248
42435
|
return null;
|
|
42249
42436
|
}
|
|
42250
42437
|
return resolved;
|
|
@@ -42254,15 +42441,15 @@ function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
|
|
|
42254
42441
|
var LIST_DIR_YIELD_EVERY = 256;
|
|
42255
42442
|
|
|
42256
42443
|
// src/files/list-dir/map-dir-entry.ts
|
|
42257
|
-
import
|
|
42258
|
-
import
|
|
42444
|
+
import path65 from "node:path";
|
|
42445
|
+
import fs44 from "node:fs";
|
|
42259
42446
|
async function mapDirEntry(d, relativePath, resolved) {
|
|
42260
|
-
const entryPath =
|
|
42261
|
-
const fullPath =
|
|
42447
|
+
const entryPath = path65.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
42448
|
+
const fullPath = path65.join(resolved, d.name);
|
|
42262
42449
|
let isDir = d.isDirectory();
|
|
42263
42450
|
if (d.isSymbolicLink()) {
|
|
42264
42451
|
try {
|
|
42265
|
-
const targetStat = await
|
|
42452
|
+
const targetStat = await fs44.promises.stat(fullPath);
|
|
42266
42453
|
isDir = targetStat.isDirectory();
|
|
42267
42454
|
} catch {
|
|
42268
42455
|
isDir = false;
|
|
@@ -42292,7 +42479,7 @@ async function listDirAsync(relativePath, sessionParentPath = getBridgeRoot()) {
|
|
|
42292
42479
|
return { error: "Path is outside working directory" };
|
|
42293
42480
|
}
|
|
42294
42481
|
try {
|
|
42295
|
-
const names = await
|
|
42482
|
+
const names = await fs45.promises.readdir(resolved, { withFileTypes: true });
|
|
42296
42483
|
const entries = [];
|
|
42297
42484
|
for (let i = 0; i < names.length; i++) {
|
|
42298
42485
|
if (i > 0 && i % LIST_DIR_YIELD_EVERY === 0) {
|
|
@@ -42308,13 +42495,13 @@ async function listDirAsync(relativePath, sessionParentPath = getBridgeRoot()) {
|
|
|
42308
42495
|
}
|
|
42309
42496
|
|
|
42310
42497
|
// src/files/handle-file-browser-search.ts
|
|
42311
|
-
import
|
|
42498
|
+
import path66 from "node:path";
|
|
42312
42499
|
var SEARCH_LIMIT = 100;
|
|
42313
42500
|
function handleFileBrowserSearch(msg, socket, e2ee, sessionWorktreeManager) {
|
|
42314
42501
|
void (async () => {
|
|
42315
42502
|
await yieldToEventLoop();
|
|
42316
42503
|
const q = typeof msg.q === "string" ? msg.q : "";
|
|
42317
|
-
const sessionParentPath =
|
|
42504
|
+
const sessionParentPath = path66.resolve(
|
|
42318
42505
|
sessionWorktreeManager != null ? await resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : getBridgeRoot()
|
|
42319
42506
|
);
|
|
42320
42507
|
if (!await bridgeFileIndexIsPopulated(sessionParentPath)) {
|
|
@@ -42418,6 +42605,19 @@ async function resolveCodeNavParentPath(sessionWorktreeManager, sessionId) {
|
|
|
42418
42605
|
}
|
|
42419
42606
|
|
|
42420
42607
|
// src/code-nav/handlers/prepare-code-nav-request.ts
|
|
42608
|
+
var CODE_NAV_INDEX_READY_WAIT_MS = 75;
|
|
42609
|
+
var CODE_NAV_INDEX_READY_POLL_MS = 15;
|
|
42610
|
+
function delay2(ms) {
|
|
42611
|
+
return new Promise((resolve32) => setTimeout(resolve32, ms));
|
|
42612
|
+
}
|
|
42613
|
+
async function waitForSymbolIndexReady(sessionParentPath, reqPath) {
|
|
42614
|
+
const deadline = Date.now() + CODE_NAV_INDEX_READY_WAIT_MS;
|
|
42615
|
+
do {
|
|
42616
|
+
if (await symbolIndexFileIsReadyAsync(sessionParentPath, reqPath)) return true;
|
|
42617
|
+
await delay2(CODE_NAV_INDEX_READY_POLL_MS);
|
|
42618
|
+
} while (Date.now() < deadline);
|
|
42619
|
+
return await symbolIndexFileIsReadyAsync(sessionParentPath, reqPath);
|
|
42620
|
+
}
|
|
42421
42621
|
async function prepareCodeNavRequest(msg, socket, e2ee, sessionWorktreeManager) {
|
|
42422
42622
|
await yieldToEventLoop();
|
|
42423
42623
|
const reqPath = msg.path.replace(/^\/+/, "") || "";
|
|
@@ -42430,12 +42630,15 @@ async function prepareCodeNavRequest(msg, socket, e2ee, sessionWorktreeManager)
|
|
|
42430
42630
|
return null;
|
|
42431
42631
|
}
|
|
42432
42632
|
const sessionParentPath = await resolveCodeNavParentPath(sessionWorktreeManager, msg.sessionId);
|
|
42433
|
-
|
|
42434
|
-
|
|
42633
|
+
await registerSymbolIndexParentAsync(sessionParentPath);
|
|
42634
|
+
scheduleSymbolIndexFile(sessionParentPath, reqPath);
|
|
42635
|
+
const indexReady = await waitForSymbolIndexReady(sessionParentPath, reqPath);
|
|
42636
|
+
if (indexReady) {
|
|
42637
|
+
const importTargets = await listDirectImportTargetsForFileAsync(sessionParentPath, reqPath);
|
|
42638
|
+
scheduleSymbolIndexImportNeighbors(sessionParentPath, importTargets);
|
|
42639
|
+
}
|
|
42640
|
+
scheduleSymbolIndexWarmup(sessionParentPath);
|
|
42435
42641
|
await yieldToEventLoop();
|
|
42436
|
-
const importTargets = listDirectImportTargetsForFile(sessionParentPath, reqPath);
|
|
42437
|
-
scheduleSymbolIndexForRequest(sessionParentPath, reqPath, importTargets);
|
|
42438
|
-
const indexReady = symbolIndexFileIsReady(sessionParentPath, reqPath);
|
|
42439
42642
|
return {
|
|
42440
42643
|
socket,
|
|
42441
42644
|
e2ee,
|
|
@@ -42499,20 +42702,22 @@ function handleCodeNavRequest(msg, socket, e2ee, sessionWorktreeManager) {
|
|
|
42499
42702
|
// src/code-nav/handlers/trigger-symbol-index-build.ts
|
|
42500
42703
|
function triggerSymbolIndexBuild(parentPath) {
|
|
42501
42704
|
setImmediate(() => {
|
|
42502
|
-
|
|
42503
|
-
|
|
42504
|
-
|
|
42705
|
+
void (async () => {
|
|
42706
|
+
const resolved = normalizeResolvedPath(parentPath);
|
|
42707
|
+
await registerSymbolIndexParentAsync(resolved);
|
|
42708
|
+
scheduleSymbolIndexWarmup(resolved);
|
|
42709
|
+
})();
|
|
42505
42710
|
});
|
|
42506
42711
|
}
|
|
42507
42712
|
|
|
42508
42713
|
// src/git/tree/resolve-repo-abs-path.ts
|
|
42509
|
-
import * as
|
|
42714
|
+
import * as path67 from "node:path";
|
|
42510
42715
|
function resolveRepoAbsPathFromBridge(repoRelPath, bridgeRoot = getBridgeRoot()) {
|
|
42511
|
-
const bridgeResolved =
|
|
42716
|
+
const bridgeResolved = path67.resolve(bridgeRoot);
|
|
42512
42717
|
const rel = repoRelPath.trim() === "." ? "" : repoRelPath.trim().replace(/\\/g, "/");
|
|
42513
|
-
const repoPath = rel === "" ? bridgeResolved :
|
|
42514
|
-
const resolved =
|
|
42515
|
-
if (!resolved.startsWith(bridgeResolved +
|
|
42718
|
+
const repoPath = rel === "" ? bridgeResolved : path67.join(bridgeResolved, rel);
|
|
42719
|
+
const resolved = path67.resolve(repoPath);
|
|
42720
|
+
if (!resolved.startsWith(bridgeResolved + path67.sep) && resolved !== bridgeResolved) {
|
|
42516
42721
|
return null;
|
|
42517
42722
|
}
|
|
42518
42723
|
return resolved;
|
|
@@ -42910,18 +43115,18 @@ async function handleFileBrowserList(socket, e2ee, id, reqPath, sessionParentPat
|
|
|
42910
43115
|
}
|
|
42911
43116
|
|
|
42912
43117
|
// src/files/read-file/resolve-file-path.ts
|
|
42913
|
-
import
|
|
43118
|
+
import fs46 from "node:fs";
|
|
42914
43119
|
async function resolveFilePathAsync(relativePath, sessionParentPath = getBridgeRoot()) {
|
|
42915
43120
|
const resolved = ensureUnderCwd(relativePath, sessionParentPath);
|
|
42916
43121
|
if (!resolved) return { error: "Path is outside working directory" };
|
|
42917
43122
|
let real;
|
|
42918
43123
|
try {
|
|
42919
|
-
real = await
|
|
43124
|
+
real = await fs46.promises.realpath(resolved);
|
|
42920
43125
|
} catch {
|
|
42921
43126
|
real = resolved;
|
|
42922
43127
|
}
|
|
42923
43128
|
try {
|
|
42924
|
-
const stat2 = await
|
|
43129
|
+
const stat2 = await fs46.promises.stat(real);
|
|
42925
43130
|
if (!stat2.isFile()) return { error: "Not a file" };
|
|
42926
43131
|
return real;
|
|
42927
43132
|
} catch (err) {
|
|
@@ -42930,11 +43135,11 @@ async function resolveFilePathAsync(relativePath, sessionParentPath = getBridgeR
|
|
|
42930
43135
|
}
|
|
42931
43136
|
|
|
42932
43137
|
// src/files/read-file/read-file-range-async.ts
|
|
42933
|
-
import
|
|
43138
|
+
import fs47 from "node:fs";
|
|
42934
43139
|
import { StringDecoder as StringDecoder2 } from "node:string_decoder";
|
|
42935
43140
|
async function readFileRangeAsync(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
42936
|
-
const fileSize = (await
|
|
42937
|
-
const fd = await
|
|
43141
|
+
const fileSize = (await fs47.promises.stat(filePath)).size;
|
|
43142
|
+
const fd = await fs47.promises.open(filePath, "r");
|
|
42938
43143
|
const bufSize = 64 * 1024;
|
|
42939
43144
|
const buf = Buffer.alloc(bufSize);
|
|
42940
43145
|
const decoder = new StringDecoder2("utf8");
|
|
@@ -43096,11 +43301,11 @@ async function readFileRangeAsync(filePath, startLine, endLine, lineOffsetIn, li
|
|
|
43096
43301
|
}
|
|
43097
43302
|
|
|
43098
43303
|
// src/files/read-file/read-file-buffer-full-async.ts
|
|
43099
|
-
import
|
|
43304
|
+
import fs48 from "node:fs";
|
|
43100
43305
|
var READ_CHUNK_BYTES = 256 * 1024;
|
|
43101
43306
|
async function readFileBufferFullAsync(filePath) {
|
|
43102
|
-
const stat2 = await
|
|
43103
|
-
const fd = await
|
|
43307
|
+
const stat2 = await fs48.promises.stat(filePath);
|
|
43308
|
+
const fd = await fs48.promises.open(filePath, "r");
|
|
43104
43309
|
const chunks = [];
|
|
43105
43310
|
let position = 0;
|
|
43106
43311
|
let bytesSinceYield = 0;
|
|
@@ -43294,8 +43499,8 @@ function isValidRemoteSkillInstallItem(item) {
|
|
|
43294
43499
|
}
|
|
43295
43500
|
|
|
43296
43501
|
// src/skills/install/install-remote-skills-async.ts
|
|
43297
|
-
import
|
|
43298
|
-
import
|
|
43502
|
+
import fs49 from "node:fs";
|
|
43503
|
+
import path68 from "node:path";
|
|
43299
43504
|
|
|
43300
43505
|
// src/skills/install/constants.ts
|
|
43301
43506
|
var INSTALL_SKILLS_YIELD_EVERY = 16;
|
|
@@ -43306,12 +43511,12 @@ async function writeInstallFileAsync(skillDir, f, filesWritten) {
|
|
|
43306
43511
|
if (++filesWritten.count % INSTALL_SKILLS_YIELD_EVERY === 0) {
|
|
43307
43512
|
await yieldToEventLoop();
|
|
43308
43513
|
}
|
|
43309
|
-
const dest =
|
|
43310
|
-
await
|
|
43514
|
+
const dest = path68.join(skillDir, f.path);
|
|
43515
|
+
await fs49.promises.mkdir(path68.dirname(dest), { recursive: true });
|
|
43311
43516
|
if (f.text !== void 0) {
|
|
43312
|
-
await
|
|
43517
|
+
await fs49.promises.writeFile(dest, f.text, "utf8");
|
|
43313
43518
|
} else if (f.base64) {
|
|
43314
|
-
await
|
|
43519
|
+
await fs49.promises.writeFile(dest, Buffer.from(f.base64, "base64"));
|
|
43315
43520
|
}
|
|
43316
43521
|
}
|
|
43317
43522
|
async function installRemoteSkillsAsync(cwd, targetDir, items) {
|
|
@@ -43323,7 +43528,7 @@ async function installRemoteSkillsAsync(cwd, targetDir, items) {
|
|
|
43323
43528
|
try {
|
|
43324
43529
|
for (const item of items) {
|
|
43325
43530
|
if (!isValidRemoteSkillInstallItem(item)) continue;
|
|
43326
|
-
const skillDir =
|
|
43531
|
+
const skillDir = path68.join(cwd, targetDir, item.skillName);
|
|
43327
43532
|
for (const f of item.files) {
|
|
43328
43533
|
await writeInstallFileAsync(skillDir, f, filesWritten);
|
|
43329
43534
|
}
|
|
@@ -43605,7 +43810,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
|
|
|
43605
43810
|
};
|
|
43606
43811
|
|
|
43607
43812
|
// src/routing/handlers/revert-turn-snapshot.ts
|
|
43608
|
-
import * as
|
|
43813
|
+
import * as fs50 from "node:fs";
|
|
43609
43814
|
var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
43610
43815
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
43611
43816
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
@@ -43618,7 +43823,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
43618
43823
|
const agentBase = sessionWorktreeManager.getSessionWorktreeRootForSession(sessionId) ?? getBridgeRoot();
|
|
43619
43824
|
const file2 = snapshotFilePath(agentBase, turnId);
|
|
43620
43825
|
try {
|
|
43621
|
-
await
|
|
43826
|
+
await fs50.promises.access(file2, fs50.constants.F_OK);
|
|
43622
43827
|
} catch {
|
|
43623
43828
|
sendWsMessage(s, {
|
|
43624
43829
|
type: "revert_turn_snapshot_result",
|
|
@@ -43662,7 +43867,7 @@ var handleDevServersConfig = (msg, deps) => {
|
|
|
43662
43867
|
};
|
|
43663
43868
|
|
|
43664
43869
|
// src/git/bridge-git-context.ts
|
|
43665
|
-
import * as
|
|
43870
|
+
import * as path69 from "node:path";
|
|
43666
43871
|
|
|
43667
43872
|
// src/git/branches/get-current-branch.ts
|
|
43668
43873
|
async function getCurrentBranch(repoPath) {
|
|
@@ -43712,12 +43917,12 @@ async function listRepoBranchRefs(repoPath) {
|
|
|
43712
43917
|
// src/git/bridge-git-context.ts
|
|
43713
43918
|
function folderNameForRelPath(relPath, bridgeRoot) {
|
|
43714
43919
|
if (relPath === "." || relPath === "") {
|
|
43715
|
-
return
|
|
43920
|
+
return path69.basename(path69.resolve(bridgeRoot)) || "repo";
|
|
43716
43921
|
}
|
|
43717
|
-
return
|
|
43922
|
+
return path69.basename(relPath) || relPath;
|
|
43718
43923
|
}
|
|
43719
43924
|
async function discoverGitReposForBridgeContext(bridgeRoot) {
|
|
43720
|
-
const root =
|
|
43925
|
+
const root = path69.resolve(bridgeRoot);
|
|
43721
43926
|
if (await isGitRepoDirectory(root)) {
|
|
43722
43927
|
const remoteUrl = await getRemoteOriginUrl(root);
|
|
43723
43928
|
return [{ absolutePath: root, remoteUrl }];
|
|
@@ -43725,19 +43930,19 @@ async function discoverGitReposForBridgeContext(bridgeRoot) {
|
|
|
43725
43930
|
const [deep, shallow] = await Promise.all([discoverGitReposUnderRoot(root), discoverGitRepos(root)]);
|
|
43726
43931
|
const byPath = /* @__PURE__ */ new Map();
|
|
43727
43932
|
for (const repo of [...deep, ...shallow]) {
|
|
43728
|
-
byPath.set(
|
|
43933
|
+
byPath.set(path69.resolve(repo.absolutePath), repo);
|
|
43729
43934
|
}
|
|
43730
43935
|
return [...byPath.values()];
|
|
43731
43936
|
}
|
|
43732
43937
|
async function getBridgeGitContext(bridgeRoot = getBridgeRoot()) {
|
|
43733
|
-
const bridgeResolved =
|
|
43938
|
+
const bridgeResolved = path69.resolve(bridgeRoot);
|
|
43734
43939
|
const repos = await discoverGitReposForBridgeContext(bridgeResolved);
|
|
43735
43940
|
const rows = [];
|
|
43736
43941
|
for (let i = 0; i < repos.length; i++) {
|
|
43737
43942
|
if (i > 0) await yieldToEventLoop();
|
|
43738
43943
|
const repo = repos[i];
|
|
43739
|
-
let rel =
|
|
43740
|
-
if (rel.startsWith("..") ||
|
|
43944
|
+
let rel = path69.relative(bridgeResolved, repo.absolutePath);
|
|
43945
|
+
if (rel.startsWith("..") || path69.isAbsolute(rel)) continue;
|
|
43741
43946
|
const relPath = rel === "" ? "." : rel.replace(/\\/g, "/");
|
|
43742
43947
|
const currentBranch = await getCurrentBranch(repo.absolutePath);
|
|
43743
43948
|
const remoteUrl = repo.remoteUrl.trim() || null;
|
|
@@ -43752,11 +43957,11 @@ async function getBridgeGitContext(bridgeRoot = getBridgeRoot()) {
|
|
|
43752
43957
|
return rows;
|
|
43753
43958
|
}
|
|
43754
43959
|
async function listRepoBranchesForBridge(repoRelPath, bridgeRoot = getBridgeRoot()) {
|
|
43755
|
-
const bridgeResolved =
|
|
43960
|
+
const bridgeResolved = path69.resolve(bridgeRoot);
|
|
43756
43961
|
const rel = repoRelPath.trim() === "." ? "" : repoRelPath.trim().replace(/\\/g, "/");
|
|
43757
|
-
const repoPath = rel === "" ? bridgeResolved :
|
|
43758
|
-
const resolved =
|
|
43759
|
-
if (!resolved.startsWith(bridgeResolved +
|
|
43962
|
+
const repoPath = rel === "" ? bridgeResolved : path69.join(bridgeResolved, rel);
|
|
43963
|
+
const resolved = path69.resolve(repoPath);
|
|
43964
|
+
if (!resolved.startsWith(bridgeResolved + path69.sep) && resolved !== bridgeResolved) {
|
|
43760
43965
|
return [];
|
|
43761
43966
|
}
|
|
43762
43967
|
return listRepoBranchRefs(resolved);
|
|
@@ -43925,25 +44130,127 @@ async function refreshBridgeTokens(params) {
|
|
|
43925
44130
|
}
|
|
43926
44131
|
}
|
|
43927
44132
|
|
|
43928
|
-
// src/connection/main-bridge-
|
|
43929
|
-
function
|
|
44133
|
+
// src/connection/main-bridge-auth-refresh-handler.ts
|
|
44134
|
+
function resetAfterAuthInvalid(params) {
|
|
44135
|
+
const { state } = params;
|
|
44136
|
+
state.reconnectAttempt = 0;
|
|
44137
|
+
resetReconnectOutageTracker(state.mainOutage);
|
|
44138
|
+
state.lastReconnectCloseMeta = null;
|
|
44139
|
+
}
|
|
44140
|
+
function createMainBridgeAuthRefreshHandler(params, connect) {
|
|
44141
|
+
const { apiUrl, workspaceId, logFn, tokens, persistTokens, onAuthInvalid } = params;
|
|
44142
|
+
let authRefreshInFlight = false;
|
|
44143
|
+
return () => {
|
|
44144
|
+
if (authRefreshInFlight) return;
|
|
44145
|
+
void (async () => {
|
|
44146
|
+
authRefreshInFlight = true;
|
|
44147
|
+
try {
|
|
44148
|
+
if (tokens.refreshToken) {
|
|
44149
|
+
const next = await refreshBridgeTokens({
|
|
44150
|
+
apiUrl,
|
|
44151
|
+
workspaceId,
|
|
44152
|
+
refreshToken: tokens.refreshToken
|
|
44153
|
+
});
|
|
44154
|
+
if (next?.token && next.refreshToken) {
|
|
44155
|
+
tokens.accessToken = next.token;
|
|
44156
|
+
tokens.refreshToken = next.refreshToken;
|
|
44157
|
+
persistTokens?.({ token: tokens.accessToken, refreshToken: tokens.refreshToken });
|
|
44158
|
+
try {
|
|
44159
|
+
logFn("[Bridge service] Access token refreshed; reconnecting\u2026");
|
|
44160
|
+
} catch {
|
|
44161
|
+
}
|
|
44162
|
+
resetAfterAuthInvalid(params);
|
|
44163
|
+
params.state.logBridgeOpenAsReconnect = true;
|
|
44164
|
+
authRefreshInFlight = false;
|
|
44165
|
+
connect();
|
|
44166
|
+
return;
|
|
44167
|
+
}
|
|
44168
|
+
}
|
|
44169
|
+
authRefreshInFlight = false;
|
|
44170
|
+
resetAfterAuthInvalid(params);
|
|
44171
|
+
onAuthInvalid();
|
|
44172
|
+
} catch {
|
|
44173
|
+
authRefreshInFlight = false;
|
|
44174
|
+
resetAfterAuthInvalid(params);
|
|
44175
|
+
onAuthInvalid();
|
|
44176
|
+
}
|
|
44177
|
+
})();
|
|
44178
|
+
};
|
|
44179
|
+
}
|
|
44180
|
+
|
|
44181
|
+
// src/connection/main-bridge-ws-close-handler.ts
|
|
44182
|
+
function createMainBridgeCloseHandler(params, connect) {
|
|
44183
|
+
const { state, logFn, bridgeHeartbeat } = params;
|
|
44184
|
+
return (code, reason) => {
|
|
44185
|
+
bridgeHeartbeat?.stop();
|
|
44186
|
+
try {
|
|
44187
|
+
const was = state.currentWs;
|
|
44188
|
+
state.currentWs = null;
|
|
44189
|
+
if (was) was.removeAllListeners();
|
|
44190
|
+
const willReconnect = !state.closedByUser;
|
|
44191
|
+
if (willReconnect) {
|
|
44192
|
+
const duplicateResult = evaluateDuplicateBridgeDisconnect(
|
|
44193
|
+
state.duplicateBridgeFlap,
|
|
44194
|
+
Date.now(),
|
|
44195
|
+
code,
|
|
44196
|
+
reason
|
|
44197
|
+
);
|
|
44198
|
+
logDuplicateBridgeWarning(logFn, duplicateResult);
|
|
44199
|
+
}
|
|
44200
|
+
beginMainBridgeDeferredDisconnect(state, code, reason, logFn, willReconnect);
|
|
44201
|
+
if (willReconnect) {
|
|
44202
|
+
state.lastReconnectCloseMeta = { code, reason };
|
|
44203
|
+
try {
|
|
44204
|
+
scheduleMainBridgeReconnect(state, connect, logFn, { code, reason });
|
|
44205
|
+
} catch {
|
|
44206
|
+
}
|
|
44207
|
+
}
|
|
44208
|
+
} catch {
|
|
44209
|
+
if (!state.closedByUser) {
|
|
44210
|
+
try {
|
|
44211
|
+
scheduleMainBridgeReconnect(state, connect, logFn);
|
|
44212
|
+
} catch {
|
|
44213
|
+
}
|
|
44214
|
+
}
|
|
44215
|
+
}
|
|
44216
|
+
};
|
|
44217
|
+
}
|
|
44218
|
+
|
|
44219
|
+
// src/connection/report-git-repos.ts
|
|
44220
|
+
function reportGitRepos(getWs, log2) {
|
|
44221
|
+
setImmediate(() => {
|
|
44222
|
+
discoverGitRepos().then((repos) => {
|
|
44223
|
+
if (repos.length > 0) {
|
|
44224
|
+
const socket = getWs();
|
|
44225
|
+
if (socket) {
|
|
44226
|
+
sendWsMessage(socket, {
|
|
44227
|
+
type: "git_repos",
|
|
44228
|
+
repos: repos.map((r) => ({ absolutePath: r.absolutePath, remoteUrl: r.remoteUrl }))
|
|
44229
|
+
});
|
|
44230
|
+
}
|
|
44231
|
+
}
|
|
44232
|
+
}).catch((err) => {
|
|
44233
|
+
log2(
|
|
44234
|
+
`[Bridge service] Git repository discovery failed: ${err instanceof Error ? err.message : String(err)}`
|
|
44235
|
+
);
|
|
44236
|
+
});
|
|
44237
|
+
});
|
|
44238
|
+
}
|
|
44239
|
+
|
|
44240
|
+
// src/connection/main-bridge-ws-open-handler.ts
|
|
44241
|
+
function createMainBridgeOpenHandler(params) {
|
|
43930
44242
|
const {
|
|
43931
44243
|
state,
|
|
43932
44244
|
getWs,
|
|
43933
|
-
apiUrl,
|
|
43934
44245
|
workspaceId,
|
|
43935
44246
|
justAuthenticated,
|
|
43936
44247
|
logFn,
|
|
43937
|
-
messageDeps,
|
|
43938
44248
|
tokens,
|
|
43939
|
-
persistTokens,
|
|
43940
|
-
onAuthInvalid,
|
|
43941
44249
|
e2ee,
|
|
43942
44250
|
identifyReportedPaths,
|
|
43943
|
-
|
|
44251
|
+
onBridgeSocketOpen
|
|
43944
44252
|
} = params;
|
|
43945
|
-
|
|
43946
|
-
function handleOpen() {
|
|
44253
|
+
return () => {
|
|
43947
44254
|
recordBridgeSessionOpened(state.duplicateBridgeFlap, Date.now());
|
|
43948
44255
|
const logOpenAsPostRefreshReconnect = state.logBridgeOpenAsReconnect;
|
|
43949
44256
|
clearMainBridgeReconnectQuietOnOpen(state, logFn);
|
|
@@ -43963,6 +44270,10 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
43963
44270
|
...e2ee ? { e: e2ee.handshake } : {}
|
|
43964
44271
|
});
|
|
43965
44272
|
reportGitRepos(getWs, logFn);
|
|
44273
|
+
try {
|
|
44274
|
+
onBridgeSocketOpen?.();
|
|
44275
|
+
} catch {
|
|
44276
|
+
}
|
|
43966
44277
|
}
|
|
43967
44278
|
if (justAuthenticated && socket) {
|
|
43968
44279
|
logFn(
|
|
@@ -43971,41 +44282,25 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
43971
44282
|
logFn(` export BUILDAUTOMATON_AUTH_TOKEN="${tokens.accessToken}"`);
|
|
43972
44283
|
logFn(` export BUILDAUTOMATON_WORKSPACE_ID="${workspaceId}"`);
|
|
43973
44284
|
}
|
|
43974
|
-
}
|
|
43975
|
-
|
|
43976
|
-
|
|
43977
|
-
|
|
43978
|
-
|
|
43979
|
-
|
|
43980
|
-
|
|
43981
|
-
|
|
43982
|
-
|
|
43983
|
-
|
|
43984
|
-
|
|
43985
|
-
|
|
43986
|
-
|
|
43987
|
-
|
|
43988
|
-
|
|
43989
|
-
|
|
43990
|
-
|
|
43991
|
-
|
|
43992
|
-
|
|
43993
|
-
state.lastReconnectCloseMeta = { code, reason };
|
|
43994
|
-
try {
|
|
43995
|
-
scheduleMainBridgeReconnect(state, connect, logFn, { code, reason });
|
|
43996
|
-
} catch {
|
|
43997
|
-
}
|
|
43998
|
-
}
|
|
43999
|
-
} catch {
|
|
44000
|
-
if (!state.closedByUser) {
|
|
44001
|
-
try {
|
|
44002
|
-
scheduleMainBridgeReconnect(state, connect, logFn);
|
|
44003
|
-
} catch {
|
|
44004
|
-
}
|
|
44005
|
-
}
|
|
44006
|
-
}
|
|
44007
|
-
}
|
|
44008
|
-
function connect() {
|
|
44285
|
+
};
|
|
44286
|
+
}
|
|
44287
|
+
|
|
44288
|
+
// src/connection/main-bridge-ws-lifecycle.ts
|
|
44289
|
+
function createMainBridgeWebSocketLifecycle(params) {
|
|
44290
|
+
const {
|
|
44291
|
+
state,
|
|
44292
|
+
apiUrl,
|
|
44293
|
+
workspaceId,
|
|
44294
|
+
logFn,
|
|
44295
|
+
messageDeps,
|
|
44296
|
+
tokens,
|
|
44297
|
+
bridgeHeartbeat
|
|
44298
|
+
} = params;
|
|
44299
|
+
let connect;
|
|
44300
|
+
const handleOpen = createMainBridgeOpenHandler(params);
|
|
44301
|
+
const handleClose = createMainBridgeCloseHandler(params, () => connect());
|
|
44302
|
+
const handleAuthInvalid = createMainBridgeAuthRefreshHandler(params, () => connect());
|
|
44303
|
+
connect = () => {
|
|
44009
44304
|
if (state.closedByUser) return;
|
|
44010
44305
|
if (state.reconnectTimeout != null) {
|
|
44011
44306
|
clearTimeout(state.reconnectTimeout);
|
|
@@ -44041,48 +44336,7 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
44041
44336
|
onCompactHeartbeatAck: (seq) => {
|
|
44042
44337
|
messageDeps.onBridgeHeartbeatAck?.(seq);
|
|
44043
44338
|
},
|
|
44044
|
-
onAuthInvalid:
|
|
44045
|
-
if (authRefreshInFlight) return;
|
|
44046
|
-
void (async () => {
|
|
44047
|
-
authRefreshInFlight = true;
|
|
44048
|
-
try {
|
|
44049
|
-
if (tokens.refreshToken) {
|
|
44050
|
-
const next = await refreshBridgeTokens({
|
|
44051
|
-
apiUrl,
|
|
44052
|
-
workspaceId,
|
|
44053
|
-
refreshToken: tokens.refreshToken
|
|
44054
|
-
});
|
|
44055
|
-
if (next?.token && next.refreshToken) {
|
|
44056
|
-
tokens.accessToken = next.token;
|
|
44057
|
-
tokens.refreshToken = next.refreshToken;
|
|
44058
|
-
persistTokens?.({ token: tokens.accessToken, refreshToken: tokens.refreshToken });
|
|
44059
|
-
try {
|
|
44060
|
-
logFn("[Bridge service] Access token refreshed; reconnecting\u2026");
|
|
44061
|
-
} catch {
|
|
44062
|
-
}
|
|
44063
|
-
state.reconnectAttempt = 0;
|
|
44064
|
-
resetReconnectOutageTracker(state.mainOutage);
|
|
44065
|
-
state.lastReconnectCloseMeta = null;
|
|
44066
|
-
state.logBridgeOpenAsReconnect = true;
|
|
44067
|
-
authRefreshInFlight = false;
|
|
44068
|
-
connect();
|
|
44069
|
-
return;
|
|
44070
|
-
}
|
|
44071
|
-
}
|
|
44072
|
-
authRefreshInFlight = false;
|
|
44073
|
-
state.reconnectAttempt = 0;
|
|
44074
|
-
resetReconnectOutageTracker(state.mainOutage);
|
|
44075
|
-
state.lastReconnectCloseMeta = null;
|
|
44076
|
-
onAuthInvalid();
|
|
44077
|
-
} catch {
|
|
44078
|
-
authRefreshInFlight = false;
|
|
44079
|
-
state.reconnectAttempt = 0;
|
|
44080
|
-
resetReconnectOutageTracker(state.mainOutage);
|
|
44081
|
-
state.lastReconnectCloseMeta = null;
|
|
44082
|
-
onAuthInvalid();
|
|
44083
|
-
}
|
|
44084
|
-
})();
|
|
44085
|
-
},
|
|
44339
|
+
onAuthInvalid: handleAuthInvalid,
|
|
44086
44340
|
onOpen: handleOpen,
|
|
44087
44341
|
onClose: handleClose,
|
|
44088
44342
|
onError: (err) => {
|
|
@@ -44109,7 +44363,7 @@ function createMainBridgeWebSocketLifecycle(params) {
|
|
|
44109
44363
|
}
|
|
44110
44364
|
}
|
|
44111
44365
|
}
|
|
44112
|
-
}
|
|
44366
|
+
};
|
|
44113
44367
|
return { connect };
|
|
44114
44368
|
}
|
|
44115
44369
|
|
|
@@ -44278,256 +44532,6 @@ function createBridgeHeartbeatController(params) {
|
|
|
44278
44532
|
};
|
|
44279
44533
|
}
|
|
44280
44534
|
|
|
44281
|
-
// src/sqlite/hash-json-sha256.ts
|
|
44282
|
-
import { createHash } from "node:crypto";
|
|
44283
|
-
function hashJsonUtf8Sha256(value) {
|
|
44284
|
-
return createHash("sha256").update(JSON.stringify(value), "utf8").digest("hex");
|
|
44285
|
-
}
|
|
44286
|
-
|
|
44287
|
-
// src/sqlite/agent-capability-cache.ts
|
|
44288
|
-
function hasNonEmptyAgentCapabilityCache(db, workspaceId, agentType) {
|
|
44289
|
-
const t = agentType.trim();
|
|
44290
|
-
if (!t) return false;
|
|
44291
|
-
try {
|
|
44292
|
-
const row = db.get(
|
|
44293
|
-
`SELECT config_options_json FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
|
|
44294
|
-
[workspaceId, t]
|
|
44295
|
-
);
|
|
44296
|
-
if (row?.config_options_json == null || row.config_options_json === "") return false;
|
|
44297
|
-
const parsed = JSON.parse(row.config_options_json);
|
|
44298
|
-
return Array.isArray(parsed) && parsed.length > 0;
|
|
44299
|
-
} catch {
|
|
44300
|
-
return false;
|
|
44301
|
-
}
|
|
44302
|
-
}
|
|
44303
|
-
function upsertCliAgentCapabilityCache(db, row) {
|
|
44304
|
-
const t = row.agentType.trim();
|
|
44305
|
-
if (!t) return false;
|
|
44306
|
-
const hash = hashJsonUtf8Sha256(row.configOptions);
|
|
44307
|
-
try {
|
|
44308
|
-
const prev = db.get(
|
|
44309
|
-
`SELECT content_hash FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
|
|
44310
|
-
[row.workspaceId, t]
|
|
44311
|
-
);
|
|
44312
|
-
if (prev?.content_hash === hash) return false;
|
|
44313
|
-
} catch {
|
|
44314
|
-
}
|
|
44315
|
-
const json2 = JSON.stringify(row.configOptions);
|
|
44316
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
44317
|
-
db.run(
|
|
44318
|
-
`INSERT INTO agent_capabilities (workspace_id, agent_type, config_options_json, content_hash, updated_at)
|
|
44319
|
-
VALUES (?, ?, ?, ?, ?)
|
|
44320
|
-
ON CONFLICT(workspace_id, agent_type) DO UPDATE SET
|
|
44321
|
-
config_options_json = excluded.config_options_json,
|
|
44322
|
-
content_hash = excluded.content_hash,
|
|
44323
|
-
updated_at = excluded.updated_at`,
|
|
44324
|
-
[row.workspaceId, t, json2, hash, now]
|
|
44325
|
-
);
|
|
44326
|
-
return true;
|
|
44327
|
-
}
|
|
44328
|
-
function listCliAgentCapabilityCacheForWorkspace(db, workspaceId) {
|
|
44329
|
-
const rows = db.all(
|
|
44330
|
-
`SELECT agent_type, config_options_json FROM agent_capabilities WHERE workspace_id = ?`,
|
|
44331
|
-
[workspaceId]
|
|
44332
|
-
);
|
|
44333
|
-
const out = [];
|
|
44334
|
-
for (const r of rows) {
|
|
44335
|
-
try {
|
|
44336
|
-
const parsed = JSON.parse(r.config_options_json);
|
|
44337
|
-
if (!Array.isArray(parsed) || parsed.length === 0) continue;
|
|
44338
|
-
out.push({ agentType: r.agent_type, configOptions: parsed });
|
|
44339
|
-
} catch {
|
|
44340
|
-
}
|
|
44341
|
-
}
|
|
44342
|
-
return out;
|
|
44343
|
-
}
|
|
44344
|
-
|
|
44345
|
-
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
44346
|
-
import * as path69 from "node:path";
|
|
44347
|
-
|
|
44348
|
-
// src/agents/capabilities/probe-one-agent-type-for-capabilities.ts
|
|
44349
|
-
import * as path68 from "node:path";
|
|
44350
|
-
async function probeOneAgentTypeForCapabilities(params) {
|
|
44351
|
-
const { agentType, cwd, workspaceId, log: log2, reportAgentCapabilities, bridgeReport = true, shouldContinue } = params;
|
|
44352
|
-
const canContinue = () => shouldContinue?.() !== false;
|
|
44353
|
-
if (!canContinue()) return false;
|
|
44354
|
-
const resolved = resolveAgentCommand(agentType);
|
|
44355
|
-
if (!resolved) return false;
|
|
44356
|
-
let sqliteChanged = false;
|
|
44357
|
-
const reportedRef = { done: false };
|
|
44358
|
-
const tryReport = (co) => {
|
|
44359
|
-
if (reportedRef.done) return;
|
|
44360
|
-
if (!Array.isArray(co) || co.length === 0) return;
|
|
44361
|
-
reportedRef.done = true;
|
|
44362
|
-
let changed = false;
|
|
44363
|
-
try {
|
|
44364
|
-
changed = withCliSqliteSync(
|
|
44365
|
-
(db) => upsertCliAgentCapabilityCache(db, {
|
|
44366
|
-
workspaceId,
|
|
44367
|
-
agentType,
|
|
44368
|
-
configOptions: co
|
|
44369
|
-
})
|
|
44370
|
-
);
|
|
44371
|
-
} catch {
|
|
44372
|
-
}
|
|
44373
|
-
sqliteChanged ||= changed;
|
|
44374
|
-
if (bridgeReport && changed) {
|
|
44375
|
-
reportAgentCapabilities?.({ agentType, configOptions: co });
|
|
44376
|
-
}
|
|
44377
|
-
};
|
|
44378
|
-
let handle = null;
|
|
44379
|
-
const killTimer = setTimeout(() => {
|
|
44380
|
-
void handle?.disconnectGracefully();
|
|
44381
|
-
}, 28e3);
|
|
44382
|
-
killTimer.unref?.();
|
|
44383
|
-
try {
|
|
44384
|
-
if (!canContinue()) return false;
|
|
44385
|
-
handle = await resolved.createClient({
|
|
44386
|
-
command: resolved.command,
|
|
44387
|
-
cwd: path68.resolve(cwd),
|
|
44388
|
-
backendAgentType: agentType,
|
|
44389
|
-
sessionMode: "agent",
|
|
44390
|
-
persistedAcpSessionId: null,
|
|
44391
|
-
agentConfig: null,
|
|
44392
|
-
getActiveConfigOptions: () => null,
|
|
44393
|
-
onAcpSessionEstablished: (info) => {
|
|
44394
|
-
tryReport(info.configOptions ?? null);
|
|
44395
|
-
},
|
|
44396
|
-
onAcpConfigOptionsUpdated: (co) => {
|
|
44397
|
-
tryReport(co);
|
|
44398
|
-
},
|
|
44399
|
-
onAgentSubprocessExit: () => {
|
|
44400
|
-
},
|
|
44401
|
-
onSessionUpdate: () => {
|
|
44402
|
-
}
|
|
44403
|
-
});
|
|
44404
|
-
if (!await delayMsUnlessShutdownRequested(1200) || !canContinue()) return false;
|
|
44405
|
-
} catch (e) {
|
|
44406
|
-
log2(
|
|
44407
|
-
`[Bridge service] Agent capability probe (${agentType}): ${e instanceof Error ? e.message : String(e)}`
|
|
44408
|
-
);
|
|
44409
|
-
} finally {
|
|
44410
|
-
clearTimeout(killTimer);
|
|
44411
|
-
try {
|
|
44412
|
-
await handle?.disconnectGracefully();
|
|
44413
|
-
} catch {
|
|
44414
|
-
}
|
|
44415
|
-
}
|
|
44416
|
-
return sqliteChanged;
|
|
44417
|
-
}
|
|
44418
|
-
|
|
44419
|
-
// src/agents/capabilities/probe-agent-capabilities-for-types.ts
|
|
44420
|
-
async function probeAgentCapabilitiesForDetectedTypes(params) {
|
|
44421
|
-
const {
|
|
44422
|
-
agentTypes,
|
|
44423
|
-
cwd,
|
|
44424
|
-
workspaceId,
|
|
44425
|
-
log: log2,
|
|
44426
|
-
reportAgentCapabilities,
|
|
44427
|
-
bridgeReport = true,
|
|
44428
|
-
forceAllTypes = false,
|
|
44429
|
-
shouldContinue
|
|
44430
|
-
} = params;
|
|
44431
|
-
const canContinue = () => !isCliImmediateShutdownRequested() && shouldContinue?.() !== false;
|
|
44432
|
-
let changedCount = 0;
|
|
44433
|
-
for (let i = 0; i < agentTypes.length; i++) {
|
|
44434
|
-
if (!canContinue()) return changedCount;
|
|
44435
|
-
if (i > 0) await yieldToEventLoop();
|
|
44436
|
-
const agentType = agentTypes[i];
|
|
44437
|
-
if (!agentType.trim()) continue;
|
|
44438
|
-
if (!forceAllTypes) {
|
|
44439
|
-
try {
|
|
44440
|
-
if (process.env.BUILDAUTOMATON_FORCE_PROBE_ACP_CAPABILITIES !== "1" && await withCliSqlite((db) => hasNonEmptyAgentCapabilityCache(db, workspaceId, agentType))) {
|
|
44441
|
-
continue;
|
|
44442
|
-
}
|
|
44443
|
-
} catch {
|
|
44444
|
-
}
|
|
44445
|
-
}
|
|
44446
|
-
const changed = await probeOneAgentTypeForCapabilities({
|
|
44447
|
-
agentType,
|
|
44448
|
-
cwd,
|
|
44449
|
-
workspaceId,
|
|
44450
|
-
log: log2,
|
|
44451
|
-
reportAgentCapabilities,
|
|
44452
|
-
bridgeReport,
|
|
44453
|
-
shouldContinue: canContinue
|
|
44454
|
-
});
|
|
44455
|
-
if (changed) changedCount += 1;
|
|
44456
|
-
}
|
|
44457
|
-
return changedCount;
|
|
44458
|
-
}
|
|
44459
|
-
|
|
44460
|
-
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
44461
|
-
async function warmupAgentCapabilitiesOnConnect(params) {
|
|
44462
|
-
const { workspaceId, log: log2, getWs } = params;
|
|
44463
|
-
const isCurrent = beginAgentCapabilityWarmupRun();
|
|
44464
|
-
if (!isCurrent()) return;
|
|
44465
|
-
const cwd = path69.resolve(getBridgeRoot());
|
|
44466
|
-
async function sendBatchFromCache() {
|
|
44467
|
-
if (!isCurrent()) return;
|
|
44468
|
-
const socket = getWs();
|
|
44469
|
-
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
44470
|
-
try {
|
|
44471
|
-
const rows = await withCliSqlite((db) => listCliAgentCapabilityCacheForWorkspace(db, workspaceId));
|
|
44472
|
-
if (!isCurrent()) return;
|
|
44473
|
-
if (rows.length === 0) return;
|
|
44474
|
-
sendWsMessage(socket, {
|
|
44475
|
-
type: "agent_capabilities_batch",
|
|
44476
|
-
items: rows.map((r) => ({ agentType: r.agentType, configOptions: r.configOptions }))
|
|
44477
|
-
});
|
|
44478
|
-
} catch (e) {
|
|
44479
|
-
if (e instanceof CliSqliteInterrupted) return;
|
|
44480
|
-
log2(
|
|
44481
|
-
`[Bridge service] Agent capability batch to bridge failed: ${e instanceof Error ? e.message : String(e)}`
|
|
44482
|
-
);
|
|
44483
|
-
}
|
|
44484
|
-
}
|
|
44485
|
-
await sendBatchFromCache();
|
|
44486
|
-
if (!isCurrent()) return;
|
|
44487
|
-
let types = [];
|
|
44488
|
-
try {
|
|
44489
|
-
types = [...await detectLocalAgentTypes()];
|
|
44490
|
-
} catch (e) {
|
|
44491
|
-
log2(`[Bridge service] detectLocalAgentTypes failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
44492
|
-
}
|
|
44493
|
-
if (!isCurrent()) return;
|
|
44494
|
-
try {
|
|
44495
|
-
const n = await probeAgentCapabilitiesForDetectedTypes({
|
|
44496
|
-
agentTypes: types,
|
|
44497
|
-
cwd,
|
|
44498
|
-
workspaceId,
|
|
44499
|
-
log: log2,
|
|
44500
|
-
bridgeReport: false,
|
|
44501
|
-
forceAllTypes: false,
|
|
44502
|
-
shouldContinue: isCurrent
|
|
44503
|
-
});
|
|
44504
|
-
if (n > 0) await sendBatchFromCache();
|
|
44505
|
-
} catch (e) {
|
|
44506
|
-
if (e instanceof CliSqliteInterrupted) return;
|
|
44507
|
-
log2(`[Bridge service] Agent capability probe (missing cache) failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
44508
|
-
}
|
|
44509
|
-
if (!isCurrent()) return;
|
|
44510
|
-
void (async () => {
|
|
44511
|
-
try {
|
|
44512
|
-
await yieldToEventLoop();
|
|
44513
|
-
if (!isCurrent()) return;
|
|
44514
|
-
const n = await probeAgentCapabilitiesForDetectedTypes({
|
|
44515
|
-
agentTypes: types,
|
|
44516
|
-
cwd,
|
|
44517
|
-
workspaceId,
|
|
44518
|
-
log: log2,
|
|
44519
|
-
bridgeReport: false,
|
|
44520
|
-
forceAllTypes: true,
|
|
44521
|
-
shouldContinue: isCurrent
|
|
44522
|
-
});
|
|
44523
|
-
if (n > 0) await sendBatchFromCache();
|
|
44524
|
-
} catch (e) {
|
|
44525
|
-
if (e instanceof CliSqliteInterrupted) return;
|
|
44526
|
-
log2(`[Bridge service] Agent capability lazy refresh failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
44527
|
-
}
|
|
44528
|
-
})();
|
|
44529
|
-
}
|
|
44530
|
-
|
|
44531
44535
|
// src/mcp/tools/session-history/fork/mcp-text-result.ts
|
|
44532
44536
|
function mcpTextResult(text, isError = false) {
|
|
44533
44537
|
return { content: [{ type: "text", text }], ...isError ? { isError: true } : {} };
|
|
@@ -44912,6 +44916,327 @@ async function createBridgeAccessState(options = {}) {
|
|
|
44912
44916
|
};
|
|
44913
44917
|
}
|
|
44914
44918
|
|
|
44919
|
+
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
44920
|
+
import * as path71 from "node:path";
|
|
44921
|
+
|
|
44922
|
+
// src/sqlite/hash-json-sha256.ts
|
|
44923
|
+
import { createHash } from "node:crypto";
|
|
44924
|
+
function hashJsonUtf8Sha256(value) {
|
|
44925
|
+
return createHash("sha256").update(JSON.stringify(value), "utf8").digest("hex");
|
|
44926
|
+
}
|
|
44927
|
+
|
|
44928
|
+
// src/sqlite/agent-capability-cache.ts
|
|
44929
|
+
function hasNonEmptyAgentCapabilityCache(db, workspaceId, agentType) {
|
|
44930
|
+
const t = agentType.trim();
|
|
44931
|
+
if (!t) return false;
|
|
44932
|
+
try {
|
|
44933
|
+
const row = db.get(
|
|
44934
|
+
`SELECT config_options_json FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
|
|
44935
|
+
[workspaceId, t]
|
|
44936
|
+
);
|
|
44937
|
+
if (row?.config_options_json == null || row.config_options_json === "") return false;
|
|
44938
|
+
const parsed = JSON.parse(row.config_options_json);
|
|
44939
|
+
return Array.isArray(parsed) && parsed.length > 0;
|
|
44940
|
+
} catch {
|
|
44941
|
+
return false;
|
|
44942
|
+
}
|
|
44943
|
+
}
|
|
44944
|
+
function upsertCliAgentCapabilityCache(db, row) {
|
|
44945
|
+
const t = row.agentType.trim();
|
|
44946
|
+
if (!t) return false;
|
|
44947
|
+
const hash = hashJsonUtf8Sha256(row.configOptions);
|
|
44948
|
+
try {
|
|
44949
|
+
const prev = db.get(
|
|
44950
|
+
`SELECT content_hash FROM agent_capabilities WHERE workspace_id = ? AND agent_type = ?`,
|
|
44951
|
+
[row.workspaceId, t]
|
|
44952
|
+
);
|
|
44953
|
+
if (prev?.content_hash === hash) return false;
|
|
44954
|
+
} catch {
|
|
44955
|
+
}
|
|
44956
|
+
const json2 = JSON.stringify(row.configOptions);
|
|
44957
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
44958
|
+
db.run(
|
|
44959
|
+
`INSERT INTO agent_capabilities (workspace_id, agent_type, config_options_json, content_hash, updated_at)
|
|
44960
|
+
VALUES (?, ?, ?, ?, ?)
|
|
44961
|
+
ON CONFLICT(workspace_id, agent_type) DO UPDATE SET
|
|
44962
|
+
config_options_json = excluded.config_options_json,
|
|
44963
|
+
content_hash = excluded.content_hash,
|
|
44964
|
+
updated_at = excluded.updated_at`,
|
|
44965
|
+
[row.workspaceId, t, json2, hash, now]
|
|
44966
|
+
);
|
|
44967
|
+
return true;
|
|
44968
|
+
}
|
|
44969
|
+
function listCliAgentCapabilityCacheForWorkspace(db, workspaceId) {
|
|
44970
|
+
const rows = db.all(
|
|
44971
|
+
`SELECT agent_type, config_options_json FROM agent_capabilities WHERE workspace_id = ?`,
|
|
44972
|
+
[workspaceId]
|
|
44973
|
+
);
|
|
44974
|
+
const out = [];
|
|
44975
|
+
for (const r of rows) {
|
|
44976
|
+
try {
|
|
44977
|
+
const parsed = JSON.parse(r.config_options_json);
|
|
44978
|
+
if (!Array.isArray(parsed) || parsed.length === 0) continue;
|
|
44979
|
+
out.push({ agentType: r.agent_type, configOptions: parsed });
|
|
44980
|
+
} catch {
|
|
44981
|
+
}
|
|
44982
|
+
}
|
|
44983
|
+
return out;
|
|
44984
|
+
}
|
|
44985
|
+
|
|
44986
|
+
// src/agents/capabilities/probe-one-agent-type-for-capabilities.ts
|
|
44987
|
+
import * as path70 from "node:path";
|
|
44988
|
+
async function probeOneAgentTypeForCapabilities(params) {
|
|
44989
|
+
const { agentType, cwd, workspaceId, log: log2, reportAgentCapabilities, bridgeReport = true, shouldContinue } = params;
|
|
44990
|
+
const canContinue = () => shouldContinue?.() !== false;
|
|
44991
|
+
if (!canContinue()) return false;
|
|
44992
|
+
const resolved = resolveAgentCommand(agentType);
|
|
44993
|
+
if (!resolved) return false;
|
|
44994
|
+
let sqliteChanged = false;
|
|
44995
|
+
const reportedRef = { done: false };
|
|
44996
|
+
const tryReport = (co) => {
|
|
44997
|
+
if (reportedRef.done) return;
|
|
44998
|
+
if (!Array.isArray(co) || co.length === 0) return;
|
|
44999
|
+
reportedRef.done = true;
|
|
45000
|
+
let changed = false;
|
|
45001
|
+
try {
|
|
45002
|
+
changed = withCliSqliteSync(
|
|
45003
|
+
(db) => upsertCliAgentCapabilityCache(db, {
|
|
45004
|
+
workspaceId,
|
|
45005
|
+
agentType,
|
|
45006
|
+
configOptions: co
|
|
45007
|
+
})
|
|
45008
|
+
);
|
|
45009
|
+
} catch {
|
|
45010
|
+
}
|
|
45011
|
+
sqliteChanged ||= changed;
|
|
45012
|
+
if (bridgeReport && changed) {
|
|
45013
|
+
reportAgentCapabilities?.({ agentType, configOptions: co });
|
|
45014
|
+
}
|
|
45015
|
+
};
|
|
45016
|
+
let handle = null;
|
|
45017
|
+
const killTimer = setTimeout(() => {
|
|
45018
|
+
void handle?.disconnectGracefully();
|
|
45019
|
+
}, 28e3);
|
|
45020
|
+
killTimer.unref?.();
|
|
45021
|
+
try {
|
|
45022
|
+
if (!canContinue()) return false;
|
|
45023
|
+
handle = await resolved.createClient({
|
|
45024
|
+
command: resolved.command,
|
|
45025
|
+
cwd: path70.resolve(cwd),
|
|
45026
|
+
backendAgentType: agentType,
|
|
45027
|
+
sessionMode: "agent",
|
|
45028
|
+
persistedAcpSessionId: null,
|
|
45029
|
+
agentConfig: null,
|
|
45030
|
+
getActiveConfigOptions: () => null,
|
|
45031
|
+
onAcpSessionEstablished: (info) => {
|
|
45032
|
+
tryReport(info.configOptions ?? null);
|
|
45033
|
+
},
|
|
45034
|
+
onAcpConfigOptionsUpdated: (co) => {
|
|
45035
|
+
tryReport(co);
|
|
45036
|
+
},
|
|
45037
|
+
onAgentSubprocessExit: () => {
|
|
45038
|
+
},
|
|
45039
|
+
onSessionUpdate: () => {
|
|
45040
|
+
}
|
|
45041
|
+
});
|
|
45042
|
+
if (!await delayMsUnlessShutdownRequested(1200) || !canContinue()) return false;
|
|
45043
|
+
} catch (e) {
|
|
45044
|
+
log2(
|
|
45045
|
+
`[Bridge service] Agent capability probe (${agentType}): ${e instanceof Error ? e.message : String(e)}`
|
|
45046
|
+
);
|
|
45047
|
+
} finally {
|
|
45048
|
+
clearTimeout(killTimer);
|
|
45049
|
+
try {
|
|
45050
|
+
await handle?.disconnectGracefully();
|
|
45051
|
+
} catch {
|
|
45052
|
+
}
|
|
45053
|
+
}
|
|
45054
|
+
return sqliteChanged;
|
|
45055
|
+
}
|
|
45056
|
+
|
|
45057
|
+
// src/agents/capabilities/probe-agent-capabilities-for-types.ts
|
|
45058
|
+
async function probeAgentCapabilitiesForDetectedTypes(params) {
|
|
45059
|
+
const {
|
|
45060
|
+
agentTypes,
|
|
45061
|
+
cwd,
|
|
45062
|
+
workspaceId,
|
|
45063
|
+
log: log2,
|
|
45064
|
+
reportAgentCapabilities,
|
|
45065
|
+
bridgeReport = true,
|
|
45066
|
+
forceAllTypes = false,
|
|
45067
|
+
shouldContinue
|
|
45068
|
+
} = params;
|
|
45069
|
+
const canContinue = () => !isCliImmediateShutdownRequested() && shouldContinue?.() !== false;
|
|
45070
|
+
let changedCount = 0;
|
|
45071
|
+
for (let i = 0; i < agentTypes.length; i++) {
|
|
45072
|
+
if (!canContinue()) return changedCount;
|
|
45073
|
+
if (i > 0) await yieldToEventLoop();
|
|
45074
|
+
const agentType = agentTypes[i];
|
|
45075
|
+
if (!agentType.trim()) continue;
|
|
45076
|
+
if (!forceAllTypes) {
|
|
45077
|
+
try {
|
|
45078
|
+
if (process.env.BUILDAUTOMATON_FORCE_PROBE_ACP_CAPABILITIES !== "1" && await withCliSqlite((db) => hasNonEmptyAgentCapabilityCache(db, workspaceId, agentType))) {
|
|
45079
|
+
continue;
|
|
45080
|
+
}
|
|
45081
|
+
} catch {
|
|
45082
|
+
}
|
|
45083
|
+
}
|
|
45084
|
+
const changed = await probeOneAgentTypeForCapabilities({
|
|
45085
|
+
agentType,
|
|
45086
|
+
cwd,
|
|
45087
|
+
workspaceId,
|
|
45088
|
+
log: log2,
|
|
45089
|
+
reportAgentCapabilities,
|
|
45090
|
+
bridgeReport,
|
|
45091
|
+
shouldContinue: canContinue
|
|
45092
|
+
});
|
|
45093
|
+
if (changed) changedCount += 1;
|
|
45094
|
+
}
|
|
45095
|
+
return changedCount;
|
|
45096
|
+
}
|
|
45097
|
+
|
|
45098
|
+
// src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
|
|
45099
|
+
async function warmupAgentCapabilitiesOnConnect(params) {
|
|
45100
|
+
const { workspaceId, log: log2, getWs } = params;
|
|
45101
|
+
const isCurrent = beginAgentCapabilityWarmupRun();
|
|
45102
|
+
if (!isCurrent()) return;
|
|
45103
|
+
const cwd = path71.resolve(getBridgeRoot());
|
|
45104
|
+
async function sendBatchFromCache() {
|
|
45105
|
+
if (!isCurrent()) return;
|
|
45106
|
+
const socket = getWs();
|
|
45107
|
+
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
45108
|
+
try {
|
|
45109
|
+
const rows = await withCliSqlite((db) => listCliAgentCapabilityCacheForWorkspace(db, workspaceId));
|
|
45110
|
+
if (!isCurrent()) return;
|
|
45111
|
+
if (rows.length === 0) return;
|
|
45112
|
+
sendWsMessage(socket, {
|
|
45113
|
+
type: "agent_capabilities_batch",
|
|
45114
|
+
items: rows.map((r) => ({ agentType: r.agentType, configOptions: r.configOptions }))
|
|
45115
|
+
});
|
|
45116
|
+
} catch (e) {
|
|
45117
|
+
if (e instanceof CliSqliteInterrupted) return;
|
|
45118
|
+
log2(
|
|
45119
|
+
`[Bridge service] Agent capability batch to bridge failed: ${e instanceof Error ? e.message : String(e)}`
|
|
45120
|
+
);
|
|
45121
|
+
}
|
|
45122
|
+
}
|
|
45123
|
+
await sendBatchFromCache();
|
|
45124
|
+
if (!isCurrent()) return;
|
|
45125
|
+
let types = [];
|
|
45126
|
+
try {
|
|
45127
|
+
types = [...await detectLocalAgentTypes()];
|
|
45128
|
+
} catch (e) {
|
|
45129
|
+
log2(`[Bridge service] detectLocalAgentTypes failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
45130
|
+
}
|
|
45131
|
+
if (!isCurrent()) return;
|
|
45132
|
+
try {
|
|
45133
|
+
const n = await probeAgentCapabilitiesForDetectedTypes({
|
|
45134
|
+
agentTypes: types,
|
|
45135
|
+
cwd,
|
|
45136
|
+
workspaceId,
|
|
45137
|
+
log: log2,
|
|
45138
|
+
bridgeReport: false,
|
|
45139
|
+
forceAllTypes: false,
|
|
45140
|
+
shouldContinue: isCurrent
|
|
45141
|
+
});
|
|
45142
|
+
if (n > 0) await sendBatchFromCache();
|
|
45143
|
+
} catch (e) {
|
|
45144
|
+
if (e instanceof CliSqliteInterrupted) return;
|
|
45145
|
+
log2(`[Bridge service] Agent capability probe (missing cache) failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
45146
|
+
}
|
|
45147
|
+
if (!isCurrent()) return;
|
|
45148
|
+
void (async () => {
|
|
45149
|
+
try {
|
|
45150
|
+
await yieldToEventLoop();
|
|
45151
|
+
if (!isCurrent()) return;
|
|
45152
|
+
const n = await probeAgentCapabilitiesForDetectedTypes({
|
|
45153
|
+
agentTypes: types,
|
|
45154
|
+
cwd,
|
|
45155
|
+
workspaceId,
|
|
45156
|
+
log: log2,
|
|
45157
|
+
bridgeReport: false,
|
|
45158
|
+
forceAllTypes: true,
|
|
45159
|
+
shouldContinue: isCurrent
|
|
45160
|
+
});
|
|
45161
|
+
if (n > 0) await sendBatchFromCache();
|
|
45162
|
+
} catch (e) {
|
|
45163
|
+
if (e instanceof CliSqliteInterrupted) return;
|
|
45164
|
+
log2(`[Bridge service] Agent capability lazy refresh failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
45165
|
+
}
|
|
45166
|
+
})();
|
|
45167
|
+
}
|
|
45168
|
+
|
|
45169
|
+
// src/connection/create-bridge-agent-capabilities-reporter.ts
|
|
45170
|
+
function createAgentCapabilitiesReporter(params) {
|
|
45171
|
+
const { workspaceId, getWs } = params;
|
|
45172
|
+
return (info) => {
|
|
45173
|
+
if (!Array.isArray(info.configOptions) || info.configOptions.length === 0) return;
|
|
45174
|
+
setImmediate(() => {
|
|
45175
|
+
let changed = false;
|
|
45176
|
+
try {
|
|
45177
|
+
changed = withCliSqliteSync(
|
|
45178
|
+
(db) => upsertCliAgentCapabilityCache(db, {
|
|
45179
|
+
workspaceId,
|
|
45180
|
+
agentType: info.agentType,
|
|
45181
|
+
configOptions: info.configOptions
|
|
45182
|
+
})
|
|
45183
|
+
);
|
|
45184
|
+
} catch (e) {
|
|
45185
|
+
if (e instanceof CliSqliteInterrupted) return;
|
|
45186
|
+
}
|
|
45187
|
+
if (!changed) return;
|
|
45188
|
+
const socket = getWs();
|
|
45189
|
+
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
45190
|
+
sendWsMessage(socket, {
|
|
45191
|
+
type: "agent_capabilities",
|
|
45192
|
+
agentType: info.agentType,
|
|
45193
|
+
configOptions: info.configOptions
|
|
45194
|
+
});
|
|
45195
|
+
});
|
|
45196
|
+
};
|
|
45197
|
+
}
|
|
45198
|
+
function createWarmupAgentCapabilitiesOnConnect(params) {
|
|
45199
|
+
return async () => {
|
|
45200
|
+
await warmupAgentCapabilitiesOnConnect(params);
|
|
45201
|
+
};
|
|
45202
|
+
}
|
|
45203
|
+
|
|
45204
|
+
// src/connection/create-bridge-message-deps.ts
|
|
45205
|
+
function createBridgeMessageDeps(params) {
|
|
45206
|
+
const {
|
|
45207
|
+
getWs,
|
|
45208
|
+
log: log2,
|
|
45209
|
+
acpManager,
|
|
45210
|
+
sessionWorktreeManager,
|
|
45211
|
+
onBridgeIdentified,
|
|
45212
|
+
bridgeHeartbeat,
|
|
45213
|
+
sendLocalSkillsReport,
|
|
45214
|
+
reportAutoDetectedAgents,
|
|
45215
|
+
warmupAgentCapabilitiesOnConnect: warmupAgentCapabilitiesOnConnect2,
|
|
45216
|
+
devServerManager,
|
|
45217
|
+
e2ee,
|
|
45218
|
+
cloudApiBaseUrl,
|
|
45219
|
+
getCloudAccessToken
|
|
45220
|
+
} = params;
|
|
45221
|
+
return {
|
|
45222
|
+
getWs,
|
|
45223
|
+
log: log2,
|
|
45224
|
+
acpManager,
|
|
45225
|
+
sessionWorktreeManager,
|
|
45226
|
+
onBridgeIdentified,
|
|
45227
|
+
onBridgeHeartbeatAck: (seq) => {
|
|
45228
|
+
bridgeHeartbeat.onAck(seq);
|
|
45229
|
+
},
|
|
45230
|
+
sendLocalSkillsReport,
|
|
45231
|
+
reportAutoDetectedAgents,
|
|
45232
|
+
warmupAgentCapabilitiesOnConnect: warmupAgentCapabilitiesOnConnect2,
|
|
45233
|
+
devServerManager,
|
|
45234
|
+
e2ee,
|
|
45235
|
+
cloudApiBaseUrl,
|
|
45236
|
+
getCloudAccessToken
|
|
45237
|
+
};
|
|
45238
|
+
}
|
|
45239
|
+
|
|
44915
45240
|
// src/connection/create-bridge-connection.ts
|
|
44916
45241
|
async function createBridgeConnection(options) {
|
|
44917
45242
|
const { apiUrl, workspaceId, justAuthenticated, onAuthInvalid, persistTokens } = options;
|
|
@@ -44945,48 +45270,36 @@ async function createBridgeConnection(options) {
|
|
|
44945
45270
|
function getWs() {
|
|
44946
45271
|
return state.currentWs;
|
|
44947
45272
|
}
|
|
44948
|
-
|
|
44949
|
-
if (!Array.isArray(info.configOptions) || info.configOptions.length === 0) return;
|
|
44950
|
-
setImmediate(() => {
|
|
44951
|
-
let changed = false;
|
|
44952
|
-
try {
|
|
44953
|
-
changed = withCliSqliteSync(
|
|
44954
|
-
(db) => upsertCliAgentCapabilityCache(db, {
|
|
44955
|
-
workspaceId,
|
|
44956
|
-
agentType: info.agentType,
|
|
44957
|
-
configOptions: info.configOptions
|
|
44958
|
-
})
|
|
44959
|
-
);
|
|
44960
|
-
} catch (e) {
|
|
44961
|
-
if (e instanceof CliSqliteInterrupted) return;
|
|
44962
|
-
}
|
|
44963
|
-
if (!changed) return;
|
|
44964
|
-
const socket = getWs();
|
|
44965
|
-
if (!socket || socket.readyState !== wrapper_default.OPEN) return;
|
|
44966
|
-
sendWsMessage(socket, {
|
|
44967
|
-
type: "agent_capabilities",
|
|
44968
|
-
agentType: info.agentType,
|
|
44969
|
-
configOptions: info.configOptions
|
|
44970
|
-
});
|
|
44971
|
-
});
|
|
44972
|
-
}
|
|
45273
|
+
const sendAgentCapabilitiesToBridge = createAgentCapabilitiesReporter({ workspaceId, getWs });
|
|
44973
45274
|
const worktreesRootPath = options.worktreesRootPath ?? defaultWorktreesRootPath();
|
|
44974
45275
|
const sessionWorktreeManager = new SessionWorktreeManager({
|
|
44975
45276
|
worktreesRootPath,
|
|
44976
45277
|
log: logFn
|
|
44977
45278
|
});
|
|
44978
45279
|
const e2ee = options.e2eCertificate ? createCliE2eeRuntime(options.e2eCertificate) : void 0;
|
|
44979
|
-
const
|
|
45280
|
+
const bridgeAccessRef = {
|
|
45281
|
+
current: null
|
|
45282
|
+
};
|
|
45283
|
+
const bridgeAccessPromise = createBridgeAccessState({
|
|
44980
45284
|
cloudApiBaseUrl: apiUrl,
|
|
44981
45285
|
getCloudAccessToken: () => tokens.accessToken,
|
|
44982
45286
|
e2ee
|
|
45287
|
+
}).then((bridgeAccess2) => {
|
|
45288
|
+
bridgeAccessRef.current = bridgeAccess2;
|
|
45289
|
+
return bridgeAccess2;
|
|
44983
45290
|
});
|
|
44984
45291
|
const acpManager = await createAcpManager({
|
|
44985
45292
|
log: logFn,
|
|
44986
|
-
getBridgeAccessPort: () =>
|
|
45293
|
+
getBridgeAccessPort: () => bridgeAccessRef.current?.getPort() ?? 0,
|
|
44987
45294
|
reportAgentCapabilities: sendAgentCapabilitiesToBridge
|
|
44988
45295
|
});
|
|
44989
45296
|
logFn("CLI running. Press Ctrl+C to exit.");
|
|
45297
|
+
let initialIndexBuildsScheduled = false;
|
|
45298
|
+
const scheduleInitialIndexBuildsOnce = () => {
|
|
45299
|
+
if (initialIndexBuildsScheduled) return;
|
|
45300
|
+
initialIndexBuildsScheduled = true;
|
|
45301
|
+
scheduleInitialIndexBuilds(getBridgeRoot());
|
|
45302
|
+
};
|
|
44990
45303
|
const devServerManager = new DevServerManager({ getWs, log: logFn, getBridgeRoot, e2ee });
|
|
44991
45304
|
const bridgeHeartbeat = createBridgeHeartbeatController({ getWs, log: logFn });
|
|
44992
45305
|
const baseOnBridgeIdentified = createOnBridgeIdentified({
|
|
@@ -45002,32 +45315,28 @@ async function createBridgeConnection(options) {
|
|
|
45002
45315
|
};
|
|
45003
45316
|
const sendLocalSkillsReport = createSendLocalSkillsReport(getWs, logFn);
|
|
45004
45317
|
const reportAutoDetectedAgents = createReportAutoDetectedAgents(getWs, logFn);
|
|
45005
|
-
const messageDeps = {
|
|
45318
|
+
const messageDeps = createBridgeMessageDeps({
|
|
45006
45319
|
getWs,
|
|
45007
45320
|
log: logFn,
|
|
45008
45321
|
acpManager,
|
|
45009
45322
|
sessionWorktreeManager,
|
|
45010
45323
|
onBridgeIdentified,
|
|
45011
|
-
|
|
45012
|
-
bridgeHeartbeat.onAck(seq);
|
|
45013
|
-
},
|
|
45324
|
+
bridgeHeartbeat,
|
|
45014
45325
|
sendLocalSkillsReport,
|
|
45015
45326
|
reportAutoDetectedAgents,
|
|
45016
|
-
warmupAgentCapabilitiesOnConnect:
|
|
45017
|
-
|
|
45018
|
-
|
|
45019
|
-
|
|
45020
|
-
|
|
45021
|
-
});
|
|
45022
|
-
},
|
|
45327
|
+
warmupAgentCapabilitiesOnConnect: createWarmupAgentCapabilitiesOnConnect({
|
|
45328
|
+
workspaceId,
|
|
45329
|
+
log: logFn,
|
|
45330
|
+
getWs
|
|
45331
|
+
}),
|
|
45023
45332
|
devServerManager,
|
|
45024
45333
|
e2ee,
|
|
45025
45334
|
cloudApiBaseUrl: apiUrl,
|
|
45026
45335
|
getCloudAccessToken: () => tokens.accessToken
|
|
45027
|
-
};
|
|
45336
|
+
});
|
|
45028
45337
|
const identifyReportedPaths = {
|
|
45029
|
-
bridgeRootPath:
|
|
45030
|
-
worktreesRootPath:
|
|
45338
|
+
bridgeRootPath: path72.resolve(getBridgeRoot()),
|
|
45339
|
+
worktreesRootPath: path72.resolve(worktreesRootPath)
|
|
45031
45340
|
};
|
|
45032
45341
|
const { connect } = createMainBridgeWebSocketLifecycle({
|
|
45033
45342
|
state,
|
|
@@ -45042,10 +45351,12 @@ async function createBridgeConnection(options) {
|
|
|
45042
45351
|
onAuthInvalid,
|
|
45043
45352
|
e2ee,
|
|
45044
45353
|
identifyReportedPaths,
|
|
45045
|
-
bridgeHeartbeat
|
|
45354
|
+
bridgeHeartbeat,
|
|
45355
|
+
onBridgeSocketOpen: scheduleInitialIndexBuildsOnce
|
|
45046
45356
|
});
|
|
45047
45357
|
connect();
|
|
45048
45358
|
const stopFileIndexWatcher = startFileIndexWatcher(getBridgeRoot());
|
|
45359
|
+
const bridgeAccess = await bridgeAccessPromise;
|
|
45049
45360
|
return {
|
|
45050
45361
|
close: async () => {
|
|
45051
45362
|
requestCliImmediateShutdown();
|