opencode-codebase-index 0.1.10 → 0.1.11
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/LICENSE +21 -0
- package/README.md +56 -29
- package/dist/index.cjs +345 -309
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +342 -306
- package/dist/index.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 +1 -1
package/dist/index.js
CHANGED
|
@@ -491,7 +491,7 @@ var require_ignore = __commonJS({
|
|
|
491
491
|
// path matching.
|
|
492
492
|
// - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
|
|
493
493
|
// @returns {TestResult} true if a file is ignored
|
|
494
|
-
test(
|
|
494
|
+
test(path7, checkUnignored, mode) {
|
|
495
495
|
let ignored = false;
|
|
496
496
|
let unignored = false;
|
|
497
497
|
let matchedRule;
|
|
@@ -500,7 +500,7 @@ var require_ignore = __commonJS({
|
|
|
500
500
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
501
501
|
return;
|
|
502
502
|
}
|
|
503
|
-
const matched = rule[mode].test(
|
|
503
|
+
const matched = rule[mode].test(path7);
|
|
504
504
|
if (!matched) {
|
|
505
505
|
return;
|
|
506
506
|
}
|
|
@@ -521,17 +521,17 @@ var require_ignore = __commonJS({
|
|
|
521
521
|
var throwError = (message, Ctor) => {
|
|
522
522
|
throw new Ctor(message);
|
|
523
523
|
};
|
|
524
|
-
var checkPath = (
|
|
525
|
-
if (!isString(
|
|
524
|
+
var checkPath = (path7, originalPath, doThrow) => {
|
|
525
|
+
if (!isString(path7)) {
|
|
526
526
|
return doThrow(
|
|
527
527
|
`path must be a string, but got \`${originalPath}\``,
|
|
528
528
|
TypeError
|
|
529
529
|
);
|
|
530
530
|
}
|
|
531
|
-
if (!
|
|
531
|
+
if (!path7) {
|
|
532
532
|
return doThrow(`path must not be empty`, TypeError);
|
|
533
533
|
}
|
|
534
|
-
if (checkPath.isNotRelative(
|
|
534
|
+
if (checkPath.isNotRelative(path7)) {
|
|
535
535
|
const r = "`path.relative()`d";
|
|
536
536
|
return doThrow(
|
|
537
537
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -540,7 +540,7 @@ var require_ignore = __commonJS({
|
|
|
540
540
|
}
|
|
541
541
|
return true;
|
|
542
542
|
};
|
|
543
|
-
var isNotRelative = (
|
|
543
|
+
var isNotRelative = (path7) => REGEX_TEST_INVALID_PATH.test(path7);
|
|
544
544
|
checkPath.isNotRelative = isNotRelative;
|
|
545
545
|
checkPath.convert = (p) => p;
|
|
546
546
|
var Ignore2 = class {
|
|
@@ -570,19 +570,19 @@ var require_ignore = __commonJS({
|
|
|
570
570
|
}
|
|
571
571
|
// @returns {TestResult}
|
|
572
572
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
573
|
-
const
|
|
573
|
+
const path7 = originalPath && checkPath.convert(originalPath);
|
|
574
574
|
checkPath(
|
|
575
|
-
|
|
575
|
+
path7,
|
|
576
576
|
originalPath,
|
|
577
577
|
this._strictPathCheck ? throwError : RETURN_FALSE
|
|
578
578
|
);
|
|
579
|
-
return this._t(
|
|
579
|
+
return this._t(path7, cache, checkUnignored, slices);
|
|
580
580
|
}
|
|
581
|
-
checkIgnore(
|
|
582
|
-
if (!REGEX_TEST_TRAILING_SLASH.test(
|
|
583
|
-
return this.test(
|
|
581
|
+
checkIgnore(path7) {
|
|
582
|
+
if (!REGEX_TEST_TRAILING_SLASH.test(path7)) {
|
|
583
|
+
return this.test(path7);
|
|
584
584
|
}
|
|
585
|
-
const slices =
|
|
585
|
+
const slices = path7.split(SLASH2).filter(Boolean);
|
|
586
586
|
slices.pop();
|
|
587
587
|
if (slices.length) {
|
|
588
588
|
const parent = this._t(
|
|
@@ -595,18 +595,18 @@ var require_ignore = __commonJS({
|
|
|
595
595
|
return parent;
|
|
596
596
|
}
|
|
597
597
|
}
|
|
598
|
-
return this._rules.test(
|
|
598
|
+
return this._rules.test(path7, false, MODE_CHECK_IGNORE);
|
|
599
599
|
}
|
|
600
|
-
_t(
|
|
601
|
-
if (
|
|
602
|
-
return cache[
|
|
600
|
+
_t(path7, cache, checkUnignored, slices) {
|
|
601
|
+
if (path7 in cache) {
|
|
602
|
+
return cache[path7];
|
|
603
603
|
}
|
|
604
604
|
if (!slices) {
|
|
605
|
-
slices =
|
|
605
|
+
slices = path7.split(SLASH2).filter(Boolean);
|
|
606
606
|
}
|
|
607
607
|
slices.pop();
|
|
608
608
|
if (!slices.length) {
|
|
609
|
-
return cache[
|
|
609
|
+
return cache[path7] = this._rules.test(path7, checkUnignored, MODE_IGNORE);
|
|
610
610
|
}
|
|
611
611
|
const parent = this._t(
|
|
612
612
|
slices.join(SLASH2) + SLASH2,
|
|
@@ -614,29 +614,29 @@ var require_ignore = __commonJS({
|
|
|
614
614
|
checkUnignored,
|
|
615
615
|
slices
|
|
616
616
|
);
|
|
617
|
-
return cache[
|
|
617
|
+
return cache[path7] = parent.ignored ? parent : this._rules.test(path7, checkUnignored, MODE_IGNORE);
|
|
618
618
|
}
|
|
619
|
-
ignores(
|
|
620
|
-
return this._test(
|
|
619
|
+
ignores(path7) {
|
|
620
|
+
return this._test(path7, this._ignoreCache, false).ignored;
|
|
621
621
|
}
|
|
622
622
|
createFilter() {
|
|
623
|
-
return (
|
|
623
|
+
return (path7) => !this.ignores(path7);
|
|
624
624
|
}
|
|
625
625
|
filter(paths) {
|
|
626
626
|
return makeArray(paths).filter(this.createFilter());
|
|
627
627
|
}
|
|
628
628
|
// @returns {TestResult}
|
|
629
|
-
test(
|
|
630
|
-
return this._test(
|
|
629
|
+
test(path7) {
|
|
630
|
+
return this._test(path7, this._testCache, true);
|
|
631
631
|
}
|
|
632
632
|
};
|
|
633
633
|
var factory = (options) => new Ignore2(options);
|
|
634
|
-
var isPathValid = (
|
|
634
|
+
var isPathValid = (path7) => checkPath(path7 && checkPath.convert(path7), path7, RETURN_FALSE);
|
|
635
635
|
var setupWindows = () => {
|
|
636
636
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
637
637
|
checkPath.convert = makePosix;
|
|
638
638
|
const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
639
|
-
checkPath.isNotRelative = (
|
|
639
|
+
checkPath.isNotRelative = (path7) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path7) || isNotRelative(path7);
|
|
640
640
|
};
|
|
641
641
|
if (
|
|
642
642
|
// Detect `process` so that it can run in browsers.
|
|
@@ -652,8 +652,8 @@ var require_ignore = __commonJS({
|
|
|
652
652
|
});
|
|
653
653
|
|
|
654
654
|
// src/index.ts
|
|
655
|
-
import { existsSync as
|
|
656
|
-
import * as
|
|
655
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
656
|
+
import * as path6 from "path";
|
|
657
657
|
|
|
658
658
|
// src/config/schema.ts
|
|
659
659
|
var DEFAULT_INCLUDE = [
|
|
@@ -688,6 +688,8 @@ function getDefaultIndexingConfig() {
|
|
|
688
688
|
autoIndex: false,
|
|
689
689
|
watchFiles: true,
|
|
690
690
|
maxFileSize: 1048576,
|
|
691
|
+
maxChunksPerFile: 100,
|
|
692
|
+
semanticOnly: false,
|
|
691
693
|
retries: 3,
|
|
692
694
|
retryDelayMs: 1e3
|
|
693
695
|
};
|
|
@@ -721,6 +723,8 @@ function parseConfig(raw) {
|
|
|
721
723
|
autoIndex: typeof rawIndexing.autoIndex === "boolean" ? rawIndexing.autoIndex : defaultIndexing.autoIndex,
|
|
722
724
|
watchFiles: typeof rawIndexing.watchFiles === "boolean" ? rawIndexing.watchFiles : defaultIndexing.watchFiles,
|
|
723
725
|
maxFileSize: typeof rawIndexing.maxFileSize === "number" ? rawIndexing.maxFileSize : defaultIndexing.maxFileSize,
|
|
726
|
+
maxChunksPerFile: typeof rawIndexing.maxChunksPerFile === "number" ? Math.max(1, rawIndexing.maxChunksPerFile) : defaultIndexing.maxChunksPerFile,
|
|
727
|
+
semanticOnly: typeof rawIndexing.semanticOnly === "boolean" ? rawIndexing.semanticOnly : defaultIndexing.semanticOnly,
|
|
724
728
|
retries: typeof rawIndexing.retries === "number" ? rawIndexing.retries : defaultIndexing.retries,
|
|
725
729
|
retryDelayMs: typeof rawIndexing.retryDelayMs === "number" ? rawIndexing.retryDelayMs : defaultIndexing.retryDelayMs
|
|
726
730
|
};
|
|
@@ -802,8 +806,8 @@ function getDefaultModelForProvider(provider) {
|
|
|
802
806
|
}
|
|
803
807
|
|
|
804
808
|
// src/indexer/index.ts
|
|
805
|
-
import { existsSync as
|
|
806
|
-
import * as
|
|
809
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync, promises as fsPromises2 } from "fs";
|
|
810
|
+
import * as path4 from "path";
|
|
807
811
|
|
|
808
812
|
// node_modules/eventemitter3/index.mjs
|
|
809
813
|
var import_index = __toESM(require_eventemitter3(), 1);
|
|
@@ -2620,139 +2624,39 @@ function generateChunkId(filePath, chunk) {
|
|
|
2620
2624
|
function generateChunkHash(chunk) {
|
|
2621
2625
|
return hashContent(chunk.content);
|
|
2622
2626
|
}
|
|
2623
|
-
|
|
2624
|
-
// src/indexer/inverted-index.ts
|
|
2625
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync } from "fs";
|
|
2626
|
-
import * as path4 from "path";
|
|
2627
2627
|
var InvertedIndex = class {
|
|
2628
|
-
|
|
2629
|
-
termToChunks = /* @__PURE__ */ new Map();
|
|
2630
|
-
chunkTokens = /* @__PURE__ */ new Map();
|
|
2631
|
-
totalTokenCount = 0;
|
|
2628
|
+
inner;
|
|
2632
2629
|
constructor(indexPath) {
|
|
2633
|
-
this.
|
|
2630
|
+
this.inner = new native.InvertedIndex(indexPath);
|
|
2634
2631
|
}
|
|
2635
2632
|
load() {
|
|
2636
|
-
|
|
2637
|
-
return;
|
|
2638
|
-
}
|
|
2639
|
-
try {
|
|
2640
|
-
const content = readFileSync3(this.indexPath, "utf-8");
|
|
2641
|
-
const data = JSON.parse(content);
|
|
2642
|
-
for (const [term, chunkIds] of Object.entries(data.termToChunks)) {
|
|
2643
|
-
this.termToChunks.set(term, new Set(chunkIds));
|
|
2644
|
-
}
|
|
2645
|
-
for (const [chunkId, tokens] of Object.entries(data.chunkTokens)) {
|
|
2646
|
-
const tokenMap = new Map(Object.entries(tokens).map(([k, v]) => [k, v]));
|
|
2647
|
-
this.chunkTokens.set(chunkId, tokenMap);
|
|
2648
|
-
for (const count of tokenMap.values()) {
|
|
2649
|
-
this.totalTokenCount += count;
|
|
2650
|
-
}
|
|
2651
|
-
}
|
|
2652
|
-
} catch {
|
|
2653
|
-
this.termToChunks.clear();
|
|
2654
|
-
this.chunkTokens.clear();
|
|
2655
|
-
this.totalTokenCount = 0;
|
|
2656
|
-
}
|
|
2633
|
+
this.inner.load();
|
|
2657
2634
|
}
|
|
2658
2635
|
save() {
|
|
2659
|
-
|
|
2660
|
-
termToChunks: {},
|
|
2661
|
-
chunkTokens: {},
|
|
2662
|
-
avgDocLength: this.getAvgDocLength()
|
|
2663
|
-
};
|
|
2664
|
-
for (const [term, chunkIds] of this.termToChunks) {
|
|
2665
|
-
data.termToChunks[term] = Array.from(chunkIds);
|
|
2666
|
-
}
|
|
2667
|
-
for (const [chunkId, tokens] of this.chunkTokens) {
|
|
2668
|
-
data.chunkTokens[chunkId] = Object.fromEntries(tokens);
|
|
2669
|
-
}
|
|
2670
|
-
writeFileSync(this.indexPath, JSON.stringify(data));
|
|
2636
|
+
this.inner.save();
|
|
2671
2637
|
}
|
|
2672
2638
|
addChunk(chunkId, content) {
|
|
2673
|
-
|
|
2674
|
-
const termFreq = /* @__PURE__ */ new Map();
|
|
2675
|
-
for (const token of tokens) {
|
|
2676
|
-
termFreq.set(token, (termFreq.get(token) || 0) + 1);
|
|
2677
|
-
const chunks = this.termToChunks.get(token) || /* @__PURE__ */ new Set();
|
|
2678
|
-
chunks.add(chunkId);
|
|
2679
|
-
this.termToChunks.set(token, chunks);
|
|
2680
|
-
}
|
|
2681
|
-
this.chunkTokens.set(chunkId, termFreq);
|
|
2682
|
-
this.totalTokenCount += tokens.length;
|
|
2639
|
+
this.inner.addChunk(chunkId, content);
|
|
2683
2640
|
}
|
|
2684
2641
|
removeChunk(chunkId) {
|
|
2685
|
-
|
|
2686
|
-
if (!tokens) return;
|
|
2687
|
-
for (const [token, count] of tokens) {
|
|
2688
|
-
this.totalTokenCount -= count;
|
|
2689
|
-
const chunks = this.termToChunks.get(token);
|
|
2690
|
-
if (chunks) {
|
|
2691
|
-
chunks.delete(chunkId);
|
|
2692
|
-
if (chunks.size === 0) {
|
|
2693
|
-
this.termToChunks.delete(token);
|
|
2694
|
-
}
|
|
2695
|
-
}
|
|
2696
|
-
}
|
|
2697
|
-
this.chunkTokens.delete(chunkId);
|
|
2642
|
+
return this.inner.removeChunk(chunkId);
|
|
2698
2643
|
}
|
|
2699
|
-
search(query) {
|
|
2700
|
-
const
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
const candidateChunks = /* @__PURE__ */ new Set();
|
|
2705
|
-
for (const token of queryTokens) {
|
|
2706
|
-
const chunks = this.termToChunks.get(token);
|
|
2707
|
-
if (chunks) {
|
|
2708
|
-
for (const chunkId of chunks) {
|
|
2709
|
-
candidateChunks.add(chunkId);
|
|
2710
|
-
}
|
|
2711
|
-
}
|
|
2644
|
+
search(query, limit) {
|
|
2645
|
+
const results = this.inner.search(query, limit ?? 100);
|
|
2646
|
+
const map = /* @__PURE__ */ new Map();
|
|
2647
|
+
for (const r of results) {
|
|
2648
|
+
map.set(r.chunkId, r.score);
|
|
2712
2649
|
}
|
|
2713
|
-
|
|
2714
|
-
const k1 = 1.2;
|
|
2715
|
-
const b = 0.75;
|
|
2716
|
-
const N = this.chunkTokens.size;
|
|
2717
|
-
const avgDocLength = this.getAvgDocLength();
|
|
2718
|
-
for (const chunkId of candidateChunks) {
|
|
2719
|
-
const termFreq = this.chunkTokens.get(chunkId);
|
|
2720
|
-
if (!termFreq) continue;
|
|
2721
|
-
const docLength = Array.from(termFreq.values()).reduce((a, b2) => a + b2, 0);
|
|
2722
|
-
let score = 0;
|
|
2723
|
-
for (const term of queryTokens) {
|
|
2724
|
-
const tf = termFreq.get(term) || 0;
|
|
2725
|
-
if (tf === 0) continue;
|
|
2726
|
-
const df = this.termToChunks.get(term)?.size || 0;
|
|
2727
|
-
const idf = Math.log((N - df + 0.5) / (df + 0.5) + 1);
|
|
2728
|
-
const tfNorm = tf * (k1 + 1) / (tf + k1 * (1 - b + b * (docLength / avgDocLength)));
|
|
2729
|
-
score += idf * tfNorm;
|
|
2730
|
-
}
|
|
2731
|
-
scores.set(chunkId, score);
|
|
2732
|
-
}
|
|
2733
|
-
const maxScore = Math.max(...scores.values(), 1);
|
|
2734
|
-
for (const [chunkId, score] of scores) {
|
|
2735
|
-
scores.set(chunkId, score / maxScore);
|
|
2736
|
-
}
|
|
2737
|
-
return scores;
|
|
2650
|
+
return map;
|
|
2738
2651
|
}
|
|
2739
2652
|
hasChunk(chunkId) {
|
|
2740
|
-
return this.
|
|
2653
|
+
return this.inner.hasChunk(chunkId);
|
|
2741
2654
|
}
|
|
2742
2655
|
clear() {
|
|
2743
|
-
this.
|
|
2744
|
-
this.chunkTokens.clear();
|
|
2745
|
-
this.totalTokenCount = 0;
|
|
2656
|
+
this.inner.clear();
|
|
2746
2657
|
}
|
|
2747
2658
|
getDocumentCount() {
|
|
2748
|
-
return this.
|
|
2749
|
-
}
|
|
2750
|
-
getAvgDocLength() {
|
|
2751
|
-
const count = this.chunkTokens.size;
|
|
2752
|
-
return count > 0 ? this.totalTokenCount / count : 100;
|
|
2753
|
-
}
|
|
2754
|
-
tokenize(text) {
|
|
2755
|
-
return text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((t) => t.length > 2);
|
|
2659
|
+
return this.inner.documentCount();
|
|
2756
2660
|
}
|
|
2757
2661
|
};
|
|
2758
2662
|
|
|
@@ -2767,23 +2671,25 @@ var Indexer = class {
|
|
|
2767
2671
|
detectedProvider = null;
|
|
2768
2672
|
fileHashCache = /* @__PURE__ */ new Map();
|
|
2769
2673
|
fileHashCachePath = "";
|
|
2674
|
+
failedBatchesPath = "";
|
|
2770
2675
|
constructor(projectRoot, config) {
|
|
2771
2676
|
this.projectRoot = projectRoot;
|
|
2772
2677
|
this.config = config;
|
|
2773
2678
|
this.indexPath = this.getIndexPath();
|
|
2774
|
-
this.fileHashCachePath =
|
|
2679
|
+
this.fileHashCachePath = path4.join(this.indexPath, "file-hashes.json");
|
|
2680
|
+
this.failedBatchesPath = path4.join(this.indexPath, "failed-batches.json");
|
|
2775
2681
|
}
|
|
2776
2682
|
getIndexPath() {
|
|
2777
2683
|
if (this.config.scope === "global") {
|
|
2778
2684
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
2779
|
-
return
|
|
2685
|
+
return path4.join(homeDir, ".opencode", "global-index");
|
|
2780
2686
|
}
|
|
2781
|
-
return
|
|
2687
|
+
return path4.join(this.projectRoot, ".opencode", "index");
|
|
2782
2688
|
}
|
|
2783
2689
|
loadFileHashCache() {
|
|
2784
2690
|
try {
|
|
2785
|
-
if (
|
|
2786
|
-
const data =
|
|
2691
|
+
if (existsSync3(this.fileHashCachePath)) {
|
|
2692
|
+
const data = readFileSync3(this.fileHashCachePath, "utf-8");
|
|
2787
2693
|
const parsed = JSON.parse(data);
|
|
2788
2694
|
this.fileHashCache = new Map(Object.entries(parsed));
|
|
2789
2695
|
}
|
|
@@ -2796,7 +2702,38 @@ var Indexer = class {
|
|
|
2796
2702
|
for (const [k, v] of this.fileHashCache) {
|
|
2797
2703
|
obj[k] = v;
|
|
2798
2704
|
}
|
|
2799
|
-
|
|
2705
|
+
writeFileSync(this.fileHashCachePath, JSON.stringify(obj));
|
|
2706
|
+
}
|
|
2707
|
+
loadFailedBatches() {
|
|
2708
|
+
try {
|
|
2709
|
+
if (existsSync3(this.failedBatchesPath)) {
|
|
2710
|
+
const data = readFileSync3(this.failedBatchesPath, "utf-8");
|
|
2711
|
+
return JSON.parse(data);
|
|
2712
|
+
}
|
|
2713
|
+
} catch {
|
|
2714
|
+
return [];
|
|
2715
|
+
}
|
|
2716
|
+
return [];
|
|
2717
|
+
}
|
|
2718
|
+
saveFailedBatches(batches) {
|
|
2719
|
+
if (batches.length === 0) {
|
|
2720
|
+
if (existsSync3(this.failedBatchesPath)) {
|
|
2721
|
+
fsPromises2.unlink(this.failedBatchesPath).catch(() => {
|
|
2722
|
+
});
|
|
2723
|
+
}
|
|
2724
|
+
return;
|
|
2725
|
+
}
|
|
2726
|
+
writeFileSync(this.failedBatchesPath, JSON.stringify(batches, null, 2));
|
|
2727
|
+
}
|
|
2728
|
+
addFailedBatch(batch, error) {
|
|
2729
|
+
const existing = this.loadFailedBatches();
|
|
2730
|
+
existing.push({
|
|
2731
|
+
chunks: batch,
|
|
2732
|
+
error,
|
|
2733
|
+
attemptCount: 1,
|
|
2734
|
+
lastAttempt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2735
|
+
});
|
|
2736
|
+
this.saveFailedBatches(existing);
|
|
2800
2737
|
}
|
|
2801
2738
|
async initialize() {
|
|
2802
2739
|
this.detectedProvider = await detectEmbeddingProvider(this.config.embeddingProvider);
|
|
@@ -2811,13 +2748,14 @@ var Indexer = class {
|
|
|
2811
2748
|
);
|
|
2812
2749
|
await fsPromises2.mkdir(this.indexPath, { recursive: true });
|
|
2813
2750
|
const dimensions = this.detectedProvider.modelInfo.dimensions;
|
|
2814
|
-
const storePath =
|
|
2751
|
+
const storePath = path4.join(this.indexPath, "vectors");
|
|
2815
2752
|
this.store = new VectorStore(storePath, dimensions);
|
|
2816
|
-
const indexFilePath =
|
|
2817
|
-
if (
|
|
2753
|
+
const indexFilePath = path4.join(this.indexPath, "vectors.usearch");
|
|
2754
|
+
if (existsSync3(indexFilePath)) {
|
|
2818
2755
|
this.store.load();
|
|
2819
2756
|
}
|
|
2820
|
-
|
|
2757
|
+
const invertedIndexPath = path4.join(this.indexPath, "inverted-index.json");
|
|
2758
|
+
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
2821
2759
|
this.invertedIndex.load();
|
|
2822
2760
|
}
|
|
2823
2761
|
async ensureInitialized() {
|
|
@@ -2916,14 +2854,22 @@ var Indexer = class {
|
|
|
2916
2854
|
for (const parsed of parsedFiles) {
|
|
2917
2855
|
currentFilePaths.add(parsed.path);
|
|
2918
2856
|
if (parsed.chunks.length === 0) {
|
|
2919
|
-
const relativePath =
|
|
2857
|
+
const relativePath = path4.relative(this.projectRoot, parsed.path);
|
|
2920
2858
|
stats.parseFailures.push(relativePath);
|
|
2921
2859
|
}
|
|
2860
|
+
let fileChunkCount = 0;
|
|
2922
2861
|
for (const chunk of parsed.chunks) {
|
|
2862
|
+
if (fileChunkCount >= this.config.indexing.maxChunksPerFile) {
|
|
2863
|
+
break;
|
|
2864
|
+
}
|
|
2865
|
+
if (this.config.indexing.semanticOnly && chunk.chunkType === "other") {
|
|
2866
|
+
continue;
|
|
2867
|
+
}
|
|
2923
2868
|
const id = generateChunkId(parsed.path, chunk);
|
|
2924
2869
|
const contentHash = generateChunkHash(chunk);
|
|
2925
2870
|
currentChunkIds.add(id);
|
|
2926
2871
|
if (existingChunks.get(id) === contentHash) {
|
|
2872
|
+
fileChunkCount++;
|
|
2927
2873
|
continue;
|
|
2928
2874
|
}
|
|
2929
2875
|
const text = createEmbeddingText(chunk, parsed.path);
|
|
@@ -2937,6 +2883,7 @@ var Indexer = class {
|
|
|
2937
2883
|
hash: contentHash
|
|
2938
2884
|
};
|
|
2939
2885
|
pendingChunks.push({ id, text, content: chunk.content, metadata });
|
|
2886
|
+
fileChunkCount++;
|
|
2940
2887
|
}
|
|
2941
2888
|
}
|
|
2942
2889
|
let removedCount = 0;
|
|
@@ -3026,6 +2973,7 @@ var Indexer = class {
|
|
|
3026
2973
|
});
|
|
3027
2974
|
} catch (error) {
|
|
3028
2975
|
stats.failedChunks += batch.length;
|
|
2976
|
+
this.addFailedBatch(batch, String(error));
|
|
3029
2977
|
console.error(`Failed to embed batch after retries: ${error}`);
|
|
3030
2978
|
}
|
|
3031
2979
|
});
|
|
@@ -3043,6 +2991,9 @@ var Indexer = class {
|
|
|
3043
2991
|
this.fileHashCache = currentFileHashes;
|
|
3044
2992
|
this.saveFileHashCache();
|
|
3045
2993
|
stats.durationMs = Date.now() - startTime;
|
|
2994
|
+
if (stats.failedChunks > 0) {
|
|
2995
|
+
stats.failedBatchesPath = this.failedBatchesPath;
|
|
2996
|
+
}
|
|
3046
2997
|
onProgress?.({
|
|
3047
2998
|
phase: "complete",
|
|
3048
2999
|
filesProcessed: files.length,
|
|
@@ -3188,7 +3139,7 @@ var Indexer = class {
|
|
|
3188
3139
|
const removedFilePaths = [];
|
|
3189
3140
|
let removedCount = 0;
|
|
3190
3141
|
for (const [filePath, chunkKeys] of filePathsToChunkKeys) {
|
|
3191
|
-
if (!
|
|
3142
|
+
if (!existsSync3(filePath)) {
|
|
3192
3143
|
for (const key of chunkKeys) {
|
|
3193
3144
|
store.remove(key);
|
|
3194
3145
|
invertedIndex.removeChunk(key);
|
|
@@ -3203,6 +3154,58 @@ var Indexer = class {
|
|
|
3203
3154
|
}
|
|
3204
3155
|
return { removed: removedCount, filePaths: removedFilePaths };
|
|
3205
3156
|
}
|
|
3157
|
+
async retryFailedBatches() {
|
|
3158
|
+
const { store, provider, invertedIndex } = await this.ensureInitialized();
|
|
3159
|
+
const failedBatches = this.loadFailedBatches();
|
|
3160
|
+
if (failedBatches.length === 0) {
|
|
3161
|
+
return { succeeded: 0, failed: 0, remaining: 0 };
|
|
3162
|
+
}
|
|
3163
|
+
let succeeded = 0;
|
|
3164
|
+
let failed = 0;
|
|
3165
|
+
const stillFailing = [];
|
|
3166
|
+
for (const batch of failedBatches) {
|
|
3167
|
+
try {
|
|
3168
|
+
const result = await pRetry(
|
|
3169
|
+
async () => {
|
|
3170
|
+
const texts = batch.chunks.map((c) => c.text);
|
|
3171
|
+
return provider.embedBatch(texts);
|
|
3172
|
+
},
|
|
3173
|
+
{
|
|
3174
|
+
retries: this.config.indexing.retries,
|
|
3175
|
+
minTimeout: this.config.indexing.retryDelayMs
|
|
3176
|
+
}
|
|
3177
|
+
);
|
|
3178
|
+
const items = batch.chunks.map((chunk, idx) => ({
|
|
3179
|
+
id: chunk.id,
|
|
3180
|
+
vector: result.embeddings[idx],
|
|
3181
|
+
metadata: chunk.metadata
|
|
3182
|
+
}));
|
|
3183
|
+
store.addBatch(items);
|
|
3184
|
+
for (const chunk of batch.chunks) {
|
|
3185
|
+
invertedIndex.removeChunk(chunk.id);
|
|
3186
|
+
invertedIndex.addChunk(chunk.id, chunk.content);
|
|
3187
|
+
}
|
|
3188
|
+
succeeded += batch.chunks.length;
|
|
3189
|
+
} catch (error) {
|
|
3190
|
+
failed += batch.chunks.length;
|
|
3191
|
+
stillFailing.push({
|
|
3192
|
+
...batch,
|
|
3193
|
+
attemptCount: batch.attemptCount + 1,
|
|
3194
|
+
lastAttempt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3195
|
+
error: String(error)
|
|
3196
|
+
});
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
this.saveFailedBatches(stillFailing);
|
|
3200
|
+
if (succeeded > 0) {
|
|
3201
|
+
store.save();
|
|
3202
|
+
invertedIndex.save();
|
|
3203
|
+
}
|
|
3204
|
+
return { succeeded, failed, remaining: stillFailing.length };
|
|
3205
|
+
}
|
|
3206
|
+
getFailedBatchesCount() {
|
|
3207
|
+
return this.loadFailedBatches().length;
|
|
3208
|
+
}
|
|
3206
3209
|
};
|
|
3207
3210
|
|
|
3208
3211
|
// node_modules/chokidar/index.js
|
|
@@ -3295,7 +3298,7 @@ var ReaddirpStream = class extends Readable {
|
|
|
3295
3298
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
3296
3299
|
const statMethod = opts.lstat ? lstat : stat;
|
|
3297
3300
|
if (wantBigintFsStats) {
|
|
3298
|
-
this._stat = (
|
|
3301
|
+
this._stat = (path7) => statMethod(path7, { bigint: true });
|
|
3299
3302
|
} else {
|
|
3300
3303
|
this._stat = statMethod;
|
|
3301
3304
|
}
|
|
@@ -3320,8 +3323,8 @@ var ReaddirpStream = class extends Readable {
|
|
|
3320
3323
|
const par = this.parent;
|
|
3321
3324
|
const fil = par && par.files;
|
|
3322
3325
|
if (fil && fil.length > 0) {
|
|
3323
|
-
const { path:
|
|
3324
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
3326
|
+
const { path: path7, depth } = par;
|
|
3327
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path7));
|
|
3325
3328
|
const awaited = await Promise.all(slice);
|
|
3326
3329
|
for (const entry of awaited) {
|
|
3327
3330
|
if (!entry)
|
|
@@ -3361,20 +3364,20 @@ var ReaddirpStream = class extends Readable {
|
|
|
3361
3364
|
this.reading = false;
|
|
3362
3365
|
}
|
|
3363
3366
|
}
|
|
3364
|
-
async _exploreDir(
|
|
3367
|
+
async _exploreDir(path7, depth) {
|
|
3365
3368
|
let files;
|
|
3366
3369
|
try {
|
|
3367
|
-
files = await readdir(
|
|
3370
|
+
files = await readdir(path7, this._rdOptions);
|
|
3368
3371
|
} catch (error) {
|
|
3369
3372
|
this._onError(error);
|
|
3370
3373
|
}
|
|
3371
|
-
return { files, depth, path:
|
|
3374
|
+
return { files, depth, path: path7 };
|
|
3372
3375
|
}
|
|
3373
|
-
async _formatEntry(dirent,
|
|
3376
|
+
async _formatEntry(dirent, path7) {
|
|
3374
3377
|
let entry;
|
|
3375
3378
|
const basename3 = this._isDirent ? dirent.name : dirent;
|
|
3376
3379
|
try {
|
|
3377
|
-
const fullPath = presolve(pjoin(
|
|
3380
|
+
const fullPath = presolve(pjoin(path7, basename3));
|
|
3378
3381
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename3 };
|
|
3379
3382
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
3380
3383
|
} catch (err) {
|
|
@@ -3774,16 +3777,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
3774
3777
|
};
|
|
3775
3778
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
3776
3779
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
3777
|
-
function createFsWatchInstance(
|
|
3780
|
+
function createFsWatchInstance(path7, options, listener, errHandler, emitRaw) {
|
|
3778
3781
|
const handleEvent = (rawEvent, evPath) => {
|
|
3779
|
-
listener(
|
|
3780
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
3781
|
-
if (evPath &&
|
|
3782
|
-
fsWatchBroadcast(sp.resolve(
|
|
3782
|
+
listener(path7);
|
|
3783
|
+
emitRaw(rawEvent, evPath, { watchedPath: path7 });
|
|
3784
|
+
if (evPath && path7 !== evPath) {
|
|
3785
|
+
fsWatchBroadcast(sp.resolve(path7, evPath), KEY_LISTENERS, sp.join(path7, evPath));
|
|
3783
3786
|
}
|
|
3784
3787
|
};
|
|
3785
3788
|
try {
|
|
3786
|
-
return fs_watch(
|
|
3789
|
+
return fs_watch(path7, {
|
|
3787
3790
|
persistent: options.persistent
|
|
3788
3791
|
}, handleEvent);
|
|
3789
3792
|
} catch (error) {
|
|
@@ -3799,12 +3802,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
3799
3802
|
listener(val1, val2, val3);
|
|
3800
3803
|
});
|
|
3801
3804
|
};
|
|
3802
|
-
var setFsWatchListener = (
|
|
3805
|
+
var setFsWatchListener = (path7, fullPath, options, handlers) => {
|
|
3803
3806
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
3804
3807
|
let cont = FsWatchInstances.get(fullPath);
|
|
3805
3808
|
let watcher;
|
|
3806
3809
|
if (!options.persistent) {
|
|
3807
|
-
watcher = createFsWatchInstance(
|
|
3810
|
+
watcher = createFsWatchInstance(path7, options, listener, errHandler, rawEmitter);
|
|
3808
3811
|
if (!watcher)
|
|
3809
3812
|
return;
|
|
3810
3813
|
return watcher.close.bind(watcher);
|
|
@@ -3815,7 +3818,7 @@ var setFsWatchListener = (path8, fullPath, options, handlers) => {
|
|
|
3815
3818
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
3816
3819
|
} else {
|
|
3817
3820
|
watcher = createFsWatchInstance(
|
|
3818
|
-
|
|
3821
|
+
path7,
|
|
3819
3822
|
options,
|
|
3820
3823
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
3821
3824
|
errHandler,
|
|
@@ -3830,7 +3833,7 @@ var setFsWatchListener = (path8, fullPath, options, handlers) => {
|
|
|
3830
3833
|
cont.watcherUnusable = true;
|
|
3831
3834
|
if (isWindows && error.code === "EPERM") {
|
|
3832
3835
|
try {
|
|
3833
|
-
const fd = await open(
|
|
3836
|
+
const fd = await open(path7, "r");
|
|
3834
3837
|
await fd.close();
|
|
3835
3838
|
broadcastErr(error);
|
|
3836
3839
|
} catch (err) {
|
|
@@ -3861,7 +3864,7 @@ var setFsWatchListener = (path8, fullPath, options, handlers) => {
|
|
|
3861
3864
|
};
|
|
3862
3865
|
};
|
|
3863
3866
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
3864
|
-
var setFsWatchFileListener = (
|
|
3867
|
+
var setFsWatchFileListener = (path7, fullPath, options, handlers) => {
|
|
3865
3868
|
const { listener, rawEmitter } = handlers;
|
|
3866
3869
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
3867
3870
|
const copts = cont && cont.options;
|
|
@@ -3883,7 +3886,7 @@ var setFsWatchFileListener = (path8, fullPath, options, handlers) => {
|
|
|
3883
3886
|
});
|
|
3884
3887
|
const currmtime = curr.mtimeMs;
|
|
3885
3888
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
3886
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
3889
|
+
foreach(cont.listeners, (listener2) => listener2(path7, curr));
|
|
3887
3890
|
}
|
|
3888
3891
|
})
|
|
3889
3892
|
};
|
|
@@ -3913,13 +3916,13 @@ var NodeFsHandler = class {
|
|
|
3913
3916
|
* @param listener on fs change
|
|
3914
3917
|
* @returns closer for the watcher instance
|
|
3915
3918
|
*/
|
|
3916
|
-
_watchWithNodeFs(
|
|
3919
|
+
_watchWithNodeFs(path7, listener) {
|
|
3917
3920
|
const opts = this.fsw.options;
|
|
3918
|
-
const directory = sp.dirname(
|
|
3919
|
-
const basename3 = sp.basename(
|
|
3921
|
+
const directory = sp.dirname(path7);
|
|
3922
|
+
const basename3 = sp.basename(path7);
|
|
3920
3923
|
const parent = this.fsw._getWatchedDir(directory);
|
|
3921
3924
|
parent.add(basename3);
|
|
3922
|
-
const absolutePath = sp.resolve(
|
|
3925
|
+
const absolutePath = sp.resolve(path7);
|
|
3923
3926
|
const options = {
|
|
3924
3927
|
persistent: opts.persistent
|
|
3925
3928
|
};
|
|
@@ -3929,12 +3932,12 @@ var NodeFsHandler = class {
|
|
|
3929
3932
|
if (opts.usePolling) {
|
|
3930
3933
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
3931
3934
|
options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
|
|
3932
|
-
closer = setFsWatchFileListener(
|
|
3935
|
+
closer = setFsWatchFileListener(path7, absolutePath, options, {
|
|
3933
3936
|
listener,
|
|
3934
3937
|
rawEmitter: this.fsw._emitRaw
|
|
3935
3938
|
});
|
|
3936
3939
|
} else {
|
|
3937
|
-
closer = setFsWatchListener(
|
|
3940
|
+
closer = setFsWatchListener(path7, absolutePath, options, {
|
|
3938
3941
|
listener,
|
|
3939
3942
|
errHandler: this._boundHandleError,
|
|
3940
3943
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -3956,7 +3959,7 @@ var NodeFsHandler = class {
|
|
|
3956
3959
|
let prevStats = stats;
|
|
3957
3960
|
if (parent.has(basename3))
|
|
3958
3961
|
return;
|
|
3959
|
-
const listener = async (
|
|
3962
|
+
const listener = async (path7, newStats) => {
|
|
3960
3963
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
3961
3964
|
return;
|
|
3962
3965
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -3970,11 +3973,11 @@ var NodeFsHandler = class {
|
|
|
3970
3973
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
3971
3974
|
}
|
|
3972
3975
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
3973
|
-
this.fsw._closeFile(
|
|
3976
|
+
this.fsw._closeFile(path7);
|
|
3974
3977
|
prevStats = newStats2;
|
|
3975
3978
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
3976
3979
|
if (closer2)
|
|
3977
|
-
this.fsw._addPathCloser(
|
|
3980
|
+
this.fsw._addPathCloser(path7, closer2);
|
|
3978
3981
|
} else {
|
|
3979
3982
|
prevStats = newStats2;
|
|
3980
3983
|
}
|
|
@@ -4006,7 +4009,7 @@ var NodeFsHandler = class {
|
|
|
4006
4009
|
* @param item basename of this item
|
|
4007
4010
|
* @returns true if no more processing is needed for this entry.
|
|
4008
4011
|
*/
|
|
4009
|
-
async _handleSymlink(entry, directory,
|
|
4012
|
+
async _handleSymlink(entry, directory, path7, item) {
|
|
4010
4013
|
if (this.fsw.closed) {
|
|
4011
4014
|
return;
|
|
4012
4015
|
}
|
|
@@ -4016,7 +4019,7 @@ var NodeFsHandler = class {
|
|
|
4016
4019
|
this.fsw._incrReadyCount();
|
|
4017
4020
|
let linkPath;
|
|
4018
4021
|
try {
|
|
4019
|
-
linkPath = await fsrealpath(
|
|
4022
|
+
linkPath = await fsrealpath(path7);
|
|
4020
4023
|
} catch (e) {
|
|
4021
4024
|
this.fsw._emitReady();
|
|
4022
4025
|
return true;
|
|
@@ -4026,12 +4029,12 @@ var NodeFsHandler = class {
|
|
|
4026
4029
|
if (dir.has(item)) {
|
|
4027
4030
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
4028
4031
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
4029
|
-
this.fsw._emit(EV.CHANGE,
|
|
4032
|
+
this.fsw._emit(EV.CHANGE, path7, entry.stats);
|
|
4030
4033
|
}
|
|
4031
4034
|
} else {
|
|
4032
4035
|
dir.add(item);
|
|
4033
4036
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
4034
|
-
this.fsw._emit(EV.ADD,
|
|
4037
|
+
this.fsw._emit(EV.ADD, path7, entry.stats);
|
|
4035
4038
|
}
|
|
4036
4039
|
this.fsw._emitReady();
|
|
4037
4040
|
return true;
|
|
@@ -4061,9 +4064,9 @@ var NodeFsHandler = class {
|
|
|
4061
4064
|
return;
|
|
4062
4065
|
}
|
|
4063
4066
|
const item = entry.path;
|
|
4064
|
-
let
|
|
4067
|
+
let path7 = sp.join(directory, item);
|
|
4065
4068
|
current.add(item);
|
|
4066
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
4069
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path7, item)) {
|
|
4067
4070
|
return;
|
|
4068
4071
|
}
|
|
4069
4072
|
if (this.fsw.closed) {
|
|
@@ -4072,8 +4075,8 @@ var NodeFsHandler = class {
|
|
|
4072
4075
|
}
|
|
4073
4076
|
if (item === target || !target && !previous.has(item)) {
|
|
4074
4077
|
this.fsw._incrReadyCount();
|
|
4075
|
-
|
|
4076
|
-
this._addToNodeFs(
|
|
4078
|
+
path7 = sp.join(dir, sp.relative(dir, path7));
|
|
4079
|
+
this._addToNodeFs(path7, initialAdd, wh, depth + 1);
|
|
4077
4080
|
}
|
|
4078
4081
|
}).on(EV.ERROR, this._boundHandleError);
|
|
4079
4082
|
return new Promise((resolve4, reject) => {
|
|
@@ -4142,13 +4145,13 @@ var NodeFsHandler = class {
|
|
|
4142
4145
|
* @param depth Child path actually targeted for watch
|
|
4143
4146
|
* @param target Child path actually targeted for watch
|
|
4144
4147
|
*/
|
|
4145
|
-
async _addToNodeFs(
|
|
4148
|
+
async _addToNodeFs(path7, initialAdd, priorWh, depth, target) {
|
|
4146
4149
|
const ready = this.fsw._emitReady;
|
|
4147
|
-
if (this.fsw._isIgnored(
|
|
4150
|
+
if (this.fsw._isIgnored(path7) || this.fsw.closed) {
|
|
4148
4151
|
ready();
|
|
4149
4152
|
return false;
|
|
4150
4153
|
}
|
|
4151
|
-
const wh = this.fsw._getWatchHelpers(
|
|
4154
|
+
const wh = this.fsw._getWatchHelpers(path7);
|
|
4152
4155
|
if (priorWh) {
|
|
4153
4156
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
4154
4157
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -4164,8 +4167,8 @@ var NodeFsHandler = class {
|
|
|
4164
4167
|
const follow = this.fsw.options.followSymlinks;
|
|
4165
4168
|
let closer;
|
|
4166
4169
|
if (stats.isDirectory()) {
|
|
4167
|
-
const absPath = sp.resolve(
|
|
4168
|
-
const targetPath = follow ? await fsrealpath(
|
|
4170
|
+
const absPath = sp.resolve(path7);
|
|
4171
|
+
const targetPath = follow ? await fsrealpath(path7) : path7;
|
|
4169
4172
|
if (this.fsw.closed)
|
|
4170
4173
|
return;
|
|
4171
4174
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -4175,29 +4178,29 @@ var NodeFsHandler = class {
|
|
|
4175
4178
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
4176
4179
|
}
|
|
4177
4180
|
} else if (stats.isSymbolicLink()) {
|
|
4178
|
-
const targetPath = follow ? await fsrealpath(
|
|
4181
|
+
const targetPath = follow ? await fsrealpath(path7) : path7;
|
|
4179
4182
|
if (this.fsw.closed)
|
|
4180
4183
|
return;
|
|
4181
4184
|
const parent = sp.dirname(wh.watchPath);
|
|
4182
4185
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
4183
4186
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
4184
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
4187
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path7, wh, targetPath);
|
|
4185
4188
|
if (this.fsw.closed)
|
|
4186
4189
|
return;
|
|
4187
4190
|
if (targetPath !== void 0) {
|
|
4188
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
4191
|
+
this.fsw._symlinkPaths.set(sp.resolve(path7), targetPath);
|
|
4189
4192
|
}
|
|
4190
4193
|
} else {
|
|
4191
4194
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
4192
4195
|
}
|
|
4193
4196
|
ready();
|
|
4194
4197
|
if (closer)
|
|
4195
|
-
this.fsw._addPathCloser(
|
|
4198
|
+
this.fsw._addPathCloser(path7, closer);
|
|
4196
4199
|
return false;
|
|
4197
4200
|
} catch (error) {
|
|
4198
4201
|
if (this.fsw._handleError(error)) {
|
|
4199
4202
|
ready();
|
|
4200
|
-
return
|
|
4203
|
+
return path7;
|
|
4201
4204
|
}
|
|
4202
4205
|
}
|
|
4203
4206
|
}
|
|
@@ -4240,24 +4243,24 @@ function createPattern(matcher) {
|
|
|
4240
4243
|
}
|
|
4241
4244
|
return () => false;
|
|
4242
4245
|
}
|
|
4243
|
-
function normalizePath(
|
|
4244
|
-
if (typeof
|
|
4246
|
+
function normalizePath(path7) {
|
|
4247
|
+
if (typeof path7 !== "string")
|
|
4245
4248
|
throw new Error("string expected");
|
|
4246
|
-
|
|
4247
|
-
|
|
4249
|
+
path7 = sp2.normalize(path7);
|
|
4250
|
+
path7 = path7.replace(/\\/g, "/");
|
|
4248
4251
|
let prepend = false;
|
|
4249
|
-
if (
|
|
4252
|
+
if (path7.startsWith("//"))
|
|
4250
4253
|
prepend = true;
|
|
4251
|
-
|
|
4254
|
+
path7 = path7.replace(DOUBLE_SLASH_RE, "/");
|
|
4252
4255
|
if (prepend)
|
|
4253
|
-
|
|
4254
|
-
return
|
|
4256
|
+
path7 = "/" + path7;
|
|
4257
|
+
return path7;
|
|
4255
4258
|
}
|
|
4256
4259
|
function matchPatterns(patterns, testString, stats) {
|
|
4257
|
-
const
|
|
4260
|
+
const path7 = normalizePath(testString);
|
|
4258
4261
|
for (let index = 0; index < patterns.length; index++) {
|
|
4259
4262
|
const pattern = patterns[index];
|
|
4260
|
-
if (pattern(
|
|
4263
|
+
if (pattern(path7, stats)) {
|
|
4261
4264
|
return true;
|
|
4262
4265
|
}
|
|
4263
4266
|
}
|
|
@@ -4295,19 +4298,19 @@ var toUnix = (string) => {
|
|
|
4295
4298
|
}
|
|
4296
4299
|
return str;
|
|
4297
4300
|
};
|
|
4298
|
-
var normalizePathToUnix = (
|
|
4299
|
-
var normalizeIgnored = (cwd = "") => (
|
|
4300
|
-
if (typeof
|
|
4301
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
4301
|
+
var normalizePathToUnix = (path7) => toUnix(sp2.normalize(toUnix(path7)));
|
|
4302
|
+
var normalizeIgnored = (cwd = "") => (path7) => {
|
|
4303
|
+
if (typeof path7 === "string") {
|
|
4304
|
+
return normalizePathToUnix(sp2.isAbsolute(path7) ? path7 : sp2.join(cwd, path7));
|
|
4302
4305
|
} else {
|
|
4303
|
-
return
|
|
4306
|
+
return path7;
|
|
4304
4307
|
}
|
|
4305
4308
|
};
|
|
4306
|
-
var getAbsolutePath = (
|
|
4307
|
-
if (sp2.isAbsolute(
|
|
4308
|
-
return
|
|
4309
|
+
var getAbsolutePath = (path7, cwd) => {
|
|
4310
|
+
if (sp2.isAbsolute(path7)) {
|
|
4311
|
+
return path7;
|
|
4309
4312
|
}
|
|
4310
|
-
return sp2.join(cwd,
|
|
4313
|
+
return sp2.join(cwd, path7);
|
|
4311
4314
|
};
|
|
4312
4315
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
4313
4316
|
var DirEntry = class {
|
|
@@ -4372,10 +4375,10 @@ var WatchHelper = class {
|
|
|
4372
4375
|
dirParts;
|
|
4373
4376
|
followSymlinks;
|
|
4374
4377
|
statMethod;
|
|
4375
|
-
constructor(
|
|
4378
|
+
constructor(path7, follow, fsw) {
|
|
4376
4379
|
this.fsw = fsw;
|
|
4377
|
-
const watchPath =
|
|
4378
|
-
this.path =
|
|
4380
|
+
const watchPath = path7;
|
|
4381
|
+
this.path = path7 = path7.replace(REPLACER_RE, "");
|
|
4379
4382
|
this.watchPath = watchPath;
|
|
4380
4383
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
4381
4384
|
this.dirParts = [];
|
|
@@ -4515,20 +4518,20 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4515
4518
|
this._closePromise = void 0;
|
|
4516
4519
|
let paths = unifyPaths(paths_);
|
|
4517
4520
|
if (cwd) {
|
|
4518
|
-
paths = paths.map((
|
|
4519
|
-
const absPath = getAbsolutePath(
|
|
4521
|
+
paths = paths.map((path7) => {
|
|
4522
|
+
const absPath = getAbsolutePath(path7, cwd);
|
|
4520
4523
|
return absPath;
|
|
4521
4524
|
});
|
|
4522
4525
|
}
|
|
4523
|
-
paths.forEach((
|
|
4524
|
-
this._removeIgnoredPath(
|
|
4526
|
+
paths.forEach((path7) => {
|
|
4527
|
+
this._removeIgnoredPath(path7);
|
|
4525
4528
|
});
|
|
4526
4529
|
this._userIgnored = void 0;
|
|
4527
4530
|
if (!this._readyCount)
|
|
4528
4531
|
this._readyCount = 0;
|
|
4529
4532
|
this._readyCount += paths.length;
|
|
4530
|
-
Promise.all(paths.map(async (
|
|
4531
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
4533
|
+
Promise.all(paths.map(async (path7) => {
|
|
4534
|
+
const res = await this._nodeFsHandler._addToNodeFs(path7, !_internal, void 0, 0, _origAdd);
|
|
4532
4535
|
if (res)
|
|
4533
4536
|
this._emitReady();
|
|
4534
4537
|
return res;
|
|
@@ -4550,17 +4553,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4550
4553
|
return this;
|
|
4551
4554
|
const paths = unifyPaths(paths_);
|
|
4552
4555
|
const { cwd } = this.options;
|
|
4553
|
-
paths.forEach((
|
|
4554
|
-
if (!sp2.isAbsolute(
|
|
4556
|
+
paths.forEach((path7) => {
|
|
4557
|
+
if (!sp2.isAbsolute(path7) && !this._closers.has(path7)) {
|
|
4555
4558
|
if (cwd)
|
|
4556
|
-
|
|
4557
|
-
|
|
4559
|
+
path7 = sp2.join(cwd, path7);
|
|
4560
|
+
path7 = sp2.resolve(path7);
|
|
4558
4561
|
}
|
|
4559
|
-
this._closePath(
|
|
4560
|
-
this._addIgnoredPath(
|
|
4561
|
-
if (this._watched.has(
|
|
4562
|
+
this._closePath(path7);
|
|
4563
|
+
this._addIgnoredPath(path7);
|
|
4564
|
+
if (this._watched.has(path7)) {
|
|
4562
4565
|
this._addIgnoredPath({
|
|
4563
|
-
path:
|
|
4566
|
+
path: path7,
|
|
4564
4567
|
recursive: true
|
|
4565
4568
|
});
|
|
4566
4569
|
}
|
|
@@ -4624,38 +4627,38 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4624
4627
|
* @param stats arguments to be passed with event
|
|
4625
4628
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
4626
4629
|
*/
|
|
4627
|
-
async _emit(event,
|
|
4630
|
+
async _emit(event, path7, stats) {
|
|
4628
4631
|
if (this.closed)
|
|
4629
4632
|
return;
|
|
4630
4633
|
const opts = this.options;
|
|
4631
4634
|
if (isWindows)
|
|
4632
|
-
|
|
4635
|
+
path7 = sp2.normalize(path7);
|
|
4633
4636
|
if (opts.cwd)
|
|
4634
|
-
|
|
4635
|
-
const args = [
|
|
4637
|
+
path7 = sp2.relative(opts.cwd, path7);
|
|
4638
|
+
const args = [path7];
|
|
4636
4639
|
if (stats != null)
|
|
4637
4640
|
args.push(stats);
|
|
4638
4641
|
const awf = opts.awaitWriteFinish;
|
|
4639
4642
|
let pw;
|
|
4640
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
4643
|
+
if (awf && (pw = this._pendingWrites.get(path7))) {
|
|
4641
4644
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
4642
4645
|
return this;
|
|
4643
4646
|
}
|
|
4644
4647
|
if (opts.atomic) {
|
|
4645
4648
|
if (event === EVENTS.UNLINK) {
|
|
4646
|
-
this._pendingUnlinks.set(
|
|
4649
|
+
this._pendingUnlinks.set(path7, [event, ...args]);
|
|
4647
4650
|
setTimeout(() => {
|
|
4648
|
-
this._pendingUnlinks.forEach((entry,
|
|
4651
|
+
this._pendingUnlinks.forEach((entry, path8) => {
|
|
4649
4652
|
this.emit(...entry);
|
|
4650
4653
|
this.emit(EVENTS.ALL, ...entry);
|
|
4651
|
-
this._pendingUnlinks.delete(
|
|
4654
|
+
this._pendingUnlinks.delete(path8);
|
|
4652
4655
|
});
|
|
4653
4656
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
4654
4657
|
return this;
|
|
4655
4658
|
}
|
|
4656
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
4659
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path7)) {
|
|
4657
4660
|
event = EVENTS.CHANGE;
|
|
4658
|
-
this._pendingUnlinks.delete(
|
|
4661
|
+
this._pendingUnlinks.delete(path7);
|
|
4659
4662
|
}
|
|
4660
4663
|
}
|
|
4661
4664
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -4673,16 +4676,16 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4673
4676
|
this.emitWithAll(event, args);
|
|
4674
4677
|
}
|
|
4675
4678
|
};
|
|
4676
|
-
this._awaitWriteFinish(
|
|
4679
|
+
this._awaitWriteFinish(path7, awf.stabilityThreshold, event, awfEmit);
|
|
4677
4680
|
return this;
|
|
4678
4681
|
}
|
|
4679
4682
|
if (event === EVENTS.CHANGE) {
|
|
4680
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
4683
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path7, 50);
|
|
4681
4684
|
if (isThrottled)
|
|
4682
4685
|
return this;
|
|
4683
4686
|
}
|
|
4684
4687
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
4685
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
4688
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path7) : path7;
|
|
4686
4689
|
let stats2;
|
|
4687
4690
|
try {
|
|
4688
4691
|
stats2 = await stat3(fullPath);
|
|
@@ -4713,23 +4716,23 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4713
4716
|
* @param timeout duration of time to suppress duplicate actions
|
|
4714
4717
|
* @returns tracking object or false if action should be suppressed
|
|
4715
4718
|
*/
|
|
4716
|
-
_throttle(actionType,
|
|
4719
|
+
_throttle(actionType, path7, timeout) {
|
|
4717
4720
|
if (!this._throttled.has(actionType)) {
|
|
4718
4721
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
4719
4722
|
}
|
|
4720
4723
|
const action = this._throttled.get(actionType);
|
|
4721
4724
|
if (!action)
|
|
4722
4725
|
throw new Error("invalid throttle");
|
|
4723
|
-
const actionPath = action.get(
|
|
4726
|
+
const actionPath = action.get(path7);
|
|
4724
4727
|
if (actionPath) {
|
|
4725
4728
|
actionPath.count++;
|
|
4726
4729
|
return false;
|
|
4727
4730
|
}
|
|
4728
4731
|
let timeoutObject;
|
|
4729
4732
|
const clear = () => {
|
|
4730
|
-
const item = action.get(
|
|
4733
|
+
const item = action.get(path7);
|
|
4731
4734
|
const count = item ? item.count : 0;
|
|
4732
|
-
action.delete(
|
|
4735
|
+
action.delete(path7);
|
|
4733
4736
|
clearTimeout(timeoutObject);
|
|
4734
4737
|
if (item)
|
|
4735
4738
|
clearTimeout(item.timeoutObject);
|
|
@@ -4737,7 +4740,7 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4737
4740
|
};
|
|
4738
4741
|
timeoutObject = setTimeout(clear, timeout);
|
|
4739
4742
|
const thr = { timeoutObject, clear, count: 0 };
|
|
4740
|
-
action.set(
|
|
4743
|
+
action.set(path7, thr);
|
|
4741
4744
|
return thr;
|
|
4742
4745
|
}
|
|
4743
4746
|
_incrReadyCount() {
|
|
@@ -4751,44 +4754,44 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4751
4754
|
* @param event
|
|
4752
4755
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
4753
4756
|
*/
|
|
4754
|
-
_awaitWriteFinish(
|
|
4757
|
+
_awaitWriteFinish(path7, threshold, event, awfEmit) {
|
|
4755
4758
|
const awf = this.options.awaitWriteFinish;
|
|
4756
4759
|
if (typeof awf !== "object")
|
|
4757
4760
|
return;
|
|
4758
4761
|
const pollInterval = awf.pollInterval;
|
|
4759
4762
|
let timeoutHandler;
|
|
4760
|
-
let fullPath =
|
|
4761
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
4762
|
-
fullPath = sp2.join(this.options.cwd,
|
|
4763
|
+
let fullPath = path7;
|
|
4764
|
+
if (this.options.cwd && !sp2.isAbsolute(path7)) {
|
|
4765
|
+
fullPath = sp2.join(this.options.cwd, path7);
|
|
4763
4766
|
}
|
|
4764
4767
|
const now = /* @__PURE__ */ new Date();
|
|
4765
4768
|
const writes = this._pendingWrites;
|
|
4766
4769
|
function awaitWriteFinishFn(prevStat) {
|
|
4767
4770
|
statcb(fullPath, (err, curStat) => {
|
|
4768
|
-
if (err || !writes.has(
|
|
4771
|
+
if (err || !writes.has(path7)) {
|
|
4769
4772
|
if (err && err.code !== "ENOENT")
|
|
4770
4773
|
awfEmit(err);
|
|
4771
4774
|
return;
|
|
4772
4775
|
}
|
|
4773
4776
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
4774
4777
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
4775
|
-
writes.get(
|
|
4778
|
+
writes.get(path7).lastChange = now2;
|
|
4776
4779
|
}
|
|
4777
|
-
const pw = writes.get(
|
|
4780
|
+
const pw = writes.get(path7);
|
|
4778
4781
|
const df = now2 - pw.lastChange;
|
|
4779
4782
|
if (df >= threshold) {
|
|
4780
|
-
writes.delete(
|
|
4783
|
+
writes.delete(path7);
|
|
4781
4784
|
awfEmit(void 0, curStat);
|
|
4782
4785
|
} else {
|
|
4783
4786
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
4784
4787
|
}
|
|
4785
4788
|
});
|
|
4786
4789
|
}
|
|
4787
|
-
if (!writes.has(
|
|
4788
|
-
writes.set(
|
|
4790
|
+
if (!writes.has(path7)) {
|
|
4791
|
+
writes.set(path7, {
|
|
4789
4792
|
lastChange: now,
|
|
4790
4793
|
cancelWait: () => {
|
|
4791
|
-
writes.delete(
|
|
4794
|
+
writes.delete(path7);
|
|
4792
4795
|
clearTimeout(timeoutHandler);
|
|
4793
4796
|
return event;
|
|
4794
4797
|
}
|
|
@@ -4799,8 +4802,8 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4799
4802
|
/**
|
|
4800
4803
|
* Determines whether user has asked to ignore this path.
|
|
4801
4804
|
*/
|
|
4802
|
-
_isIgnored(
|
|
4803
|
-
if (this.options.atomic && DOT_RE.test(
|
|
4805
|
+
_isIgnored(path7, stats) {
|
|
4806
|
+
if (this.options.atomic && DOT_RE.test(path7))
|
|
4804
4807
|
return true;
|
|
4805
4808
|
if (!this._userIgnored) {
|
|
4806
4809
|
const { cwd } = this.options;
|
|
@@ -4810,17 +4813,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4810
4813
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
4811
4814
|
this._userIgnored = anymatch(list, void 0);
|
|
4812
4815
|
}
|
|
4813
|
-
return this._userIgnored(
|
|
4816
|
+
return this._userIgnored(path7, stats);
|
|
4814
4817
|
}
|
|
4815
|
-
_isntIgnored(
|
|
4816
|
-
return !this._isIgnored(
|
|
4818
|
+
_isntIgnored(path7, stat4) {
|
|
4819
|
+
return !this._isIgnored(path7, stat4);
|
|
4817
4820
|
}
|
|
4818
4821
|
/**
|
|
4819
4822
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
4820
4823
|
* @param path file or directory pattern being watched
|
|
4821
4824
|
*/
|
|
4822
|
-
_getWatchHelpers(
|
|
4823
|
-
return new WatchHelper(
|
|
4825
|
+
_getWatchHelpers(path7) {
|
|
4826
|
+
return new WatchHelper(path7, this.options.followSymlinks, this);
|
|
4824
4827
|
}
|
|
4825
4828
|
// Directory helpers
|
|
4826
4829
|
// -----------------
|
|
@@ -4852,63 +4855,63 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4852
4855
|
* @param item base path of item/directory
|
|
4853
4856
|
*/
|
|
4854
4857
|
_remove(directory, item, isDirectory) {
|
|
4855
|
-
const
|
|
4856
|
-
const fullPath = sp2.resolve(
|
|
4857
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
4858
|
-
if (!this._throttle("remove",
|
|
4858
|
+
const path7 = sp2.join(directory, item);
|
|
4859
|
+
const fullPath = sp2.resolve(path7);
|
|
4860
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path7) || this._watched.has(fullPath);
|
|
4861
|
+
if (!this._throttle("remove", path7, 100))
|
|
4859
4862
|
return;
|
|
4860
4863
|
if (!isDirectory && this._watched.size === 1) {
|
|
4861
4864
|
this.add(directory, item, true);
|
|
4862
4865
|
}
|
|
4863
|
-
const wp = this._getWatchedDir(
|
|
4866
|
+
const wp = this._getWatchedDir(path7);
|
|
4864
4867
|
const nestedDirectoryChildren = wp.getChildren();
|
|
4865
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
4868
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path7, nested));
|
|
4866
4869
|
const parent = this._getWatchedDir(directory);
|
|
4867
4870
|
const wasTracked = parent.has(item);
|
|
4868
4871
|
parent.remove(item);
|
|
4869
4872
|
if (this._symlinkPaths.has(fullPath)) {
|
|
4870
4873
|
this._symlinkPaths.delete(fullPath);
|
|
4871
4874
|
}
|
|
4872
|
-
let relPath =
|
|
4875
|
+
let relPath = path7;
|
|
4873
4876
|
if (this.options.cwd)
|
|
4874
|
-
relPath = sp2.relative(this.options.cwd,
|
|
4877
|
+
relPath = sp2.relative(this.options.cwd, path7);
|
|
4875
4878
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
4876
4879
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
4877
4880
|
if (event === EVENTS.ADD)
|
|
4878
4881
|
return;
|
|
4879
4882
|
}
|
|
4880
|
-
this._watched.delete(
|
|
4883
|
+
this._watched.delete(path7);
|
|
4881
4884
|
this._watched.delete(fullPath);
|
|
4882
4885
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
4883
|
-
if (wasTracked && !this._isIgnored(
|
|
4884
|
-
this._emit(eventName,
|
|
4885
|
-
this._closePath(
|
|
4886
|
+
if (wasTracked && !this._isIgnored(path7))
|
|
4887
|
+
this._emit(eventName, path7);
|
|
4888
|
+
this._closePath(path7);
|
|
4886
4889
|
}
|
|
4887
4890
|
/**
|
|
4888
4891
|
* Closes all watchers for a path
|
|
4889
4892
|
*/
|
|
4890
|
-
_closePath(
|
|
4891
|
-
this._closeFile(
|
|
4892
|
-
const dir = sp2.dirname(
|
|
4893
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
4893
|
+
_closePath(path7) {
|
|
4894
|
+
this._closeFile(path7);
|
|
4895
|
+
const dir = sp2.dirname(path7);
|
|
4896
|
+
this._getWatchedDir(dir).remove(sp2.basename(path7));
|
|
4894
4897
|
}
|
|
4895
4898
|
/**
|
|
4896
4899
|
* Closes only file-specific watchers
|
|
4897
4900
|
*/
|
|
4898
|
-
_closeFile(
|
|
4899
|
-
const closers = this._closers.get(
|
|
4901
|
+
_closeFile(path7) {
|
|
4902
|
+
const closers = this._closers.get(path7);
|
|
4900
4903
|
if (!closers)
|
|
4901
4904
|
return;
|
|
4902
4905
|
closers.forEach((closer) => closer());
|
|
4903
|
-
this._closers.delete(
|
|
4906
|
+
this._closers.delete(path7);
|
|
4904
4907
|
}
|
|
4905
|
-
_addPathCloser(
|
|
4908
|
+
_addPathCloser(path7, closer) {
|
|
4906
4909
|
if (!closer)
|
|
4907
4910
|
return;
|
|
4908
|
-
let list = this._closers.get(
|
|
4911
|
+
let list = this._closers.get(path7);
|
|
4909
4912
|
if (!list) {
|
|
4910
4913
|
list = [];
|
|
4911
|
-
this._closers.set(
|
|
4914
|
+
this._closers.set(path7, list);
|
|
4912
4915
|
}
|
|
4913
4916
|
list.push(closer);
|
|
4914
4917
|
}
|
|
@@ -4938,7 +4941,7 @@ function watch(paths, options = {}) {
|
|
|
4938
4941
|
var chokidar_default = { watch, FSWatcher };
|
|
4939
4942
|
|
|
4940
4943
|
// src/watcher/index.ts
|
|
4941
|
-
import * as
|
|
4944
|
+
import * as path5 from "path";
|
|
4942
4945
|
var FileWatcher = class {
|
|
4943
4946
|
watcher = null;
|
|
4944
4947
|
projectRoot;
|
|
@@ -4959,7 +4962,7 @@ var FileWatcher = class {
|
|
|
4959
4962
|
const ignoreFilter = createIgnoreFilter(this.projectRoot);
|
|
4960
4963
|
this.watcher = chokidar_default.watch(this.projectRoot, {
|
|
4961
4964
|
ignored: (filePath) => {
|
|
4962
|
-
const relativePath =
|
|
4965
|
+
const relativePath = path5.relative(this.projectRoot, filePath);
|
|
4963
4966
|
if (!relativePath) return false;
|
|
4964
4967
|
if (ignoreFilter.ignores(relativePath)) {
|
|
4965
4968
|
return true;
|
|
@@ -5003,7 +5006,7 @@ var FileWatcher = class {
|
|
|
5003
5006
|
return;
|
|
5004
5007
|
}
|
|
5005
5008
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
5006
|
-
([
|
|
5009
|
+
([path7, type]) => ({ path: path7, type })
|
|
5007
5010
|
);
|
|
5008
5011
|
this.pendingChanges.clear();
|
|
5009
5012
|
try {
|
|
@@ -5195,10 +5198,10 @@ function formatStatus(status) {
|
|
|
5195
5198
|
|
|
5196
5199
|
// src/index.ts
|
|
5197
5200
|
function loadPluginConfig(projectRoot) {
|
|
5198
|
-
const configPath =
|
|
5201
|
+
const configPath = path6.join(projectRoot, ".opencode", "codebase-index.json");
|
|
5199
5202
|
try {
|
|
5200
|
-
if (
|
|
5201
|
-
const content =
|
|
5203
|
+
if (existsSync4(configPath)) {
|
|
5204
|
+
const content = readFileSync4(configPath, "utf-8");
|
|
5202
5205
|
return JSON.parse(content);
|
|
5203
5206
|
}
|
|
5204
5207
|
} catch {
|
|
@@ -5227,6 +5230,39 @@ var plugin = async ({ directory }) => {
|
|
|
5227
5230
|
index_codebase,
|
|
5228
5231
|
index_status,
|
|
5229
5232
|
index_health_check
|
|
5233
|
+
},
|
|
5234
|
+
async config(cfg) {
|
|
5235
|
+
cfg.command = cfg.command ?? {};
|
|
5236
|
+
cfg.command["search"] = {
|
|
5237
|
+
description: "Search codebase by meaning using semantic search",
|
|
5238
|
+
template: `Use the \`codebase_search\` tool to find code related to: $ARGUMENTS
|
|
5239
|
+
|
|
5240
|
+
If the index doesn't exist yet, run \`index_codebase\` first.
|
|
5241
|
+
|
|
5242
|
+
Return the most relevant results with file paths and line numbers.`
|
|
5243
|
+
};
|
|
5244
|
+
cfg.command["find"] = {
|
|
5245
|
+
description: "Find code using hybrid approach (semantic + grep)",
|
|
5246
|
+
template: `Find code related to: $ARGUMENTS
|
|
5247
|
+
|
|
5248
|
+
Strategy:
|
|
5249
|
+
1. First use \`codebase_search\` to find semantically related code
|
|
5250
|
+
2. From the results, identify specific function/class names
|
|
5251
|
+
3. Use grep to find all occurrences of those identifiers
|
|
5252
|
+
4. Combine findings into a comprehensive answer
|
|
5253
|
+
|
|
5254
|
+
If the semantic index doesn't exist, run \`index_codebase\` first.`
|
|
5255
|
+
};
|
|
5256
|
+
cfg.command["index"] = {
|
|
5257
|
+
description: "Index the codebase for semantic search",
|
|
5258
|
+
template: `Run the \`index_codebase\` tool to create or update the semantic search index.
|
|
5259
|
+
|
|
5260
|
+
Show progress and final statistics including:
|
|
5261
|
+
- Number of files processed
|
|
5262
|
+
- Number of chunks indexed
|
|
5263
|
+
- Tokens used
|
|
5264
|
+
- Duration`
|
|
5265
|
+
};
|
|
5230
5266
|
}
|
|
5231
5267
|
};
|
|
5232
5268
|
};
|