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/index.cjs
CHANGED
|
@@ -495,7 +495,7 @@ var require_ignore = __commonJS({
|
|
|
495
495
|
// path matching.
|
|
496
496
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
497
497
|
// @returns {TestResult} true if a file is ignored
|
|
498
|
-
test(
|
|
498
|
+
test(path23, checkUnignored, mode) {
|
|
499
499
|
let ignored = false;
|
|
500
500
|
let unignored = false;
|
|
501
501
|
let matchedRule;
|
|
@@ -504,7 +504,7 @@ var require_ignore = __commonJS({
|
|
|
504
504
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
505
505
|
return;
|
|
506
506
|
}
|
|
507
|
-
const matched = rule[mode].test(
|
|
507
|
+
const matched = rule[mode].test(path23);
|
|
508
508
|
if (!matched) {
|
|
509
509
|
return;
|
|
510
510
|
}
|
|
@@ -525,17 +525,17 @@ var require_ignore = __commonJS({
|
|
|
525
525
|
var throwError = (message, Ctor) => {
|
|
526
526
|
throw new Ctor(message);
|
|
527
527
|
};
|
|
528
|
-
var checkPath = (
|
|
529
|
-
if (!isString(
|
|
528
|
+
var checkPath = (path23, originalPath, doThrow) => {
|
|
529
|
+
if (!isString(path23)) {
|
|
530
530
|
return doThrow(
|
|
531
531
|
`path must be a string, but got \`${originalPath}\``,
|
|
532
532
|
TypeError
|
|
533
533
|
);
|
|
534
534
|
}
|
|
535
|
-
if (!
|
|
535
|
+
if (!path23) {
|
|
536
536
|
return doThrow(`path must not be empty`, TypeError);
|
|
537
537
|
}
|
|
538
|
-
if (checkPath.isNotRelative(
|
|
538
|
+
if (checkPath.isNotRelative(path23)) {
|
|
539
539
|
const r = "`path.relative()`d";
|
|
540
540
|
return doThrow(
|
|
541
541
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -544,7 +544,7 @@ var require_ignore = __commonJS({
|
|
|
544
544
|
}
|
|
545
545
|
return true;
|
|
546
546
|
};
|
|
547
|
-
var isNotRelative = (
|
|
547
|
+
var isNotRelative = (path23) => REGEX_TEST_INVALID_PATH.test(path23);
|
|
548
548
|
checkPath.isNotRelative = isNotRelative;
|
|
549
549
|
checkPath.convert = (p) => p;
|
|
550
550
|
var Ignore2 = class {
|
|
@@ -574,19 +574,19 @@ var require_ignore = __commonJS({
|
|
|
574
574
|
}
|
|
575
575
|
// @returns {TestResult}
|
|
576
576
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
577
|
-
const
|
|
577
|
+
const path23 = originalPath && checkPath.convert(originalPath);
|
|
578
578
|
checkPath(
|
|
579
|
-
|
|
579
|
+
path23,
|
|
580
580
|
originalPath,
|
|
581
581
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
582
582
|
);
|
|
583
|
-
return this._t(
|
|
583
|
+
return this._t(path23, cache, checkUnignored, slices);
|
|
584
584
|
}
|
|
585
|
-
checkIgnore(
|
|
586
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
587
|
-
return this.test(
|
|
585
|
+
checkIgnore(path23) {
|
|
586
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path23)) {
|
|
587
|
+
return this.test(path23);
|
|
588
588
|
}
|
|
589
|
-
const slices =
|
|
589
|
+
const slices = path23.split(SLASH2).filter(Boolean);
|
|
590
590
|
slices.pop();
|
|
591
591
|
if (slices.length) {
|
|
592
592
|
const parent = this._t(
|
|
@@ -599,18 +599,18 @@ var require_ignore = __commonJS({
|
|
|
599
599
|
return parent;
|
|
600
600
|
}
|
|
601
601
|
}
|
|
602
|
-
return this._rules.test(
|
|
602
|
+
return this._rules.test(path23, false, MODE_CHECK_IGNORE);
|
|
603
603
|
}
|
|
604
|
-
_t(
|
|
605
|
-
if (
|
|
606
|
-
return cache[
|
|
604
|
+
_t(path23, cache, checkUnignored, slices) {
|
|
605
|
+
if (path23 in cache) {
|
|
606
|
+
return cache[path23];
|
|
607
607
|
}
|
|
608
608
|
if (!slices) {
|
|
609
|
-
slices =
|
|
609
|
+
slices = path23.split(SLASH2).filter(Boolean);
|
|
610
610
|
}
|
|
611
611
|
slices.pop();
|
|
612
612
|
if (!slices.length) {
|
|
613
|
-
return cache[
|
|
613
|
+
return cache[path23] = this._rules.test(path23, checkUnignored, MODE_IGNORE);
|
|
614
614
|
}
|
|
615
615
|
const parent = this._t(
|
|
616
616
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -618,29 +618,29 @@ var require_ignore = __commonJS({
|
|
|
618
618
|
checkUnignored,
|
|
619
619
|
slices
|
|
620
620
|
);
|
|
621
|
-
return cache[
|
|
621
|
+
return cache[path23] = parent.ignored ? parent : this._rules.test(path23, checkUnignored, MODE_IGNORE);
|
|
622
622
|
}
|
|
623
|
-
ignores(
|
|
624
|
-
return this._test(
|
|
623
|
+
ignores(path23) {
|
|
624
|
+
return this._test(path23, this._ignoreCache, false).ignored;
|
|
625
625
|
}
|
|
626
626
|
createFilter() {
|
|
627
|
-
return (
|
|
627
|
+
return (path23) => !this.ignores(path23);
|
|
628
628
|
}
|
|
629
629
|
filter(paths) {
|
|
630
630
|
return makeArray(paths).filter(this.createFilter());
|
|
631
631
|
}
|
|
632
632
|
// @returns {TestResult}
|
|
633
|
-
test(
|
|
634
|
-
return this._test(
|
|
633
|
+
test(path23) {
|
|
634
|
+
return this._test(path23, this._testCache, true);
|
|
635
635
|
}
|
|
636
636
|
};
|
|
637
637
|
var factory = (options) => new Ignore2(options);
|
|
638
|
-
var isPathValid = (
|
|
638
|
+
var isPathValid = (path23) => checkPath(path23 && checkPath.convert(path23), path23, RETURN_FALSE);
|
|
639
639
|
var setupWindows = () => {
|
|
640
640
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
641
641
|
checkPath.convert = makePosix;
|
|
642
642
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
643
|
-
checkPath.isNotRelative = (
|
|
643
|
+
checkPath.isNotRelative = (path23) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path23) || isNotRelative(path23);
|
|
644
644
|
};
|
|
645
645
|
if (
|
|
646
646
|
// Detect `process` so that it can run in browsers.
|
|
@@ -662,7 +662,7 @@ __export(index_exports, {
|
|
|
662
662
|
});
|
|
663
663
|
module.exports = __toCommonJS(index_exports);
|
|
664
664
|
var os5 = __toESM(require("os"), 1);
|
|
665
|
-
var
|
|
665
|
+
var path22 = __toESM(require("path"), 1);
|
|
666
666
|
var import_url2 = require("url");
|
|
667
667
|
|
|
668
668
|
// src/config/constants.ts
|
|
@@ -795,7 +795,8 @@ function getDefaultIndexingConfig() {
|
|
|
795
795
|
requireProjectMarker: true,
|
|
796
796
|
maxDepth: 5,
|
|
797
797
|
maxFilesPerDirectory: 100,
|
|
798
|
-
fallbackToTextOnMaxChunks: true
|
|
798
|
+
fallbackToTextOnMaxChunks: true,
|
|
799
|
+
gitBlame: { enabled: false }
|
|
799
800
|
};
|
|
800
801
|
}
|
|
801
802
|
function getDefaultSearchConfig() {
|
|
@@ -919,7 +920,10 @@ function parseConfig(raw) {
|
|
|
919
920
|
requireProjectMarker: typeof rawIndexing.requireProjectMarker === "boolean" ? rawIndexing.requireProjectMarker : defaultIndexing.requireProjectMarker,
|
|
920
921
|
maxDepth: typeof rawIndexing.maxDepth === "number" ? rawIndexing.maxDepth < -1 ? -1 : rawIndexing.maxDepth : defaultIndexing.maxDepth,
|
|
921
922
|
maxFilesPerDirectory: typeof rawIndexing.maxFilesPerDirectory === "number" ? Math.max(1, rawIndexing.maxFilesPerDirectory) : defaultIndexing.maxFilesPerDirectory,
|
|
922
|
-
fallbackToTextOnMaxChunks: typeof rawIndexing.fallbackToTextOnMaxChunks === "boolean" ? rawIndexing.fallbackToTextOnMaxChunks : defaultIndexing.fallbackToTextOnMaxChunks
|
|
923
|
+
fallbackToTextOnMaxChunks: typeof rawIndexing.fallbackToTextOnMaxChunks === "boolean" ? rawIndexing.fallbackToTextOnMaxChunks : defaultIndexing.fallbackToTextOnMaxChunks,
|
|
924
|
+
gitBlame: {
|
|
925
|
+
enabled: rawIndexing.gitBlame && typeof rawIndexing.gitBlame === "object" && typeof rawIndexing.gitBlame.enabled === "boolean" ? rawIndexing.gitBlame.enabled : defaultIndexing.gitBlame.enabled
|
|
926
|
+
}
|
|
923
927
|
};
|
|
924
928
|
const rawSearch = input.search && typeof input.search === "object" ? input.search : {};
|
|
925
929
|
const search = {
|
|
@@ -1589,14 +1593,14 @@ function loadMergedConfig(projectRoot, host = "opencode") {
|
|
|
1589
1593
|
|
|
1590
1594
|
// src/tools/operations.ts
|
|
1591
1595
|
var import_fs9 = require("fs");
|
|
1592
|
-
var
|
|
1596
|
+
var path15 = __toESM(require("path"), 1);
|
|
1593
1597
|
|
|
1594
1598
|
// src/indexer/index.ts
|
|
1595
1599
|
var import_fs7 = require("fs");
|
|
1596
|
-
var
|
|
1600
|
+
var path12 = __toESM(require("path"), 1);
|
|
1597
1601
|
var import_perf_hooks = require("perf_hooks");
|
|
1598
|
-
var
|
|
1599
|
-
var
|
|
1602
|
+
var import_child_process3 = require("child_process");
|
|
1603
|
+
var import_util3 = require("util");
|
|
1600
1604
|
|
|
1601
1605
|
// node_modules/eventemitter3/index.mjs
|
|
1602
1606
|
var import_index = __toESM(require_eventemitter3(), 1);
|
|
@@ -4784,8 +4788,8 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
4784
4788
|
const trimmed = raw.trim();
|
|
4785
4789
|
if (!trimmed) continue;
|
|
4786
4790
|
const absolute = path10.resolve(projectRoot, trimmed);
|
|
4787
|
-
const
|
|
4788
|
-
const cleaned =
|
|
4791
|
+
const relative11 = path10.relative(projectRoot, absolute);
|
|
4792
|
+
const cleaned = relative11.startsWith("./") ? relative11.slice(2) : relative11;
|
|
4789
4793
|
if (!seen.has(cleaned)) {
|
|
4790
4794
|
seen.add(cleaned);
|
|
4791
4795
|
result.push(cleaned);
|
|
@@ -4794,8 +4798,61 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
4794
4798
|
return result;
|
|
4795
4799
|
}
|
|
4796
4800
|
|
|
4801
|
+
// src/indexer/git-blame.ts
|
|
4802
|
+
var import_child_process2 = require("child_process");
|
|
4803
|
+
var path11 = __toESM(require("path"), 1);
|
|
4804
|
+
var import_util2 = require("util");
|
|
4805
|
+
var execFileAsync2 = (0, import_util2.promisify)(import_child_process2.execFile);
|
|
4806
|
+
function parseGitBlamePorcelain(output) {
|
|
4807
|
+
const commits = /* @__PURE__ */ new Map();
|
|
4808
|
+
let current;
|
|
4809
|
+
for (const line of output.split("\n")) {
|
|
4810
|
+
if (/^[0-9a-f]{40} /.test(line)) {
|
|
4811
|
+
const sha = line.slice(0, 40);
|
|
4812
|
+
current = commits.get(sha) ?? {
|
|
4813
|
+
sha,
|
|
4814
|
+
author: "",
|
|
4815
|
+
authorEmail: "",
|
|
4816
|
+
committedAt: 0,
|
|
4817
|
+
summary: "",
|
|
4818
|
+
lines: 0
|
|
4819
|
+
};
|
|
4820
|
+
commits.set(sha, current);
|
|
4821
|
+
continue;
|
|
4822
|
+
}
|
|
4823
|
+
if (!current) {
|
|
4824
|
+
continue;
|
|
4825
|
+
}
|
|
4826
|
+
if (line.startsWith("author ")) {
|
|
4827
|
+
current.author = line.slice("author ".length);
|
|
4828
|
+
} else if (line.startsWith("author-mail ")) {
|
|
4829
|
+
current.authorEmail = line.slice("author-mail ".length).replace(/^<|>$/g, "");
|
|
4830
|
+
} else if (line.startsWith("author-time ")) {
|
|
4831
|
+
current.committedAt = Number.parseInt(line.slice("author-time ".length), 10);
|
|
4832
|
+
} else if (line.startsWith("summary ")) {
|
|
4833
|
+
current.summary = line.slice("summary ".length);
|
|
4834
|
+
} else if (line.startsWith(" ")) {
|
|
4835
|
+
current.lines += 1;
|
|
4836
|
+
}
|
|
4837
|
+
}
|
|
4838
|
+
return Array.from(commits.values()).filter((commit) => commit.lines > 0).sort((a, b) => b.lines - a.lines || b.committedAt - a.committedAt)[0];
|
|
4839
|
+
}
|
|
4840
|
+
async function getChunkGitBlame(projectRoot, filePath, startLine, endLine) {
|
|
4841
|
+
const relativePath = path11.relative(projectRoot, filePath);
|
|
4842
|
+
try {
|
|
4843
|
+
const { stdout } = await execFileAsync2(
|
|
4844
|
+
"git",
|
|
4845
|
+
["blame", "--line-porcelain", "-L", `${startLine},${endLine}`, "--", relativePath],
|
|
4846
|
+
{ cwd: projectRoot, timeout: 3e4 }
|
|
4847
|
+
);
|
|
4848
|
+
return parseGitBlamePorcelain(stdout);
|
|
4849
|
+
} catch {
|
|
4850
|
+
return void 0;
|
|
4851
|
+
}
|
|
4852
|
+
}
|
|
4853
|
+
|
|
4797
4854
|
// src/indexer/index.ts
|
|
4798
|
-
var CALL_GRAPH_LANGUAGES = /* @__PURE__ */ new Set(["typescript", "tsx", "javascript", "jsx", "python", "go", "rust", "php", "apex", "zig", "gdscript", "matlab"]);
|
|
4855
|
+
var CALL_GRAPH_LANGUAGES = /* @__PURE__ */ new Set(["typescript", "tsx", "javascript", "jsx", "python", "go", "rust", "php", "apex", "zig", "gdscript", "matlab", "bash"]);
|
|
4799
4856
|
var CASE_INSENSITIVE_LANGUAGES = /* @__PURE__ */ new Set(["apex"]);
|
|
4800
4857
|
var CALL_GRAPH_SYMBOL_CHUNK_TYPES = /* @__PURE__ */ new Set([
|
|
4801
4858
|
"function_declaration",
|
|
@@ -4875,6 +4932,45 @@ function isSqliteCorruptionError(error) {
|
|
|
4875
4932
|
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");
|
|
4876
4933
|
}
|
|
4877
4934
|
var STARTUP_WARNING_METADATA_KEY = "index.startupWarning";
|
|
4935
|
+
function metadataFromBlame(blame) {
|
|
4936
|
+
if (!blame) {
|
|
4937
|
+
return {};
|
|
4938
|
+
}
|
|
4939
|
+
return {
|
|
4940
|
+
blameSha: blame.sha,
|
|
4941
|
+
blameAuthor: blame.author,
|
|
4942
|
+
blameAuthorEmail: blame.authorEmail,
|
|
4943
|
+
blameCommittedAt: blame.committedAt,
|
|
4944
|
+
blameSummary: blame.summary
|
|
4945
|
+
};
|
|
4946
|
+
}
|
|
4947
|
+
function blameFromChunkData(chunk) {
|
|
4948
|
+
if (!chunk?.blameSha || !chunk.blameAuthor || !chunk.blameAuthorEmail || chunk.blameCommittedAt === void 0 || !chunk.blameSummary) {
|
|
4949
|
+
return void 0;
|
|
4950
|
+
}
|
|
4951
|
+
return {
|
|
4952
|
+
sha: chunk.blameSha,
|
|
4953
|
+
author: chunk.blameAuthor,
|
|
4954
|
+
authorEmail: chunk.blameAuthorEmail,
|
|
4955
|
+
committedAt: chunk.blameCommittedAt,
|
|
4956
|
+
summary: chunk.blameSummary
|
|
4957
|
+
};
|
|
4958
|
+
}
|
|
4959
|
+
function blameFromMetadata(metadata) {
|
|
4960
|
+
if (!metadata.blameSha || !metadata.blameAuthor || !metadata.blameAuthorEmail || metadata.blameCommittedAt === void 0 || !metadata.blameSummary) {
|
|
4961
|
+
return void 0;
|
|
4962
|
+
}
|
|
4963
|
+
return {
|
|
4964
|
+
sha: metadata.blameSha,
|
|
4965
|
+
author: metadata.blameAuthor,
|
|
4966
|
+
authorEmail: metadata.blameAuthorEmail,
|
|
4967
|
+
committedAt: metadata.blameCommittedAt,
|
|
4968
|
+
summary: metadata.blameSummary
|
|
4969
|
+
};
|
|
4970
|
+
}
|
|
4971
|
+
function hasBlameMetadata(metadata) {
|
|
4972
|
+
return blameFromMetadata(metadata) !== void 0;
|
|
4973
|
+
}
|
|
4878
4974
|
var INDEX_METADATA_VERSION = "1";
|
|
4879
4975
|
var EMBEDDING_STRATEGY_VERSION = "2";
|
|
4880
4976
|
var RANKING_TOKEN_CACHE_LIMIT = 4096;
|
|
@@ -5033,9 +5129,9 @@ function hasAllEmbeddingParts(parts, expectedPartCount) {
|
|
|
5033
5129
|
return true;
|
|
5034
5130
|
}
|
|
5035
5131
|
function isPathWithinRoot(filePath, rootPath) {
|
|
5036
|
-
const normalizedFilePath =
|
|
5037
|
-
const normalizedRoot =
|
|
5038
|
-
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${
|
|
5132
|
+
const normalizedFilePath = path12.resolve(filePath);
|
|
5133
|
+
const normalizedRoot = path12.resolve(rootPath);
|
|
5134
|
+
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${path12.sep}`);
|
|
5039
5135
|
}
|
|
5040
5136
|
var rankingQueryTokenCache = /* @__PURE__ */ new Map();
|
|
5041
5137
|
var rankingNameTokenCache = /* @__PURE__ */ new Map();
|
|
@@ -5794,7 +5890,8 @@ function promoteIdentifierMatches(query, combined, semanticCandidates, keywordCa
|
|
|
5794
5890
|
chunkType,
|
|
5795
5891
|
name: chunk.name ?? void 0,
|
|
5796
5892
|
language: chunk.language,
|
|
5797
|
-
hash: chunk.contentHash
|
|
5893
|
+
hash: chunk.contentHash,
|
|
5894
|
+
...metadataFromBlame(blameFromChunkData(chunk))
|
|
5798
5895
|
};
|
|
5799
5896
|
const baselineScore = existing?.score ?? 0.5;
|
|
5800
5897
|
candidateUnion.set(chunk.chunkId, {
|
|
@@ -5878,7 +5975,8 @@ function buildSymbolDefinitionLane(query, database, branchChunkIds, limit, fallb
|
|
|
5878
5975
|
chunkType,
|
|
5879
5976
|
name: chunk.name ?? void 0,
|
|
5880
5977
|
language: chunk.language,
|
|
5881
|
-
hash: chunk.contentHash
|
|
5978
|
+
hash: chunk.contentHash,
|
|
5979
|
+
...metadataFromBlame(blameFromChunkData(chunk))
|
|
5882
5980
|
}
|
|
5883
5981
|
});
|
|
5884
5982
|
}
|
|
@@ -6047,6 +6145,21 @@ function matchesSearchFilters(candidate, options, minScore) {
|
|
|
6047
6145
|
if (options?.chunkType && candidate.metadata.chunkType !== options.chunkType) {
|
|
6048
6146
|
return false;
|
|
6049
6147
|
}
|
|
6148
|
+
if (options?.blameAuthor) {
|
|
6149
|
+
const author = options.blameAuthor.toLowerCase();
|
|
6150
|
+
const candidateAuthor = candidate.metadata.blameAuthor?.toLowerCase();
|
|
6151
|
+
const candidateEmail = candidate.metadata.blameAuthorEmail?.toLowerCase();
|
|
6152
|
+
if (candidateAuthor !== author && candidateEmail !== author) return false;
|
|
6153
|
+
}
|
|
6154
|
+
if (options?.blameSha && !candidate.metadata.blameSha?.toLowerCase().startsWith(options.blameSha.toLowerCase())) {
|
|
6155
|
+
return false;
|
|
6156
|
+
}
|
|
6157
|
+
if (options?.blameSince) {
|
|
6158
|
+
const sinceMs = Date.parse(options.blameSince);
|
|
6159
|
+
if (Number.isNaN(sinceMs)) return false;
|
|
6160
|
+
const committedAt = candidate.metadata.blameCommittedAt;
|
|
6161
|
+
if (committedAt === void 0 || committedAt < Math.floor(sinceMs / 1e3)) return false;
|
|
6162
|
+
}
|
|
6050
6163
|
return true;
|
|
6051
6164
|
}
|
|
6052
6165
|
function unionCandidates(semanticCandidates, keywordCandidates) {
|
|
@@ -6090,9 +6203,9 @@ var Indexer = class {
|
|
|
6090
6203
|
this.config = config;
|
|
6091
6204
|
this.host = host;
|
|
6092
6205
|
this.indexPath = this.getIndexPath();
|
|
6093
|
-
this.fileHashCachePath =
|
|
6094
|
-
this.failedBatchesPath =
|
|
6095
|
-
this.indexingLockPath =
|
|
6206
|
+
this.fileHashCachePath = path12.join(this.indexPath, "file-hashes.json");
|
|
6207
|
+
this.failedBatchesPath = path12.join(this.indexPath, "failed-batches.json");
|
|
6208
|
+
this.indexingLockPath = path12.join(this.indexPath, "indexing.lock");
|
|
6096
6209
|
this.logger = initializeLogger(config.debug);
|
|
6097
6210
|
}
|
|
6098
6211
|
getIndexPath() {
|
|
@@ -6124,14 +6237,14 @@ var Indexer = class {
|
|
|
6124
6237
|
}
|
|
6125
6238
|
atomicWriteSync(targetPath, data) {
|
|
6126
6239
|
const tempPath = `${targetPath}.tmp`;
|
|
6127
|
-
(0, import_fs7.mkdirSync)(
|
|
6240
|
+
(0, import_fs7.mkdirSync)(path12.dirname(targetPath), { recursive: true });
|
|
6128
6241
|
(0, import_fs7.writeFileSync)(tempPath, data);
|
|
6129
6242
|
(0, import_fs7.renameSync)(tempPath, targetPath);
|
|
6130
6243
|
}
|
|
6131
6244
|
getScopedRoots() {
|
|
6132
|
-
const roots = /* @__PURE__ */ new Set([
|
|
6245
|
+
const roots = /* @__PURE__ */ new Set([path12.resolve(this.projectRoot)]);
|
|
6133
6246
|
for (const kbRoot of this.config.knowledgeBases) {
|
|
6134
|
-
roots.add(
|
|
6247
|
+
roots.add(path12.resolve(this.projectRoot, kbRoot));
|
|
6135
6248
|
}
|
|
6136
6249
|
return Array.from(roots);
|
|
6137
6250
|
}
|
|
@@ -6140,29 +6253,29 @@ var Indexer = class {
|
|
|
6140
6253
|
if (this.config.scope !== "global") {
|
|
6141
6254
|
return branchName;
|
|
6142
6255
|
}
|
|
6143
|
-
const projectHash = hashContent(
|
|
6256
|
+
const projectHash = hashContent(path12.resolve(this.projectRoot)).slice(0, 16);
|
|
6144
6257
|
return `${projectHash}:${branchName}`;
|
|
6145
6258
|
}
|
|
6146
6259
|
getBranchCatalogKeyFor(branchName) {
|
|
6147
6260
|
if (this.config.scope !== "global") {
|
|
6148
6261
|
return branchName;
|
|
6149
6262
|
}
|
|
6150
|
-
const projectHash = hashContent(
|
|
6263
|
+
const projectHash = hashContent(path12.resolve(this.projectRoot)).slice(0, 16);
|
|
6151
6264
|
return `${projectHash}:${branchName}`;
|
|
6152
6265
|
}
|
|
6153
6266
|
getLegacyBranchCatalogKey() {
|
|
6154
6267
|
return this.currentBranch || "default";
|
|
6155
6268
|
}
|
|
6156
6269
|
getLegacyMigrationMetadataKey() {
|
|
6157
|
-
const projectHash = hashContent(
|
|
6270
|
+
const projectHash = hashContent(path12.resolve(this.projectRoot)).slice(0, 16);
|
|
6158
6271
|
return `index.globalBranchMigration.${projectHash}`;
|
|
6159
6272
|
}
|
|
6160
6273
|
getProjectEmbeddingStrategyMetadataKey() {
|
|
6161
|
-
const projectHash = hashContent(
|
|
6274
|
+
const projectHash = hashContent(path12.resolve(this.projectRoot)).slice(0, 16);
|
|
6162
6275
|
return `index.embeddingStrategyVersion.${projectHash}`;
|
|
6163
6276
|
}
|
|
6164
6277
|
getProjectForceReembedMetadataKey() {
|
|
6165
|
-
const projectHash = hashContent(
|
|
6278
|
+
const projectHash = hashContent(path12.resolve(this.projectRoot)).slice(0, 16);
|
|
6166
6279
|
return `index.forceReembed.${projectHash}`;
|
|
6167
6280
|
}
|
|
6168
6281
|
hasProjectForceReembedPending() {
|
|
@@ -6256,7 +6369,7 @@ var Indexer = class {
|
|
|
6256
6369
|
if (!this.database) {
|
|
6257
6370
|
return { chunkIds, symbolIds };
|
|
6258
6371
|
}
|
|
6259
|
-
const projectRootPath =
|
|
6372
|
+
const projectRootPath = path12.resolve(this.projectRoot);
|
|
6260
6373
|
const projectLocalFilePaths = /* @__PURE__ */ new Set([
|
|
6261
6374
|
...Array.from(this.fileHashCache.keys()).filter(
|
|
6262
6375
|
(filePath) => this.isFileInCurrentScope(filePath, roots) && isPathWithinRoot(filePath, projectRootPath)
|
|
@@ -6279,7 +6392,7 @@ var Indexer = class {
|
|
|
6279
6392
|
if (this.config.scope !== "global") {
|
|
6280
6393
|
return this.getBranchCatalogCleanupKeys();
|
|
6281
6394
|
}
|
|
6282
|
-
const projectHash = hashContent(
|
|
6395
|
+
const projectHash = hashContent(path12.resolve(this.projectRoot)).slice(0, 16);
|
|
6283
6396
|
const keys = /* @__PURE__ */ new Set();
|
|
6284
6397
|
const projectChunkIdSet = new Set(projectChunkIds);
|
|
6285
6398
|
const projectSymbolIdSet = new Set(projectSymbolIds);
|
|
@@ -6363,7 +6476,7 @@ var Indexer = class {
|
|
|
6363
6476
|
if (!this.database || this.config.scope !== "global") {
|
|
6364
6477
|
return false;
|
|
6365
6478
|
}
|
|
6366
|
-
const projectHash = hashContent(
|
|
6479
|
+
const projectHash = hashContent(path12.resolve(this.projectRoot)).slice(0, 16);
|
|
6367
6480
|
const roots = this.getScopedRoots();
|
|
6368
6481
|
const { chunkIds: projectLocalChunkIds, symbolIds: projectLocalSymbolIds } = this.getProjectLocalScopedOwnershipIds(roots);
|
|
6369
6482
|
return this.database.getAllBranches().some(
|
|
@@ -6397,7 +6510,7 @@ var Indexer = class {
|
|
|
6397
6510
|
...Array.from(this.fileHashCache.keys()).filter((filePath) => this.isFileInCurrentScope(filePath, roots)),
|
|
6398
6511
|
...scopedEntries.map(({ metadata }) => metadata.filePath)
|
|
6399
6512
|
]);
|
|
6400
|
-
const projectRootPath =
|
|
6513
|
+
const projectRootPath = path12.resolve(this.projectRoot);
|
|
6401
6514
|
const projectLocalFilePaths = new Set(
|
|
6402
6515
|
Array.from(filePaths).filter((filePath) => isPathWithinRoot(filePath, projectRootPath))
|
|
6403
6516
|
);
|
|
@@ -6757,13 +6870,13 @@ var Indexer = class {
|
|
|
6757
6870
|
}
|
|
6758
6871
|
await import_fs7.promises.mkdir(this.indexPath, { recursive: true });
|
|
6759
6872
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
6760
|
-
const storePath =
|
|
6873
|
+
const storePath = path12.join(this.indexPath, "vectors");
|
|
6761
6874
|
this.store = new VectorStore(storePath, dimensions);
|
|
6762
|
-
const indexFilePath =
|
|
6875
|
+
const indexFilePath = path12.join(this.indexPath, "vectors.usearch");
|
|
6763
6876
|
if ((0, import_fs7.existsSync)(indexFilePath)) {
|
|
6764
6877
|
this.store.load();
|
|
6765
6878
|
}
|
|
6766
|
-
const invertedIndexPath =
|
|
6879
|
+
const invertedIndexPath = path12.join(this.indexPath, "inverted-index.json");
|
|
6767
6880
|
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
6768
6881
|
try {
|
|
6769
6882
|
this.invertedIndex.load();
|
|
@@ -6773,7 +6886,7 @@ var Indexer = class {
|
|
|
6773
6886
|
}
|
|
6774
6887
|
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
6775
6888
|
}
|
|
6776
|
-
const dbPath =
|
|
6889
|
+
const dbPath = path12.join(this.indexPath, "codebase.db");
|
|
6777
6890
|
let dbIsNew = !(0, import_fs7.existsSync)(dbPath);
|
|
6778
6891
|
try {
|
|
6779
6892
|
this.database = new Database(dbPath);
|
|
@@ -6854,7 +6967,7 @@ var Indexer = class {
|
|
|
6854
6967
|
if (await this.tryResetCorruptedIndex("running automatic orphan garbage collection", error)) {
|
|
6855
6968
|
return {
|
|
6856
6969
|
resetCorruptedIndex: true,
|
|
6857
|
-
warning: this.getCorruptedIndexWarning(
|
|
6970
|
+
warning: this.getCorruptedIndexWarning(path12.join(this.indexPath, "codebase.db"))
|
|
6858
6971
|
};
|
|
6859
6972
|
}
|
|
6860
6973
|
throw error;
|
|
@@ -6869,7 +6982,7 @@ var Indexer = class {
|
|
|
6869
6982
|
return;
|
|
6870
6983
|
}
|
|
6871
6984
|
const retainedEntries = store.getAllMetadata().filter(({ key }) => !excludedSet.has(key));
|
|
6872
|
-
const storeBasePath =
|
|
6985
|
+
const storeBasePath = path12.join(this.indexPath, "vectors");
|
|
6873
6986
|
const storeIndexPath = `${storeBasePath}.usearch`;
|
|
6874
6987
|
const storeMetadataPath = `${storeBasePath}.meta.json`;
|
|
6875
6988
|
const backupIndexPath = `${storeIndexPath}.bak`;
|
|
@@ -6954,7 +7067,7 @@ var Indexer = class {
|
|
|
6954
7067
|
if (!isSqliteCorruptionError(error)) {
|
|
6955
7068
|
return false;
|
|
6956
7069
|
}
|
|
6957
|
-
const dbPath =
|
|
7070
|
+
const dbPath = path12.join(this.indexPath, "codebase.db");
|
|
6958
7071
|
const warning = this.getCorruptedIndexWarning(dbPath);
|
|
6959
7072
|
const errorMessage = getErrorMessage2(error);
|
|
6960
7073
|
if (this.config.scope === "global") {
|
|
@@ -6977,15 +7090,15 @@ var Indexer = class {
|
|
|
6977
7090
|
this.indexCompatibility = null;
|
|
6978
7091
|
this.fileHashCache.clear();
|
|
6979
7092
|
const resetPaths = [
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
|
|
7093
|
+
path12.join(this.indexPath, "codebase.db"),
|
|
7094
|
+
path12.join(this.indexPath, "codebase.db-shm"),
|
|
7095
|
+
path12.join(this.indexPath, "codebase.db-wal"),
|
|
7096
|
+
path12.join(this.indexPath, "vectors.usearch"),
|
|
7097
|
+
path12.join(this.indexPath, "inverted-index.json"),
|
|
7098
|
+
path12.join(this.indexPath, "file-hashes.json"),
|
|
7099
|
+
path12.join(this.indexPath, "failed-batches.json"),
|
|
7100
|
+
path12.join(this.indexPath, "indexing.lock"),
|
|
7101
|
+
path12.join(this.indexPath, "vectors")
|
|
6989
7102
|
];
|
|
6990
7103
|
await Promise.all(resetPaths.map(async (targetPath) => {
|
|
6991
7104
|
try {
|
|
@@ -7222,6 +7335,7 @@ var Indexer = class {
|
|
|
7222
7335
|
this.logger.debug("Parsed changed files", { parsedCount: parsedFiles.length, parseMs: parseMs.toFixed(2) });
|
|
7223
7336
|
const existingChunks = /* @__PURE__ */ new Map();
|
|
7224
7337
|
const existingChunksByFile = /* @__PURE__ */ new Map();
|
|
7338
|
+
const existingMetadataById = /* @__PURE__ */ new Map();
|
|
7225
7339
|
for (const { key, metadata } of store.getAllMetadata()) {
|
|
7226
7340
|
if (scopedRoots && !this.isFileInCurrentScope(metadata.filePath, scopedRoots)) {
|
|
7227
7341
|
continue;
|
|
@@ -7230,6 +7344,7 @@ var Indexer = class {
|
|
|
7230
7344
|
continue;
|
|
7231
7345
|
}
|
|
7232
7346
|
existingChunks.set(key, metadata.hash);
|
|
7347
|
+
existingMetadataById.set(key, metadata);
|
|
7233
7348
|
const fileChunks = existingChunksByFile.get(metadata.filePath) || /* @__PURE__ */ new Set();
|
|
7234
7349
|
fileChunks.add(key);
|
|
7235
7350
|
existingChunksByFile.set(metadata.filePath, fileChunks);
|
|
@@ -7237,6 +7352,8 @@ var Indexer = class {
|
|
|
7237
7352
|
const currentChunkIds = /* @__PURE__ */ new Set();
|
|
7238
7353
|
const currentFilePaths = /* @__PURE__ */ new Set();
|
|
7239
7354
|
const pendingChunks = [];
|
|
7355
|
+
const gitBlameEnabled = this.config.indexing.gitBlame.enabled && isGitRepo(this.projectRoot);
|
|
7356
|
+
let backfilledBlameMetadata = false;
|
|
7240
7357
|
for (const filePath of unchangedFilePaths) {
|
|
7241
7358
|
currentFilePaths.add(filePath);
|
|
7242
7359
|
const fileChunks = existingChunksByFile.get(filePath);
|
|
@@ -7247,10 +7364,52 @@ var Indexer = class {
|
|
|
7247
7364
|
}
|
|
7248
7365
|
}
|
|
7249
7366
|
const chunkDataBatch = [];
|
|
7367
|
+
if (gitBlameEnabled) {
|
|
7368
|
+
const backfillItems = [];
|
|
7369
|
+
for (const chunkId of currentChunkIds) {
|
|
7370
|
+
const metadata = existingMetadataById.get(chunkId);
|
|
7371
|
+
if (!metadata || hasBlameMetadata(metadata)) {
|
|
7372
|
+
continue;
|
|
7373
|
+
}
|
|
7374
|
+
const chunk = database.getChunk(chunkId);
|
|
7375
|
+
if (!chunk) {
|
|
7376
|
+
continue;
|
|
7377
|
+
}
|
|
7378
|
+
const blame = await getChunkGitBlame(this.projectRoot, chunk.filePath, chunk.startLine, chunk.endLine);
|
|
7379
|
+
const blameMetadata = metadataFromBlame(blame);
|
|
7380
|
+
if (!blameMetadata.blameSha) {
|
|
7381
|
+
continue;
|
|
7382
|
+
}
|
|
7383
|
+
chunkDataBatch.push({
|
|
7384
|
+
...chunk,
|
|
7385
|
+
blameSha: blameMetadata.blameSha,
|
|
7386
|
+
blameAuthor: blameMetadata.blameAuthor,
|
|
7387
|
+
blameAuthorEmail: blameMetadata.blameAuthorEmail,
|
|
7388
|
+
blameCommittedAt: blameMetadata.blameCommittedAt,
|
|
7389
|
+
blameSummary: blameMetadata.blameSummary
|
|
7390
|
+
});
|
|
7391
|
+
const embeddingBuffer = database.getEmbedding(chunk.contentHash);
|
|
7392
|
+
if (!embeddingBuffer) {
|
|
7393
|
+
continue;
|
|
7394
|
+
}
|
|
7395
|
+
backfillItems.push({
|
|
7396
|
+
id: chunkId,
|
|
7397
|
+
vector: Array.from(bufferToFloat32Array(embeddingBuffer)),
|
|
7398
|
+
metadata: {
|
|
7399
|
+
...metadata,
|
|
7400
|
+
...blameMetadata
|
|
7401
|
+
}
|
|
7402
|
+
});
|
|
7403
|
+
}
|
|
7404
|
+
if (backfillItems.length > 0) {
|
|
7405
|
+
store.addBatch(backfillItems);
|
|
7406
|
+
backfilledBlameMetadata = true;
|
|
7407
|
+
}
|
|
7408
|
+
}
|
|
7250
7409
|
for (const parsed of parsedFiles) {
|
|
7251
7410
|
currentFilePaths.add(parsed.path);
|
|
7252
7411
|
if (parsed.chunks.length === 0) {
|
|
7253
|
-
const relativePath =
|
|
7412
|
+
const relativePath = path12.relative(this.projectRoot, parsed.path);
|
|
7254
7413
|
stats.parseFailures.push(relativePath);
|
|
7255
7414
|
}
|
|
7256
7415
|
let fileChunkCount = 0;
|
|
@@ -7271,6 +7430,10 @@ var Indexer = class {
|
|
|
7271
7430
|
}
|
|
7272
7431
|
const id = generateChunkId(parsed.path, chunk);
|
|
7273
7432
|
const contentHash = generateChunkHash(chunk);
|
|
7433
|
+
const existingContentHash = existingChunks.get(id);
|
|
7434
|
+
const existingChunk = gitBlameEnabled ? database.getChunk(id) : null;
|
|
7435
|
+
const blame = gitBlameEnabled && existingContentHash !== contentHash ? await getChunkGitBlame(this.projectRoot, parsed.path, chunk.startLine, chunk.endLine) : blameFromChunkData(existingChunk);
|
|
7436
|
+
const blameMetadata = metadataFromBlame(blame);
|
|
7274
7437
|
currentChunkIds.add(id);
|
|
7275
7438
|
chunkDataBatch.push({
|
|
7276
7439
|
chunkId: id,
|
|
@@ -7280,9 +7443,14 @@ var Indexer = class {
|
|
|
7280
7443
|
endLine: chunk.endLine,
|
|
7281
7444
|
nodeType: chunk.chunkType,
|
|
7282
7445
|
name: chunk.name,
|
|
7283
|
-
language: chunk.language
|
|
7446
|
+
language: chunk.language,
|
|
7447
|
+
blameSha: blameMetadata.blameSha,
|
|
7448
|
+
blameAuthor: blameMetadata.blameAuthor,
|
|
7449
|
+
blameAuthorEmail: blameMetadata.blameAuthorEmail,
|
|
7450
|
+
blameCommittedAt: blameMetadata.blameCommittedAt,
|
|
7451
|
+
blameSummary: blameMetadata.blameSummary
|
|
7284
7452
|
});
|
|
7285
|
-
if (
|
|
7453
|
+
if (existingContentHash === contentHash) {
|
|
7286
7454
|
fileChunkCount++;
|
|
7287
7455
|
continue;
|
|
7288
7456
|
}
|
|
@@ -7297,7 +7465,8 @@ var Indexer = class {
|
|
|
7297
7465
|
chunkType: chunk.chunkType,
|
|
7298
7466
|
name: chunk.name,
|
|
7299
7467
|
language: chunk.language,
|
|
7300
|
-
hash: contentHash
|
|
7468
|
+
hash: contentHash,
|
|
7469
|
+
...blameMetadata
|
|
7301
7470
|
};
|
|
7302
7471
|
pendingChunks.push({
|
|
7303
7472
|
id,
|
|
@@ -7440,6 +7609,9 @@ var Indexer = class {
|
|
|
7440
7609
|
database.addChunksToBranchBatch(branchCatalogKey, Array.from(currentChunkIds));
|
|
7441
7610
|
database.clearBranchSymbols(branchCatalogKey);
|
|
7442
7611
|
database.addSymbolsToBranchBatch(branchCatalogKey, Array.from(allSymbolIds));
|
|
7612
|
+
if (backfilledBlameMetadata) {
|
|
7613
|
+
store.save();
|
|
7614
|
+
}
|
|
7443
7615
|
if (scopedRoots) {
|
|
7444
7616
|
this.replaceScopedFileHashCache(currentFileHashes, scopedRoots);
|
|
7445
7617
|
this.clearScopedFailedBatches(scopedRoots);
|
|
@@ -8003,7 +8175,8 @@ var Indexer = class {
|
|
|
8003
8175
|
content,
|
|
8004
8176
|
score: r.score,
|
|
8005
8177
|
chunkType: r.metadata.chunkType,
|
|
8006
|
-
name: r.metadata.name
|
|
8178
|
+
name: r.metadata.name,
|
|
8179
|
+
blame: blameFromMetadata(r.metadata)
|
|
8007
8180
|
};
|
|
8008
8181
|
})
|
|
8009
8182
|
);
|
|
@@ -8095,12 +8268,12 @@ var Indexer = class {
|
|
|
8095
8268
|
this.indexCompatibility = compatibility;
|
|
8096
8269
|
return;
|
|
8097
8270
|
}
|
|
8098
|
-
const localProjectIndexPaths = [
|
|
8271
|
+
const localProjectIndexPaths = [path12.join(this.projectRoot, getHostProjectIndexRelativePath(this.host))];
|
|
8099
8272
|
if (this.host !== "opencode") {
|
|
8100
|
-
localProjectIndexPaths.push(
|
|
8273
|
+
localProjectIndexPaths.push(path12.join(this.projectRoot, getHostProjectIndexRelativePath("opencode")));
|
|
8101
8274
|
}
|
|
8102
8275
|
const isLocalProjectIndex = localProjectIndexPaths.some(
|
|
8103
|
-
(localPath) =>
|
|
8276
|
+
(localPath) => path12.resolve(this.indexPath) === path12.resolve(localPath)
|
|
8104
8277
|
);
|
|
8105
8278
|
if (!isLocalProjectIndex) {
|
|
8106
8279
|
throw new Error(
|
|
@@ -8190,7 +8363,7 @@ var Indexer = class {
|
|
|
8190
8363
|
gcOrphanSymbols: 0,
|
|
8191
8364
|
gcOrphanCallEdges: 0,
|
|
8192
8365
|
resetCorruptedIndex: true,
|
|
8193
|
-
warning: this.getCorruptedIndexWarning(
|
|
8366
|
+
warning: this.getCorruptedIndexWarning(path12.join(this.indexPath, "codebase.db"))
|
|
8194
8367
|
};
|
|
8195
8368
|
}
|
|
8196
8369
|
this.logger.recordGc(removedCount, gcOrphanChunks, gcOrphanEmbeddings);
|
|
@@ -8510,7 +8683,8 @@ var Indexer = class {
|
|
|
8510
8683
|
content,
|
|
8511
8684
|
score: r.score,
|
|
8512
8685
|
chunkType: r.metadata.chunkType,
|
|
8513
|
-
name: r.metadata.name
|
|
8686
|
+
name: r.metadata.name,
|
|
8687
|
+
blame: blameFromMetadata(r.metadata)
|
|
8514
8688
|
};
|
|
8515
8689
|
})
|
|
8516
8690
|
);
|
|
@@ -8547,9 +8721,9 @@ var Indexer = class {
|
|
|
8547
8721
|
const { database } = await this.ensureInitialized();
|
|
8548
8722
|
let shortest = [];
|
|
8549
8723
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
8550
|
-
const
|
|
8551
|
-
if (
|
|
8552
|
-
shortest =
|
|
8724
|
+
const path23 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
8725
|
+
if (path23.length > 0 && (shortest.length === 0 || path23.length < shortest.length)) {
|
|
8726
|
+
shortest = path23;
|
|
8553
8727
|
}
|
|
8554
8728
|
}
|
|
8555
8729
|
return shortest;
|
|
@@ -8581,7 +8755,7 @@ var Indexer = class {
|
|
|
8581
8755
|
}
|
|
8582
8756
|
async getPrImpact(opts) {
|
|
8583
8757
|
const { database } = await this.ensureInitialized();
|
|
8584
|
-
const
|
|
8758
|
+
const execFileAsync3 = (0, import_util3.promisify)(import_child_process3.execFile);
|
|
8585
8759
|
const changedFilesResult = await getChangedFiles({
|
|
8586
8760
|
pr: opts.pr,
|
|
8587
8761
|
branch: opts.branch,
|
|
@@ -8603,7 +8777,7 @@ var Indexer = class {
|
|
|
8603
8777
|
"Run index_codebase first to build the call graph and symbol index for this branch."
|
|
8604
8778
|
);
|
|
8605
8779
|
}
|
|
8606
|
-
const absoluteChangedFiles = changedFiles.map((f) =>
|
|
8780
|
+
const absoluteChangedFiles = changedFiles.map((f) => path12.resolve(this.projectRoot, f));
|
|
8607
8781
|
const directSymbols = database.getSymbolsForFiles(absoluteChangedFiles, branchKey);
|
|
8608
8782
|
const directIds = directSymbols.map((s) => s.id);
|
|
8609
8783
|
const direction = opts.direction ?? "both";
|
|
@@ -8665,7 +8839,7 @@ var Indexer = class {
|
|
|
8665
8839
|
if (opts.checkConflicts) {
|
|
8666
8840
|
conflictingPRs = [];
|
|
8667
8841
|
try {
|
|
8668
|
-
const { stdout } = await
|
|
8842
|
+
const { stdout } = await execFileAsync3(
|
|
8669
8843
|
"gh",
|
|
8670
8844
|
["pr", "list", "--state", "open", "--json", "number,headRefName", "--limit", "10000"],
|
|
8671
8845
|
{ cwd: this.projectRoot, timeout: 3e4 }
|
|
@@ -8686,7 +8860,7 @@ var Indexer = class {
|
|
|
8686
8860
|
projectRoot: this.projectRoot,
|
|
8687
8861
|
baseBranch: this.baseBranch
|
|
8688
8862
|
});
|
|
8689
|
-
const otherAbsolute = otherChanged.files.map((f) =>
|
|
8863
|
+
const otherAbsolute = otherChanged.files.map((f) => path12.resolve(this.projectRoot, f));
|
|
8690
8864
|
const otherBranchKey = this.getBranchCatalogKeyFor(openPr.headRefName);
|
|
8691
8865
|
const otherSymbols = database.getSymbolsForFiles(otherAbsolute, otherBranchKey);
|
|
8692
8866
|
const otherLabels = /* @__PURE__ */ new Set();
|
|
@@ -8749,12 +8923,12 @@ var Indexer = class {
|
|
|
8749
8923
|
if (meta.filePath) filePaths.add(meta.filePath);
|
|
8750
8924
|
}
|
|
8751
8925
|
const directory = options?.directory?.replace(/\/$/, "");
|
|
8752
|
-
const absoluteDirectoryFilter = directory ?
|
|
8926
|
+
const absoluteDirectoryFilter = directory ? path12.resolve(this.projectRoot, directory) : void 0;
|
|
8753
8927
|
for (const filePath of filePaths) {
|
|
8754
8928
|
if (directory) {
|
|
8755
|
-
const absoluteFilePath =
|
|
8929
|
+
const absoluteFilePath = path12.resolve(filePath);
|
|
8756
8930
|
const matchesRelative = filePath === directory || filePath.startsWith(directory + "/");
|
|
8757
|
-
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter +
|
|
8931
|
+
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter + path12.sep));
|
|
8758
8932
|
if (!matchesRelative && !matchesProjectRelative) {
|
|
8759
8933
|
continue;
|
|
8760
8934
|
}
|
|
@@ -8786,43 +8960,43 @@ var Indexer = class {
|
|
|
8786
8960
|
};
|
|
8787
8961
|
|
|
8788
8962
|
// src/tools/knowledge-base-paths.ts
|
|
8789
|
-
var
|
|
8963
|
+
var path13 = __toESM(require("path"), 1);
|
|
8790
8964
|
function resolveConfigPathValue(value, baseDir) {
|
|
8791
8965
|
const trimmed = value.trim();
|
|
8792
8966
|
if (!trimmed) {
|
|
8793
8967
|
return trimmed;
|
|
8794
8968
|
}
|
|
8795
|
-
const absolutePath =
|
|
8796
|
-
return
|
|
8969
|
+
const absolutePath = path13.isAbsolute(trimmed) ? trimmed : path13.resolve(baseDir, trimmed);
|
|
8970
|
+
return path13.normalize(absolutePath);
|
|
8797
8971
|
}
|
|
8798
8972
|
function serializeConfigPathValue(value, baseDir) {
|
|
8799
8973
|
const trimmed = value.trim();
|
|
8800
8974
|
if (!trimmed) {
|
|
8801
8975
|
return trimmed;
|
|
8802
8976
|
}
|
|
8803
|
-
if (!
|
|
8804
|
-
return normalizePathSeparators(
|
|
8977
|
+
if (!path13.isAbsolute(trimmed)) {
|
|
8978
|
+
return normalizePathSeparators(path13.normalize(trimmed));
|
|
8805
8979
|
}
|
|
8806
|
-
const relativePath =
|
|
8807
|
-
if (!relativePath || !relativePath.startsWith("..") && !
|
|
8808
|
-
return normalizePathSeparators(
|
|
8980
|
+
const relativePath = path13.relative(baseDir, trimmed);
|
|
8981
|
+
if (!relativePath || !relativePath.startsWith("..") && !path13.isAbsolute(relativePath)) {
|
|
8982
|
+
return normalizePathSeparators(path13.normalize(relativePath || "."));
|
|
8809
8983
|
}
|
|
8810
|
-
return
|
|
8984
|
+
return path13.normalize(trimmed);
|
|
8811
8985
|
}
|
|
8812
8986
|
function resolveKnowledgeBasePath(value, projectRoot) {
|
|
8813
|
-
return
|
|
8987
|
+
return path13.isAbsolute(value) ? value : path13.resolve(projectRoot, value);
|
|
8814
8988
|
}
|
|
8815
8989
|
function normalizeKnowledgeBasePath2(value, projectRoot) {
|
|
8816
|
-
return
|
|
8990
|
+
return path13.normalize(resolveKnowledgeBasePath(value, projectRoot));
|
|
8817
8991
|
}
|
|
8818
8992
|
function hasMatchingKnowledgeBasePath(knowledgeBases, inputPath, projectRoot) {
|
|
8819
|
-
const normalizedInput =
|
|
8993
|
+
const normalizedInput = path13.normalize(inputPath);
|
|
8820
8994
|
return knowledgeBases.some((kb) => normalizeKnowledgeBasePath2(kb, projectRoot) === normalizedInput);
|
|
8821
8995
|
}
|
|
8822
8996
|
function findKnowledgeBasePathIndex(knowledgeBases, inputPath, projectRoot) {
|
|
8823
|
-
const normalizedInput =
|
|
8997
|
+
const normalizedInput = path13.normalize(inputPath);
|
|
8824
8998
|
return knowledgeBases.findIndex(
|
|
8825
|
-
(kb) =>
|
|
8999
|
+
(kb) => path13.normalize(kb) === normalizedInput || normalizeKnowledgeBasePath2(kb, projectRoot) === normalizedInput
|
|
8826
9000
|
);
|
|
8827
9001
|
}
|
|
8828
9002
|
|
|
@@ -8974,7 +9148,7 @@ function formatCodebasePeek(results) {
|
|
|
8974
9148
|
const formatted = results.map((r, idx) => {
|
|
8975
9149
|
const location = `${r.filePath}:${r.startLine}-${r.endLine}`;
|
|
8976
9150
|
const name = r.name ? `"${r.name}"` : "(anonymous)";
|
|
8977
|
-
return `[${idx + 1}] ${r.chunkType} ${name} at ${location} (score: ${r.score.toFixed(2)})`;
|
|
9151
|
+
return `[${idx + 1}] ${r.chunkType} ${name} at ${location} (score: ${r.score.toFixed(2)})${formatBlame(r)}`;
|
|
8978
9152
|
});
|
|
8979
9153
|
return formatted.join("\n");
|
|
8980
9154
|
}
|
|
@@ -9006,16 +9180,57 @@ function formatHealthCheck(result) {
|
|
|
9006
9180
|
}
|
|
9007
9181
|
return lines.join("\n");
|
|
9008
9182
|
}
|
|
9183
|
+
function formatCallGraphCallers(name, callers, relationshipType) {
|
|
9184
|
+
if (callers.length === 0) {
|
|
9185
|
+
return `No callers found for "${name}"${relationshipType ? ` with type ${relationshipType}` : ""}. It may not be called by any tracked function, or the index needs updating.`;
|
|
9186
|
+
}
|
|
9187
|
+
const formatted = callers.map((edge, index) => {
|
|
9188
|
+
const confidence = edge.confidence !== "Direct" ? ` [${edge.confidence.toLowerCase()}]` : "";
|
|
9189
|
+
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]"}`;
|
|
9190
|
+
});
|
|
9191
|
+
return `"${name}" is called by ${callers.length} function(s):
|
|
9192
|
+
|
|
9193
|
+
${formatted.join("\n")}`;
|
|
9194
|
+
}
|
|
9195
|
+
function formatCallGraphCallees(symbolId, callees, relationshipType) {
|
|
9196
|
+
if (callees.length === 0) {
|
|
9197
|
+
return `No callees found for symbol ${symbolId}${relationshipType ? ` with type ${relationshipType}` : ""}. The function may not call any other tracked functions.`;
|
|
9198
|
+
}
|
|
9199
|
+
return callees.map((edge, index) => {
|
|
9200
|
+
const confidence = edge.confidence !== "Direct" ? ` [${edge.confidence.toLowerCase()}]` : "";
|
|
9201
|
+
return `[${index + 1}] \u2192 ${edge.targetName} (${edge.callType})${confidence} at line ${edge.line}${edge.isResolved ? ` [resolved: ${edge.toSymbolId}]` : " [unresolved]"}`;
|
|
9202
|
+
}).join("\n");
|
|
9203
|
+
}
|
|
9204
|
+
function formatCallGraphPath(from, to, path23) {
|
|
9205
|
+
if (path23.length === 0) {
|
|
9206
|
+
return `No path found between "${from}" and "${to}". They may be in disconnected components, or the call graph index needs updating.`;
|
|
9207
|
+
}
|
|
9208
|
+
const formatted = path23.map((hop, index) => {
|
|
9209
|
+
const prefix = index === 0 ? "[start]" : `--${hop.callType}-->`;
|
|
9210
|
+
const location = hop.filePath ? ` (${hop.filePath}:${hop.line})` : "";
|
|
9211
|
+
return `${prefix} ${hop.symbolName}${location}`;
|
|
9212
|
+
});
|
|
9213
|
+
return `Path (${path23.length} hops):
|
|
9214
|
+
${formatted.join("\n")}`;
|
|
9215
|
+
}
|
|
9009
9216
|
function formatResultHeader(result, index) {
|
|
9010
9217
|
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}`;
|
|
9011
9218
|
}
|
|
9219
|
+
function formatBlame(result) {
|
|
9220
|
+
if (!result.blame) {
|
|
9221
|
+
return "";
|
|
9222
|
+
}
|
|
9223
|
+
const date = new Date(result.blame.committedAt * 1e3).toISOString().slice(0, 10);
|
|
9224
|
+
return `
|
|
9225
|
+
${result.blame.sha.slice(0, 7)} | ${result.blame.author} | ${date} | ${result.blame.summary}`;
|
|
9226
|
+
}
|
|
9012
9227
|
function formatDefinitionLookup(results, query) {
|
|
9013
9228
|
if (results.length === 0) {
|
|
9014
9229
|
return `No definition found for "${query}". Try codebase_search for broader discovery, or verify the symbol name.`;
|
|
9015
9230
|
}
|
|
9016
9231
|
const formatted = results.map((r, idx) => {
|
|
9017
9232
|
const header = formatResultHeader(r, idx);
|
|
9018
|
-
return `${header} (score: ${r.score.toFixed(2)})
|
|
9233
|
+
return `${header} (score: ${r.score.toFixed(2)})${formatBlame(r)}
|
|
9019
9234
|
\`\`\`
|
|
9020
9235
|
${truncateContent(r.content)}
|
|
9021
9236
|
\`\`\``;
|
|
@@ -9026,7 +9241,7 @@ function formatSearchResults(results, scoreFormat = "similarity") {
|
|
|
9026
9241
|
const formatted = results.map((r, idx) => {
|
|
9027
9242
|
const header = formatResultHeader(r, idx);
|
|
9028
9243
|
const scoreLabel = scoreFormat === "similarity" ? `(similarity: ${(r.score * 100).toFixed(1)}%)` : `(score: ${r.score.toFixed(2)})`;
|
|
9029
|
-
return `${header} ${scoreLabel}
|
|
9244
|
+
return `${header} ${scoreLabel}${formatBlame(r)}
|
|
9030
9245
|
\`\`\`
|
|
9031
9246
|
${truncateContent(r.content)}
|
|
9032
9247
|
\`\`\``;
|
|
@@ -9036,7 +9251,7 @@ ${truncateContent(r.content)}
|
|
|
9036
9251
|
|
|
9037
9252
|
// src/tools/config-state.ts
|
|
9038
9253
|
var import_fs8 = require("fs");
|
|
9039
|
-
var
|
|
9254
|
+
var path14 = __toESM(require("path"), 1);
|
|
9040
9255
|
function normalizeKnowledgeBasePaths(config, projectRoot) {
|
|
9041
9256
|
const normalized = { ...config };
|
|
9042
9257
|
if (Array.isArray(normalized.knowledgeBases)) {
|
|
@@ -9063,8 +9278,8 @@ function loadEditableConfig(projectRoot, host = "opencode") {
|
|
|
9063
9278
|
}
|
|
9064
9279
|
function saveConfig(projectRoot, config, host = "opencode") {
|
|
9065
9280
|
const configPath = getConfigPath(projectRoot, host);
|
|
9066
|
-
const configDir =
|
|
9067
|
-
const configBaseDir =
|
|
9281
|
+
const configDir = path14.dirname(configPath);
|
|
9282
|
+
const configBaseDir = path14.dirname(configDir);
|
|
9068
9283
|
if (!(0, import_fs8.existsSync)(configDir)) {
|
|
9069
9284
|
(0, import_fs8.mkdirSync)(configDir, { recursive: true });
|
|
9070
9285
|
}
|
|
@@ -9125,7 +9340,7 @@ function refreshIndexerForDirectory(projectRoot, host = "opencode", config = par
|
|
|
9125
9340
|
}
|
|
9126
9341
|
function shouldForceLocalizeProjectIndex(projectRoot, host = "opencode") {
|
|
9127
9342
|
const root = getProjectRoot(projectRoot, host);
|
|
9128
|
-
const localIndexPath =
|
|
9343
|
+
const localIndexPath = path15.join(root, getHostProjectIndexRelativePath(host));
|
|
9129
9344
|
if ((0, import_fs9.existsSync)(localIndexPath)) {
|
|
9130
9345
|
return false;
|
|
9131
9346
|
}
|
|
@@ -9140,7 +9355,10 @@ async function searchCodebase(projectRoot, host, query, options = {}) {
|
|
|
9140
9355
|
chunkType: options.chunkType,
|
|
9141
9356
|
contextLines: options.contextLines,
|
|
9142
9357
|
metadataOnly: options.metadataOnly,
|
|
9143
|
-
definitionIntent: options.definitionIntent
|
|
9358
|
+
definitionIntent: options.definitionIntent,
|
|
9359
|
+
blameAuthor: options.blameAuthor,
|
|
9360
|
+
blameSha: options.blameSha,
|
|
9361
|
+
blameSince: options.blameSince
|
|
9144
9362
|
});
|
|
9145
9363
|
}
|
|
9146
9364
|
async function findSimilarCode(projectRoot, host, code, options = {}) {
|
|
@@ -9272,8 +9490,8 @@ async function getIndexLogs(projectRoot, host, args) {
|
|
|
9272
9490
|
function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
9273
9491
|
const root = getProjectRoot(projectRoot, host);
|
|
9274
9492
|
const inputPath = knowledgeBasePath.trim();
|
|
9275
|
-
const normalizedPath =
|
|
9276
|
-
|
|
9493
|
+
const normalizedPath = path15.resolve(
|
|
9494
|
+
path15.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, root)
|
|
9277
9495
|
);
|
|
9278
9496
|
if (!(0, import_fs9.existsSync)(normalizedPath)) {
|
|
9279
9497
|
return `Error: Directory does not exist: ${normalizedPath}`;
|
|
@@ -9309,7 +9527,7 @@ function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
|
9309
9527
|
}
|
|
9310
9528
|
}
|
|
9311
9529
|
for (const dotDir of sensitiveDotDirs) {
|
|
9312
|
-
const sensitiveDir =
|
|
9530
|
+
const sensitiveDir = path15.join(homeDir, dotDir);
|
|
9313
9531
|
if (sensitiveDir && (realPath === sensitiveDir || realPath.startsWith(`${sensitiveDir}/`))) {
|
|
9314
9532
|
return `Error: Adding sensitive directory as knowledge base is not allowed: ${normalizedPath}`;
|
|
9315
9533
|
}
|
|
@@ -9372,7 +9590,7 @@ function listKnowledgeBases(projectRoot, host) {
|
|
|
9372
9590
|
}
|
|
9373
9591
|
result += "\n";
|
|
9374
9592
|
}
|
|
9375
|
-
const hasHostConfig = (0, import_fs9.existsSync)(
|
|
9593
|
+
const hasHostConfig = (0, import_fs9.existsSync)(path15.join(root, getHostProjectConfigRelativePath(host)));
|
|
9376
9594
|
if (hasHostConfig) {
|
|
9377
9595
|
result += `
|
|
9378
9596
|
Config sources: 1 file(s).`;
|
|
@@ -9495,7 +9713,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
9495
9713
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
9496
9714
|
const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
|
|
9497
9715
|
if (wantBigintFsStats) {
|
|
9498
|
-
this._stat = (
|
|
9716
|
+
this._stat = (path23) => statMethod(path23, { bigint: true });
|
|
9499
9717
|
} else {
|
|
9500
9718
|
this._stat = statMethod;
|
|
9501
9719
|
}
|
|
@@ -9520,8 +9738,8 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
9520
9738
|
const par = this.parent;
|
|
9521
9739
|
const fil = par && par.files;
|
|
9522
9740
|
if (fil && fil.length > 0) {
|
|
9523
|
-
const { path:
|
|
9524
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
9741
|
+
const { path: path23, depth } = par;
|
|
9742
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path23));
|
|
9525
9743
|
const awaited = await Promise.all(slice);
|
|
9526
9744
|
for (const entry of awaited) {
|
|
9527
9745
|
if (!entry)
|
|
@@ -9561,20 +9779,20 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
9561
9779
|
this.reading = false;
|
|
9562
9780
|
}
|
|
9563
9781
|
}
|
|
9564
|
-
async _exploreDir(
|
|
9782
|
+
async _exploreDir(path23, depth) {
|
|
9565
9783
|
let files;
|
|
9566
9784
|
try {
|
|
9567
|
-
files = await (0, import_promises.readdir)(
|
|
9785
|
+
files = await (0, import_promises.readdir)(path23, this._rdOptions);
|
|
9568
9786
|
} catch (error) {
|
|
9569
9787
|
this._onError(error);
|
|
9570
9788
|
}
|
|
9571
|
-
return { files, depth, path:
|
|
9789
|
+
return { files, depth, path: path23 };
|
|
9572
9790
|
}
|
|
9573
|
-
async _formatEntry(dirent,
|
|
9791
|
+
async _formatEntry(dirent, path23) {
|
|
9574
9792
|
let entry;
|
|
9575
9793
|
const basename5 = this._isDirent ? dirent.name : dirent;
|
|
9576
9794
|
try {
|
|
9577
|
-
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(
|
|
9795
|
+
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path23, basename5));
|
|
9578
9796
|
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename5 };
|
|
9579
9797
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
9580
9798
|
} catch (err) {
|
|
@@ -9974,16 +10192,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
9974
10192
|
};
|
|
9975
10193
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
9976
10194
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
9977
|
-
function createFsWatchInstance(
|
|
10195
|
+
function createFsWatchInstance(path23, options, listener, errHandler, emitRaw) {
|
|
9978
10196
|
const handleEvent = (rawEvent, evPath) => {
|
|
9979
|
-
listener(
|
|
9980
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
9981
|
-
if (evPath &&
|
|
9982
|
-
fsWatchBroadcast(sp.resolve(
|
|
10197
|
+
listener(path23);
|
|
10198
|
+
emitRaw(rawEvent, evPath, { watchedPath: path23 });
|
|
10199
|
+
if (evPath && path23 !== evPath) {
|
|
10200
|
+
fsWatchBroadcast(sp.resolve(path23, evPath), KEY_LISTENERS, sp.join(path23, evPath));
|
|
9983
10201
|
}
|
|
9984
10202
|
};
|
|
9985
10203
|
try {
|
|
9986
|
-
return (0, import_node_fs.watch)(
|
|
10204
|
+
return (0, import_node_fs.watch)(path23, {
|
|
9987
10205
|
persistent: options.persistent
|
|
9988
10206
|
}, handleEvent);
|
|
9989
10207
|
} catch (error) {
|
|
@@ -9999,12 +10217,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
9999
10217
|
listener(val1, val2, val3);
|
|
10000
10218
|
});
|
|
10001
10219
|
};
|
|
10002
|
-
var setFsWatchListener = (
|
|
10220
|
+
var setFsWatchListener = (path23, fullPath, options, handlers) => {
|
|
10003
10221
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
10004
10222
|
let cont = FsWatchInstances.get(fullPath);
|
|
10005
10223
|
let watcher;
|
|
10006
10224
|
if (!options.persistent) {
|
|
10007
|
-
watcher = createFsWatchInstance(
|
|
10225
|
+
watcher = createFsWatchInstance(path23, options, listener, errHandler, rawEmitter);
|
|
10008
10226
|
if (!watcher)
|
|
10009
10227
|
return;
|
|
10010
10228
|
return watcher.close.bind(watcher);
|
|
@@ -10015,7 +10233,7 @@ var setFsWatchListener = (path22, fullPath, options, handlers) => {
|
|
|
10015
10233
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
10016
10234
|
} else {
|
|
10017
10235
|
watcher = createFsWatchInstance(
|
|
10018
|
-
|
|
10236
|
+
path23,
|
|
10019
10237
|
options,
|
|
10020
10238
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
10021
10239
|
errHandler,
|
|
@@ -10030,7 +10248,7 @@ var setFsWatchListener = (path22, fullPath, options, handlers) => {
|
|
|
10030
10248
|
cont.watcherUnusable = true;
|
|
10031
10249
|
if (isWindows && error.code === "EPERM") {
|
|
10032
10250
|
try {
|
|
10033
|
-
const fd = await (0, import_promises2.open)(
|
|
10251
|
+
const fd = await (0, import_promises2.open)(path23, "r");
|
|
10034
10252
|
await fd.close();
|
|
10035
10253
|
broadcastErr(error);
|
|
10036
10254
|
} catch (err) {
|
|
@@ -10061,7 +10279,7 @@ var setFsWatchListener = (path22, fullPath, options, handlers) => {
|
|
|
10061
10279
|
};
|
|
10062
10280
|
};
|
|
10063
10281
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
10064
|
-
var setFsWatchFileListener = (
|
|
10282
|
+
var setFsWatchFileListener = (path23, fullPath, options, handlers) => {
|
|
10065
10283
|
const { listener, rawEmitter } = handlers;
|
|
10066
10284
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
10067
10285
|
const copts = cont && cont.options;
|
|
@@ -10083,7 +10301,7 @@ var setFsWatchFileListener = (path22, fullPath, options, handlers) => {
|
|
|
10083
10301
|
});
|
|
10084
10302
|
const currmtime = curr.mtimeMs;
|
|
10085
10303
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
10086
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
10304
|
+
foreach(cont.listeners, (listener2) => listener2(path23, curr));
|
|
10087
10305
|
}
|
|
10088
10306
|
})
|
|
10089
10307
|
};
|
|
@@ -10113,13 +10331,13 @@ var NodeFsHandler = class {
|
|
|
10113
10331
|
* @param listener on fs change
|
|
10114
10332
|
* @returns closer for the watcher instance
|
|
10115
10333
|
*/
|
|
10116
|
-
_watchWithNodeFs(
|
|
10334
|
+
_watchWithNodeFs(path23, listener) {
|
|
10117
10335
|
const opts = this.fsw.options;
|
|
10118
|
-
const directory = sp.dirname(
|
|
10119
|
-
const basename5 = sp.basename(
|
|
10336
|
+
const directory = sp.dirname(path23);
|
|
10337
|
+
const basename5 = sp.basename(path23);
|
|
10120
10338
|
const parent = this.fsw._getWatchedDir(directory);
|
|
10121
10339
|
parent.add(basename5);
|
|
10122
|
-
const absolutePath = sp.resolve(
|
|
10340
|
+
const absolutePath = sp.resolve(path23);
|
|
10123
10341
|
const options = {
|
|
10124
10342
|
persistent: opts.persistent
|
|
10125
10343
|
};
|
|
@@ -10129,12 +10347,12 @@ var NodeFsHandler = class {
|
|
|
10129
10347
|
if (opts.usePolling) {
|
|
10130
10348
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
10131
10349
|
options.interval = enableBin && isBinaryPath(basename5) ? opts.binaryInterval : opts.interval;
|
|
10132
|
-
closer = setFsWatchFileListener(
|
|
10350
|
+
closer = setFsWatchFileListener(path23, absolutePath, options, {
|
|
10133
10351
|
listener,
|
|
10134
10352
|
rawEmitter: this.fsw._emitRaw
|
|
10135
10353
|
});
|
|
10136
10354
|
} else {
|
|
10137
|
-
closer = setFsWatchListener(
|
|
10355
|
+
closer = setFsWatchListener(path23, absolutePath, options, {
|
|
10138
10356
|
listener,
|
|
10139
10357
|
errHandler: this._boundHandleError,
|
|
10140
10358
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -10156,7 +10374,7 @@ var NodeFsHandler = class {
|
|
|
10156
10374
|
let prevStats = stats;
|
|
10157
10375
|
if (parent.has(basename5))
|
|
10158
10376
|
return;
|
|
10159
|
-
const listener = async (
|
|
10377
|
+
const listener = async (path23, newStats) => {
|
|
10160
10378
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
10161
10379
|
return;
|
|
10162
10380
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -10170,11 +10388,11 @@ var NodeFsHandler = class {
|
|
|
10170
10388
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
10171
10389
|
}
|
|
10172
10390
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
10173
|
-
this.fsw._closeFile(
|
|
10391
|
+
this.fsw._closeFile(path23);
|
|
10174
10392
|
prevStats = newStats2;
|
|
10175
10393
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
10176
10394
|
if (closer2)
|
|
10177
|
-
this.fsw._addPathCloser(
|
|
10395
|
+
this.fsw._addPathCloser(path23, closer2);
|
|
10178
10396
|
} else {
|
|
10179
10397
|
prevStats = newStats2;
|
|
10180
10398
|
}
|
|
@@ -10206,7 +10424,7 @@ var NodeFsHandler = class {
|
|
|
10206
10424
|
* @param item basename of this item
|
|
10207
10425
|
* @returns true if no more processing is needed for this entry.
|
|
10208
10426
|
*/
|
|
10209
|
-
async _handleSymlink(entry, directory,
|
|
10427
|
+
async _handleSymlink(entry, directory, path23, item) {
|
|
10210
10428
|
if (this.fsw.closed) {
|
|
10211
10429
|
return;
|
|
10212
10430
|
}
|
|
@@ -10216,7 +10434,7 @@ var NodeFsHandler = class {
|
|
|
10216
10434
|
this.fsw._incrReadyCount();
|
|
10217
10435
|
let linkPath;
|
|
10218
10436
|
try {
|
|
10219
|
-
linkPath = await (0, import_promises2.realpath)(
|
|
10437
|
+
linkPath = await (0, import_promises2.realpath)(path23);
|
|
10220
10438
|
} catch (e) {
|
|
10221
10439
|
this.fsw._emitReady();
|
|
10222
10440
|
return true;
|
|
@@ -10226,12 +10444,12 @@ var NodeFsHandler = class {
|
|
|
10226
10444
|
if (dir.has(item)) {
|
|
10227
10445
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
10228
10446
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
10229
|
-
this.fsw._emit(EV.CHANGE,
|
|
10447
|
+
this.fsw._emit(EV.CHANGE, path23, entry.stats);
|
|
10230
10448
|
}
|
|
10231
10449
|
} else {
|
|
10232
10450
|
dir.add(item);
|
|
10233
10451
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
10234
|
-
this.fsw._emit(EV.ADD,
|
|
10452
|
+
this.fsw._emit(EV.ADD, path23, entry.stats);
|
|
10235
10453
|
}
|
|
10236
10454
|
this.fsw._emitReady();
|
|
10237
10455
|
return true;
|
|
@@ -10261,9 +10479,9 @@ var NodeFsHandler = class {
|
|
|
10261
10479
|
return;
|
|
10262
10480
|
}
|
|
10263
10481
|
const item = entry.path;
|
|
10264
|
-
let
|
|
10482
|
+
let path23 = sp.join(directory, item);
|
|
10265
10483
|
current.add(item);
|
|
10266
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
10484
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path23, item)) {
|
|
10267
10485
|
return;
|
|
10268
10486
|
}
|
|
10269
10487
|
if (this.fsw.closed) {
|
|
@@ -10272,8 +10490,8 @@ var NodeFsHandler = class {
|
|
|
10272
10490
|
}
|
|
10273
10491
|
if (item === target || !target && !previous.has(item)) {
|
|
10274
10492
|
this.fsw._incrReadyCount();
|
|
10275
|
-
|
|
10276
|
-
this._addToNodeFs(
|
|
10493
|
+
path23 = sp.join(dir, sp.relative(dir, path23));
|
|
10494
|
+
this._addToNodeFs(path23, initialAdd, wh, depth + 1);
|
|
10277
10495
|
}
|
|
10278
10496
|
}).on(EV.ERROR, this._boundHandleError);
|
|
10279
10497
|
return new Promise((resolve13, reject) => {
|
|
@@ -10342,13 +10560,13 @@ var NodeFsHandler = class {
|
|
|
10342
10560
|
* @param depth Child path actually targeted for watch
|
|
10343
10561
|
* @param target Child path actually targeted for watch
|
|
10344
10562
|
*/
|
|
10345
|
-
async _addToNodeFs(
|
|
10563
|
+
async _addToNodeFs(path23, initialAdd, priorWh, depth, target) {
|
|
10346
10564
|
const ready = this.fsw._emitReady;
|
|
10347
|
-
if (this.fsw._isIgnored(
|
|
10565
|
+
if (this.fsw._isIgnored(path23) || this.fsw.closed) {
|
|
10348
10566
|
ready();
|
|
10349
10567
|
return false;
|
|
10350
10568
|
}
|
|
10351
|
-
const wh = this.fsw._getWatchHelpers(
|
|
10569
|
+
const wh = this.fsw._getWatchHelpers(path23);
|
|
10352
10570
|
if (priorWh) {
|
|
10353
10571
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
10354
10572
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -10364,8 +10582,8 @@ var NodeFsHandler = class {
|
|
|
10364
10582
|
const follow = this.fsw.options.followSymlinks;
|
|
10365
10583
|
let closer;
|
|
10366
10584
|
if (stats.isDirectory()) {
|
|
10367
|
-
const absPath = sp.resolve(
|
|
10368
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
10585
|
+
const absPath = sp.resolve(path23);
|
|
10586
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path23) : path23;
|
|
10369
10587
|
if (this.fsw.closed)
|
|
10370
10588
|
return;
|
|
10371
10589
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -10375,29 +10593,29 @@ var NodeFsHandler = class {
|
|
|
10375
10593
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
10376
10594
|
}
|
|
10377
10595
|
} else if (stats.isSymbolicLink()) {
|
|
10378
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
10596
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path23) : path23;
|
|
10379
10597
|
if (this.fsw.closed)
|
|
10380
10598
|
return;
|
|
10381
10599
|
const parent = sp.dirname(wh.watchPath);
|
|
10382
10600
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
10383
10601
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
10384
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
10602
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path23, wh, targetPath);
|
|
10385
10603
|
if (this.fsw.closed)
|
|
10386
10604
|
return;
|
|
10387
10605
|
if (targetPath !== void 0) {
|
|
10388
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
10606
|
+
this.fsw._symlinkPaths.set(sp.resolve(path23), targetPath);
|
|
10389
10607
|
}
|
|
10390
10608
|
} else {
|
|
10391
10609
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
10392
10610
|
}
|
|
10393
10611
|
ready();
|
|
10394
10612
|
if (closer)
|
|
10395
|
-
this.fsw._addPathCloser(
|
|
10613
|
+
this.fsw._addPathCloser(path23, closer);
|
|
10396
10614
|
return false;
|
|
10397
10615
|
} catch (error) {
|
|
10398
10616
|
if (this.fsw._handleError(error)) {
|
|
10399
10617
|
ready();
|
|
10400
|
-
return
|
|
10618
|
+
return path23;
|
|
10401
10619
|
}
|
|
10402
10620
|
}
|
|
10403
10621
|
}
|
|
@@ -10429,35 +10647,35 @@ function createPattern(matcher) {
|
|
|
10429
10647
|
if (matcher.path === string)
|
|
10430
10648
|
return true;
|
|
10431
10649
|
if (matcher.recursive) {
|
|
10432
|
-
const
|
|
10433
|
-
if (!
|
|
10650
|
+
const relative11 = sp2.relative(matcher.path, string);
|
|
10651
|
+
if (!relative11) {
|
|
10434
10652
|
return false;
|
|
10435
10653
|
}
|
|
10436
|
-
return !
|
|
10654
|
+
return !relative11.startsWith("..") && !sp2.isAbsolute(relative11);
|
|
10437
10655
|
}
|
|
10438
10656
|
return false;
|
|
10439
10657
|
};
|
|
10440
10658
|
}
|
|
10441
10659
|
return () => false;
|
|
10442
10660
|
}
|
|
10443
|
-
function normalizePath(
|
|
10444
|
-
if (typeof
|
|
10661
|
+
function normalizePath(path23) {
|
|
10662
|
+
if (typeof path23 !== "string")
|
|
10445
10663
|
throw new Error("string expected");
|
|
10446
|
-
|
|
10447
|
-
|
|
10664
|
+
path23 = sp2.normalize(path23);
|
|
10665
|
+
path23 = path23.replace(/\\/g, "/");
|
|
10448
10666
|
let prepend = false;
|
|
10449
|
-
if (
|
|
10667
|
+
if (path23.startsWith("//"))
|
|
10450
10668
|
prepend = true;
|
|
10451
|
-
|
|
10669
|
+
path23 = path23.replace(DOUBLE_SLASH_RE, "/");
|
|
10452
10670
|
if (prepend)
|
|
10453
|
-
|
|
10454
|
-
return
|
|
10671
|
+
path23 = "/" + path23;
|
|
10672
|
+
return path23;
|
|
10455
10673
|
}
|
|
10456
10674
|
function matchPatterns(patterns, testString, stats) {
|
|
10457
|
-
const
|
|
10675
|
+
const path23 = normalizePath(testString);
|
|
10458
10676
|
for (let index = 0; index < patterns.length; index++) {
|
|
10459
10677
|
const pattern = patterns[index];
|
|
10460
|
-
if (pattern(
|
|
10678
|
+
if (pattern(path23, stats)) {
|
|
10461
10679
|
return true;
|
|
10462
10680
|
}
|
|
10463
10681
|
}
|
|
@@ -10495,19 +10713,19 @@ var toUnix = (string) => {
|
|
|
10495
10713
|
}
|
|
10496
10714
|
return str;
|
|
10497
10715
|
};
|
|
10498
|
-
var normalizePathToUnix = (
|
|
10499
|
-
var normalizeIgnored = (cwd = "") => (
|
|
10500
|
-
if (typeof
|
|
10501
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
10716
|
+
var normalizePathToUnix = (path23) => toUnix(sp2.normalize(toUnix(path23)));
|
|
10717
|
+
var normalizeIgnored = (cwd = "") => (path23) => {
|
|
10718
|
+
if (typeof path23 === "string") {
|
|
10719
|
+
return normalizePathToUnix(sp2.isAbsolute(path23) ? path23 : sp2.join(cwd, path23));
|
|
10502
10720
|
} else {
|
|
10503
|
-
return
|
|
10721
|
+
return path23;
|
|
10504
10722
|
}
|
|
10505
10723
|
};
|
|
10506
|
-
var getAbsolutePath = (
|
|
10507
|
-
if (sp2.isAbsolute(
|
|
10508
|
-
return
|
|
10724
|
+
var getAbsolutePath = (path23, cwd) => {
|
|
10725
|
+
if (sp2.isAbsolute(path23)) {
|
|
10726
|
+
return path23;
|
|
10509
10727
|
}
|
|
10510
|
-
return sp2.join(cwd,
|
|
10728
|
+
return sp2.join(cwd, path23);
|
|
10511
10729
|
};
|
|
10512
10730
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
10513
10731
|
var DirEntry = class {
|
|
@@ -10572,10 +10790,10 @@ var WatchHelper = class {
|
|
|
10572
10790
|
dirParts;
|
|
10573
10791
|
followSymlinks;
|
|
10574
10792
|
statMethod;
|
|
10575
|
-
constructor(
|
|
10793
|
+
constructor(path23, follow, fsw) {
|
|
10576
10794
|
this.fsw = fsw;
|
|
10577
|
-
const watchPath =
|
|
10578
|
-
this.path =
|
|
10795
|
+
const watchPath = path23;
|
|
10796
|
+
this.path = path23 = path23.replace(REPLACER_RE, "");
|
|
10579
10797
|
this.watchPath = watchPath;
|
|
10580
10798
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
10581
10799
|
this.dirParts = [];
|
|
@@ -10715,20 +10933,20 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
10715
10933
|
this._closePromise = void 0;
|
|
10716
10934
|
let paths = unifyPaths(paths_);
|
|
10717
10935
|
if (cwd) {
|
|
10718
|
-
paths = paths.map((
|
|
10719
|
-
const absPath = getAbsolutePath(
|
|
10936
|
+
paths = paths.map((path23) => {
|
|
10937
|
+
const absPath = getAbsolutePath(path23, cwd);
|
|
10720
10938
|
return absPath;
|
|
10721
10939
|
});
|
|
10722
10940
|
}
|
|
10723
|
-
paths.forEach((
|
|
10724
|
-
this._removeIgnoredPath(
|
|
10941
|
+
paths.forEach((path23) => {
|
|
10942
|
+
this._removeIgnoredPath(path23);
|
|
10725
10943
|
});
|
|
10726
10944
|
this._userIgnored = void 0;
|
|
10727
10945
|
if (!this._readyCount)
|
|
10728
10946
|
this._readyCount = 0;
|
|
10729
10947
|
this._readyCount += paths.length;
|
|
10730
|
-
Promise.all(paths.map(async (
|
|
10731
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
10948
|
+
Promise.all(paths.map(async (path23) => {
|
|
10949
|
+
const res = await this._nodeFsHandler._addToNodeFs(path23, !_internal, void 0, 0, _origAdd);
|
|
10732
10950
|
if (res)
|
|
10733
10951
|
this._emitReady();
|
|
10734
10952
|
return res;
|
|
@@ -10750,17 +10968,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
10750
10968
|
return this;
|
|
10751
10969
|
const paths = unifyPaths(paths_);
|
|
10752
10970
|
const { cwd } = this.options;
|
|
10753
|
-
paths.forEach((
|
|
10754
|
-
if (!sp2.isAbsolute(
|
|
10971
|
+
paths.forEach((path23) => {
|
|
10972
|
+
if (!sp2.isAbsolute(path23) && !this._closers.has(path23)) {
|
|
10755
10973
|
if (cwd)
|
|
10756
|
-
|
|
10757
|
-
|
|
10974
|
+
path23 = sp2.join(cwd, path23);
|
|
10975
|
+
path23 = sp2.resolve(path23);
|
|
10758
10976
|
}
|
|
10759
|
-
this._closePath(
|
|
10760
|
-
this._addIgnoredPath(
|
|
10761
|
-
if (this._watched.has(
|
|
10977
|
+
this._closePath(path23);
|
|
10978
|
+
this._addIgnoredPath(path23);
|
|
10979
|
+
if (this._watched.has(path23)) {
|
|
10762
10980
|
this._addIgnoredPath({
|
|
10763
|
-
path:
|
|
10981
|
+
path: path23,
|
|
10764
10982
|
recursive: true
|
|
10765
10983
|
});
|
|
10766
10984
|
}
|
|
@@ -10824,38 +11042,38 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
10824
11042
|
* @param stats arguments to be passed with event
|
|
10825
11043
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
10826
11044
|
*/
|
|
10827
|
-
async _emit(event,
|
|
11045
|
+
async _emit(event, path23, stats) {
|
|
10828
11046
|
if (this.closed)
|
|
10829
11047
|
return;
|
|
10830
11048
|
const opts = this.options;
|
|
10831
11049
|
if (isWindows)
|
|
10832
|
-
|
|
11050
|
+
path23 = sp2.normalize(path23);
|
|
10833
11051
|
if (opts.cwd)
|
|
10834
|
-
|
|
10835
|
-
const args = [
|
|
11052
|
+
path23 = sp2.relative(opts.cwd, path23);
|
|
11053
|
+
const args = [path23];
|
|
10836
11054
|
if (stats != null)
|
|
10837
11055
|
args.push(stats);
|
|
10838
11056
|
const awf = opts.awaitWriteFinish;
|
|
10839
11057
|
let pw;
|
|
10840
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
11058
|
+
if (awf && (pw = this._pendingWrites.get(path23))) {
|
|
10841
11059
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
10842
11060
|
return this;
|
|
10843
11061
|
}
|
|
10844
11062
|
if (opts.atomic) {
|
|
10845
11063
|
if (event === EVENTS.UNLINK) {
|
|
10846
|
-
this._pendingUnlinks.set(
|
|
11064
|
+
this._pendingUnlinks.set(path23, [event, ...args]);
|
|
10847
11065
|
setTimeout(() => {
|
|
10848
|
-
this._pendingUnlinks.forEach((entry,
|
|
11066
|
+
this._pendingUnlinks.forEach((entry, path24) => {
|
|
10849
11067
|
this.emit(...entry);
|
|
10850
11068
|
this.emit(EVENTS.ALL, ...entry);
|
|
10851
|
-
this._pendingUnlinks.delete(
|
|
11069
|
+
this._pendingUnlinks.delete(path24);
|
|
10852
11070
|
});
|
|
10853
11071
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
10854
11072
|
return this;
|
|
10855
11073
|
}
|
|
10856
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
11074
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path23)) {
|
|
10857
11075
|
event = EVENTS.CHANGE;
|
|
10858
|
-
this._pendingUnlinks.delete(
|
|
11076
|
+
this._pendingUnlinks.delete(path23);
|
|
10859
11077
|
}
|
|
10860
11078
|
}
|
|
10861
11079
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -10873,16 +11091,16 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
10873
11091
|
this.emitWithAll(event, args);
|
|
10874
11092
|
}
|
|
10875
11093
|
};
|
|
10876
|
-
this._awaitWriteFinish(
|
|
11094
|
+
this._awaitWriteFinish(path23, awf.stabilityThreshold, event, awfEmit);
|
|
10877
11095
|
return this;
|
|
10878
11096
|
}
|
|
10879
11097
|
if (event === EVENTS.CHANGE) {
|
|
10880
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
11098
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path23, 50);
|
|
10881
11099
|
if (isThrottled)
|
|
10882
11100
|
return this;
|
|
10883
11101
|
}
|
|
10884
11102
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
10885
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
11103
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path23) : path23;
|
|
10886
11104
|
let stats2;
|
|
10887
11105
|
try {
|
|
10888
11106
|
stats2 = await (0, import_promises3.stat)(fullPath);
|
|
@@ -10913,23 +11131,23 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
10913
11131
|
* @param timeout duration of time to suppress duplicate actions
|
|
10914
11132
|
* @returns tracking object or false if action should be suppressed
|
|
10915
11133
|
*/
|
|
10916
|
-
_throttle(actionType,
|
|
11134
|
+
_throttle(actionType, path23, timeout) {
|
|
10917
11135
|
if (!this._throttled.has(actionType)) {
|
|
10918
11136
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
10919
11137
|
}
|
|
10920
11138
|
const action = this._throttled.get(actionType);
|
|
10921
11139
|
if (!action)
|
|
10922
11140
|
throw new Error("invalid throttle");
|
|
10923
|
-
const actionPath = action.get(
|
|
11141
|
+
const actionPath = action.get(path23);
|
|
10924
11142
|
if (actionPath) {
|
|
10925
11143
|
actionPath.count++;
|
|
10926
11144
|
return false;
|
|
10927
11145
|
}
|
|
10928
11146
|
let timeoutObject;
|
|
10929
11147
|
const clear = () => {
|
|
10930
|
-
const item = action.get(
|
|
11148
|
+
const item = action.get(path23);
|
|
10931
11149
|
const count = item ? item.count : 0;
|
|
10932
|
-
action.delete(
|
|
11150
|
+
action.delete(path23);
|
|
10933
11151
|
clearTimeout(timeoutObject);
|
|
10934
11152
|
if (item)
|
|
10935
11153
|
clearTimeout(item.timeoutObject);
|
|
@@ -10937,7 +11155,7 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
10937
11155
|
};
|
|
10938
11156
|
timeoutObject = setTimeout(clear, timeout);
|
|
10939
11157
|
const thr = { timeoutObject, clear, count: 0 };
|
|
10940
|
-
action.set(
|
|
11158
|
+
action.set(path23, thr);
|
|
10941
11159
|
return thr;
|
|
10942
11160
|
}
|
|
10943
11161
|
_incrReadyCount() {
|
|
@@ -10951,44 +11169,44 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
10951
11169
|
* @param event
|
|
10952
11170
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
10953
11171
|
*/
|
|
10954
|
-
_awaitWriteFinish(
|
|
11172
|
+
_awaitWriteFinish(path23, threshold, event, awfEmit) {
|
|
10955
11173
|
const awf = this.options.awaitWriteFinish;
|
|
10956
11174
|
if (typeof awf !== "object")
|
|
10957
11175
|
return;
|
|
10958
11176
|
const pollInterval = awf.pollInterval;
|
|
10959
11177
|
let timeoutHandler;
|
|
10960
|
-
let fullPath =
|
|
10961
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
10962
|
-
fullPath = sp2.join(this.options.cwd,
|
|
11178
|
+
let fullPath = path23;
|
|
11179
|
+
if (this.options.cwd && !sp2.isAbsolute(path23)) {
|
|
11180
|
+
fullPath = sp2.join(this.options.cwd, path23);
|
|
10963
11181
|
}
|
|
10964
11182
|
const now = /* @__PURE__ */ new Date();
|
|
10965
11183
|
const writes = this._pendingWrites;
|
|
10966
11184
|
function awaitWriteFinishFn(prevStat) {
|
|
10967
11185
|
(0, import_node_fs2.stat)(fullPath, (err, curStat) => {
|
|
10968
|
-
if (err || !writes.has(
|
|
11186
|
+
if (err || !writes.has(path23)) {
|
|
10969
11187
|
if (err && err.code !== "ENOENT")
|
|
10970
11188
|
awfEmit(err);
|
|
10971
11189
|
return;
|
|
10972
11190
|
}
|
|
10973
11191
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
10974
11192
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
10975
|
-
writes.get(
|
|
11193
|
+
writes.get(path23).lastChange = now2;
|
|
10976
11194
|
}
|
|
10977
|
-
const pw = writes.get(
|
|
11195
|
+
const pw = writes.get(path23);
|
|
10978
11196
|
const df = now2 - pw.lastChange;
|
|
10979
11197
|
if (df >= threshold) {
|
|
10980
|
-
writes.delete(
|
|
11198
|
+
writes.delete(path23);
|
|
10981
11199
|
awfEmit(void 0, curStat);
|
|
10982
11200
|
} else {
|
|
10983
11201
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
10984
11202
|
}
|
|
10985
11203
|
});
|
|
10986
11204
|
}
|
|
10987
|
-
if (!writes.has(
|
|
10988
|
-
writes.set(
|
|
11205
|
+
if (!writes.has(path23)) {
|
|
11206
|
+
writes.set(path23, {
|
|
10989
11207
|
lastChange: now,
|
|
10990
11208
|
cancelWait: () => {
|
|
10991
|
-
writes.delete(
|
|
11209
|
+
writes.delete(path23);
|
|
10992
11210
|
clearTimeout(timeoutHandler);
|
|
10993
11211
|
return event;
|
|
10994
11212
|
}
|
|
@@ -10999,8 +11217,8 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
10999
11217
|
/**
|
|
11000
11218
|
* Determines whether user has asked to ignore this path.
|
|
11001
11219
|
*/
|
|
11002
|
-
_isIgnored(
|
|
11003
|
-
if (this.options.atomic && DOT_RE.test(
|
|
11220
|
+
_isIgnored(path23, stats) {
|
|
11221
|
+
if (this.options.atomic && DOT_RE.test(path23))
|
|
11004
11222
|
return true;
|
|
11005
11223
|
if (!this._userIgnored) {
|
|
11006
11224
|
const { cwd } = this.options;
|
|
@@ -11010,17 +11228,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
11010
11228
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
11011
11229
|
this._userIgnored = anymatch(list, void 0);
|
|
11012
11230
|
}
|
|
11013
|
-
return this._userIgnored(
|
|
11231
|
+
return this._userIgnored(path23, stats);
|
|
11014
11232
|
}
|
|
11015
|
-
_isntIgnored(
|
|
11016
|
-
return !this._isIgnored(
|
|
11233
|
+
_isntIgnored(path23, stat4) {
|
|
11234
|
+
return !this._isIgnored(path23, stat4);
|
|
11017
11235
|
}
|
|
11018
11236
|
/**
|
|
11019
11237
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
11020
11238
|
* @param path file or directory pattern being watched
|
|
11021
11239
|
*/
|
|
11022
|
-
_getWatchHelpers(
|
|
11023
|
-
return new WatchHelper(
|
|
11240
|
+
_getWatchHelpers(path23) {
|
|
11241
|
+
return new WatchHelper(path23, this.options.followSymlinks, this);
|
|
11024
11242
|
}
|
|
11025
11243
|
// Directory helpers
|
|
11026
11244
|
// -----------------
|
|
@@ -11052,63 +11270,63 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
11052
11270
|
* @param item base path of item/directory
|
|
11053
11271
|
*/
|
|
11054
11272
|
_remove(directory, item, isDirectory) {
|
|
11055
|
-
const
|
|
11056
|
-
const fullPath = sp2.resolve(
|
|
11057
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
11058
|
-
if (!this._throttle("remove",
|
|
11273
|
+
const path23 = sp2.join(directory, item);
|
|
11274
|
+
const fullPath = sp2.resolve(path23);
|
|
11275
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path23) || this._watched.has(fullPath);
|
|
11276
|
+
if (!this._throttle("remove", path23, 100))
|
|
11059
11277
|
return;
|
|
11060
11278
|
if (!isDirectory && this._watched.size === 1) {
|
|
11061
11279
|
this.add(directory, item, true);
|
|
11062
11280
|
}
|
|
11063
|
-
const wp = this._getWatchedDir(
|
|
11281
|
+
const wp = this._getWatchedDir(path23);
|
|
11064
11282
|
const nestedDirectoryChildren = wp.getChildren();
|
|
11065
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
11283
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path23, nested));
|
|
11066
11284
|
const parent = this._getWatchedDir(directory);
|
|
11067
11285
|
const wasTracked = parent.has(item);
|
|
11068
11286
|
parent.remove(item);
|
|
11069
11287
|
if (this._symlinkPaths.has(fullPath)) {
|
|
11070
11288
|
this._symlinkPaths.delete(fullPath);
|
|
11071
11289
|
}
|
|
11072
|
-
let relPath =
|
|
11290
|
+
let relPath = path23;
|
|
11073
11291
|
if (this.options.cwd)
|
|
11074
|
-
relPath = sp2.relative(this.options.cwd,
|
|
11292
|
+
relPath = sp2.relative(this.options.cwd, path23);
|
|
11075
11293
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
11076
11294
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
11077
11295
|
if (event === EVENTS.ADD)
|
|
11078
11296
|
return;
|
|
11079
11297
|
}
|
|
11080
|
-
this._watched.delete(
|
|
11298
|
+
this._watched.delete(path23);
|
|
11081
11299
|
this._watched.delete(fullPath);
|
|
11082
11300
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
11083
|
-
if (wasTracked && !this._isIgnored(
|
|
11084
|
-
this._emit(eventName,
|
|
11085
|
-
this._closePath(
|
|
11301
|
+
if (wasTracked && !this._isIgnored(path23))
|
|
11302
|
+
this._emit(eventName, path23);
|
|
11303
|
+
this._closePath(path23);
|
|
11086
11304
|
}
|
|
11087
11305
|
/**
|
|
11088
11306
|
* Closes all watchers for a path
|
|
11089
11307
|
*/
|
|
11090
|
-
_closePath(
|
|
11091
|
-
this._closeFile(
|
|
11092
|
-
const dir = sp2.dirname(
|
|
11093
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
11308
|
+
_closePath(path23) {
|
|
11309
|
+
this._closeFile(path23);
|
|
11310
|
+
const dir = sp2.dirname(path23);
|
|
11311
|
+
this._getWatchedDir(dir).remove(sp2.basename(path23));
|
|
11094
11312
|
}
|
|
11095
11313
|
/**
|
|
11096
11314
|
* Closes only file-specific watchers
|
|
11097
11315
|
*/
|
|
11098
|
-
_closeFile(
|
|
11099
|
-
const closers = this._closers.get(
|
|
11316
|
+
_closeFile(path23) {
|
|
11317
|
+
const closers = this._closers.get(path23);
|
|
11100
11318
|
if (!closers)
|
|
11101
11319
|
return;
|
|
11102
11320
|
closers.forEach((closer) => closer());
|
|
11103
|
-
this._closers.delete(
|
|
11321
|
+
this._closers.delete(path23);
|
|
11104
11322
|
}
|
|
11105
|
-
_addPathCloser(
|
|
11323
|
+
_addPathCloser(path23, closer) {
|
|
11106
11324
|
if (!closer)
|
|
11107
11325
|
return;
|
|
11108
|
-
let list = this._closers.get(
|
|
11326
|
+
let list = this._closers.get(path23);
|
|
11109
11327
|
if (!list) {
|
|
11110
11328
|
list = [];
|
|
11111
|
-
this._closers.set(
|
|
11329
|
+
this._closers.set(path23, list);
|
|
11112
11330
|
}
|
|
11113
11331
|
list.push(closer);
|
|
11114
11332
|
}
|
|
@@ -11138,7 +11356,7 @@ function watch(paths, options = {}) {
|
|
|
11138
11356
|
var chokidar_default = { watch, FSWatcher };
|
|
11139
11357
|
|
|
11140
11358
|
// src/watcher/file-watcher.ts
|
|
11141
|
-
var
|
|
11359
|
+
var path16 = __toESM(require("path"), 1);
|
|
11142
11360
|
var FileWatcher = class {
|
|
11143
11361
|
watcher = null;
|
|
11144
11362
|
projectRoot;
|
|
@@ -11164,15 +11382,15 @@ var FileWatcher = class {
|
|
|
11164
11382
|
const watchTargets = this.configPath ? [this.projectRoot, this.configPath] : this.projectRoot;
|
|
11165
11383
|
this.watcher = chokidar_default.watch(watchTargets, {
|
|
11166
11384
|
ignored: (filePath) => {
|
|
11167
|
-
const relativePath =
|
|
11385
|
+
const relativePath = path16.relative(this.projectRoot, filePath);
|
|
11168
11386
|
if (!relativePath) return false;
|
|
11169
11387
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
11170
11388
|
return false;
|
|
11171
11389
|
}
|
|
11172
|
-
if (hasFilteredPathSegment(relativePath,
|
|
11390
|
+
if (hasFilteredPathSegment(relativePath, path16.sep)) {
|
|
11173
11391
|
return true;
|
|
11174
11392
|
}
|
|
11175
|
-
if (isRestrictedDirectory(relativePath,
|
|
11393
|
+
if (isRestrictedDirectory(relativePath, path16.sep)) {
|
|
11176
11394
|
return true;
|
|
11177
11395
|
}
|
|
11178
11396
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -11218,24 +11436,24 @@ var FileWatcher = class {
|
|
|
11218
11436
|
this.scheduleFlush();
|
|
11219
11437
|
}
|
|
11220
11438
|
isProjectConfigPath(filePath) {
|
|
11221
|
-
const relativePath =
|
|
11222
|
-
const normalizedRelativePath =
|
|
11439
|
+
const relativePath = path16.relative(this.projectRoot, filePath);
|
|
11440
|
+
const normalizedRelativePath = path16.normalize(relativePath);
|
|
11223
11441
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
11224
11442
|
}
|
|
11225
11443
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
11226
|
-
const normalizedRelativePath =
|
|
11444
|
+
const normalizedRelativePath = path16.normalize(relativePath);
|
|
11227
11445
|
return this.getProjectConfigRelativePaths().some(
|
|
11228
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
11446
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path16.sep}`)
|
|
11229
11447
|
);
|
|
11230
11448
|
}
|
|
11231
11449
|
getProjectConfigRelativePaths() {
|
|
11232
11450
|
if (this.configPath) {
|
|
11233
|
-
return [
|
|
11451
|
+
return [path16.normalize(path16.relative(this.projectRoot, this.configPath))];
|
|
11234
11452
|
}
|
|
11235
11453
|
return [
|
|
11236
11454
|
resolveProjectConfigPath(this.projectRoot, this.host),
|
|
11237
11455
|
resolveWritableProjectConfigPath(this.projectRoot, this.host)
|
|
11238
|
-
].map((configPath) =>
|
|
11456
|
+
].map((configPath) => path16.normalize(path16.relative(this.projectRoot, configPath)));
|
|
11239
11457
|
}
|
|
11240
11458
|
scheduleFlush() {
|
|
11241
11459
|
if (this.debounceTimer) {
|
|
@@ -11250,7 +11468,7 @@ var FileWatcher = class {
|
|
|
11250
11468
|
return;
|
|
11251
11469
|
}
|
|
11252
11470
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
11253
|
-
([
|
|
11471
|
+
([path23, type]) => ({ path: path23, type })
|
|
11254
11472
|
);
|
|
11255
11473
|
this.pendingChanges.clear();
|
|
11256
11474
|
try {
|
|
@@ -11277,7 +11495,7 @@ var FileWatcher = class {
|
|
|
11277
11495
|
};
|
|
11278
11496
|
|
|
11279
11497
|
// src/watcher/git-head-watcher.ts
|
|
11280
|
-
var
|
|
11498
|
+
var path17 = __toESM(require("path"), 1);
|
|
11281
11499
|
var GitHeadWatcher = class {
|
|
11282
11500
|
watcher = null;
|
|
11283
11501
|
projectRoot;
|
|
@@ -11299,7 +11517,7 @@ var GitHeadWatcher = class {
|
|
|
11299
11517
|
this.onBranchChange = handler;
|
|
11300
11518
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
11301
11519
|
const headPath = getHeadPath(this.projectRoot);
|
|
11302
|
-
const refsPath =
|
|
11520
|
+
const refsPath = path17.join(this.projectRoot, ".git", "refs", "heads");
|
|
11303
11521
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
11304
11522
|
persistent: true,
|
|
11305
11523
|
ignoreInitial: true,
|
|
@@ -11532,11 +11750,11 @@ var pr_impact = (0, import_plugin.tool)({
|
|
|
11532
11750
|
// src/tools/index.ts
|
|
11533
11751
|
var import_fs10 = require("fs");
|
|
11534
11752
|
var os4 = __toESM(require("os"), 1);
|
|
11535
|
-
var
|
|
11753
|
+
var path20 = __toESM(require("path"), 1);
|
|
11536
11754
|
|
|
11537
11755
|
// src/tools/visualize/activity.ts
|
|
11538
|
-
var
|
|
11539
|
-
var
|
|
11756
|
+
var import_child_process4 = require("child_process");
|
|
11757
|
+
var path18 = __toESM(require("path"), 1);
|
|
11540
11758
|
function attachRecentActivity(data, projectRoot) {
|
|
11541
11759
|
const activity = readGitActivity(projectRoot);
|
|
11542
11760
|
const changes = activity.size > 0 ? buildGitChanges(data, activity, projectRoot) : buildGraphChanges(data);
|
|
@@ -11547,7 +11765,7 @@ function attachRecentActivity(data, projectRoot) {
|
|
|
11547
11765
|
}
|
|
11548
11766
|
function readGitActivity(projectRoot) {
|
|
11549
11767
|
try {
|
|
11550
|
-
const output = (0,
|
|
11768
|
+
const output = (0, import_child_process4.execFileSync)(
|
|
11551
11769
|
"git",
|
|
11552
11770
|
["-C", projectRoot, "log", "--since=90.days", "--numstat", "--date=short", "--pretty=format:__COMMIT__%x09%h%x09%ad%x09%s"],
|
|
11553
11771
|
{ encoding: "utf8", maxBuffer: 8 * 1024 * 1024, stdio: ["ignore", "pipe", "ignore"] }
|
|
@@ -11698,7 +11916,7 @@ function normalizePath2(filePath) {
|
|
|
11698
11916
|
return filePath.replace(/\\/g, "/");
|
|
11699
11917
|
}
|
|
11700
11918
|
function toGitRelativePath(projectRoot, filePath) {
|
|
11701
|
-
const relativePath =
|
|
11919
|
+
const relativePath = path18.isAbsolute(filePath) ? path18.relative(projectRoot, filePath) : filePath;
|
|
11702
11920
|
return normalizePath2(relativePath);
|
|
11703
11921
|
}
|
|
11704
11922
|
|
|
@@ -11956,7 +12174,7 @@ render();
|
|
|
11956
12174
|
}
|
|
11957
12175
|
|
|
11958
12176
|
// src/tools/visualize/transform.ts
|
|
11959
|
-
var
|
|
12177
|
+
var path19 = __toESM(require("path"), 1);
|
|
11960
12178
|
|
|
11961
12179
|
// src/tools/visualize/modules.ts
|
|
11962
12180
|
var MAX_MODULES = 18;
|
|
@@ -12089,8 +12307,8 @@ function compactModules(prefixToNodes) {
|
|
|
12089
12307
|
function deriveModules(nodes) {
|
|
12090
12308
|
const initial = /* @__PURE__ */ new Map();
|
|
12091
12309
|
for (const node of nodes) {
|
|
12092
|
-
const
|
|
12093
|
-
const prefix = modulePrefixFromRelativePath(
|
|
12310
|
+
const relative11 = stripToProjectRelative(node.filePath);
|
|
12311
|
+
const prefix = modulePrefixFromRelativePath(relative11);
|
|
12094
12312
|
if (!initial.has(prefix)) initial.set(prefix, []);
|
|
12095
12313
|
initial.get(prefix)?.push(node);
|
|
12096
12314
|
}
|
|
@@ -12216,7 +12434,7 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
12216
12434
|
filePath: s.filePath,
|
|
12217
12435
|
kind: s.kind,
|
|
12218
12436
|
line: s.startLine,
|
|
12219
|
-
directory:
|
|
12437
|
+
directory: path19.dirname(s.filePath),
|
|
12220
12438
|
moduleId: "",
|
|
12221
12439
|
moduleLabel: ""
|
|
12222
12440
|
}));
|
|
@@ -12267,7 +12485,10 @@ var codebase_peek = (0, import_plugin2.tool)({
|
|
|
12267
12485
|
limit: z2.number().optional().default(10).describe("Maximum number of results to return"),
|
|
12268
12486
|
fileType: z2.string().optional().describe("Filter by file extension (e.g., 'ts', 'py', 'rs')"),
|
|
12269
12487
|
directory: z2.string().optional().describe("Filter by directory path (e.g., 'src/utils', 'lib')"),
|
|
12270
|
-
chunkType: z2.enum(CHUNK_TYPE_VALUES).optional().describe("Filter by code chunk type")
|
|
12488
|
+
chunkType: z2.enum(CHUNK_TYPE_VALUES).optional().describe("Filter by code chunk type"),
|
|
12489
|
+
blameAuthor: z2.string().optional().describe("Filter by git blame author name or email"),
|
|
12490
|
+
blameSha: z2.string().optional().describe("Filter by git blame commit SHA or prefix"),
|
|
12491
|
+
blameSince: z2.string().optional().describe("Filter to chunks last changed on or after this date (e.g., 2025-01-01)")
|
|
12271
12492
|
},
|
|
12272
12493
|
async execute(args, context) {
|
|
12273
12494
|
const results = await searchCodebase(context?.worktree, DEFAULT_HOST, args.query, {
|
|
@@ -12275,7 +12496,10 @@ var codebase_peek = (0, import_plugin2.tool)({
|
|
|
12275
12496
|
fileType: args.fileType,
|
|
12276
12497
|
directory: args.directory,
|
|
12277
12498
|
chunkType: args.chunkType,
|
|
12278
|
-
metadataOnly: true
|
|
12499
|
+
metadataOnly: true,
|
|
12500
|
+
blameAuthor: args.blameAuthor,
|
|
12501
|
+
blameSha: args.blameSha,
|
|
12502
|
+
blameSince: args.blameSince
|
|
12279
12503
|
});
|
|
12280
12504
|
return formatCodebasePeek(results);
|
|
12281
12505
|
}
|
|
@@ -12358,7 +12582,10 @@ var codebase_search = (0, import_plugin2.tool)({
|
|
|
12358
12582
|
fileType: z2.string().optional().describe("Filter by file extension (e.g., 'ts', 'py', 'rs')"),
|
|
12359
12583
|
directory: z2.string().optional().describe("Filter by directory path (e.g., 'src/utils', 'lib')"),
|
|
12360
12584
|
chunkType: z2.enum(CHUNK_TYPE_VALUES).optional().describe("Filter by code chunk type"),
|
|
12361
|
-
contextLines: z2.number().optional().describe("Number of extra lines to include before/after each match (default: 0)")
|
|
12585
|
+
contextLines: z2.number().optional().describe("Number of extra lines to include before/after each match (default: 0)"),
|
|
12586
|
+
blameAuthor: z2.string().optional().describe("Filter by git blame author name or email"),
|
|
12587
|
+
blameSha: z2.string().optional().describe("Filter by git blame commit SHA or prefix"),
|
|
12588
|
+
blameSince: z2.string().optional().describe("Filter to chunks last changed on or after this date (e.g., 2025-01-01)")
|
|
12362
12589
|
},
|
|
12363
12590
|
async execute(args, context) {
|
|
12364
12591
|
const results = await searchCodebase(context?.worktree, DEFAULT_HOST, args.query, {
|
|
@@ -12366,7 +12593,10 @@ var codebase_search = (0, import_plugin2.tool)({
|
|
|
12366
12593
|
fileType: args.fileType,
|
|
12367
12594
|
directory: args.directory,
|
|
12368
12595
|
chunkType: args.chunkType,
|
|
12369
|
-
contextLines: args.contextLines
|
|
12596
|
+
contextLines: args.contextLines,
|
|
12597
|
+
blameAuthor: args.blameAuthor,
|
|
12598
|
+
blameSha: args.blameSha,
|
|
12599
|
+
blameSince: args.blameSince
|
|
12370
12600
|
});
|
|
12371
12601
|
if (results.length === 0) {
|
|
12372
12602
|
return "No matching code found. Try a different query or run index_codebase first.";
|
|
@@ -12405,22 +12635,10 @@ var call_graph = (0, import_plugin2.tool)({
|
|
|
12405
12635
|
return "Error: 'symbolId' is required when direction is 'callees'. First use direction='callers' to find the symbol ID.";
|
|
12406
12636
|
}
|
|
12407
12637
|
const { callees } = await getCallGraphData(context?.worktree, DEFAULT_HOST, args);
|
|
12408
|
-
|
|
12409
|
-
return `No callees found for symbol ${args.symbolId}${args.relationshipType ? ` with type ${args.relationshipType}` : ""}. The function may not call any other tracked functions.`;
|
|
12410
|
-
}
|
|
12411
|
-
return callees.map((edge, index) => {
|
|
12412
|
-
const confidence = edge.confidence !== "Direct" ? ` [${edge.confidence.toLowerCase()}]` : "";
|
|
12413
|
-
return `[${index + 1}] \u2192 ${edge.targetName} (${edge.callType})${confidence} at line ${edge.line}${edge.isResolved ? ` [resolved: ${edge.toSymbolId}]` : " [unresolved]"}`;
|
|
12414
|
-
}).join("\n");
|
|
12638
|
+
return formatCallGraphCallees(args.symbolId, callees, args.relationshipType);
|
|
12415
12639
|
}
|
|
12416
12640
|
const { callers } = await getCallGraphData(context?.worktree, DEFAULT_HOST, args);
|
|
12417
|
-
|
|
12418
|
-
return `No callers found for "${args.name}"${args.relationshipType ? ` with type ${args.relationshipType}` : ""}. It may not be called by any tracked function, or the index needs updating.`;
|
|
12419
|
-
}
|
|
12420
|
-
return callers.map((edge, index) => {
|
|
12421
|
-
const confidence = edge.confidence !== "Direct" ? ` [${edge.confidence.toLowerCase()}]` : "";
|
|
12422
|
-
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]"}`;
|
|
12423
|
-
}).join("\n");
|
|
12641
|
+
return formatCallGraphCallers(args.name, callers, args.relationshipType);
|
|
12424
12642
|
}
|
|
12425
12643
|
});
|
|
12426
12644
|
var call_graph_path = (0, import_plugin2.tool)({
|
|
@@ -12431,17 +12649,8 @@ var call_graph_path = (0, import_plugin2.tool)({
|
|
|
12431
12649
|
maxDepth: z2.number().optional().default(10).describe("Maximum traversal depth (default: 10)")
|
|
12432
12650
|
},
|
|
12433
12651
|
async execute(args, context) {
|
|
12434
|
-
const
|
|
12435
|
-
|
|
12436
|
-
return `No path found between "${args.from}" and "${args.to}". They may be in disconnected components, or the call graph index needs updating.`;
|
|
12437
|
-
}
|
|
12438
|
-
const formatted = path22.map((hop, index) => {
|
|
12439
|
-
const prefix = index === 0 ? "[start]" : `--${hop.callType}-->`;
|
|
12440
|
-
const location = hop.filePath ? ` (${hop.filePath}:${hop.line})` : "";
|
|
12441
|
-
return `${prefix} ${hop.symbolName}${location}`;
|
|
12442
|
-
});
|
|
12443
|
-
return `Path (${path22.length} hops):
|
|
12444
|
-
${formatted.join("\n")}`;
|
|
12652
|
+
const path23 = await getCallGraphPath(context?.worktree, DEFAULT_HOST, args.from, args.to, args.maxDepth);
|
|
12653
|
+
return formatCallGraphPath(args.from, args.to, path23);
|
|
12445
12654
|
}
|
|
12446
12655
|
});
|
|
12447
12656
|
var add_knowledge_base = (0, import_plugin2.tool)({
|
|
@@ -12494,7 +12703,7 @@ var index_visualize = (0, import_plugin2.tool)({
|
|
|
12494
12703
|
return "No connected symbols found for visualization. Try including orphans with includeOrphans=true, or check that the call graph has resolved edges.";
|
|
12495
12704
|
}
|
|
12496
12705
|
const html = generateVisualizationHtml(vizData);
|
|
12497
|
-
const outputPath =
|
|
12706
|
+
const outputPath = path20.join(os4.tmpdir(), `call-graph-${Date.now()}.html`);
|
|
12498
12707
|
(0, import_fs10.writeFileSync)(outputPath, html, "utf-8");
|
|
12499
12708
|
let result = `Temporal call graph visualization generated: ${outputPath}
|
|
12500
12709
|
|
|
@@ -12517,7 +12726,7 @@ var index_visualize = (0, import_plugin2.tool)({
|
|
|
12517
12726
|
|
|
12518
12727
|
// src/commands/loader.ts
|
|
12519
12728
|
var import_fs11 = require("fs");
|
|
12520
|
-
var
|
|
12729
|
+
var path21 = __toESM(require("path"), 1);
|
|
12521
12730
|
function parseFrontmatter(content) {
|
|
12522
12731
|
const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
|
|
12523
12732
|
const match = content.match(frontmatterRegex);
|
|
@@ -12543,7 +12752,7 @@ function loadCommandsFromDirectory(commandsDir) {
|
|
|
12543
12752
|
}
|
|
12544
12753
|
const files = (0, import_fs11.readdirSync)(commandsDir).filter((f) => f.endsWith(".md"));
|
|
12545
12754
|
for (const file of files) {
|
|
12546
|
-
const filePath =
|
|
12755
|
+
const filePath = path21.join(commandsDir, file);
|
|
12547
12756
|
let content;
|
|
12548
12757
|
try {
|
|
12549
12758
|
content = (0, import_fs11.readFileSync)(filePath, "utf-8");
|
|
@@ -12552,7 +12761,7 @@ function loadCommandsFromDirectory(commandsDir) {
|
|
|
12552
12761
|
throw new Error(`Failed to load command file ${filePath}: ${message}`);
|
|
12553
12762
|
}
|
|
12554
12763
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
12555
|
-
const name =
|
|
12764
|
+
const name = path21.basename(file, ".md");
|
|
12556
12765
|
const description = frontmatter.description || `Run the ${name} command`;
|
|
12557
12766
|
commands.set(name, {
|
|
12558
12767
|
description,
|
|
@@ -12885,9 +13094,9 @@ function replaceActiveWatcher(projectRoot, nextWatcher) {
|
|
|
12885
13094
|
function getCommandsDir() {
|
|
12886
13095
|
let currentDir = process.cwd();
|
|
12887
13096
|
if (typeof import_meta2 !== "undefined" && import_meta2.url) {
|
|
12888
|
-
currentDir =
|
|
13097
|
+
currentDir = path22.dirname((0, import_url2.fileURLToPath)(import_meta2.url));
|
|
12889
13098
|
}
|
|
12890
|
-
return
|
|
13099
|
+
return path22.join(currentDir, "..", "commands");
|
|
12891
13100
|
}
|
|
12892
13101
|
function appendRoutingHints(output, hints, preferredRole) {
|
|
12893
13102
|
const preferredBucket = preferredRole === "developer" ? output.developer : output.system;
|
|
@@ -12907,7 +13116,7 @@ var plugin = async ({ directory, worktree }) => {
|
|
|
12907
13116
|
initializeTools2(projectRoot, config);
|
|
12908
13117
|
const getProjectIndexer = () => getIndexerForProject2(projectRoot);
|
|
12909
13118
|
const routingHints = config.search.routingHints ? new RoutingHintController(() => getProjectIndexer().getStatus(), 200, config.search.routingGraphHandoffHints) : null;
|
|
12910
|
-
const isHomeDir =
|
|
13119
|
+
const isHomeDir = path22.resolve(projectRoot) === path22.resolve(os5.homedir());
|
|
12911
13120
|
const isValidProject = !isHomeDir && (!config.indexing.requireProjectMarker || hasProjectMarker(projectRoot));
|
|
12912
13121
|
if (isHomeDir) {
|
|
12913
13122
|
console.warn(
|