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.js
CHANGED
|
@@ -490,7 +490,7 @@ var require_ignore = __commonJS({
|
|
|
490
490
|
// path matching.
|
|
491
491
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
492
492
|
// @returns {TestResult} true if a file is ignored
|
|
493
|
-
test(
|
|
493
|
+
test(path23, checkUnignored, mode) {
|
|
494
494
|
let ignored = false;
|
|
495
495
|
let unignored = false;
|
|
496
496
|
let matchedRule;
|
|
@@ -499,7 +499,7 @@ var require_ignore = __commonJS({
|
|
|
499
499
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
500
500
|
return;
|
|
501
501
|
}
|
|
502
|
-
const matched = rule[mode].test(
|
|
502
|
+
const matched = rule[mode].test(path23);
|
|
503
503
|
if (!matched) {
|
|
504
504
|
return;
|
|
505
505
|
}
|
|
@@ -520,17 +520,17 @@ var require_ignore = __commonJS({
|
|
|
520
520
|
var throwError = (message, Ctor) => {
|
|
521
521
|
throw new Ctor(message);
|
|
522
522
|
};
|
|
523
|
-
var checkPath = (
|
|
524
|
-
if (!isString(
|
|
523
|
+
var checkPath = (path23, originalPath, doThrow) => {
|
|
524
|
+
if (!isString(path23)) {
|
|
525
525
|
return doThrow(
|
|
526
526
|
`path must be a string, but got \`${originalPath}\``,
|
|
527
527
|
TypeError
|
|
528
528
|
);
|
|
529
529
|
}
|
|
530
|
-
if (!
|
|
530
|
+
if (!path23) {
|
|
531
531
|
return doThrow(`path must not be empty`, TypeError);
|
|
532
532
|
}
|
|
533
|
-
if (checkPath.isNotRelative(
|
|
533
|
+
if (checkPath.isNotRelative(path23)) {
|
|
534
534
|
const r = "`path.relative()`d";
|
|
535
535
|
return doThrow(
|
|
536
536
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -539,7 +539,7 @@ var require_ignore = __commonJS({
|
|
|
539
539
|
}
|
|
540
540
|
return true;
|
|
541
541
|
};
|
|
542
|
-
var isNotRelative = (
|
|
542
|
+
var isNotRelative = (path23) => REGEX_TEST_INVALID_PATH.test(path23);
|
|
543
543
|
checkPath.isNotRelative = isNotRelative;
|
|
544
544
|
checkPath.convert = (p) => p;
|
|
545
545
|
var Ignore2 = class {
|
|
@@ -569,19 +569,19 @@ var require_ignore = __commonJS({
|
|
|
569
569
|
}
|
|
570
570
|
// @returns {TestResult}
|
|
571
571
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
572
|
-
const
|
|
572
|
+
const path23 = originalPath && checkPath.convert(originalPath);
|
|
573
573
|
checkPath(
|
|
574
|
-
|
|
574
|
+
path23,
|
|
575
575
|
originalPath,
|
|
576
576
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
577
577
|
);
|
|
578
|
-
return this._t(
|
|
578
|
+
return this._t(path23, cache, checkUnignored, slices);
|
|
579
579
|
}
|
|
580
|
-
checkIgnore(
|
|
581
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
582
|
-
return this.test(
|
|
580
|
+
checkIgnore(path23) {
|
|
581
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path23)) {
|
|
582
|
+
return this.test(path23);
|
|
583
583
|
}
|
|
584
|
-
const slices =
|
|
584
|
+
const slices = path23.split(SLASH2).filter(Boolean);
|
|
585
585
|
slices.pop();
|
|
586
586
|
if (slices.length) {
|
|
587
587
|
const parent = this._t(
|
|
@@ -594,18 +594,18 @@ var require_ignore = __commonJS({
|
|
|
594
594
|
return parent;
|
|
595
595
|
}
|
|
596
596
|
}
|
|
597
|
-
return this._rules.test(
|
|
597
|
+
return this._rules.test(path23, false, MODE_CHECK_IGNORE);
|
|
598
598
|
}
|
|
599
|
-
_t(
|
|
600
|
-
if (
|
|
601
|
-
return cache[
|
|
599
|
+
_t(path23, cache, checkUnignored, slices) {
|
|
600
|
+
if (path23 in cache) {
|
|
601
|
+
return cache[path23];
|
|
602
602
|
}
|
|
603
603
|
if (!slices) {
|
|
604
|
-
slices =
|
|
604
|
+
slices = path23.split(SLASH2).filter(Boolean);
|
|
605
605
|
}
|
|
606
606
|
slices.pop();
|
|
607
607
|
if (!slices.length) {
|
|
608
|
-
return cache[
|
|
608
|
+
return cache[path23] = this._rules.test(path23, checkUnignored, MODE_IGNORE);
|
|
609
609
|
}
|
|
610
610
|
const parent = this._t(
|
|
611
611
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -613,29 +613,29 @@ var require_ignore = __commonJS({
|
|
|
613
613
|
checkUnignored,
|
|
614
614
|
slices
|
|
615
615
|
);
|
|
616
|
-
return cache[
|
|
616
|
+
return cache[path23] = parent.ignored ? parent : this._rules.test(path23, checkUnignored, MODE_IGNORE);
|
|
617
617
|
}
|
|
618
|
-
ignores(
|
|
619
|
-
return this._test(
|
|
618
|
+
ignores(path23) {
|
|
619
|
+
return this._test(path23, this._ignoreCache, false).ignored;
|
|
620
620
|
}
|
|
621
621
|
createFilter() {
|
|
622
|
-
return (
|
|
622
|
+
return (path23) => !this.ignores(path23);
|
|
623
623
|
}
|
|
624
624
|
filter(paths) {
|
|
625
625
|
return makeArray(paths).filter(this.createFilter());
|
|
626
626
|
}
|
|
627
627
|
// @returns {TestResult}
|
|
628
|
-
test(
|
|
629
|
-
return this._test(
|
|
628
|
+
test(path23) {
|
|
629
|
+
return this._test(path23, this._testCache, true);
|
|
630
630
|
}
|
|
631
631
|
};
|
|
632
632
|
var factory = (options) => new Ignore2(options);
|
|
633
|
-
var isPathValid = (
|
|
633
|
+
var isPathValid = (path23) => checkPath(path23 && checkPath.convert(path23), path23, RETURN_FALSE);
|
|
634
634
|
var setupWindows = () => {
|
|
635
635
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
636
636
|
checkPath.convert = makePosix;
|
|
637
637
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
638
|
-
checkPath.isNotRelative = (
|
|
638
|
+
checkPath.isNotRelative = (path23) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path23) || isNotRelative(path23);
|
|
639
639
|
};
|
|
640
640
|
if (
|
|
641
641
|
// Detect `process` so that it can run in browsers.
|
|
@@ -652,7 +652,7 @@ var require_ignore = __commonJS({
|
|
|
652
652
|
|
|
653
653
|
// src/index.ts
|
|
654
654
|
import * as os5 from "os";
|
|
655
|
-
import * as
|
|
655
|
+
import * as path22 from "path";
|
|
656
656
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
657
657
|
|
|
658
658
|
// src/config/constants.ts
|
|
@@ -785,7 +785,8 @@ function getDefaultIndexingConfig() {
|
|
|
785
785
|
requireProjectMarker: true,
|
|
786
786
|
maxDepth: 5,
|
|
787
787
|
maxFilesPerDirectory: 100,
|
|
788
|
-
fallbackToTextOnMaxChunks: true
|
|
788
|
+
fallbackToTextOnMaxChunks: true,
|
|
789
|
+
gitBlame: { enabled: false }
|
|
789
790
|
};
|
|
790
791
|
}
|
|
791
792
|
function getDefaultSearchConfig() {
|
|
@@ -909,7 +910,10 @@ function parseConfig(raw) {
|
|
|
909
910
|
requireProjectMarker: typeof rawIndexing.requireProjectMarker === "boolean" ? rawIndexing.requireProjectMarker : defaultIndexing.requireProjectMarker,
|
|
910
911
|
maxDepth: typeof rawIndexing.maxDepth === "number" ? rawIndexing.maxDepth < -1 ? -1 : rawIndexing.maxDepth : defaultIndexing.maxDepth,
|
|
911
912
|
maxFilesPerDirectory: typeof rawIndexing.maxFilesPerDirectory === "number" ? Math.max(1, rawIndexing.maxFilesPerDirectory) : defaultIndexing.maxFilesPerDirectory,
|
|
912
|
-
fallbackToTextOnMaxChunks: typeof rawIndexing.fallbackToTextOnMaxChunks === "boolean" ? rawIndexing.fallbackToTextOnMaxChunks : defaultIndexing.fallbackToTextOnMaxChunks
|
|
913
|
+
fallbackToTextOnMaxChunks: typeof rawIndexing.fallbackToTextOnMaxChunks === "boolean" ? rawIndexing.fallbackToTextOnMaxChunks : defaultIndexing.fallbackToTextOnMaxChunks,
|
|
914
|
+
gitBlame: {
|
|
915
|
+
enabled: rawIndexing.gitBlame && typeof rawIndexing.gitBlame === "object" && typeof rawIndexing.gitBlame.enabled === "boolean" ? rawIndexing.gitBlame.enabled : defaultIndexing.gitBlame.enabled
|
|
916
|
+
}
|
|
913
917
|
};
|
|
914
918
|
const rawSearch = input.search && typeof input.search === "object" ? input.search : {};
|
|
915
919
|
const search = {
|
|
@@ -1579,14 +1583,14 @@ function loadMergedConfig(projectRoot, host = "opencode") {
|
|
|
1579
1583
|
|
|
1580
1584
|
// src/tools/operations.ts
|
|
1581
1585
|
import { existsSync as existsSync9, realpathSync, statSync as statSync3 } from "fs";
|
|
1582
|
-
import * as
|
|
1586
|
+
import * as path15 from "path";
|
|
1583
1587
|
|
|
1584
1588
|
// src/indexer/index.ts
|
|
1585
1589
|
import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync2, renameSync, unlinkSync, mkdirSync as mkdirSync2, promises as fsPromises2 } from "fs";
|
|
1586
|
-
import * as
|
|
1590
|
+
import * as path12 from "path";
|
|
1587
1591
|
import { performance as performance2 } from "perf_hooks";
|
|
1588
|
-
import { execFile as
|
|
1589
|
-
import { promisify as
|
|
1592
|
+
import { execFile as execFile3 } from "child_process";
|
|
1593
|
+
import { promisify as promisify3 } from "util";
|
|
1590
1594
|
|
|
1591
1595
|
// node_modules/eventemitter3/index.mjs
|
|
1592
1596
|
var import_index = __toESM(require_eventemitter3(), 1);
|
|
@@ -4773,8 +4777,8 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
4773
4777
|
const trimmed = raw.trim();
|
|
4774
4778
|
if (!trimmed) continue;
|
|
4775
4779
|
const absolute = path10.resolve(projectRoot, trimmed);
|
|
4776
|
-
const
|
|
4777
|
-
const cleaned =
|
|
4780
|
+
const relative11 = path10.relative(projectRoot, absolute);
|
|
4781
|
+
const cleaned = relative11.startsWith("./") ? relative11.slice(2) : relative11;
|
|
4778
4782
|
if (!seen.has(cleaned)) {
|
|
4779
4783
|
seen.add(cleaned);
|
|
4780
4784
|
result.push(cleaned);
|
|
@@ -4783,8 +4787,61 @@ function normalizeFiles(rawFiles, projectRoot) {
|
|
|
4783
4787
|
return result;
|
|
4784
4788
|
}
|
|
4785
4789
|
|
|
4790
|
+
// src/indexer/git-blame.ts
|
|
4791
|
+
import { execFile as execFile2 } from "child_process";
|
|
4792
|
+
import * as path11 from "path";
|
|
4793
|
+
import { promisify as promisify2 } from "util";
|
|
4794
|
+
var execFileAsync2 = promisify2(execFile2);
|
|
4795
|
+
function parseGitBlamePorcelain(output) {
|
|
4796
|
+
const commits = /* @__PURE__ */ new Map();
|
|
4797
|
+
let current;
|
|
4798
|
+
for (const line of output.split("\n")) {
|
|
4799
|
+
if (/^[0-9a-f]{40} /.test(line)) {
|
|
4800
|
+
const sha = line.slice(0, 40);
|
|
4801
|
+
current = commits.get(sha) ?? {
|
|
4802
|
+
sha,
|
|
4803
|
+
author: "",
|
|
4804
|
+
authorEmail: "",
|
|
4805
|
+
committedAt: 0,
|
|
4806
|
+
summary: "",
|
|
4807
|
+
lines: 0
|
|
4808
|
+
};
|
|
4809
|
+
commits.set(sha, current);
|
|
4810
|
+
continue;
|
|
4811
|
+
}
|
|
4812
|
+
if (!current) {
|
|
4813
|
+
continue;
|
|
4814
|
+
}
|
|
4815
|
+
if (line.startsWith("author ")) {
|
|
4816
|
+
current.author = line.slice("author ".length);
|
|
4817
|
+
} else if (line.startsWith("author-mail ")) {
|
|
4818
|
+
current.authorEmail = line.slice("author-mail ".length).replace(/^<|>$/g, "");
|
|
4819
|
+
} else if (line.startsWith("author-time ")) {
|
|
4820
|
+
current.committedAt = Number.parseInt(line.slice("author-time ".length), 10);
|
|
4821
|
+
} else if (line.startsWith("summary ")) {
|
|
4822
|
+
current.summary = line.slice("summary ".length);
|
|
4823
|
+
} else if (line.startsWith(" ")) {
|
|
4824
|
+
current.lines += 1;
|
|
4825
|
+
}
|
|
4826
|
+
}
|
|
4827
|
+
return Array.from(commits.values()).filter((commit) => commit.lines > 0).sort((a, b) => b.lines - a.lines || b.committedAt - a.committedAt)[0];
|
|
4828
|
+
}
|
|
4829
|
+
async function getChunkGitBlame(projectRoot, filePath, startLine, endLine) {
|
|
4830
|
+
const relativePath = path11.relative(projectRoot, filePath);
|
|
4831
|
+
try {
|
|
4832
|
+
const { stdout } = await execFileAsync2(
|
|
4833
|
+
"git",
|
|
4834
|
+
["blame", "--line-porcelain", "-L", `${startLine},${endLine}`, "--", relativePath],
|
|
4835
|
+
{ cwd: projectRoot, timeout: 3e4 }
|
|
4836
|
+
);
|
|
4837
|
+
return parseGitBlamePorcelain(stdout);
|
|
4838
|
+
} catch {
|
|
4839
|
+
return void 0;
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4842
|
+
|
|
4786
4843
|
// src/indexer/index.ts
|
|
4787
|
-
var CALL_GRAPH_LANGUAGES = /* @__PURE__ */ new Set(["typescript", "tsx", "javascript", "jsx", "python", "go", "rust", "php", "apex", "zig", "gdscript", "matlab"]);
|
|
4844
|
+
var CALL_GRAPH_LANGUAGES = /* @__PURE__ */ new Set(["typescript", "tsx", "javascript", "jsx", "python", "go", "rust", "php", "apex", "zig", "gdscript", "matlab", "bash"]);
|
|
4788
4845
|
var CASE_INSENSITIVE_LANGUAGES = /* @__PURE__ */ new Set(["apex"]);
|
|
4789
4846
|
var CALL_GRAPH_SYMBOL_CHUNK_TYPES = /* @__PURE__ */ new Set([
|
|
4790
4847
|
"function_declaration",
|
|
@@ -4864,6 +4921,45 @@ function isSqliteCorruptionError(error) {
|
|
|
4864
4921
|
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");
|
|
4865
4922
|
}
|
|
4866
4923
|
var STARTUP_WARNING_METADATA_KEY = "index.startupWarning";
|
|
4924
|
+
function metadataFromBlame(blame) {
|
|
4925
|
+
if (!blame) {
|
|
4926
|
+
return {};
|
|
4927
|
+
}
|
|
4928
|
+
return {
|
|
4929
|
+
blameSha: blame.sha,
|
|
4930
|
+
blameAuthor: blame.author,
|
|
4931
|
+
blameAuthorEmail: blame.authorEmail,
|
|
4932
|
+
blameCommittedAt: blame.committedAt,
|
|
4933
|
+
blameSummary: blame.summary
|
|
4934
|
+
};
|
|
4935
|
+
}
|
|
4936
|
+
function blameFromChunkData(chunk) {
|
|
4937
|
+
if (!chunk?.blameSha || !chunk.blameAuthor || !chunk.blameAuthorEmail || chunk.blameCommittedAt === void 0 || !chunk.blameSummary) {
|
|
4938
|
+
return void 0;
|
|
4939
|
+
}
|
|
4940
|
+
return {
|
|
4941
|
+
sha: chunk.blameSha,
|
|
4942
|
+
author: chunk.blameAuthor,
|
|
4943
|
+
authorEmail: chunk.blameAuthorEmail,
|
|
4944
|
+
committedAt: chunk.blameCommittedAt,
|
|
4945
|
+
summary: chunk.blameSummary
|
|
4946
|
+
};
|
|
4947
|
+
}
|
|
4948
|
+
function blameFromMetadata(metadata) {
|
|
4949
|
+
if (!metadata.blameSha || !metadata.blameAuthor || !metadata.blameAuthorEmail || metadata.blameCommittedAt === void 0 || !metadata.blameSummary) {
|
|
4950
|
+
return void 0;
|
|
4951
|
+
}
|
|
4952
|
+
return {
|
|
4953
|
+
sha: metadata.blameSha,
|
|
4954
|
+
author: metadata.blameAuthor,
|
|
4955
|
+
authorEmail: metadata.blameAuthorEmail,
|
|
4956
|
+
committedAt: metadata.blameCommittedAt,
|
|
4957
|
+
summary: metadata.blameSummary
|
|
4958
|
+
};
|
|
4959
|
+
}
|
|
4960
|
+
function hasBlameMetadata(metadata) {
|
|
4961
|
+
return blameFromMetadata(metadata) !== void 0;
|
|
4962
|
+
}
|
|
4867
4963
|
var INDEX_METADATA_VERSION = "1";
|
|
4868
4964
|
var EMBEDDING_STRATEGY_VERSION = "2";
|
|
4869
4965
|
var RANKING_TOKEN_CACHE_LIMIT = 4096;
|
|
@@ -5022,9 +5118,9 @@ function hasAllEmbeddingParts(parts, expectedPartCount) {
|
|
|
5022
5118
|
return true;
|
|
5023
5119
|
}
|
|
5024
5120
|
function isPathWithinRoot(filePath, rootPath) {
|
|
5025
|
-
const normalizedFilePath =
|
|
5026
|
-
const normalizedRoot =
|
|
5027
|
-
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${
|
|
5121
|
+
const normalizedFilePath = path12.resolve(filePath);
|
|
5122
|
+
const normalizedRoot = path12.resolve(rootPath);
|
|
5123
|
+
return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${path12.sep}`);
|
|
5028
5124
|
}
|
|
5029
5125
|
var rankingQueryTokenCache = /* @__PURE__ */ new Map();
|
|
5030
5126
|
var rankingNameTokenCache = /* @__PURE__ */ new Map();
|
|
@@ -5783,7 +5879,8 @@ function promoteIdentifierMatches(query, combined, semanticCandidates, keywordCa
|
|
|
5783
5879
|
chunkType,
|
|
5784
5880
|
name: chunk.name ?? void 0,
|
|
5785
5881
|
language: chunk.language,
|
|
5786
|
-
hash: chunk.contentHash
|
|
5882
|
+
hash: chunk.contentHash,
|
|
5883
|
+
...metadataFromBlame(blameFromChunkData(chunk))
|
|
5787
5884
|
};
|
|
5788
5885
|
const baselineScore = existing?.score ?? 0.5;
|
|
5789
5886
|
candidateUnion.set(chunk.chunkId, {
|
|
@@ -5867,7 +5964,8 @@ function buildSymbolDefinitionLane(query, database, branchChunkIds, limit, fallb
|
|
|
5867
5964
|
chunkType,
|
|
5868
5965
|
name: chunk.name ?? void 0,
|
|
5869
5966
|
language: chunk.language,
|
|
5870
|
-
hash: chunk.contentHash
|
|
5967
|
+
hash: chunk.contentHash,
|
|
5968
|
+
...metadataFromBlame(blameFromChunkData(chunk))
|
|
5871
5969
|
}
|
|
5872
5970
|
});
|
|
5873
5971
|
}
|
|
@@ -6036,6 +6134,21 @@ function matchesSearchFilters(candidate, options, minScore) {
|
|
|
6036
6134
|
if (options?.chunkType && candidate.metadata.chunkType !== options.chunkType) {
|
|
6037
6135
|
return false;
|
|
6038
6136
|
}
|
|
6137
|
+
if (options?.blameAuthor) {
|
|
6138
|
+
const author = options.blameAuthor.toLowerCase();
|
|
6139
|
+
const candidateAuthor = candidate.metadata.blameAuthor?.toLowerCase();
|
|
6140
|
+
const candidateEmail = candidate.metadata.blameAuthorEmail?.toLowerCase();
|
|
6141
|
+
if (candidateAuthor !== author && candidateEmail !== author) return false;
|
|
6142
|
+
}
|
|
6143
|
+
if (options?.blameSha && !candidate.metadata.blameSha?.toLowerCase().startsWith(options.blameSha.toLowerCase())) {
|
|
6144
|
+
return false;
|
|
6145
|
+
}
|
|
6146
|
+
if (options?.blameSince) {
|
|
6147
|
+
const sinceMs = Date.parse(options.blameSince);
|
|
6148
|
+
if (Number.isNaN(sinceMs)) return false;
|
|
6149
|
+
const committedAt = candidate.metadata.blameCommittedAt;
|
|
6150
|
+
if (committedAt === void 0 || committedAt < Math.floor(sinceMs / 1e3)) return false;
|
|
6151
|
+
}
|
|
6039
6152
|
return true;
|
|
6040
6153
|
}
|
|
6041
6154
|
function unionCandidates(semanticCandidates, keywordCandidates) {
|
|
@@ -6079,9 +6192,9 @@ var Indexer = class {
|
|
|
6079
6192
|
this.config = config;
|
|
6080
6193
|
this.host = host;
|
|
6081
6194
|
this.indexPath = this.getIndexPath();
|
|
6082
|
-
this.fileHashCachePath =
|
|
6083
|
-
this.failedBatchesPath =
|
|
6084
|
-
this.indexingLockPath =
|
|
6195
|
+
this.fileHashCachePath = path12.join(this.indexPath, "file-hashes.json");
|
|
6196
|
+
this.failedBatchesPath = path12.join(this.indexPath, "failed-batches.json");
|
|
6197
|
+
this.indexingLockPath = path12.join(this.indexPath, "indexing.lock");
|
|
6085
6198
|
this.logger = initializeLogger(config.debug);
|
|
6086
6199
|
}
|
|
6087
6200
|
getIndexPath() {
|
|
@@ -6113,14 +6226,14 @@ var Indexer = class {
|
|
|
6113
6226
|
}
|
|
6114
6227
|
atomicWriteSync(targetPath, data) {
|
|
6115
6228
|
const tempPath = `${targetPath}.tmp`;
|
|
6116
|
-
mkdirSync2(
|
|
6229
|
+
mkdirSync2(path12.dirname(targetPath), { recursive: true });
|
|
6117
6230
|
writeFileSync2(tempPath, data);
|
|
6118
6231
|
renameSync(tempPath, targetPath);
|
|
6119
6232
|
}
|
|
6120
6233
|
getScopedRoots() {
|
|
6121
|
-
const roots = /* @__PURE__ */ new Set([
|
|
6234
|
+
const roots = /* @__PURE__ */ new Set([path12.resolve(this.projectRoot)]);
|
|
6122
6235
|
for (const kbRoot of this.config.knowledgeBases) {
|
|
6123
|
-
roots.add(
|
|
6236
|
+
roots.add(path12.resolve(this.projectRoot, kbRoot));
|
|
6124
6237
|
}
|
|
6125
6238
|
return Array.from(roots);
|
|
6126
6239
|
}
|
|
@@ -6129,29 +6242,29 @@ var Indexer = class {
|
|
|
6129
6242
|
if (this.config.scope !== "global") {
|
|
6130
6243
|
return branchName;
|
|
6131
6244
|
}
|
|
6132
|
-
const projectHash = hashContent(
|
|
6245
|
+
const projectHash = hashContent(path12.resolve(this.projectRoot)).slice(0, 16);
|
|
6133
6246
|
return `${projectHash}:${branchName}`;
|
|
6134
6247
|
}
|
|
6135
6248
|
getBranchCatalogKeyFor(branchName) {
|
|
6136
6249
|
if (this.config.scope !== "global") {
|
|
6137
6250
|
return branchName;
|
|
6138
6251
|
}
|
|
6139
|
-
const projectHash = hashContent(
|
|
6252
|
+
const projectHash = hashContent(path12.resolve(this.projectRoot)).slice(0, 16);
|
|
6140
6253
|
return `${projectHash}:${branchName}`;
|
|
6141
6254
|
}
|
|
6142
6255
|
getLegacyBranchCatalogKey() {
|
|
6143
6256
|
return this.currentBranch || "default";
|
|
6144
6257
|
}
|
|
6145
6258
|
getLegacyMigrationMetadataKey() {
|
|
6146
|
-
const projectHash = hashContent(
|
|
6259
|
+
const projectHash = hashContent(path12.resolve(this.projectRoot)).slice(0, 16);
|
|
6147
6260
|
return `index.globalBranchMigration.${projectHash}`;
|
|
6148
6261
|
}
|
|
6149
6262
|
getProjectEmbeddingStrategyMetadataKey() {
|
|
6150
|
-
const projectHash = hashContent(
|
|
6263
|
+
const projectHash = hashContent(path12.resolve(this.projectRoot)).slice(0, 16);
|
|
6151
6264
|
return `index.embeddingStrategyVersion.${projectHash}`;
|
|
6152
6265
|
}
|
|
6153
6266
|
getProjectForceReembedMetadataKey() {
|
|
6154
|
-
const projectHash = hashContent(
|
|
6267
|
+
const projectHash = hashContent(path12.resolve(this.projectRoot)).slice(0, 16);
|
|
6155
6268
|
return `index.forceReembed.${projectHash}`;
|
|
6156
6269
|
}
|
|
6157
6270
|
hasProjectForceReembedPending() {
|
|
@@ -6245,7 +6358,7 @@ var Indexer = class {
|
|
|
6245
6358
|
if (!this.database) {
|
|
6246
6359
|
return { chunkIds, symbolIds };
|
|
6247
6360
|
}
|
|
6248
|
-
const projectRootPath =
|
|
6361
|
+
const projectRootPath = path12.resolve(this.projectRoot);
|
|
6249
6362
|
const projectLocalFilePaths = /* @__PURE__ */ new Set([
|
|
6250
6363
|
...Array.from(this.fileHashCache.keys()).filter(
|
|
6251
6364
|
(filePath) => this.isFileInCurrentScope(filePath, roots) && isPathWithinRoot(filePath, projectRootPath)
|
|
@@ -6268,7 +6381,7 @@ var Indexer = class {
|
|
|
6268
6381
|
if (this.config.scope !== "global") {
|
|
6269
6382
|
return this.getBranchCatalogCleanupKeys();
|
|
6270
6383
|
}
|
|
6271
|
-
const projectHash = hashContent(
|
|
6384
|
+
const projectHash = hashContent(path12.resolve(this.projectRoot)).slice(0, 16);
|
|
6272
6385
|
const keys = /* @__PURE__ */ new Set();
|
|
6273
6386
|
const projectChunkIdSet = new Set(projectChunkIds);
|
|
6274
6387
|
const projectSymbolIdSet = new Set(projectSymbolIds);
|
|
@@ -6352,7 +6465,7 @@ var Indexer = class {
|
|
|
6352
6465
|
if (!this.database || this.config.scope !== "global") {
|
|
6353
6466
|
return false;
|
|
6354
6467
|
}
|
|
6355
|
-
const projectHash = hashContent(
|
|
6468
|
+
const projectHash = hashContent(path12.resolve(this.projectRoot)).slice(0, 16);
|
|
6356
6469
|
const roots = this.getScopedRoots();
|
|
6357
6470
|
const { chunkIds: projectLocalChunkIds, symbolIds: projectLocalSymbolIds } = this.getProjectLocalScopedOwnershipIds(roots);
|
|
6358
6471
|
return this.database.getAllBranches().some(
|
|
@@ -6386,7 +6499,7 @@ var Indexer = class {
|
|
|
6386
6499
|
...Array.from(this.fileHashCache.keys()).filter((filePath) => this.isFileInCurrentScope(filePath, roots)),
|
|
6387
6500
|
...scopedEntries.map(({ metadata }) => metadata.filePath)
|
|
6388
6501
|
]);
|
|
6389
|
-
const projectRootPath =
|
|
6502
|
+
const projectRootPath = path12.resolve(this.projectRoot);
|
|
6390
6503
|
const projectLocalFilePaths = new Set(
|
|
6391
6504
|
Array.from(filePaths).filter((filePath) => isPathWithinRoot(filePath, projectRootPath))
|
|
6392
6505
|
);
|
|
@@ -6746,13 +6859,13 @@ var Indexer = class {
|
|
|
6746
6859
|
}
|
|
6747
6860
|
await fsPromises2.mkdir(this.indexPath, { recursive: true });
|
|
6748
6861
|
const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
|
|
6749
|
-
const storePath =
|
|
6862
|
+
const storePath = path12.join(this.indexPath, "vectors");
|
|
6750
6863
|
this.store = new VectorStore(storePath, dimensions);
|
|
6751
|
-
const indexFilePath =
|
|
6864
|
+
const indexFilePath = path12.join(this.indexPath, "vectors.usearch");
|
|
6752
6865
|
if (existsSync7(indexFilePath)) {
|
|
6753
6866
|
this.store.load();
|
|
6754
6867
|
}
|
|
6755
|
-
const invertedIndexPath =
|
|
6868
|
+
const invertedIndexPath = path12.join(this.indexPath, "inverted-index.json");
|
|
6756
6869
|
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
6757
6870
|
try {
|
|
6758
6871
|
this.invertedIndex.load();
|
|
@@ -6762,7 +6875,7 @@ var Indexer = class {
|
|
|
6762
6875
|
}
|
|
6763
6876
|
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
6764
6877
|
}
|
|
6765
|
-
const dbPath =
|
|
6878
|
+
const dbPath = path12.join(this.indexPath, "codebase.db");
|
|
6766
6879
|
let dbIsNew = !existsSync7(dbPath);
|
|
6767
6880
|
try {
|
|
6768
6881
|
this.database = new Database(dbPath);
|
|
@@ -6843,7 +6956,7 @@ var Indexer = class {
|
|
|
6843
6956
|
if (await this.tryResetCorruptedIndex("running automatic orphan garbage collection", error)) {
|
|
6844
6957
|
return {
|
|
6845
6958
|
resetCorruptedIndex: true,
|
|
6846
|
-
warning: this.getCorruptedIndexWarning(
|
|
6959
|
+
warning: this.getCorruptedIndexWarning(path12.join(this.indexPath, "codebase.db"))
|
|
6847
6960
|
};
|
|
6848
6961
|
}
|
|
6849
6962
|
throw error;
|
|
@@ -6858,7 +6971,7 @@ var Indexer = class {
|
|
|
6858
6971
|
return;
|
|
6859
6972
|
}
|
|
6860
6973
|
const retainedEntries = store.getAllMetadata().filter(({ key }) => !excludedSet.has(key));
|
|
6861
|
-
const storeBasePath =
|
|
6974
|
+
const storeBasePath = path12.join(this.indexPath, "vectors");
|
|
6862
6975
|
const storeIndexPath = `${storeBasePath}.usearch`;
|
|
6863
6976
|
const storeMetadataPath = `${storeBasePath}.meta.json`;
|
|
6864
6977
|
const backupIndexPath = `${storeIndexPath}.bak`;
|
|
@@ -6943,7 +7056,7 @@ var Indexer = class {
|
|
|
6943
7056
|
if (!isSqliteCorruptionError(error)) {
|
|
6944
7057
|
return false;
|
|
6945
7058
|
}
|
|
6946
|
-
const dbPath =
|
|
7059
|
+
const dbPath = path12.join(this.indexPath, "codebase.db");
|
|
6947
7060
|
const warning = this.getCorruptedIndexWarning(dbPath);
|
|
6948
7061
|
const errorMessage = getErrorMessage2(error);
|
|
6949
7062
|
if (this.config.scope === "global") {
|
|
@@ -6966,15 +7079,15 @@ var Indexer = class {
|
|
|
6966
7079
|
this.indexCompatibility = null;
|
|
6967
7080
|
this.fileHashCache.clear();
|
|
6968
7081
|
const resetPaths = [
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
7082
|
+
path12.join(this.indexPath, "codebase.db"),
|
|
7083
|
+
path12.join(this.indexPath, "codebase.db-shm"),
|
|
7084
|
+
path12.join(this.indexPath, "codebase.db-wal"),
|
|
7085
|
+
path12.join(this.indexPath, "vectors.usearch"),
|
|
7086
|
+
path12.join(this.indexPath, "inverted-index.json"),
|
|
7087
|
+
path12.join(this.indexPath, "file-hashes.json"),
|
|
7088
|
+
path12.join(this.indexPath, "failed-batches.json"),
|
|
7089
|
+
path12.join(this.indexPath, "indexing.lock"),
|
|
7090
|
+
path12.join(this.indexPath, "vectors")
|
|
6978
7091
|
];
|
|
6979
7092
|
await Promise.all(resetPaths.map(async (targetPath) => {
|
|
6980
7093
|
try {
|
|
@@ -7211,6 +7324,7 @@ var Indexer = class {
|
|
|
7211
7324
|
this.logger.debug("Parsed changed files", { parsedCount: parsedFiles.length, parseMs: parseMs.toFixed(2) });
|
|
7212
7325
|
const existingChunks = /* @__PURE__ */ new Map();
|
|
7213
7326
|
const existingChunksByFile = /* @__PURE__ */ new Map();
|
|
7327
|
+
const existingMetadataById = /* @__PURE__ */ new Map();
|
|
7214
7328
|
for (const { key, metadata } of store.getAllMetadata()) {
|
|
7215
7329
|
if (scopedRoots && !this.isFileInCurrentScope(metadata.filePath, scopedRoots)) {
|
|
7216
7330
|
continue;
|
|
@@ -7219,6 +7333,7 @@ var Indexer = class {
|
|
|
7219
7333
|
continue;
|
|
7220
7334
|
}
|
|
7221
7335
|
existingChunks.set(key, metadata.hash);
|
|
7336
|
+
existingMetadataById.set(key, metadata);
|
|
7222
7337
|
const fileChunks = existingChunksByFile.get(metadata.filePath) || /* @__PURE__ */ new Set();
|
|
7223
7338
|
fileChunks.add(key);
|
|
7224
7339
|
existingChunksByFile.set(metadata.filePath, fileChunks);
|
|
@@ -7226,6 +7341,8 @@ var Indexer = class {
|
|
|
7226
7341
|
const currentChunkIds = /* @__PURE__ */ new Set();
|
|
7227
7342
|
const currentFilePaths = /* @__PURE__ */ new Set();
|
|
7228
7343
|
const pendingChunks = [];
|
|
7344
|
+
const gitBlameEnabled = this.config.indexing.gitBlame.enabled && isGitRepo(this.projectRoot);
|
|
7345
|
+
let backfilledBlameMetadata = false;
|
|
7229
7346
|
for (const filePath of unchangedFilePaths) {
|
|
7230
7347
|
currentFilePaths.add(filePath);
|
|
7231
7348
|
const fileChunks = existingChunksByFile.get(filePath);
|
|
@@ -7236,10 +7353,52 @@ var Indexer = class {
|
|
|
7236
7353
|
}
|
|
7237
7354
|
}
|
|
7238
7355
|
const chunkDataBatch = [];
|
|
7356
|
+
if (gitBlameEnabled) {
|
|
7357
|
+
const backfillItems = [];
|
|
7358
|
+
for (const chunkId of currentChunkIds) {
|
|
7359
|
+
const metadata = existingMetadataById.get(chunkId);
|
|
7360
|
+
if (!metadata || hasBlameMetadata(metadata)) {
|
|
7361
|
+
continue;
|
|
7362
|
+
}
|
|
7363
|
+
const chunk = database.getChunk(chunkId);
|
|
7364
|
+
if (!chunk) {
|
|
7365
|
+
continue;
|
|
7366
|
+
}
|
|
7367
|
+
const blame = await getChunkGitBlame(this.projectRoot, chunk.filePath, chunk.startLine, chunk.endLine);
|
|
7368
|
+
const blameMetadata = metadataFromBlame(blame);
|
|
7369
|
+
if (!blameMetadata.blameSha) {
|
|
7370
|
+
continue;
|
|
7371
|
+
}
|
|
7372
|
+
chunkDataBatch.push({
|
|
7373
|
+
...chunk,
|
|
7374
|
+
blameSha: blameMetadata.blameSha,
|
|
7375
|
+
blameAuthor: blameMetadata.blameAuthor,
|
|
7376
|
+
blameAuthorEmail: blameMetadata.blameAuthorEmail,
|
|
7377
|
+
blameCommittedAt: blameMetadata.blameCommittedAt,
|
|
7378
|
+
blameSummary: blameMetadata.blameSummary
|
|
7379
|
+
});
|
|
7380
|
+
const embeddingBuffer = database.getEmbedding(chunk.contentHash);
|
|
7381
|
+
if (!embeddingBuffer) {
|
|
7382
|
+
continue;
|
|
7383
|
+
}
|
|
7384
|
+
backfillItems.push({
|
|
7385
|
+
id: chunkId,
|
|
7386
|
+
vector: Array.from(bufferToFloat32Array(embeddingBuffer)),
|
|
7387
|
+
metadata: {
|
|
7388
|
+
...metadata,
|
|
7389
|
+
...blameMetadata
|
|
7390
|
+
}
|
|
7391
|
+
});
|
|
7392
|
+
}
|
|
7393
|
+
if (backfillItems.length > 0) {
|
|
7394
|
+
store.addBatch(backfillItems);
|
|
7395
|
+
backfilledBlameMetadata = true;
|
|
7396
|
+
}
|
|
7397
|
+
}
|
|
7239
7398
|
for (const parsed of parsedFiles) {
|
|
7240
7399
|
currentFilePaths.add(parsed.path);
|
|
7241
7400
|
if (parsed.chunks.length === 0) {
|
|
7242
|
-
const relativePath =
|
|
7401
|
+
const relativePath = path12.relative(this.projectRoot, parsed.path);
|
|
7243
7402
|
stats.parseFailures.push(relativePath);
|
|
7244
7403
|
}
|
|
7245
7404
|
let fileChunkCount = 0;
|
|
@@ -7260,6 +7419,10 @@ var Indexer = class {
|
|
|
7260
7419
|
}
|
|
7261
7420
|
const id = generateChunkId(parsed.path, chunk);
|
|
7262
7421
|
const contentHash = generateChunkHash(chunk);
|
|
7422
|
+
const existingContentHash = existingChunks.get(id);
|
|
7423
|
+
const existingChunk = gitBlameEnabled ? database.getChunk(id) : null;
|
|
7424
|
+
const blame = gitBlameEnabled && existingContentHash !== contentHash ? await getChunkGitBlame(this.projectRoot, parsed.path, chunk.startLine, chunk.endLine) : blameFromChunkData(existingChunk);
|
|
7425
|
+
const blameMetadata = metadataFromBlame(blame);
|
|
7263
7426
|
currentChunkIds.add(id);
|
|
7264
7427
|
chunkDataBatch.push({
|
|
7265
7428
|
chunkId: id,
|
|
@@ -7269,9 +7432,14 @@ var Indexer = class {
|
|
|
7269
7432
|
endLine: chunk.endLine,
|
|
7270
7433
|
nodeType: chunk.chunkType,
|
|
7271
7434
|
name: chunk.name,
|
|
7272
|
-
language: chunk.language
|
|
7435
|
+
language: chunk.language,
|
|
7436
|
+
blameSha: blameMetadata.blameSha,
|
|
7437
|
+
blameAuthor: blameMetadata.blameAuthor,
|
|
7438
|
+
blameAuthorEmail: blameMetadata.blameAuthorEmail,
|
|
7439
|
+
blameCommittedAt: blameMetadata.blameCommittedAt,
|
|
7440
|
+
blameSummary: blameMetadata.blameSummary
|
|
7273
7441
|
});
|
|
7274
|
-
if (
|
|
7442
|
+
if (existingContentHash === contentHash) {
|
|
7275
7443
|
fileChunkCount++;
|
|
7276
7444
|
continue;
|
|
7277
7445
|
}
|
|
@@ -7286,7 +7454,8 @@ var Indexer = class {
|
|
|
7286
7454
|
chunkType: chunk.chunkType,
|
|
7287
7455
|
name: chunk.name,
|
|
7288
7456
|
language: chunk.language,
|
|
7289
|
-
hash: contentHash
|
|
7457
|
+
hash: contentHash,
|
|
7458
|
+
...blameMetadata
|
|
7290
7459
|
};
|
|
7291
7460
|
pendingChunks.push({
|
|
7292
7461
|
id,
|
|
@@ -7429,6 +7598,9 @@ var Indexer = class {
|
|
|
7429
7598
|
database.addChunksToBranchBatch(branchCatalogKey, Array.from(currentChunkIds));
|
|
7430
7599
|
database.clearBranchSymbols(branchCatalogKey);
|
|
7431
7600
|
database.addSymbolsToBranchBatch(branchCatalogKey, Array.from(allSymbolIds));
|
|
7601
|
+
if (backfilledBlameMetadata) {
|
|
7602
|
+
store.save();
|
|
7603
|
+
}
|
|
7432
7604
|
if (scopedRoots) {
|
|
7433
7605
|
this.replaceScopedFileHashCache(currentFileHashes, scopedRoots);
|
|
7434
7606
|
this.clearScopedFailedBatches(scopedRoots);
|
|
@@ -7992,7 +8164,8 @@ var Indexer = class {
|
|
|
7992
8164
|
content,
|
|
7993
8165
|
score: r.score,
|
|
7994
8166
|
chunkType: r.metadata.chunkType,
|
|
7995
|
-
name: r.metadata.name
|
|
8167
|
+
name: r.metadata.name,
|
|
8168
|
+
blame: blameFromMetadata(r.metadata)
|
|
7996
8169
|
};
|
|
7997
8170
|
})
|
|
7998
8171
|
);
|
|
@@ -8084,12 +8257,12 @@ var Indexer = class {
|
|
|
8084
8257
|
this.indexCompatibility = compatibility;
|
|
8085
8258
|
return;
|
|
8086
8259
|
}
|
|
8087
|
-
const localProjectIndexPaths = [
|
|
8260
|
+
const localProjectIndexPaths = [path12.join(this.projectRoot, getHostProjectIndexRelativePath(this.host))];
|
|
8088
8261
|
if (this.host !== "opencode") {
|
|
8089
|
-
localProjectIndexPaths.push(
|
|
8262
|
+
localProjectIndexPaths.push(path12.join(this.projectRoot, getHostProjectIndexRelativePath("opencode")));
|
|
8090
8263
|
}
|
|
8091
8264
|
const isLocalProjectIndex = localProjectIndexPaths.some(
|
|
8092
|
-
(localPath) =>
|
|
8265
|
+
(localPath) => path12.resolve(this.indexPath) === path12.resolve(localPath)
|
|
8093
8266
|
);
|
|
8094
8267
|
if (!isLocalProjectIndex) {
|
|
8095
8268
|
throw new Error(
|
|
@@ -8179,7 +8352,7 @@ var Indexer = class {
|
|
|
8179
8352
|
gcOrphanSymbols: 0,
|
|
8180
8353
|
gcOrphanCallEdges: 0,
|
|
8181
8354
|
resetCorruptedIndex: true,
|
|
8182
|
-
warning: this.getCorruptedIndexWarning(
|
|
8355
|
+
warning: this.getCorruptedIndexWarning(path12.join(this.indexPath, "codebase.db"))
|
|
8183
8356
|
};
|
|
8184
8357
|
}
|
|
8185
8358
|
this.logger.recordGc(removedCount, gcOrphanChunks, gcOrphanEmbeddings);
|
|
@@ -8499,7 +8672,8 @@ var Indexer = class {
|
|
|
8499
8672
|
content,
|
|
8500
8673
|
score: r.score,
|
|
8501
8674
|
chunkType: r.metadata.chunkType,
|
|
8502
|
-
name: r.metadata.name
|
|
8675
|
+
name: r.metadata.name,
|
|
8676
|
+
blame: blameFromMetadata(r.metadata)
|
|
8503
8677
|
};
|
|
8504
8678
|
})
|
|
8505
8679
|
);
|
|
@@ -8536,9 +8710,9 @@ var Indexer = class {
|
|
|
8536
8710
|
const { database } = await this.ensureInitialized();
|
|
8537
8711
|
let shortest = [];
|
|
8538
8712
|
for (const branchKey of this.getBranchCatalogKeys()) {
|
|
8539
|
-
const
|
|
8540
|
-
if (
|
|
8541
|
-
shortest =
|
|
8713
|
+
const path23 = database.findShortestPath(fromName, toName, branchKey, maxDepth);
|
|
8714
|
+
if (path23.length > 0 && (shortest.length === 0 || path23.length < shortest.length)) {
|
|
8715
|
+
shortest = path23;
|
|
8542
8716
|
}
|
|
8543
8717
|
}
|
|
8544
8718
|
return shortest;
|
|
@@ -8570,7 +8744,7 @@ var Indexer = class {
|
|
|
8570
8744
|
}
|
|
8571
8745
|
async getPrImpact(opts) {
|
|
8572
8746
|
const { database } = await this.ensureInitialized();
|
|
8573
|
-
const
|
|
8747
|
+
const execFileAsync3 = promisify3(execFile3);
|
|
8574
8748
|
const changedFilesResult = await getChangedFiles({
|
|
8575
8749
|
pr: opts.pr,
|
|
8576
8750
|
branch: opts.branch,
|
|
@@ -8592,7 +8766,7 @@ var Indexer = class {
|
|
|
8592
8766
|
"Run index_codebase first to build the call graph and symbol index for this branch."
|
|
8593
8767
|
);
|
|
8594
8768
|
}
|
|
8595
|
-
const absoluteChangedFiles = changedFiles.map((f) =>
|
|
8769
|
+
const absoluteChangedFiles = changedFiles.map((f) => path12.resolve(this.projectRoot, f));
|
|
8596
8770
|
const directSymbols = database.getSymbolsForFiles(absoluteChangedFiles, branchKey);
|
|
8597
8771
|
const directIds = directSymbols.map((s) => s.id);
|
|
8598
8772
|
const direction = opts.direction ?? "both";
|
|
@@ -8654,7 +8828,7 @@ var Indexer = class {
|
|
|
8654
8828
|
if (opts.checkConflicts) {
|
|
8655
8829
|
conflictingPRs = [];
|
|
8656
8830
|
try {
|
|
8657
|
-
const { stdout } = await
|
|
8831
|
+
const { stdout } = await execFileAsync3(
|
|
8658
8832
|
"gh",
|
|
8659
8833
|
["pr", "list", "--state", "open", "--json", "number,headRefName", "--limit", "10000"],
|
|
8660
8834
|
{ cwd: this.projectRoot, timeout: 3e4 }
|
|
@@ -8675,7 +8849,7 @@ var Indexer = class {
|
|
|
8675
8849
|
projectRoot: this.projectRoot,
|
|
8676
8850
|
baseBranch: this.baseBranch
|
|
8677
8851
|
});
|
|
8678
|
-
const otherAbsolute = otherChanged.files.map((f) =>
|
|
8852
|
+
const otherAbsolute = otherChanged.files.map((f) => path12.resolve(this.projectRoot, f));
|
|
8679
8853
|
const otherBranchKey = this.getBranchCatalogKeyFor(openPr.headRefName);
|
|
8680
8854
|
const otherSymbols = database.getSymbolsForFiles(otherAbsolute, otherBranchKey);
|
|
8681
8855
|
const otherLabels = /* @__PURE__ */ new Set();
|
|
@@ -8738,12 +8912,12 @@ var Indexer = class {
|
|
|
8738
8912
|
if (meta.filePath) filePaths.add(meta.filePath);
|
|
8739
8913
|
}
|
|
8740
8914
|
const directory = options?.directory?.replace(/\/$/, "");
|
|
8741
|
-
const absoluteDirectoryFilter = directory ?
|
|
8915
|
+
const absoluteDirectoryFilter = directory ? path12.resolve(this.projectRoot, directory) : void 0;
|
|
8742
8916
|
for (const filePath of filePaths) {
|
|
8743
8917
|
if (directory) {
|
|
8744
|
-
const absoluteFilePath =
|
|
8918
|
+
const absoluteFilePath = path12.resolve(filePath);
|
|
8745
8919
|
const matchesRelative = filePath === directory || filePath.startsWith(directory + "/");
|
|
8746
|
-
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter +
|
|
8920
|
+
const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter + path12.sep));
|
|
8747
8921
|
if (!matchesRelative && !matchesProjectRelative) {
|
|
8748
8922
|
continue;
|
|
8749
8923
|
}
|
|
@@ -8775,43 +8949,43 @@ var Indexer = class {
|
|
|
8775
8949
|
};
|
|
8776
8950
|
|
|
8777
8951
|
// src/tools/knowledge-base-paths.ts
|
|
8778
|
-
import * as
|
|
8952
|
+
import * as path13 from "path";
|
|
8779
8953
|
function resolveConfigPathValue(value, baseDir) {
|
|
8780
8954
|
const trimmed = value.trim();
|
|
8781
8955
|
if (!trimmed) {
|
|
8782
8956
|
return trimmed;
|
|
8783
8957
|
}
|
|
8784
|
-
const absolutePath =
|
|
8785
|
-
return
|
|
8958
|
+
const absolutePath = path13.isAbsolute(trimmed) ? trimmed : path13.resolve(baseDir, trimmed);
|
|
8959
|
+
return path13.normalize(absolutePath);
|
|
8786
8960
|
}
|
|
8787
8961
|
function serializeConfigPathValue(value, baseDir) {
|
|
8788
8962
|
const trimmed = value.trim();
|
|
8789
8963
|
if (!trimmed) {
|
|
8790
8964
|
return trimmed;
|
|
8791
8965
|
}
|
|
8792
|
-
if (!
|
|
8793
|
-
return normalizePathSeparators(
|
|
8966
|
+
if (!path13.isAbsolute(trimmed)) {
|
|
8967
|
+
return normalizePathSeparators(path13.normalize(trimmed));
|
|
8794
8968
|
}
|
|
8795
|
-
const relativePath =
|
|
8796
|
-
if (!relativePath || !relativePath.startsWith("..") && !
|
|
8797
|
-
return normalizePathSeparators(
|
|
8969
|
+
const relativePath = path13.relative(baseDir, trimmed);
|
|
8970
|
+
if (!relativePath || !relativePath.startsWith("..") && !path13.isAbsolute(relativePath)) {
|
|
8971
|
+
return normalizePathSeparators(path13.normalize(relativePath || "."));
|
|
8798
8972
|
}
|
|
8799
|
-
return
|
|
8973
|
+
return path13.normalize(trimmed);
|
|
8800
8974
|
}
|
|
8801
8975
|
function resolveKnowledgeBasePath(value, projectRoot) {
|
|
8802
|
-
return
|
|
8976
|
+
return path13.isAbsolute(value) ? value : path13.resolve(projectRoot, value);
|
|
8803
8977
|
}
|
|
8804
8978
|
function normalizeKnowledgeBasePath2(value, projectRoot) {
|
|
8805
|
-
return
|
|
8979
|
+
return path13.normalize(resolveKnowledgeBasePath(value, projectRoot));
|
|
8806
8980
|
}
|
|
8807
8981
|
function hasMatchingKnowledgeBasePath(knowledgeBases, inputPath, projectRoot) {
|
|
8808
|
-
const normalizedInput =
|
|
8982
|
+
const normalizedInput = path13.normalize(inputPath);
|
|
8809
8983
|
return knowledgeBases.some((kb) => normalizeKnowledgeBasePath2(kb, projectRoot) === normalizedInput);
|
|
8810
8984
|
}
|
|
8811
8985
|
function findKnowledgeBasePathIndex(knowledgeBases, inputPath, projectRoot) {
|
|
8812
|
-
const normalizedInput =
|
|
8986
|
+
const normalizedInput = path13.normalize(inputPath);
|
|
8813
8987
|
return knowledgeBases.findIndex(
|
|
8814
|
-
(kb) =>
|
|
8988
|
+
(kb) => path13.normalize(kb) === normalizedInput || normalizeKnowledgeBasePath2(kb, projectRoot) === normalizedInput
|
|
8815
8989
|
);
|
|
8816
8990
|
}
|
|
8817
8991
|
|
|
@@ -8963,7 +9137,7 @@ function formatCodebasePeek(results) {
|
|
|
8963
9137
|
const formatted = results.map((r, idx) => {
|
|
8964
9138
|
const location = `${r.filePath}:${r.startLine}-${r.endLine}`;
|
|
8965
9139
|
const name = r.name ? `"${r.name}"` : "(anonymous)";
|
|
8966
|
-
return `[${idx + 1}] ${r.chunkType} ${name} at ${location} (score: ${r.score.toFixed(2)})`;
|
|
9140
|
+
return `[${idx + 1}] ${r.chunkType} ${name} at ${location} (score: ${r.score.toFixed(2)})${formatBlame(r)}`;
|
|
8967
9141
|
});
|
|
8968
9142
|
return formatted.join("\n");
|
|
8969
9143
|
}
|
|
@@ -8995,16 +9169,57 @@ function formatHealthCheck(result) {
|
|
|
8995
9169
|
}
|
|
8996
9170
|
return lines.join("\n");
|
|
8997
9171
|
}
|
|
9172
|
+
function formatCallGraphCallers(name, callers, relationshipType) {
|
|
9173
|
+
if (callers.length === 0) {
|
|
9174
|
+
return `No callers found for "${name}"${relationshipType ? ` with type ${relationshipType}` : ""}. It may not be called by any tracked function, or the index needs updating.`;
|
|
9175
|
+
}
|
|
9176
|
+
const formatted = callers.map((edge, index) => {
|
|
9177
|
+
const confidence = edge.confidence !== "Direct" ? ` [${edge.confidence.toLowerCase()}]` : "";
|
|
9178
|
+
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]"}`;
|
|
9179
|
+
});
|
|
9180
|
+
return `"${name}" is called by ${callers.length} function(s):
|
|
9181
|
+
|
|
9182
|
+
${formatted.join("\n")}`;
|
|
9183
|
+
}
|
|
9184
|
+
function formatCallGraphCallees(symbolId, callees, relationshipType) {
|
|
9185
|
+
if (callees.length === 0) {
|
|
9186
|
+
return `No callees found for symbol ${symbolId}${relationshipType ? ` with type ${relationshipType}` : ""}. The function may not call any other tracked functions.`;
|
|
9187
|
+
}
|
|
9188
|
+
return callees.map((edge, index) => {
|
|
9189
|
+
const confidence = edge.confidence !== "Direct" ? ` [${edge.confidence.toLowerCase()}]` : "";
|
|
9190
|
+
return `[${index + 1}] \u2192 ${edge.targetName} (${edge.callType})${confidence} at line ${edge.line}${edge.isResolved ? ` [resolved: ${edge.toSymbolId}]` : " [unresolved]"}`;
|
|
9191
|
+
}).join("\n");
|
|
9192
|
+
}
|
|
9193
|
+
function formatCallGraphPath(from, to, path23) {
|
|
9194
|
+
if (path23.length === 0) {
|
|
9195
|
+
return `No path found between "${from}" and "${to}". They may be in disconnected components, or the call graph index needs updating.`;
|
|
9196
|
+
}
|
|
9197
|
+
const formatted = path23.map((hop, index) => {
|
|
9198
|
+
const prefix = index === 0 ? "[start]" : `--${hop.callType}-->`;
|
|
9199
|
+
const location = hop.filePath ? ` (${hop.filePath}:${hop.line})` : "";
|
|
9200
|
+
return `${prefix} ${hop.symbolName}${location}`;
|
|
9201
|
+
});
|
|
9202
|
+
return `Path (${path23.length} hops):
|
|
9203
|
+
${formatted.join("\n")}`;
|
|
9204
|
+
}
|
|
8998
9205
|
function formatResultHeader(result, index) {
|
|
8999
9206
|
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}`;
|
|
9000
9207
|
}
|
|
9208
|
+
function formatBlame(result) {
|
|
9209
|
+
if (!result.blame) {
|
|
9210
|
+
return "";
|
|
9211
|
+
}
|
|
9212
|
+
const date = new Date(result.blame.committedAt * 1e3).toISOString().slice(0, 10);
|
|
9213
|
+
return `
|
|
9214
|
+
${result.blame.sha.slice(0, 7)} | ${result.blame.author} | ${date} | ${result.blame.summary}`;
|
|
9215
|
+
}
|
|
9001
9216
|
function formatDefinitionLookup(results, query) {
|
|
9002
9217
|
if (results.length === 0) {
|
|
9003
9218
|
return `No definition found for "${query}". Try codebase_search for broader discovery, or verify the symbol name.`;
|
|
9004
9219
|
}
|
|
9005
9220
|
const formatted = results.map((r, idx) => {
|
|
9006
9221
|
const header = formatResultHeader(r, idx);
|
|
9007
|
-
return `${header} (score: ${r.score.toFixed(2)})
|
|
9222
|
+
return `${header} (score: ${r.score.toFixed(2)})${formatBlame(r)}
|
|
9008
9223
|
\`\`\`
|
|
9009
9224
|
${truncateContent(r.content)}
|
|
9010
9225
|
\`\`\``;
|
|
@@ -9015,7 +9230,7 @@ function formatSearchResults(results, scoreFormat = "similarity") {
|
|
|
9015
9230
|
const formatted = results.map((r, idx) => {
|
|
9016
9231
|
const header = formatResultHeader(r, idx);
|
|
9017
9232
|
const scoreLabel = scoreFormat === "similarity" ? `(similarity: ${(r.score * 100).toFixed(1)}%)` : `(score: ${r.score.toFixed(2)})`;
|
|
9018
|
-
return `${header} ${scoreLabel}
|
|
9233
|
+
return `${header} ${scoreLabel}${formatBlame(r)}
|
|
9019
9234
|
\`\`\`
|
|
9020
9235
|
${truncateContent(r.content)}
|
|
9021
9236
|
\`\`\``;
|
|
@@ -9025,7 +9240,7 @@ ${truncateContent(r.content)}
|
|
|
9025
9240
|
|
|
9026
9241
|
// src/tools/config-state.ts
|
|
9027
9242
|
import { existsSync as existsSync8, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
9028
|
-
import * as
|
|
9243
|
+
import * as path14 from "path";
|
|
9029
9244
|
function normalizeKnowledgeBasePaths(config, projectRoot) {
|
|
9030
9245
|
const normalized = { ...config };
|
|
9031
9246
|
if (Array.isArray(normalized.knowledgeBases)) {
|
|
@@ -9052,8 +9267,8 @@ function loadEditableConfig(projectRoot, host = "opencode") {
|
|
|
9052
9267
|
}
|
|
9053
9268
|
function saveConfig(projectRoot, config, host = "opencode") {
|
|
9054
9269
|
const configPath = getConfigPath(projectRoot, host);
|
|
9055
|
-
const configDir =
|
|
9056
|
-
const configBaseDir =
|
|
9270
|
+
const configDir = path14.dirname(configPath);
|
|
9271
|
+
const configBaseDir = path14.dirname(configDir);
|
|
9057
9272
|
if (!existsSync8(configDir)) {
|
|
9058
9273
|
mkdirSync3(configDir, { recursive: true });
|
|
9059
9274
|
}
|
|
@@ -9114,7 +9329,7 @@ function refreshIndexerForDirectory(projectRoot, host = "opencode", config = par
|
|
|
9114
9329
|
}
|
|
9115
9330
|
function shouldForceLocalizeProjectIndex(projectRoot, host = "opencode") {
|
|
9116
9331
|
const root = getProjectRoot(projectRoot, host);
|
|
9117
|
-
const localIndexPath =
|
|
9332
|
+
const localIndexPath = path15.join(root, getHostProjectIndexRelativePath(host));
|
|
9118
9333
|
if (existsSync9(localIndexPath)) {
|
|
9119
9334
|
return false;
|
|
9120
9335
|
}
|
|
@@ -9129,7 +9344,10 @@ async function searchCodebase(projectRoot, host, query, options = {}) {
|
|
|
9129
9344
|
chunkType: options.chunkType,
|
|
9130
9345
|
contextLines: options.contextLines,
|
|
9131
9346
|
metadataOnly: options.metadataOnly,
|
|
9132
|
-
definitionIntent: options.definitionIntent
|
|
9347
|
+
definitionIntent: options.definitionIntent,
|
|
9348
|
+
blameAuthor: options.blameAuthor,
|
|
9349
|
+
blameSha: options.blameSha,
|
|
9350
|
+
blameSince: options.blameSince
|
|
9133
9351
|
});
|
|
9134
9352
|
}
|
|
9135
9353
|
async function findSimilarCode(projectRoot, host, code, options = {}) {
|
|
@@ -9261,8 +9479,8 @@ async function getIndexLogs(projectRoot, host, args) {
|
|
|
9261
9479
|
function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
9262
9480
|
const root = getProjectRoot(projectRoot, host);
|
|
9263
9481
|
const inputPath = knowledgeBasePath.trim();
|
|
9264
|
-
const normalizedPath =
|
|
9265
|
-
|
|
9482
|
+
const normalizedPath = path15.resolve(
|
|
9483
|
+
path15.isAbsolute(inputPath) ? inputPath : resolveKnowledgeBasePath(inputPath, root)
|
|
9266
9484
|
);
|
|
9267
9485
|
if (!existsSync9(normalizedPath)) {
|
|
9268
9486
|
return `Error: Directory does not exist: ${normalizedPath}`;
|
|
@@ -9298,7 +9516,7 @@ function addKnowledgeBase(projectRoot, host, knowledgeBasePath) {
|
|
|
9298
9516
|
}
|
|
9299
9517
|
}
|
|
9300
9518
|
for (const dotDir of sensitiveDotDirs) {
|
|
9301
|
-
const sensitiveDir =
|
|
9519
|
+
const sensitiveDir = path15.join(homeDir, dotDir);
|
|
9302
9520
|
if (sensitiveDir && (realPath === sensitiveDir || realPath.startsWith(`${sensitiveDir}/`))) {
|
|
9303
9521
|
return `Error: Adding sensitive directory as knowledge base is not allowed: ${normalizedPath}`;
|
|
9304
9522
|
}
|
|
@@ -9361,7 +9579,7 @@ function listKnowledgeBases(projectRoot, host) {
|
|
|
9361
9579
|
}
|
|
9362
9580
|
result += "\n";
|
|
9363
9581
|
}
|
|
9364
|
-
const hasHostConfig = existsSync9(
|
|
9582
|
+
const hasHostConfig = existsSync9(path15.join(root, getHostProjectConfigRelativePath(host)));
|
|
9365
9583
|
if (hasHostConfig) {
|
|
9366
9584
|
result += `
|
|
9367
9585
|
Config sources: 1 file(s).`;
|
|
@@ -9484,7 +9702,7 @@ var ReaddirpStream = class extends Readable {
|
|
|
9484
9702
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
9485
9703
|
const statMethod = opts.lstat ? lstat : stat;
|
|
9486
9704
|
if (wantBigintFsStats) {
|
|
9487
|
-
this._stat = (
|
|
9705
|
+
this._stat = (path23) => statMethod(path23, { bigint: true });
|
|
9488
9706
|
} else {
|
|
9489
9707
|
this._stat = statMethod;
|
|
9490
9708
|
}
|
|
@@ -9509,8 +9727,8 @@ var ReaddirpStream = class extends Readable {
|
|
|
9509
9727
|
const par = this.parent;
|
|
9510
9728
|
const fil = par && par.files;
|
|
9511
9729
|
if (fil && fil.length > 0) {
|
|
9512
|
-
const { path:
|
|
9513
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
9730
|
+
const { path: path23, depth } = par;
|
|
9731
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path23));
|
|
9514
9732
|
const awaited = await Promise.all(slice);
|
|
9515
9733
|
for (const entry of awaited) {
|
|
9516
9734
|
if (!entry)
|
|
@@ -9550,20 +9768,20 @@ var ReaddirpStream = class extends Readable {
|
|
|
9550
9768
|
this.reading = false;
|
|
9551
9769
|
}
|
|
9552
9770
|
}
|
|
9553
|
-
async _exploreDir(
|
|
9771
|
+
async _exploreDir(path23, depth) {
|
|
9554
9772
|
let files;
|
|
9555
9773
|
try {
|
|
9556
|
-
files = await readdir(
|
|
9774
|
+
files = await readdir(path23, this._rdOptions);
|
|
9557
9775
|
} catch (error) {
|
|
9558
9776
|
this._onError(error);
|
|
9559
9777
|
}
|
|
9560
|
-
return { files, depth, path:
|
|
9778
|
+
return { files, depth, path: path23 };
|
|
9561
9779
|
}
|
|
9562
|
-
async _formatEntry(dirent,
|
|
9780
|
+
async _formatEntry(dirent, path23) {
|
|
9563
9781
|
let entry;
|
|
9564
9782
|
const basename5 = this._isDirent ? dirent.name : dirent;
|
|
9565
9783
|
try {
|
|
9566
|
-
const fullPath = presolve(pjoin(
|
|
9784
|
+
const fullPath = presolve(pjoin(path23, basename5));
|
|
9567
9785
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename5 };
|
|
9568
9786
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
9569
9787
|
} catch (err) {
|
|
@@ -9963,16 +10181,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
9963
10181
|
};
|
|
9964
10182
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
9965
10183
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
9966
|
-
function createFsWatchInstance(
|
|
10184
|
+
function createFsWatchInstance(path23, options, listener, errHandler, emitRaw) {
|
|
9967
10185
|
const handleEvent = (rawEvent, evPath) => {
|
|
9968
|
-
listener(
|
|
9969
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
9970
|
-
if (evPath &&
|
|
9971
|
-
fsWatchBroadcast(sp.resolve(
|
|
10186
|
+
listener(path23);
|
|
10187
|
+
emitRaw(rawEvent, evPath, { watchedPath: path23 });
|
|
10188
|
+
if (evPath && path23 !== evPath) {
|
|
10189
|
+
fsWatchBroadcast(sp.resolve(path23, evPath), KEY_LISTENERS, sp.join(path23, evPath));
|
|
9972
10190
|
}
|
|
9973
10191
|
};
|
|
9974
10192
|
try {
|
|
9975
|
-
return fs_watch(
|
|
10193
|
+
return fs_watch(path23, {
|
|
9976
10194
|
persistent: options.persistent
|
|
9977
10195
|
}, handleEvent);
|
|
9978
10196
|
} catch (error) {
|
|
@@ -9988,12 +10206,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
9988
10206
|
listener(val1, val2, val3);
|
|
9989
10207
|
});
|
|
9990
10208
|
};
|
|
9991
|
-
var setFsWatchListener = (
|
|
10209
|
+
var setFsWatchListener = (path23, fullPath, options, handlers) => {
|
|
9992
10210
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
9993
10211
|
let cont = FsWatchInstances.get(fullPath);
|
|
9994
10212
|
let watcher;
|
|
9995
10213
|
if (!options.persistent) {
|
|
9996
|
-
watcher = createFsWatchInstance(
|
|
10214
|
+
watcher = createFsWatchInstance(path23, options, listener, errHandler, rawEmitter);
|
|
9997
10215
|
if (!watcher)
|
|
9998
10216
|
return;
|
|
9999
10217
|
return watcher.close.bind(watcher);
|
|
@@ -10004,7 +10222,7 @@ var setFsWatchListener = (path22, fullPath, options, handlers) => {
|
|
|
10004
10222
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
10005
10223
|
} else {
|
|
10006
10224
|
watcher = createFsWatchInstance(
|
|
10007
|
-
|
|
10225
|
+
path23,
|
|
10008
10226
|
options,
|
|
10009
10227
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
10010
10228
|
errHandler,
|
|
@@ -10019,7 +10237,7 @@ var setFsWatchListener = (path22, fullPath, options, handlers) => {
|
|
|
10019
10237
|
cont.watcherUnusable = true;
|
|
10020
10238
|
if (isWindows && error.code === "EPERM") {
|
|
10021
10239
|
try {
|
|
10022
|
-
const fd = await open(
|
|
10240
|
+
const fd = await open(path23, "r");
|
|
10023
10241
|
await fd.close();
|
|
10024
10242
|
broadcastErr(error);
|
|
10025
10243
|
} catch (err) {
|
|
@@ -10050,7 +10268,7 @@ var setFsWatchListener = (path22, fullPath, options, handlers) => {
|
|
|
10050
10268
|
};
|
|
10051
10269
|
};
|
|
10052
10270
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
10053
|
-
var setFsWatchFileListener = (
|
|
10271
|
+
var setFsWatchFileListener = (path23, fullPath, options, handlers) => {
|
|
10054
10272
|
const { listener, rawEmitter } = handlers;
|
|
10055
10273
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
10056
10274
|
const copts = cont && cont.options;
|
|
@@ -10072,7 +10290,7 @@ var setFsWatchFileListener = (path22, fullPath, options, handlers) => {
|
|
|
10072
10290
|
});
|
|
10073
10291
|
const currmtime = curr.mtimeMs;
|
|
10074
10292
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
10075
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
10293
|
+
foreach(cont.listeners, (listener2) => listener2(path23, curr));
|
|
10076
10294
|
}
|
|
10077
10295
|
})
|
|
10078
10296
|
};
|
|
@@ -10102,13 +10320,13 @@ var NodeFsHandler = class {
|
|
|
10102
10320
|
* @param listener on fs change
|
|
10103
10321
|
* @returns closer for the watcher instance
|
|
10104
10322
|
*/
|
|
10105
|
-
_watchWithNodeFs(
|
|
10323
|
+
_watchWithNodeFs(path23, listener) {
|
|
10106
10324
|
const opts = this.fsw.options;
|
|
10107
|
-
const directory = sp.dirname(
|
|
10108
|
-
const basename5 = sp.basename(
|
|
10325
|
+
const directory = sp.dirname(path23);
|
|
10326
|
+
const basename5 = sp.basename(path23);
|
|
10109
10327
|
const parent = this.fsw._getWatchedDir(directory);
|
|
10110
10328
|
parent.add(basename5);
|
|
10111
|
-
const absolutePath = sp.resolve(
|
|
10329
|
+
const absolutePath = sp.resolve(path23);
|
|
10112
10330
|
const options = {
|
|
10113
10331
|
persistent: opts.persistent
|
|
10114
10332
|
};
|
|
@@ -10118,12 +10336,12 @@ var NodeFsHandler = class {
|
|
|
10118
10336
|
if (opts.usePolling) {
|
|
10119
10337
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
10120
10338
|
options.interval = enableBin && isBinaryPath(basename5) ? opts.binaryInterval : opts.interval;
|
|
10121
|
-
closer = setFsWatchFileListener(
|
|
10339
|
+
closer = setFsWatchFileListener(path23, absolutePath, options, {
|
|
10122
10340
|
listener,
|
|
10123
10341
|
rawEmitter: this.fsw._emitRaw
|
|
10124
10342
|
});
|
|
10125
10343
|
} else {
|
|
10126
|
-
closer = setFsWatchListener(
|
|
10344
|
+
closer = setFsWatchListener(path23, absolutePath, options, {
|
|
10127
10345
|
listener,
|
|
10128
10346
|
errHandler: this._boundHandleError,
|
|
10129
10347
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -10145,7 +10363,7 @@ var NodeFsHandler = class {
|
|
|
10145
10363
|
let prevStats = stats;
|
|
10146
10364
|
if (parent.has(basename5))
|
|
10147
10365
|
return;
|
|
10148
|
-
const listener = async (
|
|
10366
|
+
const listener = async (path23, newStats) => {
|
|
10149
10367
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
10150
10368
|
return;
|
|
10151
10369
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -10159,11 +10377,11 @@ var NodeFsHandler = class {
|
|
|
10159
10377
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
10160
10378
|
}
|
|
10161
10379
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
10162
|
-
this.fsw._closeFile(
|
|
10380
|
+
this.fsw._closeFile(path23);
|
|
10163
10381
|
prevStats = newStats2;
|
|
10164
10382
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
10165
10383
|
if (closer2)
|
|
10166
|
-
this.fsw._addPathCloser(
|
|
10384
|
+
this.fsw._addPathCloser(path23, closer2);
|
|
10167
10385
|
} else {
|
|
10168
10386
|
prevStats = newStats2;
|
|
10169
10387
|
}
|
|
@@ -10195,7 +10413,7 @@ var NodeFsHandler = class {
|
|
|
10195
10413
|
* @param item basename of this item
|
|
10196
10414
|
* @returns true if no more processing is needed for this entry.
|
|
10197
10415
|
*/
|
|
10198
|
-
async _handleSymlink(entry, directory,
|
|
10416
|
+
async _handleSymlink(entry, directory, path23, item) {
|
|
10199
10417
|
if (this.fsw.closed) {
|
|
10200
10418
|
return;
|
|
10201
10419
|
}
|
|
@@ -10205,7 +10423,7 @@ var NodeFsHandler = class {
|
|
|
10205
10423
|
this.fsw._incrReadyCount();
|
|
10206
10424
|
let linkPath;
|
|
10207
10425
|
try {
|
|
10208
|
-
linkPath = await fsrealpath(
|
|
10426
|
+
linkPath = await fsrealpath(path23);
|
|
10209
10427
|
} catch (e) {
|
|
10210
10428
|
this.fsw._emitReady();
|
|
10211
10429
|
return true;
|
|
@@ -10215,12 +10433,12 @@ var NodeFsHandler = class {
|
|
|
10215
10433
|
if (dir.has(item)) {
|
|
10216
10434
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
10217
10435
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
10218
|
-
this.fsw._emit(EV.CHANGE,
|
|
10436
|
+
this.fsw._emit(EV.CHANGE, path23, entry.stats);
|
|
10219
10437
|
}
|
|
10220
10438
|
} else {
|
|
10221
10439
|
dir.add(item);
|
|
10222
10440
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
10223
|
-
this.fsw._emit(EV.ADD,
|
|
10441
|
+
this.fsw._emit(EV.ADD, path23, entry.stats);
|
|
10224
10442
|
}
|
|
10225
10443
|
this.fsw._emitReady();
|
|
10226
10444
|
return true;
|
|
@@ -10250,9 +10468,9 @@ var NodeFsHandler = class {
|
|
|
10250
10468
|
return;
|
|
10251
10469
|
}
|
|
10252
10470
|
const item = entry.path;
|
|
10253
|
-
let
|
|
10471
|
+
let path23 = sp.join(directory, item);
|
|
10254
10472
|
current.add(item);
|
|
10255
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
10473
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path23, item)) {
|
|
10256
10474
|
return;
|
|
10257
10475
|
}
|
|
10258
10476
|
if (this.fsw.closed) {
|
|
@@ -10261,8 +10479,8 @@ var NodeFsHandler = class {
|
|
|
10261
10479
|
}
|
|
10262
10480
|
if (item === target || !target && !previous.has(item)) {
|
|
10263
10481
|
this.fsw._incrReadyCount();
|
|
10264
|
-
|
|
10265
|
-
this._addToNodeFs(
|
|
10482
|
+
path23 = sp.join(dir, sp.relative(dir, path23));
|
|
10483
|
+
this._addToNodeFs(path23, initialAdd, wh, depth + 1);
|
|
10266
10484
|
}
|
|
10267
10485
|
}).on(EV.ERROR, this._boundHandleError);
|
|
10268
10486
|
return new Promise((resolve13, reject) => {
|
|
@@ -10331,13 +10549,13 @@ var NodeFsHandler = class {
|
|
|
10331
10549
|
* @param depth Child path actually targeted for watch
|
|
10332
10550
|
* @param target Child path actually targeted for watch
|
|
10333
10551
|
*/
|
|
10334
|
-
async _addToNodeFs(
|
|
10552
|
+
async _addToNodeFs(path23, initialAdd, priorWh, depth, target) {
|
|
10335
10553
|
const ready = this.fsw._emitReady;
|
|
10336
|
-
if (this.fsw._isIgnored(
|
|
10554
|
+
if (this.fsw._isIgnored(path23) || this.fsw.closed) {
|
|
10337
10555
|
ready();
|
|
10338
10556
|
return false;
|
|
10339
10557
|
}
|
|
10340
|
-
const wh = this.fsw._getWatchHelpers(
|
|
10558
|
+
const wh = this.fsw._getWatchHelpers(path23);
|
|
10341
10559
|
if (priorWh) {
|
|
10342
10560
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
10343
10561
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -10353,8 +10571,8 @@ var NodeFsHandler = class {
|
|
|
10353
10571
|
const follow = this.fsw.options.followSymlinks;
|
|
10354
10572
|
let closer;
|
|
10355
10573
|
if (stats.isDirectory()) {
|
|
10356
|
-
const absPath = sp.resolve(
|
|
10357
|
-
const targetPath = follow ? await fsrealpath(
|
|
10574
|
+
const absPath = sp.resolve(path23);
|
|
10575
|
+
const targetPath = follow ? await fsrealpath(path23) : path23;
|
|
10358
10576
|
if (this.fsw.closed)
|
|
10359
10577
|
return;
|
|
10360
10578
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -10364,29 +10582,29 @@ var NodeFsHandler = class {
|
|
|
10364
10582
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
10365
10583
|
}
|
|
10366
10584
|
} else if (stats.isSymbolicLink()) {
|
|
10367
|
-
const targetPath = follow ? await fsrealpath(
|
|
10585
|
+
const targetPath = follow ? await fsrealpath(path23) : path23;
|
|
10368
10586
|
if (this.fsw.closed)
|
|
10369
10587
|
return;
|
|
10370
10588
|
const parent = sp.dirname(wh.watchPath);
|
|
10371
10589
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
10372
10590
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
10373
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
10591
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path23, wh, targetPath);
|
|
10374
10592
|
if (this.fsw.closed)
|
|
10375
10593
|
return;
|
|
10376
10594
|
if (targetPath !== void 0) {
|
|
10377
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
10595
|
+
this.fsw._symlinkPaths.set(sp.resolve(path23), targetPath);
|
|
10378
10596
|
}
|
|
10379
10597
|
} else {
|
|
10380
10598
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
10381
10599
|
}
|
|
10382
10600
|
ready();
|
|
10383
10601
|
if (closer)
|
|
10384
|
-
this.fsw._addPathCloser(
|
|
10602
|
+
this.fsw._addPathCloser(path23, closer);
|
|
10385
10603
|
return false;
|
|
10386
10604
|
} catch (error) {
|
|
10387
10605
|
if (this.fsw._handleError(error)) {
|
|
10388
10606
|
ready();
|
|
10389
|
-
return
|
|
10607
|
+
return path23;
|
|
10390
10608
|
}
|
|
10391
10609
|
}
|
|
10392
10610
|
}
|
|
@@ -10418,35 +10636,35 @@ function createPattern(matcher) {
|
|
|
10418
10636
|
if (matcher.path === string)
|
|
10419
10637
|
return true;
|
|
10420
10638
|
if (matcher.recursive) {
|
|
10421
|
-
const
|
|
10422
|
-
if (!
|
|
10639
|
+
const relative11 = sp2.relative(matcher.path, string);
|
|
10640
|
+
if (!relative11) {
|
|
10423
10641
|
return false;
|
|
10424
10642
|
}
|
|
10425
|
-
return !
|
|
10643
|
+
return !relative11.startsWith("..") && !sp2.isAbsolute(relative11);
|
|
10426
10644
|
}
|
|
10427
10645
|
return false;
|
|
10428
10646
|
};
|
|
10429
10647
|
}
|
|
10430
10648
|
return () => false;
|
|
10431
10649
|
}
|
|
10432
|
-
function normalizePath(
|
|
10433
|
-
if (typeof
|
|
10650
|
+
function normalizePath(path23) {
|
|
10651
|
+
if (typeof path23 !== "string")
|
|
10434
10652
|
throw new Error("string expected");
|
|
10435
|
-
|
|
10436
|
-
|
|
10653
|
+
path23 = sp2.normalize(path23);
|
|
10654
|
+
path23 = path23.replace(/\\/g, "/");
|
|
10437
10655
|
let prepend = false;
|
|
10438
|
-
if (
|
|
10656
|
+
if (path23.startsWith("//"))
|
|
10439
10657
|
prepend = true;
|
|
10440
|
-
|
|
10658
|
+
path23 = path23.replace(DOUBLE_SLASH_RE, "/");
|
|
10441
10659
|
if (prepend)
|
|
10442
|
-
|
|
10443
|
-
return
|
|
10660
|
+
path23 = "/" + path23;
|
|
10661
|
+
return path23;
|
|
10444
10662
|
}
|
|
10445
10663
|
function matchPatterns(patterns, testString, stats) {
|
|
10446
|
-
const
|
|
10664
|
+
const path23 = normalizePath(testString);
|
|
10447
10665
|
for (let index = 0; index < patterns.length; index++) {
|
|
10448
10666
|
const pattern = patterns[index];
|
|
10449
|
-
if (pattern(
|
|
10667
|
+
if (pattern(path23, stats)) {
|
|
10450
10668
|
return true;
|
|
10451
10669
|
}
|
|
10452
10670
|
}
|
|
@@ -10484,19 +10702,19 @@ var toUnix = (string) => {
|
|
|
10484
10702
|
}
|
|
10485
10703
|
return str;
|
|
10486
10704
|
};
|
|
10487
|
-
var normalizePathToUnix = (
|
|
10488
|
-
var normalizeIgnored = (cwd = "") => (
|
|
10489
|
-
if (typeof
|
|
10490
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
10705
|
+
var normalizePathToUnix = (path23) => toUnix(sp2.normalize(toUnix(path23)));
|
|
10706
|
+
var normalizeIgnored = (cwd = "") => (path23) => {
|
|
10707
|
+
if (typeof path23 === "string") {
|
|
10708
|
+
return normalizePathToUnix(sp2.isAbsolute(path23) ? path23 : sp2.join(cwd, path23));
|
|
10491
10709
|
} else {
|
|
10492
|
-
return
|
|
10710
|
+
return path23;
|
|
10493
10711
|
}
|
|
10494
10712
|
};
|
|
10495
|
-
var getAbsolutePath = (
|
|
10496
|
-
if (sp2.isAbsolute(
|
|
10497
|
-
return
|
|
10713
|
+
var getAbsolutePath = (path23, cwd) => {
|
|
10714
|
+
if (sp2.isAbsolute(path23)) {
|
|
10715
|
+
return path23;
|
|
10498
10716
|
}
|
|
10499
|
-
return sp2.join(cwd,
|
|
10717
|
+
return sp2.join(cwd, path23);
|
|
10500
10718
|
};
|
|
10501
10719
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
10502
10720
|
var DirEntry = class {
|
|
@@ -10561,10 +10779,10 @@ var WatchHelper = class {
|
|
|
10561
10779
|
dirParts;
|
|
10562
10780
|
followSymlinks;
|
|
10563
10781
|
statMethod;
|
|
10564
|
-
constructor(
|
|
10782
|
+
constructor(path23, follow, fsw) {
|
|
10565
10783
|
this.fsw = fsw;
|
|
10566
|
-
const watchPath =
|
|
10567
|
-
this.path =
|
|
10784
|
+
const watchPath = path23;
|
|
10785
|
+
this.path = path23 = path23.replace(REPLACER_RE, "");
|
|
10568
10786
|
this.watchPath = watchPath;
|
|
10569
10787
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
10570
10788
|
this.dirParts = [];
|
|
@@ -10704,20 +10922,20 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
10704
10922
|
this._closePromise = void 0;
|
|
10705
10923
|
let paths = unifyPaths(paths_);
|
|
10706
10924
|
if (cwd) {
|
|
10707
|
-
paths = paths.map((
|
|
10708
|
-
const absPath = getAbsolutePath(
|
|
10925
|
+
paths = paths.map((path23) => {
|
|
10926
|
+
const absPath = getAbsolutePath(path23, cwd);
|
|
10709
10927
|
return absPath;
|
|
10710
10928
|
});
|
|
10711
10929
|
}
|
|
10712
|
-
paths.forEach((
|
|
10713
|
-
this._removeIgnoredPath(
|
|
10930
|
+
paths.forEach((path23) => {
|
|
10931
|
+
this._removeIgnoredPath(path23);
|
|
10714
10932
|
});
|
|
10715
10933
|
this._userIgnored = void 0;
|
|
10716
10934
|
if (!this._readyCount)
|
|
10717
10935
|
this._readyCount = 0;
|
|
10718
10936
|
this._readyCount += paths.length;
|
|
10719
|
-
Promise.all(paths.map(async (
|
|
10720
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
10937
|
+
Promise.all(paths.map(async (path23) => {
|
|
10938
|
+
const res = await this._nodeFsHandler._addToNodeFs(path23, !_internal, void 0, 0, _origAdd);
|
|
10721
10939
|
if (res)
|
|
10722
10940
|
this._emitReady();
|
|
10723
10941
|
return res;
|
|
@@ -10739,17 +10957,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
10739
10957
|
return this;
|
|
10740
10958
|
const paths = unifyPaths(paths_);
|
|
10741
10959
|
const { cwd } = this.options;
|
|
10742
|
-
paths.forEach((
|
|
10743
|
-
if (!sp2.isAbsolute(
|
|
10960
|
+
paths.forEach((path23) => {
|
|
10961
|
+
if (!sp2.isAbsolute(path23) && !this._closers.has(path23)) {
|
|
10744
10962
|
if (cwd)
|
|
10745
|
-
|
|
10746
|
-
|
|
10963
|
+
path23 = sp2.join(cwd, path23);
|
|
10964
|
+
path23 = sp2.resolve(path23);
|
|
10747
10965
|
}
|
|
10748
|
-
this._closePath(
|
|
10749
|
-
this._addIgnoredPath(
|
|
10750
|
-
if (this._watched.has(
|
|
10966
|
+
this._closePath(path23);
|
|
10967
|
+
this._addIgnoredPath(path23);
|
|
10968
|
+
if (this._watched.has(path23)) {
|
|
10751
10969
|
this._addIgnoredPath({
|
|
10752
|
-
path:
|
|
10970
|
+
path: path23,
|
|
10753
10971
|
recursive: true
|
|
10754
10972
|
});
|
|
10755
10973
|
}
|
|
@@ -10813,38 +11031,38 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
10813
11031
|
* @param stats arguments to be passed with event
|
|
10814
11032
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
10815
11033
|
*/
|
|
10816
|
-
async _emit(event,
|
|
11034
|
+
async _emit(event, path23, stats) {
|
|
10817
11035
|
if (this.closed)
|
|
10818
11036
|
return;
|
|
10819
11037
|
const opts = this.options;
|
|
10820
11038
|
if (isWindows)
|
|
10821
|
-
|
|
11039
|
+
path23 = sp2.normalize(path23);
|
|
10822
11040
|
if (opts.cwd)
|
|
10823
|
-
|
|
10824
|
-
const args = [
|
|
11041
|
+
path23 = sp2.relative(opts.cwd, path23);
|
|
11042
|
+
const args = [path23];
|
|
10825
11043
|
if (stats != null)
|
|
10826
11044
|
args.push(stats);
|
|
10827
11045
|
const awf = opts.awaitWriteFinish;
|
|
10828
11046
|
let pw;
|
|
10829
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
11047
|
+
if (awf && (pw = this._pendingWrites.get(path23))) {
|
|
10830
11048
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
10831
11049
|
return this;
|
|
10832
11050
|
}
|
|
10833
11051
|
if (opts.atomic) {
|
|
10834
11052
|
if (event === EVENTS.UNLINK) {
|
|
10835
|
-
this._pendingUnlinks.set(
|
|
11053
|
+
this._pendingUnlinks.set(path23, [event, ...args]);
|
|
10836
11054
|
setTimeout(() => {
|
|
10837
|
-
this._pendingUnlinks.forEach((entry,
|
|
11055
|
+
this._pendingUnlinks.forEach((entry, path24) => {
|
|
10838
11056
|
this.emit(...entry);
|
|
10839
11057
|
this.emit(EVENTS.ALL, ...entry);
|
|
10840
|
-
this._pendingUnlinks.delete(
|
|
11058
|
+
this._pendingUnlinks.delete(path24);
|
|
10841
11059
|
});
|
|
10842
11060
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
10843
11061
|
return this;
|
|
10844
11062
|
}
|
|
10845
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
11063
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path23)) {
|
|
10846
11064
|
event = EVENTS.CHANGE;
|
|
10847
|
-
this._pendingUnlinks.delete(
|
|
11065
|
+
this._pendingUnlinks.delete(path23);
|
|
10848
11066
|
}
|
|
10849
11067
|
}
|
|
10850
11068
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -10862,16 +11080,16 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
10862
11080
|
this.emitWithAll(event, args);
|
|
10863
11081
|
}
|
|
10864
11082
|
};
|
|
10865
|
-
this._awaitWriteFinish(
|
|
11083
|
+
this._awaitWriteFinish(path23, awf.stabilityThreshold, event, awfEmit);
|
|
10866
11084
|
return this;
|
|
10867
11085
|
}
|
|
10868
11086
|
if (event === EVENTS.CHANGE) {
|
|
10869
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
11087
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path23, 50);
|
|
10870
11088
|
if (isThrottled)
|
|
10871
11089
|
return this;
|
|
10872
11090
|
}
|
|
10873
11091
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
10874
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
11092
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path23) : path23;
|
|
10875
11093
|
let stats2;
|
|
10876
11094
|
try {
|
|
10877
11095
|
stats2 = await stat3(fullPath);
|
|
@@ -10902,23 +11120,23 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
10902
11120
|
* @param timeout duration of time to suppress duplicate actions
|
|
10903
11121
|
* @returns tracking object or false if action should be suppressed
|
|
10904
11122
|
*/
|
|
10905
|
-
_throttle(actionType,
|
|
11123
|
+
_throttle(actionType, path23, timeout) {
|
|
10906
11124
|
if (!this._throttled.has(actionType)) {
|
|
10907
11125
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
10908
11126
|
}
|
|
10909
11127
|
const action = this._throttled.get(actionType);
|
|
10910
11128
|
if (!action)
|
|
10911
11129
|
throw new Error("invalid throttle");
|
|
10912
|
-
const actionPath = action.get(
|
|
11130
|
+
const actionPath = action.get(path23);
|
|
10913
11131
|
if (actionPath) {
|
|
10914
11132
|
actionPath.count++;
|
|
10915
11133
|
return false;
|
|
10916
11134
|
}
|
|
10917
11135
|
let timeoutObject;
|
|
10918
11136
|
const clear = () => {
|
|
10919
|
-
const item = action.get(
|
|
11137
|
+
const item = action.get(path23);
|
|
10920
11138
|
const count = item ? item.count : 0;
|
|
10921
|
-
action.delete(
|
|
11139
|
+
action.delete(path23);
|
|
10922
11140
|
clearTimeout(timeoutObject);
|
|
10923
11141
|
if (item)
|
|
10924
11142
|
clearTimeout(item.timeoutObject);
|
|
@@ -10926,7 +11144,7 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
10926
11144
|
};
|
|
10927
11145
|
timeoutObject = setTimeout(clear, timeout);
|
|
10928
11146
|
const thr = { timeoutObject, clear, count: 0 };
|
|
10929
|
-
action.set(
|
|
11147
|
+
action.set(path23, thr);
|
|
10930
11148
|
return thr;
|
|
10931
11149
|
}
|
|
10932
11150
|
_incrReadyCount() {
|
|
@@ -10940,44 +11158,44 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
10940
11158
|
* @param event
|
|
10941
11159
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
10942
11160
|
*/
|
|
10943
|
-
_awaitWriteFinish(
|
|
11161
|
+
_awaitWriteFinish(path23, threshold, event, awfEmit) {
|
|
10944
11162
|
const awf = this.options.awaitWriteFinish;
|
|
10945
11163
|
if (typeof awf !== "object")
|
|
10946
11164
|
return;
|
|
10947
11165
|
const pollInterval = awf.pollInterval;
|
|
10948
11166
|
let timeoutHandler;
|
|
10949
|
-
let fullPath =
|
|
10950
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
10951
|
-
fullPath = sp2.join(this.options.cwd,
|
|
11167
|
+
let fullPath = path23;
|
|
11168
|
+
if (this.options.cwd && !sp2.isAbsolute(path23)) {
|
|
11169
|
+
fullPath = sp2.join(this.options.cwd, path23);
|
|
10952
11170
|
}
|
|
10953
11171
|
const now = /* @__PURE__ */ new Date();
|
|
10954
11172
|
const writes = this._pendingWrites;
|
|
10955
11173
|
function awaitWriteFinishFn(prevStat) {
|
|
10956
11174
|
statcb(fullPath, (err, curStat) => {
|
|
10957
|
-
if (err || !writes.has(
|
|
11175
|
+
if (err || !writes.has(path23)) {
|
|
10958
11176
|
if (err && err.code !== "ENOENT")
|
|
10959
11177
|
awfEmit(err);
|
|
10960
11178
|
return;
|
|
10961
11179
|
}
|
|
10962
11180
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
10963
11181
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
10964
|
-
writes.get(
|
|
11182
|
+
writes.get(path23).lastChange = now2;
|
|
10965
11183
|
}
|
|
10966
|
-
const pw = writes.get(
|
|
11184
|
+
const pw = writes.get(path23);
|
|
10967
11185
|
const df = now2 - pw.lastChange;
|
|
10968
11186
|
if (df >= threshold) {
|
|
10969
|
-
writes.delete(
|
|
11187
|
+
writes.delete(path23);
|
|
10970
11188
|
awfEmit(void 0, curStat);
|
|
10971
11189
|
} else {
|
|
10972
11190
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
10973
11191
|
}
|
|
10974
11192
|
});
|
|
10975
11193
|
}
|
|
10976
|
-
if (!writes.has(
|
|
10977
|
-
writes.set(
|
|
11194
|
+
if (!writes.has(path23)) {
|
|
11195
|
+
writes.set(path23, {
|
|
10978
11196
|
lastChange: now,
|
|
10979
11197
|
cancelWait: () => {
|
|
10980
|
-
writes.delete(
|
|
11198
|
+
writes.delete(path23);
|
|
10981
11199
|
clearTimeout(timeoutHandler);
|
|
10982
11200
|
return event;
|
|
10983
11201
|
}
|
|
@@ -10988,8 +11206,8 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
10988
11206
|
/**
|
|
10989
11207
|
* Determines whether user has asked to ignore this path.
|
|
10990
11208
|
*/
|
|
10991
|
-
_isIgnored(
|
|
10992
|
-
if (this.options.atomic && DOT_RE.test(
|
|
11209
|
+
_isIgnored(path23, stats) {
|
|
11210
|
+
if (this.options.atomic && DOT_RE.test(path23))
|
|
10993
11211
|
return true;
|
|
10994
11212
|
if (!this._userIgnored) {
|
|
10995
11213
|
const { cwd } = this.options;
|
|
@@ -10999,17 +11217,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
10999
11217
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
11000
11218
|
this._userIgnored = anymatch(list, void 0);
|
|
11001
11219
|
}
|
|
11002
|
-
return this._userIgnored(
|
|
11220
|
+
return this._userIgnored(path23, stats);
|
|
11003
11221
|
}
|
|
11004
|
-
_isntIgnored(
|
|
11005
|
-
return !this._isIgnored(
|
|
11222
|
+
_isntIgnored(path23, stat4) {
|
|
11223
|
+
return !this._isIgnored(path23, stat4);
|
|
11006
11224
|
}
|
|
11007
11225
|
/**
|
|
11008
11226
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
11009
11227
|
* @param path file or directory pattern being watched
|
|
11010
11228
|
*/
|
|
11011
|
-
_getWatchHelpers(
|
|
11012
|
-
return new WatchHelper(
|
|
11229
|
+
_getWatchHelpers(path23) {
|
|
11230
|
+
return new WatchHelper(path23, this.options.followSymlinks, this);
|
|
11013
11231
|
}
|
|
11014
11232
|
// Directory helpers
|
|
11015
11233
|
// -----------------
|
|
@@ -11041,63 +11259,63 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
11041
11259
|
* @param item base path of item/directory
|
|
11042
11260
|
*/
|
|
11043
11261
|
_remove(directory, item, isDirectory) {
|
|
11044
|
-
const
|
|
11045
|
-
const fullPath = sp2.resolve(
|
|
11046
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
11047
|
-
if (!this._throttle("remove",
|
|
11262
|
+
const path23 = sp2.join(directory, item);
|
|
11263
|
+
const fullPath = sp2.resolve(path23);
|
|
11264
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path23) || this._watched.has(fullPath);
|
|
11265
|
+
if (!this._throttle("remove", path23, 100))
|
|
11048
11266
|
return;
|
|
11049
11267
|
if (!isDirectory && this._watched.size === 1) {
|
|
11050
11268
|
this.add(directory, item, true);
|
|
11051
11269
|
}
|
|
11052
|
-
const wp = this._getWatchedDir(
|
|
11270
|
+
const wp = this._getWatchedDir(path23);
|
|
11053
11271
|
const nestedDirectoryChildren = wp.getChildren();
|
|
11054
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
11272
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path23, nested));
|
|
11055
11273
|
const parent = this._getWatchedDir(directory);
|
|
11056
11274
|
const wasTracked = parent.has(item);
|
|
11057
11275
|
parent.remove(item);
|
|
11058
11276
|
if (this._symlinkPaths.has(fullPath)) {
|
|
11059
11277
|
this._symlinkPaths.delete(fullPath);
|
|
11060
11278
|
}
|
|
11061
|
-
let relPath =
|
|
11279
|
+
let relPath = path23;
|
|
11062
11280
|
if (this.options.cwd)
|
|
11063
|
-
relPath = sp2.relative(this.options.cwd,
|
|
11281
|
+
relPath = sp2.relative(this.options.cwd, path23);
|
|
11064
11282
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
11065
11283
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
11066
11284
|
if (event === EVENTS.ADD)
|
|
11067
11285
|
return;
|
|
11068
11286
|
}
|
|
11069
|
-
this._watched.delete(
|
|
11287
|
+
this._watched.delete(path23);
|
|
11070
11288
|
this._watched.delete(fullPath);
|
|
11071
11289
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
11072
|
-
if (wasTracked && !this._isIgnored(
|
|
11073
|
-
this._emit(eventName,
|
|
11074
|
-
this._closePath(
|
|
11290
|
+
if (wasTracked && !this._isIgnored(path23))
|
|
11291
|
+
this._emit(eventName, path23);
|
|
11292
|
+
this._closePath(path23);
|
|
11075
11293
|
}
|
|
11076
11294
|
/**
|
|
11077
11295
|
* Closes all watchers for a path
|
|
11078
11296
|
*/
|
|
11079
|
-
_closePath(
|
|
11080
|
-
this._closeFile(
|
|
11081
|
-
const dir = sp2.dirname(
|
|
11082
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
11297
|
+
_closePath(path23) {
|
|
11298
|
+
this._closeFile(path23);
|
|
11299
|
+
const dir = sp2.dirname(path23);
|
|
11300
|
+
this._getWatchedDir(dir).remove(sp2.basename(path23));
|
|
11083
11301
|
}
|
|
11084
11302
|
/**
|
|
11085
11303
|
* Closes only file-specific watchers
|
|
11086
11304
|
*/
|
|
11087
|
-
_closeFile(
|
|
11088
|
-
const closers = this._closers.get(
|
|
11305
|
+
_closeFile(path23) {
|
|
11306
|
+
const closers = this._closers.get(path23);
|
|
11089
11307
|
if (!closers)
|
|
11090
11308
|
return;
|
|
11091
11309
|
closers.forEach((closer) => closer());
|
|
11092
|
-
this._closers.delete(
|
|
11310
|
+
this._closers.delete(path23);
|
|
11093
11311
|
}
|
|
11094
|
-
_addPathCloser(
|
|
11312
|
+
_addPathCloser(path23, closer) {
|
|
11095
11313
|
if (!closer)
|
|
11096
11314
|
return;
|
|
11097
|
-
let list = this._closers.get(
|
|
11315
|
+
let list = this._closers.get(path23);
|
|
11098
11316
|
if (!list) {
|
|
11099
11317
|
list = [];
|
|
11100
|
-
this._closers.set(
|
|
11318
|
+
this._closers.set(path23, list);
|
|
11101
11319
|
}
|
|
11102
11320
|
list.push(closer);
|
|
11103
11321
|
}
|
|
@@ -11127,7 +11345,7 @@ function watch(paths, options = {}) {
|
|
|
11127
11345
|
var chokidar_default = { watch, FSWatcher };
|
|
11128
11346
|
|
|
11129
11347
|
// src/watcher/file-watcher.ts
|
|
11130
|
-
import * as
|
|
11348
|
+
import * as path16 from "path";
|
|
11131
11349
|
var FileWatcher = class {
|
|
11132
11350
|
watcher = null;
|
|
11133
11351
|
projectRoot;
|
|
@@ -11153,15 +11371,15 @@ var FileWatcher = class {
|
|
|
11153
11371
|
const watchTargets = this.configPath ? [this.projectRoot, this.configPath] : this.projectRoot;
|
|
11154
11372
|
this.watcher = chokidar_default.watch(watchTargets, {
|
|
11155
11373
|
ignored: (filePath) => {
|
|
11156
|
-
const relativePath =
|
|
11374
|
+
const relativePath = path16.relative(this.projectRoot, filePath);
|
|
11157
11375
|
if (!relativePath) return false;
|
|
11158
11376
|
if (this.isProjectConfigPathOrAncestor(relativePath)) {
|
|
11159
11377
|
return false;
|
|
11160
11378
|
}
|
|
11161
|
-
if (hasFilteredPathSegment(relativePath,
|
|
11379
|
+
if (hasFilteredPathSegment(relativePath, path16.sep)) {
|
|
11162
11380
|
return true;
|
|
11163
11381
|
}
|
|
11164
|
-
if (isRestrictedDirectory(relativePath,
|
|
11382
|
+
if (isRestrictedDirectory(relativePath, path16.sep)) {
|
|
11165
11383
|
return true;
|
|
11166
11384
|
}
|
|
11167
11385
|
if (ignoreFilter.ignores(relativePath)) {
|
|
@@ -11207,24 +11425,24 @@ var FileWatcher = class {
|
|
|
11207
11425
|
this.scheduleFlush();
|
|
11208
11426
|
}
|
|
11209
11427
|
isProjectConfigPath(filePath) {
|
|
11210
|
-
const relativePath =
|
|
11211
|
-
const normalizedRelativePath =
|
|
11428
|
+
const relativePath = path16.relative(this.projectRoot, filePath);
|
|
11429
|
+
const normalizedRelativePath = path16.normalize(relativePath);
|
|
11212
11430
|
return this.getProjectConfigRelativePaths().some((configPath) => configPath === normalizedRelativePath);
|
|
11213
11431
|
}
|
|
11214
11432
|
isProjectConfigPathOrAncestor(relativePath) {
|
|
11215
|
-
const normalizedRelativePath =
|
|
11433
|
+
const normalizedRelativePath = path16.normalize(relativePath);
|
|
11216
11434
|
return this.getProjectConfigRelativePaths().some(
|
|
11217
|
-
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${
|
|
11435
|
+
(configPath) => configPath === normalizedRelativePath || configPath.startsWith(`${normalizedRelativePath}${path16.sep}`)
|
|
11218
11436
|
);
|
|
11219
11437
|
}
|
|
11220
11438
|
getProjectConfigRelativePaths() {
|
|
11221
11439
|
if (this.configPath) {
|
|
11222
|
-
return [
|
|
11440
|
+
return [path16.normalize(path16.relative(this.projectRoot, this.configPath))];
|
|
11223
11441
|
}
|
|
11224
11442
|
return [
|
|
11225
11443
|
resolveProjectConfigPath(this.projectRoot, this.host),
|
|
11226
11444
|
resolveWritableProjectConfigPath(this.projectRoot, this.host)
|
|
11227
|
-
].map((configPath) =>
|
|
11445
|
+
].map((configPath) => path16.normalize(path16.relative(this.projectRoot, configPath)));
|
|
11228
11446
|
}
|
|
11229
11447
|
scheduleFlush() {
|
|
11230
11448
|
if (this.debounceTimer) {
|
|
@@ -11239,7 +11457,7 @@ var FileWatcher = class {
|
|
|
11239
11457
|
return;
|
|
11240
11458
|
}
|
|
11241
11459
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
11242
|
-
([
|
|
11460
|
+
([path23, type]) => ({ path: path23, type })
|
|
11243
11461
|
);
|
|
11244
11462
|
this.pendingChanges.clear();
|
|
11245
11463
|
try {
|
|
@@ -11266,7 +11484,7 @@ var FileWatcher = class {
|
|
|
11266
11484
|
};
|
|
11267
11485
|
|
|
11268
11486
|
// src/watcher/git-head-watcher.ts
|
|
11269
|
-
import * as
|
|
11487
|
+
import * as path17 from "path";
|
|
11270
11488
|
var GitHeadWatcher = class {
|
|
11271
11489
|
watcher = null;
|
|
11272
11490
|
projectRoot;
|
|
@@ -11288,7 +11506,7 @@ var GitHeadWatcher = class {
|
|
|
11288
11506
|
this.onBranchChange = handler;
|
|
11289
11507
|
this.currentBranch = getCurrentBranch(this.projectRoot);
|
|
11290
11508
|
const headPath = getHeadPath(this.projectRoot);
|
|
11291
|
-
const refsPath =
|
|
11509
|
+
const refsPath = path17.join(this.projectRoot, ".git", "refs", "heads");
|
|
11292
11510
|
this.watcher = chokidar_default.watch([headPath, refsPath], {
|
|
11293
11511
|
persistent: true,
|
|
11294
11512
|
ignoreInitial: true,
|
|
@@ -11521,11 +11739,11 @@ var pr_impact = tool({
|
|
|
11521
11739
|
// src/tools/index.ts
|
|
11522
11740
|
import { writeFileSync as writeFileSync4 } from "fs";
|
|
11523
11741
|
import * as os4 from "os";
|
|
11524
|
-
import * as
|
|
11742
|
+
import * as path20 from "path";
|
|
11525
11743
|
|
|
11526
11744
|
// src/tools/visualize/activity.ts
|
|
11527
11745
|
import { execFileSync } from "child_process";
|
|
11528
|
-
import * as
|
|
11746
|
+
import * as path18 from "path";
|
|
11529
11747
|
function attachRecentActivity(data, projectRoot) {
|
|
11530
11748
|
const activity = readGitActivity(projectRoot);
|
|
11531
11749
|
const changes = activity.size > 0 ? buildGitChanges(data, activity, projectRoot) : buildGraphChanges(data);
|
|
@@ -11687,7 +11905,7 @@ function normalizePath2(filePath) {
|
|
|
11687
11905
|
return filePath.replace(/\\/g, "/");
|
|
11688
11906
|
}
|
|
11689
11907
|
function toGitRelativePath(projectRoot, filePath) {
|
|
11690
|
-
const relativePath =
|
|
11908
|
+
const relativePath = path18.isAbsolute(filePath) ? path18.relative(projectRoot, filePath) : filePath;
|
|
11691
11909
|
return normalizePath2(relativePath);
|
|
11692
11910
|
}
|
|
11693
11911
|
|
|
@@ -11945,7 +12163,7 @@ render();
|
|
|
11945
12163
|
}
|
|
11946
12164
|
|
|
11947
12165
|
// src/tools/visualize/transform.ts
|
|
11948
|
-
import * as
|
|
12166
|
+
import * as path19 from "path";
|
|
11949
12167
|
|
|
11950
12168
|
// src/tools/visualize/modules.ts
|
|
11951
12169
|
var MAX_MODULES = 18;
|
|
@@ -12078,8 +12296,8 @@ function compactModules(prefixToNodes) {
|
|
|
12078
12296
|
function deriveModules(nodes) {
|
|
12079
12297
|
const initial = /* @__PURE__ */ new Map();
|
|
12080
12298
|
for (const node of nodes) {
|
|
12081
|
-
const
|
|
12082
|
-
const prefix = modulePrefixFromRelativePath(
|
|
12299
|
+
const relative11 = stripToProjectRelative(node.filePath);
|
|
12300
|
+
const prefix = modulePrefixFromRelativePath(relative11);
|
|
12083
12301
|
if (!initial.has(prefix)) initial.set(prefix, []);
|
|
12084
12302
|
initial.get(prefix)?.push(node);
|
|
12085
12303
|
}
|
|
@@ -12205,7 +12423,7 @@ function transformForVisualization(symbols, edges, options = {}) {
|
|
|
12205
12423
|
filePath: s.filePath,
|
|
12206
12424
|
kind: s.kind,
|
|
12207
12425
|
line: s.startLine,
|
|
12208
|
-
directory:
|
|
12426
|
+
directory: path19.dirname(s.filePath),
|
|
12209
12427
|
moduleId: "",
|
|
12210
12428
|
moduleLabel: ""
|
|
12211
12429
|
}));
|
|
@@ -12256,7 +12474,10 @@ var codebase_peek = tool2({
|
|
|
12256
12474
|
limit: z2.number().optional().default(10).describe("Maximum number of results to return"),
|
|
12257
12475
|
fileType: z2.string().optional().describe("Filter by file extension (e.g., 'ts', 'py', 'rs')"),
|
|
12258
12476
|
directory: z2.string().optional().describe("Filter by directory path (e.g., 'src/utils', 'lib')"),
|
|
12259
|
-
chunkType: z2.enum(CHUNK_TYPE_VALUES).optional().describe("Filter by code chunk type")
|
|
12477
|
+
chunkType: z2.enum(CHUNK_TYPE_VALUES).optional().describe("Filter by code chunk type"),
|
|
12478
|
+
blameAuthor: z2.string().optional().describe("Filter by git blame author name or email"),
|
|
12479
|
+
blameSha: z2.string().optional().describe("Filter by git blame commit SHA or prefix"),
|
|
12480
|
+
blameSince: z2.string().optional().describe("Filter to chunks last changed on or after this date (e.g., 2025-01-01)")
|
|
12260
12481
|
},
|
|
12261
12482
|
async execute(args, context) {
|
|
12262
12483
|
const results = await searchCodebase(context?.worktree, DEFAULT_HOST, args.query, {
|
|
@@ -12264,7 +12485,10 @@ var codebase_peek = tool2({
|
|
|
12264
12485
|
fileType: args.fileType,
|
|
12265
12486
|
directory: args.directory,
|
|
12266
12487
|
chunkType: args.chunkType,
|
|
12267
|
-
metadataOnly: true
|
|
12488
|
+
metadataOnly: true,
|
|
12489
|
+
blameAuthor: args.blameAuthor,
|
|
12490
|
+
blameSha: args.blameSha,
|
|
12491
|
+
blameSince: args.blameSince
|
|
12268
12492
|
});
|
|
12269
12493
|
return formatCodebasePeek(results);
|
|
12270
12494
|
}
|
|
@@ -12347,7 +12571,10 @@ var codebase_search = tool2({
|
|
|
12347
12571
|
fileType: z2.string().optional().describe("Filter by file extension (e.g., 'ts', 'py', 'rs')"),
|
|
12348
12572
|
directory: z2.string().optional().describe("Filter by directory path (e.g., 'src/utils', 'lib')"),
|
|
12349
12573
|
chunkType: z2.enum(CHUNK_TYPE_VALUES).optional().describe("Filter by code chunk type"),
|
|
12350
|
-
contextLines: z2.number().optional().describe("Number of extra lines to include before/after each match (default: 0)")
|
|
12574
|
+
contextLines: z2.number().optional().describe("Number of extra lines to include before/after each match (default: 0)"),
|
|
12575
|
+
blameAuthor: z2.string().optional().describe("Filter by git blame author name or email"),
|
|
12576
|
+
blameSha: z2.string().optional().describe("Filter by git blame commit SHA or prefix"),
|
|
12577
|
+
blameSince: z2.string().optional().describe("Filter to chunks last changed on or after this date (e.g., 2025-01-01)")
|
|
12351
12578
|
},
|
|
12352
12579
|
async execute(args, context) {
|
|
12353
12580
|
const results = await searchCodebase(context?.worktree, DEFAULT_HOST, args.query, {
|
|
@@ -12355,7 +12582,10 @@ var codebase_search = tool2({
|
|
|
12355
12582
|
fileType: args.fileType,
|
|
12356
12583
|
directory: args.directory,
|
|
12357
12584
|
chunkType: args.chunkType,
|
|
12358
|
-
contextLines: args.contextLines
|
|
12585
|
+
contextLines: args.contextLines,
|
|
12586
|
+
blameAuthor: args.blameAuthor,
|
|
12587
|
+
blameSha: args.blameSha,
|
|
12588
|
+
blameSince: args.blameSince
|
|
12359
12589
|
});
|
|
12360
12590
|
if (results.length === 0) {
|
|
12361
12591
|
return "No matching code found. Try a different query or run index_codebase first.";
|
|
@@ -12394,22 +12624,10 @@ var call_graph = tool2({
|
|
|
12394
12624
|
return "Error: 'symbolId' is required when direction is 'callees'. First use direction='callers' to find the symbol ID.";
|
|
12395
12625
|
}
|
|
12396
12626
|
const { callees } = await getCallGraphData(context?.worktree, DEFAULT_HOST, args);
|
|
12397
|
-
|
|
12398
|
-
return `No callees found for symbol ${args.symbolId}${args.relationshipType ? ` with type ${args.relationshipType}` : ""}. The function may not call any other tracked functions.`;
|
|
12399
|
-
}
|
|
12400
|
-
return callees.map((edge, index) => {
|
|
12401
|
-
const confidence = edge.confidence !== "Direct" ? ` [${edge.confidence.toLowerCase()}]` : "";
|
|
12402
|
-
return `[${index + 1}] \u2192 ${edge.targetName} (${edge.callType})${confidence} at line ${edge.line}${edge.isResolved ? ` [resolved: ${edge.toSymbolId}]` : " [unresolved]"}`;
|
|
12403
|
-
}).join("\n");
|
|
12627
|
+
return formatCallGraphCallees(args.symbolId, callees, args.relationshipType);
|
|
12404
12628
|
}
|
|
12405
12629
|
const { callers } = await getCallGraphData(context?.worktree, DEFAULT_HOST, args);
|
|
12406
|
-
|
|
12407
|
-
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.`;
|
|
12408
|
-
}
|
|
12409
|
-
return callers.map((edge, index) => {
|
|
12410
|
-
const confidence = edge.confidence !== "Direct" ? ` [${edge.confidence.toLowerCase()}]` : "";
|
|
12411
|
-
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]"}`;
|
|
12412
|
-
}).join("\n");
|
|
12630
|
+
return formatCallGraphCallers(args.name, callers, args.relationshipType);
|
|
12413
12631
|
}
|
|
12414
12632
|
});
|
|
12415
12633
|
var call_graph_path = tool2({
|
|
@@ -12420,17 +12638,8 @@ var call_graph_path = tool2({
|
|
|
12420
12638
|
maxDepth: z2.number().optional().default(10).describe("Maximum traversal depth (default: 10)")
|
|
12421
12639
|
},
|
|
12422
12640
|
async execute(args, context) {
|
|
12423
|
-
const
|
|
12424
|
-
|
|
12425
|
-
return `No path found between "${args.from}" and "${args.to}". They may be in disconnected components, or the call graph index needs updating.`;
|
|
12426
|
-
}
|
|
12427
|
-
const formatted = path22.map((hop, index) => {
|
|
12428
|
-
const prefix = index === 0 ? "[start]" : `--${hop.callType}-->`;
|
|
12429
|
-
const location = hop.filePath ? ` (${hop.filePath}:${hop.line})` : "";
|
|
12430
|
-
return `${prefix} ${hop.symbolName}${location}`;
|
|
12431
|
-
});
|
|
12432
|
-
return `Path (${path22.length} hops):
|
|
12433
|
-
${formatted.join("\n")}`;
|
|
12641
|
+
const path23 = await getCallGraphPath(context?.worktree, DEFAULT_HOST, args.from, args.to, args.maxDepth);
|
|
12642
|
+
return formatCallGraphPath(args.from, args.to, path23);
|
|
12434
12643
|
}
|
|
12435
12644
|
});
|
|
12436
12645
|
var add_knowledge_base = tool2({
|
|
@@ -12483,7 +12692,7 @@ var index_visualize = tool2({
|
|
|
12483
12692
|
return "No connected symbols found for visualization. Try including orphans with includeOrphans=true, or check that the call graph has resolved edges.";
|
|
12484
12693
|
}
|
|
12485
12694
|
const html = generateVisualizationHtml(vizData);
|
|
12486
|
-
const outputPath =
|
|
12695
|
+
const outputPath = path20.join(os4.tmpdir(), `call-graph-${Date.now()}.html`);
|
|
12487
12696
|
writeFileSync4(outputPath, html, "utf-8");
|
|
12488
12697
|
let result = `Temporal call graph visualization generated: ${outputPath}
|
|
12489
12698
|
|
|
@@ -12506,7 +12715,7 @@ var index_visualize = tool2({
|
|
|
12506
12715
|
|
|
12507
12716
|
// src/commands/loader.ts
|
|
12508
12717
|
import { existsSync as existsSync10, readdirSync as readdirSync2, readFileSync as readFileSync7 } from "fs";
|
|
12509
|
-
import * as
|
|
12718
|
+
import * as path21 from "path";
|
|
12510
12719
|
function parseFrontmatter(content) {
|
|
12511
12720
|
const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
|
|
12512
12721
|
const match = content.match(frontmatterRegex);
|
|
@@ -12532,7 +12741,7 @@ function loadCommandsFromDirectory(commandsDir) {
|
|
|
12532
12741
|
}
|
|
12533
12742
|
const files = readdirSync2(commandsDir).filter((f) => f.endsWith(".md"));
|
|
12534
12743
|
for (const file of files) {
|
|
12535
|
-
const filePath =
|
|
12744
|
+
const filePath = path21.join(commandsDir, file);
|
|
12536
12745
|
let content;
|
|
12537
12746
|
try {
|
|
12538
12747
|
content = readFileSync7(filePath, "utf-8");
|
|
@@ -12541,7 +12750,7 @@ function loadCommandsFromDirectory(commandsDir) {
|
|
|
12541
12750
|
throw new Error(`Failed to load command file ${filePath}: ${message}`);
|
|
12542
12751
|
}
|
|
12543
12752
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
12544
|
-
const name =
|
|
12753
|
+
const name = path21.basename(file, ".md");
|
|
12545
12754
|
const description = frontmatter.description || `Run the ${name} command`;
|
|
12546
12755
|
commands.set(name, {
|
|
12547
12756
|
description,
|
|
@@ -12873,9 +13082,9 @@ function replaceActiveWatcher(projectRoot, nextWatcher) {
|
|
|
12873
13082
|
function getCommandsDir() {
|
|
12874
13083
|
let currentDir = process.cwd();
|
|
12875
13084
|
if (typeof import.meta !== "undefined" && import.meta.url) {
|
|
12876
|
-
currentDir =
|
|
13085
|
+
currentDir = path22.dirname(fileURLToPath2(import.meta.url));
|
|
12877
13086
|
}
|
|
12878
|
-
return
|
|
13087
|
+
return path22.join(currentDir, "..", "commands");
|
|
12879
13088
|
}
|
|
12880
13089
|
function appendRoutingHints(output, hints, preferredRole) {
|
|
12881
13090
|
const preferredBucket = preferredRole === "developer" ? output.developer : output.system;
|
|
@@ -12895,7 +13104,7 @@ var plugin = async ({ directory, worktree }) => {
|
|
|
12895
13104
|
initializeTools2(projectRoot, config);
|
|
12896
13105
|
const getProjectIndexer = () => getIndexerForProject2(projectRoot);
|
|
12897
13106
|
const routingHints = config.search.routingHints ? new RoutingHintController(() => getProjectIndexer().getStatus(), 200, config.search.routingGraphHandoffHints) : null;
|
|
12898
|
-
const isHomeDir =
|
|
13107
|
+
const isHomeDir = path22.resolve(projectRoot) === path22.resolve(os5.homedir());
|
|
12899
13108
|
const isValidProject = !isHomeDir && (!config.indexing.requireProjectMarker || hasProjectMarker(projectRoot));
|
|
12900
13109
|
if (isHomeDir) {
|
|
12901
13110
|
console.warn(
|