lmgrep 0.1.0 → 0.1.2
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/cli.js +559 -13
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +32 -0
- package/dist/index.js +180 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/build.d.ts +7 -0
- package/dist/lib/build.js +222 -0
- package/dist/lib/build.js.map +1 -0
- package/dist/{chunker → lib/chunker}/context.d.ts +0 -4
- package/dist/{chunker → lib/chunker}/context.js +3 -76
- package/dist/lib/chunker/context.js.map +1 -0
- package/dist/lib/chunker/index.d.ts +7 -0
- package/dist/{chunker → lib/chunker}/index.js +10 -5
- package/dist/lib/chunker/index.js.map +1 -0
- package/dist/lib/chunker/languages.js.map +1 -0
- package/dist/lib/config.d.ts +12 -0
- package/dist/lib/config.js +82 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/embedder.d.ts +55 -0
- package/dist/lib/embedder.js +221 -0
- package/dist/lib/embedder.js.map +1 -0
- package/dist/{providers.js → lib/providers.js} +0 -2
- package/dist/lib/providers.js.map +1 -0
- package/dist/lib/repair.d.ts +3 -0
- package/dist/lib/repair.js +104 -0
- package/dist/lib/repair.js.map +1 -0
- package/dist/lib/scanner.d.ts +34 -0
- package/dist/lib/scanner.js +219 -0
- package/dist/lib/scanner.js.map +1 -0
- package/dist/lib/serve.d.ts +11 -0
- package/dist/lib/serve.js +124 -0
- package/dist/lib/serve.js.map +1 -0
- package/dist/lib/store.d.ts +147 -0
- package/dist/lib/store.js +673 -0
- package/dist/lib/store.js.map +1 -0
- package/dist/lib/types.d.ts +118 -0
- package/dist/lib/types.js +13 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/mcp.js +160 -45
- package/dist/mcp.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunker/context.js.map +0 -1
- package/dist/chunker/index.d.ts +0 -3
- package/dist/chunker/index.js.map +0 -1
- package/dist/chunker/languages.js.map +0 -1
- package/dist/config.d.ts +0 -2
- package/dist/config.js +0 -31
- package/dist/config.js.map +0 -1
- package/dist/embedder.d.ts +0 -3
- package/dist/embedder.js +0 -55
- package/dist/embedder.js.map +0 -1
- package/dist/index-cmd.d.ts +0 -9
- package/dist/index-cmd.js +0 -250
- package/dist/index-cmd.js.map +0 -1
- package/dist/providers.js.map +0 -1
- package/dist/repair-cmd.d.ts +0 -5
- package/dist/repair-cmd.js +0 -112
- package/dist/repair-cmd.js.map +0 -1
- package/dist/search-cmd.d.ts +0 -10
- package/dist/search-cmd.js +0 -60
- package/dist/search-cmd.js.map +0 -1
- package/dist/serve-cmd.d.ts +0 -1
- package/dist/serve-cmd.js +0 -139
- package/dist/serve-cmd.js.map +0 -1
- package/dist/status-cmd.d.ts +0 -5
- package/dist/status-cmd.js +0 -119
- package/dist/status-cmd.js.map +0 -1
- package/dist/store.d.ts +0 -25
- package/dist/store.js +0 -207
- package/dist/store.js.map +0 -1
- package/dist/types.d.ts +0 -40
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/walker.d.ts +0 -3
- package/dist/walker.js +0 -90
- package/dist/walker.js.map +0 -1
- /package/dist/{chunker → lib/chunker}/languages.d.ts +0 -0
- /package/dist/{chunker → lib/chunker}/languages.js +0 -0
- /package/dist/{providers.d.ts → lib/providers.d.ts} +0 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { readFileSync, existsSync, watch, statSync } from "node:fs";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { join, extname, dirname } from "node:path";
|
|
4
|
+
import { globSync } from "glob";
|
|
5
|
+
import ignore from "ignore";
|
|
6
|
+
export const DEFAULT_IGNORE = [
|
|
7
|
+
"node_modules",
|
|
8
|
+
".git",
|
|
9
|
+
"dist",
|
|
10
|
+
"build",
|
|
11
|
+
".next",
|
|
12
|
+
"__pycache__",
|
|
13
|
+
".venv",
|
|
14
|
+
"vendor",
|
|
15
|
+
"target",
|
|
16
|
+
".lmgrep",
|
|
17
|
+
"*.min.js",
|
|
18
|
+
"*.min.css",
|
|
19
|
+
"*.map",
|
|
20
|
+
"*.lock",
|
|
21
|
+
"pnpm-lock.yaml",
|
|
22
|
+
"package-lock.json",
|
|
23
|
+
"yarn.lock",
|
|
24
|
+
"*.png",
|
|
25
|
+
"*.jpg",
|
|
26
|
+
"*.jpeg",
|
|
27
|
+
"*.gif",
|
|
28
|
+
"*.ico",
|
|
29
|
+
"*.woff",
|
|
30
|
+
"*.woff2",
|
|
31
|
+
"*.ttf",
|
|
32
|
+
"*.eot",
|
|
33
|
+
"*.svg",
|
|
34
|
+
"*.zip",
|
|
35
|
+
"*.tar",
|
|
36
|
+
"*.gz",
|
|
37
|
+
"*.bin",
|
|
38
|
+
"*.exe",
|
|
39
|
+
"*.dll",
|
|
40
|
+
"*.so",
|
|
41
|
+
"*.dylib",
|
|
42
|
+
"*.wasm",
|
|
43
|
+
];
|
|
44
|
+
export const CODE_EXTENSIONS = new Set([
|
|
45
|
+
".js",
|
|
46
|
+
".ts",
|
|
47
|
+
".jsx",
|
|
48
|
+
".tsx",
|
|
49
|
+
".py",
|
|
50
|
+
".rs",
|
|
51
|
+
".go",
|
|
52
|
+
".rb",
|
|
53
|
+
".c",
|
|
54
|
+
".h",
|
|
55
|
+
".cpp",
|
|
56
|
+
".hpp",
|
|
57
|
+
".cc",
|
|
58
|
+
".swift",
|
|
59
|
+
".json",
|
|
60
|
+
".yaml",
|
|
61
|
+
".yml",
|
|
62
|
+
".toml",
|
|
63
|
+
".lua",
|
|
64
|
+
".scala",
|
|
65
|
+
".zig",
|
|
66
|
+
]);
|
|
67
|
+
function buildExtensionSet(config) {
|
|
68
|
+
const exts = new Set(CODE_EXTENSIONS);
|
|
69
|
+
if (config?.include) {
|
|
70
|
+
for (const ext of config.include)
|
|
71
|
+
exts.add(ext);
|
|
72
|
+
}
|
|
73
|
+
if (config?.exclude) {
|
|
74
|
+
for (const ext of config.exclude)
|
|
75
|
+
exts.delete(ext);
|
|
76
|
+
}
|
|
77
|
+
return exts;
|
|
78
|
+
}
|
|
79
|
+
function isCodeFile(filePath, exts) {
|
|
80
|
+
const ext = extname(filePath);
|
|
81
|
+
return exts.has(ext);
|
|
82
|
+
}
|
|
83
|
+
function buildIgnoreFilter(cwd, extraPatterns) {
|
|
84
|
+
const ig = ignore();
|
|
85
|
+
ig.add(DEFAULT_IGNORE);
|
|
86
|
+
if (extraPatterns) {
|
|
87
|
+
ig.add(extraPatterns);
|
|
88
|
+
}
|
|
89
|
+
const gitignorePath = join(cwd, ".gitignore");
|
|
90
|
+
if (existsSync(gitignorePath)) {
|
|
91
|
+
ig.add(readFileSync(gitignorePath, "utf-8"));
|
|
92
|
+
}
|
|
93
|
+
const lmgrepIgnorePath = join(cwd, ".lmgrepignore");
|
|
94
|
+
if (existsSync(lmgrepIgnorePath)) {
|
|
95
|
+
ig.add(readFileSync(lmgrepIgnorePath, "utf-8"));
|
|
96
|
+
}
|
|
97
|
+
return ig;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Walk the directory tree and yield file entries.
|
|
101
|
+
* Reads nested .gitignore files at each directory level.
|
|
102
|
+
*/
|
|
103
|
+
export function walkFiles(cwd, extraIgnore, extensions) {
|
|
104
|
+
const ig = buildIgnoreFilter(cwd, extraIgnore);
|
|
105
|
+
const exts = buildExtensionSet(extensions);
|
|
106
|
+
// Collect nested .gitignore rules
|
|
107
|
+
const allFiles = globSync("**/*", { cwd, nodir: true, dot: false });
|
|
108
|
+
// Build a set of directories that have .gitignore files
|
|
109
|
+
const nestedIgnores = new Map();
|
|
110
|
+
for (const f of allFiles) {
|
|
111
|
+
if (f.endsWith("/.gitignore") || f === ".gitignore")
|
|
112
|
+
continue;
|
|
113
|
+
const dir = dirname(f);
|
|
114
|
+
if (dir === "." || nestedIgnores.has(dir))
|
|
115
|
+
continue;
|
|
116
|
+
const nestedPath = join(cwd, dir, ".gitignore");
|
|
117
|
+
if (existsSync(nestedPath)) {
|
|
118
|
+
const nested = ignore();
|
|
119
|
+
nested.add(readFileSync(nestedPath, "utf-8"));
|
|
120
|
+
nestedIgnores.set(dir, nested);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return allFiles.filter((f) => {
|
|
124
|
+
if (!isCodeFile(f, exts))
|
|
125
|
+
return false;
|
|
126
|
+
if (ig.ignores(f))
|
|
127
|
+
return false;
|
|
128
|
+
// Check nested .gitignore rules
|
|
129
|
+
for (const [dir, nested] of nestedIgnores) {
|
|
130
|
+
if (f.startsWith(dir + "/")) {
|
|
131
|
+
const rel = f.slice(dir.length + 1);
|
|
132
|
+
if (nested.ignores(rel))
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return true;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Hash a file's content for change detection.
|
|
141
|
+
*/
|
|
142
|
+
export function hashFile(cwd, filePath) {
|
|
143
|
+
try {
|
|
144
|
+
const content = readFileSync(join(cwd, filePath));
|
|
145
|
+
return createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Compute changed files by comparing disk hashes against stored hashes.
|
|
153
|
+
*/
|
|
154
|
+
export function detectChanges(files, storedHashes, cwd, force = false) {
|
|
155
|
+
const changed = [];
|
|
156
|
+
const currentHashes = new Map();
|
|
157
|
+
for (const file of files) {
|
|
158
|
+
const hash = hashFile(cwd, file);
|
|
159
|
+
if (!hash)
|
|
160
|
+
continue;
|
|
161
|
+
currentHashes.set(file, hash);
|
|
162
|
+
if (force || storedHashes.get(file) !== hash) {
|
|
163
|
+
changed.push({ path: file, hash });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return { changed, currentHashes };
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Filter files by modification time.
|
|
170
|
+
*/
|
|
171
|
+
export function filterByMtime(files, cwd, cutoffMs) {
|
|
172
|
+
return files.filter((f) => {
|
|
173
|
+
try {
|
|
174
|
+
return statSync(join(cwd, f)).mtimeMs >= cutoffMs;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Watch a directory for code file changes. Calls the callback with debouncing.
|
|
183
|
+
* Collects changed file paths during the debounce window and passes them to the callback.
|
|
184
|
+
*/
|
|
185
|
+
export function watchFiles(cwd, extraIgnore, onChanges, debounceMs = 2000, extensions) {
|
|
186
|
+
const ig = buildIgnoreFilter(cwd, extraIgnore);
|
|
187
|
+
const exts = buildExtensionSet(extensions);
|
|
188
|
+
let timer;
|
|
189
|
+
let pending = new Set();
|
|
190
|
+
const watcher = watch(cwd, { recursive: true }, (_event, filename) => {
|
|
191
|
+
if (!filename)
|
|
192
|
+
return;
|
|
193
|
+
if (!isCodeFile(filename, exts))
|
|
194
|
+
return;
|
|
195
|
+
try {
|
|
196
|
+
if (ig.ignores(filename))
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
pending.add(filename);
|
|
203
|
+
if (timer)
|
|
204
|
+
clearTimeout(timer);
|
|
205
|
+
timer = setTimeout(() => {
|
|
206
|
+
const files = [...pending];
|
|
207
|
+
pending = new Set();
|
|
208
|
+
onChanges(files);
|
|
209
|
+
}, debounceMs);
|
|
210
|
+
});
|
|
211
|
+
return {
|
|
212
|
+
close() {
|
|
213
|
+
if (timer)
|
|
214
|
+
clearTimeout(timer);
|
|
215
|
+
watcher.close();
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/lib/scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Embedder } from "./embedder.js";
|
|
2
|
+
import { type Store, isDbLocked } from "./store.js";
|
|
3
|
+
import type { Chunker, Logger, LmgrepConfig } from "./types.js";
|
|
4
|
+
export { isDbLocked as isServeLocked };
|
|
5
|
+
export declare function serve(cwd: string, store: Store, config: LmgrepConfig, embedder: Embedder, chunker: Chunker, logger?: Logger): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Start an in-process file watcher that incrementally re-indexes on changes.
|
|
8
|
+
* Acquires the DB lock. Returns a cleanup function to stop watching and release the lock.
|
|
9
|
+
* Returns undefined if the lock is already held by another process.
|
|
10
|
+
*/
|
|
11
|
+
export declare function startWatcher(cwd: string, store: Store, config: LmgrepConfig, embedder: Embedder, chunker: Chunker, logger?: Logger): (() => void) | undefined;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { build } from "./build.js";
|
|
3
|
+
import { watchFiles } from "./scanner.js";
|
|
4
|
+
import { getDbPath, findIndexedAncestor, acquireDbLock, releaseDbLock, isDbLocked, } from "./store.js";
|
|
5
|
+
import { consoleLogger } from "./types.js";
|
|
6
|
+
export { isDbLocked as isServeLocked };
|
|
7
|
+
// --- Serve ---
|
|
8
|
+
export async function serve(cwd, store, config, embedder, chunker, logger = consoleLogger) {
|
|
9
|
+
const log = logger.info.bind(logger);
|
|
10
|
+
// Require an existing index
|
|
11
|
+
const ancestor = findIndexedAncestor(cwd);
|
|
12
|
+
if (!ancestor) {
|
|
13
|
+
const dbPath = getDbPath(cwd);
|
|
14
|
+
if (!existsSync(dbPath)) {
|
|
15
|
+
throw new Error("No index found. Run `lmgrep index` first.");
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (!acquireDbLock(cwd)) {
|
|
19
|
+
throw new Error("Already running for this project.");
|
|
20
|
+
}
|
|
21
|
+
const cleanup = () => releaseDbLock(cwd);
|
|
22
|
+
process.on("exit", cleanup);
|
|
23
|
+
process.on("SIGINT", () => {
|
|
24
|
+
cleanup();
|
|
25
|
+
process.exit(0);
|
|
26
|
+
});
|
|
27
|
+
process.on("SIGTERM", () => {
|
|
28
|
+
cleanup();
|
|
29
|
+
process.exit(0);
|
|
30
|
+
});
|
|
31
|
+
// Initial index
|
|
32
|
+
log("Running initial index...");
|
|
33
|
+
await build(cwd, store, config, embedder, chunker, {}, logger);
|
|
34
|
+
// Watch with non-recursive re-trigger and per-file targeting
|
|
35
|
+
let indexing = false;
|
|
36
|
+
let pendingFiles;
|
|
37
|
+
async function runIndex(changedFiles) {
|
|
38
|
+
if (indexing) {
|
|
39
|
+
// Merge into pending set
|
|
40
|
+
if (changedFiles) {
|
|
41
|
+
pendingFiles = [...(pendingFiles ?? []), ...changedFiles];
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
pendingFiles = undefined; // full rebuild queued
|
|
45
|
+
}
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
indexing = true;
|
|
49
|
+
try {
|
|
50
|
+
const fileCount = changedFiles?.length;
|
|
51
|
+
log(fileCount
|
|
52
|
+
? `Changes detected in ${fileCount} file(s), re-indexing...`
|
|
53
|
+
: "Changes detected, re-indexing...");
|
|
54
|
+
await build(cwd, store, config, embedder, chunker, { files: changedFiles }, logger);
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
logger.error(`Index error: ${err instanceof Error ? err.message : err}`);
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
indexing = false;
|
|
61
|
+
if (pendingFiles !== undefined) {
|
|
62
|
+
const next = pendingFiles.length > 0 ? pendingFiles : undefined;
|
|
63
|
+
pendingFiles = undefined;
|
|
64
|
+
runIndex(next);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
watchFiles(cwd, config.ignore, (changedFiles) => {
|
|
69
|
+
runIndex(changedFiles);
|
|
70
|
+
}, 2000, config.extensions);
|
|
71
|
+
log("Watching for changes...");
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Start an in-process file watcher that incrementally re-indexes on changes.
|
|
75
|
+
* Acquires the DB lock. Returns a cleanup function to stop watching and release the lock.
|
|
76
|
+
* Returns undefined if the lock is already held by another process.
|
|
77
|
+
*/
|
|
78
|
+
export function startWatcher(cwd, store, config, embedder, chunker, logger = consoleLogger) {
|
|
79
|
+
if (!acquireDbLock(cwd)) {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
const log = logger.info.bind(logger);
|
|
83
|
+
let indexing = false;
|
|
84
|
+
let pendingFiles;
|
|
85
|
+
async function runIndex(changedFiles) {
|
|
86
|
+
if (indexing) {
|
|
87
|
+
if (changedFiles) {
|
|
88
|
+
pendingFiles = [...(pendingFiles ?? []), ...changedFiles];
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
pendingFiles = undefined;
|
|
92
|
+
}
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
indexing = true;
|
|
96
|
+
try {
|
|
97
|
+
const fileCount = changedFiles?.length;
|
|
98
|
+
log(fileCount
|
|
99
|
+
? `Changes detected in ${fileCount} file(s), re-indexing...`
|
|
100
|
+
: "Changes detected, re-indexing...");
|
|
101
|
+
await build(cwd, store, config, embedder, chunker, { files: changedFiles }, logger);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
logger.error(`Index error: ${err instanceof Error ? err.message : err}`);
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
indexing = false;
|
|
108
|
+
if (pendingFiles !== undefined) {
|
|
109
|
+
const next = pendingFiles.length > 0 ? pendingFiles : undefined;
|
|
110
|
+
pendingFiles = undefined;
|
|
111
|
+
runIndex(next);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const watcher = watchFiles(cwd, config.ignore, (changedFiles) => {
|
|
116
|
+
runIndex(changedFiles);
|
|
117
|
+
}, 2000, config.extensions);
|
|
118
|
+
log("Watching for changes...");
|
|
119
|
+
return () => {
|
|
120
|
+
watcher.close();
|
|
121
|
+
releaseDbLock(cwd);
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/lib/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAEN,SAAS,EACT,mBAAmB,EACnB,aAAa,EACb,aAAa,EACb,UAAU,GACV,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,CAAC;AAEvC,gBAAgB;AAEhB,MAAM,CAAC,KAAK,UAAU,KAAK,CAC1B,GAAW,EACX,KAAY,EACZ,MAAoB,EACpB,QAAkB,EAClB,OAAgB,EAChB,SAAiB,aAAa;IAE9B,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAErC,4BAA4B;IAC5B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC9D,CAAC;IACF,CAAC;IAED,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IACzC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACzB,OAAO,EAAE,CAAC;QACV,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;QAC1B,OAAO,EAAE,CAAC;QACV,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,gBAAgB;IAChB,GAAG,CAAC,0BAA0B,CAAC,CAAC;IAChC,MAAM,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;IAE/D,6DAA6D;IAC7D,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,YAAkC,CAAC;IAEvC,KAAK,UAAU,QAAQ,CAAC,YAAuB;QAC9C,IAAI,QAAQ,EAAE,CAAC;YACd,yBAAyB;YACzB,IAAI,YAAY,EAAE,CAAC;gBAClB,YAAY,GAAG,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,GAAG,YAAY,CAAC,CAAC;YAC3D,CAAC;iBAAM,CAAC;gBACP,YAAY,GAAG,SAAS,CAAC,CAAC,sBAAsB;YACjD,CAAC;YACD,OAAO;QACR,CAAC;QACD,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,CAAC;YACJ,MAAM,SAAS,GAAG,YAAY,EAAE,MAAM,CAAC;YACvC,GAAG,CACF,SAAS;gBACR,CAAC,CAAC,uBAAuB,SAAS,0BAA0B;gBAC5D,CAAC,CAAC,kCAAkC,CACrC,CAAC;YACF,MAAM,KAAK,CACV,GAAG,EACH,KAAK,EACL,MAAM,EACN,QAAQ,EACR,OAAO,EACP,EAAE,KAAK,EAAE,YAAY,EAAE,EACvB,MAAM,CACN,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,CAAC,KAAK,CACX,gBAAgB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAC1D,CAAC;QACH,CAAC;gBAAS,CAAC;YACV,QAAQ,GAAG,KAAK,CAAC;YACjB,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;gBAChC,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;gBAChE,YAAY,GAAG,SAAS,CAAC;gBACzB,QAAQ,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC;QACF,CAAC;IACF,CAAC;IAED,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,YAAY,EAAE,EAAE;QAC/C,QAAQ,CAAC,YAAY,CAAC,CAAC;IACxB,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAE5B,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC3B,GAAW,EACX,KAAY,EACZ,MAAoB,EACpB,QAAkB,EAClB,OAAgB,EAChB,SAAiB,aAAa;IAE9B,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,YAAkC,CAAC;IAEvC,KAAK,UAAU,QAAQ,CAAC,YAAuB;QAC9C,IAAI,QAAQ,EAAE,CAAC;YACd,IAAI,YAAY,EAAE,CAAC;gBAClB,YAAY,GAAG,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,GAAG,YAAY,CAAC,CAAC;YAC3D,CAAC;iBAAM,CAAC;gBACP,YAAY,GAAG,SAAS,CAAC;YAC1B,CAAC;YACD,OAAO;QACR,CAAC;QACD,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,CAAC;YACJ,MAAM,SAAS,GAAG,YAAY,EAAE,MAAM,CAAC;YACvC,GAAG,CACF,SAAS;gBACR,CAAC,CAAC,uBAAuB,SAAS,0BAA0B;gBAC5D,CAAC,CAAC,kCAAkC,CACrC,CAAC;YACF,MAAM,KAAK,CACV,GAAG,EACH,KAAK,EACL,MAAM,EACN,QAAQ,EACR,OAAO,EACP,EAAE,KAAK,EAAE,YAAY,EAAE,EACvB,MAAM,CACN,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,CAAC,KAAK,CACX,gBAAgB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAC1D,CAAC;QACH,CAAC;gBAAS,CAAC;YACV,QAAQ,GAAG,KAAK,CAAC;YACjB,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;gBAChC,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;gBAChE,YAAY,GAAG,SAAS,CAAC;gBACzB,QAAQ,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC;QACF,CAAC;IACF,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CACzB,GAAG,EACH,MAAM,CAAC,MAAM,EACb,CAAC,YAAY,EAAE,EAAE;QAChB,QAAQ,CAAC,YAAY,CAAC,CAAC;IACxB,CAAC,EACD,IAAI,EACJ,MAAM,CAAC,UAAU,CACjB,CAAC;IAEF,GAAG,CAAC,yBAAyB,CAAC,CAAC;IAE/B,OAAO,GAAG,EAAE;QACX,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,aAAa,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { IndexedChunk, SearchResult } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the project identity for a directory.
|
|
4
|
+
*
|
|
5
|
+
* For git repos: uses the remote origin URL as identity so that multiple
|
|
6
|
+
* worktrees of the same repo share one index.
|
|
7
|
+
*
|
|
8
|
+
* For non-git directories: falls back to hashing the absolute path.
|
|
9
|
+
*
|
|
10
|
+
* Returns { id, root } where id is the string to hash for the DB path,
|
|
11
|
+
* and root is the project root directory (git toplevel or cwd).
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveProject(cwd: string): {
|
|
14
|
+
id: string;
|
|
15
|
+
root: string;
|
|
16
|
+
branch: string;
|
|
17
|
+
};
|
|
18
|
+
export declare function getDbPath(cwd: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Compute the DB path using the pre-git-aware scheme (absolute path hash).
|
|
21
|
+
* Used by `lmgrep import` to find legacy indexes.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getLegacyDbPath(cwd: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Find the project root and compute the prefix (subdirectory offset).
|
|
26
|
+
* For git repos, the root is the git toplevel. For non-git dirs, walks up
|
|
27
|
+
* looking for an existing index.
|
|
28
|
+
*/
|
|
29
|
+
export declare function findIndexedAncestor(cwd: string): {
|
|
30
|
+
root: string;
|
|
31
|
+
prefix: string;
|
|
32
|
+
} | undefined;
|
|
33
|
+
export interface ProjectMetadata {
|
|
34
|
+
root: string;
|
|
35
|
+
remote?: string;
|
|
36
|
+
branch: string;
|
|
37
|
+
indexedAt: string;
|
|
38
|
+
/** Full model string used at index time (e.g. "openai:nomic-embed-text") */
|
|
39
|
+
model?: string;
|
|
40
|
+
/** Embedding vector dimensions */
|
|
41
|
+
dimensions?: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extract the base model family name from a full model string.
|
|
45
|
+
* Strips provider prefix (e.g. "openai:", "ollama:") and quantization/tag
|
|
46
|
+
* suffixes (e.g. ":Q4_K_M", ":latest", ":fp16").
|
|
47
|
+
*
|
|
48
|
+
* Examples:
|
|
49
|
+
* "openai:nomic-embed-text" → "nomic-embed-text"
|
|
50
|
+
* "ollama:nomic-embed-text:Q4_K_M" → "nomic-embed-text"
|
|
51
|
+
* "lmstudio:bge-large-en:fp16" → "bge-large-en"
|
|
52
|
+
* "openai:text-embedding-3-small" → "text-embedding-3-small"
|
|
53
|
+
*/
|
|
54
|
+
export declare function extractModelFamily(model: string): string;
|
|
55
|
+
export declare function writeProjectMetadata(cwd: string, extra?: {
|
|
56
|
+
model?: string;
|
|
57
|
+
dimensions?: number;
|
|
58
|
+
}): void;
|
|
59
|
+
export declare function readProjectMetadata(dbPath: string): ProjectMetadata | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Scan all lmgrep indexes and return their metadata.
|
|
62
|
+
*/
|
|
63
|
+
export declare function discoverIndexedProjects(): Array<{
|
|
64
|
+
dbPath: string;
|
|
65
|
+
metadata: ProjectMetadata;
|
|
66
|
+
}>;
|
|
67
|
+
/**
|
|
68
|
+
* Acquire an exclusive write lock for a project's DB.
|
|
69
|
+
* Returns true if the lock was acquired, false if another process holds it.
|
|
70
|
+
*/
|
|
71
|
+
export declare function acquireDbLock(cwd: string): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Release the write lock for a project's DB.
|
|
74
|
+
*/
|
|
75
|
+
export declare function releaseDbLock(cwd: string): void;
|
|
76
|
+
/**
|
|
77
|
+
* Check if a write lock is held by a live process.
|
|
78
|
+
*/
|
|
79
|
+
export declare function isDbLocked(cwd: string): boolean;
|
|
80
|
+
export interface RunningProcess {
|
|
81
|
+
pid: number;
|
|
82
|
+
/** Process title from /proc/<pid>/comm (e.g. "lmgrep-mcp", "lmgrep") */
|
|
83
|
+
processName: string;
|
|
84
|
+
/** Full command line */
|
|
85
|
+
cmdline: string;
|
|
86
|
+
/** Kind of process: "mcp", "serve", or "cli" */
|
|
87
|
+
kind: "mcp" | "serve" | "cli";
|
|
88
|
+
/** Project root from the index metadata */
|
|
89
|
+
projectRoot?: string;
|
|
90
|
+
/** Whether this process is maintaining (watching) the index */
|
|
91
|
+
watching: boolean;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Scan all lock files to find running lmgrep processes,
|
|
95
|
+
* which indexes they hold, and whether they are watching for changes.
|
|
96
|
+
*/
|
|
97
|
+
export declare function discoverRunningProcesses(): RunningProcess[];
|
|
98
|
+
export declare class Store {
|
|
99
|
+
private readonly dbPath;
|
|
100
|
+
private readonly branch;
|
|
101
|
+
private db;
|
|
102
|
+
private chunksTable;
|
|
103
|
+
private filesTable;
|
|
104
|
+
constructor(dbPath: string, branch?: string);
|
|
105
|
+
static forProject(cwd: string): Store;
|
|
106
|
+
private connection;
|
|
107
|
+
private openChunks;
|
|
108
|
+
private openFiles;
|
|
109
|
+
addChunks(chunks: IndexedChunk[]): Promise<void>;
|
|
110
|
+
/**
|
|
111
|
+
* Delete chunks for files that are no longer referenced by ANY branch.
|
|
112
|
+
* If another branch still has a file hash entry for a given path,
|
|
113
|
+
* the chunks are kept (they're shared via content-addressing).
|
|
114
|
+
*/
|
|
115
|
+
deleteChunksByFiles(filePaths: string[]): Promise<void>;
|
|
116
|
+
search(queryVector: number[], limit?: number, filePrefix?: string, typeFilter?: string[]): Promise<SearchResult[]>;
|
|
117
|
+
getIndexedFiles(): Promise<Map<string, string[]>>;
|
|
118
|
+
getIndexedHashes(): Promise<Set<string>>;
|
|
119
|
+
/**
|
|
120
|
+
* Given a set of chunk hashes, return those that already exist in the
|
|
121
|
+
* chunks table. Runs as batched IN() queries in the DB.
|
|
122
|
+
*/
|
|
123
|
+
filterExistingChunkHashes(hashes: string[]): Promise<Set<string>>;
|
|
124
|
+
chunkCount(): Promise<number>;
|
|
125
|
+
getFileHashes(): Promise<Map<string, string>>;
|
|
126
|
+
/**
|
|
127
|
+
* Given a set of file hashes, return those that already exist in the
|
|
128
|
+
* files table on ANY branch. The query runs in the DB, not in JS.
|
|
129
|
+
*/
|
|
130
|
+
filterKnownFileHashes(hashes: string[]): Promise<Set<string>>;
|
|
131
|
+
upsertFileHashes(entries: Array<{
|
|
132
|
+
filePath: string;
|
|
133
|
+
fileHash: string;
|
|
134
|
+
}>): Promise<void>;
|
|
135
|
+
deleteFileHashes(filePaths: string[]): Promise<void>;
|
|
136
|
+
reset(): Promise<void>;
|
|
137
|
+
compact(): Promise<void>;
|
|
138
|
+
/**
|
|
139
|
+
* Import all chunks and file hashes from another Store's database.
|
|
140
|
+
* Returns { chunks, files } counts of imported records.
|
|
141
|
+
*/
|
|
142
|
+
importFrom(sourcePath: string): Promise<{
|
|
143
|
+
chunks: number;
|
|
144
|
+
files: number;
|
|
145
|
+
}>;
|
|
146
|
+
close(): Promise<void>;
|
|
147
|
+
}
|