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.cjs
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.
|
|
@@ -657,8 +657,8 @@ __export(index_exports, {
|
|
|
657
657
|
default: () => index_default
|
|
658
658
|
});
|
|
659
659
|
module.exports = __toCommonJS(index_exports);
|
|
660
|
-
var
|
|
661
|
-
var
|
|
660
|
+
var import_fs4 = require("fs");
|
|
661
|
+
var path6 = __toESM(require("path"), 1);
|
|
662
662
|
|
|
663
663
|
// src/config/schema.ts
|
|
664
664
|
var DEFAULT_INCLUDE = [
|
|
@@ -693,6 +693,8 @@ function getDefaultIndexingConfig() {
|
|
|
693
693
|
autoIndex: false,
|
|
694
694
|
watchFiles: true,
|
|
695
695
|
maxFileSize: 1048576,
|
|
696
|
+
maxChunksPerFile: 100,
|
|
697
|
+
semanticOnly: false,
|
|
696
698
|
retries: 3,
|
|
697
699
|
retryDelayMs: 1e3
|
|
698
700
|
};
|
|
@@ -726,6 +728,8 @@ function parseConfig(raw) {
|
|
|
726
728
|
autoIndex: typeof rawIndexing.autoIndex === "boolean" ? rawIndexing.autoIndex : defaultIndexing.autoIndex,
|
|
727
729
|
watchFiles: typeof rawIndexing.watchFiles === "boolean" ? rawIndexing.watchFiles : defaultIndexing.watchFiles,
|
|
728
730
|
maxFileSize: typeof rawIndexing.maxFileSize === "number" ? rawIndexing.maxFileSize : defaultIndexing.maxFileSize,
|
|
731
|
+
maxChunksPerFile: typeof rawIndexing.maxChunksPerFile === "number" ? Math.max(1, rawIndexing.maxChunksPerFile) : defaultIndexing.maxChunksPerFile,
|
|
732
|
+
semanticOnly: typeof rawIndexing.semanticOnly === "boolean" ? rawIndexing.semanticOnly : defaultIndexing.semanticOnly,
|
|
729
733
|
retries: typeof rawIndexing.retries === "number" ? rawIndexing.retries : defaultIndexing.retries,
|
|
730
734
|
retryDelayMs: typeof rawIndexing.retryDelayMs === "number" ? rawIndexing.retryDelayMs : defaultIndexing.retryDelayMs
|
|
731
735
|
};
|
|
@@ -807,8 +811,8 @@ function getDefaultModelForProvider(provider) {
|
|
|
807
811
|
}
|
|
808
812
|
|
|
809
813
|
// src/indexer/index.ts
|
|
810
|
-
var
|
|
811
|
-
var
|
|
814
|
+
var import_fs3 = require("fs");
|
|
815
|
+
var path4 = __toESM(require("path"), 1);
|
|
812
816
|
|
|
813
817
|
// node_modules/eventemitter3/index.mjs
|
|
814
818
|
var import_index = __toESM(require_eventemitter3(), 1);
|
|
@@ -1879,7 +1883,7 @@ function getGitHubCopilotCredentials() {
|
|
|
1879
1883
|
if (!copilotAuth || copilotAuth.type !== "oauth") {
|
|
1880
1884
|
return null;
|
|
1881
1885
|
}
|
|
1882
|
-
const baseUrl = copilotAuth.enterpriseUrl ? `https://copilot-api.${copilotAuth.enterpriseUrl.replace(/^https?:\/\//, "").replace(/\/$/, "")}` : "https://
|
|
1886
|
+
const baseUrl = copilotAuth.enterpriseUrl ? `https://copilot-api.${copilotAuth.enterpriseUrl.replace(/^https?:\/\//, "").replace(/\/$/, "")}` : "https://models.github.ai";
|
|
1883
1887
|
return {
|
|
1884
1888
|
provider: "github-copilot",
|
|
1885
1889
|
baseUrl,
|
|
@@ -1954,9 +1958,6 @@ function getProviderDisplayName(provider) {
|
|
|
1954
1958
|
}
|
|
1955
1959
|
|
|
1956
1960
|
// src/embeddings/provider.ts
|
|
1957
|
-
var import_fs2 = require("fs");
|
|
1958
|
-
var path2 = __toESM(require("path"), 1);
|
|
1959
|
-
var os2 = __toESM(require("os"), 1);
|
|
1960
1961
|
function createEmbeddingProvider(credentials, modelInfo) {
|
|
1961
1962
|
switch (credentials.provider) {
|
|
1962
1963
|
case "github-copilot":
|
|
@@ -1971,56 +1972,16 @@ function createEmbeddingProvider(credentials, modelInfo) {
|
|
|
1971
1972
|
throw new Error(`Unsupported embedding provider: ${credentials.provider}`);
|
|
1972
1973
|
}
|
|
1973
1974
|
}
|
|
1974
|
-
var COPILOT_HEADERS = {
|
|
1975
|
-
"User-Agent": "GitHubCopilotChat/0.35.0",
|
|
1976
|
-
"Editor-Version": "vscode/1.107.0",
|
|
1977
|
-
"Editor-Plugin-Version": "copilot-chat/0.35.0",
|
|
1978
|
-
"Copilot-Integration-Id": "vscode-chat",
|
|
1979
|
-
"Openai-Intent": "conversation-edits"
|
|
1980
|
-
};
|
|
1981
1975
|
var GitHubCopilotEmbeddingProvider = class {
|
|
1982
1976
|
constructor(credentials, modelInfo) {
|
|
1983
1977
|
this.credentials = credentials;
|
|
1984
1978
|
this.modelInfo = modelInfo;
|
|
1985
|
-
this.accessToken = credentials.accessToken || "";
|
|
1986
|
-
this.tokenExpires = credentials.tokenExpires || 0;
|
|
1987
1979
|
}
|
|
1988
|
-
|
|
1989
|
-
tokenExpires;
|
|
1990
|
-
async ensureValidToken() {
|
|
1991
|
-
if (this.accessToken && this.tokenExpires > Date.now()) {
|
|
1992
|
-
return this.accessToken;
|
|
1993
|
-
}
|
|
1980
|
+
getToken() {
|
|
1994
1981
|
if (!this.credentials.refreshToken) {
|
|
1995
|
-
throw new Error("No
|
|
1996
|
-
}
|
|
1997
|
-
const response = await fetch("https://api.github.com/copilot_internal/v2/token", {
|
|
1998
|
-
headers: {
|
|
1999
|
-
Accept: "application/json",
|
|
2000
|
-
Authorization: `Bearer ${this.credentials.refreshToken}`,
|
|
2001
|
-
...COPILOT_HEADERS
|
|
2002
|
-
}
|
|
2003
|
-
});
|
|
2004
|
-
if (!response.ok) {
|
|
2005
|
-
throw new Error(`Token refresh failed: ${response.status}`);
|
|
2006
|
-
}
|
|
2007
|
-
const tokenData = await response.json();
|
|
2008
|
-
this.accessToken = tokenData.token;
|
|
2009
|
-
this.tokenExpires = tokenData.expires_at * 1e3 - 5 * 60 * 1e3;
|
|
2010
|
-
this.persistToken(tokenData.token, this.tokenExpires);
|
|
2011
|
-
return this.accessToken;
|
|
2012
|
-
}
|
|
2013
|
-
persistToken(token, expires) {
|
|
2014
|
-
try {
|
|
2015
|
-
const authPath = path2.join(os2.homedir(), ".local", "share", "opencode", "auth.json");
|
|
2016
|
-
const authData = JSON.parse((0, import_fs2.readFileSync)(authPath, "utf-8"));
|
|
2017
|
-
if (authData["github-copilot"]) {
|
|
2018
|
-
authData["github-copilot"].access = token;
|
|
2019
|
-
authData["github-copilot"].expires = expires;
|
|
2020
|
-
(0, import_fs2.writeFileSync)(authPath, JSON.stringify(authData, null, 2));
|
|
2021
|
-
}
|
|
2022
|
-
} catch {
|
|
1982
|
+
throw new Error("No OAuth token available for GitHub");
|
|
2023
1983
|
}
|
|
1984
|
+
return this.credentials.refreshToken;
|
|
2024
1985
|
}
|
|
2025
1986
|
async embed(text) {
|
|
2026
1987
|
const result = await this.embedBatch([text]);
|
|
@@ -2030,16 +1991,17 @@ var GitHubCopilotEmbeddingProvider = class {
|
|
|
2030
1991
|
};
|
|
2031
1992
|
}
|
|
2032
1993
|
async embedBatch(texts) {
|
|
2033
|
-
const token =
|
|
2034
|
-
const response = await fetch(`${this.credentials.baseUrl}/embeddings`, {
|
|
1994
|
+
const token = this.getToken();
|
|
1995
|
+
const response = await fetch(`${this.credentials.baseUrl}/inference/embeddings`, {
|
|
2035
1996
|
method: "POST",
|
|
2036
1997
|
headers: {
|
|
2037
1998
|
Authorization: `Bearer ${token}`,
|
|
2038
1999
|
"Content-Type": "application/json",
|
|
2039
|
-
|
|
2000
|
+
Accept: "application/vnd.github+json",
|
|
2001
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
2040
2002
|
},
|
|
2041
2003
|
body: JSON.stringify({
|
|
2042
|
-
model: this.modelInfo.model
|
|
2004
|
+
model: `openai/${this.modelInfo.model}`,
|
|
2043
2005
|
input: texts
|
|
2044
2006
|
})
|
|
2045
2007
|
});
|
|
@@ -2188,8 +2150,8 @@ var OllamaEmbeddingProvider = class {
|
|
|
2188
2150
|
|
|
2189
2151
|
// src/utils/files.ts
|
|
2190
2152
|
var import_ignore = __toESM(require_ignore(), 1);
|
|
2191
|
-
var
|
|
2192
|
-
var
|
|
2153
|
+
var import_fs2 = require("fs");
|
|
2154
|
+
var path2 = __toESM(require("path"), 1);
|
|
2193
2155
|
function createIgnoreFilter(projectRoot) {
|
|
2194
2156
|
const ig = (0, import_ignore.default)();
|
|
2195
2157
|
const defaultIgnores = [
|
|
@@ -2206,15 +2168,15 @@ function createIgnoreFilter(projectRoot) {
|
|
|
2206
2168
|
".opencode"
|
|
2207
2169
|
];
|
|
2208
2170
|
ig.add(defaultIgnores);
|
|
2209
|
-
const gitignorePath =
|
|
2210
|
-
if ((0,
|
|
2211
|
-
const gitignoreContent = (0,
|
|
2171
|
+
const gitignorePath = path2.join(projectRoot, ".gitignore");
|
|
2172
|
+
if ((0, import_fs2.existsSync)(gitignorePath)) {
|
|
2173
|
+
const gitignoreContent = (0, import_fs2.readFileSync)(gitignorePath, "utf-8");
|
|
2212
2174
|
ig.add(gitignoreContent);
|
|
2213
2175
|
}
|
|
2214
2176
|
return ig;
|
|
2215
2177
|
}
|
|
2216
2178
|
function shouldIncludeFile(filePath, projectRoot, includePatterns, excludePatterns, ignoreFilter) {
|
|
2217
|
-
const relativePath =
|
|
2179
|
+
const relativePath = path2.relative(projectRoot, filePath);
|
|
2218
2180
|
if (ignoreFilter.ignores(relativePath)) {
|
|
2219
2181
|
return false;
|
|
2220
2182
|
}
|
|
@@ -2236,10 +2198,10 @@ function matchGlob(filePath, pattern) {
|
|
|
2236
2198
|
return regex.test(filePath);
|
|
2237
2199
|
}
|
|
2238
2200
|
async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns, ignoreFilter, maxFileSize, skipped) {
|
|
2239
|
-
const entries = await
|
|
2201
|
+
const entries = await import_fs2.promises.readdir(dir, { withFileTypes: true });
|
|
2240
2202
|
for (const entry of entries) {
|
|
2241
|
-
const fullPath =
|
|
2242
|
-
const relativePath =
|
|
2203
|
+
const fullPath = path2.join(dir, entry.name);
|
|
2204
|
+
const relativePath = path2.relative(projectRoot, fullPath);
|
|
2243
2205
|
if (ignoreFilter.ignores(relativePath)) {
|
|
2244
2206
|
if (entry.isFile()) {
|
|
2245
2207
|
skipped.push({ path: relativePath, reason: "gitignore" });
|
|
@@ -2257,7 +2219,7 @@ async function* walkDirectory(dir, projectRoot, includePatterns, excludePatterns
|
|
|
2257
2219
|
skipped
|
|
2258
2220
|
);
|
|
2259
2221
|
} else if (entry.isFile()) {
|
|
2260
|
-
const stat4 = await
|
|
2222
|
+
const stat4 = await import_fs2.promises.stat(fullPath);
|
|
2261
2223
|
if (stat4.size > maxFileSize) {
|
|
2262
2224
|
skipped.push({ path: relativePath, reason: "too_large" });
|
|
2263
2225
|
continue;
|
|
@@ -2362,13 +2324,13 @@ function padRight(str, length) {
|
|
|
2362
2324
|
}
|
|
2363
2325
|
|
|
2364
2326
|
// src/native/index.ts
|
|
2365
|
-
var
|
|
2366
|
-
var
|
|
2327
|
+
var path3 = __toESM(require("path"), 1);
|
|
2328
|
+
var os2 = __toESM(require("os"), 1);
|
|
2367
2329
|
var import_url = require("url");
|
|
2368
2330
|
var import_meta = {};
|
|
2369
2331
|
function getNativeBinding() {
|
|
2370
|
-
const platform2 =
|
|
2371
|
-
const arch2 =
|
|
2332
|
+
const platform2 = os2.platform();
|
|
2333
|
+
const arch2 = os2.arch();
|
|
2372
2334
|
let bindingName;
|
|
2373
2335
|
if (platform2 === "darwin" && arch2 === "arm64") {
|
|
2374
2336
|
bindingName = "codebase-index-native.darwin-arm64.node";
|
|
@@ -2385,15 +2347,15 @@ function getNativeBinding() {
|
|
|
2385
2347
|
}
|
|
2386
2348
|
let currentDir;
|
|
2387
2349
|
if (typeof import_meta !== "undefined" && import_meta.url) {
|
|
2388
|
-
currentDir =
|
|
2350
|
+
currentDir = path3.dirname((0, import_url.fileURLToPath)(import_meta.url));
|
|
2389
2351
|
} else if (typeof __dirname !== "undefined") {
|
|
2390
2352
|
currentDir = __dirname;
|
|
2391
2353
|
} else {
|
|
2392
2354
|
currentDir = process.cwd();
|
|
2393
2355
|
}
|
|
2394
2356
|
const isDevMode = currentDir.includes("/src/native");
|
|
2395
|
-
const packageRoot = isDevMode ?
|
|
2396
|
-
const nativePath =
|
|
2357
|
+
const packageRoot = isDevMode ? path3.resolve(currentDir, "../..") : path3.resolve(currentDir, "..");
|
|
2358
|
+
const nativePath = path3.join(packageRoot, "native", bindingName);
|
|
2397
2359
|
return require(nativePath);
|
|
2398
2360
|
}
|
|
2399
2361
|
var native = getNativeBinding();
|
|
@@ -2668,139 +2630,39 @@ function generateChunkId(filePath, chunk) {
|
|
|
2668
2630
|
function generateChunkHash(chunk) {
|
|
2669
2631
|
return hashContent(chunk.content);
|
|
2670
2632
|
}
|
|
2671
|
-
|
|
2672
|
-
// src/indexer/inverted-index.ts
|
|
2673
|
-
var import_fs4 = require("fs");
|
|
2674
|
-
var path5 = __toESM(require("path"), 1);
|
|
2675
2633
|
var InvertedIndex = class {
|
|
2676
|
-
|
|
2677
|
-
termToChunks = /* @__PURE__ */ new Map();
|
|
2678
|
-
chunkTokens = /* @__PURE__ */ new Map();
|
|
2679
|
-
totalTokenCount = 0;
|
|
2634
|
+
inner;
|
|
2680
2635
|
constructor(indexPath) {
|
|
2681
|
-
this.
|
|
2636
|
+
this.inner = new native.InvertedIndex(indexPath);
|
|
2682
2637
|
}
|
|
2683
2638
|
load() {
|
|
2684
|
-
|
|
2685
|
-
return;
|
|
2686
|
-
}
|
|
2687
|
-
try {
|
|
2688
|
-
const content = (0, import_fs4.readFileSync)(this.indexPath, "utf-8");
|
|
2689
|
-
const data = JSON.parse(content);
|
|
2690
|
-
for (const [term, chunkIds] of Object.entries(data.termToChunks)) {
|
|
2691
|
-
this.termToChunks.set(term, new Set(chunkIds));
|
|
2692
|
-
}
|
|
2693
|
-
for (const [chunkId, tokens] of Object.entries(data.chunkTokens)) {
|
|
2694
|
-
const tokenMap = new Map(Object.entries(tokens).map(([k, v]) => [k, v]));
|
|
2695
|
-
this.chunkTokens.set(chunkId, tokenMap);
|
|
2696
|
-
for (const count of tokenMap.values()) {
|
|
2697
|
-
this.totalTokenCount += count;
|
|
2698
|
-
}
|
|
2699
|
-
}
|
|
2700
|
-
} catch {
|
|
2701
|
-
this.termToChunks.clear();
|
|
2702
|
-
this.chunkTokens.clear();
|
|
2703
|
-
this.totalTokenCount = 0;
|
|
2704
|
-
}
|
|
2639
|
+
this.inner.load();
|
|
2705
2640
|
}
|
|
2706
2641
|
save() {
|
|
2707
|
-
|
|
2708
|
-
termToChunks: {},
|
|
2709
|
-
chunkTokens: {},
|
|
2710
|
-
avgDocLength: this.getAvgDocLength()
|
|
2711
|
-
};
|
|
2712
|
-
for (const [term, chunkIds] of this.termToChunks) {
|
|
2713
|
-
data.termToChunks[term] = Array.from(chunkIds);
|
|
2714
|
-
}
|
|
2715
|
-
for (const [chunkId, tokens] of this.chunkTokens) {
|
|
2716
|
-
data.chunkTokens[chunkId] = Object.fromEntries(tokens);
|
|
2717
|
-
}
|
|
2718
|
-
(0, import_fs4.writeFileSync)(this.indexPath, JSON.stringify(data));
|
|
2642
|
+
this.inner.save();
|
|
2719
2643
|
}
|
|
2720
2644
|
addChunk(chunkId, content) {
|
|
2721
|
-
|
|
2722
|
-
const termFreq = /* @__PURE__ */ new Map();
|
|
2723
|
-
for (const token of tokens) {
|
|
2724
|
-
termFreq.set(token, (termFreq.get(token) || 0) + 1);
|
|
2725
|
-
const chunks = this.termToChunks.get(token) || /* @__PURE__ */ new Set();
|
|
2726
|
-
chunks.add(chunkId);
|
|
2727
|
-
this.termToChunks.set(token, chunks);
|
|
2728
|
-
}
|
|
2729
|
-
this.chunkTokens.set(chunkId, termFreq);
|
|
2730
|
-
this.totalTokenCount += tokens.length;
|
|
2645
|
+
this.inner.addChunk(chunkId, content);
|
|
2731
2646
|
}
|
|
2732
2647
|
removeChunk(chunkId) {
|
|
2733
|
-
|
|
2734
|
-
if (!tokens) return;
|
|
2735
|
-
for (const [token, count] of tokens) {
|
|
2736
|
-
this.totalTokenCount -= count;
|
|
2737
|
-
const chunks = this.termToChunks.get(token);
|
|
2738
|
-
if (chunks) {
|
|
2739
|
-
chunks.delete(chunkId);
|
|
2740
|
-
if (chunks.size === 0) {
|
|
2741
|
-
this.termToChunks.delete(token);
|
|
2742
|
-
}
|
|
2743
|
-
}
|
|
2744
|
-
}
|
|
2745
|
-
this.chunkTokens.delete(chunkId);
|
|
2648
|
+
return this.inner.removeChunk(chunkId);
|
|
2746
2649
|
}
|
|
2747
|
-
search(query) {
|
|
2748
|
-
const
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
const candidateChunks = /* @__PURE__ */ new Set();
|
|
2753
|
-
for (const token of queryTokens) {
|
|
2754
|
-
const chunks = this.termToChunks.get(token);
|
|
2755
|
-
if (chunks) {
|
|
2756
|
-
for (const chunkId of chunks) {
|
|
2757
|
-
candidateChunks.add(chunkId);
|
|
2758
|
-
}
|
|
2759
|
-
}
|
|
2760
|
-
}
|
|
2761
|
-
const scores = /* @__PURE__ */ new Map();
|
|
2762
|
-
const k1 = 1.2;
|
|
2763
|
-
const b = 0.75;
|
|
2764
|
-
const N = this.chunkTokens.size;
|
|
2765
|
-
const avgDocLength = this.getAvgDocLength();
|
|
2766
|
-
for (const chunkId of candidateChunks) {
|
|
2767
|
-
const termFreq = this.chunkTokens.get(chunkId);
|
|
2768
|
-
if (!termFreq) continue;
|
|
2769
|
-
const docLength = Array.from(termFreq.values()).reduce((a, b2) => a + b2, 0);
|
|
2770
|
-
let score = 0;
|
|
2771
|
-
for (const term of queryTokens) {
|
|
2772
|
-
const tf = termFreq.get(term) || 0;
|
|
2773
|
-
if (tf === 0) continue;
|
|
2774
|
-
const df = this.termToChunks.get(term)?.size || 0;
|
|
2775
|
-
const idf = Math.log((N - df + 0.5) / (df + 0.5) + 1);
|
|
2776
|
-
const tfNorm = tf * (k1 + 1) / (tf + k1 * (1 - b + b * (docLength / avgDocLength)));
|
|
2777
|
-
score += idf * tfNorm;
|
|
2778
|
-
}
|
|
2779
|
-
scores.set(chunkId, score);
|
|
2650
|
+
search(query, limit) {
|
|
2651
|
+
const results = this.inner.search(query, limit ?? 100);
|
|
2652
|
+
const map = /* @__PURE__ */ new Map();
|
|
2653
|
+
for (const r of results) {
|
|
2654
|
+
map.set(r.chunkId, r.score);
|
|
2780
2655
|
}
|
|
2781
|
-
|
|
2782
|
-
for (const [chunkId, score] of scores) {
|
|
2783
|
-
scores.set(chunkId, score / maxScore);
|
|
2784
|
-
}
|
|
2785
|
-
return scores;
|
|
2656
|
+
return map;
|
|
2786
2657
|
}
|
|
2787
2658
|
hasChunk(chunkId) {
|
|
2788
|
-
return this.
|
|
2659
|
+
return this.inner.hasChunk(chunkId);
|
|
2789
2660
|
}
|
|
2790
2661
|
clear() {
|
|
2791
|
-
this.
|
|
2792
|
-
this.chunkTokens.clear();
|
|
2793
|
-
this.totalTokenCount = 0;
|
|
2662
|
+
this.inner.clear();
|
|
2794
2663
|
}
|
|
2795
2664
|
getDocumentCount() {
|
|
2796
|
-
return this.
|
|
2797
|
-
}
|
|
2798
|
-
getAvgDocLength() {
|
|
2799
|
-
const count = this.chunkTokens.size;
|
|
2800
|
-
return count > 0 ? this.totalTokenCount / count : 100;
|
|
2801
|
-
}
|
|
2802
|
-
tokenize(text) {
|
|
2803
|
-
return text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((t) => t.length > 2);
|
|
2665
|
+
return this.inner.documentCount();
|
|
2804
2666
|
}
|
|
2805
2667
|
};
|
|
2806
2668
|
|
|
@@ -2815,23 +2677,25 @@ var Indexer = class {
|
|
|
2815
2677
|
detectedProvider = null;
|
|
2816
2678
|
fileHashCache = /* @__PURE__ */ new Map();
|
|
2817
2679
|
fileHashCachePath = "";
|
|
2680
|
+
failedBatchesPath = "";
|
|
2818
2681
|
constructor(projectRoot, config) {
|
|
2819
2682
|
this.projectRoot = projectRoot;
|
|
2820
2683
|
this.config = config;
|
|
2821
2684
|
this.indexPath = this.getIndexPath();
|
|
2822
|
-
this.fileHashCachePath =
|
|
2685
|
+
this.fileHashCachePath = path4.join(this.indexPath, "file-hashes.json");
|
|
2686
|
+
this.failedBatchesPath = path4.join(this.indexPath, "failed-batches.json");
|
|
2823
2687
|
}
|
|
2824
2688
|
getIndexPath() {
|
|
2825
2689
|
if (this.config.scope === "global") {
|
|
2826
2690
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
2827
|
-
return
|
|
2691
|
+
return path4.join(homeDir, ".opencode", "global-index");
|
|
2828
2692
|
}
|
|
2829
|
-
return
|
|
2693
|
+
return path4.join(this.projectRoot, ".opencode", "index");
|
|
2830
2694
|
}
|
|
2831
2695
|
loadFileHashCache() {
|
|
2832
2696
|
try {
|
|
2833
|
-
if ((0,
|
|
2834
|
-
const data = (0,
|
|
2697
|
+
if ((0, import_fs3.existsSync)(this.fileHashCachePath)) {
|
|
2698
|
+
const data = (0, import_fs3.readFileSync)(this.fileHashCachePath, "utf-8");
|
|
2835
2699
|
const parsed = JSON.parse(data);
|
|
2836
2700
|
this.fileHashCache = new Map(Object.entries(parsed));
|
|
2837
2701
|
}
|
|
@@ -2844,7 +2708,38 @@ var Indexer = class {
|
|
|
2844
2708
|
for (const [k, v] of this.fileHashCache) {
|
|
2845
2709
|
obj[k] = v;
|
|
2846
2710
|
}
|
|
2847
|
-
(0,
|
|
2711
|
+
(0, import_fs3.writeFileSync)(this.fileHashCachePath, JSON.stringify(obj));
|
|
2712
|
+
}
|
|
2713
|
+
loadFailedBatches() {
|
|
2714
|
+
try {
|
|
2715
|
+
if ((0, import_fs3.existsSync)(this.failedBatchesPath)) {
|
|
2716
|
+
const data = (0, import_fs3.readFileSync)(this.failedBatchesPath, "utf-8");
|
|
2717
|
+
return JSON.parse(data);
|
|
2718
|
+
}
|
|
2719
|
+
} catch {
|
|
2720
|
+
return [];
|
|
2721
|
+
}
|
|
2722
|
+
return [];
|
|
2723
|
+
}
|
|
2724
|
+
saveFailedBatches(batches) {
|
|
2725
|
+
if (batches.length === 0) {
|
|
2726
|
+
if ((0, import_fs3.existsSync)(this.failedBatchesPath)) {
|
|
2727
|
+
import_fs3.promises.unlink(this.failedBatchesPath).catch(() => {
|
|
2728
|
+
});
|
|
2729
|
+
}
|
|
2730
|
+
return;
|
|
2731
|
+
}
|
|
2732
|
+
(0, import_fs3.writeFileSync)(this.failedBatchesPath, JSON.stringify(batches, null, 2));
|
|
2733
|
+
}
|
|
2734
|
+
addFailedBatch(batch, error) {
|
|
2735
|
+
const existing = this.loadFailedBatches();
|
|
2736
|
+
existing.push({
|
|
2737
|
+
chunks: batch,
|
|
2738
|
+
error,
|
|
2739
|
+
attemptCount: 1,
|
|
2740
|
+
lastAttempt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2741
|
+
});
|
|
2742
|
+
this.saveFailedBatches(existing);
|
|
2848
2743
|
}
|
|
2849
2744
|
async initialize() {
|
|
2850
2745
|
this.detectedProvider = await detectEmbeddingProvider(this.config.embeddingProvider);
|
|
@@ -2857,15 +2752,16 @@ var Indexer = class {
|
|
|
2857
2752
|
this.detectedProvider.credentials,
|
|
2858
2753
|
this.detectedProvider.modelInfo
|
|
2859
2754
|
);
|
|
2860
|
-
await
|
|
2755
|
+
await import_fs3.promises.mkdir(this.indexPath, { recursive: true });
|
|
2861
2756
|
const dimensions = this.detectedProvider.modelInfo.dimensions;
|
|
2862
|
-
const storePath =
|
|
2757
|
+
const storePath = path4.join(this.indexPath, "vectors");
|
|
2863
2758
|
this.store = new VectorStore(storePath, dimensions);
|
|
2864
|
-
const indexFilePath =
|
|
2865
|
-
if ((0,
|
|
2759
|
+
const indexFilePath = path4.join(this.indexPath, "vectors.usearch");
|
|
2760
|
+
if ((0, import_fs3.existsSync)(indexFilePath)) {
|
|
2866
2761
|
this.store.load();
|
|
2867
2762
|
}
|
|
2868
|
-
|
|
2763
|
+
const invertedIndexPath = path4.join(this.indexPath, "inverted-index.json");
|
|
2764
|
+
this.invertedIndex = new InvertedIndex(invertedIndexPath);
|
|
2869
2765
|
this.invertedIndex.load();
|
|
2870
2766
|
}
|
|
2871
2767
|
async ensureInitialized() {
|
|
@@ -2929,7 +2825,7 @@ var Indexer = class {
|
|
|
2929
2825
|
if (this.fileHashCache.get(f.path) === currentHash) {
|
|
2930
2826
|
unchangedFilePaths.add(f.path);
|
|
2931
2827
|
} else {
|
|
2932
|
-
const content = await
|
|
2828
|
+
const content = await import_fs3.promises.readFile(f.path, "utf-8");
|
|
2933
2829
|
changedFiles.push({ path: f.path, content, hash: currentHash });
|
|
2934
2830
|
}
|
|
2935
2831
|
}
|
|
@@ -2964,14 +2860,22 @@ var Indexer = class {
|
|
|
2964
2860
|
for (const parsed of parsedFiles) {
|
|
2965
2861
|
currentFilePaths.add(parsed.path);
|
|
2966
2862
|
if (parsed.chunks.length === 0) {
|
|
2967
|
-
const relativePath =
|
|
2863
|
+
const relativePath = path4.relative(this.projectRoot, parsed.path);
|
|
2968
2864
|
stats.parseFailures.push(relativePath);
|
|
2969
2865
|
}
|
|
2866
|
+
let fileChunkCount = 0;
|
|
2970
2867
|
for (const chunk of parsed.chunks) {
|
|
2868
|
+
if (fileChunkCount >= this.config.indexing.maxChunksPerFile) {
|
|
2869
|
+
break;
|
|
2870
|
+
}
|
|
2871
|
+
if (this.config.indexing.semanticOnly && chunk.chunkType === "other") {
|
|
2872
|
+
continue;
|
|
2873
|
+
}
|
|
2971
2874
|
const id = generateChunkId(parsed.path, chunk);
|
|
2972
2875
|
const contentHash = generateChunkHash(chunk);
|
|
2973
2876
|
currentChunkIds.add(id);
|
|
2974
2877
|
if (existingChunks.get(id) === contentHash) {
|
|
2878
|
+
fileChunkCount++;
|
|
2975
2879
|
continue;
|
|
2976
2880
|
}
|
|
2977
2881
|
const text = createEmbeddingText(chunk, parsed.path);
|
|
@@ -2985,6 +2889,7 @@ var Indexer = class {
|
|
|
2985
2889
|
hash: contentHash
|
|
2986
2890
|
};
|
|
2987
2891
|
pendingChunks.push({ id, text, content: chunk.content, metadata });
|
|
2892
|
+
fileChunkCount++;
|
|
2988
2893
|
}
|
|
2989
2894
|
}
|
|
2990
2895
|
let removedCount = 0;
|
|
@@ -3074,6 +2979,7 @@ var Indexer = class {
|
|
|
3074
2979
|
});
|
|
3075
2980
|
} catch (error) {
|
|
3076
2981
|
stats.failedChunks += batch.length;
|
|
2982
|
+
this.addFailedBatch(batch, String(error));
|
|
3077
2983
|
console.error(`Failed to embed batch after retries: ${error}`);
|
|
3078
2984
|
}
|
|
3079
2985
|
});
|
|
@@ -3091,6 +2997,9 @@ var Indexer = class {
|
|
|
3091
2997
|
this.fileHashCache = currentFileHashes;
|
|
3092
2998
|
this.saveFileHashCache();
|
|
3093
2999
|
stats.durationMs = Date.now() - startTime;
|
|
3000
|
+
if (stats.failedChunks > 0) {
|
|
3001
|
+
stats.failedBatchesPath = this.failedBatchesPath;
|
|
3002
|
+
}
|
|
3094
3003
|
onProgress?.({
|
|
3095
3004
|
phase: "complete",
|
|
3096
3005
|
filesProcessed: files.length,
|
|
@@ -3133,7 +3042,7 @@ var Indexer = class {
|
|
|
3133
3042
|
let contextEndLine = r.metadata.endLine;
|
|
3134
3043
|
if (this.config.search.includeContext) {
|
|
3135
3044
|
try {
|
|
3136
|
-
const fileContent = await
|
|
3045
|
+
const fileContent = await import_fs3.promises.readFile(
|
|
3137
3046
|
r.metadata.filePath,
|
|
3138
3047
|
"utf-8"
|
|
3139
3048
|
);
|
|
@@ -3236,7 +3145,7 @@ var Indexer = class {
|
|
|
3236
3145
|
const removedFilePaths = [];
|
|
3237
3146
|
let removedCount = 0;
|
|
3238
3147
|
for (const [filePath, chunkKeys] of filePathsToChunkKeys) {
|
|
3239
|
-
if (!(0,
|
|
3148
|
+
if (!(0, import_fs3.existsSync)(filePath)) {
|
|
3240
3149
|
for (const key of chunkKeys) {
|
|
3241
3150
|
store.remove(key);
|
|
3242
3151
|
invertedIndex.removeChunk(key);
|
|
@@ -3251,6 +3160,58 @@ var Indexer = class {
|
|
|
3251
3160
|
}
|
|
3252
3161
|
return { removed: removedCount, filePaths: removedFilePaths };
|
|
3253
3162
|
}
|
|
3163
|
+
async retryFailedBatches() {
|
|
3164
|
+
const { store, provider, invertedIndex } = await this.ensureInitialized();
|
|
3165
|
+
const failedBatches = this.loadFailedBatches();
|
|
3166
|
+
if (failedBatches.length === 0) {
|
|
3167
|
+
return { succeeded: 0, failed: 0, remaining: 0 };
|
|
3168
|
+
}
|
|
3169
|
+
let succeeded = 0;
|
|
3170
|
+
let failed = 0;
|
|
3171
|
+
const stillFailing = [];
|
|
3172
|
+
for (const batch of failedBatches) {
|
|
3173
|
+
try {
|
|
3174
|
+
const result = await pRetry(
|
|
3175
|
+
async () => {
|
|
3176
|
+
const texts = batch.chunks.map((c) => c.text);
|
|
3177
|
+
return provider.embedBatch(texts);
|
|
3178
|
+
},
|
|
3179
|
+
{
|
|
3180
|
+
retries: this.config.indexing.retries,
|
|
3181
|
+
minTimeout: this.config.indexing.retryDelayMs
|
|
3182
|
+
}
|
|
3183
|
+
);
|
|
3184
|
+
const items = batch.chunks.map((chunk, idx) => ({
|
|
3185
|
+
id: chunk.id,
|
|
3186
|
+
vector: result.embeddings[idx],
|
|
3187
|
+
metadata: chunk.metadata
|
|
3188
|
+
}));
|
|
3189
|
+
store.addBatch(items);
|
|
3190
|
+
for (const chunk of batch.chunks) {
|
|
3191
|
+
invertedIndex.removeChunk(chunk.id);
|
|
3192
|
+
invertedIndex.addChunk(chunk.id, chunk.content);
|
|
3193
|
+
}
|
|
3194
|
+
succeeded += batch.chunks.length;
|
|
3195
|
+
} catch (error) {
|
|
3196
|
+
failed += batch.chunks.length;
|
|
3197
|
+
stillFailing.push({
|
|
3198
|
+
...batch,
|
|
3199
|
+
attemptCount: batch.attemptCount + 1,
|
|
3200
|
+
lastAttempt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3201
|
+
error: String(error)
|
|
3202
|
+
});
|
|
3203
|
+
}
|
|
3204
|
+
}
|
|
3205
|
+
this.saveFailedBatches(stillFailing);
|
|
3206
|
+
if (succeeded > 0) {
|
|
3207
|
+
store.save();
|
|
3208
|
+
invertedIndex.save();
|
|
3209
|
+
}
|
|
3210
|
+
return { succeeded, failed, remaining: stillFailing.length };
|
|
3211
|
+
}
|
|
3212
|
+
getFailedBatchesCount() {
|
|
3213
|
+
return this.loadFailedBatches().length;
|
|
3214
|
+
}
|
|
3254
3215
|
};
|
|
3255
3216
|
|
|
3256
3217
|
// node_modules/chokidar/index.js
|
|
@@ -3343,7 +3304,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
3343
3304
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
3344
3305
|
const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
|
|
3345
3306
|
if (wantBigintFsStats) {
|
|
3346
|
-
this._stat = (
|
|
3307
|
+
this._stat = (path7) => statMethod(path7, { bigint: true });
|
|
3347
3308
|
} else {
|
|
3348
3309
|
this._stat = statMethod;
|
|
3349
3310
|
}
|
|
@@ -3368,8 +3329,8 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
3368
3329
|
const par = this.parent;
|
|
3369
3330
|
const fil = par && par.files;
|
|
3370
3331
|
if (fil && fil.length > 0) {
|
|
3371
|
-
const { path:
|
|
3372
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
3332
|
+
const { path: path7, depth } = par;
|
|
3333
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path7));
|
|
3373
3334
|
const awaited = await Promise.all(slice);
|
|
3374
3335
|
for (const entry of awaited) {
|
|
3375
3336
|
if (!entry)
|
|
@@ -3409,20 +3370,20 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
3409
3370
|
this.reading = false;
|
|
3410
3371
|
}
|
|
3411
3372
|
}
|
|
3412
|
-
async _exploreDir(
|
|
3373
|
+
async _exploreDir(path7, depth) {
|
|
3413
3374
|
let files;
|
|
3414
3375
|
try {
|
|
3415
|
-
files = await (0, import_promises.readdir)(
|
|
3376
|
+
files = await (0, import_promises.readdir)(path7, this._rdOptions);
|
|
3416
3377
|
} catch (error) {
|
|
3417
3378
|
this._onError(error);
|
|
3418
3379
|
}
|
|
3419
|
-
return { files, depth, path:
|
|
3380
|
+
return { files, depth, path: path7 };
|
|
3420
3381
|
}
|
|
3421
|
-
async _formatEntry(dirent,
|
|
3382
|
+
async _formatEntry(dirent, path7) {
|
|
3422
3383
|
let entry;
|
|
3423
3384
|
const basename3 = this._isDirent ? dirent.name : dirent;
|
|
3424
3385
|
try {
|
|
3425
|
-
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(
|
|
3386
|
+
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path7, basename3));
|
|
3426
3387
|
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename3 };
|
|
3427
3388
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
3428
3389
|
} catch (err) {
|
|
@@ -3822,16 +3783,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
3822
3783
|
};
|
|
3823
3784
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
3824
3785
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
3825
|
-
function createFsWatchInstance(
|
|
3786
|
+
function createFsWatchInstance(path7, options, listener, errHandler, emitRaw) {
|
|
3826
3787
|
const handleEvent = (rawEvent, evPath) => {
|
|
3827
|
-
listener(
|
|
3828
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
3829
|
-
if (evPath &&
|
|
3830
|
-
fsWatchBroadcast(sp.resolve(
|
|
3788
|
+
listener(path7);
|
|
3789
|
+
emitRaw(rawEvent, evPath, { watchedPath: path7 });
|
|
3790
|
+
if (evPath && path7 !== evPath) {
|
|
3791
|
+
fsWatchBroadcast(sp.resolve(path7, evPath), KEY_LISTENERS, sp.join(path7, evPath));
|
|
3831
3792
|
}
|
|
3832
3793
|
};
|
|
3833
3794
|
try {
|
|
3834
|
-
return (0, import_node_fs.watch)(
|
|
3795
|
+
return (0, import_node_fs.watch)(path7, {
|
|
3835
3796
|
persistent: options.persistent
|
|
3836
3797
|
}, handleEvent);
|
|
3837
3798
|
} catch (error) {
|
|
@@ -3847,12 +3808,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
3847
3808
|
listener(val1, val2, val3);
|
|
3848
3809
|
});
|
|
3849
3810
|
};
|
|
3850
|
-
var setFsWatchListener = (
|
|
3811
|
+
var setFsWatchListener = (path7, fullPath, options, handlers) => {
|
|
3851
3812
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
3852
3813
|
let cont = FsWatchInstances.get(fullPath);
|
|
3853
3814
|
let watcher;
|
|
3854
3815
|
if (!options.persistent) {
|
|
3855
|
-
watcher = createFsWatchInstance(
|
|
3816
|
+
watcher = createFsWatchInstance(path7, options, listener, errHandler, rawEmitter);
|
|
3856
3817
|
if (!watcher)
|
|
3857
3818
|
return;
|
|
3858
3819
|
return watcher.close.bind(watcher);
|
|
@@ -3863,7 +3824,7 @@ var setFsWatchListener = (path9, fullPath, options, handlers) => {
|
|
|
3863
3824
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
3864
3825
|
} else {
|
|
3865
3826
|
watcher = createFsWatchInstance(
|
|
3866
|
-
|
|
3827
|
+
path7,
|
|
3867
3828
|
options,
|
|
3868
3829
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
3869
3830
|
errHandler,
|
|
@@ -3878,7 +3839,7 @@ var setFsWatchListener = (path9, fullPath, options, handlers) => {
|
|
|
3878
3839
|
cont.watcherUnusable = true;
|
|
3879
3840
|
if (isWindows && error.code === "EPERM") {
|
|
3880
3841
|
try {
|
|
3881
|
-
const fd = await (0, import_promises2.open)(
|
|
3842
|
+
const fd = await (0, import_promises2.open)(path7, "r");
|
|
3882
3843
|
await fd.close();
|
|
3883
3844
|
broadcastErr(error);
|
|
3884
3845
|
} catch (err) {
|
|
@@ -3909,7 +3870,7 @@ var setFsWatchListener = (path9, fullPath, options, handlers) => {
|
|
|
3909
3870
|
};
|
|
3910
3871
|
};
|
|
3911
3872
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
3912
|
-
var setFsWatchFileListener = (
|
|
3873
|
+
var setFsWatchFileListener = (path7, fullPath, options, handlers) => {
|
|
3913
3874
|
const { listener, rawEmitter } = handlers;
|
|
3914
3875
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
3915
3876
|
const copts = cont && cont.options;
|
|
@@ -3931,7 +3892,7 @@ var setFsWatchFileListener = (path9, fullPath, options, handlers) => {
|
|
|
3931
3892
|
});
|
|
3932
3893
|
const currmtime = curr.mtimeMs;
|
|
3933
3894
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
3934
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
3895
|
+
foreach(cont.listeners, (listener2) => listener2(path7, curr));
|
|
3935
3896
|
}
|
|
3936
3897
|
})
|
|
3937
3898
|
};
|
|
@@ -3961,13 +3922,13 @@ var NodeFsHandler = class {
|
|
|
3961
3922
|
* @param listener on fs change
|
|
3962
3923
|
* @returns closer for the watcher instance
|
|
3963
3924
|
*/
|
|
3964
|
-
_watchWithNodeFs(
|
|
3925
|
+
_watchWithNodeFs(path7, listener) {
|
|
3965
3926
|
const opts = this.fsw.options;
|
|
3966
|
-
const directory = sp.dirname(
|
|
3967
|
-
const basename3 = sp.basename(
|
|
3927
|
+
const directory = sp.dirname(path7);
|
|
3928
|
+
const basename3 = sp.basename(path7);
|
|
3968
3929
|
const parent = this.fsw._getWatchedDir(directory);
|
|
3969
3930
|
parent.add(basename3);
|
|
3970
|
-
const absolutePath = sp.resolve(
|
|
3931
|
+
const absolutePath = sp.resolve(path7);
|
|
3971
3932
|
const options = {
|
|
3972
3933
|
persistent: opts.persistent
|
|
3973
3934
|
};
|
|
@@ -3977,12 +3938,12 @@ var NodeFsHandler = class {
|
|
|
3977
3938
|
if (opts.usePolling) {
|
|
3978
3939
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
3979
3940
|
options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
|
|
3980
|
-
closer = setFsWatchFileListener(
|
|
3941
|
+
closer = setFsWatchFileListener(path7, absolutePath, options, {
|
|
3981
3942
|
listener,
|
|
3982
3943
|
rawEmitter: this.fsw._emitRaw
|
|
3983
3944
|
});
|
|
3984
3945
|
} else {
|
|
3985
|
-
closer = setFsWatchListener(
|
|
3946
|
+
closer = setFsWatchListener(path7, absolutePath, options, {
|
|
3986
3947
|
listener,
|
|
3987
3948
|
errHandler: this._boundHandleError,
|
|
3988
3949
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -4004,7 +3965,7 @@ var NodeFsHandler = class {
|
|
|
4004
3965
|
let prevStats = stats;
|
|
4005
3966
|
if (parent.has(basename3))
|
|
4006
3967
|
return;
|
|
4007
|
-
const listener = async (
|
|
3968
|
+
const listener = async (path7, newStats) => {
|
|
4008
3969
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
4009
3970
|
return;
|
|
4010
3971
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -4018,11 +3979,11 @@ var NodeFsHandler = class {
|
|
|
4018
3979
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
4019
3980
|
}
|
|
4020
3981
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
4021
|
-
this.fsw._closeFile(
|
|
3982
|
+
this.fsw._closeFile(path7);
|
|
4022
3983
|
prevStats = newStats2;
|
|
4023
3984
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
4024
3985
|
if (closer2)
|
|
4025
|
-
this.fsw._addPathCloser(
|
|
3986
|
+
this.fsw._addPathCloser(path7, closer2);
|
|
4026
3987
|
} else {
|
|
4027
3988
|
prevStats = newStats2;
|
|
4028
3989
|
}
|
|
@@ -4054,7 +4015,7 @@ var NodeFsHandler = class {
|
|
|
4054
4015
|
* @param item basename of this item
|
|
4055
4016
|
* @returns true if no more processing is needed for this entry.
|
|
4056
4017
|
*/
|
|
4057
|
-
async _handleSymlink(entry, directory,
|
|
4018
|
+
async _handleSymlink(entry, directory, path7, item) {
|
|
4058
4019
|
if (this.fsw.closed) {
|
|
4059
4020
|
return;
|
|
4060
4021
|
}
|
|
@@ -4064,7 +4025,7 @@ var NodeFsHandler = class {
|
|
|
4064
4025
|
this.fsw._incrReadyCount();
|
|
4065
4026
|
let linkPath;
|
|
4066
4027
|
try {
|
|
4067
|
-
linkPath = await (0, import_promises2.realpath)(
|
|
4028
|
+
linkPath = await (0, import_promises2.realpath)(path7);
|
|
4068
4029
|
} catch (e) {
|
|
4069
4030
|
this.fsw._emitReady();
|
|
4070
4031
|
return true;
|
|
@@ -4074,12 +4035,12 @@ var NodeFsHandler = class {
|
|
|
4074
4035
|
if (dir.has(item)) {
|
|
4075
4036
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
4076
4037
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
4077
|
-
this.fsw._emit(EV.CHANGE,
|
|
4038
|
+
this.fsw._emit(EV.CHANGE, path7, entry.stats);
|
|
4078
4039
|
}
|
|
4079
4040
|
} else {
|
|
4080
4041
|
dir.add(item);
|
|
4081
4042
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
4082
|
-
this.fsw._emit(EV.ADD,
|
|
4043
|
+
this.fsw._emit(EV.ADD, path7, entry.stats);
|
|
4083
4044
|
}
|
|
4084
4045
|
this.fsw._emitReady();
|
|
4085
4046
|
return true;
|
|
@@ -4109,9 +4070,9 @@ var NodeFsHandler = class {
|
|
|
4109
4070
|
return;
|
|
4110
4071
|
}
|
|
4111
4072
|
const item = entry.path;
|
|
4112
|
-
let
|
|
4073
|
+
let path7 = sp.join(directory, item);
|
|
4113
4074
|
current.add(item);
|
|
4114
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
4075
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path7, item)) {
|
|
4115
4076
|
return;
|
|
4116
4077
|
}
|
|
4117
4078
|
if (this.fsw.closed) {
|
|
@@ -4120,8 +4081,8 @@ var NodeFsHandler = class {
|
|
|
4120
4081
|
}
|
|
4121
4082
|
if (item === target || !target && !previous.has(item)) {
|
|
4122
4083
|
this.fsw._incrReadyCount();
|
|
4123
|
-
|
|
4124
|
-
this._addToNodeFs(
|
|
4084
|
+
path7 = sp.join(dir, sp.relative(dir, path7));
|
|
4085
|
+
this._addToNodeFs(path7, initialAdd, wh, depth + 1);
|
|
4125
4086
|
}
|
|
4126
4087
|
}).on(EV.ERROR, this._boundHandleError);
|
|
4127
4088
|
return new Promise((resolve4, reject) => {
|
|
@@ -4190,13 +4151,13 @@ var NodeFsHandler = class {
|
|
|
4190
4151
|
* @param depth Child path actually targeted for watch
|
|
4191
4152
|
* @param target Child path actually targeted for watch
|
|
4192
4153
|
*/
|
|
4193
|
-
async _addToNodeFs(
|
|
4154
|
+
async _addToNodeFs(path7, initialAdd, priorWh, depth, target) {
|
|
4194
4155
|
const ready = this.fsw._emitReady;
|
|
4195
|
-
if (this.fsw._isIgnored(
|
|
4156
|
+
if (this.fsw._isIgnored(path7) || this.fsw.closed) {
|
|
4196
4157
|
ready();
|
|
4197
4158
|
return false;
|
|
4198
4159
|
}
|
|
4199
|
-
const wh = this.fsw._getWatchHelpers(
|
|
4160
|
+
const wh = this.fsw._getWatchHelpers(path7);
|
|
4200
4161
|
if (priorWh) {
|
|
4201
4162
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
4202
4163
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -4212,8 +4173,8 @@ var NodeFsHandler = class {
|
|
|
4212
4173
|
const follow = this.fsw.options.followSymlinks;
|
|
4213
4174
|
let closer;
|
|
4214
4175
|
if (stats.isDirectory()) {
|
|
4215
|
-
const absPath = sp.resolve(
|
|
4216
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
4176
|
+
const absPath = sp.resolve(path7);
|
|
4177
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path7) : path7;
|
|
4217
4178
|
if (this.fsw.closed)
|
|
4218
4179
|
return;
|
|
4219
4180
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -4223,29 +4184,29 @@ var NodeFsHandler = class {
|
|
|
4223
4184
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
4224
4185
|
}
|
|
4225
4186
|
} else if (stats.isSymbolicLink()) {
|
|
4226
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
4187
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path7) : path7;
|
|
4227
4188
|
if (this.fsw.closed)
|
|
4228
4189
|
return;
|
|
4229
4190
|
const parent = sp.dirname(wh.watchPath);
|
|
4230
4191
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
4231
4192
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
4232
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
4193
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path7, wh, targetPath);
|
|
4233
4194
|
if (this.fsw.closed)
|
|
4234
4195
|
return;
|
|
4235
4196
|
if (targetPath !== void 0) {
|
|
4236
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
4197
|
+
this.fsw._symlinkPaths.set(sp.resolve(path7), targetPath);
|
|
4237
4198
|
}
|
|
4238
4199
|
} else {
|
|
4239
4200
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
4240
4201
|
}
|
|
4241
4202
|
ready();
|
|
4242
4203
|
if (closer)
|
|
4243
|
-
this.fsw._addPathCloser(
|
|
4204
|
+
this.fsw._addPathCloser(path7, closer);
|
|
4244
4205
|
return false;
|
|
4245
4206
|
} catch (error) {
|
|
4246
4207
|
if (this.fsw._handleError(error)) {
|
|
4247
4208
|
ready();
|
|
4248
|
-
return
|
|
4209
|
+
return path7;
|
|
4249
4210
|
}
|
|
4250
4211
|
}
|
|
4251
4212
|
}
|
|
@@ -4288,24 +4249,24 @@ function createPattern(matcher) {
|
|
|
4288
4249
|
}
|
|
4289
4250
|
return () => false;
|
|
4290
4251
|
}
|
|
4291
|
-
function normalizePath(
|
|
4292
|
-
if (typeof
|
|
4252
|
+
function normalizePath(path7) {
|
|
4253
|
+
if (typeof path7 !== "string")
|
|
4293
4254
|
throw new Error("string expected");
|
|
4294
|
-
|
|
4295
|
-
|
|
4255
|
+
path7 = sp2.normalize(path7);
|
|
4256
|
+
path7 = path7.replace(/\\/g, "/");
|
|
4296
4257
|
let prepend = false;
|
|
4297
|
-
if (
|
|
4258
|
+
if (path7.startsWith("//"))
|
|
4298
4259
|
prepend = true;
|
|
4299
|
-
|
|
4260
|
+
path7 = path7.replace(DOUBLE_SLASH_RE, "/");
|
|
4300
4261
|
if (prepend)
|
|
4301
|
-
|
|
4302
|
-
return
|
|
4262
|
+
path7 = "/" + path7;
|
|
4263
|
+
return path7;
|
|
4303
4264
|
}
|
|
4304
4265
|
function matchPatterns(patterns, testString, stats) {
|
|
4305
|
-
const
|
|
4266
|
+
const path7 = normalizePath(testString);
|
|
4306
4267
|
for (let index = 0; index < patterns.length; index++) {
|
|
4307
4268
|
const pattern = patterns[index];
|
|
4308
|
-
if (pattern(
|
|
4269
|
+
if (pattern(path7, stats)) {
|
|
4309
4270
|
return true;
|
|
4310
4271
|
}
|
|
4311
4272
|
}
|
|
@@ -4343,19 +4304,19 @@ var toUnix = (string) => {
|
|
|
4343
4304
|
}
|
|
4344
4305
|
return str;
|
|
4345
4306
|
};
|
|
4346
|
-
var normalizePathToUnix = (
|
|
4347
|
-
var normalizeIgnored = (cwd = "") => (
|
|
4348
|
-
if (typeof
|
|
4349
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
4307
|
+
var normalizePathToUnix = (path7) => toUnix(sp2.normalize(toUnix(path7)));
|
|
4308
|
+
var normalizeIgnored = (cwd = "") => (path7) => {
|
|
4309
|
+
if (typeof path7 === "string") {
|
|
4310
|
+
return normalizePathToUnix(sp2.isAbsolute(path7) ? path7 : sp2.join(cwd, path7));
|
|
4350
4311
|
} else {
|
|
4351
|
-
return
|
|
4312
|
+
return path7;
|
|
4352
4313
|
}
|
|
4353
4314
|
};
|
|
4354
|
-
var getAbsolutePath = (
|
|
4355
|
-
if (sp2.isAbsolute(
|
|
4356
|
-
return
|
|
4315
|
+
var getAbsolutePath = (path7, cwd) => {
|
|
4316
|
+
if (sp2.isAbsolute(path7)) {
|
|
4317
|
+
return path7;
|
|
4357
4318
|
}
|
|
4358
|
-
return sp2.join(cwd,
|
|
4319
|
+
return sp2.join(cwd, path7);
|
|
4359
4320
|
};
|
|
4360
4321
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
4361
4322
|
var DirEntry = class {
|
|
@@ -4420,10 +4381,10 @@ var WatchHelper = class {
|
|
|
4420
4381
|
dirParts;
|
|
4421
4382
|
followSymlinks;
|
|
4422
4383
|
statMethod;
|
|
4423
|
-
constructor(
|
|
4384
|
+
constructor(path7, follow, fsw) {
|
|
4424
4385
|
this.fsw = fsw;
|
|
4425
|
-
const watchPath =
|
|
4426
|
-
this.path =
|
|
4386
|
+
const watchPath = path7;
|
|
4387
|
+
this.path = path7 = path7.replace(REPLACER_RE, "");
|
|
4427
4388
|
this.watchPath = watchPath;
|
|
4428
4389
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
4429
4390
|
this.dirParts = [];
|
|
@@ -4563,20 +4524,20 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
4563
4524
|
this._closePromise = void 0;
|
|
4564
4525
|
let paths = unifyPaths(paths_);
|
|
4565
4526
|
if (cwd) {
|
|
4566
|
-
paths = paths.map((
|
|
4567
|
-
const absPath = getAbsolutePath(
|
|
4527
|
+
paths = paths.map((path7) => {
|
|
4528
|
+
const absPath = getAbsolutePath(path7, cwd);
|
|
4568
4529
|
return absPath;
|
|
4569
4530
|
});
|
|
4570
4531
|
}
|
|
4571
|
-
paths.forEach((
|
|
4572
|
-
this._removeIgnoredPath(
|
|
4532
|
+
paths.forEach((path7) => {
|
|
4533
|
+
this._removeIgnoredPath(path7);
|
|
4573
4534
|
});
|
|
4574
4535
|
this._userIgnored = void 0;
|
|
4575
4536
|
if (!this._readyCount)
|
|
4576
4537
|
this._readyCount = 0;
|
|
4577
4538
|
this._readyCount += paths.length;
|
|
4578
|
-
Promise.all(paths.map(async (
|
|
4579
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
4539
|
+
Promise.all(paths.map(async (path7) => {
|
|
4540
|
+
const res = await this._nodeFsHandler._addToNodeFs(path7, !_internal, void 0, 0, _origAdd);
|
|
4580
4541
|
if (res)
|
|
4581
4542
|
this._emitReady();
|
|
4582
4543
|
return res;
|
|
@@ -4598,17 +4559,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
4598
4559
|
return this;
|
|
4599
4560
|
const paths = unifyPaths(paths_);
|
|
4600
4561
|
const { cwd } = this.options;
|
|
4601
|
-
paths.forEach((
|
|
4602
|
-
if (!sp2.isAbsolute(
|
|
4562
|
+
paths.forEach((path7) => {
|
|
4563
|
+
if (!sp2.isAbsolute(path7) && !this._closers.has(path7)) {
|
|
4603
4564
|
if (cwd)
|
|
4604
|
-
|
|
4605
|
-
|
|
4565
|
+
path7 = sp2.join(cwd, path7);
|
|
4566
|
+
path7 = sp2.resolve(path7);
|
|
4606
4567
|
}
|
|
4607
|
-
this._closePath(
|
|
4608
|
-
this._addIgnoredPath(
|
|
4609
|
-
if (this._watched.has(
|
|
4568
|
+
this._closePath(path7);
|
|
4569
|
+
this._addIgnoredPath(path7);
|
|
4570
|
+
if (this._watched.has(path7)) {
|
|
4610
4571
|
this._addIgnoredPath({
|
|
4611
|
-
path:
|
|
4572
|
+
path: path7,
|
|
4612
4573
|
recursive: true
|
|
4613
4574
|
});
|
|
4614
4575
|
}
|
|
@@ -4672,38 +4633,38 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
4672
4633
|
* @param stats arguments to be passed with event
|
|
4673
4634
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
4674
4635
|
*/
|
|
4675
|
-
async _emit(event,
|
|
4636
|
+
async _emit(event, path7, stats) {
|
|
4676
4637
|
if (this.closed)
|
|
4677
4638
|
return;
|
|
4678
4639
|
const opts = this.options;
|
|
4679
4640
|
if (isWindows)
|
|
4680
|
-
|
|
4641
|
+
path7 = sp2.normalize(path7);
|
|
4681
4642
|
if (opts.cwd)
|
|
4682
|
-
|
|
4683
|
-
const args = [
|
|
4643
|
+
path7 = sp2.relative(opts.cwd, path7);
|
|
4644
|
+
const args = [path7];
|
|
4684
4645
|
if (stats != null)
|
|
4685
4646
|
args.push(stats);
|
|
4686
4647
|
const awf = opts.awaitWriteFinish;
|
|
4687
4648
|
let pw;
|
|
4688
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
4649
|
+
if (awf && (pw = this._pendingWrites.get(path7))) {
|
|
4689
4650
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
4690
4651
|
return this;
|
|
4691
4652
|
}
|
|
4692
4653
|
if (opts.atomic) {
|
|
4693
4654
|
if (event === EVENTS.UNLINK) {
|
|
4694
|
-
this._pendingUnlinks.set(
|
|
4655
|
+
this._pendingUnlinks.set(path7, [event, ...args]);
|
|
4695
4656
|
setTimeout(() => {
|
|
4696
|
-
this._pendingUnlinks.forEach((entry,
|
|
4657
|
+
this._pendingUnlinks.forEach((entry, path8) => {
|
|
4697
4658
|
this.emit(...entry);
|
|
4698
4659
|
this.emit(EVENTS.ALL, ...entry);
|
|
4699
|
-
this._pendingUnlinks.delete(
|
|
4660
|
+
this._pendingUnlinks.delete(path8);
|
|
4700
4661
|
});
|
|
4701
4662
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
4702
4663
|
return this;
|
|
4703
4664
|
}
|
|
4704
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
4665
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path7)) {
|
|
4705
4666
|
event = EVENTS.CHANGE;
|
|
4706
|
-
this._pendingUnlinks.delete(
|
|
4667
|
+
this._pendingUnlinks.delete(path7);
|
|
4707
4668
|
}
|
|
4708
4669
|
}
|
|
4709
4670
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -4721,16 +4682,16 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
4721
4682
|
this.emitWithAll(event, args);
|
|
4722
4683
|
}
|
|
4723
4684
|
};
|
|
4724
|
-
this._awaitWriteFinish(
|
|
4685
|
+
this._awaitWriteFinish(path7, awf.stabilityThreshold, event, awfEmit);
|
|
4725
4686
|
return this;
|
|
4726
4687
|
}
|
|
4727
4688
|
if (event === EVENTS.CHANGE) {
|
|
4728
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
4689
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path7, 50);
|
|
4729
4690
|
if (isThrottled)
|
|
4730
4691
|
return this;
|
|
4731
4692
|
}
|
|
4732
4693
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
4733
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
4694
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path7) : path7;
|
|
4734
4695
|
let stats2;
|
|
4735
4696
|
try {
|
|
4736
4697
|
stats2 = await (0, import_promises3.stat)(fullPath);
|
|
@@ -4761,23 +4722,23 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
4761
4722
|
* @param timeout duration of time to suppress duplicate actions
|
|
4762
4723
|
* @returns tracking object or false if action should be suppressed
|
|
4763
4724
|
*/
|
|
4764
|
-
_throttle(actionType,
|
|
4725
|
+
_throttle(actionType, path7, timeout) {
|
|
4765
4726
|
if (!this._throttled.has(actionType)) {
|
|
4766
4727
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
4767
4728
|
}
|
|
4768
4729
|
const action = this._throttled.get(actionType);
|
|
4769
4730
|
if (!action)
|
|
4770
4731
|
throw new Error("invalid throttle");
|
|
4771
|
-
const actionPath = action.get(
|
|
4732
|
+
const actionPath = action.get(path7);
|
|
4772
4733
|
if (actionPath) {
|
|
4773
4734
|
actionPath.count++;
|
|
4774
4735
|
return false;
|
|
4775
4736
|
}
|
|
4776
4737
|
let timeoutObject;
|
|
4777
4738
|
const clear = () => {
|
|
4778
|
-
const item = action.get(
|
|
4739
|
+
const item = action.get(path7);
|
|
4779
4740
|
const count = item ? item.count : 0;
|
|
4780
|
-
action.delete(
|
|
4741
|
+
action.delete(path7);
|
|
4781
4742
|
clearTimeout(timeoutObject);
|
|
4782
4743
|
if (item)
|
|
4783
4744
|
clearTimeout(item.timeoutObject);
|
|
@@ -4785,7 +4746,7 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
4785
4746
|
};
|
|
4786
4747
|
timeoutObject = setTimeout(clear, timeout);
|
|
4787
4748
|
const thr = { timeoutObject, clear, count: 0 };
|
|
4788
|
-
action.set(
|
|
4749
|
+
action.set(path7, thr);
|
|
4789
4750
|
return thr;
|
|
4790
4751
|
}
|
|
4791
4752
|
_incrReadyCount() {
|
|
@@ -4799,44 +4760,44 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
4799
4760
|
* @param event
|
|
4800
4761
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
4801
4762
|
*/
|
|
4802
|
-
_awaitWriteFinish(
|
|
4763
|
+
_awaitWriteFinish(path7, threshold, event, awfEmit) {
|
|
4803
4764
|
const awf = this.options.awaitWriteFinish;
|
|
4804
4765
|
if (typeof awf !== "object")
|
|
4805
4766
|
return;
|
|
4806
4767
|
const pollInterval = awf.pollInterval;
|
|
4807
4768
|
let timeoutHandler;
|
|
4808
|
-
let fullPath =
|
|
4809
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
4810
|
-
fullPath = sp2.join(this.options.cwd,
|
|
4769
|
+
let fullPath = path7;
|
|
4770
|
+
if (this.options.cwd && !sp2.isAbsolute(path7)) {
|
|
4771
|
+
fullPath = sp2.join(this.options.cwd, path7);
|
|
4811
4772
|
}
|
|
4812
4773
|
const now = /* @__PURE__ */ new Date();
|
|
4813
4774
|
const writes = this._pendingWrites;
|
|
4814
4775
|
function awaitWriteFinishFn(prevStat) {
|
|
4815
4776
|
(0, import_node_fs2.stat)(fullPath, (err, curStat) => {
|
|
4816
|
-
if (err || !writes.has(
|
|
4777
|
+
if (err || !writes.has(path7)) {
|
|
4817
4778
|
if (err && err.code !== "ENOENT")
|
|
4818
4779
|
awfEmit(err);
|
|
4819
4780
|
return;
|
|
4820
4781
|
}
|
|
4821
4782
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
4822
4783
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
4823
|
-
writes.get(
|
|
4784
|
+
writes.get(path7).lastChange = now2;
|
|
4824
4785
|
}
|
|
4825
|
-
const pw = writes.get(
|
|
4786
|
+
const pw = writes.get(path7);
|
|
4826
4787
|
const df = now2 - pw.lastChange;
|
|
4827
4788
|
if (df >= threshold) {
|
|
4828
|
-
writes.delete(
|
|
4789
|
+
writes.delete(path7);
|
|
4829
4790
|
awfEmit(void 0, curStat);
|
|
4830
4791
|
} else {
|
|
4831
4792
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
4832
4793
|
}
|
|
4833
4794
|
});
|
|
4834
4795
|
}
|
|
4835
|
-
if (!writes.has(
|
|
4836
|
-
writes.set(
|
|
4796
|
+
if (!writes.has(path7)) {
|
|
4797
|
+
writes.set(path7, {
|
|
4837
4798
|
lastChange: now,
|
|
4838
4799
|
cancelWait: () => {
|
|
4839
|
-
writes.delete(
|
|
4800
|
+
writes.delete(path7);
|
|
4840
4801
|
clearTimeout(timeoutHandler);
|
|
4841
4802
|
return event;
|
|
4842
4803
|
}
|
|
@@ -4847,8 +4808,8 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
4847
4808
|
/**
|
|
4848
4809
|
* Determines whether user has asked to ignore this path.
|
|
4849
4810
|
*/
|
|
4850
|
-
_isIgnored(
|
|
4851
|
-
if (this.options.atomic && DOT_RE.test(
|
|
4811
|
+
_isIgnored(path7, stats) {
|
|
4812
|
+
if (this.options.atomic && DOT_RE.test(path7))
|
|
4852
4813
|
return true;
|
|
4853
4814
|
if (!this._userIgnored) {
|
|
4854
4815
|
const { cwd } = this.options;
|
|
@@ -4858,17 +4819,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
4858
4819
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
4859
4820
|
this._userIgnored = anymatch(list, void 0);
|
|
4860
4821
|
}
|
|
4861
|
-
return this._userIgnored(
|
|
4822
|
+
return this._userIgnored(path7, stats);
|
|
4862
4823
|
}
|
|
4863
|
-
_isntIgnored(
|
|
4864
|
-
return !this._isIgnored(
|
|
4824
|
+
_isntIgnored(path7, stat4) {
|
|
4825
|
+
return !this._isIgnored(path7, stat4);
|
|
4865
4826
|
}
|
|
4866
4827
|
/**
|
|
4867
4828
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
4868
4829
|
* @param path file or directory pattern being watched
|
|
4869
4830
|
*/
|
|
4870
|
-
_getWatchHelpers(
|
|
4871
|
-
return new WatchHelper(
|
|
4831
|
+
_getWatchHelpers(path7) {
|
|
4832
|
+
return new WatchHelper(path7, this.options.followSymlinks, this);
|
|
4872
4833
|
}
|
|
4873
4834
|
// Directory helpers
|
|
4874
4835
|
// -----------------
|
|
@@ -4900,63 +4861,63 @@ var FSWatcher = class extends import_node_events.EventEmitter {
|
|
|
4900
4861
|
* @param item base path of item/directory
|
|
4901
4862
|
*/
|
|
4902
4863
|
_remove(directory, item, isDirectory) {
|
|
4903
|
-
const
|
|
4904
|
-
const fullPath = sp2.resolve(
|
|
4905
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
4906
|
-
if (!this._throttle("remove",
|
|
4864
|
+
const path7 = sp2.join(directory, item);
|
|
4865
|
+
const fullPath = sp2.resolve(path7);
|
|
4866
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path7) || this._watched.has(fullPath);
|
|
4867
|
+
if (!this._throttle("remove", path7, 100))
|
|
4907
4868
|
return;
|
|
4908
4869
|
if (!isDirectory && this._watched.size === 1) {
|
|
4909
4870
|
this.add(directory, item, true);
|
|
4910
4871
|
}
|
|
4911
|
-
const wp = this._getWatchedDir(
|
|
4872
|
+
const wp = this._getWatchedDir(path7);
|
|
4912
4873
|
const nestedDirectoryChildren = wp.getChildren();
|
|
4913
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
4874
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path7, nested));
|
|
4914
4875
|
const parent = this._getWatchedDir(directory);
|
|
4915
4876
|
const wasTracked = parent.has(item);
|
|
4916
4877
|
parent.remove(item);
|
|
4917
4878
|
if (this._symlinkPaths.has(fullPath)) {
|
|
4918
4879
|
this._symlinkPaths.delete(fullPath);
|
|
4919
4880
|
}
|
|
4920
|
-
let relPath =
|
|
4881
|
+
let relPath = path7;
|
|
4921
4882
|
if (this.options.cwd)
|
|
4922
|
-
relPath = sp2.relative(this.options.cwd,
|
|
4883
|
+
relPath = sp2.relative(this.options.cwd, path7);
|
|
4923
4884
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
4924
4885
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
4925
4886
|
if (event === EVENTS.ADD)
|
|
4926
4887
|
return;
|
|
4927
4888
|
}
|
|
4928
|
-
this._watched.delete(
|
|
4889
|
+
this._watched.delete(path7);
|
|
4929
4890
|
this._watched.delete(fullPath);
|
|
4930
4891
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
4931
|
-
if (wasTracked && !this._isIgnored(
|
|
4932
|
-
this._emit(eventName,
|
|
4933
|
-
this._closePath(
|
|
4892
|
+
if (wasTracked && !this._isIgnored(path7))
|
|
4893
|
+
this._emit(eventName, path7);
|
|
4894
|
+
this._closePath(path7);
|
|
4934
4895
|
}
|
|
4935
4896
|
/**
|
|
4936
4897
|
* Closes all watchers for a path
|
|
4937
4898
|
*/
|
|
4938
|
-
_closePath(
|
|
4939
|
-
this._closeFile(
|
|
4940
|
-
const dir = sp2.dirname(
|
|
4941
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
4899
|
+
_closePath(path7) {
|
|
4900
|
+
this._closeFile(path7);
|
|
4901
|
+
const dir = sp2.dirname(path7);
|
|
4902
|
+
this._getWatchedDir(dir).remove(sp2.basename(path7));
|
|
4942
4903
|
}
|
|
4943
4904
|
/**
|
|
4944
4905
|
* Closes only file-specific watchers
|
|
4945
4906
|
*/
|
|
4946
|
-
_closeFile(
|
|
4947
|
-
const closers = this._closers.get(
|
|
4907
|
+
_closeFile(path7) {
|
|
4908
|
+
const closers = this._closers.get(path7);
|
|
4948
4909
|
if (!closers)
|
|
4949
4910
|
return;
|
|
4950
4911
|
closers.forEach((closer) => closer());
|
|
4951
|
-
this._closers.delete(
|
|
4912
|
+
this._closers.delete(path7);
|
|
4952
4913
|
}
|
|
4953
|
-
_addPathCloser(
|
|
4914
|
+
_addPathCloser(path7, closer) {
|
|
4954
4915
|
if (!closer)
|
|
4955
4916
|
return;
|
|
4956
|
-
let list = this._closers.get(
|
|
4917
|
+
let list = this._closers.get(path7);
|
|
4957
4918
|
if (!list) {
|
|
4958
4919
|
list = [];
|
|
4959
|
-
this._closers.set(
|
|
4920
|
+
this._closers.set(path7, list);
|
|
4960
4921
|
}
|
|
4961
4922
|
list.push(closer);
|
|
4962
4923
|
}
|
|
@@ -4986,7 +4947,7 @@ function watch(paths, options = {}) {
|
|
|
4986
4947
|
var chokidar_default = { watch, FSWatcher };
|
|
4987
4948
|
|
|
4988
4949
|
// src/watcher/index.ts
|
|
4989
|
-
var
|
|
4950
|
+
var path5 = __toESM(require("path"), 1);
|
|
4990
4951
|
var FileWatcher = class {
|
|
4991
4952
|
watcher = null;
|
|
4992
4953
|
projectRoot;
|
|
@@ -5007,7 +4968,7 @@ var FileWatcher = class {
|
|
|
5007
4968
|
const ignoreFilter = createIgnoreFilter(this.projectRoot);
|
|
5008
4969
|
this.watcher = chokidar_default.watch(this.projectRoot, {
|
|
5009
4970
|
ignored: (filePath) => {
|
|
5010
|
-
const relativePath =
|
|
4971
|
+
const relativePath = path5.relative(this.projectRoot, filePath);
|
|
5011
4972
|
if (!relativePath) return false;
|
|
5012
4973
|
if (ignoreFilter.ignores(relativePath)) {
|
|
5013
4974
|
return true;
|
|
@@ -5051,7 +5012,7 @@ var FileWatcher = class {
|
|
|
5051
5012
|
return;
|
|
5052
5013
|
}
|
|
5053
5014
|
const changes = Array.from(this.pendingChanges.entries()).map(
|
|
5054
|
-
([
|
|
5015
|
+
([path7, type]) => ({ path: path7, type })
|
|
5055
5016
|
);
|
|
5056
5017
|
this.pendingChanges.clear();
|
|
5057
5018
|
try {
|
|
@@ -5243,10 +5204,10 @@ function formatStatus(status) {
|
|
|
5243
5204
|
|
|
5244
5205
|
// src/index.ts
|
|
5245
5206
|
function loadPluginConfig(projectRoot) {
|
|
5246
|
-
const configPath =
|
|
5207
|
+
const configPath = path6.join(projectRoot, ".opencode", "codebase-index.json");
|
|
5247
5208
|
try {
|
|
5248
|
-
if ((0,
|
|
5249
|
-
const content = (0,
|
|
5209
|
+
if ((0, import_fs4.existsSync)(configPath)) {
|
|
5210
|
+
const content = (0, import_fs4.readFileSync)(configPath, "utf-8");
|
|
5250
5211
|
return JSON.parse(content);
|
|
5251
5212
|
}
|
|
5252
5213
|
} catch {
|
|
@@ -5275,6 +5236,39 @@ var plugin = async ({ directory }) => {
|
|
|
5275
5236
|
index_codebase,
|
|
5276
5237
|
index_status,
|
|
5277
5238
|
index_health_check
|
|
5239
|
+
},
|
|
5240
|
+
async config(cfg) {
|
|
5241
|
+
cfg.command = cfg.command ?? {};
|
|
5242
|
+
cfg.command["search"] = {
|
|
5243
|
+
description: "Search codebase by meaning using semantic search",
|
|
5244
|
+
template: `Use the \`codebase_search\` tool to find code related to: $ARGUMENTS
|
|
5245
|
+
|
|
5246
|
+
If the index doesn't exist yet, run \`index_codebase\` first.
|
|
5247
|
+
|
|
5248
|
+
Return the most relevant results with file paths and line numbers.`
|
|
5249
|
+
};
|
|
5250
|
+
cfg.command["find"] = {
|
|
5251
|
+
description: "Find code using hybrid approach (semantic + grep)",
|
|
5252
|
+
template: `Find code related to: $ARGUMENTS
|
|
5253
|
+
|
|
5254
|
+
Strategy:
|
|
5255
|
+
1. First use \`codebase_search\` to find semantically related code
|
|
5256
|
+
2. From the results, identify specific function/class names
|
|
5257
|
+
3. Use grep to find all occurrences of those identifiers
|
|
5258
|
+
4. Combine findings into a comprehensive answer
|
|
5259
|
+
|
|
5260
|
+
If the semantic index doesn't exist, run \`index_codebase\` first.`
|
|
5261
|
+
};
|
|
5262
|
+
cfg.command["index"] = {
|
|
5263
|
+
description: "Index the codebase for semantic search",
|
|
5264
|
+
template: `Run the \`index_codebase\` tool to create or update the semantic search index.
|
|
5265
|
+
|
|
5266
|
+
Show progress and final statistics including:
|
|
5267
|
+
- Number of files processed
|
|
5268
|
+
- Number of chunks indexed
|
|
5269
|
+
- Tokens used
|
|
5270
|
+
- Duration`
|
|
5271
|
+
};
|
|
5278
5272
|
}
|
|
5279
5273
|
};
|
|
5280
5274
|
};
|