@wrongstack/tools 0.68.0 → 0.77.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{codebase-stats-tool-C8ApERbn.d.ts → background-indexer-C70RD7LU.d.ts} +81 -1
- package/dist/builtin.js +216 -56
- package/dist/builtin.js.map +1 -1
- package/dist/codebase-index/index.d.ts +35 -4
- package/dist/codebase-index/index.js +267 -13
- package/dist/codebase-index/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +274 -15
- package/dist/index.js.map +1 -1
- package/dist/pack.js +216 -56
- package/dist/pack.js.map +1 -1
- package/dist/todo.js +2 -1
- package/dist/todo.js.map +1 -1
- package/dist/tool-search.js +5 -1
- package/dist/tool-search.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,29 @@
|
|
|
1
|
-
import { d as Symbol, F as FileMeta, e as SymbolKind, f as SymbolLang, c as SearchResult, b as IndexStats, R as Ref } from '../
|
|
2
|
-
export { a as FileSymbols,
|
|
3
|
-
import '@wrongstack/core';
|
|
1
|
+
import { I as IndexResult, d as Symbol, F as FileMeta, e as SymbolKind, f as SymbolLang, c as SearchResult, b as IndexStats, R as Ref } from '../background-indexer-C70RD7LU.js';
|
|
2
|
+
export { a as FileSymbols, S as SCHEMA_VERSION, g as cancelPendingReindexes, h as codebaseIndexTool, i as codebaseSearchTool, j as codebaseStatsTool, k as enqueueReindex, l as getIndexState, m as isIndexReady, n as isIndexableFile, o as isIndexing, p as onIndexStateChange, r as runStartupIndex } from '../background-indexer-C70RD7LU.js';
|
|
3
|
+
import { Context } from '@wrongstack/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Main indexing orchestrator.
|
|
7
|
+
*
|
|
8
|
+
* Given a project root and a list of files:
|
|
9
|
+
* 1. Parse each file with the appropriate parser (TS, Go, Python, Rust, JSON, YAML)
|
|
10
|
+
* 2. Delete old symbols for changed/deleted files
|
|
11
|
+
* 3. Insert new symbols
|
|
12
|
+
* 4. Update file metadata
|
|
13
|
+
* 5. Return index statistics
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
interface IndexerOptions {
|
|
17
|
+
projectRoot: string;
|
|
18
|
+
files?: string[];
|
|
19
|
+
force?: boolean;
|
|
20
|
+
langs?: string[];
|
|
21
|
+
ignore?: string[];
|
|
22
|
+
/** Override the index directory (default: the global per-project dir). */
|
|
23
|
+
indexDir?: string;
|
|
24
|
+
}
|
|
25
|
+
/** Run a full or incremental index and return statistics. */
|
|
26
|
+
declare function runIndexer(_ctx: Context, opts: IndexerOptions): Promise<IndexResult>;
|
|
4
27
|
|
|
5
28
|
/**
|
|
6
29
|
* SQLite storage layer for the codebase index.
|
|
@@ -50,6 +73,14 @@ declare class IndexStore {
|
|
|
50
73
|
id: number;
|
|
51
74
|
text: string;
|
|
52
75
|
}>;
|
|
76
|
+
/**
|
|
77
|
+
* Largest symbol id currently in the table (0 when empty). New ids must be
|
|
78
|
+
* allocated from this, NOT from `COUNT(*)`: incremental reindexes delete a
|
|
79
|
+
* changed file's rows, so the row count drops below the max id and a
|
|
80
|
+
* count-based id would collide with a surviving row (UNIQUE constraint on
|
|
81
|
+
* `symbols.id`). Ids may have gaps — that is fine.
|
|
82
|
+
*/
|
|
83
|
+
getMaxSymbolId(): number;
|
|
53
84
|
getStats(): IndexStats;
|
|
54
85
|
setLastIndexed(ts: number): void;
|
|
55
86
|
clearAll(): void;
|
|
@@ -137,4 +168,4 @@ declare function lspKindToInternalKind(k: number): SymbolKind | null;
|
|
|
137
168
|
*/
|
|
138
169
|
declare function internalKindToLspKind(k: SymbolKind): number | null;
|
|
139
170
|
|
|
140
|
-
export { FileMeta, IndexStats, IndexStore, SearchResult, Symbol, SymbolKind, SymbolLang, buildBm25Index, buildIndexableText, codebaseIndexDirOverride, internalKindToLspKind, lspKindToInternalKind, resolveIndexDir, tokenise };
|
|
171
|
+
export { FileMeta, IndexResult, IndexStats, IndexStore, SearchResult, Symbol, SymbolKind, SymbolLang, buildBm25Index, buildIndexableText, codebaseIndexDirOverride, internalKindToLspKind, lspKindToInternalKind, resolveIndexDir, runIndexer, tokenise };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as fs3 from 'node:fs/promises';
|
|
2
2
|
import * as path4 from 'node:path';
|
|
3
3
|
import { resolveWstackPaths, compileGlob } from '@wrongstack/core';
|
|
4
4
|
import { createRequire } from 'node:module';
|
|
@@ -290,6 +290,17 @@ var IndexStore = class {
|
|
|
290
290
|
({ id, text }) => ({ id, text })
|
|
291
291
|
);
|
|
292
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* Largest symbol id currently in the table (0 when empty). New ids must be
|
|
295
|
+
* allocated from this, NOT from `COUNT(*)`: incremental reindexes delete a
|
|
296
|
+
* changed file's rows, so the row count drops below the max id and a
|
|
297
|
+
* count-based id would collide with a surviving row (UNIQUE constraint on
|
|
298
|
+
* `symbols.id`). Ids may have gaps — that is fine.
|
|
299
|
+
*/
|
|
300
|
+
getMaxSymbolId() {
|
|
301
|
+
const rows = this.db.prepare("SELECT MAX(id) AS m FROM symbols").all();
|
|
302
|
+
return rows[0]?.m ?? 0;
|
|
303
|
+
}
|
|
293
304
|
// ─── Stats ───────────────────────────────────────────────────────────────────
|
|
294
305
|
getStats() {
|
|
295
306
|
const sizeBytes = this.sizeBytes();
|
|
@@ -1608,8 +1619,181 @@ function makeSymbol2(opts) {
|
|
|
1608
1619
|
text: `${opts.name} ${opts.signature}`.trim()
|
|
1609
1620
|
};
|
|
1610
1621
|
}
|
|
1622
|
+
function globBody(glob) {
|
|
1623
|
+
return compileGlob(glob).source.replace(/^\^/, "").replace(/\$$/, "");
|
|
1624
|
+
}
|
|
1625
|
+
function compileGitignore(lines) {
|
|
1626
|
+
const rules = [];
|
|
1627
|
+
for (const raw of lines) {
|
|
1628
|
+
let line = raw.replace(/\r$/, "");
|
|
1629
|
+
if (!line.trim() || line.trimStart().startsWith("#")) continue;
|
|
1630
|
+
line = line.trim();
|
|
1631
|
+
let negated = false;
|
|
1632
|
+
if (line.startsWith("!")) {
|
|
1633
|
+
negated = true;
|
|
1634
|
+
line = line.slice(1);
|
|
1635
|
+
}
|
|
1636
|
+
let dirOnly = false;
|
|
1637
|
+
if (line.endsWith("/")) {
|
|
1638
|
+
dirOnly = true;
|
|
1639
|
+
line = line.slice(0, -1);
|
|
1640
|
+
}
|
|
1641
|
+
if (!line) continue;
|
|
1642
|
+
const anchored = line.startsWith("/") || line.includes("/");
|
|
1643
|
+
if (line.startsWith("/")) line = line.slice(1);
|
|
1644
|
+
const body = globBody(line);
|
|
1645
|
+
const prefix = anchored ? "^" : "(?:^|.*/)";
|
|
1646
|
+
rules.push({
|
|
1647
|
+
eqOrUnder: new RegExp(`${prefix}${body}(?:/.*)?$`),
|
|
1648
|
+
under: new RegExp(`${prefix}${body}/.*$`),
|
|
1649
|
+
negated,
|
|
1650
|
+
dirOnly
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
return (relPath, isDir) => {
|
|
1654
|
+
const p = relPath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
1655
|
+
let ignored = false;
|
|
1656
|
+
for (const r of rules) {
|
|
1657
|
+
const re = r.dirOnly && !isDir ? r.under : r.eqOrUnder;
|
|
1658
|
+
if (re.test(p)) ignored = !r.negated;
|
|
1659
|
+
}
|
|
1660
|
+
return ignored;
|
|
1661
|
+
};
|
|
1662
|
+
}
|
|
1663
|
+
async function loadGitignoreMatcher(projectRoot) {
|
|
1664
|
+
let lines = [];
|
|
1665
|
+
try {
|
|
1666
|
+
const raw = await fs3.readFile(path4.join(projectRoot, ".gitignore"), "utf8");
|
|
1667
|
+
lines = raw.split("\n");
|
|
1668
|
+
} catch {
|
|
1669
|
+
}
|
|
1670
|
+
return compileGitignore(lines);
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
// src/codebase-index/background-indexer.ts
|
|
1674
|
+
var _ready = false;
|
|
1675
|
+
var _indexing = false;
|
|
1676
|
+
var _currentFile = 0;
|
|
1677
|
+
var _totalFiles = 0;
|
|
1678
|
+
var _lastError = null;
|
|
1679
|
+
function isIndexReady() {
|
|
1680
|
+
return _ready;
|
|
1681
|
+
}
|
|
1682
|
+
function setIndexReady() {
|
|
1683
|
+
_ready = true;
|
|
1684
|
+
}
|
|
1685
|
+
function isIndexing() {
|
|
1686
|
+
return _indexing;
|
|
1687
|
+
}
|
|
1688
|
+
function getIndexState() {
|
|
1689
|
+
return {
|
|
1690
|
+
ready: _ready,
|
|
1691
|
+
indexing: _indexing,
|
|
1692
|
+
currentFile: _currentFile,
|
|
1693
|
+
totalFiles: _totalFiles,
|
|
1694
|
+
lastError: _lastError
|
|
1695
|
+
};
|
|
1696
|
+
}
|
|
1697
|
+
var _listeners = [];
|
|
1698
|
+
function onIndexStateChange(listener) {
|
|
1699
|
+
_listeners.push(listener);
|
|
1700
|
+
return () => {
|
|
1701
|
+
_listeners = _listeners.filter((l) => l !== listener);
|
|
1702
|
+
};
|
|
1703
|
+
}
|
|
1704
|
+
function emitState() {
|
|
1705
|
+
const state = getIndexState();
|
|
1706
|
+
for (const l of _listeners) l(state);
|
|
1707
|
+
}
|
|
1708
|
+
function _setIndexProgress(current, total) {
|
|
1709
|
+
_currentFile = current;
|
|
1710
|
+
_totalFiles = total;
|
|
1711
|
+
emitState();
|
|
1712
|
+
}
|
|
1713
|
+
function stubCtx(projectRoot) {
|
|
1714
|
+
return {
|
|
1715
|
+
projectRoot,
|
|
1716
|
+
cwd: projectRoot,
|
|
1717
|
+
messages: [],
|
|
1718
|
+
todos: [],
|
|
1719
|
+
readFiles: /* @__PURE__ */ new Set(),
|
|
1720
|
+
fileMtimes: /* @__PURE__ */ new Map()
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
var chain = Promise.resolve();
|
|
1724
|
+
function withMutex(job) {
|
|
1725
|
+
const run = chain.then(job, job);
|
|
1726
|
+
chain = run.then(
|
|
1727
|
+
() => void 0,
|
|
1728
|
+
() => void 0
|
|
1729
|
+
);
|
|
1730
|
+
return run;
|
|
1731
|
+
}
|
|
1732
|
+
var DEFAULT_DEBOUNCE_MS = 400;
|
|
1733
|
+
var debounceTimers = /* @__PURE__ */ new Map();
|
|
1734
|
+
function debounceKey(indexDir, file) {
|
|
1735
|
+
return `${indexDir ?? ""}|${file}`;
|
|
1736
|
+
}
|
|
1737
|
+
function isIndexableFile(filePath) {
|
|
1738
|
+
return detectLang(filePath) !== null;
|
|
1739
|
+
}
|
|
1740
|
+
async function runStartupIndex(opts) {
|
|
1741
|
+
_indexing = true;
|
|
1742
|
+
_currentFile = 0;
|
|
1743
|
+
_totalFiles = 0;
|
|
1744
|
+
_lastError = null;
|
|
1745
|
+
emitState();
|
|
1746
|
+
try {
|
|
1747
|
+
const result = await withMutex(
|
|
1748
|
+
() => runIndexer(stubCtx(opts.projectRoot), {
|
|
1749
|
+
projectRoot: opts.projectRoot,
|
|
1750
|
+
indexDir: opts.indexDir,
|
|
1751
|
+
force: opts.force
|
|
1752
|
+
})
|
|
1753
|
+
);
|
|
1754
|
+
_ready = true;
|
|
1755
|
+
return result;
|
|
1756
|
+
} catch (err) {
|
|
1757
|
+
_lastError = err instanceof Error ? err.message : String(err);
|
|
1758
|
+
_ready = true;
|
|
1759
|
+
throw err;
|
|
1760
|
+
} finally {
|
|
1761
|
+
_indexing = false;
|
|
1762
|
+
emitState();
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
function enqueueReindex(opts) {
|
|
1766
|
+
const files = opts.files.filter(isIndexableFile);
|
|
1767
|
+
if (files.length === 0) return;
|
|
1768
|
+
const ms = opts.debounceMs ?? DEFAULT_DEBOUNCE_MS;
|
|
1769
|
+
for (const file of files) {
|
|
1770
|
+
const key = debounceKey(opts.indexDir, file);
|
|
1771
|
+
const existing = debounceTimers.get(key);
|
|
1772
|
+
if (existing) clearTimeout(existing);
|
|
1773
|
+
const timer = setTimeout(() => {
|
|
1774
|
+
debounceTimers.delete(key);
|
|
1775
|
+
void withMutex(
|
|
1776
|
+
() => runIndexer(stubCtx(opts.projectRoot), {
|
|
1777
|
+
projectRoot: opts.projectRoot,
|
|
1778
|
+
files: [file],
|
|
1779
|
+
indexDir: opts.indexDir
|
|
1780
|
+
})
|
|
1781
|
+
).catch((err) => opts.onError?.(err));
|
|
1782
|
+
}, ms);
|
|
1783
|
+
timer.unref?.();
|
|
1784
|
+
debounceTimers.set(key, timer);
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
function cancelPendingReindexes() {
|
|
1788
|
+
for (const t of debounceTimers.values()) clearTimeout(t);
|
|
1789
|
+
debounceTimers.clear();
|
|
1790
|
+
}
|
|
1611
1791
|
|
|
1612
1792
|
// src/codebase-index/indexer.ts
|
|
1793
|
+
var YIELD_EVERY_N = 50;
|
|
1794
|
+
function yieldEventLoop() {
|
|
1795
|
+
return new Promise((resolve2) => setImmediate(resolve2));
|
|
1796
|
+
}
|
|
1613
1797
|
var DEFAULT_IGNORE = [
|
|
1614
1798
|
"node_modules",
|
|
1615
1799
|
".git",
|
|
@@ -1621,7 +1805,7 @@ var DEFAULT_IGNORE = [
|
|
|
1621
1805
|
"__snapshots__",
|
|
1622
1806
|
".nyc_output"
|
|
1623
1807
|
];
|
|
1624
|
-
async function findSourceFiles(projectRoot, ignore) {
|
|
1808
|
+
async function findSourceFiles(projectRoot, ignore, isGitIgnored) {
|
|
1625
1809
|
const results = [];
|
|
1626
1810
|
const ignoreSet = /* @__PURE__ */ new Set([...DEFAULT_IGNORE, ...ignore]);
|
|
1627
1811
|
const globs = [
|
|
@@ -1639,17 +1823,19 @@ async function findSourceFiles(projectRoot, ignore) {
|
|
|
1639
1823
|
const walk = async (dir) => {
|
|
1640
1824
|
let entries;
|
|
1641
1825
|
try {
|
|
1642
|
-
entries = await
|
|
1826
|
+
entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
1643
1827
|
} catch {
|
|
1644
1828
|
return;
|
|
1645
1829
|
}
|
|
1646
1830
|
for (const e of entries) {
|
|
1647
1831
|
if (ignoreSet.has(e.name)) continue;
|
|
1648
1832
|
const full = path4.join(dir, e.name);
|
|
1833
|
+
const rel = path4.relative(projectRoot, full).replace(/\\/g, "/");
|
|
1649
1834
|
if (e.isDirectory()) {
|
|
1835
|
+
if (isGitIgnored(rel, true)) continue;
|
|
1650
1836
|
await walk(full);
|
|
1651
1837
|
} else if (e.isFile()) {
|
|
1652
|
-
|
|
1838
|
+
if (isGitIgnored(rel, false)) continue;
|
|
1653
1839
|
const ext = path4.extname(e.name);
|
|
1654
1840
|
for (const { ext: extName, pat } of globs) {
|
|
1655
1841
|
if (ext === extName && (pat.test(rel) || pat.test(e.name))) {
|
|
@@ -1692,11 +1878,12 @@ async function runIndexer(_ctx, opts) {
|
|
|
1692
1878
|
const langStats = {};
|
|
1693
1879
|
let filesIndexed = 0;
|
|
1694
1880
|
let symbolsIndexed = 0;
|
|
1881
|
+
const isGitIgnored = await loadGitignoreMatcher(projectRoot);
|
|
1695
1882
|
let files;
|
|
1696
1883
|
if (opts.files && opts.files.length > 0) {
|
|
1697
|
-
files = opts.files.map((f) => path4.resolve(projectRoot, f));
|
|
1884
|
+
files = opts.files.map((f) => path4.resolve(projectRoot, f)).filter((f) => !isGitIgnored(path4.relative(projectRoot, f).replace(/\\/g, "/"), false));
|
|
1698
1885
|
} else {
|
|
1699
|
-
files = await findSourceFiles(projectRoot, ignore);
|
|
1886
|
+
files = await findSourceFiles(projectRoot, ignore, isGitIgnored);
|
|
1700
1887
|
}
|
|
1701
1888
|
if (langs && langs.length > 0) {
|
|
1702
1889
|
const langSet = new Set(langs);
|
|
@@ -1710,10 +1897,15 @@ async function runIndexer(_ctx, opts) {
|
|
|
1710
1897
|
if (!force) {
|
|
1711
1898
|
for (const meta of store.getAllFileMetas()) existingMeta.set(meta.file, meta);
|
|
1712
1899
|
}
|
|
1713
|
-
for (
|
|
1900
|
+
for (let fi = 0; fi < files.length; fi++) {
|
|
1901
|
+
const file = files[fi];
|
|
1902
|
+
_setIndexProgress(fi + 1, files.length);
|
|
1903
|
+
if (fi > 0 && fi % YIELD_EVERY_N === 0) {
|
|
1904
|
+
await yieldEventLoop();
|
|
1905
|
+
}
|
|
1714
1906
|
let stat2;
|
|
1715
1907
|
try {
|
|
1716
|
-
stat2 = await
|
|
1908
|
+
stat2 = await fs3.stat(file);
|
|
1717
1909
|
} catch {
|
|
1718
1910
|
store.deleteFile(file);
|
|
1719
1911
|
continue;
|
|
@@ -1728,11 +1920,11 @@ async function runIndexer(_ctx, opts) {
|
|
|
1728
1920
|
filesIndexed++;
|
|
1729
1921
|
continue;
|
|
1730
1922
|
}
|
|
1731
|
-
store.deleteSymbolsForFile(file);
|
|
1732
1923
|
store.deleteRefsForFile(file);
|
|
1924
|
+
store.deleteSymbolsForFile(file);
|
|
1733
1925
|
let content;
|
|
1734
1926
|
try {
|
|
1735
|
-
content = await
|
|
1927
|
+
content = await fs3.readFile(file, "utf8");
|
|
1736
1928
|
} catch (e) {
|
|
1737
1929
|
errors.push(`read error: ${file}: ${e instanceof Error ? e.message : String(e)}`);
|
|
1738
1930
|
continue;
|
|
@@ -1755,7 +1947,7 @@ async function runIndexer(_ctx, opts) {
|
|
|
1755
1947
|
filesIndexed++;
|
|
1756
1948
|
continue;
|
|
1757
1949
|
}
|
|
1758
|
-
const nextId = store.
|
|
1950
|
+
const nextId = store.getMaxSymbolId() + 1;
|
|
1759
1951
|
const symbolsWithIds = parsed.symbols.map((s, i) => ({ ...s, id: nextId + i }));
|
|
1760
1952
|
store.insertSymbols(symbolsWithIds, nextId);
|
|
1761
1953
|
const count = symbolsWithIds.length;
|
|
@@ -1782,7 +1974,7 @@ async function runIndexer(_ctx, opts) {
|
|
|
1782
1974
|
}
|
|
1783
1975
|
for (const [file_] of existingMeta) {
|
|
1784
1976
|
try {
|
|
1785
|
-
await
|
|
1977
|
+
await fs3.stat(file_);
|
|
1786
1978
|
} catch {
|
|
1787
1979
|
store.deleteFile(file_);
|
|
1788
1980
|
}
|
|
@@ -1824,12 +2016,23 @@ var codebaseIndexTool = {
|
|
|
1824
2016
|
}
|
|
1825
2017
|
},
|
|
1826
2018
|
async execute(input, ctx) {
|
|
2019
|
+
if (isIndexing()) {
|
|
2020
|
+
return {
|
|
2021
|
+
filesIndexed: 0,
|
|
2022
|
+
symbolsIndexed: 0,
|
|
2023
|
+
langStats: {},
|
|
2024
|
+
durationMs: 0,
|
|
2025
|
+
errors: [],
|
|
2026
|
+
note: "A full index is already in progress. Retry codebase-index after it completes (check codebase-stats)."
|
|
2027
|
+
};
|
|
2028
|
+
}
|
|
1827
2029
|
const result = await runIndexer(ctx, {
|
|
1828
2030
|
projectRoot: ctx.projectRoot,
|
|
1829
2031
|
force: input.force ?? false,
|
|
1830
2032
|
langs: input.langs,
|
|
1831
2033
|
indexDir: codebaseIndexDirOverride(ctx)
|
|
1832
2034
|
});
|
|
2035
|
+
setIndexReady();
|
|
1833
2036
|
return result;
|
|
1834
2037
|
}
|
|
1835
2038
|
};
|
|
@@ -1965,6 +2168,31 @@ var codebaseSearchTool = {
|
|
|
1965
2168
|
required: ["query"]
|
|
1966
2169
|
},
|
|
1967
2170
|
async execute(input, ctx) {
|
|
2171
|
+
const state = getIndexState();
|
|
2172
|
+
if (!state.ready) {
|
|
2173
|
+
return {
|
|
2174
|
+
results: [],
|
|
2175
|
+
total: 0,
|
|
2176
|
+
query: input.query,
|
|
2177
|
+
indexStatus: state.indexing ? `Indexing in progress (${state.currentFile}/${state.totalFiles} files) \u2014 retry in a moment.` : "Index not yet built. The codebase is being indexed at startup \u2014 search will be available shortly."
|
|
2178
|
+
};
|
|
2179
|
+
}
|
|
2180
|
+
if (state.indexing) {
|
|
2181
|
+
return {
|
|
2182
|
+
results: [],
|
|
2183
|
+
total: 0,
|
|
2184
|
+
query: input.query,
|
|
2185
|
+
indexStatus: `Index refresh in progress (${state.currentFile}/${state.totalFiles} files). Results may be incomplete.`
|
|
2186
|
+
};
|
|
2187
|
+
}
|
|
2188
|
+
if (state.lastError) {
|
|
2189
|
+
return {
|
|
2190
|
+
results: [],
|
|
2191
|
+
total: 0,
|
|
2192
|
+
query: input.query,
|
|
2193
|
+
indexStatus: `Index build failed: ${state.lastError}. Try /codebase-reindex.`
|
|
2194
|
+
};
|
|
2195
|
+
}
|
|
1968
2196
|
const store = new IndexStore(ctx.projectRoot, { indexDir: codebaseIndexDirOverride(ctx) });
|
|
1969
2197
|
try {
|
|
1970
2198
|
const limit = Math.min(input.limit ?? 20, 100);
|
|
@@ -2022,6 +2250,32 @@ var codebaseStatsTool = {
|
|
|
2022
2250
|
additionalProperties: false
|
|
2023
2251
|
},
|
|
2024
2252
|
async execute(_input, ctx) {
|
|
2253
|
+
const idxState = getIndexState();
|
|
2254
|
+
if (!idxState.ready) {
|
|
2255
|
+
return {
|
|
2256
|
+
totalSymbols: 0,
|
|
2257
|
+
totalFiles: 0,
|
|
2258
|
+
byLang: {},
|
|
2259
|
+
byKind: {},
|
|
2260
|
+
lastIndexed: null,
|
|
2261
|
+
sizeBytes: 0,
|
|
2262
|
+
indexPath: "",
|
|
2263
|
+
version: SCHEMA_VERSION,
|
|
2264
|
+
indexStatus: idxState.indexing ? `Indexing in progress (${idxState.currentFile}/${idxState.totalFiles} files).` : "Index not yet built."
|
|
2265
|
+
};
|
|
2266
|
+
}
|
|
2267
|
+
if (idxState.indexing) {
|
|
2268
|
+
const store2 = new IndexStore(ctx.projectRoot, { indexDir: codebaseIndexDirOverride(ctx) });
|
|
2269
|
+
try {
|
|
2270
|
+
const stats = store2.getStats();
|
|
2271
|
+
return {
|
|
2272
|
+
...stats,
|
|
2273
|
+
indexStatus: `Index refresh in progress (${idxState.currentFile}/${idxState.totalFiles} files). Stats may be incomplete.`
|
|
2274
|
+
};
|
|
2275
|
+
} finally {
|
|
2276
|
+
store2.close();
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2025
2279
|
const store = new IndexStore(ctx.projectRoot, { indexDir: codebaseIndexDirOverride(ctx) });
|
|
2026
2280
|
try {
|
|
2027
2281
|
const stats = store.getStats();
|
|
@@ -2041,6 +2295,6 @@ var codebaseStatsTool = {
|
|
|
2041
2295
|
}
|
|
2042
2296
|
};
|
|
2043
2297
|
|
|
2044
|
-
export { IndexStore, SCHEMA_VERSION, buildBm25Index, buildIndexableText, codebaseIndexDirOverride, codebaseIndexTool, codebaseSearchTool, codebaseStatsTool, internalKindToLspKind, lspKindToInternalKind, resolveIndexDir, tokenise };
|
|
2298
|
+
export { IndexStore, SCHEMA_VERSION, buildBm25Index, buildIndexableText, cancelPendingReindexes, codebaseIndexDirOverride, codebaseIndexTool, codebaseSearchTool, codebaseStatsTool, enqueueReindex, getIndexState, internalKindToLspKind, isIndexReady, isIndexableFile, isIndexing, lspKindToInternalKind, onIndexStateChange, resolveIndexDir, runIndexer, runStartupIndex, tokenise };
|
|
2045
2299
|
//# sourceMappingURL=index.js.map
|
|
2046
2300
|
//# sourceMappingURL=index.js.map
|