opencode-codebase-index 0.1.8 → 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 +371 -377
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +365 -371
- 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);
|
|
@@ -1874,7 +1878,7 @@ function getGitHubCopilotCredentials() {
|
|
|
1874
1878
|
if (!copilotAuth || copilotAuth.type !== "oauth") {
|
|
1875
1879
|
return null;
|
|
1876
1880
|
}
|
|
1877
|
-
const baseUrl = copilotAuth.enterpriseUrl ? `https://copilot-api.${copilotAuth.enterpriseUrl.replace(/^https?:\/\//, "").replace(/\/$/, "")}` : "https://
|
|
1881
|
+
const baseUrl = copilotAuth.enterpriseUrl ? `https://copilot-api.${copilotAuth.enterpriseUrl.replace(/^https?:\/\//, "").replace(/\/$/, "")}` : "https://models.github.ai";
|
|
1878
1882
|
return {
|
|
1879
1883
|
provider: "github-copilot",
|
|
1880
1884
|
baseUrl,
|
|
@@ -1949,9 +1953,6 @@ function getProviderDisplayName(provider) {
|
|
|
1949
1953
|
}
|
|
1950
1954
|
|
|
1951
1955
|
// src/embeddings/provider.ts
|
|
1952
|
-
import { readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
1953
|
-
import * as path2 from "path";
|
|
1954
|
-
import * as os2 from "os";
|
|
1955
1956
|
function createEmbeddingProvider(credentials, modelInfo) {
|
|
1956
1957
|
switch (credentials.provider) {
|
|
1957
1958
|
case "github-copilot":
|
|
@@ -1966,56 +1967,16 @@ function createEmbeddingProvider(credentials, modelInfo) {
|
|
|
1966
1967
|
throw new Error(`Unsupported embedding provider: ${credentials.provider}`);
|
|
1967
1968
|
}
|
|
1968
1969
|
}
|
|
1969
|
-
var COPILOT_HEADERS = {
|
|
1970
|
-
"User-Agent": "GitHubCopilotChat/0.35.0",
|
|
1971
|
-
"Editor-Version": "vscode/1.107.0",
|
|
1972
|
-
"Editor-Plugin-Version": "copilot-chat/0.35.0",
|
|
1973
|
-
"Copilot-Integration-Id": "vscode-chat",
|
|
1974
|
-
"Openai-Intent": "conversation-edits"
|
|
1975
|
-
};
|
|
1976
1970
|
var GitHubCopilotEmbeddingProvider = class {
|
|
1977
1971
|
constructor(credentials, modelInfo) {
|
|
1978
1972
|
this.credentials = credentials;
|
|
1979
1973
|
this.modelInfo = modelInfo;
|
|
1980
|
-
this.accessToken = credentials.accessToken || "";
|
|
1981
|
-
this.tokenExpires = credentials.tokenExpires || 0;
|
|
1982
1974
|
}
|
|
1983
|
-
|
|
1984
|
-
tokenExpires;
|
|
1985
|
-
async ensureValidToken() {
|
|
1986
|
-
if (this.accessToken && this.tokenExpires > Date.now()) {
|
|
1987
|
-
return this.accessToken;
|
|
1988
|
-
}
|
|
1975
|
+
getToken() {
|
|
1989
1976
|
if (!this.credentials.refreshToken) {
|
|
1990
|
-
throw new Error("No
|
|
1991
|
-
}
|
|
1992
|
-
const response = await fetch("https://api.github.com/copilot_internal/v2/token", {
|
|
1993
|
-
headers: {
|
|
1994
|
-
Accept: "application/json",
|
|
1995
|
-
Authorization: `Bearer ${this.credentials.refreshToken}`,
|
|
1996
|
-
...COPILOT_HEADERS
|
|
1997
|
-
}
|
|
1998
|
-
});
|
|
1999
|
-
if (!response.ok) {
|
|
2000
|
-
throw new Error(`Token refresh failed: ${response.status}`);
|
|
2001
|
-
}
|
|
2002
|
-
const tokenData = await response.json();
|
|
2003
|
-
this.accessToken = tokenData.token;
|
|
2004
|
-
this.tokenExpires = tokenData.expires_at * 1e3 - 5 * 60 * 1e3;
|
|
2005
|
-
this.persistToken(tokenData.token, this.tokenExpires);
|
|
2006
|
-
return this.accessToken;
|
|
2007
|
-
}
|
|
2008
|
-
persistToken(token, expires) {
|
|
2009
|
-
try {
|
|
2010
|
-
const authPath = path2.join(os2.homedir(), ".local", "share", "opencode", "auth.json");
|
|
2011
|
-
const authData = JSON.parse(readFileSync2(authPath, "utf-8"));
|
|
2012
|
-
if (authData["github-copilot"]) {
|
|
2013
|
-
authData["github-copilot"].access = token;
|
|
2014
|
-
authData["github-copilot"].expires = expires;
|
|
2015
|
-
writeFileSync(authPath, JSON.stringify(authData, null, 2));
|
|
2016
|
-
}
|
|
2017
|
-
} catch {
|
|
1977
|
+
throw new Error("No OAuth token available for GitHub");
|
|
2018
1978
|
}
|
|
1979
|
+
return this.credentials.refreshToken;
|
|
2019
1980
|
}
|
|
2020
1981
|
async embed(text) {
|
|
2021
1982
|
const result = await this.embedBatch([text]);
|
|
@@ -2025,16 +1986,17 @@ var GitHubCopilotEmbeddingProvider = class {
|
|
|
2025
1986
|
};
|
|
2026
1987
|
}
|
|
2027
1988
|
async embedBatch(texts) {
|
|
2028
|
-
const token =
|
|
2029
|
-
const response = await fetch(`${this.credentials.baseUrl}/embeddings`, {
|
|
1989
|
+
const token = this.getToken();
|
|
1990
|
+
const response = await fetch(`${this.credentials.baseUrl}/inference/embeddings`, {
|
|
2030
1991
|
method: "POST",
|
|
2031
1992
|
headers: {
|
|
2032
1993
|
Authorization: `Bearer ${token}`,
|
|
2033
1994
|
"Content-Type": "application/json",
|
|
2034
|
-
|
|
1995
|
+
Accept: "application/vnd.github+json",
|
|
1996
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
2035
1997
|
},
|
|
2036
1998
|
body: JSON.stringify({
|
|
2037
|
-
model: this.modelInfo.model
|
|
1999
|
+
model: `openai/${this.modelInfo.model}`,
|
|
2038
2000
|
input: texts
|
|
2039
2001
|
})
|
|
2040
2002
|
});
|
|
@@ -2183,8 +2145,8 @@ var OllamaEmbeddingProvider = class {
|
|
|
2183
2145
|
|
|
2184
2146
|
// src/utils/files.ts
|
|
2185
2147
|
var import_ignore = __toESM(require_ignore(), 1);
|
|
2186
|
-
import { existsSync as existsSync2, readFileSync as
|
|
2187
|
-
import * as
|
|
2148
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, promises as fsPromises } from "fs";
|
|
2149
|
+
import * as path2 from "path";
|
|
2188
2150
|
function createIgnoreFilter(projectRoot) {
|
|
2189
2151
|
const ig = (0, import_ignore.default)();
|
|
2190
2152
|
const defaultIgnores = [
|
|
@@ -2201,15 +2163,15 @@ function createIgnoreFilter(projectRoot) {
|
|
|
2201
2163
|
".opencode"
|
|
2202
2164
|
];
|
|
2203
2165
|
ig.add(defaultIgnores);
|
|
2204
|
-
const gitignorePath =
|
|
2166
|
+
const gitignorePath = path2.join(projectRoot, ".gitignore");
|
|
2205
2167
|
if (existsSync2(gitignorePath)) {
|
|
2206
|
-
const gitignoreContent =
|
|
2168
|
+
const gitignoreContent = readFileSync2(gitignorePath, "utf-8");
|
|
2207
2169
|
ig.add(gitignoreContent);
|
|
2208
2170
|
}
|
|
2209
2171
|
return ig;
|
|
2210
2172
|
}
|
|
2211
2173
|
function shouldIncludeFile(filePath, projectRoot, includePatterns, excludePatterns, ignoreFilter) {
|
|
2212
|
-
const relativePath =
|
|
2174
|
+
const relativePath = path2.relative(projectRoot, filePath);
|
|
2213
2175
|
if (ignoreFilter.ignores(relativePath)) {
|
|
2214
2176
|
return false;
|
|
2215
2177
|
}
|
|
@@ -2233,8 +2195,8 @@ function matchGlob(filePath, pattern) {
|
|
|
2233
2195
|
async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns, ignoreFilter, maxFileSize, skipped) {
|
|
2234
2196
|
const entries = await fsPromises.readdir(dir, { withFileTypes: true });
|
|
2235
2197
|
for (const entry of entries) {
|
|
2236
|
-
const fullPath =
|
|
2237
|
-
const relativePath =
|
|
2198
|
+
const fullPath = path2.join(dir, entry.name);
|
|
2199
|
+
const relativePath = path2.relative(projectRoot, fullPath);
|
|
2238
2200
|
if (ignoreFilter.ignores(relativePath)) {
|
|
2239
2201
|
if (entry.isFile()) {
|
|
2240
2202
|
skipped.push({ path: relativePath, reason: "gitignore" });
|
|
@@ -2357,12 +2319,12 @@ function padRight(str, length) {
|
|
|
2357
2319
|
}
|
|
2358
2320
|
|
|
2359
2321
|
// src/native/index.ts
|
|
2360
|
-
import * as
|
|
2361
|
-
import * as
|
|
2322
|
+
import * as path3 from "path";
|
|
2323
|
+
import * as os2 from "os";
|
|
2362
2324
|
import { fileURLToPath } from "url";
|
|
2363
2325
|
function getNativeBinding() {
|
|
2364
|
-
const platform2 =
|
|
2365
|
-
const arch2 =
|
|
2326
|
+
const platform2 = os2.platform();
|
|
2327
|
+
const arch2 = os2.arch();
|
|
2366
2328
|
let bindingName;
|
|
2367
2329
|
if (platform2 === "darwin" && arch2 === "arm64") {
|
|
2368
2330
|
bindingName = "codebase-index-native.darwin-arm64.node";
|
|
@@ -2379,15 +2341,15 @@ function getNativeBinding() {
|
|
|
2379
2341
|
}
|
|
2380
2342
|
let currentDir;
|
|
2381
2343
|
if (typeof import.meta !== "undefined" && import.meta.url) {
|
|
2382
|
-
currentDir =
|
|
2344
|
+
currentDir = path3.dirname(fileURLToPath(import.meta.url));
|
|
2383
2345
|
} else if (typeof __dirname !== "undefined") {
|
|
2384
2346
|
currentDir = __dirname;
|
|
2385
2347
|
} else {
|
|
2386
2348
|
currentDir = process.cwd();
|
|
2387
2349
|
}
|
|
2388
2350
|
const isDevMode = currentDir.includes("/src/native");
|
|
2389
|
-
const packageRoot = isDevMode ?
|
|
2390
|
-
const nativePath =
|
|
2351
|
+
const packageRoot = isDevMode ? path3.resolve(currentDir, "../..") : path3.resolve(currentDir, "..");
|
|
2352
|
+
const nativePath = path3.join(packageRoot, "native", bindingName);
|
|
2391
2353
|
return __require(nativePath);
|
|
2392
2354
|
}
|
|
2393
2355
|
var native = getNativeBinding();
|
|
@@ -2662,139 +2624,39 @@ function generateChunkId(filePath, chunk) {
|
|
|
2662
2624
|
function generateChunkHash(chunk) {
|
|
2663
2625
|
return hashContent(chunk.content);
|
|
2664
2626
|
}
|
|
2665
|
-
|
|
2666
|
-
// src/indexer/inverted-index.ts
|
|
2667
|
-
import { existsSync as existsSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
2668
|
-
import * as path5 from "path";
|
|
2669
2627
|
var InvertedIndex = class {
|
|
2670
|
-
|
|
2671
|
-
termToChunks = /* @__PURE__ */ new Map();
|
|
2672
|
-
chunkTokens = /* @__PURE__ */ new Map();
|
|
2673
|
-
totalTokenCount = 0;
|
|
2628
|
+
inner;
|
|
2674
2629
|
constructor(indexPath) {
|
|
2675
|
-
this.
|
|
2630
|
+
this.inner = new native.InvertedIndex(indexPath);
|
|
2676
2631
|
}
|
|
2677
2632
|
load() {
|
|
2678
|
-
|
|
2679
|
-
return;
|
|
2680
|
-
}
|
|
2681
|
-
try {
|
|
2682
|
-
const content = readFileSync4(this.indexPath, "utf-8");
|
|
2683
|
-
const data = JSON.parse(content);
|
|
2684
|
-
for (const [term, chunkIds] of Object.entries(data.termToChunks)) {
|
|
2685
|
-
this.termToChunks.set(term, new Set(chunkIds));
|
|
2686
|
-
}
|
|
2687
|
-
for (const [chunkId, tokens] of Object.entries(data.chunkTokens)) {
|
|
2688
|
-
const tokenMap = new Map(Object.entries(tokens).map(([k, v]) => [k, v]));
|
|
2689
|
-
this.chunkTokens.set(chunkId, tokenMap);
|
|
2690
|
-
for (const count of tokenMap.values()) {
|
|
2691
|
-
this.totalTokenCount += count;
|
|
2692
|
-
}
|
|
2693
|
-
}
|
|
2694
|
-
} catch {
|
|
2695
|
-
this.termToChunks.clear();
|
|
2696
|
-
this.chunkTokens.clear();
|
|
2697
|
-
this.totalTokenCount = 0;
|
|
2698
|
-
}
|
|
2633
|
+
this.inner.load();
|
|
2699
2634
|
}
|
|
2700
2635
|
save() {
|
|
2701
|
-
|
|
2702
|
-
termToChunks: {},
|
|
2703
|
-
chunkTokens: {},
|
|
2704
|
-
avgDocLength: this.getAvgDocLength()
|
|
2705
|
-
};
|
|
2706
|
-
for (const [term, chunkIds] of this.termToChunks) {
|
|
2707
|
-
data.termToChunks[term] = Array.from(chunkIds);
|
|
2708
|
-
}
|
|
2709
|
-
for (const [chunkId, tokens] of this.chunkTokens) {
|
|
2710
|
-
data.chunkTokens[chunkId] = Object.fromEntries(tokens);
|
|
2711
|
-
}
|
|
2712
|
-
writeFileSync2(this.indexPath, JSON.stringify(data));
|
|
2636
|
+
this.inner.save();
|
|
2713
2637
|
}
|
|
2714
2638
|
addChunk(chunkId, content) {
|
|
2715
|
-
|
|
2716
|
-
const termFreq = /* @__PURE__ */ new Map();
|
|
2717
|
-
for (const token of tokens) {
|
|
2718
|
-
termFreq.set(token, (termFreq.get(token) || 0) + 1);
|
|
2719
|
-
const chunks = this.termToChunks.get(token) || /* @__PURE__ */ new Set();
|
|
2720
|
-
chunks.add(chunkId);
|
|
2721
|
-
this.termToChunks.set(token, chunks);
|
|
2722
|
-
}
|
|
2723
|
-
this.chunkTokens.set(chunkId, termFreq);
|
|
2724
|
-
this.totalTokenCount += tokens.length;
|
|
2639
|
+
this.inner.addChunk(chunkId, content);
|
|
2725
2640
|
}
|
|
2726
2641
|
removeChunk(chunkId) {
|
|
2727
|
-
|
|
2728
|
-
if (!tokens) return;
|
|
2729
|
-
for (const [token, count] of tokens) {
|
|
2730
|
-
this.totalTokenCount -= count;
|
|
2731
|
-
const chunks = this.termToChunks.get(token);
|
|
2732
|
-
if (chunks) {
|
|
2733
|
-
chunks.delete(chunkId);
|
|
2734
|
-
if (chunks.size === 0) {
|
|
2735
|
-
this.termToChunks.delete(token);
|
|
2736
|
-
}
|
|
2737
|
-
}
|
|
2738
|
-
}
|
|
2739
|
-
this.chunkTokens.delete(chunkId);
|
|
2642
|
+
return this.inner.removeChunk(chunkId);
|
|
2740
2643
|
}
|
|
2741
|
-
search(query) {
|
|
2742
|
-
const
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
const candidateChunks = /* @__PURE__ */ new Set();
|
|
2747
|
-
for (const token of queryTokens) {
|
|
2748
|
-
const chunks = this.termToChunks.get(token);
|
|
2749
|
-
if (chunks) {
|
|
2750
|
-
for (const chunkId of chunks) {
|
|
2751
|
-
candidateChunks.add(chunkId);
|
|
2752
|
-
}
|
|
2753
|
-
}
|
|
2754
|
-
}
|
|
2755
|
-
const scores = /* @__PURE__ */ new Map();
|
|
2756
|
-
const k1 = 1.2;
|
|
2757
|
-
const b = 0.75;
|
|
2758
|
-
const N = this.chunkTokens.size;
|
|
2759
|
-
const avgDocLength = this.getAvgDocLength();
|
|
2760
|
-
for (const chunkId of candidateChunks) {
|
|
2761
|
-
const termFreq = this.chunkTokens.get(chunkId);
|
|
2762
|
-
if (!termFreq) continue;
|
|
2763
|
-
const docLength = Array.from(termFreq.values()).reduce((a, b2) => a + b2, 0);
|
|
2764
|
-
let score = 0;
|
|
2765
|
-
for (const term of queryTokens) {
|
|
2766
|
-
const tf = termFreq.get(term) || 0;
|
|
2767
|
-
if (tf === 0) continue;
|
|
2768
|
-
const df = this.termToChunks.get(term)?.size || 0;
|
|
2769
|
-
const idf = Math.log((N - df + 0.5) / (df + 0.5) + 1);
|
|
2770
|
-
const tfNorm = tf * (k1 + 1) / (tf + k1 * (1 - b + b * (docLength / avgDocLength)));
|
|
2771
|
-
score += idf * tfNorm;
|
|
2772
|
-
}
|
|
2773
|
-
scores.set(chunkId, score);
|
|
2774
|
-
}
|
|
2775
|
-
const maxScore = Math.max(...scores.values(), 1);
|
|
2776
|
-
for (const [chunkId, score] of scores) {
|
|
2777
|
-
scores.set(chunkId, score / maxScore);
|
|
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);
|
|
2778
2649
|
}
|
|
2779
|
-
return
|
|
2650
|
+
return map;
|
|
2780
2651
|
}
|
|
2781
2652
|
hasChunk(chunkId) {
|
|
2782
|
-
return this.
|
|
2653
|
+
return this.inner.hasChunk(chunkId);
|
|
2783
2654
|
}
|
|
2784
2655
|
clear() {
|
|
2785
|
-
this.
|
|
2786
|
-
this.chunkTokens.clear();
|
|
2787
|
-
this.totalTokenCount = 0;
|
|
2656
|
+
this.inner.clear();
|
|
2788
2657
|
}
|
|
2789
2658
|
getDocumentCount() {
|
|
2790
|
-
return this.
|
|
2791
|
-
}
|
|
2792
|
-
getAvgDocLength() {
|
|
2793
|
-
const count = this.chunkTokens.size;
|
|
2794
|
-
return count > 0 ? this.totalTokenCount / count : 100;
|
|
2795
|
-
}
|
|
2796
|
-
tokenize(text) {
|
|
2797
|
-
return text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((t) => t.length > 2);
|
|
2659
|
+
return this.inner.documentCount();
|
|
2798
2660
|
}
|
|
2799
2661
|
};
|
|
2800
2662
|
|
|
@@ -2809,23 +2671,25 @@ var Indexer = class {
|
|
|
2809
2671
|
detectedProvider = null;
|
|
2810
2672
|
fileHashCache = /* @__PURE__ */ new Map();
|
|
2811
2673
|
fileHashCachePath = "";
|
|
2674
|
+
failedBatchesPath = "";
|
|
2812
2675
|
constructor(projectRoot, config) {
|
|
2813
2676
|
this.projectRoot = projectRoot;
|
|
2814
2677
|
this.config = config;
|
|
2815
2678
|
this.indexPath = this.getIndexPath();
|
|
2816
|
-
this.fileHashCachePath =
|
|
2679
|
+
this.fileHashCachePath = path4.join(this.indexPath, "file-hashes.json");
|
|
2680
|
+
this.failedBatchesPath = path4.join(this.indexPath, "failed-batches.json");
|
|
2817
2681
|
}
|
|
2818
2682
|
getIndexPath() {
|
|
2819
2683
|
if (this.config.scope === "global") {
|
|
2820
2684
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
2821
|
-
return
|
|
2685
|
+
return path4.join(homeDir, ".opencode", "global-index");
|
|
2822
2686
|
}
|
|
2823
|
-
return
|
|
2687
|
+
return path4.join(this.projectRoot, ".opencode", "index");
|
|
2824
2688
|
}
|
|
2825
2689
|
loadFileHashCache() {
|
|
2826
2690
|
try {
|
|
2827
|
-
if (
|
|
2828
|
-
const data =
|
|
2691
|
+
if (existsSync3(this.fileHashCachePath)) {
|
|
2692
|
+
const data = readFileSync3(this.fileHashCachePath, "utf-8");
|
|
2829
2693
|
const parsed = JSON.parse(data);
|
|
2830
2694
|
this.fileHashCache = new Map(Object.entries(parsed));
|
|
2831
2695
|
}
|
|
@@ -2838,7 +2702,38 @@ var Indexer = class {
|
|
|
2838
2702
|
for (const [k, v] of this.fileHashCache) {
|
|
2839
2703
|
obj[k] = v;
|
|
2840
2704
|
}
|
|
2841
|
-
|
|
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);
|
|
2842
2737
|
}
|
|
2843
2738
|
async initialize() {
|
|
2844
2739
|
this.detectedProvider = await detectEmbeddingProvider(this.config.embeddingProvider);
|
|
@@ -2853,13 +2748,14 @@ var Indexer = class {
|
|
|
2853
2748
|
);
|
|
2854
2749
|
await fsPromises2.mkdir(this.indexPath, { recursive: true });
|
|
2855
2750
|
const dimensions = this.detectedProvider.modelInfo.dimensions;
|
|
2856
|
-
const storePath =
|
|
2751
|
+
const storePath = path4.join(this.indexPath, "vectors");
|
|
2857
2752
|
this.store = new VectorStore(storePath, dimensions);
|
|
2858
|
-
const indexFilePath =
|
|
2859
|
-
if (
|
|
2753
|
+
const indexFilePath = path4.join(this.indexPath, "vectors.usearch");
|
|
2754
|
+
if (existsSync3(indexFilePath)) {
|
|
2860
2755
|
this.store.load();
|
|
2861
2756
|
}
|
|
2862
|
-
|
|
2757
|
+
const invertedIndexPath = path4.join(this.indexPath, "inverted-index.json");
|
|
2758
|
+
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
2863
2759
|
this.invertedIndex.load();
|
|
2864
2760
|
}
|
|
2865
2761
|
async ensureInitialized() {
|
|
@@ -2958,14 +2854,22 @@ var Indexer = class {
|
|
|
2958
2854
|
for (const parsed of parsedFiles) {
|
|
2959
2855
|
currentFilePaths.add(parsed.path);
|
|
2960
2856
|
if (parsed.chunks.length === 0) {
|
|
2961
|
-
const relativePath =
|
|
2857
|
+
const relativePath = path4.relative(this.projectRoot, parsed.path);
|
|
2962
2858
|
stats.parseFailures.push(relativePath);
|
|
2963
2859
|
}
|
|
2860
|
+
let fileChunkCount = 0;
|
|
2964
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
|
+
}
|
|
2965
2868
|
const id = generateChunkId(parsed.path, chunk);
|
|
2966
2869
|
const contentHash = generateChunkHash(chunk);
|
|
2967
2870
|
currentChunkIds.add(id);
|
|
2968
2871
|
if (existingChunks.get(id) === contentHash) {
|
|
2872
|
+
fileChunkCount++;
|
|
2969
2873
|
continue;
|
|
2970
2874
|
}
|
|
2971
2875
|
const text = createEmbeddingText(chunk, parsed.path);
|
|
@@ -2979,6 +2883,7 @@ var Indexer = class {
|
|
|
2979
2883
|
hash: contentHash
|
|
2980
2884
|
};
|
|
2981
2885
|
pendingChunks.push({ id, text, content: chunk.content, metadata });
|
|
2886
|
+
fileChunkCount++;
|
|
2982
2887
|
}
|
|
2983
2888
|
}
|
|
2984
2889
|
let removedCount = 0;
|
|
@@ -3068,6 +2973,7 @@ var Indexer = class {
|
|
|
3068
2973
|
});
|
|
3069
2974
|
} catch (error) {
|
|
3070
2975
|
stats.failedChunks += batch.length;
|
|
2976
|
+
this.addFailedBatch(batch, String(error));
|
|
3071
2977
|
console.error(`Failed to embed batch after retries: ${error}`);
|
|
3072
2978
|
}
|
|
3073
2979
|
});
|
|
@@ -3085,6 +2991,9 @@ var Indexer = class {
|
|
|
3085
2991
|
this.fileHashCache = currentFileHashes;
|
|
3086
2992
|
this.saveFileHashCache();
|
|
3087
2993
|
stats.durationMs = Date.now() - startTime;
|
|
2994
|
+
if (stats.failedChunks > 0) {
|
|
2995
|
+
stats.failedBatchesPath = this.failedBatchesPath;
|
|
2996
|
+
}
|
|
3088
2997
|
onProgress?.({
|
|
3089
2998
|
phase: "complete",
|
|
3090
2999
|
filesProcessed: files.length,
|
|
@@ -3230,7 +3139,7 @@ var Indexer = class {
|
|
|
3230
3139
|
const removedFilePaths = [];
|
|
3231
3140
|
let removedCount = 0;
|
|
3232
3141
|
for (const [filePath, chunkKeys] of filePathsToChunkKeys) {
|
|
3233
|
-
if (!
|
|
3142
|
+
if (!existsSync3(filePath)) {
|
|
3234
3143
|
for (const key of chunkKeys) {
|
|
3235
3144
|
store.remove(key);
|
|
3236
3145
|
invertedIndex.removeChunk(key);
|
|
@@ -3245,6 +3154,58 @@ var Indexer = class {
|
|
|
3245
3154
|
}
|
|
3246
3155
|
return { removed: removedCount, filePaths: removedFilePaths };
|
|
3247
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
|
+
}
|
|
3248
3209
|
};
|
|
3249
3210
|
|
|
3250
3211
|
// node_modules/chokidar/index.js
|
|
@@ -3337,7 +3298,7 @@ var ReaddirpStream = class extends Readable {
|
|
|
3337
3298
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
3338
3299
|
const statMethod = opts.lstat ? lstat : stat;
|
|
3339
3300
|
if (wantBigintFsStats) {
|
|
3340
|
-
this._stat = (
|
|
3301
|
+
this._stat = (path7) => statMethod(path7, { bigint: true });
|
|
3341
3302
|
} else {
|
|
3342
3303
|
this._stat = statMethod;
|
|
3343
3304
|
}
|
|
@@ -3362,8 +3323,8 @@ var ReaddirpStream = class extends Readable {
|
|
|
3362
3323
|
const par = this.parent;
|
|
3363
3324
|
const fil = par && par.files;
|
|
3364
3325
|
if (fil && fil.length > 0) {
|
|
3365
|
-
const { path:
|
|
3366
|
-
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));
|
|
3367
3328
|
const awaited = await Promise.all(slice);
|
|
3368
3329
|
for (const entry of awaited) {
|
|
3369
3330
|
if (!entry)
|
|
@@ -3403,20 +3364,20 @@ var ReaddirpStream = class extends Readable {
|
|
|
3403
3364
|
this.reading = false;
|
|
3404
3365
|
}
|
|
3405
3366
|
}
|
|
3406
|
-
async _exploreDir(
|
|
3367
|
+
async _exploreDir(path7, depth) {
|
|
3407
3368
|
let files;
|
|
3408
3369
|
try {
|
|
3409
|
-
files = await readdir(
|
|
3370
|
+
files = await readdir(path7, this._rdOptions);
|
|
3410
3371
|
} catch (error) {
|
|
3411
3372
|
this._onError(error);
|
|
3412
3373
|
}
|
|
3413
|
-
return { files, depth, path:
|
|
3374
|
+
return { files, depth, path: path7 };
|
|
3414
3375
|
}
|
|
3415
|
-
async _formatEntry(dirent,
|
|
3376
|
+
async _formatEntry(dirent, path7) {
|
|
3416
3377
|
let entry;
|
|
3417
3378
|
const basename3 = this._isDirent ? dirent.name : dirent;
|
|
3418
3379
|
try {
|
|
3419
|
-
const fullPath = presolve(pjoin(
|
|
3380
|
+
const fullPath = presolve(pjoin(path7, basename3));
|
|
3420
3381
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename3 };
|
|
3421
3382
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
3422
3383
|
} catch (err) {
|
|
@@ -3816,16 +3777,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
3816
3777
|
};
|
|
3817
3778
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
3818
3779
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
3819
|
-
function createFsWatchInstance(
|
|
3780
|
+
function createFsWatchInstance(path7, options, listener, errHandler, emitRaw) {
|
|
3820
3781
|
const handleEvent = (rawEvent, evPath) => {
|
|
3821
|
-
listener(
|
|
3822
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
3823
|
-
if (evPath &&
|
|
3824
|
-
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));
|
|
3825
3786
|
}
|
|
3826
3787
|
};
|
|
3827
3788
|
try {
|
|
3828
|
-
return fs_watch(
|
|
3789
|
+
return fs_watch(path7, {
|
|
3829
3790
|
persistent: options.persistent
|
|
3830
3791
|
}, handleEvent);
|
|
3831
3792
|
} catch (error) {
|
|
@@ -3841,12 +3802,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
3841
3802
|
listener(val1, val2, val3);
|
|
3842
3803
|
});
|
|
3843
3804
|
};
|
|
3844
|
-
var setFsWatchListener = (
|
|
3805
|
+
var setFsWatchListener = (path7, fullPath, options, handlers) => {
|
|
3845
3806
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
3846
3807
|
let cont = FsWatchInstances.get(fullPath);
|
|
3847
3808
|
let watcher;
|
|
3848
3809
|
if (!options.persistent) {
|
|
3849
|
-
watcher = createFsWatchInstance(
|
|
3810
|
+
watcher = createFsWatchInstance(path7, options, listener, errHandler, rawEmitter);
|
|
3850
3811
|
if (!watcher)
|
|
3851
3812
|
return;
|
|
3852
3813
|
return watcher.close.bind(watcher);
|
|
@@ -3857,7 +3818,7 @@ var setFsWatchListener = (path9, fullPath, options, handlers) => {
|
|
|
3857
3818
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
3858
3819
|
} else {
|
|
3859
3820
|
watcher = createFsWatchInstance(
|
|
3860
|
-
|
|
3821
|
+
path7,
|
|
3861
3822
|
options,
|
|
3862
3823
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
3863
3824
|
errHandler,
|
|
@@ -3872,7 +3833,7 @@ var setFsWatchListener = (path9, fullPath, options, handlers) => {
|
|
|
3872
3833
|
cont.watcherUnusable = true;
|
|
3873
3834
|
if (isWindows && error.code === "EPERM") {
|
|
3874
3835
|
try {
|
|
3875
|
-
const fd = await open(
|
|
3836
|
+
const fd = await open(path7, "r");
|
|
3876
3837
|
await fd.close();
|
|
3877
3838
|
broadcastErr(error);
|
|
3878
3839
|
} catch (err) {
|
|
@@ -3903,7 +3864,7 @@ var setFsWatchListener = (path9, fullPath, options, handlers) => {
|
|
|
3903
3864
|
};
|
|
3904
3865
|
};
|
|
3905
3866
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
3906
|
-
var setFsWatchFileListener = (
|
|
3867
|
+
var setFsWatchFileListener = (path7, fullPath, options, handlers) => {
|
|
3907
3868
|
const { listener, rawEmitter } = handlers;
|
|
3908
3869
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
3909
3870
|
const copts = cont && cont.options;
|
|
@@ -3925,7 +3886,7 @@ var setFsWatchFileListener = (path9, fullPath, options, handlers) => {
|
|
|
3925
3886
|
});
|
|
3926
3887
|
const currmtime = curr.mtimeMs;
|
|
3927
3888
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
3928
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
3889
|
+
foreach(cont.listeners, (listener2) => listener2(path7, curr));
|
|
3929
3890
|
}
|
|
3930
3891
|
})
|
|
3931
3892
|
};
|
|
@@ -3955,13 +3916,13 @@ var NodeFsHandler = class {
|
|
|
3955
3916
|
* @param listener on fs change
|
|
3956
3917
|
* @returns closer for the watcher instance
|
|
3957
3918
|
*/
|
|
3958
|
-
_watchWithNodeFs(
|
|
3919
|
+
_watchWithNodeFs(path7, listener) {
|
|
3959
3920
|
const opts = this.fsw.options;
|
|
3960
|
-
const directory = sp.dirname(
|
|
3961
|
-
const basename3 = sp.basename(
|
|
3921
|
+
const directory = sp.dirname(path7);
|
|
3922
|
+
const basename3 = sp.basename(path7);
|
|
3962
3923
|
const parent = this.fsw._getWatchedDir(directory);
|
|
3963
3924
|
parent.add(basename3);
|
|
3964
|
-
const absolutePath = sp.resolve(
|
|
3925
|
+
const absolutePath = sp.resolve(path7);
|
|
3965
3926
|
const options = {
|
|
3966
3927
|
persistent: opts.persistent
|
|
3967
3928
|
};
|
|
@@ -3971,12 +3932,12 @@ var NodeFsHandler = class {
|
|
|
3971
3932
|
if (opts.usePolling) {
|
|
3972
3933
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
3973
3934
|
options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
|
|
3974
|
-
closer = setFsWatchFileListener(
|
|
3935
|
+
closer = setFsWatchFileListener(path7, absolutePath, options, {
|
|
3975
3936
|
listener,
|
|
3976
3937
|
rawEmitter: this.fsw._emitRaw
|
|
3977
3938
|
});
|
|
3978
3939
|
} else {
|
|
3979
|
-
closer = setFsWatchListener(
|
|
3940
|
+
closer = setFsWatchListener(path7, absolutePath, options, {
|
|
3980
3941
|
listener,
|
|
3981
3942
|
errHandler: this._boundHandleError,
|
|
3982
3943
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -3998,7 +3959,7 @@ var NodeFsHandler = class {
|
|
|
3998
3959
|
let prevStats = stats;
|
|
3999
3960
|
if (parent.has(basename3))
|
|
4000
3961
|
return;
|
|
4001
|
-
const listener = async (
|
|
3962
|
+
const listener = async (path7, newStats) => {
|
|
4002
3963
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
4003
3964
|
return;
|
|
4004
3965
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -4012,11 +3973,11 @@ var NodeFsHandler = class {
|
|
|
4012
3973
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
4013
3974
|
}
|
|
4014
3975
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
4015
|
-
this.fsw._closeFile(
|
|
3976
|
+
this.fsw._closeFile(path7);
|
|
4016
3977
|
prevStats = newStats2;
|
|
4017
3978
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
4018
3979
|
if (closer2)
|
|
4019
|
-
this.fsw._addPathCloser(
|
|
3980
|
+
this.fsw._addPathCloser(path7, closer2);
|
|
4020
3981
|
} else {
|
|
4021
3982
|
prevStats = newStats2;
|
|
4022
3983
|
}
|
|
@@ -4048,7 +4009,7 @@ var NodeFsHandler = class {
|
|
|
4048
4009
|
* @param item basename of this item
|
|
4049
4010
|
* @returns true if no more processing is needed for this entry.
|
|
4050
4011
|
*/
|
|
4051
|
-
async _handleSymlink(entry, directory,
|
|
4012
|
+
async _handleSymlink(entry, directory, path7, item) {
|
|
4052
4013
|
if (this.fsw.closed) {
|
|
4053
4014
|
return;
|
|
4054
4015
|
}
|
|
@@ -4058,7 +4019,7 @@ var NodeFsHandler = class {
|
|
|
4058
4019
|
this.fsw._incrReadyCount();
|
|
4059
4020
|
let linkPath;
|
|
4060
4021
|
try {
|
|
4061
|
-
linkPath = await fsrealpath(
|
|
4022
|
+
linkPath = await fsrealpath(path7);
|
|
4062
4023
|
} catch (e) {
|
|
4063
4024
|
this.fsw._emitReady();
|
|
4064
4025
|
return true;
|
|
@@ -4068,12 +4029,12 @@ var NodeFsHandler = class {
|
|
|
4068
4029
|
if (dir.has(item)) {
|
|
4069
4030
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
4070
4031
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
4071
|
-
this.fsw._emit(EV.CHANGE,
|
|
4032
|
+
this.fsw._emit(EV.CHANGE, path7, entry.stats);
|
|
4072
4033
|
}
|
|
4073
4034
|
} else {
|
|
4074
4035
|
dir.add(item);
|
|
4075
4036
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
4076
|
-
this.fsw._emit(EV.ADD,
|
|
4037
|
+
this.fsw._emit(EV.ADD, path7, entry.stats);
|
|
4077
4038
|
}
|
|
4078
4039
|
this.fsw._emitReady();
|
|
4079
4040
|
return true;
|
|
@@ -4103,9 +4064,9 @@ var NodeFsHandler = class {
|
|
|
4103
4064
|
return;
|
|
4104
4065
|
}
|
|
4105
4066
|
const item = entry.path;
|
|
4106
|
-
let
|
|
4067
|
+
let path7 = sp.join(directory, item);
|
|
4107
4068
|
current.add(item);
|
|
4108
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
4069
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path7, item)) {
|
|
4109
4070
|
return;
|
|
4110
4071
|
}
|
|
4111
4072
|
if (this.fsw.closed) {
|
|
@@ -4114,8 +4075,8 @@ var NodeFsHandler = class {
|
|
|
4114
4075
|
}
|
|
4115
4076
|
if (item === target || !target && !previous.has(item)) {
|
|
4116
4077
|
this.fsw._incrReadyCount();
|
|
4117
|
-
|
|
4118
|
-
this._addToNodeFs(
|
|
4078
|
+
path7 = sp.join(dir, sp.relative(dir, path7));
|
|
4079
|
+
this._addToNodeFs(path7, initialAdd, wh, depth + 1);
|
|
4119
4080
|
}
|
|
4120
4081
|
}).on(EV.ERROR, this._boundHandleError);
|
|
4121
4082
|
return new Promise((resolve4, reject) => {
|
|
@@ -4184,13 +4145,13 @@ var NodeFsHandler = class {
|
|
|
4184
4145
|
* @param depth Child path actually targeted for watch
|
|
4185
4146
|
* @param target Child path actually targeted for watch
|
|
4186
4147
|
*/
|
|
4187
|
-
async _addToNodeFs(
|
|
4148
|
+
async _addToNodeFs(path7, initialAdd, priorWh, depth, target) {
|
|
4188
4149
|
const ready = this.fsw._emitReady;
|
|
4189
|
-
if (this.fsw._isIgnored(
|
|
4150
|
+
if (this.fsw._isIgnored(path7) || this.fsw.closed) {
|
|
4190
4151
|
ready();
|
|
4191
4152
|
return false;
|
|
4192
4153
|
}
|
|
4193
|
-
const wh = this.fsw._getWatchHelpers(
|
|
4154
|
+
const wh = this.fsw._getWatchHelpers(path7);
|
|
4194
4155
|
if (priorWh) {
|
|
4195
4156
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
4196
4157
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -4206,8 +4167,8 @@ var NodeFsHandler = class {
|
|
|
4206
4167
|
const follow = this.fsw.options.followSymlinks;
|
|
4207
4168
|
let closer;
|
|
4208
4169
|
if (stats.isDirectory()) {
|
|
4209
|
-
const absPath = sp.resolve(
|
|
4210
|
-
const targetPath = follow ? await fsrealpath(
|
|
4170
|
+
const absPath = sp.resolve(path7);
|
|
4171
|
+
const targetPath = follow ? await fsrealpath(path7) : path7;
|
|
4211
4172
|
if (this.fsw.closed)
|
|
4212
4173
|
return;
|
|
4213
4174
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -4217,29 +4178,29 @@ var NodeFsHandler = class {
|
|
|
4217
4178
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
4218
4179
|
}
|
|
4219
4180
|
} else if (stats.isSymbolicLink()) {
|
|
4220
|
-
const targetPath = follow ? await fsrealpath(
|
|
4181
|
+
const targetPath = follow ? await fsrealpath(path7) : path7;
|
|
4221
4182
|
if (this.fsw.closed)
|
|
4222
4183
|
return;
|
|
4223
4184
|
const parent = sp.dirname(wh.watchPath);
|
|
4224
4185
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
4225
4186
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
4226
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
4187
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path7, wh, targetPath);
|
|
4227
4188
|
if (this.fsw.closed)
|
|
4228
4189
|
return;
|
|
4229
4190
|
if (targetPath !== void 0) {
|
|
4230
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
4191
|
+
this.fsw._symlinkPaths.set(sp.resolve(path7), targetPath);
|
|
4231
4192
|
}
|
|
4232
4193
|
} else {
|
|
4233
4194
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
4234
4195
|
}
|
|
4235
4196
|
ready();
|
|
4236
4197
|
if (closer)
|
|
4237
|
-
this.fsw._addPathCloser(
|
|
4198
|
+
this.fsw._addPathCloser(path7, closer);
|
|
4238
4199
|
return false;
|
|
4239
4200
|
} catch (error) {
|
|
4240
4201
|
if (this.fsw._handleError(error)) {
|
|
4241
4202
|
ready();
|
|
4242
|
-
return
|
|
4203
|
+
return path7;
|
|
4243
4204
|
}
|
|
4244
4205
|
}
|
|
4245
4206
|
}
|
|
@@ -4282,24 +4243,24 @@ function createPattern(matcher) {
|
|
|
4282
4243
|
}
|
|
4283
4244
|
return () => false;
|
|
4284
4245
|
}
|
|
4285
|
-
function normalizePath(
|
|
4286
|
-
if (typeof
|
|
4246
|
+
function normalizePath(path7) {
|
|
4247
|
+
if (typeof path7 !== "string")
|
|
4287
4248
|
throw new Error("string expected");
|
|
4288
|
-
|
|
4289
|
-
|
|
4249
|
+
path7 = sp2.normalize(path7);
|
|
4250
|
+
path7 = path7.replace(/\\/g, "/");
|
|
4290
4251
|
let prepend = false;
|
|
4291
|
-
if (
|
|
4252
|
+
if (path7.startsWith("//"))
|
|
4292
4253
|
prepend = true;
|
|
4293
|
-
|
|
4254
|
+
path7 = path7.replace(DOUBLE_SLASH_RE, "/");
|
|
4294
4255
|
if (prepend)
|
|
4295
|
-
|
|
4296
|
-
return
|
|
4256
|
+
path7 = "/" + path7;
|
|
4257
|
+
return path7;
|
|
4297
4258
|
}
|
|
4298
4259
|
function matchPatterns(patterns, testString, stats) {
|
|
4299
|
-
const
|
|
4260
|
+
const path7 = normalizePath(testString);
|
|
4300
4261
|
for (let index = 0; index < patterns.length; index++) {
|
|
4301
4262
|
const pattern = patterns[index];
|
|
4302
|
-
if (pattern(
|
|
4263
|
+
if (pattern(path7, stats)) {
|
|
4303
4264
|
return true;
|
|
4304
4265
|
}
|
|
4305
4266
|
}
|
|
@@ -4337,19 +4298,19 @@ var toUnix = (string) => {
|
|
|
4337
4298
|
}
|
|
4338
4299
|
return str;
|
|
4339
4300
|
};
|
|
4340
|
-
var normalizePathToUnix = (
|
|
4341
|
-
var normalizeIgnored = (cwd = "") => (
|
|
4342
|
-
if (typeof
|
|
4343
|
-
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));
|
|
4344
4305
|
} else {
|
|
4345
|
-
return
|
|
4306
|
+
return path7;
|
|
4346
4307
|
}
|
|
4347
4308
|
};
|
|
4348
|
-
var getAbsolutePath = (
|
|
4349
|
-
if (sp2.isAbsolute(
|
|
4350
|
-
return
|
|
4309
|
+
var getAbsolutePath = (path7, cwd) => {
|
|
4310
|
+
if (sp2.isAbsolute(path7)) {
|
|
4311
|
+
return path7;
|
|
4351
4312
|
}
|
|
4352
|
-
return sp2.join(cwd,
|
|
4313
|
+
return sp2.join(cwd, path7);
|
|
4353
4314
|
};
|
|
4354
4315
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
4355
4316
|
var DirEntry = class {
|
|
@@ -4414,10 +4375,10 @@ var WatchHelper = class {
|
|
|
4414
4375
|
dirParts;
|
|
4415
4376
|
followSymlinks;
|
|
4416
4377
|
statMethod;
|
|
4417
|
-
constructor(
|
|
4378
|
+
constructor(path7, follow, fsw) {
|
|
4418
4379
|
this.fsw = fsw;
|
|
4419
|
-
const watchPath =
|
|
4420
|
-
this.path =
|
|
4380
|
+
const watchPath = path7;
|
|
4381
|
+
this.path = path7 = path7.replace(REPLACER_RE, "");
|
|
4421
4382
|
this.watchPath = watchPath;
|
|
4422
4383
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
4423
4384
|
this.dirParts = [];
|
|
@@ -4557,20 +4518,20 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4557
4518
|
this._closePromise = void 0;
|
|
4558
4519
|
let paths = unifyPaths(paths_);
|
|
4559
4520
|
if (cwd) {
|
|
4560
|
-
paths = paths.map((
|
|
4561
|
-
const absPath = getAbsolutePath(
|
|
4521
|
+
paths = paths.map((path7) => {
|
|
4522
|
+
const absPath = getAbsolutePath(path7, cwd);
|
|
4562
4523
|
return absPath;
|
|
4563
4524
|
});
|
|
4564
4525
|
}
|
|
4565
|
-
paths.forEach((
|
|
4566
|
-
this._removeIgnoredPath(
|
|
4526
|
+
paths.forEach((path7) => {
|
|
4527
|
+
this._removeIgnoredPath(path7);
|
|
4567
4528
|
});
|
|
4568
4529
|
this._userIgnored = void 0;
|
|
4569
4530
|
if (!this._readyCount)
|
|
4570
4531
|
this._readyCount = 0;
|
|
4571
4532
|
this._readyCount += paths.length;
|
|
4572
|
-
Promise.all(paths.map(async (
|
|
4573
|
-
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);
|
|
4574
4535
|
if (res)
|
|
4575
4536
|
this._emitReady();
|
|
4576
4537
|
return res;
|
|
@@ -4592,17 +4553,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4592
4553
|
return this;
|
|
4593
4554
|
const paths = unifyPaths(paths_);
|
|
4594
4555
|
const { cwd } = this.options;
|
|
4595
|
-
paths.forEach((
|
|
4596
|
-
if (!sp2.isAbsolute(
|
|
4556
|
+
paths.forEach((path7) => {
|
|
4557
|
+
if (!sp2.isAbsolute(path7) && !this._closers.has(path7)) {
|
|
4597
4558
|
if (cwd)
|
|
4598
|
-
|
|
4599
|
-
|
|
4559
|
+
path7 = sp2.join(cwd, path7);
|
|
4560
|
+
path7 = sp2.resolve(path7);
|
|
4600
4561
|
}
|
|
4601
|
-
this._closePath(
|
|
4602
|
-
this._addIgnoredPath(
|
|
4603
|
-
if (this._watched.has(
|
|
4562
|
+
this._closePath(path7);
|
|
4563
|
+
this._addIgnoredPath(path7);
|
|
4564
|
+
if (this._watched.has(path7)) {
|
|
4604
4565
|
this._addIgnoredPath({
|
|
4605
|
-
path:
|
|
4566
|
+
path: path7,
|
|
4606
4567
|
recursive: true
|
|
4607
4568
|
});
|
|
4608
4569
|
}
|
|
@@ -4666,38 +4627,38 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4666
4627
|
* @param stats arguments to be passed with event
|
|
4667
4628
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
4668
4629
|
*/
|
|
4669
|
-
async _emit(event,
|
|
4630
|
+
async _emit(event, path7, stats) {
|
|
4670
4631
|
if (this.closed)
|
|
4671
4632
|
return;
|
|
4672
4633
|
const opts = this.options;
|
|
4673
4634
|
if (isWindows)
|
|
4674
|
-
|
|
4635
|
+
path7 = sp2.normalize(path7);
|
|
4675
4636
|
if (opts.cwd)
|
|
4676
|
-
|
|
4677
|
-
const args = [
|
|
4637
|
+
path7 = sp2.relative(opts.cwd, path7);
|
|
4638
|
+
const args = [path7];
|
|
4678
4639
|
if (stats != null)
|
|
4679
4640
|
args.push(stats);
|
|
4680
4641
|
const awf = opts.awaitWriteFinish;
|
|
4681
4642
|
let pw;
|
|
4682
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
4643
|
+
if (awf && (pw = this._pendingWrites.get(path7))) {
|
|
4683
4644
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
4684
4645
|
return this;
|
|
4685
4646
|
}
|
|
4686
4647
|
if (opts.atomic) {
|
|
4687
4648
|
if (event === EVENTS.UNLINK) {
|
|
4688
|
-
this._pendingUnlinks.set(
|
|
4649
|
+
this._pendingUnlinks.set(path7, [event, ...args]);
|
|
4689
4650
|
setTimeout(() => {
|
|
4690
|
-
this._pendingUnlinks.forEach((entry,
|
|
4651
|
+
this._pendingUnlinks.forEach((entry, path8) => {
|
|
4691
4652
|
this.emit(...entry);
|
|
4692
4653
|
this.emit(EVENTS.ALL, ...entry);
|
|
4693
|
-
this._pendingUnlinks.delete(
|
|
4654
|
+
this._pendingUnlinks.delete(path8);
|
|
4694
4655
|
});
|
|
4695
4656
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
4696
4657
|
return this;
|
|
4697
4658
|
}
|
|
4698
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
4659
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path7)) {
|
|
4699
4660
|
event = EVENTS.CHANGE;
|
|
4700
|
-
this._pendingUnlinks.delete(
|
|
4661
|
+
this._pendingUnlinks.delete(path7);
|
|
4701
4662
|
}
|
|
4702
4663
|
}
|
|
4703
4664
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -4715,16 +4676,16 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4715
4676
|
this.emitWithAll(event, args);
|
|
4716
4677
|
}
|
|
4717
4678
|
};
|
|
4718
|
-
this._awaitWriteFinish(
|
|
4679
|
+
this._awaitWriteFinish(path7, awf.stabilityThreshold, event, awfEmit);
|
|
4719
4680
|
return this;
|
|
4720
4681
|
}
|
|
4721
4682
|
if (event === EVENTS.CHANGE) {
|
|
4722
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
4683
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path7, 50);
|
|
4723
4684
|
if (isThrottled)
|
|
4724
4685
|
return this;
|
|
4725
4686
|
}
|
|
4726
4687
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
4727
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
4688
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path7) : path7;
|
|
4728
4689
|
let stats2;
|
|
4729
4690
|
try {
|
|
4730
4691
|
stats2 = await stat3(fullPath);
|
|
@@ -4755,23 +4716,23 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4755
4716
|
* @param timeout duration of time to suppress duplicate actions
|
|
4756
4717
|
* @returns tracking object or false if action should be suppressed
|
|
4757
4718
|
*/
|
|
4758
|
-
_throttle(actionType,
|
|
4719
|
+
_throttle(actionType, path7, timeout) {
|
|
4759
4720
|
if (!this._throttled.has(actionType)) {
|
|
4760
4721
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
4761
4722
|
}
|
|
4762
4723
|
const action = this._throttled.get(actionType);
|
|
4763
4724
|
if (!action)
|
|
4764
4725
|
throw new Error("invalid throttle");
|
|
4765
|
-
const actionPath = action.get(
|
|
4726
|
+
const actionPath = action.get(path7);
|
|
4766
4727
|
if (actionPath) {
|
|
4767
4728
|
actionPath.count++;
|
|
4768
4729
|
return false;
|
|
4769
4730
|
}
|
|
4770
4731
|
let timeoutObject;
|
|
4771
4732
|
const clear = () => {
|
|
4772
|
-
const item = action.get(
|
|
4733
|
+
const item = action.get(path7);
|
|
4773
4734
|
const count = item ? item.count : 0;
|
|
4774
|
-
action.delete(
|
|
4735
|
+
action.delete(path7);
|
|
4775
4736
|
clearTimeout(timeoutObject);
|
|
4776
4737
|
if (item)
|
|
4777
4738
|
clearTimeout(item.timeoutObject);
|
|
@@ -4779,7 +4740,7 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4779
4740
|
};
|
|
4780
4741
|
timeoutObject = setTimeout(clear, timeout);
|
|
4781
4742
|
const thr = { timeoutObject, clear, count: 0 };
|
|
4782
|
-
action.set(
|
|
4743
|
+
action.set(path7, thr);
|
|
4783
4744
|
return thr;
|
|
4784
4745
|
}
|
|
4785
4746
|
_incrReadyCount() {
|
|
@@ -4793,44 +4754,44 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4793
4754
|
* @param event
|
|
4794
4755
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
4795
4756
|
*/
|
|
4796
|
-
_awaitWriteFinish(
|
|
4757
|
+
_awaitWriteFinish(path7, threshold, event, awfEmit) {
|
|
4797
4758
|
const awf = this.options.awaitWriteFinish;
|
|
4798
4759
|
if (typeof awf !== "object")
|
|
4799
4760
|
return;
|
|
4800
4761
|
const pollInterval = awf.pollInterval;
|
|
4801
4762
|
let timeoutHandler;
|
|
4802
|
-
let fullPath =
|
|
4803
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
4804
|
-
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);
|
|
4805
4766
|
}
|
|
4806
4767
|
const now = /* @__PURE__ */ new Date();
|
|
4807
4768
|
const writes = this._pendingWrites;
|
|
4808
4769
|
function awaitWriteFinishFn(prevStat) {
|
|
4809
4770
|
statcb(fullPath, (err, curStat) => {
|
|
4810
|
-
if (err || !writes.has(
|
|
4771
|
+
if (err || !writes.has(path7)) {
|
|
4811
4772
|
if (err && err.code !== "ENOENT")
|
|
4812
4773
|
awfEmit(err);
|
|
4813
4774
|
return;
|
|
4814
4775
|
}
|
|
4815
4776
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
4816
4777
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
4817
|
-
writes.get(
|
|
4778
|
+
writes.get(path7).lastChange = now2;
|
|
4818
4779
|
}
|
|
4819
|
-
const pw = writes.get(
|
|
4780
|
+
const pw = writes.get(path7);
|
|
4820
4781
|
const df = now2 - pw.lastChange;
|
|
4821
4782
|
if (df >= threshold) {
|
|
4822
|
-
writes.delete(
|
|
4783
|
+
writes.delete(path7);
|
|
4823
4784
|
awfEmit(void 0, curStat);
|
|
4824
4785
|
} else {
|
|
4825
4786
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
4826
4787
|
}
|
|
4827
4788
|
});
|
|
4828
4789
|
}
|
|
4829
|
-
if (!writes.has(
|
|
4830
|
-
writes.set(
|
|
4790
|
+
if (!writes.has(path7)) {
|
|
4791
|
+
writes.set(path7, {
|
|
4831
4792
|
lastChange: now,
|
|
4832
4793
|
cancelWait: () => {
|
|
4833
|
-
writes.delete(
|
|
4794
|
+
writes.delete(path7);
|
|
4834
4795
|
clearTimeout(timeoutHandler);
|
|
4835
4796
|
return event;
|
|
4836
4797
|
}
|
|
@@ -4841,8 +4802,8 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4841
4802
|
/**
|
|
4842
4803
|
* Determines whether user has asked to ignore this path.
|
|
4843
4804
|
*/
|
|
4844
|
-
_isIgnored(
|
|
4845
|
-
if (this.options.atomic && DOT_RE.test(
|
|
4805
|
+
_isIgnored(path7, stats) {
|
|
4806
|
+
if (this.options.atomic && DOT_RE.test(path7))
|
|
4846
4807
|
return true;
|
|
4847
4808
|
if (!this._userIgnored) {
|
|
4848
4809
|
const { cwd } = this.options;
|
|
@@ -4852,17 +4813,17 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4852
4813
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
4853
4814
|
this._userIgnored = anymatch(list, void 0);
|
|
4854
4815
|
}
|
|
4855
|
-
return this._userIgnored(
|
|
4816
|
+
return this._userIgnored(path7, stats);
|
|
4856
4817
|
}
|
|
4857
|
-
_isntIgnored(
|
|
4858
|
-
return !this._isIgnored(
|
|
4818
|
+
_isntIgnored(path7, stat4) {
|
|
4819
|
+
return !this._isIgnored(path7, stat4);
|
|
4859
4820
|
}
|
|
4860
4821
|
/**
|
|
4861
4822
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
4862
4823
|
* @param path file or directory pattern being watched
|
|
4863
4824
|
*/
|
|
4864
|
-
_getWatchHelpers(
|
|
4865
|
-
return new WatchHelper(
|
|
4825
|
+
_getWatchHelpers(path7) {
|
|
4826
|
+
return new WatchHelper(path7, this.options.followSymlinks, this);
|
|
4866
4827
|
}
|
|
4867
4828
|
// Directory helpers
|
|
4868
4829
|
// -----------------
|
|
@@ -4894,63 +4855,63 @@ var FSWatcher = class extends EventEmitter2 {
|
|
|
4894
4855
|
* @param item base path of item/directory
|
|
4895
4856
|
*/
|
|
4896
4857
|
_remove(directory, item, isDirectory) {
|
|
4897
|
-
const
|
|
4898
|
-
const fullPath = sp2.resolve(
|
|
4899
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
4900
|
-
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))
|
|
4901
4862
|
return;
|
|
4902
4863
|
if (!isDirectory && this._watched.size === 1) {
|
|
4903
4864
|
this.add(directory, item, true);
|
|
4904
4865
|
}
|
|
4905
|
-
const wp = this._getWatchedDir(
|
|
4866
|
+
const wp = this._getWatchedDir(path7);
|
|
4906
4867
|
const nestedDirectoryChildren = wp.getChildren();
|
|
4907
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
4868
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path7, nested));
|
|
4908
4869
|
const parent = this._getWatchedDir(directory);
|
|
4909
4870
|
const wasTracked = parent.has(item);
|
|
4910
4871
|
parent.remove(item);
|
|
4911
4872
|
if (this._symlinkPaths.has(fullPath)) {
|
|
4912
4873
|
this._symlinkPaths.delete(fullPath);
|
|
4913
4874
|
}
|
|
4914
|
-
let relPath =
|
|
4875
|
+
let relPath = path7;
|
|
4915
4876
|
if (this.options.cwd)
|
|
4916
|
-
relPath = sp2.relative(this.options.cwd,
|
|
4877
|
+
relPath = sp2.relative(this.options.cwd, path7);
|
|
4917
4878
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
4918
4879
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
4919
4880
|
if (event === EVENTS.ADD)
|
|
4920
4881
|
return;
|
|
4921
4882
|
}
|
|
4922
|
-
this._watched.delete(
|
|
4883
|
+
this._watched.delete(path7);
|
|
4923
4884
|
this._watched.delete(fullPath);
|
|
4924
4885
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
4925
|
-
if (wasTracked && !this._isIgnored(
|
|
4926
|
-
this._emit(eventName,
|
|
4927
|
-
this._closePath(
|
|
4886
|
+
if (wasTracked && !this._isIgnored(path7))
|
|
4887
|
+
this._emit(eventName, path7);
|
|
4888
|
+
this._closePath(path7);
|
|
4928
4889
|
}
|
|
4929
4890
|
/**
|
|
4930
4891
|
* Closes all watchers for a path
|
|
4931
4892
|
*/
|
|
4932
|
-
_closePath(
|
|
4933
|
-
this._closeFile(
|
|
4934
|
-
const dir = sp2.dirname(
|
|
4935
|
-
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));
|
|
4936
4897
|
}
|
|
4937
4898
|
/**
|
|
4938
4899
|
* Closes only file-specific watchers
|
|
4939
4900
|
*/
|
|
4940
|
-
_closeFile(
|
|
4941
|
-
const closers = this._closers.get(
|
|
4901
|
+
_closeFile(path7) {
|
|
4902
|
+
const closers = this._closers.get(path7);
|
|
4942
4903
|
if (!closers)
|
|
4943
4904
|
return;
|
|
4944
4905
|
closers.forEach((closer) => closer());
|
|
4945
|
-
this._closers.delete(
|
|
4906
|
+
this._closers.delete(path7);
|
|
4946
4907
|
}
|
|
4947
|
-
_addPathCloser(
|
|
4908
|
+
_addPathCloser(path7, closer) {
|
|
4948
4909
|
if (!closer)
|
|
4949
4910
|
return;
|
|
4950
|
-
let list = this._closers.get(
|
|
4911
|
+
let list = this._closers.get(path7);
|
|
4951
4912
|
if (!list) {
|
|
4952
4913
|
list = [];
|
|
4953
|
-
this._closers.set(
|
|
4914
|
+
this._closers.set(path7, list);
|
|
4954
4915
|
}
|
|
4955
4916
|
list.push(closer);
|
|
4956
4917
|
}
|
|
@@ -4980,7 +4941,7 @@ function watch(paths, options = {}) {
|
|
|
4980
4941
|
var chokidar_default = { watch, FSWatcher };
|
|
4981
4942
|
|
|
4982
4943
|
// src/watcher/index.ts
|
|
4983
|
-
import * as
|
|
4944
|
+
import * as path5 from "path";
|
|
4984
4945
|
var FileWatcher = class {
|
|
4985
4946
|
watcher = null;
|
|
4986
4947
|
projectRoot;
|
|
@@ -5001,7 +4962,7 @@ var FileWatcher = class {
|
|
|
5001
4962
|
const ignoreFilter = createIgnoreFilter(this.projectRoot);
|
|
5002
4963
|
this.watcher = chokidar_default.watch(this.projectRoot, {
|
|
5003
4964
|
ignored: (filePath) => {
|
|
5004
|
-
const relativePath =
|
|
4965
|
+
const relativePath = path5.relative(this.projectRoot, filePath);
|
|
5005
4966
|
if (!relativePath) return false;
|
|
5006
4967
|
if (ignoreFilter.ignores(relativePath)) {
|
|
5007
4968
|
return true;
|
|
@@ -5045,7 +5006,7 @@ var FileWatcher = class {
|
|
|
5045
5006
|
return;
|
|
5046
5007
|
}
|
|
5047
5008
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
5048
|
-
([
|
|
5009
|
+
([path7, type]) => ({ path: path7, type })
|
|
5049
5010
|
);
|
|
5050
5011
|
this.pendingChanges.clear();
|
|
5051
5012
|
try {
|
|
@@ -5237,10 +5198,10 @@ function formatStatus(status) {
|
|
|
5237
5198
|
|
|
5238
5199
|
// src/index.ts
|
|
5239
5200
|
function loadPluginConfig(projectRoot) {
|
|
5240
|
-
const configPath =
|
|
5201
|
+
const configPath = path6.join(projectRoot, ".opencode", "codebase-index.json");
|
|
5241
5202
|
try {
|
|
5242
|
-
if (
|
|
5243
|
-
const content =
|
|
5203
|
+
if (existsSync4(configPath)) {
|
|
5204
|
+
const content = readFileSync4(configPath, "utf-8");
|
|
5244
5205
|
return JSON.parse(content);
|
|
5245
5206
|
}
|
|
5246
5207
|
} catch {
|
|
@@ -5269,6 +5230,39 @@ var plugin = async ({ directory }) => {
|
|
|
5269
5230
|
index_codebase,
|
|
5270
5231
|
index_status,
|
|
5271
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
|
+
};
|
|
5272
5266
|
}
|
|
5273
5267
|
};
|
|
5274
5268
|
};
|