opencode-codebase-index 0.13.1 → 0.14.0
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +22 -8
- package/commands/peek.md +4 -0
- package/commands/search.md +4 -0
- package/dist/cli.cjs +597 -398
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +595 -396
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +531 -322
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +529 -320
- package/dist/index.js.map +1 -1
- package/dist/pi-extension.cjs +638 -395
- package/dist/pi-extension.cjs.map +1 -1
- package/dist/pi-extension.js +638 -395
- package/dist/pi-extension.js.map +1 -1
- package/native/codebase-index-native.darwin-arm64.node +0 -0
- package/native/codebase-index-native.darwin-x64.node +0 -0
- package/native/codebase-index-native.linux-arm64-gnu.node +0 -0
- package/native/codebase-index-native.linux-x64-gnu.node +0 -0
- package/native/codebase-index-native.win32-x64-msvc.node +0 -0
- package/package.json +3 -1
- package/scripts/link-local-mcp-bin.mjs +25 -0
- package/skill/SKILL.md +5 -0
package/dist/cli.cjs
CHANGED
|
@@ -496,7 +496,7 @@ var require_ignore = __commonJS({
|
|
|
496
496
|
// path matching.
|
|
497
497
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
498
498
|
// @returns {TestResult} true if a file is ignored
|
|
499
|
-
test(
|
|
499
|
+
test(path26, checkUnignored, mode) {
|
|
500
500
|
let ignored = false;
|
|
501
501
|
let unignored = false;
|
|
502
502
|
let matchedRule;
|
|
@@ -505,7 +505,7 @@ var require_ignore = __commonJS({
|
|
|
505
505
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
506
506
|
return;
|
|
507
507
|
}
|
|
508
|
-
const matched = rule[mode].test(
|
|
508
|
+
const matched = rule[mode].test(path26);
|
|
509
509
|
if (!matched) {
|
|
510
510
|
return;
|
|
511
511
|
}
|
|
@@ -526,17 +526,17 @@ var require_ignore = __commonJS({
|
|
|
526
526
|
var throwError = (message, Ctor) => {
|
|
527
527
|
throw new Ctor(message);
|
|
528
528
|
};
|
|
529
|
-
var checkPath = (
|
|
530
|
-
if (!isString(
|
|
529
|
+
var checkPath = (path26, originalPath, doThrow) => {
|
|
530
|
+
if (!isString(path26)) {
|
|
531
531
|
return doThrow(
|
|
532
532
|
`path must be a string, but got \`${originalPath}\``,
|
|
533
533
|
TypeError
|
|
534
534
|
);
|
|
535
535
|
}
|
|
536
|
-
if (!
|
|
536
|
+
if (!path26) {
|
|
537
537
|
return doThrow(`path must not be empty`, TypeError);
|
|
538
538
|
}
|
|
539
|
-
if (checkPath.isNotRelative(
|
|
539
|
+
if (checkPath.isNotRelative(path26)) {
|
|
540
540
|
const r = "`path.relative()`d";
|
|
541
541
|
return doThrow(
|
|
542
542
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -545,7 +545,7 @@ var require_ignore = __commonJS({
|
|
|
545
545
|
}
|
|
546
546
|
return true;
|
|
547
547
|
};
|
|
548
|
-
var isNotRelative = (
|
|
548
|
+
var isNotRelative = (path26) => REGEX_TEST_INVALID_PATH.test(path26);
|
|
549
549
|
checkPath.isNotRelative = isNotRelative;
|
|
550
550
|
checkPath.convert = (p) => p;
|
|
551
551
|
var Ignore2 = class {
|
|
@@ -575,19 +575,19 @@ var require_ignore = __commonJS({
|
|
|
575
575
|
}
|
|
576
576
|
// @returns {TestResult}
|
|
577
577
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
578
|
-
const
|
|
578
|
+
const path26 = originalPath && checkPath.convert(originalPath);
|
|
579
579
|
checkPath(
|
|
580
|
-
|
|
580
|
+
path26,
|
|
581
581
|
originalPath,
|
|
582
582
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
583
583
|
);
|
|
584
|
-
return this._t(
|
|
584
|
+
return this._t(path26, cache, checkUnignored, slices);
|
|
585
585
|
}
|
|
586
|
-
checkIgnore(
|
|
587
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
588
|
-
return this.test(
|
|
586
|
+
checkIgnore(path26) {
|
|
587
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path26)) {
|
|
588
|
+
return this.test(path26);
|
|
589
589
|
}
|
|
590
|
-
const slices =
|
|
590
|
+
const slices = path26.split(SLASH2).filter(Boolean);
|
|
591
591
|
slices.pop();
|
|
592
592
|
if (slices.length) {
|
|
593
593
|
const parent = this._t(
|
|
@@ -600,18 +600,18 @@ var require_ignore = __commonJS({
|
|
|
600
600
|
return parent;
|
|
601
601
|
}
|
|
602
602
|
}
|
|
603
|
-
return this._rules.test(
|
|
603
|
+
return this._rules.test(path26, false, MODE_CHECK_IGNORE);
|
|
604
604
|
}
|
|
605
|
-
_t(
|
|
606
|
-
if (
|
|
607
|
-
return cache[
|
|
605
|
+
_t(path26, cache, checkUnignored, slices) {
|
|
606
|
+
if (path26 in cache) {
|
|
607
|
+
return cache[path26];
|
|
608
608
|
}
|
|
609
609
|
if (!slices) {
|
|
610
|
-
slices =
|
|
610
|
+
slices = path26.split(SLASH2).filter(Boolean);
|
|
611
611
|
}
|
|
612
612
|
slices.pop();
|
|
613
613
|
if (!slices.length) {
|
|
614
|
-
return cache[
|
|
614
|
+
return cache[path26] = this._rules.test(path26, checkUnignored, MODE_IGNORE);
|
|
615
615
|
}
|
|
616
616
|
const parent = this._t(
|
|
617
617
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -619,29 +619,29 @@ var require_ignore = __commonJS({
|
|
|
619
619
|
checkUnignored,
|
|
620
620
|
slices
|
|
621
621
|
);
|
|
622
|
-
return cache[
|
|
622
|
+
return cache[path26] = parent.ignored ? parent : this._rules.test(path26, checkUnignored, MODE_IGNORE);
|
|
623
623
|
}
|
|
624
|
-
ignores(
|
|
625
|
-
return this._test(
|
|
624
|
+
ignores(path26) {
|
|
625
|
+
return this._test(path26, this._ignoreCache, false).ignored;
|
|
626
626
|
}
|
|
627
627
|
createFilter() {
|
|
628
|
-
return (
|
|
628
|
+
return (path26) => !this.ignores(path26);
|
|
629
629
|
}
|
|
630
630
|
filter(paths) {
|
|
631
631
|
return makeArray(paths).filter(this.createFilter());
|
|
632
632
|
}
|
|
633
633
|
// @returns {TestResult}
|
|
634
|
-
test(
|
|
635
|
-
return this._test(
|
|
634
|
+
test(path26) {
|
|
635
|
+
return this._test(path26, this._testCache, true);
|
|
636
636
|
}
|
|
637
637
|
};
|
|
638
638
|
var factory = (options) => new Ignore2(options);
|
|
639
|
-
var isPathValid = (
|
|
639
|
+
var isPathValid = (path26) => checkPath(path26 && checkPath.convert(path26), path26, RETURN_FALSE);
|
|
640
640
|
var setupWindows = () => {
|
|
641
641
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
642
642
|
checkPath.convert = makePosix;
|
|
643
643
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
644
|
-
checkPath.isNotRelative = (
|
|
644
|
+
checkPath.isNotRelative = (path26) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path26) || isNotRelative(path26);
|
|
645
645
|
};
|
|
646
646
|
if (
|
|
647
647
|
// Detect `process` so that it can run in browsers.
|
|
@@ -667,7 +667,7 @@ module.exports = __toCommonJS(cli_exports);
|
|
|
667
667
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
668
668
|
var import_fs15 = require("fs");
|
|
669
669
|
var os5 = __toESM(require("os"), 1);
|
|
670
|
-
var
|
|
670
|
+
var path25 = __toESM(require("path"), 1);
|
|
671
671
|
var import_url2 = require("url");
|
|
672
672
|
|
|
673
673
|
// src/config/constants.ts
|
|
@@ -800,7 +800,8 @@ function getDefaultIndexingConfig() {
|
|
|
800
800
|
requireProjectMarker: true,
|
|
801
801
|
maxDepth: 5,
|
|
802
802
|
maxFilesPerDirectory: 100,
|
|
803
|
-
fallbackToTextOnMaxChunks: true
|
|
803
|
+
fallbackToTextOnMaxChunks: true,
|
|
804
|
+
gitBlame: { enabled: false }
|
|
804
805
|
};
|
|
805
806
|
}
|
|
806
807
|
function getDefaultSearchConfig() {
|
|
@@ -924,7 +925,10 @@ function parseConfig(raw) {
|
|
|
924
925
|
requireProjectMarker: typeof rawIndexing.requireProjectMarker === "boolean" ? rawIndexing.requireProjectMarker : defaultIndexing.requireProjectMarker,
|
|
925
926
|
maxDepth: typeof rawIndexing.maxDepth === "number" ? rawIndexing.maxDepth < -1 ? -1 : rawIndexing.maxDepth : defaultIndexing.maxDepth,
|
|
926
927
|
maxFilesPerDirectory: typeof rawIndexing.maxFilesPerDirectory === "number" ? Math.max(1, rawIndexing.maxFilesPerDirectory) : defaultIndexing.maxFilesPerDirectory,
|
|
927
|
-
fallbackToTextOnMaxChunks: typeof rawIndexing.fallbackToTextOnMaxChunks === "boolean" ? rawIndexing.fallbackToTextOnMaxChunks : defaultIndexing.fallbackToTextOnMaxChunks
|
|
928
|
+
fallbackToTextOnMaxChunks: typeof rawIndexing.fallbackToTextOnMaxChunks === "boolean" ? rawIndexing.fallbackToTextOnMaxChunks : defaultIndexing.fallbackToTextOnMaxChunks,
|
|
929
|
+
gitBlame: {
|
|
930
|
+
enabled: rawIndexing.gitBlame && typeof rawIndexing.gitBlame === "object" && typeof rawIndexing.gitBlame.enabled === "boolean" ? rawIndexing.gitBlame.enabled : defaultIndexing.gitBlame.enabled
|
|
931
|
+
}
|
|
928
932
|
};
|
|
929
933
|
const rawSearch = input.search && typeof input.search === "object" ? input.search : {};
|
|
930
934
|
const search = {
|
|
@@ -1109,9 +1113,9 @@ var import_fs = require("fs");
|
|
|
1109
1113
|
var path = __toESM(require("path"), 1);
|
|
1110
1114
|
|
|
1111
1115
|
// src/eval/report-formatters.ts
|
|
1112
|
-
function assertFiniteNumber(value,
|
|
1116
|
+
function assertFiniteNumber(value, path26) {
|
|
1113
1117
|
if (typeof value !== "number" || Number.isNaN(value) || !Number.isFinite(value)) {
|
|
1114
|
-
throw new Error(`${
|
|
1118
|
+
throw new Error(`${path26} must be a finite number`);
|
|
1115
1119
|
}
|
|
1116
1120
|
return value;
|
|
1117
1121
|
}
|
|
@@ -1300,15 +1304,15 @@ function buildPerQueryArtifact(perQuery) {
|
|
|
1300
1304
|
|
|
1301
1305
|
// src/eval/runner.ts
|
|
1302
1306
|
var import_fs10 = require("fs");
|
|
1303
|
-
var
|
|
1307
|
+
var path14 = __toESM(require("path"), 1);
|
|
1304
1308
|
var import_perf_hooks2 = require("perf_hooks");
|
|
1305
1309
|
|
|
1306
1310
|
// src/indexer/index.ts
|
|
1307
1311
|
var import_fs7 = require("fs");
|
|
1308
|
-
var
|
|
1312
|
+
var path11 = __toESM(require("path"), 1);
|
|
1309
1313
|
var import_perf_hooks = require("perf_hooks");
|
|
1310
|
-
var
|
|
1311
|
-
var
|
|
1314
|
+
var import_child_process3 = require("child_process");
|
|
1315
|
+
var import_util3 = require("util");
|
|
1312
1316
|
|
|
1313
1317
|
// node_modules/eventemitter3/index.mjs
|
|
1314
1318
|
var import_index = __toESM(require_eventemitter3(), 1);
|
|
@@ -4839,8 +4843,8 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
4839
4843
|
const trimmed = raw.trim();
|
|
4840
4844
|
if (!trimmed) continue;
|
|
4841
4845
|
const absolute = path9.resolve(projectRoot, trimmed);
|
|
4842
|
-
const
|
|
4843
|
-
const cleaned =
|
|
4846
|
+
const relative11 = path9.relative(projectRoot, absolute);
|
|
4847
|
+
const cleaned = relative11.startsWith("./") ? relative11.slice(2) : relative11;
|
|
4844
4848
|
if (!seen.has(cleaned)) {
|
|
4845
4849
|
seen.add(cleaned);
|
|
4846
4850
|
result.push(cleaned);
|
|
@@ -4849,8 +4853,61 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
4849
4853
|
return result;
|
|
4850
4854
|
}
|
|
4851
4855
|
|
|
4856
|
+
// src/indexer/git-blame.ts
|
|
4857
|
+
var import_child_process2 = require("child_process");
|
|
4858
|
+
var path10 = __toESM(require("path"), 1);
|
|
4859
|
+
var import_util2 = require("util");
|
|
4860
|
+
var execFileAsync2 = (0, import_util2.promisify)(import_child_process2.execFile);
|
|
4861
|
+
function parseGitBlamePorcelain(output) {
|
|
4862
|
+
const commits = /* @__PURE__ */ new Map();
|
|
4863
|
+
let current;
|
|
4864
|
+
for (const line of output.split("\n")) {
|
|
4865
|
+
if (/^[0-9a-f]{40} /.test(line)) {
|
|
4866
|
+
const sha = line.slice(0, 40);
|
|
4867
|
+
current = commits.get(sha) ?? {
|
|
4868
|
+
sha,
|
|
4869
|
+
author: "",
|
|
4870
|
+
authorEmail: "",
|
|
4871
|
+
committedAt: 0,
|
|
4872
|
+
summary: "",
|
|
4873
|
+
lines: 0
|
|
4874
|
+
};
|
|
4875
|
+
commits.set(sha, current);
|
|
4876
|
+
continue;
|
|
4877
|
+
}
|
|
4878
|
+
if (!current) {
|
|
4879
|
+
continue;
|
|
4880
|
+
}
|
|
4881
|
+
if (line.startsWith("author ")) {
|
|
4882
|
+
current.author = line.slice("author ".length);
|
|
4883
|
+
} else if (line.startsWith("author-mail ")) {
|
|
4884
|
+
current.authorEmail = line.slice("author-mail ".length).replace(/^<|>$/g, "");
|
|
4885
|
+
} else if (line.startsWith("author-time ")) {
|
|
4886
|
+
current.committedAt = Number.parseInt(line.slice("author-time ".length), 10);
|
|
4887
|
+
} else if (line.startsWith("summary ")) {
|
|
4888
|
+
current.summary = line.slice("summary ".length);
|
|
4889
|
+
} else if (line.startsWith(" ")) {
|
|
4890
|
+
current.lines += 1;
|
|
4891
|
+
}
|
|
4892
|
+
}
|
|
4893
|
+
return Array.from(commits.values()).filter((commit) => commit.lines > 0).sort((a, b) => b.lines - a.lines || b.committedAt - a.committedAt)[0];
|
|
4894
|
+
}
|
|
4895
|
+
async function getChunkGitBlame(projectRoot, filePath, startLine, endLine) {
|
|
4896
|
+
const relativePath = path10.relative(projectRoot, filePath);
|
|
4897
|
+
try {
|
|
4898
|
+
const { stdout } = await execFileAsync2(
|
|
4899
|
+
"git",
|
|
4900
|
+
["blame", "--line-porcelain", "-L", `${startLine},${endLine}`, "--", relativePath],
|
|
4901
|
+
{ cwd: projectRoot, timeout: 3e4 }
|
|
4902
|
+
);
|
|
4903
|
+
return parseGitBlamePorcelain(stdout);
|
|
4904
|
+
} catch {
|
|
4905
|
+
return void 0;
|
|
4906
|
+
}
|
|
4907
|
+
}
|
|
4908
|
+
|
|
4852
4909
|
// src/indexer/index.ts
|
|
4853
|
-
var CALL_GRAPH_LANGUAGES = /* @__PURE__ */ new Set(["typescript", "tsx", "javascript", "jsx", "python", "go", "rust", "php", "apex", "zig", "gdscript", "matlab"]);
|
|
4910
|
+
var CALL_GRAPH_LANGUAGES = /* @__PURE__ */ new Set(["typescript", "tsx", "javascript", "jsx", "python", "go", "rust", "php", "apex", "zig", "gdscript", "matlab", "bash"]);
|
|
4854
4911
|
var CASE_INSENSITIVE_LANGUAGES = /* @__PURE__ */ new Set(["apex"]);
|
|
4855
4912
|
var CALL_GRAPH_SYMBOL_CHUNK_TYPES = /* @__PURE__ */ new Set([
|
|
4856
4913
|
"function_declaration",
|
|
@@ -4930,6 +4987,45 @@ function isSqliteCorruptionError(error) {
|
|
|
4930
4987
|
return message.includes("database disk image is malformed") || message.includes("file is not a database") || message.includes("database schema is corrupt") || message.includes("sqlite_corrupt");
|
|
4931
4988
|
}
|
|
4932
4989
|
var STARTUP_WARNING_METADATA_KEY = "index.startupWarning";
|
|
4990
|
+
function metadataFromBlame(blame) {
|
|
4991
|
+
if (!blame) {
|
|
4992
|
+
return {};
|
|
4993
|
+
}
|
|
4994
|
+
return {
|
|
4995
|
+
blameSha: blame.sha,
|
|
4996
|
+
blameAuthor: blame.author,
|
|
4997
|
+
blameAuthorEmail: blame.authorEmail,
|
|
4998
|
+
blameCommittedAt: blame.committedAt,
|
|
4999
|
+
blameSummary: blame.summary
|
|
5000
|
+
};
|
|
5001
|
+
}
|
|
5002
|
+
function blameFromChunkData(chunk) {
|
|
5003
|
+
if (!chunk?.blameSha || !chunk.blameAuthor || !chunk.blameAuthorEmail || chunk.blameCommittedAt === void 0 || !chunk.blameSummary) {
|
|
5004
|
+
return void 0;
|
|
5005
|
+
}
|
|
5006
|
+
return {
|
|
5007
|
+
sha: chunk.blameSha,
|
|
5008
|
+
author: chunk.blameAuthor,
|
|
5009
|
+
authorEmail: chunk.blameAuthorEmail,
|
|
5010
|
+
committedAt: chunk.blameCommittedAt,
|
|
5011
|
+
summary: chunk.blameSummary
|
|
5012
|
+
};
|
|
5013
|
+
}
|
|
5014
|
+
function blameFromMetadata(metadata) {
|
|
5015
|
+
if (!metadata.blameSha || !metadata.blameAuthor || !metadata.blameAuthorEmail || metadata.blameCommittedAt === void 0 || !metadata.blameSummary) {
|
|
5016
|
+
return void 0;
|
|
5017
|
+
}
|
|
5018
|
+
return {
|
|
5019
|
+
sha: metadata.blameSha,
|
|
5020
|
+
author: metadata.blameAuthor,
|
|
5021
|
+
authorEmail: metadata.blameAuthorEmail,
|
|
5022
|
+
committedAt: metadata.blameCommittedAt,
|
|
5023
|
+
summary: metadata.blameSummary
|
|
5024
|
+
};
|
|
5025
|
+
}
|
|
5026
|
+
function hasBlameMetadata(metadata) {
|
|
5027
|
+
return blameFromMetadata(metadata) !== void 0;
|
|
5028
|
+
}
|
|
4933
5029
|
var INDEX_METADATA_VERSION = "1";
|
|
4934
5030
|
var EMBEDDING_STRATEGY_VERSION = "2";
|
|
4935
5031
|
var RANKING_TOKEN_CACHE_LIMIT = 4096;
|
|
@@ -5088,9 +5184,9 @@ function hasAllEmbeddingParts(parts, expectedPartCount) {
|
|
|
5088
5184
|
return true;
|
|
5089
5185
|
}
|
|
5090
5186
|
function isPathWithinRoot(filePath, rootPath) {
|
|
5091
|
-
const normalizedFilePath =
|
|
5092
|
-
const normalizedRoot =
|
|
5093
|
-
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${
|
|
5187
|
+
const normalizedFilePath = path11.resolve(filePath);
|
|
5188
|
+
const normalizedRoot = path11.resolve(rootPath);
|
|
5189
|
+
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${path11.sep}`);
|
|
5094
5190
|
}
|
|
5095
5191
|
var rankingQueryTokenCache = /* @__PURE__ */ new Map();
|
|
5096
5192
|
var rankingNameTokenCache = /* @__PURE__ */ new Map();
|
|
@@ -5849,7 +5945,8 @@ function promoteIdentifierMatches(query, combined, semanticCandidates, keywordCa
|
|
|
5849
5945
|
chunkType,
|
|
5850
5946
|
name: chunk.name ?? void 0,
|
|
5851
5947
|
language: chunk.language,
|
|
5852
|
-
hash: chunk.contentHash
|
|
5948
|
+
hash: chunk.contentHash,
|
|
5949
|
+
...metadataFromBlame(blameFromChunkData(chunk))
|
|
5853
5950
|
};
|
|
5854
5951
|
const baselineScore = existing?.score ?? 0.5;
|
|
5855
5952
|
candidateUnion.set(chunk.chunkId, {
|
|
@@ -5933,7 +6030,8 @@ function buildSymbolDefinitionLane(query, database, branchChunkIds, limit, fallb
|
|
|
5933
6030
|
chunkType,
|
|
5934
6031
|
name: chunk.name ?? void 0,
|
|
5935
6032
|
language: chunk.language,
|
|
5936
|
-
hash: chunk.contentHash
|
|
6033
|
+
hash: chunk.contentHash,
|
|
6034
|
+
...metadataFromBlame(blameFromChunkData(chunk))
|
|
5937
6035
|
}
|
|
5938
6036
|
});
|
|
5939
6037
|
}
|
|
@@ -6102,6 +6200,21 @@ function matchesSearchFilters(candidate, options, minScore) {
|
|
|
6102
6200
|
if (options?.chunkType && candidate.metadata.chunkType !== options.chunkType) {
|
|
6103
6201
|
return false;
|
|
6104
6202
|
}
|
|
6203
|
+
if (options?.blameAuthor) {
|
|
6204
|
+
const author = options.blameAuthor.toLowerCase();
|
|
6205
|
+
const candidateAuthor = candidate.metadata.blameAuthor?.toLowerCase();
|
|
6206
|
+
const candidateEmail = candidate.metadata.blameAuthorEmail?.toLowerCase();
|
|
6207
|
+
if (candidateAuthor !== author && candidateEmail !== author) return false;
|
|
6208
|
+
}
|
|
6209
|
+
if (options?.blameSha && !candidate.metadata.blameSha?.toLowerCase().startsWith(options.blameSha.toLowerCase())) {
|
|
6210
|
+
return false;
|
|
6211
|
+
}
|
|
6212
|
+
if (options?.blameSince) {
|
|
6213
|
+
const sinceMs = Date.parse(options.blameSince);
|
|
6214
|
+
if (Number.isNaN(sinceMs)) return false;
|
|
6215
|
+
const committedAt = candidate.metadata.blameCommittedAt;
|
|
6216
|
+
if (committedAt === void 0 || committedAt < Math.floor(sinceMs / 1e3)) return false;
|
|
6217
|
+
}
|
|
6105
6218
|
return true;
|
|
6106
6219
|
}
|
|
6107
6220
|
function unionCandidates(semanticCandidates, keywordCandidates) {
|
|
@@ -6145,9 +6258,9 @@ var Indexer = class {
|
|
|
6145
6258
|
this.config = config;
|
|
6146
6259
|
this.host = host;
|
|
6147
6260
|
this.indexPath = this.getIndexPath();
|
|
6148
|
-
this.fileHashCachePath =
|
|
6149
|
-
this.failedBatchesPath =
|
|
6150
|
-
this.indexingLockPath =
|
|
6261
|
+
this.fileHashCachePath = path11.join(this.indexPath, "file-hashes.json");
|
|
6262
|
+
this.failedBatchesPath = path11.join(this.indexPath, "failed-batches.json");
|
|
6263
|
+
this.indexingLockPath = path11.join(this.indexPath, "indexing.lock");
|
|
6151
6264
|
this.logger = initializeLogger(config.debug);
|
|
6152
6265
|
}
|
|
6153
6266
|
getIndexPath() {
|
|
@@ -6179,14 +6292,14 @@ var Indexer = class {
|
|
|
6179
6292
|
}
|
|
6180
6293
|
atomicWriteSync(targetPath, data) {
|
|
6181
6294
|
const tempPath = `${targetPath}.tmp`;
|
|
6182
|
-
(0, import_fs7.mkdirSync)(
|
|
6295
|
+
(0, import_fs7.mkdirSync)(path11.dirname(targetPath), { recursive: true });
|
|
6183
6296
|
(0, import_fs7.writeFileSync)(tempPath, data);
|
|
6184
6297
|
(0, import_fs7.renameSync)(tempPath, targetPath);
|
|
6185
6298
|
}
|
|
6186
6299
|
getScopedRoots() {
|
|
6187
|
-
const roots = /* @__PURE__ */ new Set([
|
|
6300
|
+
const roots = /* @__PURE__ */ new Set([path11.resolve(this.projectRoot)]);
|
|
6188
6301
|
for (const kbRoot of this.config.knowledgeBases) {
|
|
6189
|
-
roots.add(
|
|
6302
|
+
roots.add(path11.resolve(this.projectRoot, kbRoot));
|
|
6190
6303
|
}
|
|
6191
6304
|
return Array.from(roots);
|
|
6192
6305
|
}
|
|
@@ -6195,29 +6308,29 @@ var Indexer = class {
|
|
|
6195
6308
|
if (this.config.scope !== "global") {
|
|
6196
6309
|
return branchName;
|
|
6197
6310
|
}
|
|
6198
|
-
const projectHash = hashContent(
|
|
6311
|
+
const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
|
|
6199
6312
|
return `${projectHash}:${branchName}`;
|
|
6200
6313
|
}
|
|
6201
6314
|
getBranchCatalogKeyFor(branchName) {
|
|
6202
6315
|
if (this.config.scope !== "global") {
|
|
6203
6316
|
return branchName;
|
|
6204
6317
|
}
|
|
6205
|
-
const projectHash = hashContent(
|
|
6318
|
+
const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
|
|
6206
6319
|
return `${projectHash}:${branchName}`;
|
|
6207
6320
|
}
|
|
6208
6321
|
getLegacyBranchCatalogKey() {
|
|
6209
6322
|
return this.currentBranch || "default";
|
|
6210
6323
|
}
|
|
6211
6324
|
getLegacyMigrationMetadataKey() {
|
|
6212
|
-
const projectHash = hashContent(
|
|
6325
|
+
const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
|
|
6213
6326
|
return `index.globalBranchMigration.${projectHash}`;
|
|
6214
6327
|
}
|
|
6215
6328
|
getProjectEmbeddingStrategyMetadataKey() {
|
|
6216
|
-
const projectHash = hashContent(
|
|
6329
|
+
const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
|
|
6217
6330
|
return `index.embeddingStrategyVersion.${projectHash}`;
|
|
6218
6331
|
}
|
|
6219
6332
|
getProjectForceReembedMetadataKey() {
|
|
6220
|
-
const projectHash = hashContent(
|
|
6333
|
+
const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
|
|
6221
6334
|
return `index.forceReembed.${projectHash}`;
|
|
6222
6335
|
}
|
|
6223
6336
|
hasProjectForceReembedPending() {
|
|
@@ -6311,7 +6424,7 @@ var Indexer = class {
|
|
|
6311
6424
|
if (!this.database) {
|
|
6312
6425
|
return { chunkIds, symbolIds };
|
|
6313
6426
|
}
|
|
6314
|
-
const projectRootPath =
|
|
6427
|
+
const projectRootPath = path11.resolve(this.projectRoot);
|
|
6315
6428
|
const projectLocalFilePaths = /* @__PURE__ */ new Set([
|
|
6316
6429
|
...Array.from(this.fileHashCache.keys()).filter(
|
|
6317
6430
|
(filePath) => this.isFileInCurrentScope(filePath, roots) && isPathWithinRoot(filePath, projectRootPath)
|
|
@@ -6334,7 +6447,7 @@ var Indexer = class {
|
|
|
6334
6447
|
if (this.config.scope !== "global") {
|
|
6335
6448
|
return this.getBranchCatalogCleanupKeys();
|
|
6336
6449
|
}
|
|
6337
|
-
const projectHash = hashContent(
|
|
6450
|
+
const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
|
|
6338
6451
|
const keys = /* @__PURE__ */ new Set();
|
|
6339
6452
|
const projectChunkIdSet = new Set(projectChunkIds);
|
|
6340
6453
|
const projectSymbolIdSet = new Set(projectSymbolIds);
|
|
@@ -6418,7 +6531,7 @@ var Indexer = class {
|
|
|
6418
6531
|
if (!this.database || this.config.scope !== "global") {
|
|
6419
6532
|
return false;
|
|
6420
6533
|
}
|
|
6421
|
-
const projectHash = hashContent(
|
|
6534
|
+
const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
|
|
6422
6535
|
const roots = this.getScopedRoots();
|
|
6423
6536
|
const { chunkIds: projectLocalChunkIds, symbolIds: projectLocalSymbolIds } = this.getProjectLocalScopedOwnershipIds(roots);
|
|
6424
6537
|
return this.database.getAllBranches().some(
|
|
@@ -6452,7 +6565,7 @@ var Indexer = class {
|
|
|
6452
6565
|
...Array.from(this.fileHashCache.keys()).filter((filePath) => this.isFileInCurrentScope(filePath, roots)),
|
|
6453
6566
|
...scopedEntries.map(({ metadata }) => metadata.filePath)
|
|
6454
6567
|
]);
|
|
6455
|
-
const projectRootPath =
|
|
6568
|
+
const projectRootPath = path11.resolve(this.projectRoot);
|
|
6456
6569
|
const projectLocalFilePaths = new Set(
|
|
6457
6570
|
Array.from(filePaths).filter((filePath) => isPathWithinRoot(filePath, projectRootPath))
|
|
6458
6571
|
);
|
|
@@ -6812,13 +6925,13 @@ var Indexer = class {
|
|
|
6812
6925
|
}
|
|
6813
6926
|
await import_fs7.promises.mkdir(this.indexPath, { recursive: true });
|
|
6814
6927
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
6815
|
-
const storePath =
|
|
6928
|
+
const storePath = path11.join(this.indexPath, "vectors");
|
|
6816
6929
|
this.store = new VectorStore(storePath, dimensions);
|
|
6817
|
-
const indexFilePath =
|
|
6930
|
+
const indexFilePath = path11.join(this.indexPath, "vectors.usearch");
|
|
6818
6931
|
if ((0, import_fs7.existsSync)(indexFilePath)) {
|
|
6819
6932
|
this.store.load();
|
|
6820
6933
|
}
|
|
6821
|
-
const invertedIndexPath =
|
|
6934
|
+
const invertedIndexPath = path11.join(this.indexPath, "inverted-index.json");
|
|
6822
6935
|
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
6823
6936
|
try {
|
|
6824
6937
|
this.invertedIndex.load();
|
|
@@ -6828,7 +6941,7 @@ var Indexer = class {
|
|
|
6828
6941
|
}
|
|
6829
6942
|
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
6830
6943
|
}
|
|
6831
|
-
const dbPath =
|
|
6944
|
+
const dbPath = path11.join(this.indexPath, "codebase.db");
|
|
6832
6945
|
let dbIsNew = !(0, import_fs7.existsSync)(dbPath);
|
|
6833
6946
|
try {
|
|
6834
6947
|
this.database = new Database(dbPath);
|
|
@@ -6909,7 +7022,7 @@ var Indexer = class {
|
|
|
6909
7022
|
if (await this.tryResetCorruptedIndex("running automatic orphan garbage collection", error)) {
|
|
6910
7023
|
return {
|
|
6911
7024
|
resetCorruptedIndex: true,
|
|
6912
|
-
warning: this.getCorruptedIndexWarning(
|
|
7025
|
+
warning: this.getCorruptedIndexWarning(path11.join(this.indexPath, "codebase.db"))
|
|
6913
7026
|
};
|
|
6914
7027
|
}
|
|
6915
7028
|
throw error;
|
|
@@ -6924,7 +7037,7 @@ var Indexer = class {
|
|
|
6924
7037
|
return;
|
|
6925
7038
|
}
|
|
6926
7039
|
const retainedEntries = store.getAllMetadata().filter(({ key }) => !excludedSet.has(key));
|
|
6927
|
-
const storeBasePath =
|
|
7040
|
+
const storeBasePath = path11.join(this.indexPath, "vectors");
|
|
6928
7041
|
const storeIndexPath = `${storeBasePath}.usearch`;
|
|
6929
7042
|
const storeMetadataPath = `${storeBasePath}.meta.json`;
|
|
6930
7043
|
const backupIndexPath = `${storeIndexPath}.bak`;
|
|
@@ -7009,7 +7122,7 @@ var Indexer = class {
|
|
|
7009
7122
|
if (!isSqliteCorruptionError(error)) {
|
|
7010
7123
|
return false;
|
|
7011
7124
|
}
|
|
7012
|
-
const dbPath =
|
|
7125
|
+
const dbPath = path11.join(this.indexPath, "codebase.db");
|
|
7013
7126
|
const warning = this.getCorruptedIndexWarning(dbPath);
|
|
7014
7127
|
const errorMessage = getErrorMessage2(error);
|
|
7015
7128
|
if (this.config.scope === "global") {
|
|
@@ -7032,15 +7145,15 @@ var Indexer = class {
|
|
|
7032
7145
|
this.indexCompatibility = null;
|
|
7033
7146
|
this.fileHashCache.clear();
|
|
7034
7147
|
const resetPaths = [
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7148
|
+
path11.join(this.indexPath, "codebase.db"),
|
|
7149
|
+
path11.join(this.indexPath, "codebase.db-shm"),
|
|
7150
|
+
path11.join(this.indexPath, "codebase.db-wal"),
|
|
7151
|
+
path11.join(this.indexPath, "vectors.usearch"),
|
|
7152
|
+
path11.join(this.indexPath, "inverted-index.json"),
|
|
7153
|
+
path11.join(this.indexPath, "file-hashes.json"),
|
|
7154
|
+
path11.join(this.indexPath, "failed-batches.json"),
|
|
7155
|
+
path11.join(this.indexPath, "indexing.lock"),
|
|
7156
|
+
path11.join(this.indexPath, "vectors")
|
|
7044
7157
|
];
|
|
7045
7158
|
await Promise.all(resetPaths.map(async (targetPath) => {
|
|
7046
7159
|
try {
|
|
@@ -7277,6 +7390,7 @@ var Indexer = class {
|
|
|
7277
7390
|
this.logger.debug("Parsed changed files", { parsedCount: parsedFiles.length, parseMs: parseMs.toFixed(2) });
|
|
7278
7391
|
const existingChunks = /* @__PURE__ */ new Map();
|
|
7279
7392
|
const existingChunksByFile = /* @__PURE__ */ new Map();
|
|
7393
|
+
const existingMetadataById = /* @__PURE__ */ new Map();
|
|
7280
7394
|
for (const { key, metadata } of store.getAllMetadata()) {
|
|
7281
7395
|
if (scopedRoots && !this.isFileInCurrentScope(metadata.filePath, scopedRoots)) {
|
|
7282
7396
|
continue;
|
|
@@ -7285,6 +7399,7 @@ var Indexer = class {
|
|
|
7285
7399
|
continue;
|
|
7286
7400
|
}
|
|
7287
7401
|
existingChunks.set(key, metadata.hash);
|
|
7402
|
+
existingMetadataById.set(key, metadata);
|
|
7288
7403
|
const fileChunks = existingChunksByFile.get(metadata.filePath) || /* @__PURE__ */ new Set();
|
|
7289
7404
|
fileChunks.add(key);
|
|
7290
7405
|
existingChunksByFile.set(metadata.filePath, fileChunks);
|
|
@@ -7292,6 +7407,8 @@ var Indexer = class {
|
|
|
7292
7407
|
const currentChunkIds = /* @__PURE__ */ new Set();
|
|
7293
7408
|
const currentFilePaths = /* @__PURE__ */ new Set();
|
|
7294
7409
|
const pendingChunks = [];
|
|
7410
|
+
const gitBlameEnabled = this.config.indexing.gitBlame.enabled && isGitRepo(this.projectRoot);
|
|
7411
|
+
let backfilledBlameMetadata = false;
|
|
7295
7412
|
for (const filePath of unchangedFilePaths) {
|
|
7296
7413
|
currentFilePaths.add(filePath);
|
|
7297
7414
|
const fileChunks = existingChunksByFile.get(filePath);
|
|
@@ -7302,10 +7419,52 @@ var Indexer = class {
|
|
|
7302
7419
|
}
|
|
7303
7420
|
}
|
|
7304
7421
|
const chunkDataBatch = [];
|
|
7422
|
+
if (gitBlameEnabled) {
|
|
7423
|
+
const backfillItems = [];
|
|
7424
|
+
for (const chunkId of currentChunkIds) {
|
|
7425
|
+
const metadata = existingMetadataById.get(chunkId);
|
|
7426
|
+
if (!metadata || hasBlameMetadata(metadata)) {
|
|
7427
|
+
continue;
|
|
7428
|
+
}
|
|
7429
|
+
const chunk = database.getChunk(chunkId);
|
|
7430
|
+
if (!chunk) {
|
|
7431
|
+
continue;
|
|
7432
|
+
}
|
|
7433
|
+
const blame = await getChunkGitBlame(this.projectRoot, chunk.filePath, chunk.startLine, chunk.endLine);
|
|
7434
|
+
const blameMetadata = metadataFromBlame(blame);
|
|
7435
|
+
if (!blameMetadata.blameSha) {
|
|
7436
|
+
continue;
|
|
7437
|
+
}
|
|
7438
|
+
chunkDataBatch.push({
|
|
7439
|
+
...chunk,
|
|
7440
|
+
blameSha: blameMetadata.blameSha,
|
|
7441
|
+
blameAuthor: blameMetadata.blameAuthor,
|
|
7442
|
+
blameAuthorEmail: blameMetadata.blameAuthorEmail,
|
|
7443
|
+
blameCommittedAt: blameMetadata.blameCommittedAt,
|
|
7444
|
+
blameSummary: blameMetadata.blameSummary
|
|
7445
|
+
});
|
|
7446
|
+
const embeddingBuffer = database.getEmbedding(chunk.contentHash);
|
|
7447
|
+
if (!embeddingBuffer) {
|
|
7448
|
+
continue;
|
|
7449
|
+
}
|
|
7450
|
+
backfillItems.push({
|
|
7451
|
+
id: chunkId,
|
|
7452
|
+
vector: Array.from(bufferToFloat32Array(embeddingBuffer)),
|
|
7453
|
+
metadata: {
|
|
7454
|
+
...metadata,
|
|
7455
|
+
...blameMetadata
|
|
7456
|
+
}
|
|
7457
|
+
});
|
|
7458
|
+
}
|
|
7459
|
+
if (backfillItems.length > 0) {
|
|
7460
|
+
store.addBatch(backfillItems);
|
|
7461
|
+
backfilledBlameMetadata = true;
|
|
7462
|
+
}
|
|
7463
|
+
}
|
|
7305
7464
|
for (const parsed of parsedFiles) {
|
|
7306
7465
|
currentFilePaths.add(parsed.path);
|
|
7307
7466
|
if (parsed.chunks.length === 0) {
|
|
7308
|
-
const relativePath =
|
|
7467
|
+
const relativePath = path11.relative(this.projectRoot, parsed.path);
|
|
7309
7468
|
stats.parseFailures.push(relativePath);
|
|
7310
7469
|
}
|
|
7311
7470
|
let fileChunkCount = 0;
|
|
@@ -7326,6 +7485,10 @@ var Indexer = class {
|
|
|
7326
7485
|
}
|
|
7327
7486
|
const id = generateChunkId(parsed.path, chunk);
|
|
7328
7487
|
const contentHash = generateChunkHash(chunk);
|
|
7488
|
+
const existingContentHash = existingChunks.get(id);
|
|
7489
|
+
const existingChunk = gitBlameEnabled ? database.getChunk(id) : null;
|
|
7490
|
+
const blame = gitBlameEnabled && existingContentHash !== contentHash ? await getChunkGitBlame(this.projectRoot, parsed.path, chunk.startLine, chunk.endLine) : blameFromChunkData(existingChunk);
|
|
7491
|
+
const blameMetadata = metadataFromBlame(blame);
|
|
7329
7492
|
currentChunkIds.add(id);
|
|
7330
7493
|
chunkDataBatch.push({
|
|
7331
7494
|
chunkId: id,
|
|
@@ -7335,9 +7498,14 @@ var Indexer = class {
|
|
|
7335
7498
|
endLine: chunk.endLine,
|
|
7336
7499
|
nodeType: chunk.chunkType,
|
|
7337
7500
|
name: chunk.name,
|
|
7338
|
-
language: chunk.language
|
|
7501
|
+
language: chunk.language,
|
|
7502
|
+
blameSha: blameMetadata.blameSha,
|
|
7503
|
+
blameAuthor: blameMetadata.blameAuthor,
|
|
7504
|
+
blameAuthorEmail: blameMetadata.blameAuthorEmail,
|
|
7505
|
+
blameCommittedAt: blameMetadata.blameCommittedAt,
|
|
7506
|
+
blameSummary: blameMetadata.blameSummary
|
|
7339
7507
|
});
|
|
7340
|
-
if (
|
|
7508
|
+
if (existingContentHash === contentHash) {
|
|
7341
7509
|
fileChunkCount++;
|
|
7342
7510
|
continue;
|
|
7343
7511
|
}
|
|
@@ -7352,7 +7520,8 @@ var Indexer = class {
|
|
|
7352
7520
|
chunkType: chunk.chunkType,
|
|
7353
7521
|
name: chunk.name,
|
|
7354
7522
|
language: chunk.language,
|
|
7355
|
-
hash: contentHash
|
|
7523
|
+
hash: contentHash,
|
|
7524
|
+
...blameMetadata
|
|
7356
7525
|
};
|
|
7357
7526
|
pendingChunks.push({
|
|
7358
7527
|
id,
|
|
@@ -7495,6 +7664,9 @@ var Indexer = class {
|
|
|
7495
7664
|
database.addChunksToBranchBatch(branchCatalogKey, Array.from(currentChunkIds));
|
|
7496
7665
|
database.clearBranchSymbols(branchCatalogKey);
|
|
7497
7666
|
database.addSymbolsToBranchBatch(branchCatalogKey, Array.from(allSymbolIds));
|
|
7667
|
+
if (backfilledBlameMetadata) {
|
|
7668
|
+
store.save();
|
|
7669
|
+
}
|
|
7498
7670
|
if (scopedRoots) {
|
|
7499
7671
|
this.replaceScopedFileHashCache(currentFileHashes, scopedRoots);
|
|
7500
7672
|
this.clearScopedFailedBatches(scopedRoots);
|
|
@@ -8058,7 +8230,8 @@ var Indexer = class {
|
|
|
8058
8230
|
content,
|
|
8059
8231
|
score: r.score,
|
|
8060
8232
|
chunkType: r.metadata.chunkType,
|
|
8061
|
-
name: r.metadata.name
|
|
8233
|
+
name: r.metadata.name,
|
|
8234
|
+
blame: blameFromMetadata(r.metadata)
|
|
8062
8235
|
};
|
|
8063
8236
|
})
|
|
8064
8237
|
);
|
|
@@ -8150,12 +8323,12 @@ var Indexer = class {
|
|
|
8150
8323
|
this.indexCompatibility = compatibility;
|
|
8151
8324
|
return;
|
|
8152
8325
|
}
|
|
8153
|
-
const localProjectIndexPaths = [
|
|
8326
|
+
const localProjectIndexPaths = [path11.join(this.projectRoot, getHostProjectIndexRelativePath(this.host))];
|
|
8154
8327
|
if (this.host !== "opencode") {
|
|
8155
|
-
localProjectIndexPaths.push(
|
|
8328
|
+
localProjectIndexPaths.push(path11.join(this.projectRoot, getHostProjectIndexRelativePath("opencode")));
|
|
8156
8329
|
}
|
|
8157
8330
|
const isLocalProjectIndex = localProjectIndexPaths.some(
|
|
8158
|
-
(localPath) =>
|
|
8331
|
+
(localPath) => path11.resolve(this.indexPath) === path11.resolve(localPath)
|
|
8159
8332
|
);
|
|
8160
8333
|
if (!isLocalProjectIndex) {
|
|
8161
8334
|
throw new Error(
|
|
@@ -8245,7 +8418,7 @@ var Indexer = class {
|
|
|
8245
8418
|
gcOrphanSymbols: 0,
|
|
8246
8419
|
gcOrphanCallEdges: 0,
|
|
8247
8420
|
resetCorruptedIndex: true,
|
|
8248
|
-
warning: this.getCorruptedIndexWarning(
|
|
8421
|
+
warning: this.getCorruptedIndexWarning(path11.join(this.indexPath, "codebase.db"))
|
|
8249
8422
|
};
|
|
8250
8423
|
}
|
|
8251
8424
|
this.logger.recordGc(removedCount, gcOrphanChunks, gcOrphanEmbeddings);
|
|
@@ -8565,7 +8738,8 @@ var Indexer = class {
|
|
|
8565
8738
|
content,
|
|
8566
8739
|
score: r.score,
|
|
8567
8740
|
chunkType: r.metadata.chunkType,
|
|
8568
|
-
name: r.metadata.name
|
|
8741
|
+
name: r.metadata.name,
|
|
8742
|
+
blame: blameFromMetadata(r.metadata)
|
|
8569
8743
|
};
|
|
8570
8744
|
})
|
|
8571
8745
|
);
|
|
@@ -8602,9 +8776,9 @@ var Indexer = class {
|
|
|
8602
8776
|
const { database } = await this.ensureInitialized();
|
|
8603
8777
|
let shortest = [];
|
|
8604
8778
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
8605
|
-
const
|
|
8606
|
-
if (
|
|
8607
|
-
shortest =
|
|
8779
|
+
const path26 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
8780
|
+
if (path26.length > 0 && (shortest.length === 0 || path26.length < shortest.length)) {
|
|
8781
|
+
shortest = path26;
|
|
8608
8782
|
}
|
|
8609
8783
|
}
|
|
8610
8784
|
return shortest;
|
|
@@ -8636,7 +8810,7 @@ var Indexer = class {
|
|
|
8636
8810
|
}
|
|
8637
8811
|
async getPrImpact(opts) {
|
|
8638
8812
|
const { database } = await this.ensureInitialized();
|
|
8639
|
-
const
|
|
8813
|
+
const execFileAsync3 = (0, import_util3.promisify)(import_child_process3.execFile);
|
|
8640
8814
|
const changedFilesResult = await getChangedFiles({
|
|
8641
8815
|
pr: opts.pr,
|
|
8642
8816
|
branch: opts.branch,
|
|
@@ -8658,7 +8832,7 @@ var Indexer = class {
|
|
|
8658
8832
|
"Run index_codebase first to build the call graph and symbol index for this branch."
|
|
8659
8833
|
);
|
|
8660
8834
|
}
|
|
8661
|
-
const absoluteChangedFiles = changedFiles.map((f) =>
|
|
8835
|
+
const absoluteChangedFiles = changedFiles.map((f) => path11.resolve(this.projectRoot, f));
|
|
8662
8836
|
const directSymbols = database.getSymbolsForFiles(absoluteChangedFiles, branchKey);
|
|
8663
8837
|
const directIds = directSymbols.map((s) => s.id);
|
|
8664
8838
|
const direction = opts.direction ?? "both";
|
|
@@ -8720,7 +8894,7 @@ var Indexer = class {
|
|
|
8720
8894
|
if (opts.checkConflicts) {
|
|
8721
8895
|
conflictingPRs = [];
|
|
8722
8896
|
try {
|
|
8723
|
-
const { stdout } = await
|
|
8897
|
+
const { stdout } = await execFileAsync3(
|
|
8724
8898
|
"gh",
|
|
8725
8899
|
["pr", "list", "--state", "open", "--json", "number,headRefName", "--limit", "10000"],
|
|
8726
8900
|
{ cwd: this.projectRoot, timeout: 3e4 }
|
|
@@ -8741,7 +8915,7 @@ var Indexer = class {
|
|
|
8741
8915
|
projectRoot: this.projectRoot,
|
|
8742
8916
|
baseBranch: this.baseBranch
|
|
8743
8917
|
});
|
|
8744
|
-
const otherAbsolute = otherChanged.files.map((f) =>
|
|
8918
|
+
const otherAbsolute = otherChanged.files.map((f) => path11.resolve(this.projectRoot, f));
|
|
8745
8919
|
const otherBranchKey = this.getBranchCatalogKeyFor(openPr.headRefName);
|
|
8746
8920
|
const otherSymbols = database.getSymbolsForFiles(otherAbsolute, otherBranchKey);
|
|
8747
8921
|
const otherLabels = /* @__PURE__ */ new Set();
|
|
@@ -8804,12 +8978,12 @@ var Indexer = class {
|
|
|
8804
8978
|
if (meta.filePath) filePaths.add(meta.filePath);
|
|
8805
8979
|
}
|
|
8806
8980
|
const directory = options?.directory?.replace(/\/$/, "");
|
|
8807
|
-
const absoluteDirectoryFilter = directory ?
|
|
8981
|
+
const absoluteDirectoryFilter = directory ? path11.resolve(this.projectRoot, directory) : void 0;
|
|
8808
8982
|
for (const filePath of filePaths) {
|
|
8809
8983
|
if (directory) {
|
|
8810
|
-
const absoluteFilePath =
|
|
8984
|
+
const absoluteFilePath = path11.resolve(filePath);
|
|
8811
8985
|
const matchesRelative = filePath === directory || filePath.startsWith(directory + "/");
|
|
8812
|
-
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter +
|
|
8986
|
+
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter + path11.sep));
|
|
8813
8987
|
if (!matchesRelative && !matchesProjectRelative) {
|
|
8814
8988
|
continue;
|
|
8815
8989
|
}
|
|
@@ -9089,13 +9263,13 @@ function computeEvalMetrics(queries, perQuery, embeddingCallCount, embeddingToke
|
|
|
9089
9263
|
// src/eval/runner-config.ts
|
|
9090
9264
|
var import_fs8 = require("fs");
|
|
9091
9265
|
var os4 = __toESM(require("os"), 1);
|
|
9092
|
-
var
|
|
9266
|
+
var path13 = __toESM(require("path"), 1);
|
|
9093
9267
|
|
|
9094
9268
|
// src/config/rebase.ts
|
|
9095
|
-
var
|
|
9269
|
+
var path12 = __toESM(require("path"), 1);
|
|
9096
9270
|
function isWithinRoot(rootDir, targetPath) {
|
|
9097
|
-
const relativePath =
|
|
9098
|
-
return relativePath === "" || !relativePath.startsWith("..") && !
|
|
9271
|
+
const relativePath = path12.relative(rootDir, targetPath);
|
|
9272
|
+
return relativePath === "" || !relativePath.startsWith("..") && !path12.isAbsolute(relativePath);
|
|
9099
9273
|
}
|
|
9100
9274
|
function rebasePathEntries(values, fromDir, toDir) {
|
|
9101
9275
|
if (!Array.isArray(values)) {
|
|
@@ -9103,10 +9277,10 @@ function rebasePathEntries(values, fromDir, toDir) {
|
|
|
9103
9277
|
}
|
|
9104
9278
|
return values.filter((value) => typeof value === "string").map((value) => {
|
|
9105
9279
|
const trimmed = value.trim();
|
|
9106
|
-
if (!trimmed ||
|
|
9280
|
+
if (!trimmed || path12.isAbsolute(trimmed)) {
|
|
9107
9281
|
return trimmed;
|
|
9108
9282
|
}
|
|
9109
|
-
return normalizePathSeparators(
|
|
9283
|
+
return normalizePathSeparators(path12.normalize(path12.relative(toDir, path12.resolve(fromDir, trimmed))));
|
|
9110
9284
|
}).filter(Boolean);
|
|
9111
9285
|
}
|
|
9112
9286
|
function resolveInheritedKnowledgeBaseEntries(values, sourceRoot, targetRoot) {
|
|
@@ -9118,17 +9292,17 @@ function resolveInheritedKnowledgeBaseEntries(values, sourceRoot, targetRoot) {
|
|
|
9118
9292
|
if (!trimmed) {
|
|
9119
9293
|
return trimmed;
|
|
9120
9294
|
}
|
|
9121
|
-
if (
|
|
9295
|
+
if (path12.isAbsolute(trimmed)) {
|
|
9122
9296
|
if (isWithinRoot(sourceRoot, trimmed)) {
|
|
9123
|
-
return normalizePathSeparators(
|
|
9297
|
+
return normalizePathSeparators(path12.normalize(path12.relative(sourceRoot, trimmed) || "."));
|
|
9124
9298
|
}
|
|
9125
|
-
return
|
|
9299
|
+
return path12.normalize(trimmed);
|
|
9126
9300
|
}
|
|
9127
|
-
const resolvedFromSource =
|
|
9301
|
+
const resolvedFromSource = path12.resolve(sourceRoot, trimmed);
|
|
9128
9302
|
if (isWithinRoot(sourceRoot, resolvedFromSource)) {
|
|
9129
|
-
return normalizePathSeparators(
|
|
9303
|
+
return normalizePathSeparators(path12.normalize(trimmed));
|
|
9130
9304
|
}
|
|
9131
|
-
return normalizePathSeparators(
|
|
9305
|
+
return normalizePathSeparators(path12.normalize(path12.relative(targetRoot, resolvedFromSource)));
|
|
9132
9306
|
}).filter(Boolean);
|
|
9133
9307
|
}
|
|
9134
9308
|
|
|
@@ -9176,20 +9350,20 @@ function parseJsonConfigFile(filePath) {
|
|
|
9176
9350
|
}
|
|
9177
9351
|
}
|
|
9178
9352
|
function toAbsolute(projectRoot, maybeRelative) {
|
|
9179
|
-
return
|
|
9353
|
+
return path13.isAbsolute(maybeRelative) ? maybeRelative : path13.join(projectRoot, maybeRelative);
|
|
9180
9354
|
}
|
|
9181
9355
|
function isProjectScopedConfigPath(configPath) {
|
|
9182
|
-
return
|
|
9356
|
+
return path13.basename(configPath) === "codebase-index.json" && path13.basename(path13.dirname(configPath)) === ".opencode";
|
|
9183
9357
|
}
|
|
9184
9358
|
function normalizeEvalConfigKnowledgeBases(rawConfig, projectRoot, resolvedConfigPath) {
|
|
9185
9359
|
const config = rawConfig && typeof rawConfig === "object" ? { ...rawConfig } : {};
|
|
9186
9360
|
const rebaseEntries = (values) => isProjectScopedConfigPath(resolvedConfigPath) ? resolveInheritedKnowledgeBaseEntries(
|
|
9187
9361
|
values,
|
|
9188
|
-
|
|
9362
|
+
path13.dirname(path13.dirname(resolvedConfigPath)),
|
|
9189
9363
|
projectRoot
|
|
9190
9364
|
) : rebasePathEntries(
|
|
9191
9365
|
values,
|
|
9192
|
-
|
|
9366
|
+
path13.dirname(resolvedConfigPath),
|
|
9193
9367
|
projectRoot
|
|
9194
9368
|
);
|
|
9195
9369
|
if (Array.isArray(config.knowledgeBases)) {
|
|
@@ -9217,7 +9391,7 @@ function loadRawConfig(projectRoot, configPath) {
|
|
|
9217
9391
|
projectConfig
|
|
9218
9392
|
);
|
|
9219
9393
|
}
|
|
9220
|
-
const globalConfig =
|
|
9394
|
+
const globalConfig = path13.join(os4.homedir(), ".config", "opencode", "codebase-index.json");
|
|
9221
9395
|
if ((0, import_fs8.existsSync)(globalConfig)) {
|
|
9222
9396
|
return parseJsonConfigFile(globalConfig);
|
|
9223
9397
|
}
|
|
@@ -9227,10 +9401,10 @@ function getIndexRootPath(projectRoot, scope) {
|
|
|
9227
9401
|
return scope === "global" ? getGlobalIndexPath() : resolveProjectIndexPath(projectRoot, scope);
|
|
9228
9402
|
}
|
|
9229
9403
|
function getLocalProjectIndexRoot(projectRoot) {
|
|
9230
|
-
return
|
|
9404
|
+
return path13.join(projectRoot, ".opencode", "index");
|
|
9231
9405
|
}
|
|
9232
9406
|
function getLocalProjectConfigPath(projectRoot) {
|
|
9233
|
-
return
|
|
9407
|
+
return path13.join(projectRoot, ".opencode", "codebase-index.json");
|
|
9234
9408
|
}
|
|
9235
9409
|
function clearIndexRoot(projectRoot, scope) {
|
|
9236
9410
|
const indexRoot = scope === "global" ? getIndexRootPath(projectRoot, scope) : getLocalProjectIndexRoot(projectRoot);
|
|
@@ -9252,7 +9426,7 @@ function ensureLocalEvalProjectConfig(projectRoot, configPath) {
|
|
|
9252
9426
|
projectRoot,
|
|
9253
9427
|
resolvedConfigPath
|
|
9254
9428
|
);
|
|
9255
|
-
(0, import_fs8.mkdirSync)(
|
|
9429
|
+
(0, import_fs8.mkdirSync)(path13.dirname(localConfigPath), { recursive: true });
|
|
9256
9430
|
(0, import_fs8.writeFileSync)(localConfigPath, JSON.stringify(sourceConfig, null, 2), "utf-8");
|
|
9257
9431
|
return localConfigPath;
|
|
9258
9432
|
}
|
|
@@ -9302,23 +9476,23 @@ function isRecord2(value) {
|
|
|
9302
9476
|
function isStringArray3(value) {
|
|
9303
9477
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
9304
9478
|
}
|
|
9305
|
-
function asPositiveNumber(value,
|
|
9479
|
+
function asPositiveNumber(value, path26) {
|
|
9306
9480
|
if (typeof value !== "number" || Number.isNaN(value) || value < 0) {
|
|
9307
|
-
throw new Error(`${
|
|
9481
|
+
throw new Error(`${path26} must be a non-negative number`);
|
|
9308
9482
|
}
|
|
9309
9483
|
return value;
|
|
9310
9484
|
}
|
|
9311
|
-
function parseQueryType(value,
|
|
9485
|
+
function parseQueryType(value, path26) {
|
|
9312
9486
|
if (value === "definition" || value === "implementation-intent" || value === "similarity" || value === "keyword-heavy") {
|
|
9313
9487
|
return value;
|
|
9314
9488
|
}
|
|
9315
9489
|
throw new Error(
|
|
9316
|
-
`${
|
|
9490
|
+
`${path26} must be one of: definition, implementation-intent, similarity, keyword-heavy`
|
|
9317
9491
|
);
|
|
9318
9492
|
}
|
|
9319
|
-
function parseExpected(input,
|
|
9493
|
+
function parseExpected(input, path26) {
|
|
9320
9494
|
if (!isRecord2(input)) {
|
|
9321
|
-
throw new Error(`${
|
|
9495
|
+
throw new Error(`${path26} must be an object`);
|
|
9322
9496
|
}
|
|
9323
9497
|
const filePathRaw = input.filePath;
|
|
9324
9498
|
const acceptableFilesRaw = input.acceptableFiles;
|
|
@@ -9327,16 +9501,16 @@ function parseExpected(input, path25) {
|
|
|
9327
9501
|
const filePath = typeof filePathRaw === "string" ? filePathRaw : void 0;
|
|
9328
9502
|
const acceptableFiles = isStringArray3(acceptableFilesRaw) ? acceptableFilesRaw : void 0;
|
|
9329
9503
|
if (!filePath && (!acceptableFiles || acceptableFiles.length === 0)) {
|
|
9330
|
-
throw new Error(`${
|
|
9504
|
+
throw new Error(`${path26} must include either expected.filePath or expected.acceptableFiles`);
|
|
9331
9505
|
}
|
|
9332
9506
|
if (acceptableFilesRaw !== void 0 && !isStringArray3(acceptableFilesRaw)) {
|
|
9333
|
-
throw new Error(`${
|
|
9507
|
+
throw new Error(`${path26}.acceptableFiles must be an array of strings`);
|
|
9334
9508
|
}
|
|
9335
9509
|
if (symbolRaw !== void 0 && typeof symbolRaw !== "string") {
|
|
9336
|
-
throw new Error(`${
|
|
9510
|
+
throw new Error(`${path26}.symbol must be a string when provided`);
|
|
9337
9511
|
}
|
|
9338
9512
|
if (branchRaw !== void 0 && typeof branchRaw !== "string") {
|
|
9339
|
-
throw new Error(`${
|
|
9513
|
+
throw new Error(`${path26}.branch must be a string when provided`);
|
|
9340
9514
|
}
|
|
9341
9515
|
return {
|
|
9342
9516
|
filePath,
|
|
@@ -9346,25 +9520,25 @@ function parseExpected(input, path25) {
|
|
|
9346
9520
|
};
|
|
9347
9521
|
}
|
|
9348
9522
|
function parseQuery(input, index) {
|
|
9349
|
-
const
|
|
9523
|
+
const path26 = `queries[${index}]`;
|
|
9350
9524
|
if (!isRecord2(input)) {
|
|
9351
|
-
throw new Error(`${
|
|
9525
|
+
throw new Error(`${path26} must be an object`);
|
|
9352
9526
|
}
|
|
9353
9527
|
const id = input.id;
|
|
9354
9528
|
const query = input.query;
|
|
9355
9529
|
const queryType = input.queryType;
|
|
9356
9530
|
const expected = input.expected;
|
|
9357
9531
|
if (typeof id !== "string" || id.trim().length === 0) {
|
|
9358
|
-
throw new Error(`${
|
|
9532
|
+
throw new Error(`${path26}.id must be a non-empty string`);
|
|
9359
9533
|
}
|
|
9360
9534
|
if (typeof query !== "string" || query.trim().length === 0) {
|
|
9361
|
-
throw new Error(`${
|
|
9535
|
+
throw new Error(`${path26}.query must be a non-empty string`);
|
|
9362
9536
|
}
|
|
9363
9537
|
return {
|
|
9364
9538
|
id,
|
|
9365
9539
|
query,
|
|
9366
|
-
queryType: parseQueryType(queryType, `${
|
|
9367
|
-
expected: parseExpected(expected, `${
|
|
9540
|
+
queryType: parseQueryType(queryType, `${path26}.queryType`),
|
|
9541
|
+
expected: parseExpected(expected, `${path26}.expected`)
|
|
9368
9542
|
};
|
|
9369
9543
|
}
|
|
9370
9544
|
function parseGoldenDataset(raw, sourceLabel) {
|
|
@@ -9547,13 +9721,13 @@ async function runEvaluation(options) {
|
|
|
9547
9721
|
};
|
|
9548
9722
|
const outputDir = createRunDirectory(toAbsolute(options.projectRoot, options.outputRoot));
|
|
9549
9723
|
const perQueryArtifact = buildPerQueryArtifact(perQuery);
|
|
9550
|
-
writeJson(
|
|
9551
|
-
writeJson(
|
|
9724
|
+
writeJson(path14.join(outputDir, "summary.json"), summary);
|
|
9725
|
+
writeJson(path14.join(outputDir, "per-query.json"), perQueryArtifact);
|
|
9552
9726
|
let comparison;
|
|
9553
9727
|
if (againstPath) {
|
|
9554
9728
|
const baseline = loadSummary(againstPath);
|
|
9555
9729
|
comparison = compareSummaries(summary, baseline, againstPath);
|
|
9556
|
-
writeJson(
|
|
9730
|
+
writeJson(path14.join(outputDir, "compare.json"), comparison);
|
|
9557
9731
|
}
|
|
9558
9732
|
let gate;
|
|
9559
9733
|
if (options.ciMode) {
|
|
@@ -9566,7 +9740,7 @@ async function runEvaluation(options) {
|
|
|
9566
9740
|
if ((0, import_fs10.existsSync)(resolvedBaseline)) {
|
|
9567
9741
|
const baselineSummary = loadSummary(resolvedBaseline);
|
|
9568
9742
|
comparison = compareSummaries(summary, baselineSummary, resolvedBaseline);
|
|
9569
|
-
writeJson(
|
|
9743
|
+
writeJson(path14.join(outputDir, "compare.json"), comparison);
|
|
9570
9744
|
} else if (budget.failOnMissingBaseline) {
|
|
9571
9745
|
throw new Error(
|
|
9572
9746
|
`Budget baseline is missing: ${resolvedBaseline}. Set failOnMissingBaseline=false to allow CI run without baseline.`
|
|
@@ -9576,7 +9750,7 @@ async function runEvaluation(options) {
|
|
|
9576
9750
|
gate = evaluateBudgetGate(budget, summary, comparison);
|
|
9577
9751
|
}
|
|
9578
9752
|
const markdown = createSummaryMarkdown(summary, comparison, gate);
|
|
9579
|
-
writeText(
|
|
9753
|
+
writeText(path14.join(outputDir, "summary.md"), markdown);
|
|
9580
9754
|
return { outputDir, summary, perQuery, comparison, gate };
|
|
9581
9755
|
} finally {
|
|
9582
9756
|
await indexer.close();
|
|
@@ -9634,23 +9808,23 @@ async function runSweep(options, sweep) {
|
|
|
9634
9808
|
bestByMrrAt10,
|
|
9635
9809
|
bestByP95Latency
|
|
9636
9810
|
};
|
|
9637
|
-
writeJson(
|
|
9811
|
+
writeJson(path14.join(outputDir, "compare.json"), aggregate);
|
|
9638
9812
|
const md = createSummaryMarkdown(
|
|
9639
9813
|
bestByHitAt5?.summary ?? runs[0].summary,
|
|
9640
9814
|
bestByHitAt5?.comparison,
|
|
9641
9815
|
void 0,
|
|
9642
9816
|
aggregate
|
|
9643
9817
|
);
|
|
9644
|
-
writeText(
|
|
9645
|
-
writeJson(
|
|
9818
|
+
writeText(path14.join(outputDir, "summary.md"), md);
|
|
9819
|
+
writeJson(path14.join(outputDir, "summary.json"), bestByHitAt5?.summary ?? runs[0].summary);
|
|
9646
9820
|
return { outputDir, aggregate };
|
|
9647
9821
|
}
|
|
9648
9822
|
|
|
9649
9823
|
// src/eval/cli.ts
|
|
9650
|
-
var
|
|
9824
|
+
var path16 = __toESM(require("path"), 1);
|
|
9651
9825
|
|
|
9652
9826
|
// src/eval/cli-parser.ts
|
|
9653
|
-
var
|
|
9827
|
+
var path15 = __toESM(require("path"), 1);
|
|
9654
9828
|
function printUsage() {
|
|
9655
9829
|
console.log(`
|
|
9656
9830
|
Usage:
|
|
@@ -9722,12 +9896,12 @@ function parseEvalArgs(argv, cwd) {
|
|
|
9722
9896
|
const arg = argv[i];
|
|
9723
9897
|
const next = argv[i + 1];
|
|
9724
9898
|
if (arg === "--project" && next) {
|
|
9725
|
-
parsed.projectRoot =
|
|
9899
|
+
parsed.projectRoot = path15.resolve(cwd, next);
|
|
9726
9900
|
i += 1;
|
|
9727
9901
|
continue;
|
|
9728
9902
|
}
|
|
9729
9903
|
if (arg === "--config" && next) {
|
|
9730
|
-
parsed.configPath =
|
|
9904
|
+
parsed.configPath = path15.resolve(cwd, next);
|
|
9731
9905
|
i += 1;
|
|
9732
9906
|
continue;
|
|
9733
9907
|
}
|
|
@@ -9923,22 +10097,22 @@ async function handleEvalCommand(args, cwd) {
|
|
|
9923
10097
|
if (!parsed.againstPath.endsWith(".json")) {
|
|
9924
10098
|
throw new Error("eval diff --against must point to a summary JSON file");
|
|
9925
10099
|
}
|
|
9926
|
-
const currentSummary = loadSummary(
|
|
10100
|
+
const currentSummary = loadSummary(path16.resolve(parsed.projectRoot, currentPath), {
|
|
9927
10101
|
allowLegacyDiversityMetrics: true
|
|
9928
10102
|
});
|
|
9929
|
-
const baselineSummary = loadSummary(
|
|
10103
|
+
const baselineSummary = loadSummary(path16.resolve(parsed.projectRoot, parsed.againstPath), {
|
|
9930
10104
|
allowLegacyDiversityMetrics: true
|
|
9931
10105
|
});
|
|
9932
10106
|
const comparison = compareSummaries(
|
|
9933
10107
|
currentSummary,
|
|
9934
10108
|
baselineSummary,
|
|
9935
|
-
|
|
10109
|
+
path16.resolve(parsed.projectRoot, parsed.againstPath)
|
|
9936
10110
|
);
|
|
9937
|
-
const outputDir = createRunDirectory(
|
|
10111
|
+
const outputDir = createRunDirectory(path16.resolve(parsed.projectRoot, parsed.outputRoot));
|
|
9938
10112
|
const summaryMd = createSummaryMarkdown(currentSummary, comparison);
|
|
9939
|
-
writeJson(
|
|
9940
|
-
writeText(
|
|
9941
|
-
writeJson(
|
|
10113
|
+
writeJson(path16.join(outputDir, "compare.json"), comparison);
|
|
10114
|
+
writeText(path16.join(outputDir, "summary.md"), summaryMd);
|
|
10115
|
+
writeJson(path16.join(outputDir, "summary.json"), currentSummary);
|
|
9942
10116
|
console.log(`Eval diff complete. Artifacts: ${outputDir}`);
|
|
9943
10117
|
return 0;
|
|
9944
10118
|
}
|
|
@@ -10183,6 +10357,17 @@ function calculatePercentage(progress) {
|
|
|
10183
10357
|
if (progress.phase === "storing") return 95;
|
|
10184
10358
|
return 0;
|
|
10185
10359
|
}
|
|
10360
|
+
function formatCodebasePeek(results) {
|
|
10361
|
+
if (results.length === 0) {
|
|
10362
|
+
return "No matching code found. Try a different query or run index_codebase first.";
|
|
10363
|
+
}
|
|
10364
|
+
const formatted = results.map((r, idx) => {
|
|
10365
|
+
const location = `${r.filePath}:${r.startLine}-${r.endLine}`;
|
|
10366
|
+
const name = r.name ? `"${r.name}"` : "(anonymous)";
|
|
10367
|
+
return `[${idx + 1}] ${r.chunkType} ${name} at ${location} (score: ${r.score.toFixed(2)})${formatBlame(r)}`;
|
|
10368
|
+
});
|
|
10369
|
+
return formatted.join("\n");
|
|
10370
|
+
}
|
|
10186
10371
|
function formatHealthCheck(result) {
|
|
10187
10372
|
if (result.resetCorruptedIndex) {
|
|
10188
10373
|
return result.warning ?? "Detected a corrupted local index and reset it. Run index_codebase to rebuild search data.";
|
|
@@ -10211,16 +10396,68 @@ function formatHealthCheck(result) {
|
|
|
10211
10396
|
}
|
|
10212
10397
|
return lines.join("\n");
|
|
10213
10398
|
}
|
|
10399
|
+
function formatCallGraphCallers(name, callers, relationshipType) {
|
|
10400
|
+
if (callers.length === 0) {
|
|
10401
|
+
return `No callers found for "${name}"${relationshipType ? ` with type ${relationshipType}` : ""}. It may not be called by any tracked function, or the index needs updating.`;
|
|
10402
|
+
}
|
|
10403
|
+
const formatted = callers.map((edge, index) => {
|
|
10404
|
+
const confidence = edge.confidence !== "Direct" ? ` [${edge.confidence.toLowerCase()}]` : "";
|
|
10405
|
+
return `[${index + 1}] \u2190 from ${edge.fromSymbolName ?? "<unknown>"} in ${edge.fromSymbolFilePath ?? "<unknown file>"} [${edge.fromSymbolId}] (${edge.callType})${confidence} at line ${edge.line}${edge.isResolved ? " [resolved]" : " [unresolved]"}`;
|
|
10406
|
+
});
|
|
10407
|
+
return `"${name}" is called by ${callers.length} function(s):
|
|
10408
|
+
|
|
10409
|
+
${formatted.join("\n")}`;
|
|
10410
|
+
}
|
|
10411
|
+
function formatCallGraphCallees(symbolId, callees, relationshipType) {
|
|
10412
|
+
if (callees.length === 0) {
|
|
10413
|
+
return `No callees found for symbol ${symbolId}${relationshipType ? ` with type ${relationshipType}` : ""}. The function may not call any other tracked functions.`;
|
|
10414
|
+
}
|
|
10415
|
+
return callees.map((edge, index) => {
|
|
10416
|
+
const confidence = edge.confidence !== "Direct" ? ` [${edge.confidence.toLowerCase()}]` : "";
|
|
10417
|
+
return `[${index + 1}] \u2192 ${edge.targetName} (${edge.callType})${confidence} at line ${edge.line}${edge.isResolved ? ` [resolved: ${edge.toSymbolId}]` : " [unresolved]"}`;
|
|
10418
|
+
}).join("\n");
|
|
10419
|
+
}
|
|
10420
|
+
function formatCallGraphPath(from, to, path26) {
|
|
10421
|
+
if (path26.length === 0) {
|
|
10422
|
+
return `No path found between "${from}" and "${to}". They may be in disconnected components, or the call graph index needs updating.`;
|
|
10423
|
+
}
|
|
10424
|
+
const formatted = path26.map((hop, index) => {
|
|
10425
|
+
const prefix = index === 0 ? "[start]" : `--${hop.callType}-->`;
|
|
10426
|
+
const location = hop.filePath ? ` (${hop.filePath}:${hop.line})` : "";
|
|
10427
|
+
return `${prefix} ${hop.symbolName}${location}`;
|
|
10428
|
+
});
|
|
10429
|
+
return `Path (${path26.length} hops):
|
|
10430
|
+
${formatted.join("\n")}`;
|
|
10431
|
+
}
|
|
10214
10432
|
function formatResultHeader(result, index) {
|
|
10215
10433
|
return result.name ? `[${index + 1}] ${result.chunkType} "${result.name}" in ${result.filePath}:${result.startLine}-${result.endLine}` : `[${index + 1}] ${result.chunkType} in ${result.filePath}:${result.startLine}-${result.endLine}`;
|
|
10216
10434
|
}
|
|
10435
|
+
function formatBlame(result) {
|
|
10436
|
+
if (!result.blame) {
|
|
10437
|
+
return "";
|
|
10438
|
+
}
|
|
10439
|
+
const date = new Date(result.blame.committedAt * 1e3).toISOString().slice(0, 10);
|
|
10440
|
+
return `
|
|
10441
|
+
${result.blame.sha.slice(0, 7)} | ${result.blame.author} | ${date} | ${result.blame.summary}`;
|
|
10442
|
+
}
|
|
10217
10443
|
function formatDefinitionLookup(results, query) {
|
|
10218
10444
|
if (results.length === 0) {
|
|
10219
10445
|
return `No definition found for "${query}". Try codebase_search for broader discovery, or verify the symbol name.`;
|
|
10220
10446
|
}
|
|
10221
10447
|
const formatted = results.map((r, idx) => {
|
|
10222
10448
|
const header = formatResultHeader(r, idx);
|
|
10223
|
-
return `${header} (score: ${r.score.toFixed(2)})
|
|
10449
|
+
return `${header} (score: ${r.score.toFixed(2)})${formatBlame(r)}
|
|
10450
|
+
\`\`\`
|
|
10451
|
+
${truncateContent(r.content)}
|
|
10452
|
+
\`\`\``;
|
|
10453
|
+
});
|
|
10454
|
+
return formatted.join("\n\n");
|
|
10455
|
+
}
|
|
10456
|
+
function formatSearchResults(results, scoreFormat = "similarity") {
|
|
10457
|
+
const formatted = results.map((r, idx) => {
|
|
10458
|
+
const header = formatResultHeader(r, idx);
|
|
10459
|
+
const scoreLabel = scoreFormat === "similarity" ? `(similarity: ${(r.score * 100).toFixed(1)}%)` : `(score: ${r.score.toFixed(2)})`;
|
|
10460
|
+
return `${header} ${scoreLabel}${formatBlame(r)}
|
|
10224
10461
|
\`\`\`
|
|
10225
10462
|
${truncateContent(r.content)}
|
|
10226
10463
|
\`\`\``;
|
|
@@ -10281,11 +10518,11 @@ function formatPrImpact(result) {
|
|
|
10281
10518
|
|
|
10282
10519
|
// src/tools/operations.ts
|
|
10283
10520
|
var import_fs13 = require("fs");
|
|
10284
|
-
var
|
|
10521
|
+
var path20 = __toESM(require("path"), 1);
|
|
10285
10522
|
|
|
10286
10523
|
// src/config/merger.ts
|
|
10287
10524
|
var import_fs11 = require("fs");
|
|
10288
|
-
var
|
|
10525
|
+
var path17 = __toESM(require("path"), 1);
|
|
10289
10526
|
var PROJECT_OVERRIDE_KEYS = [
|
|
10290
10527
|
"embeddingProvider",
|
|
10291
10528
|
"customProvider",
|
|
@@ -10318,8 +10555,8 @@ function mergeUniqueStringArray(values) {
|
|
|
10318
10555
|
return [...new Set(values.map((value) => String(value).trim()))];
|
|
10319
10556
|
}
|
|
10320
10557
|
function normalizeKnowledgeBasePath(value) {
|
|
10321
|
-
let normalized =
|
|
10322
|
-
const root =
|
|
10558
|
+
let normalized = path17.normalize(String(value).trim());
|
|
10559
|
+
const root = path17.parse(normalized).root;
|
|
10323
10560
|
while (normalized.length > root.length && /[\\/]$/.test(normalized)) {
|
|
10324
10561
|
normalized = normalized.slice(0, -1);
|
|
10325
10562
|
}
|
|
@@ -10372,7 +10609,7 @@ function loadConfigFile(filePath) {
|
|
|
10372
10609
|
}
|
|
10373
10610
|
function materializeLocalProjectConfig(projectRoot, config, host = "opencode") {
|
|
10374
10611
|
const localConfigPath = resolveWritableProjectConfigPath(projectRoot, host);
|
|
10375
|
-
(0, import_fs11.mkdirSync)(
|
|
10612
|
+
(0, import_fs11.mkdirSync)(path17.dirname(localConfigPath), { recursive: true });
|
|
10376
10613
|
(0, import_fs11.writeFileSync)(localConfigPath, JSON.stringify(config, null, 2), "utf-8");
|
|
10377
10614
|
return localConfigPath;
|
|
10378
10615
|
}
|
|
@@ -10383,7 +10620,7 @@ function loadProjectConfigLayer(projectRoot, host = "opencode") {
|
|
|
10383
10620
|
return {};
|
|
10384
10621
|
}
|
|
10385
10622
|
const normalizedConfig = { ...projectConfig };
|
|
10386
|
-
const projectConfigBaseDir =
|
|
10623
|
+
const projectConfigBaseDir = path17.dirname(path17.dirname(projectConfigPath));
|
|
10387
10624
|
if (Array.isArray(normalizedConfig.knowledgeBases)) {
|
|
10388
10625
|
normalizedConfig.knowledgeBases = resolveInheritedKnowledgeBaseEntries(
|
|
10389
10626
|
normalizedConfig.knowledgeBases,
|
|
@@ -10447,19 +10684,19 @@ function loadMergedConfig(projectRoot, host = "opencode") {
|
|
|
10447
10684
|
}
|
|
10448
10685
|
|
|
10449
10686
|
// src/tools/knowledge-base-paths.ts
|
|
10450
|
-
var
|
|
10687
|
+
var path18 = __toESM(require("path"), 1);
|
|
10451
10688
|
function resolveConfigPathValue(value, baseDir) {
|
|
10452
10689
|
const trimmed = value.trim();
|
|
10453
10690
|
if (!trimmed) {
|
|
10454
10691
|
return trimmed;
|
|
10455
10692
|
}
|
|
10456
|
-
const absolutePath =
|
|
10457
|
-
return
|
|
10693
|
+
const absolutePath = path18.isAbsolute(trimmed) ? trimmed : path18.resolve(baseDir, trimmed);
|
|
10694
|
+
return path18.normalize(absolutePath);
|
|
10458
10695
|
}
|
|
10459
10696
|
|
|
10460
10697
|
// src/tools/config-state.ts
|
|
10461
10698
|
var import_fs12 = require("fs");
|
|
10462
|
-
var
|
|
10699
|
+
var path19 = __toESM(require("path"), 1);
|
|
10463
10700
|
function normalizeKnowledgeBasePaths(config, projectRoot) {
|
|
10464
10701
|
const normalized = { ...config };
|
|
10465
10702
|
if (Array.isArray(normalized.knowledgeBases)) {
|
|
@@ -10527,7 +10764,7 @@ function refreshIndexerForDirectory(projectRoot, host = "opencode", config = par
|
|
|
10527
10764
|
}
|
|
10528
10765
|
function shouldForceLocalizeProjectIndex(projectRoot, host = "opencode") {
|
|
10529
10766
|
const root = getProjectRoot(projectRoot, host);
|
|
10530
|
-
const localIndexPath =
|
|
10767
|
+
const localIndexPath = path20.join(root, getHostProjectIndexRelativePath(host));
|
|
10531
10768
|
if ((0, import_fs13.existsSync)(localIndexPath)) {
|
|
10532
10769
|
return false;
|
|
10533
10770
|
}
|
|
@@ -10542,7 +10779,10 @@ async function searchCodebase(projectRoot, host, query, options = {}) {
|
|
|
10542
10779
|
chunkType: options.chunkType,
|
|
10543
10780
|
contextLines: options.contextLines,
|
|
10544
10781
|
metadataOnly: options.metadataOnly,
|
|
10545
|
-
definitionIntent: options.definitionIntent
|
|
10782
|
+
definitionIntent: options.definitionIntent,
|
|
10783
|
+
blameAuthor: options.blameAuthor,
|
|
10784
|
+
blameSha: options.blameSha,
|
|
10785
|
+
blameSince: options.blameSince
|
|
10546
10786
|
});
|
|
10547
10787
|
}
|
|
10548
10788
|
async function findSimilarCode(projectRoot, host, code, options = {}) {
|
|
@@ -10684,13 +10924,6 @@ async function getIndexLogs(projectRoot, host, args) {
|
|
|
10684
10924
|
}
|
|
10685
10925
|
|
|
10686
10926
|
// src/mcp-server/shared.ts
|
|
10687
|
-
var MAX_CONTENT_LINES2 = 30;
|
|
10688
|
-
function truncateContent2(content) {
|
|
10689
|
-
const lines = content.split("\n");
|
|
10690
|
-
if (lines.length <= MAX_CONTENT_LINES2) return content;
|
|
10691
|
-
return lines.slice(0, MAX_CONTENT_LINES2).join("\n") + `
|
|
10692
|
-
// ... (${lines.length - MAX_CONTENT_LINES2} more lines)`;
|
|
10693
|
-
}
|
|
10694
10927
|
var CHUNK_TYPE_ENUM = [
|
|
10695
10928
|
"function",
|
|
10696
10929
|
"class",
|
|
@@ -10716,7 +10949,10 @@ function registerMcpTools(server, runtime) {
|
|
|
10716
10949
|
fileType: import_zod2.z.string().optional().describe("Filter by file extension (e.g., 'ts', 'py', 'rs')"),
|
|
10717
10950
|
directory: import_zod2.z.string().optional().describe("Filter by directory path (e.g., 'src/utils', 'lib')"),
|
|
10718
10951
|
chunkType: import_zod2.z.enum(CHUNK_TYPE_ENUM).optional().describe("Filter by code chunk type"),
|
|
10719
|
-
contextLines: import_zod2.z.number().optional().describe("Number of extra lines to include before/after each match (default: 0)")
|
|
10952
|
+
contextLines: import_zod2.z.number().optional().describe("Number of extra lines to include before/after each match (default: 0)"),
|
|
10953
|
+
blameAuthor: import_zod2.z.string().optional().describe("Filter by git blame author name or email"),
|
|
10954
|
+
blameSha: import_zod2.z.string().optional().describe("Filter by git blame commit SHA or prefix"),
|
|
10955
|
+
blameSince: import_zod2.z.string().optional().describe("Filter to chunks last changed on or after this date")
|
|
10720
10956
|
},
|
|
10721
10957
|
async (args) => {
|
|
10722
10958
|
const results = await searchCodebase(runtime.projectRoot, runtime.host, args.query, {
|
|
@@ -10724,21 +10960,17 @@ function registerMcpTools(server, runtime) {
|
|
|
10724
10960
|
fileType: args.fileType,
|
|
10725
10961
|
directory: args.directory,
|
|
10726
10962
|
chunkType: args.chunkType,
|
|
10727
|
-
contextLines: args.contextLines
|
|
10963
|
+
contextLines: args.contextLines,
|
|
10964
|
+
blameAuthor: args.blameAuthor,
|
|
10965
|
+
blameSha: args.blameSha,
|
|
10966
|
+
blameSince: args.blameSince
|
|
10728
10967
|
});
|
|
10729
10968
|
if (results.length === 0) {
|
|
10730
10969
|
return { content: [{ type: "text", text: "No matching code found. Try a different query or run index_codebase first." }] };
|
|
10731
10970
|
}
|
|
10732
|
-
const formatted = results.map((r, idx) => {
|
|
10733
|
-
const header = r.name ? `[${idx + 1}] ${r.chunkType} "${r.name}" in ${r.filePath}:${r.startLine}-${r.endLine}` : `[${idx + 1}] ${r.chunkType} in ${r.filePath}:${r.startLine}-${r.endLine}`;
|
|
10734
|
-
return `${header} (score: ${r.score.toFixed(2)})
|
|
10735
|
-
\`\`\`
|
|
10736
|
-
${truncateContent2(r.content)}
|
|
10737
|
-
\`\`\``;
|
|
10738
|
-
});
|
|
10739
10971
|
return { content: [{ type: "text", text: `Found ${results.length} results for "${args.query}":
|
|
10740
10972
|
|
|
10741
|
-
${
|
|
10973
|
+
${formatSearchResults(results, "score")}` }] };
|
|
10742
10974
|
}
|
|
10743
10975
|
);
|
|
10744
10976
|
server.tool(
|
|
@@ -10749,7 +10981,10 @@ ${formatted.join("\n\n")}` }] };
|
|
|
10749
10981
|
limit: import_zod2.z.number().optional().default(10).describe("Maximum number of results to return"),
|
|
10750
10982
|
fileType: import_zod2.z.string().optional().describe("Filter by file extension (e.g., 'ts', 'py', 'rs')"),
|
|
10751
10983
|
directory: import_zod2.z.string().optional().describe("Filter by directory path (e.g., 'src/utils', 'lib')"),
|
|
10752
|
-
chunkType: import_zod2.z.enum(CHUNK_TYPE_ENUM).optional().describe("Filter by code chunk type")
|
|
10984
|
+
chunkType: import_zod2.z.enum(CHUNK_TYPE_ENUM).optional().describe("Filter by code chunk type"),
|
|
10985
|
+
blameAuthor: import_zod2.z.string().optional().describe("Filter by git blame author name or email"),
|
|
10986
|
+
blameSha: import_zod2.z.string().optional().describe("Filter by git blame commit SHA or prefix"),
|
|
10987
|
+
blameSince: import_zod2.z.string().optional().describe("Filter to chunks last changed on or after this date")
|
|
10753
10988
|
},
|
|
10754
10989
|
async (args) => {
|
|
10755
10990
|
const results = await searchCodebase(runtime.projectRoot, runtime.host, args.query, {
|
|
@@ -10757,19 +10992,17 @@ ${formatted.join("\n\n")}` }] };
|
|
|
10757
10992
|
fileType: args.fileType,
|
|
10758
10993
|
directory: args.directory,
|
|
10759
10994
|
chunkType: args.chunkType,
|
|
10760
|
-
metadataOnly: true
|
|
10995
|
+
metadataOnly: true,
|
|
10996
|
+
blameAuthor: args.blameAuthor,
|
|
10997
|
+
blameSha: args.blameSha,
|
|
10998
|
+
blameSince: args.blameSince
|
|
10761
10999
|
});
|
|
10762
11000
|
if (results.length === 0) {
|
|
10763
11001
|
return { content: [{ type: "text", text: "No matching code found. Try a different query or run index_codebase first." }] };
|
|
10764
11002
|
}
|
|
10765
|
-
const formatted = results.map((r, idx) => {
|
|
10766
|
-
const location = `${r.filePath}:${r.startLine}-${r.endLine}`;
|
|
10767
|
-
const name = r.name ? `"${r.name}"` : "(anonymous)";
|
|
10768
|
-
return `[${idx + 1}] ${r.chunkType} ${name} at ${location} (score: ${r.score.toFixed(2)})`;
|
|
10769
|
-
});
|
|
10770
11003
|
return { content: [{ type: "text", text: `Found ${results.length} locations for "${args.query}":
|
|
10771
11004
|
|
|
10772
|
-
${
|
|
11005
|
+
${formatCodebasePeek(results)}
|
|
10773
11006
|
|
|
10774
11007
|
Use Read tool to examine specific files.` }] };
|
|
10775
11008
|
}
|
|
@@ -10850,16 +11083,9 @@ Use Read tool to examine specific files.` }] };
|
|
|
10850
11083
|
if (results.length === 0) {
|
|
10851
11084
|
return { content: [{ type: "text", text: "No similar code found. Try a different snippet or run index_codebase first." }] };
|
|
10852
11085
|
}
|
|
10853
|
-
const formatted = results.map((r, idx) => {
|
|
10854
|
-
const header = r.name ? `[${idx + 1}] ${r.chunkType} "${r.name}" in ${r.filePath}:${r.startLine}-${r.endLine}` : `[${idx + 1}] ${r.chunkType} in ${r.filePath}:${r.startLine}-${r.endLine}`;
|
|
10855
|
-
return `${header} (similarity: ${(r.score * 100).toFixed(1)}%)
|
|
10856
|
-
\`\`\`
|
|
10857
|
-
${truncateContent2(r.content)}
|
|
10858
|
-
\`\`\``;
|
|
10859
|
-
});
|
|
10860
11086
|
return { content: [{ type: "text", text: `Found ${results.length} similar code blocks:
|
|
10861
11087
|
|
|
10862
|
-
${
|
|
11088
|
+
${formatSearchResults(results)}` }] };
|
|
10863
11089
|
}
|
|
10864
11090
|
);
|
|
10865
11091
|
server.tool(
|
|
@@ -10895,28 +11121,10 @@ ${formatted.join("\n\n")}` }] };
|
|
|
10895
11121
|
return { content: [{ type: "text", text: "Error: 'symbolId' is required when direction is 'callees'." }] };
|
|
10896
11122
|
}
|
|
10897
11123
|
const { callees } = await getCallGraphData(runtime.projectRoot, runtime.host, args);
|
|
10898
|
-
|
|
10899
|
-
return { content: [{ type: "text", text: `No callees found for symbol ${args.symbolId}${args.relationshipType ? ` with type ${args.relationshipType}` : ""}.` }] };
|
|
10900
|
-
}
|
|
10901
|
-
const formatted2 = callees.map((e, i) => {
|
|
10902
|
-
const conf = e.confidence !== "Direct" ? ` [${e.confidence.toLowerCase()}]` : "";
|
|
10903
|
-
return `[${i + 1}] \u2192 ${e.targetName} (${e.callType})${conf} at line ${e.line}${e.isResolved ? ` [resolved: ${e.toSymbolId}]` : " [unresolved]"}`;
|
|
10904
|
-
});
|
|
10905
|
-
return { content: [{ type: "text", text: `Callees (${callees.length}):
|
|
10906
|
-
|
|
10907
|
-
${formatted2.join("\n")}` }] };
|
|
11124
|
+
return { content: [{ type: "text", text: formatCallGraphCallees(args.symbolId, callees, args.relationshipType) }] };
|
|
10908
11125
|
}
|
|
10909
11126
|
const { callers } = await getCallGraphData(runtime.projectRoot, runtime.host, args);
|
|
10910
|
-
|
|
10911
|
-
return { content: [{ type: "text", text: `No callers found for "${args.name}"${args.relationshipType ? ` with type ${args.relationshipType}` : ""}.` }] };
|
|
10912
|
-
}
|
|
10913
|
-
const formatted = callers.map((e, i) => {
|
|
10914
|
-
const conf = e.confidence !== "Direct" ? ` [${e.confidence.toLowerCase()}]` : "";
|
|
10915
|
-
return `[${i + 1}] \u2190 from ${e.fromSymbolName ?? "<unknown>"} in ${e.fromSymbolFilePath ?? "<unknown file>"} [${e.fromSymbolId}] (${e.callType})${conf} at line ${e.line}${e.isResolved ? " [resolved]" : " [unresolved]"}`;
|
|
10916
|
-
});
|
|
10917
|
-
return { content: [{ type: "text", text: `"${args.name}" is called by ${callers.length} function(s):
|
|
10918
|
-
|
|
10919
|
-
${formatted.join("\n")}` }] };
|
|
11127
|
+
return { content: [{ type: "text", text: formatCallGraphCallers(args.name, callers, args.relationshipType) }] };
|
|
10920
11128
|
}
|
|
10921
11129
|
);
|
|
10922
11130
|
server.tool(
|
|
@@ -10928,17 +11136,8 @@ ${formatted.join("\n")}` }] };
|
|
|
10928
11136
|
maxDepth: import_zod2.z.number().optional().default(10).describe("Maximum traversal depth (default: 10)")
|
|
10929
11137
|
},
|
|
10930
11138
|
async (args) => {
|
|
10931
|
-
const
|
|
10932
|
-
|
|
10933
|
-
return { content: [{ type: "text", text: `No path found between "${args.from}" and "${args.to}". They may be in disconnected components, or the call graph index needs updating.` }] };
|
|
10934
|
-
}
|
|
10935
|
-
const formatted = path25.map((hop, i) => {
|
|
10936
|
-
const prefix = i === 0 ? "[start]" : `--${hop.callType}-->`;
|
|
10937
|
-
const location = hop.filePath ? ` (${hop.filePath}:${hop.line})` : "";
|
|
10938
|
-
return `${prefix} ${hop.symbolName}${location}`;
|
|
10939
|
-
});
|
|
10940
|
-
return { content: [{ type: "text", text: `Path (${path25.length} hops):
|
|
10941
|
-
${formatted.join("\n")}` }] };
|
|
11139
|
+
const path26 = await getCallGraphPath(runtime.projectRoot, runtime.host, args.from, args.to, args.maxDepth);
|
|
11140
|
+
return { content: [{ type: "text", text: formatCallGraphPath(args.from, args.to, path26) }] };
|
|
10942
11141
|
}
|
|
10943
11142
|
);
|
|
10944
11143
|
server.tool(
|
|
@@ -11098,7 +11297,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
11098
11297
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
11099
11298
|
const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
|
|
11100
11299
|
if (wantBigintFsStats) {
|
|
11101
|
-
this._stat = (
|
|
11300
|
+
this._stat = (path26) => statMethod(path26, { bigint: true });
|
|
11102
11301
|
} else {
|
|
11103
11302
|
this._stat = statMethod;
|
|
11104
11303
|
}
|
|
@@ -11123,8 +11322,8 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
11123
11322
|
const par = this.parent;
|
|
11124
11323
|
const fil = par && par.files;
|
|
11125
11324
|
if (fil && fil.length > 0) {
|
|
11126
|
-
const { path:
|
|
11127
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
11325
|
+
const { path: path26, depth } = par;
|
|
11326
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path26));
|
|
11128
11327
|
const awaited = await Promise.all(slice);
|
|
11129
11328
|
for (const entry of awaited) {
|
|
11130
11329
|
if (!entry)
|
|
@@ -11164,20 +11363,20 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
11164
11363
|
this.reading = false;
|
|
11165
11364
|
}
|
|
11166
11365
|
}
|
|
11167
|
-
async _exploreDir(
|
|
11366
|
+
async _exploreDir(path26, depth) {
|
|
11168
11367
|
let files;
|
|
11169
11368
|
try {
|
|
11170
|
-
files = await (0, import_promises.readdir)(
|
|
11369
|
+
files = await (0, import_promises.readdir)(path26, this._rdOptions);
|
|
11171
11370
|
} catch (error) {
|
|
11172
11371
|
this._onError(error);
|
|
11173
11372
|
}
|
|
11174
|
-
return { files, depth, path:
|
|
11373
|
+
return { files, depth, path: path26 };
|
|
11175
11374
|
}
|
|
11176
|
-
async _formatEntry(dirent,
|
|
11375
|
+
async _formatEntry(dirent, path26) {
|
|
11177
11376
|
let entry;
|
|
11178
11377
|
const basename5 = this._isDirent ? dirent.name : dirent;
|
|
11179
11378
|
try {
|
|
11180
|
-
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(
|
|
11379
|
+
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path26, basename5));
|
|
11181
11380
|
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename5 };
|
|
11182
11381
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
11183
11382
|
} catch (err) {
|
|
@@ -11577,16 +11776,16 @@ var delFromSet = (main2, prop, item) => {
|
|
|
11577
11776
|
};
|
|
11578
11777
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
11579
11778
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
11580
|
-
function createFsWatchInstance(
|
|
11779
|
+
function createFsWatchInstance(path26, options, listener, errHandler, emitRaw) {
|
|
11581
11780
|
const handleEvent = (rawEvent, evPath) => {
|
|
11582
|
-
listener(
|
|
11583
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
11584
|
-
if (evPath &&
|
|
11585
|
-
fsWatchBroadcast(sp.resolve(
|
|
11781
|
+
listener(path26);
|
|
11782
|
+
emitRaw(rawEvent, evPath, { watchedPath: path26 });
|
|
11783
|
+
if (evPath && path26 !== evPath) {
|
|
11784
|
+
fsWatchBroadcast(sp.resolve(path26, evPath), KEY_LISTENERS, sp.join(path26, evPath));
|
|
11586
11785
|
}
|
|
11587
11786
|
};
|
|
11588
11787
|
try {
|
|
11589
|
-
return (0, import_node_fs.watch)(
|
|
11788
|
+
return (0, import_node_fs.watch)(path26, {
|
|
11590
11789
|
persistent: options.persistent
|
|
11591
11790
|
}, handleEvent);
|
|
11592
11791
|
} catch (error) {
|
|
@@ -11602,12 +11801,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
11602
11801
|
listener(val1, val2, val3);
|
|
11603
11802
|
});
|
|
11604
11803
|
};
|
|
11605
|
-
var setFsWatchListener = (
|
|
11804
|
+
var setFsWatchListener = (path26, fullPath, options, handlers) => {
|
|
11606
11805
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
11607
11806
|
let cont = FsWatchInstances.get(fullPath);
|
|
11608
11807
|
let watcher;
|
|
11609
11808
|
if (!options.persistent) {
|
|
11610
|
-
watcher = createFsWatchInstance(
|
|
11809
|
+
watcher = createFsWatchInstance(path26, options, listener, errHandler, rawEmitter);
|
|
11611
11810
|
if (!watcher)
|
|
11612
11811
|
return;
|
|
11613
11812
|
return watcher.close.bind(watcher);
|
|
@@ -11618,7 +11817,7 @@ var setFsWatchListener = (path25, fullPath, options, handlers) => {
|
|
|
11618
11817
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
11619
11818
|
} else {
|
|
11620
11819
|
watcher = createFsWatchInstance(
|
|
11621
|
-
|
|
11820
|
+
path26,
|
|
11622
11821
|
options,
|
|
11623
11822
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
11624
11823
|
errHandler,
|
|
@@ -11633,7 +11832,7 @@ var setFsWatchListener = (path25, fullPath, options, handlers) => {
|
|
|
11633
11832
|
cont.watcherUnusable = true;
|
|
11634
11833
|
if (isWindows && error.code === "EPERM") {
|
|
11635
11834
|
try {
|
|
11636
|
-
const fd = await (0, import_promises2.open)(
|
|
11835
|
+
const fd = await (0, import_promises2.open)(path26, "r");
|
|
11637
11836
|
await fd.close();
|
|
11638
11837
|
broadcastErr(error);
|
|
11639
11838
|
} catch (err) {
|
|
@@ -11664,7 +11863,7 @@ var setFsWatchListener = (path25, fullPath, options, handlers) => {
|
|
|
11664
11863
|
};
|
|
11665
11864
|
};
|
|
11666
11865
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
11667
|
-
var setFsWatchFileListener = (
|
|
11866
|
+
var setFsWatchFileListener = (path26, fullPath, options, handlers) => {
|
|
11668
11867
|
const { listener, rawEmitter } = handlers;
|
|
11669
11868
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
11670
11869
|
const copts = cont && cont.options;
|
|
@@ -11686,7 +11885,7 @@ var setFsWatchFileListener = (path25, fullPath, options, handlers) => {
|
|
|
11686
11885
|
});
|
|
11687
11886
|
const currmtime = curr.mtimeMs;
|
|
11688
11887
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
11689
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
11888
|
+
foreach(cont.listeners, (listener2) => listener2(path26, curr));
|
|
11690
11889
|
}
|
|
11691
11890
|
})
|
|
11692
11891
|
};
|
|
@@ -11716,13 +11915,13 @@ var NodeFsHandler = class {
|
|
|
11716
11915
|
* @param listener on fs change
|
|
11717
11916
|
* @returns closer for the watcher instance
|
|
11718
11917
|
*/
|
|
11719
|
-
_watchWithNodeFs(
|
|
11918
|
+
_watchWithNodeFs(path26, listener) {
|
|
11720
11919
|
const opts = this.fsw.options;
|
|
11721
|
-
const directory = sp.dirname(
|
|
11722
|
-
const basename5 = sp.basename(
|
|
11920
|
+
const directory = sp.dirname(path26);
|
|
11921
|
+
const basename5 = sp.basename(path26);
|
|
11723
11922
|
const parent = this.fsw._getWatchedDir(directory);
|
|
11724
11923
|
parent.add(basename5);
|
|
11725
|
-
const absolutePath = sp.resolve(
|
|
11924
|
+
const absolutePath = sp.resolve(path26);
|
|
11726
11925
|
const options = {
|
|
11727
11926
|
persistent: opts.persistent
|
|
11728
11927
|
};
|
|
@@ -11732,12 +11931,12 @@ var NodeFsHandler = class {
|
|
|
11732
11931
|
if (opts.usePolling) {
|
|
11733
11932
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
11734
11933
|
options.interval = enableBin && isBinaryPath(basename5) ? opts.binaryInterval : opts.interval;
|
|
11735
|
-
closer = setFsWatchFileListener(
|
|
11934
|
+
closer = setFsWatchFileListener(path26, absolutePath, options, {
|
|
11736
11935
|
listener,
|
|
11737
11936
|
rawEmitter: this.fsw._emitRaw
|
|
11738
11937
|
});
|
|
11739
11938
|
} else {
|
|
11740
|
-
closer = setFsWatchListener(
|
|
11939
|
+
closer = setFsWatchListener(path26, absolutePath, options, {
|
|
11741
11940
|
listener,
|
|
11742
11941
|
errHandler: this._boundHandleError,
|
|
11743
11942
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -11759,7 +11958,7 @@ var NodeFsHandler = class {
|
|
|
11759
11958
|
let prevStats = stats;
|
|
11760
11959
|
if (parent.has(basename5))
|
|
11761
11960
|
return;
|
|
11762
|
-
const listener = async (
|
|
11961
|
+
const listener = async (path26, newStats) => {
|
|
11763
11962
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
11764
11963
|
return;
|
|
11765
11964
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -11773,11 +11972,11 @@ var NodeFsHandler = class {
|
|
|
11773
11972
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
11774
11973
|
}
|
|
11775
11974
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
11776
|
-
this.fsw._closeFile(
|
|
11975
|
+
this.fsw._closeFile(path26);
|
|
11777
11976
|
prevStats = newStats2;
|
|
11778
11977
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
11779
11978
|
if (closer2)
|
|
11780
|
-
this.fsw._addPathCloser(
|
|
11979
|
+
this.fsw._addPathCloser(path26, closer2);
|
|
11781
11980
|
} else {
|
|
11782
11981
|
prevStats = newStats2;
|
|
11783
11982
|
}
|
|
@@ -11809,7 +12008,7 @@ var NodeFsHandler = class {
|
|
|
11809
12008
|
* @param item basename of this item
|
|
11810
12009
|
* @returns true if no more processing is needed for this entry.
|
|
11811
12010
|
*/
|
|
11812
|
-
async _handleSymlink(entry, directory,
|
|
12011
|
+
async _handleSymlink(entry, directory, path26, item) {
|
|
11813
12012
|
if (this.fsw.closed) {
|
|
11814
12013
|
return;
|
|
11815
12014
|
}
|
|
@@ -11819,7 +12018,7 @@ var NodeFsHandler = class {
|
|
|
11819
12018
|
this.fsw._incrReadyCount();
|
|
11820
12019
|
let linkPath;
|
|
11821
12020
|
try {
|
|
11822
|
-
linkPath = await (0, import_promises2.realpath)(
|
|
12021
|
+
linkPath = await (0, import_promises2.realpath)(path26);
|
|
11823
12022
|
} catch (e) {
|
|
11824
12023
|
this.fsw._emitReady();
|
|
11825
12024
|
return true;
|
|
@@ -11829,12 +12028,12 @@ var NodeFsHandler = class {
|
|
|
11829
12028
|
if (dir.has(item)) {
|
|
11830
12029
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
11831
12030
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
11832
|
-
this.fsw._emit(EV.CHANGE,
|
|
12031
|
+
this.fsw._emit(EV.CHANGE, path26, entry.stats);
|
|
11833
12032
|
}
|
|
11834
12033
|
} else {
|
|
11835
12034
|
dir.add(item);
|
|
11836
12035
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
11837
|
-
this.fsw._emit(EV.ADD,
|
|
12036
|
+
this.fsw._emit(EV.ADD, path26, entry.stats);
|
|
11838
12037
|
}
|
|
11839
12038
|
this.fsw._emitReady();
|
|
11840
12039
|
return true;
|
|
@@ -11864,9 +12063,9 @@ var NodeFsHandler = class {
|
|
|
11864
12063
|
return;
|
|
11865
12064
|
}
|
|
11866
12065
|
const item = entry.path;
|
|
11867
|
-
let
|
|
12066
|
+
let path26 = sp.join(directory, item);
|
|
11868
12067
|
current.add(item);
|
|
11869
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
12068
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path26, item)) {
|
|
11870
12069
|
return;
|
|
11871
12070
|
}
|
|
11872
12071
|
if (this.fsw.closed) {
|
|
@@ -11875,8 +12074,8 @@ var NodeFsHandler = class {
|
|
|
11875
12074
|
}
|
|
11876
12075
|
if (item === target || !target && !previous.has(item)) {
|
|
11877
12076
|
this.fsw._incrReadyCount();
|
|
11878
|
-
|
|
11879
|
-
this._addToNodeFs(
|
|
12077
|
+
path26 = sp.join(dir, sp.relative(dir, path26));
|
|
12078
|
+
this._addToNodeFs(path26, initialAdd, wh, depth + 1);
|
|
11880
12079
|
}
|
|
11881
12080
|
}).on(EV.ERROR, this._boundHandleError);
|
|
11882
12081
|
return new Promise((resolve15, reject) => {
|
|
@@ -11945,13 +12144,13 @@ var NodeFsHandler = class {
|
|
|
11945
12144
|
* @param depth Child path actually targeted for watch
|
|
11946
12145
|
* @param target Child path actually targeted for watch
|
|
11947
12146
|
*/
|
|
11948
|
-
async _addToNodeFs(
|
|
12147
|
+
async _addToNodeFs(path26, initialAdd, priorWh, depth, target) {
|
|
11949
12148
|
const ready = this.fsw._emitReady;
|
|
11950
|
-
if (this.fsw._isIgnored(
|
|
12149
|
+
if (this.fsw._isIgnored(path26) || this.fsw.closed) {
|
|
11951
12150
|
ready();
|
|
11952
12151
|
return false;
|
|
11953
12152
|
}
|
|
11954
|
-
const wh = this.fsw._getWatchHelpers(
|
|
12153
|
+
const wh = this.fsw._getWatchHelpers(path26);
|
|
11955
12154
|
if (priorWh) {
|
|
11956
12155
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
11957
12156
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -11967,8 +12166,8 @@ var NodeFsHandler = class {
|
|
|
11967
12166
|
const follow = this.fsw.options.followSymlinks;
|
|
11968
12167
|
let closer;
|
|
11969
12168
|
if (stats.isDirectory()) {
|
|
11970
|
-
const absPath = sp.resolve(
|
|
11971
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
12169
|
+
const absPath = sp.resolve(path26);
|
|
12170
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path26) : path26;
|
|
11972
12171
|
if (this.fsw.closed)
|
|
11973
12172
|
return;
|
|
11974
12173
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -11978,29 +12177,29 @@ var NodeFsHandler = class {
|
|
|
11978
12177
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
11979
12178
|
}
|
|
11980
12179
|
} else if (stats.isSymbolicLink()) {
|
|
11981
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
12180
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path26) : path26;
|
|
11982
12181
|
if (this.fsw.closed)
|
|
11983
12182
|
return;
|
|
11984
12183
|
const parent = sp.dirname(wh.watchPath);
|
|
11985
12184
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
11986
12185
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
11987
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
12186
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path26, wh, targetPath);
|
|
11988
12187
|
if (this.fsw.closed)
|
|
11989
12188
|
return;
|
|
11990
12189
|
if (targetPath !== void 0) {
|
|
11991
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
12190
|
+
this.fsw._symlinkPaths.set(sp.resolve(path26), targetPath);
|
|
11992
12191
|
}
|
|
11993
12192
|
} else {
|
|
11994
12193
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
11995
12194
|
}
|
|
11996
12195
|
ready();
|
|
11997
12196
|
if (closer)
|
|
11998
|
-
this.fsw._addPathCloser(
|
|
12197
|
+
this.fsw._addPathCloser(path26, closer);
|
|
11999
12198
|
return false;
|
|
12000
12199
|
} catch (error) {
|
|
12001
12200
|
if (this.fsw._handleError(error)) {
|
|
12002
12201
|
ready();
|
|
12003
|
-
return
|
|
12202
|
+
return path26;
|
|
12004
12203
|
}
|
|
12005
12204
|
}
|
|
12006
12205
|
}
|
|
@@ -12032,35 +12231,35 @@ function createPattern(matcher) {
|
|
|
12032
12231
|
if (matcher.path === string)
|
|
12033
12232
|
return true;
|
|
12034
12233
|
if (matcher.recursive) {
|
|
12035
|
-
const
|
|
12036
|
-
if (!
|
|
12234
|
+
const relative11 = sp2.relative(matcher.path, string);
|
|
12235
|
+
if (!relative11) {
|
|
12037
12236
|
return false;
|
|
12038
12237
|
}
|
|
12039
|
-
return !
|
|
12238
|
+
return !relative11.startsWith("..") && !sp2.isAbsolute(relative11);
|
|
12040
12239
|
}
|
|
12041
12240
|
return false;
|
|
12042
12241
|
};
|
|
12043
12242
|
}
|
|
12044
12243
|
return () => false;
|
|
12045
12244
|
}
|
|
12046
|
-
function normalizePath2(
|
|
12047
|
-
if (typeof
|
|
12245
|
+
function normalizePath2(path26) {
|
|
12246
|
+
if (typeof path26 !== "string")
|
|
12048
12247
|
throw new Error("string expected");
|
|
12049
|
-
|
|
12050
|
-
|
|
12248
|
+
path26 = sp2.normalize(path26);
|
|
12249
|
+
path26 = path26.replace(/\\/g, "/");
|
|
12051
12250
|
let prepend = false;
|
|
12052
|
-
if (
|
|
12251
|
+
if (path26.startsWith("//"))
|
|
12053
12252
|
prepend = true;
|
|
12054
|
-
|
|
12253
|
+
path26 = path26.replace(DOUBLE_SLASH_RE, "/");
|
|
12055
12254
|
if (prepend)
|
|
12056
|
-
|
|
12057
|
-
return
|
|
12255
|
+
path26 = "/" + path26;
|
|
12256
|
+
return path26;
|
|
12058
12257
|
}
|
|
12059
12258
|
function matchPatterns(patterns, testString, stats) {
|
|
12060
|
-
const
|
|
12259
|
+
const path26 = normalizePath2(testString);
|
|
12061
12260
|
for (let index = 0; index < patterns.length; index++) {
|
|
12062
12261
|
const pattern = patterns[index];
|
|
12063
|
-
if (pattern(
|
|
12262
|
+
if (pattern(path26, stats)) {
|
|
12064
12263
|
return true;
|
|
12065
12264
|
}
|
|
12066
12265
|
}
|
|
@@ -12098,19 +12297,19 @@ var toUnix = (string) => {
|
|
|
12098
12297
|
}
|
|
12099
12298
|
return str;
|
|
12100
12299
|
};
|
|
12101
|
-
var normalizePathToUnix = (
|
|
12102
|
-
var normalizeIgnored = (cwd = "") => (
|
|
12103
|
-
if (typeof
|
|
12104
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
12300
|
+
var normalizePathToUnix = (path26) => toUnix(sp2.normalize(toUnix(path26)));
|
|
12301
|
+
var normalizeIgnored = (cwd = "") => (path26) => {
|
|
12302
|
+
if (typeof path26 === "string") {
|
|
12303
|
+
return normalizePathToUnix(sp2.isAbsolute(path26) ? path26 : sp2.join(cwd, path26));
|
|
12105
12304
|
} else {
|
|
12106
|
-
return
|
|
12305
|
+
return path26;
|
|
12107
12306
|
}
|
|
12108
12307
|
};
|
|
12109
|
-
var getAbsolutePath = (
|
|
12110
|
-
if (sp2.isAbsolute(
|
|
12111
|
-
return
|
|
12308
|
+
var getAbsolutePath = (path26, cwd) => {
|
|
12309
|
+
if (sp2.isAbsolute(path26)) {
|
|
12310
|
+
return path26;
|
|
12112
12311
|
}
|
|
12113
|
-
return sp2.join(cwd,
|
|
12312
|
+
return sp2.join(cwd, path26);
|
|
12114
12313
|
};
|
|
12115
12314
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
12116
12315
|
var DirEntry = class {
|
|
@@ -12175,10 +12374,10 @@ var WatchHelper = class {
|
|
|
12175
12374
|
dirParts;
|
|
12176
12375
|
followSymlinks;
|
|
12177
12376
|
statMethod;
|
|
12178
|
-
constructor(
|
|
12377
|
+
constructor(path26, follow, fsw) {
|
|
12179
12378
|
this.fsw = fsw;
|
|
12180
|
-
const watchPath =
|
|
12181
|
-
this.path =
|
|
12379
|
+
const watchPath = path26;
|
|
12380
|
+
this.path = path26 = path26.replace(REPLACER_RE, "");
|
|
12182
12381
|
this.watchPath = watchPath;
|
|
12183
12382
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
12184
12383
|
this.dirParts = [];
|
|
@@ -12318,20 +12517,20 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
12318
12517
|
this._closePromise = void 0;
|
|
12319
12518
|
let paths = unifyPaths(paths_);
|
|
12320
12519
|
if (cwd) {
|
|
12321
|
-
paths = paths.map((
|
|
12322
|
-
const absPath = getAbsolutePath(
|
|
12520
|
+
paths = paths.map((path26) => {
|
|
12521
|
+
const absPath = getAbsolutePath(path26, cwd);
|
|
12323
12522
|
return absPath;
|
|
12324
12523
|
});
|
|
12325
12524
|
}
|
|
12326
|
-
paths.forEach((
|
|
12327
|
-
this._removeIgnoredPath(
|
|
12525
|
+
paths.forEach((path26) => {
|
|
12526
|
+
this._removeIgnoredPath(path26);
|
|
12328
12527
|
});
|
|
12329
12528
|
this._userIgnored = void 0;
|
|
12330
12529
|
if (!this._readyCount)
|
|
12331
12530
|
this._readyCount = 0;
|
|
12332
12531
|
this._readyCount += paths.length;
|
|
12333
|
-
Promise.all(paths.map(async (
|
|
12334
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
12532
|
+
Promise.all(paths.map(async (path26) => {
|
|
12533
|
+
const res = await this._nodeFsHandler._addToNodeFs(path26, !_internal, void 0, 0, _origAdd);
|
|
12335
12534
|
if (res)
|
|
12336
12535
|
this._emitReady();
|
|
12337
12536
|
return res;
|
|
@@ -12353,17 +12552,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
12353
12552
|
return this;
|
|
12354
12553
|
const paths = unifyPaths(paths_);
|
|
12355
12554
|
const { cwd } = this.options;
|
|
12356
|
-
paths.forEach((
|
|
12357
|
-
if (!sp2.isAbsolute(
|
|
12555
|
+
paths.forEach((path26) => {
|
|
12556
|
+
if (!sp2.isAbsolute(path26) && !this._closers.has(path26)) {
|
|
12358
12557
|
if (cwd)
|
|
12359
|
-
|
|
12360
|
-
|
|
12558
|
+
path26 = sp2.join(cwd, path26);
|
|
12559
|
+
path26 = sp2.resolve(path26);
|
|
12361
12560
|
}
|
|
12362
|
-
this._closePath(
|
|
12363
|
-
this._addIgnoredPath(
|
|
12364
|
-
if (this._watched.has(
|
|
12561
|
+
this._closePath(path26);
|
|
12562
|
+
this._addIgnoredPath(path26);
|
|
12563
|
+
if (this._watched.has(path26)) {
|
|
12365
12564
|
this._addIgnoredPath({
|
|
12366
|
-
path:
|
|
12565
|
+
path: path26,
|
|
12367
12566
|
recursive: true
|
|
12368
12567
|
});
|
|
12369
12568
|
}
|
|
@@ -12427,38 +12626,38 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
12427
12626
|
* @param stats arguments to be passed with event
|
|
12428
12627
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
12429
12628
|
*/
|
|
12430
|
-
async _emit(event,
|
|
12629
|
+
async _emit(event, path26, stats) {
|
|
12431
12630
|
if (this.closed)
|
|
12432
12631
|
return;
|
|
12433
12632
|
const opts = this.options;
|
|
12434
12633
|
if (isWindows)
|
|
12435
|
-
|
|
12634
|
+
path26 = sp2.normalize(path26);
|
|
12436
12635
|
if (opts.cwd)
|
|
12437
|
-
|
|
12438
|
-
const args = [
|
|
12636
|
+
path26 = sp2.relative(opts.cwd, path26);
|
|
12637
|
+
const args = [path26];
|
|
12439
12638
|
if (stats != null)
|
|
12440
12639
|
args.push(stats);
|
|
12441
12640
|
const awf = opts.awaitWriteFinish;
|
|
12442
12641
|
let pw;
|
|
12443
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
12642
|
+
if (awf && (pw = this._pendingWrites.get(path26))) {
|
|
12444
12643
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
12445
12644
|
return this;
|
|
12446
12645
|
}
|
|
12447
12646
|
if (opts.atomic) {
|
|
12448
12647
|
if (event === EVENTS.UNLINK) {
|
|
12449
|
-
this._pendingUnlinks.set(
|
|
12648
|
+
this._pendingUnlinks.set(path26, [event, ...args]);
|
|
12450
12649
|
setTimeout(() => {
|
|
12451
|
-
this._pendingUnlinks.forEach((entry,
|
|
12650
|
+
this._pendingUnlinks.forEach((entry, path27) => {
|
|
12452
12651
|
this.emit(...entry);
|
|
12453
12652
|
this.emit(EVENTS.ALL, ...entry);
|
|
12454
|
-
this._pendingUnlinks.delete(
|
|
12653
|
+
this._pendingUnlinks.delete(path27);
|
|
12455
12654
|
});
|
|
12456
12655
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
12457
12656
|
return this;
|
|
12458
12657
|
}
|
|
12459
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
12658
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path26)) {
|
|
12460
12659
|
event = EVENTS.CHANGE;
|
|
12461
|
-
this._pendingUnlinks.delete(
|
|
12660
|
+
this._pendingUnlinks.delete(path26);
|
|
12462
12661
|
}
|
|
12463
12662
|
}
|
|
12464
12663
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -12476,16 +12675,16 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
12476
12675
|
this.emitWithAll(event, args);
|
|
12477
12676
|
}
|
|
12478
12677
|
};
|
|
12479
|
-
this._awaitWriteFinish(
|
|
12678
|
+
this._awaitWriteFinish(path26, awf.stabilityThreshold, event, awfEmit);
|
|
12480
12679
|
return this;
|
|
12481
12680
|
}
|
|
12482
12681
|
if (event === EVENTS.CHANGE) {
|
|
12483
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
12682
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path26, 50);
|
|
12484
12683
|
if (isThrottled)
|
|
12485
12684
|
return this;
|
|
12486
12685
|
}
|
|
12487
12686
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
12488
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
12687
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path26) : path26;
|
|
12489
12688
|
let stats2;
|
|
12490
12689
|
try {
|
|
12491
12690
|
stats2 = await (0, import_promises3.stat)(fullPath);
|
|
@@ -12516,23 +12715,23 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
12516
12715
|
* @param timeout duration of time to suppress duplicate actions
|
|
12517
12716
|
* @returns tracking object or false if action should be suppressed
|
|
12518
12717
|
*/
|
|
12519
|
-
_throttle(actionType,
|
|
12718
|
+
_throttle(actionType, path26, timeout) {
|
|
12520
12719
|
if (!this._throttled.has(actionType)) {
|
|
12521
12720
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
12522
12721
|
}
|
|
12523
12722
|
const action = this._throttled.get(actionType);
|
|
12524
12723
|
if (!action)
|
|
12525
12724
|
throw new Error("invalid throttle");
|
|
12526
|
-
const actionPath = action.get(
|
|
12725
|
+
const actionPath = action.get(path26);
|
|
12527
12726
|
if (actionPath) {
|
|
12528
12727
|
actionPath.count++;
|
|
12529
12728
|
return false;
|
|
12530
12729
|
}
|
|
12531
12730
|
let timeoutObject;
|
|
12532
12731
|
const clear = () => {
|
|
12533
|
-
const item = action.get(
|
|
12732
|
+
const item = action.get(path26);
|
|
12534
12733
|
const count = item ? item.count : 0;
|
|
12535
|
-
action.delete(
|
|
12734
|
+
action.delete(path26);
|
|
12536
12735
|
clearTimeout(timeoutObject);
|
|
12537
12736
|
if (item)
|
|
12538
12737
|
clearTimeout(item.timeoutObject);
|
|
@@ -12540,7 +12739,7 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
12540
12739
|
};
|
|
12541
12740
|
timeoutObject = setTimeout(clear, timeout);
|
|
12542
12741
|
const thr = { timeoutObject, clear, count: 0 };
|
|
12543
|
-
action.set(
|
|
12742
|
+
action.set(path26, thr);
|
|
12544
12743
|
return thr;
|
|
12545
12744
|
}
|
|
12546
12745
|
_incrReadyCount() {
|
|
@@ -12554,44 +12753,44 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
12554
12753
|
* @param event
|
|
12555
12754
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
12556
12755
|
*/
|
|
12557
|
-
_awaitWriteFinish(
|
|
12756
|
+
_awaitWriteFinish(path26, threshold, event, awfEmit) {
|
|
12558
12757
|
const awf = this.options.awaitWriteFinish;
|
|
12559
12758
|
if (typeof awf !== "object")
|
|
12560
12759
|
return;
|
|
12561
12760
|
const pollInterval = awf.pollInterval;
|
|
12562
12761
|
let timeoutHandler;
|
|
12563
|
-
let fullPath =
|
|
12564
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
12565
|
-
fullPath = sp2.join(this.options.cwd,
|
|
12762
|
+
let fullPath = path26;
|
|
12763
|
+
if (this.options.cwd && !sp2.isAbsolute(path26)) {
|
|
12764
|
+
fullPath = sp2.join(this.options.cwd, path26);
|
|
12566
12765
|
}
|
|
12567
12766
|
const now = /* @__PURE__ */ new Date();
|
|
12568
12767
|
const writes = this._pendingWrites;
|
|
12569
12768
|
function awaitWriteFinishFn(prevStat) {
|
|
12570
12769
|
(0, import_node_fs2.stat)(fullPath, (err, curStat) => {
|
|
12571
|
-
if (err || !writes.has(
|
|
12770
|
+
if (err || !writes.has(path26)) {
|
|
12572
12771
|
if (err && err.code !== "ENOENT")
|
|
12573
12772
|
awfEmit(err);
|
|
12574
12773
|
return;
|
|
12575
12774
|
}
|
|
12576
12775
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
12577
12776
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
12578
|
-
writes.get(
|
|
12777
|
+
writes.get(path26).lastChange = now2;
|
|
12579
12778
|
}
|
|
12580
|
-
const pw = writes.get(
|
|
12779
|
+
const pw = writes.get(path26);
|
|
12581
12780
|
const df = now2 - pw.lastChange;
|
|
12582
12781
|
if (df >= threshold) {
|
|
12583
|
-
writes.delete(
|
|
12782
|
+
writes.delete(path26);
|
|
12584
12783
|
awfEmit(void 0, curStat);
|
|
12585
12784
|
} else {
|
|
12586
12785
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
12587
12786
|
}
|
|
12588
12787
|
});
|
|
12589
12788
|
}
|
|
12590
|
-
if (!writes.has(
|
|
12591
|
-
writes.set(
|
|
12789
|
+
if (!writes.has(path26)) {
|
|
12790
|
+
writes.set(path26, {
|
|
12592
12791
|
lastChange: now,
|
|
12593
12792
|
cancelWait: () => {
|
|
12594
|
-
writes.delete(
|
|
12793
|
+
writes.delete(path26);
|
|
12595
12794
|
clearTimeout(timeoutHandler);
|
|
12596
12795
|
return event;
|
|
12597
12796
|
}
|
|
@@ -12602,8 +12801,8 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
12602
12801
|
/**
|
|
12603
12802
|
* Determines whether user has asked to ignore this path.
|
|
12604
12803
|
*/
|
|
12605
|
-
_isIgnored(
|
|
12606
|
-
if (this.options.atomic && DOT_RE.test(
|
|
12804
|
+
_isIgnored(path26, stats) {
|
|
12805
|
+
if (this.options.atomic && DOT_RE.test(path26))
|
|
12607
12806
|
return true;
|
|
12608
12807
|
if (!this._userIgnored) {
|
|
12609
12808
|
const { cwd } = this.options;
|
|
@@ -12613,17 +12812,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
12613
12812
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
12614
12813
|
this._userIgnored = anymatch(list, void 0);
|
|
12615
12814
|
}
|
|
12616
|
-
return this._userIgnored(
|
|
12815
|
+
return this._userIgnored(path26, stats);
|
|
12617
12816
|
}
|
|
12618
|
-
_isntIgnored(
|
|
12619
|
-
return !this._isIgnored(
|
|
12817
|
+
_isntIgnored(path26, stat4) {
|
|
12818
|
+
return !this._isIgnored(path26, stat4);
|
|
12620
12819
|
}
|
|
12621
12820
|
/**
|
|
12622
12821
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
12623
12822
|
* @param path file or directory pattern being watched
|
|
12624
12823
|
*/
|
|
12625
|
-
_getWatchHelpers(
|
|
12626
|
-
return new WatchHelper(
|
|
12824
|
+
_getWatchHelpers(path26) {
|
|
12825
|
+
return new WatchHelper(path26, this.options.followSymlinks, this);
|
|
12627
12826
|
}
|
|
12628
12827
|
// Directory helpers
|
|
12629
12828
|
// -----------------
|
|
@@ -12655,63 +12854,63 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
12655
12854
|
* @param item base path of item/directory
|
|
12656
12855
|
*/
|
|
12657
12856
|
_remove(directory, item, isDirectory) {
|
|
12658
|
-
const
|
|
12659
|
-
const fullPath = sp2.resolve(
|
|
12660
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
12661
|
-
if (!this._throttle("remove",
|
|
12857
|
+
const path26 = sp2.join(directory, item);
|
|
12858
|
+
const fullPath = sp2.resolve(path26);
|
|
12859
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path26) || this._watched.has(fullPath);
|
|
12860
|
+
if (!this._throttle("remove", path26, 100))
|
|
12662
12861
|
return;
|
|
12663
12862
|
if (!isDirectory && this._watched.size === 1) {
|
|
12664
12863
|
this.add(directory, item, true);
|
|
12665
12864
|
}
|
|
12666
|
-
const wp = this._getWatchedDir(
|
|
12865
|
+
const wp = this._getWatchedDir(path26);
|
|
12667
12866
|
const nestedDirectoryChildren = wp.getChildren();
|
|
12668
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
12867
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path26, nested));
|
|
12669
12868
|
const parent = this._getWatchedDir(directory);
|
|
12670
12869
|
const wasTracked = parent.has(item);
|
|
12671
12870
|
parent.remove(item);
|
|
12672
12871
|
if (this._symlinkPaths.has(fullPath)) {
|
|
12673
12872
|
this._symlinkPaths.delete(fullPath);
|
|
12674
12873
|
}
|
|
12675
|
-
let relPath =
|
|
12874
|
+
let relPath = path26;
|
|
12676
12875
|
if (this.options.cwd)
|
|
12677
|
-
relPath = sp2.relative(this.options.cwd,
|
|
12876
|
+
relPath = sp2.relative(this.options.cwd, path26);
|
|
12678
12877
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
12679
12878
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
12680
12879
|
if (event === EVENTS.ADD)
|
|
12681
12880
|
return;
|
|
12682
12881
|
}
|
|
12683
|
-
this._watched.delete(
|
|
12882
|
+
this._watched.delete(path26);
|
|
12684
12883
|
this._watched.delete(fullPath);
|
|
12685
12884
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
12686
|
-
if (wasTracked && !this._isIgnored(
|
|
12687
|
-
this._emit(eventName,
|
|
12688
|
-
this._closePath(
|
|
12885
|
+
if (wasTracked && !this._isIgnored(path26))
|
|
12886
|
+
this._emit(eventName, path26);
|
|
12887
|
+
this._closePath(path26);
|
|
12689
12888
|
}
|
|
12690
12889
|
/**
|
|
12691
12890
|
* Closes all watchers for a path
|
|
12692
12891
|
*/
|
|
12693
|
-
_closePath(
|
|
12694
|
-
this._closeFile(
|
|
12695
|
-
const dir = sp2.dirname(
|
|
12696
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
12892
|
+
_closePath(path26) {
|
|
12893
|
+
this._closeFile(path26);
|
|
12894
|
+
const dir = sp2.dirname(path26);
|
|
12895
|
+
this._getWatchedDir(dir).remove(sp2.basename(path26));
|
|
12697
12896
|
}
|
|
12698
12897
|
/**
|
|
12699
12898
|
* Closes only file-specific watchers
|
|
12700
12899
|
*/
|
|
12701
|
-
_closeFile(
|
|
12702
|
-
const closers = this._closers.get(
|
|
12900
|
+
_closeFile(path26) {
|
|
12901
|
+
const closers = this._closers.get(path26);
|
|
12703
12902
|
if (!closers)
|
|
12704
12903
|
return;
|
|
12705
12904
|
closers.forEach((closer) => closer());
|
|
12706
|
-
this._closers.delete(
|
|
12905
|
+
this._closers.delete(path26);
|
|
12707
12906
|
}
|
|
12708
|
-
_addPathCloser(
|
|
12907
|
+
_addPathCloser(path26, closer) {
|
|
12709
12908
|
if (!closer)
|
|
12710
12909
|
return;
|
|
12711
|
-
let list = this._closers.get(
|
|
12910
|
+
let list = this._closers.get(path26);
|
|
12712
12911
|
if (!list) {
|
|
12713
12912
|
list = [];
|
|
12714
|
-
this._closers.set(
|
|
12913
|
+
this._closers.set(path26, list);
|
|
12715
12914
|
}
|
|
12716
12915
|
list.push(closer);
|
|
12717
12916
|
}
|
|
@@ -12741,7 +12940,7 @@ function watch(paths, options = {}) {
|
|
|
12741
12940
|
var chokidar_default = { watch, FSWatcher };
|
|
12742
12941
|
|
|
12743
12942
|
// src/watcher/file-watcher.ts
|
|
12744
|
-
var
|
|
12943
|
+
var path21 = __toESM(require("path"), 1);
|
|
12745
12944
|
var FileWatcher = class {
|
|
12746
12945
|
watcher = null;
|
|
12747
12946
|
projectRoot;
|
|
@@ -12767,15 +12966,15 @@ var FileWatcher = class {
|
|
|
12767
12966
|
const watchTargets = this.configPath ? [this.projectRoot, this.configPath] : this.projectRoot;
|
|
12768
12967
|
this.watcher = chokidar_default.watch(watchTargets, {
|
|
12769
12968
|
ignored: (filePath) => {
|
|
12770
|
-
const relativePath =
|
|
12969
|
+
const relativePath = path21.relative(this.projectRoot, filePath);
|
|
12771
12970
|
if (!relativePath) return false;
|
|
12772
12971
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
12773
12972
|
return false;
|
|
12774
12973
|
}
|
|
12775
|
-
if (hasFilteredPathSegment(relativePath,
|
|
12974
|
+
if (hasFilteredPathSegment(relativePath, path21.sep)) {
|
|
12776
12975
|
return true;
|
|
12777
12976
|
}
|
|
12778
|
-
if (isRestrictedDirectory(relativePath,
|
|
12977
|
+
if (isRestrictedDirectory(relativePath, path21.sep)) {
|
|
12779
12978
|
return true;
|
|
12780
12979
|
}
|
|
12781
12980
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -12821,24 +13020,24 @@ var FileWatcher = class {
|
|
|
12821
13020
|
this.scheduleFlush();
|
|
12822
13021
|
}
|
|
12823
13022
|
isProjectConfigPath(filePath) {
|
|
12824
|
-
const relativePath =
|
|
12825
|
-
const normalizedRelativePath =
|
|
13023
|
+
const relativePath = path21.relative(this.projectRoot, filePath);
|
|
13024
|
+
const normalizedRelativePath = path21.normalize(relativePath);
|
|
12826
13025
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
12827
13026
|
}
|
|
12828
13027
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
12829
|
-
const normalizedRelativePath =
|
|
13028
|
+
const normalizedRelativePath = path21.normalize(relativePath);
|
|
12830
13029
|
return this.getProjectConfigRelativePaths().some(
|
|
12831
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
13030
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path21.sep}`)
|
|
12832
13031
|
);
|
|
12833
13032
|
}
|
|
12834
13033
|
getProjectConfigRelativePaths() {
|
|
12835
13034
|
if (this.configPath) {
|
|
12836
|
-
return [
|
|
13035
|
+
return [path21.normalize(path21.relative(this.projectRoot, this.configPath))];
|
|
12837
13036
|
}
|
|
12838
13037
|
return [
|
|
12839
13038
|
resolveProjectConfigPath(this.projectRoot, this.host),
|
|
12840
13039
|
resolveWritableProjectConfigPath(this.projectRoot, this.host)
|
|
12841
|
-
].map((configPath) =>
|
|
13040
|
+
].map((configPath) => path21.normalize(path21.relative(this.projectRoot, configPath)));
|
|
12842
13041
|
}
|
|
12843
13042
|
scheduleFlush() {
|
|
12844
13043
|
if (this.debounceTimer) {
|
|
@@ -12853,7 +13052,7 @@ var FileWatcher = class {
|
|
|
12853
13052
|
return;
|
|
12854
13053
|
}
|
|
12855
13054
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
12856
|
-
([
|
|
13055
|
+
([path26, type]) => ({ path: path26, type })
|
|
12857
13056
|
);
|
|
12858
13057
|
this.pendingChanges.clear();
|
|
12859
13058
|
try {
|
|
@@ -12880,7 +13079,7 @@ var FileWatcher = class {
|
|
|
12880
13079
|
};
|
|
12881
13080
|
|
|
12882
13081
|
// src/watcher/git-head-watcher.ts
|
|
12883
|
-
var
|
|
13082
|
+
var path22 = __toESM(require("path"), 1);
|
|
12884
13083
|
var GitHeadWatcher = class {
|
|
12885
13084
|
watcher = null;
|
|
12886
13085
|
projectRoot;
|
|
@@ -12902,7 +13101,7 @@ var GitHeadWatcher = class {
|
|
|
12902
13101
|
this.onBranchChange = handler;
|
|
12903
13102
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
12904
13103
|
const headPath = getHeadPath(this.projectRoot);
|
|
12905
|
-
const refsPath =
|
|
13104
|
+
const refsPath = path22.join(this.projectRoot, ".git", "refs", "heads");
|
|
12906
13105
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
12907
13106
|
persistent: true,
|
|
12908
13107
|
ignoreInitial: true,
|
|
@@ -13045,8 +13244,8 @@ function getConfigPaths(projectRoot, host, options) {
|
|
|
13045
13244
|
}
|
|
13046
13245
|
|
|
13047
13246
|
// src/tools/visualize/activity.ts
|
|
13048
|
-
var
|
|
13049
|
-
var
|
|
13247
|
+
var import_child_process4 = require("child_process");
|
|
13248
|
+
var path23 = __toESM(require("path"), 1);
|
|
13050
13249
|
function attachRecentActivity(data, projectRoot) {
|
|
13051
13250
|
const activity = readGitActivity(projectRoot);
|
|
13052
13251
|
const changes = activity.size > 0 ? buildGitChanges(data, activity, projectRoot) : buildGraphChanges(data);
|
|
@@ -13057,7 +13256,7 @@ function attachRecentActivity(data, projectRoot) {
|
|
|
13057
13256
|
}
|
|
13058
13257
|
function readGitActivity(projectRoot) {
|
|
13059
13258
|
try {
|
|
13060
|
-
const output = (0,
|
|
13259
|
+
const output = (0, import_child_process4.execFileSync)(
|
|
13061
13260
|
"git",
|
|
13062
13261
|
["-C", projectRoot, "log", "--since=90.days", "--numstat", "--date=short", "--pretty=format:__COMMIT__%x09%h%x09%ad%x09%s"],
|
|
13063
13262
|
{ encoding: "utf8", maxBuffer: 8 * 1024 * 1024, stdio: ["ignore", "pipe", "ignore"] }
|
|
@@ -13208,7 +13407,7 @@ function normalizePath3(filePath) {
|
|
|
13208
13407
|
return filePath.replace(/\\/g, "/");
|
|
13209
13408
|
}
|
|
13210
13409
|
function toGitRelativePath(projectRoot, filePath) {
|
|
13211
|
-
const relativePath =
|
|
13410
|
+
const relativePath = path23.isAbsolute(filePath) ? path23.relative(projectRoot, filePath) : filePath;
|
|
13212
13411
|
return normalizePath3(relativePath);
|
|
13213
13412
|
}
|
|
13214
13413
|
|
|
@@ -13466,7 +13665,7 @@ render();
|
|
|
13466
13665
|
}
|
|
13467
13666
|
|
|
13468
13667
|
// src/tools/visualize/transform.ts
|
|
13469
|
-
var
|
|
13668
|
+
var path24 = __toESM(require("path"), 1);
|
|
13470
13669
|
|
|
13471
13670
|
// src/tools/visualize/modules.ts
|
|
13472
13671
|
var MAX_MODULES = 18;
|
|
@@ -13599,8 +13798,8 @@ function compactModules(prefixToNodes) {
|
|
|
13599
13798
|
function deriveModules(nodes) {
|
|
13600
13799
|
const initial = /* @__PURE__ */ new Map();
|
|
13601
13800
|
for (const node of nodes) {
|
|
13602
|
-
const
|
|
13603
|
-
const prefix = modulePrefixFromRelativePath(
|
|
13801
|
+
const relative11 = stripToProjectRelative(node.filePath);
|
|
13802
|
+
const prefix = modulePrefixFromRelativePath(relative11);
|
|
13604
13803
|
if (!initial.has(prefix)) initial.set(prefix, []);
|
|
13605
13804
|
initial.get(prefix)?.push(node);
|
|
13606
13805
|
}
|
|
@@ -13726,7 +13925,7 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
13726
13925
|
filePath: s.filePath,
|
|
13727
13926
|
kind: s.kind,
|
|
13728
13927
|
line: s.startLine,
|
|
13729
|
-
directory:
|
|
13928
|
+
directory: path24.dirname(s.filePath),
|
|
13730
13929
|
moduleId: "",
|
|
13731
13930
|
moduleLabel: ""
|
|
13732
13931
|
}));
|
|
@@ -13755,9 +13954,9 @@ function parseArgs(argv) {
|
|
|
13755
13954
|
let host = "opencode";
|
|
13756
13955
|
for (let i = 2; i < argv.length; i++) {
|
|
13757
13956
|
if (argv[i] === "--project" && argv[i + 1]) {
|
|
13758
|
-
project =
|
|
13957
|
+
project = path25.resolve(argv[++i]);
|
|
13759
13958
|
} else if (argv[i] === "--config" && argv[i + 1]) {
|
|
13760
|
-
config =
|
|
13959
|
+
config = path25.resolve(argv[++i]);
|
|
13761
13960
|
} else if (argv[i] === "--host" && argv[i + 1]) {
|
|
13762
13961
|
host = parseHostMode(argv[++i]);
|
|
13763
13962
|
} else if (argv[i] === "--host") {
|
|
@@ -13780,7 +13979,7 @@ function parseVisualizeArgs(argv, cwd) {
|
|
|
13780
13979
|
for (let i = 0; i < argv.length; i++) {
|
|
13781
13980
|
const arg = argv[i];
|
|
13782
13981
|
if (arg === "--project" && argv[i + 1]) {
|
|
13783
|
-
project =
|
|
13982
|
+
project = path25.resolve(argv[++i]);
|
|
13784
13983
|
} else if (arg === "--max" && argv[i + 1]) {
|
|
13785
13984
|
maxNodes = Number(argv[++i]);
|
|
13786
13985
|
} else if (arg.startsWith("--max=") || arg.startsWith("max=")) {
|
|
@@ -13817,7 +14016,7 @@ async function handleVisualizeCommand(argv, cwd) {
|
|
|
13817
14016
|
console.error("No connected symbols found. Retry with: npm run visualize -- orphans");
|
|
13818
14017
|
return 1;
|
|
13819
14018
|
}
|
|
13820
|
-
const outputPath =
|
|
14019
|
+
const outputPath = path25.join(os5.tmpdir(), `call-graph-${Date.now()}.html`);
|
|
13821
14020
|
(0, import_fs15.writeFileSync)(outputPath, generateVisualizationHtml(vizData), "utf-8");
|
|
13822
14021
|
console.log(`Temporal call graph visualization generated: ${outputPath}`);
|
|
13823
14022
|
console.log(`Nodes: ${vizData.nodes.length} | Edges: ${vizData.edges.length}`);
|
|
@@ -13847,7 +14046,7 @@ async function main() {
|
|
|
13847
14046
|
const transport = new import_stdio.StdioServerTransport();
|
|
13848
14047
|
await server.connect(transport);
|
|
13849
14048
|
let watcher = null;
|
|
13850
|
-
const isHomeDir =
|
|
14049
|
+
const isHomeDir = path25.resolve(args.project) === path25.resolve(os5.homedir());
|
|
13851
14050
|
const isValidProject = !isHomeDir && (!config.indexing.requireProjectMarker || hasProjectMarker(args.project));
|
|
13852
14051
|
if (config.indexing.autoIndex && isValidProject) {
|
|
13853
14052
|
const indexer = getIndexerForProject(args.project, args.host);
|